diff --git a/Cargo.lock b/Cargo.lock index b44c121..89d980a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -840,7 +840,7 @@ dependencies = [ "convert_case", "flate2", "infer", - "ion-rs 1.0.0-rc.4", + "ion-rs 1.0.0-rc.5", "ion-schema", "matches", "pager", @@ -876,9 +876,9 @@ dependencies = [ [[package]] name = "ion-rs" -version = "1.0.0-rc.4" +version = "1.0.0-rc.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87db81c1c2e08fd2de74c8dc62fbc4d6f192a34a883dafe21a00cad7a037e3da" +checksum = "ae6628b313b01f34e167393a688a78ce907ff7307cb9e4a93c9d3599cabb1b03" dependencies = [ "arrayvec", "base64 0.12.3", diff --git a/Cargo.toml b/Cargo.toml index 719607b..2e62e5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ clap = { version = "4.0.17", features = ["cargo"] } colored = "2.0.0" flate2 = "1.0" infer = "0.15.0" -ion-rs = { version = "1.0.0-rc.4", features = ["experimental"] } +ion-rs = { version = "1.0.0-rc.5", features = ["experimental"] } tempfile = "3.2.0" ion-schema = "0.10.0" serde = { version = "1.0.163", features = ["derive"] } diff --git a/src/bin/ion/commands/beta/generate/utils.rs b/src/bin/ion/commands/beta/generate/utils.rs index d66594c..6388b5f 100644 --- a/src/bin/ion/commands/beta/generate/utils.rs +++ b/src/bin/ion/commands/beta/generate/utils.rs @@ -5,7 +5,7 @@ use serde::Serialize; use std::fmt::{Display, Formatter}; /// Represents a field that will be added to generated data model. -/// This will be used by the template engine to fill properties of a struct/classs. +/// This will be used by the template engine to fill properties of a struct/class. #[derive(Serialize)] pub struct Field { pub(crate) name: String, @@ -76,7 +76,7 @@ impl Language for JavaLanguage { Blob | Clob => "byte[]", SchemaDefined(name) => name, } - .to_string() + .to_string() } fn target_type_as_sequence(target_type: &str) -> String { @@ -129,7 +129,7 @@ impl Language for RustLanguage { Blob | Clob => "Vec", SchemaDefined(name) => name, } - .to_string() + .to_string() } fn target_type_as_sequence(target_type: &str) -> String { diff --git a/src/bin/ion/commands/beta/inspect.rs b/src/bin/ion/commands/beta/inspect.rs index 7f4c6c3..2610f94 100644 --- a/src/bin/ion/commands/beta/inspect.rs +++ b/src/bin/ion/commands/beta/inspect.rs @@ -312,7 +312,7 @@ impl<'a, 'b> IonInspector<'a, 'b> { /// inspected; if the e-expression that produced the value was not beyond the limit, /// none of the ephemeral values it produces are either. fn is_past_limit(&mut self, maybe_item: &Option) -> bool { - let limit = self.bytes_to_skip + self.limit_bytes; + let limit = self.bytes_to_skip.saturating_add(self.limit_bytes); maybe_item.as_ref().map(|item| item.range().start >= limit).unwrap_or(false) } diff --git a/src/bin/ion/commands/beta/to/json.rs b/src/bin/ion/commands/beta/to/json.rs index e0e7cff..dd791f5 100644 --- a/src/bin/ion/commands/beta/to/json.rs +++ b/src/bin/ion/commands/beta/to/json.rs @@ -6,6 +6,7 @@ use std::fs::File; use std::io::{stdin, stdout, BufWriter, Write}; use std::str::FromStr; use ion_rs::*; +use zstd::zstd_safe::WriteBuf; pub struct ToJsonCommand; @@ -102,7 +103,7 @@ fn to_json_value(value: LazyValue) -> Result { String(s) => JsonValue::String(s.text().to_owned()), Blob(b) | Clob(b) => { use base64::{engine::general_purpose as base64_encoder, Engine as _}; - let base64_text = base64_encoder::STANDARD.encode(b.as_ref()); + let base64_text = base64_encoder::STANDARD.encode(b.as_slice()); JsonValue::String(base64_text) } SExp(s) => to_json_array(s.iter())?, diff --git a/tests/cli.rs b/tests/cli.rs index 1beb817..a89dd89 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -2,7 +2,6 @@ use anyhow::Result; use assert_cmd::Command; use ion_rs::Element; use rstest::*; -use std::fs; use std::fs::File; use std::io::{Read, Write}; use std::time::Duration; @@ -213,14 +212,18 @@ fn test_write_all_values(#[case] number: i32, #[case] expected_output: &str) -> let command_assert = cmd.assert(); let output = command_assert.get_output(); let stdout = String::from_utf8_lossy(&output.stdout); - assert_eq!(stdout.trim_end(), expected_output); + assert_eq!(Element::read_all(stdout.trim_end())?, Element::read_all(expected_output)?); Ok(()) } #[cfg(feature = "experimental-code-gen")] -#[rstest] -#[case::simple_struct( - r#" +mod code_gen_tests { + use std::fs; + use super::*; + + #[rstest] + #[case::simple_struct( + r#" type::{ name: simple_struct, fields: { @@ -229,31 +232,31 @@ fn test_write_all_values(#[case] number: i32, #[case] expected_output: &str) -> }, } "#, - &["id: i64", "name: String"], - &["pub fn name(&self) -> &String {", "pub fn id(&self) -> &i64 {"] -)] -#[case::value_struct( - r#" + & ["id: i64", "name: String"], + & ["pub fn name(&self) -> &String {", "pub fn id(&self) -> &i64 {"] + )] + #[case::value_struct( + r#" type::{ name: value_struct, type: int // this will be a field in struct } "#, - &["value: i64"], - &["pub fn value(&self) -> &i64 {"] -)] -#[case::sequence_struct( - r#" + & ["value: i64"], + & ["pub fn value(&self) -> &i64 {"] + )] + #[case::sequence_struct( + r#" type::{ name: sequence_struct, element: string // this will be a sequence field in struct } "#, - &["value: Vec"], - &["pub fn value(&self) -> &Vec {"] -)] -#[case::struct_with_reference_field( - r#" + & ["value: Vec"], + & ["pub fn value(&self) -> &Vec {"] + )] + #[case::struct_with_reference_field( + r#" type::{ name: struct_with_reference_field, fields: { @@ -266,11 +269,11 @@ fn test_write_all_values(#[case] number: i32, #[case] expected_output: &str) -> type: int } "#, - &["reference: OtherType"], - &["pub fn reference(&self) -> &OtherType {"] -)] -#[case::struct_with_anonymous_type( - r#" + & ["reference: OtherType"], + & ["pub fn reference(&self) -> &OtherType {"] + )] + #[case::struct_with_anonymous_type( + r#" type::{ name: struct_with_anonymous_type, fields: { @@ -278,56 +281,55 @@ fn test_write_all_values(#[case] number: i32, #[case] expected_output: &str) -> } } "#, - &["anonymous_type: AnonymousType1"], - &["pub fn anonymous_type(&self) -> &AnonymousType1 {"] -)] -/// Calls ion-cli beta generate with different schema file. Pass the test if the return value contains the expected properties and accessors. -fn test_code_generation_in_rust( - #[case] test_schema: &str, - #[case] expected_properties: &[&str], - #[case] expected_accessors: &[&str], -) -> Result<()> { - let mut cmd = Command::cargo_bin("ion")?; - let temp_dir = TempDir::new()?; - let input_schema_path = temp_dir.path().join("test_schema.isl"); - let mut input_schema_file = File::create(&input_schema_path)?; - input_schema_file.write(test_schema.as_bytes())?; - input_schema_file.flush()?; - cmd.args([ - "beta", - "generate", - "--schema", - "test_schema.isl", - "--output", - temp_dir.path().to_str().unwrap(), - "--language", - "rust", - "--directory", - temp_dir.path().to_str().unwrap(), - ]); - let command_assert = cmd.assert(); - let output_file_path = temp_dir.path().join("ion_generated_code.rs"); - command_assert.success(); - let contents = - fs::read_to_string(output_file_path).expect("Should have been able to read the file"); - for expected_property in expected_properties { - assert!(contents.contains(expected_property)); - } - for expected_accessor in expected_accessors { - assert!(contents.contains(expected_accessor)); + & ["anonymous_type: AnonymousType1"], + & ["pub fn anonymous_type(&self) -> &AnonymousType1 {"] + )] + /// Calls ion-cli beta generate with different schema file. Pass the test if the return value contains the expected properties and accessors. + fn test_code_generation_in_rust( + #[case] test_schema: &str, + #[case] expected_properties: &[&str], + #[case] expected_accessors: &[&str], + ) -> Result<()> { + let mut cmd = Command::cargo_bin("ion")?; + let temp_dir = TempDir::new()?; + let input_schema_path = temp_dir.path().join("test_schema.isl"); + let mut input_schema_file = File::create(&input_schema_path)?; + input_schema_file.write(test_schema.as_bytes())?; + input_schema_file.flush()?; + cmd.args([ + "beta", + "generate", + "--schema", + "test_schema.isl", + "--output", + temp_dir.path().to_str().unwrap(), + "--language", + "rust", + "--directory", + temp_dir.path().to_str().unwrap(), + ]); + let command_assert = cmd.assert(); + let output_file_path = temp_dir.path().join("ion_generated_code.rs"); + command_assert.success(); + let contents = + fs::read_to_string(output_file_path).expect("Should have been able to read the file"); + for expected_property in expected_properties { + assert!(contents.contains(expected_property)); + } + for expected_accessor in expected_accessors { + assert!(contents.contains(expected_accessor)); + } + // verify that it generates read-write APIs + assert!(contents.contains("pub fn read_from(reader: &mut Reader) -> IonResult {")); + assert!(contents + .contains("pub fn write_to(&self, writer: &mut W) -> IonResult<()> {")); + Ok(()) } - // verify that it generates read-write APIs - assert!(contents.contains("pub fn read_from(reader: &mut Reader) -> IonResult {")); - assert!(contents - .contains("pub fn write_to(&self, writer: &mut W) -> IonResult<()> {")); - Ok(()) -} -#[cfg(feature = "experimental-code-gen")] -#[rstest] -#[case( - "SimpleStruct", - r#" + #[rstest] + #[case( + "SimpleStruct", + r#" type::{ name: simple_struct, fields: { @@ -336,34 +338,34 @@ fn test_code_generation_in_rust( } } "#, - &["private int id;", "private String name;"], - &["public String getName() {", "public int getId() {"] -)] -#[case( - "ValueStruct", - r#" + & ["private int id;", "private String name;"], + & ["public String getName() {", "public int getId() {"] + )] + #[case( + "ValueStruct", + r#" type::{ name: value_struct, type: int // this will be a field in struct } "#, - &["private int value;"], - &["public int getValue() {"] -)] -#[case( - "SequenceStruct", - r#" + & ["private int value;"], + & ["public int getValue() {"] + )] + #[case( + "SequenceStruct", + r#" type::{ name: sequence_struct, element: string // this will be a sequence field in struct } "#, - &["private ArrayList value;"], - &["public ArrayList getValue() {"] -)] -#[case( - "StructWithReferenceField", - r#" + & ["private ArrayList value;"], + & ["public ArrayList getValue() {"] + )] + #[case( + "StructWithReferenceField", + r#" type::{ name: struct_with_reference_field, fields: { @@ -376,12 +378,12 @@ fn test_code_generation_in_rust( type: int } "#, - &["private OtherType reference;"], - &["public OtherType getReference() {"] -)] -#[case( - "StructWithAnonymousType", - r#" + & ["private OtherType reference;"], + & ["public OtherType getReference() {"] + )] + #[case( + "StructWithAnonymousType", + r#" type::{ name: struct_with_anonymous_type, fields: { @@ -389,45 +391,46 @@ fn test_code_generation_in_rust( } } "#, - &["private AnonymousType1 anonymousType;"], - &["public AnonymousType1 getAnonymousType() {"] -)] -/// Calls ion-cli beta generate with different schema file. Pass the test if the return value contains the expected properties and accessors. -fn test_code_generation_in_java( - #[case] test_name: &str, - #[case] test_schema: &str, - #[case] expected_properties: &[&str], - #[case] expected_accessors: &[&str], -) -> Result<()> { - let mut cmd = Command::cargo_bin("ion")?; - let temp_dir = TempDir::new()?; - let input_schema_path = temp_dir.path().join("test_schema.isl"); - let mut input_schema_file = File::create(&input_schema_path)?; - input_schema_file.write(test_schema.as_bytes())?; - input_schema_file.flush()?; - cmd.args([ - "beta", - "generate", - "--schema", - "test_schema.isl", - "--output", - temp_dir.path().to_str().unwrap(), - "--language", - "java", - "--namespace", - "org.example", - "--directory", - temp_dir.path().to_str().unwrap(), - ]); - let command_assert = cmd.assert(); - let output_file_path = temp_dir.path().join(format!("{}.java", test_name)); - command_assert.success(); - let contents = fs::read_to_string(output_file_path).expect("Can not read generated code file."); - for expected_property in expected_properties { - assert!(contents.contains(expected_property)); - } - for expected_accessor in expected_accessors { - assert!(contents.contains(expected_accessor)); + & ["private AnonymousType1 anonymousType;"], + & ["public AnonymousType1 getAnonymousType() {"] + )] + /// Calls ion-cli beta generate with different schema file. Pass the test if the return value contains the expected properties and accessors. + fn test_code_generation_in_java( + #[case] test_name: &str, + #[case] test_schema: &str, + #[case] expected_properties: &[&str], + #[case] expected_accessors: &[&str], + ) -> Result<()> { + let mut cmd = Command::cargo_bin("ion")?; + let temp_dir = TempDir::new()?; + let input_schema_path = temp_dir.path().join("test_schema.isl"); + let mut input_schema_file = File::create(&input_schema_path)?; + input_schema_file.write(test_schema.as_bytes())?; + input_schema_file.flush()?; + cmd.args([ + "beta", + "generate", + "--schema", + "test_schema.isl", + "--output", + temp_dir.path().to_str().unwrap(), + "--language", + "java", + "--namespace", + "org.example", + "--directory", + temp_dir.path().to_str().unwrap(), + ]); + let command_assert = cmd.assert(); + let output_file_path = temp_dir.path().join(format!("{}.java", test_name)); + command_assert.success(); + let contents = fs::read_to_string(output_file_path).expect("Can not read generated code file."); + for expected_property in expected_properties { + assert!(contents.contains(expected_property)); + } + for expected_accessor in expected_accessors { + assert!(contents.contains(expected_accessor)); + } + Ok(()) } - Ok(()) -} +} \ No newline at end of file diff --git a/tests/code-gen-tests.rs b/tests/code-gen-tests.rs index 3c79a22..ade8b5c 100644 --- a/tests/code-gen-tests.rs +++ b/tests/code-gen-tests.rs @@ -1,7 +1,8 @@ +#![cfg(feature = "experimental-code-gen")] + use anyhow::Result; use std::io::Write; -#[cfg(feature = "experimental-code-gen")] #[test] fn roundtrip_tests_for_generated_code_gradle() -> Result<()> { // run the gradle project defined under `code-gen-projects`, @@ -34,7 +35,6 @@ fn roundtrip_tests_for_generated_code_gradle() -> Result<()> { Ok(()) } -#[cfg(feature = "experimental-code-gen")] #[test] fn roundtrip_tests_for_generated_code_cargo() -> Result<()> { // run the cargo project defined under `code-gen-projects`,