wlentz / scan_fmt Goto Github PK
View Code? Open in Web Editor NEWSimple scanf()-like input for Rust.
License: MIT License
Simple scanf()-like input for Rust.
License: MIT License
I am trying to build a project which depends on scan_fmt v0.2.3, but also has other dependencies. Cargo is reporting that it is unable to resolve dependencies because scan_fmt requires regex ~1.1.6, but other crates require regex ^1.3.
I noticed this is already fixed in d62f75c. Could you please release a new version of scan_fmt to resolve this issue? Thanks!
use scan_fmt::scan_fmt;
fn main() {
if let Ok(ip) = scan_fmt!("x 185.187.165.163 y", "x {} y", std::net::IpAddr) {
println!("ip {}", ip);
}
}
gives:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: AddrParseError(())', src/main.rs:4:21
let a = scan_fmt!("+42", "{d}", i32);
assert_eq!( a, Some(42) );
This fails because Rust's string-to-integer conversion function parse<iXX>
does not recognize leading +
, only -
. The scanner in this crate, OTOH, scan_dec10()
, clearly accepts +
. This was confirmed in this forum message.
I suggest to either document this unusual behaviour very visibly or, even better, to work around that misfeature.
This crate is awesome!
It would be great to support no_std.
It would be useful to parse without allocating. Sometimes I only need an &str
so having to convert part of an &str
to a String
, then taking a reference to go back to an &str
is not efficient.
Would it be possible to special-case &str
to just return the right slice ?
Hi,
In C, something like the following can be done:
#include <stdio.h>
int main() {
int a, b, c;
char* line = "01021F";
sscanf(line, "%2d%2d%2x", &a, &b, &c);
printf("%d %d %d\n", a, b, c);
}
How can this be done with this library?
If this isn't yet available, let this be a feature request.
Thanks!
It would be convenient, like suggested in #2, to avoid manually unwrapping each parsed token. But better than an Option
having a proper error would allow doing something like
let (a, b, c) = scan_fmt!(line, "{d] {x} {f}", u32, u32, f64)?;
... without any more boilerplate code.
Can scan_fmt support strings too (and not just &str)?
fn main() {
let line = "10 20".to_string();
let (x, y) = scan_fmt!(line, "{} {}", u32, u32);
}
Is it a good idea to return an Option of tuple instead of a tuple of Options, to shorten and simplify the user code a little?
fn main() {
let line = "10 20".to_string();
if let Some((x, y)) = scan_fmt!(&line, "{} {}", u32, u32) {
}
}
Where the compiler is able to inference the types of the variables, can you allow omitting the types?
fn main() {
let line = "10 20".to_string();
if let (Some(x), Some(y)) = scan_fmt!(&line, "{} {}") {
let r1: u32 = x * 2;
let r2: u32 = y * 2;
}
}
If all three ideas are good and possible the user can write:
fn main() {
let line = "10 20".to_string();
if let Some((x, y)) = scan_fmt!(line, "{} {}") {
let r1: u32 = x * 2;
let r2: u32 = y * 2;
}
}
The pattern {d}cm
will match the number in 17in
(Ok(17)
) even though the suffix cm
!= in
.
The pattern {d}{*/cm/}
(or without *
) will also result in (Ok(17)
) even though cm
was never encountered.
In my opinion both of these patterns should throw a ScanError
as the desired pattern is never matched.
This issue arrises from two sources:
{d}{/cm/}
applied to the string 17in
will result in ["17", ""]
. The empty string given by the regex expression is wrongfully counted as a valid response.{d}cm
will match 17in
as {d}
matches 17.'c' == 'i'
and will come to the conclusion: the pattern is not matching, thus breaking the loop in parse.rs:scan(...)
. As it already encountered all relevant search patterns ({d}
), the resulting array will be encountered as "valid" (all searched-for variables are found) and won't save the erred return state. Therefore it seems like the pattern matching succeeded.Hello, I am a newbie to Rust. After I read the code in lib.rs, I find some keywords like "wrap" and "no_wrap". I almost google the whole the internet with rust "no_wrap"
. However, I can't figure out anything about it. I guess they are used to match Result type. Where do they come from? Even in rust source code, I don't find them.
Maybe I've missed something, but I can't figure out how to require scan_fmt!
to match the entire input string. Instead, if there are extra characters that don't match my scan expression at the end of the input string, they are silently ignored.
I thought that scan_fmt would be the answer to my input-parsing woes in 2020 Advent of Code day 4. As a partial example of how I intended to use scan_fmt to match the height-parsing requirement:
if let Some(inches) = scan_fmt!(&field, "{d}in", i32) {
return inches >= 59 && inches <= 76
}
This would correctly match a value such as "62in", but it would also match "62ink" which should have been an error. Similarly, using "#{/[0-9a-fA-F]{6}/}"
to try to match 6-digit hex codes would also match hex codes with 7 or more digits.
From the documentation and what I can understand of the code, I can't find a way to require that the entire input string matches the scan expression, or to check whether the entire input string was matched.
Simple main.rs (copy/pasted from the example, but using rust 2018 edition):
fn main() {
let (a,b,c) = scan_fmt::scan_fmt_some!( "hello 12 345 bye", // input string
"hello {} {d} {}", // format
u8, i32, String); // type of a-c Options
assert_eq!( a, Some(12) ) ;
assert_eq!( b, Some(345) ) ;
assert_eq!( c, Some("bye".into()) ) ;
}
results in:
error: cannot find macro `scan_fmt_help!` in this scope
--> src/main.rs:2:17
|
2 | let (a,b,c) = scan_fmt::scan_fmt_some!( "hello 12 345 bye", // input string
| _________________^
3 | | "hello {} {d} {}", // format
4 | | u8, i32, String); // type of a-c Options
| |________________________________________________^
Hi,
Apparently I can't write:
let (devname, start, size) = scan_fmt!(s, "{} 0x{x} 0x{x}", String, usize, usize);
I have to scan_fmt!
everything into String
and then manually
`usize::from_str_radix(&start, 16)`
Would it be possible to directly parse hex integers ?
This used to work in scan_fmt
0.1 but is broken now: I can't use a fully qualified type like mycrate::MyType
in the macros:
error: no rules expected the token `::`
--> src/ntpc.rs:296:33
|
296 | lfgt::Ip,
| ^^ no rules expected this token in macro call
Errors which derive from ScanError
can't #[derive(PartialEq)]
because ScanError
doesn't implement PartialEq
itself. Could you please add the missing derive
?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.