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
|
# 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.
|
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
|
## 0.13.1
|
||||||
|
|
||||||
* Update readme
|
* Update readme
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["librum", "librum-benchmarks", "librum-macros"]
|
members = ["oct", "oct-benchmarks", "oct-macros"]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
authors = ["Gabriel Bjørnager Jensen"]
|
authors = ["Gabriel Bjørnager Jensen"]
|
||||||
description = "Binary (de)serialiser."
|
description = "Binary (de)serialiser."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
homepage = "https://achernar.dk/index.php?p=bzipper"
|
homepage = "https://docs.rs/oct/latest/oct/"
|
||||||
repository = "https://mandelbrot.dk/librum/"
|
repository = "https://mandelbrot.dk/oct/"
|
||||||
license = "LGPL-3.0-or-later"
|
license = "LGPL-3.0-or-later"
|
||||||
keywords = ["api", "encoding", "io", "network", "no-std"]
|
keywords = ["api", "encoding", "io", "network", "no-std"]
|
||||||
categories = ["encoding", "network-programming", "parsing"]
|
categories = ["encoding", "network-programming", "parsing"]
|
||||||
|
@ -35,6 +35,7 @@ empty_enum_variants_with_brackets = "warn"
|
||||||
empty_line_after_doc_comments = "warn"
|
empty_line_after_doc_comments = "warn"
|
||||||
empty_line_after_outer_attr = "warn"
|
empty_line_after_outer_attr = "warn"
|
||||||
empty_structs_with_brackets = "warn"
|
empty_structs_with_brackets = "warn"
|
||||||
|
enum_glob_use = "forbid"
|
||||||
enum_variant_names = "allow"
|
enum_variant_names = "allow"
|
||||||
equatable_if_let = "warn"
|
equatable_if_let = "warn"
|
||||||
excessive_precision = "allow"
|
excessive_precision = "allow"
|
||||||
|
@ -52,7 +53,6 @@ from_iter_instead_of_collect = "warn"
|
||||||
future_not_send = "deny"
|
future_not_send = "deny"
|
||||||
if_not_else = "warn"
|
if_not_else = "warn"
|
||||||
if_then_some_else_none = "warn"
|
if_then_some_else_none = "warn"
|
||||||
ignored_unit_patterns = "warn"
|
|
||||||
impl_trait_in_params = "warn"
|
impl_trait_in_params = "warn"
|
||||||
implicit_clone = "warn"
|
implicit_clone = "warn"
|
||||||
imprecise_flops = "deny"
|
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 directly translating into binary encodings (whilst the mentioned crates specifically use Serde as a middle layer).
|
||||||
|
|
||||||
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).
|
|
||||||
The original goal of this project was specifically to guarantee size constraints for encodings on a per-type basis at compile-time.
|
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.
|
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
|
## 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.
|
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 Librum usually outperforms the other tested crates – as demonstrated in the following table:
|
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_u8` | 0.968 | 0.857 | 0.733 | 0.979 |
|
||||||
| `encode_u32` | 1.130 | 1.084 | 0.749 | 2.793 |
|
| `encode_u32` | 1.065 | 0.999 | 0.730 | 2.727 |
|
||||||
| `encode_u128` | 2.340 | 2.328 | 1.543 | 6.380 |
|
| `encode_u128` | 2.168 | 2.173 | 1.510 | 6.246 |
|
||||||
| `encode_struct_unit` | 0.000 | 0.000 | 0.000 | 0.000 |
|
| `encode_struct_unit` | 0.000 | 0.000 | 0.000 | 0.000 |
|
||||||
| `encode_struct_unnamed` | 1.218 | 1.160 | 0.838 | 2.392 |
|
| `encode_struct_unnamed` | 1.241 | 1.173 | 0.823 | 3.350 |
|
||||||
| `encode_struct_named` | 3.077 | 1.501 | 0.975 | 3.079 |
|
| `encode_struct_named` | 3.079 | 1.507 | 0.973 | 3.082 |
|
||||||
| `encode_enum_unit` | 0.260 | 0.310 | 0.000 | 0.303 |
|
| `encode_enum_unit` | 0.246 | 0.297 | 0.000 | 0.295 |
|
||||||
| `decode_u8` | 1.116 | 1.106 | 1.110 | 1.102 |
|
| `decode_u8` | 0.942 | 0.962 | 0.922 | 0.923 |
|
||||||
| `decode_non_zero_u8` | 1.228 | 1.236 | 1.269 | 1.263 |
|
| `decode_non_zero_u8` | 1.126 | 1.159 | 1.127 | 1.160 |
|
||||||
| **Total time** → | 11.373 | 9.672 | 7.291 | 18.284 |
|
| `decode_bool` | 1.040 | 1.099 | 1.055 | 1.177 |
|
||||||
| **Total deviation (p.c.)** → | +56 | +33 | ±0 | +150 |
|
| **Total time** → | 11.873 | 10.225 | 7.873 | 18.939 |
|
||||||
|
| **Total deviation (p.c.)** → | +51 | +30 | ±0 | +141 |
|
||||||
|
|
||||||
[Bincode]: https://crates.io/crates/bincode/
|
[Bincode]: https://crates.io/crates/bincode/
|
||||||
[Borsh]: https://crates.io/crates/borsh/
|
[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.
|
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.
|
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
|
## 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.
|
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.
|
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).
|
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:
|
Here, each field is *chained* according to declaration order:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use librum::{Buf, Decode, Encode};
|
use oct::Slot;
|
||||||
|
use oct::decode::Decode;
|
||||||
|
use oct::encode::Encode;
|
||||||
|
|
||||||
#[derive(Debug, Decode, Encode, PartialEq)]
|
#[derive(Debug, Decode, Encode, PartialEq)]
|
||||||
struct Ints {
|
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,
|
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();
|
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.
|
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).
|
These streams are separated into two type: *output streams* and *input streams*.
|
||||||
The `Buf` type can be used to handle these streams.
|
The `Slot` type can be used to handle these streams.
|
||||||
|
|
||||||
### Encoding
|
### 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
|
```rust
|
||||||
use librum::{Encode, OStream, SizedEncode};
|
use oct::encode::{Encode, Output, SizedEncode};
|
||||||
|
|
||||||
let mut buf = [0x00; char::MAX_ENCODED_SIZE];
|
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();
|
'Ж'.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:
|
Streams can also be used to chain multiple objects together:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use librum::{Encode, OStream, SizedEncode};
|
use oct::encode::{Encode, Output, SizedEncode};
|
||||||
|
|
||||||
let mut buf = [0x0; char::MAX_ENCODED_SIZE * 0x5];
|
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
|
// Note: For serialising multiple characters, the
|
||||||
// `String` and `SizedStr` types are usually
|
// `String` and `SizedStr` types are usually
|
||||||
|
@ -156,26 +157,26 @@ If the encoded type additionally implements `SizedEncode`, then the maximum size
|
||||||
### Decoding
|
### Decoding
|
||||||
|
|
||||||
Decoding works with a similar syntax to encoding.
|
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
|
```rust
|
||||||
use librum::{Decode, IStream};
|
use oct::decode::{Decode, Input};
|
||||||
|
|
||||||
let data = [0x54, 0x45];
|
let data = [0x54, 0x45];
|
||||||
let mut stream = IStream::new(&data);
|
let mut stream = Input::new(&data);
|
||||||
|
|
||||||
assert_eq!(u16::decode(&mut stream).unwrap(), 0x4554);
|
assert_eq!(u16::decode(&mut stream).unwrap(), 0x4554);
|
||||||
|
|
||||||
// Data can theoretically be reinterpretred:
|
// 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(), 0x54);
|
||||||
assert_eq!(u8::decode(&mut stream).unwrap(), 0x45);
|
assert_eq!(u8::decode(&mut stream).unwrap(), 0x45);
|
||||||
|
|
||||||
// Including as tuples:
|
// Including as tuples:
|
||||||
|
|
||||||
stream = IStream::new(&data);
|
stream = Input::new(&data);
|
||||||
|
|
||||||
assert_eq!(<(u8, u8)>::decode(&mut stream).unwrap(), (0x54, 0x45));
|
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:
|
A UDP server/client for geographic data:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use librum::{Buf, Encode, Decode, SizedEncode};
|
use oct::Slot;
|
||||||
|
use oct::decode::Decode;
|
||||||
|
use oct::encode::{Encode, SizedEncode};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
||||||
use std::thread::spawn;
|
use std::thread::spawn;
|
||||||
|
@ -221,8 +224,8 @@ enum Response {
|
||||||
struct Party {
|
struct Party {
|
||||||
pub socket: UdpSocket,
|
pub socket: UdpSocket,
|
||||||
|
|
||||||
pub request_buf: Buf::<Request>,
|
pub request_buf: Slot::<Request>,
|
||||||
pub response_buf: Buf::<Response>,
|
pub response_buf: Slot::<Response>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Party {
|
impl Party {
|
||||||
|
@ -232,8 +235,8 @@ impl Party {
|
||||||
let this = Self {
|
let this = Self {
|
||||||
socket,
|
socket,
|
||||||
|
|
||||||
request_buf: Buf::new(),
|
request_buf: Slot::new(),
|
||||||
response_buf: Buf::new(),
|
response_buf: Slot::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(this)
|
Ok(this)
|
||||||
|
@ -286,28 +289,28 @@ spawn(move || {
|
||||||
|
|
||||||
## Feature flags
|
## 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`
|
* *`alloc`: Enables the `Slot` type and implementations for e.g. `Box` and `Arc`
|
||||||
* *`proc-macro`: Pulls the procedural macros from the `librum-macros` crate
|
* *`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`
|
* *`std`: Enables implementations for types such as `Mutex` and `RwLock`
|
||||||
|
|
||||||
Features marked with * are enabled by default.
|
Features marked with * are enabled by default.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
Librum has its documentation written in-source for use by `rustdoc`.
|
oct 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.
|
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.
|
Currently, these docs make use of some unstable features for the sake of readability.
|
||||||
The nightly toolchain is therefore required when rendering them.
|
The nightly toolchain is therefore required when rendering them.
|
||||||
|
|
||||||
## Contribution
|
## 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.
|
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
|
## 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">
|
<svg height="96" width="96" xmlns="http://www.w3.org/2000/svg">
|
||||||
<mask id="z">
|
<mask id="tHorizontalArm">
|
||||||
<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" />
|
<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>
|
</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>
|
</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]
|
[package]
|
||||||
name = "librum-benchmarks"
|
name = "oct-benchmarks"
|
||||||
version = "0.13.1"
|
version = "0.14.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Librum benchmarks."
|
description = "oct benchmarks."
|
||||||
|
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
readme.workspace = true
|
readme.workspace = true
|
||||||
|
@ -10,7 +10,7 @@ homepage.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[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"
|
bincode = "1.3.0"
|
||||||
rand = "0.8.0"
|
rand = "0.8.0"
|
|
@ -18,7 +18,7 @@ macro_rules! benchmark {
|
||||||
|
|
||||||
borsh: $borsh_op:block$(,)?
|
borsh: $borsh_op:block$(,)?
|
||||||
|
|
||||||
librum: $librum_op:block$(,)?
|
oct: $oct_op:block$(,)?
|
||||||
|
|
||||||
postcard: $postcard_op:block$(,)?
|
postcard: $postcard_op:block$(,)?
|
||||||
}$(,)?)+
|
}$(,)?)+
|
||||||
|
@ -54,7 +54,7 @@ macro_rules! benchmark {
|
||||||
|
|
||||||
let mut total_bincode_duration = 0.0;
|
let mut total_bincode_duration = 0.0;
|
||||||
let mut total_borsh_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;
|
let mut total_postcard_duration = 0.0;
|
||||||
|
|
||||||
$({
|
$({
|
||||||
|
@ -63,7 +63,7 @@ macro_rules! benchmark {
|
||||||
|
|
||||||
let mut bincode_duration = 0.0;
|
let mut bincode_duration = 0.0;
|
||||||
let mut borsh_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;
|
let mut postcard_duration = 0.0;
|
||||||
|
|
||||||
for i in 0x0..TEST_COUNT {
|
for i in 0x0..TEST_COUNT {
|
||||||
|
@ -73,7 +73,7 @@ macro_rules! benchmark {
|
||||||
|
|
||||||
bincode_duration += time! { $bincode_op };
|
bincode_duration += time! { $bincode_op };
|
||||||
borsh_duration += time! { $borsh_op };
|
borsh_duration += time! { $borsh_op };
|
||||||
librum_duration += time! { $librum_op };
|
oct_duration += time! { $oct_op };
|
||||||
postcard_duration += time! { $postcard_op };
|
postcard_duration += time! { $postcard_op };
|
||||||
|
|
||||||
eprint!("\u{001B}[000m");
|
eprint!("\u{001B}[000m");
|
||||||
|
@ -83,37 +83,37 @@ macro_rules! benchmark {
|
||||||
|
|
||||||
bincode_duration /= f64::from(TEST_COUNT);
|
bincode_duration /= f64::from(TEST_COUNT);
|
||||||
borsh_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);
|
postcard_duration /= f64::from(TEST_COUNT);
|
||||||
|
|
||||||
eprint!("\u{001B}[000m");
|
eprint!("\u{001B}[000m");
|
||||||
eprintln!("bincode: {}", format_score(bincode_duration, librum_duration));
|
eprintln!("bincode: {}", format_score(bincode_duration, oct_duration));
|
||||||
eprintln!("borsh: {}", format_score(borsh_duration, librum_duration));
|
eprintln!("borsh: {}", format_score(borsh_duration, oct_duration));
|
||||||
eprintln!("librum: {}", format_score(librum_duration, librum_duration));
|
eprintln!("oct: {}", format_score(oct_duration, oct_duration));
|
||||||
eprintln!("postcard: {}", format_score(postcard_duration, librum_duration));
|
eprintln!("postcard: {}", format_score(postcard_duration, oct_duration));
|
||||||
|
|
||||||
total_bincode_duration += bincode_duration;
|
total_bincode_duration += bincode_duration;
|
||||||
total_borsh_duration += borsh_duration;
|
total_borsh_duration += borsh_duration;
|
||||||
total_librum_duration += librum_duration;
|
total_oct_duration += oct_duration;
|
||||||
total_postcard_duration += postcard_duration;
|
total_postcard_duration += postcard_duration;
|
||||||
})*
|
})*
|
||||||
|
|
||||||
eprintln!();
|
eprintln!();
|
||||||
eprintln!("\u{001B}[001mtotal score:\u{001B}[022m");
|
eprintln!("\u{001B}[001mtotal score:\u{001B}[022m");
|
||||||
eprintln!("bincode: {}", format_score(total_bincode_duration, total_librum_duration));
|
eprintln!("bincode: {}", format_score(total_bincode_duration, total_oct_duration));
|
||||||
eprintln!("borsh: {}", format_score(total_borsh_duration, total_librum_duration));
|
eprintln!("borsh: {}", format_score(total_borsh_duration, total_oct_duration));
|
||||||
eprintln!("librum: {}", format_score(total_librum_duration, total_librum_duration));
|
eprintln!("oct: {}", format_score(total_oct_duration, total_oct_duration));
|
||||||
eprintln!("postcard: {}", format_score(total_postcard_duration, total_librum_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(borsh::BorshSerialize)]
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
struct Unit;
|
struct Unit;
|
||||||
|
|
||||||
#[derive(librum::Decode, librum::Encode, librum::SizedEncode)]
|
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
|
||||||
#[derive(borsh::BorshSerialize)]
|
#[derive(borsh::BorshSerialize)]
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
#[repr(transparent)]
|
#[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(borsh::BorshSerialize)]
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
struct Named { buf: [u8; 0x8] }
|
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 {
|
impl Named {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[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>
|
fn generate_random_data<T>(item_size: usize, value_count: usize) -> impl Iterator<Item = u8>
|
||||||
where
|
where
|
||||||
T: Immutable + IntoBytes + Sized,
|
T: Immutable + IntoBytes + Sized,
|
||||||
|
@ -180,15 +180,15 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("#####################");
|
println!("##################");
|
||||||
println!("# LIBRUM BENCHMARKS #");
|
println!("# OCT BENCHMARKS #");
|
||||||
println!("#####################");
|
println!("##################");
|
||||||
println!();
|
println!();
|
||||||
println!("Each benchmark has a version written for the following crates:");
|
println!("Each benchmark has a version written for the following crates:");
|
||||||
println!();
|
println!();
|
||||||
println!("- Bincode: <https://crates.io/crates/bincode/>");
|
println!("- Bincode: <https://crates.io/crates/bincode/>");
|
||||||
println!("- Borsh: <https://crates.io/crates/borsh/>");
|
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!("- Postcard: <https://crates.io/crates/postcard/>");
|
||||||
println!();
|
println!();
|
||||||
println!("The total time the benchmark took (including memory allocations and dealloca-");
|
println!("The total time the benchmark took (including memory allocations and dealloca-");
|
||||||
|
@ -198,10 +198,10 @@ fn main() {
|
||||||
println!();
|
println!();
|
||||||
println!("When every benchmark has concluded, the total run time and vps is listed for");
|
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!("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!("crate and oct (which should always be c. `0%` for oct itself). DO NOTE THAT");
|
||||||
println!("THAT THESE FINAL RESULTS INDICATE A NON-WEIGHTED AVERAGE ACROSS BENCHMARKS. It");
|
println!("THESE FINAL RESULTS INDICATE A NON-WEIGHTED AVERAGE ACROSS BENCHMARKS. It can");
|
||||||
println!("can therefore be skewed relative to real-world performance by the similarity of");
|
println!("therefore be skewed relative to real-world performance by the similarity of some");
|
||||||
println!("some benchmarks.");
|
println!("benchmarks.");
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
eprintln!("test_count: {TEST_COUNT}");
|
eprintln!("test_count: {TEST_COUNT}");
|
||||||
|
@ -233,13 +233,13 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
librum: {
|
oct: {
|
||||||
use librum::{Encode, OStream, SizedEncode};
|
use oct::encode::{Encode, Output, SizedEncode};
|
||||||
|
|
||||||
const ITEM_SIZE: usize = u8::MAX_ENCODED_SIZE;
|
const ITEM_SIZE: usize = u8::MAX_ENCODED_SIZE;
|
||||||
|
|
||||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
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 {
|
for _ in 0x0..VALUE_COUNT {
|
||||||
random::<u8>().encode(&mut stream).unwrap();
|
random::<u8>().encode(&mut stream).unwrap();
|
||||||
|
@ -280,13 +280,13 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
librum: {
|
oct: {
|
||||||
use librum::{Encode, OStream, SizedEncode};
|
use oct::encode::{Encode, Output, SizedEncode};
|
||||||
|
|
||||||
const ITEM_SIZE: usize = u32::MAX_ENCODED_SIZE;
|
const ITEM_SIZE: usize = u32::MAX_ENCODED_SIZE;
|
||||||
|
|
||||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
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 {
|
for _ in 0x0..VALUE_COUNT {
|
||||||
random::<u32>().encode(&mut stream).unwrap();
|
random::<u32>().encode(&mut stream).unwrap();
|
||||||
|
@ -327,13 +327,13 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
librum: {
|
oct: {
|
||||||
use librum::{Encode, OStream, SizedEncode};
|
use oct::encode::{Encode, Output, SizedEncode};
|
||||||
|
|
||||||
const ITEM_SIZE: usize = u128::MAX_ENCODED_SIZE;
|
const ITEM_SIZE: usize = u128::MAX_ENCODED_SIZE;
|
||||||
|
|
||||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
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 {
|
for _ in 0x0..VALUE_COUNT {
|
||||||
random::<u128>().encode(&mut stream).unwrap();
|
random::<u128>().encode(&mut stream).unwrap();
|
||||||
|
@ -374,13 +374,13 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
librum: {
|
oct: {
|
||||||
use librum::{Encode, OStream, SizedEncode};
|
use oct::encode::{Encode, Output, SizedEncode};
|
||||||
|
|
||||||
const ITEM_SIZE: usize = Unit::MAX_ENCODED_SIZE;
|
const ITEM_SIZE: usize = Unit::MAX_ENCODED_SIZE;
|
||||||
|
|
||||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
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 {
|
for _ in 0x0..VALUE_COUNT {
|
||||||
Unit.encode(&mut stream).unwrap();
|
Unit.encode(&mut stream).unwrap();
|
||||||
|
@ -421,13 +421,13 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
librum: {
|
oct: {
|
||||||
use librum::{Encode, OStream, SizedEncode};
|
use oct::encode::{Encode, Output, SizedEncode};
|
||||||
|
|
||||||
const ITEM_SIZE: usize = Unnamed::MAX_ENCODED_SIZE;
|
const ITEM_SIZE: usize = Unnamed::MAX_ENCODED_SIZE;
|
||||||
|
|
||||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
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 {
|
for _ in 0x0..VALUE_COUNT {
|
||||||
Unnamed::from_char(random()).encode(&mut stream).unwrap();
|
Unnamed::from_char(random()).encode(&mut stream).unwrap();
|
||||||
|
@ -468,13 +468,13 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
librum: {
|
oct: {
|
||||||
use librum::{Encode, OStream, SizedEncode};
|
use oct::encode::{Encode, Output, SizedEncode};
|
||||||
|
|
||||||
const ITEM_SIZE: usize = Named::MAX_ENCODED_SIZE;
|
const ITEM_SIZE: usize = Named::MAX_ENCODED_SIZE;
|
||||||
|
|
||||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
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 {
|
for _ in 0x0..VALUE_COUNT {
|
||||||
Named::from_u64(random()).encode(&mut stream).unwrap();
|
Named::from_u64(random()).encode(&mut stream).unwrap();
|
||||||
|
@ -519,15 +519,15 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
librum: {
|
oct: {
|
||||||
use librum::{Encode, OStream, SizedEncode};
|
use oct::encode::{Encode, Output, SizedEncode};
|
||||||
|
|
||||||
const ITEM_SIZE: usize =
|
const ITEM_SIZE: usize =
|
||||||
isize::MAX_ENCODED_SIZE // discriminant
|
isize::MAX_ENCODED_SIZE // discriminant
|
||||||
+ Unit::MAX_ENCODED_SIZE;
|
+ Unit::MAX_ENCODED_SIZE;
|
||||||
|
|
||||||
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT].into_boxed_slice();
|
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 {
|
for _ in 0x0..VALUE_COUNT {
|
||||||
Enum::Unit(Unit).encode(&mut stream).unwrap();
|
Enum::Unit(Unit).encode(&mut stream).unwrap();
|
||||||
|
@ -572,13 +572,14 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
librum: {
|
oct: {
|
||||||
use librum::{Decode, IStream, SizedEncode};
|
use oct::decode::{Decode, Input};
|
||||||
|
use oct::encode::SizedEncode;
|
||||||
|
|
||||||
const ITEM_SIZE: usize = u8::MAX_ENCODED_SIZE;
|
const ITEM_SIZE: usize = u8::MAX_ENCODED_SIZE;
|
||||||
|
|
||||||
let buf: Box<[_]> = generate_random_data::<u8>(ITEM_SIZE, VALUE_COUNT).collect();
|
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 {
|
for _ in 0x0..VALUE_COUNT {
|
||||||
let _ = u8::decode(&mut stream).unwrap();
|
let _ = u8::decode(&mut stream).unwrap();
|
||||||
|
@ -623,13 +624,14 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
librum: {
|
oct: {
|
||||||
use librum::{Decode, IStream, SizedEncode};
|
use oct::decode::{Decode, Input};
|
||||||
|
use oct::encode::SizedEncode;
|
||||||
|
|
||||||
const ITEM_SIZE: usize = NonZero::<u8>::MAX_ENCODED_SIZE;
|
const ITEM_SIZE: usize = NonZero::<u8>::MAX_ENCODED_SIZE;
|
||||||
|
|
||||||
let buf: Box<[_]> = generate_random_data::<NonZero<u8>>(ITEM_SIZE, VALUE_COUNT).collect();
|
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 {
|
for _ in 0x0..VALUE_COUNT {
|
||||||
let _ = NonZero::<u8>::decode(&mut stream).unwrap();
|
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]
|
[package]
|
||||||
name = "librum-macros"
|
name = "oct-macros"
|
||||||
version = "0.13.1"
|
version = "0.14.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
documentation = "https://docs.rs/librum-macros/"
|
documentation = "https://docs.rs/oct-macros/"
|
||||||
|
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
description.workspace = true
|
description.workspace = true
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
|
@ -82,14 +82,12 @@ impl Debug for GenericName {
|
||||||
impl ToTokens for GenericName {
|
impl ToTokens for GenericName {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
use GenericName::*;
|
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
| Const(ref ident)
|
| Self::Const(ref ident)
|
||||||
| Ty( ref ident)
|
| Self::Ty( ref ident)
|
||||||
=> ident.to_tokens(tokens),
|
=> 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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{GenericName, Repr};
|
use crate::{GenericName, Repr};
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{Discriminants, Repr};
|
use crate::{Discriminants, Repr};
|
||||||
|
@ -38,9 +38,9 @@ pub fn decode_enum(data: DataEnum, repr: Repr) -> TokenStream {
|
||||||
|
|
||||||
let commands = iter::repeat_n(
|
let commands = iter::repeat_n(
|
||||||
quote! {
|
quote! {
|
||||||
::librum::Decode::decode(stream)
|
::oct::decode::Decode::decode(stream)
|
||||||
.map_err(::core::convert::Into::<::librum::error::GenericDecodeError>::into)
|
.map_err(::core::convert::Into::<::oct::error::GenericDecodeError>::into)
|
||||||
.map_err(::librum::error::EnumDecodeError::Field)?
|
.map_err(::oct::error::EnumDecodeError::BadField)?
|
||||||
},
|
},
|
||||||
variant.fields.len(),
|
variant.fields.len(),
|
||||||
);
|
);
|
||||||
|
@ -62,18 +62,18 @@ pub fn decode_enum(data: DataEnum, repr: Repr) -> TokenStream {
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
type Error = ::librum::error::EnumDecodeError<#repr, ::librum::error::GenericDecodeError>;
|
type Error = ::oct::error::EnumDecodeError<#repr, ::oct::error::GenericDecodeError>;
|
||||||
|
|
||||||
#[inline]
|
#[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 discriminant = <#repr as ::librum::Decode>::decode(stream)
|
let discriminant = <#repr as ::oct::decode::Decode>::decode(stream)
|
||||||
.map_err(::core::convert::Into::<::core::convert::Infallible>::into)
|
.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 {
|
let this = match discriminant {
|
||||||
#(#discriminants => #values,)*
|
#(#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)
|
::core::result::Result::Ok(this)
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
|
@ -28,8 +28,8 @@ use std::iter;
|
||||||
pub fn decode_struct(data: DataStruct) -> TokenStream {
|
pub fn decode_struct(data: DataStruct) -> TokenStream {
|
||||||
let commands = iter::repeat_n(
|
let commands = iter::repeat_n(
|
||||||
quote! {
|
quote! {
|
||||||
::librum::Decode::decode(stream)
|
::oct::decode::Decode::decode(stream)
|
||||||
.map_err(::core::convert::Into::<::librum::error::GenericDecodeError>::into)?
|
.map_err(::core::convert::Into::<::oct::error::GenericDecodeError>::into)?
|
||||||
},
|
},
|
||||||
data.fields.len(),
|
data.fields.len(),
|
||||||
);
|
);
|
||||||
|
@ -50,10 +50,10 @@ pub fn decode_struct(data: DataStruct) -> TokenStream {
|
||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
type Error = ::librum::error::GenericDecodeError;
|
type Error = ::oct::error::GenericDecodeError;
|
||||||
|
|
||||||
#[inline]
|
#[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;
|
let this = #value;
|
||||||
::core::result::Result::Ok(this)
|
::core::result::Result::Ok(this)
|
||||||
}
|
}
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{Discriminants, Repr};
|
use crate::{Discriminants, Repr};
|
||||||
|
@ -66,21 +66,21 @@ pub fn encode_enum(data: DataEnum, repr: Repr) -> TokenStream {
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
type Error = ::librum::error::EnumEncodeError<#repr, ::librum::error::GenericEncodeError>;
|
type Error = ::oct::error::EnumEncodeError<#repr, ::oct::error::GenericEncodeError>;
|
||||||
|
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
#[inline]
|
#[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 {
|
match *self {
|
||||||
#(
|
#(
|
||||||
#patterns => {
|
#patterns => {
|
||||||
<#repr as ::librum::Encode>::encode(&#discriminants, stream)
|
<#repr as ::oct::encode::Encode>::encode(&#discriminants, stream)
|
||||||
.map_err(::librum::error::EnumEncodeError::Discriminant)?;
|
.map_err(::oct::error::EnumEncodeError::BadDiscriminant)?;
|
||||||
|
|
||||||
#(
|
#(
|
||||||
::librum::Encode::encode(#captures, stream)
|
::oct::encode::Encode::encode(#captures, stream)
|
||||||
.map_err(::core::convert::Into::<::librum::error::GenericEncodeError>::into)
|
.map_err(::core::convert::Into::<::oct::error::GenericEncodeError>::into)
|
||||||
.map_err(::librum::error::EnumEncodeError::Field)?;
|
.map_err(::oct::error::EnumEncodeError::BadField)?;
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
)*
|
)*
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
|
@ -48,15 +48,15 @@ pub fn encode_struct(data: DataStruct) -> TokenStream {
|
||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
type Error = ::librum::error::GenericEncodeError;
|
type Error = ::oct::error::GenericEncodeError;
|
||||||
|
|
||||||
#[inline]
|
#[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;
|
let #pattern = self;
|
||||||
|
|
||||||
#(
|
#(
|
||||||
::librum::Encode::encode(#captures, stream)
|
::oct::encode::Encode::encode(#captures, stream)
|
||||||
.map_err(::core::convert::Into::<::librum::error::GenericEncodeError>::into)?;
|
.map_err(::core::convert::Into::<::oct::error::GenericEncodeError>::into)?;
|
||||||
)*
|
)*
|
||||||
|
|
||||||
::core::result::Result::Ok(())
|
::core::result::Result::Ok(())
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::use_mod;
|
use crate::use_mod;
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::Repr;
|
use crate::Repr;
|
||||||
|
@ -48,7 +48,7 @@ pub fn sized_encode_enum(data: DataEnum, repr: Repr) -> TokenStream {
|
||||||
let mut current_size = 0x0usize;
|
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 };
|
if current_size > total_size { total_size = current_size };
|
||||||
)*
|
)*
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
|
@ -31,6 +31,6 @@ pub fn sized_encode_struct(data: DataStruct) -> TokenStream {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
quote! {
|
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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// 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:
|
// For use in macros:
|
||||||
extern crate self as librum_macros;
|
extern crate self as oct_macros;
|
||||||
|
|
||||||
macro_rules! use_mod {
|
macro_rules! use_mod {
|
||||||
($vis:vis $name:ident) => {
|
($vis:vis $name:ident) => {
|
||||||
|
@ -51,7 +51,7 @@ pub fn derive_decode(input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
let output = impl_derive_macro(
|
let output = impl_derive_macro(
|
||||||
input,
|
input,
|
||||||
parse2(quote! { ::librum::Decode }).unwrap(),
|
parse2(quote! { ::oct::decode::Decode }).unwrap(),
|
||||||
None,
|
None,
|
||||||
impls::decode_struct,
|
impls::decode_struct,
|
||||||
impls::decode_enum,
|
impls::decode_enum,
|
||||||
|
@ -68,7 +68,7 @@ pub fn derive_encode(input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
let output = impl_derive_macro(
|
let output = impl_derive_macro(
|
||||||
input,
|
input,
|
||||||
parse2(quote! { ::librum::Encode }).unwrap(),
|
parse2(quote! { ::oct::encode::Encode }).unwrap(),
|
||||||
None,
|
None,
|
||||||
impls::encode_struct,
|
impls::encode_struct,
|
||||||
impls::encode_enum,
|
impls::encode_enum,
|
||||||
|
@ -85,7 +85,7 @@ pub fn derive_sized_encode(input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
let output = impl_derive_macro(
|
let output = impl_derive_macro(
|
||||||
input,
|
input,
|
||||||
parse2(quote! { ::librum::SizedEncode }).unwrap(),
|
parse2(quote! { ::oct::encode::SizedEncode }).unwrap(),
|
||||||
None,
|
None,
|
||||||
impls::sized_encode_struct,
|
impls::sized_encode_struct,
|
||||||
impls::sized_encode_enum,
|
impls::sized_encode_enum,
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
|
@ -61,22 +61,20 @@ impl Repr {
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if attr.path().is_ident("repr") {
|
if attr.path().is_ident("repr") {
|
||||||
attr.parse_nested_meta(|meta| {
|
attr.parse_nested_meta(|meta| {
|
||||||
use Repr::*;
|
|
||||||
|
|
||||||
let ident = meta.path.require_ident()?;
|
let ident = meta.path.require_ident()?;
|
||||||
|
|
||||||
if ident == "u8" { this = Some(U8) }
|
if ident == "u8" { this = Some(Self::U8) }
|
||||||
else if ident == "i8" { this = Some(I8) }
|
else if ident == "i8" { this = Some(Self::I8) }
|
||||||
else if ident == "u16" { this = Some(U16) }
|
else if ident == "u16" { this = Some(Self::U16) }
|
||||||
else if ident == "i16" { this = Some(I16) }
|
else if ident == "i16" { this = Some(Self::I16) }
|
||||||
else if ident == "u32" { this = Some(U32) }
|
else if ident == "u32" { this = Some(Self::U32) }
|
||||||
else if ident == "i32" { this = Some(I32) }
|
else if ident == "i32" { this = Some(Self::I32) }
|
||||||
else if ident == "u64" { this = Some(U64) }
|
else if ident == "u64" { this = Some(Self::U64) }
|
||||||
else if ident == "i64" { this = Some(I64) }
|
else if ident == "i64" { this = Some(Self::I64) }
|
||||||
else if ident == "u128" { this = Some(U128) }
|
else if ident == "u128" { this = Some(Self::U128) }
|
||||||
else if ident == "i128" { this = Some(I128) }
|
else if ident == "i128" { this = Some(Self::I128) }
|
||||||
else if ident == "usize" { this = Some(Usize) }
|
else if ident == "usize" { this = Some(Self::Usize) }
|
||||||
else if ident == "isize" { this = Some(Isize) }
|
else if ident == "isize" { this = Some(Self::Isize) }
|
||||||
else { panic!("`{ident}` is not a derivable enumeration representation") };
|
else { panic!("`{ident}` is not a derivable enumeration representation") };
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -92,21 +90,19 @@ impl Repr {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn to_str(self) -> &'static str {
|
pub const fn to_str(self) -> &'static str {
|
||||||
use Repr::*;
|
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
U8 => "u8",
|
Self::U8 => "u8",
|
||||||
I8 => "i8",
|
Self::I8 => "i8",
|
||||||
U16 => "u16",
|
Self::U16 => "u16",
|
||||||
I16 => "i16",
|
Self::I16 => "i16",
|
||||||
U32 => "u32",
|
Self::U32 => "u32",
|
||||||
I32 => "i32",
|
Self::I32 => "i32",
|
||||||
U64 => "u64",
|
Self::U64 => "u64",
|
||||||
I64 => "i64",
|
Self::I64 => "i64",
|
||||||
U128 => "u128",
|
Self::U128 => "u128",
|
||||||
I128 => "i128",
|
Self::I128 => "i128",
|
||||||
Usize => "usize",
|
Self::Usize => "usize",
|
||||||
Isize => "isize",
|
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]
|
[package]
|
||||||
name = "librum"
|
name = "oct"
|
||||||
version = "0.13.1"
|
version = "0.14.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.83"
|
rust-version = "1.83"
|
||||||
documentation = "https://docs.rs/librum/"
|
documentation = "https://docs.rs/oct/"
|
||||||
|
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
description.workspace = true
|
description.workspace = true
|
||||||
|
@ -21,11 +21,11 @@ all-features = true
|
||||||
default = ["alloc", "proc-macro", "std"]
|
default = ["alloc", "proc-macro", "std"]
|
||||||
|
|
||||||
alloc = []
|
alloc = []
|
||||||
proc-macro = ["librum-macros"]
|
proc-macro = ["oct-macros"]
|
||||||
std = []
|
std = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
librum-macros = { path = "../librum-macros", version = "0.13.0", optional = true}
|
oct-macros = { path = "../oct-macros", version = "0.14.0", optional = true}
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
|
@ -1,30 +1,29 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use crate::{DecodeBorrowed, IStream, SizedEncode};
|
use crate::decode::{DecodeBorrowed, Input};
|
||||||
use crate::error::{
|
use crate::error::{
|
||||||
BoolDecodeError,
|
|
||||||
CStringDecodeError,
|
CStringDecodeError,
|
||||||
CharDecodeError,
|
CharDecodeError,
|
||||||
CollectionDecodeError,
|
CollectionDecodeError,
|
||||||
|
@ -104,12 +103,12 @@ pub trait Decode: Sized {
|
||||||
/// The type returned in case of error.
|
/// The type returned in case of error.
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
/// Decodes an object from the provided stream.
|
/// Decodes an object from the provided input.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// If decoding fails due to e.g. an invalid byte sequence in the stream, then an error should be returned.
|
/// If decoding fails due to e.g. an invalid byte sequence in the input, then an error should be returned.
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error>;
|
fn decode(input: &mut Input) -> Result<Self, Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implemented for tuples with up to twelve members.
|
/// Implemented for tuples with up to twelve members.
|
||||||
|
@ -118,9 +117,9 @@ impl<T: Decode> Decode for (T, ) {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let this = (Decode::decode(stream)?, );
|
let this = (Decode::decode(input)?, );
|
||||||
Ok(this)
|
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>>;
|
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, T::Error>>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
// Initialise the array incrementally.
|
// 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() {
|
for (i, item) in buf.iter_mut().enumerate() {
|
||||||
let value = Decode::decode(stream)
|
let value = Decode::decode(input)
|
||||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }))?;
|
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
|
||||||
|
|
||||||
item.write(value);
|
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-
|
// be used here, and `transmute_unchecked` is re-
|
||||||
// served for the greedy rustc devs.
|
// served for the greedy rustc devs.
|
||||||
let this = unsafe { buf.as_ptr().cast::<[T; N]>().read() };
|
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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = Decode::decode(stream)?;
|
let value = Decode::decode(input)?;
|
||||||
|
|
||||||
let this = Self::new(value);
|
let this = Self::new(value);
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode for bool {
|
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]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = u8::decode(stream).unwrap();
|
let Ok(value) = u8::decode(input);
|
||||||
|
|
||||||
match value {
|
let this = value != 0x0;
|
||||||
0x0 => Ok(false),
|
Result::Ok(this)
|
||||||
0x1 => Ok(true),
|
|
||||||
_ => Err(BoolDecodeError { value })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,20 +184,20 @@ impl<T: Decode> Decode for Bound<T> {
|
||||||
type Error = EnumDecodeError<u8, T::Error>;
|
type Error = EnumDecodeError<u8, T::Error>;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let discriminant = u8::decode(stream).unwrap();
|
let Ok(discriminant) = u8::decode(input);
|
||||||
|
|
||||||
let this = match discriminant {
|
let this = match discriminant {
|
||||||
0x0 => {
|
0x0 => {
|
||||||
let bound = Decode::decode(stream)
|
let bound = Decode::decode(input)
|
||||||
.map_err(EnumDecodeError::Field)?;
|
.map_err(EnumDecodeError::BadField)?;
|
||||||
|
|
||||||
Self::Included(bound)
|
Self::Included(bound)
|
||||||
}
|
}
|
||||||
|
|
||||||
0x1 => {
|
0x1 => {
|
||||||
let bound = Decode::decode(stream)
|
let bound = Decode::decode(input)
|
||||||
.map_err(EnumDecodeError::Field)?;
|
.map_err(EnumDecodeError::BadField)?;
|
||||||
|
|
||||||
Self::Excluded(bound)
|
Self::Excluded(bound)
|
||||||
}
|
}
|
||||||
|
@ -208,7 +207,7 @@ impl<T: Decode> Decode for Bound<T> {
|
||||||
value => return Err(EnumDecodeError::UnassignedDiscriminant { value }),
|
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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = Decode::decode(stream)?;
|
let value = Decode::decode(input)?;
|
||||||
|
|
||||||
let this = Self::new(value);
|
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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = Decode::decode(stream)?;
|
let value = Decode::decode(input)?;
|
||||||
|
|
||||||
let this = Self::new(value);
|
let this = Self::new(value);
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,14 +241,17 @@ impl Decode for char {
|
||||||
type Error = CharDecodeError;
|
type Error = CharDecodeError;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let code_point = u32::decode(stream).unwrap();
|
let Ok(code_point) = u32::decode(input);
|
||||||
|
|
||||||
let this = code_point
|
match code_point {
|
||||||
.try_into()
|
code_point @ (0x0000..=0xD7FF | 0xDE00..=0x10FFFF) => {
|
||||||
.map_err(|_| CharDecodeError { code_point })?;
|
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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = Decode::decode(stream)?;
|
let value = Decode::decode(input)?;
|
||||||
|
|
||||||
let this = Self::Owned(value);
|
let this = Self::Owned(value);
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,10 +279,10 @@ impl Decode for CString {
|
||||||
type Error = CStringDecodeError;
|
type Error = CStringDecodeError;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let len = Decode::decode(stream).unwrap();
|
let Ok(len) = Decode::decode(input);
|
||||||
|
|
||||||
let data = stream.read(len);
|
let data = input.read(len).unwrap();
|
||||||
|
|
||||||
for (i, c) in data.iter().enumerate() {
|
for (i, c) in data.iter().enumerate() {
|
||||||
if *c == b'\x00' { return Err(CStringDecodeError { index: i }) };
|
if *c == b'\x00' { return Err(CStringDecodeError { index: i }) };
|
||||||
|
@ -298,7 +300,7 @@ impl Decode for CString {
|
||||||
|
|
||||||
// SAFETY: We have already tested the data.
|
// SAFETY: We have already tested the data.
|
||||||
let this = unsafe { Self::from_vec_unchecked(buf) };
|
let this = unsafe { Self::from_vec_unchecked(buf) };
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,12 +308,12 @@ impl Decode for Duration {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let secs = Decode::decode(stream)?;
|
let Ok(secs) = Decode::decode(input);
|
||||||
let nanos = Decode::decode(stream)?;
|
let Ok(nanos) = Decode::decode(input);
|
||||||
|
|
||||||
let this = Self::new(secs, nanos);
|
let this = Self::new(secs, nanos);
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,22 +328,22 @@ where
|
||||||
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, E>>;
|
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, E>>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let len = Decode::decode(stream).unwrap();
|
let Ok(len) = Decode::decode(input);
|
||||||
|
|
||||||
let mut this = Self::with_capacity_and_hasher(len, Default::default());
|
let mut this = Self::with_capacity_and_hasher(len, Default::default());
|
||||||
|
|
||||||
for i in 0x0..len {
|
for i in 0x0..len {
|
||||||
let key= Decode::decode(stream)
|
let key= Decode::decode(input)
|
||||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }))?;
|
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
|
||||||
|
|
||||||
let value = Decode::decode(stream)
|
let value = Decode::decode(input)
|
||||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }))?;
|
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
|
||||||
|
|
||||||
this.insert(key, value);
|
this.insert(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,19 +357,19 @@ where
|
||||||
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, K::Error>>;
|
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, K::Error>>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let len = Decode::decode(stream).unwrap();
|
let Ok(len) = Decode::decode(input);
|
||||||
|
|
||||||
let mut this = Self::with_capacity_and_hasher(len, Default::default());
|
let mut this = Self::with_capacity_and_hasher(len, Default::default());
|
||||||
|
|
||||||
for i in 0x0..len {
|
for i in 0x0..len {
|
||||||
let key = Decode::decode(stream)
|
let key = Decode::decode(input)
|
||||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }) )?;
|
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }) )?;
|
||||||
|
|
||||||
this.insert(key);
|
this.insert(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,7 +377,7 @@ impl Decode for Infallible {
|
||||||
type Error = Self;
|
type Error = Self;
|
||||||
|
|
||||||
#[inline(always)]
|
#[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")
|
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>;
|
type Error = EnumDecodeError<u8, Infallible>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let discriminant = u8::decode(stream)
|
let discriminant = u8::decode(input)
|
||||||
.map_err(EnumDecodeError::InvalidDiscriminant)?;
|
.map_err(EnumDecodeError::InvalidDiscriminant)?;
|
||||||
|
|
||||||
let this = match discriminant {
|
let this = match discriminant {
|
||||||
0x4 => Self::V4(Decode::decode(stream).unwrap()),
|
0x4 => Self::V4(Decode::decode(input).unwrap()),
|
||||||
0x6 => Self::V6(Decode::decode(stream).unwrap()),
|
0x6 => Self::V6(Decode::decode(input).unwrap()),
|
||||||
|
|
||||||
value => return Err(EnumDecodeError::UnassignedDiscriminant { value })
|
value => return Err(EnumDecodeError::UnassignedDiscriminant { value })
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,9 +405,11 @@ impl Decode for Ipv4Addr {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = Decode::decode(stream)?;
|
let Ok(value) = Decode::decode(input);
|
||||||
Ok(Self::from_bits(value))
|
|
||||||
|
let this = Self::from_bits(value);
|
||||||
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,9 +417,11 @@ impl Decode for Ipv6Addr {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = Decode::decode(stream)?;
|
let Ok(value) = Decode::decode(input);
|
||||||
Ok(Self::from_bits(value))
|
|
||||||
|
let this = Self::from_bits(value);
|
||||||
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,9 +429,10 @@ impl Decode for isize {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = i16::decode(stream)?;
|
let Ok(value) = i16::decode(input);
|
||||||
Ok(value as Self)
|
|
||||||
|
Result::Ok(value as Self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,19 +442,19 @@ impl<T: Decode> Decode for LinkedList<T> {
|
||||||
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, T::Error>>;
|
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, T::Error>>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let len = usize::decode(stream).unwrap();
|
let Ok(len) = usize::decode(input);
|
||||||
|
|
||||||
let mut this = Self::new();
|
let mut this = Self::new();
|
||||||
|
|
||||||
for i in 0x0..len {
|
for i in 0x0..len {
|
||||||
let value = T::decode(stream)
|
let value = T::decode(input)
|
||||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }))?;
|
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
|
||||||
|
|
||||||
this.push_back(value);
|
this.push_back(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,8 +464,11 @@ impl<T: Decode> Decode for Mutex<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
Ok(Self::new(Decode::decode(stream)?))
|
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)] // ???
|
#[expect(clippy::if_then_some_else_none)] // ???
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let sign = bool::decode(stream).unwrap();
|
let sign = bool::decode(input)
|
||||||
|
.map_err::<T::Error, _>(|_e| unreachable!())?;
|
||||||
|
|
||||||
let this = if sign {
|
let this = if sign {
|
||||||
Some(Decode::decode(stream)?)
|
Some(Decode::decode(input)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,8 +495,8 @@ impl<T> Decode for PhantomData<T> {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(_stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(_input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
Ok(Self)
|
Result::Ok(Self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,8 +504,8 @@ impl Decode for PhantomPinned {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(_stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(_input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
Ok(Self)
|
Result::Ok(Self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,11 +513,11 @@ impl<T: Decode> Decode for Range<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let start = Decode::decode(stream)?;
|
let start = Decode::decode(input)?;
|
||||||
let end = Decode::decode(stream)?;
|
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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let start = Decode::decode(stream)?;
|
let start = Decode::decode(input)?;
|
||||||
|
|
||||||
Ok(start..)
|
Result::Ok(start..)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,8 +536,8 @@ impl Decode for RangeFull {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(_stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(_input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
Ok(..)
|
Result::Ok(..)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,11 +545,11 @@ impl<T: Decode> Decode for RangeInclusive<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let start = Decode::decode(stream)?;
|
let start = Decode::decode(input)?;
|
||||||
let end = Decode::decode(stream)?;
|
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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let end = Decode::decode(stream)?;
|
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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let end = Decode::decode(stream)?;
|
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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
Ok(Self::new(Decode::decode(stream)?))
|
Result::Ok(Self::new(Decode::decode(input)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,15 +590,15 @@ impl<T: Decode> Decode for RefCell<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = Decode::decode(stream)?;
|
let value = Decode::decode(input)?;
|
||||||
|
|
||||||
let this = Self::new(value);
|
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
|
where
|
||||||
T: Decode<Error = Err>,
|
T: Decode<Error = Err>,
|
||||||
E: Decode<Error = Err>,
|
E: Decode<Error = Err>,
|
||||||
|
@ -595,23 +606,23 @@ where
|
||||||
type Error = EnumDecodeError<bool, Err>;
|
type Error = EnumDecodeError<bool, Err>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let sign = bool::decode(stream)
|
let sign = bool::decode(input)
|
||||||
.map_err(EnumDecodeError::InvalidDiscriminant)?;
|
.map_err(EnumDecodeError::InvalidDiscriminant)?;
|
||||||
|
|
||||||
let this = if sign {
|
let this = if sign {
|
||||||
let value = Decode::decode(stream)
|
let value = Decode::decode(input)
|
||||||
.map_err(EnumDecodeError::Field)?;
|
.map_err(EnumDecodeError::BadField)?;
|
||||||
|
|
||||||
Err(value)
|
Err(value)
|
||||||
} else {
|
} else {
|
||||||
let value = Decode::decode(stream)
|
let value = Decode::decode(input)
|
||||||
.map_err(EnumDecodeError::Field)?;
|
.map_err(EnumDecodeError::BadField)?;
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,11 +632,11 @@ impl<T: Decode> Decode for RwLock<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = Decode::decode(stream)?;
|
let value = Decode::decode(input)?;
|
||||||
|
|
||||||
let this = Self::new(value);
|
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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = Decode::decode(stream)?;
|
let value = Decode::decode(input)?;
|
||||||
|
|
||||||
let this = Self(value);
|
let this = Self(value);
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,17 +656,15 @@ impl Decode for SocketAddr {
|
||||||
type Error = EnumDecodeError<u8, Infallible>;
|
type Error = EnumDecodeError<u8, Infallible>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let discriminant = u8::decode(stream).unwrap();
|
let Ok(discriminant) = u8::decode(input);
|
||||||
|
|
||||||
let this = match discriminant {
|
match discriminant {
|
||||||
0x4 => Self::V4(Decode::decode(stream).unwrap()),
|
0x4 => Result::Ok(Self::V4(Decode::decode(input).unwrap())),
|
||||||
0x6 => Self::V6(Decode::decode(stream).unwrap()),
|
0x6 => Result::Ok(Self::V6(Decode::decode(input).unwrap())),
|
||||||
|
|
||||||
value => return Err(EnumDecodeError::UnassignedDiscriminant { value })
|
value => Err(EnumDecodeError::UnassignedDiscriminant { value }),
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(this)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,12 +672,12 @@ impl Decode for SocketAddrV4 {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let ip = Decode::decode(stream)?;
|
let ip = Decode::decode(input)?;
|
||||||
let port = Decode::decode(stream)?;
|
let port = Decode::decode(input)?;
|
||||||
|
|
||||||
let this = Self::new(ip, port);
|
let this = Self::new(ip, port);
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,14 +685,14 @@ impl Decode for SocketAddrV6 {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let ip = Decode::decode(stream)?;
|
let ip = Decode::decode(input)?;
|
||||||
let port = Decode::decode(stream)?;
|
let port = Decode::decode(input)?;
|
||||||
let flow_info = Decode::decode(stream)?;
|
let flow_info = Decode::decode(input)?;
|
||||||
let scope_id = Decode::decode(stream)?;
|
let scope_id = Decode::decode(input)?;
|
||||||
|
|
||||||
let this = Self::new(ip, port, flow_info, scope_id);
|
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>;
|
type Error = CollectionDecodeError<Infallible, Utf8Error>;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let len = Decode::decode(stream).unwrap();
|
let Ok(len) = Decode::decode(input);
|
||||||
|
|
||||||
let data = stream.read(len);
|
let data = input.read(len).unwrap();
|
||||||
|
|
||||||
str::from_utf8(data)
|
if let Err(e) = str::from_utf8(data) {
|
||||||
.map_err(|e| {
|
let i = e.valid_up_to();
|
||||||
let i = e.valid_up_to();
|
let c = data[i];
|
||||||
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);
|
let mut v = Vec::with_capacity(len);
|
||||||
|
|
||||||
|
@ -718,7 +730,7 @@ impl Decode for String {
|
||||||
|
|
||||||
// SAFETY: We have already tested the raw data.
|
// SAFETY: We have already tested the raw data.
|
||||||
let this = unsafe { Self::from_utf8_unchecked(v) };
|
let this = unsafe { Self::from_utf8_unchecked(v) };
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,8 +740,8 @@ impl Decode for SystemTime {
|
||||||
type Error = SystemTimeDecodeError;
|
type Error = SystemTimeDecodeError;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let time = i64::decode(stream).unwrap();
|
let Ok(time) = i64::decode(input);
|
||||||
|
|
||||||
let this = if time.is_positive() {
|
let this = if time.is_positive() {
|
||||||
let time = time as u64;
|
let time = time as u64;
|
||||||
|
@ -749,8 +761,8 @@ impl Decode for () {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(_stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(_input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,9 +770,9 @@ impl Decode for usize {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = u16::decode(stream)?;
|
let value = u16::decode(input)?;
|
||||||
Ok(value as Self)
|
Result::Ok(value as Self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,15 +782,15 @@ impl<T: Decode> Decode for Vec<T> {
|
||||||
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, T::Error>>;
|
type Error = CollectionDecodeError<Infallible, ItemDecodeError<usize, T::Error>>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let len = Decode::decode(stream).unwrap();
|
let Ok(len) = Decode::decode(input);
|
||||||
|
|
||||||
let mut this = Self::with_capacity(len);
|
let mut this = Self::with_capacity(len);
|
||||||
|
|
||||||
let buf = this.as_mut_ptr();
|
let buf = this.as_mut_ptr();
|
||||||
for i in 0x0..len {
|
for i in 0x0..len {
|
||||||
let value = Decode::decode(stream)
|
let value = Decode::decode(input)
|
||||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }))?;
|
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
|
||||||
|
|
||||||
// SAFETY: Each index is within bounds (i.e. capac-
|
// SAFETY: Each index is within bounds (i.e. capac-
|
||||||
// ity).
|
// ity).
|
||||||
|
@ -788,7 +800,7 @@ impl<T: Decode> Decode for Vec<T> {
|
||||||
// SAFETY: We have initialised the buffer.
|
// SAFETY: We have initialised the buffer.
|
||||||
unsafe { this.set_len(len); }
|
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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let value = Decode::decode(stream)?;
|
let value = Decode::decode(input)?;
|
||||||
|
|
||||||
let this = Self(value);
|
let this = Self(value);
|
||||||
Ok(this)
|
Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_numeric {
|
macro_rules! impl_numeric {
|
||||||
($ty:ty$(,)?) => {
|
($ty:ty$(,)?) => {
|
||||||
impl ::librum::Decode for $ty {
|
impl ::oct::decode::Decode for $ty {
|
||||||
type Error = ::core::convert::Infallible;
|
type Error = ::core::convert::Infallible;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
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 mut data = [::core::default::Default::default(); Self::MAX_ENCODED_SIZE];
|
let mut data = [::core::default::Default::default(); <Self as ::oct::encode::SizedEncode>::MAX_ENCODED_SIZE];
|
||||||
stream.read_into(&mut data);
|
input.read_into(&mut data).unwrap();
|
||||||
|
|
||||||
let this = Self::from_le_bytes(data);
|
let this = Self::from_le_bytes(data);
|
||||||
Ok(this)
|
::core::result::Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -826,19 +838,19 @@ macro_rules! impl_tuple {
|
||||||
$($tys:ident),+$(,)?
|
$($tys:ident),+$(,)?
|
||||||
} => {
|
} => {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl<$($tys, )* E> ::librum::Decode for ($($tys, )*)
|
impl<$($tys, )* E> ::oct::decode::Decode for ($($tys, )*)
|
||||||
where
|
where
|
||||||
$($tys: Decode<Error = E>, )*
|
$($tys: Decode<Error = E>, )*
|
||||||
{
|
{
|
||||||
type Error = E;
|
type Error = E;
|
||||||
|
|
||||||
#[inline(always)]
|
#[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 = (
|
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 {
|
macro_rules! impl_non_zero {
|
||||||
($ty:ty$(,)?) => {
|
($ty:ty$(,)?) => {
|
||||||
impl ::librum::Decode for ::core::num::NonZero<$ty> {
|
impl ::oct::decode::Decode for ::core::num::NonZero<$ty> {
|
||||||
type Error = ::librum::error::NonZeroDecodeError;
|
type Error = ::oct::error::NonZeroDecodeError;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
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 Ok(value) = <$ty as ::librum::Decode>::decode(stream);
|
use ::core::result::Result;
|
||||||
|
|
||||||
let this = ::core::num::NonZero::new(value)
|
let Result::Ok(value) = <$ty as ::oct::decode::Decode>::decode(input);
|
||||||
.ok_or(::librum::error::NonZeroDecodeError)?;
|
|
||||||
|
|
||||||
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(target_has_atomic = $width)]
|
||||||
#[cfg_attr(doc, doc(cfg(target_has_atomic = $width)))]
|
#[cfg_attr(doc, doc(cfg(target_has_atomic = $width)))]
|
||||||
impl ::librum::Decode for $atomic_ty {
|
impl ::oct::decode::Decode for $atomic_ty {
|
||||||
type Error = <$ty as ::librum::Decode>::Error;
|
type Error = <$ty as ::oct::decode::Decode>::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[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 value = ::librum::Decode::decode(stream)?;
|
let value = ::oct::decode::Decode::decode(input)?;
|
||||||
|
|
||||||
let this = Self::new(value);
|
let this = Self::new(value);
|
||||||
Ok(this)
|
::core::result::Result::Ok(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
|
@ -1,32 +1,33 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// 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::char;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
use std::string::String;
|
use std::string::String;
|
||||||
|
|
||||||
macro_rules! test {
|
macro_rules! test {
|
||||||
($ty:ty: $data:expr => $value:expr) => {{
|
($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 left = <$ty as Decode>::decode(&mut stream).unwrap();
|
||||||
let right = $value;
|
let right = $value;
|
||||||
|
@ -101,6 +102,7 @@ fn test_decode_derive() {
|
||||||
Unnamed(i32),
|
Unnamed(i32),
|
||||||
Named { timestamp: u64 },
|
Named { timestamp: u64 },
|
||||||
}
|
}
|
||||||
|
|
||||||
test!(ProcExit: [
|
test!(ProcExit: [
|
||||||
0x01, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x0B, 0x5E,
|
0x01, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x0B, 0x5E,
|
||||||
0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
|
@ -1,25 +1,25 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::Decode;
|
use crate::decode::Decode;
|
||||||
|
|
||||||
use core::borrow::Borrow;
|
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`.
|
/// 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).
|
/// The primary user of this trait is the `Decode` implementation of [`Cow`](alloc::borrow::Cow).
|
||||||
///
|
///
|
||||||
/// # Arrays
|
/// # Arrays
|
|
@ -19,16 +19,18 @@
|
||||||
// er General Public License along with Librum. If
|
// er General Public License along with Librum. If
|
||||||
// not, see <https://www.gnu.org/licenses/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use crate::error::InputError;
|
||||||
|
|
||||||
use core::ptr::copy_nonoverlapping;
|
use core::ptr::copy_nonoverlapping;
|
||||||
use core::slice;
|
use core::slice;
|
||||||
|
|
||||||
/// Byte stream suitable for input.
|
/// Byte stream suitable for reading.
|
||||||
pub struct IStream<'a> {
|
pub struct Input<'a> {
|
||||||
buf: &'a [u8],
|
buf: &'a [u8],
|
||||||
pos: usize,
|
pos: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IStream<'a> {
|
impl<'a> Input<'a> {
|
||||||
/// Constructs a new i-stream.
|
/// Constructs a new i-stream.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[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.
|
/// If the requested amount of bytes could not exactly be read, then this method will panic.
|
||||||
#[inline]
|
#[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;
|
let remaining = self.buf.len() - self.pos;
|
||||||
|
|
||||||
assert!(
|
if remaining < count {
|
||||||
remaining >= count,
|
return Err(InputError {
|
||||||
"cannot read ({count}) bytes at ({}) from stream with capacity of ({})",
|
capacity: self.buf.len(),
|
||||||
self.pos,
|
position: self.pos,
|
||||||
self.buf.len(),
|
count,
|
||||||
);
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let data = unsafe {
|
let data = unsafe {
|
||||||
let ptr = self.buf.as_ptr().add(self.pos);
|
let ptr = self.buf.as_ptr().add(self.pos);
|
||||||
|
@ -62,7 +65,7 @@ impl<'a> IStream<'a> {
|
||||||
|
|
||||||
self.pos += count;
|
self.pos += count;
|
||||||
|
|
||||||
data
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads bytes from the stream into a predefined buffer.
|
/// 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.
|
/// If the provided buffer could not be completely filled, then this method will panic.
|
||||||
#[inline]
|
#[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 count = buf.len();
|
||||||
let remaining = self.buf.len() - self.pos;
|
let remaining = self.remaining();
|
||||||
|
|
||||||
assert!(
|
if remaining < count {
|
||||||
remaining >= count,
|
return Err(InputError {
|
||||||
"cannot read ({count}) bytes at ({}) from stream with capacity of ({})",
|
capacity: self.buf.len(),
|
||||||
self.pos,
|
position: self.pos,
|
||||||
self.buf.len(),
|
count,
|
||||||
);
|
});
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let src = self.buf.as_ptr().add(self.pos);
|
let src = self.buf.as_ptr().add(self.pos);
|
||||||
|
@ -92,15 +96,30 @@ impl<'a> IStream<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pos += count;
|
self.pos += count;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Closes the stream.
|
/// Retrieves the maximum capacity of the input stream.
|
||||||
///
|
|
||||||
/// The total ammount of bytes read is returned.
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const fn close(self) -> usize {
|
#[must_use]
|
||||||
let Self { pos, .. } = self;
|
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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use crate::OStream;
|
use crate::encode::Output;
|
||||||
use crate::error::{
|
use crate::error::{
|
||||||
CollectionEncodeError,
|
CollectionEncodeError,
|
||||||
EnumEncodeError,
|
EnumEncodeError,
|
||||||
|
@ -96,7 +96,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
/// It is recommended to simply derive this trait for custom types.
|
/// It is recommended to simply derive this trait for custom types.
|
||||||
/// It can, of course, also just be manually implemented.
|
/// 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
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -107,7 +107,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
/// // plementation is equivalent to what would have
|
/// // plementation is equivalent to what would have
|
||||||
/// // been derived.
|
/// // been derived.
|
||||||
///
|
///
|
||||||
/// use librum::{Encode, OStream};
|
/// use oct::encode::{Encode, Output};
|
||||||
/// use core::convert::Infallible;
|
/// use core::convert::Infallible;
|
||||||
///
|
///
|
||||||
/// struct Foo {
|
/// struct Foo {
|
||||||
|
@ -120,13 +120,13 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
///
|
///
|
||||||
/// type Error = Infallible;
|
/// 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.
|
/// // Encode fields using chaining.
|
||||||
///
|
///
|
||||||
/// self.bar.encode(stream)?;
|
/// self.bar.encode(output)?;
|
||||||
/// self.baz.encode(stream)?;
|
/// self.baz.encode(output)?;
|
||||||
///
|
///
|
||||||
/// Ok(())
|
/// Result::Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -134,7 +134,7 @@ pub trait Encode {
|
||||||
/// The type returned in case of error.
|
/// The type returned in case of error.
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
/// Encodes `self` into the provided stream.
|
/// Encodes `self` into the provided output.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
|
@ -142,16 +142,16 @@ pub trait Encode {
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// If `stream` cannot contain the entirety of the resulting encoding, then this method should panic.
|
/// If `output` cannot contain the entirety of the resulting encoding, then this method should panic.
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error>;
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Encode + ?Sized> Encode for &T {
|
impl<T: Encode + ?Sized> Encode for &T {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
T::encode(self, stream)
|
T::encode(self, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,8 +159,8 @@ impl<T: Encode + ?Sized> Encode for &mut T {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
T::encode(self, stream)
|
T::encode(self, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,8 +170,8 @@ impl<T: Encode> Encode for (T, ) {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.0.encode(stream)
|
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>>;
|
type Error = CollectionEncodeError<Infallible, ItemEncodeError<usize, T::Error>>;
|
||||||
|
|
||||||
/// Encodes each element sequentially.
|
/// 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)]
|
#[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() {
|
for (i, v) in self.iter().enumerate() {
|
||||||
v
|
v
|
||||||
.encode(stream)
|
.encode(output)
|
||||||
.map_err(|e| CollectionEncodeError::Item(ItemEncodeError { index: i, error: e }))?;
|
.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.
|
/// Encodes each element sequentially with an extra length specifier (of type [`usize`]) prepended first.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self
|
self
|
||||||
.len()
|
.len()
|
||||||
.encode(stream)
|
.encode(output)
|
||||||
.map_err(CollectionEncodeError::Length)?;
|
.map_err(CollectionEncodeError::BadLength)?;
|
||||||
|
|
||||||
for (i,v) in self.iter().enumerate() {
|
for (i,v) in self.iter().enumerate() {
|
||||||
v
|
v
|
||||||
.encode(stream)
|
.encode(output)
|
||||||
.map_err(|e| CollectionEncodeError::Item(ItemEncodeError { index: i, error: e }))?;
|
.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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
T::encode(self, stream)
|
T::encode(self, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encode for bool {
|
impl Encode for bool {
|
||||||
type Error = <u8 as Encode>::Error;
|
type Error = <u8 as Encode>::Error;
|
||||||
|
|
||||||
|
/// Encodes the raw representationf of the boolean.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
u8::from(*self).encode(stream)
|
u8::from(*self).encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,24 +239,24 @@ impl<T: Encode> Encode for Bound<T> {
|
||||||
type Error = EnumEncodeError<u8, T::Error>;
|
type Error = EnumEncodeError<u8, T::Error>;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
Self::Included(ref bound) => {
|
Self::Included(ref bound) => {
|
||||||
0x0u8.encode(stream).unwrap();
|
let Ok(_) = 0x0u8.encode(output);
|
||||||
bound.encode(stream).map_err(EnumEncodeError::Field)?;
|
bound.encode(output).map_err(EnumEncodeError::BadField)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::Excluded(ref bound) => {
|
Self::Excluded(ref bound) => {
|
||||||
0x1u8.encode(stream).unwrap();
|
let Ok(_) = 0x1u8.encode(output);
|
||||||
bound.encode(stream).map_err(EnumEncodeError::Field)?;
|
bound.encode(output).map_err(EnumEncodeError::BadField)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::Unbounded => {
|
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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
T::encode(self, stream)
|
T::encode(self, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,8 +275,8 @@ impl<T: Copy + Encode> Encode for Cell<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.get().encode(stream)
|
self.get().encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,8 +284,8 @@ impl Encode for char {
|
||||||
type Error = <u32 as Encode>::Error;
|
type Error = <u32 as Encode>::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
u32::from(*self).encode(stream)
|
u32::from(*self).encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,8 +295,8 @@ impl<T: Encode + ?Sized + ToOwned> Encode for Cow<'_, T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
T::encode(self, stream)
|
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.
|
/// Encodes the string identically to [a byte slice](slice) containing the string's byte values **excluding** the null terminator.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.to_bytes().encode(stream)
|
self.to_bytes().encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,8 +317,8 @@ impl Encode for CString {
|
||||||
|
|
||||||
/// See the the implementation of [`CStr`].
|
/// See the the implementation of [`CStr`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.as_c_str().encode(stream)
|
self.as_c_str().encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,11 +327,11 @@ impl Encode for Duration {
|
||||||
|
|
||||||
/// Encodes the duration's seconds and nanoseconds counters sequentially.
|
/// Encodes the duration's seconds and nanoseconds counters sequentially.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.as_secs().encode(stream).unwrap();
|
self.as_secs().encode(output)?;
|
||||||
self.subsec_nanos().encode(stream).unwrap();
|
self.subsec_nanos().encode(output)?;
|
||||||
|
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,13 +346,13 @@ where
|
||||||
type Error = E;
|
type Error = E;
|
||||||
|
|
||||||
#[inline(always)]
|
#[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 {
|
for (key, value) in self {
|
||||||
key.encode(stream)?;
|
key.encode(output)?;
|
||||||
value.encode(stream)?;
|
value.encode(output)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,12 +366,12 @@ where
|
||||||
type Error = K::Error;
|
type Error = K::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
for key in self {
|
for key in self {
|
||||||
key.encode(stream)?;
|
key.encode(output)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,9 +381,9 @@ impl Encode for Infallible {
|
||||||
type Error = Self;
|
type Error = Self;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, _stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, _output: &mut Output) -> Result<(), Self::Error> {
|
||||||
// SAFETY: `Infallible` can **never** be construct-
|
// SAFETY: `Infallible` objects can never be con-
|
||||||
// ed.
|
// structed
|
||||||
unsafe { unreachable_unchecked() }
|
unsafe { unreachable_unchecked() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -393,22 +395,22 @@ impl Encode for IpAddr {
|
||||||
///
|
///
|
||||||
/// See also the implementations of [`Ipv4Addr`] and [`Ipv6Addr`].
|
/// See also the implementations of [`Ipv4Addr`] and [`Ipv6Addr`].
|
||||||
#[inline(always)]
|
#[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.
|
// The discriminant here is the IP version.
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Self::V4(ref addr) => {
|
Self::V4(ref addr) => {
|
||||||
0x4u8.encode(stream).map_err(EnumEncodeError::Discriminant)?;
|
0x4u8.encode(output).map_err(EnumEncodeError::BadDiscriminant)?;
|
||||||
addr.encode(stream).map_err(EnumEncodeError::Field)?;
|
addr.encode(output).map_err(EnumEncodeError::BadField)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::V6(ref addr) => {
|
Self::V6(ref addr) => {
|
||||||
0x6u8.encode(stream).map_err(EnumEncodeError::Discriminant)?;
|
0x6u8.encode(output).map_err(EnumEncodeError::BadDiscriminant)?;
|
||||||
addr.encode(stream).map_err(EnumEncodeError::Field)?;
|
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.
|
/// Encodes the address's bits in big-endian.
|
||||||
#[inline(always)]
|
#[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();
|
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.
|
/// Encodes the address's bits in big-endian.
|
||||||
#[inline(always)]
|
#[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();
|
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.
|
/// Casts `self` to [`i16`] and encodes the result.
|
||||||
#[inline]
|
#[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)
|
let value = i16::try_from(*self)
|
||||||
.map_err(|_| IsizeEncodeError(*self))?;
|
.map_err(|_| IsizeEncodeError(*self))?;
|
||||||
|
|
||||||
value.encode(stream).unwrap();
|
let Ok(_) = value.encode(output);
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,8 +454,8 @@ impl<T: Encode> Encode for LazyCell<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
T::encode(self, stream)
|
T::encode(self, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,8 +465,8 @@ impl<T: Encode> Encode for LazyLock<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
T::encode(self, stream)
|
T::encode(self, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,19 +476,19 @@ impl<T: Encode<Error = E>, E> Encode for LinkedList<T> {
|
||||||
type Error = CollectionEncodeError<UsizeEncodeError, (usize, E)>;
|
type Error = CollectionEncodeError<UsizeEncodeError, (usize, E)>;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self
|
self
|
||||||
.len()
|
.len()
|
||||||
.encode(stream)
|
.encode(output)
|
||||||
.map_err(CollectionEncodeError::Length)?;
|
.map_err(CollectionEncodeError::BadLength)?;
|
||||||
|
|
||||||
for (i, v) in self.iter().enumerate() {
|
for (i, v) in self.iter().enumerate() {
|
||||||
v
|
v
|
||||||
.encode(stream)
|
.encode(output)
|
||||||
.map_err(|e| CollectionEncodeError::Item((i, e)))?;
|
.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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self
|
self
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
.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.
|
/// This is `false` for `None` instances and `true` for `Some` instances.
|
||||||
///
|
///
|
||||||
/// If `Some`, then the contained value is encoded after this sign..
|
/// 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 {
|
match *self {
|
||||||
None => {
|
None => {
|
||||||
false.encode(stream).unwrap();
|
false
|
||||||
|
.encode(output)
|
||||||
|
.map_err::<Self::Error, _>(|_v| unreachable!())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(ref v) => {
|
Some(ref v) => {
|
||||||
true.encode(stream).unwrap();
|
true
|
||||||
v.encode(stream)?;
|
.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;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, _stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, _output: &mut Output) -> Result<(), Self::Error> {
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,8 +547,8 @@ impl Encode for PhantomPinned {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, _stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, _output: &mut Output) -> Result<(), Self::Error> {
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,11 +556,11 @@ impl<T: Encode> Encode for Range<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.start.encode(stream)?;
|
self.start.encode(output)?;
|
||||||
self.end.encode(stream)?;
|
self.end.encode(output)?;
|
||||||
|
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,8 +568,8 @@ impl<T: Encode> Encode for RangeFrom<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.start.encode(stream)
|
self.start.encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,8 +577,8 @@ impl Encode for RangeFull {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, _stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, _output: &mut Output) -> Result<(), Self::Error> {
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,11 +586,11 @@ impl<T: Encode> Encode for RangeInclusive<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.start().encode(stream)?;
|
self.start().encode(output)?;
|
||||||
self.end().encode(stream)?;
|
self.end().encode(output)?;
|
||||||
|
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,8 +598,8 @@ impl<T: Encode> Encode for RangeTo<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.end.encode(stream)
|
self.end.encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,10 +607,10 @@ impl<T: Encode> Encode for RangeToInclusive<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.end.encode(stream)?;
|
self.end.encode(output)?;
|
||||||
|
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,8 +620,8 @@ impl<T: Encode + ?Sized> Encode for Rc<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
T::encode(self, stream)
|
T::encode(self, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,21 +629,22 @@ impl<T: Encode + ?Sized> Encode for RefCell<T> {
|
||||||
type Error = RefCellEncodeError<T::Error>;
|
type Error = RefCellEncodeError<T::Error>;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
let value = self.try_borrow()
|
let value = self
|
||||||
.map_err(RefCellEncodeError::Borrow)?;
|
.try_borrow()
|
||||||
|
.map_err(RefCellEncodeError::BadBorrow)?;
|
||||||
|
|
||||||
T::encode(&value, stream)
|
T::encode(&value, output)
|
||||||
.map_err(RefCellEncodeError::Value)?;
|
.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
|
where
|
||||||
T: Encode<Error = Err>,
|
T: Encode<Error = Err>,
|
||||||
E: Encode<Error = Err>,
|
E: Encode<Error: Into<Err>>,
|
||||||
{
|
{
|
||||||
type Error = Err;
|
type Error = Err;
|
||||||
|
|
||||||
|
@ -645,23 +653,25 @@ where
|
||||||
///
|
///
|
||||||
/// If `Ok`, then the contained value is encoded after this sign.
|
/// If `Ok`, then the contained value is encoded after this sign.
|
||||||
#[inline]
|
#[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
|
// The sign here is `false` for `Ok` objects and
|
||||||
// `true` for `Err` objects.
|
// `true` for `Err` objects.
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Ok(ref v) => {
|
Ok(ref v) => {
|
||||||
false.encode(stream).unwrap();
|
let Ok(_) = false.encode(output);
|
||||||
v.encode(stream)?;
|
|
||||||
|
v.encode(output)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(ref e) => {
|
Err(ref e) => {
|
||||||
true.encode(stream).unwrap();
|
let Ok(_) = true.encode(output);
|
||||||
e.encode(stream)?;
|
|
||||||
|
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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self
|
self
|
||||||
.read()
|
.read()
|
||||||
.or_else(|e| Ok(e.into_inner()))?
|
.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;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.0.encode(stream)
|
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 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`]).
|
/// This is then followed by the respective address' own encoding (either [`SocketAddrV4`] or [`SocketAddrV6`]).
|
||||||
#[inline]
|
#[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.
|
// The discriminant here is the IP version.
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Self::V4(ref addr) => {
|
Self::V4(ref addr) => {
|
||||||
0x4u8.encode(stream)?;
|
0x4u8.encode(output)?;
|
||||||
addr.encode(stream)?;
|
addr.encode(output)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::V6(ref addr) => {
|
Self::V6(ref addr) => {
|
||||||
0x6u8.encode(stream)?;
|
0x6u8.encode(output)?;
|
||||||
addr.encode(stream)?;
|
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.
|
/// Encodes the address's bits followed by the port number, both of which in big-endian.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.ip().encode(stream)?;
|
self.ip().encode(output)?;
|
||||||
self.port().encode(stream)?;
|
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.
|
/// Encodes the address's bits followed by the port number, flow information, and scope identifier -- all of which in big-endian.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.ip().encode(stream)?;
|
self.ip().encode(output)?;
|
||||||
self.port().encode(stream)?;
|
self.port().encode(output)?;
|
||||||
self.flowinfo().encode(stream)?;
|
self.flowinfo().encode(output)?;
|
||||||
self.scope_id().encode(stream)?;
|
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.
|
/// Encodes the string identically to [a byte slice](slice) containing the string's byte values.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.as_bytes().encode(stream)
|
self.as_bytes().encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,8 +768,8 @@ impl Encode for String {
|
||||||
|
|
||||||
/// See [`str`].
|
/// See [`str`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.as_str().encode(stream)
|
self.as_str().encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,7 +782,7 @@ impl Encode for SystemTime {
|
||||||
///
|
///
|
||||||
/// Examples of some timestamps and their encodings include:
|
/// Examples of some timestamps and their encodings include:
|
||||||
///
|
///
|
||||||
/// | ISO 8601 | UNIX / Librum |
|
/// | ISO 8601 | UNIX / oct |
|
||||||
/// | :-------------------------- | -------------: |
|
/// | :-------------------------- | -------------: |
|
||||||
/// | `2024-11-03T12:02:01+01:00` | +1730631721 |
|
/// | `2024-11-03T12:02:01+01:00` | +1730631721 |
|
||||||
/// | `1989-06-03T20:00:00+09:00` | +13258800 |
|
/// | `1989-06-03T20:00:00+09:00` | +13258800 |
|
||||||
|
@ -780,7 +790,7 @@ impl Encode for SystemTime {
|
||||||
/// | `1945-05-04T18:30:00+02:00` | -778231800 |
|
/// | `1945-05-04T18:30:00+02:00` | -778231800 |
|
||||||
#[expect(clippy::cast_possible_wrap)]
|
#[expect(clippy::cast_possible_wrap)]
|
||||||
#[inline]
|
#[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 time = if *self >= UNIX_EPOCH {
|
||||||
let duration = self
|
let duration = self
|
||||||
.duration_since(UNIX_EPOCH)
|
.duration_since(UNIX_EPOCH)
|
||||||
|
@ -795,8 +805,8 @@ impl Encode for SystemTime {
|
||||||
0x0 - duration.as_secs() as i64
|
0x0 - duration.as_secs() as i64
|
||||||
};
|
};
|
||||||
|
|
||||||
time.encode(stream).unwrap();
|
time.encode(output)?;
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,8 +814,8 @@ impl Encode for () {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, _stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, _output: &mut Output) -> Result<(), Self::Error> {
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -814,12 +824,12 @@ impl Encode for usize {
|
||||||
|
|
||||||
/// Casts `self` to [`u16`] and encodes the result.
|
/// Casts `self` to [`u16`] and encodes the result.
|
||||||
#[inline]
|
#[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)
|
let value = u16::try_from(*self)
|
||||||
.map_err(|_| UsizeEncodeError(*self))?;
|
.map_err(|_e| UsizeEncodeError(*self))?;
|
||||||
|
|
||||||
value.encode(stream).unwrap();
|
let Ok(_) = value.encode(output);
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -829,8 +839,8 @@ impl<T: Encode> Encode for Vec<T> {
|
||||||
type Error = <[T] as Encode>::Error;
|
type Error = <[T] as Encode>::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.as_slice().encode(stream)
|
self.as_slice().encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,21 +848,21 @@ impl<T: Encode> Encode for Wrapping<T> {
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.0.encode(stream)
|
self.0.encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_numeric {
|
macro_rules! impl_numeric {
|
||||||
($ty:ty$(,)?) => {
|
($ty:ty$(,)?) => {
|
||||||
impl ::librum::Encode for $ty {
|
impl ::oct::encode::Encode for $ty {
|
||||||
type Error = ::core::convert::Infallible;
|
type Error = ::core::convert::Infallible;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn encode(&self, stream: &mut OStream) -> ::core::result::Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> ::core::result::Result<(), Self::Error> {
|
||||||
stream.write(&self.to_le_bytes());
|
output.write(&self.to_le_bytes()).unwrap();
|
||||||
|
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -863,20 +873,20 @@ macro_rules! impl_tuple {
|
||||||
$($captures:ident: $tys:ident),+$(,)?
|
$($captures:ident: $tys:ident),+$(,)?
|
||||||
} => {
|
} => {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl<$($tys, )* E> ::librum::Encode for ($($tys, )*)
|
impl<$($tys, )* E> ::oct::encode::Encode for ($($tys, )*)
|
||||||
where
|
where
|
||||||
$($tys: Encode<Error = E>, )* {
|
$($tys: Encode<Error = E>, )* {
|
||||||
type Error = E;
|
type Error = E;
|
||||||
|
|
||||||
#[inline(always)]
|
#[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;
|
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 {
|
macro_rules! impl_non_zero {
|
||||||
($ty:ty$(,)?) => {
|
($ty:ty$(,)?) => {
|
||||||
impl ::librum::Encode for ::core::num::NonZero<$ty> {
|
impl ::oct::encode::Encode for ::core::num::NonZero<$ty> {
|
||||||
type Error = <$ty as ::librum::Encode>::Error;
|
type Error = <$ty as ::oct::encode::Encode>::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> ::core::result::Result<(), Self::Error> {
|
fn encode(&self, output: &mut ::oct::encode::Output) -> ::core::result::Result<(), Self::Error> {
|
||||||
self.get().encode(stream)
|
self.get().encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -903,15 +913,17 @@ macro_rules! impl_atomic {
|
||||||
} => {
|
} => {
|
||||||
#[cfg(target_has_atomic = $width)]
|
#[cfg(target_has_atomic = $width)]
|
||||||
#[cfg_attr(doc, doc(cfg(target_has_atomic = $width)))]
|
#[cfg_attr(doc, doc(cfg(target_has_atomic = $width)))]
|
||||||
impl ::librum::Encode for $atomic_ty {
|
impl ::oct::encode::Encode for $atomic_ty {
|
||||||
type Error = <$ty as ::librum::Encode>::Error;
|
type Error = <$ty as ::oct::encode::Encode>::Error;
|
||||||
|
|
||||||
/// Encodes the atomic with the same scheme as that of the atomic type's primitive counterpart.
|
/// 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.
|
/// The atomic object itself is read with the [`Relaxed`](core::sync::atomic::Ordering) ordering scheme.
|
||||||
#[inline(always)]
|
#[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> {
|
||||||
self.load(::std::sync::atomic::Ordering::Relaxed).encode(stream)
|
use ::std::sync::atomic::Ordering;
|
||||||
|
|
||||||
|
self.load(Ordering::Relaxed).encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// Copyright 2024 Gabriel Bjørnager Jensen.
|
||||||
//
|
//
|
||||||
// This file is part of librum.
|
// This file is part of oct.
|
||||||
//test!(you can redistribut => []);
|
//test!(you can redistribut => []);
|
||||||
// it and/or modify it under the terms of the GNU
|
// it and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
|
@ -8,17 +8,18 @@
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// 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::Duration;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
@ -30,10 +31,10 @@ macro_rules! test {
|
||||||
|
|
||||||
let mut buf = vec![0x00; data.len()];
|
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();
|
<$ty as Encode>::encode(&$value, &mut stream).unwrap();
|
||||||
|
|
||||||
let len = stream.close();
|
let len = stream.position();
|
||||||
assert_eq!(&buf[..len], data.as_slice());
|
assert_eq!(&buf[..len], data.as_slice());
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
@ -68,7 +69,7 @@ fn test_encode() {
|
||||||
0xB1, 0x03, 0x00, 0x00,
|
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]);
|
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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use crate::Encode;
|
use crate::encode::Encode;
|
||||||
|
|
||||||
use core::cell::{Cell, LazyCell, RefCell};
|
use core::cell::{Cell, LazyCell, RefCell};
|
||||||
use core::convert::Infallible;
|
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.
|
/// 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.
|
/// 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 {
|
pub trait SizedEncode: Encode + Sized {
|
||||||
/// The maximum guaranteed amount of bytes that can result from an encoding.
|
/// 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 {
|
macro_rules! impl_numeric {
|
||||||
($ty:ty$(,)?) => {
|
($ty:ty$(,)?) => {
|
||||||
impl ::librum::SizedEncode for $ty {
|
impl ::oct::encode::SizedEncode for $ty {
|
||||||
const MAX_ENCODED_SIZE: usize = size_of::<$ty>();
|
const MAX_ENCODED_SIZE: usize = size_of::<$ty>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -289,18 +289,18 @@ macro_rules! impl_tuple {
|
||||||
$($tys:ident),+$(,)?
|
$($tys:ident),+$(,)?
|
||||||
} => {
|
} => {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl<$($tys, )* E> ::librum::SizedEncode for ($($tys, )*)
|
impl<$($tys, )* E> ::oct::encode::SizedEncode for ($($tys, )*)
|
||||||
where
|
where
|
||||||
$($tys: SizedEncode + Encode<Error = E>, )* {
|
$($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 {
|
macro_rules! impl_non_zero {
|
||||||
($ty:ty$(,)?) => {
|
($ty:ty$(,)?) => {
|
||||||
impl ::librum::SizedEncode for ::core::num::NonZero<$ty> {
|
impl ::oct::encode::SizedEncode for ::core::num::NonZero<$ty> {
|
||||||
const MAX_ENCODED_SIZE: usize = <$ty as ::librum::SizedEncode>::MAX_ENCODED_SIZE;
|
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(target_has_atomic = $width)]
|
||||||
#[cfg_attr(doc, doc(cfg(target_has_atomic = $width)))]
|
#[cfg_attr(doc, doc(cfg(target_has_atomic = $width)))]
|
||||||
impl ::librum::SizedEncode for $atomic_ty {
|
impl ::oct::encode::SizedEncode for $atomic_ty {
|
||||||
const MAX_ENCODED_SIZE: usize = <$ty as ::librum::SizedEncode>::MAX_ENCODED_SIZE;
|
const MAX_ENCODED_SIZE: usize = <$ty as ::oct::encode::SizedEncode>::MAX_ENCODED_SIZE;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,25 +1,26 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// 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::convert::Infallible;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::net::{
|
use std::net::{
|
||||||
|
@ -34,7 +35,7 @@ use std::num::NonZero;
|
||||||
|
|
||||||
macro_rules! assert_encoded_size {
|
macro_rules! assert_encoded_size {
|
||||||
($ty:ty, $value:expr$(,)?) => {{
|
($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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::error::Error;
|
use core::error::Error;
|
||||||
|
@ -24,7 +24,7 @@ use core::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
/// A C-like string could not be decoded.
|
/// 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).
|
/// 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.
|
/// 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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::error::Error;
|
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.
|
/// 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.
|
/// 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)]
|
#[derive(Debug)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct CharDecodeError {
|
pub struct CharDecodeError {
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
|
@ -26,11 +26,11 @@ use core::fmt::{self, Display, Formatter};
|
||||||
/// A collection could not be decoded.
|
/// A collection could not be decoded.
|
||||||
///
|
///
|
||||||
/// This type is intended as a partially-generic decode error for collections.
|
/// 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.
|
/// 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)]
|
#[derive(Debug)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub enum CollectionDecodeError<L, I> {
|
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).
|
/// 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`.
|
/// 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.
|
/// A collection item could not be decoded.
|
||||||
///
|
///
|
||||||
/// Sometimes the index of the item may be desired.
|
/// Sometimes the index of the item may be desired.
|
||||||
/// In these cases the [`ItemDecodeError`](crate::error::ItemDecodeError) could be used here.
|
/// In these cases the [`ItemDecodeError`](crate::error::ItemDecodeError) could be used here.
|
||||||
Item(I),
|
BadItem(I),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, I> Display for CollectionDecodeError<L, I>
|
impl<L, I> Display for CollectionDecodeError<L, I>
|
||||||
|
@ -55,13 +55,11 @@ where
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
use CollectionDecodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Length(ref e)
|
Self::BadLength(ref e)
|
||||||
=> write!(f, "unable to decode collection length: {e}"),
|
=> write!(f, "unable to decode collection length: {e}"),
|
||||||
|
|
||||||
Item(ref e)
|
Self::BadItem(ref e)
|
||||||
=> write!(f, "unable to decode collection item: {e}"),
|
=> write!(f, "unable to decode collection item: {e}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,12 +72,10 @@ where
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
use CollectionDecodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
|
@ -26,15 +26,15 @@ use core::fmt::{self, Display, Formatter};
|
||||||
/// A collection could not be encoded.
|
/// A collection could not be encoded.
|
||||||
///
|
///
|
||||||
/// This type is intended as a partially-generic encode error for collections.
|
/// 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)]
|
#[derive(Debug)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub enum CollectionEncodeError<L, I> {
|
pub enum CollectionEncodeError<L, I> {
|
||||||
/// The collection length could not be encoded.
|
/// The collection length could not be encoded.
|
||||||
Length(L),
|
BadLength(L),
|
||||||
|
|
||||||
/// A collection item could not be encoded.
|
/// A collection item could not be encoded.
|
||||||
Item(I),
|
BadItem(I),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, I> Display for CollectionEncodeError<L, I>
|
impl<L, I> Display for CollectionEncodeError<L, I>
|
||||||
|
@ -44,13 +44,11 @@ where
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
use CollectionEncodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Length(ref e)
|
Self::BadLength(ref e)
|
||||||
=> write!(f, "unable to encode collection length: {e}"),
|
=> write!(f, "unable to encode collection length: {e}"),
|
||||||
|
|
||||||
Item(ref e)
|
Self::BadItem(ref e)
|
||||||
=> write!(f, "unable to encode collection item: {e}"),
|
=> write!(f, "unable to encode collection item: {e}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,12 +61,10 @@ where
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
use CollectionEncodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
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!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::Decode;
|
use crate::decode::Decode;
|
||||||
|
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use core::error::Error;
|
use core::error::Error;
|
||||||
|
@ -42,7 +42,7 @@ pub enum EnumDecodeError<D: Decode, F> {
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A field could not be encoded.
|
/// A field could not be encoded.
|
||||||
Field(F),
|
BadField(F),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D, F> Display for EnumDecodeError<D, F>
|
impl<D, F> Display for EnumDecodeError<D, F>
|
||||||
|
@ -52,16 +52,14 @@ where
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
use EnumDecodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
InvalidDiscriminant(ref e)
|
Self::InvalidDiscriminant(ref e)
|
||||||
=> write!(f, "discriminant could not be decoded: {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"),
|
=> 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}"),
|
=> write!(f, "variant could not be decoded: {e}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,12 +72,10 @@ where
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
use EnumDecodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
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,
|
_ => None,
|
||||||
}
|
}
|
|
@ -1,25 +1,25 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::Encode;
|
use crate::encode::Encode;
|
||||||
|
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use core::error::Error;
|
use core::error::Error;
|
||||||
|
@ -30,10 +30,10 @@ use core::fmt::{self, Debug, Display, Formatter};
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub enum EnumEncodeError<D: Encode, F> {
|
pub enum EnumEncodeError<D: Encode, F> {
|
||||||
/// The discriminant could not be encoded.
|
/// The discriminant could not be encoded.
|
||||||
Discriminant(D::Error),
|
BadDiscriminant(D::Error),
|
||||||
|
|
||||||
/// A field could not be encoded.
|
/// A field could not be encoded.
|
||||||
Field(F),
|
BadField(F),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D, F> Display for EnumEncodeError<D, F>
|
impl<D, F> Display for EnumEncodeError<D, F>
|
||||||
|
@ -43,13 +43,11 @@ where
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
use EnumEncodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Discriminant(ref e)
|
Self::BadDiscriminant(ref e)
|
||||||
=> write!(f, "discriminant could not be encoded: {e}"),
|
=> write!(f, "discriminant could not be encoded: {e}"),
|
||||||
|
|
||||||
Field(ref e)
|
Self::BadField(ref e)
|
||||||
=> write!(f, "field could not be encoded: {e}"),
|
=> write!(f, "field could not be encoded: {e}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,12 +60,10 @@ where
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
use EnumEncodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{Decode, PrimitiveDiscriminant};
|
use crate::PrimitiveDiscriminant;
|
||||||
|
use crate::decode::Decode;
|
||||||
use crate::error::{
|
use crate::error::{
|
||||||
BoolDecodeError,
|
|
||||||
CollectionDecodeError,
|
CollectionDecodeError,
|
||||||
CStringDecodeError,
|
|
||||||
EnumDecodeError,
|
EnumDecodeError,
|
||||||
ItemDecodeError,
|
ItemDecodeError,
|
||||||
NonZeroDecodeError,
|
NonZeroDecodeError,
|
||||||
SizeError,
|
LengthError,
|
||||||
Utf8Error,
|
Utf8Error,
|
||||||
SystemTimeDecodeError,
|
SystemTimeDecodeError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
use crate::error::CStringDecodeError;
|
||||||
|
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use core::error::Error;
|
use core::error::Error;
|
||||||
use core::fmt::{self, Display, Formatter};
|
use core::fmt::{self, Display, Formatter};
|
||||||
|
@ -48,9 +50,6 @@ pub enum GenericDecodeError {
|
||||||
/// A string contained a non-UTF-8 sequence.
|
/// A string contained a non-UTF-8 sequence.
|
||||||
BadString(Utf8Error),
|
BadString(Utf8Error),
|
||||||
|
|
||||||
/// A boolean was neither `false` nor `true`.
|
|
||||||
InvalidBool(BoolDecodeError),
|
|
||||||
|
|
||||||
/// A C-like string contained a null byte.
|
/// A C-like string contained a null byte.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "std")))]
|
#[cfg_attr(doc, doc(cfg(feature = "std")))]
|
||||||
|
@ -60,7 +59,7 @@ pub enum GenericDecodeError {
|
||||||
NullInteger(NonZeroDecodeError),
|
NullInteger(NonZeroDecodeError),
|
||||||
|
|
||||||
/// A statically-sized buffer was too small.
|
/// A statically-sized buffer was too small.
|
||||||
SmallBuffer(SizeError),
|
SmallBuffer(LengthError),
|
||||||
|
|
||||||
/// An unassigned discriminant value was encountered.
|
/// An unassigned discriminant value was encountered.
|
||||||
///
|
///
|
||||||
|
@ -79,29 +78,24 @@ pub enum GenericDecodeError {
|
||||||
impl Display for GenericDecodeError {
|
impl Display for GenericDecodeError {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
use GenericDecodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
BadString(ref e)
|
Self::BadString(ref e)
|
||||||
=> write!(f, "{e}"),
|
=> write!(f, "{e}"),
|
||||||
|
|
||||||
InvalidBool(ref e)
|
Self::NullString(ref e)
|
||||||
=> write!(f, "{e}"),
|
=> write!(f, "{e}"),
|
||||||
|
|
||||||
NullString(ref e)
|
Self::NullInteger(ref e)
|
||||||
=> write!(f, "{e}"),
|
=> write!(f, "{e}"),
|
||||||
|
|
||||||
NullInteger(ref e)
|
Self::SmallBuffer(ref e)
|
||||||
=> write!(f, "{e}"),
|
=> write!(f, "{e}"),
|
||||||
|
|
||||||
SmallBuffer(ref e)
|
Self::UnassignedDiscriminant { value }
|
||||||
=> write!(f, "{e}"),
|
|
||||||
|
|
||||||
UnassignedDiscriminant { value }
|
|
||||||
=> write!(f, "discriminant value `{value:#X} has not been assigned"),
|
=> write!(f, "discriminant value `{value:#X} has not been assigned"),
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
NarrowSystemTime(ref e)
|
Self::NarrowSystemTime(ref e)
|
||||||
=> write!(f, "{e}"),
|
=> write!(f, "{e}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,35 +104,24 @@ impl Display for GenericDecodeError {
|
||||||
impl Error for GenericDecodeError {
|
impl Error for GenericDecodeError {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
use GenericDecodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
BadString(ref e) => Some(e),
|
Self::BadString(ref e) => Some(e),
|
||||||
|
|
||||||
InvalidBool(ref e) => Some(e),
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[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")]
|
#[cfg(feature = "std")]
|
||||||
NarrowSystemTime(ref e) => Some(e),
|
Self::NarrowSystemTime(ref e) => Some(e),
|
||||||
|
|
||||||
_ => None,
|
_ => 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
|
impl<L, I> From<CollectionDecodeError<L, I>> for GenericDecodeError
|
||||||
where
|
where
|
||||||
L: Into<Self>,
|
L: Into<Self>,
|
||||||
|
@ -146,16 +129,25 @@ where
|
||||||
{
|
{
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: CollectionDecodeError<L, I>) -> Self {
|
fn from(value: CollectionDecodeError<L, I>) -> Self {
|
||||||
use CollectionDecodeError::*;
|
use CollectionDecodeError as Error;
|
||||||
|
|
||||||
match value {
|
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
|
impl<D, F> From<EnumDecodeError<D, F>> for GenericDecodeError
|
||||||
where
|
where
|
||||||
D: Decode<Error: Into<Self>> + PrimitiveDiscriminant,
|
D: Decode<Error: Into<Self>> + PrimitiveDiscriminant,
|
||||||
|
@ -163,14 +155,14 @@ where
|
||||||
{
|
{
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: EnumDecodeError<D, F>) -> Self {
|
fn from(value: EnumDecodeError<D, F>) -> Self {
|
||||||
use EnumDecodeError::*;
|
use EnumDecodeError as Error;
|
||||||
|
|
||||||
match value {
|
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 {
|
impl From<Infallible> for GenericDecodeError {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(_value: Infallible) -> Self {
|
fn from(_value: Infallible) -> Self {
|
||||||
|
// SAFETY: `Infallible` objects can never be con-
|
||||||
|
// structed
|
||||||
unsafe { unreachable_unchecked() }
|
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 {
|
impl From<NonZeroDecodeError> for GenericDecodeError {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: NonZeroDecodeError) -> Self {
|
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)]
|
#[inline(always)]
|
||||||
fn from(value: SizeError) -> Self {
|
fn from(value: LengthError) -> Self {
|
||||||
Self::SmallBuffer(value)
|
Self::SmallBuffer(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,25 +1,25 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::Encode;
|
use crate::encode::Encode;
|
||||||
use crate::error::{
|
use crate::error::{
|
||||||
CollectionEncodeError,
|
CollectionEncodeError,
|
||||||
EnumEncodeError,
|
EnumEncodeError,
|
||||||
|
@ -36,7 +36,7 @@ use core::hint::unreachable_unchecked;
|
||||||
|
|
||||||
/// A decoding failed.
|
/// 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.
|
/// Manual implementors are recommended to use a custom or less generic type for the sake of efficiency.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -55,31 +55,29 @@ pub enum GenericEncodeError {
|
||||||
impl Display for GenericEncodeError {
|
impl Display for GenericEncodeError {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
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 {
|
Self::LargeIsize(ref e)
|
||||||
BadBorrow(ref e) => 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 {
|
impl Error for GenericEncodeError {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
use GenericEncodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
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)]
|
#[inline(always)]
|
||||||
fn from(value: CollectionEncodeError<L, I>) -> Self {
|
fn from(value: CollectionEncodeError<L, I>) -> Self {
|
||||||
use CollectionEncodeError::*;
|
use CollectionEncodeError as Error;
|
||||||
|
|
||||||
match value {
|
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)]
|
#[inline(always)]
|
||||||
fn from(value: EnumEncodeError<D, F>) -> Self {
|
fn from(value: EnumEncodeError<D, F>) -> Self {
|
||||||
use EnumEncodeError::*;
|
use EnumEncodeError as Error;
|
||||||
|
|
||||||
match value {
|
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 {
|
impl From<Infallible> for GenericEncodeError {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(_value: Infallible) -> Self {
|
fn from(_value: Infallible) -> Self {
|
||||||
|
// SAFETY: `Infallible` objects can never be con-
|
||||||
|
// structed
|
||||||
unsafe { unreachable_unchecked() }
|
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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::error::Error;
|
use core::error::Error;
|
||||||
|
@ -35,7 +35,13 @@ pub struct IsizeEncodeError(
|
||||||
impl Display for IsizeEncodeError {
|
impl Display for IsizeEncodeError {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
|
@ -1,49 +1,50 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::error::Error;
|
use core::error::Error;
|
||||||
use core::fmt::{self, Display, Formatter};
|
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)).
|
/// 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.
|
/// 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 still fits.
|
/// It is allowed for any smaller-sized `SizedSlice` instance to decode a larger-sized encoding **if** the actual length is still within bounds.
|
||||||
/// If not, then this error type is used to denote the error state.
|
/// Otherwise, this error type is used to denote the error state.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct SizeError {
|
pub struct LengthError {
|
||||||
/// The total capacity of the buffer.
|
/// The total capacity of the buffer.
|
||||||
pub cap: usize,
|
pub capacity: usize,
|
||||||
|
|
||||||
/// The required amount of elements.
|
/// The required amount of elements.
|
||||||
pub len: usize,
|
pub len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for SizeError {
|
impl Display for LengthError {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! Error variants.
|
//! 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.
|
//! All of these types define (at least conditionally) the [`Error`](core::error::Error) trait.
|
||||||
|
|
||||||
use crate::use_mod;
|
use crate::use_mod;
|
||||||
|
|
||||||
use_mod!(pub bool_decode_error);
|
|
||||||
use_mod!(pub char_decode_error);
|
use_mod!(pub char_decode_error);
|
||||||
use_mod!(pub collection_decode_error);
|
use_mod!(pub collection_decode_error);
|
||||||
use_mod!(pub collection_encode_error);
|
use_mod!(pub collection_encode_error);
|
||||||
use_mod!(pub enum_encode_error);
|
|
||||||
use_mod!(pub enum_decode_error);
|
use_mod!(pub enum_decode_error);
|
||||||
|
use_mod!(pub enum_encode_error);
|
||||||
use_mod!(pub generic_decode_error);
|
use_mod!(pub generic_decode_error);
|
||||||
use_mod!(pub generic_encode_error);
|
use_mod!(pub generic_encode_error);
|
||||||
|
use_mod!(pub input_error);
|
||||||
use_mod!(pub isize_encode_error);
|
use_mod!(pub isize_encode_error);
|
||||||
use_mod!(pub item_decode_error);
|
use_mod!(pub item_decode_error);
|
||||||
use_mod!(pub item_encode_error);
|
use_mod!(pub item_encode_error);
|
||||||
|
use_mod!(pub length_error);
|
||||||
use_mod!(pub non_zero_decode_error);
|
use_mod!(pub non_zero_decode_error);
|
||||||
|
use_mod!(pub output_error);
|
||||||
use_mod!(pub ref_cell_encode_error);
|
use_mod!(pub ref_cell_encode_error);
|
||||||
use_mod!(pub size_error);
|
|
||||||
use_mod!(pub string_error);
|
use_mod!(pub string_error);
|
||||||
use_mod!(pub usize_encode_error);
|
use_mod!(pub usize_encode_error);
|
||||||
use_mod!(pub utf16_error);
|
use_mod!(pub utf16_error);
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::error::Error;
|
use core::error::Error;
|
||||||
|
@ -24,7 +24,7 @@ use core::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
/// A non-zero integer could not be decoded.
|
/// 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)]
|
#[derive(Debug)]
|
||||||
pub struct NonZeroDecodeError;
|
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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::cell::BorrowError;
|
use core::cell::BorrowError;
|
||||||
|
@ -25,28 +25,26 @@ use core::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
/// A reference cell could not be encoded.
|
/// 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>.
|
/// 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 [`Borrow`](Self::Borrow) instance.
|
/// 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 [`Value`](Self::Value) 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)]
|
#[derive(Debug)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub enum RefCellEncodeError<E> {
|
pub enum RefCellEncodeError<E> {
|
||||||
/// The reference cell could not be borrowed.
|
/// The reference cell could not be borrowed.
|
||||||
Borrow(BorrowError),
|
BadBorrow(BorrowError),
|
||||||
|
|
||||||
/// The contained value could not be encoded.
|
/// The contained value could not be encoded.
|
||||||
Value(E),
|
BadValue(E),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Display> Display for RefCellEncodeError<E> {
|
impl<E: Display> Display for RefCellEncodeError<E> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
use RefCellEncodeError::*;
|
|
||||||
|
|
||||||
let e: &dyn Display = match *self {
|
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}")
|
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> {
|
impl<E: Error + 'static> Error for RefCellEncodeError<E> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
use RefCellEncodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// 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::error::Error;
|
||||||
use core::fmt::{self, Display, Formatter};
|
use core::fmt::{self, Display, Formatter};
|
||||||
|
@ -36,22 +36,20 @@ pub enum StringError {
|
||||||
BadUtf8(Utf8Error),
|
BadUtf8(Utf8Error),
|
||||||
|
|
||||||
/// A fixed-size buffer was too small.
|
/// A fixed-size buffer was too small.
|
||||||
SmallBuffer(SizeError),
|
SmallBuffer(LengthError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for StringError {
|
impl Display for StringError {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
use StringError::*;
|
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
BadUtf16(ref e)
|
Self::BadUtf16(ref e)
|
||||||
=> write!(f, "bad utf-16: {e}"),
|
=> write!(f, "bad utf-16: {e}"),
|
||||||
|
|
||||||
BadUtf8(ref e)
|
Self::BadUtf8(ref e)
|
||||||
=> write!(f, "bad utf-8: {e}"),
|
=> write!(f, "bad utf-8: {e}"),
|
||||||
|
|
||||||
SmallBuffer(ref e)
|
Self::SmallBuffer(ref e)
|
||||||
=> write!(f, "buffer too small: {e}"),
|
=> write!(f, "buffer too small: {e}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,14 +58,12 @@ impl Display for StringError {
|
||||||
impl Error for StringError {
|
impl Error for StringError {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
use StringError::*;
|
|
||||||
|
|
||||||
match *self {
|
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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::error::Error;
|
use core::error::Error;
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::error::Error;
|
use core::error::Error;
|
||||||
|
@ -35,7 +35,12 @@ pub struct UsizeEncodeError(
|
||||||
impl Display for UsizeEncodeError {
|
impl Display for UsizeEncodeError {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
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.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::error::Error;
|
use core::error::Error;
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use core::error::Error;
|
use core::error::Error;
|
|
@ -1,29 +1,29 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// 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.
|
//! 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.
|
//! Therefore, this crate may be more suited for networking or other cases where many allocations are unwanted.
|
||||||
//!
|
//!
|
||||||
|
@ -34,24 +34,25 @@
|
||||||
//!
|
//!
|
||||||
//! # Performance
|
//! # 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.
|
//! 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 Librum usually outperforms the other tested crates -- as demonstrated in the following table:
|
//! 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_u8` | 0.968 | 0.857 | 0.733 | 0.979 |
|
||||||
//! | `encode_u32` | 1.130 | 1.084 | 0.749 | 2.793 |
|
//! | `encode_u32` | 1.065 | 0.999 | 0.730 | 2.727 |
|
||||||
//! | `encode_u128` | 2.340 | 2.328 | 1.543 | 6.380 |
|
//! | `encode_u128` | 2.168 | 2.173 | 1.510 | 6.246 |
|
||||||
//! | `encode_struct_unit` | 0.000 | 0.000 | 0.000 | 0.000 |
|
//! | `encode_struct_unit` | 0.000 | 0.000 | 0.000 | 0.000 |
|
||||||
//! | `encode_struct_unnamed` | 1.218 | 1.160 | 0.838 | 2.392 |
|
//! | `encode_struct_unnamed` | 1.241 | 1.173 | 0.823 | 3.350 |
|
||||||
//! | `encode_struct_named` | 3.077 | 1.501 | 0.975 | 3.079 |
|
//! | `encode_struct_named` | 3.079 | 1.507 | 0.973 | 3.082 |
|
||||||
//! | `encode_enum_unit` | 0.260 | 0.310 | 0.000 | 0.303 |
|
//! | `encode_enum_unit` | 0.246 | 0.297 | 0.000 | 0.295 |
|
||||||
//! | `decode_u8` | 1.116 | 1.106 | 1.110 | 1.102 |
|
//! | `decode_u8` | 0.942 | 0.962 | 0.922 | 0.923 |
|
||||||
//! | `decode_non_zero_u8` | 1.228 | 1.236 | 1.269 | 1.263 |
|
//! | `decode_non_zero_u8` | 1.126 | 1.159 | 1.127 | 1.160 |
|
||||||
//! | **Total time** → | 11.373 | 9.672 | 7.291 | 18.284 |
|
//! | `decode_bool` | 1.040 | 1.099 | 1.055 | 1.177 |
|
||||||
//! | **Total deviation (p.c.)** → | +56 | +33 | ±0 | +150 |
|
//! | **Total time** → | 11.873 | 10.225 | 7.873 | 18.939 |
|
||||||
|
//! | **Total deviation (p.c.)** → | +51 | +30 | ±0 | +141 |
|
||||||
//!
|
//!
|
||||||
//! [Bincode]: https://crates.io/crates/bincode/
|
//! [Bincode]: https://crates.io/crates/bincode/
|
||||||
//! [Borsh]: https://crates.io/crates/borsh/
|
//! [Borsh]: https://crates.io/crates/borsh/
|
||||||
|
@ -59,9 +60,9 @@
|
||||||
//!
|
//!
|
||||||
//! All quantities are measured in seconds unless otherwise noted.
|
//! 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.
|
//! 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
|
//! # Data model
|
||||||
//!
|
//!
|
||||||
|
@ -78,16 +79,18 @@
|
||||||
//!
|
//!
|
||||||
//! # Usage
|
//! # 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.
|
//! 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).
|
//! 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:
|
//! 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)]
|
//! #[derive(Debug, Decode, Encode, PartialEq)]
|
||||||
//! struct Ints {
|
//! struct Ints {
|
||||||
|
@ -106,7 +109,7 @@
|
||||||
//! value4: 0x1E_1D_1C_1B_1A_19_18_17_16_15_14_13_12_11_10_0F,
|
//! 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();
|
//! buf.write(VALUE).unwrap();
|
||||||
//!
|
//!
|
||||||
|
@ -127,20 +130,20 @@
|
||||||
//!
|
//!
|
||||||
//! ## Buffer types
|
//! ## 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).
|
//! These streams are separated into two type: [*output streams*](encode::Output) and [*input streams*](decode::Input).
|
||||||
//! The [`Buf`] type can be used to handle these streams.
|
//! The [`Slot`] type can be used to handle these streams.
|
||||||
//!
|
//!
|
||||||
//! ## Encoding
|
//! ## 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 buf = [0x00; char::MAX_ENCODED_SIZE];
|
||||||
//! let mut stream = OStream::new(&mut buf);
|
//! let mut stream = Output::new(&mut buf);
|
||||||
//!
|
//!
|
||||||
//! 'Ж'.encode(&mut stream).unwrap();
|
//! 'Ж'.encode(&mut stream).unwrap();
|
||||||
//!
|
//!
|
||||||
|
@ -150,10 +153,10 @@
|
||||||
//! Streams can also be used to chain multiple objects together:
|
//! 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 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
|
//! // Note: For serialising multiple characters, the
|
||||||
//! // `String` and `SizedStr` types are usually
|
//! // `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
|
||||||
//!
|
//!
|
||||||
//! Decoding works with a similar syntax to encoding.
|
//! 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 data = [0x54, 0x45];
|
||||||
//! let mut stream = IStream::new(&data);
|
//! let mut stream = Input::new(&data);
|
||||||
//!
|
//!
|
||||||
//! assert_eq!(u16::decode(&mut stream).unwrap(), 0x4554);
|
//! assert_eq!(u16::decode(&mut stream).unwrap(), 0x4554);
|
||||||
//!
|
//!
|
||||||
//! // Data can theoretically be reinterpretred:
|
//! // 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(), 0x54);
|
||||||
//! assert_eq!(u8::decode(&mut stream).unwrap(), 0x45);
|
//! assert_eq!(u8::decode(&mut stream).unwrap(), 0x45);
|
||||||
//!
|
//!
|
||||||
//! // Including as tuples:
|
//! // Including as tuples:
|
||||||
//!
|
//!
|
||||||
//! stream = IStream::new(&data);
|
//! stream = Input::new(&data);
|
||||||
//!
|
//!
|
||||||
//! assert_eq!(<(u8, u8)>::decode(&mut stream).unwrap(), (0x54, 0x45));
|
//! assert_eq!(<(u8, u8)>::decode(&mut stream).unwrap(), (0x54, 0x45));
|
||||||
//! ```
|
//! ```
|
||||||
|
@ -206,7 +209,9 @@
|
||||||
//! A UDP server/client for geographic data:
|
//! 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::io;
|
||||||
//! use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
//! use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
||||||
//! use std::thread::spawn;
|
//! use std::thread::spawn;
|
||||||
|
@ -242,8 +247,8 @@
|
||||||
//! struct Party {
|
//! struct Party {
|
||||||
//! pub socket: UdpSocket,
|
//! pub socket: UdpSocket,
|
||||||
//!
|
//!
|
||||||
//! pub request_buf: Buf::<Request>,
|
//! pub request_buf: Slot::<Request>,
|
||||||
//! pub response_buf: Buf::<Response>,
|
//! pub response_buf: Slot::<Response>,
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! impl Party {
|
//! impl Party {
|
||||||
|
@ -253,8 +258,8 @@
|
||||||
//! let this = Self {
|
//! let this = Self {
|
||||||
//! socket,
|
//! socket,
|
||||||
//!
|
//!
|
||||||
//! request_buf: Buf::new(),
|
//! request_buf: Slot::new(),
|
||||||
//! response_buf: Buf::new(),
|
//! response_buf: Slot::new(),
|
||||||
//! };
|
//! };
|
||||||
//!
|
//!
|
||||||
//! Ok(this)
|
//! Ok(this)
|
||||||
|
@ -307,28 +312,28 @@
|
||||||
//!
|
//!
|
||||||
//! # Feature flags
|
//! # 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)
|
//! * *`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 [`librum-macros`](https://crates.io/crates/librum-macros/) crate
|
//! * *`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)
|
//! * *`std`: Enables implementations for types such as [`Mutex`](std::sync::Mutex) and [`RwLock`](std::sync::RwLock)
|
||||||
//!
|
//!
|
||||||
//! Features marked with * are enabled by default.
|
//! Features marked with * are enabled by default.
|
||||||
//!
|
//!
|
||||||
//! # Documentation
|
//! # Documentation
|
||||||
//!
|
//!
|
||||||
//! Librum has its documentation written in-source for use by `rustdoc`.
|
//! oct 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.
|
//! 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.
|
//! Currently, these docs make use of some unstable features for the sake of readability.
|
||||||
//! The nightly toolchain is therefore required when rendering them.
|
//! The nightly toolchain is therefore required when rendering them.
|
||||||
//!
|
//!
|
||||||
//! # Contribution
|
//! # 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.
|
//! 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
|
//! # Copyright & Licence
|
||||||
//!
|
//!
|
||||||
|
@ -344,13 +349,13 @@
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
#![warn(missing_docs)]
|
||||||
#![cfg_attr(doc, allow(internal_features))]
|
#![cfg_attr(doc, allow(internal_features))]
|
||||||
|
|
||||||
#![cfg_attr(doc, feature(doc_cfg, rustdoc_internals))]
|
#![cfg_attr(doc, feature(doc_cfg, rustdoc_internals))]
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
|
||||||
|
|
||||||
// For use in macros:
|
// For use in macros:
|
||||||
extern crate self as librum;
|
extern crate self as oct;
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
@ -358,116 +363,6 @@ extern crate alloc;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
extern crate 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 {
|
macro_rules! use_mod {
|
||||||
($vis:vis $name:ident$(,)?) => {
|
($vis:vis $name:ident$(,)?) => {
|
||||||
mod $name;
|
mod $name;
|
||||||
|
@ -476,18 +371,14 @@ macro_rules! use_mod {
|
||||||
}
|
}
|
||||||
pub(crate) use 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 primitive_discriminant);
|
||||||
use_mod!(pub sized_encode);
|
|
||||||
use_mod!(pub sized_iter);
|
use_mod!(pub sized_iter);
|
||||||
use_mod!(pub sized_slice);
|
use_mod!(pub sized_slice);
|
||||||
use_mod!(pub sized_str);
|
use_mod!(pub sized_str);
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use_mod!(pub buf);
|
use_mod!(pub slot);
|
||||||
|
|
||||||
|
pub mod decode;
|
||||||
|
pub mod encode;
|
||||||
pub mod error;
|
pub mod error;
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
mod sealed {
|
mod sealed {
|
||||||
|
@ -46,16 +46,15 @@ pub trait PrimitiveDiscriminant: Copy + SealedPrimitiveDiscriminant + Sized { }
|
||||||
|
|
||||||
macro_rules! impl_primitive_discriminant {
|
macro_rules! impl_primitive_discriminant {
|
||||||
($ty:ty) => {
|
($ty:ty) => {
|
||||||
impl ::librum::SealedPrimitiveDiscriminant for $ty {
|
impl ::oct::SealedPrimitiveDiscriminant for $ty {
|
||||||
#[allow(clippy::cast_lossless)]
|
#[allow(clippy::cast_lossless)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
|
||||||
fn to_u128(self) -> u128 {
|
fn to_u128(self) -> u128 {
|
||||||
self as u128
|
self as u128
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::librum::PrimitiveDiscriminant for $ty { }
|
impl ::oct::PrimitiveDiscriminant for $ty { }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#[cfg(test)]
|
#[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> {
|
impl<T: Clone, const N: usize> Clone for SizedIter<T, N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clone(&self) -> Self {
|
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 Self { pos, len, .. } = *self;
|
||||||
|
|
||||||
let start = pos;
|
let start = pos;
|
|
@ -1,25 +1,25 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use librum::{SizedSlice, SizedStr};
|
use oct::{SizedSlice, SizedStr};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sized_iter_clone() {
|
fn test_sized_iter_clone() {
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::SizedSlice;
|
use crate::SizedSlice;
|
|
@ -1,50 +1,44 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{
|
use crate::SizedSlice;
|
||||||
Decode,
|
use crate::decode::{Decode, DecodeBorrowed, Input};
|
||||||
DecodeBorrowed,
|
use crate::encode::{Encode, Output, SizedEncode};
|
||||||
Encode,
|
use crate::error::{CollectionDecodeError, ItemDecodeError, LengthError};
|
||||||
IStream,
|
|
||||||
OStream,
|
|
||||||
SizedEncode,
|
|
||||||
SizedSlice
|
|
||||||
};
|
|
||||||
use crate::error::{CollectionDecodeError, ItemDecodeError, SizeError};
|
|
||||||
|
|
||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
impl<T: Decode, const N: usize> Decode for SizedSlice<T, N> {
|
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]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let len = Decode::decode(stream).unwrap();
|
let len = Decode::decode(input).unwrap();
|
||||||
if len > N { return Err(CollectionDecodeError::Length(SizeError { cap: N, len })) };
|
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() {
|
for (i, slot) in buf.iter_mut().enumerate() {
|
||||||
let v = Decode::decode(stream)
|
let v = Decode::decode(input)
|
||||||
.map_err(|e| CollectionDecodeError::Item(ItemDecodeError { index: i, error: e }))?;
|
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
|
||||||
|
|
||||||
slot.write(v);
|
slot.write(v);
|
||||||
}
|
}
|
||||||
|
@ -59,8 +53,8 @@ impl<T: Encode, const N: usize> Encode for SizedSlice<T, N> {
|
||||||
type Error = <[T] as Encode>::Error;
|
type Error = <[T] as Encode>::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.as_slice().encode(stream)
|
self.as_slice().encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::SizedSlice;
|
use crate::SizedSlice;
|
||||||
use crate::error::SizeError;
|
use crate::error::LengthError;
|
||||||
|
|
||||||
use core::borrow::{Borrow, BorrowMut};
|
use core::borrow::{Borrow, BorrowMut};
|
||||||
use core::mem::MaybeUninit;
|
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> {
|
impl<T: Clone, const N: usize> TryFrom<&[T]> for SizedSlice<T, N> {
|
||||||
type Error = SizeError;
|
type Error = LengthError;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn try_from(value: &[T]) -> Result<Self, Self::Error> {
|
fn try_from(value: &[T]) -> Result<Self, Self::Error> {
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{SizedIter, SizedSlice};
|
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 {
|
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
|
||||||
let mut iter = iter.into_iter();
|
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;
|
let mut len = 0x0;
|
||||||
|
|
||||||
for item in &mut buf {
|
for item in &mut buf {
|
|
@ -1,28 +1,28 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use crate::error::SizeError;
|
use crate::error::LengthError;
|
||||||
|
|
||||||
use core::fmt::{self, Debug, Formatter};
|
use core::fmt::{self, Debug, Formatter};
|
||||||
use core::hash::{Hash, Hasher};
|
use core::hash::{Hash, Hasher};
|
||||||
|
@ -31,6 +31,9 @@ use core::ops::{Index, IndexMut};
|
||||||
use core::ptr::{copy_nonoverlapping, null, null_mut};
|
use core::ptr::{copy_nonoverlapping, null, null_mut};
|
||||||
use core::slice::SliceIndex;
|
use core::slice::SliceIndex;
|
||||||
|
|
||||||
|
// Encode/decode facilities:
|
||||||
|
mod code;
|
||||||
|
|
||||||
// Conversion facilities:
|
// Conversion facilities:
|
||||||
mod conv;
|
mod conv;
|
||||||
|
|
||||||
|
@ -40,12 +43,9 @@ mod cmp;
|
||||||
// Iterator facilities:
|
// Iterator facilities:
|
||||||
mod iter;
|
mod iter;
|
||||||
|
|
||||||
// Encode/decode facilities:
|
|
||||||
mod serdes;
|
|
||||||
|
|
||||||
/// Stack-allocated vector with maximum length.
|
/// 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`.
|
/// 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:
|
/// 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 vec0 = SizedSlice::<u8, 0x4>::try_from([0x3].as_slice()).unwrap();
|
||||||
/// let vec1 = SizedSlice::<u8, 0x4>::try_from([0x3, 0x2].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> {
|
impl<T: Clone, const N: usize> SizedSlice<T, N> {
|
||||||
/// Constructs an empty, fixed-size vector.
|
/// Constructs an empty, fixed-size vector.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(data: &[T]) -> Result<Self, SizeError> {
|
pub fn new(data: &[T]) -> Result<Self, LengthError> {
|
||||||
let mut buf: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
|
let mut buf = [const { MaybeUninit::<T>::uninit() };N];
|
||||||
|
|
||||||
let len = data.len();
|
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()) {
|
for (item, value) in buf.iter_mut().zip(data.iter()) {
|
||||||
item.write(value.clone());
|
item.write(value.clone());
|
|
@ -1,25 +1,25 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use librum::SizedSlice;
|
use oct::SizedSlice;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::SizedStr;
|
use crate::SizedStr;
|
|
@ -1,49 +1,43 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{
|
use crate::SizedStr;
|
||||||
Decode,
|
use crate::decode::{Decode, DecodeBorrowed, Input};
|
||||||
DecodeBorrowed,
|
use crate::encode::{Encode, Output, SizedEncode};
|
||||||
Encode,
|
use crate::error::{CollectionDecodeError, LengthError, StringError, Utf8Error};
|
||||||
IStream,
|
|
||||||
OStream,
|
|
||||||
SizedEncode,
|
|
||||||
SizedStr
|
|
||||||
};
|
|
||||||
use crate::error::{CollectionDecodeError, SizeError, StringError, Utf8Error};
|
|
||||||
|
|
||||||
impl<const N: usize> Decode for SizedStr<N> {
|
impl<const N: usize> Decode for SizedStr<N> {
|
||||||
type Error = CollectionDecodeError<SizeError, Utf8Error>;
|
type Error = CollectionDecodeError<LengthError, Utf8Error>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(stream: &mut IStream) -> Result<Self, Self::Error> {
|
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
|
||||||
let len = Decode::decode(stream).unwrap();
|
let len = Decode::decode(input).unwrap();
|
||||||
|
|
||||||
let data = stream.read(len);
|
let data = input.read(len).unwrap();
|
||||||
|
|
||||||
Self::from_utf8(data)
|
Self::from_utf8(data)
|
||||||
.map_err(|e| match e {
|
.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!(),
|
_ => unreachable!(),
|
||||||
})
|
})
|
||||||
|
@ -56,8 +50,8 @@ impl<const N: usize> Encode for SizedStr<N> {
|
||||||
type Error = <str as Encode>::Error;
|
type Error = <str as Encode>::Error;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn encode(&self, stream: &mut OStream) -> Result<(), Self::Error> {
|
fn encode(&self, output: &mut Output) -> Result<(), Self::Error> {
|
||||||
self.as_str().encode(stream)
|
self.as_str().encode(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{SizedSlice, SizedStr};
|
use crate::{SizedSlice, SizedStr};
|
||||||
use crate::error::{SizeError, StringError, Utf8Error};
|
use crate::error::{LengthError, StringError, Utf8Error};
|
||||||
|
|
||||||
use core::borrow::{Borrow, BorrowMut};
|
use core::borrow::{Borrow, BorrowMut};
|
||||||
use core::mem::{ManuallyDrop, MaybeUninit};
|
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.
|
/// Each byte value must be a valid UTF-8 code point.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_utf8(data: &[u8]) -> Result<Self, StringError> {
|
pub const fn from_utf8(s: &[u8]) -> Result<Self, StringError> {
|
||||||
if data.len() > N { return Err(StringError::SmallBuffer(SizeError { cap: N, len: data.len() })) };
|
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,
|
Ok(s) => s,
|
||||||
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let i = e.valid_up_to();
|
let i = e.valid_up_to();
|
||||||
let c = data[i];
|
let c = s[i];
|
||||||
|
|
||||||
return Err(StringError::BadUtf8(Utf8Error { value: c, index: i }));
|
return Err(StringError::BadUtf8(Utf8Error { value: c, index: i }));
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,7 @@ impl<const N: usize> FromStr for SizedStr<N> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
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()) };
|
let this = unsafe { Self::from_utf8_unchecked(s.as_bytes()) };
|
||||||
Ok(this)
|
Ok(this)
|
|
@ -1,29 +1,29 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use crate::SizedSlice;
|
use crate::SizedSlice;
|
||||||
use crate::error::{SizeError, StringError};
|
use crate::error::{LengthError, StringError};
|
||||||
|
|
||||||
use core::fmt::{self, Debug, Display, Formatter};
|
use core::fmt::{self, Debug, Display, Formatter};
|
||||||
use core::hash::{Hash, Hasher};
|
use core::hash::{Hash, Hasher};
|
||||||
|
@ -34,12 +34,12 @@ use core::str::{Chars, CharIndices};
|
||||||
// Comparison facilities:
|
// Comparison facilities:
|
||||||
mod cmp;
|
mod cmp;
|
||||||
|
|
||||||
|
// Encode/decode facilities:
|
||||||
|
mod code;
|
||||||
|
|
||||||
// Conversion facilities:
|
// Conversion facilities:
|
||||||
mod conv;
|
mod conv;
|
||||||
|
|
||||||
// Encode/decode facilities:
|
|
||||||
mod serdes;
|
|
||||||
|
|
||||||
/// Stack-allocated string with maximum length.
|
/// 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.
|
/// 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.
|
/// Therefore, the following four strings have -- despite their different contents -- the same total size.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use librum::SizedStr;
|
/// use oct::SizedStr;
|
||||||
/// use std::str::FromStr;
|
/// use std::str::FromStr;
|
||||||
///
|
///
|
||||||
/// let str0 = SizedStr::<0x40>::default(); // Empty string.
|
/// 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.
|
/// If the internal buffer cannot contain the entirety of `s`, then an error is returned.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const fn new(s: &str) -> Result<Self, StringError> {
|
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()) };
|
let this = unsafe { Self::from_utf8_unchecked(s.as_bytes()) };
|
||||||
Ok(this)
|
Ok(this)
|
||||||
|
@ -201,4 +201,3 @@ impl<I: SliceIndex<str>, const N: usize> IndexMut<I> for SizedStr<N> {
|
||||||
self.get_mut(index).unwrap()
|
self.get_mut(index).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use librum::SizedStr;
|
use oct::SizedStr;
|
||||||
use librum::error::{StringError, Utf8Error};
|
use oct::error::{StringError, Utf8Error};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
|
@ -1,34 +1,29 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use crate::{
|
use crate::decode::{Decode, Input};
|
||||||
Decode,
|
use crate::encode::{Encode, Output, SizedEncode};
|
||||||
Encode,
|
|
||||||
IStream,
|
|
||||||
OStream,
|
|
||||||
SizedEncode,
|
|
||||||
};
|
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
|
@ -39,7 +34,7 @@ use core::ops::{Deref, DerefMut, Index, IndexMut};
|
||||||
use core::ptr::{self, copy_nonoverlapping};
|
use core::ptr::{self, copy_nonoverlapping};
|
||||||
use core::slice::{self, SliceIndex};
|
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.
|
/// 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
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Create a buffer for holding a `Request` enumeration:
|
/// Create a slot for holding a `Request` enumeration:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use librum::{
|
/// use oct::{SizedStr, Slot};
|
||||||
/// Buf,
|
/// use oct::encode::{Encode, Output, SizedEncode};
|
||||||
/// Encode,
|
|
||||||
/// OStream,
|
|
||||||
/// SizedEncode,
|
|
||||||
/// SizedStr,
|
|
||||||
/// };
|
|
||||||
///
|
///
|
||||||
/// #[derive(Debug, Encode, SizedEncode)]
|
/// #[derive(Debug, Encode, SizedEncode)]
|
||||||
/// enum Request {
|
/// enum Request {
|
||||||
|
@ -68,15 +58,15 @@ use core::slice::{self, SliceIndex};
|
||||||
/// SendMessage { message: SizedStr<0x80> },
|
/// SendMessage { message: SizedStr<0x80> },
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let mut buf = Buf::new();
|
/// let mut buf = Slot::new();
|
||||||
///
|
///
|
||||||
/// buf.write(Request::Join { username: "epsiloneridani".parse().unwrap() }).unwrap();
|
/// buf.write(Request::Join { username: "epsiloneridani".parse().unwrap() }).unwrap();
|
||||||
/// assert_eq!(buf.as_slice(), b"\0\0\x0E\0epsiloneridani");
|
/// 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")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
pub struct Buf<T> {
|
pub struct Slot<T> {
|
||||||
buf: Box<[u8]>,
|
buf: Box<[u8]>,
|
||||||
len: usize,
|
len: usize,
|
||||||
|
|
||||||
|
@ -84,8 +74,8 @@ pub struct Buf<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T> Buf<T> {
|
impl<T> Slot<T> {
|
||||||
/// Allocates a new buffer suitable for encoding.
|
/// Allocates a new slot suitable for encodings.
|
||||||
///
|
///
|
||||||
/// The given capacity should be large enough to hold any expected encoding of `T`.
|
/// 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
|
/// # 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).
|
/// 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)]
|
#[inline(always)]
|
||||||
|
@ -135,7 +125,7 @@ impl<T> Buf<T> {
|
||||||
self.buf.as_ptr()
|
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).
|
/// 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)]
|
#[inline(always)]
|
||||||
|
@ -144,10 +134,10 @@ impl<T> Buf<T> {
|
||||||
self.buf.as_mut_ptr()
|
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)).
|
/// 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 buffer.
|
/// This is in contrast to [`as_mut_slice`](Self::as_mut_slice), which references the entire slot buffer.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn as_slice(&self) -> &[u8] {
|
pub fn as_slice(&self) -> &[u8] {
|
||||||
|
@ -155,9 +145,9 @@ impl<T> Buf<T> {
|
||||||
unsafe { slice::from_raw_parts(self.as_ptr(), self.len()) }
|
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.
|
/// Users should call [`set_len`](Self::set_len) if writing has modified the portion of used bytes.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -167,7 +157,7 @@ impl<T> Buf<T> {
|
||||||
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.capacity()) }
|
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.
|
/// 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]) {
|
pub fn copy_from_slice(&mut self, data: &[u8]) {
|
||||||
let len = data.len();
|
let len = data.len();
|
||||||
|
|
||||||
assert!(len <= self.capacity(), "buffer cannot contain source slice");
|
assert!(len <= self.capacity(), "slot cannot contain source slice");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let src = data.as_ptr();
|
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)).
|
/// 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).
|
/// For the same operation *without* these checks, see [`set_len_unchecked`](Self::set_len_unchecked).
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # 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.
|
/// If this is the case, however, this method will panic.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_len(&mut self, len: usize) {
|
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.
|
// SAFETY: The length has been tested.
|
||||||
unsafe { self.set_len_unchecked(len) }
|
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.
|
/// The provided size is **not** tested before being written.
|
||||||
/// For the same operation *with* checks, see [`set_len`](Self::set_len).
|
/// For the same operation *with* checks, see [`set_len`](Self::set_len).
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # 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.
|
/// Exceeding this will yield undefined behaviour.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn set_len_unchecked(&mut self, len: usize) {
|
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
|
// SAFETY: The length has been guaranteed by the
|
||||||
// caller.
|
// caller.
|
||||||
self.len = len;
|
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.
|
/// In other cases, however, this may either be greater or less than this value.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -237,18 +227,18 @@ impl<T> Buf<T> {
|
||||||
self.buf.len()
|
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).
|
/// 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)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.len
|
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.
|
/// This is strictly equivalent to testing if [`len`](Self::len) is null.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -257,7 +247,7 @@ impl<T> Buf<T> {
|
||||||
self.len() == 0x0
|
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).
|
/// This is strictly equivalent to testing if [`len`](Self::len) is equal to [`capacity`](Self::capacity).
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -268,8 +258,8 @@ impl<T> Buf<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T: Encode> Buf<T> {
|
impl<T: Encode> Slot<T> {
|
||||||
/// Encodes an object into the buffer.
|
/// Encodes an object into the slot.
|
||||||
///
|
///
|
||||||
/// The object is encoded as by being passed to <code><T as [Encode]>::[encode](Encode::encode)</code>.
|
/// 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.
|
/// Any error that occurs during encoding is passed on and returned from this method.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn write<U: Borrow<T>>(&mut self, value: U) -> Result<(), T::Error> {
|
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)?;
|
value.borrow().encode(&mut stream)?;
|
||||||
|
|
||||||
let len = stream.close();
|
let len = stream.position();
|
||||||
self.set_len(len);
|
self.set_len(len);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -290,8 +280,8 @@ impl<T: Encode> Buf<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T: Decode> Buf<T> {
|
impl<T: Decode> Slot<T> {
|
||||||
/// Decodes an object from the buffer.
|
/// Decodes an object from the slot.
|
||||||
///
|
///
|
||||||
/// This is done as by passing the contained bytes to <code><T as [Decode]>::[decode](Decode::decode)</code>.
|
/// 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.
|
/// Any error that occurs during decoding is passed on and returned from this method.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read(&self) -> Result<T, T::Error> {
|
pub fn read(&self) -> Result<T, T::Error> {
|
||||||
// We should only pass the used part of the buffer
|
// We should only pass the used part of the slot to
|
||||||
// to `deserialise`.
|
// `decode`.
|
||||||
|
|
||||||
let mut stream = IStream::new(&self.buf);
|
let mut stream = Input::new(&self.buf);
|
||||||
|
|
||||||
let value = Decode::decode(&mut stream)?;
|
let value = Decode::decode(&mut stream)?;
|
||||||
Ok(value)
|
Ok(value)
|
||||||
|
@ -314,10 +304,10 @@ impl<T: Decode> Buf<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T: SizedEncode> Buf<T> {
|
impl<T: SizedEncode> Slot<T> {
|
||||||
/// Allocates a new buffer suitable for encoding.
|
/// 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.
|
/// See also the [`with_capacity`](Self::with_capacity) constructor.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -328,7 +318,7 @@ impl<T: SizedEncode> Buf<T> {
|
||||||
|
|
||||||
/// See also [`as_mut_slice`](Self::as_mut_slice).
|
/// See also [`as_mut_slice`](Self::as_mut_slice).
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T> AsMut<[u8]> for Buf<T> {
|
impl<T> AsMut<[u8]> for Slot<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn as_mut(&mut self) -> &mut [u8] {
|
fn as_mut(&mut self) -> &mut [u8] {
|
||||||
self.as_mut_slice()
|
self.as_mut_slice()
|
||||||
|
@ -337,7 +327,7 @@ impl<T> AsMut<[u8]> for Buf<T> {
|
||||||
|
|
||||||
/// See also [`as_slice`](Self::as_slice).
|
/// See also [`as_slice`](Self::as_slice).
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T> AsRef<[u8]> for Buf<T> {
|
impl<T> AsRef<[u8]> for Slot<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn as_ref(&self) -> &[u8] {
|
fn as_ref(&self) -> &[u8] {
|
||||||
self.as_slice()
|
self.as_slice()
|
||||||
|
@ -346,7 +336,7 @@ impl<T> AsRef<[u8]> for Buf<T> {
|
||||||
|
|
||||||
/// See also [`as_slice`](Self::as_slice).
|
/// See also [`as_slice`](Self::as_slice).
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T> Borrow<[u8]> for Buf<T> {
|
impl<T> Borrow<[u8]> for Slot<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn borrow(&self) -> &[u8] {
|
fn borrow(&self) -> &[u8] {
|
||||||
self.as_slice()
|
self.as_slice()
|
||||||
|
@ -355,7 +345,7 @@ impl<T> Borrow<[u8]> for Buf<T> {
|
||||||
|
|
||||||
/// See also [`as_mut_slice`](Self::as_mut_slice).
|
/// See also [`as_mut_slice`](Self::as_mut_slice).
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T> BorrowMut<[u8]> for Buf<T> {
|
impl<T> BorrowMut<[u8]> for Slot<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn borrow_mut(&mut self) -> &mut [u8] {
|
fn borrow_mut(&mut self) -> &mut [u8] {
|
||||||
self.as_mut_slice()
|
self.as_mut_slice()
|
||||||
|
@ -363,13 +353,13 @@ impl<T> BorrowMut<[u8]> for Buf<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T> Debug for Buf<T> {
|
impl<T> Debug for Slot<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{:?}", self.as_slice()) }
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{:?}", self.as_slice()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T: SizedEncode> Default for Buf<T> {
|
impl<T: SizedEncode> Default for Slot<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
|
@ -377,7 +367,7 @@ impl<T: SizedEncode> Default for Buf<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T> Deref for Buf<T> {
|
impl<T> Deref for Slot<T> {
|
||||||
type Target = [u8];
|
type Target = [u8];
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -387,7 +377,7 @@ impl<T> Deref for Buf<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T> DerefMut for Buf<T> {
|
impl<T> DerefMut for Slot<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
self.as_mut_slice()
|
self.as_mut_slice()
|
||||||
|
@ -395,7 +385,7 @@ impl<T> DerefMut for Buf<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[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;
|
type Output = I::Output;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -405,7 +395,7 @@ impl<T, I: SliceIndex<[u8]>> Index<I> for Buf<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[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)]
|
#[inline(always)]
|
||||||
fn index_mut(&mut self, index: I) -> &mut Self::Output {
|
fn index_mut(&mut self, index: I) -> &mut Self::Output {
|
||||||
self.get_mut(index).unwrap()
|
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")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T> PartialEq<[u8]> for Buf<T> {
|
impl<T> PartialEq<[u8]> for Slot<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn eq(&self, other: &[u8]) -> bool {
|
fn eq(&self, other: &[u8]) -> bool {
|
||||||
self.as_slice() == other
|
self.as_slice() == other
|
||||||
|
@ -421,7 +411,7 @@ impl<T> PartialEq<[u8]> for Buf<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
||||||
impl<T> PartialEq<&[u8]> for Buf<T> {
|
impl<T> PartialEq<&[u8]> for Slot<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn eq(&self, other: &&[u8]) -> bool {
|
fn eq(&self, other: &&[u8]) -> bool {
|
||||||
self.as_slice() == *other
|
self.as_slice() == *other
|
||||||
|
@ -429,7 +419,7 @@ impl<T> PartialEq<&[u8]> for Buf<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
|
#[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)]
|
#[inline(always)]
|
||||||
fn eq(&self, other: &&mut [u8]) -> bool {
|
fn eq(&self, other: &&mut [u8]) -> bool {
|
||||||
self.as_slice() == *other
|
self.as_slice() == *other
|
|
@ -1,30 +1,30 @@
|
||||||
// Copyright 2024 Gabriel Bjørnager Jensen.
|
// 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
|
// and/or modify it under the terms of the GNU
|
||||||
// Lesser General Public License as published by
|
// Lesser General Public License as published by
|
||||||
// the Free Software Foundation, either version 3
|
// the Free Software Foundation, either version 3
|
||||||
// of the License, or (at your option) any later
|
// of the License, or (at your option) any later
|
||||||
// version.
|
// 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
|
// be useful, but WITHOUT ANY WARRANTY; without
|
||||||
// even the implied warranty of MERCHANTABILITY or
|
// even the implied warranty of MERCHANTABILITY or
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
// Lesser General Public License for more details.
|
// Lesser General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Less-
|
// 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/>.
|
// not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use librum::Buf;
|
use oct::Slot;
|
||||||
use librum::error::CharDecodeError;
|
use oct::error::CharDecodeError;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_buf_write_read() {
|
fn test_buf_write_read() {
|
||||||
let mut buf = Buf::<char>::new();
|
let mut buf = Slot::<char>::new();
|
||||||
|
|
||||||
macro_rules! test_read {
|
macro_rules! test_read {
|
||||||
($pattern:pat$(,)?) => {{
|
($pattern:pat$(,)?) => {{
|
Loading…
Add table
Add a link
Reference in a new issue