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
#![warn(missing_docs)]
// #![doc(test(no_crate_inject))]
#![allow(dead_code)]
//! # Zordon
//!
//! ![zordan_image](https://upload.wikimedia.org/wikipedia/en/b/bc/Zordon_power_rangers.jpg)
//!
//! # About
//!
//! `zordon` provides simple low-level abstractions for zero-copy parsing and mutation. It is a no_std crate with alloc.
//!
//! `zordon` types allow a single mutable u8 buffer to be treated as
//! a series of u8-u128, i8-i128 or [u8; _] values without the need to copy data in the original buffer. Setting, getting and
//! adding to the values is transparent via the methods implemented on the calling type.
//!
//! The `[MutView]` derive macro can be used on a data structure whose fields use zordon types. Allowing a buffer to be
//! parsed and manipulated like a typical rust struct.
//!
//! ## Simple example
//! ```
//! use zordon::prelude::*;
//!
//! #[derive(MutView)]
//! struct Example<'a> {
//! u8_f: ByteView<'a, u8>,
//! u16_f: MulByteView<'a, u16, BigEnd>,
//! arr_f: ArrayView<'a, [u8; 3]>,
//! }
//!
//! fn main() {
//! let mut input_buf = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
//! let (mut example, _) = Example::mut_view(&mut input_buf);
//!
//! assert_eq!(example.u8_f.val(), 0x00);
//! assert_eq!(example.u16_f.val(), 0x0102);
//! assert_eq!(*example.arr_f.as_ref(), [0x03, 0x04, 0x05]);
//! }
//! ```
//! ### How it works
//! [`ByteView`]: types::ByteView
//! [`MulByteView`]: types::MulByteView
//! [`ArrayView`]: types::ArrayView
//! [`VarArrayView`]: types::VarArrayView
//! [`ModByteView`]: types::ModByteView
//! [`ModMulByteView`]: types::ModMulByteView
//!
//! #### Deriving `mut_view`
//! ```
//! # use zordon::prelude::*;
//! #[derive(MutView)]
//! struct Example<'a> {
//! u8_f: ByteView<'a, u8>,
//! u16_f: MulByteView<'a, u16, BigEnd>,
//! arr_f: ArrayView<'a, [u8; 3]>,
//! }
//! ```
//! The derive macro [`MutView`] implements a `mut_view` method for the `Example` struct.
//!
//! - `ByteView<'a, u8>` specifies that the underlying data is a single byte value of type [`u8`]
//! - `MulByteView<'a, u16, LitEnd>` specifies that the underlying data is a little endian two byte
//! value of type [`u16`].
//! - `LitEnd` can be swapped with `BigEnd` and the data will be treated as big endian.
//! - `u16` can be swapped with u32-u128 or i16-i128
//! - `ArrayView<'a, [u8; 3]>` specifies that the underlying data is three byte value of type [`u8; 3`]
//!
//! #### Instantiating the struct
//! ```
//! # use zordon::prelude::*;
//! # #[derive(MutView)]
//! # struct Example<'a> {
//! # u8_f: ByteView<'a, u8>,
//! # u16_f: MulByteView<'a, u16, BigEnd>,
//! # arr_f: ArrayView<'a, [u8; 3]>,
//! # }
//! # fn main() {
//! let mut input_buf = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05];
//! let (mut example, _) = Example::mut_view(&mut input_buf);
//! # }
//! ```
//! `mut_view` is called with a `&mut [u8]` as input, which it slices into multiple mutable slices of different
//! lengths based on the field type. Ownership of each slice is transfered to it's respective field.
//!
//! In this case it will:
//! - First, split `input_buf` at an index of 1 (since the length of [`u8`] is one) - `u8_f` now owns this slice
//! - Second, split the remaining slice at an index of 2 (since the length of [`u16`] is two) - `u16_f` now owns this slice
//! - Finally, it splits the remaining slice at an index of 3 (since the length of [`u8; 3`] is three) - `arr_f` now owns this slice
//!
//! The return value of `mut_view` is (Self, &'mut [u8]) where `Self` is the calling type and `&'mut [u8]`
//! is the remaining slice.
//!
//! #### Setting/Getting values
//! ##### [`ByteView`] and [`MulByteView`]
//! To retrive/set the underlying value, the val/set trait methods must be called.
//! - For [`ByteView`] the [`ModByteView`] trait must be in scope.
//! - For [`MulByteView`] the [`ModMulByteView`] trait must be in scope
//! ```
//! use zordon::prelude::*;
//!
//! #[derive(MutView)]
//! struct Example<'a> {
//! u8_f: ByteView<'a, u8>,
//! }
//!
//! fn main() {
//! let mut input_buf = [0x00];
//! let (mut example, _) = Example::mut_view(&mut input_buf);
//!
//! assert_eq!(example.u8_f.val(), 0x00);
//!
//! example.u8_f.set(0xFF);
//! assert_eq!(input_buf[0], 0xFF);
//! }
//! ```
//!
//! ##### [`ArrayView`]
//! Retriving the underlying value for [`ArrayView`] works slightly differently. Rather than returning
//! the data, a mutable/immutable reference to the data is returned.
//! ```
//! # use zordon::prelude::*;
//! #[derive(MutView)]
//! struct Example<'a> {
//! arr_f: ArrayView<'a, [u8; 3]>,
//! }
//!
//! fn main() {
//! let buf = [0x00, 0x01, 0x02];
//! let mut input_buf = buf.clone();
//! let (mut example, _) = Example::mut_view(&mut input_buf);
//!
//! // as reference
//! assert_eq!(*example.arr_f.as_ref(), buf.clone());
//!
//! // set
//! example.arr_f.set(&[0xAA, 0xBB, 0xCC]);
//! assert_eq!(*example.arr_f.as_ref(), [0xAA, 0xBB, 0xCC]);
//!
//! // as mutable reference
//! {
//! let mut m_ref = example.arr_f.as_mut_ref();
//! m_ref[0] = 0xFF;
//! }
//! assert_eq!(input_buf, [0xFF, 0xBB, 0xCC]);
//! }
//! ```
//! ## Composite example
//! ```
//! use zordon::prelude::*;
//!
//! #[derive(MutView)]
//! struct ExampleA<'a> {
//! u8_f: ByteView<'a, u8>,
//! }
//!
//! #[derive(MutView)]
//! struct ExampleB<'a> {
//! u16_f: MulByteView<'a, u16, BigEnd>,
//! }
//!
//! #[derive(MutView)]
//! struct Composite<'a> {
//! example_a: ExampleA<'a>,
//! example_b: ExampleB<'a>,
//! option_c: Option<u8>,
//! }
//!
//! fn main() {
//! let mut input_buf = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05];
//! let (mut comp_e, _) = Composite::mut_view(&mut input_buf);
//!
//! assert_eq!(comp_e.example_a.u8_f.val(), 0x00);
//! assert_eq!(comp_e.example_b.u16_f.val(), 0x0102);
//! assert_eq!(comp_e.option_c, None);
//!
//! comp_e.example_a.u8_f.set(0xFF);
//! assert_eq!(input_buf[0], 0xFF);
//! }
//! ```
//! ## [`VarArrayView`] example
//! This type creates a mutable array view which for a non compile time known length.
//! ```
//! use zordon::prelude::*;
//!
//! fn main() {
//! let arr = &mut [0x1 as u8, 0x2, 0x3, 0x4] as &mut [u8];
//! let buf = arr.iter().map(|x| x.clone()).collect::<Vec<u8>>();
//! let (t, _): (VarArrayView<u8>, _) = VarArrayView::mut_view(arr, arr.len());
//!
//! assert_eq!(*t.as_ref(), buf);
//! }
//! ```
//! ## More examples
//!
//! The crate (NOT PUBLISHED YET) uses zordon for zero-copy parsing of the [PE](https://en.wikipedia.org/wiki/Portable_Executable) format.
//!
//! ## Features
//!
//! - Zero-copy -- Original buffer is split into mutable slices
//! - Able to parse the following types: `[u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, [u8; _], &mut [u8]]`
//! - The types u16..u128 and i16..i128 can be treated as little endian or big endian
//! - Auto implementation of `mut_view` for structs via the [`MutView`] derive macro.
//!
//!
//!
#![no_std]
#[cfg(feature = "std_unit_tests")]
extern crate std;
extern crate alloc;
#[cfg(feature = "std_unit_tests")]
mod tests;
pub mod types;
pub use mutview::MutView;
/// Import prelude to get everything needed into scope
pub mod prelude {
pub use mutview::MutView;
pub use crate::types::*;
}