1use serde::{Deserialize, Serialize};
2use opys_mojang_rules::{satisfies_ruleset, OsOptions, RuleError, Ruleset};
3
4use crate::shorthand::{encode_short_ruleset, parse_short_ruleset, RawRuleset, ShorthandError};
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct Val {
8 pub rules: Ruleset,
9 pub value: Vec<String>,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14#[serde(untagged)]
15pub enum ValWire {
16 Bare(String),
17 Object {
18 #[serde(default, skip_serializing_if = "Option::is_none")]
19 rules: Option<RawRuleset>,
20 value: ValValueWire,
21 },
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
25#[serde(untagged)]
26pub enum ValValueWire {
27 One(String),
28 Many(Vec<String>),
29}
30
31pub fn parse_val(raw: ValWire) -> Result<Val, ShorthandError> {
32 match raw {
33 ValWire::Bare(s) => Ok(Val {
34 rules: Vec::new(),
35 value: vec![s],
36 }),
37 ValWire::Object { rules, value } => Ok(Val {
38 rules: match rules {
39 Some(r) => parse_short_ruleset(r)?,
40 None => Vec::new(),
41 },
42 value: match value {
43 ValValueWire::One(s) => vec![s],
44 ValValueWire::Many(v) => v,
45 },
46 }),
47 }
48}
49
50pub fn encode_val(val: &Val) -> serde_json::Value {
51 if val.rules.is_empty() && val.value.len() == 1 {
52 return serde_json::Value::String(val.value[0].clone());
53 }
54 let mut map = serde_json::Map::new();
55 map.insert(
56 "rules".into(),
57 serde_json::to_value(encode_short_ruleset(&val.rules)).unwrap(),
58 );
59 map.insert(
60 "value".into(),
61 serde_json::Value::Array(
62 val.value
63 .iter()
64 .cloned()
65 .map(serde_json::Value::String)
66 .collect(),
67 ),
68 );
69 serde_json::Value::Object(map)
70}
71
72pub type Valset = Vec<Val>;
73
74pub fn parse_valset(raw: Vec<ValWire>) -> Result<Valset, ShorthandError> {
75 raw.into_iter().map(parse_val).collect()
76}
77
78pub fn encode_valset(vs: &Valset) -> Vec<serde_json::Value> {
79 vs.iter().map(encode_val).collect()
80}
81
82pub fn resolve_valset(
83 vs: &Valset,
84 os: &OsOptions,
85 feats: &[String],
86) -> Result<Vec<String>, RuleError> {
87 let mut acc = Vec::new();
88 for val in vs {
89 if satisfies_ruleset(&val.rules, os, feats)? {
90 acc.extend_from_slice(&val.value);
91 }
92 }
93 Ok(acc)
94}