Skip to main content

knowledge_base_extension_framework/
bindings.rs

1use crate::contracts::{BindingKind, BindingReference, ExtensionMetadata};
2use crate::error::FrameworkError;
3use knowledge_base_models::{EntityTypeId, PropertyId};
4use std::collections::BTreeMap;
5
6/// A resolved ontology identifier assigned to a semantic binding.
7#[derive(Clone, Debug, Eq, PartialEq)]
8pub enum BindingValue {
9    EntityType(EntityTypeId),
10    Property(PropertyId),
11}
12
13impl BindingValue {
14    pub const fn kind(&self) -> BindingKind {
15        match self {
16            Self::EntityType(_) => BindingKind::EntityType,
17            Self::Property(_) => BindingKind::Property,
18        }
19    }
20}
21
22/// Typed bindings visible to an activated extension.
23#[derive(Clone, Debug, Default)]
24pub struct ResolvedBindings {
25    pub(crate) values: BTreeMap<BindingReference, BindingValue>,
26}
27
28impl ResolvedBindings {
29    /// Looks up a binding owned by this extension or one of its direct dependencies.
30    ///
31    /// Limiting access to direct dependencies makes an extension's required contracts
32    /// explicit instead of allowing it to rely on unrelated active extensions.
33    pub fn get(&self, extension: &ExtensionMetadata, reference: &BindingReference) -> Result<&BindingValue, FrameworkError> {
34        if reference.extension_id() != &extension.id && !extension.dependencies.iter().any(|dependency| dependency.id == *reference.extension_id()) {
35            return Err(FrameworkError::InaccessibleBinding {
36                extension: extension.id.clone(),
37                binding: reference.clone(),
38            });
39        }
40        self.values.get(reference).ok_or_else(|| FrameworkError::MissingBinding(reference.clone()))
41    }
42
43    /// Retrieves an entity-type binding and verifies its declared kind.
44    pub fn entity_type(&self, extension: &ExtensionMetadata, reference: &BindingReference) -> Result<&EntityTypeId, FrameworkError> {
45        match self.get(extension, reference)? {
46            BindingValue::EntityType(id) => Ok(id),
47            value => Err(FrameworkError::BindingKindMismatch {
48                binding: reference.clone(),
49                expected: BindingKind::EntityType,
50                actual: value.kind(),
51            }),
52        }
53    }
54
55    /// Retrieves a property binding and verifies its declared kind.
56    pub fn property(&self, extension: &ExtensionMetadata, reference: &BindingReference) -> Result<&PropertyId, FrameworkError> {
57        match self.get(extension, reference)? {
58            BindingValue::Property(id) => Ok(id),
59            value => Err(FrameworkError::BindingKindMismatch {
60                binding: reference.clone(),
61                expected: BindingKind::Property,
62                actual: value.kind(),
63            }),
64        }
65    }
66}