qubit_codec/value/
value_codec_registry.rs1use std::collections::BTreeMap;
10use std::sync::OnceLock;
11
12use crate::ValueCodecId;
13use crate::ValueCodecRegistration;
14use crate::ValueCodecRegistrationFactory;
15use crate::ValueCodecRegistryError;
16
17#[derive(Debug)]
28pub struct ValueCodecRegistry {
29 registrations: Box<[ValueCodecRegistration]>,
30 indices: BTreeMap<ValueCodecId, usize>,
31}
32
33impl ValueCodecRegistry {
34 pub fn from_registrations(
40 registrations: impl IntoIterator<Item = &'static ValueCodecRegistration>,
41 ) -> Result<Self, ValueCodecRegistryError> {
42 Self::build(registrations.into_iter().copied().collect())
43 }
44
45 #[must_use]
47 pub fn empty() -> Self {
48 Self {
49 registrations: Box::new([]),
50 indices: BTreeMap::new(),
51 }
52 }
53
54 pub fn try_global() -> Result<&'static Self, ValueCodecRegistryError> {
61 static REGISTRY: OnceLock<Result<ValueCodecRegistry, ValueCodecRegistryError>> = OnceLock::new();
62 match REGISTRY.get_or_init(|| {
63 let registrations = inventory::iter::<ValueCodecRegistrationFactory>
64 .into_iter()
65 .map(|factory| (factory.0)())
66 .collect();
67 Self::build(registrations)
68 }) {
69 Ok(registry) => Ok(registry),
70 Err(error) => Err(error.clone()),
71 }
72 }
73
74 #[must_use]
80 pub fn global() -> &'static Self {
81 Self::try_global().unwrap_or_else(|error| panic!("invalid global value codec registry: {error}"))
82 }
83
84 #[must_use]
88 pub fn get(&self, id: &str) -> Option<&ValueCodecRegistration> {
89 let index = *self.indices.get(id)?;
90 self.registrations.get(index)
91 }
92
93 #[must_use]
95 pub fn registrations(&self) -> &[ValueCodecRegistration] {
96 &self.registrations
97 }
98
99 fn build(mut registrations: Vec<ValueCodecRegistration>) -> Result<Self, ValueCodecRegistryError> {
101 registrations.sort_by_key(ValueCodecRegistration::id);
102 for pair in registrations.windows(2) {
103 if pair[0].id() == pair[1].id() {
104 let mut sources = pair.iter().map(ValueCodecRegistration::source).collect::<Vec<_>>();
105 sources.sort_unstable();
106 return Err(ValueCodecRegistryError::DuplicateId {
107 id: pair[0].id().as_str(),
108 sources,
109 });
110 }
111 }
112 let indices = registrations
113 .iter()
114 .enumerate()
115 .map(|(index, registration)| (registration.id(), index))
116 .collect();
117 Ok(Self {
118 registrations: registrations.into_boxed_slice(),
119 indices,
120 })
121 }
122}