wasmrs_frames/frames/
f_error.rs

1use bytes::{BufMut, Bytes, BytesMut};
2
3use super::{Error, FrameHeader, FrameType, RSocketFrame};
4use crate::util::{from_u24_bytes, from_u32_bytes, to_u24_bytes};
5use crate::{Frame, FrameFlags};
6
7#[derive(Clone)]
8#[cfg_attr(not(target = "wasm32-unknown-unknown"), derive(Debug))]
9#[must_use]
10pub struct ErrorFrame {
11  /// The stream ID this frame belongs to.
12  pub stream_id: u32,
13  /// The error code.
14  pub code: u32,
15  /// Any metadata associated with the Error as raw bytes.
16  pub metadata: Option<Bytes>,
17  /// The error message data.
18  pub data: String,
19}
20
21impl ErrorFrame {}
22
23impl RSocketFrame<ErrorFrame> for ErrorFrame {
24  const FRAME_TYPE: FrameType = FrameType::Err;
25
26  fn stream_id(&self) -> u32 {
27    self.stream_id
28  }
29
30  fn decode_all(mut buffer: Bytes) -> Result<Self, Error> {
31    let header = FrameHeader::from_bytes(buffer.split_to(Frame::LEN_HEADER));
32    Self::decode_frame(&header, buffer)
33  }
34
35  fn decode_frame(header: &FrameHeader, mut buffer: Bytes) -> Result<Self, Error> {
36    Self::check_type(header)?;
37    let metadata = if header.has_metadata() {
38      let metadata_len = from_u24_bytes(&buffer.split_to(3)) as usize;
39      Some(buffer.split_to(metadata_len))
40    } else {
41      None
42    };
43
44    Ok(ErrorFrame {
45      stream_id: header.stream_id(),
46      metadata,
47      code: from_u32_bytes(&buffer.split_to(4)),
48      data: String::from_utf8(buffer.to_vec()).map_err(|_| crate::Error::StringConversion)?,
49    })
50  }
51
52  fn encode(self) -> Bytes {
53    let header = self.gen_header().encode();
54    let (mlen, md) = self.metadata.map_or_else(
55      || (Bytes::new(), Bytes::new()),
56      |md| (to_u24_bytes(md.len() as u32), md),
57    );
58
59    let code = self.code.to_be_bytes();
60    let data = self.data.into_bytes();
61    let mut bytes = BytesMut::with_capacity(Frame::LEN_HEADER + code.len() + data.len());
62    bytes.put(header);
63    bytes.put(mlen);
64    bytes.put(md);
65    bytes.put(code.as_slice());
66    bytes.put(data.as_slice());
67    bytes.freeze()
68  }
69
70  fn gen_header(&self) -> FrameHeader {
71    FrameHeader::new(self.stream_id, FrameType::Err, self.get_flag())
72  }
73
74  fn get_flag(&self) -> FrameFlags {
75    let mut flags = 0;
76    if self.metadata.is_some() {
77      flags |= Frame::FLAG_METADATA;
78    }
79    flags
80  }
81}
82
83#[cfg(test)]
84mod test {
85  use anyhow::Result;
86
87  use super::*;
88  use crate::frames::RSocketFrame;
89
90  static BYTES: &[u8] = include_bytes!("../../testdata/frame.error.bin");
91
92  #[test]
93  fn test_decode() -> Result<()> {
94    println!("{:?}", BYTES);
95    let p = ErrorFrame::decode_all(BYTES.into())?;
96    assert_eq!(p.stream_id, 1234);
97    assert_eq!(&p.data, "errstr");
98    assert_eq!(p.code, 11);
99    Ok(())
100  }
101
102  #[test]
103  fn test_encode() -> Result<()> {
104    let payload = ErrorFrame {
105      stream_id: 1234,
106      metadata: None,
107      data: "errstr".to_owned(),
108      code: 11,
109    };
110    let encoded = payload.encode();
111    assert_eq!(encoded, Bytes::from(BYTES));
112    Ok(())
113  }
114}