From dde0bcacf227d4c1ee2ac6b9b12ae2a6cfc4919e Mon Sep 17 00:00:00 2001 From: Mr-Leshiy Date: Wed, 15 Jan 2025 12:21:07 +0200 Subject: [PATCH 1/3] modify `decode_any` function --- rust/cbork-utils/src/decode_helper.rs | 80 ++++----------------------- 1 file changed, 12 insertions(+), 68 deletions(-) diff --git a/rust/cbork-utils/src/decode_helper.rs b/rust/cbork-utils/src/decode_helper.rs index 7ebf2d7afb..851a29cce0 100644 --- a/rust/cbork-utils/src/decode_helper.rs +++ b/rust/cbork-utils/src/decode_helper.rs @@ -74,79 +74,23 @@ pub fn decode_tag(d: &mut Decoder, from: &str) -> Result { .map_err(|e| decode::Error::message(format!("Failed to decode tag in {from}: {e}"))) } -/// Decode any in CDDL, only support basic datatype +/// Decode any in CDDL (any CBOR type) and return its bytes. /// /// # Errors /// /// Error if the decoding fails. pub fn decode_any(d: &mut Decoder, from: &str) -> Result, decode::Error> { - match d.datatype()? { - minicbor::data::Type::String => { - match decode_helper::(d, &format!("{from} Any"), &mut ()) { - Ok(i) => Ok(i.as_bytes().to_vec()), - Err(e) => Err(e), - } - }, - minicbor::data::Type::U8 => { - match decode_helper::(d, &format!("{from} Any"), &mut ()) { - Ok(i) => Ok(i.to_be_bytes().to_vec()), - Err(e) => Err(e), - } - }, - minicbor::data::Type::U16 => { - match decode_helper::(d, &format!("{from} Any"), &mut ()) { - Ok(i) => Ok(i.to_be_bytes().to_vec()), - Err(e) => Err(e), - } - }, - minicbor::data::Type::U32 => { - match decode_helper::(d, &format!("{from} Any"), &mut ()) { - Ok(i) => Ok(i.to_be_bytes().to_vec()), - Err(e) => Err(e), - } - }, - minicbor::data::Type::U64 => { - match decode_helper::(d, &format!("{from} Any"), &mut ()) { - Ok(i) => Ok(i.to_be_bytes().to_vec()), - Err(e) => Err(e), - } - }, - minicbor::data::Type::I8 => { - match decode_helper::(d, &format!("{from} Any"), &mut ()) { - Ok(i) => Ok(i.to_be_bytes().to_vec()), - Err(e) => Err(e), - } - }, - minicbor::data::Type::I16 => { - match decode_helper::(d, &format!("{from} Any"), &mut ()) { - Ok(i) => Ok(i.to_be_bytes().to_vec()), - Err(e) => Err(e), - } - }, - minicbor::data::Type::I32 => { - match decode_helper::(d, &format!("{from} Any"), &mut ()) { - Ok(i) => Ok(i.to_be_bytes().to_vec()), - Err(e) => Err(e), - } - }, - minicbor::data::Type::I64 => { - match decode_helper::(d, &format!("{from} Any"), &mut ()) { - Ok(i) => Ok(i.to_be_bytes().to_vec()), - Err(e) => Err(e), - } - }, - minicbor::data::Type::Bytes => Ok(decode_bytes(d, &format!("{from} Any"))?), - minicbor::data::Type::Array => { - Ok(decode_array_len(d, &format!("{from} Any"))? - .to_be_bytes() - .to_vec()) - }, - _ => { - Err(decode::Error::message(format!( - "{from} Any, Data type not supported" - ))) - }, - } + let start = d.position(); + d.skip()?; + let end = d.position(); + let bytes = d + .input() + .get(start..end) + .ok_or(decode::Error::message(format!( + "Failed to get any CBOR bytes in {from}. Ivalid CBOR bytes." + )))? + .to_vec(); + Ok(bytes) } #[cfg(test)] From 5cabb1c82f3a17b5c76f5ce6da3809935482a927 Mon Sep 17 00:00:00 2001 From: Mr-Leshiy Date: Wed, 15 Jan 2025 12:37:32 +0200 Subject: [PATCH 2/3] fix spelling --- rust/cbork-utils/src/decode_helper.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/cbork-utils/src/decode_helper.rs b/rust/cbork-utils/src/decode_helper.rs index 851a29cce0..01708372f7 100644 --- a/rust/cbork-utils/src/decode_helper.rs +++ b/rust/cbork-utils/src/decode_helper.rs @@ -87,7 +87,7 @@ pub fn decode_any(d: &mut Decoder, from: &str) -> Result, decode::Error> .input() .get(start..end) .ok_or(decode::Error::message(format!( - "Failed to get any CBOR bytes in {from}. Ivalid CBOR bytes." + "Failed to get any CBOR bytes in {from}. Invalid CBOR bytes." )))? .to_vec(); Ok(bytes) From 46981e1308dbbdae5f90a031a63bfd2a5065fddd Mon Sep 17 00:00:00 2001 From: Mr-Leshiy Date: Wed, 15 Jan 2025 12:56:47 +0200 Subject: [PATCH 3/3] update tests --- rust/cbork-utils/Cargo.toml | 6 ++ rust/cbork-utils/src/decode_helper.rs | 94 +++++++++++++-------------- 2 files changed, 52 insertions(+), 48 deletions(-) diff --git a/rust/cbork-utils/Cargo.toml b/rust/cbork-utils/Cargo.toml index a32ad179b8..87bf9aced8 100644 --- a/rust/cbork-utils/Cargo.toml +++ b/rust/cbork-utils/Cargo.toml @@ -12,3 +12,9 @@ workspace = true [dependencies] minicbor = { version = "0.25.1", features = ["std"] } + +[dev-dependencies] +proptest = { version = "1.5.0" } +# Potentially it could be replaced with using `proptest::property_test` attribute macro, +# after this PR will be merged https://github.com/proptest-rs/proptest/pull/523 +test-strategy = "0.4.0" diff --git a/rust/cbork-utils/src/decode_helper.rs b/rust/cbork-utils/src/decode_helper.rs index 01708372f7..db7462de44 100644 --- a/rust/cbork-utils/src/decode_helper.rs +++ b/rust/cbork-utils/src/decode_helper.rs @@ -79,7 +79,7 @@ pub fn decode_tag(d: &mut Decoder, from: &str) -> Result { /// # Errors /// /// Error if the decoding fails. -pub fn decode_any(d: &mut Decoder, from: &str) -> Result, decode::Error> { +pub fn decode_any<'d>(d: &mut Decoder<'d>, from: &str) -> Result<&'d [u8], decode::Error> { let start = d.position(); d.skip()?; let end = d.position(); @@ -88,93 +88,91 @@ pub fn decode_any(d: &mut Decoder, from: &str) -> Result, decode::Error> .get(start..end) .ok_or(decode::Error::message(format!( "Failed to get any CBOR bytes in {from}. Invalid CBOR bytes." - )))? - .to_vec(); + )))?; Ok(bytes) } #[cfg(test)] mod tests { - use minicbor::Encoder; + use test_strategy::proptest; use super::*; - #[test] - fn test_decode_any_bytes() { + #[proptest] + fn test_decode_any_bytes(random_bytes: Vec) { let mut buf = Vec::new(); let mut e = Encoder::new(&mut buf); - e.bytes(&[1, 2, 3, 4]).expect("Error encoding bytes"); + e.bytes(&random_bytes).expect("Error encoding bytes"); let mut d = Decoder::new(&buf); - let result = decode_any(&mut d, "test").expect("Error decoding bytes"); - assert_eq!(result, vec![1, 2, 3, 4]); + let cbor_bytes = decode_any(&mut d, "test").expect("Error decoding bytes"); + + let result = decode_bytes(&mut Decoder::new(cbor_bytes), "test").unwrap(); + assert_eq!(result, random_bytes); } - #[test] - fn test_decode_any_string() { + #[proptest] + fn test_decode_any_string(random_string: String) { let mut buf = Vec::new(); let mut e = Encoder::new(&mut buf); - e.str("hello").expect("Error encoding string"); + e.str(&random_string).expect("Error encoding string"); let mut d = Decoder::new(&buf); - let result = decode_any(&mut d, "test").expect("Error decoding string"); - assert_eq!(result, b"hello".to_vec()); + let cbor_bytes = decode_any(&mut d, "test").expect("Error decoding string"); + + let result = + decode_helper::(&mut Decoder::new(cbor_bytes), "test", &mut ()).unwrap(); + assert_eq!(result, random_string); } - #[test] - fn test_decode_any_array() { + #[proptest] + fn test_decode_any_array(random_array: Vec) { // The array should contain a supported type let mut buf = Vec::new(); let mut e = Encoder::new(&mut buf); - e.array(2).expect("Error encoding array"); - e.u8(1).expect("Error encoding u8"); - e.u8(2).expect("Error encoding u8"); + e.array(random_array.len() as u64) + .expect("Error encoding array"); + for el in &random_array { + e.u8(*el).expect("Error encoding u8"); + } let mut d = Decoder::new(&buf); - let result = decode_any(&mut d, "test").expect("Error decoding array"); + let cbor_bytes = decode_any(&mut d, "test").expect("Error decoding array"); // The decode of array is just a length of the array - assert_eq!( - u64::from_be_bytes(result.try_into().expect("Error converting bytes to u64")), - 2 - ); + let result = decode_array_len(&mut Decoder::new(cbor_bytes), "test").unwrap(); + assert_eq!(result, random_array.len() as u64); } - #[test] - fn test_decode_any_u32() { + #[proptest] + fn test_decode_any_u32(random_u32: u32) { let mut buf = Vec::new(); let mut e = Encoder::new(&mut buf); - let num: u32 = 123_456_789; - e.u32(num).expect("Error encoding u32"); + e.u32(random_u32).expect("Error encoding u32"); let mut d = Decoder::new(&buf); - let result = decode_any(&mut d, "test").expect("Error decoding u32"); - assert_eq!( - u32::from_be_bytes(result.try_into().expect("Error converting bytes to u32")), - num - ); + let cbor_bytes = decode_any(&mut d, "test").expect("Error decoding u32"); + + let result = + decode_helper::(&mut Decoder::new(cbor_bytes), "test", &mut ()).unwrap(); + assert_eq!(result, random_u32); } - #[test] - fn test_decode_any_i32() { + #[proptest] + fn test_decode_any_i32(random_i32: i32) { let mut buf = Vec::new(); let mut e = Encoder::new(&mut buf); - let num: i32 = -123_456_789; - e.i32(num).expect("Error encoding i32"); + e.i32(random_i32).expect("Error encoding i32"); let mut d = Decoder::new(&buf); - let result = decode_any(&mut d, "test").expect("Error decoding i32"); - assert_eq!( - i32::from_be_bytes(result.try_into().expect("Error converting bytes to i32")), - num - ); + let cbor_bytes = decode_any(&mut d, "test").expect("Error decoding i32"); + + let result = + decode_helper::(&mut Decoder::new(cbor_bytes), "test", &mut ()).unwrap(); + assert_eq!(result, random_i32); } #[test] - fn test_decode_any_unsupported_type() { - let mut buf = Vec::new(); - let mut e = Encoder::new(&mut buf); - e.null().expect("Error encoding null"); // Encode a null type which is unsupported - - let mut d = Decoder::new(&buf); + fn test_decode_any_not_cbor() { + let mut d = Decoder::new(&[]); let result = decode_any(&mut d, "test"); // Should print out the error message with the location of the error assert!(result.is_err());