qubit_codec/value/value_codec_registry/value_bytes_codec_registry.rs
1// =============================================================================
2// Copyright (c) 2025 - 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8
9//! Process-wide registry for bytes-wire value codecs.
10
11use std::sync::OnceLock;
12
13use inventory::iter;
14
15use crate::ValueBytesCodecDescriptor;
16use crate::ValueBytesCodecRegistrationFactory;
17use crate::ValueCodecRegistry;
18use crate::ValueCodecRegistryError;
19
20/// An immutable bytes-wire value-codec registry sorted by stable ID.
21///
22/// # Examples
23///
24/// ```
25/// use qubit_codec::ValueBytesCodecRegistry;
26///
27/// let registry = ValueBytesCodecRegistry::empty();
28/// assert!(registry.get("missing.example").is_none());
29/// ```
30pub type ValueBytesCodecRegistry = ValueCodecRegistry<ValueBytesCodecDescriptor>;
31
32impl ValueBytesCodecRegistry {
33 /// Initializes and returns the process-wide linked bytes registry.
34 ///
35 /// Initialization is synchronized and cached, including construction
36 /// failures.
37 ///
38 /// # Returns
39 ///
40 /// A shared static registry containing all linked bytes registrations.
41 ///
42 /// # Errors
43 ///
44 /// Returns the cached construction error when linked registrations
45 /// conflict. The error identifies the lexically first duplicate ID and
46 /// all declarations for that ID in source-field order.
47 pub fn try_global() -> Result<&'static Self, ValueCodecRegistryError> {
48 // Caches both successful construction and duplicate-ID failures.
49 static REGISTRY: OnceLock<Result<ValueBytesCodecRegistry, ValueCodecRegistryError>> = OnceLock::new();
50 match REGISTRY.get_or_init(|| {
51 let registrations = iter::<ValueBytesCodecRegistrationFactory>
52 .into_iter()
53 .map(|factory| (factory.0)())
54 .collect();
55 ValueCodecRegistry::build(registrations)
56 }) {
57 Ok(registry) => Ok(registry),
58 Err(error) => Err(error.clone()),
59 }
60 }
61
62 /// Returns the process-wide bytes registry or panics with a stable
63 /// diagnostic.
64 ///
65 /// # Returns
66 ///
67 /// A shared static registry, initialized at most once by `try_global`.
68 ///
69 /// # Panics
70 ///
71 /// Panics when linked registrations conflict.
72 #[must_use]
73 pub fn global() -> &'static Self {
74 Self::try_global().unwrap_or_else(|error| panic!("invalid global value bytes codec registry: {error}"))
75 }
76}