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 {}