wasmrs_frames/frames/
f_error.rs1use 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 pub stream_id: u32,
13 pub code: u32,
15 pub metadata: Option<Bytes>,
17 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}