1pub const TAG_HANDSHAKE_1: u8 = 1;
8pub const TAG_HANDSHAKE_2: u8 = 2;
10pub const TAG_TRANSPORT: u8 = 3;
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14pub enum InnerKind {
15 Handshake1,
16 Handshake2,
17 Transport,
18}
19
20impl InnerKind {
21 pub fn tag(self) -> u8 {
22 match self {
23 Self::Handshake1 => TAG_HANDSHAKE_1,
24 Self::Handshake2 => TAG_HANDSHAKE_2,
25 Self::Transport => TAG_TRANSPORT,
26 }
27 }
28}
29
30pub fn encode_inner(kind: InnerKind, body: &[u8]) -> Vec<u8> {
31 let mut out = Vec::with_capacity(1 + body.len());
32 out.push(kind.tag());
33 out.extend_from_slice(body);
34 out
35}
36
37pub fn decode_inner(bytes: &[u8]) -> Option<(InnerKind, &[u8])> {
38 let (&tag, body) = bytes.split_first()?;
39 let kind = match tag {
40 TAG_HANDSHAKE_1 => InnerKind::Handshake1,
41 TAG_HANDSHAKE_2 => InnerKind::Handshake2,
42 TAG_TRANSPORT => InnerKind::Transport,
43 _ => return None,
44 };
45 Some((kind, body))
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn roundtrip_and_unknown_tag() {
54 let b = encode_inner(InnerKind::Transport, b"x");
55 assert_eq!(decode_inner(&b), Some((InnerKind::Transport, &b"x"[..])));
56 assert_eq!(decode_inner(&[9, 1]), None);
57 assert_eq!(decode_inner(&[]), None);
58 }
59}