rskit_inference/
registry.rs1use std::{collections::BTreeMap, sync::Arc};
2
3use thiserror::Error;
4
5use crate::{Inference, InferenceError};
6
7pub type Factory = Arc<dyn Fn() -> Result<Arc<dyn Inference>, InferenceError> + Send + Sync>;
9
10#[derive(Default)]
12pub struct Registry {
13 factories: BTreeMap<String, Factory>,
14}
15
16impl Registry {
17 #[must_use]
19 pub fn new() -> Self {
20 Self::default()
21 }
22
23 pub fn register(&mut self, kind: &str, factory: Factory) -> Result<(), RegistryError> {
25 let kind = Self::normalize_kind(kind).map_err(|_| RegistryError::EmptyKind)?;
26 if self.factories.contains_key(&kind) {
27 return Err(RegistryError::DuplicateKind(kind));
28 }
29 self.factories.insert(kind, factory);
30 Ok(())
31 }
32
33 pub fn build(&self, kind: &str) -> Result<Arc<dyn Inference>, InferenceError> {
35 let kind = Self::normalize_kind(kind)?;
36 let factory = self
37 .factories
38 .get(&kind)
39 .ok_or_else(|| InferenceError::Decode(format!("unknown inference adapter {kind:?}")))?;
40 factory()
41 }
42
43 fn normalize_kind(kind: &str) -> Result<String, InferenceError> {
44 let kind = kind.trim();
45 if kind.is_empty() {
46 return Err(InferenceError::InvalidInput(
47 "inference adapter kind is required".to_owned(),
48 ));
49 }
50 Ok(kind.to_owned())
51 }
52
53 #[must_use]
55 pub fn kinds(&self) -> Vec<String> {
56 self.factories.keys().cloned().collect()
57 }
58}
59
60#[derive(Debug, Error, PartialEq, Eq)]
62#[non_exhaustive]
63pub enum RegistryError {
64 #[error("inference adapter kind is required")]
66 EmptyKind,
67 #[error("inference adapter {0:?} already registered")]
69 DuplicateKind(String),
70}
71
72#[must_use]
77pub fn default_registry() -> Registry {
78 Registry::new()
79}
80
81#[cfg(test)]
82mod tests {
83 use rskit_errors::ErrorCode;
84
85 use super::{Registry, RegistryError};
86 use crate::InferenceError;
87
88 #[test]
89 fn register_rejects_empty_kind() {
90 let mut registry = Registry::new();
91 let factory = std::sync::Arc::new(|| unreachable!("factory should not run"));
92 let err = registry.register(" \t ", factory).unwrap_err();
93 assert_eq!(err, RegistryError::EmptyKind);
94 }
95
96 #[test]
97 fn build_rejects_empty_kind_as_invalid_input() {
98 let Err(err) = Registry::new().build(" \t ") else {
99 panic!("empty inference adapter kind should be rejected");
100 };
101 assert!(matches!(err, InferenceError::InvalidInput(_)));
102
103 let app_error = rskit_errors::AppError::from(err);
104 assert_eq!(app_error.code(), ErrorCode::InvalidInput);
105 }
106}