rune_core/item/
item_buf.rs1use 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;
8
9use crate::alloc::alloc::{Allocator, Global};
10use crate::alloc::clone::TryClone;
11use crate::alloc::iter::TryFromIteratorIn;
12use crate::alloc::{self, Vec};
13
14use crate::item::{ComponentRef, IntoComponent, Item, Iter};
15
16#[repr(transparent)]
65pub struct ItemBuf<A: Allocator = Global> {
66 content: Vec<u8, A>,
67}
68
69impl<A: Allocator> ItemBuf<A> {
70 pub(crate) const fn new_in(alloc: A) -> Self {
72 Self {
73 content: Vec::new_in(alloc),
74 }
75 }
76
77 pub(super) const unsafe fn from_raw(content: Vec<u8, A>) -> Self {
83 Self { content }
84 }
85
86 pub(crate) fn with_item_in(
88 iter: impl IntoIterator<Item: IntoComponent>,
89 alloc: A,
90 ) -> alloc::Result<Self> {
91 let mut content = Vec::new_in(alloc);
92
93 for c in iter {
94 c.write_component(&mut content)?;
95 }
96
97 Ok(Self { content })
98 }
99
100 pub fn push<C>(&mut self, c: C) -> alloc::Result<()>
102 where
103 C: IntoComponent,
104 {
105 c.write_component(&mut self.content)?;
106 Ok(())
107 }
108
109 pub fn pop(&mut self) -> bool {
111 let mut it = self.iter();
112
113 if it.next_back().is_none() {
114 return false;
115 };
116
117 let new_len = it.len();
118
119 unsafe {
123 debug_assert!(new_len < self.content.len());
124 self.content.set_len(new_len);
125 }
126
127 true
128 }
129
130 pub fn extend<I>(&mut self, i: I) -> alloc::Result<()>
132 where
133 I: IntoIterator,
134 I::Item: IntoComponent,
135 {
136 for c in i {
137 self.push(c)?;
138 }
139
140 Ok(())
141 }
142
143 pub fn clear(&mut self) {
145 self.content.clear();
146 }
147}
148
149impl ItemBuf {
150 pub const fn new() -> Self {
163 Self {
164 content: Vec::new(),
165 }
166 }
167
168 pub fn with_item(iter: impl IntoIterator<Item: IntoComponent>) -> alloc::Result<Self> {
185 Self::with_item_in(iter, Global)
186 }
187
188 pub fn with_crate(name: &str) -> alloc::Result<Self> {
207 Self::with_item(&[ComponentRef::Crate(name)])
208 }
209
210 pub fn with_crate_item<I>(name: &str, iter: I) -> alloc::Result<Self>
228 where
229 I: IntoIterator,
230 I::Item: IntoComponent,
231 {
232 let mut content = Vec::new();
233 ComponentRef::Crate(name).write_component(&mut content)?;
234
235 for c in iter {
236 c.write_component(&mut content)?;
237 }
238
239 Ok(Self { content })
240 }
241}
242
243impl<A: Allocator> Default for ItemBuf<A>
244where
245 A: Default,
246{
247 fn default() -> Self {
248 Self {
249 content: Vec::new_in(A::default()),
250 }
251 }
252}
253
254impl<A: Allocator> PartialEq for ItemBuf<A> {
255 #[inline]
256 fn eq(&self, other: &Self) -> bool {
257 self.content == other.content
258 }
259}
260
261impl<A: Allocator> Eq for ItemBuf<A> {}
262
263impl<A: Allocator> PartialOrd for ItemBuf<A> {
264 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
265 Some(self.cmp(other))
266 }
267}
268
269impl<A: Allocator> Ord for ItemBuf<A> {
270 fn cmp(&self, other: &Self) -> Ordering {
271 self.content.cmp(&other.content)
272 }
273}
274
275impl<A: Allocator> Hash for ItemBuf<A> {
276 fn hash<H: Hasher>(&self, state: &mut H) {
277 self.content.hash(state);
278 }
279}
280
281impl<A: Allocator + Clone> TryClone for ItemBuf<A> {
282 #[inline]
283 fn try_clone(&self) -> alloc::Result<Self> {
284 Ok(Self {
285 content: self.content.try_clone()?,
286 })
287 }
288}
289
290impl<A: Allocator> AsRef<Item> for ItemBuf<A> {
291 #[inline]
292 fn as_ref(&self) -> &Item {
293 self
294 }
295}
296
297impl<A: Allocator> Borrow<Item> for ItemBuf<A> {
298 #[inline]
299 fn borrow(&self) -> &Item {
300 self
301 }
302}
303
304impl<C, A: Allocator> TryFromIteratorIn<C, A> for ItemBuf<A>
305where
306 C: IntoComponent,
307{
308 #[inline]
309 fn try_from_iter_in<T: IntoIterator<Item = C>>(iter: T, alloc: A) -> alloc::Result<Self> {
310 Self::with_item_in(iter, alloc)
311 }
312}
313
314impl<A: Allocator> Deref for ItemBuf<A> {
315 type Target = Item;
316
317 fn deref(&self) -> &Self::Target {
318 unsafe { Item::from_bytes(self.content.as_ref()) }
320 }
321}
322
323impl<A: Allocator> fmt::Display for ItemBuf<A> {
325 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
326 Item::fmt(self, f)
327 }
328}
329
330impl<A: Allocator> fmt::Debug for ItemBuf<A> {
331 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
332 Item::fmt(self, f)
333 }
334}
335
336impl<'a, A: Allocator> IntoIterator for &'a ItemBuf<A> {
337 type IntoIter = Iter<'a>;
338 type Item = ComponentRef<'a>;
339
340 fn into_iter(self) -> Self::IntoIter {
341 self.iter()
342 }
343}
344
345impl<A: Allocator> PartialEq<Item> for ItemBuf<A> {
346 fn eq(&self, other: &Item) -> bool {
347 self.content.as_slice() == other.as_bytes()
348 }
349}
350
351impl<A: Allocator> PartialEq<Item> for &ItemBuf<A> {
352 fn eq(&self, other: &Item) -> bool {
353 self.content.as_slice() == other.as_bytes()
354 }
355}
356
357impl<A: Allocator> PartialEq<&Item> for ItemBuf<A> {
358 fn eq(&self, other: &&Item) -> bool {
359 self.content.as_slice() == other.as_bytes()
360 }
361}
362
363impl<A: Allocator> PartialEq<Iter<'_>> for ItemBuf<A> {
364 fn eq(&self, other: &Iter<'_>) -> bool {
365 self == other.as_item()
366 }
367}
368
369impl<A: Allocator> PartialEq<Iter<'_>> for &ItemBuf<A> {
370 fn eq(&self, other: &Iter<'_>) -> bool {
371 *self == other.as_item()
372 }
373}
374
375#[derive(Debug)]
377#[non_exhaustive]
378pub struct FromStrError {
379 kind: FromStrErrorKind,
380}
381
382impl From<alloc::Error> for FromStrError {
383 fn from(error: alloc::Error) -> Self {
384 Self {
385 kind: FromStrErrorKind::AllocError(error),
386 }
387 }
388}
389
390impl From<FromStrErrorKind> for FromStrError {
391 fn from(kind: FromStrErrorKind) -> Self {
392 Self { kind }
393 }
394}
395
396#[derive(Debug)]
397enum FromStrErrorKind {
398 ParseError,
400 AllocError(alloc::Error),
402}
403
404impl fmt::Display for FromStrError {
405 #[inline]
406 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
407 match &self.kind {
408 FromStrErrorKind::ParseError => write!(f, "String is not a valid item"),
409 FromStrErrorKind::AllocError(error) => error.fmt(f),
410 }
411 }
412}
413
414impl core::error::Error for FromStrError {}
415
416impl<A: Allocator> FromStr for ItemBuf<A>
417where
418 A: Default,
419{
420 type Err = FromStrError;
421
422 fn from_str(s: &str) -> Result<Self, Self::Err> {
423 let mut item = ItemBuf::new_in(A::default());
424
425 let (s, mut next_crate) = if let Some(remainder) = s.strip_prefix("::") {
426 (remainder, true)
427 } else {
428 (s, false)
429 };
430
431 for c in s.split("::") {
432 if 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 }
442
443 Ok(item)
444 }
445}