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

Kriskras99 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 3e0ab4b  feat: Optimize UUID decoding in `decode.rs` (#663)
3e0ab4b is described below

commit 3e0ab4b718e2cc6421516d844234f2ada7cd7f5b
Author: Kriskras99 <[email protected]>
AuthorDate: Mon Sep 7 22:30:35 2026 +0200

    feat: Optimize UUID decoding in `decode.rs` (#663)
    
    * feat: Optimize UUID decoding in `decode.rs`
    
    This way we don't have to do any allocations or check that the bytes
    are valid UTF-8.
    
    * fix: Wrong error message
    
    * fix: Leftover imports after rebase
---
 avro/src/decode.rs | 72 +++++++++++++++++++++++-------------------------------
 avro/src/error.rs  |  6 +++++
 2 files changed, 37 insertions(+), 41 deletions(-)

diff --git a/avro/src/decode.rs b/avro/src/decode.rs
index 24d61d2..00b8b67 100644
--- a/avro/src/decode.rs
+++ b/avro/src/decode.rs
@@ -17,7 +17,7 @@
 
 use crate::schema::{InnerDecimalSchema, NamespaceRef, UuidSchema};
 use crate::{
-    AvroResult, Error,
+    AvroResult,
     bigdecimal::deserialize_big_decimal,
     decimal::Decimal,
     duration::Duration,
@@ -29,11 +29,7 @@ use crate::{
         safe_collection_len, safe_len, zag_i32, zag_i64,
     },
 };
-use std::{
-    borrow::Borrow,
-    collections::HashMap,
-    io::{ErrorKind, Read},
-};
+use std::{borrow::Borrow, collections::HashMap, io::Read};
 use uuid::Uuid;
 
 #[inline]
@@ -216,46 +212,40 @@ fn decode_internal_body<R: Read, S: Borrow<Schema>>(
             }
         }
         Schema::Uuid(UuidSchema::String) => {
-            let Value::String(string) =
-                decode_internal(&Schema::String, names, enclosing_namespace, 
reader, ctx)?
-            else {
-                // decoding a String can also return a Null, indicating EOF
-                return Err(Error::new(Details::ReadBytes(std::io::Error::from(
-                    ErrorKind::UnexpectedEof,
-                ))));
-            };
-            let uuid = 
Uuid::parse_str(&string).map_err(Details::ConvertStrToUuid)?;
-            Ok(Value::Uuid(uuid))
+            let len = decode_len(reader)?;
+            if len <= uuid::fmt::Urn::LENGTH {
+                let mut buf = [0u8; uuid::fmt::Urn::LENGTH];
+                reader
+                    .read_exact(&mut buf[..len])
+                    .map_err(Details::ReadString)?;
+                let uuid = 
Uuid::try_parse_ascii(&buf[..len]).map_err(Details::ConvertStrToUuid)?;
+                Ok(Value::Uuid(uuid))
+            } else {
+                Err(Details::ConvertStringToUuid(uuid::fmt::Urn::LENGTH, 
len).into())
+            }
         }
         Schema::Uuid(UuidSchema::Bytes) => {
-            let Value::Bytes(bytes) =
-                decode_internal(&Schema::Bytes, names, enclosing_namespace, 
reader, ctx)?
-            else {
-                unreachable!(
-                    "decode_internal(Schema::Bytes) can only return a 
Value::Bytes or an error"
-                )
-            };
-            let uuid = 
Uuid::from_slice(&bytes).map_err(Details::ConvertSliceToUuid)?;
-            Ok(Value::Uuid(uuid))
+            let len = decode_len(reader)?;
+            if len == 16 {
+                let mut buf = [0u8; 16];
+                reader.read_exact(&mut buf).map_err(Details::ReadBytes)?;
+                let uuid = 
Uuid::from_slice(&buf).map_err(Details::ConvertSliceToUuid)?;
+                Ok(Value::Uuid(uuid))
+            } else {
+                Err(Details::ConvertBytesToUuid(len).into())
+            }
         }
         Schema::Uuid(UuidSchema::Fixed(fixed)) => {
-            let Value::Fixed(n, bytes) = decode_internal(
-                &Schema::Fixed(fixed.copy_only_size()),
-                names,
-                enclosing_namespace,
-                reader,
-                ctx,
-            )?
-            else {
-                unreachable!(
-                    "decode_internal(Schema::Fixed) can only return a 
Value::Fixed or an error"
-                )
-            };
-            if n != 16 {
-                return Err(Details::ConvertFixedToUuid(n).into());
+            if fixed.size == 16 {
+                let mut buf = [0u8; 16];
+                reader
+                    .read_exact(&mut buf)
+                    .map_err(|e| Details::ReadFixed(e, 16))?;
+                let uuid = 
Uuid::from_slice(&buf).map_err(Details::ConvertSliceToUuid)?;
+                Ok(Value::Uuid(uuid))
+            } else {
+                Err(Details::ConvertFixedToUuid(fixed.size).into())
             }
-            let uuid = 
Uuid::from_slice(&bytes).map_err(Details::ConvertSliceToUuid)?;
-            Ok(Value::Uuid(uuid))
         }
         Schema::Int => decode_int(reader),
         Schema::Date => zag_i32(reader).map(Value::Date),
diff --git a/avro/src/error.rs b/avro/src/error.rs
index 0c05913..58f9145 100644
--- a/avro/src/error.rs
+++ b/avro/src/error.rs
@@ -156,6 +156,12 @@ pub enum Details {
     #[error("Failed to convert Fixed bytes to UUID. It must be exactly 16 
bytes, got {0}")]
     ConvertFixedToUuid(usize),
 
+    #[error("Failed to convert Bytes to UUID. It must be exactly 16 bytes, got 
{0}")]
+    ConvertBytesToUuid(usize),
+
+    #[error("Failed to convert String to UUID. Expected at most {0} bytes, got 
{0}")]
+    ConvertStringToUuid(usize, usize),
+
     #[error("Failed to convert Fixed bytes to UUID: {0}")]
     ConvertSliceToUuid(#[source] uuid::Error),
 

Reply via email to