dcbor/
array.rs

1import_stdlib!();
2
3use crate::{CBOR, CBORCase, Error};
4
5/// # Array Support in dCBOR
6///
7/// dCBOR provides convenient conversions to and from CBOR arrays through
8/// implementation of the `From<T>` and `TryFrom<CBOR>` traits for various
9/// collection types. This enables idiomatic conversions using Rust's `.into()`
10/// method.
11///
12/// Supported collection types:
13/// - Rust arrays (`[T; N]`)
14/// - Vectors (`Vec<T>`)
15/// - VecDeque (`VecDeque<T>`)
16/// - HashSet (`HashSet<T>`)
17///
18/// For all of these, the elements must be convertible to CBOR via the
19/// `Into<CBOR>` trait.
20///
21/// ## Examples
22///
23/// ```
24/// use dcbor::prelude::*;
25///
26/// // Create CBOR from Rust array (fixed size)
27/// let array_cbor: CBOR = [1, 2, 3].into();
28///
29/// // Create CBOR from Vec
30/// let vec = vec![1, 2, 3];
31/// let vec_cbor: CBOR = vec.into();
32///
33/// // Mixed types in Vec
34/// let mixed_vec: Vec<CBOR> = vec![
35///     1.into(),         // Integer
36///     "hello".into(),   // String
37///     [1, 2, 3].into(), // Nested array
38///     true.into(),      // Boolean
39/// ];
40/// let mixed_cbor: CBOR = mixed_vec.into();
41///
42/// // Convert back to Vec
43/// let numbers: Vec<i32> = array_cbor.try_into().unwrap();
44/// assert_eq!(numbers, vec![1, 2, 3]);
45/// ```
46impl<T> From<Vec<T>> for CBOR
47where
48    T: Into<CBOR>,
49{
50    fn from(vec: Vec<T>) -> Self {
51        CBORCase::Array(vec.into_iter().map(|x| x.into()).collect()).into()
52    }
53}
54
55impl<T> From<&[T]> for CBOR
56where
57    T: Into<CBOR> + Clone,
58{
59    fn from(array: &[T]) -> Self {
60        CBORCase::Array(array.iter().map(|x| x.clone().into()).collect()).into()
61    }
62}
63
64impl<T> TryFrom<CBOR> for Vec<T>
65where
66    T: TryFrom<CBOR, Error = Error> + Clone,
67{
68    type Error = Error;
69
70    fn try_from(cbor: CBOR) -> Result<Self, Self::Error> {
71        match cbor.into_case() {
72            CBORCase::Array(cbor_array) => {
73                let mut result = Vec::new();
74                for cbor in cbor_array {
75                    result.push(T::try_from(cbor)?);
76                }
77                Ok(result)
78            }
79            _ => Err(Error::WrongType),
80        }
81    }
82}
83
84impl<T, const N: usize> From<[T; N]> for CBOR
85where
86    T: Into<CBOR>,
87{
88    fn from(array: [T; N]) -> Self {
89        CBORCase::Array(array.into_iter().map(|x| x.into()).collect()).into()
90    }
91}
92
93impl<T> From<VecDeque<T>> for CBOR
94where
95    T: Into<CBOR>,
96{
97    fn from(deque: VecDeque<T>) -> Self {
98        CBORCase::Array(deque.into_iter().map(|x| x.into()).collect()).into()
99    }
100}
101
102impl<T> TryFrom<CBOR> for VecDeque<T>
103where
104    T: TryFrom<CBOR, Error = Error> + Clone,
105{
106    type Error = Error;
107
108    fn try_from(cbor: CBOR) -> Result<Self, Self::Error> {
109        match cbor.into_case() {
110            CBORCase::Array(cbor_array) => {
111                let mut result = VecDeque::new();
112                for cbor in cbor_array {
113                    result.push_back(T::try_from(cbor)?);
114                }
115                Ok(result)
116            }
117            _ => Err(Error::WrongType),
118        }
119    }
120}
121
122impl<T> From<HashSet<T>> for CBOR
123where
124    T: Into<CBOR>,
125{
126    fn from(set: HashSet<T>) -> Self {
127        CBORCase::Array(set.into_iter().map(|x| x.into()).collect()).into()
128    }
129}
130
131impl<T> TryFrom<CBOR> for HashSet<T>
132where
133    T: TryFrom<CBOR, Error = Error> + Eq + hash::Hash + Clone,
134{
135    type Error = Error;
136
137    fn try_from(cbor: CBOR) -> Result<Self, Self::Error> {
138        match cbor.into_case() {
139            CBORCase::Array(cbor_array) => {
140                let mut result = HashSet::new();
141                for cbor in cbor_array {
142                    result.insert(T::try_from(cbor)?);
143                }
144                Ok(result)
145            }
146            _ => Err(Error::WrongType),
147        }
148    }
149}
150
151pub fn sort_array_by_cbor_encoding<T>(array: impl AsRef<[T]>) -> Vec<T>
152where
153    T: Into<CBOR> + Clone,
154{
155    let mut a: Vec<(Vec<u8>, T)> = array
156        .as_ref()
157        .iter()
158        .map(|item| (item.clone().into().to_cbor_data(), item.clone()))
159        .collect();
160    a.sort_by(|a, b| a.0.cmp(&b.0));
161    a.into_iter().map(|(_, item)| item).collect()
162}
163
164pub trait CBORSortable<T> {
165    fn sort_by_cbor_encoding(&self) -> Vec<T>
166    where
167        Self: Sized + Into<CBOR> + Clone;
168}
169
170impl<T> CBORSortable<T> for Vec<T>
171where
172    T: Into<CBOR> + Clone,
173{
174    fn sort_by_cbor_encoding(&self) -> Vec<T> {
175        sort_array_by_cbor_encoding(self)
176    }
177}
178
179impl<T> CBORSortable<T> for &[T]
180where
181    T: Into<CBOR> + Clone,
182{
183    fn sort_by_cbor_encoding(&self) -> Vec<T> {
184        sort_array_by_cbor_encoding(self)
185    }
186}
187
188impl<T> CBORSortable<T> for HashSet<T>
189where
190    T: Into<CBOR> + Clone,
191{
192    fn sort_by_cbor_encoding(&self) -> Vec<T> {
193        let array: Vec<T> = self.iter().cloned().collect();
194        array.sort_by_cbor_encoding()
195    }
196}