bp3d_proto/message/
interface.rs1use bp3d_util::simple_error;
30
31simple_error! {
32 pub Error {
33 InvalidUtf8 => "invalid UTF-8 string",
34 Truncated => "truncated input",
35 InvalidUnionDiscriminant(usize) => "invalid union discriminant ({})",
36 (impl From) Io(std::io::Error) => "io error: {}"
37 }
38}
39
40pub type Result<T> = std::result::Result<T, Error>;
41
42#[derive(Default, Copy, Clone, Debug)]
43pub struct FieldOffset {
44 pub start: usize,
45 pub end: usize,
46}
47
48impl FieldOffset {
49 pub fn size(&self) -> usize {
50 self.end - self.start
51 }
52}
53
54pub struct Message<T> {
55 data: T,
56 size: usize,
57}
58
59impl<T> Message<T> {
60 pub fn new(size: usize, data: T) -> Self {
61 Self { data, size }
62 }
63
64 pub fn into_inner(self) -> T {
65 self.data
66 }
67
68 pub fn into_parts(self) -> (T, usize) {
70 (self.data, self.size)
71 }
72
73 pub fn size(&self) -> usize {
74 self.size
75 }
76
77 pub fn map<T1, F: FnOnce(T) -> T1>(self, f: F) -> Message<T1> {
78 Message::new(self.size(), f(self.into_inner()))
79 }
80}
81
82pub trait FromBytes<'a> {
83 type Output: Sized;
84
85 fn from_bytes(slice: &'a [u8]) -> Result<Message<Self::Output>>;
86 }
88
89pub trait FromBytesWithOffsets<'a>: FromBytes<'a> {
90 type Offsets: Sized;
91
92 fn from_bytes_with_offsets(slice: &'a [u8]) -> Result<Message<(Self::Output, Self::Offsets)>>;
93}
94
95pub trait WriteTo {
96 type Input<'a>: Sized;
97
98 fn write_to<W: std::io::Write>(input: &Self::Input<'_>, out: W) -> Result<()>;
99}
100
101pub trait ShapeAndWrite {
102 fn shape_and_write<W: std::io::Write>(self, out: W) -> Result<()>;
103}
104
105#[cfg(feature = "tokio")]
106pub trait ShapeAndWriteAsync {
107 fn shape_and_write_async<W: tokio::io::AsyncWriteExt + Unpin>(
108 self,
109 out: W,
110 ) -> impl std::future::Future<Output = Result<()>>;
111}
112
113#[cfg(feature = "tokio")]
114pub trait WriteToAsync: WriteTo {
115 fn write_to_async<W: tokio::io::AsyncWriteExt + Unpin>(
116 input: &Self::Input<'_>,
117 out: W,
118 ) -> impl std::future::Future<Output = Result<()>>;
119}
120
121pub trait WriteSelf {
122 fn write_self<W: std::io::Write>(&self, out: W) -> Result<()>;
123 fn size(&self) -> Result<usize>;
124}
125
126#[cfg(feature = "tokio")]
127pub trait WriteSelfAsync {
128 fn write_self_async<W: tokio::io::AsyncWriteExt + Unpin>(
129 &self,
130 out: W,
131 ) -> impl std::future::Future<Output = Result<()>>;
132}
133
134pub trait FromBytesWithHeader<'a, H> {
135 type Output: Sized;
136
137 fn from_bytes_with_header(slice: &'a [u8], header: &H) -> Result<Message<Self::Output>>;
138}
139
140pub trait WriteToWithHeader<H> {
141 type Input<'a>: Sized;
142
143 fn write_to_with_header<W: std::io::Write>(input: &Self::Input<'_>, header: &H, out: W) -> Result<()>;
144}
145
146pub trait ShapeHeader<H> {
147 fn shape_header(&self, header: &mut H) -> Result<()>;
148}
149
150impl<H, T: WriteSelf> ShapeHeader<H> for T {
151 fn shape_header(&self, _: &mut H) -> Result<()> {
152 Ok(())
153 }
154}
155
156#[cfg(feature = "tokio")]
157pub trait WriteToWithHeaderAsync<H>: WriteToWithHeader<H> {
158 fn write_to_with_header_async<W: tokio::io::AsyncWriteExt + Unpin>(
159 input: &Self::Input<'_>,
160 header: &H,
161 out: W,
162 ) -> impl std::future::Future<Output = Result<()>>;
163}
164
165impl<'a, T: WriteTo<Input<'a> = T>> WriteSelf for T {
166 fn write_self<W: std::io::Write>(&self, out: W) -> Result<()> {
167 T::write_to(self, out)
168 }
169
170 fn size(&self) -> Result<usize> {
171 crate::message::util::size_of(self)
172 }
173}
174
175#[cfg(feature = "tokio")]
176impl<T> WriteSelfAsync for T
177where
178 for<'a> T: WriteToAsync<Input<'a> = T>,
179{
180 async fn write_self_async<W: tokio::io::AsyncWriteExt + Unpin>(&self, out: W) -> Result<()> {
181 T::write_to_async(self, out).await
182 }
183}
184
185impl<H, T: WriteSelf> WriteToWithHeader<H> for T {
186 type Input<'b> = T;
187
188 fn write_to_with_header<W: std::io::Write>(input: &Self::Input<'_>, _: &H, out: W) -> Result<()> {
189 input.write_self(out)
190 }
191}
192
193#[cfg(feature = "tokio")]
194impl<H, T: WriteSelf + WriteSelfAsync> WriteToWithHeaderAsync<H> for T {
195 fn write_to_with_header_async<W: tokio::io::AsyncWriteExt + Unpin>(
196 input: &Self::Input<'_>,
197 _: &H,
198 out: W,
199 ) -> impl std::future::Future<Output = Result<()>> {
200 input.write_self_async(out)
201 }
202}
203
204impl<'a, H, T: FromBytes<'a>> FromBytesWithHeader<'a, H> for T {
205 type Output = T::Output;
206
207 fn from_bytes_with_header(slice: &'a [u8], _: &H) -> Result<Message<Self::Output>> {
208 T::from_bytes(slice)
209 }
210}