1use indexmap::IndexMap;
2use serde::{Deserialize, Serialize};
3use opys_mojang_rules::{satisfies_ruleset, OsOptions, RuleError, Ruleset};
4
5use crate::shorthand::{encode_short_ruleset, parse_short_ruleset, RawRuleset, ShorthandError};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct ConditionalVal {
9 pub value: String,
10 pub rules: Ruleset,
11}
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum ValDef {
15 Flat(String),
16 Arms(Vec<ConditionalVal>),
17}
18
19pub type ValDefs = IndexMap<String, ValDef>;
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct ConditionalValWire {
23 pub value: String,
24 #[serde(default, skip_serializing_if = "Option::is_none")]
25 pub rules: Option<RawRuleset>,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
29#[serde(untagged)]
30pub enum ValDefWire {
31 Flat(String),
32 Arms(Vec<ConditionalValWire>),
33}
34
35pub fn parse_val_defs(raw: IndexMap<String, ValDefWire>) -> Result<ValDefs, ShorthandError> {
36 raw.into_iter()
37 .map(|(key, val)| {
38 let parsed = match val {
39 ValDefWire::Flat(s) => ValDef::Flat(s),
40 ValDefWire::Arms(arms) => ValDef::Arms(
41 arms.into_iter()
42 .map(|arm| {
43 Ok(ConditionalVal {
44 value: arm.value,
45 rules: arm
46 .rules
47 .map(parse_short_ruleset)
48 .transpose()?
49 .unwrap_or_default(),
50 })
51 })
52 .collect::<Result<_, ShorthandError>>()?,
53 ),
54 };
55 Ok((key, parsed))
56 })
57 .collect()
58}
59
60pub fn encode_val_defs(defs: &ValDefs) -> serde_json::Value {
61 let mut out = serde_json::Map::new();
62 for (key, val) in defs {
63 let v = match val {
64 ValDef::Flat(s) => serde_json::Value::String(s.clone()),
65 ValDef::Arms(arms) => serde_json::Value::Array(
66 arms.iter()
67 .map(|arm| {
68 let mut m = serde_json::Map::new();
69 m.insert("value".into(), serde_json::Value::String(arm.value.clone()));
70 if !arm.rules.is_empty() {
71 m.insert(
72 "rules".into(),
73 serde_json::to_value(encode_short_ruleset(&arm.rules)).unwrap(),
74 );
75 }
76 serde_json::Value::Object(m)
77 })
78 .collect(),
79 ),
80 };
81 out.insert(key.clone(), v);
82 }
83 serde_json::Value::Object(out)
84}
85
86pub fn resolve_val_defs(
88 defs: &ValDefs,
89 os: &OsOptions,
90 feats: &[String],
91) -> Result<IndexMap<String, String>, RuleError> {
92 let mut result = IndexMap::new();
93 for (key, val) in defs {
94 match val {
95 ValDef::Flat(s) => {
96 result.insert(key.clone(), s.clone());
97 }
98 ValDef::Arms(arms) => {
99 let mut chosen: Option<String> = None;
100 for arm in arms {
101 if satisfies_ruleset(&arm.rules, os, feats)? {
102 chosen = Some(arm.value.clone());
103 }
104 }
105 if let Some(v) = chosen {
106 result.insert(key.clone(), v);
107 }
108 }
109 }
110 }
111 Ok(result)
112}