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