binrw/binwrite/mod.rs
1mod impls;
2
3use crate::{
4 io::{Seek, Write},
5 BinResult, Endian,
6 __private::Required,
7};
8
9/// The `BinWrite` trait serialises objects and writes them to streams.
10///
11/// This trait is usually derived, but can also be manually implemented by
12/// writing an appropriate [`Args`] type and [`write_options()`] function.
13///
14/// [`Args`]: Self::Args
15/// [`write_options()`]: Self::write_options
16///
17/// # Derivable
18///
19/// This trait can be used with `#[derive]` or `#[binwrite]`. Each field
20/// of a derived type must either implement `BinWrite` or be annotated with an
21/// attribute containing a [`map`], [`try_map`], or [`write_with`] directive.
22///
23/// [`map`]: crate::docs::attribute#map
24/// [`write_with`]: crate::docs::attribute#custom-parserswriters
25/// [`try_map`]: crate::docs::attribute#map
26///
27/// Using `#[binwrite]` instead of `#[derive]` is required when using
28/// [temporary fields].
29///
30/// [temporary fields]: crate::docs::attribute#temp
31pub trait BinWrite {
32 /// The type used for the `args` parameter of [`write_args()`] and
33 /// [`write_options()`].
34 ///
35 /// When the given type implements [`Default`], convenience functions like
36 /// [`write()`] are enabled. `BinWrite` implementations that don’t
37 /// receive any arguments should use the `()` type.
38 ///
39 /// When `BinWrite` is derived, the [`import`] and [`import_tuple`]
40 /// directives define this type.
41 ///
42 /// [`import`]: crate::docs::attribute#arguments
43 /// [`import_tuple`]: crate::docs::attribute#arguments
44 /// [`write()`]: Self::write
45 /// [`write_args()`]: Self::write_args
46 /// [`write_options()`]: Self::write_options
47 type Args<'a>;
48
49 /// Write `Self` to the writer using default arguments.
50 ///
51 /// # Errors
52 ///
53 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
54 #[inline]
55 fn write<W: Write + Seek>(&self, writer: &mut W) -> BinResult<()>
56 where
57 Self: crate::meta::WriteEndian,
58 for<'a> Self::Args<'a>: Required,
59 {
60 self.write_args(writer, Self::Args::args())
61 }
62
63 /// Write `Self` to the writer assuming big-endian byte order.
64 ///
65 /// # Errors
66 ///
67 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
68 #[inline]
69 fn write_be<W: Write + Seek>(&self, writer: &mut W) -> BinResult<()>
70 where
71 for<'a> Self::Args<'a>: Required,
72 {
73 self.write_be_args(writer, Self::Args::args())
74 }
75
76 /// Write `Self` to the writer assuming little-endian byte order.
77 ///
78 /// # Errors
79 ///
80 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
81 #[inline]
82 fn write_le<W: Write + Seek>(&self, writer: &mut W) -> BinResult<()>
83 where
84 for<'a> Self::Args<'a>: Required,
85 {
86 self.write_le_args(writer, Self::Args::args())
87 }
88
89 /// Write `Self` to the writer assuming native-endian byte order.
90 ///
91 /// # Errors
92 ///
93 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
94 #[inline]
95 fn write_ne<W: Write + Seek>(&self, writer: &mut W) -> BinResult<()>
96 where
97 for<'a> Self::Args<'a>: Required,
98 {
99 self.write_ne_args(writer, Self::Args::args())
100 }
101
102 /// Write `Self` to the writer using the given arguments.
103 ///
104 /// # Errors
105 ///
106 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
107 #[inline]
108 fn write_args<W: Write + Seek>(&self, writer: &mut W, args: Self::Args<'_>) -> BinResult<()>
109 where
110 Self: crate::meta::WriteEndian,
111 {
112 self.write_options(writer, Endian::Little, args)
113 }
114
115 /// Write `Self` to the writer, assuming big-endian byte order, using the
116 /// given arguments.
117 ///
118 /// # Errors
119 ///
120 /// If reading fails, an [`Error`](crate::Error) variant will be returned.
121 #[inline]
122 fn write_be_args<W: Write + Seek>(
123 &self,
124 writer: &mut W,
125 args: Self::Args<'_>,
126 ) -> BinResult<()> {
127 self.write_options(writer, Endian::Big, args)
128 }
129
130 /// Write `Self` to the writer, assuming little-endian byte order, using the
131 /// given arguments.
132 ///
133 /// # Errors
134 ///
135 /// If reading fails, an [`Error`](crate::Error) variant will be returned.
136 #[inline]
137 fn write_le_args<W: Write + Seek>(
138 &self,
139 writer: &mut W,
140 args: Self::Args<'_>,
141 ) -> BinResult<()> {
142 self.write_options(writer, Endian::Little, args)
143 }
144
145 /// Write `Self` to the writer, assuming native-endian byte order, using the
146 /// given arguments.
147 ///
148 /// # Errors
149 ///
150 /// If reading fails, an [`Error`](crate::Error) variant will be returned.
151 #[inline]
152 fn write_ne_args<W: Write + Seek>(
153 &self,
154 writer: &mut W,
155 args: Self::Args<'_>,
156 ) -> BinResult<()> {
157 self.write_options(writer, Endian::NATIVE, args)
158 }
159
160 /// Write `Self` to the writer using the given [`Endian`] and
161 /// arguments.
162 ///
163 /// # Errors
164 ///
165 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
166 fn write_options<W: Write + Seek>(
167 &self,
168 writer: &mut W,
169 endian: Endian,
170 args: Self::Args<'_>,
171 ) -> BinResult<()>;
172}
173
174/// Extension methods for writing [`BinWrite`] objects directly to a writer.
175///
176/// # Examples
177///
178/// ```
179/// use binrw::{binwrite, BinWriterExt, io::Cursor, Endian};
180///
181/// #[binwrite]
182/// struct MyStruct(u8, u16, u8);
183///
184/// let mut writer = Cursor::new(Vec::new());
185/// writer.write_be(&MyStruct(1, 0xffff, 2)).unwrap();
186/// writer.write_type(&0x1234_u16, Endian::Little).unwrap();
187///
188/// assert_eq!(writer.into_inner(), [1, 0xff, 0xff, 2, 0x34, 0x12]);
189/// ```
190pub trait BinWriterExt: Write + Seek + Sized {
191 /// Write `T` to the writer with the given byte order.
192 ///
193 /// # Errors
194 ///
195 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
196 #[inline]
197 fn write_type<T: BinWrite>(&mut self, value: &T, endian: Endian) -> BinResult<()>
198 where
199 for<'a> T::Args<'a>: Required,
200 {
201 self.write_type_args(value, endian, T::Args::args())
202 }
203
204 /// Write `T` to the writer assuming big-endian byte order.
205 ///
206 /// # Errors
207 ///
208 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
209 #[inline]
210 fn write_be<T: BinWrite>(&mut self, value: &T) -> BinResult<()>
211 where
212 for<'a> T::Args<'a>: Required,
213 {
214 self.write_type(value, Endian::Big)
215 }
216
217 /// Write `T` to the writer assuming little-endian byte order.
218 ///
219 /// # Errors
220 ///
221 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
222 #[inline]
223 fn write_le<T: BinWrite>(&mut self, value: &T) -> BinResult<()>
224 where
225 for<'a> T::Args<'a>: Required,
226 {
227 self.write_type(value, Endian::Little)
228 }
229
230 /// Write `T` to the writer assuming native-endian byte order.
231 ///
232 /// # Errors
233 ///
234 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
235 #[inline]
236 fn write_ne<T: BinWrite>(&mut self, value: &T) -> BinResult<()>
237 where
238 for<'a> T::Args<'a>: Required,
239 {
240 self.write_type(value, Endian::NATIVE)
241 }
242
243 /// Write `T` to the writer with the given byte order and arguments.
244 ///
245 /// # Errors
246 ///
247 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
248 #[inline]
249 fn write_type_args<T: BinWrite>(
250 &mut self,
251 value: &T,
252 endian: Endian,
253 args: T::Args<'_>,
254 ) -> BinResult<()> {
255 T::write_options(value, self, endian, args)
256 }
257
258 /// Write `T` to the writer, assuming big-endian byte order, using the
259 /// given arguments.
260 ///
261 /// # Errors
262 ///
263 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
264 #[inline]
265 fn write_be_args<T: BinWrite>(&mut self, value: &T, args: T::Args<'_>) -> BinResult<()> {
266 self.write_type_args(value, Endian::Big, args)
267 }
268
269 /// Write `T` to the writer, assuming little-endian byte order, using the
270 /// given arguments.
271 ///
272 /// # Errors
273 ///
274 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
275 #[inline]
276 fn write_le_args<T: BinWrite>(&mut self, value: &T, args: T::Args<'_>) -> BinResult<()> {
277 self.write_type_args(value, Endian::Little, args)
278 }
279
280 /// Write `T` to the writer, assuming native-endian byte order, using the
281 /// given arguments.
282 ///
283 /// # Errors
284 ///
285 /// If writing fails, an [`Error`](crate::Error) variant will be returned.
286 #[inline]
287 fn write_ne_args<T: BinWrite>(&mut self, value: &T, args: T::Args<'_>) -> BinResult<()> {
288 self.write_type_args(value, Endian::NATIVE, args)
289 }
290}
291
292impl<W: Write + Seek + Sized> BinWriterExt for W {}