From 5a120faa5d8efd6a843c8ad08252e9f35cd0707d Mon Sep 17 00:00:00 2001 From: anweiss <2326106+anweiss@users.noreply.github.com> Date: Tue, 28 Sep 2021 11:44:15 -0400 Subject: [PATCH 1/5] replace serde_cbor with ciborium --- Cargo.toml | 4 +- README.md | 2 +- src/lib.rs | 6 +- src/validator/cbor.rs | 274 +++++++++++++++++++++++------------------- src/validator/json.rs | 2 + src/validator/mod.rs | 25 ++-- tests/cbor_tests.rs | 22 ++-- tests/did.rs | 5 +- 8 files changed, 191 insertions(+), 149 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 85e13185..410f5239 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ lexical-core = "0.7.6" regex = { version = "1.5.4", default-features = false, features = ["std"] } regex-syntax = { version = "0.6.25", optional = true } serde = { version = "1.0.127", optional = true, features = ["derive"] } -serde_cbor = { version = "0.11.1", optional = true, default-features = false, features = ["std", "tags"] } +ciborium = { git = "https://github.com/enarx/ciborium", branch = "master", optional = true } serde_json = { version = "1.0.66", optional = true, default-features = false } uriparse = { version = "0.6.3", optional = true } base64-url = { version = "1.4.10", optional = true } @@ -54,7 +54,7 @@ wasm-bindgen-test = "0.3.25" [features] default = ["std", "ast-span", "ast-comments", "json", "cbor", "additional-controls"] -std = ["base16/alloc", "base64/alloc", "serde_json", "serde_cbor", "serde", "chrono", "wasm-bindgen", "clap", "crossterm", "uriparse", "base64-url", "regex-syntax"] +std = ["base16/alloc", "base64/alloc", "serde_json", "ciborium", "serde", "chrono", "wasm-bindgen", "clap", "crossterm", "uriparse", "base64-url", "regex-syntax"] lsp = ["std"] additional-controls = [] ast-span = [] diff --git a/README.md b/README.md index 1c480d8f..3e878139 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # cddl-rs -[![crates.io](https://img.shields.io/crates/v/cddl.svg)](https://crates.io/crates/cddl) [![docs.rs](https://docs.rs/cddl/badge.svg)](https://docs.rs/cddl) [![Publish packages](https://github.com/anweiss/cddl/workflows/Publish%20packages/badge.svg?branch=0.9.0-beta.0&event=release)](https://github.com/anweiss/cddl/actions?query=workflow%3A%22Publish+packages%22) [![Build and Test](https://github.com/anweiss/cddl/workflows/Build%20and%20Test/badge.svg)](https://github.com/anweiss/cddl/actions?query=workflow%3A%22Build+and+Test%22) +[![crates.io](https://img.shields.io/crates/v/cddl.svg)](https://crates.io/crates/cddl) [![docs.rs](https://docs.rs/cddl/badge.svg)](https://docs.rs/cddl) [![Publish packages](https://github.com/anweiss/cddl/workflows/Publish%20packages/badge.svg?branch=0.9.0-beta.0&event=release)](https://github.com/anweiss/cddl/actions?query=workflow%3A%22Publish+packages%22) [![Build and Test](https://github.com/anweiss/cddl/workflows/Build%20and%20Test/badge.svg)](https://github.com/anweiss/cddl/actions?query=workflow%3A%22Build+and+Test%22) [![Active Development](https://img.shields.io/badge/Maintenance%20Level-Actively%20Developed-brightgreen.svg)](https://gist.github.com/cheerfulstoic/d107229326a01ff0f333a1d3476e068d) > This crate was originally developed as a personal learning exercise for getting acquainted with Rust and parsing in general. There are likely more performant and stable libraries out there for parsing CDDL. While there are some examples of this crate being used in production, careful consideration should be made prior to using this crate as such. diff --git a/src/lib.rs b/src/lib.rs index fbcfbeba..5b84bcea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,8 @@ //! packages](https://github.com/anweiss/cddl/workflows/Publish%20packages/badge.svg?branch=0.9.0-beta.0&event=release)](https://github.com/anweiss/cddl/actions?query=workflow%3A%22Publish+packages%22) //! [![Build and //! Test](https://github.com/anweiss/cddl/workflows/Build%20and%20Test/badge.svg)](https://github.com/anweiss/cddl/actions?query=workflow%3A%22Build+and+Test%22) +//! [![Active +//! Development](https://img.shields.io/badge/Maintenance%20Level-Actively%20Developed-brightgreen.svg)](https://gist.github.com/cheerfulstoic/d107229326a01ff0f333a1d3476e068d) //! //! > This crate was originally developed as a personal learning exercise for //! > getting acquainted with Rust and parsing in general. There are likely more @@ -532,8 +534,8 @@ extern crate core as std; #[cfg(feature = "std")] extern crate serde_json; -#[cfg(feature = "std")] -extern crate serde_cbor; +// #[cfg(feature = "std")] +// extern crate serde_cbor; #[cfg(feature = "std")] extern crate uriparse; diff --git a/src/validator/cbor.rs b/src/validator/cbor.rs index 10c9d949..8016c24d 100644 --- a/src/validator/cbor.rs +++ b/src/validator/cbor.rs @@ -12,7 +12,8 @@ use crate::{ use std::{borrow::Cow, collections::HashMap, convert::TryFrom, fmt}; use chrono::{TimeZone, Utc}; -use serde_cbor::Value; +use ciborium::value::Value; +use serde_json; #[cfg(feature = "additional-controls")] use crate::validator::control::{ @@ -20,22 +21,24 @@ use crate::validator::control::{ }; /// cbor validation Result -pub type Result = std::result::Result<(), Error>; +pub type Result = std::result::Result<(), Error>; /// cbor validation error #[derive(Debug)] -pub enum Error { +pub enum Error { /// Zero or more validation errors Validation(Vec), /// cbor parsing error - CBORParsing(serde_cbor::Error), + CBORParsing(ciborium::de::Error), + /// json parsing error. Used only for parsing regex controller strings + JSONParsing(serde_json::Error), /// CDDL parsing error CDDLParsing(String), /// UTF8 parsing error, UTF8Parsing(std::str::Utf8Error), } -impl fmt::Display for Error { +impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Error::Validation(errors) => { @@ -46,13 +49,14 @@ impl fmt::Display for Error { write!(f, "{}", error_str) } Error::CBORParsing(error) => write!(f, "error parsing cbor: {}", error), + Error::JSONParsing(error) => write!(f, "error parsing json string: {}", error), Error::CDDLParsing(error) => write!(f, "error parsing CDDL: {}", error), Error::UTF8Parsing(error) => write!(f, "error pasing utf8: {}", error), } } } -impl std::error::Error for Error { +impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { Error::CBORParsing(error) => Some(error), @@ -110,7 +114,7 @@ impl std::error::Error for ValidationError { } } -impl Error { +impl Error { fn from_validator(cv: &CBORValidator, reason: String) -> Self { Error::Validation(vec![ValidationError { cddl_location: cv.cddl_location.clone(), @@ -351,7 +355,10 @@ impl<'a> CBORValidator<'a> { } /// Validate - pub fn validate(&mut self) -> std::result::Result<(), Error> { + pub fn validate(&mut self) -> std::result::Result<(), Error> + where + cbor::Error: From>, + { for r in self.cddl.rules.iter() { // First type rule is root if let Rule::Type { rule, .. } = r { @@ -384,8 +391,11 @@ impl<'a> CBORValidator<'a> { } } -impl<'a> Visitor<'a, Error> for CBORValidator<'a> { - fn visit_type_rule(&mut self, tr: &TypeRule<'a>) -> visitor::Result { +impl<'a, T: std::fmt::Debug + 'static> Visitor<'a, Error> for CBORValidator<'a> +where + cbor::Error: From>, +{ + fn visit_type_rule(&mut self, tr: &TypeRule<'a>) -> visitor::Result> { if let Some(gp) = &tr.generic_params { if let Some(gr) = self .generic_rules @@ -419,7 +429,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { Ok(()) } - fn visit_group_rule(&mut self, gr: &GroupRule<'a>) -> visitor::Result { + fn visit_group_rule(&mut self, gr: &GroupRule<'a>) -> visitor::Result> { if let Some(gp) = &gr.generic_params { if let Some(gr) = self .generic_rules @@ -453,7 +463,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { Ok(()) } - fn visit_type(&mut self, t: &Type<'a>) -> visitor::Result { + fn visit_type(&mut self, t: &Type<'a>) -> visitor::Result> { if t.type_choices.len() > 1 { self.is_multi_type_choice = true; } @@ -535,7 +545,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { Ok(()) } - fn visit_group(&mut self, g: &Group<'a>) -> visitor::Result { + fn visit_group(&mut self, g: &Group<'a>) -> visitor::Result> { if g.group_choices.len() > 1 { self.is_multi_group_choice = true; } @@ -612,7 +622,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { Ok(()) } - fn visit_group_choice(&mut self, gc: &GroupChoice<'a>) -> visitor::Result { + fn visit_group_choice(&mut self, gc: &GroupChoice<'a>) -> visitor::Result> { if self.is_group_to_choice_enum { let initial_error_count = self.errors.len(); for tc in type_choices_from_group_choice(self.cddl, gc).iter() { @@ -646,7 +656,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { lower: &Type2, upper: &Type2, is_inclusive: bool, - ) -> visitor::Result { + ) -> visitor::Result> { if let Value::Array(a) = &self.cbor { match validate_array_occurrence( self.occurrence.as_ref().take(), @@ -756,12 +766,12 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { match &self.cbor { Value::Integer(i) => { if is_inclusive { - if *i < *l as i128 || *i > *u as i128 { + if i128::from(*i) < *l as i128 || i128::from(*i) > *u as i128 { self.add_error(error_str); } else { return Ok(()); } - } else if *i <= *l as i128 || *i >= *u as i128 { + } else if i128::from(*i) <= *l as i128 || i128::from(*i) >= *u as i128 { self.add_error(error_str); return Ok(()); } else { @@ -790,12 +800,12 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { match &self.cbor { Value::Integer(i) => { if is_inclusive { - if *i < *l as i128 || *i > *u as i128 { + if i128::from(*i) < *l as i128 || i128::from(*i) > *u as i128 { self.add_error(error_str); } else { return Ok(()); } - } else if *i <= *l as i128 || *i >= *u as i128 { + } else if i128::from(*i) <= *l as i128 || i128::from(*i) >= *u as i128 { self.add_error(error_str); return Ok(()); } else { @@ -833,12 +843,12 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { match &self.cbor { Value::Integer(i) => { if is_inclusive { - if *i < *l as i128 || *i > *u as i128 { + if i128::from(*i) < *l as i128 || i128::from(*i) > *u as i128 { self.add_error(error_str); } else { return Ok(()); } - } else if *i <= *l as i128 || *i >= *u as i128 { + } else if i128::from(*i) <= *l as i128 || i128::from(*i) >= *u as i128 { self.add_error(error_str); return Ok(()); } else { @@ -902,12 +912,12 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { match &self.cbor { Value::Float(f) => { if is_inclusive { - if *f < *l as f64 || *f > *u as f64 { + if f64::from(*f) < *l || f64::from(*f) > *u { self.add_error(error_str); } else { return Ok(()); } - } else if *f <= *l as f64 || *f >= *u as f64 { + } else if f64::from(*f) <= *l || f64::from(*f) >= *u { self.add_error(error_str); return Ok(()); } else { @@ -946,7 +956,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { target: &Type2<'a>, ctrl: &str, controller: &Type2<'a>, - ) -> visitor::Result { + ) -> visitor::Result> { if let Type2::Typename { ident: target_ident, .. @@ -1215,7 +1225,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { { match &self.cbor { Value::Bytes(_) | Value::Array(_) => self.visit_type2(controller)?, - Value::Integer(i) if *i >= 0 => self.visit_type2(controller)?, + Value::Integer(i) if i128::from(*i) >= 0i128 => self.visit_type2(controller)?, _ => self.add_error(format!( "{} control can only be matched against a CBOR byte string or uint, got {:?}", ctrl, self.cbor, @@ -1506,10 +1516,10 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { } } - fn visit_type2(&mut self, t2: &Type2<'a>) -> visitor::Result { + fn visit_type2(&mut self, t2: &Type2<'a>) -> visitor::Result> { if matches!(self.ctrl, Some(Token::CBOR)) { if let Value::Bytes(b) = &self.cbor { - let value = serde_cbor::from_slice::(b); + let value = ciborium::de::from_reader(&b[..]); match value { Ok(value) => { let current_location = self.cbor_location.clone(); @@ -1546,7 +1556,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { return Ok(()); } else if matches!(self.ctrl, Some(Token::CBORSEQ)) { if let Value::Bytes(b) = &self.cbor { - let value = serde_cbor::from_slice::(b); + let value = ciborium::de::from_reader(&b[..]); match value { Ok(Value::Array(_)) => { let current_location = self.cbor_location.clone(); @@ -1635,7 +1645,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { return Ok(()); } - let m = m.keys().cloned().collect::>(); + let m = m.iter().map(|entry| entry.0.clone()).collect::>(); self.visit_group(group)?; @@ -2075,7 +2085,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { Value::Integer(i) => { match mt { 0u8 => match constraint { - Some(c) if *i == *c as i128 && *i >= 0i128 => return Ok(()), + Some(c) if i128::from(*i) == *c as i128 && i128::from(*i) >= 0i128 => return Ok(()), Some(c) => { self.add_error(format!( "expected uint data type with constraint {} (#{}.{}), got {:?}", @@ -2084,7 +2094,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { return Ok(()); } _ => { - if i.is_negative() { + if i128::from(*i).is_negative() { self.add_error(format!( "expected uint data type (#{}), got {:?}", mt, self.cbor @@ -2094,7 +2104,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { } }, 1u8 => match constraint { - Some(c) if *i == 0i128 - *c as i128 => return Ok(()), + Some(c) if i128::from(*i) == 0i128 - *c as i128 => return Ok(()), Some(c) => { self.add_error(format!( "expected nint type with constraint {} (#{}.{}), got {:?}", @@ -2103,7 +2113,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { return Ok(()); } _ => { - if *i >= 0i128 { + if i128::from(*i) >= 0i128 { self.add_error(format!( "expected nint data type (#{}), got {:?}", mt, self.cbor @@ -2233,7 +2243,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { } } - fn visit_identifier(&mut self, ident: &Identifier<'a>) -> visitor::Result { + fn visit_identifier(&mut self, ident: &Identifier<'a>) -> visitor::Result> { if let Some(name) = self.eval_generic_rule { if let Some(gr) = self .generic_rules @@ -2280,7 +2290,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { } Value::Integer(i) => { if is_ident_uint_data_type(self.cddl, ident) { - if i.is_negative() { + if i128::from(*i).is_negative() { self.add_error(format!("expected type {}, got {:?}", ident, self.cbor)); } @@ -2288,10 +2298,12 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { } else if is_ident_integer_data_type(self.cddl, ident) { Ok(()) } else if is_ident_time_data_type(self.cddl, ident) { - if let chrono::LocalResult::None = Utc.timestamp_millis_opt((i * 1000) as i64) { + if let chrono::LocalResult::None = + Utc.timestamp_millis_opt((i128::from(*i) * 1000) as i64) + { let i = *i; self.add_error(format!( - "expected time data type, invalid UNIX timestamp {}", + "expected time data type, invalid UNIX timestamp {:?}", i, )); } @@ -2306,10 +2318,12 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { if is_ident_float_data_type(self.cddl, ident) { Ok(()) } else if is_ident_time_data_type(self.cddl, ident) { - if let chrono::LocalResult::None = Utc.timestamp_millis_opt((f * 1000f64) as i64) { + if let chrono::LocalResult::None = + Utc.timestamp_millis_opt((f64::from(*f) * 1000f64) as i64) + { let f = *f; self.add_error(format!( - "expected time data type, invalid UNIX timestamp {}", + "expected time data type, invalid UNIX timestamp {:?}", f, )); } @@ -2978,7 +2992,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { fn visit_value_member_key_entry( &mut self, entry: &ValueMemberKeyEntry<'a>, - ) -> visitor::Result { + ) -> visitor::Result> { if let Some(occur) = &entry.occur { self.visit_occurrence(occur)?; } @@ -3061,7 +3075,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { fn visit_type_groupname_entry( &mut self, entry: &TypeGroupnameEntry<'a>, - ) -> visitor::Result { + ) -> visitor::Result> { self.type_group_name_entry = Some(entry.name.ident); if let Some(ga) = &entry.generic_args { @@ -3107,7 +3121,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { Ok(()) } - fn visit_memberkey(&mut self, mk: &MemberKey<'a>) -> visitor::Result { + fn visit_memberkey(&mut self, mk: &MemberKey<'a>) -> visitor::Result> { match mk { MemberKey::Type1 { is_cut, .. } => { self.is_cut_present = *is_cut; @@ -3125,137 +3139,141 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { Ok(()) } - fn visit_value(&mut self, value: &token::Value<'a>) -> visitor::Result { + fn visit_value(&mut self, value: &token::Value<'a>) -> visitor::Result> { let error: Option = match &self.cbor { Value::Integer(i) => match value { token::Value::INT(v) => match &self.ctrl { - Some(Token::NE) | Some(Token::DEFAULT) if *i != *v as i128 => None, - Some(Token::LT) if *i < *v as i128 => None, - Some(Token::LE) if *i <= *v as i128 => None, - Some(Token::GT) if *i > *v as i128 => None, - Some(Token::GE) if *i >= *v as i128 => None, + Some(Token::NE) | Some(Token::DEFAULT) if i128::from(*i) != *v as i128 => None, + Some(Token::LT) if i128::from(*i) < *v as i128 => None, + Some(Token::LE) if i128::from(*i) <= *v as i128 => None, + Some(Token::GT) if i128::from(*i) > *v as i128 => None, + Some(Token::GE) if i128::from(*i) >= *v as i128 => None, #[cfg(feature = "additional-controls")] Some(Token::PLUS) => { - if *i == *v as i128 { + if i128::from(*i) == *v as i128 { None } else { - Some(format!("expected computed .plus value {}, got {}", v, i)) + Some(format!("expected computed .plus value {}, got {:?}", v, i)) } } #[cfg(feature = "additional-controls")] None | Some(Token::FEATURE) => { - if *i == *v as i128 { + if i128::from(*i) == *v as i128 { None } else { - Some(format!("expected value {}, got {}", v, i)) + Some(format!("expected value {}, got {:?}", v, i)) } } #[cfg(not(feature = "additional-controls"))] None => { - if *i == *v as i128 { + if i128::from(*i) == *v as i128 { None } else { - Some(format!("expected value {}, got {}", v, i)) + Some(format!("expected value {}, got {:?}", v, i)) } } _ => Some(format!( - "expected value {} {}, got {}", + "expected value {} {}, got {:?}", self.ctrl.clone().unwrap(), v, i )), }, token::Value::UINT(v) => match &self.ctrl { - Some(Token::NE) | Some(Token::DEFAULT) if *i != *v as i128 => None, - Some(Token::LT) if *i < *v as i128 => None, - Some(Token::LE) if *i <= *v as i128 => None, - Some(Token::GT) if *i > *v as i128 => None, - Some(Token::GE) if *i >= *v as i128 => None, - Some(Token::SIZE) if *i < 256i128.pow(*v as u32) => None, + Some(Token::NE) | Some(Token::DEFAULT) if i128::from(*i) != *v as i128 => None, + Some(Token::LT) if i128::from(*i) < *v as i128 => None, + Some(Token::LE) if i128::from(*i) <= *v as i128 => None, + Some(Token::GT) if i128::from(*i) > *v as i128 => None, + Some(Token::GE) if i128::from(*i) >= *v as i128 => None, + Some(Token::SIZE) if i128::from(*i) < 256i128.pow(*v as u32) => None, Some(Token::BITS) => { if let Some(sv) = 1u32.checked_shl(*v as u32) { - if (i & sv as i128) != 0 { + if (i128::from(*i) & sv as i128) != 0 { None } else { - Some(format!("expected uint .bits {}, got {}", v, i)) + Some(format!("expected uint .bits {}, got {:?}", v, i)) } } else { - Some(format!("expected uint .bits {}, got {}", v, i)) + Some(format!("expected uint .bits {}, got {:?}", v, i)) } } #[cfg(feature = "additional-controls")] Some(Token::PLUS) => { - if *i == *v as i128 { + if i128::from(*i) == *v as i128 { None } else { - Some(format!("expected computed .plus value {}, got {}", v, i)) + Some(format!("expected computed .plus value {}, got {:?}", v, i)) } } #[cfg(feature = "additional-controls")] None | Some(Token::FEATURE) => { - if *i == *v as i128 { + if i128::from(*i) == *v as i128 { None } else { - Some(format!("expected value {}, got {}", v, i)) + Some(format!("expected value {}, got {:?}", v, i)) } } #[cfg(not(feature = "additional-controls"))] None => { - if *i == *v as i128 { + if i128::from(*i) == *v as i128 { None } else { - Some(format!("expected value {}, got {}", v, i)) + Some(format!("expected value {}, got {:?}", v, i)) } } _ => Some(format!( - "expected value {} {}, got {}", + "expected value {} {}, got {:?}", self.ctrl.clone().unwrap(), v, i )), }, - _ => Some(format!("expected {}, got {}", value, i)), + _ => Some(format!("expected {}, got {:?}", value, i)), }, Value::Float(f) => match value { token::Value::FLOAT(v) => match &self.ctrl { - Some(Token::NE) | Some(Token::DEFAULT) if (f - *v).abs() > std::f64::EPSILON => None, - Some(Token::LT) if *f < *v as f64 => None, - Some(Token::LE) if *f <= *v as f64 => None, - Some(Token::GT) if *f > *v as f64 => None, - Some(Token::GE) if *f >= *v as f64 => None, + Some(Token::NE) | Some(Token::DEFAULT) + if (f64::from(*f) - *v).abs() > std::f64::EPSILON => + { + None + } + Some(Token::LT) if f64::from(*f) < *v as f64 => None, + Some(Token::LE) if f64::from(*f) <= *v as f64 => None, + Some(Token::GT) if f64::from(*f) > *v as f64 => None, + Some(Token::GE) if f64::from(*f) >= *v as f64 => None, #[cfg(feature = "additional-controls")] Some(Token::PLUS) => { - if (f - *v).abs() < std::f64::EPSILON { + if (f64::from(*f) - *v).abs() < std::f64::EPSILON { None } else { - Some(format!("expected computed .plus value {}, got {}", v, f)) + Some(format!("expected computed .plus value {}, got {:?}", v, f)) } } #[cfg(feature = "additional-controls")] None | Some(Token::FEATURE) => { - if (f - *v).abs() < std::f64::EPSILON { + if (f64::from(*f) - *v).abs() < std::f64::EPSILON { None } else { - Some(format!("expected value {}, got {}", v, f)) + Some(format!("expected value {}, got {:?}", v, f)) } } #[cfg(not(feature = "additional-controls"))] None => { - if (f - *v).abs() < std::f64::EPSILON { + if (f64::from(*f) - *v).abs() < std::f64::EPSILON { None } else { - Some(format!("expected value {}, got {}", v, f)) + Some(format!("expected value {}, got {:?}", v, f)) } } _ => Some(format!( - "expected value {} {}, got {}", + "expected value {} {}, got {:?}", self.ctrl.clone().unwrap(), v, f )), }, - _ => Some(format!("expected {}, got {}", value, f)), + _ => Some(format!("expected {}, got {:?}", value, f)), }, Value::Text(s) => match value { token::Value::TEXT(t) => match &self.ctrl { @@ -3267,23 +3285,23 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { } } Some(Token::REGEXP) | Some(Token::PCRE) => { - if let Value::Text(t) = - serde_cbor::from_slice::(format!("\"{}\"", t).as_bytes()) - .map_err(Error::CBORParsing)? - { - let re = regex::Regex::new( - &format_regex(&t) + let re = regex::Regex::new( + &format_regex( + // Text strings must be JSON escaped per + // https://datatracker.ietf.org/doc/html/rfc8610#section-3.1 + serde_json::from_str::(&format!("\"{}\"", t)) + .map_err(Error::JSONParsing)? + .as_str() .ok_or_else(|| Error::from_validator(self, "malformed regex".to_string()))?, ) - .map_err(|e| Error::from_validator(self, e.to_string()))?; + .ok_or_else(|| Error::from_validator(self, "malformed regex".to_string()))?, + ) + .map_err(|e| Error::from_validator(self, e.to_string()))?; - if re.is_match(s) { - None - } else { - Some(format!("expected \"{}\" to match regex \"{}\"", s, t)) - } + if re.is_match(s) { + None } else { - return Err(Error::from_validator(self, "malformed regex".to_string())); + Some(format!("expected \"{}\" to match regex \"{}\"", s, t)) } } #[cfg(feature = "additional-controls")] @@ -3514,7 +3532,10 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { let k = token_value_into_cbor_value(value.clone()); #[cfg(feature = "ast-span")] - if let Some(v) = o.get(&k) { + if let Some(v) = o + .iter() + .find_map(|entry| if entry.0 == k { Some(&entry.1) } else { None }) + { self.validated_keys.get_or_insert(vec![k.clone()]).push(k); self.object_value = Some(v.clone()); self.cbor_location.push_str(&format!("/{}", value)); @@ -3532,7 +3553,10 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { } #[cfg(not(feature = "ast-span"))] - if let Some(v) = o.get(&k) { + if let Some(v) = o + .iter() + .find_map(|entry| if entry.0 == k { Some(&entry.1) } else { None }) + { self.validated_keys.get_or_insert(vec![k.clone()]).push(k); self.object_value = Some(v.clone()); self.cbor_location.push_str(&format!("/{}", value)); @@ -3557,7 +3581,7 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { Ok(()) } - fn visit_occurrence(&mut self, o: &Occurrence) -> visitor::Result { + fn visit_occurrence(&mut self, o: &Occurrence) -> visitor::Result> { self.occurrence = Some(o.occur.clone()); Ok(()) @@ -3565,15 +3589,15 @@ impl<'a> Visitor<'a, Error> for CBORValidator<'a> { } /// Converts a CDDL value type to serde_cbor::Value -pub fn token_value_into_cbor_value(value: token::Value) -> serde_cbor::Value { +pub fn token_value_into_cbor_value(value: token::Value) -> ciborium::value::Value { match value { - token::Value::UINT(i) => serde_cbor::Value::Integer(i as i128), - token::Value::INT(i) => serde_cbor::Value::Integer(i as i128), - token::Value::FLOAT(f) => serde_cbor::Value::Float(f), - token::Value::TEXT(t) => serde_cbor::Value::Text(t.to_string()), + token::Value::UINT(i) => ciborium::value::Value::Integer(i.into()), + token::Value::INT(i) => ciborium::value::Value::Integer(i.into()), + token::Value::FLOAT(f) => ciborium::value::Value::Float(f.into()), + token::Value::TEXT(t) => ciborium::value::Value::Text(t.to_string()), token::Value::BYTE(b) => match b { ByteValue::UTF8(b) | ByteValue::B16(b) | ByteValue::B64(b) => { - serde_cbor::Value::Bytes(b.into_owned()) + ciborium::value::Value::Bytes(b.into_owned()) } }, } @@ -3588,20 +3612,24 @@ mod tests { #[cfg(not(feature = "additional-controls"))] #[test] fn validate() -> std::result::Result<(), Box> { - let cddl = r#"tcpflagbytes = bstr .bits flags - flags = &( - fin: 8, - syn: 9, - rst: 10, - psh: 11, - ack: 12, - urg: 13, - ece: 14, - cwr: 15, - ns: 0, - ) / (4..7) ; data offset bits"#; - - let cbor = serde_cbor::Value::Bytes(vec![0x90, 0x6d]); + let cddl = indoc!( + r#" + tcpflagbytes = bstr .bits flags + flags = &( + fin: 8, + syn: 9, + rst: 10, + psh: 11, + ack: 12, + urg: 13, + ece: 14, + cwr: 15, + ns: 0, + ) / (4..7) ; data offset bits + "# + ); + + let cbor = ciborium::value::Value::Bytes(vec![0x90, 0x6d]); let mut lexer = lexer_from_str(cddl); let cddl = cddl_from_str(&mut lexer, cddl, true)?; @@ -3631,7 +3659,7 @@ mod tests { let sha256_oid = "2.16.840.1.101.3.4.2.1"; - let cbor = serde_cbor::Value::Bytes(sha256_oid.as_bytes().to_vec()); + let cbor = ciborium::value::Value::Bytes(sha256_oid.as_bytes().to_vec()); let mut lexer = lexer_from_str(cddl); let cddl = cddl_from_str(&mut lexer, cddl, true)?; @@ -3658,7 +3686,7 @@ mod tests { println!("{}", e); } - let cbor = serde_cbor::Value::Integer(2); + let cbor = ciborium::value::Value::Integer(2.into()); let cddl = cddl.unwrap(); diff --git a/src/validator/json.rs b/src/validator/json.rs index 9d76b468..6a04c40c 100644 --- a/src/validator/json.rs +++ b/src/validator/json.rs @@ -2530,6 +2530,8 @@ impl<'a> Visitor<'a, Error> for JSONValidator<'a> { Some(Token::REGEXP) | Some(Token::PCRE) => { let re = regex::Regex::new( &format_regex( + // Text strings must be JSON escaped per + // https://datatracker.ietf.org/doc/html/rfc8610#section-3.1 serde_json::from_str::(&format!("\"{}\"", t)) .map_err(Error::JSONParsing)? .as_str() diff --git a/src/validator/mod.rs b/src/validator/mod.rs index 618ce296..51ffd3cd 100644 --- a/src/validator/mod.rs +++ b/src/validator/mod.rs @@ -20,6 +20,8 @@ use std::error::Error; #[cfg(feature = "cbor")] use cbor::CBORValidator; +#[cfg(feature = "cbor")] +use ciborium; #[cfg(feature = "json")] use json::JSONValidator; use serde::de::Deserialize; @@ -50,11 +52,6 @@ trait Validator<'a, E: Error>: Visitor<'a, E> { fn add_error(&mut self, reason: String); } -trait Validatable {} - -impl Validatable for serde_cbor::Value {} -impl Validatable for serde_json::Value {} - #[cfg(not(target_arch = "wasm32"))] #[cfg(feature = "json")] /// Validate JSON string from a given CDDL document string @@ -165,11 +162,13 @@ pub fn validate_cbor_from_slice( cddl: &str, cbor_slice: &[u8], enabled_features: Option<&[&str]>, -) -> cbor::Result { +) -> cbor::Result { let mut lexer = lexer_from_str(cddl); let cddl = cddl_from_str(&mut lexer, cddl, true).map_err(cbor::Error::CDDLParsing)?; - let cbor = - serde_cbor::from_slice::(cbor_slice).map_err(cbor::Error::CBORParsing)?; + // let cbor = + // serde_cbor::from_slice::(cbor_slice).map_err(cbor::Error::CBORParsing)?; + + let cbor: ciborium::value::Value = ciborium::de::from_reader(cbor_slice).unwrap(); let mut cv = CBORValidator::new(&cddl, cbor, enabled_features); cv.validate() @@ -179,11 +178,11 @@ pub fn validate_cbor_from_slice( #[cfg(feature = "cbor")] #[cfg(not(feature = "additional-controls"))] /// Validate CBOR slice from a given CDDL document string -pub fn validate_cbor_from_slice(cddl: &str, cbor_slice: &[u8]) -> cbor::Result { +pub fn validate_cbor_from_slice(cddl: &str, cbor_slice: &[u8]) -> cbor::Result { let mut lexer = lexer_from_str(cddl); let cddl = cddl_from_str(&mut lexer, cddl, true).map_err(cbor::Error::CDDLParsing)?; - let cbor = - serde_cbor::from_slice::(cbor_slice).map_err(cbor::Error::CBORParsing)?; + let cbor: ciborium::value::Value = + ciborium::de::from_reader(cbor_slice).map_err(cbor::Error::CBORParsing)?; let mut cv = CBORValidator::new(&cddl, cbor); cv.validate() @@ -223,8 +222,8 @@ pub fn validate_cbor_from_slice( ); } - let cbor = serde_cbor::from_slice::(cbor_slice) - .map_err(|e| JsValue::from(e.to_string()))?; + let cbor: ciborium::value::Value = + ciborium::de::from_reader(cbor_slice).map_err(|e| JsValue::from(e.to_string()))?; let mut cv = CBORValidator::new(&c, cbor, enabled_features); cv.validate() diff --git a/tests/cbor_tests.rs b/tests/cbor_tests.rs index bbe4d986..b4748087 100644 --- a/tests/cbor_tests.rs +++ b/tests/cbor_tests.rs @@ -4,6 +4,7 @@ #![cfg(not(feature = "additional-controls"))] use cddl::{self, validator::validate_cbor_from_slice}; +use ciborium; use serde::{Deserialize, Serialize}; #[rustfmt::skip] // allow arbitrary indents for readability @@ -165,7 +166,8 @@ fn validate_cbor_homogenous_array() { validate_cbor_from_slice(cddl_input, cbor::ARRAY_EMPTY).unwrap_err(); let cddl_input = r#"thing = [? int]"#; // zero or one validate_cbor_from_slice(cddl_input, cbor::ARRAY_EMPTY).unwrap(); - let cbor_bytes = serde_cbor::to_vec(&[42]).unwrap(); + let mut cbor_bytes = Vec::new(); + ciborium::ser::into_writer(&[42], &mut cbor_bytes).unwrap(); validate_cbor_from_slice(cddl_input, &cbor_bytes).unwrap(); validate_cbor_from_slice(cddl_input, cbor::ARRAY_123).unwrap_err(); @@ -198,25 +200,30 @@ fn validate_cbor_array_record() { let cddl_input = r#"thing = [a: tstr, b: int]"#; let input = PersonTuple("Alice".to_string(), 42); - let cbor_bytes = serde_cbor::to_vec(&input).unwrap(); + let mut cbor_bytes = Vec::new(); + ciborium::ser::into_writer(&input, &mut cbor_bytes).unwrap(); validate_cbor_from_slice(cddl_input, &cbor_bytes).unwrap(); let input = BackwardsTuple(43, "Carol".to_string()); - let cbor_bytes = serde_cbor::to_vec(&input).unwrap(); + let mut cbor_bytes = Vec::new(); + ciborium::ser::into_writer(&input, &mut cbor_bytes).unwrap(); validate_cbor_from_slice(cddl_input, &cbor_bytes).unwrap_err(); let input = LongTuple("David".to_string(), 44, 45); - let cbor_bytes = serde_cbor::to_vec(&input).unwrap(); + let mut cbor_bytes = Vec::new(); + ciborium::ser::into_writer(&input, &mut cbor_bytes).unwrap(); validate_cbor_from_slice(cddl_input, &cbor_bytes).unwrap_err(); let input = ShortTuple("Eve".to_string()); - let cbor_bytes = serde_cbor::to_vec(&input).unwrap(); + let mut cbor_bytes = Vec::new(); + ciborium::ser::into_writer(&input, &mut cbor_bytes).unwrap(); validate_cbor_from_slice(cddl_input, &cbor_bytes).unwrap_err(); let cddl_input = r#"thing = [a: tstr, b: uint, c: float32, d: bool]"#; let input = KitchenSink("xyz".to_string(), 17, 9.9, false); - let cbor_bytes = serde_cbor::to_vec(&input).unwrap(); + let mut cbor_bytes = Vec::new(); + ciborium::ser::into_writer(&input, &mut cbor_bytes).unwrap(); validate_cbor_from_slice(cddl_input, &cbor_bytes).unwrap(); // FIXME: there isn't any way at present to serialize a struct @@ -234,7 +241,8 @@ fn validate_cbor_map() { name: "Bob".to_string(), age: 43, }; - let cbor_bytes = serde_cbor::to_vec(&input).unwrap(); + let mut cbor_bytes = Vec::new(); + ciborium::ser::into_writer(&input, &mut cbor_bytes).unwrap(); let cddl_input = r#"thing = {name: tstr, age: int}"#; validate_cbor_from_slice(cddl_input, &cbor_bytes).unwrap(); let cddl_input = r#"thing = {name: tstr, ? age: int}"#; diff --git a/tests/did.rs b/tests/did.rs index 09e91bdf..b7e0a323 100644 --- a/tests/did.rs +++ b/tests/did.rs @@ -1,5 +1,4 @@ #![cfg(feature = "std")] -#![cfg(not(feature = "additional-controls"))] #![cfg(not(target_arch = "wasm32"))] use cddl::{validate_cbor_from_slice, validate_json_from_str}; @@ -92,7 +91,11 @@ fn validate_did_cbor_examples() -> Result<(), Box> { let mut f = File::open(file.path())?; let mut data = Vec::new(); f.read_to_end(&mut data)?; + #[cfg(feature = "additional-controls")] + let r = validate_cbor_from_slice(&cddl, &data, None); + #[cfg(not(feature = "additional-controls"))] let r = validate_cbor_from_slice(&cddl, &data); + println!("assert ok {:?}", file.path()); if let Err(e) = &r { println!("error validating {:?}\n", file.path()); From d5bcd5bfba634468a4b417af5dbb28bdca8c1e9c Mon Sep 17 00:00:00 2001 From: anweiss <2326106+anweiss@users.noreply.github.com> Date: Tue, 28 Sep 2021 11:52:23 -0400 Subject: [PATCH 2/5] bump msrv to 1.51.0 --- .github/workflows/ci.yml | 2 +- Dockerfile | 2 +- README.md | 2 +- src/lib.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4ebcc86..e8940146 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: minimum-version-check: strategy: matrix: - rust_toolchain: [1.46.0] + rust_toolchain: [1.51.0] os: [ubuntu-latest, macOS-latest, windows-latest] name: minimum version check using Rust ${{ matrix.rust_toolchain }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} diff --git a/Dockerfile b/Dockerfile index 56f1b7e1..533df512 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ekidd/rust-musl-builder:1.47.0 AS builder +FROM ekidd/rust-musl-builder:1.51.0 AS builder COPY . ./ RUN cargo b --release --bin cddl diff --git a/README.md b/README.md index 3e878139..646f87c1 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A Rust implementation of the Concise data definition language (CDDL). CDDL is an This crate includes a handwritten parser and lexer for CDDL, and its development has been heavily inspired by the techniques outlined in Thorsten Ball's book ["Writing An Interpretor In Go"](https://interpreterbook.com/). The AST has been built to closely match the rules defined by the ABNF grammar in [Appendix B.](https://tools.ietf.org/html/rfc8610#appendix-B) of the spec. All CDDL must use UTF-8 for its encoding per the spec. -This crate supports validation of both CBOR and JSON data structures. An extremely basic REPL is included as well. This crate's minimum supported Rust version (MSRV) is 1.46.0. +This crate supports validation of both CBOR and JSON data structures. An extremely basic REPL is included as well. This crate's minimum supported Rust version (MSRV) is 1.51.0. Also bundled into this repository is a basic language server implementation and extension for Visual Studio Code for editing CDDL. The implementation is backed by the compiled WebAssembly target included in this crate. diff --git a/src/lib.rs b/src/lib.rs index 5b84bcea..33c57f71 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,7 @@ //! //! This crate supports validation of both CBOR and JSON data structures. An //! extremely basic REPL is included as well. This crate's minimum supported -//! Rust version (MSRV) is 1.46.0. +//! Rust version (MSRV) is 1.51.0. //! //! Also bundled into this repository is a basic language server implementation //! and extension for Visual Studio Code for editing CDDL. The implementation is From 2499748a85cdb2632a83cf86d1bf035a49fca6d9 Mon Sep 17 00:00:00 2001 From: anweiss <2326106+anweiss@users.noreply.github.com> Date: Mon, 4 Oct 2021 13:57:37 -0400 Subject: [PATCH 3/5] update docs --- README.md | 4 ++-- src/lib.rs | 15 +++++---------- src/validator/cbor.rs | 2 +- src/validator/mod.rs | 6 ++---- tests/cbor_tests.rs | 7 ++++--- 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 646f87c1..688b03ec 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ let json = r#"{ assert!(validate_json_from_str(cddl, json).is_ok()) ``` -This crate uses the [Serde](https://serde.rs/) framework, and more specifically, the [serde_json](https://crates.io/crates/serde_json) crate, for parsing and validating JSON. Serde was chosen due to its maturity in the ecosystem and its support for serializing and deserializing CBOR via the [serde_cbor](https://crates.io/crates/serde_cbor) crate. +This crate uses the [Serde](https://serde.rs/) framework, and more specifically, the [serde_json](https://crates.io/crates/serde_json) crate, for parsing and validating JSON. Serde was chosen due to its maturity in the ecosystem and its support for serializing and deserializing CBOR via the [ciborium](https://crates.io/crates/ciborium) crate. As outlined in [Appendix E.](https://tools.ietf.org/html/rfc8610#appendix-E) of the standard, only the JSON data model subset of CBOR can be used for validation. The limited prelude from the spec has been included below for brevity: @@ -333,7 +333,7 @@ let cbor = b"\xF4"; assert!(validate_cbor_from_slice(cddl, cbor).is_ok()) ``` -This crate also uses [Serde](https://serde.rs/) and [serde_cbor](https://crates.io/crates/serde_cbor) for validating CBOR data structures. CBOR validation is done via the loosely typed [`serde_cbor::Value`](https://docs.rs/serde_cbor/0.10.1/serde_cbor/enum.Value.html) enum. In addition to all of the same features implemented by the JSON validator, this crate also supports validating CBOR tags (e.g. `#6.32(tstr)`), CBOR major types (e.g. `#1.2`), table types (e.g. `{ [ + tstr ] => int }`) and byte strings. The `.bits`, `.cbor` and `.cborseq` control operators are all supported as well. +This crate also uses [Serde](https://serde.rs/) and [ciborium](https://crates.io/crates/ciborium) for validating CBOR data structures. CBOR validation is done via the loosely typed [`ciborium::value::Value`](https://github.com/enarx/ciborium/blob/main/ciborium/src/value/mod.rs#L22) enum. In addition to all of the same features implemented by the JSON validator, this crate also supports validating CBOR tags (e.g. `#6.32(tstr)`), CBOR major types (e.g. `#1.2`), table types (e.g. `{ [ + tstr ] => int }`) and byte strings. The `.bits`, `.cbor` and `.cborseq` control operators are all supported as well. The following tags are supported when validating CBOR: diff --git a/src/lib.rs b/src/lib.rs index 33c57f71..0eb8f3ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -186,7 +186,7 @@ //! //! ```toml //! [dependencies] -//! cddl = "0.9" +//! cddl = "0.9.0-beta.0" //! ``` //! //! Both JSON and CBOR validation require `std`. @@ -247,7 +247,6 @@ //! "address": "1234 Lakeshore Dr" //! }"#; //! -//! #[cfg(not(feature = "additional-controls"))] //! assert!(validate_json_from_str(cddl, json).is_ok()) //! ``` //! @@ -255,7 +254,7 @@ //! specifically, the [serde_json](https://crates.io/crates/serde_json) crate, //! for parsing and validating JSON. Serde was chosen due to its maturity in the //! ecosystem and its support for serializing and deserializing CBOR via the -//! [serde_cbor](https://crates.io/crates/serde_cbor) crate. +//! [ciborium](https://crates.io/crates/ciborium) crate. //! //! As outlined in [Appendix E.](https://tools.ietf.org/html/rfc8610#appendix-E) //! of the standard, only the JSON data model subset of CBOR can be used for @@ -431,14 +430,13 @@ //! //! let cbor = b"\xF4"; //! -//! #[cfg(not(feature = "additional-controls"))] //! assert!(validate_cbor_from_slice(cddl, cbor).is_ok()) //! ``` //! //! This crate also uses [Serde](https://serde.rs/) and -//! [serde_cbor](https://crates.io/crates/serde_cbor) for validating CBOR data +//! [ciborium](https://crates.io/crates/ciborium) for validating CBOR data //! structures. CBOR validation is done via the loosely typed -//! [`serde_cbor::Value`](https://docs.rs/serde_cbor/0.10.1/serde_cbor/enum.Value.html) +//! [`ciborium::value::Value`](https://github.com/enarx/ciborium/blob/main/ciborium/src/value/mod.rs#L22) //! enum. In addition to all of the same features implemented by the JSON //! validator, this crate also supports validating CBOR tags (e.g. //! `#6.32(tstr)`), CBOR major types (e.g. `#1.2`), table types (e.g. `{ [ + @@ -502,7 +500,7 @@ //! //! ```toml //! [dependencies] -//! cddl = { version = "0.9", default-features = false } +//! cddl = { version = "0.9.0-beta.0", default-features = false } //! ``` //! //! Zero-copy parsing is implemented to the extent that is possible. Allocation @@ -534,9 +532,6 @@ extern crate core as std; #[cfg(feature = "std")] extern crate serde_json; -// #[cfg(feature = "std")] -// extern crate serde_cbor; - #[cfg(feature = "std")] extern crate uriparse; diff --git a/src/validator/cbor.rs b/src/validator/cbor.rs index 8016c24d..512cb705 100644 --- a/src/validator/cbor.rs +++ b/src/validator/cbor.rs @@ -3588,7 +3588,7 @@ where } } -/// Converts a CDDL value type to serde_cbor::Value +/// Converts a CDDL value type to ciborium::value::Value pub fn token_value_into_cbor_value(value: token::Value) -> ciborium::value::Value { match value { token::Value::UINT(i) => ciborium::value::Value::Integer(i.into()), diff --git a/src/validator/mod.rs b/src/validator/mod.rs index 51ffd3cd..ac45027c 100644 --- a/src/validator/mod.rs +++ b/src/validator/mod.rs @@ -165,8 +165,6 @@ pub fn validate_cbor_from_slice( ) -> cbor::Result { let mut lexer = lexer_from_str(cddl); let cddl = cddl_from_str(&mut lexer, cddl, true).map_err(cbor::Error::CDDLParsing)?; - // let cbor = - // serde_cbor::from_slice::(cbor_slice).map_err(cbor::Error::CBORParsing)?; let cbor: ciborium::value::Value = ciborium::de::from_reader(cbor_slice).unwrap(); @@ -264,8 +262,8 @@ pub fn validate_cbor_from_slice( ); } - let cbor = serde_cbor::from_slice::(cbor_slice) - .map_err(|e| JsValue::from(e.to_string()))?; + let cbor: ciborium::value::Value = + ciborium::de::from_reader(cbor_slice).map_err(|e| JsValue::from(e.to_string()))?; let mut cv = CBORValidator::new(&c, cbor); cv.validate() diff --git a/tests/cbor_tests.rs b/tests/cbor_tests.rs index b4748087..70cb095a 100644 --- a/tests/cbor_tests.rs +++ b/tests/cbor_tests.rs @@ -228,9 +228,10 @@ fn validate_cbor_array_record() { // FIXME: there isn't any way at present to serialize a struct // into a CBOR array. See https://github.com/pyfisch/cbor/issues/107 - //let input = PersonStruct{name: "Bob".to_string(), age: 43}; - //let cbor_bytes = serde_cbor::to_vec(&input).unwrap(); - //validate_cbor_from_slice(cddl_input, &cbor_bytes).unwrap(); + // let input = PersonStruct{name: "Bob".to_string(), age: 43}; + // let mut cbor_bytes = Vec::new(); + // ciborium::ser::into_writer(&input, &mut cbor_bytes).unwrap(); + // validate_cbor_from_slice(cddl_input, &cbor_bytes).unwrap(); validate_cbor_from_slice(cddl_input, cbor::ARRAY_123).unwrap_err(); } From 076c36b4818af58b4cfd78a05f84323d0ee48147 Mon Sep 17 00:00:00 2001 From: anweiss <2326106+anweiss@users.noreply.github.com> Date: Mon, 4 Oct 2021 14:48:02 -0400 Subject: [PATCH 4/5] fix ciborium dep branch --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 410f5239..2196da2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ lexical-core = "0.7.6" regex = { version = "1.5.4", default-features = false, features = ["std"] } regex-syntax = { version = "0.6.25", optional = true } serde = { version = "1.0.127", optional = true, features = ["derive"] } -ciborium = { git = "https://github.com/enarx/ciborium", branch = "master", optional = true } +ciborium = { git = "https://github.com/enarx/ciborium", branch = "main", optional = true } serde_json = { version = "1.0.66", optional = true, default-features = false } uriparse = { version = "0.6.3", optional = true } base64-url = { version = "1.4.10", optional = true } From ca12059d96d22b6b8fe5baf802544e40cb97cdb9 Mon Sep 17 00:00:00 2001 From: anweiss <2326106+anweiss@users.noreply.github.com> Date: Mon, 4 Oct 2021 14:59:19 -0400 Subject: [PATCH 5/5] doc test fixes --- src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 0eb8f3ed..856931c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -247,6 +247,7 @@ //! "address": "1234 Lakeshore Dr" //! }"#; //! +//! #[cfg(not(feature = "additional-controls"))] //! assert!(validate_json_from_str(cddl, json).is_ok()) //! ``` //! @@ -405,6 +406,7 @@ //! //! let json = r#""v""#; //! +//! #[cfg(feature = "additional-controls")] //! assert!(validate_json_from_str(cddl, json, Some(&["json"])).is_ok()) //! ``` //! @@ -430,6 +432,7 @@ //! //! let cbor = b"\xF4"; //! +//! #[cfg(not(feature = "additional-controls"))] //! assert!(validate_cbor_from_slice(cddl, cbor).is_ok()) //! ``` //! @@ -489,6 +492,7 @@ //! //! let cbor = b"\x02"; //! +//! #[cfg(feature = "additional-controls")] //! assert!(validate_cbor_from_slice(cddl, cbor, Some(&["cbor"])).is_ok()) //! ``` //!