Skip to main content

PolicyRegistry

Struct PolicyRegistry 

Source
pub struct PolicyRegistry<R = f32, C = bool> { /* private fields */ }
Expand description

What resolves a manifest’s control kind to the code that decides it.

The four built-in kinds resolve to a Controller. A kind pamoja never shipped resolves to the factory registered under its name, which reads the parameters the manifest carried beside the kind and builds the policy, so a fleet can share a manifest for a policy of its own the same way it shares one for a setpoint. A registry is generic over the reading and command its policies work in; resolve exists for the f32 reading and bool command the built-in kinds share, and custom for any other pair.

§Examples

use pamoja_core::Error;
use pamoja_profile::{Alert, BoxedPolicy, Policy, PolicyRegistry, Profile, Reaction};

struct FrostGuard {
    warn_below: f32,
}

impl Policy for FrostGuard {
    type Reading = f32;
    type Command = bool;

    fn evaluate(&mut self, reading: &f32) -> Reaction {
        let cold = *reading < self.warn_below;
        Reaction {
            actuator: Some(cold),
            alert: cold.then_some(Alert::Custom { code: "FrostRisk", value: *reading }),
        }
    }
}

// The manifest names a kind the library has never heard of, with its parameter
// beside it, exactly as a built-in kind carries its own.
let manifest = r#"{
    "name": "orchard-frost",
    "topic": "orchard/air/temperature",
    "control": { "kind": "frost_guard", "warn_below": 2.0 },
    "power": { "active_secs": 60, "saver_secs": 300, "critical_secs": 900 }
}"#;
let profile = Profile::from_json(manifest)?;

let registry = PolicyRegistry::new().register("frost_guard", |params| {
    let warn_below = params
        .number("warn_below")
        .ok_or(Error::Unsupported("frost_guard needs a `warn_below` parameter"))?;
    Ok(Box::new(FrostGuard { warn_below: warn_below as f32 }) as BoxedPolicy)
});
let mut policy = registry.resolve(&profile.control)?;
assert_eq!(policy.evaluate(&1.0).alert.map(Alert::kind), Some("FrostRisk"));
assert_eq!(policy.evaluate(&5.0).actuator, Some(false));

// A built-in kind resolves through the same registry.
let mut fridge = registry.resolve(&Profile::vaccine_fridge_monitor().control)?;
assert_eq!(fridge.evaluate(&9.0).actuator, Some(true));

Implementations§

Source§

impl<R, C> PolicyRegistry<R, C>

Source

pub fn new() -> Self

Starts a registry with no custom kinds.

§Returns

A registry that resolves only what is registered on it.

Source

pub fn register<F>(self, kind: impl Into<String>, factory: F) -> Self
where F: Fn(&Params) -> Result<BoxedPolicy<R, C>> + Send + Sync + 'static,

Registers the factory for a custom kind, replacing one of the same name.

§Arguments
  • kind - the kind as a manifest names it, such as "frost_guard".
  • factory - builds the policy from the parameters beside the kind, or says which parameter it needed.
§Returns

The registry, for chaining.

Source

pub fn kinds(&self) -> impl Iterator<Item = &str>

Lists the custom kinds registered, in name order.

§Returns

Each kind’s name.

Source

pub fn custom(&self, kind: &str, params: &Params) -> Result<BoxedPolicy<R, C>>

Builds the policy for a custom kind from its parameters.

§Arguments
  • kind - the kind as a manifest names it.
  • params - the parameters the manifest carried beside it.
§Returns

The policy, ready to evaluate readings.

§Errors

Returns [Error::Codec] naming the kind when no factory is registered for it, or whatever the factory returns when the parameters are not what it needs.

Source§

impl PolicyRegistry<f32, bool>

Source

pub fn resolve(&self, spec: &ControlSpec) -> Result<BoxedPolicy<f32, bool>>

Resolves a manifest’s control kind: a built-in kind to its Controller, a custom kind to the policy its factory builds.

§Arguments
  • spec - the control policy a profile carries.
§Returns

The policy, ready to evaluate readings.

§Errors

Returns [Error::Codec] naming the kind when it is custom and no factory is registered for it, or whatever the factory returns.

Trait Implementations§

Source§

impl<R, C> Debug for PolicyRegistry<R, C>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<R, C> Default for PolicyRegistry<R, C>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<R = f32, C = bool> !RefUnwindSafe for PolicyRegistry<R, C>

§

impl<R = f32, C = bool> !UnwindSafe for PolicyRegistry<R, C>

§

impl<R, C> Freeze for PolicyRegistry<R, C>

§

impl<R, C> Send for PolicyRegistry<R, C>

§

impl<R, C> Sync for PolicyRegistry<R, C>

§

impl<R, C> Unpin for PolicyRegistry<R, C>

§

impl<R, C> UnsafeUnpin for PolicyRegistry<R, C>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.