Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds implementation for WriteToIsl #183

Merged
merged 12 commits into from
Jun 15, 2023
Merged

adds implementation for WriteToIsl #183

merged 12 commits into from
Jun 15, 2023

Conversation

desaikd
Copy link
Contributor

@desaikd desaikd commented Jun 8, 2023

Issue #173

Description of changes:

This PR works on adding implementation of WriteToIsl which serializes a schema model into a schema file using Ion writer.

Example:

Here is a quick example of how to serialize a schema model using Ion writer.

// construct an ISL type programmatically
let isl_type = named_type(
    // represents the `name` of the defined type
    "my_number_type".to_owned(),
    vec![
        // represents `one_of` constraint
        one_of(vec![
            named_type_ref("int"),
            named_type_ref("float"),
            named_type_ref("decimal"),
        ]),
    ],
);

// create an ISL schema using above `isl_type`
let isl_schema = IslSchema::schema_v_1_0(
    "my_schema.isl", // represents schem id which is usually same as the schema file name
    vec![], // represents imports
    vec![isl_type.to_owned()],
    vec![], // represents inline imports
    vec![], // represents open content
);

// use an Ion Writer to write the ISL model
let mut buffer = Vec::new();
let mut writer = TextWriterBuilder::pretty().build(&mut buffer)?;
isl_schema.write_to(&mut writer)?;

// write into schema file
let mut file = File::create("my_schema.isl")?;
file.write_all(writer.output().as_bytes())?;

Output:

$ion_schema_1_0
schema_header::{}
type::{
    name: "my_number_type",
    one_of: [
        int,
        float,
        decimal
    ]
}
schema_footer::{}

List of changes:

  • adds WriteToIsl to serialize isl model into schema file
    • Defines WriteToIsl trait which will be sued by all ISL model structs to write schema content to an Ion writer
    • Implements WriteToIsl for IslSchema
  • adds WriteToIsl implementation for
    • UserReservedFields
    • ISL imports
    • ISL type references
    • ISL constraints
    • ISL ranges
    • ISL model utils

Test:

Adds unit tests for WriteToIsl implementations.


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@desaikd desaikd requested review from popematt and zslayton June 8, 2023 23:11
use ion_rs::Symbol;
use ion_rs::{IonType, TextWriterBuilder};
use nom::AsBytes;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this being used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is being used in the tests for WriteToIsl.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nom is a pretty heavy dependency to bring in for the AsBytes trait, which seems to be a helper for fixed-sized arrays. Consider either:

  • Removing the dependency and using Vec::as_slice to access the bytes of the Vec<u8>.
  • Downgrading the dependency to a dev dependency.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nom is a pretty heavy dependency to bring in for the AsBytes trait, which seems to be a helper for fixed-sized arrays. Consider either:

* Removing the dependency and using [`Vec::as_slice`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.as_slice) to access the bytes of the `Vec<u8>`.

* Downgrading the dependency to a dev dependency.

According to your suggestion and since I am using this only for tests, I will remove the dependency and just use as_slice.

Comment on lines 509 to 518
IslTypeRefImpl::Named(name, nullability_modifier) => {
nullability_modifier.write_to(writer)?;
writer.write_symbol(name)?;
}
IslTypeRefImpl::TypeImport(type_import, nullability_modifier) => {
nullability_modifier.write_to(writer)?;
writer.step_in(IonType::Struct)?;
type_import.write_to(writer)?;
writer.step_out()?;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming that it's possible to construct an IslVariableOccurringTypeRef that has a Named or TypeImport. If that's the case, then we should also be writing out the occurs in these branches, if it's not the default occurs for that constraint.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, for TypeImport I will modify it to add the occurs field here. For Named if it has an occurs other than the default value then it becomes an Anonymous(inline) type reference.
e.g.

// Named
fields : {
   name: string
}

// Anonymous
fields: {
    name: { type: string, occurs: required }
}

Comment on lines 1012 to 1016
"ion-schema-schemas/json/json.isl", // the file contains `nan` which fails on equivalence for two schemas
"ion-schema-tests/ion_schema_1_0/nullable.isl", // Needs `nullable` annotation related fixes
"ion-schema-tests/ion_schema_1_0/schema/import/import_inline.isl", // related to order of types in the schema file
"ion-schema-tests/ion_schema_2_0/imports/tree/inline_import_a.isl", // related to order of types in the schema file
"ion-schema-tests/ion_schema_2_0/imports/tree/inline_import_c.isl", // related to order of types in the schema file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have any GitHub issue to track the nan issue or the "order of types in a schema file" issue?

Copy link
Contributor Author

@desaikd desaikd Jun 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created an issue for this, I will add it in the comments for these SKIP_LIST items.
#184

ion-schema/src/lib.rs Show resolved Hide resolved
ion-schema/src/isl/mod.rs Show resolved Hide resolved
* adds more doc comments
* `write_to` writes `occurs` field for `TypeImport` in
`IslVariablyOccurringTypeRef`
@desaikd desaikd requested a review from popematt June 12, 2023 18:14
if range_boundary_type == &RangeBoundaryType::Exclusive {
writer.set_annotations(["exclusive"]);
}
let element = Element::read_one(format!("{value}").as_bytes())?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a concrete suggestion at the moment, but this bit feels a bit fragile to me. We're using the constraint T: Display but actually hoping that T is something that's serialized as text Ion, which is a narrower set of types.

ion-schema/src/isl/isl_type.rs Outdated Show resolved Hide resolved
use ion_rs::Symbol;
use ion_rs::{IonType, TextWriterBuilder};
use nom::AsBytes;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nom is a pretty heavy dependency to bring in for the AsBytes trait, which seems to be a helper for fixed-sized arrays. Consider either:

  • Removing the dependency and using Vec::as_slice to access the bytes of the Vec<u8>.
  • Downgrading the dependency to a dev dependency.

@desaikd desaikd merged commit 7927b1f into main Jun 15, 2023
@desaikd desaikd deleted the desaikd-model-write-to-isl branch June 29, 2023 20:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants