Skip to main content

qubit_codec/value/
value_codec_registration.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
9//! Distributed value-codec registrations.
10
11use crate::ValueCodecId;
12use crate::ValueCodecRegistrationSource;
13
14/// One statically linked value-codec implementation.
15///
16/// A registration bundles the stable identifier used for lookup and duplicate
17/// detection, a borrowed executable descriptor, and the link-time location the
18/// registration was declared at. It is produced by
19/// [`register_value_string_codec!`](crate::register_value_string_codec) or
20/// [`register_value_bytes_codec!`](crate::register_value_bytes_codec)
21/// rather than built by hand.
22///
23/// The registration macros validate codecs through the matching descriptor.
24/// Encoder and decoder error types must implement `Error + Send + Sync +
25/// 'static`; codec and value types do not need those bounds.
26#[derive(Clone, Copy, Debug)]
27pub struct ValueCodecRegistration<D: 'static> {
28    /// Stable identifier shared with registry lookups and duplicate detection.
29    id: ValueCodecId,
30    /// Executable descriptor borrowed from static storage.
31    descriptor: &'static D,
32    /// Link-time location the registration was declared at.
33    source: ValueCodecRegistrationSource,
34}
35
36impl<D: 'static> ValueCodecRegistration<D> {
37    /// Creates a registration from validated static facts.
38    #[doc(hidden)]
39    #[inline]
40    #[must_use]
41    pub const fn new(id: ValueCodecId, descriptor: &'static D, source: ValueCodecRegistrationSource) -> Self {
42        Self { id, descriptor, source }
43    }
44
45    /// Returns the stable value-codec ID.
46    #[inline]
47    #[must_use]
48    pub const fn id(&self) -> ValueCodecId {
49        self.id
50    }
51
52    /// Returns the executable descriptor.
53    #[inline]
54    #[must_use]
55    pub const fn descriptor(&self) -> &'static D {
56        self.descriptor
57    }
58
59    /// Returns the linked source location.
60    #[inline]
61    #[must_use]
62    pub const fn source(&self) -> ValueCodecRegistrationSource {
63        self.source
64    }
65}
66
67/// Registers a default-constructible bidirectional string codec.
68///
69/// The macro must be invoked at module scope; it defines the descriptor, a
70/// registration function, and an inventory submission in an anonymous const.
71/// The `id` must be a constant expression. Use a literal, constant, or
72/// `const fn` result; a runtime function call cannot define a static ID.
73/// The encoder and decoder error types must implement `Error + Send + Sync +
74/// 'static`, as required by [`crate::ValueStringCodecDescriptor::of`].
75///
76/// # Examples
77///
78/// ```compile_fail
79/// use qubit_codec::JsonStringValueCodec;
80/// use qubit_codec::register_value_string_codec;
81///
82/// fn invalid_id() -> &'static str { "example.u32" }
83/// register_value_string_codec!(id = invalid_id(), codec = JsonStringValueCodec<u32>, value = u32);
84/// ```
85///
86/// ```compile_fail
87/// use qubit_codec::JsonStringValueCodec;
88/// use qubit_codec::register_value_string_codec;
89/// register_value_string_codec!(id = "invalid-id", codec = JsonStringValueCodec<u32>, value = u32);
90/// ```
91///
92/// ```
93/// # #[cfg(feature = "json")]
94/// # {
95/// use qubit_codec::JsonStringValueCodec;
96/// use qubit_codec::register_value_string_codec;
97///
98/// register_value_string_codec!(
99///     id = "example.u32",
100///     codec = JsonStringValueCodec<u32>,
101///     value = u32,
102/// );
103/// # }
104/// ```
105#[macro_export]
106macro_rules! register_value_string_codec {
107    (id = $id:expr, codec = $codec:ty, value = $value:ty $(,)?) => {
108        const _: () = {
109            const ID: $crate::ValueCodecId = $crate::ValueCodecId::new($id);
110            static DESCRIPTOR: $crate::ValueStringCodecDescriptor =
111                $crate::ValueStringCodecDescriptor::of::<$codec, $value>();
112
113            fn registration() -> $crate::ValueStringCodecRegistration {
114                $crate::ValueCodecRegistration::new(
115                    ID,
116                    &DESCRIPTOR,
117                    $crate::ValueCodecRegistrationSource::new(env!("CARGO_PKG_NAME"), module_path!(), file!(), line!()),
118                )
119            }
120
121            $crate::__private::inventory::submit! {
122                $crate::ValueStringCodecRegistrationFactory(registration)
123            }
124        };
125    };
126}
127
128/// Registers a default-constructible bidirectional bytes codec.
129///
130/// The macro must be invoked at module scope; it defines the descriptor, a
131/// registration function, and an inventory submission in an anonymous const.
132/// The `id` must be a constant expression. Use a literal, constant, or
133/// `const fn` result; a runtime function call cannot define a static ID.
134/// The encoder and decoder error types must implement `Error + Send + Sync +
135/// 'static`, as required by [`crate::ValueBytesCodecDescriptor::of`].
136///
137/// # Examples
138///
139/// ```compile_fail
140/// use qubit_codec::JsonBytesValueCodec;
141/// use qubit_codec::register_value_bytes_codec;
142/// register_value_bytes_codec!(id = "invalid-id", codec = JsonBytesValueCodec<u32>, value = u32);
143/// ```
144///
145/// ```
146/// # #[cfg(feature = "json")]
147/// # {
148/// use qubit_codec::JsonBytesValueCodec;
149/// use qubit_codec::register_value_bytes_codec;
150///
151/// register_value_bytes_codec!(
152///     id = "example.u32",
153///     codec = JsonBytesValueCodec<u32>,
154///     value = u32,
155/// );
156/// # }
157/// ```
158#[macro_export]
159macro_rules! register_value_bytes_codec {
160    (id = $id:expr, codec = $codec:ty, value = $value:ty $(,)?) => {
161        const _: () = {
162            const ID: $crate::ValueCodecId = $crate::ValueCodecId::new($id);
163            static DESCRIPTOR: $crate::ValueBytesCodecDescriptor =
164                $crate::ValueBytesCodecDescriptor::of::<$codec, $value>();
165
166            fn registration() -> $crate::ValueBytesCodecRegistration {
167                $crate::ValueCodecRegistration::new(
168                    ID,
169                    &DESCRIPTOR,
170                    $crate::ValueCodecRegistrationSource::new(env!("CARGO_PKG_NAME"), module_path!(), file!(), line!()),
171                )
172            }
173
174            $crate::__private::inventory::submit! {
175                $crate::ValueBytesCodecRegistrationFactory(registration)
176            }
177        };
178    };
179}