Skip to main content

geop_core_program/
operation_registry.rs

1use std::{collections::BTreeMap, rc::Rc};
2
3use geop_core_math::geop_error::{GeopError, GeopResult};
4
5use crate::operation::{ErasedOperation, Operation};
6
7/// The operations a program may use, by name.
8#[derive(Clone, Default)]
9pub struct OperationRegistry(BTreeMap<&'static str, Rc<dyn ErasedOperation>>);
10
11impl OperationRegistry {
12    /// Adds `operation`. Fails if an operation of its name is already there: a
13    /// program could not tell the two apart.
14    pub fn with<O: Operation>(self, operation: O) -> GeopResult<Self> {
15        self.with_erased(Rc::new(operation))
16    }
17
18    /// Adds `operation`, its type erased (see [`OperationRegistry::with`]).
19    pub fn with_erased(mut self, operation: Rc<dyn ErasedOperation>) -> GeopResult<Self> {
20        let kind = operation.kind();
21        if self.0.contains_key(kind) {
22            return Err(GeopError::new(format!(
23                "operation `{kind}` is registered twice"
24            )));
25        }
26        self.0.insert(kind, operation);
27        Ok(self)
28    }
29
30    pub fn get(&self, name: &str) -> GeopResult<&dyn ErasedOperation> {
31        self.0
32            .get(name)
33            .map(Rc::as_ref)
34            .ok_or_else(|| GeopError::new(format!("unknown operation `{name}`")))
35    }
36}