1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
// -*- 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,
I::Item: 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
|