qubit_codec/value/value_codec_registry/value_string_codec_registry.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//! Process-wide registry for string-wire value codecs.
10
11use std::sync::OnceLock;
12
13use inventory::iter;
14
15use crate::ValueCodecRegistry;
16use crate::ValueCodecRegistryError;
17use crate::ValueStringCodecDescriptor;
18use crate::ValueStringCodecRegistrationFactory;
19
20/// An immutable string-wire value-codec registry sorted by stable ID.
21///
22/// # Examples
23///
24/// ```
25/// use qubit_codec::ValueStringCodecRegistry;
26///
27/// let registry = ValueStringCodecRegistry::empty();
28/// assert!(registry.get("missing.example").is_none());
29/// ```
30pub type ValueStringCodecRegistry = ValueCodecRegistry<ValueStringCodecDescriptor>;
31
32impl ValueStringCodecRegistry {
33 /// Initializes and returns the process-wide linked string registry.
34 ///
35 /// Initialization is synchronized and cached, including construction
36 /// failures.
37 ///
38 /// # Returns
39 ///
40 /// A shared static registry containing all linked string 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<ValueStringCodecRegistry, ValueCodecRegistryError>> = OnceLock::new();
50 match REGISTRY.get_or_init(|| {
51 let registrations = iter::<ValueStringCodecRegistrationFactory>
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 string 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 #[inline]
74 pub fn global() -> &'static Self {
75 Self::try_global().unwrap_or_else(|error| panic!("invalid global value string codec registry: {error}"))
76 }
77}