Skip to main content

qubit_codec/
lib.rs

1// =============================================================================
2//    Copyright (c) 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! # qubit-codec
9//!
10//! Domain-neutral codec traits and buffer conversion primitives.
11//!
12//! `qubit-codec` is the foundation shared by the Qubit binary, text, misc, and
13//! I/O codec crates. It defines the small contracts that concrete format crates
14//! build on, without shipping concrete binary or text formats itself.
15//!
16//! # Overview
17//!
18//! The crate provides:
19//!
20//! - [`Codec`] for low-level single-value codecs over caller-managed buffers.
21//! - [`CodecValueEncoder`] and [`CodecValueDecoder`] for owned one-value
22//!   convenience APIs.
23//! - [`CodecTranscodeEncoder`], [`CodecTranscodeDecoder`], and
24//!   [`CodecTranscodeConverter`] for strict streaming adapters around a
25//!   [`Codec`].
26//! - [`engine::TranscodeEncodeEngine`], [`engine::TranscodeDecodeEngine`], and
27//!   [`engine::TranscodeConvertEngine`] for policy-aware buffered loops.
28//! - [`engine::TranscodeEncodeHooks`] and [`engine::TranscodeDecodeHooks`] for
29//!   replacement, skip, report, finish, and reset policy decisions.
30//! - [`Transcoder`], [`TranscodeProgress`], and [`TranscodeStatus`] for
31//!   caller-managed streaming conversion.
32//! - [`ValueEncoder`] and [`ValueDecoder`] for whole-value convenience APIs.
33//! - [`ByteOrder`], [`ByteOrderSpec`], [`BigEndian`], [`LittleEndian`], and
34//!   [`NativeEndian`] for shared byte-order metadata.
35//! - `qubit_utils::nonzero()` for checked `NonZeroUsize` construction shared by
36//!   codec implementations.
37//!
38//! Concrete codecs live in sibling crates such as `qubit-codec-binary`,
39//! `qubit-codec-text`, and `qubit-codec-misc`.
40//!
41//! # Choosing an Abstraction
42//!
43//! Pick the smallest layer that matches the shape of the problem:
44//!
45//! ```text
46//! What are you writing?
47//!
48//! +-- A codec for one logical value
49//! |   (UTF-8 char, LEB128 integer, fixed-width scalar, ...)
50//! |       -> implement Codec
51//! |
52//! +-- A whole-value codec where a single-value quantum is not useful
53//! |   (Base64 text, percent encoding, escaped strings, ...)
54//! |       -> implement ValueEncoder<Input> / ValueDecoder<Input>
55//! |
56//! +-- A strict streaming wrapper around an existing Codec
57//! |       -> use CodecTranscodeDecoder<C> / CodecTranscodeEncoder<C>
58//! |          / CodecTranscodeConverter<D, E>
59//! |
60//! +-- An owned-output wrapper around an existing Codec
61//! |       -> use CodecValueEncoder<C> / CodecValueDecoder<C>
62//! |
63//! +-- A streaming codec with policy decisions
64//!     (skip, replace, count, report, finish output, ...)
65//!         -> implement engine::TranscodeDecodeHooks<C>
66//!            / engine::TranscodeEncodeHooks<C>
67//!            and use engine::TranscodeDecodeEngine<C, H>
68//!            / engine::TranscodeEncodeEngine<C, H>
69//! ```
70//!
71//! Unit-to-unit conversions, such as UTF-8 bytes to UTF-16 units, compose a
72//! decode side and an encode side. Use [`CodecTranscodeConverter`] for a strict
73//! pipeline and [`engine::TranscodeConvertEngine`] when either side needs
74//! policy hooks.
75//!
76//! # Layer Overview
77//!
78//! ```text
79//! concrete I/O crates
80//!   |
81//! TranscodeDecodeInput / TranscodeEncodeOutput  [feature = "io"]
82//!   |
83//! Transcode*Engine + Transcode*Hooks
84//! CodecTranscodeDecoder / Encoder / Converter
85//!   |
86//! Transcoder + TranscodeProgress + TranscodeStatus
87//! ValueEncoder / ValueDecoder
88//!   |
89//! Codec
90//! ```
91//!
92//! Implementing further up the stack does not require rewriting the lower
93//! layers. The adapter types turn any suitable [`Codec`] into owned-value or
94//! streaming APIs. Drop down to the engine and hook layer when the codec needs
95//! continuous-stream semantics or policy decisions.
96
97#![deny(missing_docs)]
98#![deny(unsafe_op_in_unsafe_fn)]
99
100mod byte_order;
101mod codec;
102mod transcode;
103mod value;
104
105/// Policy-aware transcode engines, hooks, contexts, and policy actions.
106pub mod engine {
107    pub use crate::transcode::DecodeContext;
108    pub use crate::transcode::DecodeIncompleteAction;
109    pub use crate::transcode::DecodeIncompleteActionOf;
110    pub use crate::transcode::DecodeInvalidAction;
111    pub use crate::transcode::DecodeInvalidActionOf;
112    pub use crate::transcode::EncodeContext;
113    pub use crate::transcode::EncodeUnencodableAction;
114    pub use crate::transcode::EncodeUnencodableActionOf;
115    pub use crate::transcode::TranscodeConvertEngine;
116    pub use crate::transcode::TranscodeDecodeEngine;
117    pub use crate::transcode::TranscodeDecodeHooks;
118    pub use crate::transcode::TranscodeEncodeEngine;
119    pub use crate::transcode::TranscodeEncodeHooks;
120}
121
122pub use byte_order::BigEndian;
123pub use byte_order::ByteOrder;
124pub use byte_order::ByteOrderSpec;
125pub use byte_order::LittleEndian;
126pub use byte_order::NativeEndian;
127pub use codec::Codec;
128pub use codec::DecodeFailure;
129#[cfg(feature = "io")]
130pub use transcode::AsyncTranscodeDecodeInput;
131#[cfg(feature = "io")]
132pub use transcode::AsyncTranscodeDecodeStep;
133#[cfg(feature = "io")]
134pub use transcode::AsyncTranscodeEncodeOutput;
135pub use transcode::CapacityError;
136pub use transcode::CodecTranscodeConverter;
137pub use transcode::CodecTranscodeDecoder;
138pub use transcode::CodecTranscodeEncoder;
139pub use transcode::TranscodeContractError;
140pub use transcode::TranscodeConvertError;
141pub use transcode::TranscodeConvertErrorOf;
142pub use transcode::TranscodeConverter;
143pub use transcode::TranscodeDecodeError;
144pub use transcode::TranscodeDecodeErrorOf;
145#[cfg(feature = "io")]
146pub use transcode::TranscodeDecodeInput;
147pub use transcode::TranscodeDecoder;
148pub use transcode::TranscodeDomainError;
149pub use transcode::TranscodeEncodeError;
150pub use transcode::TranscodeEncodeErrorOf;
151#[cfg(feature = "io")]
152pub use transcode::TranscodeEncodeOutput;
153pub use transcode::TranscodeEncoder;
154pub use transcode::TranscodeFailure;
155pub use transcode::TranscodeProgress;
156pub use transcode::TranscodeStatus;
157pub use transcode::Transcoder;
158pub use value::CodecValueDecoder;
159pub use value::CodecValueEncoder;
160pub use value::DecodeLifecycleOutput;
161pub use value::DecodeLifecycleProgress;
162#[cfg(feature = "registry")]
163pub use value::ValueCodecDescriptor;
164#[cfg(feature = "registry")]
165pub use value::ValueCodecExecutionError;
166#[cfg(feature = "registry")]
167pub use value::ValueCodecId;
168#[cfg(feature = "registry")]
169pub use value::ValueCodecIdError;
170#[cfg(feature = "registry")]
171pub use value::ValueCodecRegistration;
172#[cfg(feature = "registry")]
173#[doc(hidden)]
174pub use value::ValueCodecRegistrationFactory;
175#[cfg(feature = "registry")]
176pub use value::ValueCodecRegistrationSource;
177#[cfg(feature = "registry")]
178pub use value::ValueCodecRegistry;
179#[cfg(feature = "registry")]
180pub use value::ValueCodecRegistryError;
181pub use value::ValueDecoder;
182pub use value::ValueEncoder;
183
184#[cfg(feature = "registry")]
185#[doc(hidden)]
186pub mod __private {
187    pub use inventory;
188}