1use crate::rust::mem::MaybeUninit;
2use crate::value_kind::*;
3use crate::*;
4
5impl<X: CustomValueKind, T> Categorize<X> for [T] {
6 #[inline]
7 fn value_kind() -> ValueKind<X> {
8 ValueKind::Array
9 }
10}
11
12impl<X: CustomValueKind, T, const N: usize> Categorize<X> for [T; N] {
13 #[inline]
14 fn value_kind() -> ValueKind<X> {
15 ValueKind::Array
16 }
17}
18
19impl<X: CustomValueKind, E: Encoder<X>, T: Encode<X, E> + Categorize<X>> Encode<X, E> for [T] {
20 #[inline]
21 fn encode_value_kind(&self, encoder: &mut E) -> Result<(), EncodeError> {
22 encoder.write_value_kind(Self::value_kind())
23 }
24
25 #[inline]
26 fn encode_body(&self, encoder: &mut E) -> Result<(), EncodeError> {
27 encoder.write_value_kind(T::value_kind())?;
28 encoder.write_size(self.len())?;
29 if T::value_kind() == ValueKind::U8 || T::value_kind() == ValueKind::I8 {
30 let ptr = self.as_ptr().cast::<u8>();
31 let slice = unsafe { sbor::rust::slice::from_raw_parts(ptr, self.len()) };
32 encoder.write_slice(slice)?;
33 } else {
34 for v in self {
35 encoder.encode_deeper_body(v)?;
36 }
37 }
38 Ok(())
39 }
40}
41
42impl<X: CustomValueKind, E: Encoder<X>, T: Encode<X, E> + Categorize<X>, const N: usize>
43 Encode<X, E> for [T; N]
44{
45 #[inline]
46 fn encode_value_kind(&self, encoder: &mut E) -> Result<(), EncodeError> {
47 encoder.write_value_kind(Self::value_kind())
48 }
49 #[inline]
50 fn encode_body(&self, encoder: &mut E) -> Result<(), EncodeError> {
51 self.as_slice().encode_body(encoder)
52 }
53}
54
55#[allow(clippy::forget_non_drop)]
56impl<X: CustomValueKind, D: Decoder<X>, T: Decode<X, D> + Categorize<X>, const N: usize>
57 Decode<X, D> for [T; N]
58{
59 #[inline]
60 fn decode_body_with_value_kind(
61 decoder: &mut D,
62 value_kind: ValueKind<X>,
63 ) -> Result<Self, DecodeError> {
64 decoder.check_preloaded_value_kind(value_kind, Self::value_kind())?;
65 let element_value_kind = decoder.read_and_check_value_kind(T::value_kind())?;
66 decoder.read_and_check_size(N)?;
67
68 let mut data: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
76
77 for elem in &mut data[..] {
79 elem.write(decoder.decode_deeper_body_with_value_kind(element_value_kind)?);
80 }
81
82 let ptr = &mut data as *mut _ as *mut [T; N];
84 let res = unsafe { ptr.read() };
85 core::mem::forget(data);
86
87 Ok(res)
88 }
89}
90
91mod schema {
92 use super::*;
93
94 impl<C: CustomTypeKind<RustTypeId>, T: Describe<C>> Describe<C> for [T] {
95 const TYPE_ID: RustTypeId = match T::TYPE_ID {
96 RustTypeId::WellKnown(basic_well_known_types::U8_TYPE) => {
97 RustTypeId::WellKnown(basic_well_known_types::BYTES_TYPE)
98 }
99 _ => RustTypeId::novel("Array", &[T::TYPE_ID]),
100 };
101
102 fn type_data() -> TypeData<C, RustTypeId> {
103 match T::TYPE_ID {
104 RustTypeId::WellKnown(basic_well_known_types::U8_TYPE) => {
105 basic_well_known_types::bytes_type_data()
106 }
107 _ => TypeData::new(
108 TypeKind::Array {
109 element_type: T::TYPE_ID,
110 },
111 TypeMetadata::unnamed(),
112 ),
113 }
114 }
115
116 fn add_all_dependencies(aggregator: &mut TypeAggregator<C>) {
117 aggregator.add_child_type_and_descendents::<T>();
118 }
119 }
120
121 impl<C: CustomTypeKind<RustTypeId>, T: Describe<C>, const N: usize> Describe<C> for [T; N] {
122 const TYPE_ID: RustTypeId = RustTypeId::novel_validated(
123 "Array",
124 &[T::TYPE_ID],
125 &[("min", &N.to_le_bytes()), ("max", &N.to_le_bytes())],
126 );
127
128 fn type_data() -> TypeData<C, RustTypeId> {
129 let size = N
130 .try_into()
131 .expect("The array length is too large for a u32 for the SBOR schema");
132
133 TypeData::new(
134 TypeKind::Array {
135 element_type: T::TYPE_ID,
136 },
137 TypeMetadata::unnamed(),
138 )
139 .with_validation(TypeValidation::Array(LengthValidation {
140 min: Some(size),
141 max: Some(size),
142 }))
143 }
144
145 fn add_all_dependencies(aggregator: &mut TypeAggregator<C>) {
146 aggregator.add_child_type_and_descendents::<T>();
147 }
148 }
149}