use serde::{Deserialize, Serialize}; pub const OPAQUE_ID_BYTES: usize = 32; pub const SHA256_BYTES: usize = 32; macro_rules! opaque_identity { ($($name:ident),+ $(,)?) => { $( #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct $name([u8; OPAQUE_ID_BYTES]); impl $name { #[must_use] pub const fn new(bytes: [u8; OPAQUE_ID_BYTES]) -> Self { Self(bytes) } #[must_use] pub const fn as_bytes(&self) -> &[u8; OPAQUE_ID_BYTES] { &self.0 } } )+ }; } macro_rules! digest_identity { ($($name:ident),+ $(,)?) => { $( #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct $name([u8; SHA256_BYTES]); impl $name { #[must_use] pub const fn new(bytes: [u8; SHA256_BYTES]) -> Self { Self(bytes) } #[must_use] pub const fn as_bytes(&self) -> &[u8; SHA256_BYTES] { &self.0 } } )+ }; } macro_rules! numeric_identity { ($($name:ident($inner:ty)),+ $(,)?) => { $( #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct $name($inner); impl $name { #[must_use] pub const fn new(value: $inner) -> Self { Self(value) } #[must_use] pub const fn get(self) -> $inner { self.0 } } )+ }; } opaque_identity!( DomainId, CoordinatorId, NetworkSidecarId, SandboxId, ClientId, SessionId, SessionAnchorId, RequestId, PreparedArtifactId, PrepareOperationId, ProtocolCredentialId, CapabilityId, ContainerId, PolicyId, ); digest_identity!( ConfigurationFingerprint, DerivedPolicyDigest, ReadinessFingerprint, BundleDigest, SelectedManifestDigest, IdMapDigest, CertificateDigest, TrustManifestDigest, RequestDigest, StreamDigest, ); numeric_identity!( GenerationId(u64), ProcessId(u32), ProcessStartTime(u64), GuestProcessGroupId(u32), FileDescriptor(i32), DeviceId(u64), InodeId(u64), MountId(u64), ); #[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct HostPath(Vec); impl HostPath { #[must_use] pub const fn new(bytes: Vec) -> Self { Self(bytes) } #[must_use] pub fn as_bytes(&self) -> &[u8] { &self.0 } } #[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct SourceIdentity(Vec); impl SourceIdentity { #[must_use] pub const fn new(bytes: Vec) -> Self { Self(bytes) } #[must_use] pub fn as_bytes(&self) -> &[u8] { &self.0 } } #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct ProcessIdentity { pub pid: ProcessId, pub start_time: ProcessStartTime, } #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct NamespaceIdentity { pub device: DeviceId, pub inode: InodeId, } #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct MountIdentity { pub mount_id: MountId, pub device: DeviceId, pub inode: InodeId, } #[cfg(test)] mod tests { use std::any::TypeId; use std::collections::HashSet; use super::{ ContainerId, CoordinatorId, DomainId, GenerationId, MountIdentity, NamespaceIdentity, NetworkSidecarId, PreparedArtifactId, ProcessIdentity, RequestId, SandboxId, SessionId, }; #[test] fn identity_categories_are_nominally_distinct() { let identities = [ TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), ]; assert_eq!( identities.into_iter().collect::>().len(), identities.len() ); } }