1use crate::block::BV;
4use crate::datatype::Datatype;
5use crate::everything::Everything;
6use crate::item::Item;
7use crate::report::{ErrorKey, err, warn};
8use crate::token::Token;
9use crate::validator::Validator;
10
11#[derive(Debug, Clone, Copy)]
13#[allow(dead_code)]
14pub enum DefineType {
15 Boolean,
16 Integer,
17 Number,
18 Date,
19 String,
20 Item(Item),
21 SingleQuotedItem(Item),
22 Choice(&'static [&'static str]),
23 UnknownList,
24 IntegerList,
25 NumberList,
26 StringList,
27 ItemList(Item),
28 ItemOrEmptyList(Item),
29 Color,
31 Color3,
33}
34
35impl From<DefineType> for Datatype {
36 fn from(dt: DefineType) -> Self {
37 match dt {
38 DefineType::Boolean => Datatype::bool,
39 DefineType::Integer | DefineType::Number => Datatype::CFixedPoint,
40 DefineType::Date => Datatype::Date,
41 DefineType::String
42 | DefineType::Item(_)
43 | DefineType::SingleQuotedItem(_)
44 | DefineType::Choice(_) => Datatype::CString,
45 DefineType::UnknownList
46 | DefineType::IntegerList
47 | DefineType::NumberList
48 | DefineType::StringList
49 | DefineType::ItemList(_)
50 | DefineType::ItemOrEmptyList(_) => Datatype::Unknown,
51 DefineType::Color3 => Datatype::CVector3f,
52 DefineType::Color => Datatype::CVector4f,
53 }
54 }
55}
56
57impl DefineType {
58 pub fn validate(self, bv: &BV, data: &Everything) {
59 match self {
60 DefineType::Boolean => {
61 if let Some(token) = bv.expect_value() {
62 if !token.is("yes") && !token.is("no") {
63 let msg = "expected `yes` or `no`";
64 err(ErrorKey::Validation).msg(msg).loc(token).push();
65 }
66 }
67 }
68 DefineType::Integer => {
69 bv.expect_value().map(Token::expect_integer);
70 }
71 DefineType::Number => {
72 bv.expect_value().map(Token::expect_precise_number);
73 }
74 DefineType::Date => {
75 bv.expect_value().map(Token::expect_date);
76 }
77 DefineType::String => {
78 bv.expect_value();
79 }
80 DefineType::Item(itype) => {
81 if let Some(token) = bv.expect_value() {
82 if !(itype == Item::Sound && token.as_str().is_empty()) {
83 data.verify_exists(itype, token);
84 }
85 }
86 }
87 DefineType::SingleQuotedItem(itype) => {
88 if let Some(token) = bv.expect_value() {
89 if let Some(sfx) = token.strip_prefix("'") {
90 if let Some(bare) = sfx.strip_suffix("'") {
91 data.verify_exists(itype, &bare);
92 }
93 }
94 }
95 }
96 DefineType::Choice(choices) => {
97 if let Some(token) = bv.expect_value() {
98 if !choices.contains(&token.as_str()) {
99 let msg = format!("expected one of {}", choices.join(", "));
100 err(ErrorKey::Choice).msg(msg).loc(token).push();
101 }
102 }
103 }
104 DefineType::UnknownList | DefineType::StringList => {
105 bv.expect_block();
106 }
107 DefineType::IntegerList => {
108 if let Some(block) = bv.expect_block() {
109 let mut vd = Validator::new(block, data);
110 for value in vd.values() {
111 value.expect_integer();
112 }
113 }
114 }
115 DefineType::NumberList => {
116 if let Some(block) = bv.expect_block() {
117 let mut vd = Validator::new(block, data);
118 for value in vd.values() {
119 value.expect_precise_number();
120 }
121 }
122 }
123 DefineType::ItemList(itype) => {
124 if let Some(block) = bv.expect_block() {
125 let mut vd = Validator::new(block, data);
126 for value in vd.values() {
127 data.verify_exists(itype, value);
128 }
129 }
130 }
131 DefineType::ItemOrEmptyList(itype) => {
132 if let Some(block) = bv.expect_block() {
133 let mut vd = Validator::new(block, data);
134 for value in vd.values() {
135 if !value.as_str().is_empty() {
136 data.verify_exists(itype, value);
137 }
138 }
139 }
140 }
141 DefineType::Color => {
142 if let Some(block) = bv.expect_block() {
143 let mut vd = Validator::new(block, data);
144 let mut count = 0;
145 for value in vd.values() {
146 value.expect_precise_number();
147 count += 1;
148 }
149 if count != 4 {
150 let msg = "expected exactly 4 values for color";
151 warn(ErrorKey::Colors).msg(msg).loc(block).push();
152 }
153 }
154 }
155 DefineType::Color3 => {
156 if let Some(block) = bv.expect_block() {
157 let mut vd = Validator::new(block, data);
158 let mut count = 0;
159 for value in vd.values() {
160 value.expect_precise_number();
161 count += 1;
162 }
163 if count != 3 {
164 let msg = "expected exactly 3 values for this color";
165 warn(ErrorKey::Colors).msg(msg).loc(block).push();
166 }
167 }
168 }
169 }
170 }
171}