typed_index_collections/slice/
boxed.rs1use alloc::boxed::Box;
2use alloc::vec;
3use core::iter::FromIterator;
4use core::mem::transmute;
5
6#[cfg(feature = "bincode")]
7use bincode::de::{BorrowDecode, BorrowDecoder, Decode, Decoder};
8#[cfg(feature = "bincode")]
9use bincode::error::DecodeError;
10#[cfg(all(feature = "alloc", feature = "serde"))]
11use serde::de::{Deserialize, Deserializer};
12
13use crate::{TiSlice, TiVec};
14
15impl<K, V> From<Box<TiSlice<K, V>>> for Box<[V]> {
16 #[inline]
17 fn from(slice: Box<TiSlice<K, V>>) -> Self {
18 unsafe { transmute::<Box<TiSlice<K, V>>, Self>(slice) }
20 }
21}
22
23impl<K, V> From<Box<[V]>> for Box<TiSlice<K, V>> {
24 #[inline]
25 fn from(slice: Box<[V]>) -> Self {
26 unsafe { transmute::<Box<[V]>, Self>(slice) }
28 }
29}
30
31impl<K, V: Clone> Clone for Box<TiSlice<K, V>> {
32 #[inline]
33 fn clone(&self) -> Self {
34 self.to_vec().into_boxed_slice()
35 }
36}
37
38impl<K, V> IntoIterator for Box<TiSlice<K, V>> {
39 type Item = V;
40 type IntoIter = vec::IntoIter<V>;
41
42 #[inline]
43 fn into_iter(self) -> Self::IntoIter {
44 self.into_vec().into_iter()
45 }
46}
47
48impl<K, V> Default for Box<TiSlice<K, V>> {
49 #[inline]
50 fn default() -> Self {
51 TiVec::new().into()
52 }
53}
54
55impl<K, V: Copy> From<&TiSlice<K, V>> for Box<TiSlice<K, V>> {
56 #[inline]
57 fn from(slice: &TiSlice<K, V>) -> Self {
58 Box::<[V]>::from(&slice.raw).into()
59 }
60}
61
62impl<K, V> From<Box<TiSlice<K, V>>> for TiVec<K, V> {
63 #[inline]
64 fn from(s: Box<TiSlice<K, V>>) -> Self {
65 s.into_vec()
66 }
67}
68
69impl<K, V> From<TiVec<K, V>> for Box<TiSlice<K, V>> {
70 #[inline]
71 fn from(v: TiVec<K, V>) -> Self {
72 v.into_boxed_slice()
73 }
74}
75
76impl<K, V> FromIterator<V> for Box<TiSlice<K, V>> {
77 #[inline]
78 fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
79 iter.into_iter().collect::<TiVec<K, V>>().into_boxed_slice()
80 }
81}
82
83#[cfg(feature = "serde")]
84#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "serde"))))]
85impl<'de, K, V> Deserialize<'de> for Box<TiSlice<K, V>>
86where
87 V: Deserialize<'de>,
88{
89 #[inline]
90 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
91 where
92 D: Deserializer<'de>,
93 {
94 Box::<[V]>::deserialize(deserializer).map(Into::into)
95 }
96}
97
98#[cfg(feature = "bincode")]
99#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "bincode"))))]
100impl<K, V, Context> Decode<Context> for Box<TiSlice<K, V>>
101where
102 V: 'static + Decode<Context>,
103{
104 #[inline]
105 fn decode<D>(decoder: &mut D) -> Result<Self, DecodeError>
106 where
107 D: Decoder<Context = Context>,
108 {
109 Box::<[V]>::decode(decoder).map(Into::into)
110 }
111}
112
113#[cfg(feature = "bincode")]
114#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "bincode"))))]
115impl<'de, K, V, Context> BorrowDecode<'de, Context> for Box<TiSlice<K, V>>
116where
117 V: 'de + BorrowDecode<'de, Context>,
118{
119 #[inline]
120 fn borrow_decode<D>(decoder: &mut D) -> Result<Self, DecodeError>
121 where
122 D: BorrowDecoder<'de, Context = Context>,
123 {
124 Box::<[V]>::borrow_decode(decoder).map(Into::into)
125 }
126}
127
128#[expect(dead_code, unused_imports, unused_mut, reason = "okay in tests")]
129#[cfg(test)]
130mod test {
131 use alloc::borrow::{Cow, ToOwned};
132 use alloc::boxed::Box;
133 use alloc::ffi::CString;
134 use alloc::string::ToString;
135 use alloc::vec::Vec;
136 use core::borrow::{Borrow, BorrowMut};
137 use core::hash::{Hash, Hasher};
138 use core::ops::Bound;
139 #[cfg(feature = "std")]
140 use std::hash::DefaultHasher;
141 #[cfg(feature = "std")]
142 use std::io::{IoSlice, Write};
143
144 use crate::test_util::{AsSliceAndCapacity, Id};
145 use crate::{TiSlice, TiVec};
146
147 #[test]
148 fn test_boxed_slice_api_compatibility() {
149 for v in [
150 &[0_u32; 0][..],
151 &[1],
152 &[1, 1234],
153 &[1, 2, 4],
154 &[1, 5, 3, 2],
155 &[1, 1, 9, 2, 4, 1, 12345, 12],
156 ] {
157 let mut cv = (v, TiSlice::from_ref(v));
158 assert_eq_api!(
159 cv, v => Box::<TheSlice<u32>>::from(v) == <Box<TheSlice<u32>>>::default()
160 );
161 assert_eq_api!(cv, v => Box::<TheSlice<_>>::from(v).into_std());
162 assert_eq_api!(cv, v => Box::<TheSlice<_>>::from(v).clone().into_std());
163 assert_eq_api!(
164 cv, v => IntoIterator::into_iter(Box::<TheSlice<u32>>::from(v)).collect::<Vec<_>>()
165 );
166 assert_eq_api!(cv, v => TheVec::from(Box::<TheSlice<_>>::from(v)).into_std());
167 assert_eq_api!(cv, v => Box::<TheSlice<_>>::from(TheVec::from(v)).into_std());
168 assert_eq_api!(cv, v => v.iter().copied().collect::<Box<TheSlice<_>>>().into_std());
169 }
170 }
171
172 #[expect(clippy::unwrap_used, reason = "okay in tests")]
173 #[cfg(feature = "serde")]
174 #[test]
175 fn test_boxed_slice_deserialize() {
176 let s0: Box<TiSlice<Id, u32>> = serde_json::from_str("[]").unwrap();
177 let s1: Box<TiSlice<Id, u32>> = serde_json::from_str("[12]").unwrap();
178 let s2: Box<TiSlice<Id, u32>> = serde_json::from_str("[23, 34]").unwrap();
179 assert_eq!(s0.as_ref().raw, [0; 0][..]);
180 assert_eq!(s1.as_ref().raw, [12][..]);
181 assert_eq!(s2.as_ref().raw, [23, 34][..]);
182 }
183
184 #[expect(clippy::unwrap_used, reason = "okay in tests")]
185 #[cfg(feature = "bincode")]
186 #[test]
187 fn test_boxed_slice_decode() {
188 fn decode_whole(bytes: &[u8]) -> Box<TiSlice<Id, u32>> {
189 let config = bincode::config::standard();
190 let (decoded, len) = bincode::decode_from_slice(bytes, config).unwrap();
191 assert_eq!(len, bytes.len());
192 decoded
193 }
194
195 let s0: Box<TiSlice<Id, u32>> = decode_whole(&[0]);
196 let s1: Box<TiSlice<Id, u32>> = decode_whole(&[1, 12]);
197 let s2: Box<TiSlice<Id, u32>> = decode_whole(&[2, 23, 34]);
198 let s3: Box<TiSlice<Id, u32>> =
199 decode_whole(&[2, 252, 0x78, 0x56, 0x34, 0x12, 252, 0x89, 0x67, 0x45, 0x23]);
200 assert_eq!(s0.as_ref().raw, [0; 0][..]);
201 assert_eq!(s1.as_ref().raw, [12][..]);
202 assert_eq!(s2.as_ref().raw, [23, 34][..]);
203 assert_eq!(s3.as_ref().raw, [0x1234_5678, 0x2345_6789][..]);
204 }
205
206 #[expect(clippy::unwrap_used, reason = "okay in tests")]
207 #[cfg(feature = "bincode")]
208 #[test]
209 fn test_boxed_slice_borrow_decode() {
210 fn decode_whole(bytes: &[u8]) -> Box<TiSlice<Id, &str>> {
211 let config = bincode::config::standard();
212 let (decoded, len) = bincode::borrow_decode_from_slice(bytes, config).unwrap();
213 assert_eq!(len, bytes.len());
214 decoded
215 }
216
217 let s0: Box<TiSlice<Id, &str>> = decode_whole(&[0]);
218 let s1: Box<TiSlice<Id, &str>> = decode_whole(&[1, 1, b'a']);
219 let s2: Box<TiSlice<Id, &str>> = decode_whole(&[2, 2, b'b', b'c', 3, b'd', b'e', b'f']);
220 assert_eq!(s0.as_ref().raw, [""; 0][..]);
221 assert_eq!(s1.as_ref().raw, ["a"][..]);
222 assert_eq!(s2.as_ref().raw, ["bc", "def"][..]);
223 }
224}