use std::borrow::Borrow;
use std::fmt::{Display, Formatter};
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
pub enum Requirement {
#[default]
Strips,
Typing,
NegativePreconditions,
DisjunctivePreconditions,
Equality,
ExistentialPreconditions,
UniversalPreconditions,
QuantifiedPreconditions,
ConditionalEffects,
Fluents,
NumericFluents,
ObjectFluents,
Adl,
DurativeActions,
DurationInequalities,
ContinuousEffects,
DerivedPredicates,
TimedInitialLiterals,
Preferences,
Constraints,
ActionCosts,
}
pub mod names {
pub const STRIPS: &str = ":strips";
pub const TYPING: &str = ":typing";
pub const NEGATIVE_PRECONDITIONS: &str = ":negative-preconditions";
pub const DISJUNCTIVE_PRECONDITIONS: &str = ":disjunctive-preconditions";
pub const EQUALITY: &str = ":equality";
pub const EXISTENTIAL_PRECONDITIONS: &str = ":existential-preconditions";
pub const UNIVERSAL_PRECONDITIONS: &str = ":universal-preconditions";
pub const QUANTIFIED_PRECONDITIONS: &str = ":quantified-preconditions";
pub const CONDITIONAL_EFFECTS: &str = ":conditional-effects";
pub const FLUENTS: &str = ":fluents";
pub const NUMERIC_FLUENTS: &str = ":numeric-fluents";
pub const OBJECT_FLUENTS: &str = ":object-fluents";
pub const ADL: &str = ":adl";
pub const DURATIVE_ACTIONS: &str = ":durative-actions";
pub const DURATION_INEQUALITIES: &str = ":duration-inequalities";
pub const CONTINUOUS_EFFECTS: &str = ":continuous-effects";
pub const DERIVED_PREDICATES: &str = ":derived-predicates";
pub const TIMED_INITIAL_LITERALS: &str = ":timed-initial-literals";
pub const PREFERENCES: &str = ":preferences";
pub const CONSTRAINTS: &str = ":constraints";
pub const ACTION_COSTS: &str = ":action-costs";
}
impl Requirement {
pub fn contains<T: Borrow<Requirement>>(&self, other: T) -> bool {
let other = other.borrow();
match self {
Self::QuantifiedPreconditions => {
other == Self::QuantifiedPreconditions
|| other == Self::ExistentialPreconditions
|| other == Self::UniversalPreconditions
}
Self::Adl => {
other == Self::Adl
|| other == Self::Strips
|| other == Self::Typing
|| other == Self::NegativePreconditions
|| other == Self::DisjunctivePreconditions
|| other == Self::Equality
|| other == Self::QuantifiedPreconditions
|| other == Self::ContinuousEffects
}
Self::Fluents => {
other == Self::Fluents
|| other == Self::NumericFluents
|| other == Self::ObjectFluents
}
x => other.eq(x),
}
}
pub fn as_str(&self) -> &'static str {
match self {
Requirement::Strips => names::STRIPS,
Requirement::Typing => names::TYPING,
Requirement::NegativePreconditions => names::NEGATIVE_PRECONDITIONS,
Requirement::DisjunctivePreconditions => names::DISJUNCTIVE_PRECONDITIONS,
Requirement::Equality => names::EQUALITY,
Requirement::ExistentialPreconditions => names::EXISTENTIAL_PRECONDITIONS,
Requirement::UniversalPreconditions => names::UNIVERSAL_PRECONDITIONS,
Requirement::QuantifiedPreconditions => names::QUANTIFIED_PRECONDITIONS,
Requirement::ConditionalEffects => names::CONDITIONAL_EFFECTS,
Requirement::Fluents => names::FLUENTS,
Requirement::NumericFluents => names::NUMERIC_FLUENTS,
Requirement::ObjectFluents => names::OBJECT_FLUENTS,
Requirement::Adl => names::ADL,
Requirement::DurativeActions => names::DURATIVE_ACTIONS,
Requirement::DurationInequalities => names::DURATION_INEQUALITIES,
Requirement::ContinuousEffects => names::CONTINUOUS_EFFECTS,
Requirement::DerivedPredicates => names::DERIVED_PREDICATES,
Requirement::TimedInitialLiterals => names::TIMED_INITIAL_LITERALS,
Requirement::Preferences => names::PREFERENCES,
Requirement::Constraints => names::CONSTRAINTS,
Requirement::ActionCosts => names::ACTION_COSTS,
}
}
pub fn expand(&self) -> Vec<Requirement> {
match self {
Requirement::QuantifiedPreconditions => vec![
Requirement::ExistentialPreconditions,
Requirement::UniversalPreconditions,
],
Requirement::Fluents => vec![Requirement::NumericFluents, Requirement::ObjectFluents],
Requirement::Adl => vec![
Requirement::Strips,
Requirement::Typing,
Requirement::NegativePreconditions,
Requirement::DisjunctivePreconditions,
Requirement::Equality,
Requirement::ExistentialPreconditions, Requirement::UniversalPreconditions, Requirement::ConditionalEffects,
],
r => vec![*r],
}
}
}
impl TryFrom<&str> for Requirement {
type Error = ParseError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
names::STRIPS => Ok(Requirement::Strips),
names::TYPING => Ok(Requirement::Typing),
names::NEGATIVE_PRECONDITIONS => Ok(Requirement::NegativePreconditions),
names::DISJUNCTIVE_PRECONDITIONS => Ok(Requirement::DisjunctivePreconditions),
names::EQUALITY => Ok(Requirement::Equality),
names::EXISTENTIAL_PRECONDITIONS => Ok(Requirement::ExistentialPreconditions),
names::UNIVERSAL_PRECONDITIONS => Ok(Requirement::UniversalPreconditions),
names::QUANTIFIED_PRECONDITIONS => Ok(Requirement::QuantifiedPreconditions),
names::CONDITIONAL_EFFECTS => Ok(Requirement::ConditionalEffects),
names::FLUENTS => Ok(Requirement::Fluents),
names::NUMERIC_FLUENTS => Ok(Requirement::NumericFluents),
names::OBJECT_FLUENTS => Ok(Requirement::ObjectFluents),
names::ADL => Ok(Requirement::Adl),
names::DURATIVE_ACTIONS => Ok(Requirement::DurativeActions),
names::DURATION_INEQUALITIES => Ok(Requirement::DurationInequalities),
names::CONTINUOUS_EFFECTS => Ok(Requirement::ContinuousEffects),
names::DERIVED_PREDICATES => Ok(Requirement::DerivedPredicates),
names::TIMED_INITIAL_LITERALS => Ok(Requirement::TimedInitialLiterals),
names::PREFERENCES => Ok(Requirement::Preferences),
names::CONSTRAINTS => Ok(Requirement::Constraints),
names::ACTION_COSTS => Ok(Requirement::ActionCosts),
_ => Err(ParseError::InvalidRequirement),
}
}
}
#[derive(Debug, Clone, thiserror::Error)]
pub enum ParseError {
#[error("Invalid requirement")]
InvalidRequirement,
}
impl Borrow<str> for Requirement {
fn borrow(&self) -> &str {
self.as_str()
}
}
impl AsRef<str> for Requirement {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl Display for Requirement {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_ref())
}
}
impl PartialEq<Requirement> for &Requirement {
#[inline(always)]
fn eq(&self, other: &Requirement) -> bool {
other.eq(*self)
}
}
impl PartialEq<&Requirement> for Requirement {
#[inline(always)]
fn eq(&self, other: &&Requirement) -> bool {
self.eq(*other)
}
}
impl PartialEq<String> for Requirement {
#[inline(always)]
fn eq(&self, other: &String) -> bool {
other.eq(self.as_ref())
}
}
impl PartialEq<&str> for Requirement {
#[inline(always)]
fn eq(&self, other: &&str) -> bool {
(*other).eq(self.as_ref())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn str_equals_works() {
assert_eq!(Requirement::Strips, ":strips");
assert_eq!(Requirement::Typing, ":typing");
assert_eq!(
Requirement::NegativePreconditions,
":negative-preconditions"
);
assert_eq!(
Requirement::DisjunctivePreconditions,
":disjunctive-preconditions"
);
assert_eq!(Requirement::Equality, ":equality");
assert_eq!(
Requirement::ExistentialPreconditions,
":existential-preconditions"
);
assert_eq!(
Requirement::UniversalPreconditions,
":universal-preconditions"
);
assert_eq!(
Requirement::QuantifiedPreconditions,
":quantified-preconditions"
);
assert_eq!(Requirement::ConditionalEffects, ":conditional-effects");
assert_eq!(Requirement::Fluents, ":fluents");
assert_eq!(Requirement::NumericFluents, ":numeric-fluents");
assert_eq!(Requirement::Adl, ":adl");
assert_eq!(Requirement::DurativeActions, ":durative-actions");
assert_eq!(Requirement::DurationInequalities, ":duration-inequalities");
assert_eq!(Requirement::ContinuousEffects, ":continuous-effects");
assert_eq!(Requirement::DerivedPredicates, ":derived-predicates");
assert_eq!(Requirement::TimedInitialLiterals, ":timed-initial-literals");
assert_eq!(Requirement::Preferences, ":preferences");
assert_eq!(Requirement::Constraints, ":constraints");
assert_eq!(Requirement::ActionCosts, ":action-costs");
}
#[test]
fn contains_adl_works() {
for req in [
Requirement::Strips,
Requirement::Typing,
Requirement::NegativePreconditions,
Requirement::DisjunctivePreconditions,
Requirement::Equality,
Requirement::QuantifiedPreconditions,
Requirement::ContinuousEffects,
] {
assert!(Requirement::Adl.contains(req));
}
assert!(Requirement::Adl.contains(Requirement::Adl));
}
#[test]
fn contains_quantified_preconditions_works() {
for req in [
Requirement::ExistentialPreconditions,
Requirement::UniversalPreconditions,
] {
assert!(Requirement::QuantifiedPreconditions.contains(req));
}
assert!(Requirement::QuantifiedPreconditions.contains(Requirement::QuantifiedPreconditions));
}
#[test]
fn contains_fluents_works() {
for req in [Requirement::NumericFluents, Requirement::ObjectFluents] {
assert!(Requirement::Fluents.contains(req));
}
assert!(Requirement::Fluents.contains(Requirement::Fluents));
}
}