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