oct 0.37.0

Octonary utilities.
Documentation
// Copyright 2024-2026 Gabriel Bjørnager Jensen.
//
// SPDX: MIT OR Apache-2.0

//! Octonary transcoder.
//!
//! This library provides facilities for safe (and
//! hopefully sound) transmutations of Rust objects,
//! mainly to and from octonary (bytewise)
//! representations. These transformations may be
//! done in two ways:
//!
//! * In-place transmutations: Objects can be
//!   reinterpret between different types in-place.
//! * Serialisations: Objects can also be serialise
//!   into a portable representation.
//!
//! These interfaces are generally safe and are
//! designed so that most programmes can completely
//! avoid any unsafe code.
//!
//! # Security
//!
//! Do note that this project is still relatively
//! early in its development. But even with the
//! hundreds of man-hours of development so far, I
//! very much recommend auditing it before using it
//! in production (nevertheless the so-far soundness
//! holes uncovered.) I would not *yet* use this
//! project in critical systems -- although I am
//! confident that it will become realistic to do so
//! at some point.
//!
//! # Interface stability and versioning
//!
//! Breaking changes are common, and usage of this
//! library will require continuous maintenance so
//! as to avoid becoming stuck on an unmaintained
//! major release. Nonetheless, core designs are
//! likely to remain more or less the same, and most
//! breakage will be in the form of lesser,
//! syntactical changes, e.g. identifier renaming or
//! parameter reordering.
//!
//! The octonary format used by serialisations is
//! not stabilised and are not on track to become
//! stabilised. Instead, users should use in-place
//! transmutations or custom serialisers for
//! specific specifications.
//!
//! # Copyright and licence
//!
//! Copyright © 2024‐2026 Gabriel
//! Bjørnager Jensen.
//!
//! This library is distributed under either an MIT
//! licence or version 2.0 of the Apache License, at
//! your option. See `LICENCE-MIT.txt` and
//! `LICENCE-APACHE.txt` for more information.
//!
//! SPDX identifier: `MIT OR Apache-2.0`

#![doc(html_logo_url = "https://codeberg.org/bjoernager/oct/raw/branch/master/DOC-ICON.svg")]

#![no_std]

#![cfg_attr(feature = "unstable_docs", allow(internal_features))]

#![cfg_attr(feature = "ascii", feature(ascii_char))]

#![cfg_attr(all(target_has_atomic = "128", feature = "atomic_u128_i128"), feature(integer_atomics))]

#![cfg_attr(feature = "bstr", feature(bstr))]

#![cfg_attr(feature = "f128", feature(f128))]

#![cfg_attr(feature = "f16", feature(f16))]

#![cfg_attr(
	all(
		any(
			target_arch = "aarch64",
			target_arch = "arm64ec",
			target_feature = "v7",
		),
		feature = "f16",
	),
	feature(
		stdarch_neon_f16,
	),
)]

#![cfg_attr(feature = "simd", feature(portable_simd))]

#![cfg_attr(feature = "unstable_docs", feature(doc_cfg, rustdoc_internals))]

extern crate self as oct;

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "std")]
extern crate std;

pub mod serdes;

mod from_octets;
mod immutable;
mod into_octets;
mod outlay;
mod util;
mod unaligned;
mod zeroable;

pub use from_octets::FromOctets;
pub use immutable::Immutable;
pub use into_octets::IntoOctets;
pub use outlay::Outlay;
pub use unaligned::Unaligned;
pub use util::{
	fill,
	fill_unchecked,
	fill_zeros,
	filled,
	octets_of,
	octets_of_mut,
	transmute,
	transmute_copy,
	transmute_mut,
	transmute_mut_with_metadata,
	transmute_ref,
	transmute_ref_with_metadata,
	transmute_unchecked,
	zeroed,
};
pub use zeroable::Zeroable;

#[cfg(feature = "alloc")]
pub use util::{
	boxed_from_fn_with_metadata,
	zeroed_boxed_with_metadata,
};

/// Implements [`FromOctets`] for the given type.
///
/// [`FromOctets`]: trait@FromOctets
///
/// # Examples
///
/// Any type can derive [`FromOctets`] -- as long as
/// all member fields also implement it.
///
/// [`FromOctets`]: trait@FromOctets
///
/// ```rust
/// use oct::{FromOctets, Zeroable};
///
/// #[derive(FromOctets, Zeroable)]
/// struct Reminder {
///     timestamp: i64,
/// }
/// ```
///
/// For enumerations, this includes the discriminant
/// -- which must have all values occupied:
///
/// ```rust
/// use oct::{FromOctets, Zeroable};
///
/// #[repr(u8)]
/// #[derive(FromOctets, Zeroable)]
/// enum U8Enum {
///     V000, V001, V002, V003, V004, V005, V006, V007, V008, V009,
///     V010, V011, V012, V013, V014, V015, V016, V017, V018, V019,
///     V020, V021, V022, V023, V024, V025, V026, V027, V028, V029,
///     V030, V031, V032, V033, V034, V035, V036, V037, V038, V039,
///     V040, V041, V042, V043, V044, V045, V046, V047, V048, V049,
///     V050, V051, V052, V053, V054, V055, V056, V057, V058, V059,
///     V060, V061, V062, V063, V064, V065, V066, V067, V068, V069,
///     V070, V071, V072, V073, V074, V075, V076, V077, V078, V079,
///     V080, V081, V082, V083, V084, V085, V086, V087, V088, V089,
///     V090, V091, V092, V093, V094, V095, V096, V097, V098, V099,
///     V100, V101, V102, V103, V104, V105, V106, V107, V108, V109,
///     V110, V111, V112, V113, V114, V115, V116, V117, V118, V119,
///     V120, V121, V122, V123, V124, V125, V126, V127, V128, V129,
///     V130, V131, V132, V133, V134, V135, V136, V137, V138, V139,
///     V140, V141, V142, V143, V144, V145, V146, V147, V148, V149,
///     V150, V151, V152, V153, V154, V155, V156, V157, V158, V159,
///     V160, V161, V162, V163, V164, V165, V166, V167, V168, V169,
///     V170, V171, V172, V173, V174, V175, V176, V177, V178, V179,
///     V180, V181, V182, V183, V184, V185, V186, V187, V188, V189,
///     V190, V191, V192, V193, V194, V195, V196, V197, V198, V199,
///     V200, V201, V202, V203, V204, V205, V206, V207, V208, V209,
///     V210, V211, V212, V213, V214, V215, V216, V217, V218, V219,
///     V220, V221, V222, V223, V224, V225, V226, V227, V228, V229,
///     V230, V231, V232, V233, V234, V235, V236, V237, V238, V239,
///     V240, V241, V242, V243, V244, V245, V246, V247, V248, V249,
///     V250, V251, V252, V253, V254, V255,
/// }
/// ```
///
/// Enumerations without defined representations are
/// always rejected:
///
/// ```rust,compile_fail
/// use oct::{FromOctets, Zeroable};
///
/// #[derive(FromOctets, Zeroable)]
/// enum EnumWithoutRepr {
///     V000, V001, V002, V003, V004, V005, V006, V007, V008, V009,
///     V010, V011, V012, V013, V014, V015, V016, V017, V018, V019,
///     V020, V021, V022, V023, V024, V025, V026, V027, V028, V029,
///     V030, V031, V032, V033, V034, V035, V036, V037, V038, V039,
///     V040, V041, V042, V043, V044, V045, V046, V047, V048, V049,
///     V050, V051, V052, V053, V054, V055, V056, V057, V058, V059,
///     V060, V061, V062, V063, V064, V065, V066, V067, V068, V069,
///     V070, V071, V072, V073, V074, V075, V076, V077, V078, V079,
///     V080, V081, V082, V083, V084, V085, V086, V087, V088, V089,
///     V090, V091, V092, V093, V094, V095, V096, V097, V098, V099,
///     V100, V101, V102, V103, V104, V105, V106, V107, V108, V109,
///     V110, V111, V112, V113, V114, V115, V116, V117, V118, V119,
///     V120, V121, V122, V123, V124, V125, V126, V127, V128, V129,
///     V130, V131, V132, V133, V134, V135, V136, V137, V138, V139,
///     V140, V141, V142, V143, V144, V145, V146, V147, V148, V149,
///     V150, V151, V152, V153, V154, V155, V156, V157, V158, V159,
///     V160, V161, V162, V163, V164, V165, V166, V167, V168, V169,
///     V170, V171, V172, V173, V174, V175, V176, V177, V178, V179,
///     V180, V181, V182, V183, V184, V185, V186, V187, V188, V189,
///     V190, V191, V192, V193, V194, V195, V196, V197, V198, V199,
///     V200, V201, V202, V203, V204, V205, V206, V207, V208, V209,
///     V210, V211, V212, V213, V214, V215, V216, V217, V218, V219,
///     V220, V221, V222, V223, V224, V225, V226, V227, V228, V229,
///     V230, V231, V232, V233, V234, V235, V236, V237, V238, V239,
///     V240, V241, V242, V243, V244, V245, V246, V247, V248, V249,
///     V250, V251, V252, V253, V254, V255,
/// }
/// ```
///
/// Enumerations are also rejected if they have a
/// partial discriminant:
///
/// ```rust,compile_fail
/// use oct::{FromOctets, Zeroable};
///
/// #[derive(FromOctets, Zeroable)]
/// enum EnumWithoutCompleteDiscriminant {
///     V000, V001, V002, V003, V004, V005, V006, V007, V008, V009,
///     V010, V011, V012, V013, V014, V015, V016, V017, V018, V019,
///     V020, V021, V022, V023, V024, V025, V026, V027, V028, V029,
///     V030, V031, V032, V033, V034, V035, V036, V037, V038, V039,
///     V040, V041, V042, V043, V044, V045, V046, V047, V048, V049,
///     V050, V051, V052, V053, V054, V055, V056, V057, V058, V059,
///     V060, V061, V062, V063, V064, V065, V066, V067, V068, V069,
///     V070, V071, V072, V073, V074, V075, V076, V077, V078, V079,
///     V080, V081, V082, V083, V084, V085, V086, V087, V088, V089,
///     V090, V091, V092, V093, V094, V095, V096, V097, V098, V099,
///     V100, V101, V102, V103, V104, V105, V106, V107, V108, V109,
///     V110, V111, V112, V113, V114, V115, V116, V117, V118, V119,
///     V120, V121, V122, V123, V124, V125, V126, V127, V128, V129,
///     V130, V131, V132, V133, V134, V135, V136, V137, V138, V139,
///     V140, V141, V142, V143, V144, V145, V146, V147, V148, V149,
///     V150, V151, V152, V153, V154, V155, V156, V157, V158, V159,
///     V160, V161, V162, V163, V164, V165, V166, V167, V168, V169,
///     V170, V171, V172, V173, V174, V175, V176, V177, V178, V179,
///     V180, V181, V182, V183, V184, V185, V186, V187, V188, V189,
///     V190, V191, V192, V193, V194, V195, V196, V197, V198, V199,
///     V200, V201, V202, V203, V204, V205, V206, V207, V208, V209,
///     V210, V211, V212, V213, V214, V215, V216, V217, V218, V219,
///     V220, V221, V222, V223, V224, V225, V226, V227, V228, V229,
///     V230, V231, V232, V233, V234, V235, V236, V237, V238, V239,
///     V240, V241, V242, V243, V244, V245, V246, V247, V248, V249,
///     V250, V251, V252, V253, V254, /* V255, */
/// }
/// ```
#[cfg(feature = "proc_macro")]
#[doc(inline)]
pub use oct_macros::FromOctets;

/// Implements [`Immutable`] for the given type.
///
/// [`Immutable`]: trait@Immutable
///
/// # Examples
///
/// Most types can simply derive [`Immutable`],
/// provided that all fields also implement
/// `Immutable`:
///
/// [`Immutable`]: trait@Immutable
///
/// ```rust
/// use oct::Immutable;
///
/// #[derive(Immutable)]
/// struct InteriourImmutableI32 {
///     value: i32,
/// }
/// ```
///
/// Types that contain [`UnsafeCell`] (or other cell
/// types) can thus not derive `Immutable`:
///
/// [`UnsafeCell`]: core::cell::UnsafeCell
///
/// ```rust,compile_fail
/// use core::cell::Cell;
/// use oct::Immutable;
///
/// #[derive(Immutable)]
/// struct InteriourMutableI32 {
///     value: Cell<i32>,
/// }
/// ```
#[cfg(feature = "proc_macro")]
#[doc(inline)]
pub use oct_macros::Immutable;

/// Implements [`Zeroable`] for the given type.
///
/// [`Zeroable`]: trait@Zeroable
///
/// # Examples
///
/// Enumerations must have a variant that uses `0`
/// as its discriminant:
///
/// ```rust
/// use oct::Zeroable;
///
/// #[repr(u8)]
/// #[derive(Zeroable)]
/// enum ExplicitZero {
///     Zero = 0,
/// }
///
/// #[repr(i8)]
/// #[derive(Zeroable)]
/// enum ImplicitZero {
///     NegativeOne = -1,
///     Zero,
/// }
/// ```
///
/// Thus, the following is rejected:
///
/// ```rust,compile_fail
/// use oct::Zeroable;
///
/// #[repr(i32)]
/// #[derive(Zeroable)]
/// enum NoZeroDiscriminant {
///     NegativeTwo = -2,
///     NegativeOne,
///     One         = 1,
/// }
/// ```
#[cfg(feature = "proc_macro")]
#[doc(inline)]
pub use oct_macros::Zeroable;