use core::fmt;
use crate::sys;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct SdkIndex(u32);
impl SdkIndex {
pub const ZERO: Self = Self(0);
#[must_use]
pub const fn new(raw: u32) -> Option<Self> {
if raw == sys::SCS_U32_NIL {
None
} else {
Some(Self(raw))
}
}
#[must_use]
pub const fn raw(self) -> u32 {
self.0
}
}
impl fmt::Display for SdkIndex {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(formatter)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct TrailerIndex(u32);
impl TrailerIndex {
pub const COUNT: usize = sys::configuration::MAX_TRAILERS;
pub const ZERO: Self = Self(0);
pub const ALL: [Self; Self::COUNT] = [
Self(0),
Self(1),
Self(2),
Self(3),
Self(4),
Self(5),
Self(6),
Self(7),
Self(8),
Self(9),
];
#[must_use]
pub fn new(raw: u32) -> Option<Self> {
match usize::try_from(raw) {
Ok(index) if index < Self::COUNT => Some(Self(raw)),
Ok(_) | Err(_) => None,
}
}
#[must_use]
pub const fn raw(self) -> u32 {
self.0
}
}
impl fmt::Display for TrailerIndex {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(formatter)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum TrailerConfigurationId {
Legacy,
Numbered(TrailerIndex),
}
impl TrailerConfigurationId {
#[must_use]
pub const fn index(self) -> Option<TrailerIndex> {
match self {
Self::Legacy => None,
Self::Numbered(index) => Some(index),
}
}
#[must_use]
pub const fn is_legacy(self) -> bool {
matches!(self, Self::Legacy)
}
}
const _: [(); TrailerIndex::COUNT] = [(); sys::configuration::MAX_TRAILERS];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sdk_index_excludes_only_the_scalar_sentinel() {
assert_eq!(SdkIndex::new(0), Some(SdkIndex::ZERO));
assert_eq!(SdkIndex::new(42).map(SdkIndex::raw), Some(42));
assert_eq!(SdkIndex::new(sys::SCS_U32_NIL), None);
}
#[test]
fn trailer_indices_match_the_official_header_range() {
assert_eq!(TrailerIndex::COUNT, 10);
assert_eq!(TrailerIndex::COUNT, sys::configuration::MAX_TRAILERS);
for (expected, index) in (0_u32..10).zip(TrailerIndex::ALL) {
assert_eq!(index.raw(), expected);
assert_eq!(TrailerIndex::new(expected), Some(index));
}
assert_eq!(TrailerIndex::new(10), None);
assert_eq!(TrailerIndex::new(u32::MAX), None);
}
#[test]
fn trailer_configuration_identity_keeps_legacy_separate() {
assert!(TrailerConfigurationId::Legacy.is_legacy());
assert_eq!(TrailerConfigurationId::Legacy.index(), None);
assert_eq!(
TrailerConfigurationId::Numbered(TrailerIndex::ZERO).index(),
Some(TrailerIndex::ZERO)
);
assert!(!TrailerConfigurationId::Numbered(TrailerIndex::ZERO).is_legacy());
}
}