Skip to content

Commit 5f1cecc

Browse files
committedDec 4, 2020
concat updates
1 parent 62f46e6 commit 5f1cecc

File tree

2 files changed

+224
-146
lines changed

2 files changed

+224
-146
lines changed
 

‎src/validator/json.rs

+65-146
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,20 @@ impl std::error::Error for Error {
5050
}
5151
}
5252

53+
impl Error {
54+
fn from_validator(jv: &JSONValidator, reason: String) -> Self {
55+
Error::Validation(vec![ValidationError {
56+
cddl_location: jv.cddl_location.clone(),
57+
json_location: jv.json_location.clone(),
58+
reason,
59+
is_multi_type_choice: jv.is_multi_type_choice,
60+
is_group_to_choice_enum: jv.is_group_to_choice_enum,
61+
type_group_name_entry: jv.type_group_name_entry.map(|e| e.to_string()),
62+
is_multi_group_choice: jv.is_multi_group_choice,
63+
}])
64+
}
65+
}
66+
5367
/// JSON validation error
5468
#[derive(Clone, Debug)]
5569
pub struct ValidationError {
@@ -107,20 +121,6 @@ impl std::error::Error for ValidationError {
107121
}
108122
}
109123

110-
impl ValidationError {
111-
fn from_validator(jv: &JSONValidator, reason: String) -> Self {
112-
ValidationError {
113-
cddl_location: jv.cddl_location.clone(),
114-
json_location: jv.json_location.clone(),
115-
reason,
116-
is_multi_type_choice: jv.is_multi_type_choice,
117-
is_group_to_choice_enum: jv.is_group_to_choice_enum,
118-
type_group_name_entry: jv.type_group_name_entry.map(|e| e.to_string()),
119-
is_multi_group_choice: jv.is_multi_group_choice,
120-
}
121-
}
122-
}
123-
124124
/// JSON validator type
125125
#[derive(Clone)]
126126
pub struct JSONValidator<'a> {
@@ -212,16 +212,16 @@ impl<'a> JSONValidator<'a> {
212212
array_errors: None,
213213
}
214214
}
215+
}
215216

217+
impl<'a> Validator<'a, Error> for JSONValidator<'a> {
216218
/// Validate
217-
pub fn validate(&mut self) -> std::result::Result<(), Error> {
219+
fn validate(&mut self) -> std::result::Result<(), Error> {
218220
for r in self.cddl.rules.iter() {
219221
// First type rule is root
220222
if let Rule::Type { rule, .. } = r {
221223
if rule.generic_params.is_none() {
222-
self
223-
.visit_type_rule(rule)
224-
.map_err(|e| Error::Validation(vec![e]))?;
224+
self.visit_type_rule(rule)?;
225225
break;
226226
}
227227
}
@@ -247,8 +247,8 @@ impl<'a> JSONValidator<'a> {
247247
}
248248
}
249249

250-
impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
251-
fn visit_type_rule(&mut self, tr: &TypeRule<'a>) -> visitor::Result<ValidationError> {
250+
impl<'a> Visitor<'a, Error> for JSONValidator<'a> {
251+
fn visit_type_rule(&mut self, tr: &TypeRule<'a>) -> visitor::Result<Error> {
252252
if let Some(gp) = &tr.generic_params {
253253
if let Some(gr) = self
254254
.generic_rules
@@ -282,7 +282,7 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
282282
Ok(())
283283
}
284284

285-
fn visit_group_rule(&mut self, gr: &GroupRule<'a>) -> visitor::Result<ValidationError> {
285+
fn visit_group_rule(&mut self, gr: &GroupRule<'a>) -> visitor::Result<Error> {
286286
if let Some(gp) = &gr.generic_params {
287287
if let Some(gr) = self
288288
.generic_rules
@@ -316,7 +316,7 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
316316
Ok(())
317317
}
318318

319-
fn visit_type(&mut self, t: &Type<'a>) -> visitor::Result<ValidationError> {
319+
fn visit_type(&mut self, t: &Type<'a>) -> visitor::Result<Error> {
320320
if t.type_choices.len() > 1 {
321321
self.is_multi_type_choice = true;
322322
}
@@ -362,7 +362,7 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
362362
Ok(())
363363
}
364364

365-
fn visit_group(&mut self, g: &Group<'a>) -> visitor::Result<ValidationError> {
365+
fn visit_group(&mut self, g: &Group<'a>) -> visitor::Result<Error> {
366366
if g.group_choices.len() > 1 {
367367
self.is_multi_group_choice = true;
368368
}
@@ -439,7 +439,7 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
439439
Ok(())
440440
}
441441

442-
fn visit_group_choice(&mut self, gc: &GroupChoice<'a>) -> visitor::Result<ValidationError> {
442+
fn visit_group_choice(&mut self, gc: &GroupChoice<'a>) -> visitor::Result<Error> {
443443
if self.is_group_to_choice_enum {
444444
let initial_error_count = self.errors.len();
445445
for tc in type_choices_from_group_choice(self.cddl, gc).iter() {
@@ -473,7 +473,7 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
473473
lower: &Type2,
474474
upper: &Type2,
475475
is_inclusive: bool,
476-
) -> visitor::Result<ValidationError> {
476+
) -> visitor::Result<Error> {
477477
if let Value::Array(a) = &self.json {
478478
match validate_array_occurrence(
479479
self.occurrence.as_ref().take(),
@@ -782,7 +782,7 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
782782
target: &Type2<'a>,
783783
ctrl: &str,
784784
controller: &Type2<'a>,
785-
) -> visitor::Result<ValidationError> {
785+
) -> visitor::Result<Error> {
786786
match lookup_control_from_str(ctrl) {
787787
t @ Some(Token::EQ) => match target {
788788
Type2::Typename { ident, .. } => {
@@ -945,109 +945,29 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
945945
}
946946
t @ Some(Token::CAT) => {
947947
self.ctrl = t;
948-
match target {
949-
Type2::TextValue { value: target, .. } => match controller {
950-
Type2::TextValue {
951-
value: controller, ..
952-
} => {
953-
let s = format!("{}{}", target, controller);
954-
let mut jv = self.clone();
955-
jv.visit_value(&(&*s).into())?;
956-
self.errors.append(&mut jv.errors)
957-
}
958-
Type2::Typename { ident, .. } => {
959-
for controller in string_literals_from_ident(self.cddl, ident).iter() {
960-
let s = format!("{}{}", target, controller);
961-
let mut jv = self.clone();
962-
jv.visit_value(&(&*s).into())?;
963-
self.errors.append(&mut jv.errors)
964-
}
965-
}
966-
Type2::UTF8ByteString {
967-
value: controller, ..
968-
} => match std::str::from_utf8(controller) {
969-
Ok(controller) => {
970-
let s = format!("{}{}", target, controller);
971-
let mut jv = self.clone();
972-
jv.visit_value(&(&*s).into())?;
973-
self.errors.append(&mut jv.errors)
974-
}
975948

976-
Err(e) => self.add_error(format!("error parsing byte string: {}", e)),
977-
},
978-
_ => unimplemented!(),
979-
},
980-
Type2::Typename { ident, .. } => {
981-
// Only grab the first type choice literal from the target per
982-
// https://github.com/cbor-wg/cddl-control/issues/2#issuecomment-729253368
983-
if let Some(target) = string_literals_from_ident(self.cddl, ident).first() {
984-
match controller {
985-
Type2::TextValue {
986-
value: controller, ..
987-
} => {
988-
let s = format!("{}{}", target, controller);
989-
let mut jv = self.clone();
990-
jv.visit_value(&(&*s).into())?;
991-
self.errors.append(&mut jv.errors)
992-
}
993-
Type2::Typename { ident, .. } => {
994-
for controller in string_literals_from_ident(self.cddl, ident).iter() {
995-
let s = format!("{}{}", target, controller);
996-
let mut jv = self.clone();
997-
jv.visit_value(&(&*s).into())?;
998-
self.errors.append(&mut jv.errors)
999-
}
1000-
}
1001-
Type2::UTF8ByteString {
1002-
value: controller, ..
1003-
} => match std::str::from_utf8(controller) {
1004-
Ok(controller) => {
1005-
let s = format!("{}{}", target, controller);
1006-
let mut jv = self.clone();
1007-
jv.visit_value(&(&*s).into())?;
1008-
self.errors.append(&mut jv.errors)
1009-
}
1010-
Err(e) => self.add_error(format!("error parsing byte string: {}", e)),
1011-
},
1012-
_ => unimplemented!(),
1013-
}
1014-
}
949+
let mut values = Vec::new();
950+
if let Err(e) = cat_operation(self.cddl, target, controller, &mut values) {
951+
self.add_error(e);
952+
}
953+
954+
let mut success = false;
955+
let mut errors = Vec::new();
956+
for v in values.iter() {
957+
let mut jv = self.clone();
958+
jv.visit_value(&(&**v).into())?;
959+
if jv.errors.is_empty() {
960+
success = true;
961+
break;
1015962
}
1016-
Type2::UTF8ByteString { value: target, .. } => match std::str::from_utf8(target) {
1017-
Ok(target) => match controller {
1018-
Type2::TextValue {
1019-
value: controller, ..
1020-
} => {
1021-
let s = format!("{}{}", target, controller);
1022-
let mut jv = self.clone();
1023-
jv.visit_value(&(&*s).into())?;
1024-
self.errors.append(&mut jv.errors)
1025-
}
1026-
Type2::Typename { ident, .. } => {
1027-
for controller in string_literals_from_ident(self.cddl, ident).iter() {
1028-
let s = format!("{}{}", target, controller);
1029-
let mut jv = self.clone();
1030-
jv.visit_value(&(&*s).into())?;
1031-
self.errors.append(&mut jv.errors)
1032-
}
1033-
}
1034-
Type2::UTF8ByteString {
1035-
value: controller, ..
1036-
} => match std::str::from_utf8(controller) {
1037-
Ok(controller) => {
1038-
let s = format!("{}{}", target, controller);
1039-
let mut jv = self.clone();
1040-
jv.visit_value(&(&*s).into())?;
1041-
self.errors.append(&mut jv.errors)
1042-
}
1043-
Err(e) => self.add_error(format!("error parsing byte string: {}", e)),
1044-
},
1045-
_ => unimplemented!(),
1046-
},
1047-
Err(e) => self.add_error(format!("error parsing byte string: {}", e)),
1048-
},
1049-
_ => unimplemented!(),
963+
964+
errors.append(&mut jv.errors)
1050965
}
966+
967+
if !success {
968+
self.errors.append(&mut errors)
969+
}
970+
1051971
self.ctrl = None;
1052972
}
1053973
_ => {
@@ -1058,7 +978,7 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
1058978
Ok(())
1059979
}
1060980

1061-
fn visit_type2(&mut self, t2: &Type2<'a>) -> visitor::Result<ValidationError> {
981+
fn visit_type2(&mut self, t2: &Type2<'a>) -> visitor::Result<Error> {
1062982
match t2 {
1063983
Type2::TextValue { value, .. } => self.visit_value(&token::Value::TEXT(value)),
1064984
Type2::Map { group, .. } => match &self.json {
@@ -1372,7 +1292,7 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
13721292
}
13731293
}
13741294

1375-
fn visit_identifier(&mut self, ident: &Identifier<'a>) -> visitor::Result<ValidationError> {
1295+
fn visit_identifier(&mut self, ident: &Identifier<'a>) -> visitor::Result<Error> {
13761296
if let Some(name) = self.eval_generic_rule {
13771297
if let Some(gr) = self
13781298
.generic_rules
@@ -1613,7 +1533,7 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
16131533
fn visit_value_member_key_entry(
16141534
&mut self,
16151535
entry: &ValueMemberKeyEntry<'a>,
1616-
) -> visitor::Result<ValidationError> {
1536+
) -> visitor::Result<Error> {
16171537
if let Some(occur) = &entry.occur {
16181538
self.visit_occurrence(occur)?;
16191539
}
@@ -1683,23 +1603,23 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
16831603
fn visit_type_groupname_entry(
16841604
&mut self,
16851605
entry: &TypeGroupnameEntry<'a>,
1686-
) -> visitor::Result<ValidationError> {
1606+
) -> visitor::Result<Error> {
16871607
self.type_group_name_entry = Some(entry.name.ident);
16881608
walk_type_groupname_entry(self, entry)?;
16891609
self.type_group_name_entry = None;
16901610

16911611
Ok(())
16921612
}
16931613

1694-
fn visit_memberkey(&mut self, mk: &MemberKey<'a>) -> visitor::Result<ValidationError> {
1614+
fn visit_memberkey(&mut self, mk: &MemberKey<'a>) -> visitor::Result<Error> {
16951615
if let MemberKey::Type1 { is_cut, .. } = mk {
16961616
self.is_cut_present = *is_cut;
16971617
}
16981618

16991619
walk_memberkey(self, mk)
17001620
}
17011621

1702-
fn visit_value(&mut self, value: &token::Value<'a>) -> visitor::Result<ValidationError> {
1622+
fn visit_value(&mut self, value: &token::Value<'a>) -> visitor::Result<Error> {
17031623
let error: Option<String> = match &self.json {
17041624
Value::Number(n) => match value {
17051625
token::Value::INT(v) => match n.as_i64() {
@@ -1787,17 +1707,13 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
17871707
let re = regex::Regex::new(
17881708
&format_regex(
17891709
serde_json::from_str::<Value>(&format!("\"{}\"", t))
1790-
.map_err(|e| ValidationError::from_validator(self, e.to_string()))?
1710+
.map_err(Error::JSONParsing)?
17911711
.as_str()
1792-
.ok_or_else(|| {
1793-
ValidationError::from_validator(self, "malformed regex".to_string())
1794-
})?,
1712+
.ok_or_else(|| Error::from_validator(self, "malformed regex".to_string()))?,
17951713
)
1796-
.ok_or_else(|| {
1797-
ValidationError::from_validator(self, "malformed regex".to_string())
1798-
})?,
1714+
.ok_or_else(|| Error::from_validator(self, "malformed regex".to_string()))?,
17991715
)
1800-
.map_err(|e| ValidationError::from_validator(self, e.to_string()))?;
1716+
.map_err(|e| Error::from_validator(self, e.to_string()))?;
18011717

18021718
if re.is_match(s) {
18031719
None
@@ -1808,6 +1724,11 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
18081724
_ => {
18091725
if s == t {
18101726
None
1727+
} else if let Some(Token::CAT) = &self.ctrl {
1728+
Some(format!(
1729+
"expected value to match concatenated string {}, got \"{}\"",
1730+
value, s
1731+
))
18111732
} else if let Some(ctrl) = &self.ctrl {
18121733
Some(format!("expected value {} {}, got \"{}\"", ctrl, value, s))
18131734
} else {
@@ -1959,7 +1880,7 @@ impl<'a> Visitor<'a, ValidationError> for JSONValidator<'a> {
19591880
Ok(())
19601881
}
19611882

1962-
fn visit_occurrence(&mut self, o: &Occurrence) -> visitor::Result<ValidationError> {
1883+
fn visit_occurrence(&mut self, o: &Occurrence) -> visitor::Result<Error> {
19631884
self.occurrence = Some(o.occur.clone());
19641885

19651886
Ok(())
@@ -1975,12 +1896,10 @@ mod tests {
19751896
fn validate() -> std::result::Result<(), Box<dyn std::error::Error>> {
19761897
let cddl = indoc!(
19771898
r#"
1978-
a = "foo" .cat '
1979-
bar
1980-
baz
1981-
'"#
1899+
a = "foo" .cat b
1900+
b = "bar" / "baz" / "test""#
19821901
);
1983-
let json = r#""foo\n bar\n baz\n""#;
1902+
let json = r#""foobar""#;
19841903

19851904
let mut lexer = lexer_from_str(cddl);
19861905
let cddl = cddl_from_str(&mut lexer, cddl, true).map_err(json::Error::CDDLParsing);

0 commit comments

Comments
 (0)