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

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

commit 7fda1076ab2c2d351f0e65631165d1b5ec8b5e24
Author: Kriskras99 <[email protected]>
AuthorDate: Mon Jul 6 22:20:45 2026 +0200

    feat: Allow to supply own names when using `Value::resolve` and 
`Value::Validate`
---
 avro/src/reader/datum.rs        |   2 +-
 avro/src/schema/parser.rs       |   2 +-
 avro/src/schema/record/field.rs |   4 +-
 avro/src/schema/union.rs        |   6 +--
 avro/src/types.rs               | 104 +++++++++++++++++++++++++++++++++-------
 5 files changed, 93 insertions(+), 25 deletions(-)

diff --git a/avro/src/reader/datum.rs b/avro/src/reader/datum.rs
index fa692e1..4f0c31e 100644
--- a/avro/src/reader/datum.rs
+++ b/avro/src/reader/datum.rs
@@ -132,7 +132,7 @@ impl<'s> GenericDatumReader<'s> {
     pub fn read_value<R: Read>(&self, reader: &mut R) -> AvroResult<Value> {
         let value = decode_internal(self.writer, self.resolved.get_names(), 
None, reader)?;
         if let Some((reader, resolved)) = &self.reader {
-            value.resolve_internal(reader, resolved.get_names(), None, &None)
+            value.resolve_internal(reader, resolved.get_names(), None, None)
         } else {
             Ok(value)
         }
diff --git a/avro/src/schema/parser.rs b/avro/src/schema/parser.rs
index 2310e08..f84766f 100644
--- a/avro/src/schema/parser.rs
+++ b/avro/src/schema/parser.rs
@@ -662,7 +662,7 @@ impl Parser {
 
         if let Some(ref value) = default {
             let resolved = types::Value::from(value.clone())
-                .resolve_enum(&symbols, &Some(value.to_string()), &None)
+                .resolve_enum(&symbols, &Some(value.to_string()), None)
                 .is_ok();
             if !resolved {
                 return Err(Details::GetEnumDefault {
diff --git a/avro/src/schema/record/field.rs b/avro/src/schema/record/field.rs
index 10f8856..2bd6468 100644
--- a/avro/src/schema/record/field.rs
+++ b/avro/src/schema/record/field.rs
@@ -146,7 +146,7 @@ impl RecordField {
                 let resolved = schemas.iter().any(|schema| {
                     avro_value
                         .to_owned()
-                        .resolve_internal(schema, names, schema.namespace(), 
&None)
+                        .resolve_internal(schema, names, schema.namespace(), 
None)
                         .is_ok()
                 });
 
@@ -163,7 +163,7 @@ impl RecordField {
                 }
             } else {
                 let resolved = avro_value
-                    .resolve_internal(field_schema, names, 
field_schema.namespace(), &None)
+                    .resolve_internal(field_schema, names, 
field_schema.namespace(), None)
                     .is_ok();
 
                 if !resolved {
diff --git a/avro/src/schema/union.rs b/avro/src/schema/union.rs
index 1561c11..ca9a997 100644
--- a/avro/src/schema/union.rs
+++ b/avro/src/schema/union.rs
@@ -251,7 +251,7 @@ impl UnionSchema {
                     // TODO: Do this without the clone
                     value
                         .clone()
-                        .resolve_internal(schema, known_schemata, namespace, 
&None)
+                        .resolve_internal(schema, known_schemata, namespace, 
None)
                         .ok()
                         .map(|_| (index, schema))
                 } else {
@@ -275,7 +275,7 @@ impl UnionSchema {
                     // TODO: Do this without the clone
                     value
                         .clone()
-                        .resolve_internal(schema, known_schemata, namespace, 
&None)
+                        .resolve_internal(schema, known_schemata, namespace, 
None)
                         .is_ok()
                 })
         });
@@ -293,7 +293,7 @@ impl UnionSchema {
                     // TODO: Do this without the clone
                     value
                         .clone()
-                        .resolve_internal(schema, known_schemata, namespace, 
&None)
+                        .resolve_internal(schema, known_schemata, namespace, 
None)
                         .is_ok()
                 })
             }
diff --git a/avro/src/types.rs b/avro/src/types.rs
index ad0258b..19fee49 100644
--- a/avro/src/types.rs
+++ b/avro/src/types.rs
@@ -370,6 +370,10 @@ impl TryFrom<Value> for JsonValue {
 impl Value {
     /// Validate the value against the given [`Schema`].
     ///
+    /// Note: This will first build a reference map from the schema (see 
[`ResolvedSchema`]). If this
+    /// function is called more than once for the same schema, it is 
recommended to use
+    /// [`validate_with_names`](Self::validate_with_names) instead.
+    ///
     /// See the [Avro 
specification](https://avro.apache.org/docs/++version++/specification)
     /// for the full set of rules of schema validation.
     ///
@@ -381,6 +385,13 @@ impl Value {
 
     /// Validate the value against the given schemata.
     ///
+    /// Note: This will first build a reference map from the schema (see 
[`ResolvedSchema`]). If this
+    /// function is called more than once for the same schema, it is 
recommended to use
+    /// [`validate_with_names`](Self::validate_with_names) instead.
+    ///
+    /// See the [Avro 
specification](https://avro.apache.org/docs/++version++/specification)
+    /// for the full set of rules of schema validation.
+    ///
     /// # Panics
     /// Will panic if the schemata contain unresolved references or duplicate 
schemas.
     pub fn validate_schemata(&self, schemata: &[&Schema]) -> bool {
@@ -404,6 +415,26 @@ impl Value {
         )
     }
 
+    /// Validate the value against the given schema using `names` to resolve 
any references.
+    ///
+    /// See the [Avro 
specification](https://avro.apache.org/docs/++version++/specification)
+    /// for the full set of rules of schema validation.
+    pub fn validate_with_names<S: Borrow<Schema> + Debug>(
+        &self,
+        schema: &Schema,
+        names: &HashMap<Name, S>,
+    ) -> bool {
+        match self.validate_internal(schema, names, None) {
+            Some(reason) => {
+                let log_message =
+                    format!("Invalid value: {self:?} for schema: {schema:?}. 
Reason: {reason}");
+                error!("{log_message}");
+                false
+            }
+            None => true,
+        }
+    }
+
     fn accumulate(accumulator: Option<String>, other: Option<String>) -> 
Option<String> {
         match (accumulator, other) {
             (None, None) => None,
@@ -656,30 +687,62 @@ impl Value {
         }
     }
 
-    /// Attempt to perform schema resolution on the value, with the given
-    /// [Schema](../schema/enum.Schema.html).
+    /// Resolve this value into a new schema.
+    ///
+    /// Note: This will first build a reference map from the schema (see 
[`ResolvedSchema`]). If this
+    /// function is called more than once for the same schema, it is 
recommended to use
+    /// [`resolve_with_names`](Self::resolve_with_names) instead.
     ///
     /// See [Schema 
Resolution](https://avro.apache.org/docs/++version++/specification/#schema-resolution)
-    /// in the Avro specification for the full set of rules of schema
-    /// resolution.
+    /// in the Avro specification for the full set of rules of schema 
resolution.
     pub fn resolve(self, schema: &Schema) -> AvroResult<Self> {
         self.resolve_schemata(schema, Vec::with_capacity(0))
     }
 
-    /// Attempt to perform schema resolution on the value, with the given
-    /// [Schema](../schema/enum.Schema.html) and set of schemas to use for 
Refs resolution.
+    /// Resolve this value into a new schema using `schemata` to resolve any 
references.
+    ///
+    /// `schemata` must contain all referenced schemas in `schema`, including 
references to parts of
+    /// `schema` itself.
+    ///
+    /// Note: This will first build a reference map from the schema (see 
[`ResolvedSchema`]). If this
+    /// function is called more than once for the same schema, it is 
recommended to use
+    /// [`resolve_with_names`](Self::resolve_with_names) instead.
     ///
     /// See [Schema 
Resolution](https://avro.apache.org/docs/++version++/specification/#schema-resolution)
-    /// in the Avro specification for the full set of rules of schema
-    /// resolution.
+    /// in the Avro specification for the full set of rules of schema 
resolution.
     pub fn resolve_schemata(self, schema: &Schema, schemata: Vec<&Schema>) -> 
AvroResult<Self> {
-        let enclosing_namespace = schema.namespace();
         let rs = if schemata.is_empty() {
             ResolvedSchema::try_from(schema)?
         } else {
             ResolvedSchema::try_from(schemata)?
         };
-        self.resolve_internal(schema, rs.get_names(), enclosing_namespace, 
&None)
+        self.resolve_internal(schema, rs.get_names(), None, None)
+    }
+
+    /// Resolve this value into a new schema using `names` to resolve any 
references.
+    ///
+    /// See [Schema 
Resolution](https://avro.apache.org/docs/++version++/specification/#schema-resolution)
+    /// in the Avro specification for the full set of rules of schema 
resolution.
+    ///
+    /// # Example
+    /// ```
+    /// # use apache_avro::{types::Value, Error, Schema, 
schema::ResolvedSchema};
+    /// # let values: [Value; 0] = [];
+    /// # let schema = Schema::Null;
+    /// let resolved_schema = ResolvedSchema::new(&schema)?;
+    ///
+    /// for value in values {
+    ///     let resolved = value.resolve_with_names(&schema, 
resolved_schema.get_names())?;
+    ///     // Do something with the resolved value
+    /// }
+    /// # Ok::<(), Error>(())
+    /// ```
+    pub fn resolve_with_names<S: Borrow<Schema> + Debug>(
+        self,
+        schema: &Schema,
+        names: &HashMap<Name, S>,
+    ) -> AvroResult<Self> {
+        self.resolve_internal(schema, names, None, None)
     }
 
     pub(crate) fn resolve_internal<S: Borrow<Schema> + Debug>(
@@ -687,7 +750,7 @@ impl Value {
         schema: &Schema,
         names: &HashMap<Name, S>,
         enclosing_namespace: NamespaceRef,
-        field_default: &Option<JsonValue>,
+        field_default: Option<&JsonValue>,
     ) -> AvroResult<Self> {
         // Check if this schema is a union, and if the reader schema is not.
         if SchemaKind::from(&self) == SchemaKind::Union
@@ -1045,7 +1108,7 @@ impl Value {
         self,
         symbols: &[String],
         enum_default: &Option<String>,
-        _field_default: &Option<JsonValue>,
+        _field_default: Option<&JsonValue>,
     ) -> Result<Self, Error> {
         let validate_symbol = |symbol: String, symbols: &[String]| {
             if let Some(index) = symbols.iter().position(|item| item == 
&symbol) {
@@ -1084,7 +1147,7 @@ impl Value {
         schema: &UnionSchema,
         names: &HashMap<Name, S>,
         enclosing_namespace: NamespaceRef,
-        field_default: &Option<JsonValue>,
+        field_default: Option<&JsonValue>,
     ) -> Result<Self, Error> {
         let v = match self {
             // Both are unions case.
@@ -1115,7 +1178,7 @@ impl Value {
             Value::Array(items) => Ok(Value::Array(
                 items
                     .into_iter()
-                    .map(|item| item.resolve_internal(schema, names, 
enclosing_namespace, &None))
+                    .map(|item| item.resolve_internal(schema, names, 
enclosing_namespace, None))
                     .collect::<Result<_, _>>()?,
             )),
             other => Err(Details::GetArray {
@@ -1138,7 +1201,7 @@ impl Value {
                     .into_iter()
                     .map(|(key, value)| {
                         value
-                            .resolve_internal(schema, names, 
enclosing_namespace, &None)
+                            .resolve_internal(schema, names, 
enclosing_namespace, None)
                             .map(|value| (key, value))
                     })
                     .collect::<Result<_, _>>()?,
@@ -1183,7 +1246,7 @@ impl Value {
                             }) => Value::try_from(value.clone())?.resolve_enum(
                                 symbols,
                                 default,
-                                &field.default.clone(),
+                                field.default.as_ref(),
                             )?,
                             Schema::Union(ref union_schema) => {
                                 let first = &union_schema.variants()[0];
@@ -1198,7 +1261,7 @@ impl Value {
                                                 first,
                                                 names,
                                                 enclosing_namespace,
-                                                &field.default,
+                                                field.default.as_ref(),
                                             )?,
                                         ),
                                     ),
@@ -1212,7 +1275,12 @@ impl Value {
                     },
                 };
                 value
-                    .resolve_internal(&field.schema, names, 
enclosing_namespace, &field.default)
+                    .resolve_internal(
+                        &field.schema,
+                        names,
+                        enclosing_namespace,
+                        field.default.as_ref(),
+                    )
                     .map(|value| (field.name.clone(), value))
             })
             .collect::<Result<Vec<_>, _>>()?;

Reply via email to