aboutsummaryrefslogtreecommitdiff
path: root/src/proto2.rs
blob: 4e126d3854581729c7884b8e33f867f1c30ded9e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use crate::proto::*;
use crate::error::*;

pub(crate) struct QueryMessage<'a> {
	pub(crate) prio: RequestPriority,
	pub(crate) path: &'a [u8],
	pub(crate) telemetry_id: Option<Vec<u8>>,
	pub(crate) body: &'a [u8],
}

/// QueryMessage encoding:
/// - priority: u8
/// - path length: u8
/// - path: [u8; path length]
/// - telemetry id length: u8
/// - telemetry id: [u8; telemetry id length]
/// - body [u8; ..]
impl<'a> QueryMessage<'a> {
	pub(crate) fn encode(self) -> Vec<u8> {
		let tel_len = match &self.telemetry_id {
			Some(t) => t.len(),
			None => 0,
		};

		let mut ret = Vec::with_capacity(10 + self.path.len() + tel_len + self.body.len());

		ret.push(self.prio);

		ret.push(self.path.len() as u8);
		ret.extend_from_slice(self.path);

		if let Some(t) = self.telemetry_id {
			ret.push(t.len() as u8);
			ret.extend(t);
		} else {
			ret.push(0u8);
		}

		ret.extend_from_slice(self.body);

		ret
	}

	pub(crate) fn decode(bytes: &'a [u8]) -> Result<Self, Error> {
		if bytes.len() < 3 {
			return Err(Error::Message("Invalid protocol message".into()));
		}

		let path_length = bytes[1] as usize;
		if bytes.len() < 3 + path_length {
			return Err(Error::Message("Invalid protocol message".into()));
		}

		let telemetry_id_len = bytes[2 + path_length] as usize;
		if bytes.len() < 3 + path_length + telemetry_id_len {
			return Err(Error::Message("Invalid protocol message".into()));
		}

		let path = &bytes[2..2 + path_length];
		let telemetry_id = if telemetry_id_len > 0 {
			Some(bytes[3 + path_length .. 3 + path_length + telemetry_id_len].to_vec())
		} else {
			None
		};

		let body = &bytes[3 + path_length + telemetry_id_len..];

		Ok(Self {
			prio: bytes[0],
			path,
			telemetry_id,
			body,
		})
	}
}