parade-rs 2.0.0

Rust rewrite of Parade - an experimental interactive-fiction playground / filesystem / operating system?
Documentation
use std::fmt::{Display, Write};

use serde::{Deserialize, Serialize};
use strum::EnumString;

use crate::action::Action;

/// The basic object-type within Parade.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Vessel {
    /// The article to use by default when referring to the Vessel.
    pub article: Option<Article>,
    /// The text to display to users inside the vessel, or who Look at it.
    pub note: Option<String>,
    /// The program to be executed by the Use action.
    pub program: Option<Vec<Action>>,
}
impl Vessel {
    /// Creates a new [Vessel] with the specified values.
    pub fn new(
        article: Option<Article>,
        note: Option<String>,
        program: Option<Vec<Action>>,
    ) -> Self {
        Self {
            article,
            note,
            program,
        }
    }
    /// Creates a new [Vessel] with the specified [Article], and no note or program.
    pub fn with_article(article: Option<Article>) -> Self {
        Self {
            article,
            note: None,
            program: None,
        }
    }
}
impl Default for Vessel {
    fn default() -> Self {
        Self {
            article: Some(Article::A),
            note: None,
            program: None,
        }
    }
}

/// An English article, to prefix a noun.
#[derive(
    Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, EnumString,
)]
#[strum(ascii_case_insensitive)]
pub enum Article {
    /// The word "A".
    A,
    /// The word "An".
    An,
    /// The word "The".
    The,
}
impl Display for Article {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Article::A => f.write_str("a"),
            Article::An => f.write_str("an"),
            Article::The => f.write_str("the"),
        }
    }
}

/// Prints a name and (if present) article to a [String].
pub fn vessel_text(name: &str, article: &Option<Article>) -> String {
    let mut out = String::new();
    if let Some(article) = article {
        out.write_str(&format!("{article} ")).unwrap();
    }
    out.write_str(name).unwrap();
    out
}