bp3d_proto/message/util/
common.rs1use crate::message::{Error, FromBytes, FromBytesWithOffsets, Message, WriteTo};
30use bytesutil::ReadBytes;
31use std::io::Write;
32use std::marker::PhantomData;
33
34pub struct Optional<T>(PhantomData<T>);
35
36impl<'a, T: FromBytes<'a>> FromBytes<'a> for Optional<T> {
37 type Output = Option<T::Output>;
38
39 fn from_bytes(slice: &'a [u8]) -> Result<Message<Option<T::Output>>, Error> {
40 if slice.is_empty() {
41 Err(Error::Truncated)
42 } else {
43 let b = slice[0] > 0;
44 if b {
45 let msg = T::from_bytes(&slice[1..])?;
46 Ok(Message::new(msg.size() + 1, Some(msg.into_inner())))
47 } else {
48 Ok(Message::new(1, None))
49 }
50 }
51 }
52}
53
54impl<'a, T: FromBytes<'a> + FromBytesWithOffsets<'a>> FromBytesWithOffsets<'a> for Optional<T> {
55 type Offsets = Option<T::Offsets>;
56
57 fn from_bytes_with_offsets(slice: &'a [u8]) -> crate::message::Result<Message<(Self::Output, Self::Offsets)>> {
58 if slice.is_empty() {
59 Err(Error::Truncated)
60 } else {
61 let b = slice[0] > 0;
62 if b {
63 let msg = T::from_bytes_with_offsets(&slice[1..])?;
64 let size = msg.size();
65 let (msg, offsets) = msg.into_inner();
66 Ok(Message::new(size + 1, (Some(msg), Some(offsets))))
67 } else {
68 Ok(Message::new(1, (None, None)))
69 }
70 }
71 }
72}
73
74impl<T: WriteTo> WriteTo for Optional<T> {
75 type Input<'a> = Option<T::Input<'a>>;
76
77 fn write_to<W: Write>(input: &Self::Input<'_>, mut out: W) -> Result<(), Error> {
78 match input {
79 None => out.write_all(&[0x0])?,
80 Some(v) => {
81 out.write_all(&[0x1])?;
82 T::write_to(v, out)?;
83 }
84 }
85 Ok(())
86 }
87}
88
89#[cfg(feature = "tokio")]
90impl<T: crate::message::WriteToAsync> crate::message::WriteToAsync for Optional<T> {
91 async fn write_to_async<W: tokio::io::AsyncWriteExt + Unpin>(
92 input: &Self::Input<'_>,
93 mut out: W,
94 ) -> crate::message::Result<()> {
95 match input {
96 None => out.write_all(&[0x0]).await?,
97 Some(v) => {
98 out.write_all(&[0x1]).await?;
99 T::write_to_async(v, out).await?;
100 }
101 }
102 Ok(())
103 }
104}
105
106#[derive(Debug, Copy, Clone)]
107pub struct ValueLE<T>(PhantomData<T>);
108#[derive(Debug, Copy, Clone)]
109pub struct ValueBE<T>(PhantomData<T>);
110
111impl<'a, T: ReadBytes> FromBytes<'a> for ValueLE<T> {
112 type Output = T;
113
114 fn from_bytes(slice: &'a [u8]) -> Result<Message<Self::Output>, Error> {
115 let size = size_of::<T>();
116 if slice.len() < size {
117 Err(Error::Truncated)
118 } else {
119 let value = T::read_bytes_le(slice);
120 Ok(Message::new(size, value))
121 }
122 }
123}
124
125impl<T: bytesutil::WriteTo> WriteTo for ValueLE<T> {
126 type Input<'a> = T;
127
128 fn write_to<W: Write>(input: &Self::Input<'_>, out: W) -> Result<(), Error> {
129 input.write_to_le(out)?;
130 Ok(())
131 }
132}
133
134#[cfg(feature = "tokio")]
135impl<T: bytesutil::WriteTo + bytesutil::WriteBytes> crate::message::WriteToAsync for ValueLE<T> {
136 async fn write_to_async<W: tokio::io::AsyncWriteExt + Unpin>(
137 input: &Self::Input<'_>,
138 mut out: W,
139 ) -> crate::message::Result<()> {
140 let mut buffer = [0; 8];
141 T::write_bytes_le(input, &mut buffer);
142 out.write_all(&buffer[..size_of::<T>()]).await?;
143 Ok(())
144 }
145}
146
147impl<'a, T: ReadBytes> FromBytes<'a> for ValueBE<T> {
148 type Output = T;
149
150 fn from_bytes(slice: &'a [u8]) -> Result<Message<Self::Output>, Error> {
151 let size = size_of::<T>();
152 if slice.len() < size {
153 Err(Error::Truncated)
154 } else {
155 let value = T::read_bytes_be(slice);
156 Ok(Message::new(size, value))
157 }
158 }
159}
160
161impl<T: bytesutil::WriteTo> WriteTo for ValueBE<T> {
162 type Input<'a> = T;
163
164 fn write_to<W: Write>(input: &Self::Input<'_>, out: W) -> Result<(), Error> {
165 input.write_to_be(out)?;
166 Ok(())
167 }
168}
169
170#[cfg(feature = "tokio")]
171impl<T: bytesutil::WriteTo + bytesutil::WriteBytes> crate::message::WriteToAsync for ValueBE<T> {
172 async fn write_to_async<W: tokio::io::AsyncWriteExt + Unpin>(
173 input: &Self::Input<'_>,
174 mut out: W,
175 ) -> crate::message::Result<()> {
176 let mut buffer = [0; 8];
177 T::write_bytes_be(input, &mut buffer);
178 out.write_all(&buffer[..size_of::<T>()]).await?;
179 Ok(())
180 }
181}