This is an automated email from the ASF dual-hosted git repository.

mgrigorov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new 4a65d5d  feat: Accept more inputs for `Schema::parse_(str_with)_list` 
(#195)
4a65d5d is described below

commit 4a65d5da5d3564045bd8c03cb62f210aa1100667
Author: Kriskras99 <[email protected]>
AuthorDate: Thu May 15 07:57:04 2025 +0200

    feat: Accept more inputs for `Schema::parse_(str_with)_list` (#195)
    
    They now accept anything that can iterate over types that can be
    converted into strings. For example: `Vec<String>`, `&[&str]`, and
    `files.iter().map(std::fs::read_to_string).filter_map(Result::ok)`.
---
 avro/src/schema.rs                        | 38 ++++++++++++++++++-------------
 avro/src/schema_compatibility.rs          |  2 +-
 avro/src/types.rs                         |  4 ++--
 avro/tests/schema.rs                      | 28 +++++++++++------------
 avro/tests/to_from_avro_datum_schemata.rs |  6 ++---
 avro/tests/union_schema.rs                | 10 ++++----
 6 files changed, 47 insertions(+), 41 deletions(-)

diff --git a/avro/src/schema.rs b/avro/src/schema.rs
index c12bc93..ee88e2b 100644
--- a/avro/src/schema.rs
+++ b/avro/src/schema.rs
@@ -1096,11 +1096,14 @@ impl Schema {
     /// during parsing.
     ///
     /// If two of the input schemas have the same fullname, an Error will be 
returned.
-    pub fn parse_list(input: &[&str]) -> AvroResult<Vec<Schema>> {
-        let mut input_schemas: HashMap<Name, Value> = 
HashMap::with_capacity(input.len());
-        let mut input_order: Vec<Name> = Vec::with_capacity(input.len());
-        for js in input {
-            let schema: Value = 
serde_json::from_str(js).map_err(Error::ParseSchemaJson)?;
+    pub fn parse_list(input: impl IntoIterator<Item = impl AsRef<str>>) -> 
AvroResult<Vec<Schema>> {
+        let input = input.into_iter();
+        let input_len = input.size_hint().0;
+        let mut input_schemas: HashMap<Name, Value> = 
HashMap::with_capacity(input_len);
+        let mut input_order: Vec<Name> = Vec::with_capacity(input_len);
+        for json in input {
+            let json = json.as_ref();
+            let schema: Value = 
serde_json::from_str(json).map_err(Error::ParseSchemaJson)?;
             if let Value::Object(inner) = &schema {
                 let name = Name::parse(inner, &None)?;
                 let previous_value = input_schemas.insert(name.clone(), 
schema);
@@ -1116,7 +1119,7 @@ impl Schema {
             input_schemas,
             resolving_schemas: HashMap::default(),
             input_order,
-            parsed_schemas: HashMap::with_capacity(input.len()),
+            parsed_schemas: HashMap::with_capacity(input_len),
         };
         parser.parse_list()
     }
@@ -1135,11 +1138,14 @@ impl Schema {
     /// * `schemata` - a slice of additional schemas that is used to resolve 
cross-references
     pub fn parse_str_with_list(
         schema: &str,
-        schemata: &[&str],
+        schemata: impl IntoIterator<Item = impl AsRef<str>>,
     ) -> AvroResult<(Schema, Vec<Schema>)> {
-        let mut input_schemas: HashMap<Name, Value> = 
HashMap::with_capacity(schemata.len());
-        let mut input_order: Vec<Name> = Vec::with_capacity(schemata.len());
+        let schemata = schemata.into_iter();
+        let schemata_len = schemata.size_hint().0;
+        let mut input_schemas: HashMap<Name, Value> = 
HashMap::with_capacity(schemata_len);
+        let mut input_order: Vec<Name> = Vec::with_capacity(schemata_len);
         for json in schemata {
+            let json = json.as_ref();
             let schema: Value = 
serde_json::from_str(json).map_err(Error::ParseSchemaJson)?;
             if let Value::Object(inner) = &schema {
                 let name = Name::parse(inner, &None)?;
@@ -1155,7 +1161,7 @@ impl Schema {
             input_schemas,
             resolving_schemas: HashMap::default(),
             input_order,
-            parsed_schemas: HashMap::with_capacity(schemata.len()),
+            parsed_schemas: HashMap::with_capacity(schemata_len),
         };
         parser.parse_input_schemas()?;
 
@@ -2782,7 +2788,7 @@ mod tests {
             ]
         }"#;
 
-        let schema_c = Schema::parse_list(&[schema_str_a, schema_str_b, 
schema_str_c])?
+        let schema_c = Schema::parse_list([schema_str_a, schema_str_b, 
schema_str_c])?
             .last()
             .unwrap()
             .clone();
@@ -2831,7 +2837,7 @@ mod tests {
         let schema_str_c = r#"["A", "B"]"#;
 
         let (schema_c, schemata) =
-            Schema::parse_str_with_list(schema_str_c, &[schema_str_a, 
schema_str_b])?;
+            Schema::parse_str_with_list(schema_str_c, [schema_str_a, 
schema_str_b])?;
 
         let schema_a_expected = Schema::Record(RecordSchema {
             name: Name::new("A")?,
@@ -2906,7 +2912,7 @@ mod tests {
 
         let schema_str_c = r#"["A", "A"]"#;
 
-        match Schema::parse_str_with_list(schema_str_c, &[schema_str_a1, 
schema_str_a2]) {
+        match Schema::parse_str_with_list(schema_str_c, [schema_str_a1, 
schema_str_a2]) {
             Ok(_) => unreachable!("Expected an error that the name is already 
defined"),
             Err(e) => assert_eq!(
                 e.to_string(),
@@ -2937,7 +2943,7 @@ mod tests {
 
         let schema_str_c = r#"["A", "A"]"#;
 
-        match Schema::parse_str_with_list(schema_str_c, &[schema_str_a, 
schema_str_b]) {
+        match Schema::parse_str_with_list(schema_str_c, [schema_str_a, 
schema_str_b]) {
             Ok(_) => unreachable!("Expected an error that schema_str_b is 
missing a name field"),
             Err(e) => assert_eq!(e.to_string(), "No `name` field"),
         }
@@ -2960,7 +2966,7 @@ mod tests {
             "fields": [ {"name": "field_one", "type": "A"} ]
         }"#;
 
-        let list = Schema::parse_list(&[schema_str_a, schema_str_b])?;
+        let list = Schema::parse_list([schema_str_a, schema_str_b])?;
 
         let schema_a = list.first().unwrap().clone();
 
@@ -3000,7 +3006,7 @@ mod tests {
             ]
         }"#;
 
-        let schema_option_a = Schema::parse_list(&[schema_str_a, 
schema_str_option_a])?
+        let schema_option_a = Schema::parse_list([schema_str_a, 
schema_str_option_a])?
             .last()
             .unwrap()
             .clone();
diff --git a/avro/src/schema_compatibility.rs b/avro/src/schema_compatibility.rs
index 5df7c52..909430d 100644
--- a/avro/src/schema_compatibility.rs
+++ b/avro/src/schema_compatibility.rs
@@ -1766,7 +1766,7 @@ mod tests {
         "#,
         ];
 
-        let schemas = Schema::parse_list(&schema_strs).unwrap();
+        let schemas = Schema::parse_list(schema_strs).unwrap();
         SchemaCompatibility::can_read(&schemas[1], &schemas[1])?;
 
         Ok(())
diff --git a/avro/src/types.rs b/avro/src/types.rs
index d5fa174..dd7dd77 100644
--- a/avro/src/types.rs
+++ b/avro/src/types.rs
@@ -2969,7 +2969,7 @@ Field with name '"b"' is not a member of the map items"#,
 
         let avro_value = Value::from(value);
 
-        let schemas = Schema::parse_list(&[main_schema, referenced_schema])?;
+        let schemas = Schema::parse_list([main_schema, referenced_schema])?;
 
         let main_schema = schemas.first().unwrap();
         let schemata: Vec<_> = schemas.iter().skip(1).collect();
@@ -3011,7 +3011,7 @@ Field with name '"b"' is not a member of the map items"#,
 
         let avro_value = Value::from(value);
 
-        let schemata = Schema::parse_list(&[referenced_enum, 
referenced_record, main_schema])?;
+        let schemata = Schema::parse_list([referenced_enum, referenced_record, 
main_schema])?;
 
         let main_schema = schemata.last().unwrap();
         let other_schemata: Vec<&Schema> = schemata.iter().take(2).collect();
diff --git a/avro/tests/schema.rs b/avro/tests/schema.rs
index c4a06c6..73967bb 100644
--- a/avro/tests/schema.rs
+++ b/avro/tests/schema.rs
@@ -187,7 +187,7 @@ fn test_parse_list_without_cross_deps() -> TestResult {
         "size": 16
     }"#;
     let schema_strs = [schema_str_1, schema_str_2];
-    let schemas = Schema::parse_list(&schema_strs)?;
+    let schemas = Schema::parse_list(schema_strs)?;
 
     for schema_str in &schema_strs {
         let parsed = Schema::parse_str(schema_str)?;
@@ -220,8 +220,8 @@ fn test_parse_list_with_cross_deps_basic() -> TestResult {
 
     let schema_strs_first = [schema_a_str, schema_b_str];
     let schema_strs_second = [schema_b_str, schema_a_str];
-    let schemas_first = Schema::parse_list(&schema_strs_first)?;
-    let schemas_second = Schema::parse_list(&schema_strs_second)?;
+    let schemas_first = Schema::parse_list(schema_strs_first)?;
+    let schemas_second = Schema::parse_list(schema_strs_second)?;
 
     assert_eq!(schemas_first[0], schemas_second[1]);
     assert_eq!(schemas_first[1], schemas_second[0]);
@@ -249,8 +249,8 @@ fn test_parse_list_recursive_type() -> TestResult {
     }"#;
     let schema_strs_first = [schema_str_1, schema_str_2];
     let schema_strs_second = [schema_str_2, schema_str_1];
-    let _ = Schema::parse_list(&schema_strs_first)?;
-    let _ = Schema::parse_list(&schema_strs_second)?;
+    let _ = Schema::parse_list(schema_strs_first)?;
+    let _ = Schema::parse_list(schema_strs_second)?;
     Ok(())
 }
 
@@ -274,8 +274,8 @@ fn test_parse_list_with_cross_deps_and_namespaces() -> 
TestResult {
         ]
     }"#;
 
-    let schemas_first = Schema::parse_list(&[schema_a_str, schema_b_str])?;
-    let schemas_second = Schema::parse_list(&[schema_b_str, schema_a_str])?;
+    let schemas_first = Schema::parse_list([schema_a_str, schema_b_str])?;
+    let schemas_second = Schema::parse_list([schema_b_str, schema_a_str])?;
 
     assert_eq!(schemas_first[0], schemas_second[1]);
     assert_eq!(schemas_first[1], schemas_second[0]);
@@ -305,8 +305,8 @@ fn test_parse_list_with_cross_deps_and_namespaces_error() 
-> TestResult {
 
     let schema_strs_first = [schema_str_1, schema_str_2];
     let schema_strs_second = [schema_str_2, schema_str_1];
-    let _ = Schema::parse_list(&schema_strs_first).expect_err("Test failed");
-    let _ = Schema::parse_list(&schema_strs_second).expect_err("Test failed");
+    let _ = Schema::parse_list(schema_strs_first).expect_err("Test failed");
+    let _ = Schema::parse_list(schema_strs_second).expect_err("Test failed");
 
     Ok(())
 }
@@ -453,7 +453,7 @@ fn test_parse_list_multiple_dependencies() -> TestResult {
         ]
     }"#;
 
-    let parsed = Schema::parse_list(&[schema_a_str, schema_b_str, 
schema_c_str])?;
+    let parsed = Schema::parse_list([schema_a_str, schema_b_str, 
schema_c_str])?;
     let schema_strs = vec![schema_a_str, schema_b_str, schema_c_str];
     for schema_str_perm in permutations(&schema_strs) {
         let schema_str_perm: Vec<&str> = schema_str_perm.iter().map(|s| 
**s).collect();
@@ -493,7 +493,7 @@ fn test_parse_list_shared_dependency() -> TestResult {
         ]
     }"#;
 
-    let parsed = Schema::parse_list(&[schema_a_str, schema_b_str, 
schema_c_str])?;
+    let parsed = Schema::parse_list([schema_a_str, schema_b_str, 
schema_c_str])?;
     let schema_strs = vec![schema_a_str, schema_b_str, schema_c_str];
     for schema_str_perm in permutations(&schema_strs) {
         let schema_str_perm: Vec<&str> = schema_str_perm.iter().map(|s| 
**s).collect();
@@ -526,7 +526,7 @@ fn test_name_collision_error() -> TestResult {
         ]
     }"#;
 
-    let _ = Schema::parse_list(&[schema_str_1, schema_str_2]).expect_err("Test 
failed");
+    let _ = Schema::parse_list([schema_str_1, schema_str_2]).expect_err("Test 
failed");
     Ok(())
 }
 
@@ -550,7 +550,7 @@ fn test_namespace_prevents_collisions() -> TestResult {
         ]
     }"#;
 
-    let parsed = Schema::parse_list(&[schema_str_1, schema_str_2])?;
+    let parsed = Schema::parse_list([schema_str_1, schema_str_2])?;
     let parsed_1 = Schema::parse_str(schema_str_1)?;
     let parsed_2 = Schema::parse_str(schema_str_2)?;
     assert_eq!(parsed, vec!(parsed_1, parsed_2));
@@ -2346,7 +2346,7 @@ fn 
avro_rs_66_test_independent_canonical_form_missing_ref() -> TestResult {
     }"#;
 
     let schema_strs = [record_primitive, record_usage];
-    let schemata = Schema::parse_list(&schema_strs)?;
+    let schemata = Schema::parse_list(schema_strs)?;
     assert!(matches!(
         schemata[1].independent_canonical_form(&Vec::with_capacity(0)), //NOTE 
- we're passing in an empty schemata
         Err(Error::SchemaResolutionError(..))
diff --git a/avro/tests/to_from_avro_datum_schemata.rs 
b/avro/tests/to_from_avro_datum_schemata.rs
index 776c446..6f2d595 100644
--- a/avro/tests/to_from_avro_datum_schemata.rs
+++ b/avro/tests/to_from_avro_datum_schemata.rs
@@ -46,7 +46,7 @@ fn test_avro_3683_multiple_schemata_to_from_avro_datum() -> 
TestResult {
         Value::Record(vec![(String::from("field_a"), Value::Float(1.0))]),
     )]);
 
-    let schemata: Vec<Schema> = Schema::parse_list(&[SCHEMA_A_STR, 
SCHEMA_B_STR])?;
+    let schemata: Vec<Schema> = Schema::parse_list([SCHEMA_A_STR, 
SCHEMA_B_STR])?;
     let schemata: Vec<&Schema> = schemata.iter().collect();
 
     // this is the Schema we want to use for write/read
@@ -70,7 +70,7 @@ fn 
avro_rs_106_test_multiple_schemata_to_from_avro_datum_with_resolution() -> Te
         Value::Record(vec![(String::from("field_a"), Value::Float(1.0))]),
     )]);
 
-    let schemata: Vec<Schema> = Schema::parse_list(&[SCHEMA_A_STR, 
SCHEMA_B_STR])?;
+    let schemata: Vec<Schema> = Schema::parse_list([SCHEMA_A_STR, 
SCHEMA_B_STR])?;
     let schemata: Vec<&Schema> = schemata.iter().collect();
 
     // this is the Schema we want to use for write/read
@@ -100,7 +100,7 @@ fn test_avro_3683_multiple_schemata_writer_reader() -> 
TestResult {
         Value::Record(vec![(String::from("field_a"), Value::Float(1.0))]),
     )]);
 
-    let schemata: Vec<Schema> = Schema::parse_list(&[SCHEMA_A_STR, 
SCHEMA_B_STR])?;
+    let schemata: Vec<Schema> = Schema::parse_list([SCHEMA_A_STR, 
SCHEMA_B_STR])?;
     let schemata: Vec<&Schema> = schemata.iter().collect();
 
     // this is the Schema we want to use for write/read
diff --git a/avro/tests/union_schema.rs b/avro/tests/union_schema.rs
index 6dcb1b6..106b062 100644
--- a/avro/tests/union_schema.rs
+++ b/avro/tests/union_schema.rs
@@ -82,7 +82,7 @@ where
 #[test]
 fn test_avro_3901_union_schema_round_trip_no_null() -> AvroResult<()> {
     let schemata: Vec<Schema> =
-        Schema::parse_list(&[SCHEMA_A_STR, SCHEMA_B_STR, 
SCHEMA_C_STR]).expect("parsing schemata");
+        Schema::parse_list([SCHEMA_A_STR, SCHEMA_B_STR, 
SCHEMA_C_STR]).expect("parsing schemata");
 
     let input = C {
         field_union: (UnionAB::A(A { field_a: 45.5 })),
@@ -126,7 +126,7 @@ struct D {
 #[test]
 fn test_avro_3901_union_schema_round_trip_null_at_start() -> AvroResult<()> {
     let schemata: Vec<Schema> =
-        Schema::parse_list(&[SCHEMA_A_STR, SCHEMA_B_STR, 
SCHEMA_D_STR]).expect("parsing schemata");
+        Schema::parse_list([SCHEMA_A_STR, SCHEMA_B_STR, 
SCHEMA_D_STR]).expect("parsing schemata");
 
     let input = D {
         field_union: UnionNoneAB::A(A { field_a: 54.25 }),
@@ -177,7 +177,7 @@ struct E {
 #[test]
 fn test_avro_3901_union_schema_round_trip_with_out_of_order_null() -> 
AvroResult<()> {
     let schemata: Vec<Schema> =
-        Schema::parse_list(&[SCHEMA_A_STR, SCHEMA_B_STR, 
SCHEMA_E_STR]).expect("parsing schemata");
+        Schema::parse_list([SCHEMA_A_STR, SCHEMA_B_STR, 
SCHEMA_E_STR]).expect("parsing schemata");
 
     let input = E {
         field_union: UnionANoneB::A(A { field_a: 23.75 }),
@@ -228,7 +228,7 @@ struct F {
 #[test]
 fn test_avro_3901_union_schema_round_trip_with_end_null() -> AvroResult<()> {
     let schemata: Vec<Schema> =
-        Schema::parse_list(&[SCHEMA_A_STR, SCHEMA_B_STR, 
SCHEMA_F_STR]).expect("parsing schemata");
+        Schema::parse_list([SCHEMA_A_STR, SCHEMA_B_STR, 
SCHEMA_F_STR]).expect("parsing schemata");
 
     let input = F {
         field_union: UnionABNone::A(A { field_a: 23.75 }),
@@ -318,7 +318,7 @@ struct H {
 
 #[test]
 fn test_avro_3901_union_schema_as_optional() -> AvroResult<()> {
-    let schemata: Vec<Schema> = 
Schema::parse_list(&[SCHEMA_H_STR]).expect("parsing schemata");
+    let schemata: Vec<Schema> = 
Schema::parse_list([SCHEMA_H_STR]).expect("parsing schemata");
 
     let input = H {
         field_union: Some(23),

Reply via email to