moq_lite/ietf/
parameters.rs

1use std::collections::{hash_map, HashMap};
2
3use num_enum::{FromPrimitive, IntoPrimitive};
4
5use crate::coding::*;
6
7const MAX_PARAMS: u64 = 64;
8
9#[derive(Debug, Copy, Clone, FromPrimitive, IntoPrimitive, Eq, Hash, PartialEq)]
10#[repr(u64)]
11pub enum ParameterVarInt {
12	MaxRequestId = 2,
13	MaxAuthTokenCacheSize = 4,
14	#[num_enum(catch_all)]
15	Unknown(u64),
16}
17
18#[derive(Debug, Copy, Clone, FromPrimitive, IntoPrimitive, Eq, Hash, PartialEq)]
19#[repr(u64)]
20pub enum ParameterBytes {
21	Path = 1,
22	AuthorizationToken = 3,
23	Authority = 5,
24	Implementation = 7,
25	#[num_enum(catch_all)]
26	Unknown(u64),
27}
28
29#[derive(Default, Debug, Clone)]
30pub struct Parameters {
31	vars: HashMap<ParameterVarInt, u64>,
32	bytes: HashMap<ParameterBytes, Vec<u8>>,
33}
34
35impl<V: Clone> Decode<V> for Parameters {
36	fn decode<R: bytes::Buf>(mut r: &mut R, version: V) -> Result<Self, DecodeError> {
37		let mut vars = HashMap::new();
38		let mut bytes = HashMap::new();
39
40		// I hate this encoding so much; let me encode my role and get on with my life.
41		let count = u64::decode(r, version.clone())?;
42
43		if count > MAX_PARAMS {
44			return Err(DecodeError::TooMany);
45		}
46
47		for _ in 0..count {
48			let kind = u64::decode(r, version.clone())?;
49
50			if kind % 2 == 0 {
51				let kind = ParameterVarInt::from(kind);
52				match vars.entry(kind) {
53					hash_map::Entry::Occupied(_) => return Err(DecodeError::Duplicate),
54					hash_map::Entry::Vacant(entry) => entry.insert(u64::decode(&mut r, version.clone())?),
55				};
56			} else {
57				let kind = ParameterBytes::from(kind);
58				match bytes.entry(kind) {
59					hash_map::Entry::Occupied(_) => return Err(DecodeError::Duplicate),
60					hash_map::Entry::Vacant(entry) => entry.insert(Vec::<u8>::decode(&mut r, version.clone())?),
61				};
62			}
63		}
64
65		Ok(Parameters { vars, bytes })
66	}
67}
68
69impl<V: Clone> Encode<V> for Parameters {
70	fn encode<W: bytes::BufMut>(&self, w: &mut W, version: V) {
71		(self.vars.len() + self.bytes.len()).encode(w, version.clone());
72
73		for (kind, value) in self.vars.iter() {
74			u64::from(*kind).encode(w, version.clone());
75			value.encode(w, version.clone());
76		}
77
78		for (kind, value) in self.bytes.iter() {
79			u64::from(*kind).encode(w, version.clone());
80			value.encode(w, version.clone());
81		}
82	}
83}
84
85impl Parameters {
86	pub fn get_varint(&self, kind: ParameterVarInt) -> Option<u64> {
87		self.vars.get(&kind).copied()
88	}
89
90	pub fn set_varint(&mut self, kind: ParameterVarInt, value: u64) {
91		self.vars.insert(kind, value);
92	}
93
94	pub fn get_bytes(&self, kind: ParameterBytes) -> Option<&[u8]> {
95		self.bytes.get(&kind).map(|v| v.as_slice())
96	}
97
98	pub fn set_bytes(&mut self, kind: ParameterBytes, value: Vec<u8>) {
99		self.bytes.insert(kind, value);
100	}
101}