amplify/collection/
confinement.rs

1// Rust language amplification library providing multiple generic trait
2// implementations, type wrappers, derive macros and other language enhancements
3//
4// Written in 2022-2024 by
5//     Dr. Maxim Orlovsky <orlovsky@ubideco.org>
6//
7// To the extent possible under law, the author(s) have dedicated all
8// copyright and related and neighboring rights to this software to
9// the public domain worldwide. This software is distributed without
10// any warranty.
11//
12// You should have received a copy of the MIT License
13// along with this software.
14// If not, see <https://opensource.org/licenses/MIT>.
15
16//! Confinement puts a constraint on the number of elements within a collection.
17
18use core::borrow::{Borrow, BorrowMut};
19use core::fmt::{self, Display, Formatter, LowerHex, UpperHex};
20use core::str::FromStr;
21use core::hash::Hash;
22use core::ops::{
23    Deref, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
24};
25use alloc::vec::Vec;
26use alloc::string::String;
27use alloc::borrow::ToOwned;
28use alloc::collections::{btree_map, BTreeMap, BTreeSet, VecDeque};
29use alloc::collections::vec_deque::Drain;
30use core::slice::SliceIndex;
31use core::ops::RangeBounds;
32#[cfg(feature = "std")]
33use std::{
34    io,
35    collections::{hash_map, HashMap, HashSet},
36};
37use amplify_num::hex;
38use amplify_num::hex::{FromHex, ToHex};
39use ascii::{AsAsciiStrError, AsciiChar, AsciiString};
40
41use crate::num::u24;
42
43/// Trait implemented by a collection types which need to support collection
44/// confinement.
45pub trait Collection: FromIterator<Self::Item> + Extend<Self::Item> {
46    /// Item type contained within the collection.
47    type Item;
48
49    /// Creates a new collection with certain capacity.
50    fn with_capacity(capacity: usize) -> Self;
51
52    /// Returns the length of a collection.
53    fn len(&self) -> usize;
54
55    /// Detects whether a collection is empty.
56    #[inline]
57    fn is_empty(&self) -> bool {
58        self.len() == 0
59    }
60
61    /// Pushes or inserts an element to the collection.
62    fn push(&mut self, elem: Self::Item);
63
64    /// Removes all elements from the collection.
65    fn clear(&mut self);
66}
67
68/// Trait implemented by key-value maps which need to support collection
69/// confinement.
70pub trait KeyedCollection: Collection<Item = (Self::Key, Self::Value)> {
71    /// Key type for the collection.
72    type Key: Eq + Hash;
73    /// Value type for the collection.
74    type Value;
75    type Entry<'a>
76    where
77        Self: 'a;
78
79    /// Checks whether a given key is contained in the collection.
80    fn contains_key(&self, key: &Self::Key) -> bool;
81
82    /// Gets a value of the collection.
83    fn get(&self, key: &Self::Key) -> Option<&Self::Value>;
84
85    /// Gets a mutable value of the collection.
86    fn get_mut(&mut self, key: &Self::Key) -> Option<&mut Self::Value>;
87
88    /// Returns iterator over keys and values.
89    fn iter(&self) -> impl Iterator<Item = (&Self::Key, &Self::Value)>;
90
91    /// Returns iterator over keys and mutable values.
92    fn iter_mut(&mut self) -> impl Iterator<Item = (&Self::Key, &mut Self::Value)>;
93
94    /// Constructs iterator over mutable values.
95    fn values_mut(&mut self) -> impl Iterator<Item = &mut Self::Value>;
96
97    /// Inserts a new value under a key. Returns previous value if a value under
98    /// the key was already present in the collection.
99    fn insert(&mut self, key: Self::Key, value: Self::Value) -> Option<Self::Value>;
100
101    /// Removes a value stored under a given key, returning an owned value if
102    /// it was in the collection.
103    fn remove(&mut self, key: &Self::Key) -> Option<Self::Value>;
104
105    /// Gets the given key's corresponding entry in the map for in-place
106    /// manipulation.
107    fn entry(&mut self, key: Self::Key) -> Self::Entry<'_>;
108
109    /// Retains only the elements specified by the predicate.
110    ///
111    /// In other words, remove all pairs `(k, v)` for which `f(&k, &mut v)`
112    /// returns `false`. The elements are visited in unsorted (and
113    /// unspecified) order.
114    fn retain(&mut self, f: impl FnMut(&Self::Key, &mut Self::Value) -> bool);
115}
116
117// Impls for main collection types
118
119impl Collection for String {
120    type Item = char;
121
122    fn with_capacity(capacity: usize) -> Self {
123        Self::with_capacity(capacity)
124    }
125
126    fn len(&self) -> usize {
127        self.len()
128    }
129
130    fn push(&mut self, elem: Self::Item) {
131        self.push(elem)
132    }
133
134    fn clear(&mut self) {
135        self.clear()
136    }
137}
138
139impl Collection for AsciiString {
140    type Item = AsciiChar;
141
142    fn with_capacity(capacity: usize) -> Self {
143        Self::with_capacity(capacity)
144    }
145
146    fn len(&self) -> usize {
147        self.len()
148    }
149
150    fn push(&mut self, elem: Self::Item) {
151        self.push(elem)
152    }
153
154    fn clear(&mut self) {
155        self.clear()
156    }
157}
158
159impl<T> Collection for Vec<T> {
160    type Item = T;
161
162    fn with_capacity(capacity: usize) -> Self {
163        Self::with_capacity(capacity)
164    }
165
166    fn len(&self) -> usize {
167        self.len()
168    }
169
170    fn push(&mut self, elem: Self::Item) {
171        self.push(elem)
172    }
173
174    fn clear(&mut self) {
175        self.clear()
176    }
177}
178
179impl<T> Collection for VecDeque<T> {
180    type Item = T;
181
182    fn with_capacity(capacity: usize) -> Self {
183        Self::with_capacity(capacity)
184    }
185
186    fn len(&self) -> usize {
187        self.len()
188    }
189
190    fn push(&mut self, elem: Self::Item) {
191        self.push_back(elem)
192    }
193
194    fn clear(&mut self) {
195        self.clear()
196    }
197}
198
199#[cfg(feature = "std")]
200impl<T: Eq + Hash> Collection for HashSet<T> {
201    type Item = T;
202
203    fn with_capacity(capacity: usize) -> Self {
204        Self::with_capacity(capacity)
205    }
206
207    fn len(&self) -> usize {
208        self.len()
209    }
210
211    fn push(&mut self, elem: Self::Item) {
212        self.insert(elem);
213    }
214
215    fn clear(&mut self) {
216        self.clear()
217    }
218}
219
220impl<T: Ord> Collection for BTreeSet<T> {
221    type Item = T;
222
223    #[doc(hidden)]
224    fn with_capacity(_capacity: usize) -> Self {
225        BTreeSet::new()
226    }
227
228    fn len(&self) -> usize {
229        self.len()
230    }
231
232    fn push(&mut self, elem: Self::Item) {
233        self.insert(elem);
234    }
235
236    fn clear(&mut self) {
237        self.clear()
238    }
239}
240
241#[cfg(feature = "std")]
242impl<K: Eq + Hash, V> Collection for HashMap<K, V> {
243    type Item = (K, V);
244
245    fn with_capacity(capacity: usize) -> Self {
246        Self::with_capacity(capacity)
247    }
248
249    fn len(&self) -> usize {
250        self.len()
251    }
252
253    fn push(&mut self, elem: Self::Item) {
254        HashMap::insert(self, elem.0, elem.1);
255    }
256
257    fn clear(&mut self) {
258        self.clear()
259    }
260}
261
262#[cfg(feature = "std")]
263impl<K: Eq + Hash, V> KeyedCollection for HashMap<K, V> {
264    type Key = K;
265    type Value = V;
266    type Entry<'a>
267        = hash_map::Entry<'a, K, V>
268    where
269        K: 'a,
270        V: 'a;
271
272    fn contains_key(&self, key: &Self::Key) -> bool {
273        HashMap::contains_key(self, key)
274    }
275
276    fn get(&self, key: &Self::Key) -> Option<&Self::Value> {
277        HashMap::get(self, key)
278    }
279
280    fn get_mut(&mut self, key: &Self::Key) -> Option<&mut Self::Value> {
281        HashMap::get_mut(self, key)
282    }
283
284    fn iter(&self) -> impl Iterator<Item = (&Self::Key, &Self::Value)> {
285        HashMap::iter(self)
286    }
287
288    fn iter_mut(&mut self) -> impl Iterator<Item = (&Self::Key, &mut Self::Value)> {
289        HashMap::iter_mut(self)
290    }
291
292    fn values_mut(&mut self) -> impl Iterator<Item = &mut Self::Value> {
293        HashMap::values_mut(self)
294    }
295
296    fn insert(&mut self, key: Self::Key, value: Self::Value) -> Option<Self::Value> {
297        HashMap::insert(self, key, value)
298    }
299
300    fn remove(&mut self, key: &Self::Key) -> Option<Self::Value> {
301        HashMap::remove(self, key)
302    }
303
304    fn entry(&mut self, key: Self::Key) -> Self::Entry<'_> {
305        HashMap::entry(self, key)
306    }
307
308    fn retain(&mut self, f: impl FnMut(&K, &mut V) -> bool) {
309        HashMap::retain(self, f)
310    }
311}
312
313impl<K: Ord + Hash, V> Collection for BTreeMap<K, V> {
314    type Item = (K, V);
315
316    #[doc(hidden)]
317    fn with_capacity(_capacity: usize) -> Self {
318        BTreeMap::new()
319    }
320
321    fn len(&self) -> usize {
322        self.len()
323    }
324
325    fn push(&mut self, elem: Self::Item) {
326        BTreeMap::insert(self, elem.0, elem.1);
327    }
328
329    fn clear(&mut self) {
330        self.clear()
331    }
332}
333
334impl<K: Ord + Hash, V> KeyedCollection for BTreeMap<K, V> {
335    type Key = K;
336    type Value = V;
337    type Entry<'a>
338        = btree_map::Entry<'a, K, V>
339    where
340        K: 'a,
341        V: 'a;
342
343    fn contains_key(&self, key: &Self::Key) -> bool {
344        BTreeMap::contains_key(self, key)
345    }
346
347    fn get(&self, key: &Self::Key) -> Option<&Self::Value> {
348        BTreeMap::get(self, key)
349    }
350
351    fn get_mut(&mut self, key: &Self::Key) -> Option<&mut Self::Value> {
352        BTreeMap::get_mut(self, key)
353    }
354
355    fn iter(&self) -> impl Iterator<Item = (&Self::Key, &Self::Value)> {
356        BTreeMap::iter(self)
357    }
358
359    fn iter_mut(&mut self) -> impl Iterator<Item = (&Self::Key, &mut Self::Value)> {
360        BTreeMap::iter_mut(self)
361    }
362
363    fn values_mut(&mut self) -> impl Iterator<Item = &mut Self::Value> {
364        BTreeMap::values_mut(self)
365    }
366
367    fn insert(&mut self, key: Self::Key, value: Self::Value) -> Option<Self::Value> {
368        BTreeMap::insert(self, key, value)
369    }
370
371    fn remove(&mut self, key: &Self::Key) -> Option<Self::Value> {
372        BTreeMap::remove(self, key)
373    }
374
375    fn entry(&mut self, key: Self::Key) -> Self::Entry<'_> {
376        BTreeMap::entry(self, key)
377    }
378
379    fn retain(&mut self, f: impl FnMut(&K, &mut V) -> bool) {
380        BTreeMap::retain(self, f)
381    }
382}
383
384// Errors
385
386/// Errors when confinement constraints were not met.
387#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
388pub enum Error {
389    /// Operation results in collection reduced below the required minimum
390    /// number of elements.
391    Undersize {
392        /** Current collection length */
393        len: usize,
394        /** Minimum number of elements which must be present in the
395         * collection */
396        min_len: usize,
397    },
398
399    /// Operation results in collection growth above the required maximum number
400    /// of elements.
401    Oversize {
402        /** Current collection length */
403        len: usize,
404        /** Maximum number of elements which must be present in the
405         * collection */
406        max_len: usize,
407    },
408
409    /// Attempt to address an index outside the collection bounds.
410    OutOfBoundary {
411        /** Index which was outside the bounds */
412        index: usize,
413        /** The actual number of elements in the collection */
414        len: usize,
415    },
416}
417
418impl Display for Error {
419    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
420        match self {
421            Error::Undersize { len, min_len } => write!(
422                f,
423                "operation results in collection size {len} less than lower boundary \
424                 of {min_len}, which is prohibited"
425            ),
426            Error::Oversize { len, max_len } => write!(
427                f,
428                "operation results in collection size {len} exceeding {max_len}, \
429                which is prohibited"
430            ),
431            Error::OutOfBoundary { index, len } => write!(
432                f,
433                "attempt to access the element at {index} which is outside of the \
434                collection length boundary {len}"
435            ),
436        }
437    }
438}
439
440#[cfg(feature = "std")]
441impl std::error::Error for Error {}
442
443/// Errors generated by constructing confined [`AsciiString`] from `str`.
444#[derive(Clone, Copy, PartialEq, Eq, Debug)]
445pub enum AsciiError {
446    /// The string contains non-ASCII characters
447    Ascii(AsAsciiStrError),
448
449    /// Confinement requirements are violated
450    Confinement(Error),
451}
452
453impl From<AsAsciiStrError> for AsciiError {
454    fn from(err: AsAsciiStrError) -> Self {
455        AsciiError::Ascii(err)
456    }
457}
458
459impl From<Error> for AsciiError {
460    fn from(err: Error) -> Self {
461        AsciiError::Confinement(err)
462    }
463}
464
465impl Display for AsciiError {
466    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
467        match self {
468            AsciiError::Ascii(e) => Display::fmt(e, f),
469            AsciiError::Confinement(e) => Display::fmt(e, f),
470        }
471    }
472}
473
474#[cfg(feature = "std")]
475impl std::error::Error for AsciiError {}
476
477// Confinement params
478
479/// Constant for a minimal size of a confined collection.
480pub const ZERO: usize = 0;
481/// Constant for a minimal size of a confined collection.
482pub const ONE: usize = 1;
483/// Constant for a maximal size of a confined collection equal to [`u8::MAX`].
484pub const U8: usize = u8::MAX as usize;
485/// Constant for a maximal size of a confined collection equal to [`u16::MAX`].
486pub const U16: usize = u16::MAX as usize;
487/// Constant for a maximal size of a confined collection equal to [`u24::MAX`].
488pub const U24: usize = 0xFFFFFFusize;
489/// Constant for a maximal size of a confined collection equal to [`u32::MAX`].
490pub const U32: usize = u32::MAX as usize;
491/// Constant for a maximal size of a confined collection equal to [`u64::MAX`].
492pub const U64: usize = u64::MAX as usize;
493
494// Confined collection
495
496/// The confinement for the collection.
497#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
498#[cfg_attr(
499    feature = "serde",
500    derive(Serialize, Deserialize),
501    serde(crate = "serde_crate")
502)]
503pub struct Confined<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize>(C);
504
505impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> Deref
506    for Confined<C, MIN_LEN, MAX_LEN>
507{
508    type Target = C;
509
510    fn deref(&self) -> &Self::Target {
511        &self.0
512    }
513}
514
515impl<C, const MIN_LEN: usize, const MAX_LEN: usize> AsRef<[C::Item]>
516    for Confined<C, MIN_LEN, MAX_LEN>
517where
518    C: Collection + AsRef<[C::Item]>,
519{
520    fn as_ref(&self) -> &[C::Item] {
521        self.0.as_ref()
522    }
523}
524
525impl<C, const MIN_LEN: usize, const MAX_LEN: usize> AsMut<[C::Item]>
526    for Confined<C, MIN_LEN, MAX_LEN>
527where
528    C: Collection + AsMut<[C::Item]>,
529{
530    fn as_mut(&mut self) -> &mut [C::Item] {
531        self.0.as_mut()
532    }
533}
534
535impl<C, const MIN_LEN: usize, const MAX_LEN: usize> Borrow<[C::Item]>
536    for Confined<C, MIN_LEN, MAX_LEN>
537where
538    C: Collection + Borrow<[C::Item]>,
539{
540    fn borrow(&self) -> &[C::Item] {
541        self.0.borrow()
542    }
543}
544
545impl<C, const MIN_LEN: usize, const MAX_LEN: usize> BorrowMut<[C::Item]>
546    for Confined<C, MIN_LEN, MAX_LEN>
547where
548    C: Collection + BorrowMut<[C::Item]>,
549{
550    fn borrow_mut(&mut self) -> &mut [C::Item] {
551        self.0.borrow_mut()
552    }
553}
554
555impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> IntoIterator
556    for Confined<C, MIN_LEN, MAX_LEN>
557where
558    C: IntoIterator,
559{
560    type Item = <C as IntoIterator>::Item;
561    type IntoIter = <C as IntoIterator>::IntoIter;
562
563    fn into_iter(self) -> Self::IntoIter {
564        self.0.into_iter()
565    }
566}
567
568impl<'c, C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> IntoIterator
569    for &'c Confined<C, MIN_LEN, MAX_LEN>
570where
571    &'c C: IntoIterator,
572{
573    type Item = <&'c C as IntoIterator>::Item;
574    type IntoIter = <&'c C as IntoIterator>::IntoIter;
575
576    fn into_iter(self) -> Self::IntoIter {
577        self.0.into_iter()
578    }
579}
580
581impl<'c, C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> IntoIterator
582    for &'c mut Confined<C, MIN_LEN, MAX_LEN>
583where
584    &'c mut C: IntoIterator,
585{
586    type Item = <&'c mut C as IntoIterator>::Item;
587    type IntoIter = <&'c mut C as IntoIterator>::IntoIter;
588
589    fn into_iter(self) -> Self::IntoIter {
590        self.0.into_iter()
591    }
592}
593
594impl<'c, C, const MIN_LEN: usize, const MAX_LEN: usize> Confined<C, MIN_LEN, MAX_LEN>
595where
596    C: Collection + 'c,
597    &'c mut C: IntoIterator<Item = &'c mut <C as Collection>::Item>,
598{
599    /// Returns an iterator that allows modifying each value.
600    ///
601    /// The iterator yields all items from start to end.
602    pub fn iter_mut(&'c mut self) -> <&'c mut C as IntoIterator>::IntoIter {
603        let coll = &mut self.0;
604        coll.into_iter()
605    }
606}
607
608impl<C, const MIN_LEN: usize, const MAX_LEN: usize> Confined<C, MIN_LEN, MAX_LEN>
609where
610    C: KeyedCollection,
611{
612    /// Returns an iterator that allows modifying each value for each key.
613    pub fn values_mut(&mut self) -> impl Iterator<Item = &mut C::Value> {
614        let coll = &mut self.0;
615        coll.values_mut()
616    }
617
618    /// Returns an iterator that allows modifying each value for each key.
619    pub fn keyed_values_mut(&mut self) -> impl Iterator<Item = (&C::Key, &mut C::Value)> {
620        let coll = &mut self.0;
621        coll.iter_mut()
622    }
623}
624
625impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> Index<usize>
626    for Confined<C, MIN_LEN, MAX_LEN>
627where
628    C: Index<usize, Output = C::Item>,
629{
630    type Output = C::Item;
631
632    fn index(&self, index: usize) -> &Self::Output {
633        self.0.index(index)
634    }
635}
636
637impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> IndexMut<usize>
638    for Confined<C, MIN_LEN, MAX_LEN>
639where
640    C: IndexMut<usize, Output = C::Item>,
641{
642    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
643        self.0.index_mut(index)
644    }
645}
646
647impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> Index<Range<usize>>
648    for Confined<C, MIN_LEN, MAX_LEN>
649where
650    C: Index<Range<usize>, Output = [C::Item]>,
651{
652    type Output = [C::Item];
653
654    fn index(&self, index: Range<usize>) -> &Self::Output {
655        self.0.index(index)
656    }
657}
658
659impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> IndexMut<Range<usize>>
660    for Confined<C, MIN_LEN, MAX_LEN>
661where
662    C: IndexMut<Range<usize>, Output = [C::Item]>,
663{
664    fn index_mut(&mut self, index: Range<usize>) -> &mut Self::Output {
665        self.0.index_mut(index)
666    }
667}
668
669impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> Index<RangeTo<usize>>
670    for Confined<C, MIN_LEN, MAX_LEN>
671where
672    C: Index<RangeTo<usize>, Output = [C::Item]>,
673{
674    type Output = [C::Item];
675
676    fn index(&self, index: RangeTo<usize>) -> &Self::Output {
677        self.0.index(index)
678    }
679}
680
681impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> IndexMut<RangeTo<usize>>
682    for Confined<C, MIN_LEN, MAX_LEN>
683where
684    C: IndexMut<RangeTo<usize>, Output = [C::Item]>,
685{
686    fn index_mut(&mut self, index: RangeTo<usize>) -> &mut Self::Output {
687        self.0.index_mut(index)
688    }
689}
690
691impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> Index<RangeFrom<usize>>
692    for Confined<C, MIN_LEN, MAX_LEN>
693where
694    C: Index<RangeFrom<usize>, Output = [C::Item]>,
695{
696    type Output = [C::Item];
697
698    fn index(&self, index: RangeFrom<usize>) -> &Self::Output {
699        self.0.index(index)
700    }
701}
702
703impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> IndexMut<RangeFrom<usize>>
704    for Confined<C, MIN_LEN, MAX_LEN>
705where
706    C: IndexMut<RangeFrom<usize>, Output = [C::Item]>,
707{
708    fn index_mut(&mut self, index: RangeFrom<usize>) -> &mut Self::Output {
709        self.0.index_mut(index)
710    }
711}
712
713impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> Index<RangeInclusive<usize>>
714    for Confined<C, MIN_LEN, MAX_LEN>
715where
716    C: Index<RangeInclusive<usize>, Output = [C::Item]>,
717{
718    type Output = [C::Item];
719
720    fn index(&self, index: RangeInclusive<usize>) -> &Self::Output {
721        self.0.index(index)
722    }
723}
724
725impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> IndexMut<RangeInclusive<usize>>
726    for Confined<C, MIN_LEN, MAX_LEN>
727where
728    C: IndexMut<RangeInclusive<usize>, Output = [C::Item]>,
729{
730    fn index_mut(&mut self, index: RangeInclusive<usize>) -> &mut Self::Output {
731        self.0.index_mut(index)
732    }
733}
734
735impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> Index<RangeToInclusive<usize>>
736    for Confined<C, MIN_LEN, MAX_LEN>
737where
738    C: Index<RangeToInclusive<usize>, Output = [C::Item]>,
739{
740    type Output = [C::Item];
741
742    fn index(&self, index: RangeToInclusive<usize>) -> &Self::Output {
743        self.0.index(index)
744    }
745}
746
747impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> IndexMut<RangeToInclusive<usize>>
748    for Confined<C, MIN_LEN, MAX_LEN>
749where
750    C: IndexMut<RangeToInclusive<usize>, Output = [C::Item]>,
751{
752    fn index_mut(&mut self, index: RangeToInclusive<usize>) -> &mut Self::Output {
753        self.0.index_mut(index)
754    }
755}
756
757impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> Index<RangeFull>
758    for Confined<C, MIN_LEN, MAX_LEN>
759where
760    C: Index<RangeFull, Output = [C::Item]>,
761{
762    type Output = [C::Item];
763
764    fn index(&self, index: RangeFull) -> &Self::Output {
765        self.0.index(index)
766    }
767}
768
769impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> IndexMut<RangeFull>
770    for Confined<C, MIN_LEN, MAX_LEN>
771where
772    C: IndexMut<RangeFull, Output = [C::Item]>,
773{
774    fn index_mut(&mut self, index: RangeFull) -> &mut Self::Output {
775        self.0.index_mut(index)
776    }
777}
778
779impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> Display
780    for Confined<C, MIN_LEN, MAX_LEN>
781where
782    C: Display,
783{
784    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
785        self.0.fmt(f)
786    }
787}
788
789impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> FromStr
790    for Confined<C, MIN_LEN, MAX_LEN>
791where
792    C: FromStr,
793{
794    type Err = C::Err;
795
796    fn from_str(s: &str) -> Result<Self, Self::Err> {
797        C::from_str(s).map(Self)
798    }
799}
800
801impl<C: Collection, const MIN_LEN: usize, const MAX_LEN: usize> Confined<C, MIN_LEN, MAX_LEN> {
802    fn does_fit_confinement(col: &C) -> Result<(), Error> {
803        let len = col.len();
804        if len < MIN_LEN {
805            return Err(Error::Undersize {
806                len,
807                min_len: MIN_LEN,
808            });
809        }
810        if len > MAX_LEN {
811            return Err(Error::Oversize {
812                len,
813                max_len: MAX_LEN,
814            });
815        }
816        Ok(())
817    }
818
819    /// Constructs confinement over collection which was already size-checked.
820    ///
821    /// # Panics
822    ///
823    /// Panics if the collection size doesn't fit confinement type requirements.
824    pub fn from_checked(col: C) -> Self {
825        Self::try_from(col).expect("collection size mismatch, use try_from instead")
826    }
827
828    #[deprecated(since = "4.7.0", note = "use `from_checked`")]
829    pub fn from_collection_unsafe(col: C) -> Self {
830        Self::from_checked(col)
831    }
832
833    /// Tries to construct a confinement over a collection. Fails if the number
834    /// of items in the collection exceeds one of the confinement bounds.
835    // We can't use `impl TryFrom` due to the conflict with core library blanked
836    // implementation
837    pub fn try_from(col: C) -> Result<Self, Error> {
838        Self::does_fit_confinement(&col)?;
839        Ok(Self(col))
840    }
841
842    /// Tries to construct a confinement with a collection of elements taken
843    /// from an iterator. Fails if the number of items in the collection
844    /// exceeds one of the confinement bounds.
845    pub fn try_from_iter<I: IntoIterator<Item = C::Item>>(iter: I) -> Result<Self, Error> {
846        let mut col = C::with_capacity(MIN_LEN);
847        for item in iter {
848            col.push(item);
849        }
850        Self::try_from(col)
851    }
852
853    /// Construct a confinement with a collection of elements taken from an
854    /// iterator.
855    ///
856    /// # Panics
857    ///
858    /// Panics if the number of items in the collection exceeds one
859    /// of the confinement bounds.
860    pub fn from_iter_checked<I: IntoIterator<Item = C::Item>>(iter: I) -> Self {
861        Self::from_checked(iter.into_iter().collect())
862    }
863
864    #[deprecated(since = "4.7.0", note = "use `from_iter_checked`")]
865    pub fn from_iter_unsafe<I: IntoIterator<Item = C::Item>>(iter: I) -> Self {
866        Self::from_iter_checked(iter)
867    }
868
869    /// Returns inner collection type
870    #[deprecated(since = "4.7.0", note = "use as_unconfined method")]
871    pub fn as_inner(&self) -> &C {
872        &self.0
873    }
874
875    /// Returns reference to the inner collection type.
876    pub fn as_unconfined(&self) -> &C {
877        &self.0
878    }
879
880    /// Clones inner collection type and returns it
881    #[deprecated(since = "4.7.0", note = "use to_unconfined method")]
882    pub fn to_inner(&self) -> C
883    where
884        C: Clone,
885    {
886        self.0.clone()
887    }
888
889    /// Clones inner collection and returns an unconfined version of it.
890    pub fn to_unconfined(&self) -> C
891    where
892        C: Clone,
893    {
894        self.0.clone()
895    }
896
897    /// Decomposes into the inner collection type
898    #[deprecated(since = "4.7.0", note = "use release method")]
899    pub fn into_inner(self) -> C {
900        self.0
901    }
902
903    /// Attempts to add a single element to the confined collection. Fails if
904    /// the number of elements in the collection already maximal.
905    pub fn push(&mut self, elem: C::Item) -> Result<(), Error> {
906        let len = self.len();
907        if len == MAX_LEN || len + 1 > MAX_LEN {
908            return Err(Error::Oversize {
909                len: len + 1,
910                max_len: MAX_LEN,
911            });
912        }
913        self.0.push(elem);
914        Ok(())
915    }
916
917    /// Attempts to add all elements from an iterator to the confined
918    /// collection. Fails if the number of elements in the collection
919    /// already maximal.
920    pub fn extend<T: IntoIterator<Item = C::Item>>(&mut self, iter: T) -> Result<(), Error> {
921        for elem in iter {
922            self.push(elem)?;
923        }
924        Ok(())
925    }
926
927    /// Removes confinement and returns the underlying collection.
928    #[deprecated(since = "4.7.0", note = "use release method")]
929    pub fn unbox(self) -> C {
930        self.0
931    }
932
933    /// Releases underlying collection from the confinement.
934    pub fn release(self) -> C {
935        self.0
936    }
937
938    /// Allows mutation of the confinement, checking that the mutation does not
939    /// break confinement requirements.
940    pub fn with_mut(mut self, f: impl FnOnce(&mut Self)) -> Result<Self, Error> {
941        f(&mut self);
942        Self::does_fit_confinement(&self)?;
943        Ok(self)
944    }
945
946    /// Allows mutation of the confinement, checking that the mutation does not
947    /// break confinement requirements.
948    pub fn as_mut_checked(&mut self, f: impl FnOnce(&mut Self)) {
949        f(self);
950        Self::does_fit_confinement(self).expect("confinement broken");
951    }
952}
953
954impl<C: Collection, const MAX_LEN: usize> Confined<C, ZERO, MAX_LEN>
955where
956    C: Default,
957{
958    /// Constructs a new confinement containing no elements.
959    pub fn new() -> Self {
960        Self::default()
961    }
962
963    /// Constructs a new confinement containing no elements, but with a
964    /// pre-allocated storage for the `capacity` of elements.
965    pub fn with_capacity(capacity: usize) -> Self {
966        Self(C::with_capacity(capacity))
967    }
968
969    /// Removes all elements from the confined collection.
970    pub fn clear(&mut self) {
971        self.0.clear()
972    }
973}
974
975impl<C: Collection, const MAX_LEN: usize> Default for Confined<C, ZERO, MAX_LEN>
976where
977    C: Default,
978{
979    fn default() -> Self {
980        Self(C::default())
981    }
982}
983
984impl<C: Collection, const MAX_LEN: usize> Confined<C, ONE, MAX_LEN>
985where
986    C: Default,
987{
988    /// Constructs a confinement with a collection made of a single required
989    /// element.
990    pub fn with(elem: C::Item) -> Self {
991        let mut c = C::default();
992        c.push(elem);
993        Self(c)
994    }
995}
996
997impl<C: Collection, const MIN_LEN: usize> Confined<C, MIN_LEN, U8>
998where
999    C: Default,
1000{
1001    /// Returns number of elements in the confined collection as `u8`. The
1002    /// confinement guarantees that the collection length can't exceed
1003    /// `u8::MAX`.
1004    pub fn len_u8(&self) -> u8 {
1005        self.len() as u8
1006    }
1007}
1008
1009impl<C: Collection, const MIN_LEN: usize> Confined<C, MIN_LEN, U16>
1010where
1011    C: Default,
1012{
1013    /// Returns number of elements in the confined collection as `u16`. The
1014    /// confinement guarantees that the collection length can't exceed
1015    /// `u16::MAX`.
1016    pub fn len_u16(&self) -> u16 {
1017        self.len() as u16
1018    }
1019}
1020
1021impl<C: Collection, const MIN_LEN: usize> Confined<C, MIN_LEN, U24>
1022where
1023    C: Default,
1024{
1025    /// Returns number of elements in the confined collection as `u24`. The
1026    /// confinement guarantees that the collection length can't exceed
1027    /// `u24::MAX`.
1028    pub fn len_u24(&self) -> u24 {
1029        u24::try_from(self.len() as u32).expect("confinement broken")
1030    }
1031}
1032
1033impl<C: Collection, const MIN_LEN: usize> Confined<C, MIN_LEN, U32>
1034where
1035    C: Default,
1036{
1037    /// Returns number of elements in the confined collection as `u32`. The
1038    /// confinement guarantees that the collection length can't exceed
1039    /// `u32::MAX`.
1040    pub fn len_u32(&self) -> u32 {
1041        self.len() as u32
1042    }
1043}
1044
1045impl<C: KeyedCollection, const MIN_LEN: usize, const MAX_LEN: usize> Confined<C, MIN_LEN, MAX_LEN> {
1046    /// Gets mutable reference to an element of the collection.
1047    pub fn get_mut(&mut self, key: &C::Key) -> Option<&mut C::Value> {
1048        self.0.get_mut(key)
1049    }
1050
1051    /// Inserts a new value into the confined collection under a given key.
1052    /// Fails if the collection already contains maximum number of elements
1053    /// allowed by the confinement.
1054    pub fn insert(&mut self, key: C::Key, value: C::Value) -> Result<Option<C::Value>, Error> {
1055        let len = self.len();
1056        if len == MAX_LEN || len + 1 > MAX_LEN {
1057            return Err(Error::Oversize {
1058                len: len + 1,
1059                max_len: MAX_LEN,
1060            });
1061        }
1062        Ok(self.0.insert(key, value))
1063    }
1064
1065    /// Gets the given key's corresponding entry in the map for in-place
1066    /// manipulation. Errors if the collection entry is vacant and the
1067    /// collection has already reached maximal size of its confinement.
1068    pub fn entry(&mut self, key: C::Key) -> Result<C::Entry<'_>, Error> {
1069        let len = self.len();
1070        if len == MAX_LEN && !self.0.contains_key(&key) {
1071            return Err(Error::Oversize {
1072                len: len + 1,
1073                max_len: MAX_LEN,
1074            });
1075        }
1076        Ok(self.0.entry(key))
1077    }
1078
1079    /// Retains only the elements specified by the predicate.
1080    ///
1081    /// In other words, remove all pairs `(k, v)` for which `f(&k, &mut v)`
1082    /// returns `false`. The elements are visited in unsorted (and
1083    /// unspecified) order.
1084    ///
1085    /// # Errors
1086    ///
1087    /// Errors if the minimum confinement is not met after the retain operation.
1088    pub fn try_retain(
1089        &mut self,
1090        f: impl FnMut(&C::Key, &mut C::Value) -> bool,
1091    ) -> Result<(), Error> {
1092        self.0.retain(f);
1093        if self.0.len() < MIN_LEN {
1094            return Err(Error::Undersize {
1095                len: self.0.len(),
1096                min_len: MIN_LEN,
1097            });
1098        }
1099        Ok(())
1100    }
1101}
1102
1103impl<C: KeyedCollection, const MAX_LEN: usize> Confined<C, ZERO, MAX_LEN> {
1104    /// Retains only the elements specified by the predicate.
1105    ///
1106    /// In other words, remove all pairs `(k, v)` for which `f(&k, &mut v)`
1107    /// returns `false`. The elements are visited in unsorted (and
1108    /// unspecified) order.
1109    pub fn retain(&mut self, f: impl FnMut(&C::Key, &mut C::Value) -> bool) {
1110        self.0.retain(f)
1111    }
1112}
1113
1114impl<C: KeyedCollection, const MAX_LEN: usize> Confined<C, ONE, MAX_LEN>
1115where
1116    C: Default,
1117{
1118    /// Constructs a confinement with a collection made of a single required
1119    /// key-value pair.
1120    pub fn with_key_value(key: C::Key, value: C::Value) -> Self {
1121        let mut c = C::default();
1122        c.insert(key, value);
1123        Self(c)
1124    }
1125}
1126
1127impl<const MIN_LEN: usize, const MAX_LEN: usize> TryFrom<&str>
1128    for Confined<String, MIN_LEN, MAX_LEN>
1129{
1130    type Error = Error;
1131
1132    fn try_from(value: &str) -> Result<Self, Self::Error> {
1133        Self::try_from(value.to_owned())
1134    }
1135}
1136
1137impl<const MIN_LEN: usize, const MAX_LEN: usize> TryFrom<&str>
1138    for Confined<AsciiString, MIN_LEN, MAX_LEN>
1139{
1140    type Error = AsciiError;
1141
1142    fn try_from(value: &str) -> Result<Self, Self::Error> {
1143        let a = AsciiString::from_str(value)?;
1144        Self::try_from(a).map_err(AsciiError::from)
1145    }
1146}
1147
1148impl<const MAX_LEN: usize> Confined<String, ZERO, MAX_LEN> {
1149    /// Removes the last character from a string and returns it, or [`None`] if
1150    /// it is empty.
1151    pub fn pop(&mut self) -> Option<char> {
1152        self.0.pop()
1153    }
1154}
1155
1156impl<const MIN_LEN: usize, const MAX_LEN: usize> Confined<String, MIN_LEN, MAX_LEN> {
1157    /// Removes a single character from the confined string, unless the string
1158    /// doesn't shorten more than the confinement requirement. Errors
1159    /// otherwise.
1160    pub fn remove(&mut self, index: usize) -> Result<char, Error> {
1161        let len = self.len();
1162        if self.is_empty() || len <= MIN_LEN {
1163            return Err(Error::Undersize {
1164                len,
1165                min_len: MIN_LEN,
1166            });
1167        }
1168        if index >= len {
1169            return Err(Error::OutOfBoundary { index, len });
1170        }
1171        Ok(self.0.remove(index))
1172    }
1173}
1174
1175impl<const MAX_LEN: usize> Confined<AsciiString, ZERO, MAX_LEN> {
1176    /// Removes the last character from a string and returns it, or [`None`] if
1177    /// it is empty.
1178    pub fn pop(&mut self) -> Option<AsciiChar> {
1179        self.0.pop()
1180    }
1181}
1182
1183impl<const MIN_LEN: usize, const MAX_LEN: usize> Confined<AsciiString, MIN_LEN, MAX_LEN> {
1184    /// Removes a single character from the confined string, unless the string
1185    /// doesn't shorten more than the confinement requirement. Errors
1186    /// otherwise.
1187    pub fn remove(&mut self, index: usize) -> Result<AsciiChar, Error> {
1188        let len = self.len();
1189        if self.is_empty() || len <= MIN_LEN {
1190            return Err(Error::Undersize {
1191                len,
1192                min_len: MIN_LEN,
1193            });
1194        }
1195        if index >= len {
1196            return Err(Error::OutOfBoundary { index, len });
1197        }
1198        Ok(self.0.remove(index))
1199    }
1200}
1201
1202impl<T, const MIN_LEN: usize, const MAX_LEN: usize> Confined<Vec<T>, MIN_LEN, MAX_LEN> {
1203    /// Constructs confinement out of slice of items. Does allocation.
1204    ///
1205    /// # Panics
1206    ///
1207    /// Panics if the size of the slice doesn't match the confinement type
1208    /// bounds.
1209    #[inline]
1210    pub fn from_slice_checked(slice: &[T]) -> Self
1211    where
1212        T: Clone,
1213    {
1214        assert!(slice.len() > MIN_LEN && slice.len() <= MAX_LEN);
1215        Self(slice.to_vec())
1216    }
1217
1218    #[deprecated(since = "4.7.0", note = "use `from_slice_checked`")]
1219    #[inline]
1220    pub fn from_slice_unsafe(slice: &[T]) -> Self
1221    where
1222        T: Clone,
1223    {
1224        Self::from_slice_checked(slice)
1225    }
1226
1227    /// Constructs confinement out of slice of items. Does allocation.
1228    #[inline]
1229    pub fn try_from_slice(slice: &[T]) -> Result<Self, Error>
1230    where
1231        T: Clone,
1232    {
1233        Self::try_from(slice.to_vec())
1234    }
1235
1236    /// Returns slice representation of the vec.
1237    #[inline]
1238    pub fn as_slice(&self) -> &[T] {
1239        &self.0
1240    }
1241
1242    /// Converts into the inner unconfined vector.
1243    #[inline]
1244    pub fn into_vec(self) -> Vec<T> {
1245        self.0
1246    }
1247
1248    /// Gets the mutable element of a vector
1249    #[inline]
1250    pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
1251    where
1252        I: SliceIndex<[T]>,
1253    {
1254        self.0.get_mut(index)
1255    }
1256}
1257
1258impl<T, const MAX_LEN: usize> Confined<Vec<T>, ZERO, MAX_LEN> {
1259    /// Removes the last element from a vector and returns it, or [`None`] if it
1260    /// is empty.
1261    #[inline]
1262    pub fn pop(&mut self) -> Option<T> {
1263        self.0.pop()
1264    }
1265}
1266
1267impl<T, const MIN_LEN: usize, const MAX_LEN: usize> Confined<Vec<T>, MIN_LEN, MAX_LEN> {
1268    /// Removes an element from the vector at a given index. Errors if the index
1269    /// exceeds the number of elements in the vector, of if the new vector
1270    /// length will be less than the confinement requirement. Returns the
1271    /// removed element otherwise.
1272    pub fn remove(&mut self, index: usize) -> Result<T, Error> {
1273        let len = self.len();
1274        if self.is_empty() || len <= MIN_LEN {
1275            return Err(Error::Undersize {
1276                len,
1277                min_len: MIN_LEN,
1278            });
1279        }
1280        if index >= len {
1281            return Err(Error::OutOfBoundary { index, len });
1282        }
1283        Ok(self.0.remove(index))
1284    }
1285
1286    /// Returns an iterator over the slice.
1287    ///
1288    /// The iterator yields all items from start to end.
1289    pub fn iter(&self) -> core::slice::Iter<T> {
1290        self.0.iter()
1291    }
1292}
1293
1294impl<T, const MIN_LEN: usize, const MAX_LEN: usize> Confined<VecDeque<T>, MIN_LEN, MAX_LEN> {
1295    /// Removes the first element and returns it, or `None` if the deque is
1296    /// empty.
1297    pub fn pop_front(&mut self) -> Option<T> {
1298        self.0.pop_front()
1299    }
1300
1301    /// Removes the last element and returns it, or `None` if the deque is
1302    /// empty.
1303    pub fn pop_back(&mut self) -> Option<T> {
1304        self.0.pop_back()
1305    }
1306}
1307
1308impl<T, const MIN_LEN: usize, const MAX_LEN: usize> Confined<VecDeque<T>, MIN_LEN, MAX_LEN> {
1309    /// Prepends an element to the deque. Errors if the new collection length
1310    /// will not fit the confinement requirements.
1311    pub fn push_front(&mut self, elem: T) -> Result<(), Error> {
1312        let len = self.len();
1313        if len == MAX_LEN || len + 1 > MAX_LEN {
1314            return Err(Error::Oversize {
1315                len: len + 1,
1316                max_len: MAX_LEN,
1317            });
1318        }
1319        self.0.push_front(elem);
1320        Ok(())
1321    }
1322
1323    #[deprecated(since = "4.7.1", note = "use `push_front`")]
1324    pub fn push_from(&mut self, elem: T) -> Result<(), Error> {
1325        self.push_front(elem)
1326    }
1327
1328    /// Appends an element to the deque. Errors if the new collection length
1329    /// will not fit the confinement requirements.
1330    pub fn push_back(&mut self, elem: T) -> Result<(), Error> {
1331        let len = self.len();
1332        if len == MAX_LEN || len + 1 > MAX_LEN {
1333            return Err(Error::Oversize {
1334                len: len + 1,
1335                max_len: MAX_LEN,
1336            });
1337        }
1338        self.0.push_back(elem);
1339        Ok(())
1340    }
1341
1342    /// Removes an element from the deque at a given index. Errors if the index
1343    /// exceeds the number of elements in the deque, of if the new deque
1344    /// length will be less than the confinement requirement. Returns the
1345    /// removed element otherwise.
1346    pub fn remove(&mut self, index: usize) -> Result<T, Error> {
1347        let len = self.len();
1348        if self.is_empty() || len <= MIN_LEN {
1349            return Err(Error::Undersize {
1350                len,
1351                min_len: MIN_LEN,
1352            });
1353        }
1354        if index >= len {
1355            return Err(Error::OutOfBoundary { index, len });
1356        }
1357        Ok(self.0.remove(index).expect("element within the length"))
1358    }
1359
1360    /// Removes the specified range from the deque in bulk, returning all
1361    /// removed elements as an iterator. If the iterator is dropped before
1362    /// being fully consumed, it drops the remaining removed elements.
1363    ///
1364    /// The returned iterator keeps a mutable borrow on the queue to optimize
1365    /// its implementation.
1366    ///
1367    /// # Panics
1368    ///
1369    /// Panics if the starting point is greater than the end point or if
1370    /// the end point is greater than the length of the deque.
1371    ///
1372    /// # Leaking
1373    ///
1374    /// If the returned iterator goes out of scope without being dropped (due to
1375    /// [`mem::forget`], for example), the deque may have lost and leaked
1376    /// elements arbitrarily, including elements outside the range.
1377    pub fn drain<R: RangeBounds<usize>>(&mut self, range: R) -> Drain<'_, T> {
1378        self.0.drain(range)
1379    }
1380
1381    /// Shortens the deque, keeping the first `len` elements and dropping
1382    /// the rest.
1383    ///
1384    /// If `len` is greater or equal to the deque's current length, this has
1385    /// no effect.
1386    pub fn truncate(&mut self, len: usize) {
1387        self.0.truncate(len)
1388    }
1389}
1390
1391#[cfg(feature = "std")]
1392impl<T: Hash + Eq, const MIN_LEN: usize, const MAX_LEN: usize>
1393    Confined<HashSet<T>, MIN_LEN, MAX_LEN>
1394{
1395    /// Removes an element from the set. Errors if the index exceeds the number
1396    /// of elements in the set, of if the new collection length will be less
1397    /// than the confinement requirement. Returns if the element was present
1398    /// in the set.
1399    pub fn remove(&mut self, elem: &T) -> Result<bool, Error> {
1400        if !self.0.contains(elem) {
1401            return Ok(false);
1402        }
1403        let len = self.len();
1404        if self.is_empty() || len <= MIN_LEN {
1405            return Err(Error::Undersize {
1406                len,
1407                min_len: MIN_LEN,
1408            });
1409        }
1410        Ok(self.0.remove(elem))
1411    }
1412
1413    /// Removes an element from the set. Errors if the index exceeds the number
1414    /// of elements in the set, of if the new collection length will be less
1415    /// than the confinement requirement. Returns the removed element
1416    /// otherwise.
1417    pub fn take(&mut self, elem: &T) -> Result<Option<T>, Error> {
1418        if !self.0.contains(elem) {
1419            return Ok(None);
1420        }
1421        let len = self.len();
1422        if self.is_empty() || len <= MIN_LEN {
1423            return Err(Error::Undersize {
1424                len,
1425                min_len: MIN_LEN,
1426            });
1427        }
1428        Ok(self.0.take(elem))
1429    }
1430}
1431
1432impl<T: Ord, const MIN_LEN: usize, const MAX_LEN: usize> Confined<BTreeSet<T>, MIN_LEN, MAX_LEN> {
1433    /// Removes an element from the set. Errors if the index exceeds the number
1434    /// of elements in the set, of if the new collection length will be less
1435    /// than the confinement requirement. Returns if the element was present
1436    /// in the set.
1437    pub fn remove(&mut self, elem: &T) -> Result<bool, Error> {
1438        if !self.0.contains(elem) {
1439            return Ok(false);
1440        }
1441        let len = self.len();
1442        if self.is_empty() || len <= MIN_LEN {
1443            return Err(Error::Undersize {
1444                len,
1445                min_len: MIN_LEN,
1446            });
1447        }
1448        Ok(self.0.remove(elem))
1449    }
1450
1451    /// Removes an element from the set. Errors if the index exceeds the number
1452    /// of elements in the set, of if the new collection length will be less
1453    /// than the confinement requirement. Returns the removed element
1454    /// otherwise.
1455    pub fn take(&mut self, elem: &T) -> Result<Option<T>, Error> {
1456        if !self.0.contains(elem) {
1457            return Ok(None);
1458        }
1459        let len = self.len();
1460        if self.is_empty() || len - 1 <= MIN_LEN {
1461            return Err(Error::Undersize {
1462                len,
1463                min_len: MIN_LEN,
1464            });
1465        }
1466        Ok(self.0.take(elem))
1467    }
1468}
1469
1470#[cfg(feature = "std")]
1471impl<K: Hash + Eq, V, const MIN_LEN: usize, const MAX_LEN: usize>
1472    Confined<HashMap<K, V>, MIN_LEN, MAX_LEN>
1473{
1474    /// Removes an element from the map. Errors if the index exceeds the number
1475    /// of elements in the map, of if the new collection length will be less
1476    /// than the confinement requirement. Returns the removed value
1477    /// otherwise.
1478    pub fn remove(&mut self, key: &K) -> Result<Option<V>, Error> {
1479        if !self.0.contains_key(key) {
1480            return Ok(None);
1481        }
1482        let len = self.len();
1483        if self.is_empty() || len <= MIN_LEN {
1484            return Err(Error::Undersize {
1485                len,
1486                min_len: MIN_LEN,
1487            });
1488        }
1489        Ok(self.0.remove(key))
1490    }
1491
1492    /// Creates a consuming iterator visiting all the keys in arbitrary order.
1493    /// The map cannot be used after calling this.
1494    /// The iterator element type is `K`.
1495    pub fn into_keys(self) -> hash_map::IntoKeys<K, V> {
1496        self.0.into_keys()
1497    }
1498
1499    /// Creates a consuming iterator visiting all the values in arbitrary order.
1500    /// The map cannot be used after calling this.
1501    /// The iterator element type is `V`.
1502    pub fn into_values(self) -> hash_map::IntoValues<K, V> {
1503        self.0.into_values()
1504    }
1505}
1506
1507impl<K: Ord + Hash, V, const MIN_LEN: usize, const MAX_LEN: usize>
1508    Confined<BTreeMap<K, V>, MIN_LEN, MAX_LEN>
1509{
1510    /// Removes an element from the map. Errors if the index exceeds the number
1511    /// of elements in the map, of if the new collection length will be less
1512    /// than the confinement requirement. Returns the removed value
1513    /// otherwise.
1514    pub fn remove(&mut self, key: &K) -> Result<Option<V>, Error> {
1515        if !self.0.contains_key(key) {
1516            return Ok(None);
1517        }
1518        let len = self.len();
1519        if self.is_empty() || len <= MIN_LEN {
1520            return Err(Error::Undersize {
1521                len,
1522                min_len: MIN_LEN,
1523            });
1524        }
1525        Ok(self.0.remove(key))
1526    }
1527
1528    /// Creates a consuming iterator visiting all the keys in arbitrary order.
1529    /// The map cannot be used after calling this.
1530    /// The iterator element type is `K`.
1531    pub fn into_keys(self) -> btree_map::IntoKeys<K, V> {
1532        self.0.into_keys()
1533    }
1534
1535    /// Creates a consuming iterator visiting all the values in arbitrary order.
1536    /// The map cannot be used after calling this.
1537    /// The iterator element type is `V`.
1538    pub fn into_values(self) -> btree_map::IntoValues<K, V> {
1539        self.0.into_values()
1540    }
1541}
1542
1543// io::Writer
1544#[cfg(feature = "std")]
1545impl<const MAX_LEN: usize> io::Write for Confined<Vec<u8>, ZERO, MAX_LEN> {
1546    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1547        if buf.len() + self.len() >= MAX_LEN {
1548            return Err(io::Error::from(io::ErrorKind::OutOfMemory));
1549        }
1550        self.0.extend(buf);
1551        Ok(buf.len())
1552    }
1553
1554    fn flush(&mut self) -> io::Result<()> {
1555        // Do nothing
1556        Ok(())
1557    }
1558}
1559
1560// Vec<u8>-specific things
1561
1562impl<const MIN_LEN: usize, const MAX_LEN: usize> LowerHex for Confined<Vec<u8>, MIN_LEN, MAX_LEN> {
1563    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1564        f.write_str(&self.0.to_hex())
1565    }
1566}
1567
1568impl<const MIN_LEN: usize, const MAX_LEN: usize> UpperHex for Confined<Vec<u8>, MIN_LEN, MAX_LEN> {
1569    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1570        f.write_str(&self.0.to_hex().to_uppercase())
1571    }
1572}
1573
1574impl<const MIN_LEN: usize, const MAX_LEN: usize> FromHex for Confined<Vec<u8>, MIN_LEN, MAX_LEN> {
1575    fn from_byte_iter<I>(iter: I) -> Result<Self, hex::Error>
1576    where
1577        I: Iterator<Item = Result<u8, hex::Error>> + ExactSizeIterator + DoubleEndedIterator,
1578    {
1579        Vec::<u8>::from_byte_iter(iter).map(Self)
1580    }
1581}
1582
1583// Type aliases
1584
1585/// [`String`] with maximum 255 characters.
1586pub type TinyString = Confined<String, ZERO, U8>;
1587/// [`String`] with maximum 2^16-1 characters.
1588pub type SmallString = Confined<String, ZERO, U16>;
1589/// [`String`] with maximum 2^24-1 characters.
1590pub type MediumString = Confined<String, ZERO, U24>;
1591/// [`String`] with maximum 2^32-1 characters.
1592pub type LargeString = Confined<String, ZERO, U32>;
1593/// Confined [`String`].
1594pub type ConfinedString<const MIN: usize = 0, const MAX: usize = U64> = Confined<String, MIN, MAX>;
1595/// [`String`] which contains at least a single character.
1596pub type NonEmptyString<const MAX: usize = U64> = Confined<String, ONE, MAX>;
1597
1598/// [`AsciiString`] with maximum 255 characters.
1599pub type TinyAscii = Confined<AsciiString, ZERO, U8>;
1600/// [`AsciiString`] with maximum 2^16-1 characters.
1601pub type SmallAscii = Confined<AsciiString, ZERO, U16>;
1602/// [`AsciiString`] with maximum 2^24-1 characters.
1603pub type MediumAscii = Confined<AsciiString, ZERO, U24>;
1604/// [`AsciiString`] with maximum 2^32-1 characters.
1605pub type LargeAscii = Confined<AsciiString, ZERO, U32>;
1606/// Confined [`AsciiString`].
1607pub type ConfinedAscii<const MIN: usize = 0, const MAX: usize = U64> =
1608    Confined<AsciiString, MIN, MAX>;
1609/// [`AsciiString`] which contains at least a single character.
1610pub type NonEmptyAscii<const MAX: usize = U64> = Confined<AsciiString, ONE, MAX>;
1611
1612/// [`Vec<u8>`] with maximum 255 characters.
1613pub type TinyBlob = Confined<Vec<u8>, ZERO, U8>;
1614/// [`Vec<u8>`] with maximum 2^16-1 characters.
1615pub type SmallBlob = Confined<Vec<u8>, ZERO, U16>;
1616/// [`Vec<u8>`] with maximum 2^24-1 characters.
1617pub type MediumBlob = Confined<Vec<u8>, ZERO, U24>;
1618/// [`Vec<u8>`] with maximum 2^32-1 characters.
1619pub type LargeBlob = Confined<Vec<u8>, ZERO, U32>;
1620/// Confined [`Vec<u8>`].
1621pub type ConfinedBlob<const MIN: usize = 0, const MAX: usize = U64> = Confined<Vec<u8>, MIN, MAX>;
1622/// [`Vec<u8>`] which contains at least a single character.
1623pub type NonEmptyBlob<const MAX: usize = U64> = Confined<Vec<u8>, ONE, MAX>;
1624
1625/// [`Vec`] with maximum 255 items of type `T`.
1626pub type TinyVec<T> = Confined<Vec<T>, ZERO, U8>;
1627/// [`Vec`] with maximum 2^16-1 items of type `T`.
1628pub type SmallVec<T> = Confined<Vec<T>, ZERO, U16>;
1629/// [`Vec`] with maximum 2^24-1 items of type `T`.
1630pub type MediumVec<T> = Confined<Vec<T>, ZERO, U24>;
1631/// [`Vec`] with maximum 2^32-1 items of type `T`.
1632pub type LargeVec<T> = Confined<Vec<T>, ZERO, U32>;
1633/// Confined [`Vec`].
1634pub type ConfinedVec<T, const MIN: usize = 0, const MAX: usize = U64> = Confined<Vec<T>, MIN, MAX>;
1635/// [`Vec`] which contains at least a single item.
1636pub type NonEmptyVec<T, const MAX: usize = U64> = Confined<Vec<T>, ONE, MAX>;
1637
1638/// [`VecDeque`] with maximum 255 items of type `T`.
1639pub type TinyDeque<T> = Confined<VecDeque<T>, ZERO, U8>;
1640/// [`VecDeque`] with maximum 2^16-1 items of type `T`.
1641pub type SmallDeque<T> = Confined<VecDeque<T>, ZERO, U16>;
1642/// [`VecDeque`] with maximum 2^24-1 items of type `T`.
1643pub type MediumDeque<T> = Confined<VecDeque<T>, ZERO, U24>;
1644/// [`VecDeque`] with maximum 2^32-1 items of type `T`.
1645pub type LargeDeque<T> = Confined<VecDeque<T>, ZERO, U32>;
1646/// Confined [`VecDeque`].
1647pub type ConfinedDeque<T, const MIN: usize = 0, const MAX: usize = U64> =
1648    Confined<VecDeque<T>, MIN, MAX>;
1649/// [`VecDeque`] which contains at least a single item.
1650pub type NonEmptyDeque<T, const MAX: usize = U64> = Confined<VecDeque<T>, ONE, MAX>;
1651
1652/// [`HashSet`] with maximum 255 items of type `T`.
1653#[cfg(feature = "std")]
1654pub type TinyHashSet<T> = Confined<HashSet<T>, ZERO, U8>;
1655/// [`HashSet`] with maximum 2^16-1 items of type `T`.
1656#[cfg(feature = "std")]
1657pub type SmallHashSet<T> = Confined<HashSet<T>, ZERO, U16>;
1658/// [`HashSet`] with maximum 2^24-1 items of type `T`.
1659#[cfg(feature = "std")]
1660pub type MediumHashSet<T> = Confined<HashSet<T>, ZERO, U24>;
1661/// [`HashSet`] with maximum 2^32-1 items of type `T`.
1662#[cfg(feature = "std")]
1663pub type LargeHashSet<T> = Confined<HashSet<T>, ZERO, U32>;
1664#[cfg(feature = "std")]
1665/// Confined [`HashSet`].
1666pub type ConfinedHashSet<T, const MIN: usize = 0, const MAX: usize = U64> =
1667    Confined<HashSet<T>, MIN, MAX>;
1668/// [`HashSet`] which contains at least a single item.
1669#[cfg(feature = "std")]
1670pub type NonEmptyHashSet<T, const MAX: usize = U64> = Confined<HashSet<T>, ONE, MAX>;
1671
1672/// [`BTreeSet`] with maximum 255 items of type `T`.
1673pub type TinyOrdSet<T> = Confined<BTreeSet<T>, ZERO, U8>;
1674/// [`BTreeSet`] with maximum 2^16-1 items of type `T`.
1675pub type SmallOrdSet<T> = Confined<BTreeSet<T>, ZERO, U16>;
1676/// [`BTreeSet`] with maximum 2^24-1 items of type `T`.
1677pub type MediumOrdSet<T> = Confined<BTreeSet<T>, ZERO, U24>;
1678/// [`BTreeSet`] with maximum 2^32-1 items of type `T`.
1679pub type LargeOrdSet<T> = Confined<BTreeSet<T>, ZERO, U32>;
1680/// Confined [`BTreeSet`].
1681pub type ConfinedOrdSet<T, const MIN: usize = 0, const MAX: usize = U64> =
1682    Confined<BTreeSet<T>, MIN, MAX>;
1683/// [`BTreeSet`] which contains at least a single item.
1684pub type NonEmptyOrdSet<T, const MAX: usize = U64> = Confined<BTreeSet<T>, ONE, MAX>;
1685
1686/// [`HashMap`] with maximum 255 items.
1687#[cfg(feature = "std")]
1688pub type TinyHashMap<K, V> = Confined<HashMap<K, V>, ZERO, U8>;
1689/// [`HashMap`] with maximum 2^16-1 items.
1690#[cfg(feature = "std")]
1691pub type SmallHashMap<K, V> = Confined<HashMap<K, V>, ZERO, U16>;
1692/// [`HashMap`] with maximum 2^24-1 items.
1693#[cfg(feature = "std")]
1694pub type MediumHashMap<K, V> = Confined<HashMap<K, V>, ZERO, U24>;
1695/// [`HashMap`] with maximum 2^32-1 items.
1696#[cfg(feature = "std")]
1697pub type LargeHashMap<K, V> = Confined<HashMap<K, V>, ZERO, U32>;
1698#[cfg(feature = "std")]
1699/// Confined [`HashMap`].
1700pub type ConfinedHashMap<K, V, const MIN: usize = 0, const MAX: usize = U64> =
1701    Confined<HashSet<K, V>, MIN, MAX>;
1702/// [`HashMap`] which contains at least a single item.
1703#[cfg(feature = "std")]
1704pub type NonEmptyHashMap<K, V, const MAX: usize = U64> = Confined<HashMap<K, V>, ONE, MAX>;
1705
1706/// [`BTreeMap`] with maximum 255 items.
1707pub type TinyOrdMap<K, V> = Confined<BTreeMap<K, V>, ZERO, U8>;
1708/// [`BTreeMap`] with maximum 2^16-1 items.
1709pub type SmallOrdMap<K, V> = Confined<BTreeMap<K, V>, ZERO, U16>;
1710/// [`BTreeMap`] with maximum 2^24-1 items.
1711pub type MediumOrdMap<K, V> = Confined<BTreeMap<K, V>, ZERO, U24>;
1712/// [`BTreeMap`] with maximum 2^32-1 items.
1713pub type LargeOrdMap<K, V> = Confined<BTreeMap<K, V>, ZERO, U32>;
1714/// Confined [`BTreeMap`].
1715pub type ConfinedOrdMap<K, V, const MIN: usize = 0, const MAX: usize = U64> =
1716    Confined<BTreeMap<K, V>, MIN, MAX>;
1717/// [`BTreeMap`] which contains at least a single item.
1718pub type NonEmptyOrdMap<K, V, const MAX: usize = U64> = Confined<BTreeMap<K, V>, ONE, MAX>;
1719
1720/// Helper macro to construct confined string
1721#[macro_export]
1722#[deprecated(since = "4.7.0", note = "use size-specific macros")]
1723macro_rules! confined_s {
1724    () => {
1725        $crate::confinement::Confined::<String>::new()
1726    };
1727    ($s:literal) => {
1728        $crate::confinement::Confined::try_from(s!($s))
1729            .expect("inline confined_s literal exceeds confinement length")
1730            .into()
1731    };
1732}
1733
1734/// Helper macro to construct confined string of a [`TinyString`] type
1735#[macro_export]
1736macro_rules! tiny_s {
1737    () => {
1738        $crate::confinement::TinyString::new()
1739    };
1740    ($lit:literal) => {
1741        $crate::confinement::TinyString::try_from(s!($lit))
1742            .expect("static string for tiny_s literal cis too long")
1743    };
1744}
1745
1746/// Helper macro to construct confined string of a [`SmallString`] type
1747#[macro_export]
1748macro_rules! small_s {
1749    () => {
1750        $crate::confinement::SmallString::new()
1751    };
1752    ($lit:literal) => {
1753        $crate::confinement::SmallString::try_from(s!($lit))
1754            .expect("static string for small_s literal cis too long")
1755    };
1756}
1757
1758/// Helper macro to construct confined string of a [`MediumString`] type
1759#[macro_export]
1760macro_rules! medium_s {
1761    () => {
1762        $crate::confinement::MediumString::new()
1763    };
1764    ($lit:literal) => {
1765        $crate::confinement::MediumString::try_from(s!($lit))
1766            .expect("static string for medium_s literal cis too long")
1767    };
1768}
1769
1770/// Helper macro to construct confined blob
1771#[macro_export]
1772#[deprecated(since = "4.7.0", note = "use size-specific macros")]
1773macro_rules! confined_blob {
1774    () => {
1775        $crate::confinement::ConfinedBlob::new()
1776    };
1777    ($elem:expr; $n:expr) => (
1778        $crate::confinement::ConfinedBlob::try_from(vec![$elem; $n])
1779            .expect("inline confined_blob contains invalid number of items")
1780    );
1781    ($($x:expr),+ $(,)?) => (
1782        $crate::confinement::ConfinedBlob::try_from(vec![$($x,)+])
1783            .expect("inline confined_blob contains invalid number of items")
1784            .into()
1785    )
1786}
1787
1788/// Helper macro to construct confined blob of a [`TinyBlob`] type
1789#[macro_export]
1790macro_rules! tiny_blob {
1791    () => {
1792        $crate::confinement::TinyBlob::new()
1793    };
1794    ($elem:expr; $n:expr) => (
1795        $crate::confinement::TinyBlob::try_from(vec![$elem; $n])
1796            .expect("inline tiny_blob contains invalid number of items")
1797    );
1798    ($($x:expr),+ $(,)?) => (
1799        $crate::confinement::TinyBlob::try_from(vec![$($x,)+])
1800            .expect("inline tiny_blob contains invalid number of items")
1801    )
1802}
1803
1804/// Helper macro to construct confined blob of a [`SmallBlob`] type
1805#[macro_export]
1806macro_rules! small_blob {
1807    () => {
1808        $crate::confinement::SmallBlob::new()
1809    };
1810    ($elem:expr; $n:expr) => (
1811        $crate::confinement::SmallBlob::try_from(vec![$elem; $n])
1812            .expect("inline small_blob contains invalid number of items")
1813    );
1814    ($($x:expr),+ $(,)?) => (
1815        $crate::confinement::SmallBlob::try_from(vec![$($x,)+])
1816            .expect("inline small_blob contains invalid number of items")
1817    )
1818}
1819
1820/// Helper macro to construct confined blob of a [`MediumBlob`] type
1821#[macro_export]
1822macro_rules! medium_blob {
1823    () => {
1824        $crate::confinement::MediumBlob::new()
1825    };
1826    ($elem:expr; $n:expr) => (
1827        $crate::confinement::MediumBlob::try_from(vec![$elem; $n])
1828            .expect("inline medium_blob contains invalid number of items")
1829    );
1830    ($($x:expr),+ $(,)?) => (
1831        $crate::confinement::MediumBlob::try_from(vec![$($x,)+])
1832            .expect("inline medium_blob contains invalid number of items")
1833    )
1834}
1835
1836/// Helper macro to construct confined vector of a given type
1837#[macro_export]
1838#[deprecated(since = "4.7.0", note = "use size-specific macros")]
1839macro_rules! confined_vec {
1840    () => {
1841        $crate::confinement::Confined::<Vec<_>>::new()
1842    };
1843    ($elem:expr; $n:expr) => (
1844        $crate::confinement::Confined::try_from(vec![$elem; $n])
1845            .expect("inline confined_vec literal contains invalid number of items")
1846    );
1847    ($($x:expr),+ $(,)?) => (
1848        $crate::confinement::Confined::try_from(vec![$($x,)+])
1849            .expect("inline confined_vec literal contains invalid number of items")
1850            .into()
1851    )
1852}
1853
1854/// Helper macro to construct confined vector of a [`TinyVec`] type
1855#[macro_export]
1856macro_rules! tiny_vec {
1857    () => {
1858        $crate::confinement::TinyVec::new()
1859    };
1860    ($elem:expr; $n:expr) => (
1861        $crate::confinement::TinyVec::try_from(vec![$elem; $n])
1862            .expect("inline tiny_vec literal contains invalid number of items")
1863    );
1864    ($($x:expr),+ $(,)?) => (
1865        $crate::confinement::TinyVec::try_from(vec![$($x,)+])
1866            .expect("inline tiny_vec literal contains invalid number of items")
1867    )
1868}
1869
1870/// Helper macro to construct confined vector of a [`SmallVec`] type
1871#[macro_export]
1872macro_rules! small_vec {
1873    () => {
1874        $crate::confinement::SmallVec::new()
1875    };
1876    ($elem:expr; $n:expr) => (
1877        $crate::confinement::SmallVec::try_from(vec![$elem; $n])
1878            .expect("inline small_vec literal contains invalid number of items")
1879    );
1880    ($($x:expr),+ $(,)?) => (
1881        $crate::confinement::SmallVec::try_from(vec![$($x,)+])
1882            .expect("inline small_vec literal contains invalid number of items")
1883    )
1884}
1885
1886/// Helper macro to construct confined vector of a [`MediumVec`] type
1887#[macro_export]
1888macro_rules! medium_vec {
1889    () => {
1890        $crate::confinement::MediumVec::new()
1891    };
1892    ($elem:expr; $n:expr) => (
1893        $crate::confinement::MediumVec::try_from(vec![$elem; $n])
1894            .expect("inline medium_vec literal contains invalid number of items")
1895    );
1896    ($($x:expr),+ $(,)?) => (
1897        $crate::confinement::MediumVec::try_from(vec![$($x,)+])
1898            .expect("inline medium_vec literal contains invalid number of items")
1899    )
1900}
1901
1902/// Helper macro to construct confined [`HashSet`] of a given type
1903#[macro_export]
1904#[deprecated(since = "4.7.0", note = "use size-specific macros")]
1905macro_rules! confined_set {
1906    () => {
1907        $crate::confinement::Confined::<HashSet<_>>::new()
1908    };
1909    ($($x:expr),+ $(,)?) => (
1910        $crate::confinement::Confined::try_from(set![$($x,)+])
1911            .expect("inline confined_set literal contains invalid number of items")
1912            .into()
1913    )
1914}
1915
1916/// Helper macro to construct confined [`HashSet`] of a [`TinyHashSet`] type
1917#[macro_export]
1918macro_rules! tiny_set {
1919    () => {
1920        $crate::confinement::TinyHashSet::new()
1921    };
1922    ($($x:expr),+ $(,)?) => (
1923        $crate::confinement::TinyHashSet::try_from(set![$($x,)+])
1924            .expect("inline tiny_set literal contains invalid number of items")
1925    )
1926}
1927
1928/// Helper macro to construct confined [`HashSet`] of a [`SmallHashSet`] type
1929#[macro_export]
1930macro_rules! small_set {
1931    () => {
1932        $crate::confinement::SmallHashSet::new()
1933    };
1934    ($($x:expr),+ $(,)?) => (
1935        $crate::confinement::SmallHashSet::try_from(set![$($x,)+])
1936            .expect("inline small_set literal contains invalid number of items")
1937    )
1938}
1939
1940/// Helper macro to construct confined [`HashSet`] of a [`MediumHashSet`] type
1941#[macro_export]
1942macro_rules! medium_set {
1943    () => {
1944        $crate::confinement::MediumHashSet::new()
1945    };
1946    ($($x:expr),+ $(,)?) => (
1947        $crate::confinement::MediumHashSet::try_from(set![$($x,)+])
1948            .expect("inline medium_set literal contains invalid number of items")
1949    )
1950}
1951
1952/// Helper macro to construct confined [`BTreeSet`] of a given type
1953#[macro_export]
1954#[deprecated(since = "4.7.0", note = "use size-specific macros")]
1955macro_rules! confined_bset {
1956    () => {
1957        $crate::confinement::Confined::<BTreeSet<_>>::new()
1958    };
1959    ($($x:expr),+ $(,)?) => (
1960        $crate::confinement::Confined::try_from(bset![$($x,)+])
1961            .expect("inline confined_bset literal contains invalid number of items")
1962            .into()
1963    )
1964}
1965
1966/// Helper macro to construct confined [`BTreeSet`] of a [`TinyOrdSet`] type
1967#[macro_export]
1968macro_rules! tiny_bset {
1969    () => {
1970        $crate::confinement::TinyOrdSet::new()
1971    };
1972    ($($x:expr),+ $(,)?) => (
1973        $crate::confinement::TinyOrdSet::try_from(bset![$($x,)+])
1974            .expect("inline tiny_bset literal contains invalid number of items")
1975    )
1976}
1977
1978/// Helper macro to construct confined [`BTreeSet`] of a [`SmallOrdSet`] type
1979#[macro_export]
1980macro_rules! small_bset {
1981    () => {
1982        $crate::confinement::SmallOrdSet::new()
1983    };
1984    ($($x:expr),+ $(,)?) => (
1985        $crate::confinement::SmallOrdSet::try_from(bset![$($x,)+])
1986            .expect("inline small_bset literal contains invalid number of items")
1987    )
1988}
1989
1990/// Helper macro to construct confined [`BTreeSet`] of a [`MediumOrdSet`] type
1991#[macro_export]
1992macro_rules! medium_bset {
1993    () => {
1994        $crate::confinement::MediumOrdSet::new()
1995    };
1996    ($($x:expr),+ $(,)?) => (
1997        $crate::confinement::MediumOrdSet::try_from(bset![$($x,)+])
1998            .expect("inline medium_bset literal contains invalid number of items")
1999    )
2000}
2001
2002/// Helper macro to construct confined [`HashMap`] of a given type
2003#[macro_export]
2004#[deprecated(since = "4.7.0", note = "use size-specific macros")]
2005macro_rules! confined_map {
2006    () => {
2007        $crate::confinement::Confined::<HashMap<_, _>>::new()
2008    };
2009    ($($key:expr => $value:expr),+ $(,)?) => (
2010        $crate::confinement::Confined::try_from(map!{ $($key => $value),+ })
2011            .expect("inline confined_map literal contains invalid number of items")
2012            .into()
2013    )
2014}
2015
2016/// Helper macro to construct confined [`HashMap`] of a [`TinyHashMap`] type
2017#[macro_export]
2018macro_rules! tiny_map {
2019    () => {
2020        $crate::confinement::TinyHashMap::new()
2021    };
2022    { $($key:expr => $value:expr),+ $(,)? } => {
2023        $crate::confinement::TinyHashMap::try_from(map!{ $($key => $value,)+ })
2024            .expect("inline tiny_map literal contains invalid number of items")
2025    }
2026}
2027
2028/// Helper macro to construct confined [`HashMap`] of a [`SmallHashMap`] type
2029#[macro_export]
2030macro_rules! small_map {
2031    () => {
2032        $crate::confinement::SmallHashMap::new()
2033    };
2034    { $($key:expr => $value:expr),+ $(,)? } => {
2035        $crate::confinement::SmallHashMap::try_from(map!{ $($key => $value,)+ })
2036            .expect("inline small_map literal contains invalid number of items")
2037    }
2038}
2039
2040/// Helper macro to construct confined [`HashMap`] of a [`MediumHashMap`] type
2041#[macro_export]
2042macro_rules! medium_map {
2043    () => {
2044        $crate::confinement::MediumHashMap::new()
2045    };
2046    { $($key:expr => $value:expr),+ $(,)? } => {
2047        $crate::confinement::MediumHashMap::try_from(map!{ $($key => $value,)+ })
2048            .expect("inline medium_map literal contains invalid number of items")
2049    }
2050}
2051
2052/// Helper macro to construct confined [`BTreeMap`] of a given type
2053#[macro_export]
2054#[deprecated(since = "4.7.0", note = "use size-specific macros")]
2055macro_rules! confined_bmap {
2056    () => {
2057        $crate::confinement::Confined::<BTreeMap<_, _>>::new()
2058    };
2059    ($($key:expr => $value:expr),+ $(,)?) => (
2060        $crate::confinement::Confined::try_from(bmap!{ $($key => $value),+ })
2061            .expect("inline confined_bmap literal contains invalid number of items")
2062            .into()
2063    )
2064}
2065
2066/// Helper macro to construct confined [`BTreeMap`] of a [`TinyOrdMap`] type
2067#[macro_export]
2068macro_rules! tiny_bmap {
2069    () => {
2070        $crate::confinement::TinyOrdMap::new()
2071    };
2072    { $($key:expr => $value:expr),+ $(,)? } => {
2073        $crate::confinement::TinyOrdMap::try_from(bmap!{ $($key => $value,)+ })
2074            .expect("inline tiny_bmap literal contains invalid number of items")
2075    }
2076}
2077
2078/// Helper macro to construct confined [`BTreeMap`] of a [`SmallOrdMap`] type
2079#[macro_export]
2080macro_rules! small_bmap {
2081    () => {
2082        $crate::confinement::SmallOrdMap::new()
2083    };
2084    { $($key:expr => $value:expr),+ $(,)? } => {
2085        $crate::confinement::SmallOrdMap::try_from(bmap!{ $($key => $value,)+ })
2086            .expect("inline small_bmap literal contains invalid number of items")
2087    }
2088}
2089
2090/// Helper macro to construct confined [`BTreeMap`] of a [`MediumOrdMap`] type
2091#[macro_export]
2092macro_rules! medium_bmap {
2093    () => {
2094        $crate::confinement::MediumOrdMap::new()
2095    };
2096    { $($key:expr => $value:expr),+ $(,)? } => {
2097        $crate::confinement::MediumOrdMap::try_from(bmap!{ $($key => $value,)+ })
2098            .expect("inline medium_bmap literal contains invalid number of items")
2099    }
2100}
2101
2102#[cfg(test)]
2103mod test {
2104    use super::*;
2105
2106    #[test]
2107    fn fits_max() {
2108        let mut s = TinyString::new();
2109        assert!(s.is_empty());
2110        for _ in 1..=255 {
2111            s.push('a').unwrap();
2112        }
2113        assert_eq!(s.len_u8(), u8::MAX);
2114        assert_eq!(s.len_u8(), s.len() as u8);
2115        assert!(!s.is_empty());
2116
2117        let mut vec = TinyVec::new();
2118        let mut deque = TinyDeque::new();
2119        let mut set = TinyHashSet::new();
2120        let mut bset = TinyOrdSet::new();
2121        let mut map = TinyHashMap::new();
2122        let mut bmap = TinyOrdMap::new();
2123        assert!(vec.is_empty());
2124        assert!(deque.is_empty());
2125        assert!(set.is_empty());
2126        assert!(bset.is_empty());
2127        assert!(map.is_empty());
2128        assert!(bmap.is_empty());
2129        for index in 1..=255 {
2130            vec.push(5u8).unwrap();
2131            deque.push(5u8).unwrap();
2132            set.push(index).unwrap();
2133            bset.push(5u8).unwrap();
2134            map.insert(5u8, 'a').unwrap();
2135            bmap.insert(index, 'a').unwrap();
2136        }
2137        assert_eq!(vec.len_u8(), u8::MAX);
2138        assert_eq!(deque.len_u8(), u8::MAX);
2139        assert_eq!(set.len_u8(), u8::MAX);
2140        assert_eq!(bset.len_u8(), 1);
2141        assert_eq!(map.len_u8(), 1);
2142        assert_eq!(bmap.len_u8(), u8::MAX);
2143
2144        vec.clear();
2145        assert!(vec.is_empty());
2146    }
2147
2148    #[test]
2149    #[should_panic(expected = "Oversize")]
2150    fn cant_go_above_max() {
2151        let mut s = TinyString::new();
2152        for _ in 1..=256 {
2153            s.push('a').unwrap();
2154        }
2155    }
2156
2157    #[test]
2158    #[should_panic(expected = "Undersize")]
2159    fn cant_go_below_min() {
2160        let mut s = NonEmptyString::<U8>::with('a');
2161        s.remove(0).unwrap();
2162    }
2163
2164    #[test]
2165    fn entry() {
2166        let mut col = tiny_bmap!(0u16 => 'a');
2167        assert!(matches!(
2168            col.entry(0).unwrap(),
2169            btree_map::Entry::Occupied(_)
2170        ));
2171        assert!(matches!(col.entry(1).unwrap(), btree_map::Entry::Vacant(_)));
2172        for idx in 1..u8::MAX {
2173            col.insert(idx as u16, 'b').unwrap();
2174        }
2175        assert!(matches!(
2176            col.entry(2).unwrap(),
2177            btree_map::Entry::Occupied(_)
2178        ));
2179        assert!(col.entry(256).is_err());
2180    }
2181
2182    #[test]
2183    fn macros() {
2184        tiny_vec!() as TinyVec<&str>;
2185        tiny_vec!("a", "b", "c");
2186        small_vec!("a", "b", "c");
2187
2188        tiny_set!() as TinyHashSet<&str>;
2189        tiny_set!("a", "b", "c");
2190        tiny_bset!() as TinyOrdSet<&str>;
2191        tiny_bset!("a", "b", "c");
2192        tiny_map!() as TinyHashMap<&str, u8>;
2193        tiny_map!("a" => 1, "b" => 2, "c" => 3);
2194        tiny_bmap!() as TinyOrdMap<&str, u8>;
2195        tiny_bmap!("a" => 1, "b" => 2, "c" => 3);
2196
2197        small_set!("a", "b", "c");
2198        small_bset!("a", "b", "c");
2199        small_map!("a" => 1, "b" => 2, "c" => 3);
2200        small_bmap!("a" => 1, "b" => 2, "c" => 3);
2201    }
2202
2203    #[test]
2204    fn iter_mut_btree() {
2205        let mut coll = tiny_bmap!(1 => "one");
2206        for (_index, item) in &mut coll {
2207            *item = "two";
2208        }
2209        assert_eq!(coll.get(&1), Some(&"two"));
2210        for (_index, item) in coll.keyed_values_mut() {
2211            *item = "three";
2212        }
2213        assert_eq!(coll.get(&1), Some(&"three"));
2214        for item in coll.values_mut() {
2215            *item = "four";
2216        }
2217        assert_eq!(coll.get(&1), Some(&"four"));
2218        *coll.get_mut(&1).unwrap() = "five";
2219        assert_eq!(coll.get(&1), Some(&"five"));
2220    }
2221}