livekit_datatrack/
track.rs1use crate::{
16 packet::Handle,
17 schema::{DataTrackFrameEncoding, DataTrackSchemaId},
18};
19use from_variants::FromVariants;
20use std::{
21 fmt::Display,
22 marker::PhantomData,
23 sync::{Arc, RwLock},
24};
25use thiserror::Error;
26
27#[derive(Debug, Clone)]
29pub struct DataTrack<L> {
30 pub(crate) info: Arc<DataTrackInfo>,
31 pub(crate) inner: Arc<DataTrackInner>,
32 pub(crate) _location: PhantomData<L>,
34}
35
36#[derive(Debug, Clone, FromVariants)]
37pub(crate) enum DataTrackInner {
38 Local(crate::local::LocalTrackInner),
39 Remote(crate::remote::RemoteTrackInner),
40}
41
42impl<L> DataTrack<L> {
43 pub fn info(&self) -> &DataTrackInfo {
45 &self.info
46 }
47
48 pub fn is_published(&self) -> bool {
50 match self.inner.as_ref() {
51 DataTrackInner::Local(inner) => inner.is_published(),
52 DataTrackInner::Remote(inner) => inner.is_published(),
53 }
54 }
55
56 pub async fn wait_for_unpublish(&self) {
62 match self.inner.as_ref() {
63 DataTrackInner::Local(inner) => inner.wait_for_unpublish().await,
64 DataTrackInner::Remote(inner) => inner.wait_for_unpublish().await,
65 }
66 }
67}
68
69#[derive(Debug, Clone)]
71#[cfg_attr(test, derive(fake::Dummy))]
72pub struct DataTrackInfo {
73 pub(crate) sid: Arc<RwLock<DataTrackSid>>,
74 pub(crate) pub_handle: Handle,
75 pub(crate) name: String,
76 pub(crate) uses_e2ee: bool,
77 pub(crate) schema: Option<DataTrackSchemaId>,
78 pub(crate) frame_encoding: Option<DataTrackFrameEncoding>,
79}
80
81impl DataTrackInfo {
82 pub fn sid(&self) -> DataTrackSid {
88 self.sid.read().unwrap().clone()
89 }
90
91 pub fn name(&self) -> &str {
93 &self.name
94 }
95
96 pub fn uses_e2ee(&self) -> bool {
98 self.uses_e2ee
99 }
100
101 pub fn schema(&self) -> Option<&DataTrackSchemaId> {
107 self.schema.as_ref()
108 }
109
110 pub fn frame_encoding(&self) -> Option<&DataTrackFrameEncoding> {
116 self.frame_encoding.as_ref()
117 }
118}
119
120#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
122pub struct DataTrackSid(String);
123
124#[derive(Debug, Error)]
125#[error("Invalid data track SID")]
126pub struct DataTrackSidError;
127
128impl DataTrackSid {
129 const PREFIX: &str = "DTR_";
130}
131
132impl TryFrom<String> for DataTrackSid {
133 type Error = DataTrackSidError;
134
135 fn try_from(raw_id: String) -> Result<Self, Self::Error> {
136 if raw_id.starts_with(Self::PREFIX) {
137 Ok(Self(raw_id))
138 } else {
139 Err(DataTrackSidError)
140 }
141 }
142}
143
144impl From<DataTrackSid> for String {
145 fn from(id: DataTrackSid) -> Self {
146 id.0
147 }
148}
149
150impl Display for DataTrackSid {
151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152 write!(f, "{}", self.0)
153 }
154}
155
156#[cfg(test)]
157impl fake::Dummy<fake::Faker> for DataTrackSid {
158 fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &fake::Faker, rng: &mut R) -> Self {
159 const BASE_57_ALPHABET: &[u8; 57] =
160 b"23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
161 let random_id: String = (0..12)
162 .map(|_| {
163 let idx = rng.random_range(0..BASE_57_ALPHABET.len());
164 BASE_57_ALPHABET[idx] as char
165 })
166 .collect();
167 Self::try_from(format!("{}{}", Self::PREFIX, random_id)).unwrap()
168 }
169}