zennode 0.1.1

Self-documenting node definitions for image processing pipelines
Documentation
//! Core traits for node definitions and instances.

use alloc::boxed::Box;
use core::any::Any;

use crate::error::NodeError;
use crate::kv::KvPairs;
use crate::param::{ParamMap, ParamValue};
use crate::schema::NodeSchema;

/// A node type definition — the factory and schema holder.
///
/// Each operation crate creates one static singleton per node type
/// (typically a unit struct generated by `#[derive(Node)]`).
///
/// `NodeDef` is `Send + Sync + 'static` — it carries no mutable state.
pub trait NodeDef: Send + Sync + 'static {
    /// The static schema for this node type (zero-allocation access).
    fn schema(&self) -> &'static NodeSchema;

    /// Create a node instance from a parameter map.
    ///
    /// Missing parameters are filled with their schema defaults.
    fn create(&self, params: &ParamMap) -> Result<Box<dyn NodeInstance>, NodeError>;

    /// Create a node instance from RIAPI key-value pairs.
    ///
    /// Returns `Ok(None)` if no relevant keys were found in `kv`.
    /// Consumed keys are marked in the `KvPairs` tracker.
    #[allow(clippy::wrong_self_convention)]
    fn from_kv(&self, kv: &mut KvPairs) -> Result<Option<Box<dyn NodeInstance>>, NodeError>;

    /// Create a node instance with all default parameters.
    fn create_default(&self) -> Result<Box<dyn NodeInstance>, NodeError> {
        self.create(&ParamMap::new())
    }
}

/// A concrete node instance with parameter values.
///
/// Created by [`NodeDef::create`] or [`NodeDef::from_kv`].
/// Supports introspection, mutation, serialization, and downcasting.
pub trait NodeInstance: Send + Sync + Any {
    /// The static schema for this node's type.
    fn schema(&self) -> &'static NodeSchema;

    /// Export all current parameter values.
    fn to_params(&self) -> ParamMap;

    /// Get a single parameter value by name.
    fn get_param(&self, name: &str) -> Option<ParamValue>;

    /// Set a single parameter value by name.
    ///
    /// Returns `true` if the parameter exists and the value type matched.
    fn set_param(&mut self, name: &str, value: ParamValue) -> bool;

    /// Downcast to concrete type.
    fn as_any(&self) -> &dyn Any;

    /// Downcast to concrete type (mutable).
    fn as_any_mut(&mut self) -> &mut dyn Any;

    /// Clone into a boxed trait object.
    fn clone_boxed(&self) -> Box<dyn NodeInstance>;

    /// Whether all parameters are at their identity values (no-op node).
    fn is_identity(&self) -> bool {
        false
    }
}