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 {