#![doc = include_str!("crate.md")]
#![doc = include_str!("examples.md")]
#![cfg_attr(
not(any(test, feature = "arbitrary", feature = "bitcode", feature = "speedy",)),
no_std
)]
#[cfg(test)]
mod tests;
#[cfg(all(test, not(miri), feature = "arbitrary"))]
mod tests_prop;
#[cfg(kani)]
mod tests_kani;
#[cfg(all(test, not(miri)))]
mod tests_readme;
use core::cmp::Ordering;
use core::ops::Add;
#[doc = include_str!("examples.md")]
#[must_use]
#[repr(transparent)]
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "bincode", derive(bincode::Decode, bincode::Encode))]
#[cfg_attr(feature = "bitcode", derive(bitcode::Decode, bitcode::Encode))]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshDeserialize, borsh::BorshSerialize)
)]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
#[cfg_attr(
feature = "postcard",
derive(
postcard::experimental::max_size::MaxSize,
postcard::experimental::schema::Schema
)
)]
#[cfg_attr(
feature = "rkyv",
derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize),
archive(compare(PartialEq)),
archive_attr(derive(Clone, Copy, Debug))
)]
#[cfg_attr(feature = "rkyv-safe", archive(check_bytes))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))]
pub struct Serial(u16);
const NAN_U16: u16 = u16::MAX;
const NAN_U32: u32 = 65_535;
const MAX_U16: u16 = u16::MAX - 1;
const MID_I32: i32 = 32_767;
const MID_U16: u16 = 32_767;
impl Serial {
pub const NAN: Self = Self(NAN_U16);
#[inline]
#[must_use]
pub fn is_nan(self) -> bool {
self == Self::NAN
}
#[inline]
pub fn increase(&mut self) {
if self.is_nan() {
return;
}
if self.0 < MAX_U16 {
self.0 += 1;
} else {
self.0 = 0; }
}
#[inline]
pub fn increase_get(&mut self) -> Self {
self.increase();
*self
}
#[inline]
pub fn get_increase(&mut self) -> Self {
let num = *self;
self.increase();
num
}
#[inline]
#[must_use]
pub fn dist(self, other: Self) -> u16 {
if self.is_nan() && other.is_nan() {
return 0;
}
if self.is_nan() || other.is_nan() {
return MID_U16; }
if self.0 == other.0 {
return 0;
}
let min = self.min(other);
let max = self.max(other);
if min.0 < max.0 {
max.0 - min.0
} else {
MAX_U16 - min.0 + max.0 + 1
}
}
#[inline]
#[must_use]
pub fn diff(self, other: Self) -> i16 {
let dist = self.dist(other);
if self.precedes(other) {
-(dist as i16)
} else {
dist as i16
}
}
#[inline]
pub fn min(self, other: Self) -> Self {
match self.partial_cmp(other) {
Some(Ordering::Less) => self,
Some(_) => other,
None if self.is_nan() => other,
None => self,
}
}
#[inline]
pub fn max(self, other: Self) -> Self {
match self.partial_cmp(other) {
Some(Ordering::Greater) => self,
Some(_) => other,
None if self.is_nan() => other,
None => self,
}
}
#[inline]
#[must_use]
pub fn partial_cmp(self, other: Self) -> Option<Ordering> {
if self.is_nan() || other.is_nan() {
return None;
}
if self.0 == other.0 {
return Some(Ordering::Equal);
}
let a = i32::from(self.0);
let b = i32::from(other.0);
if (b > a && b - a <= MID_I32) || (a > b && a - b > MID_I32) {
Some(Ordering::Less)
} else {
Some(Ordering::Greater)
}
}
#[inline]
#[must_use]
pub fn precedes(self, other: Self) -> bool {
self.partial_cmp(other) == Some(Ordering::Less)
}
#[inline]
#[must_use]
pub fn precedes_or_eq(self, other: Self) -> bool {
match self.partial_cmp(other) {
Some(Ordering::Less | Ordering::Equal) => true,
Some(Ordering::Greater) | None => false,
}
}
#[inline]
#[must_use]
pub fn succeeds(self, other: Self) -> bool {
self.partial_cmp(other) == Some(Ordering::Greater)
}
#[inline]
#[must_use]
pub fn succeeds_or_eq(self, other: Self) -> bool {
match self.partial_cmp(other) {
Some(Ordering::Greater | Ordering::Equal) => true,
Some(Ordering::Less) | None => false,
}
}
#[inline]
pub fn or(self, other: Self) -> Self {
if self.is_nan() {
other
} else {
self
}
}
#[inline]
pub fn or_default(self) -> Self {
if self.is_nan() {
Self::default()
} else {
self
}
}
#[inline]
pub fn take(&mut self) -> Self {
core::mem::replace(self, Self::NAN)
}
}
impl Add<u16> for Serial {
type Output = Serial;
#[inline]
fn add(self, rhs: u16) -> Self::Output {
if self.is_nan() {
return self;
}
let n = (u32::from(self.0) + u32::from(rhs)) % (NAN_U32);
Self(n as u16)
}
}