// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 //! Layout handle type encoding worker ID and layout ID. use bincode::{Decode, Encode}; use serde::{Deserialize, Serialize}; /// Unique handle for a layout combining worker_id and layout_id. /// /// The handle encodes: /// - Bits 0-63: worker_id (u64) /// - Bits 64-79: layout_id (u16) /// - Bits 80-127: Reserved (48 bits, currently unused) #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode, Serialize, Deserialize)] pub struct LayoutHandle(u128); impl LayoutHandle { /// Create a new layout handle from worker_id and layout_id. /// /// # Arguments /// * `worker_id` - Unique identifier for the worker (0-63 bits) /// * `layout_id` - Layout identifier within the worker (64-79 bits) pub fn new(worker_id: u64, layout_id: u16) -> Self { let handle = (worker_id as u128) | ((layout_id as u128) << 64); Self(handle) } /// Extract the worker_id from this handle. pub fn worker_id(&self) -> u64 { (self.0 & 0xFFFF_FFFF_FFFF_FFFF) as u64 } /// Extract the layout_id from this handle. pub fn layout_id(&self) -> u16 { ((self.0 >> 64) & 0xFFFF) as u16 } /// Get the raw u128 value. pub fn as_u128(&self) -> u128 { self.0 } /// Reconstruct a handle from a raw u128 value. /// /// This preserves all bits including reserved bits, and is intended for /// deserialization roundtrips with `as_u128()`. pub fn from_u128(value: u128) -> Self { Self(value) } } impl std::fmt::Display for LayoutHandle { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "LayoutHandle(worker={}, layout={})", self.worker_id(), self.layout_id() ) } } #[cfg(all(test, feature = "testing-kvbm"))] mod tests { use super::*; #[test] fn test_handle_encoding() { let worker_id = 0x1234_5678_9ABC_DEF0u64; let layout_id = 0x4242u16; let handle = LayoutHandle::new(worker_id, layout_id); assert_eq!(handle.worker_id(), worker_id); assert_eq!(handle.layout_id(), layout_id); } #[test] fn test_handle_roundtrip() { let handle = LayoutHandle::new(42, 100); let raw = handle.as_u128(); let restored = LayoutHandle::from_u128(raw); assert_eq!(handle, restored); assert_eq!(restored.worker_id(), 42); assert_eq!(restored.layout_id(), 100); } #[test] fn test_handle_max_values() { let max_worker = u64::MAX; let max_layout = u16::MAX; let handle = LayoutHandle::new(max_worker, max_layout); assert_eq!(handle.worker_id(), max_worker); assert_eq!(handle.layout_id(), max_layout); } #[test] fn test_handle_bincode_roundtrip() { let handle = LayoutHandle::new(999, 42); let encoded = bincode::encode_to_vec(handle, bincode::config::standard()).unwrap(); let (decoded, _): (LayoutHandle, _) = bincode::decode_from_slice(&encoded, bincode::config::standard()).unwrap(); assert_eq!(handle, decoded); } #[test] fn test_handle_display() { let handle = LayoutHandle::new(123, 456); let display = format!("{}", handle); assert!(display.contains("123")); assert!(display.contains("456")); } }