|
| 1 | +//! CBOR decoding helper functions. |
| 2 | +
|
| 3 | +use minicbor::{data::Tag, decode, Decoder}; |
| 4 | + |
| 5 | +/// Generic helper function for decoding different types. |
| 6 | +/// |
| 7 | +/// # Errors |
| 8 | +/// |
| 9 | +/// Error if the decoding fails. |
| 10 | +pub fn decode_helper<'a, T, C>( |
| 11 | + d: &mut Decoder<'a>, from: &str, context: &mut C, |
| 12 | +) -> Result<T, decode::Error> |
| 13 | +where T: minicbor::Decode<'a, C> { |
| 14 | + T::decode(d, context).map_err(|e| { |
| 15 | + decode::Error::message(format!( |
| 16 | + "Failed to decode {:?} in {from}: {e}", |
| 17 | + std::any::type_name::<T>() |
| 18 | + )) |
| 19 | + }) |
| 20 | +} |
| 21 | + |
| 22 | +/// Helper function for decoding bytes. |
| 23 | +/// |
| 24 | +/// # Errors |
| 25 | +/// |
| 26 | +/// Error if the decoding fails. |
| 27 | +pub fn decode_bytes(d: &mut Decoder, from: &str) -> Result<Vec<u8>, decode::Error> { |
| 28 | + d.bytes().map(<[u8]>::to_vec).map_err(|e| { |
| 29 | + decode::Error::message(format!( |
| 30 | + "Failed to decode bytes in {from}: |
| 31 | + {e}" |
| 32 | + )) |
| 33 | + }) |
| 34 | +} |
| 35 | + |
| 36 | +/// Helper function for decoding array. |
| 37 | +/// |
| 38 | +/// # Errors |
| 39 | +/// |
| 40 | +/// Error if the decoding fails. |
| 41 | +pub fn decode_array_len(d: &mut Decoder, from: &str) -> Result<u64, decode::Error> { |
| 42 | + d.array() |
| 43 | + .map_err(|e| { |
| 44 | + decode::Error::message(format!( |
| 45 | + "Failed to decode array in {from}: |
| 46 | + {e}" |
| 47 | + )) |
| 48 | + })? |
| 49 | + .ok_or(decode::Error::message(format!( |
| 50 | + "Failed to decode array in {from}, unexpected indefinite length", |
| 51 | + ))) |
| 52 | +} |
| 53 | + |
| 54 | +/// Helper function for decoding map. |
| 55 | +/// |
| 56 | +/// # Errors |
| 57 | +/// |
| 58 | +/// Error if the decoding fails. |
| 59 | +pub fn decode_map_len(d: &mut Decoder, from: &str) -> Result<u64, decode::Error> { |
| 60 | + d.map() |
| 61 | + .map_err(|e| decode::Error::message(format!("Failed to decode map in {from}: {e}")))? |
| 62 | + .ok_or(decode::Error::message(format!( |
| 63 | + "Failed to decode map in {from}, unexpected indefinite length", |
| 64 | + ))) |
| 65 | +} |
| 66 | + |
| 67 | +/// Helper function for decoding tag. |
| 68 | +/// |
| 69 | +/// # Errors |
| 70 | +/// |
| 71 | +/// Error if the decoding fails. |
| 72 | +pub fn decode_tag(d: &mut Decoder, from: &str) -> Result<Tag, decode::Error> { |
| 73 | + d.tag() |
| 74 | + .map_err(|e| decode::Error::message(format!("Failed to decode tag in {from}: {e}"))) |
| 75 | +} |
| 76 | + |
| 77 | +/// Decode any in CDDL, only support basic datatype |
| 78 | +/// |
| 79 | +/// # Errors |
| 80 | +/// |
| 81 | +/// Error if the decoding fails. |
| 82 | +pub fn decode_any(d: &mut Decoder, from: &str) -> Result<Vec<u8>, decode::Error> { |
| 83 | + match d.datatype()? { |
| 84 | + minicbor::data::Type::String => { |
| 85 | + match decode_helper::<String, _>(d, &format!("{from} Any"), &mut ()) { |
| 86 | + Ok(i) => Ok(i.as_bytes().to_vec()), |
| 87 | + Err(e) => Err(e), |
| 88 | + } |
| 89 | + }, |
| 90 | + minicbor::data::Type::U8 => { |
| 91 | + match decode_helper::<u8, _>(d, &format!("{from} Any"), &mut ()) { |
| 92 | + Ok(i) => Ok(i.to_be_bytes().to_vec()), |
| 93 | + Err(e) => Err(e), |
| 94 | + } |
| 95 | + }, |
| 96 | + minicbor::data::Type::U16 => { |
| 97 | + match decode_helper::<u16, _>(d, &format!("{from} Any"), &mut ()) { |
| 98 | + Ok(i) => Ok(i.to_be_bytes().to_vec()), |
| 99 | + Err(e) => Err(e), |
| 100 | + } |
| 101 | + }, |
| 102 | + minicbor::data::Type::U32 => { |
| 103 | + match decode_helper::<u32, _>(d, &format!("{from} Any"), &mut ()) { |
| 104 | + Ok(i) => Ok(i.to_be_bytes().to_vec()), |
| 105 | + Err(e) => Err(e), |
| 106 | + } |
| 107 | + }, |
| 108 | + minicbor::data::Type::U64 => { |
| 109 | + match decode_helper::<u64, _>(d, &format!("{from} Any"), &mut ()) { |
| 110 | + Ok(i) => Ok(i.to_be_bytes().to_vec()), |
| 111 | + Err(e) => Err(e), |
| 112 | + } |
| 113 | + }, |
| 114 | + minicbor::data::Type::I8 => { |
| 115 | + match decode_helper::<i8, _>(d, &format!("{from} Any"), &mut ()) { |
| 116 | + Ok(i) => Ok(i.to_be_bytes().to_vec()), |
| 117 | + Err(e) => Err(e), |
| 118 | + } |
| 119 | + }, |
| 120 | + minicbor::data::Type::I16 => { |
| 121 | + match decode_helper::<i16, _>(d, &format!("{from} Any"), &mut ()) { |
| 122 | + Ok(i) => Ok(i.to_be_bytes().to_vec()), |
| 123 | + Err(e) => Err(e), |
| 124 | + } |
| 125 | + }, |
| 126 | + minicbor::data::Type::I32 => { |
| 127 | + match decode_helper::<i32, _>(d, &format!("{from} Any"), &mut ()) { |
| 128 | + Ok(i) => Ok(i.to_be_bytes().to_vec()), |
| 129 | + Err(e) => Err(e), |
| 130 | + } |
| 131 | + }, |
| 132 | + minicbor::data::Type::I64 => { |
| 133 | + match decode_helper::<i64, _>(d, &format!("{from} Any"), &mut ()) { |
| 134 | + Ok(i) => Ok(i.to_be_bytes().to_vec()), |
| 135 | + Err(e) => Err(e), |
| 136 | + } |
| 137 | + }, |
| 138 | + minicbor::data::Type::Bytes => Ok(decode_bytes(d, &format!("{from} Any"))?), |
| 139 | + minicbor::data::Type::Array => { |
| 140 | + Ok(decode_array_len(d, &format!("{from} Any"))? |
| 141 | + .to_be_bytes() |
| 142 | + .to_vec()) |
| 143 | + }, |
| 144 | + _ => { |
| 145 | + Err(decode::Error::message(format!( |
| 146 | + "{from} Any, Data type not supported" |
| 147 | + ))) |
| 148 | + }, |
| 149 | + } |
| 150 | +} |
| 151 | + |
| 152 | +#[cfg(test)] |
| 153 | +mod tests { |
| 154 | + |
| 155 | + use minicbor::Encoder; |
| 156 | + |
| 157 | + use super::*; |
| 158 | + |
| 159 | + #[test] |
| 160 | + fn test_decode_any_bytes() { |
| 161 | + let mut buf = Vec::new(); |
| 162 | + let mut e = Encoder::new(&mut buf); |
| 163 | + e.bytes(&[1, 2, 3, 4]).expect("Error encoding bytes"); |
| 164 | + |
| 165 | + let mut d = Decoder::new(&buf); |
| 166 | + let result = decode_any(&mut d, "test").expect("Error decoding bytes"); |
| 167 | + assert_eq!(result, vec![1, 2, 3, 4]); |
| 168 | + } |
| 169 | + |
| 170 | + #[test] |
| 171 | + fn test_decode_any_string() { |
| 172 | + let mut buf = Vec::new(); |
| 173 | + let mut e = Encoder::new(&mut buf); |
| 174 | + e.str("hello").expect("Error encoding string"); |
| 175 | + |
| 176 | + let mut d = Decoder::new(&buf); |
| 177 | + let result = decode_any(&mut d, "test").expect("Error decoding string"); |
| 178 | + assert_eq!(result, b"hello".to_vec()); |
| 179 | + } |
| 180 | + |
| 181 | + #[test] |
| 182 | + fn test_decode_any_array() { |
| 183 | + // The array should contain a supported type |
| 184 | + let mut buf = Vec::new(); |
| 185 | + let mut e = Encoder::new(&mut buf); |
| 186 | + e.array(2).expect("Error encoding array"); |
| 187 | + e.u8(1).expect("Error encoding u8"); |
| 188 | + e.u8(2).expect("Error encoding u8"); |
| 189 | + let mut d = Decoder::new(&buf); |
| 190 | + let result = decode_any(&mut d, "test").expect("Error decoding array"); |
| 191 | + // The decode of array is just a length of the array |
| 192 | + assert_eq!( |
| 193 | + u64::from_be_bytes(result.try_into().expect("Error converting bytes to u64")), |
| 194 | + 2 |
| 195 | + ); |
| 196 | + } |
| 197 | + |
| 198 | + #[test] |
| 199 | + fn test_decode_any_u32() { |
| 200 | + let mut buf = Vec::new(); |
| 201 | + let mut e = Encoder::new(&mut buf); |
| 202 | + let num: u32 = 123_456_789; |
| 203 | + e.u32(num).expect("Error encoding u32"); |
| 204 | + |
| 205 | + let mut d = Decoder::new(&buf); |
| 206 | + let result = decode_any(&mut d, "test").expect("Error decoding u32"); |
| 207 | + assert_eq!( |
| 208 | + u32::from_be_bytes(result.try_into().expect("Error converting bytes to u32")), |
| 209 | + num |
| 210 | + ); |
| 211 | + } |
| 212 | + |
| 213 | + #[test] |
| 214 | + fn test_decode_any_i32() { |
| 215 | + let mut buf = Vec::new(); |
| 216 | + let mut e = Encoder::new(&mut buf); |
| 217 | + let num: i32 = -123_456_789; |
| 218 | + e.i32(num).expect("Error encoding i32"); |
| 219 | + let mut d = Decoder::new(&buf); |
| 220 | + let result = decode_any(&mut d, "test").expect("Error decoding i32"); |
| 221 | + assert_eq!( |
| 222 | + i32::from_be_bytes(result.try_into().expect("Error converting bytes to i32")), |
| 223 | + num |
| 224 | + ); |
| 225 | + } |
| 226 | + |
| 227 | + #[test] |
| 228 | + fn test_decode_any_unsupported_type() { |
| 229 | + let mut buf = Vec::new(); |
| 230 | + let mut e = Encoder::new(&mut buf); |
| 231 | + e.null().expect("Error encoding null"); // Encode a null type which is unsupported |
| 232 | + |
| 233 | + let mut d = Decoder::new(&buf); |
| 234 | + let result = decode_any(&mut d, "test"); |
| 235 | + // Should print out the error message with the location of the error |
| 236 | + assert!(result.is_err()); |
| 237 | + } |
| 238 | +} |
0 commit comments