Remove 'Vec::set_len'; Rename 'Vec::set_len_unchecked' to 'Vec::set_len'; Update repository link; Always expose 'SystemTimeDecodeError'; Update lints; Migrate Bincode benchmark to version 2.0;

This commit is contained in:
Gabriel Bjørnager Jensen 2025-04-01 16:04:55 +02:00
parent 7a6f49ed8f
commit c764c4b724
43 changed files with 189 additions and 143 deletions

View file

@ -3,6 +3,15 @@
This is the changelog of [Oct](https://crates.io/crates/oct/).
See `README.md` for more information.
## 0.20.0
* Remove `Vec::set_len`
* Rename `Vec::set_len_unchecked` to `Vec::set_len`
* Update repository link
* Always expose `SystemTimeDecodeError`
* Update lints
* Migrate Bincode benchmark to version 2.0
## 0.19.1
* Clean up code

View file

@ -1,12 +1,18 @@
[profile.release]
codegen-units = 1
lto = "fat"
opt-level = 3
[workspace]
members = ["oct", "oct-benchmarks", "oct-macros"]
resolver = "2"
[workspace.package]
version = "0.19.1"
version = "0.20.0"
authors = ["Gabriel Bjørnager Jensen"]
readme = "README.md"
repository = "https://gitlab.com/bjoernager/oct/"
repository = "https://mandelbrot.dk/bjoernager/oct/"
keywords = ["encoding", "io", "network", "no-std", "serialization"]
categories = ["encoding", "network-programming"]
@ -96,6 +102,7 @@ mismatching_type_param_order = "warn"
missing_errors_doc = "forbid"
missing_transmute_annotations = "forbid"
mixed_read_write_in_expression = "forbid"
module_inception = "allow"
must_use_unit = "forbid"
mut_mut = "warn"
mutex_atomic = "forbid"
@ -174,9 +181,3 @@ verbose_bit_mask = "warn"
verbose_file_reads = "warn"
wildcard_dependencies = "forbid"
zero_prefixed_literal = "allow"
[profile.release]
codegen-units = 1
lto = "fat"
opt-level = 3

View file

View file

@ -20,17 +20,19 @@ According to my runs on an AMD Ryzen 7 3700X with default settings, these benchm
| Benchmark | [Bincode] | [Borsh] | Oct | [Postcard] |
| :--------------------------------- | --------: | ------: | -----: | ---------: |
| `encode_u8` | 0.927 | 0.939 | 0.742 | 0.896 |
| `encode_u32` | 1.069 | 1.007 | 0.738 | 2.732 |
| `encode_u128` | 2.180 | 2.204 | 1.522 | 6.412 |
| `encode_char` | 2.474 | 1.261 | 0.817 | 2.480 |
| `encode_u8` | 1.004 | 0.880 | 0.812 | 0.860 |
| `encode_u32` | 1.312 | 0.973 | 0.818 | 2.706 |
| `encode_u128` | 2.631 | 2.174 | 1.561 | 6.159 |
| `encode_char` | 1.598 | 1.256 | 0.830 | 2.393 |
| `encode_struct_unit` | 0.000 | 0.000 | 0.000 | 0.000 |
| `encode_struct_unnamed` | 1.245 | 1.146 | 0.834 | 2.378 |
| `encode_struct_named` | 3.037 | 1.541 | 0.961 | 3.014 |
| `encode_enum_unit` | 0.250 | 0.297 | 0.000 | 0.296 |
| `decode_u8` | 0.992 | 0.926 | 0.915 | 0.981 |
| `decode_non_zero_u8` | 1.218 | 1.215 | 1.225 | 1.238 |
| `decode_bool` | 1.064 | 1.088 | 1.046 | 1.080 |
| `encode_struct_unnamed` | 1.452 | 1.238 | 0.815 | 2.296 |
| `encode_struct_named` | 1.464 | 1.471 | 1.105 | 3.026 |
| `encode_enum_unit` | 0.290 | 0.290 | 0.000 | 0.288 |
| `decode_u8` | 0.975 | 1.018 | 0.987 | 0.974 |
| `decode_non_zero_u8` | 1.192 | 1.292 | 1.268 | 1.286 |
| `decode_bool` | 1.037 | 1.099 | 1.041 | 1.101 |
| **Total time** → | 12.957 | 11.690 | 9.238 | 21.091 |
| **Total deviation (p.c.)** → | +40 | +27 | ±0 | +128 |
| **Total time** → | 14.456 | 11.624 | 8.800 | 21.509 |
| **Total deviation (p.c.)** → | +64 | +32 | ±0 | +144 |

View file

@ -32,16 +32,16 @@ readme.workspace = true
repository.workspace = true
[dependencies]
oct = { path = "../oct", version = "0.19", features = ["proc-macro"]}
oct = { path = "../oct", version = "0.20", features = ["proc-macro"]}
bincode = "1.3.0"
rand = "0.8.0"
rayon = "1.10.0"
zerocopy = "0.8.0"
bincode = "2.0"
rand = "0.8"
rayon = "1.10"
zerocopy = "0.8"
borsh = { version = "1.5.1", features = ["derive"] }
postcard = { version = "1.0.10", features = ["use-std"] }
serde = { version = "1.0.214", features = ["derive"] }
borsh = { version = "1.5", features = ["derive"] }
postcard = { version = "1.0", features = ["use-std"] }
serde = { version = "1.0", features = ["derive"] }
[lints]
workspace = true

View file

@ -128,14 +128,16 @@ macro_rules! benchmark {
}};
}
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
#[derive(bincode::Decode, bincode::Encode)]
#[derive(borsh::BorshSerialize)]
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
#[derive(serde::Deserialize, serde::Serialize)]
#[repr(transparent)]
struct Unit;
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
#[derive(bincode::Decode, bincode::Encode)]
#[derive(borsh::BorshSerialize)]
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
#[derive(serde::Deserialize, serde::Serialize)]
#[repr(transparent)]
struct Unnamed(u32);
@ -148,8 +150,9 @@ impl Unnamed {
}
}
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
#[derive(bincode::Decode, bincode::Encode)]
#[derive(borsh::BorshSerialize)]
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
#[derive(serde::Deserialize, serde::Serialize)]
#[repr(transparent)]
struct Named { buf: [u8; 0x8] }
@ -173,8 +176,9 @@ impl Named {
}
}
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
#[derive(bincode::Decode, bincode::Encode)]
#[derive(borsh::BorshSerialize)]
#[derive(oct::decode::Decode, oct::encode::Encode, oct::encode::SizedEncode)]
#[derive(serde::Deserialize, serde::Serialize)]
enum Enum {
Unit(Unit),
@ -233,14 +237,15 @@ fn main() {
bincode: {
// Requires `std`.
use bincode::serialize_into;
use bincode::encode_into_std_write;
use bincode::config;
const ITEM_SIZE: usize = size_of::<u8>();
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT];
for _ in 0x0..VALUE_COUNT {
serialize_into(&mut buf, &random::<u8>()).unwrap();
encode_into_std_write(random::<u8>(), &mut buf, config::standard()).unwrap();
}
}
@ -280,14 +285,15 @@ fn main() {
encode_u32: {
bincode: {
use bincode::serialize_into;
use bincode::encode_into_std_write;
use bincode::config;
const ITEM_SIZE: usize = size_of::<u32>();
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT];
for _ in 0x0..VALUE_COUNT {
serialize_into(&mut buf, &random::<u32>()).unwrap();
encode_into_std_write(random::<u32>(), &mut buf, config::standard()).unwrap();
}
}
@ -327,14 +333,15 @@ fn main() {
encode_u128: {
bincode: {
use bincode::serialize_into;
use bincode::encode_into_std_write;
use bincode::config;
const ITEM_SIZE: usize = size_of::<u128>();
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT];
for _ in 0x0..VALUE_COUNT {
serialize_into(&mut buf, &random::<u128>()).unwrap();
encode_into_std_write(random::<u128>(), &mut buf, config::standard()).unwrap();
}
}
@ -374,14 +381,15 @@ fn main() {
encode_char: {
bincode: {
use bincode::serialize_into;
use bincode::encode_into_std_write;
use bincode::config;
const ITEM_SIZE: usize = size_of::<char>();
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT];
for _ in 0x0..VALUE_COUNT {
serialize_into(&mut buf, &random::<char>()).unwrap();
encode_into_std_write(random::<char>(), &mut buf, config::standard()).unwrap();
}
}
@ -421,14 +429,15 @@ fn main() {
encode_struct_unit: {
bincode: {
use bincode::serialize_into;
use bincode::encode_into_std_write;
use bincode::config;
const ITEM_SIZE: usize = size_of::<Unit>();
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT];
for _ in 0x0..VALUE_COUNT {
serialize_into(&mut buf, &Unit).unwrap();
encode_into_std_write(Unit, &mut buf, config::standard()).unwrap();
}
}
@ -468,14 +477,15 @@ fn main() {
encode_struct_unnamed: {
bincode: {
use bincode::serialize_into;
use bincode::encode_into_std_write;
use bincode::config;
const ITEM_SIZE: usize = size_of::<Unnamed>();
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT];
for _ in 0x0..VALUE_COUNT {
serialize_into(&mut buf, &Unnamed::from_char(random())).unwrap();
encode_into_std_write(Unnamed::from_char(random()), &mut buf, config::standard()).unwrap();
}
}
@ -515,14 +525,15 @@ fn main() {
encode_struct_named: {
bincode: {
use bincode::serialize_into;
use bincode::encode_into_std_write;
use bincode::config;
const ITEM_SIZE: usize = size_of::<Named>();
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT];
for _ in 0x0..VALUE_COUNT {
serialize_into(&mut buf, &Named::from_u64(random())).unwrap();
encode_into_std_write(Named::from_u64(random()), &mut buf, config::standard()).unwrap();
}
}
@ -562,7 +573,8 @@ fn main() {
encode_enum_unit: {
bincode: {
use bincode::serialize_into;
use bincode::encode_into_std_write;
use bincode::config;
const ITEM_SIZE: usize =
size_of::<u32>() // discriminant
@ -571,7 +583,7 @@ fn main() {
let mut buf = vec![0x00; ITEM_SIZE * VALUE_COUNT];
for _ in 0x0..VALUE_COUNT {
serialize_into(&mut buf, &Enum::Unit(Unit)).unwrap();
encode_into_std_write(Enum::Unit(Unit), &mut buf, config::standard()).unwrap();
}
}
@ -617,6 +629,9 @@ fn main() {
decode_u8: {
bincode: {
use bincode::decode_from_slice;
use bincode::config;
const ITEM_SIZE: usize = size_of::<u8>();
let buf: Box<[_]> = generate_random_data::<u8>(ITEM_SIZE, VALUE_COUNT).collect();
@ -624,7 +639,7 @@ fn main() {
for i in 0x0..VALUE_COUNT {
let data = array::from_ref(&buf[i]).as_slice();
let _: u8 = bincode::deserialize_from(data).unwrap();
let _: (u8, usize) = decode_from_slice(data, config::standard()).unwrap();
}
}
@ -669,6 +684,9 @@ fn main() {
decode_non_zero_u8: {
bincode: {
use bincode::decode_from_slice;
use bincode::config;
const ITEM_SIZE: usize = size_of::<NonZero<u8>>();
let buf: Box<[_]> = generate_random_data::<NonZero<u8>>(ITEM_SIZE, VALUE_COUNT).collect();
@ -676,7 +694,7 @@ fn main() {
for i in 0x0..VALUE_COUNT {
let data = array::from_ref(&buf[i]).as_slice();
let _: NonZero<u8> = bincode::deserialize_from(data).unwrap();
let _: (NonZero<u8>, usize) = decode_from_slice(data, config::standard()).unwrap();
}
}
@ -721,6 +739,9 @@ fn main() {
decode_bool: {
bincode: {
use bincode::decode_from_slice;
use bincode::config;
const ITEM_SIZE: usize = size_of::<bool>();
let buf: Box<[_]> = generate_random_data::<bool>(ITEM_SIZE, VALUE_COUNT).collect();
@ -728,7 +749,7 @@ fn main() {
for i in 0x0..VALUE_COUNT {
let data = array::from_ref(&buf[i]).as_slice();
let _: bool = bincode::deserialize_from(data).unwrap();
let _: (bool, usize) = decode_from_slice(data, config::standard()).unwrap();
}
}
@ -754,7 +775,7 @@ fn main() {
let mut stream = Input::new(&buf);
for _ in 0x0..VALUE_COUNT {
let _ = bool::decode(&mut stream).unwrap();
let Ok(_) = bool::decode(&mut stream);
}
}

View file

@ -25,9 +25,9 @@ categories.workspace = true
proc-macro = true
[dependencies]
proc-macro2 = "1.0.0"
quote = "1.0.0"
syn = "2.0.0"
proc-macro2 = "1.0"
quote = "1.0"
syn = "2.0"
[lints]
workspace = true

View file

@ -62,7 +62,11 @@ pub fn decode_enum(data: DataEnum, repr: Repr) -> TokenStream {
let this = match discriminant {
#(#discriminants => #values,)*
value => return ::core::result::Result::Err(::oct::error::EnumDecodeError::UnassignedDiscriminant(value)),
value => {
::oct::__cold_path();
return ::core::result::Result::Err(::oct::error::EnumDecodeError::UnassignedDiscriminant(value))
},
};
::core::result::Result::Ok(this)

View file

@ -26,7 +26,7 @@ categories.workspace = true
all-features = true
[dependencies]
oct-macros = { path = "../oct-macros", version = "0.19", optional = true}
oct-macros = { path = "../oct-macros", version = "0.20", optional = true}
[features]
default = ["alloc", "proc-macro", "std"]

View file

@ -6,9 +6,9 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#[cfg(test)]
mod test;
use crate::__cold_path;
use crate::decode::{DecodeBorrowed, Input};
use crate::error::{
CharDecodeError,
@ -119,8 +119,14 @@ impl<T: Decode, const N: usize> Decode for [T; N] {
let mut buf = [const { MaybeUninit::<T>::uninit() }; N];
for (i, item) in buf.iter_mut().enumerate() {
let value = Decode::decode(input)
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
let value = match Decode::decode(input) {
Ok(value) => value,
Err(e) => {
__cold_path();
return Err(CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }));
}
};
item.write(value);
}
@ -283,7 +289,10 @@ impl Decode for char {
Ok(this)
},
code_point => Err(CharDecodeError { code_point }),
code_point => {
__cold_path();
Err(CharDecodeError { code_point })
},
}
}
}
@ -652,8 +661,7 @@ where
#[inline]
fn decode(input: &mut Input) -> Result<Self, Self::Error> {
let sign = bool::decode(input)
.map_err(EnumDecodeError::InvalidDiscriminant)?;
let Ok(sign) = bool::decode(input);
let this = if sign {
let value = Decode::decode(input)
@ -709,7 +717,10 @@ impl Decode for SocketAddr {
0x4 => Ok(Self::V4(Decode::decode(input).unwrap())),
0x6 => Ok(Self::V6(Decode::decode(input).unwrap())),
value => Err(EnumDecodeError::UnassignedDiscriminant(value)),
value => {
__cold_path();
Err(EnumDecodeError::UnassignedDiscriminant(value))
},
}
}
}
@ -758,6 +769,8 @@ impl Decode for alloc::string::String {
Ok(s) => Ok(s),
Err(e) => {
__cold_path();
let i = e.utf8_error().valid_up_to();
let c = e.as_bytes()[i];
@ -836,8 +849,14 @@ impl<T: Decode> Decode for alloc::vec::Vec<T> {
let buf = this.as_mut_ptr();
for i in 0x0..len {
let value = Decode::decode(input)
.map_err(|e| CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }))?;
let value = match Decode::decode(input) {
Ok(value) => value,
Err(e) => {
__cold_path();
return Err(CollectionDecodeError::BadItem(ItemDecodeError { index: i, error: e }));
}
};
// SAFETY: Each index is within bounds (i.e. capac-
// ity).
@ -922,7 +941,10 @@ macro_rules! impl_non_zero {
let Ok(value) = <$ty as ::oct::decode::Decode>::decode(input);
match value {
0x0 => Err(::oct::error::NonZeroDecodeError),
0x0 => {
__cold_path();
Err(::oct::error::NonZeroDecodeError)
},
value => {
let this = unsafe { ::core::num::NonZero::new_unchecked(value) };

View file

@ -6,6 +6,8 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#![cfg(test)]
use core::char;
use oct::decode::{Decode, Input};
use oct::encode::{Encode, SizedEncode};

View file

@ -6,7 +6,6 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#[cfg(test)]
mod test;
use crate::error::InputError;
@ -186,7 +185,7 @@ impl Borrow<[u8]> for Input<'_> {
}
impl Debug for Input<'_> {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Debug::fmt(self.as_slice(), f)
}

View file

@ -6,6 +6,8 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#![cfg(test)]
use oct::decode::Input;
use oct::error::InputError;

View file

@ -6,7 +6,6 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#[cfg(test)]
mod test;
use crate::encode::Output;

View file

@ -6,6 +6,8 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#![cfg(test)]
use core::time::Duration;
use oct::encode::{Encode, SizedEncode};
use oct::error::UsizeEncodeError;

View file

@ -6,7 +6,6 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#[cfg(test)]
mod test;
use crate::error::OutputError;
@ -118,7 +117,7 @@ impl Borrow<[u8]> for Output<'_> {
}
impl Debug for Output<'_> {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Debug::fmt(self.as_slice(), f)
}

View file

@ -6,6 +6,8 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#![cfg(test)]
use oct::encode::Output;
use oct::error::OutputError;

View file

@ -6,7 +6,6 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#[cfg(test)]
mod test;
use crate::encode::Encode;

View file

@ -6,6 +6,8 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#![cfg(test)]
use core::convert::Infallible;
use core::marker::PhantomData;
use core::net::{

View file

@ -26,7 +26,7 @@ pub struct CharDecodeError {
}
impl Display for CharDecodeError {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "code point U+{:04X} is not defined", self.code_point)
}

View file

@ -45,8 +45,6 @@ pub enum GenericDecodeError {
UnassignedDiscriminant(PrimDiscriminant),
/// The [`SystemTime`](std::time::SystemTime) type was too narrow.
#[cfg(feature = "std")]
#[cfg_attr(doc, doc(cfg(feature = "std")))]
NarrowSystemTime(SystemTimeDecodeError),
}
@ -66,7 +64,6 @@ impl Display for GenericDecodeError {
Self::UnassignedDiscriminant(value)
=> write!(f, "discriminant value `{value:#X} has not been assigned"),
#[cfg(feature = "std")]
Self::NarrowSystemTime(ref e)
=> write!(f, "{e}"),
}
@ -83,7 +80,6 @@ impl Error for GenericDecodeError {
Self::SmallBuffer(ref e) => Some(e),
#[cfg(feature = "std")]
Self::NarrowSystemTime(ref e) => Some(e),
_ => None,
@ -158,8 +154,6 @@ impl From<LengthError> for GenericDecodeError {
}
}
#[cfg(feature = "std")]
#[cfg_attr(doc, doc(cfg(feature = "std")))]
impl From<SystemTimeDecodeError> for GenericDecodeError {
#[inline(always)]
fn from(value: SystemTimeDecodeError) -> Self {

View file

@ -28,7 +28,7 @@ pub struct InputError {
}
impl Display for InputError {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,

View file

@ -22,7 +22,7 @@ pub struct IsizeEncodeError(
);
impl Display for IsizeEncodeError {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,

View file

@ -29,7 +29,7 @@ where
I: Display,
E: Display,
{
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "could not decode item at `{}`: {}", self.index, self.error)
}

View file

@ -29,7 +29,7 @@ where
I: Display,
E: Display,
{
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "could not encode item at `{}`: {}", self.index, self.error)
}

View file

@ -30,7 +30,7 @@ pub struct LengthError {
}
impl Display for LengthError {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "collection with ({}) remaining size cannot hold ({}) more elements", self.remaining, self.count)
}

View file

@ -26,12 +26,10 @@ mod length_error;
mod non_zero_decode_error;
mod output_error;
mod ref_cell_encode_error;
mod system_time_decode_error;
mod usize_encode_error;
mod utf8_error;
#[cfg(feature = "std")]
mod system_time_decode_error;
pub use char_decode_error::CharDecodeError;
pub use collection_decode_error::CollectionDecodeError;
pub use collection_encode_error::CollectionEncodeError;
@ -47,8 +45,6 @@ pub use length_error::LengthError;
pub use non_zero_decode_error::NonZeroDecodeError;
pub use output_error::OutputError;
pub use ref_cell_encode_error::RefCellEncodeError;
pub use system_time_decode_error::SystemTimeDecodeError;
pub use usize_encode_error::UsizeEncodeError;
pub use utf8_error::Utf8Error;
#[cfg(feature = "std")]
pub use system_time_decode_error::SystemTimeDecodeError;

View file

@ -18,7 +18,7 @@ use core::hint::unreachable_unchecked;
pub struct NonZeroDecodeError;
impl Display for NonZeroDecodeError {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "expected non-zero integer but found `0`")
}

View file

@ -28,7 +28,7 @@ pub struct OutputError {
}
impl Display for OutputError {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,

View file

@ -15,7 +15,6 @@ use core::hint::unreachable_unchecked;
///
/// Note that a UNIX timestamp is here defined as a signed, 64-bit integer denoting a difference of time to 1 january 1970, as measured in Greenwich using seconds.
/// This error should therefore not occur on systems that use the same or a more precise counter.
#[cfg_attr(doc, doc(cfg(feature = "std")))]
#[derive(Debug, Eq, PartialEq)]
#[must_use]
pub struct SystemTimeDecodeError {
@ -23,18 +22,15 @@ pub struct SystemTimeDecodeError {
pub timestamp: i64,
}
#[cfg_attr(doc, doc(cfg(feature = "std")))]
impl Display for SystemTimeDecodeError {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "could not represent `{}` as a system timestamp", self.timestamp)
}
}
#[cfg_attr(doc, doc(cfg(feature = "std")))]
impl Error for SystemTimeDecodeError { }
#[cfg_attr(doc, doc(cfg(feature = "std")))]
impl From<Infallible> for SystemTimeDecodeError {
#[inline(always)]
fn from(_value: Infallible) -> Self {

View file

@ -22,7 +22,7 @@ pub struct UsizeEncodeError(
);
impl Display for UsizeEncodeError {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,

View file

@ -23,7 +23,7 @@ pub struct Utf8Error {
}
impl Display for Utf8Error {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "found invalid utf-8 octet {:#02X} at offset ({})", self.value, self.index)
}

View file

@ -28,19 +28,19 @@
//!
//! | Benchmark | [Bincode] | [Borsh] | Oct | [Postcard] |
//! | :--------------------------------- | --------: | ------: | -----: | ---------: |
//! | `encode_u8` | 0.927 | 0.939 | 0.742 | 0.896 |
//! | `encode_u32` | 1.069 | 1.007 | 0.738 | 2.732 |
//! | `encode_u128` | 2.180 | 2.204 | 1.522 | 6.412 |
//! | `encode_char` | 2.474 | 1.261 | 0.817 | 2.480 |
//! | `encode_u8` | 1.004 | 0.880 | 0.812 | 0.860 |
//! | `encode_u32` | 1.312 | 0.973 | 0.818 | 2.706 |
//! | `encode_u128` | 2.631 | 2.174 | 1.561 | 6.159 |
//! | `encode_char` | 1.598 | 1.256 | 0.830 | 2.393 |
//! | `encode_struct_unit` | 0.000 | 0.000 | 0.000 | 0.000 |
//! | `encode_struct_unnamed` | 1.245 | 1.146 | 0.834 | 2.378 |
//! | `encode_struct_named` | 3.037 | 1.541 | 0.961 | 3.014 |
//! | `encode_enum_unit` | 0.250 | 0.297 | 0.000 | 0.296 |
//! | `decode_u8` | 0.992 | 0.926 | 0.915 | 0.981 |
//! | `decode_non_zero_u8` | 1.218 | 1.215 | 1.225 | 1.238 |
//! | `decode_bool` | 1.064 | 1.088 | 1.046 | 1.080 |
//! | **Total time** &#8594; | 14.456 | 11.624 | 8.800 | 21.509 |
//! | **Total deviation (p.c.)** &#8594; | +64 | +32 | ±0 | +144 |
//! | `encode_struct_unnamed` | 1.452 | 1.238 | 0.815 | 2.296 |
//! | `encode_struct_named` | 1.464 | 1.471 | 1.105 | 3.026 |
//! | `encode_enum_unit` | 0.290 | 0.290 | 0.000 | 0.288 |
//! | `decode_u8` | 0.975 | 1.018 | 0.987 | 0.974 |
//! | `decode_non_zero_u8` | 1.192 | 1.292 | 1.268 | 1.286 |
//! | `decode_bool` | 1.037 | 1.099 | 1.041 | 1.101 |
//! | **Total time** &#8594; | 12.957 | 11.690 | 9.238 | 21.091 |
//! | **Total deviation (p.c.)** &#8594; | +40 | +27 | ±0 | +128 |
//!
//! [Bincode]: https://crates.io/crates/bincode/
//! [Borsh]: https://crates.io/crates/borsh/
@ -286,3 +286,11 @@ macro_rules! string {
const { $crate::string::__string("") }
}};
}
// NOTE: Stable equivalent of `core::hint::
// cold_path`. Should not be used directly, but is
// used in derive macros.
#[doc(hidden)]
#[inline(always)]
#[cold]
pub const fn __cold_path() { }

View file

@ -8,7 +8,6 @@
use crate::PrimRepr;
#[cfg(test)]
mod test;
/// A generic-but-primitive discriminant.

View file

@ -6,6 +6,8 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#![cfg(test)]
use alloc::format;
use oct::PrimDiscriminant;

View file

@ -6,7 +6,6 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#[cfg(test)]
mod test;
use crate::decode::{Decode, Input};
@ -343,8 +342,10 @@ impl<T> BorrowMut<[u8]> for Slot<T> {
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]
impl<T> Debug for Slot<T> {
#[inline(always)]
fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{:?}", &**self) }
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{:?}", &**self)
}
}
#[cfg_attr(doc, doc(cfg(feature = "alloc")))]

View file

@ -6,6 +6,8 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#![cfg(test)]
use oct::error::CharDecodeError;
use oct::slot::Slot;

View file

@ -6,7 +6,6 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#[cfg(test)]
mod test;
use crate::decode::{self, Decode, DecodeBorrowed};
@ -437,7 +436,7 @@ impl<const N: usize> DerefMut for String<N> {
}
impl<const N: usize> Debug for String<N> {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Debug::fmt(self.as_str(), f)
}
@ -462,7 +461,7 @@ impl<const N: usize> Decode for String<N> {
impl<const N: usize> DecodeBorrowed<str> for String<N> { }
impl<const N: usize> Display for String<N> {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Display::fmt(self.as_str(), f)
}

View file

@ -6,6 +6,8 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#![cfg(test)]
use core::cmp::Ordering;
use oct::string;
use oct::error::Utf8Error;

View file

@ -6,7 +6,6 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#[cfg(test)]
mod test;
use crate::vec::{clone_to_uninit_in_range, Vec};

View file

@ -6,6 +6,8 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#![cfg(test)]
use oct::string;
use oct::string::String;
use oct::vec::Vec;

View file

@ -6,7 +6,6 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#[cfg(test)]
mod test;
use crate::decode::{self, Decode, DecodeBorrowed};
@ -255,31 +254,9 @@ impl<T, const N: usize> Vec<T, N> {
unsafe { Vec::from_raw_parts(buf, len) }
}
/// Sets the length of the vector.
///
/// The provided length is tested to be no greater than the current length.
/// For the same operation *without* these checks, see [`set_len_unchecked`](Self::set_len_unchecked).
///
/// # Panics
///
/// The new length `len` may not be larger than `N`.
///
/// It is only valid to enlarge vectors if `T` supports being in a purely uninitialised state.
/// Such is permitted with e.g. [`MaybeUninit`].
#[inline(always)]
#[track_caller]
pub const fn set_len(&mut self, len: usize) {
assert!(len <= self.len(), "cannot extend length of vector");
// SAFETY: We have asserted that the new length is
// still within bounds.
unsafe { self.set_len_unchecked(len) };
}
/// Unsafely sets the length of the vector.
///
/// The provided length is **not** tested in any way.
/// For the same operation *with* these checks, see [`set_len`](Self::set_len).
///
/// # Safety
///
@ -289,9 +266,11 @@ impl<T, const N: usize> Vec<T, N> {
/// Such is permitted by e.g. [`MaybeUninit`].
#[inline(always)]
#[track_caller]
pub const unsafe fn set_len_unchecked(&mut self, len: usize) {
pub const unsafe fn set_len(&mut self, len: usize) {
debug_assert!(len <= N, "cannot set length past bounds");
// SAFETY: The caller guarantees that `len` is not
// be freaky.
self.len = len
}
@ -478,7 +457,7 @@ impl<T: Clone, const N: usize> Clone for Vec<T, N> {
}
impl<T: Debug, const N: usize> Debug for Vec<T, N> {
#[inline(always)]
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Debug::fmt(self.as_slice(), f)
}

View file

@ -8,6 +8,8 @@
// can obtain one at:
// <https://mozilla.org/MPL/2.0/>.
#![cfg(test)]
use oct::vec;
use oct::vec::Vec;