From 686d72e93a763dcde04134d5fee27fc7e0dfae37 Mon Sep 17 00:00:00 2001 From: Khushboo Desai Date: Tue, 3 Oct 2023 13:06:15 -0700 Subject: [PATCH] Remove wrappers around ISL model * Renames structs IslTypeImpl, IslTypeRefImpl, IslSchemaImpl * adds `constraint()` to get constraint type enum --- ion-schema/src/constraint.rs | 76 ++--- ion-schema/src/isl/isl_constraint.rs | 362 +++++++++++------------ ion-schema/src/isl/isl_type.rs | 105 +++---- ion-schema/src/isl/isl_type_reference.rs | 138 ++++----- ion-schema/src/isl/mod.rs | 219 ++++++-------- ion-schema/src/lib.rs | 15 +- ion-schema/src/system.rs | 20 +- ion-schema/src/types.rs | 22 +- 8 files changed, 425 insertions(+), 532 deletions(-) diff --git a/ion-schema/src/constraint.rs b/ion-schema/src/constraint.rs index 12dd6cf..b28edfe 100644 --- a/ion-schema/src/constraint.rs +++ b/ion-schema/src/constraint.rs @@ -1,8 +1,10 @@ use crate::ion_extension::ElementExtensions; use crate::ion_path::{IonPath, IonPathElement}; -use crate::isl::isl_constraint::{IslAnnotationsConstraint, IslConstraintImpl, IslRegexConstraint}; +use crate::isl::isl_constraint::{ + IslAnnotationsConstraint, IslConstraintValue, IslRegexConstraint, +}; use crate::isl::isl_type_reference::{ - IslTypeRefImpl, IslVariablyOccurringTypeRef, NullabilityModifier, + IslTypeRef, IslVariablyOccurringTypeRef, NullabilityModifier, }; use crate::isl::ranges::{I64Range, Limit, TimestampPrecisionRange, U64Range, UsizeRange}; use crate::isl::util::{ @@ -293,29 +295,27 @@ impl Constraint { /// Resolves all ISL type references to corresponding [TypeReference]s fn resolve_type_references( isl_version: IslVersion, - type_references: &[IslTypeRefImpl], + type_references: &[IslTypeRef], type_store: &mut TypeStore, pending_types: &mut PendingTypes, ) -> IonSchemaResult> { type_references .iter() - .map(|t| { - IslTypeRefImpl::resolve_type_reference(isl_version, t, type_store, pending_types) - }) + .map(|t| IslTypeRef::resolve_type_reference(isl_version, t, type_store, pending_types)) .collect::>>() } /// Parse an [IslConstraint] to a [Constraint] pub(crate) fn resolve_from_isl_constraint( isl_version: IslVersion, - isl_constraint: &IslConstraintImpl, + isl_constraint: &IslConstraintValue, type_store: &mut TypeStore, pending_types: &mut PendingTypes, open_content: bool, // this will be used by Fields constraint to verify if open content is allowed or not ) -> IonSchemaResult { // TODO: add more constraints below match isl_constraint { - IslConstraintImpl::AllOf(isl_type_references) => { + IslConstraintValue::AllOf(isl_type_references) => { let type_references = Constraint::resolve_type_references( isl_version, isl_type_references, @@ -324,7 +324,7 @@ impl Constraint { )?; Ok(Constraint::AllOf(AllOfConstraint::new(type_references))) } - IslConstraintImpl::Annotations(isl_annotations) => match isl_annotations { + IslConstraintValue::Annotations(isl_annotations) => match isl_annotations { IslAnnotationsConstraint::SimpleAnnotations(simple_annotations) => { match isl_version { IslVersion::V1_0 => { @@ -335,7 +335,7 @@ impl Constraint { ))) } IslVersion::V2_0 => { - let type_ref = IslTypeRefImpl::resolve_type_reference( + let type_ref = IslTypeRef::resolve_type_reference( IslVersion::V2_0, &simple_annotations.convert_to_type_reference()?, type_store, @@ -349,7 +349,7 @@ impl Constraint { } } IslAnnotationsConstraint::StandardAnnotations(isl_type_ref) => { - let type_ref = IslTypeRefImpl::resolve_type_reference( + let type_ref = IslTypeRef::resolve_type_reference( isl_version, isl_type_ref, type_store, @@ -360,7 +360,7 @@ impl Constraint { ))) } }, - IslConstraintImpl::AnyOf(isl_type_references) => { + IslConstraintValue::AnyOf(isl_type_references) => { let type_references = Constraint::resolve_type_references( isl_version, isl_type_references, @@ -369,25 +369,25 @@ impl Constraint { )?; Ok(Constraint::AnyOf(AnyOfConstraint::new(type_references))) } - IslConstraintImpl::ByteLength(byte_length) => Ok(Constraint::ByteLength( + IslConstraintValue::ByteLength(byte_length) => Ok(Constraint::ByteLength( ByteLengthConstraint::new(byte_length.to_owned()), )), - IslConstraintImpl::CodepointLength(codepoint_length) => { + IslConstraintValue::CodepointLength(codepoint_length) => { Ok(Constraint::CodepointLength(CodepointLengthConstraint::new( codepoint_length.to_owned(), ))) } - IslConstraintImpl::Contains(values) => { + IslConstraintValue::Contains(values) => { let contains_constraint: ContainsConstraint = ContainsConstraint::new(values.to_owned()); Ok(Constraint::Contains(contains_constraint)) } - IslConstraintImpl::ContentClosed => Ok(Constraint::ContentClosed), - IslConstraintImpl::ContainerLength(isl_length) => Ok(Constraint::ContainerLength( + IslConstraintValue::ContentClosed => Ok(Constraint::ContentClosed), + IslConstraintValue::ContainerLength(isl_length) => Ok(Constraint::ContainerLength( ContainerLengthConstraint::new(isl_length.to_owned()), )), - IslConstraintImpl::Element(type_reference, require_distinct_elements) => { - let type_id = IslTypeRefImpl::resolve_type_reference( + IslConstraintValue::Element(type_reference, require_distinct_elements) => { + let type_id = IslTypeRef::resolve_type_reference( isl_version, type_reference, type_store, @@ -398,8 +398,8 @@ impl Constraint { *require_distinct_elements, ))) } - IslConstraintImpl::FieldNames(isl_type_reference, distinct) => { - let type_reference = IslTypeRefImpl::resolve_type_reference( + IslConstraintValue::FieldNames(isl_type_reference, distinct) => { + let type_reference = IslTypeRef::resolve_type_reference( isl_version, isl_type_reference, type_store, @@ -410,7 +410,7 @@ impl Constraint { *distinct, ))) } - IslConstraintImpl::Fields(fields, content_closed) => { + IslConstraintValue::Fields(fields, content_closed) => { let open_content = match isl_version { IslVersion::V1_0 => open_content, IslVersion::V2_0 => !content_closed, // for ISL 2.0 whether open content is allowed or not depends on `fields` constraint @@ -425,10 +425,10 @@ impl Constraint { )?; Ok(Constraint::Fields(fields_constraint)) } - IslConstraintImpl::Ieee754Float(iee754_interchange_format) => Ok( + IslConstraintValue::Ieee754Float(iee754_interchange_format) => Ok( Constraint::Ieee754Float(Ieee754FloatConstraint::new(*iee754_interchange_format)), ), - IslConstraintImpl::OneOf(isl_type_references) => { + IslConstraintValue::OneOf(isl_type_references) => { let type_references = Constraint::resolve_type_references( isl_version, isl_type_references, @@ -437,8 +437,8 @@ impl Constraint { )?; Ok(Constraint::OneOf(OneOfConstraint::new(type_references))) } - IslConstraintImpl::Not(type_reference) => { - let type_id = IslTypeRefImpl::resolve_type_reference( + IslConstraintValue::Not(type_reference) => { + let type_id = IslTypeRef::resolve_type_reference( isl_version, type_reference, type_store, @@ -446,8 +446,8 @@ impl Constraint { )?; Ok(Constraint::Not(NotConstraint::new(type_id))) } - IslConstraintImpl::Type(type_reference) => { - let type_id = IslTypeRefImpl::resolve_type_reference( + IslConstraintValue::Type(type_reference) => { + let type_id = IslTypeRef::resolve_type_reference( isl_version, type_reference, type_store, @@ -455,7 +455,7 @@ impl Constraint { )?; Ok(Constraint::Type(TypeConstraint::new(type_id))) } - IslConstraintImpl::OrderedElements(isl_type_references) => { + IslConstraintValue::OrderedElements(isl_type_references) => { Ok(Constraint::OrderedElements( OrderedElementsConstraint::resolve_from_isl_constraint( isl_version, @@ -465,41 +465,41 @@ impl Constraint { )?, )) } - IslConstraintImpl::Precision(precision_range) => { + IslConstraintValue::Precision(precision_range) => { isl_require!(precision_range.lower() != &Limit::Inclusive(0) => "precision range must have non-zero values")?; Ok(Constraint::Precision(PrecisionConstraint::new( precision_range.to_owned(), ))) } - IslConstraintImpl::Regex(regex) => Ok(Constraint::Regex(RegexConstraint::from_isl( + IslConstraintValue::Regex(regex) => Ok(Constraint::Regex(RegexConstraint::from_isl( regex, isl_version, )?)), - IslConstraintImpl::Scale(scale_range) => Ok(Constraint::Scale(ScaleConstraint::new( + IslConstraintValue::Scale(scale_range) => Ok(Constraint::Scale(ScaleConstraint::new( scale_range.to_owned(), ))), - IslConstraintImpl::TimestampOffset(timestamp_offset) => { + IslConstraintValue::TimestampOffset(timestamp_offset) => { Ok(Constraint::TimestampOffset(TimestampOffsetConstraint::new( timestamp_offset.valid_offsets().to_vec(), ))) } - IslConstraintImpl::Exponent(exponent_range) => Ok(Constraint::Exponent( + IslConstraintValue::Exponent(exponent_range) => Ok(Constraint::Exponent( ExponentConstraint::new(exponent_range.to_owned()), )), - IslConstraintImpl::TimestampPrecision(timestamp_precision_range) => { + IslConstraintValue::TimestampPrecision(timestamp_precision_range) => { Ok(Constraint::TimestampPrecision( TimestampPrecisionConstraint::new(timestamp_precision_range.to_owned()), )) } - IslConstraintImpl::Utf8ByteLength(utf8_byte_length) => Ok(Constraint::Utf8ByteLength( + IslConstraintValue::Utf8ByteLength(utf8_byte_length) => Ok(Constraint::Utf8ByteLength( Utf8ByteLengthConstraint::new(utf8_byte_length.to_owned()), )), - IslConstraintImpl::ValidValues(valid_values) => { + IslConstraintValue::ValidValues(valid_values) => { Ok(Constraint::ValidValues(ValidValuesConstraint { valid_values: valid_values.values().to_owned(), })) } - IslConstraintImpl::Unknown(constraint_name, element) => Ok(Constraint::Unknown( + IslConstraintValue::Unknown(constraint_name, element) => Ok(Constraint::Unknown( constraint_name.to_owned(), element.to_owned(), )), diff --git a/ion-schema/src/isl/isl_constraint.rs b/ion-schema/src/isl/isl_constraint.rs index 010d4e2..74343a0 100644 --- a/ion-schema/src/isl/isl_constraint.rs +++ b/ion-schema/src/isl/isl_constraint.rs @@ -1,6 +1,6 @@ use crate::ion_extension::ElementExtensions; use crate::isl::isl_import::IslImportType; -use crate::isl::isl_type_reference::{IslTypeRefImpl, IslVariablyOccurringTypeRef}; +use crate::isl::isl_type_reference::{IslTypeRef, IslVariablyOccurringTypeRef}; use crate::isl::ranges::{I64Range, TimestampPrecisionRange, U64Range, UsizeRange}; use crate::isl::util::{ Annotation, Ieee754InterchangeFormat, TimestampOffset, TimestampPrecision, ValidValue, @@ -19,7 +19,7 @@ use std::convert::TryInto; /// Provides public facing APIs for constructing ISL constraints programmatically for ISL 1.0 pub mod v_1_0 { use crate::isl::isl_constraint::{ - IslAnnotationsConstraint, IslConstraint, IslConstraintImpl, IslRegexConstraint, + IslAnnotationsConstraint, IslConstraint, IslConstraintValue, IslRegexConstraint, IslSimpleAnnotationsConstraint, IslTimestampOffsetConstraint, IslValidValuesConstraint, }; use crate::isl::isl_type_reference::{IslTypeRef, IslVariablyOccurringTypeRef}; @@ -32,23 +32,14 @@ pub mod v_1_0 { /// Creates a `type` constraint using the [IslTypeRef] referenced inside it // type is rust keyword hence this method is named type_constraint unlike other ISL constraint methods pub fn type_constraint(isl_type: IslTypeRef) -> IslConstraint { - IslConstraint::new( - IslVersion::V1_0, - IslConstraintImpl::Type(isl_type.type_reference), - ) + IslConstraint::new(IslVersion::V1_0, IslConstraintValue::Type(isl_type)) } /// Creates an `all_of` constraint using the [IslTypeRef] referenced inside it pub fn all_of>>(isl_types: A) -> IslConstraint { IslConstraint::new( IslVersion::V1_0, - IslConstraintImpl::AllOf( - isl_types - .into() - .into_iter() - .map(|t| t.type_reference) - .collect(), - ), + IslConstraintValue::AllOf(isl_types.into()), ) } @@ -56,13 +47,7 @@ pub mod v_1_0 { pub fn any_of>>(isl_types: A) -> IslConstraint { IslConstraint::new( IslVersion::V1_0, - IslConstraintImpl::AnyOf( - isl_types - .into() - .into_iter() - .map(|t| t.type_reference) - .collect(), - ), + IslConstraintValue::AnyOf(isl_types.into()), ) } @@ -70,13 +55,7 @@ pub mod v_1_0 { pub fn one_of>>(isl_types: A) -> IslConstraint { IslConstraint::new( IslVersion::V1_0, - IslConstraintImpl::OneOf( - isl_types - .into() - .into_iter() - .map(|t| t.type_reference) - .collect(), - ), + IslConstraintValue::OneOf(isl_types.into()), ) } @@ -86,18 +65,18 @@ pub mod v_1_0 { ) -> IslConstraint { IslConstraint::new( IslVersion::V1_0, - IslConstraintImpl::OrderedElements(isl_types.into().into_iter().collect()), + IslConstraintValue::OrderedElements(isl_types.into()), ) } /// Creates a `precision` constraint using the range specified in it pub fn precision(precision: U64Range) -> IslConstraint { - IslConstraint::new(IslVersion::V1_0, IslConstraintImpl::Precision(precision)) + IslConstraint::new(IslVersion::V1_0, IslConstraintValue::Precision(precision)) } /// Creates a `scale` constraint using the range specified in it pub fn scale(scale: I64Range) -> IslConstraint { - IslConstraint::new(IslVersion::V1_0, IslConstraintImpl::Scale(scale)) + IslConstraint::new(IslVersion::V1_0, IslConstraintValue::Scale(scale)) } /// Creates a `fields` constraint using the field names and [IslVariablyOccurringTypeRef]s referenced inside it @@ -107,43 +86,49 @@ pub mod v_1_0 { { IslConstraint::new( IslVersion::V1_0, - IslConstraintImpl::Fields(fields.map(|(s, t)| (s, t)).collect(), false), + IslConstraintValue::Fields(fields.map(|(s, t)| (s, t)).collect(), false), ) } /// Creates a `not` constraint using the [IslTypeRef] referenced inside it pub fn not(isl_type: IslTypeRef) -> IslConstraint { - IslConstraint::new( - IslVersion::V1_0, - IslConstraintImpl::Not(isl_type.type_reference), - ) + IslConstraint::new(IslVersion::V1_0, IslConstraintValue::Not(isl_type)) } /// Creates a `contains` constraint using the [Element] specified inside it pub fn contains>>(values: A) -> IslConstraint { - IslConstraint::new(IslVersion::V1_0, IslConstraintImpl::Contains(values.into())) + IslConstraint::new( + IslVersion::V1_0, + IslConstraintValue::Contains(values.into()), + ) } /// Creates a `container_length` constraint using the range specified in it pub fn container_length(length: UsizeRange) -> IslConstraint { - IslConstraint::new(IslVersion::V1_0, IslConstraintImpl::ContainerLength(length)) + IslConstraint::new( + IslVersion::V1_0, + IslConstraintValue::ContainerLength(length), + ) } /// Creates a `byte_length` constraint using the range specified in it pub fn byte_length(length: UsizeRange) -> IslConstraint { - IslConstraint::new(IslVersion::V1_0, IslConstraintImpl::ByteLength(length)) + IslConstraint::new(IslVersion::V1_0, IslConstraintValue::ByteLength(length)) } /// Creates a `codepoint_length` constraint using the range specified in it pub fn codepoint_length(length: UsizeRange) -> IslConstraint { - IslConstraint::new(IslVersion::V1_0, IslConstraintImpl::CodepointLength(length)) + IslConstraint::new( + IslVersion::V1_0, + IslConstraintValue::CodepointLength(length), + ) } /// Creates a `timestamp_precision` constraint using the range specified in it pub fn timestamp_precision(precision: TimestampPrecisionRange) -> IslConstraint { IslConstraint::new( IslVersion::V1_0, - IslConstraintImpl::TimestampPrecision(precision), + IslConstraintValue::TimestampPrecision(precision), ) } @@ -151,20 +136,20 @@ pub mod v_1_0 { pub fn timestamp_offset(offsets: Vec) -> IslConstraint { IslConstraint::new( IslVersion::V1_0, - IslConstraintImpl::TimestampOffset(IslTimestampOffsetConstraint::new(offsets)), + IslConstraintValue::TimestampOffset(IslTimestampOffsetConstraint::new(offsets)), ) } /// Creates an `utf_byte_length` constraint using the range specified in it pub fn utf8_byte_length(length: UsizeRange) -> IslConstraint { - IslConstraint::new(IslVersion::V1_0, IslConstraintImpl::Utf8ByteLength(length)) + IslConstraint::new(IslVersion::V1_0, IslConstraintValue::Utf8ByteLength(length)) } /// Creates an `element` constraint using the [IslTypeRef] referenced inside it pub fn element(isl_type: IslTypeRef) -> IslConstraint { IslConstraint::new( IslVersion::V1_0, - IslConstraintImpl::Element(isl_type.type_reference, false), + IslConstraintValue::Element(isl_type, false), ) } @@ -189,7 +174,7 @@ pub mod v_1_0 { .collect(); IslConstraint::new( IslVersion::V1_0, - IslConstraintImpl::Annotations(IslAnnotationsConstraint::SimpleAnnotations( + IslConstraintValue::Annotations(IslAnnotationsConstraint::SimpleAnnotations( IslSimpleAnnotationsConstraint::new( annotations_modifiers.contains(&"closed"), annotations_modifiers.contains(&"ordered"), @@ -204,7 +189,7 @@ pub mod v_1_0 { pub fn valid_values(valid_values: Vec) -> IonSchemaResult { Ok(IslConstraint::new( IslVersion::V1_0, - IslConstraintImpl::ValidValues(IslValidValuesConstraint { valid_values }), + IslConstraintValue::ValidValues(IslValidValuesConstraint { valid_values }), )) } @@ -212,7 +197,7 @@ pub mod v_1_0 { pub fn regex(case_insensitive: bool, multi_line: bool, expression: String) -> IslConstraint { IslConstraint::new( IslVersion::V1_0, - IslConstraintImpl::Regex(IslRegexConstraint::new( + IslConstraintValue::Regex(IslRegexConstraint::new( case_insensitive, multi_line, expression, @@ -227,7 +212,7 @@ pub mod v_2_0 { IslAnnotationsConstraint, IslConstraint, IslSimpleAnnotationsConstraint, }; use crate::isl::isl_constraint::{ - IslConstraintImpl, IslTimestampOffsetConstraint, IslValidValuesConstraint, + IslConstraintValue, IslTimestampOffsetConstraint, IslValidValuesConstraint, }; use crate::isl::isl_type_reference::{IslTypeRef, IslVariablyOccurringTypeRef}; use crate::isl::ranges::{I64Range, TimestampPrecisionRange, U64Range, UsizeRange}; @@ -239,23 +224,14 @@ pub mod v_2_0 { /// Creates a `type` constraint using the [IslTypeRef] referenced inside it // type is rust keyword hence this method is named type_constraint unlike other ISL constraint methods pub fn type_constraint(isl_type: IslTypeRef) -> IslConstraint { - IslConstraint::new( - IslVersion::V2_0, - IslConstraintImpl::Type(isl_type.type_reference), - ) + IslConstraint::new(IslVersion::V2_0, IslConstraintValue::Type(isl_type)) } /// Creates an `all_of` constraint using the [IslTypeRef] referenced inside it pub fn all_of>>(isl_types: A) -> IslConstraint { IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::AllOf( - isl_types - .into() - .into_iter() - .map(|t| t.type_reference) - .collect(), - ), + IslConstraintValue::AllOf(isl_types.into()), ) } @@ -263,13 +239,7 @@ pub mod v_2_0 { pub fn any_of>>(isl_types: A) -> IslConstraint { IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::AnyOf( - isl_types - .into() - .into_iter() - .map(|t| t.type_reference) - .collect(), - ), + IslConstraintValue::AnyOf(isl_types.into()), ) } @@ -277,13 +247,7 @@ pub mod v_2_0 { pub fn one_of>>(isl_types: A) -> IslConstraint { IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::OneOf( - isl_types - .into() - .into_iter() - .map(|t| t.type_reference) - .collect(), - ), + IslConstraintValue::OneOf(isl_types.into()), ) } @@ -293,18 +257,18 @@ pub mod v_2_0 { ) -> IslConstraint { IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::OrderedElements(isl_types.into().into_iter().collect()), + IslConstraintValue::OrderedElements(isl_types.into()), ) } /// Creates a `precision` constraint using the range specified in it pub fn precision(precision: U64Range) -> IslConstraint { - IslConstraint::new(IslVersion::V2_0, IslConstraintImpl::Precision(precision)) + IslConstraint::new(IslVersion::V2_0, IslConstraintValue::Precision(precision)) } /// Creates an `exponent` constraint from a [Range] specifying an exponent range. pub fn exponent(exponent: I64Range) -> IslConstraint { - IslConstraint::new(IslVersion::V2_0, IslConstraintImpl::Exponent(exponent)) + IslConstraint::new(IslVersion::V2_0, IslConstraintValue::Exponent(exponent)) } /// Creates a `fields` constraint using the field names and [IslVariablyOccurringTypeRef]s referenced inside it @@ -314,7 +278,7 @@ pub mod v_2_0 { { IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::Fields(fields.map(|(s, t)| (s, t)).collect(), false), + IslConstraintValue::Fields(fields.map(|(s, t)| (s, t)).collect(), false), ) } @@ -322,43 +286,49 @@ pub mod v_2_0 { pub fn field_names(isl_type: IslTypeRef, require_distinct_field_names: bool) -> IslConstraint { IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::FieldNames(isl_type.type_reference, require_distinct_field_names), + IslConstraintValue::FieldNames(isl_type, require_distinct_field_names), ) } /// Creates a `not` constraint using the [IslTypeRef] referenced inside it pub fn not(isl_type: IslTypeRef) -> IslConstraint { - IslConstraint::new( - IslVersion::V2_0, - IslConstraintImpl::Not(isl_type.type_reference), - ) + IslConstraint::new(IslVersion::V2_0, IslConstraintValue::Not(isl_type)) } /// Creates a `contains` constraint using the [Element] specified inside it pub fn contains>>(values: A) -> IslConstraint { - IslConstraint::new(IslVersion::V2_0, IslConstraintImpl::Contains(values.into())) + IslConstraint::new( + IslVersion::V2_0, + IslConstraintValue::Contains(values.into()), + ) } /// Creates a `container_length` constraint using the range specified in it pub fn container_length(length: UsizeRange) -> IslConstraint { - IslConstraint::new(IslVersion::V2_0, IslConstraintImpl::ContainerLength(length)) + IslConstraint::new( + IslVersion::V2_0, + IslConstraintValue::ContainerLength(length), + ) } /// Creates a `byte_length` constraint using the range specified in it pub fn byte_length(length: UsizeRange) -> IslConstraint { - IslConstraint::new(IslVersion::V2_0, IslConstraintImpl::ByteLength(length)) + IslConstraint::new(IslVersion::V2_0, IslConstraintValue::ByteLength(length)) } /// Creates a `codepoint_length` constraint using the range specified in it pub fn codepoint_length(length: UsizeRange) -> IslConstraint { - IslConstraint::new(IslVersion::V2_0, IslConstraintImpl::CodepointLength(length)) + IslConstraint::new( + IslVersion::V2_0, + IslConstraintValue::CodepointLength(length), + ) } /// Creates a `timestamp_precision` constraint using the range specified in it pub fn timestamp_precision(precision: TimestampPrecisionRange) -> IslConstraint { IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::TimestampPrecision(precision), + IslConstraintValue::TimestampPrecision(precision), ) } @@ -366,20 +336,20 @@ pub mod v_2_0 { pub fn timestamp_offset(offsets: Vec) -> IslConstraint { IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::TimestampOffset(IslTimestampOffsetConstraint::new(offsets)), + IslConstraintValue::TimestampOffset(IslTimestampOffsetConstraint::new(offsets)), ) } /// Creates a `utf8_byte_length` constraint using the range specified in it pub fn utf8_byte_length(length: UsizeRange) -> IslConstraint { - IslConstraint::new(IslVersion::V2_0, IslConstraintImpl::Utf8ByteLength(length)) + IslConstraint::new(IslVersion::V2_0, IslConstraintValue::Utf8ByteLength(length)) } /// Creates an `element` constraint using the [IslTypeRef] referenced inside it and considers whether distinct elements are required or not pub fn element(isl_type: IslTypeRef, require_distinct_elements: bool) -> IslConstraint { IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::Element(isl_type.type_reference, require_distinct_elements), + IslConstraintValue::Element(isl_type, require_distinct_elements), ) } @@ -409,7 +379,7 @@ pub mod v_2_0 { Ok(IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::Annotations(IslAnnotationsConstraint::SimpleAnnotations( + IslConstraintValue::Annotations(IslAnnotationsConstraint::SimpleAnnotations( IslSimpleAnnotationsConstraint::new(is_closed, false, is_required, annotations), )), )) @@ -419,8 +389,8 @@ pub mod v_2_0 { pub fn annotations(isl_type: IslTypeRef) -> IslConstraint { IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::Annotations(IslAnnotationsConstraint::StandardAnnotations( - isl_type.type_reference, + IslConstraintValue::Annotations(IslAnnotationsConstraint::StandardAnnotations( + isl_type, )), ) } @@ -429,7 +399,7 @@ pub mod v_2_0 { pub fn valid_values(valid_values: Vec) -> IonSchemaResult { Ok(IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::ValidValues(IslValidValuesConstraint { valid_values }), + IslConstraintValue::ValidValues(IslValidValuesConstraint { valid_values }), )) } @@ -442,7 +412,7 @@ pub mod v_2_0 { pub fn ieee754_float(interchange_format: Ieee754InterchangeFormat) -> IslConstraint { IslConstraint::new( IslVersion::V2_0, - IslConstraintImpl::Ieee754Float(interchange_format), + IslConstraintValue::Ieee754Float(interchange_format), ) } } @@ -451,23 +421,28 @@ pub mod v_2_0 { #[derive(Debug, Clone, PartialEq)] pub struct IslConstraint { pub(crate) version: IslVersion, - pub(crate) constraint: IslConstraintImpl, + pub(crate) constraint_value: IslConstraintValue, } impl IslConstraint { - pub(crate) fn new(version: IslVersion, constraint: IslConstraintImpl) -> Self { + pub(crate) fn new(version: IslVersion, constraint: IslConstraintValue) -> Self { Self { - constraint, + constraint_value: constraint, version, } } + + /// Provides an enum to match constraint types and get underlying constraint value + pub fn constraint(&self) -> &IslConstraintValue { + &self.constraint_value + } } #[derive(Debug, Clone, PartialEq)] -pub(crate) enum IslConstraintImpl { - AllOf(Vec), +pub enum IslConstraintValue { + AllOf(Vec), Annotations(IslAnnotationsConstraint), - AnyOf(Vec), + AnyOf(Vec), ByteLength(UsizeRange), CodepointLength(UsizeRange), Contains(Vec), @@ -476,7 +451,7 @@ pub(crate) enum IslConstraintImpl { // Represents Element(type_reference, expected_distinct). // For ISL 2.0 true/false is specified based on whether `distinct` annotation is present or not. // For ISL 1.0 which doesn't support `distinct` elements this will be (type_reference, false). - Element(IslTypeRefImpl, bool), + Element(IslTypeRef, bool), Exponent(I64Range), // Represents Fields(fields, content_closed) // For ISL 2.0 true/false is specified based on whether `closed::` annotation is present or not @@ -485,23 +460,23 @@ pub(crate) enum IslConstraintImpl { // Represents FieldNames(type_reference, expected_distinct). // For ISL 2.0 true/false is specified based on whether `distinct` annotation is present or not. // For ISL 1.0 which doesn't support `field_names` constraint this will be (type_reference, false). - FieldNames(IslTypeRefImpl, bool), + FieldNames(IslTypeRef, bool), Ieee754Float(Ieee754InterchangeFormat), - Not(IslTypeRefImpl), - OneOf(Vec), + Not(IslTypeRef), + OneOf(Vec), OrderedElements(Vec), Precision(U64Range), Regex(IslRegexConstraint), Scale(I64Range), TimestampOffset(IslTimestampOffsetConstraint), TimestampPrecision(TimestampPrecisionRange), - Type(IslTypeRefImpl), + Type(IslTypeRef), Unknown(String, Element), // Unknown constraint is used to store open contents Utf8ByteLength(UsizeRange), ValidValues(IslValidValuesConstraint), } -impl IslConstraintImpl { +impl IslConstraintValue { /// Parse constraints inside an [Element] to an [IslConstraint] pub fn from_ion_element( isl_version: IslVersion, @@ -509,18 +484,18 @@ impl IslConstraintImpl { value: &Element, type_name: &str, inline_imported_types: &mut Vec, - ) -> IonSchemaResult { + ) -> IonSchemaResult { // TODO: add more constraints to match below match constraint_name { "all_of" => { - let types: Vec = - IslConstraintImpl::isl_type_references_from_ion_element( + let types: Vec = + IslConstraintValue::isl_type_references_from_ion_element( isl_version, value, inline_imported_types, "all_of", )?; - Ok(IslConstraintImpl::AllOf(types)) + Ok(IslConstraintValue::AllOf(types)) } "annotations" => { if value.is_null() { @@ -530,19 +505,16 @@ impl IslConstraintImpl { } if value.ion_type() == IonType::List { - Ok(IslConstraintImpl::Annotations( + Ok(IslConstraintValue::Annotations( IslAnnotationsConstraint::SimpleAnnotations( IslSimpleAnnotationsConstraint::from_ion_element(value, isl_version)?, ), )) } else if value.ion_type() == IonType::Struct && isl_version == IslVersion::V2_0 { - let type_reference: IslTypeRefImpl = IslTypeRefImpl::from_ion_element( - isl_version, - value, - inline_imported_types, - )?; + let type_reference: IslTypeRef = + IslTypeRef::from_ion_element(isl_version, value, inline_imported_types)?; - Ok(IslConstraintImpl::Annotations( + Ok(IslConstraintValue::Annotations( IslAnnotationsConstraint::StandardAnnotations(type_reference), )) } else { @@ -553,20 +525,19 @@ impl IslConstraintImpl { } } "any_of" => { - let types: Vec = - IslConstraintImpl::isl_type_references_from_ion_element( + let types: Vec = + IslConstraintValue::isl_type_references_from_ion_element( isl_version, value, inline_imported_types, "any_of", )?; - Ok(IslConstraintImpl::AnyOf(types)) + Ok(IslConstraintValue::AnyOf(types)) } - "byte_length" => Ok(IslConstraintImpl::ByteLength(UsizeRange::from_ion_element( - value, - Element::as_usize, - )?)), - "codepoint_length" => Ok(IslConstraintImpl::CodepointLength( + "byte_length" => Ok(IslConstraintValue::ByteLength( + UsizeRange::from_ion_element(value, Element::as_usize)?, + )), + "codepoint_length" => Ok(IslConstraintValue::CodepointLength( UsizeRange::from_ion_element(value, Element::as_usize)?, )), "contains" => { @@ -593,7 +564,7 @@ impl IslConstraintImpl { .elements() .map(|e| e.to_owned()) .collect(); - Ok(IslConstraintImpl::Contains(values)) + Ok(IslConstraintValue::Contains(values)) } "content" => { if value.is_null() { @@ -617,19 +588,19 @@ impl IslConstraintImpl { } } - Ok(IslConstraintImpl::ContentClosed) + Ok(IslConstraintValue::ContentClosed) } - "container_length" => Ok(IslConstraintImpl::ContainerLength( + "container_length" => Ok(IslConstraintValue::ContainerLength( UsizeRange::from_ion_element(value, Element::as_usize)?, )), "element" => { - let type_reference: IslTypeRefImpl = - IslTypeRefImpl::from_ion_element(isl_version, value, inline_imported_types)?; + let type_reference: IslTypeRef = + IslTypeRef::from_ion_element(isl_version, value, inline_imported_types)?; match isl_version { IslVersion::V1_0 => { // for ISL 1.0 `distinct annotation on `element` constraint is not supported which is represented by `false` here - Ok(IslConstraintImpl::Element(type_reference, false)) + Ok(IslConstraintValue::Element(type_reference, false)) } IslVersion::V2_0 => { // return error if there are any annotations other than `distinct` or `$null_or` @@ -646,17 +617,20 @@ impl IslConstraintImpl { // verify whether `distinct`annotation is present or not let require_distinct = value.annotations().contains("distinct"); - Ok(IslConstraintImpl::Element(type_reference, require_distinct)) + Ok(IslConstraintValue::Element( + type_reference, + require_distinct, + )) } } } "field_names" => { let type_reference = - IslTypeRefImpl::from_ion_element(isl_version, value, inline_imported_types)?; + IslTypeRef::from_ion_element(isl_version, value, inline_imported_types)?; match isl_version { IslVersion::V1_0 => { // for ISL 1.0 `field_names` constraint does not exist hence `field_names` will be considered as open content - Ok(IslConstraintImpl::Unknown( + Ok(IslConstraintValue::Unknown( constraint_name.to_string(), value.to_owned(), )) @@ -674,7 +648,7 @@ impl IslConstraintImpl { ); } - Ok(IslConstraintImpl::FieldNames( + Ok(IslConstraintValue::FieldNames( type_reference, value.annotations().contains("distinct"), )) @@ -683,7 +657,7 @@ impl IslConstraintImpl { } "fields" => { let fields: HashMap = - IslConstraintImpl::isl_fields_from_ion_element( + IslConstraintValue::isl_fields_from_ion_element( isl_version, value, inline_imported_types, @@ -693,7 +667,7 @@ impl IslConstraintImpl { return invalid_schema_error("fields constraint can not be empty"); } match isl_version { - IslVersion::V1_0 => Ok(IslConstraintImpl::Fields(fields, false)), + IslVersion::V1_0 => Ok(IslConstraintValue::Fields(fields, false)), IslVersion::V2_0 => { if value.annotations().len() > 1 || value @@ -705,7 +679,7 @@ impl IslConstraintImpl { "fields constraint may only be annotated with 'closed'", ); } - Ok(IslConstraintImpl::Fields( + Ok(IslConstraintValue::Fields( fields, value.annotations().contains("closed"), )) @@ -726,27 +700,27 @@ impl IslConstraintImpl { invalid_schema_error_raw(format!( "expected ieee754_float to be one of 'binary16', 'binary32', or 'binary64', but it was: {value}")) })?; - Ok(IslConstraintImpl::Ieee754Float(string_value.try_into()?)) + Ok(IslConstraintValue::Ieee754Float(string_value.try_into()?)) } "one_of" => { - let types: Vec = - IslConstraintImpl::isl_type_references_from_ion_element( + let types: Vec = + IslConstraintValue::isl_type_references_from_ion_element( isl_version, value, inline_imported_types, "one_of", )?; - Ok(IslConstraintImpl::OneOf(types)) + Ok(IslConstraintValue::OneOf(types)) } "not" => { - let type_reference: IslTypeRefImpl = - IslTypeRefImpl::from_ion_element(isl_version, value, inline_imported_types)?; - Ok(IslConstraintImpl::Not(type_reference)) + let type_reference: IslTypeRef = + IslTypeRef::from_ion_element(isl_version, value, inline_imported_types)?; + Ok(IslConstraintValue::Not(type_reference)) } "type" => { - let type_reference: IslTypeRefImpl = - IslTypeRefImpl::from_ion_element(isl_version, value, inline_imported_types)?; - Ok(IslConstraintImpl::Type(type_reference)) + let type_reference: IslTypeRef = + IslTypeRef::from_ion_element(isl_version, value, inline_imported_types)?; + Ok(IslConstraintValue::Type(type_reference)) } "ordered_elements" => { if value.is_null() { @@ -774,9 +748,9 @@ impl IslConstraintImpl { ) }) .collect::>>()?; - Ok(IslConstraintImpl::OrderedElements(types)) + Ok(IslConstraintValue::OrderedElements(types)) } - "precision" => Ok(IslConstraintImpl::Precision(U64Range::from_ion_element( + "precision" => Ok(IslConstraintValue::Precision(U64Range::from_ion_element( value, Element::as_u64, )?)), @@ -807,26 +781,26 @@ impl IslConstraintImpl { ); } - Ok(IslConstraintImpl::Regex(IslRegexConstraint::new( + Ok(IslConstraintValue::Regex(IslRegexConstraint::new( case_insensitive, multi_line, expression.to_string(), ))) } "scale" => match isl_version { - IslVersion::V1_0 => Ok(IslConstraintImpl::Scale(I64Range::from_ion_element( + IslVersion::V1_0 => Ok(IslConstraintValue::Scale(I64Range::from_ion_element( value, Element::as_i64, )?)), IslVersion::V2_0 => { // for ISL 2.0 scale constraint does not exist hence `scale` will be considered as open content - Ok(IslConstraintImpl::Unknown( + Ok(IslConstraintValue::Unknown( constraint_name.to_string(), value.to_owned(), )) } }, - "timestamp_precision" => Ok(IslConstraintImpl::TimestampPrecision( + "timestamp_precision" => Ok(IslConstraintValue::TimestampPrecision( TimestampPrecisionRange::from_ion_element(value, |e| { let symbol_text = e.as_symbol().and_then(Symbol::text)?; TimestampPrecision::try_from(symbol_text).ok() @@ -835,12 +809,12 @@ impl IslConstraintImpl { "exponent" => match isl_version { IslVersion::V1_0 => { // for ISL 1.0 exponent constraint does not exist hence `exponent` will be considered as open content - Ok(IslConstraintImpl::Unknown( + Ok(IslConstraintValue::Unknown( constraint_name.to_string(), value.to_owned(), )) } - IslVersion::V2_0 => Ok(IslConstraintImpl::Exponent(I64Range::from_ion_element( + IslVersion::V2_0 => Ok(IslConstraintValue::Exponent(I64Range::from_ion_element( value, Element::as_i64, )?)), @@ -901,17 +875,17 @@ impl IslConstraintImpl { )) } }; - Ok(IslConstraintImpl::TimestampOffset( + Ok(IslConstraintValue::TimestampOffset( IslTimestampOffsetConstraint::new(valid_offsets), )) } - "utf8_byte_length" => Ok(IslConstraintImpl::Utf8ByteLength( + "utf8_byte_length" => Ok(IslConstraintValue::Utf8ByteLength( UsizeRange::from_ion_element(value, Element::as_usize)?, )), - "valid_values" => Ok(IslConstraintImpl::ValidValues( + "valid_values" => Ok(IslConstraintValue::ValidValues( IslValidValuesConstraint::from_ion_element(value, isl_version)?, )), - _ => Ok(IslConstraintImpl::Unknown( + _ => Ok(IslConstraintValue::Unknown( constraint_name.to_string(), value.to_owned(), )), @@ -924,7 +898,7 @@ impl IslConstraintImpl { value: &Element, inline_imported_types: &mut Vec, constraint_name: &str, - ) -> IonSchemaResult> { + ) -> IonSchemaResult> { //TODO: create a method/macro for this ion type check which can be reused if value.is_null() { return invalid_schema_error(format!( @@ -942,8 +916,8 @@ impl IslConstraintImpl { .as_sequence() .unwrap() .elements() - .map(|e| IslTypeRefImpl::from_ion_element(isl_version, e, inline_imported_types)) - .collect::>>() + .map(|e| IslTypeRef::from_ion_element(isl_version, e, inline_imported_types)) + .collect::>>() } // helper method for from_ion_element to get isl fields from given ion element @@ -987,10 +961,10 @@ impl IslConstraintImpl { } } -impl WriteToIsl for IslConstraintImpl { +impl WriteToIsl for IslConstraintValue { fn write_to(&self, writer: &mut W) -> IonSchemaResult<()> { match self { - IslConstraintImpl::AllOf(type_refs) => { + IslConstraintValue::AllOf(type_refs) => { writer.set_field_name("all_of"); writer.step_in(IonType::List)?; for type_ref in type_refs { @@ -998,10 +972,10 @@ impl WriteToIsl for IslConstraintImpl { } writer.step_out()?; } - IslConstraintImpl::Annotations(annotations) => { + IslConstraintValue::Annotations(annotations) => { annotations.write_to(writer)?; } - IslConstraintImpl::AnyOf(type_refs) => { + IslConstraintValue::AnyOf(type_refs) => { writer.set_field_name("any_of"); writer.step_in(IonType::List)?; for type_ref in type_refs { @@ -1009,15 +983,15 @@ impl WriteToIsl for IslConstraintImpl { } writer.step_out()?; } - IslConstraintImpl::ByteLength(range) => { + IslConstraintValue::ByteLength(range) => { writer.set_field_name("byte_length"); range.write_to(writer)?; } - IslConstraintImpl::CodepointLength(range) => { + IslConstraintValue::CodepointLength(range) => { writer.set_field_name("codepoint_length"); range.write_to(writer)?; } - IslConstraintImpl::Contains(elements) => { + IslConstraintValue::Contains(elements) => { writer.set_field_name("contains"); writer.step_in(IonType::List)?; for element in elements { @@ -1025,26 +999,26 @@ impl WriteToIsl for IslConstraintImpl { } writer.step_out()?; } - IslConstraintImpl::ContentClosed => { + IslConstraintValue::ContentClosed => { writer.set_field_name("content"); writer.write_symbol("closed")?; } - IslConstraintImpl::ContainerLength(range) => { + IslConstraintValue::ContainerLength(range) => { writer.set_field_name("container_length"); range.write_to(writer)?; } - IslConstraintImpl::Element(type_ref, is_distinct) => { + IslConstraintValue::Element(type_ref, is_distinct) => { writer.set_field_name("element"); if *is_distinct { writer.set_annotations(["distinct"]); } type_ref.write_to(writer)?; } - IslConstraintImpl::Exponent(range) => { + IslConstraintValue::Exponent(range) => { writer.set_field_name("exponent"); range.write_to(writer)?; } - IslConstraintImpl::Fields(fields, content_closed) => { + IslConstraintValue::Fields(fields, content_closed) => { writer.set_field_name("fields"); if *content_closed { writer.set_annotations(["closed"]); @@ -1056,22 +1030,22 @@ impl WriteToIsl for IslConstraintImpl { } writer.step_out()?; } - IslConstraintImpl::FieldNames(type_ref, is_distinct) => { + IslConstraintValue::FieldNames(type_ref, is_distinct) => { writer.set_field_name("field_names"); if *is_distinct { writer.set_annotations(["distinct"]); } type_ref.write_to(writer)?; } - IslConstraintImpl::Ieee754Float(format) => { + IslConstraintValue::Ieee754Float(format) => { writer.set_field_name("ieee754_float"); format.write_to(writer)?; } - IslConstraintImpl::Not(type_ref) => { + IslConstraintValue::Not(type_ref) => { writer.set_field_name("not"); type_ref.write_to(writer)?; } - IslConstraintImpl::OneOf(type_refs) => { + IslConstraintValue::OneOf(type_refs) => { writer.set_field_name("one_of"); writer.step_in(IonType::List)?; for type_ref in type_refs { @@ -1079,7 +1053,7 @@ impl WriteToIsl for IslConstraintImpl { } writer.step_out()?; } - IslConstraintImpl::OrderedElements(type_refs) => { + IslConstraintValue::OrderedElements(type_refs) => { writer.set_field_name("ordered_elements"); writer.step_in(IonType::List)?; for type_ref in type_refs { @@ -1087,37 +1061,37 @@ impl WriteToIsl for IslConstraintImpl { } writer.step_out()?; } - IslConstraintImpl::Precision(range) => { + IslConstraintValue::Precision(range) => { writer.set_field_name("precision"); range.write_to(writer)?; } - IslConstraintImpl::Regex(regex) => { + IslConstraintValue::Regex(regex) => { regex.write_to(writer)?; } - IslConstraintImpl::Scale(range) => { + IslConstraintValue::Scale(range) => { writer.set_field_name("scale"); range.write_to(writer)?; } - IslConstraintImpl::TimestampOffset(timestamp_offset) => { + IslConstraintValue::TimestampOffset(timestamp_offset) => { timestamp_offset.write_to(writer)?; } - IslConstraintImpl::TimestampPrecision(range) => { + IslConstraintValue::TimestampPrecision(range) => { writer.set_field_name("timestamp_precision"); range.write_to(writer)?; } - IslConstraintImpl::Type(type_ref) => { + IslConstraintValue::Type(type_ref) => { writer.set_field_name("type"); type_ref.write_to(writer)?; } - IslConstraintImpl::Unknown(field_name, value) => { + IslConstraintValue::Unknown(field_name, value) => { writer.set_field_name(field_name); writer.write_element(value)?; } - IslConstraintImpl::Utf8ByteLength(range) => { + IslConstraintValue::Utf8ByteLength(range) => { writer.set_field_name("utf8_byte_length"); range.write_to(writer)?; } - IslConstraintImpl::ValidValues(valid_values) => { + IslConstraintValue::ValidValues(valid_values) => { writer.set_field_name("valid_values"); writer.step_in(IonType::List)?; for valid_value in &valid_values.valid_values { @@ -1134,9 +1108,9 @@ impl WriteToIsl for IslConstraintImpl { /// /// [annotations]: https://amazon-ion.github.io/ion-schema/docs/isl-1-0/spec#annotations #[derive(Debug, Clone, PartialEq)] -pub(crate) enum IslAnnotationsConstraint { +pub enum IslAnnotationsConstraint { SimpleAnnotations(IslSimpleAnnotationsConstraint), - StandardAnnotations(IslTypeRefImpl), + StandardAnnotations(IslTypeRef), } impl WriteToIsl for IslAnnotationsConstraint { @@ -1241,7 +1215,7 @@ impl IslSimpleAnnotationsConstraint { )) } - pub(crate) fn convert_to_type_reference(&self) -> IonSchemaResult { + pub(crate) fn convert_to_type_reference(&self) -> IonSchemaResult { let mut isl_constraints = vec![]; if self.is_closed { isl_constraints.push(isl::isl_constraint::v_2_0::element( @@ -1266,7 +1240,9 @@ impl IslSimpleAnnotationsConstraint { )) } - Ok(isl::isl_type_reference::v_2_0::anonymous_type_ref(isl_constraints).type_reference) + Ok(isl::isl_type_reference::v_2_0::anonymous_type_ref( + isl_constraints, + )) } } diff --git a/ion-schema/src/isl/isl_type.rs b/ion-schema/src/isl/isl_type.rs index b7ffb73..54a3f23 100644 --- a/ion-schema/src/isl/isl_type.rs +++ b/ion-schema/src/isl/isl_type.rs @@ -1,4 +1,4 @@ -use crate::isl::isl_constraint::{IslConstraint, IslConstraintImpl}; +use crate::isl::isl_constraint::{IslConstraint, IslConstraintValue}; use crate::isl::isl_import::IslImportType; use crate::isl::IslVersion; use crate::isl::WriteToIsl; @@ -8,8 +8,8 @@ use ion_rs::{IonType, IonWriter}; /// Provides public facing APIs for constructing ISL types programmatically for ISL 1.0 pub mod v_1_0 { - use crate::isl::isl_constraint::{IslConstraint, IslConstraintImpl}; - use crate::isl::isl_type::{IslType, IslTypeImpl}; + use crate::isl::isl_constraint::{IslConstraint, IslConstraintValue}; + use crate::isl::isl_type::IslType; /// Creates a named [IslType] using the [IslConstraint] defined within it pub fn named_type, B: Into>>( @@ -17,24 +17,17 @@ pub mod v_1_0 { constraints: B, ) -> IslType { let constraints = constraints.into(); - let isl_constraints: Vec = constraints - .iter() - .map(|c| c.constraint.to_owned()) - .collect(); - IslType::new( - IslTypeImpl::new(Some(name.into()), isl_constraints, None), - constraints, - ) + IslType::new(Some(name.into()), constraints, None) } /// Creates an anonymous [IslType] using the [IslConstraint] defined within it pub fn anonymous_type>>(constraints: A) -> IslType { let constraints = constraints.into(); - let isl_constraints: Vec = constraints + let isl_constraints: Vec = constraints .iter() - .map(|c| c.constraint.to_owned()) + .map(|c| c.constraint_value.to_owned()) .collect(); - IslType::new(IslTypeImpl::new(None, isl_constraints, None), constraints) + IslType::new(None, constraints, None) } } @@ -57,54 +50,22 @@ pub mod v_2_0 { } } -/// Represents a type in an ISL schema. -#[derive(Debug, Clone, PartialEq)] -pub struct IslType { - pub(crate) type_definition: IslTypeImpl, - constraints: Vec, -} - -impl IslType { - pub(crate) fn new(type_definition: IslTypeImpl, constraints: Vec) -> Self { - Self { - type_definition, - constraints, - } - } - - /// Provides a name if the ISL type is named type definition - /// Otherwise returns None - pub fn name(&self) -> &Option { - self.type_definition.name() - } - - /// Provides open content that is there in the type definition - pub fn open_content(&self) -> Vec<(String, Element)> { - self.type_definition.open_content() - } - - /// Provides the underlying constraints of [IslType] - pub fn constraints(&self) -> &[IslConstraint] { - &self.constraints - } -} - /// Represents both named and anonymous [IslType]s and can be converted to a resolved type definition /// Named ISL type grammar: `type:: { name: , ...}` /// Anonymous ISL type grammar: `{ ... }` #[derive(Debug, Clone)] -pub(crate) struct IslTypeImpl { +pub struct IslType { name: Option, - constraints: Vec, + constraints: Vec, // Represents the ISL type struct in string format for anonymous type definition // For named type definition & programmatically created type definition, this will be `None` pub(crate) isl_type_struct: Option, } -impl IslTypeImpl { - pub fn new( +impl IslType { + pub(crate) fn new( name: Option, - constraints: Vec, + constraints: Vec, isl_type_struct: Option, ) -> Self { Self { @@ -118,14 +79,16 @@ impl IslTypeImpl { &self.name } - pub fn constraints(&self) -> &[IslConstraintImpl] { + pub fn constraints(&self) -> &[IslConstraint] { &self.constraints } pub fn open_content(&self) -> Vec<(String, Element)> { let mut open_content = vec![]; for constraint in &self.constraints { - if let IslConstraintImpl::Unknown(constraint_name, element) = constraint { + if let IslConstraintValue::Unknown(constraint_name, element) = + &constraint.constraint_value + { open_content.push((constraint_name.to_owned(), element.to_owned())) } } @@ -134,14 +97,17 @@ impl IslTypeImpl { pub(crate) fn is_open_content_allowed(&self) -> bool { let mut open_content = true; - if self.constraints.contains(&IslConstraintImpl::ContentClosed) { + if self.constraints.contains(&IslConstraint::new( + IslVersion::V1_0, + IslConstraintValue::ContentClosed, + )) { open_content = false; } open_content } - /// Parse constraints inside an [Element] to an [IslTypeImpl] - pub fn from_owned_element( + /// Parse constraints inside an [Element] to an [IslType] + pub(crate) fn from_owned_element( isl_version: IslVersion, ion: &Element, inline_imported_types: &mut Vec, // stores the inline_imports that are discovered while loading this ISL type @@ -209,24 +175,23 @@ impl IslTypeImpl { } }; - let constraint = IslConstraintImpl::from_ion_element( + let constraint = IslConstraint::new( isl_version, - constraint_name, - value, - &isl_type_name, - inline_imported_types, - )?; + IslConstraintValue::from_ion_element( + isl_version, + constraint_name, + value, + &isl_type_name, + inline_imported_types, + )?, + ); constraints.push(constraint); } - Ok(IslTypeImpl::new( - type_name, - constraints, - Some(ion.to_owned()), - )) + Ok(IslType::new(type_name, constraints, Some(ion.to_owned()))) } } -impl WriteToIsl for IslTypeImpl { +impl WriteToIsl for IslType { fn write_to(&self, writer: &mut W) -> IonSchemaResult<()> { writer.set_annotations(["type"]); writer.step_in(IonType::Struct)?; @@ -239,7 +204,7 @@ impl WriteToIsl for IslTypeImpl { "Top level type definitions must contain a `name` field", ))?; for constraint in self.constraints() { - constraint.write_to(writer)?; + constraint.constraint_value.write_to(writer)?; } writer.step_out()?; Ok(()) @@ -248,7 +213,7 @@ impl WriteToIsl for IslTypeImpl { // OwnedStruct doesn't preserve field order hence the PartialEq won't work properly for unordered constraints // Related issue: https://github.com/amazon-ion/ion-rust/issues/200 -impl PartialEq for IslTypeImpl { +impl PartialEq for IslType { fn eq(&self, other: &Self) -> bool { self.constraints.len() == other.constraints.len() && self.name == other.name diff --git a/ion-schema/src/isl/isl_type_reference.rs b/ion-schema/src/isl/isl_type_reference.rs index 89dec2f..c4eab76 100644 --- a/ion-schema/src/isl/isl_type_reference.rs +++ b/ion-schema/src/isl/isl_type_reference.rs @@ -1,6 +1,6 @@ use crate::ion_extension::ElementExtensions; use crate::isl::isl_import::{IslImport, IslImportType}; -use crate::isl::isl_type::IslTypeImpl; +use crate::isl::isl_type::IslType; use crate::isl::ranges::{Limit, UsizeRange}; use crate::isl::IslVersion; use crate::isl::WriteToIsl; @@ -16,41 +16,31 @@ use ion_rs::{IonType, IonWriter}; /// Provides public facing APIs for constructing ISL type references programmatically for ISL 1.0 pub mod v_1_0 { - use crate::isl::isl_constraint::{IslConstraint, IslConstraintImpl}; - use crate::isl::isl_type::IslTypeImpl; + use crate::isl::isl_constraint::IslConstraint; + use crate::isl::isl_type::IslType; use crate::isl::isl_type_reference::{ - IslTypeRef, IslTypeRefImpl, IslVariablyOccurringTypeRef, NullabilityModifier, + IslTypeRef, IslVariablyOccurringTypeRef, NullabilityModifier, }; use crate::isl::ranges::UsizeRange; use ion_rs::IonType; /// Creates a named [IslTypeRef] using the name of the type referenced inside it pub fn named_type_ref>(name: A) -> IslTypeRef { - IslTypeRef::new(IslTypeRefImpl::Named( - name.into(), - NullabilityModifier::Nothing, - )) + IslTypeRef::Named(name.into(), NullabilityModifier::Nothing) } /// Creates a nullable [IslTypeRef] using the [IonType] referenced inside it pub fn nullable_built_in_type_ref(name: IonType) -> IslTypeRef { - IslTypeRef::new(IslTypeRefImpl::Named( - format!("{name}"), - NullabilityModifier::Nullable, - )) + IslTypeRef::Named(format!("{name}"), NullabilityModifier::Nullable) } /// Creates an anonymous [IslTypeRef] using the [IslConstraint]s referenced inside it pub fn anonymous_type_ref>>(constraints: A) -> IslTypeRef { let constraints = constraints.into(); - let isl_constraints: Vec = constraints - .iter() - .map(|c| c.constraint.to_owned()) - .collect(); - IslTypeRef::new(IslTypeRefImpl::Anonymous( - IslTypeImpl::new(None, isl_constraints, None), + IslTypeRef::Anonymous( + IslType::new(None, constraints, None), NullabilityModifier::Nothing, - )) + ) } /// Creates an [IslVariablyOccurringTypeRef] using the [IslConstraint]s and [Range] referenced inside it @@ -66,7 +56,7 @@ pub mod v_1_0 { pub mod v_2_0 { use crate::isl::isl_constraint::IslConstraint; use crate::isl::isl_type_reference::{ - v_1_0, IslTypeRef, IslTypeRefImpl, IslVariablyOccurringTypeRef, NullabilityModifier, + v_1_0, IslTypeRef, IslVariablyOccurringTypeRef, NullabilityModifier, }; use crate::isl::ranges::UsizeRange; @@ -77,10 +67,7 @@ pub mod v_2_0 { /// Creates a nullable [IslTypeRef] using the name of the type referenced inside it pub fn null_or_named_type_ref>(name: A) -> IslTypeRef { - IslTypeRef::new(IslTypeRefImpl::Named( - name.into(), - NullabilityModifier::NullOr, - )) + IslTypeRef::Named(name.into(), NullabilityModifier::NullOr) } /// Creates an anonymous [IslTypeRef] using the [IslConstraint]s referenced inside it @@ -97,21 +84,6 @@ pub mod v_2_0 { } } -/// Provides an internal representation of a schema type reference. -/// The type reference grammar is defined in the [Ion Schema Spec] -/// -/// [Ion Schema spec]: https://amazon-ion.github.io/ion-schema/docs/isl-1-0/spec#grammar -#[derive(Debug, Clone, PartialEq)] -pub struct IslTypeRef { - pub(crate) type_reference: IslTypeRefImpl, -} - -impl IslTypeRef { - pub(crate) fn new(type_reference: IslTypeRefImpl) -> Self { - Self { type_reference } - } -} - #[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] pub enum NullabilityModifier { Nullable, @@ -134,17 +106,21 @@ impl WriteToIsl for NullabilityModifier { } } +/// Provides an internal representation of a schema type reference. +/// The type reference grammar is defined in the [Ion Schema Spec] +/// +/// [Ion Schema spec]: https://amazon-ion.github.io/ion-schema/docs/isl-1-0/spec#grammar #[derive(Debug, Clone, PartialEq)] -pub(crate) enum IslTypeRefImpl { +pub enum IslTypeRef { /// Represents a reference to a named type (including aliases and built-in types) Named(String, NullabilityModifier), /// Represents a type reference defined as an inlined import of a type from another schema TypeImport(IslImportType, NullabilityModifier), /// represents an unnamed type definition reference - Anonymous(IslTypeImpl, NullabilityModifier), + Anonymous(IslType, NullabilityModifier), } -impl IslTypeRefImpl { +impl IslTypeRef { fn from_ion_element_with_occurs_flag( isl_version: IslVersion, value: &Element, @@ -193,7 +169,7 @@ impl IslTypeRefImpl { // TODO: currently it only allows for built in types (other than `document`) to be defined with `nullable` annotation. For `document` and all other type references it returns an error. "int" | "float" | "bool" | "decimal" | "string" | "symbol" | "blob" | "clob" | "timestamp" | "struct" | "sexp" | "list" | "text" | "lob" | "number" | "any" | "nothing" | "$null" | "$int" | "$float" | "$bool" | "$decimal" | "$string" | "$symbol" | "$blob" | "$clob" | "$timestamp" | "$struct" | "$sexp" | "$list" | "$text" | "$lob" | "$number" | "$any" => { - Ok(IslTypeRefImpl::Named(type_name.to_owned(), Nullable)) + Ok(IslTypeRef::Named(type_name.to_owned(), Nullable)) } _ => { invalid_schema_error( @@ -203,7 +179,7 @@ impl IslTypeRefImpl { } } - Ok(IslTypeRefImpl::Named(type_name.to_owned(), nullability)) + Ok(IslTypeRef::Named(type_name.to_owned(), nullability)) } IonType::Struct => { if value.is_null() { @@ -223,7 +199,7 @@ impl IslTypeRefImpl { let value_struct = try_to!(value.as_struct()); // if the struct doesn't have an id field then it must be an anonymous type if value_struct.get("id").is_none() { - let type_def= IslTypeImpl::from_owned_element(isl_version, value, inline_imported_types)?; + let type_def= IslType::from_owned_element(isl_version, value, inline_imported_types)?; // if type reference contains `occurs` field and has modifier `$null_or` then return an error if nullability == NullOr && value_struct.get("occurs").is_some() { return invalid_schema_error( @@ -243,7 +219,7 @@ impl IslTypeRefImpl { } } - return Ok(IslTypeRefImpl::Anonymous(type_def, nullability)) + return Ok(IslTypeRef::Anonymous(type_def, nullability)) } // if it is an inline import type store it as import type reference let isl_import_type = match IslImport::from_ion_element(value)? { @@ -262,7 +238,7 @@ impl IslTypeRefImpl { // if an inline import type is encountered add it in the inline_imports_types // this will help resolve these inline imports before we start loading the schema types that uses them as reference inline_imported_types.push(isl_import_type.to_owned()); - Ok(IslTypeRefImpl::TypeImport(isl_import_type, nullability)) + Ok(IslTypeRef::TypeImport(isl_import_type, nullability)) }, _ => Err(invalid_schema_error_raw( "type reference can either be a symbol(For base/alias type reference) or a struct (for anonymous type reference)", @@ -270,13 +246,20 @@ impl IslTypeRefImpl { } } + pub fn name(&self) -> String { + match self { + IslTypeRef::Named(name, _) => name.to_string(), + IslTypeRef::TypeImport(import_type, _) => import_type.type_name().to_string(), + IslTypeRef::Anonymous(anonymous_type, _) => "".to_string(), + } + } /// Tries to create an [IslTypeRef] from the given Element - pub fn from_ion_element( + pub(crate) fn from_ion_element( isl_version: IslVersion, value: &Element, inline_imported_types: &mut Vec, ) -> IonSchemaResult { - IslTypeRefImpl::from_ion_element_with_occurs_flag( + IslTypeRef::from_ion_element_with_occurs_flag( isl_version, value, inline_imported_types, @@ -314,18 +297,18 @@ impl IslTypeRefImpl { // TODO: break match arms into helper methods as we add more constraints /// Resolves a type_reference into a [TypeId] using the type_store - pub fn resolve_type_reference( + pub(crate) fn resolve_type_reference( isl_version: IslVersion, - type_reference: &IslTypeRefImpl, + type_reference: &IslTypeRef, type_store: &mut TypeStore, pending_types: &mut PendingTypes, ) -> IonSchemaResult { match type_reference { - IslTypeRefImpl::Named(alias, type_ref_modifier) => Ok(TypeReference::new( - IslTypeRefImpl::get_type_id_from_type_name(alias, type_store, pending_types)?, + IslTypeRef::Named(alias, type_ref_modifier) => Ok(TypeReference::new( + IslTypeRef::get_type_id_from_type_name(alias, type_store, pending_types)?, type_ref_modifier.to_owned(), )), - IslTypeRefImpl::Anonymous(isl_type, type_ref_modifier) => { + IslTypeRef::Anonymous(isl_type, type_ref_modifier) => { let type_id = pending_types.get_total_types(type_store); let type_def = TypeDefinitionImpl::parse_from_isl_type_and_update_pending_types( isl_version, @@ -336,7 +319,7 @@ impl IslTypeRefImpl { // get the last added anonymous type's type_id for given anonymous type Ok(TypeReference::new(type_id, type_ref_modifier.to_owned())) } - IslTypeRefImpl::TypeImport(isl_import_type, type_ref_modifier) => { + IslTypeRef::TypeImport(isl_import_type, type_ref_modifier) => { // verify if the inline import type already exists in the type_store match type_store .get_defined_type_id_or_imported_type_id_by_name(isl_import_type.type_name()) @@ -352,24 +335,24 @@ impl IslTypeRefImpl { } } -impl WriteToIsl for IslTypeRefImpl { +impl WriteToIsl for IslTypeRef { fn write_to(&self, writer: &mut W) -> IonSchemaResult<()> { match self { - IslTypeRefImpl::Named(name, nullability_modifier) => { + IslTypeRef::Named(name, nullability_modifier) => { nullability_modifier.write_to(writer)?; writer.write_symbol(name)?; } - IslTypeRefImpl::TypeImport(type_import, nullability_modifier) => { + IslTypeRef::TypeImport(type_import, nullability_modifier) => { nullability_modifier.write_to(writer)?; writer.step_in(IonType::Struct)?; type_import.write_to(writer)?; writer.step_out()?; } - IslTypeRefImpl::Anonymous(type_def, nullability_modifier) => { + IslTypeRef::Anonymous(type_def, nullability_modifier) => { nullability_modifier.write_to(writer)?; writer.step_in(IonType::Struct)?; for constraint in type_def.constraints() { - constraint.write_to(writer)?; + constraint.constraint_value.write_to(writer)?; } writer.step_out()?; } @@ -393,28 +376,33 @@ impl WriteToIsl for IslTypeRefImpl { /// [variably occurring type reference]: https://amazon-ion.github.io/ion-schema/docs/isl-2-0/spec#variably-occurring-type-arguments #[derive(Debug, Clone, PartialEq)] pub struct IslVariablyOccurringTypeRef { - type_ref: IslTypeRefImpl, + pub(crate) type_ref: IslTypeRef, occurs: UsizeRange, } impl IslVariablyOccurringTypeRef { pub(crate) fn new(type_ref: IslTypeRef, occurs: UsizeRange) -> Self { - Self { - type_ref: type_ref.type_reference, - occurs, - } + Self { type_ref, occurs } + } + + pub fn type_reference(&self) -> &IslTypeRef { + &self.type_ref + } + + pub fn name(&self) -> String { + self.type_ref.name() } pub fn optional(type_ref: IslTypeRef) -> Self { Self { - type_ref: type_ref.type_reference, + type_ref, occurs: UsizeRange::zero_or_one(), } } pub fn required(type_ref: IslTypeRef) -> Self { Self { - type_ref: type_ref.type_reference, + type_ref, occurs: UsizeRange::new_single_value(1), } } @@ -424,13 +412,13 @@ impl IslVariablyOccurringTypeRef { } /// Tries to create an [IslVariablyOccurringTypeRef] from the given Element - pub fn from_ion_element( + pub(crate) fn from_ion_element( constraint_name: &str, isl_version: IslVersion, value: &Element, inline_imported_types: &mut Vec, ) -> IonSchemaResult { - let type_ref = IslTypeRefImpl::from_ion_element_with_occurs_flag( + let type_ref = IslTypeRef::from_ion_element_with_occurs_flag( isl_version, value, inline_imported_types, @@ -470,13 +458,13 @@ impl IslVariablyOccurringTypeRef { } /// Resolves an [IslVariablyOccurringTypeRef] into a [VariablyOccurringTypeRef] using the type_store - pub fn resolve_type_reference( + pub(crate) fn resolve_type_reference( &self, isl_version: IslVersion, type_store: &mut TypeStore, pending_types: &mut PendingTypes, ) -> IonSchemaResult { - let type_ref = IslTypeRefImpl::resolve_type_reference( + let type_ref = IslTypeRef::resolve_type_reference( isl_version, &self.type_ref, type_store, @@ -490,11 +478,11 @@ impl IslVariablyOccurringTypeRef { impl WriteToIsl for IslVariablyOccurringTypeRef { fn write_to(&self, writer: &mut W) -> IonSchemaResult<()> { match &self.type_ref { - IslTypeRefImpl::Named(name, nullability_modifier) => { + IslTypeRef::Named(name, nullability_modifier) => { nullability_modifier.write_to(writer)?; writer.write_symbol(name)?; } - IslTypeRefImpl::TypeImport(type_import, nullability_modifier) => { + IslTypeRef::TypeImport(type_import, nullability_modifier) => { nullability_modifier.write_to(writer)?; writer.step_in(IonType::Struct)?; type_import.write_to(writer)?; @@ -502,11 +490,11 @@ impl WriteToIsl for IslVariablyOccurringTypeRef { self.occurs.write_to(writer)?; writer.step_out()?; } - IslTypeRefImpl::Anonymous(type_def, nullability_modifier) => { + IslTypeRef::Anonymous(type_def, nullability_modifier) => { nullability_modifier.write_to(writer)?; writer.step_in(IonType::Struct)?; for constraint in type_def.constraints() { - constraint.write_to(writer)?; + constraint.constraint_value.write_to(writer)?; } writer.set_field_name("occurs"); self.occurs.write_to(writer)?; diff --git a/ion-schema/src/isl/mod.rs b/ion-schema/src/isl/mod.rs index 35d477d..6435c3b 100644 --- a/ion-schema/src/isl/mod.rs +++ b/ion-schema/src/isl/mod.rs @@ -19,8 +19,10 @@ //! //! ## Example usage of `isl` module to create an `IslSchema` using `IslType`: //! ``` -//! use ion_schema::isl::{isl_type::v_1_0::*, isl_constraint::v_1_0::*, isl_type_reference::v_1_0::*, IslSchema}; -//! use ion_schema::schema::Schema; +//! use ion_schema::isl::isl_constraint::v_1_0::{all_of, type_constraint}; +//! use ion_schema::isl::isl_type::v_1_0::named_type; +//! use ion_schema::isl::isl_type_reference::v_1_0::{anonymous_type_ref, named_type_ref}; +//! use ion_schema::isl::IslSchema; //! use ion_schema::system::SchemaSystem; //! //! // below code represents an ISL type: @@ -179,10 +181,60 @@ pub trait WriteToIsl { /// Provides an internal representation of an schema file #[derive(Debug, Clone, PartialEq)] pub struct IslSchema { - pub(crate) schema: IslSchemaImpl, + /// Represents an id for the given ISL model + id: String, + /// Represents the ISL version for given schema + version: IslVersion, + /// Represents the user defined reserved fields + /// For ISL 2.0 this contains the use reserved fields that are defined within schema header, + /// Otherwise, it is None. + user_reserved_fields: Option, + /// Represents all the IslImports inside the schema file. + /// For more information: https://amazon-ion.github.io/ion-schema/docs/isl-1-0/spec#imports + imports: Vec, + /// Represents all the IslType defined in this schema file. + /// For more information: https://amazon-ion.github.io/ion-schema/docs/isl-1-0/spec#type-definitions + types: Vec, + /// Represents all the inline IslImportTypes in this schema file. + inline_imported_types: Vec, + /// Represents open content as `Element`s + /// Note: This doesn't preserve the information about where the open content is placed in the schema file. + /// e.g. This method doesn't differentiate between following schemas with open content: + /// ```ion + /// $foo + /// $bar + /// type::{ name: foo, codepoint_length: 1 } + /// ``` + /// + /// ```ion + /// type::{ name: foo, codepoint_length: 1 } + /// $foo + /// $bar + /// ``` + open_content: Vec, } impl IslSchema { + pub(crate) fn new>( + id: A, + version: IslVersion, + user_reserved_fields: Option, + imports: Vec, + types: Vec, + inline_imports: Vec, + open_content: Vec, + ) -> Self { + Self { + id: id.as_ref().to_owned(), + version, + user_reserved_fields, + imports, + types, + inline_imported_types: inline_imports, + open_content, + } + } + /// Creates an ISL schema using the [IslType]s, [IslImport]s, open content and schema id pub fn schema_v_1_0>( id: A, @@ -191,17 +243,15 @@ impl IslSchema { inline_imports: Vec, open_content: Vec, ) -> IslSchema { - IslSchema { - schema: IslSchemaImpl::new( - id.as_ref(), - IslVersion::V1_0, - None, - imports, - types, - inline_imports, - open_content, - ), - } + IslSchema::new( + id.as_ref(), + IslVersion::V1_0, + None, + imports, + types, + inline_imports, + open_content, + ) } /// Creates an ISL schema using the [IslType]s, [IslImport]s, [UserReservedFields] open content and schema id @@ -213,63 +263,61 @@ impl IslSchema { inline_imports: Vec, open_content: Vec, ) -> IslSchema { - IslSchema { - schema: IslSchemaImpl::new( - id.as_ref(), - IslVersion::V2_0, - Some(user_reserved_fields), - imports, - types, - inline_imports, - open_content, - ), - } + IslSchema::new( + id.as_ref(), + IslVersion::V2_0, + Some(user_reserved_fields), + imports, + types, + inline_imports, + open_content, + ) } pub fn id(&self) -> String { - self.schema.id.to_owned() + self.id.to_owned() } pub fn version(&self) -> IslVersion { - self.schema.version + self.version } pub fn imports(&self) -> &[IslImport] { - &self.schema.imports + &self.imports } pub fn types(&self) -> &[IslType] { - &self.schema.types + &self.types } pub fn inline_imported_types(&self) -> &[IslImportType] { - &self.schema.inline_imported_types + &self.inline_imported_types } /// Provides top level open content for given schema /// For open content defined within type definitions use IslType#open_content() pub fn open_content(&self) -> &Vec { - &self.schema.open_content + &self.open_content } /// Provide user reserved field defined in the given schema for ISL 2.0, /// Otherwise returns None pub fn user_reserved_fields(&self) -> Option<&UserReservedFields> { - self.schema.user_reserved_fields.as_ref() + self.user_reserved_fields.as_ref() } fn write_header(&self, writer: &mut W) -> IonSchemaResult<()> { writer.set_annotations(["schema_header"]); writer.step_in(IonType::Struct)?; - if !self.schema.imports.is_empty() { + if !self.imports.is_empty() { writer.set_field_name("imports"); writer.step_in(IonType::List)?; - for import in &self.schema.imports { + for import in &self.imports { import.write_to(writer)?; } writer.step_out()?; } - if let Some(user_reserved_fields) = &self.schema.user_reserved_fields { + if let Some(user_reserved_fields) = &self.user_reserved_fields { user_reserved_fields.write_to(writer)?; } writer.step_out()?; @@ -280,7 +328,7 @@ impl IslSchema { impl WriteToIsl for IslSchema { fn write_to(&self, writer: &mut W) -> IonSchemaResult<()> { - let version = self.schema.version; + let version = self.version; // write the version marker for given schema match version { IslVersion::V1_0 => { @@ -291,11 +339,11 @@ impl WriteToIsl for IslSchema { } } self.write_header(writer)?; - for isl_type in &self.schema.types { - isl_type.type_definition.write_to(writer)?; + for isl_type in &self.types { + isl_type.write_to(writer)?; } // write open content at the end of the schema - for value in &self.schema.open_content { + for value in &self.open_content { writer.write_element(value)?; } @@ -308,71 +356,13 @@ impl WriteToIsl for IslSchema { } } -#[derive(Debug, Clone, PartialEq)] -pub(crate) struct IslSchemaImpl { - /// Represents an id for the given ISL model - id: String, - /// Represents the ISL version for given schema - version: IslVersion, - /// Represents the user defined reserved fields - /// For ISL 2.0 this contains the use reserved fields that are defined within schema header, - /// Otherwise, it is None. - user_reserved_fields: Option, - /// Represents all the IslImports inside the schema file. - /// For more information: https://amazon-ion.github.io/ion-schema/docs/isl-1-0/spec#imports - imports: Vec, - /// Represents all the IslType defined in this schema file. - /// For more information: https://amazon-ion.github.io/ion-schema/docs/isl-1-0/spec#type-definitions - types: Vec, - /// Represents all the inline IslImportTypes in this schema file. - inline_imported_types: Vec, - /// Represents open content as `Element`s - /// Note: This doesn't preserve the information about where the open content is placed in the schema file. - /// e.g. This method doesn't differentiate between following schemas with open content: - /// ```ion - /// $foo - /// $bar - /// type::{ name: foo, codepoint_length: 1 } - /// ``` - /// - /// ```ion - /// type::{ name: foo, codepoint_length: 1 } - /// $foo - /// $bar - /// ``` - open_content: Vec, -} - -impl IslSchemaImpl { - pub fn new>( - id: A, - version: IslVersion, - user_reserved_fields: Option, - imports: Vec, - types: Vec, - inline_imports: Vec, - open_content: Vec, - ) -> Self { - Self { - id: id.as_ref().to_owned(), - version, - user_reserved_fields, - imports, - types, - inline_imported_types: inline_imports, - open_content, - } - } -} - #[cfg(test)] mod isl_tests { use crate::authority::FileSystemDocumentAuthority; use crate::ion_extension::ElementExtensions; use crate::isl::isl_constraint::v_1_0::*; - use crate::isl::isl_constraint::IslConstraint; use crate::isl::isl_type::v_1_0::*; - use crate::isl::isl_type::{IslType, IslTypeImpl}; + use crate::isl::isl_type::IslType; use crate::isl::isl_type_reference::v_1_0::*; use crate::isl::ranges::*; use crate::isl::util::Ieee754InterchangeFormat; @@ -384,58 +374,41 @@ mod isl_tests { use crate::system::SchemaSystem; use ion_rs::element::Element; use ion_rs::types::Decimal; + use ion_rs::IonType; use ion_rs::Symbol; - use ion_rs::{IonType, TextWriterBuilder}; + use ion_rs::TextWriterBuilder; use rstest::*; use std::path::Path; use test_generator::test_resources; // helper function to create NamedIslType for isl tests using ISL 1.0 fn load_named_type(text: &str) -> IslType { - let type_def = IslTypeImpl::from_owned_element( + IslType::from_owned_element( IslVersion::V1_0, &Element::read_one(text.as_bytes()).expect("parsing failed unexpectedly"), &mut vec![], ) - .unwrap(); - let constraints = type_def - .constraints() - .iter() - .map(|c| IslConstraint::new(IslVersion::V1_0, c.to_owned())) - .collect(); - IslType::new(type_def, constraints) + .unwrap() } // helper function to create AnonymousIslType for isl tests using ISL 1.0 fn load_anonymous_type(text: &str) -> IslType { - let type_def = IslTypeImpl::from_owned_element( + IslType::from_owned_element( IslVersion::V1_0, &Element::read_one(text.as_bytes()).expect("parsing failed unexpectedly"), &mut vec![], ) - .unwrap(); - let constraints = type_def - .constraints() - .iter() - .map(|c| IslConstraint::new(IslVersion::V1_0, c.to_owned())) - .collect(); - IslType::new(type_def, constraints) + .unwrap() } // helper function to create AnonymousIslType for isl tests using ISL 2.0 fn load_anonymous_type_v2_0(text: &str) -> IslType { - let type_def = IslTypeImpl::from_owned_element( + IslType::from_owned_element( IslVersion::V2_0, &Element::read_one(text.as_bytes()).expect("parsing failed unexpectedly"), &mut vec![], ) - .unwrap(); - let constraints = type_def - .constraints() - .iter() - .map(|c| IslConstraint::new(IslVersion::V2_0, c.to_owned())) - .collect(); - IslType::new(type_def, constraints) + .unwrap() } #[test] diff --git a/ion-schema/src/lib.rs b/ion-schema/src/lib.rs index 3af1bd7..f4e35b2 100644 --- a/ion-schema/src/lib.rs +++ b/ion-schema/src/lib.rs @@ -3,8 +3,8 @@ use crate::external::ion_rs::IonType; use crate::ion_path::IonPath; -use crate::isl::isl_constraint::IslConstraintImpl; -use crate::isl::isl_type::IslTypeImpl; +use crate::isl::isl_constraint::IslConstraintValue; +use crate::isl::isl_type::IslType; use crate::isl::WriteToIsl; use crate::result::{invalid_schema_error, invalid_schema_error_raw, IonSchemaResult}; use crate::violation::{Violation, ViolationCode}; @@ -312,16 +312,13 @@ impl UserReservedFields { Ok(()) } - pub(crate) fn validate_field_names_in_type( - &self, - isl_type: &IslTypeImpl, - ) -> IonSchemaResult<()> { + pub(crate) fn validate_field_names_in_type(&self, isl_type: &IslType) -> IonSchemaResult<()> { let unexpected_fields: &Vec<&String> = &isl_type .constraints() .iter() - .filter(|c| matches!(c, IslConstraintImpl::Unknown(_, _))) - .map(|c| match c { - IslConstraintImpl::Unknown(f, v) => f, + .filter(|c| matches!(c.constraint_value, IslConstraintValue::Unknown(_, _))) + .map(|c| match &c.constraint_value { + IslConstraintValue::Unknown(f, v) => f, _ => { unreachable!("we have already filtered all other constraints") } diff --git a/ion-schema/src/system.rs b/ion-schema/src/system.rs index 2684edf..ff8857b 100644 --- a/ion-schema/src/system.rs +++ b/ion-schema/src/system.rs @@ -20,9 +20,8 @@ //! ``` use crate::authority::DocumentAuthority; -use crate::isl::isl_constraint::IslConstraint; use crate::isl::isl_import::{IslImport, IslImportType}; -use crate::isl::isl_type::{IslType, IslTypeImpl}; +use crate::isl::isl_type::IslType; use crate::isl::{IslSchema, IslVersion}; use crate::result::{ invalid_schema_error, invalid_schema_error_raw, unresolvable_schema_error, @@ -517,7 +516,7 @@ impl TypeStore { // get the derived built in types map and related text value for given type_name [type_ids: 25 - 33] let pending_types = &mut PendingTypes::default(); for text in DERIVED_ISL_TYPES { - let isl_type = IslTypeImpl::from_owned_element( + let isl_type = IslType::from_owned_element( isl_version, &Element::read_one(text.as_bytes()).expect("parsing failed unexpectedly"), &mut vec![], @@ -743,7 +742,7 @@ impl Resolver { TypeDefinitionImpl::parse_from_isl_type_and_update_pending_types( isl_version, - &isl_type.type_definition, + isl_type, &mut type_store, pending_types, )? @@ -872,8 +871,8 @@ impl Resolver { } // convert Element to IslType - let isl_type: IslTypeImpl = - IslTypeImpl::from_owned_element(isl_version, &value, &mut isl_inline_imports)?; + let isl_type: IslType = + IslType::from_owned_element(isl_version, &value, &mut isl_inline_imports)?; if isl_type.name().is_none() { // if a top level type definition doesn't contain `name` field return an error return invalid_schema_error( @@ -892,12 +891,7 @@ impl Resolver { ); } - let constraints = isl_type - .constraints() - .iter() - .map(|c| IslConstraint::new(isl_version, c.to_owned())) - .collect(); - isl_types.push(IslType::new(isl_type, constraints)); + isl_types.push(isl_type); } // load footer for schema else if annotations.contains("schema_footer") { @@ -1028,7 +1022,7 @@ impl Resolver { let type_id: TypeId = TypeDefinitionImpl::parse_from_isl_type_and_update_pending_types( isl_version, - &isl_type.type_definition, + isl_type, type_store, pending_types, )?; diff --git a/ion-schema/src/types.rs b/ion-schema/src/types.rs index 540c830..75ace16 100644 --- a/ion-schema/src/types.rs +++ b/ion-schema/src/types.rs @@ -1,7 +1,7 @@ use crate::constraint::Constraint; use crate::ion_path::IonPath; -use crate::isl::isl_constraint::IslConstraintImpl; -use crate::isl::isl_type::IslTypeImpl; +use crate::isl::isl_constraint::IslConstraintValue; +use crate::isl::isl_type::IslType; use crate::isl::IslVersion; use crate::result::{invalid_schema_error, IonSchemaResult, ValidationResult}; use crate::system::{PendingTypes, TypeId, TypeStore}; @@ -124,7 +124,7 @@ pub(crate) enum Nullability { impl BuiltInTypeDefinition { pub(crate) fn parse_from_isl_type( isl_version: IslVersion, - isl_type: &IslTypeImpl, + isl_type: &IslType, type_store: &mut TypeStore, pending_types: &mut PendingTypes, ) -> IonSchemaResult { @@ -138,7 +138,7 @@ impl BuiltInTypeDefinition { // For built in types, open_content is set as true as Ion Schema by default allows open content let constraint = Constraint::resolve_from_isl_constraint( isl_version, - isl_constraint, + &isl_constraint.constraint_value, type_store, pending_types, true, @@ -442,13 +442,13 @@ impl TypeDefinitionImpl { &self.constraints } - /// Parse constraints inside an [`IslTypeImpl`] to a schema type definition, update the [`PendingTypes`] + /// Parse constraints inside an [`IslType`] to a schema type definition, update the [`PendingTypes`] /// and return its [`TypeId`] if the conversion was successful, otherwise return an [`IonSchemaError`] /// /// [`IonSchemaError`]: crate::result::IonSchemaError pub(crate) fn parse_from_isl_type_and_update_pending_types( isl_version: IslVersion, - isl_type: &IslTypeImpl, + isl_type: &IslType, type_store: &mut TypeStore, pending_types: &mut PendingTypes, ) -> IonSchemaResult { @@ -476,13 +476,13 @@ impl TypeDefinitionImpl { // convert IslConstraint to Constraint let mut found_type_constraint = false; for isl_constraint in isl_type.constraints() { - if let IslConstraintImpl::Type(_) = isl_constraint { + if let IslConstraintValue::Type(_) = isl_constraint.constraint_value { found_type_constraint = true; } let constraint = Constraint::resolve_from_isl_constraint( isl_version, - isl_constraint, + &isl_constraint.constraint_value, type_store, pending_types, isl_type.is_open_content_allowed(), @@ -502,9 +502,9 @@ impl TypeDefinitionImpl { }, }; - let isl_constraint: IslConstraintImpl = + let isl_constraint: IslConstraintValue = // default type for ISL 1.0 is `any` - IslConstraintImpl::from_ion_element( + IslConstraintValue::from_ion_element( isl_version, "type", &Element::symbol(Symbol::from("any")), @@ -872,7 +872,7 @@ mod type_definition_tests { let this_type_def = { let type_id = TypeDefinitionImpl::parse_from_isl_type_and_update_pending_types( IslVersion::V1_0, - &isl_type.type_definition, + &isl_type, type_store, pending_types, )