itertools.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // -*- coding: utf-8 -*-
  2. //
  3. // Simple CMS
  4. //
  5. // Copyright (C) 2011-2024 Michael Büsch <m@bues.ch>
  6. //
  7. // Licensed under the Apache License version 2.0
  8. // or the MIT license, at your option.
  9. // SPDX-License-Identifier: Apache-2.0 OR MIT
  10. pub trait Char {
  11. fn get(&self) -> char;
  12. }
  13. impl Char for char {
  14. #[inline]
  15. fn get(&self) -> char {
  16. *self
  17. }
  18. }
  19. pub trait Peek {
  20. fn peek_next(&mut self) -> Option<&impl Char>;
  21. fn cons_next(&mut self) -> Option<impl Char>;
  22. }
  23. impl<I, const A: usize, const B: usize> Peek for peekable_fwd_bwd::Peekable<I, A, B>
  24. where
  25. I: Iterator,
  26. I::Item: Char + Clone,
  27. {
  28. #[inline]
  29. fn peek_next(&mut self) -> Option<&impl Char> {
  30. self.peek()
  31. }
  32. #[inline]
  33. fn cons_next(&mut self) -> Option<impl Char> {
  34. self.next()
  35. }
  36. }
  37. impl<I> Peek for std::iter::Peekable<I>
  38. where
  39. I: Iterator,
  40. I::Item: Char,
  41. {
  42. #[inline]
  43. fn peek_next(&mut self) -> Option<&impl Char> {
  44. self.peek()
  45. }
  46. #[inline]
  47. fn cons_next(&mut self) -> Option<impl Char> {
  48. self.next()
  49. }
  50. }
  51. #[inline]
  52. fn iter_cons_until_generic<P: Peek>(
  53. iter: &mut P,
  54. chars: &[char],
  55. invert: bool,
  56. ) -> Result<String, String> {
  57. let mut ret = String::with_capacity(64);
  58. while let Some(c) = iter.peek_next() {
  59. let c = c.get();
  60. if chars.contains(&c) ^ invert {
  61. return Ok(ret);
  62. }
  63. iter.cons_next(); // consume char.
  64. ret.push(c);
  65. }
  66. Err(ret)
  67. }
  68. pub fn iter_cons_until_not_in<P: Peek>(iter: &mut P, chars: &[char]) -> Result<String, String> {
  69. iter_cons_until_generic(iter, chars, true)
  70. }
  71. pub fn iter_cons_until_in<P: Peek>(iter: &mut P, chars: &[char]) -> Result<String, String> {
  72. iter_cons_until_generic(iter, chars, false)
  73. }
  74. pub fn iter_cons_until<P: Peek>(iter: &mut P, ch: char) -> Result<String, String> {
  75. iter_cons_until_generic(iter, &[ch], false)
  76. }
  77. #[cfg(test)]
  78. mod tests {
  79. use super::*;
  80. type Peekable<'a> = peekable_fwd_bwd::Peekable<std::str::Chars<'a>, 1, 8>;
  81. #[test]
  82. fn test_iter_cons_until() {
  83. let mut it = Peekable::new("abc(def".chars());
  84. let a = iter_cons_until(&mut it, '(');
  85. assert_eq!(a, Ok("abc".to_string()));
  86. assert_eq!(it.next(), Some('('));
  87. let mut it = Peekable::new("abcdef".chars());
  88. let a = iter_cons_until(&mut it, '(');
  89. assert_eq!(a, Err("abcdef".to_string()));
  90. assert_eq!(it.next(), None);
  91. }
  92. #[test]
  93. fn test_iter_cons_until_in() {
  94. let mut it = Peekable::new("abc()def".chars());
  95. let a = iter_cons_until_in(&mut it, &['(', ')']);
  96. assert_eq!(a, Ok("abc".to_string()));
  97. assert_eq!(it.next(), Some('('));
  98. let a = iter_cons_until_in(&mut it, &['(', ')']);
  99. assert_eq!(a, Ok("".to_string()));
  100. assert_eq!(it.next(), Some(')'));
  101. let mut it = Peekable::new("abcdef".chars());
  102. let a = iter_cons_until_in(&mut it, &['(', ')']);
  103. assert_eq!(a, Err("abcdef".to_string()));
  104. assert_eq!(it.next(), None);
  105. }
  106. #[test]
  107. fn test_iter_cons_until_not_in() {
  108. let mut it = Peekable::new("abc(def".chars());
  109. let a = iter_cons_until_not_in(&mut it, &['a', 'b', 'c', 'd', 'e', 'f']);
  110. assert_eq!(a, Ok("abc".to_string()));
  111. assert_eq!(it.next(), Some('('));
  112. let mut it = Peekable::new("abcdef".chars());
  113. let a = iter_cons_until_not_in(&mut it, &['a', 'b', 'c', 'd', 'e', 'f']);
  114. assert_eq!(a, Err("abcdef".to_string()));
  115. assert_eq!(it.next(), None);
  116. }
  117. }
  118. // vim: ts=4 sw=4 expandtab