shared_string/
iter.rs

1
2//! Iterator types
3
4use crate::{SharedGenString, RefCounter};
5
6/// A Split iterator returned by
7/// [split](../struct.SharedGenString.html#method.split).
8#[derive(Debug, Clone)]
9pub struct Split<R> {
10	start: usize,
11	len: usize,
12	bytes: R,
13	byte: u8
14}
15
16impl<R> Split<R>
17where R: RefCounter {
18	pub(crate) fn new(start: usize, len: usize, bytes: R, byte: u8) -> Self {
19		Self { start, len, bytes, byte }
20	}
21
22	#[inline]
23	fn remaning_slice(&self) -> &[u8] {
24		// Safe because only we control start and len
25		let range = self.start..(self.start + self.len);
26		unsafe { self.bytes.get_unchecked(range) }
27	}
28
29	// returns index of new byte or self.len
30	#[inline]
31	fn find_next(&self) -> usize {
32		self.remaning_slice()
33			.iter()
34			.position(|b| b == &self.byte)
35			.unwrap_or(self.len)
36	}
37}
38
39impl<R> Iterator for Split<R>
40where R: RefCounter {
41	type Item = SharedGenString<R>;
42
43	fn next(&mut self) -> Option<Self::Item> {
44		if self.len == 0 {
45			return None
46		}
47
48		let at = self.find_next();
49		let n_at = at + 1; // might out-of-bound
50
51		let n_start = self.start;
52		self.start += n_at;
53		self.len = self.len.saturating_sub(n_at);
54		Some(SharedGenString::new_raw(
55			n_start,
56			at,
57			self.bytes.clone()
58		))
59	}
60}
61
62/// A Lines iterator returned by
63/// [lines](../struct.SharedGenString.html#method.lines).
64#[derive(Debug, Clone)]
65pub struct Lines<R> {
66	start: usize,
67	len: usize,
68	bytes: R
69}
70
71impl<R> Lines<R>
72where R: RefCounter {
73	pub(crate) fn new(start: usize, len: usize, bytes: R) -> Self {
74		Self { start, len, bytes }
75	}
76
77	#[inline]
78	fn remaning_slice(&self) -> &[u8] {
79		// Safe because only we control start and len
80		let range = self.start..(self.start + self.len);
81		unsafe { self.bytes.get_unchecked(range) }
82	}
83
84	// returns index of new byte or self.len
85	#[inline]
86	fn find_next(&self) -> usize {
87		self.remaning_slice()
88			.iter()
89			.position(|&b| b == b'\n')
90			.unwrap_or(self.len)
91	}
92}
93
94impl<R> Iterator for Lines<R>
95where R: RefCounter {
96	type Item = SharedGenString<R>;
97
98	fn next(&mut self) -> Option<Self::Item> {
99		if self.len == 0 {
100			return None
101		}
102
103		let mut at = self.find_next();
104		// + 1 for skipping \n
105		let newline_at = at + 1; // could be out-of-bound
106
107		let n_start = self.start;
108		self.start += newline_at;
109		self.len = self.len.saturating_sub(newline_at);
110
111		// check if should do at - 1 (to remove \r)
112		if at >= 1 && self.bytes[n_start + at - 1] == b'\r' {
113			at -= 1;
114		}
115
116		Some(SharedGenString::new_raw(
117			n_start,
118			at,
119			self.bytes.clone()
120		))
121	}
122}