strict_encoding/
embedded.rs

1// Strict encoding library for deterministic binary serialization.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2019-2024 by
6//     Dr. Maxim Orlovsky <orlovsky@ubideco.org>
7//
8// Copyright 2022-2024 UBIDECO Labs
9//
10// Licensed under the Apache License, Version 2.0 (the "License");
11// you may not use this file except in compliance with the License.
12// You may obtain a copy of the License at
13//
14//     http://www.apache.org/licenses/LICENSE-2.0
15//
16// Unless required by applicable law or agreed to in writing, software
17// distributed under the License is distributed on an "AS IS" BASIS,
18// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19// See the License for the specific language governing permissions and
20// limitations under the License.
21
22use std::collections::{BTreeMap, BTreeSet, VecDeque};
23use std::hash::Hash;
24use std::io;
25use std::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8};
26
27use amplify::ascii::AsciiString;
28use amplify::confinement::Confined;
29#[cfg(feature = "float")]
30use amplify::num::apfloat::{ieee, Float};
31use amplify::num::{i1024, i256, i512, u1024, u24, u256, u40, u48, u512, u56};
32use amplify::{Array, Wrapper};
33
34use crate::stl::AsciiSym;
35use crate::{
36    DecodeError, DefineUnion, Primitive, RString, ReadRaw, ReadTuple, ReadUnion, RestrictedCharSet,
37    Sizing, StrictDecode, StrictDumb, StrictEncode, StrictProduct, StrictStruct, StrictSum,
38    StrictTuple, StrictType, StrictUnion, TypeName, TypedRead, TypedWrite, WriteRaw, WriteTuple,
39    WriteUnion, LIB_EMBEDDED,
40};
41
42pub trait DecodeRawLe: Sized {
43    fn decode_raw_le(reader: &mut (impl ReadRaw + ?Sized)) -> Result<Self, DecodeError>;
44}
45
46#[derive(
47    Wrapper, WrapperMut, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default, From
48)]
49#[wrapper(Display, FromStr, Octal, BitOps)]
50#[wrapper_mut(BitAssign)]
51#[derive(StrictType, StrictDecode)]
52#[strict_type(lib = LIB_EMBEDDED, crate = crate)]
53pub struct Byte(u8);
54
55impl StrictEncode for Byte {
56    fn strict_encode<W: TypedWrite>(&self, mut writer: W) -> io::Result<W> {
57        unsafe {
58            writer = writer.register_primitive(Primitive::BYTE);
59            writer.raw_writer().write_raw::<1>([self.0])?;
60        }
61        Ok(writer)
62    }
63}
64
65macro_rules! encode_num {
66    ($ty:ty, $id:ident) => {
67        impl $crate::StrictType for $ty {
68            const STRICT_LIB_NAME: &'static str = $crate::LIB_EMBEDDED;
69            fn strict_name() -> Option<TypeName> { Some(tn!(stringify!($id))) }
70        }
71        impl $crate::StrictEncode for $ty {
72            fn strict_encode<W: TypedWrite>(&self, mut writer: W) -> io::Result<W> {
73                unsafe {
74                    writer = writer.register_primitive(Primitive::$id);
75                    writer.raw_writer().write_raw_array(self.to_le_bytes())?;
76                }
77                Ok(writer)
78            }
79        }
80        impl $crate::DecodeRawLe for $ty {
81            fn decode_raw_le(reader: &mut (impl ReadRaw + ?Sized)) -> Result<Self, DecodeError> {
82                let buf = reader.read_raw_array::<{ Self::BITS as usize / 8 }>()?;
83                Ok(Self::from_le_bytes(buf))
84            }
85        }
86        impl $crate::StrictDecode for $ty {
87            fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
88                Self::decode_raw_le(unsafe { reader.raw_reader() })
89            }
90        }
91    };
92}
93
94macro_rules! encode_nonzero {
95    ($ty:ty, $p:ty, $id:ident) => {
96        impl $crate::StrictType for $ty {
97            const STRICT_LIB_NAME: &'static str = $crate::LIB_EMBEDDED;
98            fn strict_name() -> Option<TypeName> { Some(tn!(stringify!($id))) }
99        }
100        impl $crate::StrictEncode for $ty {
101            fn strict_encode<W: TypedWrite>(&self, mut writer: W) -> io::Result<W> {
102                unsafe {
103                    writer = writer.register_primitive(Primitive::$id);
104                    writer.raw_writer().write_raw_array(self.get().to_le_bytes())?;
105                }
106                Ok(writer)
107            }
108        }
109        impl $crate::StrictDecode for $ty {
110            fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
111                let buf =
112                    unsafe { reader.raw_reader().read_raw_array::<{ Self::BITS as usize / 8 }>()? };
113                let v = <$p>::from_le_bytes(buf);
114                Self::new(v).ok_or(DecodeError::ZeroNatural)
115            }
116        }
117    };
118}
119
120macro_rules! encode_float {
121    ($ty:ty, $len:literal, $id:ident) => {
122        #[cfg(feature = "float")]
123        impl $crate::StrictType for $ty {
124            const STRICT_LIB_NAME: &'static str = $crate::LIB_EMBEDDED;
125            fn strict_name() -> Option<TypeName> { Some(tn!(stringify!($id))) }
126        }
127        #[cfg(feature = "float")]
128        impl $crate::StrictEncode for $ty {
129            fn strict_encode<W: TypedWrite>(&self, mut writer: W) -> io::Result<W> {
130                let mut be = [0u8; $len];
131                be.copy_from_slice(&self.to_bits().to_le_bytes()[..$len]);
132                unsafe {
133                    writer = writer.register_primitive(Primitive::$id);
134                    writer.raw_writer().write_raw_array(be)?;
135                }
136                Ok(writer)
137            }
138        }
139        #[cfg(feature = "float")]
140        impl $crate::StrictDecode for $ty {
141            fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
142                const BYTES: usize = <$ty>::BITS / 8;
143                let mut inner = [0u8; 32];
144                let buf = unsafe { reader.raw_reader().read_raw_array::<BYTES>()? };
145                inner[..BYTES].copy_from_slice(&buf[..]);
146                let bits = u256::from_le_bytes(inner);
147                Ok(Self::from_bits(bits))
148            }
149        }
150    };
151}
152
153encode_num!(u8, U8);
154encode_num!(u16, U16);
155encode_num!(u24, U24);
156encode_num!(u32, U32);
157encode_num!(u40, U40);
158encode_num!(u48, U48);
159encode_num!(u56, U56);
160encode_num!(u64, U64);
161encode_num!(u128, U128);
162encode_num!(u256, U256);
163encode_num!(u512, U512);
164encode_num!(u1024, U1024);
165
166encode_num!(i8, I8);
167encode_num!(i16, I16);
168encode_num!(i32, I32);
169encode_num!(i64, I64);
170encode_num!(i128, I128);
171encode_num!(i256, I256);
172encode_num!(i512, I512);
173encode_num!(i1024, I1024);
174
175encode_nonzero!(NonZeroU8, u8, N8);
176encode_nonzero!(NonZeroU16, u16, N16);
177encode_nonzero!(NonZeroU32, u32, U32);
178encode_nonzero!(NonZeroU64, u64, U64);
179encode_nonzero!(NonZeroU128, u128, U128);
180
181encode_float!(ieee::Half, 2, F16);
182encode_float!(ieee::Single, 4, F32);
183encode_float!(ieee::Double, 8, F64);
184encode_float!(ieee::X87DoubleExtended, 10, F80);
185encode_float!(ieee::Quad, 16, F128);
186encode_float!(ieee::Oct, 32, F256);
187
188impl<T> StrictType for Box<T>
189where T: StrictType
190{
191    const STRICT_LIB_NAME: &'static str = T::STRICT_LIB_NAME;
192}
193impl<T> StrictSum for Box<T>
194where T: StrictSum
195{
196    const ALL_VARIANTS: &'static [(u8, &'static str)] = T::ALL_VARIANTS;
197    fn variant_name(&self) -> &'static str { self.as_ref().variant_name() }
198}
199impl<T> StrictProduct for Box<T> where T: Default + StrictProduct {}
200impl<T> StrictUnion for Box<T> where T: Default + StrictUnion {}
201impl<T> StrictTuple for Box<T>
202where T: Default + StrictTuple
203{
204    const FIELD_COUNT: u8 = T::FIELD_COUNT;
205}
206impl<T> StrictStruct for Box<T>
207where T: Default + StrictStruct
208{
209    const ALL_FIELDS: &'static [&'static str] = T::ALL_FIELDS;
210}
211impl<T> StrictEncode for Box<T>
212where T: StrictEncode
213{
214    fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
215        self.as_ref().strict_encode(writer)
216    }
217}
218impl<T> StrictDecode for Box<T>
219where T: StrictDecode
220{
221    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
222        T::strict_decode(reader).map(Box::new)
223    }
224}
225
226impl<T> StrictType for Option<T>
227where T: StrictType
228{
229    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
230    fn strict_name() -> Option<TypeName> { None }
231}
232impl<T> StrictSum for Option<T>
233where T: StrictType
234{
235    const ALL_VARIANTS: &'static [(u8, &'static str)] = &[(0u8, "none"), (1u8, "some")];
236    fn variant_name(&self) -> &'static str {
237        match self {
238            None => "none",
239            Some(_) => "some",
240        }
241    }
242}
243impl<T> StrictUnion for Option<T> where T: StrictType {}
244impl<T: StrictEncode + StrictDumb> StrictEncode for Option<T> {
245    fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
246        writer.write_union::<Self>(|u| {
247            let u = u.define_unit(vname!("none")).define_newtype::<T>(vname!("some")).complete();
248
249            Ok(match self {
250                None => u.write_unit(vname!("none")),
251                Some(val) => u.write_newtype(vname!("some"), val),
252            }?
253            .complete())
254        })
255    }
256}
257impl<T: StrictDecode> StrictDecode for Option<T> {
258    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
259        reader.read_union(|field_name, u| match field_name.as_str() {
260            "none" => Ok(None),
261            "some" => u.read_tuple(|r| r.read_field().map(Some)),
262            _ => unreachable!("unknown option field"),
263        })
264    }
265}
266
267impl StrictType for () {
268    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
269    fn strict_name() -> Option<TypeName> { None }
270}
271impl StrictEncode for () {
272    fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
273        Ok(unsafe { writer.register_primitive(Primitive::UNIT) })
274    }
275}
276impl StrictDecode for () {
277    fn strict_decode(_reader: &mut impl TypedRead) -> Result<Self, DecodeError> { Ok(()) }
278}
279
280impl<A: StrictType, B: StrictType> StrictType for (A, B) {
281    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
282    fn strict_name() -> Option<TypeName> { None }
283}
284impl<A: StrictType + Default, B: StrictType + Default> StrictProduct for (A, B) {}
285impl<A: StrictType + Default, B: StrictType + Default> StrictTuple for (A, B) {
286    const FIELD_COUNT: u8 = 2;
287}
288impl<A: StrictEncode + Default, B: StrictEncode + Default> StrictEncode for (A, B) {
289    fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
290        writer.write_tuple::<Self>(|w| Ok(w.write_field(&self.0)?.write_field(&self.1)?.complete()))
291    }
292}
293impl<A: StrictDecode + Default, B: StrictDecode + Default> StrictDecode for (A, B) {
294    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
295        reader.read_tuple(|r| {
296            let a = r.read_field()?;
297            let b = r.read_field()?;
298            Ok((a, b))
299        })
300    }
301}
302
303impl<A: StrictType, B: StrictType, C: StrictType> StrictType for (A, B, C) {
304    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
305    fn strict_name() -> Option<TypeName> { None }
306}
307impl<A: StrictType + Default, B: StrictType + Default, C: StrictType + Default> StrictProduct
308    for (A, B, C)
309{
310}
311impl<A: StrictType + Default, B: StrictType + Default, C: StrictType + Default> StrictTuple
312    for (A, B, C)
313{
314    const FIELD_COUNT: u8 = 3;
315}
316impl<A: StrictEncode + Default, B: StrictEncode + Default, C: StrictEncode + Default> StrictEncode
317    for (A, B, C)
318{
319    fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
320        writer.write_tuple::<Self>(|w| {
321            Ok(w.write_field(&self.0)?.write_field(&self.1)?.write_field(&self.2)?.complete())
322        })
323    }
324}
325impl<A: StrictDecode + Default, B: StrictDecode + Default, C: StrictDecode + Default> StrictDecode
326    for (A, B, C)
327{
328    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
329        reader.read_tuple(|r| {
330            let a = r.read_field()?;
331            let b = r.read_field()?;
332            let c = r.read_field()?;
333            Ok((a, b, c))
334        })
335    }
336}
337
338impl<T: StrictType + Copy + StrictDumb, const LEN: usize> StrictType for [T; LEN] {
339    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
340    fn strict_name() -> Option<TypeName> { None }
341}
342impl<T: StrictEncode + Copy + StrictDumb, const LEN: usize> StrictEncode for [T; LEN] {
343    fn strict_encode<W: TypedWrite>(&self, mut writer: W) -> io::Result<W> {
344        for item in self {
345            writer = item.strict_encode(writer)?;
346        }
347        Ok(unsafe {
348            if T::strict_name() == u8::strict_name() {
349                writer.register_array(&Byte::strict_dumb(), LEN as u16)
350            } else {
351                writer.register_array(&T::strict_dumb(), LEN as u16)
352            }
353        })
354    }
355}
356impl<T: StrictDecode + Copy + StrictDumb, const LEN: usize> StrictDecode for [T; LEN] {
357    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
358        let mut ar = [T::strict_dumb(); LEN];
359        for c in ar.iter_mut() {
360            *c = T::strict_decode(reader)?;
361        }
362        Ok(ar)
363    }
364}
365
366impl<T: StrictType + StrictDumb + Copy, const LEN: usize, const REVERSE_STR: bool> StrictType
367    for Array<T, LEN, REVERSE_STR>
368{
369    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
370    fn strict_name() -> Option<TypeName> { None }
371}
372impl<T: StrictEncode + StrictDumb + Copy, const LEN: usize, const REVERSE_STR: bool> StrictEncode
373    for Array<T, LEN, REVERSE_STR>
374{
375    fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
376        self.as_inner().strict_encode(writer)
377    }
378}
379impl<T: StrictDecode + StrictDumb + Copy, const LEN: usize, const REVERSE_STR: bool> StrictDecode
380    for Array<T, LEN, REVERSE_STR>
381{
382    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
383        <[T; LEN]>::strict_decode(reader).map(Self::from_inner)
384    }
385}
386
387impl<const MIN_LEN: usize, const MAX_LEN: usize> StrictType for Confined<String, MIN_LEN, MAX_LEN> {
388    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
389    fn strict_name() -> Option<TypeName> { None }
390}
391impl<const MIN_LEN: usize, const MAX_LEN: usize> StrictEncode
392    for Confined<String, MIN_LEN, MAX_LEN>
393{
394    fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
395        unsafe {
396            writer
397                .register_unicode(Sizing::new(MIN_LEN as u64, MAX_LEN as u64))
398                .write_string::<MAX_LEN>(self.as_bytes())
399        }
400    }
401}
402impl<const MIN_LEN: usize, const MAX_LEN: usize> StrictDecode
403    for Confined<String, MIN_LEN, MAX_LEN>
404{
405    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
406        let bytes = unsafe { reader.read_string::<MAX_LEN>()? };
407        let s = String::from_utf8(bytes)?;
408        Confined::try_from(s).map_err(DecodeError::from)
409    }
410}
411
412impl<const MIN_LEN: usize, const MAX_LEN: usize> StrictType
413    for Confined<AsciiString, MIN_LEN, MAX_LEN>
414{
415    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
416    fn strict_name() -> Option<TypeName> { None }
417}
418impl<const MIN_LEN: usize, const MAX_LEN: usize> StrictEncode
419    for Confined<AsciiString, MIN_LEN, MAX_LEN>
420{
421    fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
422        unsafe {
423            writer
424                .register_list(
425                    &AsciiSym::strict_dumb(),
426                    Sizing::new(MIN_LEN as u64, MAX_LEN as u64),
427                )
428                .write_string::<MAX_LEN>(self.as_bytes())
429        }
430    }
431}
432impl<const MIN_LEN: usize, const MAX_LEN: usize> StrictDecode
433    for Confined<AsciiString, MIN_LEN, MAX_LEN>
434{
435    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
436        let bytes = unsafe { reader.read_string::<MAX_LEN>()? };
437        let s = AsciiString::from_ascii(bytes).map_err(|err| err.ascii_error())?;
438        Confined::try_from(s).map_err(DecodeError::from)
439    }
440}
441
442impl<C1: RestrictedCharSet, C: RestrictedCharSet, const MIN_LEN: usize, const MAX_LEN: usize>
443    StrictType for RString<C1, C, MIN_LEN, MAX_LEN>
444{
445    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
446    fn strict_name() -> Option<TypeName> { None }
447}
448impl<C1: RestrictedCharSet, C: RestrictedCharSet, const MIN_LEN: usize, const MAX_LEN: usize>
449    StrictDumb for RString<C1, C, MIN_LEN, MAX_LEN>
450{
451    fn strict_dumb() -> Self {
452        Self::try_from(format!(
453            "{}{}",
454            C1::strict_dumb(),
455            String::from_utf8(vec![C::strict_dumb().into(); MIN_LEN - 1]).expect("dumb")
456        ))
457        .expect("dumb")
458    }
459}
460impl<C1: RestrictedCharSet, C: RestrictedCharSet, const MIN_LEN: usize, const MAX_LEN: usize>
461    StrictEncode for RString<C1, C, MIN_LEN, MAX_LEN>
462{
463    fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
464        debug_assert_ne!(
465            MIN_LEN, 0,
466            "Restricted string type can't have minimum length equal to zero"
467        );
468        let sizing = Sizing::new(MIN_LEN as u64, MAX_LEN as u64);
469        unsafe {
470            writer
471                .register_rstring(&C::strict_dumb(), &C1::strict_dumb(), sizing)
472                .write_string::<MAX_LEN>(self.as_bytes())
473        }
474    }
475}
476impl<C1: RestrictedCharSet, C: RestrictedCharSet, const MIN_LEN: usize, const MAX_LEN: usize>
477    StrictDecode for RString<C1, C, MIN_LEN, MAX_LEN>
478{
479    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
480        let bytes = unsafe { reader.read_string::<MAX_LEN>()? };
481        RString::try_from(bytes).map_err(|e| DecodeError::DataIntegrityError(e.to_string()))
482    }
483}
484
485impl<T: StrictType, const MIN_LEN: usize, const MAX_LEN: usize> StrictType
486    for Confined<Vec<T>, MIN_LEN, MAX_LEN>
487{
488    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
489    fn strict_name() -> Option<TypeName> { None }
490}
491impl<T: StrictEncode + StrictDumb, const MIN_LEN: usize, const MAX_LEN: usize> StrictEncode
492    for Confined<Vec<T>, MIN_LEN, MAX_LEN>
493{
494    fn strict_encode<W: TypedWrite>(&self, mut writer: W) -> io::Result<W> {
495        let sizing = Sizing::new(MIN_LEN as u64, MAX_LEN as u64);
496        writer = unsafe {
497            writer = writer.write_collection::<Vec<T>, MIN_LEN, MAX_LEN>(self)?;
498            if T::strict_name() == u8::strict_name() {
499                writer.register_list(&Byte::strict_dumb(), sizing)
500            } else {
501                writer.register_list(&T::strict_dumb(), sizing)
502            }
503        };
504        Ok(writer)
505    }
506}
507impl<T: StrictDecode, const MIN_LEN: usize, const MAX_LEN: usize> StrictDecode
508    for Confined<Vec<T>, MIN_LEN, MAX_LEN>
509{
510    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
511        let len = unsafe { reader.raw_reader().read_raw_len::<MAX_LEN>()? };
512        let mut col = Vec::<T>::with_capacity(len);
513        for _ in 0..len {
514            col.push(StrictDecode::strict_decode(reader)?);
515        }
516        Confined::try_from(col).map_err(DecodeError::from)
517    }
518}
519
520impl<T: StrictType, const MIN_LEN: usize, const MAX_LEN: usize> StrictType
521    for Confined<VecDeque<T>, MIN_LEN, MAX_LEN>
522{
523    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
524    fn strict_name() -> Option<TypeName> { None }
525}
526impl<T: StrictEncode + StrictDumb, const MIN_LEN: usize, const MAX_LEN: usize> StrictEncode
527    for Confined<VecDeque<T>, MIN_LEN, MAX_LEN>
528{
529    fn strict_encode<W: TypedWrite>(&self, mut writer: W) -> io::Result<W> {
530        let sizing = Sizing::new(MIN_LEN as u64, MAX_LEN as u64);
531        writer = unsafe {
532            writer = writer.write_collection::<VecDeque<T>, MIN_LEN, MAX_LEN>(self)?;
533            if T::strict_name() == u8::strict_name() {
534                writer.register_list(&Byte::strict_dumb(), sizing)
535            } else {
536                writer.register_list(&T::strict_dumb(), sizing)
537            }
538        };
539        Ok(writer)
540    }
541}
542impl<T: StrictDecode, const MIN_LEN: usize, const MAX_LEN: usize> StrictDecode
543    for Confined<VecDeque<T>, MIN_LEN, MAX_LEN>
544{
545    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
546        let len = unsafe { reader.raw_reader().read_raw_len::<MAX_LEN>()? };
547        let mut col = VecDeque::<T>::with_capacity(len);
548        for _ in 0..len {
549            col.push_back(StrictDecode::strict_decode(reader)?);
550        }
551        Confined::try_from(col).map_err(DecodeError::from)
552    }
553}
554
555impl<T: StrictType + Ord, const MIN_LEN: usize, const MAX_LEN: usize> StrictType
556    for Confined<BTreeSet<T>, MIN_LEN, MAX_LEN>
557{
558    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
559    fn strict_name() -> Option<TypeName> { None }
560}
561impl<T: StrictEncode + Ord + StrictDumb, const MIN_LEN: usize, const MAX_LEN: usize> StrictEncode
562    for Confined<BTreeSet<T>, MIN_LEN, MAX_LEN>
563{
564    fn strict_encode<W: TypedWrite>(&self, mut writer: W) -> io::Result<W> {
565        unsafe {
566            writer = writer.write_collection::<BTreeSet<T>, MIN_LEN, MAX_LEN>(self)?;
567        }
568        Ok(unsafe {
569            writer.register_set(&T::strict_dumb(), Sizing::new(MIN_LEN as u64, MAX_LEN as u64))
570        })
571    }
572}
573impl<T: StrictDecode + Ord, const MIN_LEN: usize, const MAX_LEN: usize> StrictDecode
574    for Confined<BTreeSet<T>, MIN_LEN, MAX_LEN>
575{
576    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
577        let len = unsafe { reader.raw_reader().read_raw_len::<MAX_LEN>()? };
578        let mut col = BTreeSet::<T>::new();
579        for _ in 0..len {
580            let item = StrictDecode::strict_decode(reader)?;
581            if matches!(col.last(), Some(last) if last > &item) {
582                return Err(DecodeError::BrokenSetOrder);
583            }
584            if !col.insert(item) {
585                return Err(DecodeError::RepeatedSetValue);
586            }
587        }
588        Confined::try_from(col).map_err(DecodeError::from)
589    }
590}
591
592impl<K: StrictType + Ord + Hash, V: StrictType, const MIN_LEN: usize, const MAX_LEN: usize>
593    StrictType for Confined<BTreeMap<K, V>, MIN_LEN, MAX_LEN>
594{
595    const STRICT_LIB_NAME: &'static str = LIB_EMBEDDED;
596    fn strict_name() -> Option<TypeName> { None }
597}
598impl<
599        K: StrictEncode + Ord + Hash + StrictDumb,
600        V: StrictEncode + StrictDumb,
601        const MIN_LEN: usize,
602        const MAX_LEN: usize,
603    > StrictEncode for Confined<BTreeMap<K, V>, MIN_LEN, MAX_LEN>
604{
605    fn strict_encode<W: TypedWrite>(&self, mut writer: W) -> io::Result<W> {
606        unsafe {
607            writer.raw_writer().write_raw_len::<MAX_LEN>(self.len())?;
608        }
609        for (k, v) in self {
610            writer = k.strict_encode(writer)?;
611            writer = v.strict_encode(writer)?
612        }
613        Ok(unsafe {
614            writer.register_map(
615                &K::strict_dumb(),
616                &V::strict_dumb(),
617                Sizing::new(MIN_LEN as u64, MAX_LEN as u64),
618            )
619        })
620    }
621}
622impl<
623        K: StrictDecode + Ord + Hash + StrictDumb,
624        V: StrictDecode + StrictDumb,
625        const MIN_LEN: usize,
626        const MAX_LEN: usize,
627    > StrictDecode for Confined<BTreeMap<K, V>, MIN_LEN, MAX_LEN>
628{
629    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
630        let len = unsafe { reader.raw_reader().read_raw_len::<MAX_LEN>()? };
631        let mut col = BTreeMap::new();
632        for _ in 0..len {
633            let key = StrictDecode::strict_decode(reader)?;
634            let val = StrictDecode::strict_decode(reader)?;
635            if matches!(col.last_key_value(), Some((last, _)) if last > &key) {
636                return Err(DecodeError::BrokenMapOrder);
637            }
638            if col.insert(key, val).is_some() {
639                return Err(DecodeError::RepeatedMapValue);
640            }
641        }
642        Confined::try_from(col).map_err(DecodeError::from)
643    }
644}