behaviortree-core 0.1.0

Core implementaion of behaviortree
Documentation
// Copyright © 2025 Stephan Kunz
//! [`PreConditions`] and [`PostConditions`] implementation.

use core::ops::{Deref, DerefMut};

use crate::{ConstString, FAILURE_IF, ON_FAILURE, ON_HALTED, ON_SUCCESS, POST, SKIP_IF, SUCCESS_IF, WHILE};

use super::error::Error as BehaviorError;

/// Helper struct to reduce amount of parameters
#[derive(Default)]
pub struct Conditions {
	pub(crate) pre: PreConditions,
	pub(crate) post: PostConditions,
}

/// Names and order of the `PreConditions`.
pub const PRE_CONDITIONS: [&str; 4] = [FAILURE_IF, SUCCESS_IF, SKIP_IF, WHILE];

/// Array holding the pre conditions.
#[derive(Default)]
pub struct PreConditions(pub(crate) Option<[Option<ConstString>; PRE_CONDITIONS.len()]>);

impl Deref for PreConditions {
	type Target = Option<[Option<ConstString>; PRE_CONDITIONS.len()]>;

	fn deref(&self) -> &Self::Target {
		&self.0
	}
}

impl DerefMut for PreConditions {
	fn deref_mut(&mut self) -> &mut Self::Target {
		&mut self.0
	}
}

impl PreConditions {
	/// Get a pre condition.
	#[must_use]
	pub fn get(&self, name: &str) -> Option<&ConstString> {
		let array = self.0.as_ref()?;
		let index = (0..PRE_CONDITIONS.len()).find(|&i| PRE_CONDITIONS[i] == name)?;
		array[index].as_ref()
	}

	/// Set a pre condition.
	/// # Errors
	/// - if name is not a pre condition
	pub fn set(&mut self, name: &str, script: &str) -> Result<(), BehaviorError> {
		let array = self.0.get_or_insert([None, None, None, None]);
		let index = (0..PRE_CONDITIONS.len())
			.find(|&i| PRE_CONDITIONS[i] == name)
			.ok_or_else(|| BehaviorError::NoCondition { value: name.into() })?;
		array[index] = Some(script.into());
		Ok(())
	}
}

/// Names and order of the `PostConditions`.
pub const POST_CONDITIONS: [&str; 4] = [ON_HALTED, ON_FAILURE, ON_SUCCESS, POST];

/// Array holding the post conditions.
#[derive(Default)]
pub struct PostConditions(pub(crate) Option<[Option<ConstString>; POST_CONDITIONS.len()]>);

impl Deref for PostConditions {
	type Target = Option<[Option<ConstString>; POST_CONDITIONS.len()]>;

	fn deref(&self) -> &Self::Target {
		&self.0
	}
}

impl DerefMut for PostConditions {
	fn deref_mut(&mut self) -> &mut Self::Target {
		&mut self.0
	}
}

impl PostConditions {
	/// Get a post condition.
	#[must_use]
	pub fn get(&self, name: &str) -> Option<&ConstString> {
		let array = self.0.as_ref()?;
		let index = (0..POST_CONDITIONS.len()).find(|&i| POST_CONDITIONS[i] == name)?;
		array[index].as_ref()
	}

	/// Set a post condition.
	/// # Errors
	/// - if name is not a post condition
	pub fn set(&mut self, name: &str, script: &str) -> Result<(), BehaviorError> {
		let array = self.0.get_or_insert([None, None, None, None]);
		let index = (0..POST_CONDITIONS.len())
			.find(|&i| POST_CONDITIONS[i] == name)
			.ok_or_else(|| BehaviorError::NoCondition { value: name.into() })?;
		array[index] = Some(script.into());
		Ok(())
	}
}