use crate::packet::Handle;
use from_variants::FromVariants;
use std::{
fmt::Display,
marker::PhantomData,
sync::{Arc, RwLock},
};
use thiserror::Error;
#[derive(Debug, Clone)]
pub struct DataTrack<L> {
pub(crate) info: Arc<DataTrackInfo>,
pub(crate) inner: Arc<DataTrackInner>,
pub(crate) _location: PhantomData<L>,
}
#[derive(Debug, Clone, FromVariants)]
pub(crate) enum DataTrackInner {
Local(crate::local::LocalTrackInner),
Remote(crate::remote::RemoteTrackInner),
}
impl<L> DataTrack<L> {
pub fn info(&self) -> &DataTrackInfo {
&self.info
}
pub fn is_published(&self) -> bool {
match self.inner.as_ref() {
DataTrackInner::Local(inner) => inner.is_published(),
DataTrackInner::Remote(inner) => inner.is_published(),
}
}
pub async fn wait_for_unpublish(&self) {
match self.inner.as_ref() {
DataTrackInner::Local(inner) => inner.wait_for_unpublish().await,
DataTrackInner::Remote(inner) => inner.wait_for_unpublish().await,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(test, derive(fake::Dummy))]
pub struct DataTrackInfo {
pub(crate) sid: Arc<RwLock<DataTrackSid>>,
pub(crate) pub_handle: Handle,
pub(crate) name: String,
pub(crate) uses_e2ee: bool,
}
impl DataTrackInfo {
pub fn sid(&self) -> DataTrackSid {
self.sid.read().unwrap().clone()
}
pub fn name(&self) -> &str {
&self.name
}
pub fn uses_e2ee(&self) -> bool {
self.uses_e2ee
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct DataTrackSid(String);
#[derive(Debug, Error)]
#[error("Invalid data track SID")]
pub struct DataTrackSidError;
impl DataTrackSid {
const PREFIX: &str = "DTR_";
}
impl TryFrom<String> for DataTrackSid {
type Error = DataTrackSidError;
fn try_from(raw_id: String) -> Result<Self, Self::Error> {
if raw_id.starts_with(Self::PREFIX) {
Ok(Self(raw_id))
} else {
Err(DataTrackSidError)
}
}
}
impl From<DataTrackSid> for String {
fn from(id: DataTrackSid) -> Self {
id.0
}
}
impl Display for DataTrackSid {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[cfg(test)]
impl fake::Dummy<fake::Faker> for DataTrackSid {
fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &fake::Faker, rng: &mut R) -> Self {
const BASE_57_ALPHABET: &[u8; 57] =
b"23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
let random_id: String = (0..12)
.map(|_| {
let idx = rng.random_range(0..BASE_57_ALPHABET.len());
BASE_57_ALPHABET[idx] as char
})
.collect();
Self::try_from(format!("{}{}", Self::PREFIX, random_id)).unwrap()
}
}