Struct Workflow

Source
pub struct Workflow { /* private fields */ }
Expand description

Represents a workflow containing rules with version control and change tracking.

A workflow is the central container for rules in the AIMX system. It manages:

  • Rule storage and indexing for efficient access
  • Version control with epoch and partial tracking
  • Change detection for optimal persistence
  • File system integration for loading and saving

§Internal Structure

The workflow maintains rules using two complementary data structures:

  • rows: A vector preserving rule order and empty slots
  • lookup: A hash map enabling O(1) identifier-based access

This dual-structure approach provides both ordered serialization and fast lookup.

§Version Control

Workflows support sophisticated version control:

  • Epoch: Major version numbers for structural changes
  • Partial: Minor version numbers for incremental updates
  • Journaling: External files track version offsets for efficient loading

§Change Tracking

The workflow automatically tracks changes to optimize persistence:

  • None: No changes, skip saving
  • Partial: Incremental changes, append partial update
  • Version: Structural changes, create new version

§Examples

use aimx::{Workflow, WorkflowLike, Rule, Typedef, Expression, Literal, Value};

// Create a new workflow
let mut workflow = Workflow::new();
 
// Add a rule
let rule = Rule::new("temperature".to_string(), Typedef::Number, 
    Expression::Empty, Value::Literal(Literal::Number(72.0)));
workflow.append_or_update(Some(rule));
 
// Access rules by identifier
let temp_rule = workflow.get_rule("temperature").unwrap();
let temp = temp_rule.value().to_literal();
assert_eq!(temp, &Literal::Number(72.0));

Implementations§

Source§

impl Workflow

Source

pub fn new() -> Self

Creates a new empty workflow.

The workflow starts with:

  • Empty rule storage
  • Version 0.0
  • Empty path and reference
  • No changes pending
  • Change tracking disabled
§Returns

A new Workflow instance ready for use.

§Examples
use aimx::{Workflow, WorkflowLike};

let workflow = Workflow::new();
assert_eq!(workflow.version(), 0);
assert_eq!(workflow.rule_count(), 0);
Source

pub fn parse_new(input: &str) -> Self

Creates a new workflow by parsing AIM content.

This constructor parses the provided AIM content and creates a workflow with the parsed rules. Change tracking is automatically enabled.

§Parameters
  • input - The AIM content to parse
§Returns

A new Workflow instance containing the parsed rules.

§Examples
use aimx::{Workflow, WorkflowLike};

let workflow = Workflow::parse_new("[1]\ntemperature: Number = 72");
assert!(workflow.rule_count() > 0);
Source

pub fn load_new(reference: &Reference) -> Self

Creates a new workflow by loading from a reference.

This constructor loads a workflow from the file system based on the provided reference. If the file doesn’t exist, an empty workflow is created with the reference set.

§Parameters
  • reference - The workflow reference to load
§Returns

A new Workflow instance loaded from the file system.

Source

pub fn new_workspace(path: &Path) -> Self

Creates a new workflow by loading from a workspace path.

This constructor loads a workflow from the specified file system path.

§Parameters
  • path - The path to the AIM file to load
§Returns

A new Workflow instance loaded from the file system.

Source

pub fn is_touched(&self) -> bool

Checks if the workflow has unsaved changes.

§Returns

true if the workflow has changes that need to be saved, false otherwise.

Source

pub fn set_partial_change(&mut self)

Flags changes that only require a partial save.

This method escalates the change status from None to Partial. If changes are already at Partial or Version, they remain unchanged.

Source

pub fn set_version_change(&mut self)

Flags changes that require a version change on save.

This method sets the change status to Version, indicating that structural changes have been made that require a new version.

Source

pub fn clear_changes(&mut self)

Clears the changes flag.

This method is typically called after a successful save operation to reset the change tracking state.

Source

pub fn track_changes(&mut self)

Enables change tracking for partial saves.

When enabled, the workflow will track changes made through specific operations (append_or_update, update_rule, set_rule) and automatically flag them for partial saving.

This should be enabled before or after using workflow.parse() directly.

Source

pub fn first_version(&self) -> u32

Gets the first version number from the journal.

§Returns

The epoch of the first version, or 0 if no versions exist.

Source

pub fn latest_version(&self) -> u32

Gets the latest version number from the journal.

§Returns

The epoch of the latest version, or 0 if no versions exist.

Source

pub fn load_version( &mut self, path: &Path, version: u32, partial: Option<u32>, ) -> Result<()>

Loads a specific version of an AIM file.

This method loads a particular version (and optionally a specific partial) from the AIM file. After loading, the workflow switches back to the latest version but flags that a version change is needed since the loaded version differs from the current one.

§Parameters
  • path - The path to the AIM file
  • version - The epoch version to load
  • partial - Optional partial version within the epoch
§Returns

Ok(()) if successful, or an error if the version cannot be loaded.

Source

pub fn load(&mut self, path: &Path) -> Result<()>

Loads the latest version of an AIM file.

This method loads the most recent version from the AIM file and clears any pending changes. Change tracking is enabled after loading.

§Parameters
  • path - The path to the AIM file
§Returns

Ok(()) if successful, or an error if the file cannot be loaded.

Source

pub fn save(&mut self) -> Result<()>

Saves the AIM structure to its associated file.

This function saves changes to the AIM file based on the type of changes made:

  • Changes::Version: Creates a new version with incremented epoch
  • Changes::Partial: Creates a partial update with incremented partial counter
  • Changes::None: No changes to save, returns Ok(())

The function also updates the journal file with position information for fast lookup.

§Returns

Ok(()) if successful, or an error if the save operation fails.

§Examples
use aimx::{Workflow, Rule, Typedef, Expression, Literal, Value};

let mut workflow = Workflow::new();
let rule = Rule::new("test".to_string(), Typedef::Number, 
    Expression::Empty, Value::Literal(Literal::Number(42.0)));
workflow.track_changes();
workflow.append_or_update(Some(rule));
 
// Workflow now has changes that could be saved
assert!(workflow.is_touched());
Source

pub fn get_rule_mut(&mut self, identifier: &str) -> Option<&mut Rule>

Gets a mutable reference to a rule by identifier.

§Parameters
  • identifier - The rule identifier
§Returns

Some(&mut Rule) if the rule exists, None otherwise.

Source

pub fn append_or_update(&mut self, row: Option<Rule>)

Appends a rule to the workflow or updates an existing rule.

If a rule with the same identifier already exists, it is updated. Otherwise, the rule is appended to the end of the workflow.

§Parameters
  • row - The rule to append or update
Source

pub fn update_rule(&mut self, rule: Rule) -> Result<()>

Updates an existing rule.

§Parameters
  • rule - The updated rule
§Returns

Ok(()) if successful, or an error if the rule doesn’t exist.

Source

pub fn delete_rule(&mut self, identifier: &str) -> Option<Rule>

Deletes a rule by identifier.

§Parameters
  • identifier - The rule identifier to delete
§Returns

Some(Rule) if the rule was deleted, None if it didn’t exist.

Source

pub fn get_index(&self, identifier: &str) -> Option<usize>

Gets the row index of a rule by identifier.

§Parameters
  • identifier - The rule identifier
§Returns

Some(usize) if the rule exists, None otherwise.

Source

pub fn set_row(&mut self, index: usize, row: Option<Rule>) -> Result<()>

Sets a rule at a specific row index.

If a rule already exists at the specified index with a different identifier, this method will return an error. If the index is beyond the current size of the workflow, the rows vector will be expanded to accommodate it.

§Parameters
  • index - The zero-based row index where to place the rule
  • row - The rule to set, or None to create an empty row
§Returns

Ok(()) if successful, or an error if there’s a conflict with an existing rule

Source

pub fn insert_row(&mut self, index: usize, row: Option<Rule>) -> Result<()>

Inserts a rule at a specific row index.

This method inserts a rule at the specified index, shifting existing rules to higher indices. If the index is beyond the current size of the workflow, empty rows will be created as needed. If a rule with the same identifier already exists in the workflow, this method returns an error.

§Parameters
  • index - The zero-based row index where to insert the rule
  • row - The rule to insert, or None to create an empty row
§Returns

Ok(()) if successful, or an error if a rule with the same identifier already exists

Source

pub fn reposition_row(&mut self, from: usize, to: usize) -> Result<()>

Repositions a rule from one row index to another.

This method moves a rule from the from index to the to index, shifting other rules as needed. If either index is beyond the current size of the workflow, the rows vector will be expanded to accommodate them.

§Parameters
  • from - The current zero-based row index of the rule to move
  • to - The target zero-based row index where to place the rule
§Returns

Ok(()) if successful, or an error if the operation fails

Source

pub fn clear_row(&mut self, index: usize) -> Option<Rule>

Clears a row at a specific index, removing the rule if present.

This method removes the rule at the specified index but keeps the row structure intact. The row will become empty but still exist in the workflow. If the index is out of bounds, this method returns None.

§Parameters
  • index - The zero-based row index to clear
§Returns

Some(Rule) if a rule was present and removed, None if the row was already empty or index was out of bounds

Source

pub fn remove_row(&mut self, index: usize) -> Option<Rule>

Removes a row at a specific index, removing the rule and shrinking the workflow.

This method removes the rule at the specified index and removes the row entirely from the workflow, shifting subsequent rows to lower indices. If the index is out of bounds, this method returns None.

§Parameters
  • index - The zero-based row index to remove
§Returns

Some(Rule) if a rule was present and removed, None if the index was out of bounds

Source

pub fn iter_rows_mut<'a>( &'a mut self, ) -> Box<dyn Iterator<Item = &'a mut Option<Rule>> + 'a>

Create a mutable iterator over the rows.

This iterator yields mutable references to Option<Rule>, allowing modification of both rules and empty rows.

Source

pub fn iter_rules_mut<'a>( &'a mut self, ) -> Box<dyn Iterator<Item = &'a mut Rule> + 'a>

Create a mutable iterator over the rules.

This iterator yields mutable references to Rule, skipping empty rows. It’s useful when you need to modify only the actual rules in the workflow.

Source

pub fn iter_with_rows(&self) -> impl Iterator<Item = (usize, &Option<Rule>)>

Create an iterator over the rules with their indices.

This iterator yields tuples of (index, &Option<Rule>), providing both the position and content of each row including empty ones.

Source

pub fn iter_mut_with_rows( &mut self, ) -> impl Iterator<Item = (usize, &mut Option<Rule>)>

Create a mutable iterator over the rules with their indices.

This iterator yields tuples of (index, &mut Option<Rule>), providing both the position and mutable content of each row including empty ones.

Source

pub fn reindex(&mut self)

Rebuilds the lookup mapping index.

This helper function rebuilds the internal hash map that maps rule identifiers to their row indices. It’s called automatically after operations that change the position of rules within the workflow.

Source

pub fn evaluate(&self, context: &mut dyn ContextLike)

Evaluates all rules in the workflow.

This method evaluates each rule’s expression in the context and stores the result back in the context. It’s used to compute the current values of all rules in the workflow.

§Parameters
  • context - The evaluation context where results will be stored
Source

pub fn parse(&mut self, input: &str, partial: Option<u32>) -> Result<()>

Parses AIM content and populates the workflow.

This method parses AIM format content and creates rules based on the parsed data. It can optionally parse only up to a specific partial version. The method clears the current workflow contents before parsing.

§Parameters
  • input - The AIM content to parse
  • partial - Optional partial version to parse up to
§Returns

Ok(()) if parsing was successful, or an error if parsing failed

Trait Implementations§

Source§

impl Clone for Workflow

Source§

fn clone(&self) -> Workflow

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Workflow

Source§

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

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

impl PartialEq<Reference> for Workflow

Source§

fn eq(&self, other: &Reference) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialEq<Workflow> for Reference

Source§

fn eq(&self, other: &Workflow) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialEq for Workflow

Source§

fn eq(&self, other: &Workflow) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl WorkflowLike for Workflow

Source§

fn version(&self) -> u32

Returns the major version (epoch) of the workflow. Read more
Source§

fn minor_version(&self) -> u32

Returns the minor version (partial) of the workflow. Read more
Source§

fn reference(&self) -> &Reference

Returns the reference identifier for this workflow. Read more
Source§

fn path(&self) -> &Path

Returns the file system path to the workflow’s AIM file. Read more
Source§

fn get_row(&self, index: usize) -> Option<Rule>

Retrieves a rule by its row index. Read more
Source§

fn get_rule(&self, identifier: &str) -> Option<Rule>

Retrieves a rule by its identifier. Read more
Source§

fn contains(&self, identifier: &str) -> bool

Checks if a rule with the given identifier exists. Read more
Source§

fn has_rule(&self, index: usize) -> bool

Checks if a specific row index contains a rule. Read more
Source§

fn rule_count(&self) -> usize

Returns the number of rules in the workflow. Read more
Source§

fn rule_rows(&self) -> usize

Returns the total number of rows in the workflow. Read more
Source§

fn iter_rows<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Option<Rule>> + 'a>

Returns an iterator over all rows. Read more
Source§

fn iter_rules<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Rule> + 'a>

Returns an iterator over all rules. Read more
Source§

fn as_any(&self) -> &dyn Any

Returns a reference to the workflow as a trait object. Read more

Auto Trait Implementations§

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
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,