A port of Java's java.util.Scanner
interface to Rust.
This project is available on crates.io.
For the most recent version, always check this repository.
Code should be styled according to rustfmt
. There is currently no behavior
in our roadmap that should require the use of an unsafe
block.
All unwrap()
s should either immediately follow a check that they are safe or
include a comment explaining why they are guaranteed to be safe.
We are following test-driven development. Use the behavior of java.util.Scanner
as the reference implementation for a test, with the exception that exceptions should never be raised in a situation where a wrapped return value, e.g., Option
, Result
, would be appropriate. This will present some places where we will not have parity with Java.
Finally, have fun. There is no need to be overly strict about 1:1 parity with Java, but it does offer a good pattern for complex IO without variadic functions or operator overloading that one finds in C and C++'s approaches. We are attempting to keep parity so that developers familiar with the idioms of Java's Scanner will have a fast learning curve, but this is also an opportunity to air grievances with Java's Scanner, so long as you can justify them.
Simply add file_scanner = "0.2.0"
to your [dependencies]
.
Note changes from previous version: We now take an immutable object implementing Read
instead of a mutable reference to an object implementing BufRead
. See example code below.
extern crate file_scanner;
use file_scanner::Scanner;
//snip
let file = File::open(...)?;
let mut s = Scanner::new(file);
let int = s.next_int().unwrap();
let bin = s.next_int_radix(2).unwrap();
let real = s.next_float().unwrap();
let hex_real = s.next_float_radix(16).unwrap();
let word = s.next().unwrap();
let line = s.next_line().unwrap();
s.set_delim_str("[ foo ]"); // words will now be delimited by "[ foo ]"
// words are delimited by whitespace (this is the default behavior)
s.set_delim(Regex::new(r"\s+").unwrap());
s.set_radix(2); // future calls to next_int or next_float will use binary
s.set_radix(16); // hexadecimal
s.set_radix(36); // alphanumeric
// or anything in between
For full documentation, see https://hxtk.github.io/Rust-Scanner/file_scanner/
Note we are currently tracking a bug where precedent delimiters larger than the buffer are undetectable. See Issue #4 for details.
-
Scanner.next() -> Option<String>
-
Scanner.next_line() -> Option<String>
-
Scanner.next_int<T: Integer>() -> Option<T>
-
Support for regular language delimiters*
-
Scanner.next_float<T: Float>() -> Option<T>
-
Arbitrary radix integer parsing
Scanner.has_next*
In general, feel free to work on any feature that is found in java.util.Scanner
that we have not implemented here. The repository owner(s) reserve the right to reject pull requests. Here are some tips to make sure your pull request is accepted:
-
Comment on the issue for the feature you are writing. If there isn't an issue, make one.
-
Get approval from one of the main contributors.
-
Include unit tests for your feature. Where there is pairity with
java.util.Scanner
, ensure those tests match its behavior (see exception caveat under "Developing").
One of the best ways you can help if you don't have time to implement a feature is to nitpick (politely). The lead developer is still a student of both Rust and software engineering in general.