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}