nuts_bytes/lib.rs
1// MIT License
2//
3// Copyright (c) 2023,2024 Robin Doer
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to
7// deal in the Software without restriction, including without limitation the
8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9// sell copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21// IN THE SOFTWARE.
22
23//! Conversion into a binary data format.
24//!
25//! The `nuts-bytes` crate implements a tool that converts structured data into
26//! a binary format. See the [Format specification] section for a detailed
27//! description of the format.
28//!
29//! # Deserialization from a binary representation
30//!
31//! The deserialization describes the process of converting binary data into a
32//! data type that implements the [`FromBytes`] trait.
33//!
34//! The [`Reader`] utility performs this deserialization by
35//!
36//! 1. taking binary data from a source type that implements the [`TakeBytes`]
37//! trait and finally
38//! 2. performs the [deserialization](Reader::read).
39//!
40//! The crate implements [`TakeBytes`] already for
41//! [`&[u8]`](trait.TakeBytes.html#impl-TakeBytes-for-%26%5Bu8%5D).
42//! It takes bytes from a [slice] of `u8` values.
43//!
44//! ## Deserialization example
45//!
46//! ```rust
47//! use nuts_bytes::{Error, Reader, TakeBytesError};
48//!
49//! // deserialize a primitive (u32)
50//! let mut reader = Reader::new([0x00, 0x00, 0x02, 0x9A].as_slice());
51//! let n: u32 = reader.read().unwrap();
52//!
53//! assert_eq!(n, 666);
54//!
55//! // Not enough data available
56//! let mut reader = Reader::new([0; 3].as_slice());
57//! let err = reader.read::<u32>().unwrap_err();
58//!
59//! assert!(matches!(err, Error::TakeBytes(TakeBytesError::Eof)));
60//! ```
61//!
62//! # Serialization into a binary representation
63//!
64//! The serialization describes the process of converting a data type that
65//! implements the [`ToBytes`] trait into its binary representation.
66//!
67//! The [`Writer`] utility performs this serialization. It
68//!
69//! 1. performs the serialization and finally
70//! 2. pushes the binary data into a target type, that implements the
71//! [`PutBytes`] trait.
72//!
73//! The crate implements [`PutBytes`] for the following types:
74//!
75//! * [`&mut [u8]`](trait.PutBytes.html#impl-PutBytes-for-%26mut+%5Bu8%5D)
76//! Serialize into a [slice] of `u8` values. Not more than [`slice::len()`]
77//! bytes can be written. If the number of bytes exceeds the size of the
78//! slice, a [`PutBytesError::NoSpace`] error is raised.
79//! * [`Vec<u8>`](trait.PutBytes.html#impl-PutBytes-for-Vec<u8>)
80//! Serialize into a [`Vec`] of `u8` values. The binary data are appended to
81//! the [`Vec`].
82//! * [`&mut Vec<u8>`](trait.PutBytes.html#impl-PutBytes-for-%26mut+Vec<u8>)
83//! Serialize into a mutable reference of a [`Vec`] of `u8` values. The
84//! binary data are appended to the [`Vec`].
85//!
86//! ## Serialization examples
87//!
88//! ### Serialize into a vec
89//!
90//! ```rust
91//! use nuts_bytes::Writer;
92//!
93//! // serialize a primitive (u32)
94//! let mut writer = Writer::new(vec![]);
95//! let n = writer.write(&666u32).unwrap();
96//!
97//! assert_eq!(n, 4);
98//! assert_eq!(writer.into_target(), [0x00, 0x00, 0x02, 0x9A]);
99//! ```
100//!
101//! ### Serialize into a slice
102//!
103//! ```rust
104//! use nuts_bytes::Writer;
105//!
106//! // serialize a primitive (u32)
107//! let mut buf = [0; 4];
108//! let mut writer = Writer::new(buf.as_mut_slice());
109//! let n = writer.write(&666u32).unwrap();
110//!
111//! assert_eq!(n, 4);
112//! assert_eq!(buf, [0x00, 0x00, 0x02, 0x9A]);
113//!
114//! // Not enough space for serialization
115//! let mut buf = [0; 3];
116//! let mut writer = Writer::new(buf.as_mut_slice());
117//! let err = writer.write(&666u32).unwrap_err();
118//!
119//! assert_eq!(format!("{}", err), "no more space available for writing");
120//! ```
121//!
122//! # Format specification
123//!
124//! The binary format is described [here](doc_format) in detail.
125//!
126//! [Format specification]: #format-specification
127
128mod error;
129mod from_bytes;
130mod put_bytes;
131mod reader;
132mod take_bytes;
133mod to_bytes;
134mod writer;
135
136#[cfg(doc)]
137pub mod doc_format {
138 //! Documentation: format specification
139 //!
140 #![doc = include_str!("../docs/format.md")]
141}
142
143#[cfg(all(doc, feature = "derive"))]
144pub mod doc_derive {
145 //! Derive macros available if nuts-bytes is built with
146 //! `features = ["derive"]`.
147 //!
148 #![doc = include_str!("../docs/derive.md")]
149}
150
151pub use error::Error;
152pub use from_bytes::FromBytes;
153#[cfg(feature = "derive")]
154pub use nuts_bytes_derive::{FromBytes, ToBytes};
155pub use put_bytes::{PutBytes, PutBytesError};
156pub use reader::Reader;
157pub use take_bytes::{TakeBytes, TakeBytesError};
158pub use to_bytes::ToBytes;
159pub use writer::Writer;
160
161#[doc = include_str!("../README.md")]
162#[cfg(doctest)]
163pub struct ReadmeDoctests;