123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- // -*- coding: utf-8 -*-
- //
- // Simple CMS
- //
- // Copyright (C) 2011-2024 Michael Büsch <m@bues.ch>
- //
- // Licensed under the Apache License version 2.0
- // or the MIT license, at your option.
- // SPDX-License-Identifier: Apache-2.0 OR MIT
- pub trait Char {
- fn get(&self) -> char;
- }
- impl Char for char {
- #[inline]
- fn get(&self) -> char {
- *self
- }
- }
- pub trait Peek {
- fn peek_next(&mut self) -> Option<&impl Char>;
- fn cons_next(&mut self) -> Option<impl Char>;
- }
- impl<I, const A: usize, const B: usize> Peek for peekable_fwd_bwd::Peekable<I, A, B>
- where
- I: Iterator,
- I::Item: Char + Clone,
- {
- #[inline]
- fn peek_next(&mut self) -> Option<&impl Char> {
- self.peek()
- }
- #[inline]
- fn cons_next(&mut self) -> Option<impl Char> {
- self.next()
- }
- }
- impl<I> Peek for std::iter::Peekable<I>
- where
- I: Iterator,
- I::Item: Char,
- {
- #[inline]
- fn peek_next(&mut self) -> Option<&impl Char> {
- self.peek()
- }
- #[inline]
- fn cons_next(&mut self) -> Option<impl Char> {
- self.next()
- }
- }
- #[inline]
- fn iter_cons_until_generic<P: Peek>(
- iter: &mut P,
- chars: &[char],
- invert: bool,
- ) -> Result<String, String> {
- let mut ret = String::with_capacity(64);
- while let Some(c) = iter.peek_next() {
- let c = c.get();
- if chars.contains(&c) ^ invert {
- return Ok(ret);
- }
- iter.cons_next(); // consume char.
- ret.push(c);
- }
- Err(ret)
- }
- pub fn iter_cons_until_not_in<P: Peek>(iter: &mut P, chars: &[char]) -> Result<String, String> {
- iter_cons_until_generic(iter, chars, true)
- }
- pub fn iter_cons_until_in<P: Peek>(iter: &mut P, chars: &[char]) -> Result<String, String> {
- iter_cons_until_generic(iter, chars, false)
- }
- pub fn iter_cons_until<P: Peek>(iter: &mut P, ch: char) -> Result<String, String> {
- iter_cons_until_generic(iter, &[ch], false)
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- type Peekable<'a> = peekable_fwd_bwd::Peekable<std::str::Chars<'a>, 1, 8>;
- #[test]
- fn test_iter_cons_until() {
- let mut it = Peekable::new("abc(def".chars());
- let a = iter_cons_until(&mut it, '(');
- assert_eq!(a, Ok("abc".to_string()));
- assert_eq!(it.next(), Some('('));
- let mut it = Peekable::new("abcdef".chars());
- let a = iter_cons_until(&mut it, '(');
- assert_eq!(a, Err("abcdef".to_string()));
- assert_eq!(it.next(), None);
- }
- #[test]
- fn test_iter_cons_until_in() {
- let mut it = Peekable::new("abc()def".chars());
- let a = iter_cons_until_in(&mut it, &['(', ')']);
- assert_eq!(a, Ok("abc".to_string()));
- assert_eq!(it.next(), Some('('));
- let a = iter_cons_until_in(&mut it, &['(', ')']);
- assert_eq!(a, Ok("".to_string()));
- assert_eq!(it.next(), Some(')'));
- let mut it = Peekable::new("abcdef".chars());
- let a = iter_cons_until_in(&mut it, &['(', ')']);
- assert_eq!(a, Err("abcdef".to_string()));
- assert_eq!(it.next(), None);
- }
- #[test]
- fn test_iter_cons_until_not_in() {
- let mut it = Peekable::new("abc(def".chars());
- let a = iter_cons_until_not_in(&mut it, &['a', 'b', 'c', 'd', 'e', 'f']);
- assert_eq!(a, Ok("abc".to_string()));
- assert_eq!(it.next(), Some('('));
- let mut it = Peekable::new("abcdef".chars());
- let a = iter_cons_until_not_in(&mut it, &['a', 'b', 'c', 'd', 'e', 'f']);
- assert_eq!(a, Err("abcdef".to_string()));
- assert_eq!(it.next(), None);
- }
- }
- // vim: ts=4 sw=4 expandtab
|