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

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


The following commit(s) were added to refs/heads/branch-1.11 by this push:
     new 5abfe272e AVRO-3799: [Rust] Enable the schema parser to read and parse 
from input streams for Rust binding (#2352)
5abfe272e is described below

commit 5abfe272e0f31bf49bea25bd720e6240ba4ed467
Author: Kousuke Saruta <[email protected]>
AuthorDate: Mon Jul 17 15:24:35 2023 +0900

    AVRO-3799: [Rust] Enable the schema parser to read and parse from input 
streams for Rust binding (#2352)
    
    * Add a feature reading and parsing schemas from readers.
    
    * Fix format.
    
    * Add Jira number to the test names.
    
    (cherry picked from commit 1d1742b45ceaf73e09b82a9c6f1ab080f20d8808)
---
 lang/rust/avro/src/error.rs    |  3 +++
 lang/rust/avro/src/schema.rs   | 10 ++++++++
 lang/rust/avro/tests/schema.rs | 57 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+)

diff --git a/lang/rust/avro/src/error.rs b/lang/rust/avro/src/error.rs
index b9b6ccf66..f4479a1ae 100644
--- a/lang/rust/avro/src/error.rs
+++ b/lang/rust/avro/src/error.rs
@@ -256,6 +256,9 @@ pub enum Error {
     #[error("Failed to parse schema from JSON")]
     ParseSchemaJson(#[source] serde_json::Error),
 
+    #[error("Failed to read schema")]
+    ReadSchemaFromReader(#[source] std::io::Error),
+
     #[error("Must be a JSON string, object or array")]
     ParseSchemaFromValidJson,
 
diff --git a/lang/rust/avro/src/schema.rs b/lang/rust/avro/src/schema.rs
index 567d811be..4d7609fd2 100644
--- a/lang/rust/avro/src/schema.rs
+++ b/lang/rust/avro/src/schema.rs
@@ -32,6 +32,7 @@ use std::{
     fmt,
     fmt::Debug,
     hash::Hash,
+    io::Read,
     str::FromStr,
 };
 use strum_macros::{EnumDiscriminants, EnumString};
@@ -933,6 +934,15 @@ impl Schema {
         parser.parse_list()
     }
 
+    /// Create a `Schema` from a reader which implements [`Read`].
+    pub fn parse_reader(reader: &mut (impl Read + ?Sized)) -> 
AvroResult<Schema> {
+        let mut buf = String::new();
+        match reader.read_to_string(&mut buf) {
+            Ok(_) => Self::parse_str(&buf),
+            Err(e) => Err(Error::ReadSchemaFromReader(e)),
+        }
+    }
+
     /// Parses an Avro schema from JSON.
     pub fn parse(value: &Value) -> AvroResult<Schema> {
         let mut parser = Parser::default();
diff --git a/lang/rust/avro/tests/schema.rs b/lang/rust/avro/tests/schema.rs
index 1b98a2a3e..e2ab945f6 100644
--- a/lang/rust/avro/tests/schema.rs
+++ b/lang/rust/avro/tests/schema.rs
@@ -15,6 +15,8 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use std::io::{Cursor, Read};
+
 use apache_avro::{
     schema::{EnumSchema, FixedSchema, Name, RecordField, RecordSchema},
     to_avro_datum, to_value,
@@ -682,6 +684,61 @@ fn test_parse() -> TestResult {
     Ok(())
 }
 
+#[test]
+fn test_3799_parse_reader() -> TestResult {
+    init();
+    for (raw_schema, valid) in EXAMPLES.iter() {
+        let schema = Schema::parse_reader(&mut Cursor::new(raw_schema));
+        if *valid {
+            assert!(
+                schema.is_ok(),
+                "schema {raw_schema} was supposed to be valid; error: 
{schema:?}",
+            )
+        } else {
+            assert!(
+                schema.is_err(),
+                "schema {raw_schema} was supposed to be invalid"
+            )
+        }
+    }
+
+    // Ensure it works for trait objects too.
+    for (raw_schema, valid) in EXAMPLES.iter() {
+        let reader: &mut dyn Read = &mut Cursor::new(raw_schema);
+        let schema = Schema::parse_reader(reader);
+        if *valid {
+            assert!(
+                schema.is_ok(),
+                "schema {raw_schema} was supposed to be valid; error: 
{schema:?}",
+            )
+        } else {
+            assert!(
+                schema.is_err(),
+                "schema {raw_schema} was supposed to be invalid"
+            )
+        }
+    }
+    Ok(())
+}
+
+#[test]
+fn test_3799_raise_io_error_from_parse_read() -> Result<(), String> {
+    // 0xDF is invalid for UTF-8.
+    let mut invalid_data = Cursor::new([0xDF]);
+
+    let error = Schema::parse_reader(&mut invalid_data).unwrap_err();
+
+    if let Error::ReadSchemaFromReader(e) = error {
+        assert!(
+            e.to_string().contains("stream did not contain valid UTF-8"),
+            "{e}"
+        );
+        Ok(())
+    } else {
+        Err(format!("Expected std::io::Error, got {error:?}"))
+    }
+}
+
 #[test]
 /// Test that the string generated by an Avro Schema object is, in fact, a 
valid Avro schema.
 fn test_valid_cast_to_string_after_parse() -> TestResult {

Reply via email to