qubit-codec 0.16.2

Core codec traits and buffer conversion primitives for Rust
Documentation
// =============================================================================
//    Copyright (c) 2026 Haixing Hu.
//
//    SPDX-License-Identifier: Apache-2.0
//
//    Licensed under the Apache License, Version 2.0.
// =============================================================================
//! # qubit-codec
//!
//! Domain-neutral codec traits and buffer conversion primitives.
//!
//! `qubit-codec` is the foundation shared by the Qubit binary, text, misc, and
//! I/O codec crates. It defines the small contracts that concrete format crates
//! build on, without shipping concrete binary or text formats itself.
//!
//! # Overview
//!
//! The crate provides:
//!
//! - [`Codec`] for low-level single-value codecs over caller-managed buffers.
//! - [`CodecValueEncoder`] and [`CodecValueDecoder`] for owned one-value
//!   convenience APIs.
//! - [`CodecTranscodeEncoder`], [`CodecTranscodeDecoder`], and
//!   [`CodecTranscodeConverter`] for strict streaming adapters around a
//!   [`Codec`].
//! - [`engine::TranscodeEncodeEngine`], [`engine::TranscodeDecodeEngine`], and
//!   [`engine::TranscodeConvertEngine`] for policy-aware buffered loops.
//! - [`engine::TranscodeEncodeHooks`] and [`engine::TranscodeDecodeHooks`] for
//!   replacement, skip, report, finish, and reset policy decisions.
//! - [`Transcoder`], [`TranscodeProgress`], and [`TranscodeStatus`] for
//!   caller-managed streaming conversion.
//! - [`ValueEncoder`] and [`ValueDecoder`] for whole-value convenience APIs.
//! - [`ByteOrder`], [`ByteOrderSpec`], [`BigEndian`], [`LittleEndian`], and
//!   [`NativeEndian`] for shared byte-order metadata.
//! - `qubit_utils::nonzero()` for checked `NonZeroUsize` construction shared by
//!   codec implementations.
//!
//! Concrete codecs live in sibling crates such as `qubit-codec-binary`,
//! `qubit-codec-text`, and `qubit-codec-misc`.
//!
//! # Choosing an Abstraction
//!
//! Pick the smallest layer that matches the shape of the problem:
//!
//! ```text
//! What are you writing?
//!
//! +-- A codec for one logical value
//! |   (UTF-8 char, LEB128 integer, fixed-width scalar, ...)
//! |       -> implement Codec
//! |
//! +-- A whole-value codec where a single-value quantum is not useful
//! |   (Base64 text, percent encoding, escaped strings, ...)
//! |       -> implement ValueEncoder<Input> / ValueDecoder<Input>
//! |
//! +-- A strict streaming wrapper around an existing Codec
//! |       -> use CodecTranscodeDecoder<C> / CodecTranscodeEncoder<C>
//! |          / CodecTranscodeConverter<D, E>
//! |
//! +-- An owned-output wrapper around an existing Codec
//! |       -> use CodecValueEncoder<C> / CodecValueDecoder<C>
//! |
//! +-- A streaming codec with policy decisions
//!     (skip, replace, count, report, finish output, ...)
//!         -> implement engine::TranscodeDecodeHooks<C>
//!            / engine::TranscodeEncodeHooks<C>
//!            and use engine::TranscodeDecodeEngine<C, H>
//!            / engine::TranscodeEncodeEngine<C, H>
//! ```
//!
//! Unit-to-unit conversions, such as UTF-8 bytes to UTF-16 units, compose a
//! decode side and an encode side. Use [`CodecTranscodeConverter`] for a strict
//! pipeline and [`engine::TranscodeConvertEngine`] when either side needs
//! policy hooks.
//!
//! # Layer Overview
//!
//! ```text
//! concrete I/O crates
//!   |
//! TranscodeDecodeInput / TranscodeEncodeOutput  [feature = "io"]
//!   |
//! Transcode*Engine + Transcode*Hooks
//! CodecTranscodeDecoder / Encoder / Converter
//!   |
//! Transcoder + TranscodeProgress + TranscodeStatus
//! ValueEncoder / ValueDecoder
//!   |
//! Codec
//! ```
//!
//! Implementing further up the stack does not require rewriting the lower
//! layers. The adapter types turn any suitable [`Codec`] into owned-value or
//! streaming APIs. Drop down to the engine and hook layer when the codec needs
//! continuous-stream semantics or policy decisions.

#![deny(missing_docs)]
#![deny(unsafe_op_in_unsafe_fn)]

mod byte_order;
mod codec;
mod transcode;
mod value;

/// Policy-aware transcode engines, hooks, contexts, and policy actions.
pub mod engine {
    pub use crate::transcode::DecodeContext;
    pub use crate::transcode::DecodeIncompleteAction;
    pub use crate::transcode::DecodeIncompleteActionOf;
    pub use crate::transcode::DecodeInvalidAction;
    pub use crate::transcode::DecodeInvalidActionOf;
    pub use crate::transcode::EncodeContext;
    pub use crate::transcode::EncodeUnencodableAction;
    pub use crate::transcode::EncodeUnencodableActionOf;
    pub use crate::transcode::TranscodeConvertEngine;
    pub use crate::transcode::TranscodeDecodeEngine;
    pub use crate::transcode::TranscodeDecodeHooks;
    pub use crate::transcode::TranscodeEncodeEngine;
    pub use crate::transcode::TranscodeEncodeHooks;
}

pub use byte_order::BigEndian;
pub use byte_order::ByteOrder;
pub use byte_order::ByteOrderSpec;
pub use byte_order::LittleEndian;
pub use byte_order::NativeEndian;
pub use codec::Codec;
pub use codec::DecodeFailure;
#[cfg(feature = "io")]
pub use transcode::AsyncTranscodeDecodeInput;
#[cfg(feature = "io")]
pub use transcode::AsyncTranscodeDecodeStep;
#[cfg(feature = "io")]
pub use transcode::AsyncTranscodeEncodeOutput;
pub use transcode::CapacityError;
pub use transcode::CodecTranscodeConverter;
pub use transcode::CodecTranscodeDecoder;
pub use transcode::CodecTranscodeEncoder;
pub use transcode::TranscodeContractError;
pub use transcode::TranscodeConvertError;
pub use transcode::TranscodeConvertErrorOf;
pub use transcode::TranscodeConverter;
pub use transcode::TranscodeDecodeError;
pub use transcode::TranscodeDecodeErrorOf;
#[cfg(feature = "io")]
pub use transcode::TranscodeDecodeInput;
pub use transcode::TranscodeDecoder;
pub use transcode::TranscodeDomainError;
pub use transcode::TranscodeEncodeError;
pub use transcode::TranscodeEncodeErrorOf;
#[cfg(feature = "io")]
pub use transcode::TranscodeEncodeOutput;
pub use transcode::TranscodeEncoder;
pub use transcode::TranscodeFailure;
pub use transcode::TranscodeProgress;
pub use transcode::TranscodeStatus;
pub use transcode::Transcoder;
pub use value::CodecValueDecoder;
pub use value::CodecValueEncoder;
pub use value::DecodeLifecycleOutput;
pub use value::DecodeLifecycleProgress;
#[cfg(all(feature = "json", feature = "registry"))]
pub use value::JSON_BYTES_VALUE_CODEC_ID;
#[cfg(all(feature = "json", feature = "registry"))]
pub use value::JSON_STRING_VALUE_CODEC_ID;
#[cfg(feature = "json")]
pub use value::JsonBytesValueCodec;
#[cfg(feature = "json")]
pub use value::JsonBytesValueDecoder;
#[cfg(feature = "json")]
pub use value::JsonBytesValueEncoder;
#[cfg(feature = "json")]
pub use value::JsonStringValueCodec;
#[cfg(feature = "json")]
pub use value::JsonStringValueDecoder;
#[cfg(feature = "json")]
pub use value::JsonStringValueEncoder;
#[cfg(feature = "registry")]
pub use value::ValueBytesCodecDescriptor;
#[cfg(feature = "registry")]
pub use value::ValueBytesCodecRegistration;
#[cfg(feature = "registry")]
#[doc(hidden)]
pub use value::ValueBytesCodecRegistrationFactory;
#[cfg(feature = "registry")]
pub use value::ValueBytesCodecRegistry;
#[cfg(feature = "registry")]
pub use value::ValueCodecExecutionError;
#[cfg(feature = "registry")]
pub use value::ValueCodecId;
#[cfg(feature = "registry")]
pub use value::ValueCodecIdError;
#[cfg(feature = "registry")]
pub use value::ValueCodecRegistration;
#[cfg(feature = "registry")]
pub use value::ValueCodecRegistrationSource;
#[cfg(feature = "registry")]
pub use value::ValueCodecRegistry;
#[cfg(feature = "registry")]
pub use value::ValueCodecRegistryError;
pub use value::ValueDecoder;
pub use value::ValueEncoder;
#[cfg(feature = "registry")]
pub use value::ValueStringCodecDescriptor;
#[cfg(feature = "registry")]
pub use value::ValueStringCodecRegistration;
#[cfg(feature = "registry")]
#[doc(hidden)]
pub use value::ValueStringCodecRegistrationFactory;
#[cfg(feature = "registry")]
pub use value::ValueStringCodecRegistry;

#[cfg(feature = "registry")]
#[doc(hidden)]
pub mod __private {
    pub use inventory;
}