Non-primitive to primitive cast in Rust? - casting

I'm trying to verify an IP address in Rust, but I can't find a solution casting a str into a u8 that doesn't involve using nightly Rust:
use std::net::{IpAddr, Ipv4Addr};
fn verify_address(address: String) -> bool {
let v: Vec<&str> = address.split('.').collect();
let v_u8: Vec<u8> = v.iter().map(|c| *c.to_owned() as u8).collect();
let addr = IpAddr::V4(Ipv4Addr::new(v_u8[0], v_u8[1], v_u8[2], v_u8[3]));
//.expect("ERR: Error parsing IPv4 address!");
if !addr.is_ipv4() {
return false;
}
return true;
}
error[E0605]: non-primitive cast: `str` as `u8`
--> src/lib.rs:6:42
|
6 | let v_u8: Vec<u8> = v.iter().map(|c| *c.to_owned() as u8).collect();
| ^^^^^^^^^^^^^^^^^^^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait

Please reread the chapter about error handling. You do not need all this:
use std::net::Ipv4Addr;
fn main() {
let ip = "127.0.0.1".parse::<Ipv4Addr>();
match ip {
Ok(ip) => println!("valid"),
Err(e) => println!("invalid"),
}
}
About your question, you can use primitive cast for... primitive types only. You must use From and Into, or parse if you convert a &str into another type.

Related

different function type when using if statement in Rust

I'm new in rust and i need to make a small if statement on function option for example
use isahc::{
HttpClient,
config::{
RedirectPolicy,
VersionNegotiation,
SslOption},
prelude::*
};
use std::{
time::Duration
};
pub struct http {
pub timeout: u64
}
impl http {
pub fn send(&self) -> HttpClient {
let client =
HttpClient::builder()
.version_negotiation(VersionNegotiation::http11())
.redirect_policy(RedirectPolicy::None)
.timeout(Duration::from_secs(self.timeout));
.ssl_options(SslOption::DANGER_ACCEPT_INVALID_CERTS | SslOption::DANGER_ACCEPT_REVOKED_CERTS);
return client.build().unwrap();
}
}
fn main(){
let req = http{ timeout:"20".parse().unwrap()};
let test = req.send();
test.get("https://www.google.com");
}
now in my program the user will give me the options of the request (eg: follow redirects or not ) and this need if statement on these options so i tried to use it on this case but i always get a different function return type
impl http {
pub fn send(&self) -> HttpClient {
let client =
HttpClient::builder()
.version_negotiation(VersionNegotiation::http11())
.redirect_policy(RedirectPolicy::None)
.ssl_options(SslOption::DANGER_ACCEPT_INVALID_CERTS | SslOption::DANGER_ACCEPT_REVOKED_CERTS);
if 1 == 1 {
client.timeout(Duration::from_secs(self.timeout));
}
return client.build().unwrap();
}
}
Cargo Output
warning: type `http` should have an upper camel case name
--> src/sender.rs:14:12
|
14 | pub struct http {
| ^^^^ help: convert the identifier to upper camel case: `Http`
|
= note: `#[warn(non_camel_case_types)]` on by default
error[E0382]: use of moved value: `client`
--> src/sender.rs:32:16
|
24 | let client =
| ------ move occurs because `client` has type `HttpClientBuilder`, which does not implement the `Copy` trait
...
30 | client.timeout(Duration::from_secs(self.timeout));
| ------ value moved here
31 | }
32 | return client.build().unwrap();
| ^^^^^^ value used here after move
so what I'm doing wrong ?
i tired to change the function type exception but i can't use the function of the class client.get() for example
this a clear example in python for explain what i need to do
options : dict = {
"redirects": False,
"ssl_path":"~/cer.pem"
}
def send(opts):
# not real httplib !
r = httplib.get("http://stackoverflow.com")
if opts.get('redirects') == True:
r.redirects = True
if opts.get('cert_path',''):
r.ssl = opts.get('cert_path')
return r.send()
def main():
send(options)
Thanks
Since this is a builder pattern, each function call consumes the builder and returns it back. So you need to capture client from the return value of the timeout function in order to continue using it. Note that you also need to make client mutable.
Something like
impl http {
pub fn send(&self) -> HttpClient {
let mut client =
HttpClient::builder()
.version_negotiation(VersionNegotiation::http11())
.redirect_policy(RedirectPolicy::None)
.ssl_options(SslOption::DANGER_ACCEPT_INVALID_CERTS | SslOption::DANGER_ACCEPT_REVOKED_CERTS);
if 1 == 1 {
client = client.timeout(Duration::from_secs(self.timeout));
}
return client.build().unwrap();
}
}

Convenient way to get the first char index of a given string that caused a specific text pattern not to match in Rust?

Language:
Rust
Rust regex crate: https://docs.rs/regex/1.5.4/regex/
Use case:
Printing friendly diagnostic message to user that inputs text that does not match an expected regex pattern
e.g.
if patterns are Regex::new(r"^--(\w+)=(\w+)$").unwrap(); and Regex = Regex::new(r"^-(\w+)$").unwrap();
and user inputs "---abc"
user can see diagnostic like:
"---abc"
^ Problem with character "-" at index 2.
Expecting format "--key=value".
^ Does not match expected format at index 2.
Possible solution:
Can I do something with capture groups? (They might only be relevant if there is a match). If no solution with capture groups, what else?
// "-a[bc..]" or "--key=value"
lazy_static! {
static ref SHORT_OPTION_RE: Regex = Regex::new(r"^-(\w+)$").unwrap();
static ref LONG_OPTION_RE: Regex = Regex::new(r"^--(\w+)=(\w+)$").unwrap();
}
// long option example
let caps = LONG_OPTION_RE.captures(s).ok_or(e_msg)?;
let key = caps.get(1).unwrap().as_str().to_string();
let value = caps.get(2).unwrap().as_str().to_string();
if key.is_some { }
Issue:
Can't get exact char index that caused capture group not to match.
Alternatives:
Just manually add in if/else checks for various indexes to try to catch every error scenario ("---a", "-a=b", etc) (Essentially implement mini parser that generates diagnostic message and problematic char index without using regex)
Out of scope:
I do not need recommendations for cli program libs/frameworks (unless you're pointing to an implementation detail within one)
Edit:
Modified question to be more generic than just regex.
I would use a parser like nom.
Here is a quick and partial implementation of your use case:
use nom::{
bytes::complete::tag, character::complete::alphanumeric1, combinator::map, sequence::tuple,
IResult,
};
#[derive(Debug)]
struct OptPair {
key: String,
value: String,
}
fn parse_option(input: &str) -> IResult<&str, OptPair> {
map(
tuple((tag("--"), alphanumeric1, tag("="), alphanumeric1)),
|(_, k, _, v): (&str, &str, &str, &str)| OptPair {
key: k.to_owned(),
value: v.to_owned(),
},
)(input)
}
fn test_parse(input: &str) {
println!("TEST: input = \"{}\":", input);
match parse_option(input) {
Ok((_, opt_pair)) => println!(" Ok, {:?}", opt_pair),
Err(err) => match err {
nom::Err::Incomplete(_) => eprintln!(" Incomplete"),
nom::Err::Error(err) => {
let offset = err.input.as_ptr() as usize - input.as_ptr() as usize;
eprintln!(" Error at index {}", offset);
}
nom::Err::Failure(_err) => println!(" Failure"),
},
}
}
fn main() {
test_parse("--foo=bar");
test_parse("---foo=bar");
test_parse("--foo=");
test_parse("Hello");
}
Output:
TEST: input = "--foo=bar":
Ok, OptPair { key: "foo", value: "bar" }
TEST: input = "---foo=bar":
Error at index 2
TEST: input = "--foo=":
Error at index 6
TEST: input = "Hello":
Error at index 0

How to write custom ppx decorator to rescript?

I need to generate a value with a different type from my passed type. This is the first time I write on ocaml-like, and for example, in a familiar me haskell I would use Data.Generics.
How I have understood I need to use decorator and ppx. I wrote simple example
let recordHandler = (loc: Location.t, _recFlag: rec_flag, _t: type_declaration, fields: list(label_declaration)) => {
let (module Builder) = Ast_builder.make(loc);
let test = [%str
let schema: Schema = { name: "", _type: String, properties: [] }
]
let moduleExpr = Builder.pmod_structure(test);
[%str
module S = [%m moduleExpr]
]
}
let str_gen = (~loc, ~path as _, (_rec: rec_flag, t: list(type_declaration))) => {
let t = List.hd(t)
switch t.ptype_kind {
| Ptype_record(fields) => recordHandler(loc, _rec, t, fields);
| _ => Location.raise_errorf(~loc, "schema is used only for records.");
};
};
let name = "my_schema";
let () = {
let str_type_decl = Deriving.Generator.make_noarg(str_gen);
Deriving.add(name, ~str_type_decl) |> Deriving.ignore;
};
And
open Ppxlib;
let _ = Driver.run_as_ppx_rewriter()
But in using in rescript code
module User = {
#deriving(my_schema)
type my_typ = {
foo: int,
};
};
I caught:
schema is not supported
. And I made myself sure me to connect it right when I had changed #deriving(my_schema) for #deriving(abcd) and #deriving(sschema).
I got different error
Ppxlib.Deriving: 'abcd' is not a supported type deriving generator.
And my last experiment was to copy past existing library deriving accessors .
ppx_accessor
I copied-pasted it and renamed for accessors_2. And I got same error such as experiment.
accessors_2 is not supported
Also I haven't found examples "ppx rescript". Can you please help me.
What am I doing wrong (ALL , I know)
I have found answer in the article
Dropping support for custom PPXes such as ppx_deriving (the deriving
attribute is now exclusively interpreted as bs.deriving)

Regex or Wildcard in Kotlin's when statement?

I'm working on a RESTful app in Kotlin and for the router, I'm using a when statement, as it's the most readable and good looking conditional.
Is there a way to use Regex or a wildcard in the when statement for a string?
(So that URIs like "/article/get/" would all be passed to the same controller)
The structure of my router is as follows:
when(uri) {
"some/url" -> return SomeController(config).someAction(session)
}
Yes.
import kotlin.text.regex
val regex1 = Regex( /* pattern */ )
val regex2 = Regex( /* pattern */ )
/* etc */
when {
regex1.matches(uri) -> /* do stuff */
regex2.matches(uri) -> /* do stuff */
/* etc */
}
You could also use containsMatchIn if that suits your needs better than matches.
Explanation:
The test expression of a when statement is optional. If no test expression is included, then the when statement functions like an if-else if chain, where the whenCondition of each whenEntry shall independently evaluate to a boolean.
EDIT:
So I thought about it for awhile, and I came up with a different approach that might be closer to what you want.
import kotlin.text.regex
when (RegexWhenArgument(uri)) {
Regex(/* pattern */) -> /* do stuff */
Regex(/* pattern */) -> /* do stuff */
/* etc */
}
Where RegexWhenArgument is minimally defined as:
class RegexWhenArgument (val whenArgument: CharSequence) {
operator fun equals(whenEntry: Regex) = whenEntry.matches(whenArgument)
override operator fun equals(whenEntry: Any?) = (whenArgument == whenEntry)
}
This approach lets you get as close as possible to the "argument-ful" when expression syntax. I think it's about as streamlined and readable as it can be (assuming that you define the RegexWhenArgument class elsewhere).
This approach uses something similar to the visitor design pattern in combination with Kotlin's operator overloading to redefine what constitutes a "match" between a when expression argument and a whenEntry. If you really wanted to, I suppose you could take this approach a step further and generify RegexWhenArgument into a general-purpose WhenArgument and WhenArgumentDecorator that allows you to specify custom "match" criteria in a when expression for any sort of type, not just Regex.
The typing of the when statement enforces to have compatible types between the whenSubject and the whenEntries. So we cannot compare a String whenSubject with a Regex directly.
We can use when with no subject, then branch conditions may be simply boolean expressions.
fun main() {
val uri: String? = "http://my.site.com/a/b/c"
val res = when {
uri == null -> "NULL"
uri == "http://my.site.com/" -> "ROOT"
uri.startsWith("http://my.site.com/a/") -> "A STUFF"
uri.matches(Regex("http://my.site.com/b/.*")) -> "B STUFF"
else -> "DEFAULT"
}
/* do stuff */
}
Alternatively, we can emulate a kind of when+regex with a dedicated class and few helper functions.
fun main() {
val uri: String? = "http://my.site.com/a/b/c"
val res2 = when(matching(uri)) {
null -> "NULL"
matchesLiteral("http://my.site.com/") -> "ROOT"
matchesRegex("http://my.site.com/a/.*") -> "A STUFF"
else -> "DEFAULT"
}
/* do stuff */
}
class MatchLiteralOrPattern(val value: String, val isPattern: Boolean) {
override fun equals(other: Any?): Boolean {
if (other !is MatchLiteralOrPattern) return false
if (isPattern && !other.isPattern) return Regex(this.value).matches(other.value)
if (!isPattern && other.isPattern) return Regex(other.value).matches(this.value)
return value == other.value
}
}
fun matching(whenSubject: String?) = whenSubject?.let { MatchLiteralOrPattern(it, false) }
fun matchesLiteral(value: String) = MatchLiteralOrPattern(value, false)
fun matchesRegex(value: String) = MatchLiteralOrPattern(value, true)
I tried the following on the kotlin playground and it seems to work as expected.
class WhenArgument (val whenArg: CharSequence) {
override operator fun equals(other: Any?): Boolean {
return when (other) {
is Regex -> other.matches(whenArg)
else -> whenArg.equals(other)
}
}
}
fun what(target: String): String {
return when (WhenArgument(target) as Any) {
Regex("source-.*") -> "${target} is-a-source"
Regex(".*-foo") -> "${target} is-a-foo"
"target-fool" -> "${target} is-the-target-fool"
else -> "nothing"
}
}
fun main() {
println(what("target-foo"))
println(what("source-foo"))
println(what("target-bar"))
println(what("target-fool"))
}
It works around the type compatibility problem by making the 'when' argument of type Any.

Cannot use `replace_all` from the regex crate: expected (), found String

I'm trying to find and replace all instances of a string with a shortened version, and I want to maintain references to a capture if it's found.
I've written this code:
extern crate regex;
use regex::{Regex, Captures};
//... get buffer from stdin
let re = Regex::new(r"(capture something1) and (capture 2)").unwrap();
let out = re.replace_all(&buffer, |caps: &Captures| {
if let ref = caps.at(2).unwrap().to_owned() {
refs.push(ref.to_owned());
}
caps.at(1).unwrap().to_owned();
});
Unfortunately compilation fails with the error:
src/bin/remove_links.rs:16:18: 16:29 error: type mismatch resolving `for<'r, 'r> <[closure#src/bin/remove_links.rs:16:39: 22:6] as std::ops::FnOnce<(&'r regex::Captures<'r>,)>>::Output == std::string::String`:
expected (),
found struct `std::string::String` [E0271]
src/bin/remove_links.rs:16 let out = re.replace_all(&buffer, |caps: &Captures| {
^~~~~~~~~~~
src/bin/remove_links.rs:16:18: 16:29 help: run `rustc --explain E0271` to see a detailed explanation
src/bin/remove_links.rs:16:18: 16:29 note: required because of the requirements on the impl of `regex::Replacer` for `[closure#src/bin/remove_links.rs:16:39: 22:6]`
I can't make sense of it. I've also tried adding use regex::{Regex, Captures, Replacer} but that doesn't change the error at all.
As #BurntSushi5 pointed out, your closure should return a String. Here is a complete example for future reference:
extern crate regex;
use regex::{Regex, Captures};
fn main() {
let buffer = "abcdef";
let re = Regex::new(r"(\w)bc(\w)").unwrap();
let out = re.replace_all(&buffer, |caps: &Captures| {
caps.at(1).unwrap().to_owned()
});
println!("{:?}", out); // => "aef"
}