use livekit_common::ParticipantIdentity;
use std::{collections::HashMap, fmt, sync::Arc};
use crate::{
types::{OperationType, StreamId, TextHeader},
utils::StreamProgress,
};
pub(crate) mod manager;
mod constants;
mod raw_stream;
mod stream_writer;
pub use stream_writer::{ByteStreamWriter, StreamWriter, TextStreamWriter};
#[derive(Clone)]
pub struct StreamProgressCallback(Arc<dyn Fn(StreamProgress) + Send + Sync>);
impl StreamProgressCallback {
pub fn new(callback: impl Fn(StreamProgress) + Send + Sync + 'static) -> Self {
Self(Arc::new(callback))
}
pub fn call(&self, progress: StreamProgress) {
(self.0)(progress);
}
}
impl fmt::Debug for StreamProgressCallback {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("StreamProgressCallback")
}
}
impl PartialEq for StreamProgressCallback {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}
impl Eq for StreamProgressCallback {}
macro_rules! common_setters {
() => {
pub fn with_topic(mut self, topic: impl Into<String>) -> Self {
self.topic = topic.into();
self
}
pub fn with_attributes(mut self, attributes: HashMap<String, String>) -> Self {
self.attributes = attributes;
self
}
pub fn with_attribute(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.attributes.insert(key.into(), value.into());
self
}
pub fn with_destination_identities(
mut self,
destination_identities: Vec<ParticipantIdentity>,
) -> Self {
self.destination_identities = destination_identities;
self
}
pub fn with_destination_identity(
mut self,
identity: impl Into<ParticipantIdentity>,
) -> Self {
self.destination_identities.push(identity.into());
self
}
pub fn with_id(mut self, id: impl Into<String>) -> Self {
self.id = Some(id.into());
self
}
pub fn with_sender_identity(mut self, identity: impl Into<ParticipantIdentity>) -> Self {
self.sender_identity = Some(identity.into());
self
}
};
}
macro_rules! text_setters {
() => {
pub(crate) fn text_header(&self) -> TextHeader {
TextHeader {
operation_type: self.operation_type.unwrap_or_default(),
version: self.version.unwrap_or_default(),
reply_to_stream_id: self.reply_to_stream_id.clone().map(StreamId::from),
attached_stream_ids: self
.attached_stream_ids
.clone()
.into_iter()
.map(StreamId::from)
.collect(),
generated: self.generated.unwrap_or_default(),
}
}
pub fn with_operation_type(mut self, operation_type: OperationType) -> Self {
self.operation_type = Some(operation_type);
self
}
pub fn with_version(mut self, version: i32) -> Self {
self.version = Some(version);
self
}
pub fn with_reply_to_stream_id(mut self, reply_to_stream_id: impl Into<String>) -> Self {
self.reply_to_stream_id = Some(reply_to_stream_id.into());
self
}
pub fn with_attached_stream_ids(mut self, attached_stream_ids: Vec<String>) -> Self {
self.attached_stream_ids = attached_stream_ids;
self
}
pub fn with_attached_stream_id(mut self, attached_stream_id: impl Into<String>) -> Self {
self.attached_stream_ids.push(attached_stream_id.into());
self
}
pub fn with_generated(mut self, generated: bool) -> Self {
self.generated = Some(generated);
self
}
};
}
macro_rules! byte_setters {
() => {
pub fn with_mime_type(mut self, mime_type: impl Into<String>) -> Self {
self.mime_type = Some(mime_type.into());
self
}
pub fn with_name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
};
}
macro_rules! send_setters {
() => {
pub fn with_compress(mut self, compress: bool) -> Self {
self.compress = Some(compress);
self
}
pub fn with_on_progress(
mut self,
callback: impl Fn(StreamProgress) + Send + Sync + 'static,
) -> Self {
self.on_progress = Some(StreamProgressCallback::new(callback));
self
}
};
}
macro_rules! stream_setters {
() => {
pub fn with_total_length(mut self, total_length: u64) -> Self {
self.total_length = Some(total_length);
self
}
};
}
#[non_exhaustive]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SendTextOptions {
pub topic: String,
pub attributes: HashMap<String, String>,
pub destination_identities: Vec<ParticipantIdentity>,
pub id: Option<String>,
pub operation_type: Option<OperationType>,
pub version: Option<i32>,
pub reply_to_stream_id: Option<String>,
pub attached_stream_ids: Vec<String>,
pub generated: Option<bool>,
pub sender_identity: Option<ParticipantIdentity>,
pub compress: Option<bool>,
pub on_progress: Option<StreamProgressCallback>,
}
impl SendTextOptions {
pub fn new_with_topic(topic: impl Into<String>) -> Self {
Self {
topic: topic.into(),
attributes: HashMap::new(),
destination_identities: vec![],
id: None,
operation_type: None,
version: None,
reply_to_stream_id: None,
attached_stream_ids: vec![],
generated: None,
sender_identity: None,
compress: None,
on_progress: None,
}
}
common_setters!();
text_setters!();
send_setters!();
}
#[non_exhaustive]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SendByteOptions {
pub topic: String,
pub attributes: HashMap<String, String>,
pub destination_identities: Vec<ParticipantIdentity>,
pub id: Option<String>,
pub mime_type: Option<String>,
pub name: Option<String>,
pub sender_identity: Option<ParticipantIdentity>,
pub compress: Option<bool>,
pub on_progress: Option<StreamProgressCallback>,
}
impl SendByteOptions {
pub fn new_with_topic(topic: impl Into<String>) -> Self {
Self {
topic: topic.into(),
attributes: HashMap::new(),
destination_identities: vec![],
id: None,
mime_type: None,
name: None,
sender_identity: None,
compress: None,
on_progress: None,
}
}
common_setters!();
byte_setters!();
send_setters!();
}
#[non_exhaustive]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct StreamTextOptions {
pub topic: String,
pub attributes: HashMap<String, String>,
pub destination_identities: Vec<ParticipantIdentity>,
pub id: Option<String>,
pub operation_type: Option<OperationType>,
pub version: Option<i32>,
pub reply_to_stream_id: Option<String>,
pub attached_stream_ids: Vec<String>,
pub generated: Option<bool>,
pub sender_identity: Option<ParticipantIdentity>,
pub total_length: Option<u64>,
}
impl StreamTextOptions {
pub fn new_with_topic(topic: impl Into<String>) -> Self {
Self {
topic: topic.into(),
attributes: HashMap::new(),
destination_identities: vec![],
id: None,
operation_type: None,
version: None,
reply_to_stream_id: None,
attached_stream_ids: vec![],
generated: None,
sender_identity: None,
total_length: None,
}
}
common_setters!();
text_setters!();
stream_setters!();
}
#[non_exhaustive]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct StreamByteOptions {
pub topic: String,
pub attributes: HashMap<String, String>,
pub destination_identities: Vec<ParticipantIdentity>,
pub id: Option<String>,
pub mime_type: Option<String>,
pub name: Option<String>,
pub sender_identity: Option<ParticipantIdentity>,
pub total_length: Option<u64>,
}
impl StreamByteOptions {
pub fn new_with_topic(topic: impl Into<String>) -> Self {
Self {
topic: topic.into(),
attributes: HashMap::new(),
destination_identities: vec![],
id: None,
mime_type: None,
name: None,
sender_identity: None,
total_length: None,
}
}
common_setters!();
byte_setters!();
stream_setters!();
}