Skip to main content

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 using the given arguments.
90    ///
91    /// # Errors
92    ///
93    /// If writing fails, an [`Error`](crate::Error) variant will be returned.
94    #[inline]
95    fn write_args<W: Write + Seek>(&self, writer: &mut W, args: Self::Args<'_>) -> BinResult<()>
96    where
97        Self: crate::meta::WriteEndian,
98    {
99        self.write_options(writer, Endian::Little, args)
100    }
101
102    /// Write `Self` to the writer, assuming big-endian byte order, using the
103    /// given arguments.
104    ///
105    /// # Errors
106    ///
107    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
108    #[inline]
109    fn write_be_args<W: Write + Seek>(
110        &self,
111        writer: &mut W,
112        args: Self::Args<'_>,
113    ) -> BinResult<()> {
114        self.write_options(writer, Endian::Big, args)
115    }
116
117    /// Write `Self` to the writer, assuming little-endian byte order, using the
118    /// given arguments.
119    ///
120    /// # Errors
121    ///
122    /// If reading fails, an [`Error`](crate::Error) variant will be returned.
123    #[inline]
124    fn write_le_args<W: Write + Seek>(
125        &self,
126        writer: &mut W,
127        args: Self::Args<'_>,
128    ) -> BinResult<()> {
129        self.write_options(writer, Endian::Little, args)
130    }
131
132    /// Write `Self` to the writer using the given [`Endian`] and
133    /// arguments.
134    ///
135    /// # Errors
136    ///
137    /// If writing fails, an [`Error`](crate::Error) variant will be returned.
138    fn write_options<W: Write + Seek>(
139        &self,
140        writer: &mut W,
141        endian: Endian,
142        args: Self::Args<'_>,
143    ) -> BinResult<()>;
144}
145
146/// Extension methods for writing [`BinWrite`] objects directly to a writer.
147///
148/// # Examples
149///
150/// ```
151/// use binrw::{binwrite, BinWriterExt, io::Cursor, Endian};
152///
153/// #[binwrite]
154/// struct MyStruct(u8, u16, u8);
155///
156/// let mut writer = Cursor::new(Vec::new());
157/// writer.write_be(&MyStruct(1, 0xffff, 2)).unwrap();
158/// writer.write_type(&0x1234_u16, Endian::Little).unwrap();
159///
160/// assert_eq!(writer.into_inner(), [1, 0xff, 0xff, 2, 0x34, 0x12]);
161/// ```
162pub trait BinWriterExt: Write + Seek + Sized {
163    /// Write `T` to the writer with the given byte order.
164    ///
165    /// # Errors
166    ///
167    /// If writing fails, an [`Error`](crate::Error) variant will be returned.
168    fn write_type<T: BinWrite>(&mut self, value: &T, endian: Endian) -> BinResult<()>
169    where
170        for<'a> T::Args<'a>: Required,
171    {
172        self.write_type_args(value, endian, T::Args::args())
173    }
174
175    /// Write `T` to the writer assuming big-endian byte order.
176    ///
177    /// # Errors
178    ///
179    /// If writing fails, an [`Error`](crate::Error) variant will be returned.
180    fn write_be<T: BinWrite>(&mut self, value: &T) -> BinResult<()>
181    where
182        for<'a> T::Args<'a>: Required,
183    {
184        self.write_type(value, Endian::Big)
185    }
186
187    /// Write `T` to the writer assuming little-endian byte order.
188    ///
189    /// # Errors
190    ///
191    /// If writing fails, an [`Error`](crate::Error) variant will be returned.
192    fn write_le<T: BinWrite>(&mut self, value: &T) -> BinResult<()>
193    where
194        for<'a> T::Args<'a>: Required,
195    {
196        self.write_type(value, Endian::Little)
197    }
198
199    /// Write `T` to the writer assuming native-endian byte order.
200    ///
201    /// # Errors
202    ///
203    /// If writing fails, an [`Error`](crate::Error) variant will be returned.
204    fn write_ne<T: BinWrite>(&mut self, value: &T) -> BinResult<()>
205    where
206        for<'a> T::Args<'a>: Required,
207    {
208        self.write_type(value, Endian::NATIVE)
209    }
210
211    /// Write `T` to the writer with the given byte order and arguments.
212    ///
213    /// # Errors
214    ///
215    /// If writing fails, an [`Error`](crate::Error) variant will be returned.
216    fn write_type_args<T: BinWrite>(
217        &mut self,
218        value: &T,
219        endian: Endian,
220        args: T::Args<'_>,
221    ) -> BinResult<()> {
222        T::write_options(value, self, endian, args)?;
223
224        Ok(())
225    }
226
227    /// Write `T` to the writer, assuming big-endian byte order, using the
228    /// given arguments.
229    ///
230    /// # Errors
231    ///
232    /// If writing fails, an [`Error`](crate::Error) variant will be returned.
233    fn write_be_args<T: BinWrite>(&mut self, value: &T, args: T::Args<'_>) -> BinResult<()> {
234        self.write_type_args(value, Endian::Big, args)
235    }
236
237    /// Write `T` to the writer, assuming little-endian byte order, using the
238    /// given arguments.
239    ///
240    /// # Errors
241    ///
242    /// If writing fails, an [`Error`](crate::Error) variant will be returned.
243    fn write_le_args<T: BinWrite>(&mut self, value: &T, args: T::Args<'_>) -> BinResult<()> {
244        self.write_type_args(value, Endian::Little, args)
245    }
246
247    /// Write `T` to the writer, assuming native-endian byte order, using the
248    /// given arguments.
249    ///
250    /// # Errors
251    ///
252    /// If writing fails, an [`Error`](crate::Error) variant will be returned.
253    fn write_ne_args<T: BinWrite>(&mut self, value: &T, args: T::Args<'_>) -> BinResult<()> {
254        self.write_type_args(value, Endian::NATIVE, args)
255    }
256}
257
258impl<W: Write + Seek + Sized> BinWriterExt for W {}