rune_core/item/
iter.rs

1use core::str;
2
3use crate::item::internal;
4use crate::item::{ComponentRef, Item, ItemBuf};
5
6/// An item over the iterator.
7///
8/// Constructed using [Item::iter].
9#[derive(Clone)]
10pub struct Iter<'a> {
11    content: &'a [u8],
12}
13
14impl<'a> Iter<'a> {
15    /// Constructor for an iterator.
16    pub(super) fn new(content: &'a [u8]) -> Self {
17        Self { content }
18    }
19
20    /// The length of the content being held by the iterator.
21    pub(super) fn len(&self) -> usize {
22        self.content.len()
23    }
24
25    /// Check if the iterator is empty.
26    #[inline]
27    pub fn is_empty(&self) -> bool {
28        self.content.is_empty()
29    }
30
31    /// Coerce the iterator into an item.
32    #[inline]
33    pub fn as_item(&self) -> &Item {
34        // SAFETY: Iterator ensures that content is valid.
35        unsafe { Item::from_bytes(self.content) }
36    }
37
38    /// Coerce the iterator into an item with the lifetime of the iterator.
39    #[inline]
40    pub fn into_item(self) -> &'a Item {
41        // SAFETY: Iterator ensures that content is valid.
42        unsafe { Item::from_bytes(self.content) }
43    }
44
45    /// Get the next component as a string.
46    ///
47    /// Will consume the next component in the iterator, but will only indicate
48    /// if the next component was present, and was a [Component::Str].
49    ///
50    /// [Component::Str]: super::Component::Str
51    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    /// Get the next back as a string component.
59    ///
60    /// Will consume the next component in the iterator, but will only indicate
61    /// if the next component was present, and was a [Component::Str].
62    ///
63    /// [Component::Str]: super::Component::Str
64    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            // consume the head tag.
143            let (content, _) = content.split_at(
144                content
145                    .len()
146                    .checked_sub(internal::TAG_BYTES)
147                    .expect("length underflow"),
148            );
149
150            // Safety: we control the construction of the item.
151            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}