wick_packet/
metadata.rs

1use bytes::{Buf, BufMut, Bytes, BytesMut};
2use serde::{Deserialize, Serialize};
3use wasmrs_frames::ex_err;
4
5use crate::Base64Bytes;
6
7pub const DONE_FLAG: u8 = /******/ 0b1000_0000;
8pub const OPEN_BRACKET: u8 = /***/ 0b0100_0000;
9pub const CLOSE_BRACKET: u8 = /**/ 0b0010_0000;
10
11#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
12#[allow(clippy::exhaustive_enums)]
13pub enum Flags {
14  Done,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
18#[must_use]
19pub struct WickMetadata {
20  pub(crate) flags: u8,
21  pub(crate) port: String,
22  pub(crate) context: Option<Base64Bytes>,
23}
24
25impl Default for WickMetadata {
26  fn default() -> Self {
27    Self {
28      flags: 0,
29      port: crate::Packet::FATAL_ERROR.to_owned(),
30      context: None,
31    }
32  }
33}
34
35impl WickMetadata {
36  pub fn new<T: Into<String>>(port: T, flags: u8) -> Self {
37    Self {
38      flags,
39      port: port.into(),
40      context: None,
41    }
42  }
43
44  #[must_use]
45  pub const fn flags(&self) -> u8 {
46    self.flags
47  }
48
49  pub fn set_context(&mut self, config: Base64Bytes) {
50    self.context = Some(config);
51  }
52
53  #[must_use]
54  pub fn port(&self) -> &str {
55    &self.port
56  }
57
58  #[must_use]
59  pub const fn is_done(&self) -> bool {
60    self.flags & DONE_FLAG == DONE_FLAG
61  }
62
63  #[must_use]
64  pub const fn is_open_bracket(&self) -> bool {
65    self.flags & OPEN_BRACKET == OPEN_BRACKET
66  }
67
68  #[must_use]
69  pub const fn is_close_bracket(&self) -> bool {
70    self.flags & CLOSE_BRACKET == CLOSE_BRACKET
71  }
72
73  pub fn decode(mut bytes: Bytes) -> Result<Self, wasmrs_frames::Error> {
74    let flags = bytes.get_u8();
75    let name_len = bytes.get_u16();
76    let name_bytes = bytes
77      .get(0..(name_len as _))
78      .ok_or_else(|| ex_err("Could not read port name bytes"))?;
79    let port_name = String::from_utf8(name_bytes.to_vec()).map_err(|_| ex_err("Could not parse port name"))?;
80    bytes.advance(name_len.into());
81    let config_len = bytes.get_u16();
82    let config_bytes = if config_len > 0 {
83      bytes.get(0..(config_len as _)).map(|v| v.to_vec())
84    } else {
85      None
86    };
87    Ok(WickMetadata {
88      flags,
89      port: port_name,
90      context: config_bytes.map(Into::into),
91    })
92  }
93
94  #[must_use]
95  pub fn encode(self) -> Bytes {
96    let mut bytes = BytesMut::new();
97    bytes.put_u8(self.flags);
98    bytes.put_u16(self.port.len() as _);
99    bytes.put(self.port.as_bytes());
100    let config = self.context.unwrap_or_default();
101    bytes.put_u16(config.len() as _);
102    bytes.put(config);
103    bytes.freeze()
104  }
105}
106
107#[cfg(test)]
108mod test {
109
110  use anyhow::Result;
111
112  use super::*;
113
114  #[test]
115  fn test_metadata_decode() -> Result<()> {
116    let mut md = WickMetadata::new("left", DONE_FLAG | CLOSE_BRACKET);
117    md.set_context(b"hello".to_vec().into());
118    println!("md: {:?}", md);
119    let bytes = md.encode();
120    println!("bytes: {:02x?}", bytes.to_vec());
121    let meta = WickMetadata::decode(bytes)?;
122    assert_eq!(meta.port, "left");
123    assert!(meta.is_done());
124    assert!(meta.is_close_bracket());
125    assert_eq!(meta.context.unwrap(), b"hello".to_vec());
126    Ok(())
127  }
128}