diff --git a/shex_ast/src/ast/node_constraint.rs b/shex_ast/src/ast/node_constraint.rs index 49d52af7..d1b02f48 100644 --- a/shex_ast/src/ast/node_constraint.rs +++ b/shex_ast/src/ast/node_constraint.rs @@ -10,7 +10,7 @@ use serde::{ use super::ValueSetValue; use crate::{ Deref, DerefError, IriRef, NodeKind, NumericFacet, NumericLiteral, Pattern, StringFacet, - ValueSetValueWrapper, XsFacet, + XsFacet, }; use serde::ser::SerializeMap; @@ -26,7 +26,7 @@ pub struct NodeConstraint { xs_facet: Option>, // #[serde(default, skip_serializing_if = "Option::is_none")] - values: Option>, + values: Option>, } impl NodeConstraint { @@ -131,28 +131,28 @@ impl NodeConstraint { } pub fn with_values(mut self, values: Vec) -> Self { - let mut vs: Vec = Vec::with_capacity(values.len()); + let mut vs: Vec = Vec::with_capacity(values.len()); for v in values { - vs.push(ValueSetValueWrapper::new(v)); + vs.push(v); } self.values = Some(vs); self } - pub fn with_values_wrapped(mut self, values: Vec) -> Self { + /* pub fn with_values_wrapped(mut self, values: Vec) -> Self { self.values = Some(values); self - } + } */ pub fn values(&self) -> Option> { match &self.values { None => None, - Some(values) => { - let mut vs: Vec = Vec::with_capacity(values.len()); - for v in values { - vs.push(v.value()); + Some(vs) => { + let mut r = Vec::new(); + for v in vs { + r.push((*v).clone()) } - Some(vs) + Some(r) } } } @@ -168,7 +168,7 @@ impl Deref for NodeConstraint { Self: Sized, { let datatype = ::deref_opt(&self.datatype, base, prefixmap)?; - let values = ::deref_opt_vec(&self.values, base, prefixmap)?; + let values = ::deref_opt_vec(&self.values, base, prefixmap)?; Ok(NodeConstraint { node_kind: self.node_kind.clone(), datatype, @@ -363,7 +363,7 @@ impl<'de> Deserialize<'de> for NodeConstraint { let mut totaldigits: Option = None; let mut fractiondigits: Option = None; let mut flags: Option = None; - let mut values: Option> = None; + let mut values: Option> = None; while let Some(key) = map.next_key()? { match key { Field::NodeKind => { @@ -394,7 +394,7 @@ impl<'de> Deserialize<'de> for NodeConstraint { if values.is_some() { return Err(de::Error::duplicate_field("values")); } - let vs: Vec = map.next_value()?; + let vs: Vec = map.next_value()?; values = Some(vs) } Field::Pattern => { @@ -495,7 +495,7 @@ impl<'de> Deserialize<'de> for NodeConstraint { nc = nc.with_datatype(datatype) } if let Some(values) = values { - nc = nc.with_values_wrapped(values) + nc = nc.with_values(values) } if let Some(minlength) = minlength { nc = nc.with_minlength(minlength) diff --git a/shex_ast/src/ast/object_value.rs b/shex_ast/src/ast/object_value.rs index 3ff02f35..cde434d9 100644 --- a/shex_ast/src/ast/object_value.rs +++ b/shex_ast/src/ast/object_value.rs @@ -15,6 +15,11 @@ pub enum ObjectValue { NumericLiteral(NumericLiteral), + #[serde(serialize_with = "serialize_boolean_literal")] + BooleanLiteral { + value: bool, + }, + ObjectLiteral { value: String, @@ -65,6 +70,9 @@ impl Deref for ObjectValue { Ok(ObjectValue::IriRef(new_iri_ref)) } ObjectValue::NumericLiteral(n) => Ok(ObjectValue::NumericLiteral(n.clone())), + ObjectValue::BooleanLiteral { value } => Ok(ObjectValue::BooleanLiteral { + value: value.clone(), + }), ObjectValue::ObjectLiteral { value, language, @@ -128,3 +136,13 @@ impl Deref for ObjectValueWrapper { Ok(ObjectValueWrapper { ov }) } } + +fn serialize_boolean_literal(value: &bool, serializer: S) -> result::Result +where + S: Serializer, +{ + match value { + false => serializer.serialize_str("false"), + true => serializer.serialize_str("true"), + } +} diff --git a/shex_ast/src/ast/schema_json_compiler.rs b/shex_ast/src/ast/schema_json_compiler.rs index a11db292..c5586886 100644 --- a/shex_ast/src/ast/schema_json_compiler.rs +++ b/shex_ast/src/ast/schema_json_compiler.rs @@ -539,7 +539,7 @@ fn cnv_value(v: &ast::ValueSetValue) -> CResult { Ok(ValueSetValue::IriStem { stem: cnv_stem }) } ast::ValueSetValue::ObjectValue(ovw) => { - let ov = cnv_object_value(&ovw.ov)?; + let ov = cnv_object_value(&ovw)?; Ok(ValueSetValue::ObjectValue(ov)) } ast::ValueSetValue::Language { language_tag, .. } => Ok(ValueSetValue::Language { @@ -630,6 +630,9 @@ fn cnv_object_value(ov: &ast::ObjectValue) -> CResult { ast::ObjectValue::NumericLiteral(n) => { todo!() } + ast::ObjectValue::BooleanLiteral { value } => { + todo!() + } ast::ObjectValue::ObjectLiteral { value, language, .. } => Ok(ObjectValue::ObjectLiteral { diff --git a/shex_ast/src/ast/value_set_value.rs b/shex_ast/src/ast/value_set_value.rs index 6b3ca705..4b686094 100644 --- a/shex_ast/src/ast/value_set_value.rs +++ b/shex_ast/src/ast/value_set_value.rs @@ -1,71 +1,48 @@ -use std::{result, str::FromStr, fmt}; +use std::{fmt, result, str::FromStr}; use crate::{ast::serde_string_or_struct::*, Deref, DerefError, LangOrWildcard}; use iri_s::IriSError; use serde::{ - de::{self, MapAccess, Visitor, Unexpected}, + de::{self, MapAccess, Unexpected, Visitor}, Deserialize, Serialize, Serializer, }; -use serde_derive::{Serialize}; +use serde_derive::Serialize; use srdf::lang::Lang; use super::{ iri_ref::IriRef, iri_ref_or_wildcard::IriRefOrWildcard, string_or_iri_stem::StringOrIriStemWrapper, string_or_literal_stem::StringOrLiteralStemWrapper, - string_or_wildcard::StringOrWildcard, ObjectValue, ObjectValueWrapper, + string_or_wildcard::StringOrWildcard, ObjectValue, }; -#[derive(Serialize, Debug, PartialEq, Clone)] -#[serde(tag = "type")] +#[derive(Debug, PartialEq, Clone)] pub enum ValueSetValue { IriStem { stem: IriRef, }, IriStemRange { - #[serde( - serialize_with = "serialize_string_or_struct", - deserialize_with = "deserialize_string_or_struct" - )] stem: IriRefOrWildcard, - - #[serde(skip_serializing_if = "Option::is_none")] exclusions: Option>, }, LiteralStem { stem: String, }, LiteralStemRange { - #[serde( - serialize_with = "serialize_string_or_struct", - deserialize_with = "deserialize_string_or_struct" - )] stem: StringOrWildcard, - #[serde(skip_serializing_if = "Option::is_none")] exclusions: Option>, }, Language { - #[serde(rename = "languageTag", - serialize_with = "serialize_lang", - deserialize_with = "deserialize_lang")] language_tag: Lang, }, LanguageStem { - #[serde(rename = "stem", - serialize_with = "serialize_lang", - deserialize_with = "deserialize_lang")] stem: Lang, }, LanguageStemRange { - #[serde( - serialize_with = "serialize_string_or_struct", - deserialize_with = "deserialize_string_or_struct" - )] stem: LangOrWildcard, - - #[serde(skip_serializing_if = "Option::is_none")] exclusions: Option>, }, + ObjectValue(ObjectValue), } @@ -84,21 +61,16 @@ impl ValueSetValue { } pub fn object_value(value: ObjectValue) -> ValueSetValue { - ValueSetValue::ObjectValue(ov) + ValueSetValue::ObjectValue(value) } pub fn language(lang: Lang) -> ValueSetValue { - ValueSetValue::Language { - language_tag: lang - } + ValueSetValue::Language { language_tag: lang } } pub fn language_stem(lang: Lang) -> ValueSetValue { - ValueSetValue::LanguageStem { - stem: lang - } + ValueSetValue::LanguageStem { stem: lang } } - } impl Deref for ValueSetValue { @@ -114,13 +86,14 @@ impl Deref for ValueSetValue { ValueSetValue::ObjectValue(ov) => { let ov = ov.deref(base, prefixmap)?; Ok(ValueSetValue::ObjectValue(ov)) - }, - ValueSetValue::Language { language_tag } => { - Ok(ValueSetValue::Language { language_tag: language_tag.clone() }) } + ValueSetValue::Language { language_tag } => Ok(ValueSetValue::Language { + language_tag: language_tag.clone(), + }), ValueSetValue::LanguageStem { stem } => { Ok(ValueSetValue::LanguageStem { stem: stem.clone() }) } + ValueSetValue::IriStem { stem } => Ok(ValueSetValue::IriStem { stem: stem.clone() }), _ => { todo!() } @@ -187,125 +160,255 @@ fn serialize_lang(lang: &Lang, serializer: S) -> result::Result(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - struct LangVisitor; +where + D: serde::Deserializer<'de>, +{ + struct LangVisitor; - impl<'de> Visitor<'de> for LangVisitor { - type Value = Lang; + impl<'de> Visitor<'de> for LangVisitor { + type Value = Lang; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("Lang") - } + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Lang") + } - fn visit_str(self, v: &str) -> Result - where - E: serde::de::Error, - { - Ok(Lang::new(v)) - } - + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Ok(Lang::new(v)) + } + } + deserializer.deserialize_str(LangVisitor) +} +#[derive(Debug, PartialEq)] +enum ValueSetValueType { + IriStem, + LanguageStem, + LiteralStem, + IriStemRange, + LanguageStemRange, + LiteralStemRange, + Language, + Boolean, + Integer, + Decimal, + Double, +} + +impl ValueSetValueType { + fn parse(s: &str) -> Option { + match s { + "IriStem" => Some(ValueSetValueType::IriStem), + "LanguageStem" => Some(ValueSetValueType::LanguageStem), + "LiteralStem" => Some(ValueSetValueType::LiteralStem), + "Language" => Some(ValueSetValueType::Language), + "IriStemRange" => Some(ValueSetValueType::IriStemRange), + "LanguageStemRange" => Some(ValueSetValueType::LanguageStemRange), + "LiteralStemRange" => Some(ValueSetValueType::LiteralStemRange), + "http://www.w3.org/2001/XMLSchema#boolean" => Some(ValueSetValueType::Boolean), + "http://www.w3.org/2001/XMLSchema#decimal" => Some(ValueSetValueType::Decimal), + "http://www.w3.org/2001/XMLSchema#double" => Some(ValueSetValueType::Double), + "http://www.w3.org/2001/XMLSchema#integer" => Some(ValueSetValueType::Integer), + _ => None, } - deserializer.deserialize_str(LangVisitor) } +} +impl Serialize for ValueSetValue { + fn serialize(&self, serializer: S) -> result::Result + where + S: Serializer, + { + match self { + ValueSetValue::ObjectValue(v) => { + let s = format!("objectValue {v:?}"); + serializer.serialize_str(s.as_str()) + }, + _ => todo!(), + } + } +} impl<'de> Deserialize<'de> for ValueSetValue { fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - enum Field { - Type, - Value, - Language, - Stem, - Exclusions - } - - impl<'de> Deserialize<'de> for Field { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - struct FieldVisitor; - - impl<'de> Visitor<'de> for FieldVisitor { - type Value = Field; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str( + where + D: serde::Deserializer<'de>, + { + enum Field { + Type, + Value, + Language, + Stem, + Exclusions, + LanguageTag, + } + + impl<'de> Deserialize<'de> for Field { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct FieldVisitor; + + impl<'de> Visitor<'de> for FieldVisitor { + type Value = Field; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str( "field of value set value: `type` or `value` or `language` or `stem` or `exclusions`", ) - } - - fn visit_str(self, value: &str) -> Result - where - E: de::Error, - { - match value { - "type" => Ok(Field::Type), - "value" => Ok(Field::Value), - "stem" => Ok(Field::Stem), - "language" => Ok(Field::Language), - "exclusions" => Ok(Field::Exclusions), - _ => Err(de::Error::unknown_field(value, FIELDS)), - } + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + match value { + "type" => Ok(Field::Type), + "value" => Ok(Field::Value), + "stem" => Ok(Field::Stem), + "language" => Ok(Field::Language), + "languageTag" => Ok(Field::LanguageTag), + "exclusions" => Ok(Field::Exclusions), + _ => Err(de::Error::unknown_field(value, FIELDS)), } } - - deserializer.deserialize_identifier(FieldVisitor) } + + deserializer.deserialize_identifier(FieldVisitor) + } + } + + struct ValueSetValueVisitor; + + const FIELDS: &'static [&'static str] = &[ + "type", + "value", + "stem", + "language", + "languageTag", + "exclusions", + ]; + + impl<'de> Visitor<'de> for ValueSetValueVisitor { + type Value = ValueSetValue; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("ValueSet value") } - - struct ValueSetValueVisitor; - - impl<'de> Visitor<'de> for ValueSetValueVisitor { - type Value = ValueSetValue; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("ValueSet value") - } - fn visit_str(self, s: &str) -> Result - where E: de::Error { - FromStr::from_str(s).map_err(|e| { - de::Error::invalid_value(Unexpected::Str(s), &self) - }) - } - - fn visit_map(self, mut map: V) -> Result - where - V: MapAccess<'de>, - { - let mut type_: Option = None; - while let Some(key) = map.next_key()? { - match key { - Field::Type => { - if type_.is_some() { - return Err(de::Error::duplicate_field("type")); - } - let value: String = map.next_value()?; - if value != "NodeConstraint" { - return Err(de::Error::custom(format!( - "Expected NodeConstraint, found: {value}" - ))); - } - type_ = Some("NodeConstraint".to_string()); + fn visit_str(self, s: &str) -> Result + where + E: de::Error, + { + FromStr::from_str(s) + .map_err(|e| de::Error::invalid_value(Unexpected::Str(s), &self)) + } + + fn visit_map(self, mut map: V) -> Result + where + V: MapAccess<'de>, + { + let mut type_: Option = None; + let mut stem: Option = None; + let mut value: Option = None; + let mut language_tag: Option = None; + let mut language: Option = None; + let mut exclusions: Option = None; + while let Some(key) = map.next_key()? { + match key { + Field::Type => { + if type_.is_some() { + return Err(de::Error::duplicate_field("type")); + } + let value: String = map.next_value()?; + + if let Some(parsed_type_) = ValueSetValueType::parse(&value.as_str()) { + type_ = Some(parsed_type_) + } else { + return Err(de::Error::custom(format!( + "Expected ValueSetValue type, found: {value}" + ))); + } + } + Field::Value => { + if value.is_some() { + return Err(de::Error::duplicate_field("value")); + } + value = Some(map.next_value()?); + } + Field::Language => { + if language.is_some() { + return Err(de::Error::duplicate_field("language")); + } + language = Some(map.next_value()?); + } + Field::Stem => { + if stem.is_some() { + return Err(de::Error::duplicate_field("stem")); + } + stem = Some(map.next_value()?); + } + Field::Exclusions => { + if exclusions.is_some() { + return Err(de::Error::duplicate_field("exclusions")); + } + exclusions = Some(map.next_value()?); + } + Field::LanguageTag => { + if language_tag.is_some() { + return Err(de::Error::duplicate_field("languageTag")); } + language_tag = Some(map.next_value()?); } } - Ok(nc) + } + match type_ { + Some(ValueSetValueType::Language) => match language_tag { + Some(language_tag) => Ok(ValueSetValue::Language { + language_tag: Lang::new(language_tag.as_str()), + }), + None => Err(de::Error::missing_field("languageTag")), + }, + Some(ValueSetValueType::IriStem) => match stem { + Some(stem) => { + let iri_ref = TryFrom::try_from(stem.as_str()).map_err(|e| { + de::Error::custom(format!( + "Can't parse stem as IRIREF for IriStem: {e}" + )) + })?; + Ok(ValueSetValue::IriStem { stem: iri_ref }) + } + None => Err(de::Error::missing_field("stem")), + }, + Some(ValueSetValueType::Boolean) => match value { + Some(s) => match s.as_str() { + "false" => { + Ok(ValueSetValue::ObjectValue(ObjectValue::BooleanLiteral { + value: false, + })) + } + "true" => Ok(ValueSetValue::ObjectValue(ObjectValue::BooleanLiteral { + value: true, + })), + _ => Err(de::Error::invalid_value(Unexpected::Str(&s), &self)), + }, + None => Err(de::Error::missing_field("value")), + }, + Some(v) => Err(de::Error::custom(format!( + "Unknown ValueSetValueType {v:?}" + ))), + None => todo!(), } } - - deserializer.deserialize_any(ValueSetValueVisitor) } + + deserializer.deserialize_any(ValueSetValueVisitor) } - \ No newline at end of file +} diff --git a/shex_compact/src/compact_printer.rs b/shex_compact/src/compact_printer.rs index 28e8e155..0397e2bd 100644 --- a/shex_compact/src/compact_printer.rs +++ b/shex_compact/src/compact_printer.rs @@ -493,26 +493,21 @@ where match v { ValueSetValue::LanguageStem { stem } => todo!(), ValueSetValue::LanguageStemRange { stem, exclusions } => todo!(), - ValueSetValue::ObjectValue(ov) => self.pp_object_value(&ov.ov), + ValueSetValue::ObjectValue(ov) => self.pp_object_value(&ov), ValueSetValue::IriStem { stem } => todo!(), - ValueSetValue::IriStemRange { - stem, - exclusions, - } => todo!(), + ValueSetValue::IriStemRange { stem, exclusions } => todo!(), ValueSetValue::LiteralStem { stem } => todo!(), - ValueSetValue::LiteralStemRange { - stem, - exclusions, - } => todo!(), - ValueSetValue::Language { - language_tag, - } => todo!(), + ValueSetValue::LiteralStemRange { stem, exclusions } => todo!(), + ValueSetValue::Language { language_tag } => todo!(), } } fn pp_object_value(&self, v: &ObjectValue) -> DocBuilder<'a, Arena<'a, A>, A> { match v { ObjectValue::IriRef(i) => self.pp_iri_ref(i), + ObjectValue::BooleanLiteral { value } => { + todo!() + } ObjectValue::ObjectLiteral { type_, value, diff --git a/shex_compact/src/grammar.rs b/shex_compact/src/grammar.rs index 34998ece..f3bd2b78 100644 --- a/shex_compact/src/grammar.rs +++ b/shex_compact/src/grammar.rs @@ -1095,10 +1095,16 @@ type Exclusion = (); /// `[51] iriRange ::= iri ('~' exclusion*)?` fn iri_range(i: Span) -> IRes { - let (i, (iri, _, maybe_exc)) = tuple((iri, tws0, opt(tilde_exclusion)))(i)?; - // Pending char_exclusion - let vs = ValueSetValue::iri(iri); - Ok((i, vs)) + let (i, (iri, _, maybe_stem)) = tuple((iri, tws0, opt(tilde_exclusion)))(i)?; + let value = match maybe_stem { + None => ValueSetValue::iri(iri), + Some(excs) => if excs.is_empty() { + ValueSetValue::IriStem { stem: iri } + } else { + todo!() + } + }; + Ok((i, value)) } fn tilde_exclusion(i: Span) -> IRes> {