Skip to main content

binja/
lib.rs

1mod par;
2mod ser;
3
4pub mod config;
5pub mod containers;
6pub mod error;
7
8pub use par::{BinaryParse, parser::BinaryParser};
9pub use ser::{BinarySerialize, serializer::BinarySerializer};
10
11use crate::error::Result;
12use bytes::BytesMut;
13use config::Config;
14
15#[cfg(feature = "serde")]
16use serde::{Deserialize, Serialize};
17
18#[cfg(feature = "derive")]
19pub use binja_derive::{BinaryParse, BinarySerialize};
20
21/// Serializes a given value into a binary format using the default configuration.
22///
23/// # Default Configuration
24/// - **Optional Strategy**: Tagged (uses a single byte to indicate `Some` or `None`)
25/// - **Endianness**: Little-endian
26/// - **Limit**: No size limit
27/// - **Container Length**: 4 bytes (used to encode the length of sequences, strings, etc.)
28///
29/// # Parameters
30/// - `value`: A reference to the value to be serialized. The value must implement the `Serialize` trait.
31///
32/// # Returns
33/// - `Ok(BytesMut)`: The serialized binary representation of the value.
34/// - `Err(Error)`: An error if serialization fails or exceeds the configured limit.
35///
36/// # Example
37/// ```rust
38/// use binja::{to_bytes, BinarySerialize};
39///
40/// #[derive(BinarySerialize)]
41/// struct Example {
42///     field1: u32,
43///     field2: Option<u32>,
44/// }
45///
46/// let value = Example {
47///     field1: 42,
48///     field2: Some(7),
49/// };
50///
51/// let serialized = to_bytes(&value).unwrap().to_vec();
52/// assert_eq!(serialized, vec![0x2A, 0x0, 0x0, 0x0, 0x1, 0x7, 0x0, 0x0, 0x0]);
53/// ```
54pub fn to_bytes<T>(value: &T) -> Result<BytesMut>
55where
56    T: BinarySerialize,
57{
58    to_bytes_with_config(value, Config::default())
59}
60
61/// See [`to_bytes`].
62#[cfg(feature = "serde")]
63pub fn serde_to_bytes<T>(value: &T) -> Result<BytesMut>
64where
65    T: Serialize,
66{
67    serde_to_bytes_with_config(value, Config::default())
68}
69
70/// Serializes a given value into a binary format using a custom configuration.
71///
72/// # Parameters
73/// - `value`: A reference to the value to be serialized. The value must implement the `Serialize` trait.
74/// - `config`: A `Config` object specifying the serialization settings (e.g., endianness, optional strategy, etc.).
75///
76/// # Returns
77/// - `Ok(BytesMut)`: The serialized binary representation of the value.
78/// - `Err(Error)`: An error if serialization fails or exceeds the configured limit.
79///
80/// # Example
81/// ```rust
82/// use binja::{to_bytes_with_config, BinarySerialize};
83/// use binja::config::{Config, EndiannessStrategy, OptionalStrategy};
84///
85/// #[derive(BinarySerialize)]
86/// struct Example {
87///     field1: u32,
88///     field2: Option<u32>,
89/// }
90///
91/// let config = Config {
92///     endianness_strategy: EndiannessStrategy::Big,
93///     optional_strategy: OptionalStrategy::Tagged,
94///     ..Default::default()
95/// };
96///
97/// let value = Example {
98///     field1: 42,
99///     field2: Some(7),
100/// };
101///
102/// let serialized = to_bytes_with_config(&value, config).unwrap().to_vec();
103/// assert_eq!(serialized, vec![0x00, 0x00, 0x00, 0x2A, 0x01, 0x00, 0x00, 0x00, 0x07]);
104/// ```
105pub fn to_bytes_with_config<T>(value: &T, config: Config) -> Result<BytesMut>
106where
107    T: BinarySerialize,
108{
109    let mut serializer = BinarySerializer::new(config);
110    value.binary_serialize(&mut serializer)?;
111    Ok(serializer.output())
112}
113
114/// See [`to_bytes_with_config`].
115#[cfg(feature = "serde")]
116pub fn serde_to_bytes_with_config<T>(value: &T, config: Config) -> Result<BytesMut>
117where
118    T: Serialize,
119{
120    let mut ser = BinarySerializer::new(config);
121    value.serialize(&mut ser)?;
122    Ok(ser.output())
123}
124
125/// Deserializes a binary slice into a value of type `T` using the default configuration.
126///
127/// # Default Configuration
128/// - **Optional Strategy**: Tagged (uses a single byte to indicate `Some` or `None`)
129/// - **Endianness**: Little-endian
130/// - **Limit**: No size limit
131/// - **Container Length**: 4 bytes (used to decode the length of sequences, strings, etc.)
132///
133/// # Parameters
134/// - `bytes`: The binary slice to deserialize. Must represent a valid serialized value of type `T`.
135///
136/// # Returns
137/// - `Ok((T, usize))`: The deserialized value and the number of bytes read.
138/// - `Err(Error)`: If deserialization fails or the input is invalid.
139///
140/// # Example
141/// ```rust
142/// use binja::{from_bytes, BinaryParse};
143///
144/// #[derive(BinaryParse, PartialEq, Debug)]
145/// struct Example {
146///     field1: u32,
147///     field2: Option<u32>,
148/// }
149///
150/// let bytes = vec![0x2A, 0x0, 0x0, 0x0, 0x1, 0x7, 0x0, 0x0, 0x0];
151/// let (value, size): (Example, usize) = from_bytes(&bytes).unwrap();
152/// assert_eq!(
153///     value,
154///     Example {
155///         field1: 42,
156///         field2: Some(7),
157///     }
158/// );
159/// assert_eq!(size, 0);
160/// ```
161pub fn from_bytes<T>(bytes: &[u8]) -> Result<(T, usize)>
162where
163    T: BinaryParse,
164{
165    from_bytes_with_config(bytes, Config::default())
166}
167
168/// See [`from_bytes`].
169#[cfg(feature = "serde")]
170pub fn serde_from_bytes<'a, T>(bytes: &'a [u8]) -> Result<(T, usize)>
171where
172    T: Deserialize<'a>,
173{
174    serde_from_bytes_with_config(bytes, Config::default())
175}
176
177/// Deserializes a binary slice into a value of type `T` using a custom configuration.
178///
179/// # Parameters
180/// - `bytes`: The binary slice to deserialize. Must represent a valid serialized value of type `T`.
181/// - `config`: The `Config` specifying deserialization settings (endianness, optional strategy, etc.).
182///
183/// # Returns
184/// - `Ok((T, usize))`: The deserialized value and the number of bytes read.
185/// - `Err(Error)`: If deserialization fails or the input is invalid.
186///
187/// # Example
188/// ```rust
189/// use binja::{from_bytes_with_config, BinaryParse};
190/// use binja::config::{Config, EndiannessStrategy, OptionalStrategy};
191///
192/// #[derive(BinaryParse, PartialEq, Debug)]
193/// struct Example {
194///     field1: u32,
195///     field2: Option<u32>,
196/// }
197///
198/// let config = Config {
199///     endianness_strategy: EndiannessStrategy::Big,
200///     optional_strategy: OptionalStrategy::Tagged,
201///     ..Default::default()
202/// };
203///
204/// let bytes = vec![0x00, 0x00, 0x00, 0x2A, 0x01, 0x00, 0x00, 0x00, 0x07];
205/// let (value, size): (Example, usize) = from_bytes_with_config(&bytes, config).unwrap();
206/// assert_eq!(
207///     value,
208///     Example {
209///         field1: 42,
210///         field2: Some(7),
211///     }
212/// );
213/// assert_eq!(size, 0);
214/// ```
215pub fn from_bytes_with_config<T>(bytes: &[u8], config: Config) -> Result<(T, usize)>
216where
217    T: BinaryParse,
218{
219    let mut deserializer = BinaryParser::new(bytes, config);
220
221    let v = T::binary_parse(&mut deserializer)?;
222    let size = deserializer.size();
223
224    Ok((v, size))
225}
226
227/// See [`from_bytes_with_config`].
228#[cfg(feature = "serde")]
229pub fn serde_from_bytes_with_config<'a, T>(bytes: &'a [u8], config: Config) -> Result<(T, usize)>
230where
231    T: Deserialize<'a>,
232{
233    let mut deserializer = BinaryParser::new(bytes, config);
234
235    let v = T::deserialize(&mut deserializer)?;
236    let size = deserializer.size();
237
238    Ok((v, size))
239}
240
241#[macro_export]
242macro_rules! bit {
243    ($bits:expr) => {
244        (1 << $bits)
245    };
246}
247
248#[macro_export]
249macro_rules! bit_mask {
250    ($bits:expr) => {
251        ((1 << $bits) - 1)
252    };
253}