use std::fmt;
use std::ops::Deref;
use std::str::from_utf8;
use serde::{Deserialize, Serialize};
use str0m_proto::Id;
use str0m_proto::NonCryptographicRng;
macro_rules! str_id {
($id:ident, $name:literal, $num:tt, $new_len:tt) => {
impl $id {
pub fn new() -> $id {
let mut arr = Id::<$num>::random().into_array();
for i in $new_len..$num {
arr[i] = b' ';
}
$id(arr)
}
pub const fn from_array(a: [u8; $num]) -> $id {
$id(a)
}
}
impl fmt::Display for $id {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s: &str = self;
write!(f, "{}", s)
}
}
impl fmt::Debug for $id {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s: &str = self;
write!(f, "{}({})", $name, s)
}
}
impl Deref for $id {
type Target = str;
fn deref(&self) -> &Self::Target {
from_utf8(&self.0).expect("ascii id").trim()
}
}
impl<'a> From<&'a str> for $id {
fn from(v: &'a str) -> Self {
let v = v
.chars()
.map(|c| if c.is_ascii_alphanumeric() { c } else { '_' })
.collect::<String>();
let bytes = v.as_bytes();
let bytes = &bytes[0..$num.min(bytes.len())];
let mut array = [b' '; $num];
let max = bytes.len().min(array.len());
(&mut array[0..max]).copy_from_slice(bytes);
$id(array)
}
}
impl Default for $id {
fn default() -> Self {
$id::new()
}
}
};
}
macro_rules! num_id {
($id:ident, $t:tt) => {
impl $id {
pub fn new() -> Self {
loop {
let v = NonCryptographicRng::$t();
if v != 0 {
return $id(v);
}
}
}
}
impl Deref for $id {
type Target = $t;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<$t> for $id {
fn from(v: $t) -> Self {
$id(v)
}
}
impl fmt::Display for $id {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
};
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Mid([u8; 16]);
str_id!(Mid, "Mid", 16, 3);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Rid([u8; 8]);
str_id!(Rid, "Rid", 8, 3);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Ssrc(u32);
num_id!(Ssrc, u32);
impl Ssrc {
pub fn is_probe(&self) -> bool {
self.0 == 0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Pt(u8);
num_id!(Pt, u8);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct SessionId(u64);
num_id!(SessionId, u64);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct SeqNo(u64);
num_id!(SeqNo, u64);
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, Default,
)]
pub struct TwccSeq(u64);
num_id!(TwccSeq, u64);
impl SeqNo {
pub(crate) const MAX: SeqNo = SeqNo(u64::MAX);
#[inline(always)]
pub fn is_next(&self, other: SeqNo) -> bool {
if **self >= *other {
return false;
}
*other - **self == 1
}
#[inline(always)]
pub fn inc(&mut self) -> SeqNo {
let n = SeqNo(self.0);
self.0 += 1;
n
}
#[inline(always)]
pub(crate) fn is_max(&self) -> bool {
self.0 == Self::MAX.0
}
#[inline(always)]
pub fn as_u16(&self) -> u16 {
self.0 as u16
}
#[inline(always)]
pub fn roc(&self) -> u64 {
self.0 >> 16
}
}
impl TwccSeq {
#[inline(always)]
pub fn is_next(&self, other: TwccSeq) -> bool {
if **self >= *other {
return false;
}
*other - **self == 1
}
#[inline(always)]
pub fn inc(&mut self) -> TwccSeq {
let n = TwccSeq(self.0);
self.0 += 1;
n
}
#[inline(always)]
pub fn as_u16(&self) -> u16 {
self.0 as u16
}
#[inline(always)]
pub fn roc(&self) -> u64 {
self.0 >> 16
}
}
impl Default for SeqNo {
fn default() -> Self {
Self((NonCryptographicRng::u16() % 32767 + 1) as u64)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub struct TwccClusterId(u64);
num_id!(TwccClusterId, u64);
impl TwccClusterId {
#[inline(always)]
pub fn inc(&mut self) -> TwccClusterId {
let n = TwccClusterId(self.0);
self.0 = self.0.wrapping_add(1);
n
}
}
impl Pt {
pub const fn new_with_value(v: u8) -> Pt {
Pt(v)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct MidRid(pub Mid, pub Option<Rid>);
impl MidRid {
#[inline(always)]
pub fn mid(&self) -> Mid {
self.0
}
#[inline(always)]
pub fn rid(&self) -> Option<Rid> {
self.1
}
pub fn special_equals(&self, other: &MidRid) -> bool {
self.0 == other.0 && (self.1.is_none() || self.1 == other.1)
}
}