rune_core/item/
into_component.rs

1use core::hash::{self, Hash};
2
3#[cfg(feature = "alloc")]
4use crate::alloc::alloc::Allocator;
5#[cfg(feature = "alloc")]
6use crate::alloc::borrow::Cow;
7#[cfg(feature = "alloc")]
8use crate::alloc::clone::TryClone;
9#[cfg(feature = "alloc")]
10use crate::alloc::{self, Box, String, Vec};
11
12#[cfg(feature = "alloc")]
13use crate::item::Component;
14use crate::item::{internal, ComponentRef};
15
16/// Trait for encoding the current type into a [Component].
17pub trait IntoComponent: Sized {
18    /// Convert into a component directly.
19    fn as_component_ref(&self) -> ComponentRef<'_>;
20
21    /// Convert into component.
22    #[inline]
23    #[cfg(feature = "alloc")]
24    fn into_component(self) -> alloc::Result<Component> {
25        into_component(self.as_component_ref())
26    }
27
28    /// Write a component directly to a buffer.
29    #[inline]
30    #[doc(hidden)]
31    #[cfg(feature = "alloc")]
32    fn write_component<A>(self, output: &mut Vec<u8, A>) -> alloc::Result<()>
33    where
34        A: Allocator,
35    {
36        write_component(self.as_component_ref(), output)
37    }
38
39    /// Hash the current component.
40    #[inline]
41    #[doc(hidden)]
42    fn hash_component<H>(self, hasher: &mut H)
43    where
44        H: hash::Hasher,
45    {
46        hash_component(self.as_component_ref(), hasher)
47    }
48}
49
50/// IntoCompoment implementation preserved for backwards compatibility.
51impl<T> IntoComponent for [T; 1]
52where
53    T: IntoComponent,
54{
55    fn as_component_ref(&self) -> ComponentRef<'_> {
56        let [this] = self;
57        this.as_component_ref()
58    }
59
60    #[inline]
61    #[cfg(feature = "alloc")]
62    fn into_component(self) -> alloc::Result<Component> {
63        let [this] = self;
64        this.into_component()
65    }
66
67    #[inline]
68    #[doc(hidden)]
69    #[cfg(feature = "alloc")]
70    fn write_component<A>(self, output: &mut Vec<u8, A>) -> alloc::Result<()>
71    where
72        A: Allocator,
73    {
74        let [this] = self;
75        this.write_component(output)
76    }
77
78    #[inline]
79    fn hash_component<H>(self, hasher: &mut H)
80    where
81        H: hash::Hasher,
82    {
83        let [this] = self;
84        this.hash_component(hasher)
85    }
86}
87
88impl IntoComponent for ComponentRef<'_> {
89    #[inline]
90    fn as_component_ref(&self) -> ComponentRef<'_> {
91        *self
92    }
93
94    #[inline]
95    #[cfg(feature = "alloc")]
96    fn into_component(self) -> alloc::Result<Component> {
97        into_component(self)
98    }
99}
100
101impl IntoComponent for &ComponentRef<'_> {
102    #[inline]
103    fn as_component_ref(&self) -> ComponentRef<'_> {
104        **self
105    }
106
107    #[inline]
108    #[cfg(feature = "alloc")]
109    fn into_component(self) -> alloc::Result<Component> {
110        into_component(*self)
111    }
112}
113
114#[cfg(feature = "alloc")]
115impl IntoComponent for Component {
116    #[inline]
117    fn as_component_ref(&self) -> ComponentRef<'_> {
118        Component::as_component_ref(self)
119    }
120
121    #[inline]
122    fn into_component(self) -> alloc::Result<Component> {
123        Ok(self)
124    }
125}
126
127#[cfg(feature = "alloc")]
128impl IntoComponent for &Component {
129    #[inline]
130    fn as_component_ref(&self) -> ComponentRef<'_> {
131        Component::as_component_ref(self)
132    }
133
134    #[inline]
135    fn into_component(self) -> alloc::Result<Component> {
136        self.try_clone()
137    }
138}
139
140macro_rules! impl_into_component_for_str {
141    ($ty:ty, $slf:ident, $into:expr) => {
142        impl IntoComponent for $ty {
143            fn as_component_ref(&self) -> ComponentRef<'_> {
144                ComponentRef::Str(self.as_ref())
145            }
146
147            #[cfg(feature = "alloc")]
148            fn into_component($slf) -> alloc::Result<Component> {
149                Ok(Component::Str($into))
150            }
151
152            #[cfg(feature = "alloc")]
153            fn write_component<A>(self, output: &mut Vec<u8, A>) -> alloc::Result<()>
154            where
155                A: Allocator,
156            {
157                internal::write_str(self.as_ref(), output)
158            }
159
160            fn hash_component<H>(self, hasher: &mut H)
161            where
162                H: hash::Hasher,
163            {
164                internal::hash_str(self.as_ref(), hasher);
165            }
166        }
167    }
168}
169
170impl_into_component_for_str!(&str, self, self.try_into()?);
171impl_into_component_for_str!(&&str, self, (*self).try_into()?);
172#[cfg(feature = "alloc")]
173impl_into_component_for_str!(String, self, self.as_str().try_into()?);
174#[cfg(feature = "alloc")]
175impl_into_component_for_str!(&String, self, self.as_str().try_into()?);
176#[cfg(feature = "alloc")]
177impl_into_component_for_str!(Box<str>, self, self);
178#[cfg(feature = "alloc")]
179impl_into_component_for_str!(&Box<str>, self, self.try_clone()?);
180#[cfg(feature = "alloc")]
181impl_into_component_for_str!(Cow<'_, str>, self, self.as_ref().try_into()?);
182#[cfg(feature = "alloc")]
183impl_into_component_for_str!(
184    rust_alloc::borrow::Cow<'_, str>,
185    self,
186    self.as_ref().try_into()?
187);
188
189/// Convert into an owned component.
190#[cfg(feature = "alloc")]
191fn into_component(component: ComponentRef<'_>) -> alloc::Result<Component> {
192    Ok(match component {
193        ComponentRef::Crate(s) => Component::Crate(s.try_into()?),
194        ComponentRef::Str(s) => Component::Str(s.try_into()?),
195        ComponentRef::Id(n) => Component::Id(n),
196    })
197}
198
199/// Write the current component to the given vector.
200#[cfg(feature = "alloc")]
201fn write_component<A>(component: ComponentRef<'_>, output: &mut Vec<u8, A>) -> alloc::Result<()>
202where
203    A: Allocator,
204{
205    match component {
206        ComponentRef::Crate(s) => internal::write_crate(s, output),
207        ComponentRef::Str(s) => internal::write_str(s, output),
208        ComponentRef::Id(c) => internal::write_tag(output, internal::ID, c),
209    }
210}
211
212/// Hash the current component to the given hasher.
213fn hash_component<H>(component: ComponentRef<'_>, hasher: &mut H)
214where
215    H: hash::Hasher,
216{
217    match component {
218        ComponentRef::Crate(s) => {
219            internal::CRATE.hash(hasher);
220            s.hash(hasher);
221        }
222        ComponentRef::Str(s) => {
223            internal::STRING.hash(hasher);
224            s.hash(hasher);
225        }
226        ComponentRef::Id(c) => {
227            internal::ID.hash(hasher);
228            c.hash(hasher);
229        }
230    }
231}