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}