Initial commit
This commit is contained in:
commit
40a56c4f15
3 changed files with 94 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
/Cargo.lock
|
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "readformat"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/tudbut/readformat"
|
||||
license = "MIT"
|
||||
description = "Very small format reader"
|
||||
|
||||
[dependencies]
|
83
src/lib.rs
Normal file
83
src/lib.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
|
||||
pub fn readf(format: &str, mut s: &str) -> Option<Vec<String>> {
|
||||
if !format.contains("{}") {
|
||||
return if format == s { Some(vec![]) } else { None };
|
||||
}
|
||||
if format.contains("{}{}") {
|
||||
panic!("Ambiguous argument: '{}' found in format string.", "{}{}");
|
||||
}
|
||||
let mut f = format;
|
||||
let mut occurences = 0;
|
||||
while let Some(idx) = f.find("{}") {
|
||||
f = &f[(idx + 2)..];
|
||||
occurences += 1;
|
||||
}
|
||||
let mut result: Vec<String> = Vec::with_capacity(occurences);
|
||||
|
||||
let mut f = format;
|
||||
for n in 0..=occurences {
|
||||
// shave off space until next {}
|
||||
let i = if let Some(x) = f.find("{}") { x } else { f.len() };
|
||||
if &f[0..i] != &s[0..i] {
|
||||
return None;
|
||||
}
|
||||
if n == occurences {
|
||||
break;
|
||||
}
|
||||
// abcde | a{}cd{} => bcde | cd{}
|
||||
f = &f[(i + 2)..];
|
||||
s = &s[i..];
|
||||
// populate
|
||||
match f.find("{}") { // has next
|
||||
Some(x) => { // yes, append until next segment
|
||||
// bcde | cd{}
|
||||
// | \ |
|
||||
// gets the next segment, and appends everything until the beginning of it
|
||||
result.push(s[0..s.find(&f[0..x])?].into());
|
||||
},
|
||||
None => { // no, append until last segment
|
||||
// gets the last segment (last {} until end of string) and pushes up until it
|
||||
result.push(s[0..(s.len() - (format.len() - format.rfind("{}").unwrap() - 2))].into())
|
||||
},
|
||||
}
|
||||
// shave the appended string away
|
||||
s = &s[result[n].len()..];
|
||||
}
|
||||
if result.len() != occurences {
|
||||
None
|
||||
} else {
|
||||
Some(result)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn readf1(format: &str, s: &str) -> Option<String> {
|
||||
let r = readf(format, s);
|
||||
r.map(|x| if x.len() == 0 { "".into() } else { x[0].clone() })
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn t_readf1() {
|
||||
assert_eq!(readf1("hello, {}", "hello, person"), Some("person".into()));
|
||||
assert_eq!(readf1("hello, {}!", "hello, person!"), Some("person".into()));
|
||||
assert_eq!(readf1("Hello, {}", "hello, person"), None);
|
||||
assert_eq!(readf1("Hello, {}!", "hello, person"), None);
|
||||
assert_eq!(readf1("hello!", "hello!"), Some("".into()));
|
||||
assert_eq!(readf1("Hello!", "hello!"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn t_readf() {
|
||||
assert_eq!(readf("hello, {} and {}", "hello, person 1 and person 2"), Some(vec!["person 1".into(), "person 2".into()]));
|
||||
assert_eq!(readf("hello, {} and {}!", "hello, person 1 and person 2!"), Some(vec!["person 1".into(), "person 2".into()]));
|
||||
assert_eq!(readf("hello, {} and {}", "hello, person"), None);
|
||||
assert_eq!(readf("hello, {} and {}!", "hello, person!"), None);
|
||||
assert_eq!(readf("Hello, {} and {}", "hello, person 1 and person 2"), None);
|
||||
assert_eq!(readf("Hello, {} and {}!", "hello, person 1 and person 2!"), None);
|
||||
assert_eq!(readf("hello!", "hello!"), Some(vec![]));
|
||||
assert_eq!(readf("Hello!", "hello!"), None);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue