1pub mod codec;
2pub mod utils;
3pub mod common_impls;
4pub use codec::{FrameCodec, Framed, FramedRead, FramedWrite};
5pub use common_impls::*;
6pub use bytes;
7pub use tokio_util::codec as tokio_codec;
8
9use bytes::{Bytes, BytesMut};
10
11pub trait FromFrame: Sized {
13 type Error;
15
16 fn parse_frame(frame: &mut Bytes) -> Result<Self, Self::Error>;
18
19 fn from_frame(mut frame: Bytes) -> Result<Self, Self::Error> {
21 Self::parse_frame(&mut frame)
22 }
23}
24
25pub trait IntoFrame: Sized {
27 fn extend_frame(&self, frame: &mut BytesMut);
29
30 fn size_hint(&self) -> usize {
32 std::mem::size_of::<Self>()
33 }
34
35 fn into_frame(&self) -> Bytes {
37 let mut frame = BytesMut::with_capacity(self.size_hint());
38 self.extend_frame(&mut frame);
39 frame.into()
40 }
41}
42
43
44#[cfg(test)]
45mod tests {
46 use bytes::{BufMut, BytesMut};
47 use super::*;
48
49 struct Test {
50 id: u64,
51 data: Data,
52 }
53
54 struct Data {
55 a: u32,
56 b: u32,
57 }
58
59 #[test]
60 fn from_frame_test() {
61 impl FromFrame for Test {
62 type Error = anyhow::Error;
63
64 fn parse_frame(frame: &mut Bytes) -> Result<Self, Self::Error> {
65 let id = utils::get_u64(frame, "id")?;
66 let data = Data {
67 a: utils::get_u32(frame, "data.a")?,
68 b: utils::get_u32(frame, "data.b")?,
69 };
70
71 Ok(Self {
72 id,
73 data,
74 })
75 }
76 }
77
78 let mut frame = BytesMut::new();
79 frame.put_u64(42);
80 frame.put_u32(127);
81 frame.put_u32(72);
82
83 let parsed = Test::from_frame(frame.into()).unwrap();
84 assert_eq!(parsed.id, 42);
85 assert_eq!(parsed.data.a, 127);
86 assert_eq!(parsed.data.b, 72);
87 }
88
89 #[test]
90 fn into_frame_test() {
91 impl IntoFrame for Test {
92 fn extend_frame(&self, frame: &mut BytesMut) {
93 frame.put_u64(self.id);
94 frame.put_u32(self.data.a);
95 frame.put_u32(self.data.b);
96 }
97 }
98
99 let test = Test { id: 42, data: Data { a: 127, b: 72 } };
100 let result = test.into_frame();
101
102 let target = Bytes::from_static(&[
103 0, 0, 0, 0, 0, 0, 0, 42,
104 0, 0, 0, 127,
105 0, 0, 0, 72,
106 ]);
107 assert_eq!(&result, &target);
108 }
109}