1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
//! Need help or want to contribute? Join us on [discord] or [matrix]! (whichever you prefer, they're
//! bridged together)
//!
//! ---
//!
//! |**Quick links**|[`#[br]`](attribute::read)|[`#[bw]`](attribute::write)|[`BinReaderExt`]|[discord]|[matrix]|
//! |-|-|-|-|-|-|
//!
//! ---
//!
//! [discord]: https://discord.gg/ABy4Qh549j
//! [matrix]: https://matrix.to/#/#binrw:matrix.org
//!
//! binrw helps you write maintainable & easy-to-read declarative binary data
//! readers and writers using ✨macro magic✨.
//!
//! Adding [`#[binrw]`](macro@binrw) (or `#[derive(BinRead, BinWrite)]`) to a struct or enum
//! generates a parser that can read that type from raw data and a writer that
//! can write it back to bytes:
//!
//! ```
//! use binrw::binrw; // #[binrw] attribute
//! use binrw::{BinReaderExt, BinWrite, io::Cursor}; // reading/writing utilities
//!
//! #[binrw]
//! # #[derive(Debug, PartialEq)]
//! #[br(little)]
//! struct Point(i16, i16);
//!
//! // Read a point from bytes
//! let point: Point = Cursor::new(b"\x80\x02\xe0\x01").read_le().unwrap();
//! assert_eq!(point, Point(640, 480));
//!
//! // Write the point back to bytes
//! let mut writer = Cursor::new(Vec::new());
//! point.write_to(&mut writer).unwrap();
//! assert_eq!(&writer.into_inner()[..], b"\x80\x02\xe0\x01");
//! ```
//!
//! These types are composable, allowing you to use [`BinRead`]/[`BinWrite`] types within
//! others without any special logic:
//!
//! ```
//! # use binrw::{binrw, BinRead, BinWrite, io::Cursor};
//! # #[binrw]
//! # #[derive(Debug, PartialEq)]
//! # #[br(little)]
//! # struct Point(i16, i16);
//! #
//! # #[derive(Debug, PartialEq)]
//! #[derive(BinRead)]
//! #[br(big, magic = b"SHAP")]
//! enum Shape {
//!     #[br(magic(0u8))] Rect {
//!         left: i16, top: i16, right: i16, bottom: i16
//!     },
//!     #[br(magic(1u8))] Oval { origin: Point, rx: u8, ry: u8 }
//! }
//!
//! let oval = Shape::read(&mut Cursor::new(b"SHAP\x01\x80\x02\xe0\x01\x2a\x15")).unwrap();
//! assert_eq!(oval, Shape::Oval { origin: Point(640, 480), rx: 42, ry: 21 });
//! ```
//!
//! Types that can’t implement `BinRead` directly (e.g. types from third party
//! crates) can also be read using
//! [free parser functions](attribute#custom-parsers) or by
//! [mapping values](attribute#map).
//!
//! Unlike “zero-copy” libraries, the in-memory representation of binrw structs
//! doesn’t need to match the raw data. This can allow for better memory
//! performance, especially on architectures where unaligned memory access is
//! slow. Also, because data is never [transmuted](core::mem::transmute), there
//! is no risk of undefined behaviour.
//!
//! # Input
//!
//! `BinRead` reads data from any object that implements [`io::Read`] +
//! [`io::Seek`]. This means that data can come from memory, network, disk, or
//! any other streaming source. It also means that low-level data operations
//! like buffering and compression are efficient and easy to implement.
//!
//! `BinRead` also includes an [extension trait](BinReaderExt) for reading types
//! directly from input objects:
//!
//! ```rust
//! use binrw::{BinReaderExt, io::Cursor};
//!
//! let mut reader = Cursor::new(b"\x00\x0A");
//! let val: u16 = reader.read_be().unwrap();
//! assert_eq!(val, 10);
//! ```
//!
//! # Directives
//!
//! Handling things like magic numbers, byte ordering, and padding & alignment
//! is typical when working with binary data, so binrw includes a variety of
//! [built-in directives](attribute) for these common cases that can be applied
//! using the `#[br]` attribute:
//!
//! ```
//! # use binrw::{prelude::*, io::Cursor, NullString};
//! #
//! #[derive(BinRead)]
//! #[br(magic = b"DOG", assert(name.len() != 0))]
//! struct Dog {
//!     bone_pile_count: u8,
//!
//!     #[br(big, count = bone_pile_count)]
//!     bone_piles: Vec<u16>,
//!
//!     #[br(align_before = 0xA)]
//!     name: NullString
//! }
//!
//! let mut data = Cursor::new(b"DOG\x02\x00\x01\x00\x12\0\0Rudy\0");
//! let dog = Dog::read(&mut data).unwrap();
//! assert_eq!(dog.bone_piles, &[0x1, 0x12]);
//! assert_eq!(dog.name.into_string(), "Rudy")
//! ```
//!
//! Directives can also reference earlier fields by name. For tuple types,
//! earlier fields are addressable by `self_N`, where `N` is the index of the
//! field.
//!
//! See the [attribute module](attribute) for the full list of available
//! directives.
//!
//! # Built-in implementations
//!
//! Implementations for all primitive data types, arrays, tuples, and standard
//! Rust types like [`Vec`] are included, along with parsers for other
//! frequently used binary data patterns like
//! [null-terminated strings](NullString) and
//! [indirect addressing using offsets](FilePtr). Convenient access into
//! bitfields is possible using crates like
//! [modular-bitfield](attribute#using-map-on-a-struct-to-create-a-bit-field).
//!
//! See the [`BinRead` trait](BinRead#foreign-impls) for the full list of
//! built-in implementations.
//!
//! # no_std support
//!
//! binrw supports no_std and includes a compatible subset of [`io`]
//! functionality. The [`alloc`] crate is required.

#![cfg_attr(not(feature = "std"), no_std)]
#![warn(rust_2018_idioms)]
#![warn(missing_docs)]

// binrw_derive expects to be able to access items in binrw via
// `::binrw::<whatever>`. Normally, this would fail in this crate
// because binrw knows of no crate called "binrw".
// This causes binrw to associate *itself* as binrw,
// meaning it makes access via ::binrw work.
#[allow(unused_extern_crates)]
extern crate self as binrw;

#[doc(hidden)]
#[cfg(feature = "std")]
pub use std as alloc;

#[doc(hidden)]
#[cfg(not(feature = "std"))]
pub extern crate alloc;

#[cfg(all(doc, not(feature = "std")))]
use alloc::vec::Vec;

#[doc(hidden)]
#[path = "private.rs"]
pub mod __private;

pub mod attribute;
pub mod endian;
pub mod error;
pub mod file_ptr;
#[doc(hidden)]
pub mod has_magic;
pub mod helpers;
pub mod io;

#[doc(hidden)]
pub mod pos_value;
pub mod punctuated;
#[doc(hidden)]
pub mod strings;

#[doc(inline)]
pub use {
    endian::Endian,
    error::Error,
    file_ptr::{FilePtr, FilePtr128, FilePtr16, FilePtr32, FilePtr64, FilePtr8},
    has_magic::HasMagic,
    helpers::{count, until, until_eof, until_exclusive},
    pos_value::PosValue,
    strings::{NullString, NullWideString},
};

/// The derive macro for [`BinRead`].
pub use binrw_derive::BinRead;

/// The attribute version of the derive macro for [`BinRead`]. Use this instead
/// of `#[derive(BinRead)]` to enable [temporary variables](attribute#temp).
pub use binrw_derive::binread;

/// The derive macro for [`BinWrite`].
pub use binrw_derive::BinWrite;

/// The attribute version of the derive macro for [`BinRead`]. Use this instead
/// of `#[derive(BinRead)]` to enable [temporary variables](attribute#temp).
pub use binrw_derive::binwrite;

/// The attribute version of the derive macro for both [`BinRead`] and [`BinWrite`]. Use
/// instead of `#[derive(BinRead, BinWrite)]` to enable [temporary variables](attribute#temp).
pub use binrw_derive::binrw;

pub use binrw_derive::BinrwNamedArgs;

/// A specialized [`Result`] type for BinRead operations.
pub type BinResult<T> = core::result::Result<T, Error>;

mod binread;
pub use binread::*;

mod binwrite;
pub use binwrite::*;

mod builder_types;
pub use builder_types::*;

pub mod prelude {
    //! The binrw prelude.
    //!
    //! A collection of traits and types you’ll likely need when working with
    //! binrw and are unlikely to cause name conflicts.
    //!
    //! ```
    //! # #![allow(unused_imports)]
    //! use binrw::prelude::*;
    //! ```

    pub use crate::BinRead;
    pub use crate::BinReaderExt;
    pub use crate::BinResult;
    pub use crate::BinWrite;
    pub use crate::BinWriterExt;
}