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 = Global>
66where
67 A: Allocator,
68{
69 content: Vec<u8, A>,
70}
71
72impl<A> ItemBuf<A>
73where
74 A: Allocator,
75{
76 #[inline]
78 pub(crate) const fn new_in(alloc: A) -> Self {
79 Self {
80 content: Vec::new_in(alloc),
81 }
82 }
83
84 #[inline]
90 pub(super) const unsafe fn from_raw(content: Vec<u8, A>) -> Self {
91 Self { content }
92 }
93
94 #[inline]
96 pub(crate) fn with_item_in(
97 iter: impl IntoIterator<Item: IntoComponent>,
98 alloc: A,
99 ) -> alloc::Result<Self> {
100 let mut content = Vec::new_in(alloc);
101
102 for c in iter {
103 c.write_component(&mut content)?;
104 }
105
106 Ok(Self { content })
107 }
108
109 #[inline]
111 pub fn push(&mut self, c: impl IntoComponent) -> alloc::Result<()> {
112 c.write_component(&mut self.content)?;
113 Ok(())
114 }
115
116 pub fn pop(&mut self) -> bool {
118 let mut it = self.iter();
119
120 if it.next_back().is_none() {
121 return false;
122 };
123
124 let new_len = it.len();
125
126 unsafe {
130 debug_assert!(new_len < self.content.len());
131 self.content.set_len(new_len);
132 }
133
134 true
135 }
136
137 #[inline]
139 pub fn extend(&mut self, iter: impl IntoIterator<Item: IntoComponent>) -> alloc::Result<()> {
140 for c in iter {
141 self.push(c)?;
142 }
143
144 Ok(())
145 }
146
147 #[inline]
149 pub fn clear(&mut self) {
150 self.content.clear();
151 }
152}
153
154impl ItemBuf {
155 pub const fn new() -> Self {
168 Self {
169 content: Vec::new(),
170 }
171 }
172
173 pub fn with_item(iter: impl IntoIterator<Item: IntoComponent>) -> alloc::Result<Self> {
190 Self::with_item_in(iter, Global)
191 }
192
193 pub fn with_crate(name: &str) -> alloc::Result<Self> {
212 Self::with_item(&[ComponentRef::Crate(name)])
213 }
214
215 #[inline]
233 pub fn with_crate_item(
234 name: &str,
235 iter: impl IntoIterator<Item: IntoComponent>,
236 ) -> alloc::Result<Self> {
237 let mut content = Vec::new();
238 ComponentRef::Crate(name).write_component(&mut content)?;
239
240 for c in iter {
241 c.write_component(&mut content)?;
242 }
243
244 Ok(Self { content })
245 }
246}
247
248impl<A> Default for ItemBuf<A>
249where
250 A: Allocator + Default,
251{
252 #[inline]
253 fn default() -> Self {
254 Self {
255 content: Vec::new_in(A::default()),
256 }
257 }
258}
259
260impl<A> PartialEq for ItemBuf<A>
261where
262 A: Allocator,
263{
264 #[inline]
265 fn eq(&self, other: &Self) -> bool {
266 self.content == other.content
267 }
268}
269
270impl<A> Eq for ItemBuf<A> where A: Allocator {}
271
272impl<A> PartialOrd for ItemBuf<A>
273where
274 A: Allocator,
275{
276 #[inline]
277 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
278 Some(self.cmp(other))
279 }
280}
281
282impl<A> Ord for ItemBuf<A>
283where
284 A: Allocator,
285{
286 #[inline]
287 fn cmp(&self, other: &Self) -> Ordering {
288 self.content.cmp(&other.content)
289 }
290}
291
292impl<A> Hash for ItemBuf<A>
293where
294 A: Allocator,
295{
296 #[inline]
297 fn hash<H>(&self, state: &mut H)
298 where
299 H: Hasher,
300 {
301 self.content.hash(state);
302 }
303}
304
305impl<A> TryClone for ItemBuf<A>
306where
307 A: Allocator + Clone,
308{
309 #[inline]
310 fn try_clone(&self) -> alloc::Result<Self> {
311 Ok(Self {
312 content: self.content.try_clone()?,
313 })
314 }
315}
316
317impl<A> AsRef<Item> for ItemBuf<A>
318where
319 A: Allocator,
320{
321 #[inline]
322 fn as_ref(&self) -> &Item {
323 self
324 }
325}
326
327impl<A> Borrow<Item> for ItemBuf<A>
328where
329 A: Allocator,
330{
331 #[inline]
332 fn borrow(&self) -> &Item {
333 self
334 }
335}
336
337impl<C, A> TryFromIteratorIn<C, A> for ItemBuf<A>
338where
339 C: IntoComponent,
340 A: Allocator,
341{
342 #[inline]
343 fn try_from_iter_in<T: IntoIterator<Item = C>>(iter: T, alloc: A) -> alloc::Result<Self> {
344 Self::with_item_in(iter, alloc)
345 }
346}
347
348impl<A> Deref for ItemBuf<A>
349where
350 A: Allocator,
351{
352 type Target = Item;
353
354 #[inline]
355 fn deref(&self) -> &Self::Target {
356 unsafe { Item::from_bytes(self.content.as_ref()) }
358 }
359}
360
361impl<A> fmt::Display for ItemBuf<A>
363where
364 A: Allocator,
365{
366 #[inline]
367 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
368 Item::fmt(self, f)
369 }
370}
371
372impl<A> fmt::Debug for ItemBuf<A>
373where
374 A: Allocator,
375{
376 #[inline]
377 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
378 Item::fmt(self, f)
379 }
380}
381
382impl<'a, A> IntoIterator for &'a ItemBuf<A>
383where
384 A: Allocator,
385{
386 type IntoIter = Iter<'a>;
387 type Item = ComponentRef<'a>;
388
389 #[inline]
390 fn into_iter(self) -> Self::IntoIter {
391 self.iter()
392 }
393}
394
395impl<A> PartialEq<Item> for ItemBuf<A>
396where
397 A: Allocator,
398{
399 #[inline]
400 fn eq(&self, other: &Item) -> bool {
401 self.content.as_slice() == other.as_bytes()
402 }
403}
404
405impl<A> PartialEq<Item> for &ItemBuf<A>
406where
407 A: Allocator,
408{
409 #[inline]
410 fn eq(&self, other: &Item) -> bool {
411 self.content.as_slice() == other.as_bytes()
412 }
413}
414
415impl<A> PartialEq<&Item> for ItemBuf<A>
416where
417 A: Allocator,
418{
419 #[inline]
420 fn eq(&self, other: &&Item) -> bool {
421 self.content.as_slice() == other.as_bytes()
422 }
423}
424
425impl<A> PartialEq<Iter<'_>> for ItemBuf<A>
426where
427 A: Allocator,
428{
429 #[inline]
430 fn eq(&self, other: &Iter<'_>) -> bool {
431 self == other.as_item()
432 }
433}
434
435impl<A> PartialEq<Iter<'_>> for &ItemBuf<A>
436where
437 A: Allocator,
438{
439 #[inline]
440 fn eq(&self, other: &Iter<'_>) -> bool {
441 *self == other.as_item()
442 }
443}
444
445#[derive(Debug)]
447#[non_exhaustive]
448pub struct FromStrError {
449 kind: FromStrErrorKind,
450}
451
452impl From<alloc::Error> for FromStrError {
453 #[inline]
454 fn from(error: alloc::Error) -> Self {
455 Self {
456 kind: FromStrErrorKind::AllocError(error),
457 }
458 }
459}
460
461impl From<FromStrErrorKind> for FromStrError {
462 #[inline]
463 fn from(kind: FromStrErrorKind) -> Self {
464 Self { kind }
465 }
466}
467
468#[derive(Debug)]
469enum FromStrErrorKind {
470 ParseError,
472 AllocError(alloc::Error),
474}
475
476impl fmt::Display for FromStrError {
477 #[inline]
478 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
479 match &self.kind {
480 FromStrErrorKind::ParseError => write!(f, "String is not a valid item"),
481 FromStrErrorKind::AllocError(error) => error.fmt(f),
482 }
483 }
484}
485
486impl core::error::Error for FromStrError {}
487
488impl<A> FromStr for ItemBuf<A>
489where
490 A: Allocator + Default,
491{
492 type Err = FromStrError;
493
494 fn from_str(s: &str) -> Result<Self, Self::Err> {
495 let mut item = ItemBuf::new_in(A::default());
496
497 let (s, mut next_crate) = if let Some(remainder) = s.strip_prefix("::") {
498 (remainder, true)
499 } else {
500 (s, false)
501 };
502
503 for c in s.split("::") {
504 if take(&mut next_crate) {
505 item.push(ComponentRef::Crate(c))?;
506 } else if let Some(num) = c.strip_prefix('$') {
507 item.push(ComponentRef::Id(
508 num.parse().map_err(|_| FromStrErrorKind::ParseError)?,
509 ))?;
510 } else {
511 item.push(ComponentRef::Str(c))?;
512 }
513 }
514
515 Ok(item)
516 }
517}