1use core::borrow::Borrow;
2use core::cmp::Ordering;
3use core::fmt;
4use core::hash::{Hash, Hasher};
5use core::mem::take;
6use core::ops::Deref;
7use core::str::FromStr;
89use crate::alloc::alloc::{Allocator, Global};
10use crate::alloc::clone::TryClone;
11use crate::alloc::iter::TryFromIteratorIn;
12use crate::alloc::{self, Vec};
1314use crate::item::{ComponentRef, IntoComponent, Item, Iter};
1516/// The name of an item in the Rune Language.
17///
18/// This is made up of a collection of strings, like `["foo", "bar"]`.
19/// This is indicated in rune as `foo::bar`.
20///
21/// An item can also belongs to a crate, which in rune could be indicated as
22/// `::crate::foo::bar`. These items must be constructed using
23/// [ItemBuf::with_crate].
24///
25/// Items are inlined if they are smaller than 32 bytes.
26///
27/// # Panics
28///
29/// The max length of a string component is is 2**14 = 16384. Attempting to add
30/// a string larger than that will panic. This also constitutes the maximum
31/// number of *nested* sibling components that can exist in a single source file
32/// since they all use anonymous identifiers.
33///
34/// # Component encoding
35///
36/// The following details internal implementation details of an [`Item`], and is
37/// not exposed through its API. It is provided here in case you need to work
38/// with the internal of an item.
39///
40/// A single component is encoded as:
41///
42/// * A two byte tag as a u16 in native endianess, indicating its type (least
43/// significant 2 bits) and data (most significant 14 bits).
44/// * If the type is a `STRING`, the data is treated as the length of the
45/// string. Any other type this the `data` is treated as the numeric id of the
46/// component.
47/// * If the type is a `STRING`, the tag is repeated at the end of it to allow
48/// for seeking backwards. This is *not* the case for other types. Since they
49/// are fixed size its not necessary.
50///
51/// So all in all, a string is encoded as this where the `d` part indicates the
52/// length of the string:
53///
54/// ```text
55/// dddddddd ddddddtt *string content* dddddddd ddddddtt
56/// ```
57///
58/// And any other component is just the two bytes where the `d` part makes up a
59/// numerical component:
60///
61/// ```text
62/// dddddddd ddddddtt
63/// ```
64#[repr(transparent)]
65pub struct ItemBuf<A: Allocator = Global> {
66 content: Vec<u8, A>,
67}
6869impl<A: Allocator> ItemBuf<A> {
70/// Construct a new item buffer inside of the given allocator.
71pub(crate) const fn new_in(alloc: A) -> Self {
72Self {
73 content: Vec::new_in(alloc),
74 }
75 }
7677/// Internal raw constructor for an item.
78 ///
79 /// # Safety
80 ///
81 /// Caller must ensure that its representation is valid.
82pub(super) const unsafe fn from_raw(content: Vec<u8, A>) -> Self {
83Self { content }
84 }
8586/// Construct a new item with the given path in the given allocator.
87pub(crate) fn with_item_in(
88 iter: impl IntoIterator<Item: IntoComponent>,
89 alloc: A,
90 ) -> alloc::Result<Self> {
91let mut content = Vec::new_in(alloc);
9293for c in iter {
94 c.write_component(&mut content)?;
95 }
9697Ok(Self { content })
98 }
99100/// Push the given component to the current item.
101pub fn push<C>(&mut self, c: C) -> alloc::Result<()>
102where
103C: IntoComponent,
104 {
105 c.write_component(&mut self.content)?;
106Ok(())
107 }
108109/// Pop a the tail component, returning `true` if there was something to pop.
110pub fn pop(&mut self) -> bool {
111let mut it = self.iter();
112113if it.next_back().is_none() {
114return false;
115 };
116117let new_len = it.len();
118119// SAFETY: Advancing the back end of the iterator ensures that the new
120 // length is smaller than the original, and an item buffer is a byte
121 // array which does not need to be dropped.
122unsafe {
123debug_assert!(new_len < self.content.len());
124self.content.set_len(new_len);
125 }
126127true
128}
129130/// Extend the current item with an iterator.
131pub fn extend<I>(&mut self, i: I) -> alloc::Result<()>
132where
133I: IntoIterator,
134 I::Item: IntoComponent,
135 {
136for c in i {
137self.push(c)?;
138 }
139140Ok(())
141 }
142143/// Clear the current item.
144pub fn clear(&mut self) {
145self.content.clear();
146 }
147}
148149impl ItemBuf {
150/// Construct a new empty item.
151 ///
152 /// # Examples
153 ///
154 /// ```
155 /// use rune::ItemBuf;
156 ///
157 /// let item = ItemBuf::new();
158 /// let mut it = item.iter();
159 ///
160 /// assert_eq!(it.next(), None);
161 /// ```
162pub const fn new() -> Self {
163Self {
164 content: Vec::new(),
165 }
166 }
167168/// Construct a new item with the given path.
169 ///
170 /// # Examples
171 ///
172 /// ```
173 /// use rune::ItemBuf;
174 /// use rune::item::ComponentRef;
175 ///
176 /// let item = ItemBuf::with_item(["foo", "bar"])?;
177 /// let mut it = item.iter();
178 ///
179 /// assert_eq!(it.next(), Some(ComponentRef::Str("foo")));
180 /// assert_eq!(it.next(), Some(ComponentRef::Str("bar")));
181 /// assert_eq!(it.next(), None);
182 /// # Ok::<(), rune::support::Error>(())
183 /// ```
184pub fn with_item(iter: impl IntoIterator<Item: IntoComponent>) -> alloc::Result<Self> {
185Self::with_item_in(iter, Global)
186 }
187188/// Construct item for a crate.
189 ///
190 /// # Examples
191 ///
192 /// ```
193 /// use rune::ItemBuf;
194 /// use rune::item::ComponentRef;
195 ///
196 /// let mut item = ItemBuf::with_crate("std")?;
197 /// item.push("foo");
198 /// assert_eq!(item.as_crate(), Some("std"));
199 ///
200 /// let mut it = item.iter();
201 /// assert_eq!(it.next(), Some(ComponentRef::Crate("std")));
202 /// assert_eq!(it.next(), Some(ComponentRef::Str("foo")));
203 /// assert_eq!(it.next(), None);
204 /// # Ok::<(), rune::support::Error>(())
205 /// ```
206pub fn with_crate(name: &str) -> alloc::Result<Self> {
207Self::with_item(&[ComponentRef::Crate(name)])
208 }
209210/// Create a crated item with the given name.
211 ///
212 /// # Examples
213 ///
214 /// ```
215 /// use rune::ItemBuf;
216 /// use rune::item::ComponentRef;
217 ///
218 /// let item = ItemBuf::with_crate_item("std", ["option"])?;
219 /// assert_eq!(item.as_crate(), Some("std"));
220 ///
221 /// let mut it = item.iter();
222 /// assert_eq!(it.next(), Some(ComponentRef::Crate("std")));
223 /// assert_eq!(it.next(), Some(ComponentRef::Str("option")));
224 /// assert_eq!(it.next(), None);
225 /// # Ok::<(), rune::support::Error>(())
226 /// ```
227pub fn with_crate_item<I>(name: &str, iter: I) -> alloc::Result<Self>
228where
229I: IntoIterator,
230 I::Item: IntoComponent,
231 {
232let mut content = Vec::new();
233 ComponentRef::Crate(name).write_component(&mut content)?;
234235for c in iter {
236 c.write_component(&mut content)?;
237 }
238239Ok(Self { content })
240 }
241}
242243impl<A: Allocator> Default for ItemBuf<A>
244where
245A: Default,
246{
247fn default() -> Self {
248Self {
249 content: Vec::new_in(A::default()),
250 }
251 }
252}
253254impl<A: Allocator> PartialEq for ItemBuf<A> {
255#[inline]
256fn eq(&self, other: &Self) -> bool {
257self.content == other.content
258 }
259}
260261impl<A: Allocator> Eq for ItemBuf<A> {}
262263impl<A: Allocator> PartialOrd for ItemBuf<A> {
264fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
265Some(self.content.cmp(&other.content))
266 }
267}
268269impl<A: Allocator> Ord for ItemBuf<A> {
270fn cmp(&self, other: &Self) -> Ordering {
271self.content.cmp(&other.content)
272 }
273}
274275impl<A: Allocator> Hash for ItemBuf<A> {
276fn hash<H: Hasher>(&self, state: &mut H) {
277self.content.hash(state);
278 }
279}
280281impl<A: Allocator + Clone> TryClone for ItemBuf<A> {
282#[inline]
283fn try_clone(&self) -> alloc::Result<Self> {
284Ok(Self {
285 content: self.content.try_clone()?,
286 })
287 }
288}
289290impl<A: Allocator> AsRef<Item> for ItemBuf<A> {
291#[inline]
292fn as_ref(&self) -> &Item {
293self
294}
295}
296297impl<A: Allocator> Borrow<Item> for ItemBuf<A> {
298#[inline]
299fn borrow(&self) -> &Item {
300self
301}
302}
303304impl<C, A: Allocator> TryFromIteratorIn<C, A> for ItemBuf<A>
305where
306C: IntoComponent,
307{
308#[inline]
309fn try_from_iter_in<T: IntoIterator<Item = C>>(iter: T, alloc: A) -> alloc::Result<Self> {
310Self::with_item_in(iter, alloc)
311 }
312}
313314impl<A: Allocator> Deref for ItemBuf<A> {
315type Target = Item;
316317fn deref(&self) -> &Self::Target {
318// SAFETY: Item ensures that content is valid.
319unsafe { Item::from_bytes(self.content.as_ref()) }
320 }
321}
322323/// Format implementation for an [ItemBuf], defers to [Item].
324impl<A: Allocator> fmt::Display for ItemBuf<A> {
325fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
326 Item::fmt(self, f)
327 }
328}
329330impl<A: Allocator> fmt::Debug for ItemBuf<A> {
331fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
332 Item::fmt(self, f)
333 }
334}
335336impl<'a, A: Allocator> IntoIterator for &'a ItemBuf<A> {
337type IntoIter = Iter<'a>;
338type Item = ComponentRef<'a>;
339340fn into_iter(self) -> Self::IntoIter {
341self.iter()
342 }
343}
344345impl<A: Allocator> PartialEq<Item> for ItemBuf<A> {
346fn eq(&self, other: &Item) -> bool {
347self.content.as_slice() == other.as_bytes()
348 }
349}
350351impl<A: Allocator> PartialEq<Item> for &ItemBuf<A> {
352fn eq(&self, other: &Item) -> bool {
353self.content.as_slice() == other.as_bytes()
354 }
355}
356357impl<A: Allocator> PartialEq<&Item> for ItemBuf<A> {
358fn eq(&self, other: &&Item) -> bool {
359self.content.as_slice() == other.as_bytes()
360 }
361}
362363impl<A: Allocator> PartialEq<Iter<'_>> for ItemBuf<A> {
364fn eq(&self, other: &Iter<'_>) -> bool {
365self == other.as_item()
366 }
367}
368369impl<A: Allocator> PartialEq<Iter<'_>> for &ItemBuf<A> {
370fn eq(&self, other: &Iter<'_>) -> bool {
371*self == other.as_item()
372 }
373}
374375/// Error when parsing an item.
376#[derive(Debug)]
377#[non_exhaustive]
378pub struct FromStrError {
379 kind: FromStrErrorKind,
380}
381382impl From<alloc::Error> for FromStrError {
383fn from(error: alloc::Error) -> Self {
384Self {
385 kind: FromStrErrorKind::AllocError(error),
386 }
387 }
388}
389390impl From<FromStrErrorKind> for FromStrError {
391fn from(kind: FromStrErrorKind) -> Self {
392Self { kind }
393 }
394}
395396#[derive(Debug)]
397enum FromStrErrorKind {
398/// Error during parse.
399ParseError,
400/// An error occured when allocating.
401AllocError(alloc::Error),
402}
403404impl fmt::Display for FromStrError {
405#[inline]
406fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
407match &self.kind {
408 FromStrErrorKind::ParseError => write!(f, "String is not a valid item"),
409 FromStrErrorKind::AllocError(error) => error.fmt(f),
410 }
411 }
412}
413414impl core::error::Error for FromStrError {}
415416impl<A: Allocator> FromStr for ItemBuf<A>
417where
418A: Default,
419{
420type Err = FromStrError;
421422fn from_str(s: &str) -> Result<Self, Self::Err> {
423let mut item = ItemBuf::new_in(A::default());
424425let (s, mut next_crate) = if let Some(remainder) = s.strip_prefix("::") {
426 (remainder, true)
427 } else {
428 (s, false)
429 };
430431for c in s.split("::") {
432if take(&mut next_crate) {
433 item.push(ComponentRef::Crate(c))?;
434 } else if let Some(num) = c.strip_prefix('$') {
435 item.push(ComponentRef::Id(
436 num.parse().map_err(|_| FromStrErrorKind::ParseError)?,
437 ))?;
438 } else {
439 item.push(ComponentRef::Str(c))?;
440 }
441 }
442443Ok(item)
444 }
445}