1use crate::prelude::*;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq, Reflect)]
7pub enum StorageFormat {
8 #[cfg(feature = "bincode")]
9 Bincode,
10 #[cfg(feature = "ini")]
11 Ini,
12 #[cfg(feature = "json")]
13 Json,
14 #[cfg(all(feature = "json", feature = "pretty"))]
15 JsonPretty,
16 #[cfg(feature = "ron")]
17 Ron,
18 #[cfg(all(feature = "ron", feature = "pretty"))]
19 RonPretty,
20 #[cfg(all(feature = "ron", feature = "pretty"))]
21 RonPrettyWithStructNames,
22 #[cfg(feature = "toml")]
23 Toml,
24 #[cfg(all(feature = "toml", feature = "pretty"))]
25 TomlPretty,
26 #[cfg(feature = "yaml")]
27 Yaml,
28}
29
30#[cfg(any(
31 feature = "bincode",
32 feature = "ini",
33 feature = "json",
34 feature = "ron",
35 feature = "toml",
36 feature = "yaml",
37))]
38impl StorageFormat {
39 pub fn serialize<R: Serialize + DeserializeOwned>(
41 self,
42 name: &str,
43 resource: &R,
44 ) -> Result<Vec<u8>, PersistenceError> {
45 match self {
46 #[cfg(feature = "bincode")]
47 StorageFormat::Bincode => {
48 bincode::serialize(resource).map_err(|error| {
49 log::error!("failed to serialize {} to Bincode\n\n{}", name, error);
50 PersistenceError::BincodeSerialization(error)
51 })
52 },
53 #[cfg(feature = "ini")]
54 StorageFormat::Ini => {
55 serde_ini::to_string(resource)
56 .map(|serialized_resource| serialized_resource.into_bytes())
57 .map_err(|error| {
58 log::error!("failed to serialize {} to INI\n\n{}", name, error);
59 PersistenceError::IniSerialization(error)
60 })
61 },
62 #[cfg(feature = "json")]
63 StorageFormat::Json => {
64 serde_json::to_string(resource)
65 .map(|serialized_resource| serialized_resource.into_bytes())
66 .map_err(|error| {
67 log::error!("failed to serialize {} to JSON\n\n{}", name, error);
68 PersistenceError::JsonSerialization(error)
69 })
70 },
71 #[cfg(all(feature = "json", feature = "pretty"))]
72 StorageFormat::JsonPretty => {
73 serde_json::to_string_pretty(resource)
74 .map(|serialized_resource| serialized_resource.into_bytes())
75 .map_err(|error| {
76 log::error!("failed to serialize {} to pretty JSON\n\n{}", name, error);
77 PersistenceError::JsonSerialization(error)
78 })
79 },
80 #[cfg(feature = "ron")]
81 StorageFormat::Ron => {
82 ron::to_string(resource)
83 .map(|serialized_resource| serialized_resource.into_bytes())
84 .map_err(|error| {
85 log::error!("failed to serialize {} to RON\n\n{}", name, error);
86 PersistenceError::RonSerialization(error)
87 })
88 },
89 #[cfg(all(feature = "ron", feature = "pretty"))]
90 StorageFormat::RonPretty => {
91 use ron::ser::PrettyConfig;
92 ron::ser::to_string_pretty(resource, PrettyConfig::new().struct_names(false))
93 .map(|serialized_resource| serialized_resource.into_bytes())
94 .map_err(|error| {
95 log::error!("failed to serialize {} to pretty RON\n\n{}", name, error);
96 PersistenceError::RonSerialization(error)
97 })
98 },
99 #[cfg(all(feature = "ron", feature = "pretty"))]
100 StorageFormat::RonPrettyWithStructNames => {
101 use ron::ser::PrettyConfig;
102 ron::ser::to_string_pretty(resource, PrettyConfig::new().struct_names(true))
103 .map(|serialized_resource| serialized_resource.into_bytes())
104 .map_err(|error| {
105 log::error!(
106 "failed to serialize {} to pretty RON with struct names\n\n{}",
107 name,
108 error,
109 );
110 PersistenceError::RonSerialization(error)
111 })
112 },
113 #[cfg(feature = "toml")]
114 StorageFormat::Toml => {
115 toml::to_string(resource)
116 .map(|serialized_resource| serialized_resource.into_bytes())
117 .map_err(|error| {
118 log::error!("failed to serialize {} to TOML\n\n{}", name, error);
119 PersistenceError::TomlSerialization(error)
120 })
121 },
122 #[cfg(all(feature = "toml", feature = "pretty"))]
123 StorageFormat::TomlPretty => {
124 toml::to_string(resource)
125 .map(|serialized_resource| serialized_resource.into_bytes())
126 .map_err(|error| {
127 log::error!("failed to serialize {} to pretty TOML\n\n{}", name, error);
128 PersistenceError::TomlSerialization(error)
129 })
130 },
131 #[cfg(feature = "yaml")]
132 StorageFormat::Yaml => {
133 serde_yaml::to_string(resource)
134 .map(|serialized_resource| serialized_resource.into_bytes())
135 .map_err(|error| {
136 log::error!("failed to serialize {} to YAML\n\n{}", name, error);
137 PersistenceError::YamlSerialization(error)
138 })
139 },
140 }
141 }
142
143 pub fn deserialize<R: Serialize + DeserializeOwned>(
145 self,
146 name: &str,
147 serialized_resource: &[u8],
148 ) -> Result<R, PersistenceError> {
149 #[cfg(feature = "bincode")]
150 #[allow(irrefutable_let_patterns)]
151 if let StorageFormat::Bincode = self {
152 return bincode::deserialize::<R>(serialized_resource).map_err(|error| {
153 log::error!("failed to parse {} as Bincode\n\n{}", name, error);
154 PersistenceError::BincodeDeserialization(error)
155 });
156 }
157
158 #[cfg(any(
159 feature = "ini",
160 feature = "json",
161 feature = "ron",
162 feature = "toml",
163 feature = "yaml"
164 ))]
165 let serialized_resource_str =
166 std::str::from_utf8(serialized_resource).map_err(|error| {
167 log::error!("failed to decode {} as UTF-8\n\n{}", name, error);
168 PersistenceError::Encoding(error)
169 })?;
170
171 match self {
172 #[cfg(feature = "bincode")]
173 StorageFormat::Bincode => unreachable!(),
174 #[cfg(feature = "ini")]
175 StorageFormat::Ini => {
176 serde_ini::from_str::<R>(serialized_resource_str).map_err(|error| {
177 log::error!("failed to parse {} as INI\n\n{}", name, error);
178 PersistenceError::IniDeserialization(error)
179 })
180 },
181 #[cfg(feature = "json")]
182 StorageFormat::Json => {
183 serde_json::from_str::<R>(serialized_resource_str).map_err(|error| {
184 log::error!("failed to parse {} as JSON\n\n{}", name, error);
185 PersistenceError::JsonDeserialization(error)
186 })
187 },
188 #[cfg(all(feature = "json", feature = "pretty"))]
189 StorageFormat::JsonPretty => {
190 serde_json::from_str::<R>(serialized_resource_str).map_err(|error| {
191 log::error!("failed to parse {} as pretty JSON\n\n{}", name, error);
192 PersistenceError::JsonDeserialization(error)
193 })
194 },
195 #[cfg(feature = "ron")]
196 StorageFormat::Ron => {
197 ron::from_str::<R>(serialized_resource_str).map_err(|error| {
198 log::error!("failed to parse {} as RON\n\n{}", name, error);
199 PersistenceError::RonDeserialization(error.into())
200 })
201 },
202 #[cfg(all(feature = "ron", feature = "pretty"))]
203 StorageFormat::RonPretty => {
204 ron::from_str::<R>(serialized_resource_str).map_err(|error| {
205 log::error!("failed to parse {} as pretty RON\n\n{}", name, error);
206 PersistenceError::RonDeserialization(error.into())
207 })
208 },
209 #[cfg(all(feature = "ron", feature = "pretty"))]
210 StorageFormat::RonPrettyWithStructNames => {
211 ron::from_str::<R>(serialized_resource_str).map_err(|error| {
212 log::error!(
213 "failed to parse {} as pretty RON with struct names\n\n{}",
214 name,
215 error,
216 );
217 PersistenceError::RonDeserialization(error.into())
218 })
219 },
220 #[cfg(feature = "toml")]
221 StorageFormat::Toml => {
222 toml::from_str::<R>(serialized_resource_str).map_err(|error| {
223 log::error!("failed to parse {} as TOML\n\n{}", name, error);
224 PersistenceError::TomlDeserialization(error)
225 })
226 },
227 #[cfg(all(feature = "toml", feature = "pretty"))]
228 StorageFormat::TomlPretty => {
229 toml::from_str::<R>(serialized_resource_str).map_err(|error| {
230 log::error!("failed to parse {} as pretty TOML\n\n{}", name, error);
231 PersistenceError::TomlDeserialization(error)
232 })
233 },
234 #[cfg(feature = "yaml")]
235 StorageFormat::Yaml => {
236 serde_yaml::from_str::<R>(serialized_resource_str).map_err(|error| {
237 log::error!("failed to parse {} as YAML\n\n{}", name, error);
238 PersistenceError::YamlDeserialization(error)
239 })
240 },
241 }
242 }
243}
244
245#[cfg(not(any(
246 feature = "bincode",
247 feature = "ini",
248 feature = "json",
249 feature = "ron",
250 feature = "toml",
251 feature = "yaml",
252)))]
253impl StorageFormat {
254 pub fn serialize<R: Serialize + DeserializeOwned>(
256 self,
257 _name: &str,
258 _resource: &R,
259 ) -> Result<Vec<u8>, PersistenceError> {
260 unreachable!()
261 }
262
263 pub fn deserialize<R: Serialize + DeserializeOwned>(
265 self,
266 _name: &str,
267 _serialized_resource: &[u8],
268 ) -> Result<R, PersistenceError> {
269 unreachable!()
270 }
271}