diff --git a/libraries/cbor/src/lib.rs b/libraries/cbor/src/lib.rs index 0a128fc..0667484 100644 --- a/libraries/cbor/src/lib.rs +++ b/libraries/cbor/src/lib.rs @@ -24,5 +24,5 @@ pub mod values; pub mod writer; pub use self::reader::read; -pub use self::values::{KeyType, SimpleValue, Value}; +pub use self::values::{SimpleValue, Value}; pub use self::writer::write; diff --git a/libraries/cbor/src/macros.rs b/libraries/cbor/src/macros.rs index 758925e..7dac984 100644 --- a/libraries/cbor/src/macros.rs +++ b/libraries/cbor/src/macros.rs @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::values::{KeyType, Value}; +use crate::values::Value; use alloc::vec; use core::cmp::Ordering; use core::iter::Peekable; -/// This macro generates code to extract multiple values from a `Vec<(KeyType, Value)>` at once +/// This macro generates code to extract multiple values from a `Vec<(Value, Value)>` at once /// in an optimized manner, consuming the input vector. /// /// It takes as input a `Vec` as well as a list of identifiers and keys, and generates code @@ -57,7 +57,7 @@ macro_rules! destructure_cbor_map { #[cfg(test)] $crate::assert_sorted_keys!($( $key, )+); - use $crate::values::{IntoCborKey, Value}; + use $crate::values::{IntoCborValue, Value}; use $crate::macros::destructure_cbor_map_peek_value; // This algorithm first converts the map into a peekable iterator - whose items are sorted @@ -70,7 +70,7 @@ macro_rules! destructure_cbor_map { // to come in the same order (i.e. sorted). let mut it = $map.into_iter().peekable(); $( - let $variable: Option = destructure_cbor_map_peek_value(&mut it, $key.into_cbor_key()); + let $variable: Option = destructure_cbor_map_peek_value(&mut it, $key.into_cbor_value()); )+ }; } @@ -87,14 +87,14 @@ macro_rules! destructure_cbor_map { /// would be inlined for every use case. As of June 2020, this saves ~40KB of binary size for the /// CTAP2 application of OpenSK. pub fn destructure_cbor_map_peek_value( - it: &mut Peekable>, - needle: KeyType, + it: &mut Peekable>, + needle: Value, ) -> Option { loop { match it.peek() { None => return None, Some(item) => { - let key: &KeyType = &item.0; + let key: &Value = &item.0; match key.cmp(&needle) { Ordering::Less => { it.next(); @@ -118,9 +118,9 @@ macro_rules! assert_sorted_keys { ( $key1:expr, $key2:expr, $( $keys:expr, )* ) => { { - use $crate::values::{IntoCborKey, KeyType}; - let k1: KeyType = $key1.into_cbor_key(); - let k2: KeyType = $key2.into_cbor_key(); + use $crate::values::{IntoCborValue, Value}; + let k1: Value = $key1.into_cbor_value(); + let k2: Value = $key2.into_cbor_value(); assert!( k1 < k2, "{:?} < {:?} failed. The destructure_cbor_map! macro requires keys in sorted order.", @@ -160,10 +160,10 @@ macro_rules! cbor_map { { // The import is unused if the list is empty. #[allow(unused_imports)] - use $crate::values::{IntoCborKey, IntoCborValue}; + use $crate::values::IntoCborValue; let mut _map = ::alloc::vec::Vec::new(); $( - _map.push(($key.into_cbor_key(), $value.into_cbor_value())); + _map.push(($key.into_cbor_value(), $value.into_cbor_value())); )* $crate::values::Value::Map(_map) } @@ -201,13 +201,13 @@ macro_rules! cbor_map_options { { // The import is unused if the list is empty. #[allow(unused_imports)] - use $crate::values::{IntoCborKey, IntoCborValueOption}; + use $crate::values::{IntoCborValue, IntoCborValueOption}; let mut _map = ::alloc::vec::Vec::<(_, $crate::values::Value)>::new(); $( { let opt: Option<$crate::values::Value> = $value.into_cbor_value_option(); if let Some(val) = opt { - _map.push(($key.into_cbor_key(), val)); + _map.push(($key.into_cbor_value(), val)); } } )* @@ -216,7 +216,7 @@ macro_rules! cbor_map_options { }; } -/// Creates a CBOR Value of type Map from a Vec<(KeyType, Value)>. +/// Creates a CBOR Value of type Map from a Vec<(Value, Value)>. #[macro_export] macro_rules! cbor_map_collection { ( $tree:expr ) => {{ @@ -261,6 +261,7 @@ macro_rules! cbor_array_vec { }}; } +/// Creates a CBOR Value of type Simple with value true. #[macro_export] macro_rules! cbor_true { ( ) => { @@ -268,6 +269,7 @@ macro_rules! cbor_true { }; } +/// Creates a CBOR Value of type Simple with value false. #[macro_export] macro_rules! cbor_false { ( ) => { @@ -275,6 +277,7 @@ macro_rules! cbor_false { }; } +/// Creates a CBOR Value of type Simple with value null. #[macro_export] macro_rules! cbor_null { ( ) => { @@ -282,6 +285,7 @@ macro_rules! cbor_null { }; } +/// Creates a CBOR Value of type Simple with the undefined value. #[macro_export] macro_rules! cbor_undefined { ( ) => { @@ -289,6 +293,7 @@ macro_rules! cbor_undefined { }; } +/// Creates a CBOR Value of type Simple with the given bool value. #[macro_export] macro_rules! cbor_bool { ( $x:expr ) => { @@ -296,37 +301,47 @@ macro_rules! cbor_bool { }; } -// For key types, we construct a KeyType and call .into(), which will automatically convert it to a -// KeyType or a Value depending on the context. +/// Creates a CBOR Value of type Unsigned with the given numeric value. #[macro_export] macro_rules! cbor_unsigned { ( $x:expr ) => { - $crate::cbor_key_unsigned!($x).into() + $crate::values::Value::Unsigned($x) }; } +/// Creates a CBOR Value of type Unsigned or Negative with the given numeric value. #[macro_export] macro_rules! cbor_int { ( $x:expr ) => { - $crate::cbor_key_int!($x).into() + $crate::values::Value::integer($x) }; } +/// Creates a CBOR Value of type Text String with the given string. #[macro_export] macro_rules! cbor_text { ( $x:expr ) => { - $crate::cbor_key_text!($x).into() + $crate::values::Value::TextString($x.into()) }; } +/// Creates a CBOR Value of type Byte String with the given slice or vector. #[macro_export] macro_rules! cbor_bytes { ( $x:expr ) => { - $crate::cbor_key_bytes!($x).into() + $crate::values::Value::ByteString($x) }; } -// Macro to use with a literal, e.g. cbor_bytes_lit!(b"foo") +/// Creates a CBOR Value of type Byte String with the given byte string literal. +/// +/// Example usage: +/// +/// ```rust +/// # extern crate alloc; +/// # use cbor::cbor_bytes_lit; +/// let byte_array = cbor_bytes_lit!(b"foo"); +/// ``` #[macro_export] macro_rules! cbor_bytes_lit { ( $x:expr ) => { @@ -334,38 +349,9 @@ macro_rules! cbor_bytes_lit { }; } -// Some explicit macros are also available for contexts where the type is not explicit. -#[macro_export] -macro_rules! cbor_key_unsigned { - ( $x:expr ) => { - $crate::values::KeyType::Unsigned($x) - }; -} - -#[macro_export] -macro_rules! cbor_key_int { - ( $x:expr ) => { - $crate::values::KeyType::integer($x) - }; -} - -#[macro_export] -macro_rules! cbor_key_text { - ( $x:expr ) => { - $crate::values::KeyType::TextString($x.into()) - }; -} - -#[macro_export] -macro_rules! cbor_key_bytes { - ( $x:expr ) => { - $crate::values::KeyType::ByteString($x) - }; -} - #[cfg(test)] mod test { - use super::super::values::{KeyType, SimpleValue, Value}; + use super::super::values::{SimpleValue, Value}; #[test] fn test_cbor_simple_values() { @@ -383,23 +369,20 @@ mod test { #[test] fn test_cbor_int_unsigned() { - assert_eq!(cbor_key_int!(0), KeyType::Unsigned(0)); - assert_eq!(cbor_key_int!(1), KeyType::Unsigned(1)); - assert_eq!(cbor_key_int!(123456), KeyType::Unsigned(123456)); + assert_eq!(cbor_int!(0), Value::Unsigned(0)); + assert_eq!(cbor_int!(1), Value::Unsigned(1)); + assert_eq!(cbor_int!(123456), Value::Unsigned(123456)); assert_eq!( - cbor_key_int!(std::i64::MAX), - KeyType::Unsigned(std::i64::MAX as u64) + cbor_int!(std::i64::MAX), + Value::Unsigned(std::i64::MAX as u64) ); } #[test] fn test_cbor_int_negative() { - assert_eq!(cbor_key_int!(-1), KeyType::Negative(-1)); - assert_eq!(cbor_key_int!(-123456), KeyType::Negative(-123456)); - assert_eq!( - cbor_key_int!(std::i64::MIN), - KeyType::Negative(std::i64::MIN) - ); + assert_eq!(cbor_int!(-1), Value::Negative(-1)); + assert_eq!(cbor_int!(-123456), Value::Negative(-123456)); + assert_eq!(cbor_int!(std::i64::MIN), Value::Negative(std::i64::MIN)); } #[test] @@ -417,16 +400,16 @@ mod test { std::u64::MAX, ]; let b = Value::Array(vec![ - Value::KeyValue(KeyType::Negative(std::i64::MIN)), - Value::KeyValue(KeyType::Negative(std::i32::MIN as i64)), - Value::KeyValue(KeyType::Negative(-123456)), - Value::KeyValue(KeyType::Negative(-1)), - Value::KeyValue(KeyType::Unsigned(0)), - Value::KeyValue(KeyType::Unsigned(1)), - Value::KeyValue(KeyType::Unsigned(123456)), - Value::KeyValue(KeyType::Unsigned(std::i32::MAX as u64)), - Value::KeyValue(KeyType::Unsigned(std::i64::MAX as u64)), - Value::KeyValue(KeyType::Unsigned(std::u64::MAX)), + Value::Negative(std::i64::MIN), + Value::Negative(std::i32::MIN as i64), + Value::Negative(-123456), + Value::Negative(-1), + Value::Unsigned(0), + Value::Unsigned(1), + Value::Unsigned(123456), + Value::Unsigned(std::i32::MAX as u64), + Value::Unsigned(std::i64::MAX as u64), + Value::Unsigned(std::u64::MAX), ]); assert_eq!(a, b); } @@ -446,20 +429,17 @@ mod test { cbor_map! {2 => 3}, ]; let b = Value::Array(vec![ - Value::KeyValue(KeyType::Negative(-123)), - Value::KeyValue(KeyType::Unsigned(456)), + Value::Negative(-123), + Value::Unsigned(456), Value::Simple(SimpleValue::TrueValue), Value::Simple(SimpleValue::NullValue), - Value::KeyValue(KeyType::TextString(String::from("foo"))), - Value::KeyValue(KeyType::ByteString(b"bar".to_vec())), + Value::TextString(String::from("foo")), + Value::ByteString(b"bar".to_vec()), Value::Array(Vec::new()), - Value::Array(vec![ - Value::KeyValue(KeyType::Unsigned(0)), - Value::KeyValue(KeyType::Unsigned(1)), - ]), + Value::Array(vec![Value::Unsigned(0), Value::Unsigned(1)]), Value::Map(Vec::new()), Value::Map( - [(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))] + [(Value::Unsigned(2), Value::Unsigned(3))] .iter() .cloned() .collect(), @@ -479,10 +459,10 @@ mod test { fn test_cbor_array_vec_int() { let a = cbor_array_vec!(vec![1, 2, 3, 4]); let b = Value::Array(vec![ - Value::KeyValue(KeyType::Unsigned(1)), - Value::KeyValue(KeyType::Unsigned(2)), - Value::KeyValue(KeyType::Unsigned(3)), - Value::KeyValue(KeyType::Unsigned(4)), + Value::Unsigned(1), + Value::Unsigned(2), + Value::Unsigned(3), + Value::Unsigned(4), ]); assert_eq!(a, b); } @@ -491,9 +471,9 @@ mod test { fn test_cbor_array_vec_text() { let a = cbor_array_vec!(vec!["a", "b", "c"]); let b = Value::Array(vec![ - Value::KeyValue(KeyType::TextString(String::from("a"))), - Value::KeyValue(KeyType::TextString(String::from("b"))), - Value::KeyValue(KeyType::TextString(String::from("c"))), + Value::TextString(String::from("a")), + Value::TextString(String::from("b")), + Value::TextString(String::from("c")), ]); assert_eq!(a, b); } @@ -502,9 +482,9 @@ mod test { fn test_cbor_array_vec_bytes() { let a = cbor_array_vec!(vec![b"a", b"b", b"c"]); let b = Value::Array(vec![ - Value::KeyValue(KeyType::ByteString(b"a".to_vec())), - Value::KeyValue(KeyType::ByteString(b"b".to_vec())), - Value::KeyValue(KeyType::ByteString(b"c".to_vec())), + Value::ByteString(b"a".to_vec()), + Value::ByteString(b"b".to_vec()), + Value::ByteString(b"c".to_vec()), ]); assert_eq!(a, b); } @@ -525,40 +505,28 @@ mod test { }; let b = Value::Map( [ + (Value::Negative(-1), Value::Negative(-23)), + (Value::Unsigned(4), Value::Unsigned(56)), ( - KeyType::Negative(-1), - Value::KeyValue(KeyType::Negative(-23)), - ), - (KeyType::Unsigned(4), Value::KeyValue(KeyType::Unsigned(56))), - ( - KeyType::TextString(String::from("foo")), + Value::TextString(String::from("foo")), Value::Simple(SimpleValue::TrueValue), ), ( - KeyType::ByteString(b"bar".to_vec()), + Value::ByteString(b"bar".to_vec()), Value::Simple(SimpleValue::NullValue), ), + (Value::Unsigned(5), Value::TextString(String::from("foo"))), + (Value::Unsigned(6), Value::ByteString(b"bar".to_vec())), + (Value::Unsigned(7), Value::Array(Vec::new())), ( - KeyType::Unsigned(5), - Value::KeyValue(KeyType::TextString(String::from("foo"))), + Value::Unsigned(8), + Value::Array(vec![Value::Unsigned(0), Value::Unsigned(1)]), ), + (Value::Unsigned(9), Value::Map(Vec::new())), ( - KeyType::Unsigned(6), - Value::KeyValue(KeyType::ByteString(b"bar".to_vec())), - ), - (KeyType::Unsigned(7), Value::Array(Vec::new())), - ( - KeyType::Unsigned(8), - Value::Array(vec![ - Value::KeyValue(KeyType::Unsigned(0)), - Value::KeyValue(KeyType::Unsigned(1)), - ]), - ), - (KeyType::Unsigned(9), Value::Map(Vec::new())), - ( - KeyType::Unsigned(10), + Value::Unsigned(10), Value::Map( - [(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))] + [(Value::Unsigned(2), Value::Unsigned(3))] .iter() .cloned() .collect(), @@ -596,40 +564,28 @@ mod test { }; let b = Value::Map( [ + (Value::Negative(-1), Value::Negative(-23)), + (Value::Unsigned(4), Value::Unsigned(56)), ( - KeyType::Negative(-1), - Value::KeyValue(KeyType::Negative(-23)), - ), - (KeyType::Unsigned(4), Value::KeyValue(KeyType::Unsigned(56))), - ( - KeyType::TextString(String::from("foo")), + Value::TextString(String::from("foo")), Value::Simple(SimpleValue::TrueValue), ), ( - KeyType::ByteString(b"bar".to_vec()), + Value::ByteString(b"bar".to_vec()), Value::Simple(SimpleValue::NullValue), ), + (Value::Unsigned(5), Value::TextString(String::from("foo"))), + (Value::Unsigned(6), Value::ByteString(b"bar".to_vec())), + (Value::Unsigned(7), Value::Array(Vec::new())), ( - KeyType::Unsigned(5), - Value::KeyValue(KeyType::TextString(String::from("foo"))), + Value::Unsigned(8), + Value::Array(vec![Value::Unsigned(0), Value::Unsigned(1)]), ), + (Value::Unsigned(9), Value::Map(Vec::new())), ( - KeyType::Unsigned(6), - Value::KeyValue(KeyType::ByteString(b"bar".to_vec())), - ), - (KeyType::Unsigned(7), Value::Array(Vec::new())), - ( - KeyType::Unsigned(8), - Value::Array(vec![ - Value::KeyValue(KeyType::Unsigned(0)), - Value::KeyValue(KeyType::Unsigned(1)), - ]), - ), - (KeyType::Unsigned(9), Value::Map(Vec::new())), - ( - KeyType::Unsigned(10), + Value::Unsigned(10), Value::Map( - [(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))] + [(Value::Unsigned(2), Value::Unsigned(3))] .iter() .cloned() .collect(), @@ -652,18 +608,12 @@ mod test { #[test] fn test_cbor_map_collection_foo() { - let a = cbor_map_collection!(vec![( - KeyType::Unsigned(2), - Value::KeyValue(KeyType::Unsigned(3)) - )]); - let b = Value::Map(vec![( - KeyType::Unsigned(2), - Value::KeyValue(KeyType::Unsigned(3)), - )]); + let a = cbor_map_collection!(vec![(Value::Unsigned(2), Value::Unsigned(3))]); + let b = Value::Map(vec![(Value::Unsigned(2), Value::Unsigned(3))]); assert_eq!(a, b); } - fn extract_map(cbor_value: Value) -> Vec<(KeyType, Value)> { + fn extract_map(cbor_value: Value) -> Vec<(Value, Value)> { match cbor_value { Value::Map(map) => map, _ => panic!("Expected CBOR map."), diff --git a/libraries/cbor/src/reader.rs b/libraries/cbor/src/reader.rs index 0634d84..b11cf84 100644 --- a/libraries/cbor/src/reader.rs +++ b/libraries/cbor/src/reader.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::values::{Constants, KeyType, SimpleValue, Value}; +use super::values::{Constants, SimpleValue, Value}; use crate::{cbor_array_vec, cbor_bytes_lit, cbor_map_collection, cbor_text, cbor_unsigned}; use alloc::str; use alloc::vec::Vec; @@ -22,7 +22,6 @@ pub enum DecoderError { UnsupportedMajorType, UnknownAdditionalInfo, IncompleteCborData, - IncorrectMapKeyType, TooMuchNesting, InvalidUtf8, ExtranousData, @@ -134,7 +133,7 @@ impl<'a> Reader<'a> { if signed_size < 0 { Err(DecoderError::OutOfRangeIntegerValue) } else { - Ok(Value::KeyValue(KeyType::Negative(-(size_value as i64) - 1))) + Ok(Value::Negative(-(size_value as i64) - 1)) } } @@ -176,18 +175,14 @@ impl<'a> Reader<'a> { let mut value_map = Vec::new(); let mut last_key_option = None; for _ in 0..size_value { - let key_value = self.decode_complete_data_item(remaining_depth - 1)?; - if let Value::KeyValue(key) = key_value { - if let Some(last_key) = last_key_option { - if last_key >= key { - return Err(DecoderError::OutOfOrderKey); - } + let key = self.decode_complete_data_item(remaining_depth - 1)?; + if let Some(last_key) = last_key_option { + if last_key >= key { + return Err(DecoderError::OutOfOrderKey); } - last_key_option = Some(key.clone()); - value_map.push((key, self.decode_complete_data_item(remaining_depth - 1)?)); - } else { - return Err(DecoderError::IncorrectMapKeyType); } + last_key_option = Some(key.clone()); + value_map.push((key, self.decode_complete_data_item(remaining_depth - 1)?)); } Ok(cbor_map_collection!(value_map)) } @@ -614,19 +609,6 @@ mod test { } } - #[test] - fn test_read_unsupported_map_key_format_error() { - // While CBOR can handle all types as map keys, we only support a subset. - let bad_map_cbor = vec![ - 0xa2, // map of 2 pairs - 0x82, 0x01, 0x02, // invalid key : [1, 2] - 0x02, // value : 2 - 0x61, 0x64, // key : "d" - 0x03, // value : 3 - ]; - assert_eq!(read(&bad_map_cbor), Err(DecoderError::IncorrectMapKeyType)); - } - #[test] fn test_read_unknown_additional_info_error() { let cases = vec![ diff --git a/libraries/cbor/src/values.rs b/libraries/cbor/src/values.rs index c2f7b72..1e1324d 100644 --- a/libraries/cbor/src/values.rs +++ b/libraries/cbor/src/values.rs @@ -12,31 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +use super::writer::write; use alloc::string::{String, ToString}; use alloc::vec::Vec; use core::cmp::Ordering; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug)] pub enum Value { - KeyValue(KeyType), - Array(Vec), - Map(Vec<(KeyType, Value)>), - // TAG is omitted - Simple(SimpleValue), -} - -// The specification recommends to limit the available keys. -// Currently supported are both integer and string types. -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum KeyType { Unsigned(u64), // We only use 63 bits of information here. Negative(i64), ByteString(Vec), TextString(String), + Array(Vec), + Map(Vec<(Value, Value)>), + // TAG is omitted + Simple(SimpleValue), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum SimpleValue { FalseValue = 20, TrueValue = 21, @@ -57,6 +51,15 @@ impl Constants { } impl Value { + // For simplicity, this only takes i64. Construct directly for the last bit. + pub fn integer(int: i64) -> Value { + if int >= 0 { + Value::Unsigned(int as u64) + } else { + Value::Negative(int) + } + } + pub fn bool_value(b: bool) -> Value { if b { Value::Simple(SimpleValue::TrueValue) @@ -66,8 +69,13 @@ impl Value { } pub fn type_label(&self) -> u8 { + // TODO use enum discriminant instead when stable + // https://github.com/rust-lang/rust/issues/60553 match self { - Value::KeyValue(key) => key.type_label(), + Value::Unsigned(_) => 0, + Value::Negative(_) => 1, + Value::ByteString(_) => 2, + Value::TextString(_) => 3, Value::Array(_) => 4, Value::Map(_) => 5, Value::Simple(_) => 7, @@ -75,29 +83,11 @@ impl Value { } } -impl KeyType { - // For simplicity, this only takes i64. Construct directly for the last bit. - pub fn integer(int: i64) -> KeyType { - if int >= 0 { - KeyType::Unsigned(int as u64) - } else { - KeyType::Negative(int) - } - } - - pub fn type_label(&self) -> u8 { - match self { - KeyType::Unsigned(_) => 0, - KeyType::Negative(_) => 1, - KeyType::ByteString(_) => 2, - KeyType::TextString(_) => 3, - } - } -} - -impl Ord for KeyType { - fn cmp(&self, other: &KeyType) -> Ordering { - use super::values::KeyType::{ByteString, Negative, TextString, Unsigned}; +impl Ord for Value { + fn cmp(&self, other: &Value) -> Ordering { + use super::values::Value::{ + Array, ByteString, Map, Negative, Simple, TextString, Unsigned, + }; let self_type_value = self.type_label(); let other_type_value = other.type_label(); if self_type_value != other_type_value { @@ -108,17 +98,35 @@ impl Ord for KeyType { (Negative(n1), Negative(n2)) => n1.cmp(n2).reverse(), (ByteString(b1), ByteString(b2)) => b1.len().cmp(&b2.len()).then(b1.cmp(b2)), (TextString(t1), TextString(t2)) => t1.len().cmp(&t2.len()).then(t1.cmp(t2)), - _ => unreachable!(), + (Array(a1), Array(a2)) if a1.len() != a2.len() => a1.len().cmp(&a2.len()), + (Map(m1), Map(m2)) if m1.len() != m2.len() => m1.len().cmp(&m2.len()), + (Simple(s1), Simple(s2)) => s1.cmp(s2), + (v1, v2) => { + // This case could handle all of the above as well. Checking individually is faster. + let mut encoding1 = Vec::new(); + write(v1.clone(), &mut encoding1); + let mut encoding2 = Vec::new(); + write(v2.clone(), &mut encoding2); + encoding1.cmp(&encoding2) + } } } } -impl PartialOrd for KeyType { - fn partial_cmp(&self, other: &KeyType) -> Option { +impl PartialOrd for Value { + fn partial_cmp(&self, other: &Value) -> Option { Some(self.cmp(other)) } } +impl Eq for Value {} + +impl PartialEq for Value { + fn eq(&self, other: &Value) -> bool { + self.cmp(other) == Ordering::Equal + } +} + impl SimpleValue { pub fn from_integer(int: u64) -> Option { match int { @@ -131,59 +139,50 @@ impl SimpleValue { } } -impl From for KeyType { +impl From for Value { fn from(unsigned: u64) -> Self { - KeyType::Unsigned(unsigned) + Value::Unsigned(unsigned) } } -impl From for KeyType { +impl From for Value { fn from(i: i64) -> Self { - KeyType::integer(i) + Value::integer(i) } } -impl From for KeyType { +impl From for Value { fn from(i: i32) -> Self { - KeyType::integer(i as i64) + Value::integer(i as i64) } } -impl From> for KeyType { +impl From> for Value { fn from(bytes: Vec) -> Self { - KeyType::ByteString(bytes) + Value::ByteString(bytes) } } -impl From<&[u8]> for KeyType { +impl From<&[u8]> for Value { fn from(bytes: &[u8]) -> Self { - KeyType::ByteString(bytes.to_vec()) + Value::ByteString(bytes.to_vec()) } } -impl From for KeyType { +impl From for Value { fn from(text: String) -> Self { - KeyType::TextString(text) + Value::TextString(text) } } -impl From<&str> for KeyType { +impl From<&str> for Value { fn from(text: &str) -> Self { - KeyType::TextString(text.to_string()) + Value::TextString(text.to_string()) } } -impl From for Value -where - KeyType: From, -{ - fn from(t: T) -> Self { - Value::KeyValue(KeyType::from(t)) - } -} - -impl From> for Value { - fn from(map: Vec<(KeyType, Value)>) -> Self { +impl From> for Value { + fn from(map: Vec<(Value, Value)>) -> Self { Value::Map(map) } } @@ -194,19 +193,6 @@ impl From for Value { } } -pub trait IntoCborKey { - fn into_cbor_key(self) -> KeyType; -} - -impl IntoCborKey for T -where - KeyType: From, -{ - fn into_cbor_key(self) -> KeyType { - KeyType::from(self) - } -} - pub trait IntoCborValue { fn into_cbor_value(self) -> Value; } @@ -244,32 +230,69 @@ where #[cfg(test)] mod test { - use crate::{cbor_key_bytes, cbor_key_int, cbor_key_text}; + use super::*; + use crate::{cbor_array, cbor_bool, cbor_bytes, cbor_int, cbor_map, cbor_text}; #[test] - fn test_key_type_ordering() { - assert!(cbor_key_int!(0) < cbor_key_int!(23)); - assert!(cbor_key_int!(23) < cbor_key_int!(24)); - assert!(cbor_key_int!(24) < cbor_key_int!(1000)); - assert!(cbor_key_int!(1000) < cbor_key_int!(1000000)); - assert!(cbor_key_int!(1000000) < cbor_key_int!(std::i64::MAX)); - assert!(cbor_key_int!(std::i64::MAX) < cbor_key_int!(-1)); - assert!(cbor_key_int!(-1) < cbor_key_int!(-23)); - assert!(cbor_key_int!(-23) < cbor_key_int!(-24)); - assert!(cbor_key_int!(-24) < cbor_key_int!(-1000)); - assert!(cbor_key_int!(-1000) < cbor_key_int!(-1000000)); - assert!(cbor_key_int!(-1000000) < cbor_key_int!(std::i64::MIN)); - assert!(cbor_key_int!(std::i64::MIN) < cbor_key_bytes!(vec![])); - assert!(cbor_key_bytes!(vec![]) < cbor_key_bytes!(vec![0x00])); - assert!(cbor_key_bytes!(vec![0x00]) < cbor_key_bytes!(vec![0x01])); - assert!(cbor_key_bytes!(vec![0x01]) < cbor_key_bytes!(vec![0xFF])); - assert!(cbor_key_bytes!(vec![0xFF]) < cbor_key_bytes!(vec![0x00, 0x00])); - assert!(cbor_key_bytes!(vec![0x00, 0x00]) < cbor_key_text!("")); - assert!(cbor_key_text!("") < cbor_key_text!("a")); - assert!(cbor_key_text!("a") < cbor_key_text!("b")); - assert!(cbor_key_text!("b") < cbor_key_text!("aa")); - assert!(cbor_key_int!(1) < cbor_key_bytes!(vec![0x00])); - assert!(cbor_key_int!(1) < cbor_key_text!("s")); - assert!(cbor_key_int!(-1) < cbor_key_text!("s")); + fn test_value_ordering() { + assert!(cbor_int!(0) < cbor_int!(23)); + assert!(cbor_int!(23) < cbor_int!(24)); + assert!(cbor_int!(24) < cbor_int!(1000)); + assert!(cbor_int!(1000) < cbor_int!(1000000)); + assert!(cbor_int!(1000000) < cbor_int!(std::i64::MAX)); + assert!(cbor_int!(std::i64::MAX) < cbor_int!(-1)); + assert!(cbor_int!(-1) < cbor_int!(-23)); + assert!(cbor_int!(-23) < cbor_int!(-24)); + assert!(cbor_int!(-24) < cbor_int!(-1000)); + assert!(cbor_int!(-1000) < cbor_int!(-1000000)); + assert!(cbor_int!(-1000000) < cbor_int!(std::i64::MIN)); + assert!(cbor_int!(std::i64::MIN) < cbor_bytes!(vec![])); + assert!(cbor_bytes!(vec![]) < cbor_bytes!(vec![0x00])); + assert!(cbor_bytes!(vec![0x00]) < cbor_bytes!(vec![0x01])); + assert!(cbor_bytes!(vec![0x01]) < cbor_bytes!(vec![0xFF])); + assert!(cbor_bytes!(vec![0xFF]) < cbor_bytes!(vec![0x00, 0x00])); + assert!(cbor_bytes!(vec![0x00, 0x00]) < cbor_text!("")); + assert!(cbor_text!("") < cbor_text!("a")); + assert!(cbor_text!("a") < cbor_text!("b")); + assert!(cbor_text!("b") < cbor_text!("aa")); + assert!(cbor_text!("aa") < cbor_array![]); + assert!(cbor_array![] < cbor_array![0]); + assert!(cbor_array![0] < cbor_array![-1]); + assert!(cbor_array![1] < cbor_array![b""]); + assert!(cbor_array![b""] < cbor_array![""]); + assert!(cbor_array![""] < cbor_array![cbor_array![]]); + assert!(cbor_array![cbor_array![]] < cbor_array![cbor_map! {}]); + assert!(cbor_array![cbor_map! {}] < cbor_array![false]); + assert!(cbor_array![false] < cbor_array![0, 0]); + assert!(cbor_array![0, 0] < cbor_map! {}); + assert!(cbor_map! {} < cbor_map! {0 => 0}); + assert!(cbor_map! {0 => 0} < cbor_map! {0 => 1}); + assert!(cbor_map! {0 => 1} < cbor_map! {1 => 0}); + assert!(cbor_map! {1 => 0} < cbor_map! {-1 => 0}); + assert!(cbor_map! {-1 => 0} < cbor_map! {b"" => 0}); + assert!(cbor_map! {b"" => 0} < cbor_map! {"" => 0}); + assert!(cbor_map! {"" => 0} < cbor_map! {cbor_array![] => 0}); + assert!(cbor_map! {cbor_array![] => 0} < cbor_map! {cbor_map!{} => 0}); + assert!(cbor_map! {cbor_map!{} => 0} < cbor_map! {false => 0}); + assert!(cbor_map! {false => 0} < cbor_map! {0 => 0, 0 => 0}); + assert!(cbor_map! {0 => 0, 0 => 0} < cbor_bool!(false)); + assert!(cbor_bool!(false) < cbor_bool!(true)); + assert!(cbor_bool!(true) < Value::Simple(SimpleValue::NullValue)); + assert!(Value::Simple(SimpleValue::NullValue) < Value::Simple(SimpleValue::Undefined)); + assert!(cbor_int!(1) < cbor_bytes!(vec![0x00])); + assert!(cbor_int!(1) < cbor_text!("s")); + assert!(cbor_int!(1) < cbor_array![]); + assert!(cbor_int!(1) < cbor_map! {}); + assert!(cbor_int!(1) < cbor_bool!(false)); + assert!(cbor_int!(-1) < cbor_text!("s")); + assert!(cbor_int!(-1) < cbor_array![]); + assert!(cbor_int!(-1) < cbor_map! {}); + assert!(cbor_int!(-1) < cbor_bool!(false)); + assert!(cbor_bytes!(vec![0x00]) < cbor_array![]); + assert!(cbor_bytes!(vec![0x00]) < cbor_map! {}); + assert!(cbor_bytes!(vec![0x00]) < cbor_bool!(false)); + assert!(cbor_text!("s") < cbor_map! {}); + assert!(cbor_text!("s") < cbor_bool!(false)); + assert!(cbor_array![] < cbor_bool!(false)); } } diff --git a/libraries/cbor/src/writer.rs b/libraries/cbor/src/writer.rs index 386f0b5..c8a4808 100644 --- a/libraries/cbor/src/writer.rs +++ b/libraries/cbor/src/writer.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::values::{Constants, KeyType, Value}; +use super::values::{Constants, Value}; use alloc::vec::Vec; pub fn write(value: Value, encoded_cbor: &mut Vec) -> bool { @@ -35,21 +35,20 @@ impl<'a> Writer<'a> { if remaining_depth < 0 { return false; } + let type_label = value.type_label(); match value { - Value::KeyValue(KeyType::Unsigned(unsigned)) => self.start_item(0, unsigned), - Value::KeyValue(KeyType::Negative(negative)) => { - self.start_item(1, -(negative + 1) as u64) - } - Value::KeyValue(KeyType::ByteString(byte_string)) => { - self.start_item(2, byte_string.len() as u64); + Value::Unsigned(unsigned) => self.start_item(type_label, unsigned), + Value::Negative(negative) => self.start_item(type_label, -(negative + 1) as u64), + Value::ByteString(byte_string) => { + self.start_item(type_label, byte_string.len() as u64); self.encoded_cbor.extend(byte_string); } - Value::KeyValue(KeyType::TextString(text_string)) => { - self.start_item(3, text_string.len() as u64); + Value::TextString(text_string) => { + self.start_item(type_label, text_string.len() as u64); self.encoded_cbor.extend(text_string.into_bytes()); } Value::Array(array) => { - self.start_item(4, array.len() as u64); + self.start_item(type_label, array.len() as u64); for el in array { if !self.encode_cbor(el, remaining_depth - 1) { return false; @@ -63,9 +62,9 @@ impl<'a> Writer<'a> { if map_len != map.len() { return false; } - self.start_item(5, map_len as u64); + self.start_item(type_label, map_len as u64); for (k, v) in map { - if !self.encode_cbor(Value::KeyValue(k), remaining_depth - 1) { + if !self.encode_cbor(k, remaining_depth - 1) { return false; } if !self.encode_cbor(v, remaining_depth - 1) { @@ -73,7 +72,7 @@ impl<'a> Writer<'a> { } } } - Value::Simple(simple_value) => self.start_item(7, simple_value as u64), + Value::Simple(simple_value) => self.start_item(type_label, simple_value as u64), } true } diff --git a/src/ctap/data_formats.rs b/src/ctap/data_formats.rs index 673b850..be76b65 100644 --- a/src/ctap/data_formats.rs +++ b/src/ctap/data_formats.rs @@ -586,8 +586,8 @@ enum PublicKeyCredentialSourceField { // - CredRandom = 5, } -impl From for cbor::KeyType { - fn from(field: PublicKeyCredentialSourceField) -> cbor::KeyType { +impl From for cbor::Value { + fn from(field: PublicKeyCredentialSourceField) -> cbor::Value { (field as u64).into() } } @@ -1076,35 +1076,35 @@ impl From for cbor::Value { pub(super) fn extract_unsigned(cbor_value: cbor::Value) -> Result { match cbor_value { - cbor::Value::KeyValue(cbor::KeyType::Unsigned(unsigned)) => Ok(unsigned), + cbor::Value::Unsigned(unsigned) => Ok(unsigned), _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), } } pub(super) fn extract_integer(cbor_value: cbor::Value) -> Result { match cbor_value { - cbor::Value::KeyValue(cbor::KeyType::Unsigned(unsigned)) => { + cbor::Value::Unsigned(unsigned) => { if unsigned <= core::i64::MAX as u64 { Ok(unsigned as i64) } else { Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE) } } - cbor::Value::KeyValue(cbor::KeyType::Negative(signed)) => Ok(signed), + cbor::Value::Negative(signed) => Ok(signed), _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), } } pub fn extract_byte_string(cbor_value: cbor::Value) -> Result, Ctap2StatusCode> { match cbor_value { - cbor::Value::KeyValue(cbor::KeyType::ByteString(byte_string)) => Ok(byte_string), + cbor::Value::ByteString(byte_string) => Ok(byte_string), _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), } } pub(super) fn extract_text_string(cbor_value: cbor::Value) -> Result { match cbor_value { - cbor::Value::KeyValue(cbor::KeyType::TextString(text_string)) => Ok(text_string), + cbor::Value::TextString(text_string) => Ok(text_string), _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), } } @@ -1118,7 +1118,7 @@ pub(super) fn extract_array(cbor_value: cbor::Value) -> Result, pub(super) fn extract_map( cbor_value: cbor::Value, -) -> Result, Ctap2StatusCode> { +) -> Result, Ctap2StatusCode> { match cbor_value { cbor::Value::Map(map) => Ok(map), _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), @@ -1681,7 +1681,7 @@ mod test { #[test] fn test_into_packed_attestation_statement() { - let certificate: cbor::values::KeyType = cbor_bytes![vec![0x5C, 0x5C, 0x5C, 0x5C]]; + let certificate = cbor_bytes![vec![0x5C, 0x5C, 0x5C, 0x5C]]; let cbor_packed_attestation_statement = cbor_map! { "alg" => 1, "sig" => vec![0x55, 0x55, 0x55, 0x55], diff --git a/src/ctap/response.rs b/src/ctap/response.rs index 2568bae..765403d 100644 --- a/src/ctap/response.rs +++ b/src/ctap/response.rs @@ -326,7 +326,7 @@ mod test { #[test] fn test_make_credential_into_cbor() { - let certificate: cbor::values::KeyType = cbor_bytes![vec![0x5C, 0x5C, 0x5C, 0x5C]]; + let certificate = cbor_bytes![vec![0x5C, 0x5C, 0x5C, 0x5C]]; let att_stmt = PackedAttestationStatement { alg: 1, sig: vec![0x55, 0x55, 0x55, 0x55],