Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- fn resolve_indexes(s: &str, delims: &[&str]) -> Vec<(usize, usize)> {
- let mut offsets = Vec::new();
- for delim in delims {
- for (index, _) in s.match_indices(delim) {
- offsets.push((index, index + delim.len()));
- }
- }
- offsets.sort();
- offsets.dedup_by(|a, b| a.0 == b.0 || a.1 == b.1);
- offsets
- }
- struct Args {
- message: String,
- delims: Vec<Vec<char>>,
- offset: usize,
- offsets: Vec<(usize, usize)>,
- // Used for rewinding
- prev: Vec<(usize, (usize, usize))>,
- }
- use std::error::Error as StdError;
- use std::str::FromStr;
- #[derive(Debug, PartialEq)]
- enum Error<E> {
- Eof,
- Parse(E),
- }
- impl<E: StdError> From<E> for Error<E> {
- fn from(e: E) -> Self {
- Error::Parse(e)
- }
- }
- impl Args {
- fn new(msg: &str, delims: &[&str]) -> Self {
- Args {
- message: msg.to_string(),
- delims: delims.iter().map(|s| s.chars().collect()).collect(),
- prev: Vec::new(),
- offset: 0,
- offsets: resolve_indexes(msg, delims),
- }
- }
- fn until_internal<T: FromStr>(&mut self, change: bool) -> Result<T, Error<T::Err>>
- where
- T::Err: StdError,
- {
- // Reborrowing the fields individually gives them their own lifetime, thus preventing "cannot mutably borrow whilst an immutable borrow is alive" errors.
- fn until<T: FromStr>(
- msg: &str,
- offset: &mut usize,
- offsets: &mut Vec<(usize, usize)>,
- delims: &[Vec<char>],
- prev: &mut Vec<(usize, (usize, usize))>,
- change: bool,
- ) -> Result<T, Error<T::Err>>
- where
- T::Err: StdError,
- {
- if *offset >= msg.len() {
- return Err(Error::Eof);
- }
- if offsets.is_empty() {
- let s = &msg[*offset..];
- // We've reached the end; invalidate the offset.
- *offset = msg.len();
- return Ok(T::from_str(s)?);
- }
- let (start, end) = if change {
- offsets.remove(0)
- } else {
- offsets[0]
- };
- let string = &msg[*offset..start];
- if string.is_empty() {
- return until(msg, offset, offsets, delims, prev, change);
- }
- if change {
- prev.push((*offset, (start, end)));
- *offset = end;
- }
- for delim in delims {
- if string.trim_matches(delim.as_slice()).is_empty() {
- return until(msg, offset, offsets, delims, prev, change);
- }
- }
- Ok(T::from_str(&string)?)
- }
- until(&self.message, &mut self.offset, &mut self.offsets, &self.delims, &mut self.prev, change)
- }
- #[inline]
- fn single<T: FromStr>(&mut self) -> Result<T, Error<T::Err>>
- where
- T::Err: StdError,
- {
- self.until_internal(true)
- }
- #[inline]
- fn single_s<T: FromStr>(&mut self) -> Result<T, Error<T::Err>>
- where
- T::Err: StdError,
- {
- self.until_internal(false)
- }
- #[inline]
- fn skip(&mut self) -> Option<String> {
- self.single::<String>().ok()
- }
- fn rewind(&mut self) {
- if self.prev.is_empty() {
- self.offset = 0;
- return;
- }
- let (off, offsets) = self.prev.pop().unwrap();
- self.offset = off;
- self.offsets.insert(0, offsets);
- }
- }
- fn main() {
- const MESSAGE: &str = "42 fd88 π!π .f . asd . sd a ! s ! εε ±εε ±ε γ©γγγ ζΌ’ε μ‘°μ κΈμ‘°μ κΈμ‘°μ κΈμ‘° Ψ¨Ψ·Ψ§ΩΨ© Ψ§ΩΩ Ψ³Ψ§ΨΉΨ―Ψ© Ψ§ΩΨΊΨ°Ψ§Ψ¦ΩΨ© μ κΈμ‘°μ κΈγ γ΄λ°μ γ γ γ γ γ γ γ μ λ² γ γ γ γ μλ€μμ!γ ???γ γ λ 체[γΉ γ΄μλ μΌγ γ λ€γ ‘μΆννμΉγ γ γ΄μγ γΉ 99";
- let mut args = Args::new(MESSAGE, &[" ", "!", " . "]);
- assert_eq!(args.single_s::<u64>().unwrap(), 42);
- assert_eq!(args.single::<u64>().unwrap(), 42);
- args.rewind();
- assert_eq!(args.single_s::<String>().unwrap(), "42");
- while let Ok(s) = args.single::<String>() {
- println!("{:?}", s);
- }
- let mut args2 = Args::new("hello dear sir um ma'am", &[" "]);
- args2.skip();
- args2.skip();
- args2.skip();
- args2.rewind();
- args2.rewind();
- args2.rewind();
- println!("test rewind");
- while let Ok(s) = args2.single::<String>() {
- println!("{:?}", s);
- }
- }
Add Comment
Please, Sign In to add comment