1use crate::varint::VarInt;
2use bytes::{Buf, BufMut};
3
4pub const MAX_KVP_VALUE_LEN: usize = 65535;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum KvpValue {
12 Varint(VarInt),
13 Bytes(Vec<u8>),
14}
15
16#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct KeyValuePair {
19 pub key: VarInt,
20 pub value: KvpValue,
21}
22
23#[derive(Debug, thiserror::Error, PartialEq, Eq, Clone)]
24pub enum KvpError {
25 #[error("odd key type requires length-prefixed value")]
26 MissingLength,
27 #[error("value length {0} exceeds maximum ({MAX_KVP_VALUE_LEN})")]
28 ValueTooLong(usize),
29 #[error("insufficient bytes")]
30 UnexpectedEnd,
31 #[error("varint error: {0}")]
32 VarInt(#[from] crate::varint::VarIntError),
33}
34
35impl KeyValuePair {
36 pub fn encode(&self, buf: &mut impl BufMut) {
38 self.key.encode(buf);
39 match &self.value {
40 KvpValue::Varint(v) => {
41 v.encode(buf);
43 }
44 KvpValue::Bytes(bytes) => {
45 VarInt::from_u64(bytes.len() as u64).unwrap().encode(buf);
47 buf.put_slice(bytes);
48 }
49 }
50 }
51
52 pub fn decode(buf: &mut impl Buf) -> Result<Self, KvpError> {
54 let key = VarInt::decode(buf)?;
55 let key_val = key.into_inner();
56
57 if key_val % 2 == 0 {
58 let value = VarInt::decode(buf)?;
60 Ok(KeyValuePair { key, value: KvpValue::Varint(value) })
61 } else {
62 let len = VarInt::decode(buf)?.into_inner() as usize;
64 if len > MAX_KVP_VALUE_LEN {
65 return Err(KvpError::ValueTooLong(len));
66 }
67 if buf.remaining() < len {
68 return Err(KvpError::UnexpectedEnd);
69 }
70 let mut bytes = vec![0u8; len];
71 buf.copy_to_slice(&mut bytes);
72 Ok(KeyValuePair { key, value: KvpValue::Bytes(bytes) })
73 }
74 }
75
76 pub fn encode_list(pairs: &[KeyValuePair], buf: &mut impl BufMut) {
78 VarInt::from_u64(pairs.len() as u64).unwrap().encode(buf);
79 for pair in pairs {
80 pair.encode(buf);
81 }
82 }
83
84 pub fn decode_list(buf: &mut impl Buf) -> Result<Vec<KeyValuePair>, KvpError> {
86 let count = VarInt::decode(buf)?.into_inner() as usize;
87 let mut pairs = Vec::with_capacity(count);
88 for _ in 0..count {
89 pairs.push(KeyValuePair::decode(buf)?);
90 }
91 Ok(pairs)
92 }
93}