Fix UUID handling in Rust Thrift compact protocol (#3179)
This commit fixes two bugs in the Rust Thrift implementation that prevented
UUID fields from working correctly with the compact protocol:
1. Missing UUID case in skip_till_depth function
- The skip function in lib/rs/src/protocol/mod.rs did not handle TType::Uuid
- This caused "cannot skip field type Uuid" errors when trying to skip UUID fields
- Fixed by adding: TType::Uuid => self.read_uuid().map(|_| ())
2. Incorrect UUID serialization in compact protocol
- The compact protocol was using read_bytes()/write_bytes() for UUIDs
- These methods include a length prefix, but UUIDs should be transmitted as
raw 16-byte values per the Thrift specification
- This caused "don't know what type: 15" errors during cross-language tests
- Fixed by reading/writing UUID bytes directly without length prefix
- Implementation now matches the binary protocol's approach for consistency
The bug manifested as failures in cross-language tests between Go and Rust
when using compact protocol. The error occurred because Go correctly expected
raw 16-byte UUID values while Rust was incorrectly adding a length prefix.
Testing:
- Verified all go-rs and rs-go cross tests now pass with compact protocol
- Tests confirm UUID values are correctly serialized and deserialized
- Both buffered and framed transports work correctly
diff --git a/lib/rs/src/protocol/compact.rs b/lib/rs/src/protocol/compact.rs
index 7e1a751..d47df5d 100644
--- a/lib/rs/src/protocol/compact.rs
+++ b/lib/rs/src/protocol/compact.rs
@@ -301,7 +301,11 @@
}
fn read_uuid(&mut self) -> crate::Result<uuid::Uuid> {
- uuid::Uuid::from_slice(&self.read_bytes()?).map_err(From::from)
+ let mut buf = [0u8; 16];
+ self.transport
+ .read_exact(&mut buf)
+ .map(|_| uuid::Uuid::from_bytes(buf))
+ .map_err(From::from)
}
fn read_string(&mut self) -> crate::Result<String> {
@@ -621,7 +625,9 @@
}
fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> {
- self.write_bytes(uuid.as_bytes())
+ self.transport
+ .write_all(uuid.as_bytes())
+ .map_err(From::from)
}
fn write_string(&mut self, s: &str) -> crate::Result<()> {
diff --git a/lib/rs/src/protocol/mod.rs b/lib/rs/src/protocol/mod.rs
index 573978a..0fbf509 100644
--- a/lib/rs/src/protocol/mod.rs
+++ b/lib/rs/src/protocol/mod.rs
@@ -209,6 +209,7 @@
TType::I64 => self.read_i64().map(|_| ()),
TType::Double => self.read_double().map(|_| ()),
TType::String => self.read_string().map(|_| ()),
+ TType::Uuid => self.read_uuid().map(|_| ()),
TType::Struct => {
self.read_struct_begin()?;
loop {