|
| 1 | +use std::collections::HashMap; |
| 2 | + |
| 3 | +use crate::coding::*; |
| 4 | + |
| 5 | +const MAX_PARAMS: u64 = 64; |
| 6 | + |
| 7 | +#[derive(Default, Debug, Clone)] |
| 8 | +pub struct Parameters(HashMap<u64, Vec<u8>>); |
| 9 | + |
| 10 | +impl Decode for Parameters { |
| 11 | + fn decode<R: bytes::Buf>(mut r: &mut R) -> Result<Self, DecodeError> { |
| 12 | + let mut map = HashMap::new(); |
| 13 | + |
| 14 | + // I hate this encoding so much; let me encode my role and get on with my life. |
| 15 | + let count = u64::decode(r)?; |
| 16 | + |
| 17 | + if count > MAX_PARAMS { |
| 18 | + return Err(DecodeError::TooMany); |
| 19 | + } |
| 20 | + |
| 21 | + for _ in 0..count { |
| 22 | + let kind = u64::decode(r)?; |
| 23 | + |
| 24 | + if map.contains_key(&kind) { |
| 25 | + return Err(DecodeError::Duplicate); |
| 26 | + } |
| 27 | + |
| 28 | + // Per draft-ietf-moq-transport-14 Section 1.4.2: |
| 29 | + // - If Type is even, Value is a single varint (no length prefix) |
| 30 | + // - If Type is odd, Value has a length prefix followed by bytes |
| 31 | + let data = if kind % 2 == 0 { |
| 32 | + // Even: decode as varint and encode it as bytes |
| 33 | + let value = u64::decode(&mut r)?; |
| 34 | + // Store the varint as bytes (we'll need to encode it back when accessing) |
| 35 | + let mut bytes = Vec::new(); |
| 36 | + value.encode(&mut bytes); |
| 37 | + bytes |
| 38 | + } else { |
| 39 | + // Odd: decode as length-prefixed bytes |
| 40 | + Vec::<u8>::decode(&mut r)? |
| 41 | + }; |
| 42 | + |
| 43 | + map.insert(kind, data); |
| 44 | + } |
| 45 | + |
| 46 | + Ok(Parameters(map)) |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +impl Encode for Parameters { |
| 51 | + fn encode<W: bytes::BufMut>(&self, w: &mut W) { |
| 52 | + self.0.len().encode(w); |
| 53 | + |
| 54 | + for (kind, value) in self.0.iter() { |
| 55 | + kind.encode(w); |
| 56 | + // Per draft-ietf-moq-transport-14 Section 1.4.2: |
| 57 | + // - If Type is even, Value is a single varint (no length prefix) |
| 58 | + // - If Type is odd, Value has a length prefix followed by bytes |
| 59 | + if kind % 2 == 0 { |
| 60 | + // Even: value is stored as encoded varint bytes, write them directly |
| 61 | + w.put_slice(value); |
| 62 | + } else { |
| 63 | + // Odd: encode as length-prefixed bytes |
| 64 | + value.encode(w); |
| 65 | + } |
| 66 | + } |
| 67 | + } |
| 68 | +} |
| 69 | + |
| 70 | +impl Parameters { |
| 71 | + pub fn get(&self, kind: u64) -> Option<&Vec<u8>> { |
| 72 | + self.0.get(&kind) |
| 73 | + } |
| 74 | + |
| 75 | + pub fn set(&mut self, kind: u64, value: Vec<u8>) { |
| 76 | + self.0.insert(kind, value); |
| 77 | + } |
| 78 | +} |
0 commit comments