use crate::model::{
common::pair::KeyValuePair,
error::ParseError,
parameter::{authorization_token::AuthorizationToken, constant::SetupParameterType},
};
use bytes::{Bytes, BytesMut};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SetupParameter {
Path { moqt_path: String },
MaxRequestId { request_id: u64 },
AuthorizationToken { token: AuthorizationToken },
MaxAuthTokenCacheSize { max_size: u64 },
MoqtImplementation { info: String },
}
impl SetupParameter {
pub fn new_path(moqt_path: String) -> Self {
SetupParameter::Path { moqt_path }
}
pub fn new_max_request_id(request_id: u64) -> Self {
SetupParameter::MaxRequestId { request_id }
}
pub fn new_auth_token(token: AuthorizationToken) -> Self {
SetupParameter::AuthorizationToken { token }
}
pub fn new_max_auth_token_cache_size(max_size: u64) -> Self {
SetupParameter::MaxAuthTokenCacheSize { max_size }
}
pub fn new_moqt_implementation(info: String) -> Self {
SetupParameter::MoqtImplementation { info }
}
pub fn serialize(&self) -> Result<Bytes, ParseError> {
let mut bytes = BytesMut::new();
match self {
Self::Path { moqt_path } => {
let data = moqt_path.as_bytes();
let kvp = KeyValuePair::try_new_bytes(
SetupParameterType::Path as u64,
Bytes::copy_from_slice(data),
)?;
let slice = kvp.serialize()?;
bytes.extend_from_slice(&slice);
}
Self::MaxRequestId { request_id } => {
let kvp =
KeyValuePair::try_new_varint(SetupParameterType::MaxRequestId as u64, *request_id)?;
let slice = kvp.serialize()?;
bytes.extend_from_slice(&slice);
}
Self::AuthorizationToken { token } => match token.serialize() {
Ok(payload_bytes) => {
let kvp = KeyValuePair::try_new_bytes(
SetupParameterType::AuthorizationToken as u64,
payload_bytes,
)?;
let slice = kvp.serialize()?;
bytes.extend_from_slice(&slice);
}
Err(e) => {
return Err(ParseError::Other {
context: "SetupParameter::serialize",
msg: e.to_string(),
});
}
},
Self::MaxAuthTokenCacheSize { max_size } => {
let kvp = KeyValuePair::try_new_varint(
SetupParameterType::MaxAuthTokenCacheSize as u64,
*max_size,
)?;
let slice = kvp.serialize()?;
bytes.extend_from_slice(&slice);
}
Self::MoqtImplementation { info } => {
let data = info.as_bytes();
let kvp = KeyValuePair::try_new_bytes(
SetupParameterType::MoqtImplementation as u64,
Bytes::copy_from_slice(data),
)?;
let slice = kvp.serialize()?;
bytes.extend_from_slice(&slice);
}
}
Ok(bytes.freeze())
}
pub fn deserialize(kvp: &KeyValuePair) -> Result<SetupParameter, ParseError> {
match kvp {
KeyValuePair::VarInt { type_value, value } => {
let type_value = SetupParameterType::try_from(*type_value)?;
match type_value {
SetupParameterType::MaxRequestId => {
Ok(SetupParameter::MaxRequestId { request_id: *value })
}
SetupParameterType::MaxAuthTokenCacheSize => {
Ok(SetupParameter::MaxAuthTokenCacheSize { max_size: *value })
}
_ => Err(ParseError::KeyValueFormattingError {
context: "SetupParameter::deserialize",
}),
}
}
KeyValuePair::Bytes { type_value, value } => {
let type_value = SetupParameterType::try_from(*type_value)?;
let mut payload_bytes = value.clone();
match type_value {
SetupParameterType::Path => {
let moqt_path =
String::from_utf8(value.to_vec()).map_err(|e| ParseError::InvalidUTF8 {
context: "SetupParameter::deserialize",
details: e.to_string(),
})?;
Ok(SetupParameter::Path { moqt_path })
}
SetupParameterType::AuthorizationToken => Ok(SetupParameter::new_auth_token(
AuthorizationToken::deserialize(&mut payload_bytes)?,
)),
SetupParameterType::MoqtImplementation => {
let info = String::from_utf8(value.to_vec()).map_err(|e| ParseError::InvalidUTF8 {
context: "SetupParameter::deserialize",
details: e.to_string(),
})?;
Ok(SetupParameter::MoqtImplementation { info })
}
_ => Err(ParseError::KeyValueFormattingError {
context: "SetupParameter::deserialize",
}),
}
}
}
}
}
impl TryInto<KeyValuePair> for SetupParameter {
type Error = ParseError;
fn try_into(self) -> Result<KeyValuePair, Self::Error> {
match self {
SetupParameter::Path { moqt_path } => {
let data = moqt_path.as_bytes();
KeyValuePair::try_new_bytes(
SetupParameterType::Path as u64,
Bytes::copy_from_slice(data),
)
}
SetupParameter::MaxRequestId { request_id } => {
KeyValuePair::try_new_varint(SetupParameterType::MaxRequestId as u64, request_id)
}
SetupParameter::AuthorizationToken { token } => KeyValuePair::try_new_bytes(
SetupParameterType::AuthorizationToken as u64,
token.serialize()?,
),
SetupParameter::MaxAuthTokenCacheSize { max_size } => {
KeyValuePair::try_new_varint(SetupParameterType::MaxAuthTokenCacheSize as u64, max_size)
}
SetupParameter::MoqtImplementation { info } => KeyValuePair::try_new_bytes(
SetupParameterType::MoqtImplementation as u64,
Bytes::copy_from_slice(info.as_bytes()),
),
}
}
}
#[cfg(test)]
mod tests {
use super::SetupParameter;
use crate::model::common::pair::KeyValuePair;
use crate::model::common::varint::BufMutVarIntExt;
use crate::model::parameter::constant::SetupParameterType;
use bytes::{Buf, BytesMut};
#[test]
fn test_roundtrip_path() {
let orig = SetupParameter::new_path("test/path".to_string());
let serialized = orig.serialize().unwrap();
let mut buf = serialized.clone();
let kvp = KeyValuePair::deserialize(&mut buf).unwrap();
let got = SetupParameter::deserialize(&kvp).unwrap();
assert_eq!(orig, got);
assert_eq!(buf.remaining(), 0);
}
#[test]
fn test_roundtrip_empty_path() {
let orig = SetupParameter::new_path(String::new());
let serialized = orig.serialize().unwrap();
let mut buf = serialized.clone();
let kvp = KeyValuePair::deserialize(&mut buf).unwrap();
let got = SetupParameter::deserialize(&kvp).unwrap();
assert_eq!(orig, got);
assert_eq!(buf.remaining(), 0);
}
#[test]
fn test_roundtrip_max_request_id() {
let orig = SetupParameter::new_max_request_id(0xDEAD_BEEFu64);
let serialized = orig.serialize().unwrap();
let mut buf = serialized.clone();
let kvp = KeyValuePair::deserialize(&mut buf).unwrap();
let got = SetupParameter::deserialize(&kvp).unwrap();
assert_eq!(orig, got);
assert_eq!(buf.remaining(), 0);
}
#[test]
fn test_roundtrip_max_auth_cache_size() {
let orig = SetupParameter::new_max_auth_token_cache_size(123456);
let serialized = orig.serialize().unwrap();
let mut buf = serialized.clone();
let kvp = KeyValuePair::deserialize(&mut buf).unwrap();
let got = SetupParameter::deserialize(&kvp).unwrap();
assert_eq!(orig, got);
assert_eq!(buf.remaining(), 0);
}
#[test]
fn test_roundtrip_moqt_implementation() {
let orig = SetupParameter::new_moqt_implementation("moqtail".to_string());
let serialized = orig.serialize().unwrap();
let mut buf = serialized.clone();
let kvp = KeyValuePair::deserialize(&mut buf).unwrap();
let got = SetupParameter::deserialize(&kvp).unwrap();
assert_eq!(orig, got);
assert_eq!(buf.remaining(), 0);
}
#[test]
fn test_deserialize_invalid_type() {
let kvp = KeyValuePair::VarInt {
type_value: 999, value: 42,
};
let err = SetupParameter::deserialize(&kvp);
assert!(err.is_err());
}
#[test]
fn test_deserialize_path_missing_length() {
let mut buf = BytesMut::new();
buf.put_vi(SetupParameterType::Path as u64).unwrap();
let mut bytes = buf.freeze();
let err = KeyValuePair::deserialize(&mut bytes);
assert!(err.is_err());
}
#[test]
fn test_deserialize_path_insufficient_data() {
let mut buf = BytesMut::new();
buf.put_vi(SetupParameterType::Path as u64).unwrap();
buf.put_vi(5).unwrap(); buf.extend_from_slice(b"abc"); let mut bytes = buf.freeze();
let err = KeyValuePair::deserialize(&mut bytes);
assert!(err.is_err());
}
#[test]
fn test_deserialize_max_request_id_missing_value() {
let mut buf = BytesMut::new();
buf.put_vi(SetupParameterType::MaxRequestId as u64).unwrap();
let mut bytes = buf.freeze();
let err = KeyValuePair::deserialize(&mut bytes);
assert!(err.is_err());
}
#[test]
fn test_deserialize_max_auth_cache_missing_value() {
let mut buf = BytesMut::new();
buf
.put_vi(SetupParameterType::MaxAuthTokenCacheSize as u64)
.unwrap();
let mut bytes = buf.freeze();
let err = KeyValuePair::deserialize(&mut bytes);
assert!(err.is_err());
}
#[test]
fn test_excess_bytes_after_path() {
let orig = SetupParameter::new_path("ok".to_string());
let mut buf = BytesMut::from(&orig.serialize().unwrap()[..]);
buf.extend_from_slice(b"XYZ");
let mut bytes = buf.freeze();
let kvp = KeyValuePair::deserialize(&mut bytes).unwrap();
let got = SetupParameter::deserialize(&kvp).unwrap();
assert_eq!(got, orig);
assert_eq!(bytes.remaining(), 3);
assert_eq!(&bytes[..], b"XYZ");
}
#[test]
fn test_excess_bytes_after_max_request_id() {
let orig = SetupParameter::new_max_request_id(42);
let mut buf = BytesMut::from(&orig.serialize().unwrap()[..]);
buf.extend_from_slice(&[0xFF, 0xEE]);
let mut bytes = buf.freeze();
let kvp = KeyValuePair::deserialize(&mut bytes).unwrap();
let got = SetupParameter::deserialize(&kvp).unwrap();
assert_eq!(got, orig);
assert_eq!(bytes.remaining(), 2);
assert_eq!(&bytes[..], &[0xFF, 0xEE]);
}
#[test]
fn test_excess_bytes_after_max_auth_cache() {
let orig = SetupParameter::new_max_auth_token_cache_size(7);
let mut buf = BytesMut::from(&orig.serialize().unwrap()[..]);
buf.extend_from_slice(&[1, 2, 3]);
let mut bytes = buf.freeze();
let kvp = KeyValuePair::deserialize(&mut bytes).unwrap();
let got = SetupParameter::deserialize(&kvp).unwrap();
assert_eq!(got, orig);
assert_eq!(bytes.remaining(), 3);
assert_eq!(&bytes[..], &[1, 2, 3]);
}
}