1use hash40::Hash40;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4use std::convert::{TryFrom, TryInto};
5
6#[doc(hidden)]
7pub const MAGIC: &[u8; 8] = b"paracobn";
8const UNWRAP_ERR: &str = "Tried to unwrap param into inconsistent type";
9
10#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
13pub enum ParamKind {
14 Bool(bool),
16 I8(i8),
17 U8(u8),
18 I16(i16),
19 U16(u16),
20 I32(i32),
21 U32(u32),
22 Float(f32),
23 Hash(Hash40),
24 Str(String),
25 List(ParamList),
26 Struct(ParamStruct),
27}
28
29#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
31#[serde(transparent)]
32pub struct ParamList(pub Vec<ParamKind>);
33
34#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
38#[serde(transparent)]
39pub struct ParamStruct(pub Vec<(Hash40, ParamKind)>);
40
41impl ParamKind {
42 pub fn try_into_owned<T>(self) -> Result<T, T::Error>
45 where
46 T: TryFrom<ParamKind>,
47 {
48 self.try_into()
49 }
50
51 pub fn try_into_ref<'a, T>(
54 &'a self,
55 ) -> Result<&'a T, <&'a T as std::convert::TryFrom<&'a ParamKind>>::Error>
56 where
57 &'a T: TryFrom<&'a ParamKind>,
58 {
59 self.try_into()
60 }
61
62 pub fn try_into_mut<'a, T>(
65 &'a mut self,
66 ) -> Result<&'a mut T, <&'a mut T as TryFrom<&'a mut ParamKind>>::Error>
67 where
68 &'a mut T: TryFrom<&'a mut ParamKind>,
69 {
70 self.try_into()
71 }
72
73 pub fn unwrap_as_hashmap(self) -> HashMap<Hash40, ParamKind> {
76 TryInto::<ParamStruct>::try_into(self)
77 .unwrap()
78 .0
79 .drain(..)
80 .collect::<HashMap<_, _>>()
81 }
82
83 pub fn unwrap_as_hashmap_ref(&self) -> HashMap<Hash40, &ParamKind> {
86 TryInto::<&ParamStruct>::try_into(self)
87 .unwrap()
88 .0
89 .iter()
90 .map(|(h, p)| (*h, p))
91 .collect::<HashMap<_, _>>()
92 }
93
94 pub fn unwrap_as_hashmap_mut(&mut self) -> HashMap<Hash40, &mut ParamKind> {
97 TryInto::<&mut ParamStruct>::try_into(self)
98 .unwrap()
99 .0
100 .iter_mut()
101 .map(|(h, p)| (*h, p))
102 .collect::<HashMap<_, _>>()
103 }
104}
105
106use ParamKind::*;
107
108macro_rules! impl_from_param {
109 ($($param:ident ($t:ty)),*$(,)?) => {
110 $(
111 impl TryFrom<ParamKind> for $t {
112 type Error = &'static str;
113
114 fn try_from(param: ParamKind) -> Result<Self, Self::Error> {
115 if let $param(val) = param {
116 Ok(val)
117 } else {
118 Err(UNWRAP_ERR)
119 }
120 }
121 }
122
123 impl<'a> TryFrom<&'a ParamKind> for &'a $t {
124 type Error = &'static str;
125
126 fn try_from(param: &'a ParamKind) -> Result<Self, Self::Error> {
127 if let $param(val) = param {
128 Ok(val)
129 } else {
130 Err(UNWRAP_ERR)
131 }
132 }
133 }
134
135 impl<'a> TryFrom<&'a mut ParamKind> for &'a mut $t {
136 type Error = &'static str;
137
138 fn try_from(param: &'a mut ParamKind) -> Result<Self, Self::Error> {
139 if let $param(val) = param {
140 Ok(val)
141 } else {
142 Err(UNWRAP_ERR)
143 }
144 }
145 }
146
147 impl From<$t> for ParamKind {
148 fn from(v: $t) -> ParamKind {
149 ParamKind::$param(v)
150 }
151 }
152 )*
153 }
154}
155
156impl_from_param! {
157 Bool(bool),
158 I8(i8),
159 U8(u8),
160 I16(i16),
161 U16(u16),
162 I32(i32),
163 U32(u32),
164 Float(f32),
165 Hash(Hash40),
166 Str(String),
167 List(ParamList),
168 Struct(ParamStruct),
169}