use from_variants::FromVariants;
use livekit_common::EncryptionType;
use livekit_protocol::data_stream as proto;
use std::collections::HashMap;
use super::StreamId;
#[derive(Clone, Copy, Default, Debug, Hash, Eq, PartialEq)]
pub enum OperationType {
#[default]
Create,
Update,
Delete,
Reaction,
}
impl From<proto::OperationType> for OperationType {
fn from(value: proto::OperationType) -> Self {
match value {
proto::OperationType::Create => Self::Create,
proto::OperationType::Update => Self::Update,
proto::OperationType::Delete => Self::Delete,
proto::OperationType::Reaction => Self::Reaction,
}
}
}
impl From<OperationType> for proto::OperationType {
fn from(value: OperationType) -> Self {
match value {
OperationType::Create => Self::Create,
OperationType::Update => Self::Update,
OperationType::Delete => Self::Delete,
OperationType::Reaction => Self::Reaction,
}
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct TextHeader {
pub(crate) operation_type: OperationType,
pub(crate) version: i32,
pub(crate) reply_to_stream_id: Option<StreamId>,
pub(crate) attached_stream_ids: Vec<StreamId>,
pub(crate) generated: bool,
}
impl From<proto::TextHeader> for TextHeader {
fn from(value: proto::TextHeader) -> Self {
Self {
operation_type: value.operation_type().into(),
version: value.version,
reply_to_stream_id: if !value.reply_to_stream_id.is_empty() {
Some(value.reply_to_stream_id.into())
} else {
None
},
attached_stream_ids: value.attached_stream_ids.into_iter().map(Into::into).collect(),
generated: value.generated,
}
}
}
impl From<TextHeader> for proto::TextHeader {
fn from(value: TextHeader) -> Self {
Self {
operation_type: proto::OperationType::from(value.operation_type) as i32,
version: value.version,
reply_to_stream_id: value.reply_to_stream_id.map(Into::into).unwrap_or_default(),
attached_stream_ids: value.attached_stream_ids.into_iter().map(Into::into).collect(),
generated: value.generated,
}
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ByteHeader {
pub(crate) name: String,
}
impl From<proto::ByteHeader> for ByteHeader {
fn from(value: proto::ByteHeader) -> Self {
Self { name: value.name }
}
}
impl From<ByteHeader> for proto::ByteHeader {
fn from(value: ByteHeader) -> Self {
Self { name: value.name }
}
}
#[derive(Clone, Debug, PartialEq, FromVariants)]
pub enum ContentHeader {
TextHeader(TextHeader),
ByteHeader(ByteHeader),
}
impl From<proto::header::ContentHeader> for ContentHeader {
fn from(value: proto::header::ContentHeader) -> Self {
match value {
proto::header::ContentHeader::TextHeader(text_header) => {
Self::TextHeader(text_header.into())
}
proto::header::ContentHeader::ByteHeader(text_header) => {
Self::ByteHeader(text_header.into())
}
}
}
}
impl From<ContentHeader> for proto::header::ContentHeader {
fn from(value: ContentHeader) -> Self {
match value {
ContentHeader::TextHeader(text_header) => Self::TextHeader(text_header.into()),
ContentHeader::ByteHeader(byte_header) => Self::ByteHeader(byte_header.into()),
}
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub enum CompressionType {
#[default]
None,
DeflateRaw,
Unrecognized,
}
impl From<proto::CompressionType> for CompressionType {
fn from(value: proto::CompressionType) -> Self {
match value {
proto::CompressionType::DeflateRaw => Self::DeflateRaw,
proto::CompressionType::None => Self::None,
}
}
}
impl From<CompressionType> for proto::CompressionType {
fn from(value: CompressionType) -> Self {
match value {
CompressionType::DeflateRaw => Self::DeflateRaw,
CompressionType::None | CompressionType::Unrecognized => Self::None,
}
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Header {
pub(crate) stream_id: StreamId,
pub(crate) timestamp: i64,
pub(crate) topic: String,
pub(crate) mime_type: String,
pub(crate) total_length: Option<u64>,
pub(crate) attributes: HashMap<String, String>,
pub(crate) inline_content: Option<Vec<u8>>,
pub(crate) compression: CompressionType,
pub(crate) content_header: Option<ContentHeader>,
}
impl From<proto::Header> for Header {
fn from(value: proto::Header) -> Self {
let compression = proto::CompressionType::try_from(value.compression)
.map(CompressionType::from)
.unwrap_or(CompressionType::Unrecognized);
let content_header: Option<ContentHeader> =
value.content_header.map(|content_header| content_header.into());
Self {
stream_id: value.stream_id.into(),
timestamp: value.timestamp,
topic: value.topic,
mime_type: value.mime_type,
total_length: value.total_length,
attributes: value.attributes,
inline_content: value.inline_content,
compression,
content_header,
}
}
}
impl From<Header> for proto::Header {
fn from(value: Header) -> Self {
Self {
stream_id: value.stream_id.into(),
timestamp: value.timestamp,
topic: value.topic,
mime_type: value.mime_type,
total_length: value.total_length,
attributes: value.attributes,
inline_content: value.inline_content,
compression: proto::CompressionType::from(value.compression) as i32,
content_header: value.content_header.map(Into::into),
..Default::default()
}
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Chunk {
pub(crate) stream_id: StreamId,
pub(crate) chunk_index: u64,
pub(crate) content: Vec<u8>,
pub(crate) version: i32,
pub(crate) encryption_type: EncryptionType,
}
impl From<proto::Chunk> for Chunk {
fn from(value: proto::Chunk) -> Self {
Self {
stream_id: value.stream_id.into(),
chunk_index: value.chunk_index,
content: value.content,
version: value.version,
encryption_type: EncryptionType::default(),
}
}
}
impl From<Chunk> for proto::Chunk {
fn from(value: Chunk) -> Self {
Self {
stream_id: value.stream_id.into(),
chunk_index: value.chunk_index,
content: value.content,
version: value.version,
..Default::default()
}
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Trailer {
pub(crate) stream_id: StreamId,
pub(crate) reason: String,
pub(crate) attributes: HashMap<String, String>,
}
impl From<proto::Trailer> for Trailer {
fn from(value: proto::Trailer) -> Self {
Self {
stream_id: value.stream_id.into(),
reason: value.reason,
attributes: value.attributes,
}
}
}
impl From<Trailer> for proto::Trailer {
fn from(value: Trailer) -> Self {
Self {
stream_id: value.stream_id.into(),
reason: value.reason,
attributes: value.attributes,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Packet {
Header { header: Header, encryption_type: EncryptionType },
Chunk { chunk: Chunk, encryption_type: EncryptionType },
Trailer(Trailer),
}