1use super::GffType;
13use crate::gff::{GffLocalizedString, GffValue};
14use rakata_core::ResRef;
15
16pub trait GffScalar: Sized {
29 const GFF_TYPE: GffType;
31
32 fn from_gff_value(value: &GffValue) -> Option<Self>;
37
38 fn to_gff_value(self) -> GffValue;
40}
41
42macro_rules! integer_scalar {
48 ($rust:ty, $gff:ident, $write:ident, $( $accept:ident ),+ $(,)?) => {
49 impl GffScalar for $rust {
50 const GFF_TYPE: GffType = GffType::$gff;
51
52 fn from_gff_value(value: &GffValue) -> Option<Self> {
53 match value {
54 $( GffValue::$accept(v) => Self::try_from(*v).ok(), )+
55 _ => None,
56 }
57 }
58
59 fn to_gff_value(self) -> GffValue {
60 GffValue::$write(self)
61 }
62 }
63 };
64}
65
66integer_scalar!(u8, UInt8, UInt8, UInt8, Int8, UInt16, Int16, UInt32, Int32);
76integer_scalar!(i8, Int8, Int8, Int8, UInt8, Int16, UInt16, Int32, UInt32);
77integer_scalar!(u16, UInt16, UInt16, UInt16, Int16, UInt8, Int8, UInt32, Int32);
78integer_scalar!(i16, Int16, Int16, Int16, UInt16, Int8, UInt8, Int32, UInt32);
79integer_scalar!(u32, UInt32, UInt32, UInt32, Int32, UInt16, UInt8);
80integer_scalar!(i32, Int32, Int32, Int32, UInt32, Int16, UInt16, Int8, UInt8);
81integer_scalar!(u64, UInt64, UInt64, UInt64, UInt32, Int64, Int32, UInt16, UInt8);
82integer_scalar!(i64, Int64, Int64, Int32, Int64);
85
86impl GffScalar for f32 {
87 const GFF_TYPE: GffType = GffType::Single;
88
89 fn from_gff_value(value: &GffValue) -> Option<Self> {
90 match value {
91 GffValue::Single(v) => Some(*v),
92 #[allow(clippy::cast_possible_truncation, clippy::as_conversions)]
96 GffValue::Double(v) => Some(*v as f32),
97 _ => None,
98 }
99 }
100
101 fn to_gff_value(self) -> GffValue {
102 GffValue::Single(self)
103 }
104}
105
106impl GffScalar for f64 {
107 const GFF_TYPE: GffType = GffType::Double;
108
109 fn from_gff_value(value: &GffValue) -> Option<Self> {
110 match value {
111 GffValue::Double(v) => Some(*v),
112 _ => None,
113 }
114 }
115
116 fn to_gff_value(self) -> GffValue {
117 GffValue::Double(self)
118 }
119}
120
121impl GffScalar for bool {
125 const GFF_TYPE: GffType = GffType::UInt8;
126
127 fn from_gff_value(value: &GffValue) -> Option<Self> {
128 match value {
129 GffValue::UInt8(v) => Some(*v != 0),
130 GffValue::Int8(v) => Some(*v != 0),
131 GffValue::UInt16(v) => Some(*v != 0),
132 GffValue::Int16(v) => Some(*v != 0),
133 GffValue::UInt32(v) => Some(*v != 0),
134 GffValue::Int32(v) => Some(*v != 0),
135 _ => None,
136 }
137 }
138
139 fn to_gff_value(self) -> GffValue {
140 GffValue::UInt8(u8::from(self))
141 }
142}
143
144impl GffScalar for String {
145 const GFF_TYPE: GffType = GffType::String;
146
147 fn from_gff_value(value: &GffValue) -> Option<Self> {
148 match value {
149 GffValue::String(v) => Some(v.clone()),
150 _ => None,
151 }
152 }
153
154 fn to_gff_value(self) -> GffValue {
155 GffValue::String(self)
156 }
157}
158
159impl GffScalar for ResRef {
160 const GFF_TYPE: GffType = GffType::ResRef;
161
162 fn from_gff_value(value: &GffValue) -> Option<Self> {
163 match value {
164 GffValue::ResRef(v) => Some(*v),
165 _ => None,
166 }
167 }
168
169 fn to_gff_value(self) -> GffValue {
170 GffValue::ResRef(self)
171 }
172}
173
174impl GffScalar for GffLocalizedString {
175 const GFF_TYPE: GffType = GffType::LocalizedString;
176
177 fn from_gff_value(value: &GffValue) -> Option<Self> {
178 match value {
179 GffValue::LocalizedString(v) => Some(v.clone()),
180 _ => None,
181 }
182 }
183
184 fn to_gff_value(self) -> GffValue {
185 GffValue::LocalizedString(self)
186 }
187}
188
189impl GffScalar for Vec<u8> {
190 const GFF_TYPE: GffType = GffType::Binary;
191
192 fn from_gff_value(value: &GffValue) -> Option<Self> {
193 match value {
194 GffValue::Binary(v) => Some(v.clone()),
195 _ => None,
196 }
197 }
198
199 fn to_gff_value(self) -> GffValue {
200 GffValue::Binary(self)
201 }
202}
203
204impl GffScalar for [f32; 3] {
205 const GFF_TYPE: GffType = GffType::Vector3;
206
207 fn from_gff_value(value: &GffValue) -> Option<Self> {
208 match value {
209 GffValue::Vector3(v) => Some(*v),
210 _ => None,
211 }
212 }
213
214 fn to_gff_value(self) -> GffValue {
215 GffValue::Vector3(self)
216 }
217}
218
219impl GffScalar for [f32; 4] {
220 const GFF_TYPE: GffType = GffType::Vector4;
221
222 fn from_gff_value(value: &GffValue) -> Option<Self> {
223 match value {
224 GffValue::Vector4(v) => Some(*v),
225 _ => None,
226 }
227 }
228
229 fn to_gff_value(self) -> GffValue {
230 GffValue::Vector4(self)
231 }
232}