Add more benchmarks; Redefine 'bool' scheme; Remove 'BoolDecodeError'; Rename project to *oct*; Rename 'librum' crate to 'oct'; Rename 'librum-macros' crate to 'oct-macros'; Rename 'librum-benchmarks' crate to 'oct-benchmarks'; Update lints; Update logo; Restructure tests; Rename 'IStream' to 'Input'; Rename 'OStream' to 'Output'; Make 'Output::write' and 'Input::{read, read_into}' fallible; Add 'OutputError' and 'InputError' error types; Mark 'Output::write' and 'Input::{read, read_into}' with 'const'; Add 'position', 'capacity', and 'remaining' methods to 'Output' and 'Input'; Rename 'SizeError' to 'LengthError'; Rework some error types; Fix feature flags for 'From<CStringDecodeError>' for 'GenericDecodeError'; Rename 'Buf' to 'Slot'; Remove '{Output, Input}::close'; Implement 'AsRef<[u8]>', 'Borrow<[u8]>', 'PartialEq<{Self, [u8], &[u8], &mut [u8]}>', and 'Eq' for 'Output'; Add 'as_slice' and 'as_ptr' methods to 'Output'; Add 'encode' and 'decode' modules; Update homepage link; Refactor code; Update readme;
This commit is contained in:
parent
ef4b3c269a
commit
b6f171e913
74 changed files with 1759 additions and 1445 deletions
32
CHANGELOG.md
32
CHANGELOG.md
|
@ -1,8 +1,38 @@
|
|||
# Changelog
|
||||
|
||||
This is the changelog of [Librum](https://mandelbrot.dk/librum/).
|
||||
This is the changelog of [oct](https://mandelbrot.dk/oct/).
|
||||
See `README.md` for more information.
|
||||
|
||||
## 0.14.0
|
||||
|
||||
* Add more benchmarks
|
||||
* Redefine `bool` scheme
|
||||
* Remove `BoolDecodeError`
|
||||
* Rename project to *oct*
|
||||
* Rename `librum` crate to `oct`
|
||||
* Rename `librum-macros` crate to `oct-macros`
|
||||
* Rename `librum-benchmarks` crate to `oct-benchmarks`
|
||||
* Update lints
|
||||
* Update logo
|
||||
* Restructure tests
|
||||
* Rename `IStream` to `Input`
|
||||
* Rename `OStream` to `Output`
|
||||
* Make `Output::write` and `Input::{read, read_into}` fallible
|
||||
* Add `OutputError` and `InputError` error types
|
||||
* Mark `Output::write` and `Input::{read, read_into}` with `const`
|
||||
* Add `position`, `capacity`, and `remaining` methods to `Output` and `Input`
|
||||
* Rename `SizeError` to `LengthError`
|
||||
* Rework some error types
|
||||
* Fix feature flags for `From<CStringDecodeError>` for `GenericDecodeError`
|
||||
* Rename `Buf` to `Slot`
|
||||
* Remove `{Output, Input}::close`
|
||||
* Implement `AsRef<[u8]>`, `Borrow<[u8]>`, `PartialEq<{Self, [u8], &[u8], &mut [u8]}>`, and `Eq` for `Output`
|
||||
* Add `as_slice` and `as_ptr` methods to `Output`
|
||||
* Add `encode` and `decode` modules
|
||||
* Update homepage link
|
||||
* Refactor code
|
||||
* Update readme
|
||||
|
||||
## 0.13.1
|
||||
|
||||
* Update readme
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
[workspace]
|
||||
members = ["librum", "librum-benchmarks", "librum-macros"]
|
||||
members = ["oct", "oct-benchmarks", "oct-macros"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
authors = ["Gabriel Bjørnager Jensen"]
|
||||
description = "Binary (de)serialiser."
|
||||
readme = "README.md"
|
||||
homepage = "https://achernar.dk/index.php?p=bzipper"
|
||||
repository = "https://mandelbrot.dk/librum/"
|
||||
homepage = "https://docs.rs/oct/latest/oct/"
|
||||
repository = "https://mandelbrot.dk/oct/"
|
||||
license = "LGPL-3.0-or-later"
|
||||
keywords = ["api", "encoding", "io", "network", "no-std"]
|
||||
categories = ["encoding", "network-programming", "parsing"]
|
||||
|
@ -35,6 +35,7 @@ empty_enum_variants_with_brackets = "warn"
|
|||
empty_line_after_doc_comments = "warn"
|
||||
empty_line_after_outer_attr = "warn"
|
||||
empty_structs_with_brackets = "warn"
|
||||
enum_glob_use = "forbid"
|
||||
enum_variant_names = "allow"
|
||||
equatable_if_let = "warn"
|
||||
excessive_precision = "allow"
|
||||
|
@ -52,7 +53,6 @@ from_iter_instead_of_collect = "warn"
|
|||
future_not_send = "deny"
|
||||
if_not_else = "warn"
|
||||
if_then_some_else_none = "warn"
|
||||
ignored_unit_patterns = "warn"
|
||||
impl_trait_in_params = "warn"
|
||||
implicit_clone = "warn"
|
||||
imprecise_flops = "deny"
|
||||
|
|
97
README.md
97
README.md
|
@ -1,8 +1,6 @@
|
|||
# Librum
|
||||
oct is a Rust crate for cheaply serialising (encoding) and deserialising (decoding) data structures into binary streams
|
||||
|
||||
Librum is a Rust crate for cheaply serialising (encoding) and deserialising (decoding) data structures into binary streams
|
||||
|
||||
What separates this crate from others such as [Bincode](https://crates.io/crates/bincode/) or [Postcard](https://crates.io/crates/postcard/) is that this crate is extensively optimised for *just* binary encodings (whilst the mentioned crates specifically use Serde and build on a more abstract data model).
|
||||
What separates this crate from others such as [Bincode](https://crates.io/crates/bincode/) or [Postcard](https://crates.io/crates/postcard/) is that this crate is extensively optimised for directly translating into binary encodings (whilst the mentioned crates specifically use Serde as a middle layer).
|
||||
The original goal of this project was specifically to guarantee size constraints for encodings on a per-type basis at compile-time.
|
||||
Therefore, this crate may be more suited for networking or other cases where many allocations are unwanted.
|
||||
|
||||
|
@ -13,24 +11,25 @@ This crate is compatible with `no_std`.
|
|||
|
||||
## Performance
|
||||
|
||||
As Librum is optimised exclusively for a single, binary format, it *may* outperform other libraries that are more generic in nature.
|
||||
As oct is optimised exclusively for a single, binary format, it *may* outperform other libraries that are more generic in nature.
|
||||
|
||||
The `librum-benchmarks` binary compares multiple scenarios using Librum and other, similar crates.
|
||||
According to my runs on an AMD Ryzen 7 3700X with default settings, these benchmarks indicate that Librum usually outperforms the other tested crates – as demonstrated in the following table:
|
||||
The `oct-benchmarks` binary compares multiple scenarios using oct and other, similar crates.
|
||||
According to my runs on an AMD Ryzen 7 3700X with default settings, these benchmarks indicate that oct usually outperforms the other tested crates -- as demonstrated in the following table:
|
||||
|
||||
| Benchmark | [Bincode] | [Borsh] | Librum | [Postcard] |
|
||||
| Benchmark | [Bincode] | [Borsh] | oct | [Postcard] |
|
||||
| :--------------------------------- | --------: | ------: | ------: | ---------: |
|
||||
| `encode_u8` | 1.004 | 0.947 | 0.806 | 0.972 |
|
||||
| `encode_u32` | 1.130 | 1.084 | 0.749 | 2.793 |
|
||||
| `encode_u128` | 2.340 | 2.328 | 1.543 | 6.380 |
|
||||
| `encode_u8` | 0.968 | 0.857 | 0.733 | 0.979 |
|
||||
| `encode_u32` | 1.065 | 0.999 | 0.730 | 2.727 |
|
||||
| `encode_u128` | 2.168 | 2.173 | 1.510 | 6.246 |
|
||||
| `encode_struct_unit` | 0.000 | 0.000 | 0.000 | 0.000 |
|
||||
| `encode_struct_unnamed` | 1.218 | 1.160 | 0.838 | 2.392 |
|
||||
| `encode_struct_named` | 3.077 | 1.501 | 0.975 | 3.079 |
|
||||
| `encode_enum_unit` | 0.260 | 0.310 | 0.000 | 0.303 |
|
||||
| `decode_u8` | 1.116 | 1.106 | 1.110 | 1.102 |
|
||||
| `decode_non_zero_u8` | 1.228 | 1.236 | 1.269 | 1.263 |
|
||||
| **Total time** → | 11.373 | 9.672 | 7.291 | 18.284 |
|
||||
| **Total deviation (p.c.)** → | +56 | +33 | ±0 | +150 |
|
||||
| `encode_struct_unnamed` | 1.241 | 1.173 | 0.823 | 3.350 |
|
||||
| `encode_struct_named` | 3.079 | 1.507 | 0.973 | 3.082 |
|
||||
| `encode_enum_unit` | 0.246 | 0.297 | 0.000 | 0.295 |
|
||||
| `decode_u8` | 0.942 | 0.962 | 0.922 | 0.923 |
|
||||
| `decode_non_zero_u8` | 1.126 | 1.159 | 1.127 | 1.160 |
|
||||
| `decode_bool` | 1.040 | 1.099 | 1.055 | 1.177 |
|
||||
| **Total time** → | 11.873 | 10.225 | 7.873 | 18.939 |
|
||||
| **Total deviation (p.c.)** → | +51 | +30 | ±0 | +141 |
|
||||
|
||||
[Bincode]: https://crates.io/crates/bincode/
|
||||
[Borsh]: https://crates.io/crates/borsh/
|
||||
|
@ -38,9 +37,9 @@ According to my runs on an AMD Ryzen 7 3700X with default settings, these benchm
|
|||
|
||||
All quantities are measured in seconds unless otherwise noted.
|
||||
|
||||
Currently, Librum's weakest point seems to be decoding.
|
||||
Currently, oct's weakest point seems to be decoding.
|
||||
Please note that I myself find large (relatively speaking) inconsistencies between runs in these last two benchmarks.
|
||||
Do feel free to conduct your own tests of Librum.
|
||||
Do feel free to conduct your own tests of oct.
|
||||
|
||||
## Data model
|
||||
|
||||
|
@ -59,14 +58,16 @@ It may therefore be undesired to store encodings long-term.
|
|||
|
||||
This crate revolves around the `Encode` and `Decode` traits, both of which handle conversions to and from byte streams.
|
||||
|
||||
Many standard types come implemented with Librum, including most primitives as well as some standard library types such as `Option` and `Result`.
|
||||
Many standard types come implemented with oct, including most primitives as well as some standard library types such as `Option` and `Result`.
|
||||
Some [features](#feature-flags) enable an extended set of implementations.
|
||||
|
||||
It is recommended in most cases to simply derive these two traits for user-defined types (although this is only supported with enumerations and structures -- not untagged unions).
|
||||
Here, each field is *chained* according to declaration order:
|
||||
|
||||
```rust
|
||||
use librum::{Buf, Decode, Encode};
|
||||
use oct::Slot;
|
||||
use oct::decode::Decode;
|
||||
use oct::encode::Encode;
|
||||
|
||||
#[derive(Debug, Decode, Encode, PartialEq)]
|
||||
struct Ints {
|
||||
|
@ -85,7 +86,7 @@ const VALUE: Ints = Ints {
|
|||
value4: 0x1E_1D_1C_1B_1A_19_18_17_16_15_14_13_12_11_10_0F,
|
||||
};
|
||||
|
||||
let mut buf = Buf::with_capacity(0x100);
|
||||
let mut buf = Slot::with_capacity(0x100);
|
||||
|
||||
buf.write(VALUE).unwrap();
|
||||
|
||||
|
@ -108,18 +109,18 @@ assert_eq!(buf.read().unwrap(), VALUE);
|
|||
|
||||
The `Encode` and `Decode` traits both rely on streams for carrying the manipulated bytes.
|
||||
|
||||
These streams are separated into two type: *O-streams* (output streams) and *i-streams* (input streams).
|
||||
The `Buf` type can be used to handle these streams.
|
||||
These streams are separated into two type: *output streams* and *input streams*.
|
||||
The `Slot` type can be used to handle these streams.
|
||||
|
||||
### Encoding
|
||||
|
||||
To encode an object directly using the `Encode` trait, simply allocate a buffer for the encoding and wrap it in an `OStream` object:
|
||||
To encode an object directly using the `Encode` trait, simply allocate a buffer for the encoding and wrap it in an `Output` object:
|
||||
|
||||
```rust
|
||||
use librum::{Encode, OStream, SizedEncode};
|
||||
use oct::encode::{Encode, Output, SizedEncode};
|
||||
|
||||
let mut buf = [0x00; char::MAX_ENCODED_SIZE];
|
||||
let mut stream = OStream::new(&mut buf);
|
||||
let mut stream = Output::new(&mut buf);
|
||||
|
||||
'Ж'.encode(&mut stream).unwrap();
|
||||
|
||||
|
@ -129,10 +130,10 @@ assert_eq!(buf, [0x16, 0x04, 0x00, 0x00].as_slice());
|
|||
Streams can also be used to chain multiple objects together:
|
||||
|
||||
```rust
|
||||
use librum::{Encode, OStream, SizedEncode};
|
||||
use oct::encode::{Encode, Output, SizedEncode};
|
||||
|
||||
let mut buf = [0x0; char::MAX_ENCODED_SIZE * 0x5];
|
||||
let mut stream = OStream::new(&mut buf);
|
||||
let mut stream = Output::new(&mut buf);
|
||||
|
||||
// Note: For serialising multiple characters, the
|
||||
// `String` and `SizedStr` types are usually
|
||||
|
@ -156,26 +157,26 @@ If the encoded type additionally implements `SizedEncode`, then the maximum size
|
|||
### Decoding
|
||||
|
||||
Decoding works with a similar syntax to encoding.
|
||||
To decode a byte array, simply call the `decode` method with an `IStream` object:
|
||||
To decode a byte array, simply call the `decode` method with an `Input` object:
|
||||
|
||||
```rust
|
||||
use librum::{Decode, IStream};
|
||||
use oct::decode::{Decode, Input};
|
||||
|
||||
let data = [0x54, 0x45];
|
||||
let mut stream = IStream::new(&data);
|
||||
let mut stream = Input::new(&data);
|
||||
|
||||
assert_eq!(u16::decode(&mut stream).unwrap(), 0x4554);
|
||||
|
||||
// Data can theoretically be reinterpretred:
|
||||
|
||||
stream = IStream::new(&data);
|
||||
stream = Input::new(&data);
|
||||
|
||||
assert_eq!(u8::decode(&mut stream).unwrap(), 0x54);
|
||||
assert_eq!(u8::decode(&mut stream).unwrap(), 0x45);
|
||||
|
||||
// Including as tuples:
|
||||
|
||||
stream = IStream::new(&data);
|
||||
stream = Input::new(&data);
|
||||
|
||||
assert_eq!(<(u8, u8)>::decode(&mut stream).unwrap(), (0x54, 0x45));
|
||||
```
|
||||
|
@ -185,7 +186,9 @@ assert_eq!(<(u8, u8)>::decode(&mut stream).unwrap(), (0x54, 0x45));
|
|||
A UDP server/client for geographic data:
|
||||
|
||||
```rust
|
||||
use librum::{Buf, Encode, Decode, SizedEncode};
|
||||
use oct::Slot;
|
||||
use oct::decode::Decode;
|
||||
use oct::encode::{Encode, SizedEncode};
|
||||
use std::io;
|
||||
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
||||
use std::thread::spawn;
|
||||
|
@ -221,8 +224,8 @@ enum Response {
|
|||
struct Party {
|
||||
pub socket: UdpSocket,
|
||||
|
||||
pub request_buf: Buf::<Request>,
|
||||
pub response_buf: Buf::<Response>,
|
||||
pub request_buf: Slot::<Request>,
|
||||
pub response_buf: Slot::<Response>,
|
||||
}
|
||||
|
||||
impl Party {
|
||||
|
@ -232,8 +235,8 @@ impl Party {
|
|||
let this = Self {
|
||||
socket,
|
||||
|
||||
request_buf: Buf::new(),
|
||||
response_buf: Buf::new(),
|
||||
request_buf: Slot::new(),
|
||||
response_buf: Slot::new(),
|
||||
};
|
||||
|
||||
Ok(this)
|
||||
|
@ -286,28 +289,28 @@ spawn(move || {
|
|||
|
||||
## Feature flags
|
||||
|
||||
Librum defines the following features:
|
||||
oct defines the following features:
|
||||
|
||||
* *`alloc`: Enables the `Buf` type and implementations for e.g. `Box` and `Arc`
|
||||
* *`proc-macro`: Pulls the procedural macros from the `librum-macros` crate
|
||||
* *`alloc`: Enables the `Slot` type and implementations for e.g. `Box` and `Arc`
|
||||
* *`proc-macro`: Pulls the procedural macros from the [`oct-macros`](https://crates.io/crates/oct-macros/) crate
|
||||
* *`std`: Enables implementations for types such as `Mutex` and `RwLock`
|
||||
|
||||
Features marked with * are enabled by default.
|
||||
|
||||
## Documentation
|
||||
|
||||
Librum has its documentation written in-source for use by `rustdoc`.
|
||||
See [Docs.rs](https://docs.rs/librum/latest/librum/) for an on-line, rendered instance.
|
||||
oct has its documentation written in-source for use by `rustdoc`.
|
||||
See [Docs.rs](https://docs.rs/oct/latest/oct/) for an on-line, rendered instance.
|
||||
|
||||
Currently, these docs make use of some unstable features for the sake of readability.
|
||||
The nightly toolchain is therefore required when rendering them.
|
||||
|
||||
## Contribution
|
||||
|
||||
Librum does not accept source code contributions at the moment.
|
||||
oct does not accept source code contributions at the moment.
|
||||
This is a personal choice by the maintainer and may be undone in the future.
|
||||
|
||||
Do however feel free to open up an issue on [GitLab](https://gitlab.com/bjoernager/librum/issues/) or (preferably) [GitHub](https://github.com/bjoernager/librum/issues/) if you feel the need to express any concerns over the project.
|
||||
Do however feel free to open up an issue on [GitLab](https://gitlab.com/bjoernager/oct/issues/) or (preferably) [GitHub](https://github.com/bjoernager/oct/issues/) if you feel the need to express any concerns over the project.
|
||||
|
||||
## Copyright & Licence
|
||||
|
||||
|
|
18
doc-icon.svg
18
doc-icon.svg
|
@ -1,7 +1,17 @@
|
|||
<svg height="72" width="72" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="z">
|
||||
<polygon fill="white" points="12,12 72,12 60,24 48,24 42,30 66,30 54,42 48,42 42,48 72,48 60,60 0,60 12,48 24,48 30,42 5,42 18,30 24,30 30,24 0,24" />
|
||||
<svg height="96" width="96" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="tHorizontalArm">
|
||||
<rect fill="white" height="100%" width="100%" x="0" y="0" />
|
||||
<circle cx="48" cy="48" fill="none" r="32" stroke="black" stroke-width="20" />
|
||||
</mask>
|
||||
|
||||
<rect fill="#FFFFFF" height="100%" mask="url(#z)" width="100%" x="0" y="0" />
|
||||
<mask id="glyph">
|
||||
<!-- O: -->
|
||||
<circle cx="48" cy="48" fill="none" r="32" stroke="white" stroke-width="16" />
|
||||
|
||||
<!-- T: -->
|
||||
<rect fill="white" height="16" paint-order="stroke" stroke="black" stroke-width="4" width="96" x="0" y="40" />
|
||||
<rect fill="white" height="96" mask="url(#tHorizontalArm)" width="16" x="40" y="0" />
|
||||
</mask>
|
||||
|
||||
<rect fill="#FFFFFF" height="100%" mask="url(#glyph)" width="100%" x="0" y="0" />
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 328 B After Width: | Height: | Size: 676 B |
|
@ -1,8 +0,0 @@
|
|||
<svg height="96" width="96" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="z">
|
||||
<polygon fill="white" points="24,24 84,24 72,36 60,36 54,42 78,42 66,54 60,54 54,60 84,60 72,72 12,72 24,60 36,60 42,54 17,54 30,42 36,42 42,36 12,36" />
|
||||
</mask>
|
||||
|
||||
<rect fill="#02764a" height="100%" width="100%" x="0" y="0" /> <!-- oklch(50% 0.115300 158.520) -->
|
||||
<rect fill="#FFFFFF" height="100%" mask="url(#z)" width="100%" x="0" y="0" />
|
||||
</svg>
|
Before Width: | Height: | Size: 432 B |
|
@ -1,43 +0,0 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::error::Error;
|
||||
use core::fmt::{self, Display, Formatter};
|
||||
|
||||
/// A boolean could not be decoded.
|
||||
///
|
||||
/// The encoding scheme for [`bool`] only defines the 8-bit values `0` and `1` (as `false` and `true`, respectively).
|
||||
/// If any other 8-bit is read by <code><bool as [Decode](crate::Decode)>::[decode](crate::Decode::decode)</code>, then an instance of this type is returned.
|
||||
#[derive(Debug)]
|
||||
#[must_use]
|
||||
pub struct BoolDecodeError {
|
||||
/// The invalid value.
|
||||
pub value: u8,
|
||||
}
|
||||
|
||||
impl Display for BoolDecodeError {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "expected boolean but got `{:#02X}`", self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for BoolDecodeError { }
|
|
@ -1,74 +0,0 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::ptr::copy_nonoverlapping;
|
||||
|
||||
/// Byte stream suitable for output.
|
||||
pub struct OStream<'a> {
|
||||
buf: &'a mut [u8],
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl<'a> OStream<'a> {
|
||||
/// Constructs a new o-stream.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn new(buf: &'a mut [u8]) -> Self {
|
||||
Self { buf, pos: 0x0 }
|
||||
}
|
||||
|
||||
/// Writes bytes to the stream.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If the requested amount of bytes could not exactly be written, then this method will panic.
|
||||
#[inline]
|
||||
pub fn write(&mut self, data: &[u8]) {
|
||||
let remaining = self.buf.len() - self.pos;
|
||||
let count = data.len();
|
||||
|
||||
assert!(
|
||||
remaining >= count,
|
||||
"cannot write ({count}) bytes at ({}) to stream with capacity of ({})",
|
||||
self.pos,
|
||||
self.buf.len(),
|
||||
);
|
||||
|
||||
unsafe {
|
||||
let src = data.as_ptr();
|
||||
let dst = self.buf.as_mut_ptr().add(self.pos);
|
||||
|
||||
copy_nonoverlapping(src, dst, count);
|
||||
}
|
||||
|
||||
self.pos += count;
|
||||
}
|
||||
|
||||
/// Closes the stream.
|
||||
///
|
||||
/// The total ammount of bytes written is returned.
|
||||
#[inline(always)]
|
||||
pub const fn close(self) -> usize {
|
||||
let Self { pos, .. } = self;
|
||||
|
||||
pos
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
[package]
|
||||
name = "librum-benchmarks"
|
||||
version = "0.13.1"
|
||||
name = "oct-benchmarks"
|
||||
version = "0.14.0"
|
||||
edition = "2021"
|
||||
description = "Librum benchmarks."
|
||||
description = "oct benchmarks."
|
||||
|
||||
authors.workspace = true
|
||||
readme.workspace = true
|
||||
|
@ -10,7 +10,7 @@ homepage.workspace = true
|
|||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
librum = { path = "../librum", version = "0.13.0", features = ["proc-macro"]}
|
||||
oct = { path = "../oct", version = "0.14.0", features = ["proc-macro"]}
|
||||
|
||||
bincode = "1.3.0"
|
||||
rand = "0.8.0"
|
|
@ -18,7 +18,7 @@ macro_rules! benchmark {
|
|||
|
||||
borsh: $borsh_op:block$(,)?
|
||||
|
||||
librum: $librum_op:block$(,)?
|
||||
oct: $oct_op:block$(,)?
|
||||
|
||||
postcard: $postcard_op:block$(,)?
|
||||
}$(,)?)+
|
||||
|
@ -54,7 +54,7 @@ macro_rules! benchmark {
|
|||
|
||||
let mut total_bincode_duration = 0.0;
|
||||
let mut total_borsh_duration = 0.0;
|
||||
let mut total_librum_duration = 0.0;
|
||||
let mut total_oct_duration = 0.0;
|
||||
let mut total_postcard_duration = 0.0;
|
||||
|
||||
$({
|
||||
|
@ -63,7 +63,7 @@ macro_rules! benchmark {
|
|||
|
||||
let mut bincode_duration = 0.0;
|
||||
let mut borsh_duration = 0.0;
|
||||
let mut librum_duration = 0.0;
|
||||
let mut oct_duration = 0.0;
|
||||
let mut postcard_duration = 0.0;
|
||||
|
||||
for i in 0x0..TEST_COUNT {
|
||||
|
@ -73,7 +73,7 @@ macro_rules! benchmark {
|
|||
|
||||
bincode_duration += time! { $bincode_op };
|
||||
borsh_duration += time! { $borsh_op };
|
||||
librum_duration += time! { $librum_op };
|
||||
oct_duration += time! { $oct_op };
|
||||
postcard_duration += time! { $postcard_op };
|
||||
|
||||
eprint!("\u{001B}[000m");
|
||||
|
@ -83,37 +83,37 @@ macro_rules! benchmark {
|
|||
|
||||
bincode_duration /= f64::from(TEST_COUNT);
|
||||
borsh_duration /= f64::from(TEST_COUNT);
|
||||
librum_duration /= f64::from(TEST_COUNT);
|
||||
oct_duration /= f64::from(TEST_COUNT);
|
||||
postcard_duration /= f64::from(TEST_COUNT);
|
||||
|
||||
eprint!("\u{001B}[000m");
|
||||
eprintln!("bincode: {}", format_score(bincode_duration, librum_duration));
|
||||
eprintln!("borsh: {}", format_score(borsh_duration, librum_duration));
|
||||
eprintln!("librum: {}", format_score(librum_duration, librum_duration));
|
||||
eprintln!("postcard: {}", format_score(postcard_duration, librum_duration));
|
||||
eprintln!("bincode: {}", format_score(bincode_duration, oct_duration));
|
||||
eprintln!("borsh: {}", format_score(borsh_duration, oct_duration));
|
||||
eprintln!("oct: {}", format_score(oct_duration, oct_duration));
|
||||
eprintln!("postcard: {}", format_score(postcard_duration, oct_duration));
|
||||
|
||||
total_bincode_duration += bincode_duration;
|
||||
total_borsh_duration += borsh_duration;
|
||||
total_librum_duration += librum_duration;
|
||||
total_oct_duration += oct_duration;
|
||||
total_postcard_duration += postcard_duration;
|
||||
})*
|
||||
|
||||
eprintln!();
|
||||
eprintln!("\u{001B}[001mtotal score:\u{001B}[022m");
|
||||
eprintln!("bincode: {}", format_score(total_bincode_duration, total_librum_duration));
|
||||
eprintln!("borsh: {}", format_score(total_borsh_duration, total_librum_duration));
|
||||
eprintln!("librum: {}", format_score(total_librum_duration, total_librum_duration));
|
||||
eprintln!("postcard: {}", format_score(total_postcard_duration, total_librum_duration));
|
||||
eprintln!("bincode: {}", format_score(total_bincode_duration, total_oct_duration));
|
||||
eprintln!("borsh: {}", format_score(total_borsh_duration, total_oct_duration));
|
||||
eprintln!("oct: {}", format_score(total_oct_duration, total_oct_duration));
|
||||
eprintln!("postcard: {}", format_score(total_postcard_duration, total_oct_duration));
|
||||
}};
|
||||
}
|
||||
|
||||
#[derive(librum::Decode, librum::Encode, librum::SizedEncode)]
|
||||
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
|
||||
#[derive(borsh::BorshSerialize)]
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
#[repr(transparent)]
|
||||
struct Unit;
|
||||
|
||||
#[derive(librum::Decode, librum::Encode, librum::SizedEncode)]
|
||||
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
|
||||
#[derive(borsh::BorshSerialize)]
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
#[repr(transparent)]
|
||||
|
@ -127,21 +127,12 @@ impl Unnamed {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(librum::Decode, librum::Encode, librum::SizedEncode)]
|
||||
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
|
||||
#[derive(borsh::BorshSerialize)]
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
#[repr(transparent)]
|
||||
struct Named { buf: [u8; 0x8] }
|
||||
|
||||
#[derive(librum::Decode, librum::Encode, librum::SizedEncode)]
|
||||
#[derive(borsh::BorshSerialize)]
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
enum Enum {
|
||||
Unit(Unit),
|
||||
Unnamed(Unnamed),
|
||||
Named(Named),
|
||||
}
|
||||
|
||||
impl Named {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
|
@ -161,6 +152,15 @@ impl Named {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
|
||||
#[derive(borsh::BorshSerialize)]
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
enum Enum {
|
||||
Unit(Unit),
|
||||
Unnamed(Unnamed),
|
||||
Named(Named),
|
||||
}
|
||||
|
||||
fn generate_random_data<T>(item_size: usize, value_count: usize) -> impl Iterator<Item = u8>
|
||||
where
|
||||
T: Immutable + IntoBytes + Sized,
|
||||
|
@ -180,15 +180,15 @@ where
|
|||
}
|
||||
|
||||
fn main() {
|
||||
println!("#####################");
|
||||
println!("# LIBRUM BENCHMARKS #");
|
||||
println!("#####################");
|
||||
println!("##################");
|
||||
println!("# OCT BENCHMARKS #");
|
||||
println!("##################");
|
||||
println!();
|
||||
println!("Each benchmark has a version written for the following crates:");
|
||||
println!();
|
||||
println!("- Bincode: <https://crates.io/crates/bincode/>");
|
||||
println!("- Borsh: <https://crates.io/crates/borsh/>");
|
||||
println!("- Librum: <https://crates.io/crates/librum/>");
|
||||
println!("- oct: <https://crates.io/crates/oct/>");
|
||||
println!("- Postcard: <https://crates.io/crates/postcard/>");
|
||||
println!();
|
||||
println!("The total time the benchmark took (including memory allocations and dealloca-");
|
||||
|
@ -198,10 +198,10 @@ fn main() {
|
|||
println!();
|
||||
println!("When every benchmark has concluded, the total run time and vps is listed for");
|
||||
println!("each crate. A percantage additionally compares the run time between the listed");
|
||||
println!("crate and librum (which should always be c. `0%` for Librum itself). DO NOTE");
|
||||
println!("THAT THESE FINAL RESULTS INDICATE A NON-WEIGHTED AVERAGE ACROSS BENCHMARKS. It");
|
||||
println!("can therefore be skewed relative to real-world performance by the similarity of");
|
||||
println!("some benchmarks.");
|
||||
println!("crate and oct (which should always be c. `0%` for oct itself). DO NOTE THAT");
|
||||
println!("THESE FINAL RESULTS INDICATE A NON-WEIGHTED AVERAGE ACROSS BENCHMARKS. It can");
|
||||
println!("therefore be skewed relative to real-world performance by the similarity of some");
|
||||
println!("benchmarks.");
|
||||
println!();
|
||||
|
||||
eprintln!("test_count: {TEST_COUNT}");
|
||||
|
@ -233,13 +233,13 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
librum: {
|
||||
use librum::{Encode, OStream, SizedEncode};
|
||||
oct: {
|
||||
use oct::encode::{Encode, Output, SizedEncode};
|
||||
|
||||
const ITEM_SIZE: usize = u8::MAX_ENCODED_SIZE;
|
||||
|
||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
||||
let mut stream = OStream::new(&mut buf);
|
||||
let mut stream = Output::new(&mut buf);
|
||||
|
||||
for _ in 0x0..VALUE_COUNT {
|
||||
random::<u8>().encode(&mut stream).unwrap();
|
||||
|
@ -280,13 +280,13 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
librum: {
|
||||
use librum::{Encode, OStream, SizedEncode};
|
||||
oct: {
|
||||
use oct::encode::{Encode, Output, SizedEncode};
|
||||
|
||||
const ITEM_SIZE: usize = u32::MAX_ENCODED_SIZE;
|
||||
|
||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
||||
let mut stream = OStream::new(&mut buf);
|
||||
let mut stream = Output::new(&mut buf);
|
||||
|
||||
for _ in 0x0..VALUE_COUNT {
|
||||
random::<u32>().encode(&mut stream).unwrap();
|
||||
|
@ -327,13 +327,13 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
librum: {
|
||||
use librum::{Encode, OStream, SizedEncode};
|
||||
oct: {
|
||||
use oct::encode::{Encode, Output, SizedEncode};
|
||||
|
||||
const ITEM_SIZE: usize = u128::MAX_ENCODED_SIZE;
|
||||
|
||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
||||
let mut stream = OStream::new(&mut buf);
|
||||
let mut stream = Output::new(&mut buf);
|
||||
|
||||
for _ in 0x0..VALUE_COUNT {
|
||||
random::<u128>().encode(&mut stream).unwrap();
|
||||
|
@ -374,13 +374,13 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
librum: {
|
||||
use librum::{Encode, OStream, SizedEncode};
|
||||
oct: {
|
||||
use oct::encode::{Encode, Output, SizedEncode};
|
||||
|
||||
const ITEM_SIZE: usize = Unit::MAX_ENCODED_SIZE;
|
||||
|
||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
||||
let mut stream = OStream::new(&mut buf);
|
||||
let mut stream = Output::new(&mut buf);
|
||||
|
||||
for _ in 0x0..VALUE_COUNT {
|
||||
Unit.encode(&mut stream).unwrap();
|
||||
|
@ -421,13 +421,13 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
librum: {
|
||||
use librum::{Encode, OStream, SizedEncode};
|
||||
oct: {
|
||||
use oct::encode::{Encode, Output, SizedEncode};
|
||||
|
||||
const ITEM_SIZE: usize = Unnamed::MAX_ENCODED_SIZE;
|
||||
|
||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
||||
let mut stream = OStream::new(&mut buf);
|
||||
let mut stream = Output::new(&mut buf);
|
||||
|
||||
for _ in 0x0..VALUE_COUNT {
|
||||
Unnamed::from_char(random()).encode(&mut stream).unwrap();
|
||||
|
@ -468,13 +468,13 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
librum: {
|
||||
use librum::{Encode, OStream, SizedEncode};
|
||||
oct: {
|
||||
use oct::encode::{Encode, Output, SizedEncode};
|
||||
|
||||
const ITEM_SIZE: usize = Named::MAX_ENCODED_SIZE;
|
||||
|
||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
||||
let mut stream = OStream::new(&mut buf);
|
||||
let mut stream = Output::new(&mut buf);
|
||||
|
||||
for _ in 0x0..VALUE_COUNT {
|
||||
Named::from_u64(random()).encode(&mut stream).unwrap();
|
||||
|
@ -519,15 +519,15 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
librum: {
|
||||
use librum::{Encode, OStream, SizedEncode};
|
||||
oct: {
|
||||
use oct::encode::{Encode, Output, SizedEncode};
|
||||
|
||||
const ITEM_SIZE: usize =
|
||||
isize::MAX_ENCODED_SIZE // discriminant
|
||||
+ Unit::MAX_ENCODED_SIZE;
|
||||
|
||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
||||
let mut stream = OStream::new(&mut buf);
|
||||
let mut stream = Output::new(&mut buf);
|
||||
|
||||
for _ in 0x0..VALUE_COUNT {
|
||||
Enum::Unit(Unit).encode(&mut stream).unwrap();
|
||||
|
@ -572,13 +572,14 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
librum: {
|
||||
use librum::{Decode, IStream, SizedEncode};
|
||||
oct: {
|
||||
use oct::decode::{Decode, Input};
|
||||
use oct::encode::SizedEncode;
|
||||
|
||||
const ITEM_SIZE: usize = u8::MAX_ENCODED_SIZE;
|
||||
|
||||
let buf: Box<[_]> = generate_random_data::<u8>(ITEM_SIZE, VALUE_COUNT).collect();
|
||||
let mut stream = IStream::new(&buf);
|
||||
let mut stream = Input::new(&buf);
|
||||
|
||||
for _ in 0x0..VALUE_COUNT {
|
||||
let _ = u8::decode(&mut stream).unwrap();
|
||||
|
@ -623,13 +624,14 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
librum: {
|
||||
use librum::{Decode, IStream, SizedEncode};
|
||||
oct: {
|
||||
use oct::decode::{Decode, Input};
|
||||
use oct::encode::SizedEncode;
|
||||
|
||||
const ITEM_SIZE: usize = NonZero::<u8>::MAX_ENCODED_SIZE;
|
||||
|
||||
let buf: Box<[_]> = generate_random_data::<NonZero<u8>>(ITEM_SIZE, VALUE_COUNT).collect();
|
||||
let mut stream = IStream::new(&buf);
|
||||
let mut stream = Input::new(&buf);
|
||||
|
||||
for _ in 0x0..VALUE_COUNT {
|
||||
let _ = NonZero::<u8>::decode(&mut stream).unwrap();
|
||||
|
@ -648,5 +650,57 @@ fn main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
decode_bool: {
|
||||
bincode: {
|
||||
const ITEM_SIZE: usize = size_of::<bool>();
|
||||
|
||||
let buf: Box<[_]> = generate_random_data::<bool>(ITEM_SIZE, VALUE_COUNT).collect();
|
||||
|
||||
for i in 0x0..VALUE_COUNT {
|
||||
let data = array::from_ref(&buf[i]).as_slice();
|
||||
|
||||
let _: bool = bincode::deserialize_from(data).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
borsh: {
|
||||
const ITEM_SIZE: usize = size_of::<bool>();
|
||||
|
||||
let buf: Box<[_]> = generate_random_data::<bool>(ITEM_SIZE, VALUE_COUNT).collect();
|
||||
|
||||
for i in 0x0..VALUE_COUNT {
|
||||
let data = array::from_ref(&buf[i]).as_slice();
|
||||
|
||||
let _: bool = borsh::from_slice(data).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
oct: {
|
||||
use oct::decode::{Decode, Input};
|
||||
use oct::encode::SizedEncode;
|
||||
|
||||
const ITEM_SIZE: usize = bool::MAX_ENCODED_SIZE;
|
||||
|
||||
let buf: Box<[_]> = generate_random_data::<bool>(ITEM_SIZE, VALUE_COUNT).collect();
|
||||
let mut stream = Input::new(&buf);
|
||||
|
||||
for _ in 0x0..VALUE_COUNT {
|
||||
let _ = bool::decode(&mut stream).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
postcard: {
|
||||
const ITEM_SIZE: usize = size_of::<bool>();
|
||||
|
||||
let buf: Box<[_]> = generate_random_data::<bool>(ITEM_SIZE, VALUE_COUNT).collect();
|
||||
|
||||
for i in 0x0..VALUE_COUNT {
|
||||
let data = array::from_ref(&buf[i]).as_slice();
|
||||
|
||||
let _: bool = postcard::from_bytes(data).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
[package]
|
||||
name = "librum-macros"
|
||||
version = "0.13.1"
|
||||
name = "oct-macros"
|
||||
version = "0.14.0"
|
||||
edition = "2021"
|
||||
documentation = "https://docs.rs/librum-macros/"
|
||||
documentation = "https://docs.rs/oct-macros/"
|
||||
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::borrow::Borrow;
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
|
@ -82,14 +82,12 @@ impl Debug for GenericName {
|
|||
impl ToTokens for GenericName {
|
||||
#[inline(always)]
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
use GenericName::*;
|
||||
|
||||
match *self {
|
||||
| Const(ref ident)
|
||||
| Ty( ref ident)
|
||||
| Self::Const(ref ident)
|
||||
| Self::Ty( ref ident)
|
||||
=> ident.to_tokens(tokens),
|
||||
|
||||
Lifetime(ref lifetime) => lifetime.to_tokens(tokens),
|
||||
Self::Lifetime(ref lifetime) => lifetime.to_tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{GenericName, Repr};
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Discriminants, Repr};
|
||||
|
@ -38,9 +38,9 @@ pub fn decode_enum(data: DataEnum, repr: Repr) -> TokenStream {
|
|||
|
||||
let commands = iter::repeat_n(
|
||||
quote! {
|
||||
::librum::Decode::decode(stream)
|
||||
.map_err(::core::convert::Into::<::librum::error::GenericDecodeError>::into)
|
||||
.map_err(::librum::error::EnumDecodeError::Field)?
|
||||
::oct::decode::Decode::decode(stream)
|
||||
.map_err(::core::convert::Into::<::oct::error::GenericDecodeError>::into)
|
||||
.map_err(::oct::error::EnumDecodeError::BadField)?
|
||||
},
|
||||
variant.fields.len(),
|
||||
);
|
||||
|
@ -62,18 +62,18 @@ pub fn decode_enum(data: DataEnum, repr: Repr) -> TokenStream {
|
|||
});
|
||||
|
||||
quote! {
|
||||
type Error = ::librum::error::EnumDecodeError<#repr, ::librum::error::GenericDecodeError>;
|
||||
type Error = ::oct::error::EnumDecodeError<#repr, ::oct::error::GenericDecodeError>;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut ::librum::IStream) -> ::core::result::Result<Self, Self::Error> {
|
||||
let discriminant = <#repr as ::librum::Decode>::decode(stream)
|
||||
fn decode(stream: &mut ::oct::decode::Input) -> ::core::result::Result<Self, Self::Error> {
|
||||
let discriminant = <#repr as ::oct::decode::Decode>::decode(stream)
|
||||
.map_err(::core::convert::Into::<::core::convert::Infallible>::into)
|
||||
.map_err(::librum::error::EnumDecodeError::InvalidDiscriminant)?;
|
||||
.map_err(::oct::error::EnumDecodeError::InvalidDiscriminant)?;
|
||||
|
||||
let this = match discriminant {
|
||||
#(#discriminants => #values,)*
|
||||
|
||||
value => return ::core::result::Result::Err(::librum::error::EnumDecodeError::UnassignedDiscriminant { value }),
|
||||
value => return ::core::result::Result::Err(::oct::error::EnumDecodeError::UnassignedDiscriminant { value }),
|
||||
};
|
||||
|
||||
::core::result::Result::Ok(this)
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
|
@ -28,8 +28,8 @@ use std::iter;
|
|||
pub fn decode_struct(data: DataStruct) -> TokenStream {
|
||||
let commands = iter::repeat_n(
|
||||
quote! {
|
||||
::librum::Decode::decode(stream)
|
||||
.map_err(::core::convert::Into::<::librum::error::GenericDecodeError>::into)?
|
||||
::oct::decode::Decode::decode(stream)
|
||||
.map_err(::core::convert::Into::<::oct::error::GenericDecodeError>::into)?
|
||||
},
|
||||
data.fields.len(),
|
||||
);
|
||||
|
@ -50,10 +50,10 @@ pub fn decode_struct(data: DataStruct) -> TokenStream {
|
|||
};
|
||||
|
||||
quote! {
|
||||
type Error = ::librum::error::GenericDecodeError;
|
||||
type Error = ::oct::error::GenericDecodeError;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut ::librum::IStream) -> ::core::result::Result<Self, Self::Error> {
|
||||
fn decode(stream: &mut ::oct::decode::Input) -> ::core::result::Result<Self, Self::Error> {
|
||||
let this = #value;
|
||||
::core::result::Result::Ok(this)
|
||||
}
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Discriminants, Repr};
|
||||
|
@ -66,21 +66,21 @@ pub fn encode_enum(data: DataEnum, repr: Repr) -> TokenStream {
|
|||
});
|
||||
|
||||
quote! {
|
||||
type Error = ::librum::error::EnumEncodeError<#repr, ::librum::error::GenericEncodeError>;
|
||||
type Error = ::oct::error::EnumEncodeError<#repr, ::oct::error::GenericEncodeError>;
|
||||
|
||||
#[allow(unreachable_patterns)]
|
||||
#[inline]
|
||||
fn encode(&self, stream: &mut ::librum::OStream) -> ::core::result::Result<(), Self::Error> {
|
||||
fn encode(&self, stream: &mut ::oct::encode::Output) -> ::core::result::Result<(), Self::Error> {
|
||||
match *self {
|
||||
#(
|
||||
#patterns => {
|
||||
<#repr as ::librum::Encode>::encode(&#discriminants, stream)
|
||||
.map_err(::librum::error::EnumEncodeError::Discriminant)?;
|
||||
<#repr as ::oct::encode::Encode>::encode(&#discriminants, stream)
|
||||
.map_err(::oct::error::EnumEncodeError::BadDiscriminant)?;
|
||||
|
||||
#(
|
||||
::librum::Encode::encode(#captures, stream)
|
||||
.map_err(::core::convert::Into::<::librum::error::GenericEncodeError>::into)
|
||||
.map_err(::librum::error::EnumEncodeError::Field)?;
|
||||
::oct::encode::Encode::encode(#captures, stream)
|
||||
.map_err(::core::convert::Into::<::oct::error::GenericEncodeError>::into)
|
||||
.map_err(::oct::error::EnumEncodeError::BadField)?;
|
||||
)*
|
||||
}
|
||||
)*
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
|
@ -48,15 +48,15 @@ pub fn encode_struct(data: DataStruct) -> TokenStream {
|
|||
};
|
||||
|
||||
quote! {
|
||||
type Error = ::librum::error::GenericEncodeError;
|
||||
type Error = ::oct::error::GenericEncodeError;
|
||||
|
||||
#[inline]
|
||||
fn encode(&self, stream: &mut ::librum::OStream) -> ::core::result::Result<(), Self::Error> {
|
||||
fn encode(&self, stream: &mut ::oct::encode::Output) -> ::core::result::Result<(), Self::Error> {
|
||||
let #pattern = self;
|
||||
|
||||
#(
|
||||
::librum::Encode::encode(#captures, stream)
|
||||
.map_err(::core::convert::Into::<::librum::error::GenericEncodeError>::into)?;
|
||||
::oct::encode::Encode::encode(#captures, stream)
|
||||
.map_err(::core::convert::Into::<::oct::error::GenericEncodeError>::into)?;
|
||||
)*
|
||||
|
||||
::core::result::Result::Ok(())
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::use_mod;
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::Repr;
|
||||
|
@ -48,7 +48,7 @@ pub fn sized_encode_enum(data: DataEnum, repr: Repr) -> TokenStream {
|
|||
let mut current_size = 0x0usize;
|
||||
|
||||
#(
|
||||
current_size = 0x0 #(+ <#tys as ::librum::SizedEncode>::MAX_ENCODED_SIZE)*;
|
||||
current_size = 0x0 #(+ <#tys as ::oct::encode::SizedEncode>::MAX_ENCODED_SIZE)*;
|
||||
|
||||
if current_size > total_size { total_size = current_size };
|
||||
)*
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
|
@ -31,6 +31,6 @@ pub fn sized_encode_struct(data: DataStruct) -> TokenStream {
|
|||
.collect();
|
||||
|
||||
quote! {
|
||||
const MAX_ENCODED_SIZE: usize = 0x0 #( + <#tys as ::librum::SizedEncode>::MAX_ENCODED_SIZE)*;
|
||||
const MAX_ENCODED_SIZE: usize = 0x0 #( + <#tys as ::oct::encode::SizedEncode>::MAX_ENCODED_SIZE)*;
|
||||
}
|
||||
}
|
|
@ -1,30 +1,30 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#![doc(html_logo_url = "https://gitlab.com/bjoernager/librum/-/raw/master/doc-icon.svg")]
|
||||
#![doc(html_logo_url = "https://gitlab.com/bjoernager/oct/-/raw/master/doc-icon.svg")]
|
||||
|
||||
//! This crate implements procedural macros for [`Librum`](https://crates.io/crates/librum/).
|
||||
//! This crate implements procedural macros for [`oct`](https://crates.io/crates/oct/).
|
||||
|
||||
// For use in macros:
|
||||
extern crate self as librum_macros;
|
||||
extern crate self as oct_macros;
|
||||
|
||||
macro_rules! use_mod {
|
||||
($vis:vis $name:ident) => {
|
||||
|
@ -51,7 +51,7 @@ pub fn derive_decode(input: TokenStream) -> TokenStream {
|
|||
|
||||
let output = impl_derive_macro(
|
||||
input,
|
||||
parse2(quote! { ::librum::Decode }).unwrap(),
|
||||
parse2(quote! { ::oct::decode::Decode }).unwrap(),
|
||||
None,
|
||||
impls::decode_struct,
|
||||
impls::decode_enum,
|
||||
|
@ -68,7 +68,7 @@ pub fn derive_encode(input: TokenStream) -> TokenStream {
|
|||
|
||||
let output = impl_derive_macro(
|
||||
input,
|
||||
parse2(quote! { ::librum::Encode }).unwrap(),
|
||||
parse2(quote! { ::oct::encode::Encode }).unwrap(),
|
||||
None,
|
||||
impls::encode_struct,
|
||||
impls::encode_enum,
|
||||
|
@ -85,7 +85,7 @@ pub fn derive_sized_encode(input: TokenStream) -> TokenStream {
|
|||
|
||||
let output = impl_derive_macro(
|
||||
input,
|
||||
parse2(quote! { ::librum::SizedEncode }).unwrap(),
|
||||
parse2(quote! { ::oct::encode::SizedEncode }).unwrap(),
|
||||
None,
|
||||
impls::sized_encode_struct,
|
||||
impls::sized_encode_enum,
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
|
@ -61,22 +61,20 @@ impl Repr {
|
|||
for attr in attrs {
|
||||
if attr.path().is_ident("repr") {
|
||||
attr.parse_nested_meta(|meta| {
|
||||
use Repr::*;
|
||||
|
||||
let ident = meta.path.require_ident()?;
|
||||
|
||||
if ident == "u8" { this = Some(U8) }
|
||||
else if ident == "i8" { this = Some(I8) }
|
||||
else if ident == "u16" { this = Some(U16) }
|
||||
else if ident == "i16" { this = Some(I16) }
|
||||
else if ident == "u32" { this = Some(U32) }
|
||||
else if ident == "i32" { this = Some(I32) }
|
||||
else if ident == "u64" { this = Some(U64) }
|
||||
else if ident == "i64" { this = Some(I64) }
|
||||
else if ident == "u128" { this = Some(U128) }
|
||||
else if ident == "i128" { this = Some(I128) }
|
||||
else if ident == "usize" { this = Some(Usize) }
|
||||
else if ident == "isize" { this = Some(Isize) }
|
||||
if ident == "u8" { this = Some(Self::U8) }
|
||||
else if ident == "i8" { this = Some(Self::I8) }
|
||||
else if ident == "u16" { this = Some(Self::U16) }
|
||||
else if ident == "i16" { this = Some(Self::I16) }
|
||||
else if ident == "u32" { this = Some(Self::U32) }
|
||||
else if ident == "i32" { this = Some(Self::I32) }
|
||||
else if ident == "u64" { this = Some(Self::U64) }
|
||||
else if ident == "i64" { this = Some(Self::I64) }
|
||||
else if ident == "u128" { this = Some(Self::U128) }
|
||||
else if ident == "i128" { this = Some(Self::I128) }
|
||||
else if ident == "usize" { this = Some(Self::Usize) }
|
||||
else if ident == "isize" { this = Some(Self::Isize) }
|
||||
else { panic!("`{ident}` is not a derivable enumeration representation") };
|
||||
|
||||
Ok(())
|
||||
|
@ -92,21 +90,19 @@ impl Repr {
|
|||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn to_str(self) -> &'static str {
|
||||
use Repr::*;
|
||||
|
||||
match self {
|
||||
U8 => "u8",
|
||||
I8 => "i8",
|
||||
U16 => "u16",
|
||||
I16 => "i16",
|
||||
U32 => "u32",
|
||||
I32 => "i32",
|
||||
U64 => "u64",
|
||||
I64 => "i64",
|
||||
U128 => "u128",
|
||||
I128 => "i128",
|
||||
Usize => "usize",
|
||||
Isize => "isize",
|
||||
Self::U8 => "u8",
|
||||
Self::I8 => "i8",
|
||||
Self::U16 => "u16",
|
||||
Self::I16 => "i16",
|
||||
Self::U32 => "u32",
|
||||
Self::I32 => "i32",
|
||||
Self::U64 => "u64",
|
||||
Self::I64 => "i64",
|
||||
Self::U128 => "u128",
|
||||
Self::I128 => "i128",
|
||||
Self::Usize => "usize",
|
||||
Self::Isize => "isize",
|
||||
}
|
||||
}
|
||||
|
18
oct.svg
Normal file
18
oct.svg
Normal file
|
@ -0,0 +1,18 @@
|
|||
<svg height="112" width="112" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="tHorizontalArm">
|
||||
<rect fill="white" height="100%" width="100%" x="0" y="0" />
|
||||
<circle cx="56" cy="56" fill="none" r="32" stroke="black" stroke-width="20" />
|
||||
</mask>
|
||||
|
||||
<mask id="glyph">
|
||||
<!-- O: -->
|
||||
<circle cx="56" cy="56" fill="none" r="32" stroke="white" stroke-width="16" />
|
||||
|
||||
<!-- T: -->
|
||||
<rect fill="white" height="16" paint-order="stroke" stroke="black" stroke-width="4" width="96" x="8" y="48" />
|
||||
<rect fill="white" height="96" mask="url(#tHorizontalArm)" width="16" x="48" y="8" />
|
||||
</mask>
|
||||
|
||||
<rect fill="#02764A" height="100%" width="100%" x="0" y="0" /> <!-- oklch(50% 0.115300 158.520) -->
|
||||
<rect fill="#FFFFFF" height="100%" mask="url(#glyph)" width="100%" x="0" y="0" />
|
||||
</svg>
|
After Width: | Height: | Size: 779 B |
|
@ -1,9 +1,9 @@
|
|||
[package]
|
||||
name = "librum"
|
||||
version = "0.13.1"
|
||||
name = "oct"
|
||||
version = "0.14.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.83"
|
||||
documentation = "https://docs.rs/librum/"
|
||||
documentation = "https://docs.rs/oct/"
|
||||
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
|
@ -21,11 +21,11 @@ all-features = true
|
|||
default = ["alloc", "proc-macro", "std"]
|
||||
|
||||
alloc = []
|
||||
proc-macro = ["librum-macros"]
|
||||
proc-macro = ["oct-macros"]
|
||||
std = []
|
||||
|
||||
[dependencies]
|
||||
librum-macros = { path = "../librum-macros", version = "0.13.0", optional = true}
|
||||
oct-macros = { path = "../oct-macros", version = "0.14.0", optional = true}
|
||||
|
||||
[lints]
|
||||
workspace = true
|
|
@ -1,30 +1,29 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::{DecodeBorrowed, IStream, SizedEncode};
|
||||
use crate::decode::{DecodeBorrowed, Input};
|
||||
use crate::error::{
|
||||
BoolDecodeError,
|
||||
CStringDecodeError,
|
||||
CharDecodeError,
|
||||
CollectionDecodeError,
|
||||
|
@ -104,12 +103,12 @@ pub trait Decode: Sized {
|
|||
/// The type returned in case of error.
|
||||
type Error;
|
||||
|
||||
/// Decodes an object from the provided stream.
|
||||
/// Decodes an object from the provided input.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If decoding fails due to e.g. an invalid byte sequence in the stream, then an error should be returned.
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error>;
|
||||
/// If decoding fails due to e.g. an invalid byte sequence in the input, then an error should be returned.
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error>;
|
||||
}
|
||||
|
||||
/// Implemented for tuples with up to twelve members.
|
||||
|
@ -118,9 +117,9 @@ impl<T: Decode> Decode for (T, ) {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let this = (Decode::decode(stream)?, );
|
||||
Ok(this)
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let this = (Decode::decode(input)?, );
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,14 +127,14 @@ impl<T: Decode, const N: usize> Decode for [T; N] {
|
|||
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, T::Error>>;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
// Initialise the array incrementally.
|
||||
|
||||
let mut buf: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||
let mut buf = [const { MaybeUninit::<T>::uninit() }; N];
|
||||
|
||||
for (i, item) in buf.iter_mut().enumerate() {
|
||||
let value = Decode::decode(stream)
|
||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }))?;
|
||||
let value = Decode::decode(input)
|
||||
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
|
||||
|
||||
item.write(value);
|
||||
}
|
||||
|
@ -148,7 +147,7 @@ impl<T: Decode, const N: usize> Decode for [T; N] {
|
|||
// be used here, and `transmute_unchecked` is re-
|
||||
// served for the greedy rustc devs.
|
||||
let this = unsafe { buf.as_ptr().cast::<[T; N]>().read() };
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,26 +157,26 @@ impl<T: Decode> Decode for Arc<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(input)?;
|
||||
|
||||
let this = Self::new(value);
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode for bool {
|
||||
type Error = BoolDecodeError;
|
||||
type Error = Infallible;
|
||||
|
||||
/// Lossily reinterprets a byte value as a boolean.
|
||||
///
|
||||
/// Whilst <code>[Encode](crate::encode::Encode)::[encode](crate::encode::Encode::encode)</code> will only yield the values `0` and `1`, this method clamps all values above `1`.
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = u8::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(value) = u8::decode(input);
|
||||
|
||||
match value {
|
||||
0x0 => Ok(false),
|
||||
0x1 => Ok(true),
|
||||
_ => Err(BoolDecodeError { value })
|
||||
}
|
||||
let this = value != 0x0;
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,20 +184,20 @@ impl<T: Decode> Decode for Bound<T> {
|
|||
type Error = EnumDecodeError<u8, T::Error>;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let discriminant = u8::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(discriminant) = u8::decode(input);
|
||||
|
||||
let this = match discriminant {
|
||||
0x0 => {
|
||||
let bound = Decode::decode(stream)
|
||||
.map_err(EnumDecodeError::Field)?;
|
||||
let bound = Decode::decode(input)
|
||||
.map_err(EnumDecodeError::BadField)?;
|
||||
|
||||
Self::Included(bound)
|
||||
}
|
||||
|
||||
0x1 => {
|
||||
let bound = Decode::decode(stream)
|
||||
.map_err(EnumDecodeError::Field)?;
|
||||
let bound = Decode::decode(input)
|
||||
.map_err(EnumDecodeError::BadField)?;
|
||||
|
||||
Self::Excluded(bound)
|
||||
}
|
||||
|
@ -208,7 +207,7 @@ impl<T: Decode> Decode for Bound<T> {
|
|||
value => return Err(EnumDecodeError::UnassignedDiscriminant { value }),
|
||||
};
|
||||
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,11 +217,11 @@ impl<T: Decode> Decode for Box<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(input)?;
|
||||
|
||||
let this = Self::new(value);
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,11 +229,11 @@ impl<T: Decode> Decode for Cell<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(input)?;
|
||||
|
||||
let this = Self::new(value);
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,14 +241,17 @@ impl Decode for char {
|
|||
type Error = CharDecodeError;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let code_point = u32::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(code_point) = u32::decode(input);
|
||||
|
||||
let this = code_point
|
||||
.try_into()
|
||||
.map_err(|_| CharDecodeError { code_point })?;
|
||||
match code_point {
|
||||
code_point @ (0x0000..=0xD7FF | 0xDE00..=0x10FFFF) => {
|
||||
let this = unsafe { Self::from_u32_unchecked(code_point) };
|
||||
Result::Ok(this)
|
||||
},
|
||||
|
||||
Ok(this)
|
||||
code_point => Err(CharDecodeError { code_point }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,11 +265,11 @@ where
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(input)?;
|
||||
|
||||
let this = Self::Owned(value);
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,10 +279,10 @@ impl Decode for CString {
|
|||
type Error = CStringDecodeError;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let len = Decode::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(len) = Decode::decode(input);
|
||||
|
||||
let data = stream.read(len);
|
||||
let data = input.read(len).unwrap();
|
||||
|
||||
for (i, c) in data.iter().enumerate() {
|
||||
if *c == b'\x00' { return Err(CStringDecodeError { index: i }) };
|
||||
|
@ -298,7 +300,7 @@ impl Decode for CString {
|
|||
|
||||
// SAFETY: We have already tested the data.
|
||||
let this = unsafe { Self::from_vec_unchecked(buf) };
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,12 +308,12 @@ impl Decode for Duration {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let secs = Decode::decode(stream)?;
|
||||
let nanos = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(secs) = Decode::decode(input);
|
||||
let Ok(nanos) = Decode::decode(input);
|
||||
|
||||
let this = Self::new(secs, nanos);
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,22 +328,22 @@ where
|
|||
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, E>>;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let len = Decode::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(len) = Decode::decode(input);
|
||||
|
||||
let mut this = Self::with_capacity_and_hasher(len, Default::default());
|
||||
|
||||
for i in 0x0..len {
|
||||
let key= Decode::decode(stream)
|
||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }))?;
|
||||
let key= Decode::decode(input)
|
||||
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
|
||||
|
||||
let value = Decode::decode(stream)
|
||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }))?;
|
||||
let value = Decode::decode(input)
|
||||
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
|
||||
|
||||
this.insert(key, value);
|
||||
}
|
||||
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,19 +357,19 @@ where
|
|||
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, K::Error>>;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let len = Decode::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(len) = Decode::decode(input);
|
||||
|
||||
let mut this = Self::with_capacity_and_hasher(len, Default::default());
|
||||
|
||||
for i in 0x0..len {
|
||||
let key = Decode::decode(stream)
|
||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }) )?;
|
||||
let key = Decode::decode(input)
|
||||
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }) )?;
|
||||
|
||||
this.insert(key);
|
||||
}
|
||||
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -375,7 +377,7 @@ impl Decode for Infallible {
|
|||
type Error = Self;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(_stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
fn decode(_input: &mut Input) -> Result<Self, Self::Error> {
|
||||
panic!("cannot deserialise `Infallible` as it cannot be serialised to begin with")
|
||||
}
|
||||
}
|
||||
|
@ -384,18 +386,18 @@ impl Decode for IpAddr {
|
|||
type Error = EnumDecodeError<u8, Infallible>;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let discriminant = u8::decode(stream)
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let discriminant = u8::decode(input)
|
||||
.map_err(EnumDecodeError::InvalidDiscriminant)?;
|
||||
|
||||
let this = match discriminant {
|
||||
0x4 => Self::V4(Decode::decode(stream).unwrap()),
|
||||
0x6 => Self::V6(Decode::decode(stream).unwrap()),
|
||||
0x4 => Self::V4(Decode::decode(input).unwrap()),
|
||||
0x6 => Self::V6(Decode::decode(input).unwrap()),
|
||||
|
||||
value => return Err(EnumDecodeError::UnassignedDiscriminant { value })
|
||||
};
|
||||
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,9 +405,11 @@ impl Decode for Ipv4Addr {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(stream)?;
|
||||
Ok(Self::from_bits(value))
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(value) = Decode::decode(input);
|
||||
|
||||
let this = Self::from_bits(value);
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -413,9 +417,11 @@ impl Decode for Ipv6Addr {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(stream)?;
|
||||
Ok(Self::from_bits(value))
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(value) = Decode::decode(input);
|
||||
|
||||
let this = Self::from_bits(value);
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,9 +429,10 @@ impl Decode for isize {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = i16::decode(stream)?;
|
||||
Ok(value as Self)
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(value) = i16::decode(input);
|
||||
|
||||
Result::Ok(value as Self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -435,19 +442,19 @@ impl<T: Decode> Decode for LinkedList<T> {
|
|||
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, T::Error>>;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let len = usize::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(len) = usize::decode(input);
|
||||
|
||||
let mut this = Self::new();
|
||||
|
||||
for i in 0x0..len {
|
||||
let value = T::decode(stream)
|
||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }))?;
|
||||
let value = T::decode(input)
|
||||
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
|
||||
|
||||
this.push_back(value);
|
||||
}
|
||||
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,8 +464,11 @@ impl<T: Decode> Decode for Mutex<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
Ok(Self::new(Decode::decode(stream)?))
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(input)?;
|
||||
|
||||
let this = Self::new(value);
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -467,16 +477,17 @@ impl<T: Decode> Decode for Option<T> {
|
|||
|
||||
#[expect(clippy::if_then_some_else_none)] // ???
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let sign = bool::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let sign = bool::decode(input)
|
||||
.map_err::<T::Error, _>(|_e| unreachable!())?;
|
||||
|
||||
let this = if sign {
|
||||
Some(Decode::decode(stream)?)
|
||||
Some(Decode::decode(input)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -484,8 +495,8 @@ impl<T> Decode for PhantomData<T> {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(_stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
Ok(Self)
|
||||
fn decode(_input: &mut Input) -> Result<Self, Self::Error> {
|
||||
Result::Ok(Self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -493,8 +504,8 @@ impl Decode for PhantomPinned {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(_stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
Ok(Self)
|
||||
fn decode(_input: &mut Input) -> Result<Self, Self::Error> {
|
||||
Result::Ok(Self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -502,11 +513,11 @@ impl<T: Decode> Decode for Range<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let start = Decode::decode(stream)?;
|
||||
let end = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let start = Decode::decode(input)?;
|
||||
let end = Decode::decode(input)?;
|
||||
|
||||
Ok(start..end)
|
||||
Result::Ok(start..end)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -514,10 +525,10 @@ impl<T: Decode> Decode for RangeFrom<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let start = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let start = Decode::decode(input)?;
|
||||
|
||||
Ok(start..)
|
||||
Result::Ok(start..)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,8 +536,8 @@ impl Decode for RangeFull {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(_stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
Ok(..)
|
||||
fn decode(_input: &mut Input) -> Result<Self, Self::Error> {
|
||||
Result::Ok(..)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -534,11 +545,11 @@ impl<T: Decode> Decode for RangeInclusive<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let start = Decode::decode(stream)?;
|
||||
let end = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let start = Decode::decode(input)?;
|
||||
let end = Decode::decode(input)?;
|
||||
|
||||
Ok(start..=end)
|
||||
Result::Ok(start..=end)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -546,10 +557,10 @@ impl<T: Decode> Decode for RangeTo<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let end = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let end = Decode::decode(input)?;
|
||||
|
||||
Ok(..end)
|
||||
Result::Ok(..end)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -557,10 +568,10 @@ impl<T: Decode> Decode for RangeToInclusive<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let end = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let end = Decode::decode(input)?;
|
||||
|
||||
Ok(..=end)
|
||||
Result::Ok(..=end)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -570,8 +581,8 @@ impl<T: Decode> Decode for Rc<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
Ok(Self::new(Decode::decode(stream)?))
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
Result::Ok(Self::new(Decode::decode(input)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -579,15 +590,15 @@ impl<T: Decode> Decode for RefCell<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(input)?;
|
||||
|
||||
let this = Self::new(value);
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E, Err> Decode for core::result::Result<T, E>
|
||||
impl<T, E, Err> Decode for Result<T, E>
|
||||
where
|
||||
T: Decode<Error = Err>,
|
||||
E: Decode<Error = Err>,
|
||||
|
@ -595,23 +606,23 @@ where
|
|||
type Error = EnumDecodeError<bool, Err>;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let sign = bool::decode(stream)
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let sign = bool::decode(input)
|
||||
.map_err(EnumDecodeError::InvalidDiscriminant)?;
|
||||
|
||||
let this = if sign {
|
||||
let value = Decode::decode(stream)
|
||||
.map_err(EnumDecodeError::Field)?;
|
||||
let value = Decode::decode(input)
|
||||
.map_err(EnumDecodeError::BadField)?;
|
||||
|
||||
Err(value)
|
||||
} else {
|
||||
let value = Decode::decode(stream)
|
||||
.map_err(EnumDecodeError::Field)?;
|
||||
let value = Decode::decode(input)
|
||||
.map_err(EnumDecodeError::BadField)?;
|
||||
|
||||
Ok(value)
|
||||
};
|
||||
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -621,11 +632,11 @@ impl<T: Decode> Decode for RwLock<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(input)?;
|
||||
|
||||
let this = Self::new(value);
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -633,11 +644,11 @@ impl<T: Decode> Decode for Saturating<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(input)?;
|
||||
|
||||
let this = Self(value);
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -645,17 +656,15 @@ impl Decode for SocketAddr {
|
|||
type Error = EnumDecodeError<u8, Infallible>;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let discriminant = u8::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(discriminant) = u8::decode(input);
|
||||
|
||||
let this = match discriminant {
|
||||
0x4 => Self::V4(Decode::decode(stream).unwrap()),
|
||||
0x6 => Self::V6(Decode::decode(stream).unwrap()),
|
||||
match discriminant {
|
||||
0x4 => Result::Ok(Self::V4(Decode::decode(input).unwrap())),
|
||||
0x6 => Result::Ok(Self::V6(Decode::decode(input).unwrap())),
|
||||
|
||||
value => return Err(EnumDecodeError::UnassignedDiscriminant { value })
|
||||
};
|
||||
|
||||
Ok(this)
|
||||
value => Err(EnumDecodeError::UnassignedDiscriminant { value }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -663,12 +672,12 @@ impl Decode for SocketAddrV4 {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let ip = Decode::decode(stream)?;
|
||||
let port = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let ip = Decode::decode(input)?;
|
||||
let port = Decode::decode(input)?;
|
||||
|
||||
let this = Self::new(ip, port);
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -676,14 +685,14 @@ impl Decode for SocketAddrV6 {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let ip = Decode::decode(stream)?;
|
||||
let port = Decode::decode(stream)?;
|
||||
let flow_info = Decode::decode(stream)?;
|
||||
let scope_id = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let ip = Decode::decode(input)?;
|
||||
let port = Decode::decode(input)?;
|
||||
let flow_info = Decode::decode(input)?;
|
||||
let scope_id = Decode::decode(input)?;
|
||||
|
||||
let this = Self::new(ip, port, flow_info, scope_id);
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -693,18 +702,21 @@ impl Decode for String {
|
|||
type Error = CollectionDecodeError<Infallible, Utf8Error>;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let len = Decode::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(len) = Decode::decode(input);
|
||||
|
||||
let data = stream.read(len);
|
||||
let data = input.read(len).unwrap();
|
||||
|
||||
str::from_utf8(data)
|
||||
.map_err(|e| {
|
||||
let i = e.valid_up_to();
|
||||
let c = data[i];
|
||||
if let Err(e) = str::from_utf8(data) {
|
||||
let i = e.valid_up_to();
|
||||
let c = data[i];
|
||||
|
||||
CollectionDecodeError::Item(Utf8Error { value: c, index: i })
|
||||
})?;
|
||||
return Err(
|
||||
CollectionDecodeError::BadItem(
|
||||
Utf8Error { value: c, index: i },
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
let mut v = Vec::with_capacity(len);
|
||||
|
||||
|
@ -718,7 +730,7 @@ impl Decode for String {
|
|||
|
||||
// SAFETY: We have already tested the raw data.
|
||||
let this = unsafe { Self::from_utf8_unchecked(v) };
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -728,8 +740,8 @@ impl Decode for SystemTime {
|
|||
type Error = SystemTimeDecodeError;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let time = i64::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(time) = i64::decode(input);
|
||||
|
||||
let this = if time.is_positive() {
|
||||
let time = time as u64;
|
||||
|
@ -749,8 +761,8 @@ impl Decode for () {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(_stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
Ok(())
|
||||
fn decode(_input: &mut Input) -> Result<Self, Self::Error> {
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -758,9 +770,9 @@ impl Decode for usize {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = u16::decode(stream)?;
|
||||
Ok(value as Self)
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let value = u16::decode(input)?;
|
||||
Result::Ok(value as Self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -770,15 +782,15 @@ impl<T: Decode> Decode for Vec<T> {
|
|||
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, T::Error>>;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let len = Decode::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let Ok(len) = Decode::decode(input);
|
||||
|
||||
let mut this = Self::with_capacity(len);
|
||||
|
||||
let buf = this.as_mut_ptr();
|
||||
for i in 0x0..len {
|
||||
let value = Decode::decode(stream)
|
||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }))?;
|
||||
let value = Decode::decode(input)
|
||||
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
|
||||
|
||||
// SAFETY: Each index is within bounds (i.e. capac-
|
||||
// ity).
|
||||
|
@ -788,7 +800,7 @@ impl<T: Decode> Decode for Vec<T> {
|
|||
// SAFETY: We have initialised the buffer.
|
||||
unsafe { this.set_len(len); }
|
||||
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -796,26 +808,26 @@ impl<T: Decode> Decode for Wrapping<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(stream)?;
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let value = Decode::decode(input)?;
|
||||
|
||||
let this = Self(value);
|
||||
Ok(this)
|
||||
Result::Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_numeric {
|
||||
($ty:ty$(,)?) => {
|
||||
impl ::librum::Decode for $ty {
|
||||
impl ::oct::decode::Decode for $ty {
|
||||
type Error = ::core::convert::Infallible;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut ::librum::IStream) -> ::core::result::Result<Self, Self::Error> {
|
||||
let mut data = [::core::default::Default::default(); Self::MAX_ENCODED_SIZE];
|
||||
stream.read_into(&mut data);
|
||||
fn decode(input: &mut ::oct::decode::Input) -> ::core::result::Result<Self, Self::Error> {
|
||||
let mut data = [::core::default::Default::default(); <Self as ::oct::encode::SizedEncode>::MAX_ENCODED_SIZE];
|
||||
input.read_into(&mut data).unwrap();
|
||||
|
||||
let this = Self::from_le_bytes(data);
|
||||
Ok(this)
|
||||
::core::result::Result::Ok(this)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -826,19 +838,19 @@ macro_rules! impl_tuple {
|
|||
$($tys:ident),+$(,)?
|
||||
} => {
|
||||
#[doc(hidden)]
|
||||
impl<$($tys, )* E> ::librum::Decode for ($($tys, )*)
|
||||
impl<$($tys, )* E> ::oct::decode::Decode for ($($tys, )*)
|
||||
where
|
||||
$($tys: Decode<Error = E>, )*
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut ::librum::IStream) -> ::core::result::Result<Self, Self::Error> {
|
||||
fn decode(input: &mut ::oct::decode::Input) -> ::core::result::Result<Self, Self::Error> {
|
||||
let this = (
|
||||
$( <$tys as ::librum::Decode>::decode(stream)?, )*
|
||||
$( <$tys as ::oct::decode::Decode>::decode(input)?, )*
|
||||
);
|
||||
|
||||
Ok(this)
|
||||
::core::result::Result::Ok(this)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -846,17 +858,23 @@ macro_rules! impl_tuple {
|
|||
|
||||
macro_rules! impl_non_zero {
|
||||
($ty:ty$(,)?) => {
|
||||
impl ::librum::Decode for ::core::num::NonZero<$ty> {
|
||||
type Error = ::librum::error::NonZeroDecodeError;
|
||||
impl ::oct::decode::Decode for ::core::num::NonZero<$ty> {
|
||||
type Error = ::oct::error::NonZeroDecodeError;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut ::librum::IStream) -> ::core::result::Result<Self, Self::Error> {
|
||||
let Ok(value) = <$ty as ::librum::Decode>::decode(stream);
|
||||
fn decode(input: &mut ::oct::decode::Input) -> ::core::result::Result<Self, Self::Error> {
|
||||
use ::core::result::Result;
|
||||
|
||||
let this = ::core::num::NonZero::new(value)
|
||||
.ok_or(::librum::error::NonZeroDecodeError)?;
|
||||
let Result::Ok(value) = <$ty as ::oct::decode::Decode>::decode(input);
|
||||
|
||||
Ok(this)
|
||||
match value {
|
||||
0x0 => Result::Err(::oct::error::NonZeroDecodeError),
|
||||
|
||||
value => {
|
||||
let this = unsafe { ::core::num::NonZero::new_unchecked(value) };
|
||||
Result::Ok(this)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -870,15 +888,15 @@ macro_rules! impl_atomic {
|
|||
} => {
|
||||
#[cfg(target_has_atomic = $width)]
|
||||
#[cfg_attr(doc, doc(cfg(target_has_atomic = $width)))]
|
||||
impl ::librum::Decode for $atomic_ty {
|
||||
type Error = <$ty as ::librum::Decode>::Error;
|
||||
impl ::oct::decode::Decode for $atomic_ty {
|
||||
type Error = <$ty as ::oct::decode::Decode>::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn decode(stream: &mut ::librum::IStream) -> ::core::result::Result<Self, Self::Error> {
|
||||
let value = ::librum::Decode::decode(stream)?;
|
||||
fn decode(input: &mut ::oct::decode::Input) -> ::core::result::Result<Self, Self::Error> {
|
||||
let value = ::oct::decode::Decode::decode(input)?;
|
||||
|
||||
let this = Self::new(value);
|
||||
Ok(this)
|
||||
::core::result::Result::Ok(this)
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,32 +1,33 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use librum::{Decode, Encode, IStream, SizedEncode};
|
||||
use oct::decode::{Decode, Input};
|
||||
use oct::encode::{Encode, SizedEncode};
|
||||
use std::char;
|
||||
use std::vec::Vec;
|
||||
use std::string::String;
|
||||
|
||||
macro_rules! test {
|
||||
($ty:ty: $data:expr => $value:expr) => {{
|
||||
let mut stream = IStream::new(&$data);
|
||||
let mut stream = Input::new(&$data);
|
||||
|
||||
let left = <$ty as Decode>::decode(&mut stream).unwrap();
|
||||
let right = $value;
|
||||
|
@ -101,6 +102,7 @@ fn test_decode_derive() {
|
|||
Unnamed(i32),
|
||||
Named { timestamp: u64 },
|
||||
}
|
||||
|
||||
test!(ProcExit: [
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x0B, 0x5E,
|
||||
0x00, 0x00, 0x00, 0x00,
|
|
@ -1,25 +1,25 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::Decode;
|
||||
use crate::decode::Decode;
|
||||
|
||||
use core::borrow::Borrow;
|
||||
|
||||
|
@ -45,7 +45,7 @@ use alloc::sync::Arc;
|
|||
///
|
||||
/// Implementing this trait is specifically a promise that <code><Self as [Decode]>::[decode](Decode::decode)</code> can handle any encoding of `B`.
|
||||
///
|
||||
/// This trait is mainly useful for types that implement [`Encode`](crate::Encode::encode) but do not implement `Decode` for whatever reason (mostly due to being unsized).
|
||||
/// This trait is mainly useful for types that implement [`Encode`](crate::encode::Encode::encode) but do not implement `Decode` for whatever reason (mostly due to being unsized).
|
||||
/// The primary user of this trait is the `Decode` implementation of [`Cow`](alloc::borrow::Cow).
|
||||
///
|
||||
/// # Arrays
|
|
@ -19,16 +19,18 @@
|
|||
// er General Public License along with Librum. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::error::InputError;
|
||||
|
||||
use core::ptr::copy_nonoverlapping;
|
||||
use core::slice;
|
||||
|
||||
/// Byte stream suitable for input.
|
||||
pub struct IStream<'a> {
|
||||
/// Byte stream suitable for reading.
|
||||
pub struct Input<'a> {
|
||||
buf: &'a [u8],
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl<'a> IStream<'a> {
|
||||
impl<'a> Input<'a> {
|
||||
/// Constructs a new i-stream.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
|
@ -44,15 +46,16 @@ impl<'a> IStream<'a> {
|
|||
///
|
||||
/// If the requested amount of bytes could not exactly be read, then this method will panic.
|
||||
#[inline]
|
||||
pub fn read(&mut self, count: usize) -> &'a [u8] {
|
||||
pub const fn read(&mut self, count: usize) -> Result<&'a [u8], InputError> {
|
||||
let remaining = self.buf.len() - self.pos;
|
||||
|
||||
assert!(
|
||||
remaining >= count,
|
||||
"cannot read ({count}) bytes at ({}) from stream with capacity of ({})",
|
||||
self.pos,
|
||||
self.buf.len(),
|
||||
);
|
||||
if remaining < count {
|
||||
return Err(InputError {
|
||||
capacity: self.buf.len(),
|
||||
position: self.pos,
|
||||
count,
|
||||
});
|
||||
}
|
||||
|
||||
let data = unsafe {
|
||||
let ptr = self.buf.as_ptr().add(self.pos);
|
||||
|
@ -62,7 +65,7 @@ impl<'a> IStream<'a> {
|
|||
|
||||
self.pos += count;
|
||||
|
||||
data
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
/// Reads bytes from the stream into a predefined buffer.
|
||||
|
@ -73,16 +76,17 @@ impl<'a> IStream<'a> {
|
|||
///
|
||||
/// If the provided buffer could not be completely filled, then this method will panic.
|
||||
#[inline]
|
||||
pub fn read_into(&mut self, buf: &mut [u8]) {
|
||||
pub const fn read_into(&mut self, buf: &mut [u8]) -> Result<(), InputError> {
|
||||
let count = buf.len();
|
||||
let remaining = self.buf.len() - self.pos;
|
||||
let remaining = self.remaining();
|
||||
|
||||
assert!(
|
||||
remaining >= count,
|
||||
"cannot read ({count}) bytes at ({}) from stream with capacity of ({})",
|
||||
self.pos,
|
||||
self.buf.len(),
|
||||
);
|
||||
if remaining < count {
|
||||
return Err(InputError {
|
||||
capacity: self.buf.len(),
|
||||
position: self.pos,
|
||||
count,
|
||||
});
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let src = self.buf.as_ptr().add(self.pos);
|
||||
|
@ -92,15 +96,30 @@ impl<'a> IStream<'a> {
|
|||
}
|
||||
|
||||
self.pos += count;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Closes the stream.
|
||||
///
|
||||
/// The total ammount of bytes read is returned.
|
||||
/// Retrieves the maximum capacity of the input stream.
|
||||
#[inline(always)]
|
||||
pub const fn close(self) -> usize {
|
||||
let Self { pos, .. } = self;
|
||||
#[must_use]
|
||||
pub const fn capacity(&self) -> usize {
|
||||
self.buf.len()
|
||||
}
|
||||
|
||||
pos
|
||||
/// Retrieves the remaining, free capacity of the input stream.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn remaining(&self) -> usize {
|
||||
// SAFETY: The cursor position can never exceed the
|
||||
// stream's capacity.
|
||||
unsafe { self.capacity().unchecked_sub(self.position()) }
|
||||
}
|
||||
|
||||
/// Retrieves the current cursor position of the input stream.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn position(&self) -> usize {
|
||||
self.pos
|
||||
}
|
||||
}
|
39
oct/src/decode/mod.rs
Normal file
39
oct/src/decode/mod.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of oct.
|
||||
//
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Error variants.
|
||||
//!
|
||||
//! This module defines the error types used by oct.
|
||||
//! All of these types define (at least conditionally) the [`Error`](core::error::Error) trait.
|
||||
|
||||
use crate::use_mod;
|
||||
|
||||
use_mod!(pub decode);
|
||||
use_mod!(pub decode_borrowed);
|
||||
use_mod!(pub input);
|
||||
|
||||
/// Implements [`Decode`] for the provided type.
|
||||
///
|
||||
/// This macro assumes the same format used by the equivalent [`Encode`](derive@crate::encode::Encode) macro.
|
||||
#[cfg(feature = "proc-macro")]
|
||||
#[cfg_attr(doc, doc(cfg(feature = "proc-macro")))]
|
||||
#[doc(inline)]
|
||||
pub use oct_macros::Decode;
|
|
@ -1,28 +1,28 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::OStream;
|
||||
use crate::encode::Output;
|
||||
use crate::error::{
|
||||
CollectionEncodeError,
|
||||
EnumEncodeError,
|
||||
|
@ -96,7 +96,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
|||
/// It is recommended to simply derive this trait for custom types.
|
||||
/// It can, of course, also just be manually implemented.
|
||||
///
|
||||
/// If all possible encodings have a known maximum size, then the [`SizedEncode`](crate::SizedEncode) trait should additionally be implemented.
|
||||
/// If all possible encodings have a known maximum size, then the [`SizedEncode`](crate::encode::SizedEncode) trait should additionally be implemented.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -107,7 +107,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
|||
/// // plementation is equivalent to what would have
|
||||
/// // been derived.
|
||||
///
|
||||
/// use librum::{Encode, OStream};
|
||||
/// use oct::encode::{Encode, Output};
|
||||
/// use core::convert::Infallible;
|
||||
///
|
||||
/// struct Foo {
|
||||
|
@ -120,13 +120,13 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
|||
///
|
||||
/// type Error = Infallible;
|
||||
///
|
||||
/// fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
/// fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
/// // Encode fields using chaining.
|
||||
///
|
||||
/// self.bar.encode(stream)?;
|
||||
/// self.baz.encode(stream)?;
|
||||
/// self.bar.encode(output)?;
|
||||
/// self.baz.encode(output)?;
|
||||
///
|
||||
/// Ok(())
|
||||
/// Result::Ok(())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -134,7 +134,7 @@ pub trait Encode {
|
|||
/// The type returned in case of error.
|
||||
type Error;
|
||||
|
||||
/// Encodes `self` into the provided stream.
|
||||
/// Encodes `self` into the provided output.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -142,16 +142,16 @@ pub trait Encode {
|
|||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If `stream` cannot contain the entirety of the resulting encoding, then this method should panic.
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error>;
|
||||
/// If `output` cannot contain the entirety of the resulting encoding, then this method should panic.
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
impl<T: Encode + ?Sized> Encode for &T {
|
||||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
T::encode(self, stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
T::encode(self, output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,8 +159,8 @@ impl<T: Encode + ?Sized> Encode for &mut T {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
T::encode(self, stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
T::encode(self, output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,8 +170,8 @@ impl<T: Encode> Encode for (T, ) {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.0.encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.0.encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,16 +179,17 @@ impl<T: Encode, const N: usize> Encode for [T; N] {
|
|||
type Error = CollectionEncodeError<Infallible, ItemEncodeError<usize, T::Error>>;
|
||||
|
||||
/// Encodes each element sequentially.
|
||||
/// The length is hard-coded into the type and is therefore not encoded.
|
||||
///
|
||||
/// The length `N ` is hard-coded into the type and is therefore not encoded.
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
for (i, v) in self.iter().enumerate() {
|
||||
v
|
||||
.encode(stream)
|
||||
.map_err(|e| CollectionEncodeError::Item(ItemEncodeError { index: i, error: e }))?;
|
||||
.encode(output)
|
||||
.map_err(|e| CollectionEncodeError::BadItem(ItemEncodeError { index: i, error: e }))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,19 +198,19 @@ impl<T: Encode> Encode for [T] {
|
|||
|
||||
/// Encodes each element sequentially with an extra length specifier (of type [`usize`]) prepended first.
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self
|
||||
.len()
|
||||
.encode(stream)
|
||||
.map_err(CollectionEncodeError::Length)?;
|
||||
.encode(output)
|
||||
.map_err(CollectionEncodeError::BadLength)?;
|
||||
|
||||
for (i,v) in self.iter().enumerate() {
|
||||
v
|
||||
.encode(stream)
|
||||
.map_err(|e| CollectionEncodeError::Item(ItemEncodeError { index: i, error: e }))?;
|
||||
.encode(output)
|
||||
.map_err(|e| CollectionEncodeError::BadItem(ItemEncodeError { index: i, error: e }))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,17 +220,18 @@ impl<T: Encode + ?Sized> Encode for Arc<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
T::encode(self, stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
T::encode(self, output)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for bool {
|
||||
type Error = <u8 as Encode>::Error;
|
||||
|
||||
/// Encodes the raw representationf of the boolean.
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
u8::from(*self).encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
u8::from(*self).encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,24 +239,24 @@ impl<T: Encode> Encode for Bound<T> {
|
|||
type Error = EnumEncodeError<u8, T::Error>;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
match *self {
|
||||
Self::Included(ref bound) => {
|
||||
0x0u8.encode(stream).unwrap();
|
||||
bound.encode(stream).map_err(EnumEncodeError::Field)?;
|
||||
let Ok(_) = 0x0u8.encode(output);
|
||||
bound.encode(output).map_err(EnumEncodeError::BadField)?;
|
||||
}
|
||||
|
||||
Self::Excluded(ref bound) => {
|
||||
0x1u8.encode(stream).unwrap();
|
||||
bound.encode(stream).map_err(EnumEncodeError::Field)?;
|
||||
let Ok(_) = 0x1u8.encode(output);
|
||||
bound.encode(output).map_err(EnumEncodeError::BadField)?;
|
||||
}
|
||||
|
||||
Self::Unbounded => {
|
||||
0x2u8.encode(stream).unwrap();
|
||||
let Ok(_) = 0x2u8.encode(output);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -264,8 +266,8 @@ impl<T: Encode + ?Sized> Encode for Box<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
T::encode(self, stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
T::encode(self, output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,8 +275,8 @@ impl<T: Copy + Encode> Encode for Cell<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.get().encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.get().encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,8 +284,8 @@ impl Encode for char {
|
|||
type Error = <u32 as Encode>::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
u32::from(*self).encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
u32::from(*self).encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,8 +295,8 @@ impl<T: Encode + ?Sized + ToOwned> Encode for Cow<'_, T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
T::encode(self, stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
T::encode(self, output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,8 +305,8 @@ impl Encode for CStr {
|
|||
|
||||
/// Encodes the string identically to [a byte slice](slice) containing the string's byte values **excluding** the null terminator.
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.to_bytes().encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.to_bytes().encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,8 +317,8 @@ impl Encode for CString {
|
|||
|
||||
/// See the the implementation of [`CStr`].
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.as_c_str().encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.as_c_str().encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,11 +327,11 @@ impl Encode for Duration {
|
|||
|
||||
/// Encodes the duration's seconds and nanoseconds counters sequentially.
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.as_secs().encode(stream).unwrap();
|
||||
self.subsec_nanos().encode(stream).unwrap();
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.as_secs().encode(output)?;
|
||||
self.subsec_nanos().encode(output)?;
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,13 +346,13 @@ where
|
|||
type Error = E;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
for (key, value) in self {
|
||||
key.encode(stream)?;
|
||||
value.encode(stream)?;
|
||||
key.encode(output)?;
|
||||
value.encode(output)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,12 +366,12 @@ where
|
|||
type Error = K::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
for key in self {
|
||||
key.encode(stream)?;
|
||||
key.encode(output)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,9 +381,9 @@ impl Encode for Infallible {
|
|||
type Error = Self;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, _stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
// SAFETY: `Infallible` can **never** be construct-
|
||||
// ed.
|
||||
fn encode(&self, _output: &mut Output) -> Result<(), Self::Error> {
|
||||
// SAFETY: `Infallible` objects can never be con-
|
||||
// structed
|
||||
unsafe { unreachable_unchecked() }
|
||||
}
|
||||
}
|
||||
|
@ -393,22 +395,22 @@ impl Encode for IpAddr {
|
|||
///
|
||||
/// See also the implementations of [`Ipv4Addr`] and [`Ipv6Addr`].
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
// The discriminant here is the IP version.
|
||||
|
||||
match *self {
|
||||
Self::V4(ref addr) => {
|
||||
0x4u8.encode(stream).map_err(EnumEncodeError::Discriminant)?;
|
||||
addr.encode(stream).map_err(EnumEncodeError::Field)?;
|
||||
0x4u8.encode(output).map_err(EnumEncodeError::BadDiscriminant)?;
|
||||
addr.encode(output).map_err(EnumEncodeError::BadField)?;
|
||||
}
|
||||
|
||||
Self::V6(ref addr) => {
|
||||
0x6u8.encode(stream).map_err(EnumEncodeError::Discriminant)?;
|
||||
addr.encode(stream).map_err(EnumEncodeError::Field)?;
|
||||
0x6u8.encode(output).map_err(EnumEncodeError::BadDiscriminant)?;
|
||||
addr.encode(output).map_err(EnumEncodeError::BadField)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -417,9 +419,9 @@ impl Encode for Ipv4Addr {
|
|||
|
||||
/// Encodes the address's bits in big-endian.
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
let value = self.to_bits();
|
||||
value.encode(stream)
|
||||
value.encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -428,9 +430,9 @@ impl Encode for Ipv6Addr {
|
|||
|
||||
/// Encodes the address's bits in big-endian.
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
let value = self.to_bits();
|
||||
value.encode(stream)
|
||||
value.encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -439,12 +441,12 @@ impl Encode for isize {
|
|||
|
||||
/// Casts `self` to [`i16`] and encodes the result.
|
||||
#[inline]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
let value = i16::try_from(*self)
|
||||
.map_err(|_| IsizeEncodeError(*self))?;
|
||||
|
||||
value.encode(stream).unwrap();
|
||||
Ok(())
|
||||
let Ok(_) = value.encode(output);
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -452,8 +454,8 @@ impl<T: Encode> Encode for LazyCell<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
T::encode(self, stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
T::encode(self, output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -463,8 +465,8 @@ impl<T: Encode> Encode for LazyLock<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
T::encode(self, stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
T::encode(self, output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,19 +476,19 @@ impl<T: Encode<Error = E>, E> Encode for LinkedList<T> {
|
|||
type Error = CollectionEncodeError<UsizeEncodeError, (usize, E)>;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self
|
||||
.len()
|
||||
.encode(stream)
|
||||
.map_err(CollectionEncodeError::Length)?;
|
||||
.encode(output)
|
||||
.map_err(CollectionEncodeError::BadLength)?;
|
||||
|
||||
for (i, v) in self.iter().enumerate() {
|
||||
v
|
||||
.encode(stream)
|
||||
.map_err(|e| CollectionEncodeError::Item((i, e)))?;
|
||||
.encode(output)
|
||||
.map_err(|e| CollectionEncodeError::BadItem((i, e)))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -496,11 +498,11 @@ impl<T: Encode + ?Sized> Encode for Mutex<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.encode(stream)
|
||||
.encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -511,19 +513,24 @@ impl<T: Encode> Encode for Option<T> {
|
|||
/// This is `false` for `None` instances and `true` for `Some` instances.
|
||||
///
|
||||
/// If `Some`, then the contained value is encoded after this sign..
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
match *self {
|
||||
None => {
|
||||
false.encode(stream).unwrap();
|
||||
false
|
||||
.encode(output)
|
||||
.map_err::<Self::Error, _>(|_v| unreachable!())?;
|
||||
}
|
||||
|
||||
Some(ref v) => {
|
||||
true.encode(stream).unwrap();
|
||||
v.encode(stream)?;
|
||||
true
|
||||
.encode(output)
|
||||
.map_err::<Self::Error, _>(|_v| unreachable!())?;
|
||||
|
||||
v.encode(output)?;
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -531,8 +538,8 @@ impl<T> Encode for PhantomData<T> {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, _stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
fn encode(&self, _output: &mut Output) -> Result<(), Self::Error> {
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,8 +547,8 @@ impl Encode for PhantomPinned {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, _stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
fn encode(&self, _output: &mut Output) -> Result<(), Self::Error> {
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -549,11 +556,11 @@ impl<T: Encode> Encode for Range<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.start.encode(stream)?;
|
||||
self.end.encode(stream)?;
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.start.encode(output)?;
|
||||
self.end.encode(output)?;
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -561,8 +568,8 @@ impl<T: Encode> Encode for RangeFrom<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.start.encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.start.encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -570,8 +577,8 @@ impl Encode for RangeFull {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, _stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
fn encode(&self, _output: &mut Output) -> Result<(), Self::Error> {
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -579,11 +586,11 @@ impl<T: Encode> Encode for RangeInclusive<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.start().encode(stream)?;
|
||||
self.end().encode(stream)?;
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.start().encode(output)?;
|
||||
self.end().encode(output)?;
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -591,8 +598,8 @@ impl<T: Encode> Encode for RangeTo<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.end.encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.end.encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -600,10 +607,10 @@ impl<T: Encode> Encode for RangeToInclusive<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.end.encode(stream)?;
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.end.encode(output)?;
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -613,8 +620,8 @@ impl<T: Encode + ?Sized> Encode for Rc<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
T::encode(self, stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
T::encode(self, output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -622,21 +629,22 @@ impl<T: Encode + ?Sized> Encode for RefCell<T> {
|
|||
type Error = RefCellEncodeError<T::Error>;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
let value = self.try_borrow()
|
||||
.map_err(RefCellEncodeError::Borrow)?;
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
let value = self
|
||||
.try_borrow()
|
||||
.map_err(RefCellEncodeError::BadBorrow)?;
|
||||
|
||||
T::encode(&value, stream)
|
||||
.map_err(RefCellEncodeError::Value)?;
|
||||
T::encode(&value, output)
|
||||
.map_err(RefCellEncodeError::BadValue)?;
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E, Err> Encode for core::result::Result<T, E>
|
||||
impl<T, E, Err> Encode for Result<T, E>
|
||||
where
|
||||
T: Encode<Error = Err>,
|
||||
E: Encode<Error = Err>,
|
||||
E: Encode<Error: Into<Err>>,
|
||||
{
|
||||
type Error = Err;
|
||||
|
||||
|
@ -645,23 +653,25 @@ where
|
|||
///
|
||||
/// If `Ok`, then the contained value is encoded after this sign.
|
||||
#[inline]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
// The sign here is `false` for `Ok` objects and
|
||||
// `true` for `Err` objects.
|
||||
|
||||
match *self {
|
||||
Ok(ref v) => {
|
||||
false.encode(stream).unwrap();
|
||||
v.encode(stream)?;
|
||||
let Ok(_) = false.encode(output);
|
||||
|
||||
v.encode(output)?;
|
||||
}
|
||||
|
||||
Err(ref e) => {
|
||||
true.encode(stream).unwrap();
|
||||
e.encode(stream)?;
|
||||
let Ok(_) = true.encode(output);
|
||||
|
||||
e.encode(output).map_err(Into::into)?;
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -671,11 +681,11 @@ impl<T: Encode + ?Sized> Encode for RwLock<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self
|
||||
.read()
|
||||
.or_else(|e| Ok(e.into_inner()))?
|
||||
.encode(stream)
|
||||
.encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -683,8 +693,8 @@ impl<T: Encode> Encode for Saturating<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.0.encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.0.encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -694,22 +704,22 @@ impl Encode for SocketAddr {
|
|||
/// This implementation encoded as discriminant denoting the IP version of the address (i.e. `4` for IPv4 and `6` for IPv6).
|
||||
/// This is then followed by the respective address' own encoding (either [`SocketAddrV4`] or [`SocketAddrV6`]).
|
||||
#[inline]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
// The discriminant here is the IP version.
|
||||
|
||||
match *self {
|
||||
Self::V4(ref addr) => {
|
||||
0x4u8.encode(stream)?;
|
||||
addr.encode(stream)?;
|
||||
0x4u8.encode(output)?;
|
||||
addr.encode(output)?;
|
||||
}
|
||||
|
||||
Self::V6(ref addr) => {
|
||||
0x6u8.encode(stream)?;
|
||||
addr.encode(stream)?;
|
||||
0x6u8.encode(output)?;
|
||||
addr.encode(output)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -718,11 +728,11 @@ impl Encode for SocketAddrV4 {
|
|||
|
||||
/// Encodes the address's bits followed by the port number, both of which in big-endian.
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.ip().encode(stream)?;
|
||||
self.port().encode(stream)?;
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.ip().encode(output)?;
|
||||
self.port().encode(output)?;
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -731,13 +741,13 @@ impl Encode for SocketAddrV6 {
|
|||
|
||||
/// Encodes the address's bits followed by the port number, flow information, and scope identifier -- all of which in big-endian.
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.ip().encode(stream)?;
|
||||
self.port().encode(stream)?;
|
||||
self.flowinfo().encode(stream)?;
|
||||
self.scope_id().encode(stream)?;
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.ip().encode(output)?;
|
||||
self.port().encode(output)?;
|
||||
self.flowinfo().encode(output)?;
|
||||
self.scope_id().encode(output)?;
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -746,8 +756,8 @@ impl Encode for str {
|
|||
|
||||
/// Encodes the string identically to [a byte slice](slice) containing the string's byte values.
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.as_bytes().encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.as_bytes().encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -758,8 +768,8 @@ impl Encode for String {
|
|||
|
||||
/// See [`str`].
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.as_str().encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.as_str().encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -772,7 +782,7 @@ impl Encode for SystemTime {
|
|||
///
|
||||
/// Examples of some timestamps and their encodings include:
|
||||
///
|
||||
/// | ISO 8601 | UNIX / Librum |
|
||||
/// | ISO 8601 | UNIX / oct |
|
||||
/// | :-------------------------- | -------------: |
|
||||
/// | `2024-11-03T12:02:01+01:00` | +1730631721 |
|
||||
/// | `1989-06-03T20:00:00+09:00` | +13258800 |
|
||||
|
@ -780,7 +790,7 @@ impl Encode for SystemTime {
|
|||
/// | `1945-05-04T18:30:00+02:00` | -778231800 |
|
||||
#[expect(clippy::cast_possible_wrap)]
|
||||
#[inline]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
let time = if *self >= UNIX_EPOCH {
|
||||
let duration = self
|
||||
.duration_since(UNIX_EPOCH)
|
||||
|
@ -795,8 +805,8 @@ impl Encode for SystemTime {
|
|||
0x0 - duration.as_secs() as i64
|
||||
};
|
||||
|
||||
time.encode(stream).unwrap();
|
||||
Ok(())
|
||||
time.encode(output)?;
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -804,8 +814,8 @@ impl Encode for () {
|
|||
type Error = Infallible;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, _stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
fn encode(&self, _output: &mut Output) -> Result<(), Self::Error> {
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -814,12 +824,12 @@ impl Encode for usize {
|
|||
|
||||
/// Casts `self` to [`u16`] and encodes the result.
|
||||
#[inline]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
let value = u16::try_from(*self)
|
||||
.map_err(|_| UsizeEncodeError(*self))?;
|
||||
.map_err(|_e| UsizeEncodeError(*self))?;
|
||||
|
||||
value.encode(stream).unwrap();
|
||||
Ok(())
|
||||
let Ok(_) = value.encode(output);
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -829,8 +839,8 @@ impl<T: Encode> Encode for Vec<T> {
|
|||
type Error = <[T] as Encode>::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.as_slice().encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.as_slice().encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -838,21 +848,21 @@ impl<T: Encode> Encode for Wrapping<T> {
|
|||
type Error = T::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.0.encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.0.encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_numeric {
|
||||
($ty:ty$(,)?) => {
|
||||
impl ::librum::Encode for $ty {
|
||||
impl ::oct::encode::Encode for $ty {
|
||||
type Error = ::core::convert::Infallible;
|
||||
|
||||
#[inline]
|
||||
fn encode(&self, stream: &mut OStream) -> ::core::result::Result<(), Self::Error> {
|
||||
stream.write(&self.to_le_bytes());
|
||||
fn encode(&self, output: &mut Output) -> ::core::result::Result<(), Self::Error> {
|
||||
output.write(&self.to_le_bytes()).unwrap();
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -863,20 +873,20 @@ macro_rules! impl_tuple {
|
|||
$($captures:ident: $tys:ident),+$(,)?
|
||||
} => {
|
||||
#[doc(hidden)]
|
||||
impl<$($tys, )* E> ::librum::Encode for ($($tys, )*)
|
||||
impl<$($tys, )* E> ::oct::encode::Encode for ($($tys, )*)
|
||||
where
|
||||
$($tys: Encode<Error = E>, )* {
|
||||
type Error = E;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut ::librum::OStream) -> ::core::result::Result<(), Self::Error> {
|
||||
fn encode(&self, output: &mut ::oct::encode::Output) -> ::core::result::Result<(), Self::Error> {
|
||||
let ($(ref $captures, )*) = *self;
|
||||
|
||||
$(
|
||||
$captures.encode(stream)?;
|
||||
$captures.encode(output)?;
|
||||
)*
|
||||
|
||||
Ok(())
|
||||
Result::Ok(())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -884,12 +894,12 @@ macro_rules! impl_tuple {
|
|||
|
||||
macro_rules! impl_non_zero {
|
||||
($ty:ty$(,)?) => {
|
||||
impl ::librum::Encode for ::core::num::NonZero<$ty> {
|
||||
type Error = <$ty as ::librum::Encode>::Error;
|
||||
impl ::oct::encode::Encode for ::core::num::NonZero<$ty> {
|
||||
type Error = <$ty as ::oct::encode::Encode>::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> ::core::result::Result<(), Self::Error> {
|
||||
self.get().encode(stream)
|
||||
fn encode(&self, output: &mut ::oct::encode::Output) -> ::core::result::Result<(), Self::Error> {
|
||||
self.get().encode(output)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -903,15 +913,17 @@ macro_rules! impl_atomic {
|
|||
} => {
|
||||
#[cfg(target_has_atomic = $width)]
|
||||
#[cfg_attr(doc, doc(cfg(target_has_atomic = $width)))]
|
||||
impl ::librum::Encode for $atomic_ty {
|
||||
type Error = <$ty as ::librum::Encode>::Error;
|
||||
impl ::oct::encode::Encode for $atomic_ty {
|
||||
type Error = <$ty as ::oct::encode::Encode>::Error;
|
||||
|
||||
/// Encodes the atomic with the same scheme as that of the atomic type's primitive counterpart.
|
||||
///
|
||||
/// The atomic object itself is read with the [`Relaxed`](core::sync::atomic::Ordering) ordering scheme.
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut ::librum::OStream) -> ::core::result::Result<(), Self::Error> {
|
||||
self.load(::std::sync::atomic::Ordering::Relaxed).encode(stream)
|
||||
fn encode(&self, output: &mut ::oct::encode::Output) -> ::core::result::Result<(), Self::Error> {
|
||||
use ::std::sync::atomic::Ordering;
|
||||
|
||||
self.load(Ordering::Relaxed).encode(output)
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of librum.
|
||||
// This file is part of oct.
|
||||
//test!(you can redistribut => []);
|
||||
// it and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
|
@ -8,17 +8,18 @@
|
|||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use librum::{Encode, OStream, SizedEncode, SizedStr};
|
||||
use oct::SizedStr;
|
||||
use oct::encode::{Encode, Output, SizedEncode};
|
||||
use std::time::Duration;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use std::vec;
|
||||
|
@ -30,10 +31,10 @@ macro_rules! test {
|
|||
|
||||
let mut buf = vec![0x00; data.len()];
|
||||
|
||||
let mut stream = OStream::new(&mut buf);
|
||||
let mut stream = Output::new(&mut buf);
|
||||
<$ty as Encode>::encode(&$value, &mut stream).unwrap();
|
||||
|
||||
let len = stream.close();
|
||||
let len = stream.position();
|
||||
assert_eq!(&buf[..len], data.as_slice());
|
||||
}};
|
||||
}
|
||||
|
@ -68,7 +69,7 @@ fn test_encode() {
|
|||
0xB1, 0x03, 0x00, 0x00,
|
||||
]);
|
||||
|
||||
test!(Result::<u16, char>: Ok(0x45_45) => [0x00, 0x45, 0x45]);
|
||||
test!(Result::<u16, char>: Ok(0x4545) => [0x00, 0x45, 0x45]);
|
||||
|
||||
test!(Result::<u16, char>: Err(char::REPLACEMENT_CHARACTER) => [0x01, 0xFD, 0xFF, 0x00, 0x00]);
|
||||
|
134
oct/src/encode/mod.rs
Normal file
134
oct/src/encode/mod.rs
Normal file
|
@ -0,0 +1,134 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of oct.
|
||||
//
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Error variants.
|
||||
//!
|
||||
//! This module defines the error types used by oct.
|
||||
//! All of these types define (at least conditionally) the [`Error`](core::error::Error) trait.
|
||||
|
||||
use crate::use_mod;
|
||||
|
||||
use_mod!(pub encode);
|
||||
use_mod!(pub output);
|
||||
use_mod!(pub sized_encode);
|
||||
|
||||
/// Implements [`Encode`] for the provided type.
|
||||
///
|
||||
/// This derive macro assumes that all fields implement <code>Encode<[Error]: [Into]<[GenericEncodeError]>></code>.
|
||||
/// If this is **not** the case, then the trait should be implemented manually instead.
|
||||
///
|
||||
/// [Error]: Encode::Error
|
||||
/// [GenericEncodeError]: crate::error::GenericEncodeError
|
||||
///
|
||||
/// Do also consider deriving [`SizedEncode`](derive@SizedEncode) -- if possible.
|
||||
///
|
||||
/// # Structs
|
||||
///
|
||||
/// For structures, each element is chained in **order of declaration.**
|
||||
/// If the structure is a unit structure (i.e. it has *no* fields) then it is encoded equivalently to the [unit] type.
|
||||
///
|
||||
/// For example, the following struct will encode its field `foo` followed by `bar`:
|
||||
///
|
||||
/// ```
|
||||
/// use oct::encode::Encode;
|
||||
///
|
||||
/// #[derive(Encode)]
|
||||
/// struct FooBar {
|
||||
/// pub foo: char,
|
||||
/// pub bar: char,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This should be kept in mind when changing the structure's declarationm as doing so may invalidate previous encodings.
|
||||
///
|
||||
/// The [`Error`](Encode::Error) type will in all cases just be `GenericEncodeError`.
|
||||
///
|
||||
/// # Enums
|
||||
///
|
||||
/// Enumerations encode like structures except that each variant additionally encodes a unique discriminant.
|
||||
///
|
||||
/// By default, each discriminant is assigned from the range 0 to infinite, to the extend allowed by the [`isize`] type and its encoding (as which **all** discriminants are encoded).
|
||||
/// A custom discriminant may be set instead by assigning the variant an integer constant.
|
||||
/// Unspecified discriminants then increment the previous variant's discriminant:
|
||||
///
|
||||
/// ```
|
||||
/// use oct::Slot;
|
||||
/// use oct::encode::Encode;
|
||||
///
|
||||
/// #[derive(Encode)]
|
||||
/// enum Num {
|
||||
/// Two = 0x2,
|
||||
///
|
||||
/// Three,
|
||||
///
|
||||
/// Zero = 0x0,
|
||||
///
|
||||
/// One,
|
||||
/// }
|
||||
///
|
||||
/// let mut buf = Slot::with_capacity(size_of::<i16>());
|
||||
///
|
||||
/// buf.write(Num::Zero).unwrap();
|
||||
/// assert_eq!(buf, [0x00, 0x00].as_slice());
|
||||
///
|
||||
/// buf.write(Num::One).unwrap();
|
||||
/// assert_eq!(buf, [0x01, 0x00].as_slice());
|
||||
///
|
||||
/// buf.write(Num::Two).unwrap();
|
||||
/// assert_eq!(buf, [0x02, 0x00].as_slice());
|
||||
///
|
||||
/// buf.write(Num::Three).unwrap();
|
||||
/// assert_eq!(buf, [0x03, 0x00].as_slice());
|
||||
/// ```
|
||||
///
|
||||
/// Variants with fields are encoded exactly like structures.
|
||||
/// That is, each field is chained in order of declaration.
|
||||
///
|
||||
/// For error handling, the `Error` type is defined as:
|
||||
///
|
||||
/// <code>[EnumEncodeError]<<Repr as Encode>::Error, GenericEncodeError></code>,
|
||||
///
|
||||
/// [EnumEncodeError]: crate::error::GenericEncodeError
|
||||
///
|
||||
/// wherein `Repr` is the enumeration's representation.
|
||||
///
|
||||
/// # Unions
|
||||
///
|
||||
/// Unions cannot derive `Encode` due to the uncertainty of their contents.
|
||||
/// The trait should therefore be implemented manually for such types.
|
||||
#[cfg(feature = "proc-macro")]
|
||||
#[cfg_attr(doc, doc(cfg(feature = "proc-macro")))]
|
||||
#[doc(inline)]
|
||||
pub use oct_macros::Encode;
|
||||
|
||||
/// Implements [`Encode`](trait@Encode) using the default implementation.
|
||||
///
|
||||
/// For simple structures, the value of [`MAX_ENCODED_SIZE`](SizedEncode::MAX_ENCODED_SIZE) is set as the combined value of <code>T*n*::MAX_ENCODED_SIZE</code> wherein <code>T*n*</code> is the type of each field.
|
||||
///
|
||||
/// For enumerations, the value is set such that each variant is treated like a structure (with the discriminant as an extra field) and where the variant that produces the largest `MAX_ENCODED_SIZE` is chosen.
|
||||
///
|
||||
/// As untagged unions cannot derive `Encode`, `SizedEncode` also cannot be derived for them.
|
||||
///
|
||||
/// Do remember that deriving this trait is only recommended
|
||||
#[cfg(feature = "proc-macro")]
|
||||
#[cfg_attr(doc, doc(cfg(feature = "proc-macro")))]
|
||||
#[doc(inline)]
|
||||
pub use oct_macros::SizedEncode;
|
156
oct/src/encode/output/mod.rs
Normal file
156
oct/src/encode/output/mod.rs
Normal file
|
@ -0,0 +1,156 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::error::OutputError;
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::ptr::copy_nonoverlapping;
|
||||
use core::slice;
|
||||
|
||||
/// Byte stream suitable for writing.
|
||||
#[derive(Eq)]
|
||||
pub struct Output<'a> {
|
||||
buf: &'a mut [u8],
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl<'a> Output<'a> {
|
||||
/// Constructs a new o-stream.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn new(buf: &'a mut [u8]) -> Self {
|
||||
Self { buf, pos: 0x0 }
|
||||
}
|
||||
|
||||
/// Writes bytes to the stream.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If the requested amount of bytes could not exactly be written, then this method will panic.
|
||||
#[inline]
|
||||
pub const fn write(&mut self, data: &[u8]) -> Result<(), OutputError> {
|
||||
let remaining = self.buf.len() - self.pos;
|
||||
let count = data.len();
|
||||
|
||||
if remaining < count {
|
||||
return Err(OutputError {
|
||||
capacity: self.buf.len(),
|
||||
position: self.pos,
|
||||
count,
|
||||
});
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let src = data.as_ptr();
|
||||
let dst = self.buf.as_mut_ptr().add(self.pos);
|
||||
|
||||
copy_nonoverlapping(src, dst, count);
|
||||
}
|
||||
|
||||
self.pos += count;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets a pointer to the first byte of the output stream.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn as_ptr(&self) -> *const u8 {
|
||||
self.buf.as_ptr()
|
||||
}
|
||||
|
||||
/// Gets a slice of the written bytes in the output stream.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn as_slice(&self) -> &[u8] {
|
||||
unsafe {
|
||||
let ptr = self.as_ptr();
|
||||
let len = self.position();
|
||||
|
||||
slice::from_raw_parts(ptr, len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the maximum capacity of the output stream.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn capacity(&self) -> usize {
|
||||
self.buf.len()
|
||||
}
|
||||
|
||||
/// Retrieves the remaining, free capacity of the output stream.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn remaining(&self) -> usize {
|
||||
// SAFETY: The cursor position can never exceed the
|
||||
// stream's capacity.
|
||||
unsafe { self.capacity().unchecked_sub(self.position()) }
|
||||
}
|
||||
|
||||
/// Retrieves the current cursor position of the output stream.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn position(&self) -> usize {
|
||||
self.pos
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Output<'_> {
|
||||
#[inline(always)]
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<[u8]> for Output<'_> {
|
||||
#[inline(always)]
|
||||
fn borrow(&self) -> &[u8] {
|
||||
self.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Output<'_> {
|
||||
#[inline(always)]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_slice() == other.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<[u8]> for Output<'_> {
|
||||
#[inline(always)]
|
||||
fn eq(&self, other: &[u8]) -> bool {
|
||||
self.as_slice() == other
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<&[u8]> for Output<'_> {
|
||||
#[inline(always)]
|
||||
fn eq(&self, other: &&[u8]) -> bool {
|
||||
self.as_slice() == *other
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<&mut [u8]> for Output<'_> {
|
||||
#[inline(always)]
|
||||
fn eq(&self, other: &&mut [u8]) -> bool {
|
||||
self.as_slice() == *other
|
||||
}
|
||||
}
|
|
@ -1,28 +1,28 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::Encode;
|
||||
use crate::encode::Encode;
|
||||
|
||||
use core::cell::{Cell, LazyCell, RefCell};
|
||||
use core::convert::Infallible;
|
||||
|
@ -74,7 +74,7 @@ use std::time::SystemTime;
|
|||
/// The general rule is that the size limit must be a substantial part of a type's design to constitute implementing this trait.
|
||||
///
|
||||
/// Also note that -- in practice -- this trait is **not** strictly enforceable.
|
||||
/// Users of the `Encode` and [`Decode`](crate::Decode) traits should assume that this trait is mostly properly defined, but should also still leave room for the possibility that it isn't.
|
||||
/// Users of the `Encode` and [`Decode`](crate::decode::Decode) traits should assume that this trait is mostly properly defined, but should also still leave room for the possibility that it isn't.
|
||||
pub trait SizedEncode: Encode + Sized {
|
||||
/// The maximum guaranteed amount of bytes that can result from an encoding.
|
||||
///
|
||||
|
@ -278,7 +278,7 @@ impl<T: SizedEncode> SizedEncode for Wrapping<T> {
|
|||
|
||||
macro_rules! impl_numeric {
|
||||
($ty:ty$(,)?) => {
|
||||
impl ::librum::SizedEncode for $ty {
|
||||
impl ::oct::encode::SizedEncode for $ty {
|
||||
const MAX_ENCODED_SIZE: usize = size_of::<$ty>();
|
||||
}
|
||||
};
|
||||
|
@ -289,18 +289,18 @@ macro_rules! impl_tuple {
|
|||
$($tys:ident),+$(,)?
|
||||
} => {
|
||||
#[doc(hidden)]
|
||||
impl<$($tys, )* E> ::librum::SizedEncode for ($($tys, )*)
|
||||
impl<$($tys, )* E> ::oct::encode::SizedEncode for ($($tys, )*)
|
||||
where
|
||||
$($tys: SizedEncode + Encode<Error = E>, )* {
|
||||
const MAX_ENCODED_SIZE: usize = 0x0 $(+ <$tys as ::librum::SizedEncode>::MAX_ENCODED_SIZE)*;
|
||||
const MAX_ENCODED_SIZE: usize = 0x0 $(+ <$tys as ::oct::encode::SizedEncode>::MAX_ENCODED_SIZE)*;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_non_zero {
|
||||
($ty:ty$(,)?) => {
|
||||
impl ::librum::SizedEncode for ::core::num::NonZero<$ty> {
|
||||
const MAX_ENCODED_SIZE: usize = <$ty as ::librum::SizedEncode>::MAX_ENCODED_SIZE;
|
||||
impl ::oct::encode::SizedEncode for ::core::num::NonZero<$ty> {
|
||||
const MAX_ENCODED_SIZE: usize = <$ty as ::oct::encode::SizedEncode>::MAX_ENCODED_SIZE;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -313,8 +313,8 @@ macro_rules! impl_atomic {
|
|||
} => {
|
||||
#[cfg(target_has_atomic = $width)]
|
||||
#[cfg_attr(doc, doc(cfg(target_has_atomic = $width)))]
|
||||
impl ::librum::SizedEncode for $atomic_ty {
|
||||
const MAX_ENCODED_SIZE: usize = <$ty as ::librum::SizedEncode>::MAX_ENCODED_SIZE;
|
||||
impl ::oct::encode::SizedEncode for $atomic_ty {
|
||||
const MAX_ENCODED_SIZE: usize = <$ty as ::oct::encode::SizedEncode>::MAX_ENCODED_SIZE;
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,25 +1,26 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use librum::{Encode, SizedStr, SizedEncode};
|
||||
use oct::SizedStr;
|
||||
use oct::encode::{Encode, SizedEncode};
|
||||
use std::convert::Infallible;
|
||||
use std::marker::PhantomData;
|
||||
use std::net::{
|
||||
|
@ -34,7 +35,7 @@ use std::num::NonZero;
|
|||
|
||||
macro_rules! assert_encoded_size {
|
||||
($ty:ty, $value:expr$(,)?) => {{
|
||||
assert_eq!(<$ty as ::librum::SizedEncode>::MAX_ENCODED_SIZE, $value);
|
||||
assert_eq!(<$ty as ::oct::encode::SizedEncode>::MAX_ENCODED_SIZE, $value);
|
||||
}};
|
||||
}
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::error::Error;
|
||||
|
@ -24,7 +24,7 @@ use core::fmt::{self, Display, Formatter};
|
|||
|
||||
/// A C-like string could not be decoded.
|
||||
///
|
||||
/// This error is generatead when <code><[CString](alloc::ffi::CString) as [Decode](crate::Decode)>::[decode](crate::Decode::decode)</code> encounteres a null byte within bounds.
|
||||
/// This error is generatead when <code><[CString](alloc::ffi::CString) as [Decode](crate::decode::Decode)>::[decode](crate::decode::Decode::decode)</code> encounteres a null byte within bounds.
|
||||
///
|
||||
/// Note that although any null value is *theoretically* also the string's null terminator, the implementations for [`CStr`](core::ffi::CStr) and `CString` use the same encoding scheme as [`[u8]`](slice).
|
||||
/// This is mainly for efficiency's sake (as to allow the entire stream to be read at once), but this also allows for the aforementioned case to happen.
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::error::Error;
|
||||
|
@ -28,7 +28,7 @@ use core::fmt::{self, Display, Formatter};
|
|||
/// UTF-32 (the format used by the [`char`] data type) additionally specifies that these code points are padded to 32 bits.
|
||||
///
|
||||
/// The encoding scheme used by `char` yields an untransformed representation (disregarding endian corrections), but this regrettably also leads to many bit patterns being undefined with respect to UTF-32.
|
||||
/// If any of these values is read by <code><char as [Decode](crate::Decode)>::[decode](crate::Decode::decode)</code>, then an instance of this error type is returned.
|
||||
/// If any of these values is read by <code><char as [Decode](crate::decode::Decode)>::[decode](crate::decode::Decode::decode)</code>, then an instance of this error type is returned.
|
||||
#[derive(Debug)]
|
||||
#[must_use]
|
||||
pub struct CharDecodeError {
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::convert::Infallible;
|
||||
|
@ -26,11 +26,11 @@ use core::fmt::{self, Display, Formatter};
|
|||
/// A collection could not be decoded.
|
||||
///
|
||||
/// This type is intended as a partially-generic decode error for collections.
|
||||
/// It supports denoting an error for when the collection's length is invalid -- see the [`Length`](Self::Length) variant -- and when an element is invalid -- see the [`Item`](Self::Item)) variant.
|
||||
/// It supports denoting an error for when the collection's length is invalid -- see the [`BadLength`](Self::BadLength) variant -- and when an element is invalid -- see the [`Item`](Self::BadItem)) variant.
|
||||
///
|
||||
/// The most common form of this type is <code>CollectionDecodeError<[Infallible](core::convert::Infallible), [ItemDecodeError](crate::error::ItemDecodeError)<[usize], ..></code>, but this may not always necessarily be the preferred form.
|
||||
///
|
||||
/// An example of a type using a different form is [`SizedStr`](crate::SizedStr), which uses <code>CollectionDecodeError<[`SizeError`](crate::error::SizeError), [Utf8Error](crate::error::Utf8Error)></code>.
|
||||
/// An example of a type using a different form is [`SizedStr`](crate::SizedStr), which uses <code>CollectionDecodeError<[`LengthError`](crate::error::LengthError), [Utf8Error](crate::error::Utf8Error)></code>.
|
||||
#[derive(Debug)]
|
||||
#[must_use]
|
||||
pub enum CollectionDecodeError<L, I> {
|
||||
|
@ -39,13 +39,13 @@ pub enum CollectionDecodeError<L, I> {
|
|||
/// For most dynamically-sized collections, the suitable type here is [`Infallible`] due to there basically being no restriction on the collection's size (depending on the data type used for denoting lengths).
|
||||
///
|
||||
/// Sometimes the length isn't even encoded in the stream (instead lying in the type signature), and in these cases the appropriate type would also be `Infallible`.
|
||||
Length(L),
|
||||
BadLength(L),
|
||||
|
||||
/// A collection item could not be decoded.
|
||||
///
|
||||
/// Sometimes the index of the item may be desired.
|
||||
/// In these cases the [`ItemDecodeError`](crate::error::ItemDecodeError) could be used here.
|
||||
Item(I),
|
||||
BadItem(I),
|
||||
}
|
||||
|
||||
impl<L, I> Display for CollectionDecodeError<L, I>
|
||||
|
@ -55,13 +55,11 @@ where
|
|||
{
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
use CollectionDecodeError::*;
|
||||
|
||||
match *self {
|
||||
Length(ref e)
|
||||
Self::BadLength(ref e)
|
||||
=> write!(f, "unable to decode collection length: {e}"),
|
||||
|
||||
Item(ref e)
|
||||
Self::BadItem(ref e)
|
||||
=> write!(f, "unable to decode collection item: {e}"),
|
||||
}
|
||||
}
|
||||
|
@ -74,12 +72,10 @@ where
|
|||
{
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
use CollectionDecodeError::*;
|
||||
|
||||
match *self {
|
||||
Length(ref e) => Some(e),
|
||||
Self::BadLength(ref e) => Some(e),
|
||||
|
||||
Item(ref e) => Some(e),
|
||||
Self::BadItem(ref e) => Some(e),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::convert::Infallible;
|
||||
|
@ -26,15 +26,15 @@ use core::fmt::{self, Display, Formatter};
|
|||
/// A collection could not be encoded.
|
||||
///
|
||||
/// This type is intended as a partially-generic encode error for collections.
|
||||
/// It supports denoting an error for when the collection's length is invalid -- see the [`Length`](Self::Length) variant -- and when an element is invalid -- see the [`Item`](Self::Item)) variant.
|
||||
/// It supports denoting an error for when the collection's length is invalid -- see the [`BadLength`](Self::BadLength) variant -- and when an element is invalid -- see the [`Item`](Self::BadItem)) variant.
|
||||
#[derive(Debug)]
|
||||
#[must_use]
|
||||
pub enum CollectionEncodeError<L, I> {
|
||||
/// The collection length could not be encoded.
|
||||
Length(L),
|
||||
BadLength(L),
|
||||
|
||||
/// A collection item could not be encoded.
|
||||
Item(I),
|
||||
BadItem(I),
|
||||
}
|
||||
|
||||
impl<L, I> Display for CollectionEncodeError<L, I>
|
||||
|
@ -44,13 +44,11 @@ where
|
|||
{
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
use CollectionEncodeError::*;
|
||||
|
||||
match *self {
|
||||
Length(ref e)
|
||||
Self::BadLength(ref e)
|
||||
=> write!(f, "unable to encode collection length: {e}"),
|
||||
|
||||
Item(ref e)
|
||||
Self::BadItem(ref e)
|
||||
=> write!(f, "unable to encode collection item: {e}"),
|
||||
}
|
||||
}
|
||||
|
@ -63,12 +61,10 @@ where
|
|||
{
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
use CollectionEncodeError::*;
|
||||
|
||||
match *self {
|
||||
Length(ref e) => Some(e),
|
||||
Self::BadLength(ref e) => Some(e),
|
||||
|
||||
Item(ref e) => Some(e),
|
||||
Self::BadItem(ref e) => Some(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,4 +79,3 @@ where
|
|||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +1,25 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::Decode;
|
||||
use crate::decode::Decode;
|
||||
|
||||
use core::convert::Infallible;
|
||||
use core::error::Error;
|
||||
|
@ -42,7 +42,7 @@ pub enum EnumDecodeError<D: Decode, F> {
|
|||
},
|
||||
|
||||
/// A field could not be encoded.
|
||||
Field(F),
|
||||
BadField(F),
|
||||
}
|
||||
|
||||
impl<D, F> Display for EnumDecodeError<D, F>
|
||||
|
@ -52,16 +52,14 @@ where
|
|||
{
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
use EnumDecodeError::*;
|
||||
|
||||
match *self {
|
||||
InvalidDiscriminant(ref e)
|
||||
Self::InvalidDiscriminant(ref e)
|
||||
=> write!(f, "discriminant could not be decoded: {e}"),
|
||||
|
||||
UnassignedDiscriminant { ref value }
|
||||
Self::UnassignedDiscriminant { ref value }
|
||||
=> write!(f, "`{value}` is not an assigned discriminant for the given enumeration"),
|
||||
|
||||
Field(ref e)
|
||||
Self::BadField(ref e)
|
||||
=> write!(f, "variant could not be decoded: {e}"),
|
||||
}
|
||||
}
|
||||
|
@ -74,12 +72,10 @@ where
|
|||
{
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
use EnumDecodeError::*;
|
||||
|
||||
match *self {
|
||||
InvalidDiscriminant(ref e) => Some(e),
|
||||
Self::InvalidDiscriminant(ref e) => Some(e),
|
||||
|
||||
Field(ref e) => Some(e),
|
||||
Self::BadField(ref e) => Some(e),
|
||||
|
||||
_ => None,
|
||||
}
|
|
@ -1,25 +1,25 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::Encode;
|
||||
use crate::encode::Encode;
|
||||
|
||||
use core::convert::Infallible;
|
||||
use core::error::Error;
|
||||
|
@ -30,10 +30,10 @@ use core::fmt::{self, Debug, Display, Formatter};
|
|||
#[must_use]
|
||||
pub enum EnumEncodeError<D: Encode, F> {
|
||||
/// The discriminant could not be encoded.
|
||||
Discriminant(D::Error),
|
||||
BadDiscriminant(D::Error),
|
||||
|
||||
/// A field could not be encoded.
|
||||
Field(F),
|
||||
BadField(F),
|
||||
}
|
||||
|
||||
impl<D, F> Display for EnumEncodeError<D, F>
|
||||
|
@ -43,13 +43,11 @@ where
|
|||
{
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
use EnumEncodeError::*;
|
||||
|
||||
match *self {
|
||||
Discriminant(ref e)
|
||||
Self::BadDiscriminant(ref e)
|
||||
=> write!(f, "discriminant could not be encoded: {e}"),
|
||||
|
||||
Field(ref e)
|
||||
Self::BadField(ref e)
|
||||
=> write!(f, "field could not be encoded: {e}"),
|
||||
}
|
||||
}
|
||||
|
@ -62,12 +60,10 @@ where
|
|||
{
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
use EnumEncodeError::*;
|
||||
|
||||
match *self {
|
||||
Discriminant(ref e) => Some(e),
|
||||
Self::BadDiscriminant(ref e) => Some(e),
|
||||
|
||||
Field(ref e) => Some(e),
|
||||
Self::BadField(ref e) => Some(e),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +1,39 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Decode, PrimitiveDiscriminant};
|
||||
use crate::PrimitiveDiscriminant;
|
||||
use crate::decode::Decode;
|
||||
use crate::error::{
|
||||
BoolDecodeError,
|
||||
CollectionDecodeError,
|
||||
CStringDecodeError,
|
||||
EnumDecodeError,
|
||||
ItemDecodeError,
|
||||
NonZeroDecodeError,
|
||||
SizeError,
|
||||
LengthError,
|
||||
Utf8Error,
|
||||
SystemTimeDecodeError,
|
||||
};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::error::CStringDecodeError;
|
||||
|
||||
use core::convert::Infallible;
|
||||
use core::error::Error;
|
||||
use core::fmt::{self, Display, Formatter};
|
||||
|
@ -48,9 +50,6 @@ pub enum GenericDecodeError {
|
|||
/// A string contained a non-UTF-8 sequence.
|
||||
BadString(Utf8Error),
|
||||
|
||||
/// A boolean was neither `false` nor `true`.
|
||||
InvalidBool(BoolDecodeError),
|
||||
|
||||
/// A C-like string contained a null byte.
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc, doc(cfg(feature = "std")))]
|
||||
|
@ -60,7 +59,7 @@ pub enum GenericDecodeError {
|
|||
NullInteger(NonZeroDecodeError),
|
||||
|
||||
/// A statically-sized buffer was too small.
|
||||
SmallBuffer(SizeError),
|
||||
SmallBuffer(LengthError),
|
||||
|
||||
/// An unassigned discriminant value was encountered.
|
||||
///
|
||||
|
@ -79,29 +78,24 @@ pub enum GenericDecodeError {
|
|||
impl Display for GenericDecodeError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
use GenericDecodeError::*;
|
||||
|
||||
match *self {
|
||||
BadString(ref e)
|
||||
Self::BadString(ref e)
|
||||
=> write!(f, "{e}"),
|
||||
|
||||
InvalidBool(ref e)
|
||||
Self::NullString(ref e)
|
||||
=> write!(f, "{e}"),
|
||||
|
||||
NullString(ref e)
|
||||
Self::NullInteger(ref e)
|
||||
=> write!(f, "{e}"),
|
||||
|
||||
NullInteger(ref e)
|
||||
Self::SmallBuffer(ref e)
|
||||
=> write!(f, "{e}"),
|
||||
|
||||
SmallBuffer(ref e)
|
||||
=> write!(f, "{e}"),
|
||||
|
||||
UnassignedDiscriminant { value }
|
||||
Self::UnassignedDiscriminant { value }
|
||||
=> write!(f, "discriminant value `{value:#X} has not been assigned"),
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
NarrowSystemTime(ref e)
|
||||
Self::NarrowSystemTime(ref e)
|
||||
=> write!(f, "{e}"),
|
||||
}
|
||||
}
|
||||
|
@ -110,35 +104,24 @@ impl Display for GenericDecodeError {
|
|||
impl Error for GenericDecodeError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
use GenericDecodeError::*;
|
||||
|
||||
match *self {
|
||||
BadString(ref e) => Some(e),
|
||||
|
||||
InvalidBool(ref e) => Some(e),
|
||||
Self::BadString(ref e) => Some(e),
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
NullString(ref e) => Some(e),
|
||||
Self::NullString(ref e) => Some(e),
|
||||
|
||||
NullInteger(ref e) => Some(e),
|
||||
Self::NullInteger(ref e) => Some(e),
|
||||
|
||||
SmallBuffer(ref e) => Some(e),
|
||||
Self::SmallBuffer(ref e) => Some(e),
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
NarrowSystemTime(ref e) => Some(e),
|
||||
Self::NarrowSystemTime(ref e) => Some(e),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BoolDecodeError> for GenericDecodeError {
|
||||
#[inline(always)]
|
||||
fn from(value: BoolDecodeError) -> Self {
|
||||
Self::InvalidBool(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<L, I> From<CollectionDecodeError<L, I>> for GenericDecodeError
|
||||
where
|
||||
L: Into<Self>,
|
||||
|
@ -146,16 +129,25 @@ where
|
|||
{
|
||||
#[inline(always)]
|
||||
fn from(value: CollectionDecodeError<L, I>) -> Self {
|
||||
use CollectionDecodeError::*;
|
||||
use CollectionDecodeError as Error;
|
||||
|
||||
match value {
|
||||
Length(e) => e.into(),
|
||||
Error::BadLength(e) => e.into(),
|
||||
|
||||
Item(e) => e.into(),
|
||||
Error::BadItem(e) => e.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl From<CStringDecodeError> for GenericDecodeError {
|
||||
#[inline(always)]
|
||||
fn from(value: CStringDecodeError) -> Self {
|
||||
Self::NullString(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D, F> From<EnumDecodeError<D, F>> for GenericDecodeError
|
||||
where
|
||||
D: Decode<Error: Into<Self>> + PrimitiveDiscriminant,
|
||||
|
@ -163,14 +155,14 @@ where
|
|||
{
|
||||
#[inline(always)]
|
||||
fn from(value: EnumDecodeError<D, F>) -> Self {
|
||||
use EnumDecodeError::*;
|
||||
use EnumDecodeError as Error;
|
||||
|
||||
match value {
|
||||
InvalidDiscriminant(e) => e.into(),
|
||||
Error::InvalidDiscriminant(e) => e.into(),
|
||||
|
||||
UnassignedDiscriminant { value } => Self::UnassignedDiscriminant { value: value.to_u128() },
|
||||
Error::UnassignedDiscriminant { value } => Self::UnassignedDiscriminant { value: value.to_u128() },
|
||||
|
||||
Field(e) => e.into(),
|
||||
Error::BadField(e) => e.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,6 +170,8 @@ where
|
|||
impl From<Infallible> for GenericDecodeError {
|
||||
#[inline(always)]
|
||||
fn from(_value: Infallible) -> Self {
|
||||
// SAFETY: `Infallible` objects can never be con-
|
||||
// structed
|
||||
unsafe { unreachable_unchecked() }
|
||||
}
|
||||
}
|
||||
|
@ -189,15 +183,6 @@ impl<I, E: Into<Self>> From<ItemDecodeError<I, E>> for GenericDecodeError {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc, doc(cfg(feature = "std")))]
|
||||
impl From<CStringDecodeError> for GenericDecodeError {
|
||||
#[inline(always)]
|
||||
fn from(value: CStringDecodeError) -> Self {
|
||||
Self::NullString(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NonZeroDecodeError> for GenericDecodeError {
|
||||
#[inline(always)]
|
||||
fn from(value: NonZeroDecodeError) -> Self {
|
||||
|
@ -205,9 +190,9 @@ impl From<NonZeroDecodeError> for GenericDecodeError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<SizeError> for GenericDecodeError {
|
||||
impl From<LengthError> for GenericDecodeError {
|
||||
#[inline(always)]
|
||||
fn from(value: SizeError) -> Self {
|
||||
fn from(value: LengthError) -> Self {
|
||||
Self::SmallBuffer(value)
|
||||
}
|
||||
}
|
|
@ -1,25 +1,25 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::Encode;
|
||||
use crate::encode::Encode;
|
||||
use crate::error::{
|
||||
CollectionEncodeError,
|
||||
EnumEncodeError,
|
||||
|
@ -36,7 +36,7 @@ use core::hint::unreachable_unchecked;
|
|||
|
||||
/// A decoding failed.
|
||||
///
|
||||
/// The intended use of this type is by [derived](derive@crate::Encode) implementations of [`Encode`](crate::Encode).
|
||||
/// The intended use of this type is by [derived](derive@crate::encode::Encode) implementations of [`Encode`](crate::encode::Encode).
|
||||
/// Manual implementors are recommended to use a custom or less generic type for the sake of efficiency.
|
||||
#[derive(Debug)]
|
||||
#[must_use]
|
||||
|
@ -55,31 +55,29 @@ pub enum GenericEncodeError {
|
|||
impl Display for GenericEncodeError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
use GenericEncodeError::*;
|
||||
match *self {
|
||||
Self::BadBorrow(ref e)
|
||||
=> write!(f, "{e}"),
|
||||
|
||||
let e: &dyn Display = match *self {
|
||||
BadBorrow(ref e) => e,
|
||||
Self::LargeIsize(ref e)
|
||||
=> write!(f, "{e}"),
|
||||
|
||||
LargeIsize(ref e) => e,
|
||||
Self::LargeUsize(ref e)
|
||||
=> write!(f, "{e}"),
|
||||
|
||||
LargeUsize(ref e) => e,
|
||||
};
|
||||
|
||||
e.fmt(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for GenericEncodeError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
use GenericEncodeError::*;
|
||||
|
||||
match *self {
|
||||
BadBorrow(ref e) => Some(e),
|
||||
Self::BadBorrow(ref e) => Some(e),
|
||||
|
||||
LargeIsize(ref e) => Some(e),
|
||||
Self::LargeIsize(ref e) => Some(e),
|
||||
|
||||
LargeUsize(ref e) => Some(e),
|
||||
Self::LargeUsize(ref e) => Some(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,12 +96,12 @@ where
|
|||
{
|
||||
#[inline(always)]
|
||||
fn from(value: CollectionEncodeError<L, I>) -> Self {
|
||||
use CollectionEncodeError::*;
|
||||
use CollectionEncodeError as Error;
|
||||
|
||||
match value {
|
||||
Length(e) => e.into(),
|
||||
Error::BadLength(e) => e.into(),
|
||||
|
||||
Item(e) => e.into(),
|
||||
Error::BadItem(e) => e.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,12 +113,12 @@ where
|
|||
{
|
||||
#[inline(always)]
|
||||
fn from(value: EnumEncodeError<D, F>) -> Self {
|
||||
use EnumEncodeError::*;
|
||||
use EnumEncodeError as Error;
|
||||
|
||||
match value {
|
||||
Discriminant(e) => e.into(),
|
||||
Error::BadDiscriminant(e) => e.into(),
|
||||
|
||||
Field(e) => e.into(),
|
||||
Error::BadField(e) => e.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,6 +126,8 @@ where
|
|||
impl From<Infallible> for GenericEncodeError {
|
||||
#[inline(always)]
|
||||
fn from(_value: Infallible) -> Self {
|
||||
// SAFETY: `Infallible` objects can never be con-
|
||||
// structed
|
||||
unsafe { unreachable_unchecked() }
|
||||
}
|
||||
}
|
54
oct/src/error/input_error.rs
Normal file
54
oct/src/error/input_error.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of oct.
|
||||
//
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::error::Error;
|
||||
use core::fmt::{self, Display, Formatter};
|
||||
|
||||
/// An input-related error.
|
||||
///
|
||||
/// This structure is mainly returned by the [`read`](crate::decode::Input::read) and [`read_into`](crate::decode::Input::read_into) methods in [`decode::Input`](crate::decode::Input).
|
||||
#[derive(Debug)]
|
||||
#[must_use]
|
||||
pub struct InputError {
|
||||
/// The total capacity of the output stream.
|
||||
pub capacity: usize,
|
||||
|
||||
/// The cursor position of the requested read.
|
||||
pub position: usize,
|
||||
|
||||
/// The requested amount of octets.
|
||||
pub count: usize,
|
||||
}
|
||||
|
||||
impl Display for InputError {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"cannot read ({}) bytes at ({}) from input stream with capacity of ({})",
|
||||
self.count,
|
||||
self.position,
|
||||
self.capacity,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for InputError { }
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::error::Error;
|
||||
|
@ -35,7 +35,13 @@ pub struct IsizeEncodeError(
|
|||
impl Display for IsizeEncodeError {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "signed size value ({}) cannot be serialised: must be in the range ({}) to ({})", self.0, i16::MIN, i16::MAX)
|
||||
write!(
|
||||
f,
|
||||
"signed size value ({}) cannot be serialised: must be in the range ({}) to ({})",
|
||||
self.0,
|
||||
i16::MIN,
|
||||
i16::MAX,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::convert::Infallible;
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::convert::Infallible;
|
|
@ -1,49 +1,50 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::error::Error;
|
||||
use core::fmt::{self, Display, Formatter};
|
||||
|
||||
/// A fixed-size buffer was too small.
|
||||
/// A collection buffer was too small to contain all of its elements.
|
||||
///
|
||||
/// Some data types use a statically-sized buffer whilst still allowing for partial usage of this buffer (e.g. [`SizedSlice`](crate::SizedSlice)).
|
||||
/// These types should return this error in cases where their size limit has exceeded.
|
||||
///
|
||||
/// Taking `SizedSlice` as an example, it encodes its actual length before encoding each of its elements.
|
||||
/// It is allowed for any smaller-sized `SizedSlice` instance to decode a larger-sized encoding **if** the actual length still fits.
|
||||
/// If not, then this error type is used to denote the error state.
|
||||
/// Taking [`SizedSlice`](crate::SizedSlice) as an example, it encodes its actual length before encoding its elements.
|
||||
/// It is allowed for any smaller-sized `SizedSlice` instance to decode a larger-sized encoding **if** the actual length is still within bounds.
|
||||
/// Otherwise, this error type is used to denote the error state.
|
||||
#[derive(Debug)]
|
||||
#[must_use]
|
||||
pub struct SizeError {
|
||||
pub struct LengthError {
|
||||
/// The total capacity of the buffer.
|
||||
pub cap: usize,
|
||||
pub capacity: usize,
|
||||
|
||||
/// The required amount of elements.
|
||||
pub len: usize,
|
||||
}
|
||||
|
||||
impl Display for SizeError {
|
||||
impl Display for LengthError {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "collection of size ({}) cannot hold ({}) elements", self.cap, self.len)
|
||||
write!(f, "collection of size ({}) cannot hold ({}) elements", self.capacity, self.len)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for SizeError { }
|
||||
impl Error for LengthError { }
|
|
@ -1,45 +1,46 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! Error variants.
|
||||
//!
|
||||
//! This module defines the error types used by Librum.
|
||||
//! This module defines the error types used by oct.
|
||||
//! All of these types define (at least conditionally) the [`Error`](core::error::Error) trait.
|
||||
|
||||
use crate::use_mod;
|
||||
|
||||
use_mod!(pub bool_decode_error);
|
||||
use_mod!(pub char_decode_error);
|
||||
use_mod!(pub collection_decode_error);
|
||||
use_mod!(pub collection_encode_error);
|
||||
use_mod!(pub enum_encode_error);
|
||||
use_mod!(pub enum_decode_error);
|
||||
use_mod!(pub enum_encode_error);
|
||||
use_mod!(pub generic_decode_error);
|
||||
use_mod!(pub generic_encode_error);
|
||||
use_mod!(pub input_error);
|
||||
use_mod!(pub isize_encode_error);
|
||||
use_mod!(pub item_decode_error);
|
||||
use_mod!(pub item_encode_error);
|
||||
use_mod!(pub length_error);
|
||||
use_mod!(pub non_zero_decode_error);
|
||||
use_mod!(pub output_error);
|
||||
use_mod!(pub ref_cell_encode_error);
|
||||
use_mod!(pub size_error);
|
||||
use_mod!(pub string_error);
|
||||
use_mod!(pub usize_encode_error);
|
||||
use_mod!(pub utf16_error);
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::error::Error;
|
||||
|
@ -24,7 +24,7 @@ use core::fmt::{self, Display, Formatter};
|
|||
|
||||
/// A non-zero integer could not be decoded.
|
||||
///
|
||||
/// The implementations of [`Decode`](crate::Decode) for <code>[NonZero](core::num::NonZero)<T></code> yield this error type if decoding `T` yields zero.
|
||||
/// The implementations of [`Decode`](crate::decode::Decode) for <code>[NonZero](core::num::NonZero)<T></code> yield this error type if decoding `T` yields zero.
|
||||
#[derive(Debug)]
|
||||
pub struct NonZeroDecodeError;
|
||||
|
54
oct/src/error/output_error.rs
Normal file
54
oct/src/error/output_error.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of oct.
|
||||
//
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::error::Error;
|
||||
use core::fmt::{self, Display, Formatter};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[must_use]
|
||||
/// An output-related error
|
||||
///
|
||||
/// This structure is mainly returned by the [`write`](crate::encode::Output::write) method in [`encode::Output`](crate::encode::Output).
|
||||
pub struct OutputError {
|
||||
/// The total capacity of the output stream.
|
||||
pub capacity: usize,
|
||||
|
||||
/// The cursor position of the requested write.
|
||||
pub position: usize,
|
||||
|
||||
/// The requested amount of octets.
|
||||
pub count: usize,
|
||||
}
|
||||
|
||||
impl Display for OutputError {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"cannot write ({}) bytes at ({}) to output stream with capacity of ({})",
|
||||
self.count,
|
||||
self.position,
|
||||
self.capacity,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for OutputError { }
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::cell::BorrowError;
|
||||
|
@ -25,28 +25,26 @@ use core::fmt::{self, Display, Formatter};
|
|||
|
||||
/// A reference cell could not be encoded.
|
||||
///
|
||||
/// The implementation of <code><[RefCell](core::cell::RefCell)<T> as [Encode](crate::Encode)>::[encode](crate::Encode::encode)</code> will first attempt to call <code>RefCell::[borrow](core::cell::RefCell::borrow)</code>.
|
||||
/// If this call fails, then the returned error is again returned as a [`Borrow`](Self::Borrow) instance.
|
||||
/// If the following call to <code>T::encode</code> fails instead, then the error returned from that call is passed on as a [`Value`](Self::Value) instance.
|
||||
/// The implementation of <code><[RefCell](core::cell::RefCell)<T> as [Encode](crate::encode::Encode)>::[encode](crate::encode::Encode::encode)</code> will first attempt to call <code>RefCell::[borrow](core::cell::RefCell::borrow)</code>.
|
||||
/// If this call fails, then the returned error is again returned as a [`BadBorrow`](Self::BadBorrow) instance.
|
||||
/// If the following call to <code>T::encode</code> fails instead, then the error returned from that call is passed on as a [`BadValue`](Self::BadValue) instance.
|
||||
#[derive(Debug)]
|
||||
#[must_use]
|
||||
pub enum RefCellEncodeError<E> {
|
||||
/// The reference cell could not be borrowed.
|
||||
Borrow(BorrowError),
|
||||
BadBorrow(BorrowError),
|
||||
|
||||
/// The contained value could not be encoded.
|
||||
Value(E),
|
||||
BadValue(E),
|
||||
}
|
||||
|
||||
impl<E: Display> Display for RefCellEncodeError<E> {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
use RefCellEncodeError::*;
|
||||
|
||||
let e: &dyn Display = match *self {
|
||||
Borrow(ref e) => e,
|
||||
Self::BadBorrow(ref e) => e,
|
||||
|
||||
Value(ref e) => e,
|
||||
Self::BadValue(ref e) => e,
|
||||
};
|
||||
|
||||
write!(f, "unable to encode reference cell: {e}")
|
||||
|
@ -56,12 +54,10 @@ impl<E: Display> Display for RefCellEncodeError<E> {
|
|||
impl<E: Error + 'static> Error for RefCellEncodeError<E> {
|
||||
#[inline(always)]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
use RefCellEncodeError::*;
|
||||
|
||||
match *self {
|
||||
Borrow(ref e) => Some(e),
|
||||
Self::BadBorrow(ref e) => Some(e),
|
||||
|
||||
Value(ref e) => Some(e)
|
||||
Self::BadValue(ref e) => Some(e)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +1,25 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::error::{SizeError, Utf16Error, Utf8Error};
|
||||
use crate::error::{LengthError, Utf16Error, Utf8Error};
|
||||
|
||||
use core::error::Error;
|
||||
use core::fmt::{self, Display, Formatter};
|
||||
|
@ -36,22 +36,20 @@ pub enum StringError {
|
|||
BadUtf8(Utf8Error),
|
||||
|
||||
/// A fixed-size buffer was too small.
|
||||
SmallBuffer(SizeError),
|
||||
SmallBuffer(LengthError),
|
||||
}
|
||||
|
||||
impl Display for StringError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
use StringError::*;
|
||||
|
||||
match *self {
|
||||
BadUtf16(ref e)
|
||||
Self::BadUtf16(ref e)
|
||||
=> write!(f, "bad utf-16: {e}"),
|
||||
|
||||
BadUtf8(ref e)
|
||||
Self::BadUtf8(ref e)
|
||||
=> write!(f, "bad utf-8: {e}"),
|
||||
|
||||
SmallBuffer(ref e)
|
||||
Self::SmallBuffer(ref e)
|
||||
=> write!(f, "buffer too small: {e}"),
|
||||
}
|
||||
}
|
||||
|
@ -60,14 +58,12 @@ impl Display for StringError {
|
|||
impl Error for StringError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
use StringError::*;
|
||||
|
||||
match *self {
|
||||
BadUtf16(ref e) => Some(e),
|
||||
Self::BadUtf16(ref e) => Some(e),
|
||||
|
||||
BadUtf8(ref e) => Some(e),
|
||||
Self::BadUtf8(ref e) => Some(e),
|
||||
|
||||
SmallBuffer(ref e) => Some(e),
|
||||
Self::SmallBuffer(ref e) => Some(e),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::error::Error;
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::error::Error;
|
||||
|
@ -35,7 +35,12 @@ pub struct UsizeEncodeError(
|
|||
impl Display for UsizeEncodeError {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "unsigned size value ({}) cannot be serialised: must be at most ({})", self.0, u16::MAX)
|
||||
write!(
|
||||
f,
|
||||
"unsigned size value ({}) cannot be serialised: must be at most ({})",
|
||||
self.0,
|
||||
u16::MAX,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::error::Error;
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use core::error::Error;
|
|
@ -1,29 +1,29 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#![doc(html_logo_url = "https://gitlab.com/bjoernager/librum/-/raw/master/doc-icon.svg")]
|
||||
#![doc(html_logo_url = "https://gitlab.com/bjoernager/oct/-/raw/master/doc-icon.svg")]
|
||||
|
||||
//! Librum is a Rust crate for cheaply serialising (encoding) and deserialising (decoding) data structures into binary streams
|
||||
//! oct is a Rust crate for cheaply serialising (encoding) and deserialising (decoding) data structures into binary streams
|
||||
//!
|
||||
//! What separates this crate from others such as [Bincode](https://crates.io/crates/bincode/) or [Postcard](https://crates.io/crates/postcard/) is that this crate is extensively optimised for *just* binary encodings (whilst the mentioned crates specifically use Serde and build on a more abstract data model).
|
||||
//! What separates this crate from others such as [Bincode](https://crates.io/crates/bincode/) or [Postcard](https://crates.io/crates/postcard/) is that this crate is extensively optimised for directly translating into binary encodings (whilst the mentioned crates specifically use Serde as a middle layer).
|
||||
//! The original goal of this project was specifically to guarantee size constraints for encodings on a per-type basis at compile-time.
|
||||
//! Therefore, this crate may be more suited for networking or other cases where many allocations are unwanted.
|
||||
//!
|
||||
|
@ -34,24 +34,25 @@
|
|||
//!
|
||||
//! # Performance
|
||||
//!
|
||||
//! As Librum is optimised exclusively for a single, binary format, it *may* outperform other libraries that are more generic in nature.
|
||||
//! As oct is optimised exclusively for a single, binary format, it *may* outperform other libraries that are more generic in nature.
|
||||
//!
|
||||
//! The `librum-benchmarks` binary compares multiple scenarios using Librum and other, similar crates.
|
||||
//! According to my runs on an AMD Ryzen 7 3700X with default settings, these benchmarks indicate that Librum usually outperforms the other tested crates -- as demonstrated in the following table:
|
||||
//! The `oct-benchmarks` binary compares multiple scenarios using oct and other, similar crates.
|
||||
//! According to my runs on an AMD Ryzen 7 3700X with default settings, these benchmarks indicate that oct usually outperforms the other tested crates -- as demonstrated in the following table:
|
||||
//!
|
||||
//! | Benchmark | [Bincode] | [Borsh] | Librum | [Postcard] |
|
||||
//! | Benchmark | [Bincode] | [Borsh] | oct | [Postcard] |
|
||||
//! | :--------------------------------- | --------: | ------: | ------: | ---------: |
|
||||
//! | `encode_u8` | 1.004 | 0.947 | 0.806 | 0.972 |
|
||||
//! | `encode_u32` | 1.130 | 1.084 | 0.749 | 2.793 |
|
||||
//! | `encode_u128` | 2.340 | 2.328 | 1.543 | 6.380 |
|
||||
//! | `encode_u8` | 0.968 | 0.857 | 0.733 | 0.979 |
|
||||
//! | `encode_u32` | 1.065 | 0.999 | 0.730 | 2.727 |
|
||||
//! | `encode_u128` | 2.168 | 2.173 | 1.510 | 6.246 |
|
||||
//! | `encode_struct_unit` | 0.000 | 0.000 | 0.000 | 0.000 |
|
||||
//! | `encode_struct_unnamed` | 1.218 | 1.160 | 0.838 | 2.392 |
|
||||
//! | `encode_struct_named` | 3.077 | 1.501 | 0.975 | 3.079 |
|
||||
//! | `encode_enum_unit` | 0.260 | 0.310 | 0.000 | 0.303 |
|
||||
//! | `decode_u8` | 1.116 | 1.106 | 1.110 | 1.102 |
|
||||
//! | `decode_non_zero_u8` | 1.228 | 1.236 | 1.269 | 1.263 |
|
||||
//! | **Total time** → | 11.373 | 9.672 | 7.291 | 18.284 |
|
||||
//! | **Total deviation (p.c.)** → | +56 | +33 | ±0 | +150 |
|
||||
//! | `encode_struct_unnamed` | 1.241 | 1.173 | 0.823 | 3.350 |
|
||||
//! | `encode_struct_named` | 3.079 | 1.507 | 0.973 | 3.082 |
|
||||
//! | `encode_enum_unit` | 0.246 | 0.297 | 0.000 | 0.295 |
|
||||
//! | `decode_u8` | 0.942 | 0.962 | 0.922 | 0.923 |
|
||||
//! | `decode_non_zero_u8` | 1.126 | 1.159 | 1.127 | 1.160 |
|
||||
//! | `decode_bool` | 1.040 | 1.099 | 1.055 | 1.177 |
|
||||
//! | **Total time** → | 11.873 | 10.225 | 7.873 | 18.939 |
|
||||
//! | **Total deviation (p.c.)** → | +51 | +30 | ±0 | +141 |
|
||||
//!
|
||||
//! [Bincode]: https://crates.io/crates/bincode/
|
||||
//! [Borsh]: https://crates.io/crates/borsh/
|
||||
|
@ -59,9 +60,9 @@
|
|||
//!
|
||||
//! All quantities are measured in seconds unless otherwise noted.
|
||||
//!
|
||||
//! Currently, Librum's weakest point seems to be decoding.
|
||||
//! Currently, oct's weakest point seems to be decoding.
|
||||
//! Please note that I myself find large (relatively speaking) inconsistencies between runs in these last two benchmarks.
|
||||
//! Do feel free to conduct your own tests of Librum.
|
||||
//! Do feel free to conduct your own tests of oct.
|
||||
//!
|
||||
//! # Data model
|
||||
//!
|
||||
|
@ -78,16 +79,18 @@
|
|||
//!
|
||||
//! # Usage
|
||||
//!
|
||||
//! This crate revolves around the [`Encode`] and [`Decode`] traits, both of which handle conversions to and from byte streams.
|
||||
//! This crate revolves around the [`Encode`](encode::Encode) and [`Decode`](decode::Decode) traits, both of which handle conversions to and from byte streams.
|
||||
//!
|
||||
//! Many standard types come implemented with Librum, including most primitives as well as some standard library types such as [`Option`] and [`Result`].
|
||||
//! Many standard types come implemented with oct, including most primitives as well as some standard library types such as [`Option`] and [`Result`].
|
||||
//! Some [features](#feature-flags) enable an extended set of implementations.
|
||||
//!
|
||||
//! It is recommended in most cases to simply derive these two traits for user-defined types (although this is only supported with enumerations and structures -- not untagged unions).
|
||||
//! Here, each field is *chained* according to declaration order:
|
||||
//!
|
||||
//! ```
|
||||
//! use librum::{Buf, Decode, Encode};
|
||||
//! use oct::Slot;
|
||||
//! use oct::decode::Decode;
|
||||
//! use oct::encode::Encode;
|
||||
//!
|
||||
//! #[derive(Debug, Decode, Encode, PartialEq)]
|
||||
//! struct Ints {
|
||||
|
@ -106,7 +109,7 @@
|
|||
//! value4: 0x1E_1D_1C_1B_1A_19_18_17_16_15_14_13_12_11_10_0F,
|
||||
//! };
|
||||
//!
|
||||
//! let mut buf = Buf::with_capacity(0x100);
|
||||
//! let mut buf = Slot::with_capacity(0x100);
|
||||
//!
|
||||
//! buf.write(VALUE).unwrap();
|
||||
//!
|
||||
|
@ -127,20 +130,20 @@
|
|||
//!
|
||||
//! ## Buffer types
|
||||
//!
|
||||
//! The [`Encode`] and [`Decode`] traits both rely on streams for carrying the manipulated bytes.
|
||||
//! The [`Encode`](encode::Encode) and [`Decode`](decode::Decode) traits both rely on streams for carrying the manipulated bytes.
|
||||
//!
|
||||
//! These streams are separated into two type: [*O-streams*](OStream) (output streams) and [*i-streams*](IStream) (input streams).
|
||||
//! The [`Buf`] type can be used to handle these streams.
|
||||
//! These streams are separated into two type: [*output streams*](encode::Output) and [*input streams*](decode::Input).
|
||||
//! The [`Slot`] type can be used to handle these streams.
|
||||
//!
|
||||
//! ## Encoding
|
||||
//!
|
||||
//! To encode an object directly using the `Encode` trait, simply allocate a buffer for the encoding and wrap it in an [`OStream`] object:
|
||||
//! To encode an object directly using the `Encode` trait, simply allocate a buffer for the encoding and wrap it in an `Output` object:
|
||||
//!
|
||||
//! ```
|
||||
//! use librum::{Encode, OStream, SizedEncode};
|
||||
//! use oct::encode::{Encode, Output, SizedEncode};
|
||||
//!
|
||||
//! let mut buf = [0x00; char::MAX_ENCODED_SIZE];
|
||||
//! let mut stream = OStream::new(&mut buf);
|
||||
//! let mut stream = Output::new(&mut buf);
|
||||
//!
|
||||
//! 'Ж'.encode(&mut stream).unwrap();
|
||||
//!
|
||||
|
@ -150,10 +153,10 @@
|
|||
//! Streams can also be used to chain multiple objects together:
|
||||
//!
|
||||
//! ```
|
||||
//! use librum::{Encode, OStream, SizedEncode};
|
||||
//! use oct::encode::{Encode, Output, SizedEncode};
|
||||
//!
|
||||
//! let mut buf = [0x0; char::MAX_ENCODED_SIZE * 0x5];
|
||||
//! let mut stream = OStream::new(&mut buf);
|
||||
//! let mut stream = Output::new(&mut buf);
|
||||
//!
|
||||
//! // Note: For serialising multiple characters, the
|
||||
//! // `String` and `SizedStr` types are usually
|
||||
|
@ -172,31 +175,31 @@
|
|||
//! ]);
|
||||
//! ```
|
||||
//!
|
||||
//! If the encoded type additionally implements [`SizedEncode`], then the maximum size of any encoding is guaranteed with the [`MAX_ENCODED_SIZE`](SizedEncode::MAX_ENCODED_SIZE) constant.
|
||||
//! If the encoded type additionally implements [`SizedEncode`](encode::SizedEncode), then the maximum size of any encoding is guaranteed with the [`MAX_ENCODED_SIZE`](encode::SizedEncode::MAX_ENCODED_SIZE) constant.
|
||||
//!
|
||||
//! ## Decoding
|
||||
//!
|
||||
//! Decoding works with a similar syntax to encoding.
|
||||
//! To decode a byte array, simply call the [`decode`](Decode::decode) method with an [`IStream`] object:
|
||||
//! To decode a byte array, simply call the [`decode`](decode::Decode::decode) method with an [`Input`](decode::Input) object:
|
||||
//!
|
||||
//! ```
|
||||
//! use librum::{Decode, IStream};
|
||||
//! use oct::decode::{Decode, Input};
|
||||
//!
|
||||
//! let data = [0x54, 0x45];
|
||||
//! let mut stream = IStream::new(&data);
|
||||
//! let mut stream = Input::new(&data);
|
||||
//!
|
||||
//! assert_eq!(u16::decode(&mut stream).unwrap(), 0x4554);
|
||||
//!
|
||||
//! // Data can theoretically be reinterpretred:
|
||||
//!
|
||||
//! stream = IStream::new(&data);
|
||||
//! stream = Input::new(&data);
|
||||
//!
|
||||
//! assert_eq!(u8::decode(&mut stream).unwrap(), 0x54);
|
||||
//! assert_eq!(u8::decode(&mut stream).unwrap(), 0x45);
|
||||
//!
|
||||
//! // Including as tuples:
|
||||
//!
|
||||
//! stream = IStream::new(&data);
|
||||
//! stream = Input::new(&data);
|
||||
//!
|
||||
//! assert_eq!(<(u8, u8)>::decode(&mut stream).unwrap(), (0x54, 0x45));
|
||||
//! ```
|
||||
|
@ -206,7 +209,9 @@
|
|||
//! A UDP server/client for geographic data:
|
||||
//!
|
||||
//! ```
|
||||
//! use librum::{Buf, Encode, Decode, SizedEncode};
|
||||
//! use oct::Slot;
|
||||
//! use oct::decode::Decode;
|
||||
//! use oct::encode::{Encode, SizedEncode};
|
||||
//! use std::io;
|
||||
//! use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
||||
//! use std::thread::spawn;
|
||||
|
@ -242,8 +247,8 @@
|
|||
//! struct Party {
|
||||
//! pub socket: UdpSocket,
|
||||
//!
|
||||
//! pub request_buf: Buf::<Request>,
|
||||
//! pub response_buf: Buf::<Response>,
|
||||
//! pub request_buf: Slot::<Request>,
|
||||
//! pub response_buf: Slot::<Response>,
|
||||
//! }
|
||||
//!
|
||||
//! impl Party {
|
||||
|
@ -253,8 +258,8 @@
|
|||
//! let this = Self {
|
||||
//! socket,
|
||||
//!
|
||||
//! request_buf: Buf::new(),
|
||||
//! response_buf: Buf::new(),
|
||||
//! request_buf: Slot::new(),
|
||||
//! response_buf: Slot::new(),
|
||||
//! };
|
||||
//!
|
||||
//! Ok(this)
|
||||
|
@ -307,28 +312,28 @@
|
|||
//!
|
||||
//! # Feature flags
|
||||
//!
|
||||
//! Librum defines the following features:
|
||||
//! oct defines the following features:
|
||||
//!
|
||||
//! * *`alloc`: Enables the [`Buf`] type and implementations for e.g. [`Box`](alloc::boxed::Box) and [`Arc`](alloc::sync::Arc)
|
||||
//! * *`proc-macro`: Pulls the procedural macros from the [`librum-macros`](https://crates.io/crates/librum-macros/) crate
|
||||
//! * *`alloc`: Enables the [`Slot`] type and implementations for e.g. [`Box`](alloc::boxed::Box) and [`Arc`](alloc::sync::Arc)
|
||||
//! * *`proc-macro`: Pulls the procedural macros from the [`oct-macros`](https://crates.io/crates/oct-macros/) crate
|
||||
//! * *`std`: Enables implementations for types such as [`Mutex`](std::sync::Mutex) and [`RwLock`](std::sync::RwLock)
|
||||
//!
|
||||
//! Features marked with * are enabled by default.
|
||||
//!
|
||||
//! # Documentation
|
||||
//!
|
||||
//! Librum has its documentation written in-source for use by `rustdoc`.
|
||||
//! See [Docs.rs](https://docs.rs/librum/latest/librum/) for an on-line, rendered instance.
|
||||
//! oct has its documentation written in-source for use by `rustdoc`.
|
||||
//! See [Docs.rs](https://docs.rs/oct/latest/oct/) for an on-line, rendered instance.
|
||||
//!
|
||||
//! Currently, these docs make use of some unstable features for the sake of readability.
|
||||
//! The nightly toolchain is therefore required when rendering them.
|
||||
//!
|
||||
//! # Contribution
|
||||
//!
|
||||
//! Librum does not accept source code contributions at the moment.
|
||||
//! oct does not accept source code contributions at the moment.
|
||||
//! This is a personal choice by the maintainer and may be undone in the future.
|
||||
//!
|
||||
//! Do however feel free to open up an issue on [GitLab](https://gitlab.com/bjoernager/librum/issues/) or (preferably) [GitHub](https://github.com/bjoernager/librum/issues/) if you feel the need to express any concerns over the project.
|
||||
//! Do however feel free to open up an issue on [GitLab](https://gitlab.com/bjoernager/oct/issues/) or (preferably) [GitHub](https://github.com/bjoernager/oct/issues/) if you feel the need to express any concerns over the project.
|
||||
//!
|
||||
//! # Copyright & Licence
|
||||
//!
|
||||
|
@ -344,13 +349,13 @@
|
|||
|
||||
#![no_std]
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(doc, allow(internal_features))]
|
||||
|
||||
#![cfg_attr(doc, feature(doc_cfg, rustdoc_internals))]
|
||||
|
||||
#![deny(missing_docs)]
|
||||
|
||||
// For use in macros:
|
||||
extern crate self as librum;
|
||||
extern crate self as oct;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
|
@ -358,116 +363,6 @@ extern crate alloc;
|
|||
#[cfg(feature = "std")]
|
||||
extern crate std;
|
||||
|
||||
/// Implements [`Decode`] for the provided type.
|
||||
///
|
||||
/// This macro assumes the same format used by the equivalent [`Encode`](derive@Encode) macro.
|
||||
#[cfg(feature = "proc-macro")]
|
||||
#[cfg_attr(doc, doc(cfg(feature = "proc-macro")))]
|
||||
#[doc(inline)]
|
||||
pub use librum_macros::Decode;
|
||||
|
||||
/// Implements [`Encode`] for the provided type.
|
||||
///
|
||||
/// This derive macro assumes that all fields implement <code>Encode<[Error]: [Into]<[GenericEncodeError]>></code>.
|
||||
/// If this is **not** the case, then the trait should be implemented manually instead.
|
||||
///
|
||||
/// [Error]: Encode::Error
|
||||
/// [GenericEncodeError]: crate::error::GenericEncodeError
|
||||
///
|
||||
/// Do also consider deriving [`SizedEncode`](derive@SizedEncode) -- if possible.
|
||||
///
|
||||
/// # Structs
|
||||
///
|
||||
/// For structures, each element is chained in **order of declaration.**
|
||||
/// If the structure is a unit structure (i.e. it has *no* fields) then it is encoded equivalently to the [unit] type.
|
||||
///
|
||||
/// For example, the following struct will encode its field `foo` followed by `bar`:
|
||||
///
|
||||
/// ```
|
||||
/// use librum::Encode;
|
||||
///
|
||||
/// #[derive(Encode)]
|
||||
/// struct FooBar {
|
||||
/// pub foo: char,
|
||||
/// pub bar: char,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This should be kept in mind when changing the structure's declarationm as doing so may invalidate previous encodings.
|
||||
///
|
||||
/// The [`Error`](Encode::Error) type will in all cases just be `GenericEncodeError`.
|
||||
///
|
||||
/// # Enums
|
||||
///
|
||||
/// Enumerations encode like structures except that each variant additionally encodes a unique discriminant.
|
||||
///
|
||||
/// By default, each discriminant is assigned from the range 0 to infinite, to the extend allowed by the [`isize`] type and its encoding (as which **all** discriminants are encoded).
|
||||
/// A custom discriminant may be set instead by assigning the variant an integer constant.
|
||||
/// Unspecified discriminants then increment the previous variant's discriminant:
|
||||
///
|
||||
/// ```
|
||||
/// use librum::{Buf, Encode};
|
||||
///
|
||||
/// #[derive(Encode)]
|
||||
/// enum Num {
|
||||
/// Two = 0x2,
|
||||
///
|
||||
/// Three,
|
||||
///
|
||||
/// Zero = 0x0,
|
||||
///
|
||||
/// One,
|
||||
/// }
|
||||
///
|
||||
/// let mut buf = Buf::with_capacity(size_of::<i16>());
|
||||
///
|
||||
/// buf.write(Num::Zero).unwrap();
|
||||
/// assert_eq!(buf, [0x00, 0x00].as_slice());
|
||||
///
|
||||
/// buf.write(Num::One).unwrap();
|
||||
/// assert_eq!(buf, [0x01, 0x00].as_slice());
|
||||
///
|
||||
/// buf.write(Num::Two).unwrap();
|
||||
/// assert_eq!(buf, [0x02, 0x00].as_slice());
|
||||
///
|
||||
/// buf.write(Num::Three).unwrap();
|
||||
/// assert_eq!(buf, [0x03, 0x00].as_slice());
|
||||
/// ```
|
||||
///
|
||||
/// Variants with fields are encoded exactly like structures.
|
||||
/// That is, each field is chained in order of declaration.
|
||||
///
|
||||
/// For error handling, the `Error` type is defined as:
|
||||
///
|
||||
/// <code>[EnumEncodeError]<<Repr as Encode>::Error, GenericEncodeError></code>,
|
||||
///
|
||||
/// [EnumEncodeError]: crate::error::GenericEncodeError
|
||||
///
|
||||
/// wherein `Repr` is the enumeration's representation.
|
||||
///
|
||||
/// # Unions
|
||||
///
|
||||
/// Unions cannot derive `Encode` due to the uncertainty of their contents.
|
||||
/// The trait should therefore be implemented manually for such types.
|
||||
#[cfg(feature = "proc-macro")]
|
||||
#[cfg_attr(doc, doc(cfg(feature = "proc-macro")))]
|
||||
#[doc(inline)]
|
||||
pub use librum_macros::Encode;
|
||||
|
||||
/// Implements [`Encode`](trait@Encode) using the default implementation.
|
||||
///
|
||||
/// For simple structures, the value of [`MAX_ENCODED_SIZE`](SizedEncode::MAX_ENCODED_SIZE) is set as the combined value of <code>T*n*::MAX_ENCODED_SIZE</code> wherein <code>T*n*</code> is the type of each field.
|
||||
///
|
||||
/// For enumerations, the value is set such that each variant is treated like a structure (with the discriminant as an extra field) and where the variant that produces the largest `MAX_ENCODED_SIZE` is chosen.
|
||||
///
|
||||
/// As untagged unions cannot derive `Encode`, `SizedEncode` also cannot be derived for them.
|
||||
///
|
||||
/// Do remember that deriving this trait is only recommended
|
||||
#[cfg(feature = "proc-macro")]
|
||||
#[cfg_attr(doc, doc(cfg(feature = "proc-macro")))]
|
||||
#[doc(inline)]
|
||||
pub use librum_macros::SizedEncode;
|
||||
|
||||
macro_rules! use_mod {
|
||||
($vis:vis $name:ident$(,)?) => {
|
||||
mod $name;
|
||||
|
@ -476,18 +371,14 @@ macro_rules! use_mod {
|
|||
}
|
||||
pub(crate) use use_mod;
|
||||
|
||||
use_mod!(pub decode);
|
||||
use_mod!(pub decode_borrowed);
|
||||
use_mod!(pub encode);
|
||||
use_mod!(pub i_stream);
|
||||
use_mod!(pub o_stream);
|
||||
use_mod!(pub primitive_discriminant);
|
||||
use_mod!(pub sized_encode);
|
||||
use_mod!(pub sized_iter);
|
||||
use_mod!(pub sized_slice);
|
||||
use_mod!(pub sized_str);
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use_mod!(pub buf);
|
||||
use_mod!(pub slot);
|
||||
|
||||
pub mod decode;
|
||||
pub mod encode;
|
||||
pub mod error;
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
mod sealed {
|
||||
|
@ -46,16 +46,15 @@ pub trait PrimitiveDiscriminant: Copy + SealedPrimitiveDiscriminant + Sized { }
|
|||
|
||||
macro_rules! impl_primitive_discriminant {
|
||||
($ty:ty) => {
|
||||
impl ::librum::SealedPrimitiveDiscriminant for $ty {
|
||||
impl ::oct::SealedPrimitiveDiscriminant for $ty {
|
||||
#[allow(clippy::cast_lossless)]
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
fn to_u128(self) -> u128 {
|
||||
self as u128
|
||||
}
|
||||
}
|
||||
|
||||
impl ::librum::PrimitiveDiscriminant for $ty { }
|
||||
impl ::oct::PrimitiveDiscriminant for $ty { }
|
||||
};
|
||||
}
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -89,7 +89,7 @@ impl<T, const N: usize> AsRef<[T]> for SizedIter<T, N> {
|
|||
impl<T: Clone, const N: usize> Clone for SizedIter<T, N> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
let mut buf: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||
let mut buf = [const { MaybeUninit::<T>::uninit() };N];
|
||||
let Self { pos, len, .. } = *self;
|
||||
|
||||
let start = pos;
|
|
@ -1,25 +1,25 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use librum::{SizedSlice, SizedStr};
|
||||
use oct::{SizedSlice, SizedStr};
|
||||
|
||||
#[test]
|
||||
fn test_sized_iter_clone() {
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::SizedSlice;
|
||||
|
@ -93,4 +93,4 @@ impl<T: PartialOrd, const N: usize> PartialOrd<Vec<T>> for SizedSlice<T, N> {
|
|||
fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
|
||||
self.as_slice().partial_cmp(other.as_slice())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,50 +1,44 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
Decode,
|
||||
DecodeBorrowed,
|
||||
Encode,
|
||||
IStream,
|
||||
OStream,
|
||||
SizedEncode,
|
||||
SizedSlice
|
||||
};
|
||||
use crate::error::{CollectionDecodeError, ItemDecodeError, SizeError};
|
||||
use crate::SizedSlice;
|
||||
use crate::decode::{Decode, DecodeBorrowed, Input};
|
||||
use crate::encode::{Encode, Output, SizedEncode};
|
||||
use crate::error::{CollectionDecodeError, ItemDecodeError, LengthError};
|
||||
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
impl<T: Decode, const N: usize> Decode for SizedSlice<T, N> {
|
||||
type Error = CollectionDecodeError<SizeError, ItemDecodeError<usize, T::Error>>;
|
||||
type Error = CollectionDecodeError<LengthError, ItemDecodeError<usize, T::Error>>;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let len = Decode::decode(stream).unwrap();
|
||||
if len > N { return Err(CollectionDecodeError::Length(SizeError { cap: N, len })) };
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let len = Decode::decode(input).unwrap();
|
||||
if len > N { return Err(CollectionDecodeError::BadLength(LengthError { capacity: N, len })) };
|
||||
|
||||
let mut buf: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||
let mut buf = [const { MaybeUninit::<T>::uninit() };N];
|
||||
|
||||
for (i, slot) in buf.iter_mut().enumerate() {
|
||||
let v = Decode::decode(stream)
|
||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }))?;
|
||||
let v = Decode::decode(input)
|
||||
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
|
||||
|
||||
slot.write(v);
|
||||
}
|
||||
|
@ -59,11 +53,11 @@ impl<T: Encode, const N: usize> Encode for SizedSlice<T, N> {
|
|||
type Error = <[T] as Encode>::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.as_slice().encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.as_slice().encode(output)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SizedEncode, const N: usize> SizedEncode for SizedSlice<T, N> {
|
||||
const MAX_ENCODED_SIZE: usize = T::MAX_ENCODED_SIZE * N;
|
||||
}
|
||||
}
|
|
@ -1,26 +1,26 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::SizedSlice;
|
||||
use crate::error::SizeError;
|
||||
use crate::error::LengthError;
|
||||
|
||||
use core::borrow::{Borrow, BorrowMut};
|
||||
use core::mem::MaybeUninit;
|
||||
|
@ -203,7 +203,7 @@ impl<T, const N: usize> From<[T; N]> for SizedSlice<T, N> {
|
|||
}
|
||||
|
||||
impl<T: Clone, const N: usize> TryFrom<&[T]> for SizedSlice<T, N> {
|
||||
type Error = SizeError;
|
||||
type Error = LengthError;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_from(value: &[T]) -> Result<Self, Self::Error> {
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{SizedIter, SizedSlice};
|
||||
|
@ -29,7 +29,7 @@ impl<T, const N: usize> FromIterator<T> for SizedSlice<T, N> {
|
|||
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
|
||||
let mut iter = iter.into_iter();
|
||||
|
||||
let mut buf: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||
let mut buf = [const { MaybeUninit::<T>::uninit() };N];
|
||||
let mut len = 0x0;
|
||||
|
||||
for item in &mut buf {
|
|
@ -1,28 +1,28 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::error::SizeError;
|
||||
use crate::error::LengthError;
|
||||
|
||||
use core::fmt::{self, Debug, Formatter};
|
||||
use core::hash::{Hash, Hasher};
|
||||
|
@ -31,6 +31,9 @@ use core::ops::{Index, IndexMut};
|
|||
use core::ptr::{copy_nonoverlapping, null, null_mut};
|
||||
use core::slice::SliceIndex;
|
||||
|
||||
// Encode/decode facilities:
|
||||
mod code;
|
||||
|
||||
// Conversion facilities:
|
||||
mod conv;
|
||||
|
||||
|
@ -40,12 +43,9 @@ mod cmp;
|
|||
// Iterator facilities:
|
||||
mod iter;
|
||||
|
||||
// Encode/decode facilities:
|
||||
mod serdes;
|
||||
|
||||
/// Stack-allocated vector with maximum length.
|
||||
///
|
||||
/// This type is intended as a [sized-encodable](crate::SizedEncode) alternative to [`Vec`](alloc::vec::Vec) -- for cases where [arrays](array) may not be wanted -- as well as a [decodable](crate::Decode) alternative to normal [slices](slice).
|
||||
/// This type is intended as a [sized-encodable](crate::encode::SizedEncode) alternative to [`Vec`](alloc::vec::Vec) -- for cases where [arrays](array) may not be wanted -- as well as a [decodable](crate::decode::Decode) alternative to normal [slices](slice).
|
||||
///
|
||||
/// Note that this type is immutable in the sense that it does **not** define methods like `push` and `pop`, unlike `Vec`.
|
||||
///
|
||||
|
@ -56,7 +56,7 @@ mod serdes;
|
|||
/// All instances of this type with the same `T` and `N` also have the exact same layout:
|
||||
///
|
||||
/// ```
|
||||
/// use librum::SizedSlice;
|
||||
/// use oct::SizedSlice;
|
||||
///
|
||||
/// let vec0 = SizedSlice::<u8, 0x4>::try_from([0x3].as_slice()).unwrap();
|
||||
/// let vec1 = SizedSlice::<u8, 0x4>::try_from([0x3, 0x2].as_slice()).unwrap();
|
||||
|
@ -201,11 +201,11 @@ impl<T, const N: usize> SizedSlice<T, N> {
|
|||
impl<T: Clone, const N: usize> SizedSlice<T, N> {
|
||||
/// Constructs an empty, fixed-size vector.
|
||||
#[inline]
|
||||
pub fn new(data: &[T]) -> Result<Self, SizeError> {
|
||||
let mut buf: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||
pub fn new(data: &[T]) -> Result<Self, LengthError> {
|
||||
let mut buf = [const { MaybeUninit::<T>::uninit() };N];
|
||||
|
||||
let len = data.len();
|
||||
if len > N { return Err(SizeError { cap: N, len }) };
|
||||
if len > N { return Err(LengthError { capacity: N, len }) };
|
||||
|
||||
for (item, value) in buf.iter_mut().zip(data.iter()) {
|
||||
item.write(value.clone());
|
|
@ -1,25 +1,25 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use librum::SizedSlice;
|
||||
use oct::SizedSlice;
|
||||
use std::vec::Vec;
|
||||
|
||||
#[test]
|
|
@ -1,22 +1,22 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::SizedStr;
|
|
@ -1,49 +1,43 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
Decode,
|
||||
DecodeBorrowed,
|
||||
Encode,
|
||||
IStream,
|
||||
OStream,
|
||||
SizedEncode,
|
||||
SizedStr
|
||||
};
|
||||
use crate::error::{CollectionDecodeError, SizeError, StringError, Utf8Error};
|
||||
use crate::SizedStr;
|
||||
use crate::decode::{Decode, DecodeBorrowed, Input};
|
||||
use crate::encode::{Encode, Output, SizedEncode};
|
||||
use crate::error::{CollectionDecodeError, LengthError, StringError, Utf8Error};
|
||||
|
||||
impl<const N: usize> Decode for SizedStr<N> {
|
||||
type Error = CollectionDecodeError<SizeError, Utf8Error>;
|
||||
type Error = CollectionDecodeError<LengthError, Utf8Error>;
|
||||
|
||||
#[inline]
|
||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
||||
let len = Decode::decode(stream).unwrap();
|
||||
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||
let len = Decode::decode(input).unwrap();
|
||||
|
||||
let data = stream.read(len);
|
||||
let data = input.read(len).unwrap();
|
||||
|
||||
Self::from_utf8(data)
|
||||
.map_err(|e| match e {
|
||||
StringError::BadUtf8(e) => CollectionDecodeError::Item(e),
|
||||
StringError::BadUtf8(e) => CollectionDecodeError::BadItem(e),
|
||||
|
||||
StringError::SmallBuffer(e) => CollectionDecodeError::Length(e),
|
||||
StringError::SmallBuffer(e) => CollectionDecodeError::BadLength(e),
|
||||
|
||||
_ => unreachable!(),
|
||||
})
|
||||
|
@ -56,8 +50,8 @@ impl<const N: usize> Encode for SizedStr<N> {
|
|||
type Error = <str as Encode>::Error;
|
||||
|
||||
#[inline(always)]
|
||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
||||
self.as_str().encode(stream)
|
||||
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||
self.as_str().encode(output)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +1,26 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{SizedSlice, SizedStr};
|
||||
use crate::error::{SizeError, StringError, Utf8Error};
|
||||
use crate::error::{LengthError, StringError, Utf8Error};
|
||||
|
||||
use core::borrow::{Borrow, BorrowMut};
|
||||
use core::mem::{ManuallyDrop, MaybeUninit};
|
||||
|
@ -54,15 +54,15 @@ impl<const N: usize> SizedStr<N> {
|
|||
///
|
||||
/// Each byte value must be a valid UTF-8 code point.
|
||||
#[inline]
|
||||
pub const fn from_utf8(data: &[u8]) -> Result<Self, StringError> {
|
||||
if data.len() > N { return Err(StringError::SmallBuffer(SizeError { cap: N, len: data.len() })) };
|
||||
pub const fn from_utf8(s: &[u8]) -> Result<Self, StringError> {
|
||||
if s.len() > N { return Err(StringError::SmallBuffer(LengthError { capacity: N, len: s.len() })) };
|
||||
|
||||
let s = match str::from_utf8(data) {
|
||||
let s = match str::from_utf8(s) {
|
||||
Ok(s) => s,
|
||||
|
||||
Err(e) => {
|
||||
let i = e.valid_up_to();
|
||||
let c = data[i];
|
||||
let c = s[i];
|
||||
|
||||
return Err(StringError::BadUtf8(Utf8Error { value: c, index: i }));
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ impl<const N: usize> FromStr for SizedStr<N> {
|
|||
|
||||
#[inline]
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if s.len() > N { return Err(StringError::SmallBuffer(SizeError { cap: N, len: s.len() })) };
|
||||
if s.len() > N { return Err(StringError::SmallBuffer(LengthError { capacity: N, len: s.len() })) };
|
||||
|
||||
let this = unsafe { Self::from_utf8_unchecked(s.as_bytes()) };
|
||||
Ok(this)
|
|
@ -1,29 +1,29 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::SizedSlice;
|
||||
use crate::error::{SizeError, StringError};
|
||||
use crate::error::{LengthError, StringError};
|
||||
|
||||
use core::fmt::{self, Debug, Display, Formatter};
|
||||
use core::hash::{Hash, Hasher};
|
||||
|
@ -34,12 +34,12 @@ use core::str::{Chars, CharIndices};
|
|||
// Comparison facilities:
|
||||
mod cmp;
|
||||
|
||||
// Encode/decode facilities:
|
||||
mod code;
|
||||
|
||||
// Conversion facilities:
|
||||
mod conv;
|
||||
|
||||
// Encode/decode facilities:
|
||||
mod serdes;
|
||||
|
||||
/// Stack-allocated string with maximum length.
|
||||
///
|
||||
/// This is in contrast to [`String`](alloc::string::String) -- which has no size limit in practice -- and [`prim@str`], which is unsized.
|
||||
|
@ -56,7 +56,7 @@ mod serdes;
|
|||
/// Therefore, the following four strings have -- despite their different contents -- the same total size.
|
||||
///
|
||||
/// ```
|
||||
/// use librum::SizedStr;
|
||||
/// use oct::SizedStr;
|
||||
/// use std::str::FromStr;
|
||||
///
|
||||
/// let str0 = SizedStr::<0x40>::default(); // Empty string.
|
||||
|
@ -86,7 +86,7 @@ impl<const N: usize> SizedStr<N> {
|
|||
/// If the internal buffer cannot contain the entirety of `s`, then an error is returned.
|
||||
#[inline(always)]
|
||||
pub const fn new(s: &str) -> Result<Self, StringError> {
|
||||
if s.len() > N { return Err(StringError::SmallBuffer(SizeError { cap: N, len: s.len() })) };
|
||||
if s.len() > N { return Err(StringError::SmallBuffer(LengthError { capacity: N, len: s.len() })) };
|
||||
|
||||
let this = unsafe { Self::from_utf8_unchecked(s.as_bytes()) };
|
||||
Ok(this)
|
||||
|
@ -201,4 +201,3 @@ impl<I: SliceIndex<str>, const N: usize> IndexMut<I> for SizedStr<N> {
|
|||
self.get_mut(index).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +1,26 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use librum::SizedStr;
|
||||
use librum::error::{StringError, Utf8Error};
|
||||
use oct::SizedStr;
|
||||
use oct::error::{StringError, Utf8Error};
|
||||
use std::cmp::Ordering;
|
||||
|
||||
#[test]
|
|
@ -1,34 +1,29 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::{
|
||||
Decode,
|
||||
Encode,
|
||||
IStream,
|
||||
OStream,
|
||||
SizedEncode,
|
||||
};
|
||||
use crate::decode::{Decode, Input};
|
||||
use crate::encode::{Encode, Output, SizedEncode};
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use alloc::vec;
|
||||
|
@ -39,7 +34,7 @@ use core::ops::{Deref, DerefMut, Index, IndexMut};
|
|||
use core::ptr::{self, copy_nonoverlapping};
|
||||
use core::slice::{self, SliceIndex};
|
||||
|
||||
/// Typed encode buffer.
|
||||
/// Typed encode/decode slot.
|
||||
///
|
||||
/// This structure is intended as a lightweight byte buffer suitable for encoding a single, predefined type.
|
||||
///
|
||||
|
@ -48,16 +43,11 @@ use core::slice::{self, SliceIndex};
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Create a buffer for holding a `Request` enumeration:
|
||||
/// Create a slot for holding a `Request` enumeration:
|
||||
///
|
||||
/// ```
|
||||
/// use librum::{
|
||||
/// Buf,
|
||||
/// Encode,
|
||||
/// OStream,
|
||||
/// SizedEncode,
|
||||
/// SizedStr,
|
||||
/// };
|
||||
/// use oct::{SizedStr, Slot};
|
||||
/// use oct::encode::{Encode, Output, SizedEncode};
|
||||
///
|
||||
/// #[derive(Debug, Encode, SizedEncode)]
|
||||
/// enum Request {
|
||||
|
@ -68,15 +58,15 @@ use core::slice::{self, SliceIndex};
|
|||
/// SendMessage { message: SizedStr<0x80> },
|
||||
/// }
|
||||
///
|
||||
/// let mut buf = Buf::new();
|
||||
/// let mut buf = Slot::new();
|
||||
///
|
||||
/// buf.write(Request::Join { username: "epsiloneridani".parse().unwrap() }).unwrap();
|
||||
/// assert_eq!(buf.as_slice(), b"\0\0\x0E\0epsiloneridani");
|
||||
///
|
||||
/// // Do something with the buffer...
|
||||
/// // Do something with the slot...
|
||||
/// ```
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
pub struct Buf<T> {
|
||||
pub struct Slot<T> {
|
||||
buf: Box<[u8]>,
|
||||
len: usize,
|
||||
|
||||
|
@ -84,8 +74,8 @@ pub struct Buf<T> {
|
|||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T> Buf<T> {
|
||||
/// Allocates a new buffer suitable for encoding.
|
||||
impl<T> Slot<T> {
|
||||
/// Allocates a new slot suitable for encodings.
|
||||
///
|
||||
/// The given capacity should be large enough to hold any expected encoding of `T`.
|
||||
///
|
||||
|
@ -103,7 +93,7 @@ impl<T> Buf<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Constructs a new buffer from raw parts.
|
||||
/// Constructs a new slot from raw parts.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
|
@ -126,7 +116,7 @@ impl<T> Buf<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Gets a pointer to the first byte of the buffer.
|
||||
/// Gets a pointer to the first byte of the slot's buffer.
|
||||
///
|
||||
/// Note that the all reads to bytes up to the amount specified by [`capacity`](Self::capacity) are valid (i.e. the bytes are always initialised).
|
||||
#[inline(always)]
|
||||
|
@ -135,7 +125,7 @@ impl<T> Buf<T> {
|
|||
self.buf.as_ptr()
|
||||
}
|
||||
|
||||
/// Gets a mutable pointer to the first byte of the buffer.
|
||||
/// Gets a mutable pointer to the first byte of the slot's buffer.
|
||||
///
|
||||
/// Note that the all reads to bytes up to the amount specified by [`capacity`](Self::capacity) are valid (i.e. the bytes are always initialised).
|
||||
#[inline(always)]
|
||||
|
@ -144,10 +134,10 @@ impl<T> Buf<T> {
|
|||
self.buf.as_mut_ptr()
|
||||
}
|
||||
|
||||
/// Gets a slice of the buffer.
|
||||
/// Gets a slice of the slot's buffer.
|
||||
///
|
||||
/// The returned slice will only include the used part of the buffer (as specified by [`len`](Self::len)).
|
||||
/// This is in contrast to [`as_mut_slice`](Self::as_mut_slice), which references the entire buffer.
|
||||
/// The returned slice will only include the used part of the slot (as specified by [`len`](Self::len)).
|
||||
/// This is in contrast to [`as_mut_slice`](Self::as_mut_slice), which references the entire slot buffer.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
|
@ -155,9 +145,9 @@ impl<T> Buf<T> {
|
|||
unsafe { slice::from_raw_parts(self.as_ptr(), self.len()) }
|
||||
}
|
||||
|
||||
/// Gets a mutable slice of the buffer.
|
||||
/// Gets a mutable slice of the slot's buffer.
|
||||
///
|
||||
/// Contrary to [`as_slice`](Self::as_slice), this method returns a slice of the **entire** buffer (as specified by [`capacity`](Self::capacity)).
|
||||
/// Contrary to [`as_slice`](Self::as_slice), this method returns a slice of the slot's **entire** buffer (as specified by [`capacity`](Self::capacity)).
|
||||
///
|
||||
/// Users should call [`set_len`](Self::set_len) if writing has modified the portion of used bytes.
|
||||
#[inline(always)]
|
||||
|
@ -167,7 +157,7 @@ impl<T> Buf<T> {
|
|||
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.capacity()) }
|
||||
}
|
||||
|
||||
/// Copies data from another slice.
|
||||
/// Copies data from a slice.
|
||||
///
|
||||
/// The length of `self` is updated to reflect the new data.
|
||||
///
|
||||
|
@ -176,7 +166,7 @@ impl<T> Buf<T> {
|
|||
pub fn copy_from_slice(&mut self, data: &[u8]) {
|
||||
let len = data.len();
|
||||
|
||||
assert!(len <= self.capacity(), "buffer cannot contain source slice");
|
||||
assert!(len <= self.capacity(), "slot cannot contain source slice");
|
||||
|
||||
unsafe {
|
||||
let src = data.as_ptr();
|
||||
|
@ -192,44 +182,44 @@ impl<T> Buf<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sets the length of the buffer.
|
||||
/// Sets the length of the slot.
|
||||
///
|
||||
/// The provided size is checked before being written (i.e. `len` may not be greater than [`len`](Self::len)).
|
||||
/// For the same operation *without* these checks, see [`set_len_unchecked`](Self::set_len_unchecked).
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// The provided size must not be greater than the buffer's capacity.
|
||||
/// The provided size must not be greater than the slot's capacity.
|
||||
/// If this is the case, however, this method will panic.
|
||||
#[inline(always)]
|
||||
pub fn set_len(&mut self, len: usize) {
|
||||
assert!(len <= self.capacity(), "cannot extend buffer beyond capacity");
|
||||
assert!(len <= self.capacity(), "cannot extend slot beyond capacity");
|
||||
|
||||
// SAFETY: The length has been tested.
|
||||
unsafe { self.set_len_unchecked(len) }
|
||||
}
|
||||
|
||||
/// Sets the length of the buffer without checks.
|
||||
/// Sets the length of the slot without checks.
|
||||
///
|
||||
/// The provided size is **not** tested before being written.
|
||||
/// For the same operation *with* checks, see [`set_len`](Self::set_len).
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The value of `len` may never be greater than the capacity of the buffer.
|
||||
/// The value of `len` may never be greater than the capacity of the slot.
|
||||
/// Exceeding this will yield undefined behaviour.
|
||||
#[inline(always)]
|
||||
pub unsafe fn set_len_unchecked(&mut self, len: usize) {
|
||||
debug_assert!(len <= self.capacity(), "cannot extend buffer beyond capacity");
|
||||
debug_assert!(len <= self.capacity(), "cannot extend slot beyond capacity");
|
||||
|
||||
// SAFETY: The length has been guaranteed by the
|
||||
// caller.
|
||||
self.len = len;
|
||||
}
|
||||
|
||||
/// Retrieves the capacity of the buffer.
|
||||
/// Retrieves the capacity of the slot.
|
||||
///
|
||||
/// If the buffer was constructed using [`new`](Self::new), this value is exactly equal to that of [`MAX_ENCODED_SIZE`](SizedEncode::MAX_ENCODED_SIZE).
|
||||
/// If the slot was constructed using [`new`](Self::new), this value is exactly equal to [`MAX_ENCODED_SIZE`](SizedEncode::MAX_ENCODED_SIZE).
|
||||
/// In other cases, however, this may either be greater or less than this value.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
|
@ -237,18 +227,18 @@ impl<T> Buf<T> {
|
|||
self.buf.len()
|
||||
}
|
||||
|
||||
/// Retrieves the length of the buffer.
|
||||
/// Retrieves the length of the slot.
|
||||
///
|
||||
/// This value specifically denotes the length of the previous encoding (if any).
|
||||
///
|
||||
/// For retrieving the capacity of the buffer, see [`capacity`](Self::capacity).
|
||||
/// For retrieving the capacity of the slot, see [`capacity`](Self::capacity).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
|
||||
/// Tests if the buffer is empty.
|
||||
/// Tests if the slot is empty.
|
||||
///
|
||||
/// This is strictly equivalent to testing if [`len`](Self::len) is null.
|
||||
#[inline(always)]
|
||||
|
@ -257,7 +247,7 @@ impl<T> Buf<T> {
|
|||
self.len() == 0x0
|
||||
}
|
||||
|
||||
/// Tests if the buffer is full.
|
||||
/// Tests if the slot is full.
|
||||
///
|
||||
/// This is strictly equivalent to testing if [`len`](Self::len) is equal to [`capacity`](Self::capacity).
|
||||
#[inline(always)]
|
||||
|
@ -268,8 +258,8 @@ impl<T> Buf<T> {
|
|||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T: Encode> Buf<T> {
|
||||
/// Encodes an object into the buffer.
|
||||
impl<T: Encode> Slot<T> {
|
||||
/// Encodes an object into the slot.
|
||||
///
|
||||
/// The object is encoded as by being passed to <code><T as [Encode]>::[encode](Encode::encode)</code>.
|
||||
///
|
||||
|
@ -278,11 +268,11 @@ impl<T: Encode> Buf<T> {
|
|||
/// Any error that occurs during encoding is passed on and returned from this method.
|
||||
#[inline]
|
||||
pub fn write<U: Borrow<T>>(&mut self, value: U) -> Result<(), T::Error> {
|
||||
let mut stream = OStream::new(&mut self.buf);
|
||||
let mut stream = Output::new(&mut self.buf);
|
||||
|
||||
value.borrow().encode(&mut stream)?;
|
||||
|
||||
let len = stream.close();
|
||||
let len = stream.position();
|
||||
self.set_len(len);
|
||||
|
||||
Ok(())
|
||||
|
@ -290,8 +280,8 @@ impl<T: Encode> Buf<T> {
|
|||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T: Decode> Buf<T> {
|
||||
/// Decodes an object from the buffer.
|
||||
impl<T: Decode> Slot<T> {
|
||||
/// Decodes an object from the slot.
|
||||
///
|
||||
/// This is done as by passing the contained bytes to <code><T as [Decode]>::[decode](Decode::decode)</code>.
|
||||
///
|
||||
|
@ -303,10 +293,10 @@ impl<T: Decode> Buf<T> {
|
|||
/// Any error that occurs during decoding is passed on and returned from this method.
|
||||
#[inline]
|
||||
pub fn read(&self) -> Result<T, T::Error> {
|
||||
// We should only pass the used part of the buffer
|
||||
// to `deserialise`.
|
||||
// We should only pass the used part of the slot to
|
||||
// `decode`.
|
||||
|
||||
let mut stream = IStream::new(&self.buf);
|
||||
let mut stream = Input::new(&self.buf);
|
||||
|
||||
let value = Decode::decode(&mut stream)?;
|
||||
Ok(value)
|
||||
|
@ -314,10 +304,10 @@ impl<T: Decode> Buf<T> {
|
|||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T: SizedEncode> Buf<T> {
|
||||
/// Allocates a new buffer suitable for encoding.
|
||||
impl<T: SizedEncode> Slot<T> {
|
||||
/// Allocates a new slot suitable for encoding.
|
||||
///
|
||||
/// The capacity of the buffer is set so that any encoding of `T` may be stored (as specified by [`MAX_ENCODED_SIZE`](SizedEncode::MAX_ENCODED_SIZE)).
|
||||
/// The capacity of the slot is set so that any encoding of `T` may be stored (as specified by [`MAX_ENCODED_SIZE`](SizedEncode::MAX_ENCODED_SIZE)).
|
||||
/// See also the [`with_capacity`](Self::with_capacity) constructor.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
|
@ -328,7 +318,7 @@ impl<T: SizedEncode> Buf<T> {
|
|||
|
||||
/// See also [`as_mut_slice`](Self::as_mut_slice).
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T> AsMut<[u8]> for Buf<T> {
|
||||
impl<T> AsMut<[u8]> for Slot<T> {
|
||||
#[inline(always)]
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
self.as_mut_slice()
|
||||
|
@ -337,7 +327,7 @@ impl<T> AsMut<[u8]> for Buf<T> {
|
|||
|
||||
/// See also [`as_slice`](Self::as_slice).
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T> AsRef<[u8]> for Buf<T> {
|
||||
impl<T> AsRef<[u8]> for Slot<T> {
|
||||
#[inline(always)]
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_slice()
|
||||
|
@ -346,7 +336,7 @@ impl<T> AsRef<[u8]> for Buf<T> {
|
|||
|
||||
/// See also [`as_slice`](Self::as_slice).
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T> Borrow<[u8]> for Buf<T> {
|
||||
impl<T> Borrow<[u8]> for Slot<T> {
|
||||
#[inline(always)]
|
||||
fn borrow(&self) -> &[u8] {
|
||||
self.as_slice()
|
||||
|
@ -355,7 +345,7 @@ impl<T> Borrow<[u8]> for Buf<T> {
|
|||
|
||||
/// See also [`as_mut_slice`](Self::as_mut_slice).
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T> BorrowMut<[u8]> for Buf<T> {
|
||||
impl<T> BorrowMut<[u8]> for Slot<T> {
|
||||
#[inline(always)]
|
||||
fn borrow_mut(&mut self) -> &mut [u8] {
|
||||
self.as_mut_slice()
|
||||
|
@ -363,13 +353,13 @@ impl<T> BorrowMut<[u8]> for Buf<T> {
|
|||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T> Debug for Buf<T> {
|
||||
impl<T> Debug for Slot<T> {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{:?}", self.as_slice()) }
|
||||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T: SizedEncode> Default for Buf<T> {
|
||||
impl<T: SizedEncode> Default for Slot<T> {
|
||||
#[inline(always)]
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
|
@ -377,7 +367,7 @@ impl<T: SizedEncode> Default for Buf<T> {
|
|||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T> Deref for Buf<T> {
|
||||
impl<T> Deref for Slot<T> {
|
||||
type Target = [u8];
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -387,7 +377,7 @@ impl<T> Deref for Buf<T> {
|
|||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T> DerefMut for Buf<T> {
|
||||
impl<T> DerefMut for Slot<T> {
|
||||
#[inline(always)]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.as_mut_slice()
|
||||
|
@ -395,7 +385,7 @@ impl<T> DerefMut for Buf<T> {
|
|||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T, I: SliceIndex<[u8]>> Index<I> for Buf<T> {
|
||||
impl<T, I: SliceIndex<[u8]>> Index<I> for Slot<T> {
|
||||
type Output = I::Output;
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -405,7 +395,7 @@ impl<T, I: SliceIndex<[u8]>> Index<I> for Buf<T> {
|
|||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T, I: SliceIndex<[u8]>> IndexMut<I> for Buf<T> {
|
||||
impl<T, I: SliceIndex<[u8]>> IndexMut<I> for Slot<T> {
|
||||
#[inline(always)]
|
||||
fn index_mut(&mut self, index: I) -> &mut Self::Output {
|
||||
self.get_mut(index).unwrap()
|
||||
|
@ -413,7 +403,7 @@ impl<T, I: SliceIndex<[u8]>> IndexMut<I> for Buf<T> {
|
|||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T> PartialEq<[u8]> for Buf<T> {
|
||||
impl<T> PartialEq<[u8]> for Slot<T> {
|
||||
#[inline(always)]
|
||||
fn eq(&self, other: &[u8]) -> bool {
|
||||
self.as_slice() == other
|
||||
|
@ -421,7 +411,7 @@ impl<T> PartialEq<[u8]> for Buf<T> {
|
|||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T> PartialEq<&[u8]> for Buf<T> {
|
||||
impl<T> PartialEq<&[u8]> for Slot<T> {
|
||||
#[inline(always)]
|
||||
fn eq(&self, other: &&[u8]) -> bool {
|
||||
self.as_slice() == *other
|
||||
|
@ -429,7 +419,7 @@ impl<T> PartialEq<&[u8]> for Buf<T> {
|
|||
}
|
||||
|
||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||
impl<T> PartialEq<&mut [u8]> for Buf<T> {
|
||||
impl<T> PartialEq<&mut [u8]> for Slot<T> {
|
||||
#[inline(always)]
|
||||
fn eq(&self, other: &&mut [u8]) -> bool {
|
||||
self.as_slice() == *other
|
|
@ -1,30 +1,30 @@
|
|||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||
//
|
||||
// This file is part of Librum.
|
||||
// This file is part of oct.
|
||||
//
|
||||
// Librum is free software: you can redistribute it
|
||||
// oct is free software: you can redistribute it
|
||||
// and/or modify it under the terms of the GNU
|
||||
// Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3
|
||||
// of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// Librum is distributed in the hope that it will
|
||||
// oct is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without
|
||||
// even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Less-
|
||||
// er General Public License along with Librum. If
|
||||
// er General Public License along with oct. If
|
||||
// not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use librum::Buf;
|
||||
use librum::error::CharDecodeError;
|
||||
use oct::Slot;
|
||||
use oct::error::CharDecodeError;
|
||||
|
||||
#[test]
|
||||
fn test_buf_write_read() {
|
||||
let mut buf = Buf::<char>::new();
|
||||
let mut buf = Slot::<char>::new();
|
||||
|
||||
macro_rules! test_read {
|
||||
($pattern:pat$(,)?) => {{
|
Loading…
Add table
Add a link
Reference in a new issue