From a66111d9f9c99f91d9256209b5e9a65e42cde7f5 Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Sun, 30 Oct 2022 00:49:56 -0300 Subject: Implement parser --- src/vm/de.rs | 61 ++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 18 deletions(-) (limited to 'src/vm/de.rs') diff --git a/src/vm/de.rs b/src/vm/de.rs index 985b1b2..e26ec5e 100644 --- a/src/vm/de.rs +++ b/src/vm/de.rs @@ -14,7 +14,6 @@ use serde::de::IntoDeserializer as _; use smallvec::SmallVec; -use these::These; use super::Frame; use super::Interpreter; @@ -275,31 +274,51 @@ where { if let Err(e) = self.step_in() { return Err(e); } let pat = self.interp.pat; - let target_type = self.frames().iter_active().fold( + let target_type = self.frames().iter_active().try_fold( Type::IgnoredAny, |target_type, frame| { - match (target_type, frame.get_type()) { - (Type::IgnoredAny, Some((ty, _))) => ty, - (ty, Some((Type::IgnoredAny, _))) => ty, - (Type::String, Some((Type::Str, _))) => { + Ok(match (target_type, frame.get_type()) { + // required type binds stronger than any/ignored_any + (Type::IgnoredAny, Some((ty, true))) => ty, + (Type::Any, Some((ty, true))) => ty, + (ty, Some((Type::IgnoredAny, true))) => ty, + (ty, Some((Type::Any, true))) => ty, + // prefer owned if any branch prefers owned + (Type::String, Some((Type::Str, true))) => { Type::String }, - (Type::Str, Some((Type::String, _))) => { + (Type::Str, Some((Type::String, true))) => { Type::String }, - (Type::Bytes, Some((Type::ByteBuf, _))) => { + (Type::Bytes, Some((Type::ByteBuf, true))) => { Type::ByteBuf }, - (Type::ByteBuf, Some((Type::Bytes, _))) => { + (Type::ByteBuf, Some((Type::Bytes, true))) => { Type::ByteBuf }, + // types which are the same are okay (left, Some((right, _))) if left == right => { left }, + // optional type vs Any/IgnoredAny prefers Any + (Type::IgnoredAny, Some((_, false))) => Type::Any, + (Type::Any, Some((_, false))) => Type::Any, + // types which are not the same are an error because we + // only request a specific type if it's actually required + (left, Some((right, _))) => { + return Err(todo!()); + }, _ => Type::Any, - } + }) }, ); + let target_type = match target_type { + Ok(target_type) => target_type, + Err(e) => { + self.interp.error.insert(e); + return Err(D::Error::custom("type conflict")); + }, + }; match target_type { Type::Any => deserializer.deserialize_any(&mut *self), Type::IgnoredAny => { @@ -840,7 +859,6 @@ mod tests { use crate::vm::PatternElement; use crate::vm::SerdeObject; use crate::vm::Frame; - use these::These; use serde_json::Deserializer as JsonDeserializer; use serde::de::DeserializeSeed as _; @@ -886,7 +904,8 @@ mod tests { consts.strings.push("hello".into()); consts.protos.push(vec![ PatternElement::Value { - name_and_value: These::Both(0, Value::Type { + name: Some(0), + value: Some(Value::Type { ty: Type::U64, skippable: false, }), @@ -909,7 +928,8 @@ mod tests { consts.strings.push("hello".into()); consts.protos.push(vec![ PatternElement::Value { - name_and_value: These::Both(0, Value::Type { + name: Some(0), + value: Some(Value::Type { ty: Type::U64, skippable: false, }), @@ -933,7 +953,8 @@ mod tests { consts.strings.push("b".into()); consts.protos.push(vec![ PatternElement::Value { - name_and_value: These::Both(0, Value::Type { + name: Some(0), + value: Some(Value::Type { ty: Type::U64, skippable: true, }), @@ -941,7 +962,8 @@ mod tests { ]); consts.protos.push(vec![ PatternElement::Value { - name_and_value: These::Both(1, Value::Type { + name: Some(1), + value: Some(Value::Type { ty: Type::Bool, skippable: true, }), @@ -986,12 +1008,14 @@ mod tests { consts.strings.push("value".into()); consts.protos.push(vec![ PatternElement::Value { - name_and_value: These::This(0), + name: Some(0), + value: None, }, ]); consts.protos.push(vec![ PatternElement::Value { - name_and_value: These::That(Value::Type { + name: None, + value: Some(Value::Type { ty: Type::Map, skippable: false, }), @@ -1000,7 +1024,8 @@ mod tests { key_subtree: Some(0), }, PatternElement::Value { - name_and_value: These::Both(1, Value::Type { + name: Some(1), + value: Some(Value::Type { ty: Type::U64, skippable: false, }), -- cgit 1.4.1