rune_core/item/
iter.rs
1use core::str;
2
3use crate::item::internal;
4use crate::item::{ComponentRef, Item, ItemBuf};
5
6#[derive(Clone)]
10pub struct Iter<'a> {
11 content: &'a [u8],
12}
13
14impl<'a> Iter<'a> {
15 pub(super) fn new(content: &'a [u8]) -> Self {
17 Self { content }
18 }
19
20 pub(super) fn len(&self) -> usize {
22 self.content.len()
23 }
24
25 #[inline]
27 pub fn is_empty(&self) -> bool {
28 self.content.is_empty()
29 }
30
31 #[inline]
33 pub fn as_item(&self) -> &Item {
34 unsafe { Item::from_bytes(self.content) }
36 }
37
38 #[inline]
40 pub fn into_item(self) -> &'a Item {
41 unsafe { Item::from_bytes(self.content) }
43 }
44
45 pub fn next_str(&mut self) -> Option<&'a str> {
52 match self.next()? {
53 ComponentRef::Str(s) => Some(s),
54 _ => None,
55 }
56 }
57
58 pub fn next_back_str(&mut self) -> Option<&'a str> {
65 match self.next_back()? {
66 ComponentRef::Str(s) => Some(s),
67 _ => None,
68 }
69 }
70}
71
72impl<'a> Iterator for Iter<'a> {
73 type Item = ComponentRef<'a>;
74
75 fn next(&mut self) -> Option<Self::Item> {
76 if self.content.is_empty() {
77 return None;
78 }
79
80 let (head_tag, content) = self.content.split_at(internal::TAG_BYTES);
81 let (b, n) = internal::read_tag(head_tag);
82
83 let c = match b {
84 internal::CRATE => {
85 let (s, content, tail_tag) = internal::read_string(content, n);
86 debug_assert_eq!(head_tag, tail_tag);
87 self.content = content;
88 return Some(ComponentRef::Crate(s));
89 }
90 internal::STRING => {
91 let (s, content, tail_tag) = internal::read_string(content, n);
92 debug_assert_eq!(head_tag, tail_tag);
93 self.content = content;
94 return Some(ComponentRef::Str(s));
95 }
96 internal::ID => ComponentRef::Id(n),
97 internal::Tag(b) => panic!("unsupported control byte {:?}", b),
98 };
99
100 self.content = content;
101 Some(c)
102 }
103}
104
105impl DoubleEndedIterator for Iter<'_> {
106 fn next_back(&mut self) -> Option<Self::Item> {
107 if self.content.is_empty() {
108 return None;
109 }
110
111 let content = self.content;
112 let (content, tail) = content.split_at(
113 content
114 .len()
115 .checked_sub(internal::TAG_BYTES)
116 .expect("length underflow"),
117 );
118 let (b, n) = internal::read_tag(tail);
119
120 let c = match b {
121 internal::CRATE => {
122 let (s, content) = read_string_back(content, n);
123 self.content = content;
124 return Some(ComponentRef::Crate(s));
125 }
126 internal::STRING => {
127 let (s, content) = read_string_back(content, n);
128 self.content = content;
129 return Some(ComponentRef::Str(s));
130 }
131 internal::ID => ComponentRef::Id(n),
132 internal::Tag(b) => panic!("unsupported control byte {:?}", b),
133 };
134
135 self.content = content;
136 return Some(c);
137
138 fn read_string_back(content: &[u8], n: usize) -> (&str, &[u8]) {
139 let (content, buf) =
140 content.split_at(content.len().checked_sub(n).expect("length underflow"));
141
142 let (content, _) = content.split_at(
144 content
145 .len()
146 .checked_sub(internal::TAG_BYTES)
147 .expect("length underflow"),
148 );
149
150 let s = unsafe { str::from_utf8_unchecked(buf) };
152
153 (s, content)
154 }
155 }
156}
157
158impl PartialEq<ItemBuf> for Iter<'_> {
159 fn eq(&self, other: &ItemBuf) -> bool {
160 self.as_item() == other
161 }
162}
163
164impl PartialEq<Item> for Iter<'_> {
165 fn eq(&self, other: &Item) -> bool {
166 self.as_item() == other
167 }
168}