use crate::{
Buf,
BufError::{self},
BufMut, BufResult, Codec, Cursor,
ietf::ipv4,
ietf::ipv6,
ietf::quicv1::{ConnectionId, VarInt, VariableLengthInteger},
ietf::transport::Port,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u64)]
pub enum TransportParameterId {
OriginalDestinationConnectionId = 0x00,
MaxIdleTimeout = 0x01,
StatelessResetToken = 0x02,
MaxUdpPayloadSize = 0x03,
InitialMaxData = 0x04,
InitialMaxStreamDataBidiLocal = 0x05,
InitialMaxStreamDataBidiRemote = 0x06,
InitialMaxStreamDataUni = 0x07,
InitialMaxStreamsBidi = 0x08,
InitialMaxStreamsUni = 0x09,
AckDelayExponent = 0x0a,
MaxAckDelay = 0x0b,
DisableActiveMigration = 0x0c,
PreferredAddress = 0x0d,
ActiveConnectionIdLimit = 0x0e,
InitialSourceConnectionId = 0x0f,
RetrySourceConnectionId = 0x10,
}
impl Codec for TransportParameterId {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
VariableLengthInteger::new(*self as u64)
.unwrap()
.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
match (VarInt::decode(reader, ())?).into_inner() {
x if x == Self::OriginalDestinationConnectionId as u64 => {
Ok(Self::OriginalDestinationConnectionId)
}
x if x == Self::MaxIdleTimeout as u64 => Ok(Self::MaxIdleTimeout),
x if x == Self::StatelessResetToken as u64 => Ok(Self::StatelessResetToken),
x if x == Self::MaxUdpPayloadSize as u64 => Ok(Self::MaxUdpPayloadSize),
x if x == Self::InitialMaxData as u64 => Ok(Self::InitialMaxData),
x if x == Self::InitialMaxStreamDataBidiLocal as u64 => {
Ok(Self::InitialMaxStreamDataBidiLocal)
}
x if x == Self::InitialMaxStreamDataBidiRemote as u64 => {
Ok(Self::InitialMaxStreamDataBidiRemote)
}
x if x == Self::InitialMaxStreamDataUni as u64 => Ok(Self::InitialMaxStreamDataUni),
x if x == Self::InitialMaxStreamsBidi as u64 => Ok(Self::InitialMaxStreamsBidi),
x if x == Self::InitialMaxStreamsUni as u64 => Ok(Self::InitialMaxStreamsUni),
x if x == Self::AckDelayExponent as u64 => Ok(Self::AckDelayExponent),
x if x == Self::MaxAckDelay as u64 => Ok(Self::MaxAckDelay),
x if x == Self::DisableActiveMigration as u64 => Ok(Self::DisableActiveMigration),
x if x == Self::PreferredAddress as u64 => Ok(Self::PreferredAddress),
x if x == Self::ActiveConnectionIdLimit as u64 => Ok(Self::ActiveConnectionIdLimit),
x if x == Self::InitialSourceConnectionId as u64 => Ok(Self::InitialSourceConnectionId),
x if x == Self::RetrySourceConnectionId as u64 => Ok(Self::RetrySourceConnectionId),
_ => Err(BufError::OutOfBounds),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TransportParameter<'a> {
pub transport_parameter_id: VarInt,
pub transport_parameter_value: &'a [u8],
}
impl<'a> Codec for TransportParameter<'a> {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
self.transport_parameter_id.encode(writer, ())?;
match VarInt::new(self.transport_parameter_value.len() as u64) {
Ok(x) => x.encode(writer, ())?,
Err(_) => return Err(BufError::UnexpectedValue),
}
writer.write_slice(self.transport_parameter_value)
}
fn decode<R: Buf>(_reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
todo!()
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct OriginalDestinationConnectionId(pub ConnectionId);
impl OriginalDestinationConnectionId {
pub const ID: VarInt =
VarInt::new_const(TransportParameterId::OriginalDestinationConnectionId as u64);
}
impl Codec for OriginalDestinationConnectionId {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.length() as u64)?.encode(writer, ())?;
self.0.encode(writer, self.0.length())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?; let length = VarInt::decode(reader, ())?;
Ok(Self(ConnectionId::decode(reader, length.0 as u8)?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MaxIdleTimeout(pub VarInt);
impl MaxIdleTimeout {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::MaxIdleTimeout as u64);
}
impl Codec for MaxIdleTimeout {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.encoded_length() as u64)?.encode(writer, ())?;
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let _length = VarInt::decode(reader, ())?;
Ok(Self(VarInt::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StatelessResetToken(pub [u8; 16]);
impl StatelessResetToken {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::StatelessResetToken as u64);
}
impl Codec for StatelessResetToken {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(16)?.encode(writer, ())?;
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let length = VarInt::decode(reader, ())?;
if length.0 != 16 {
return Err(BufError::UnexpectedValue);
}
Ok(Self(reader.read_array::<16>()?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MaxUdpPayloadSize(pub VarInt);
impl MaxUdpPayloadSize {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::MaxUdpPayloadSize as u64);
}
impl Codec for MaxUdpPayloadSize {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.encoded_length() as u64)?.encode(writer, ())?;
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let _length = VarInt::decode(reader, ())?;
Ok(Self(VarInt::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InitialMaxData(pub VarInt);
impl InitialMaxData {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::InitialMaxData as u64);
}
impl Codec for InitialMaxData {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.encoded_length() as u64)?.encode(writer, ())?;
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let _length = VarInt::decode(reader, ())?;
Ok(Self(VarInt::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InitialMaxStreamDataBidiLocal(pub VarInt);
impl InitialMaxStreamDataBidiLocal {
pub const ID: VarInt =
VarInt::new_const(TransportParameterId::InitialMaxStreamDataBidiLocal as u64);
}
impl Codec for InitialMaxStreamDataBidiLocal {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.encoded_length() as u64)?.encode(writer, ())?;
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let _length = VarInt::decode(reader, ())?;
Ok(Self(VarInt::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InitialMaxStreamDataBidiRemote(pub VarInt);
impl InitialMaxStreamDataBidiRemote {
pub const ID: VarInt =
VarInt::new_const(TransportParameterId::InitialMaxStreamDataBidiRemote as u64);
}
impl Codec for InitialMaxStreamDataBidiRemote {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.encoded_length() as u64)?.encode(writer, ())?;
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let _length = VarInt::decode(reader, ())?;
Ok(Self(VarInt::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InitialMaxStreamDataUni(pub VarInt);
impl InitialMaxStreamDataUni {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::InitialMaxStreamDataUni as u64);
}
impl Codec for InitialMaxStreamDataUni {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.encoded_length() as u64)?.encode(writer, ())?;
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let _length = VarInt::decode(reader, ())?;
Ok(Self(VarInt::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InitialMaxStreamsBidi(pub VarInt);
impl InitialMaxStreamsBidi {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::InitialMaxStreamsBidi as u64);
}
impl Codec for InitialMaxStreamsBidi {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.encoded_length() as u64)?.encode(writer, ())?;
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let _length = VarInt::decode(reader, ())?;
Ok(Self(VarInt::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InitialMaxStreamsUni(pub VarInt);
impl InitialMaxStreamsUni {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::InitialMaxStreamsUni as u64);
}
impl Codec for InitialMaxStreamsUni {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.encoded_length() as u64)?.encode(writer, ())?;
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let _length = VarInt::decode(reader, ())?;
Ok(Self(VarInt::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AckDelayExponent(pub VarInt);
impl AckDelayExponent {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::AckDelayExponent as u64);
}
impl Codec for AckDelayExponent {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.encoded_length() as u64)?.encode(writer, ())?;
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let _length = VarInt::decode(reader, ())?;
Ok(Self(VarInt::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MaxAckDelay(pub VarInt);
impl MaxAckDelay {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::MaxAckDelay as u64);
}
impl Codec for MaxAckDelay {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.encoded_length() as u64)?.encode(writer, ())?;
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let _length = VarInt::decode(reader, ())?;
Ok(Self(VarInt::decode(reader, ())?))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DisableActiveMigration;
impl DisableActiveMigration {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::DisableActiveMigration as u64);
}
impl Codec for DisableActiveMigration {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(0)?.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let length = VarInt::decode(reader, ())?;
if length.0 != 0 {
return Err(BufError::UnexpectedValue);
}
Ok(Self)
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PreferredAddress {
pub ipv4_address: ipv4::Address,
pub ipv4_port: Port,
pub ipv6_address: ipv6::Address,
pub ipv6_port: Port,
pub connection_id: ConnectionId,
pub stateless_reset_token: [u8; 16],
}
impl PreferredAddress {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::PreferredAddress as u64);
}
impl Codec for PreferredAddress {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
let cid_len = self.connection_id.length();
let value_len = 4 + 2 + 16 + 2 + 1 + cid_len + 16;
VarInt::new(value_len as u64)?.encode(writer, ())?;
self.ipv4_address.encode(writer, ())?;
self.ipv4_port.encode(writer, ())?;
self.ipv6_address.encode(writer, ())?;
self.ipv6_port.encode(writer, ())?;
VarInt::new(cid_len as u64)?.encode(writer, ())?;
self.connection_id.encode(writer, cid_len)?;
self.stateless_reset_token.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let _length = VarInt::decode(reader, ())?;
let ipv4_address = ipv4::Address::decode(reader, ())?;
let ipv4_port = Port::decode(reader, ())?;
let ipv6_address = ipv6::Address::decode(reader, ())?;
let ipv6_port = Port::decode(reader, ())?;
let cid_len = VarInt::decode(reader, ())?;
let connection_id = ConnectionId::decode(reader, cid_len.0 as u8)?;
let stateless_reset_token = reader.read_array::<16>()?;
Ok(Self {
ipv4_address,
ipv4_port,
ipv6_address,
ipv6_port,
connection_id,
stateless_reset_token,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ActiveConnectionIdLimit(pub VarInt);
impl ActiveConnectionIdLimit {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::ActiveConnectionIdLimit as u64);
}
impl Codec for ActiveConnectionIdLimit {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.encoded_length() as u64)?.encode(writer, ())?;
self.0.encode(writer, ())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let _length = VarInt::decode(reader, ())?;
Ok(Self(VarInt::decode(reader, ())?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InitialSourceConnectionId(pub ConnectionId);
impl InitialSourceConnectionId {
pub const ID: VarInt =
VarInt::new_const(TransportParameterId::InitialSourceConnectionId as u64);
}
impl Codec for InitialSourceConnectionId {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.length() as u64)?.encode(writer, ())?;
self.0.encode(writer, self.0.length())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let length = VarInt::decode(reader, ())?;
Ok(Self(ConnectionId::decode(reader, length.0 as u8)?))
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RetrySourceConnectionId(pub ConnectionId);
impl RetrySourceConnectionId {
pub const ID: VarInt = VarInt::new_const(TransportParameterId::RetrySourceConnectionId as u64);
}
impl Codec for RetrySourceConnectionId {
fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
Self::ID.encode(writer, ())?;
VarInt::new(self.0.length() as u64)?.encode(writer, ())?;
self.0.encode(writer, self.0.length())
}
fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
VarInt::decode(reader, ())?;
let length = VarInt::decode(reader, ())?;
Ok(Self(ConnectionId::decode(reader, length.0 as u8)?))
}
}
#[cfg(test)]
mod tests {
use crate::{
Codec, Cursor,
ietf::quicv1::{
AckDelayExponent, ActiveConnectionIdLimit, ConnectionId, DisableActiveMigration,
InitialMaxData, InitialMaxStreamDataBidiLocal, InitialMaxStreamDataBidiRemote,
InitialMaxStreamDataUni, InitialMaxStreamsBidi, InitialMaxStreamsUni,
InitialSourceConnectionId, MaxAckDelay, MaxIdleTimeout, MaxUdpPayloadSize,
OriginalDestinationConnectionId, PreferredAddress, RetrySourceConnectionId,
StatelessResetToken, VariableLengthInteger,
},
ietf::{ipv4, ipv6, transport::Port},
};
use core::fmt::Debug;
fn codec_roundtrip<T: Codec + Debug + Eq>(etalon_struct: T, etalon_bytes: &[u8]) {
let mut encoded_bytes = vec![];
{
let writer = &mut Cursor::new(&mut encoded_bytes);
etalon_struct.encode(writer, ()).unwrap();
}
assert_eq!(etalon_bytes, &encoded_bytes);
let decoded_struct = {
let reader = &mut Cursor::new(&mut encoded_bytes);
T::decode(reader, ()).unwrap()
};
assert_eq!(etalon_struct, decoded_struct);
encoded_bytes.fill(0xFF);
{
let writer = &mut Cursor::new(&mut encoded_bytes);
decoded_struct.encode(writer, ()).unwrap();
}
assert_eq!(etalon_bytes, &encoded_bytes);
}
#[test]
fn original_destination_connection_id() {
let etalon_bytes: &[u8] = &[0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08];
let etalon_struct = OriginalDestinationConnectionId(ConnectionId::new(&[0x08; 8]).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn max_idle_timeout() {
let etalon_bytes: &[u8] = &[0x01, 0x01, 0x09];
let etalon_struct = MaxIdleTimeout(VariableLengthInteger::new(0x09).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn stateless_reset_token() {
let etalon_bytes: &[u8] = &[
0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];
let etalon_struct = StatelessResetToken([0u8; 16]);
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn max_udp_payload_size() {
let etalon_bytes: &[u8] = &[0x03, 0x02, 0x44, 0xB0];
let etalon_struct = MaxUdpPayloadSize(VariableLengthInteger::new(1200).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn initial_max_data() {
let etalon_bytes: &[u8] = &[0x04, 0x01, 0x01];
let etalon_struct = InitialMaxData(VariableLengthInteger::new(1).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn initial_max_stream_data_bidi_local() {
let etalon_bytes: &[u8] = &[0x05, 0x01, 0x01];
let etalon_struct = InitialMaxStreamDataBidiLocal(VariableLengthInteger::new(1).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn initial_max_stream_data_bidi_remote() {
let etalon_bytes: &[u8] = &[0x06, 0x01, 0x01];
let etalon_struct = InitialMaxStreamDataBidiRemote(VariableLengthInteger::new(1).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn initial_max_stream_data_uni() {
let etalon_bytes: &[u8] = &[0x07, 0x01, 0x01];
let etalon_struct = InitialMaxStreamDataUni(VariableLengthInteger::new(1).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn initial_max_streams_bidi() {
let etalon_bytes: &[u8] = &[0x08, 0x01, 0x01];
let etalon_struct = InitialMaxStreamsBidi(VariableLengthInteger::new(1).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn initial_max_streams_uni() {
let etalon_bytes: &[u8] = &[0x09, 0x01, 0x01];
let etalon_struct = InitialMaxStreamsUni(VariableLengthInteger::new(1).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn ack_delay_exponent() {
let etalon_bytes: &[u8] = &[0x0A, 0x01, 0x03];
let etalon_struct = AckDelayExponent(VariableLengthInteger::new(3).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn max_ack_delay() {
let etalon_bytes: &[u8] = &[0x0B, 0x01, 0x19];
let etalon_struct = MaxAckDelay(VariableLengthInteger::new(25).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn disable_active_migration() {
let etalon_bytes: &[u8] = &[0x0C, 0x00];
let etalon_struct = DisableActiveMigration;
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn preferred_address() {
let etalon_bytes: &[u8] = &[
0x0D, 0x31, 0x7F, 0x00, 0x00, 0x01, 0x01, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xBB, 0x08, 0x82,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let etalon_struct = PreferredAddress {
ipv4_address: ipv4::Address::LOOPBACK,
ipv4_port: Port(443),
ipv6_address: ipv6::Address::LOOPBACK,
ipv6_port: Port(443),
connection_id: ConnectionId::new(&[0x82; 8]).unwrap(),
stateless_reset_token: [0u8; 16],
};
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn active_connection_id_limit() {
let etalon_bytes: &[u8] = &[0x0E, 0x01, 0x02];
let etalon_struct = ActiveConnectionIdLimit(VariableLengthInteger::new(2).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn initial_source_connection_id() {
let etalon_bytes: &[u8] = &[0x0F, 0x08, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F];
let etalon_struct = InitialSourceConnectionId(ConnectionId::new(&[0x0F; 8]).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
#[test]
fn retry_source_connection_id() {
let etalon_bytes: &[u8] = &[0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10];
let etalon_struct = RetrySourceConnectionId(ConnectionId::new(&[0x10; 8]).unwrap());
codec_roundtrip(etalon_struct, etalon_bytes);
}
}