use crate::error::CodecError;
use crate::varint::{MoqtProfile, VarInt, VarIntError};
use bytes::{Buf, BufMut};
pub const AUTH_TOKEN_PARAMETER: u64 = 0x03;
pub const AUTH_TOKEN_PARAMETER_D11: u64 = 0x01;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TokenAliasType {
Delete,
Register,
UseAlias,
UseValue,
}
impl TokenAliasType {
pub const fn from_id(id: u64) -> Option<Self> {
match id {
0x0 => Some(Self::Delete),
0x1 => Some(Self::Register),
0x2 => Some(Self::UseAlias),
0x3 => Some(Self::UseValue),
_ => None,
}
}
pub const fn id(self) -> u64 {
match self {
Self::Delete => 0x0,
Self::Register => 0x1,
Self::UseAlias => 0x2,
Self::UseValue => 0x3,
}
}
pub const fn has_alias(self) -> bool {
!matches!(self, Self::UseValue)
}
pub const fn has_type_and_value(self) -> bool {
matches!(self, Self::Register | Self::UseValue)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AuthorizationToken {
pub alias_type: TokenAliasType,
pub alias: Option<u64>,
pub token_type: Option<u64>,
pub value: Vec<u8>,
}
fn malformed(key: u64, detail: &'static str) -> CodecError {
CodecError::KeyValueFormatting { key, detail }
}
impl AuthorizationToken {
pub fn decode(key: u64, bytes: &[u8]) -> Result<Self, CodecError> {
Self::decode_with(key, bytes, |buf: &mut &[u8]| VarInt::decode(buf))
}
pub fn decode_moqt<P: MoqtProfile>(key: u64, bytes: &[u8]) -> Result<Self, CodecError> {
Self::decode_with(key, bytes, |buf: &mut &[u8]| VarInt::decode_moqt::<P>(buf))
}
fn decode_with<F>(key: u64, bytes: &[u8], mut read: F) -> Result<Self, CodecError>
where
F: FnMut(&mut &[u8]) -> Result<VarInt, VarIntError>,
{
const NO_ALIAS_TYPE: &str = "it carries no Alias Type";
const UNASSIGNED: &str = "its Alias Type is not one this draft assigns";
const NO_ALIAS: &str = "its Alias Type promises a Token Alias and the value ends first";
const NO_TYPE: &str = "its Alias Type promises a Token Type and the value ends first";
const TRAILING: &str =
"its Alias Type promises no Token Value and bytes follow the Token Alias";
let mut buf = bytes;
let raw = read(&mut buf).map_err(|_| malformed(key, NO_ALIAS_TYPE))?;
let alias_type =
TokenAliasType::from_id(raw.into_inner()).ok_or_else(|| malformed(key, UNASSIGNED))?;
let alias = if alias_type.has_alias() {
Some(read(&mut buf).map_err(|_| malformed(key, NO_ALIAS))?.into_inner())
} else {
None
};
let (token_type, value) = if alias_type.has_type_and_value() {
let token_type = read(&mut buf).map_err(|_| malformed(key, NO_TYPE))?.into_inner();
(Some(token_type), buf.to_vec())
} else {
if buf.has_remaining() {
return Err(malformed(key, TRAILING));
}
(None, Vec::new())
};
Ok(AuthorizationToken { alias_type, alias, token_type, value })
}
pub fn encode(&self, buf: &mut impl BufMut) -> Result<(), CodecError> {
let mut out = Vec::with_capacity(24 + self.value.len());
VarInt::from_u64(self.alias_type.id())?.encode(&mut out);
if self.alias_type.has_alias() {
VarInt::from_u64(self.alias.unwrap_or(0))?.encode(&mut out);
}
if self.alias_type.has_type_and_value() {
VarInt::from_u64(self.token_type.unwrap_or(0))?.encode(&mut out);
out.extend_from_slice(&self.value);
}
buf.put_slice(&out);
Ok(())
}
pub fn encode_moqt<P: MoqtProfile>(&self, buf: &mut impl BufMut) {
VarInt::from_u64_moqt(self.alias_type.id()).encode_moqt::<P>(buf);
if self.alias_type.has_alias() {
VarInt::from_u64_moqt(self.alias.unwrap_or(0)).encode_moqt::<P>(buf);
}
if self.alias_type.has_type_and_value() {
VarInt::from_u64_moqt(self.token_type.unwrap_or(0)).encode_moqt::<P>(buf);
buf.put_slice(&self.value);
}
}
}