Files
markbase/vendor/smb2/src/pack/guid.rs
Warren 7eb528d35f
Some checks failed
Test / build (push) Has been cancelled
Test / test (push) Has been cancelled
SMB Server Phase 2: VFS backend build fix + integration test
- Add VfsFile: Send supertrait for Mutex compatibility
- Fix SmbServerCommand: struct → Subcommand enum with Start variant
- Fix tracing_subscriber::init() → try_init() to avoid panic when
  logger already initialized
- Fix CLI subcommand name: smb-server → smb-start (flatten naming)
- Add #[command(name = "smb-start")] for CLI disambiguation
- Fix unused variable warnings (smb_fs.rs, smb_server_backend.rs)
- Remove unused VfsFile imports (webdav.rs, scp_handler.rs)
- Integration test: Docker smbclient verified (list, upload, read)
2026-06-20 19:42:29 +08:00

177 lines
4.9 KiB
Rust

//! GUID (Globally Unique Identifier) type for SMB2.
//!
//! GUIDs follow the mixed-endian layout defined in MS-DTYP section 2.3.4:
//! - Bytes 0-3: `data1` (`u32`, little-endian)
//! - Bytes 4-5: `data2` (`u16`, little-endian)
//! - Bytes 6-7: `data3` (`u16`, little-endian)
//! - Bytes 8-15: `data4` (8 raw bytes, big-endian order)
use std::fmt;
use super::{Pack, ReadCursor, Unpack, WriteCursor};
use crate::error::Result;
/// A 128-bit GUID in mixed-endian wire format (MS-DTYP 2.3.4).
///
/// With the `serde` feature on, the JSON form mirrors the in-memory
/// field shape (`{data1, data2, data3, data4}`), **not** the wire byte
/// order — the wire layout is mixed-endian and round-tripping it through
/// JSON would just be confusing.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct Guid {
/// First component (bytes 0-3, little-endian on wire).
pub data1: u32,
/// Second component (bytes 4-5, little-endian on wire).
pub data2: u16,
/// Third component (bytes 6-7, little-endian on wire).
pub data3: u16,
/// Fourth component (bytes 8-15, raw byte order on wire).
pub data4: [u8; 8],
}
impl Guid {
/// The NULL GUID: `{00000000-0000-0000-0000-000000000000}`.
pub const ZERO: Self = Self {
data1: 0,
data2: 0,
data3: 0,
data4: [0; 8],
};
}
impl Pack for Guid {
fn pack(&self, cursor: &mut WriteCursor) {
cursor.write_u32_le(self.data1);
cursor.write_u16_le(self.data2);
cursor.write_u16_le(self.data3);
cursor.write_bytes(&self.data4);
}
}
impl Unpack for Guid {
fn unpack(cursor: &mut ReadCursor<'_>) -> Result<Self> {
let data1 = cursor.read_u32_le()?;
let data2 = cursor.read_u16_le()?;
let data3 = cursor.read_u16_le()?;
let raw = cursor.read_bytes(8)?;
let mut data4 = [0u8; 8];
data4.copy_from_slice(raw);
Ok(Self {
data1,
data2,
data3,
data4,
})
}
}
impl fmt::Display for Guid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{{{:08x}-{:04x}-{:04x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}}}",
self.data1,
self.data2,
self.data3,
self.data4[0],
self.data4[1],
self.data4[2],
self.data4[3],
self.data4[4],
self.data4[5],
self.data4[6],
self.data4[7],
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn unpack_null_guid() {
let bytes = [0u8; 16];
let mut cursor = ReadCursor::new(&bytes);
let guid = Guid::unpack(&mut cursor).unwrap();
assert_eq!(guid, Guid::ZERO);
}
#[test]
fn pack_null_guid() {
let mut cursor = WriteCursor::new();
Guid::ZERO.pack(&mut cursor);
assert_eq!(cursor.as_bytes(), &[0u8; 16]);
}
#[test]
fn roundtrip_known_guid() {
let guid = Guid {
data1: 0x6BA7B810,
data2: 0x9DAD,
data3: 0x11D1,
data4: [0x80, 0xB4, 0x00, 0xC0, 0x4F, 0xD4, 0x30, 0xC8],
};
let mut w = WriteCursor::new();
guid.pack(&mut w);
let mut r = ReadCursor::new(w.as_bytes());
let unpacked = Guid::unpack(&mut r).unwrap();
assert_eq!(unpacked, guid);
}
#[test]
fn display_format() {
let guid = Guid {
data1: 0x6BA7B810,
data2: 0x9DAD,
data3: 0x11D1,
data4: [0x80, 0xB4, 0x00, 0xC0, 0x4F, 0xD4, 0x30, 0xC8],
};
assert_eq!(guid.to_string(), "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}");
}
#[test]
fn display_null_guid() {
assert_eq!(
Guid::ZERO.to_string(),
"{00000000-0000-0000-0000-000000000000}"
);
}
#[test]
fn mixed_endian_byte_ordering() {
// Build a GUID with known values and verify the wire bytes directly.
let guid = Guid {
data1: 0x04030201,
data2: 0x0605,
data3: 0x0807,
data4: [0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10],
};
let mut w = WriteCursor::new();
guid.pack(&mut w);
let bytes = w.as_bytes();
// data1: u32 LE -> 01 02 03 04
assert_eq!(&bytes[0..4], &[0x01, 0x02, 0x03, 0x04]);
// data2: u16 LE -> 05 06
assert_eq!(&bytes[4..6], &[0x05, 0x06]);
// data3: u16 LE -> 07 08
assert_eq!(&bytes[6..8], &[0x07, 0x08]);
// data4: raw bytes -> 09 0A 0B 0C 0D 0E 0F 10
assert_eq!(
&bytes[8..16],
&[0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10]
);
}
#[test]
fn unpack_insufficient_bytes() {
let bytes = [0u8; 10]; // need 16
let mut cursor = ReadCursor::new(&bytes);
assert!(Guid::unpack(&mut cursor).is_err());
}
}