use crate::{error::Recover, located::Located, quantity::Value, span::Span, text::Text};
use bitflags::bitflags;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, PartialEq, Clone)]
pub enum Block<'a> {
Metadata { key: Text<'a>, value: Text<'a> },
Section { name: Option<Text<'a>> },
Step {
items: Vec<Item<'a>>,
},
TextBlock(Vec<Text<'a>>),
}
#[derive(Debug, Serialize, PartialEq, Clone)]
pub enum Item<'a> {
Text(Text<'a>),
Ingredient(Box<Located<Ingredient<'a>>>),
Cookware(Box<Located<Cookware<'a>>>),
Timer(Box<Located<Timer<'a>>>),
}
impl Item<'_> {
pub fn span(&self) -> Span {
match self {
Item::Text(t) => t.span(),
Item::Ingredient(c) => c.span(),
Item::Cookware(c) => c.span(),
Item::Timer(c) => c.span(),
}
}
}
#[derive(Debug, Clone, Serialize, PartialEq)]
pub struct Ingredient<'a> {
pub modifiers: Located<Modifiers>,
pub intermediate_data: Option<Located<IntermediateData>>,
pub name: Text<'a>,
pub alias: Option<Text<'a>>,
pub quantity: Option<Located<Quantity<'a>>>,
pub note: Option<Text<'a>>,
}
#[derive(Debug, Clone, Serialize, PartialEq)]
pub struct Cookware<'a> {
pub modifiers: Located<Modifiers>,
pub name: Text<'a>,
pub alias: Option<Text<'a>>,
pub quantity: Option<Located<Quantity<'a>>>,
pub note: Option<Text<'a>>,
}
#[derive(Debug, Clone, Serialize, PartialEq)]
pub struct Timer<'a> {
pub name: Option<Text<'a>>,
pub quantity: Option<Located<Quantity<'a>>>,
}
#[derive(Debug, Clone, Serialize, PartialEq)]
pub struct Quantity<'a> {
pub value: QuantityValue,
pub unit: Option<Text<'a>>,
}
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct QuantityValue {
pub value: Located<Value>,
pub scaling_lock: Option<Span>,
}
impl QuantityValue {
pub fn span(&self) -> Span {
self.value.span()
}
}
impl Recover for Text<'_> {
fn recover() -> Self {
Self::empty(0)
}
}
impl Recover for Quantity<'_> {
fn recover() -> Self {
Self {
value: Recover::recover(),
unit: Recover::recover(),
}
}
}
impl Recover for QuantityValue {
fn recover() -> Self {
Self {
value: Recover::recover(),
scaling_lock: None,
}
}
}
impl Recover for Value {
fn recover() -> Self {
1.0.into()
}
}
bitflags! {
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct Modifiers: u16 {
const RECIPE = 1 << 0;
const REF = 1 << 1;
const HIDDEN = 1 << 2;
const OPT = 1 << 3;
const NEW = 1 << 4;
}
}
impl Modifiers {
pub fn should_be_listed(self) -> bool {
!self.intersects(Modifiers::HIDDEN | Modifiers::REF)
}
pub fn is_hidden(&self) -> bool {
self.contains(Modifiers::HIDDEN)
}
pub fn is_optional(&self) -> bool {
self.contains(Modifiers::OPT)
}
pub fn is_recipe(&self) -> bool {
self.contains(Modifiers::RECIPE)
}
pub fn is_reference(&self) -> bool {
self.contains(Modifiers::REF)
}
}
impl std::fmt::Display for Modifiers {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Display::fmt(&self.0, f)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct IntermediateData {
pub ref_mode: IntermediateRefMode,
pub target_kind: IntermediateTargetKind,
pub val: i16,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum IntermediateRefMode {
Number,
Relative,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum IntermediateTargetKind {
Step,
Section,
}