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