1pub mod metadata;
9pub mod settings;
10pub mod slots;
11pub mod states;
12
13use crate::projects::{
14 metadata::OsMetadata, settings::Settings, slots::SlotsAttributes, states::State,
15};
16use crate::{Decode, Encode, IsDefault, OptionEnumValueConvert, OtToolsIoErrors, RBoxErr};
17use ot_tools_io_derive::OctatrackFile;
18use serde::{Deserialize, Serialize};
19use std::cmp::PartialEq;
20use std::{collections::HashMap, fmt::Debug, str::FromStr};
21
22trait FromHashMap {
24 type A;
26
27 type B;
29
30 type T;
32
33 fn from_hashmap(hmap: &HashMap<Self::A, Self::B>) -> RBoxErr<Self::T>;
35}
36
37fn parse_hashmap_string_value<T: FromStr>(
39 hmap: &HashMap<String, String>,
40 key: &str,
41 default_str: Option<&str>,
42) -> Result<T, <T as FromStr>::Err>
43where
44 <T as FromStr>::Err: Debug,
45{
46 match default_str {
47 Some(x) => hmap.get(key).unwrap_or(&x.to_string()).parse::<T>(),
48 None => hmap.get(key).unwrap().parse::<T>(),
49 }
50}
51
52fn parse_hashmap_string_value_bool(
55 hmap: &HashMap<String, String>,
56 key: &str,
57 default_str: Option<&str>,
58) -> RBoxErr<bool> {
59 Ok(matches!(
61 parse_hashmap_string_value::<u8>(hmap, key, default_str)?,
62 1
63 ))
64}
65
66fn string_to_hashmap(
68 data: &str,
69 section: &ProjectRawFileSection,
70) -> RBoxErr<HashMap<String, String>> {
71 let start_idx: usize = data.find(§ion.start_string()?).unwrap();
72 let start_idx_shifted: usize = start_idx + section.start_string()?.len();
73 let end_idx: usize = data.find(§ion.end_string()?).unwrap();
74
75 let section: String = data[start_idx_shifted..end_idx].to_string();
76
77 let mut hmap: HashMap<String, String> = HashMap::new();
78 let mut trig_mode_midi_field_idx = 1;
79
80 for split_s in section.split("\r\n") {
81 if !split_s.is_empty() {
84 let key_pair_string = split_s.to_string();
85 let mut key_pair_split: Vec<&str> = key_pair_string.split('=').collect();
86
87 let key_renamed: String = format!("trig_mode_midi_track_{}", &trig_mode_midi_field_idx);
92 if key_pair_split[0] == "TRIG_MODE_MIDI" {
93 key_pair_split[0] = key_renamed.as_str();
94 trig_mode_midi_field_idx += 1;
95 }
96
97 hmap.insert(
98 key_pair_split[0].to_string().to_ascii_lowercase(),
99 key_pair_split[1].to_string(),
100 );
101 }
102 }
103
104 Ok(hmap)
105}
106
107#[derive(Debug, PartialEq)]
109enum ProjectRawFileSection {
110 Meta,
111 States,
112 Settings,
113 Samples,
114}
115
116impl OptionEnumValueConvert<String> for ProjectRawFileSection {
117 fn from_value(v: &String) -> RBoxErr<Self> {
118 match v.to_ascii_uppercase().as_str() {
119 "META" => Ok(Self::Meta),
120 "STATES" => Ok(Self::States),
121 "SETTINGS" => Ok(Self::Settings),
122 "SAMPLES" => Ok(Self::Samples),
123 _ => Err(OtToolsIoErrors::NoMatchingOptionEnumValue.into()),
124 }
125 }
126
127 fn value(&self) -> RBoxErr<String> {
129 match self {
130 Self::Meta => Ok("META".to_string()),
131 Self::States => Ok("STATES".to_string()),
132 Self::Settings => Ok("SETTINGS".to_string()),
133 Self::Samples => Ok("SAMPLES".to_string()),
134 }
135 }
136}
137
138impl ProjectRawFileSection {
139 fn start_string(&self) -> RBoxErr<String> {
140 Ok(format!("[{}]", self.value()?))
141 }
142 fn end_string(&self) -> RBoxErr<String> {
143 Ok(format!("[/{}]", self.value()?))
144 }
145}
146
147#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, OctatrackFile)]
161pub struct ProjectFile {
162 pub metadata: OsMetadata,
164
165 pub settings: Settings,
167
168 pub states: State,
170
171 pub slots: SlotsAttributes,
173}
174
175impl Default for ProjectFile {
176 fn default() -> Self {
177 let metadata = OsMetadata::default();
178 let states = State::default();
179 let settings = Settings::default();
180 let slots = SlotsAttributes::default();
181
182 ProjectFile {
183 metadata,
184 settings,
185 states,
186 slots,
187 }
188 }
189}
190
191impl IsDefault for ProjectFile {
192 fn is_default(&self) -> bool {
193 &ProjectFile::default() == self
194 }
195}
196
197impl std::fmt::Display for ProjectFile {
198 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
199 let states_header =
200 "############################\r\n# Project States\r\n############################"
201 .to_string();
202 let settings_header =
203 "############################\r\n# Project Settings\r\n############################"
204 .to_string();
205 let slots_header =
206 "############################\r\n# Samples\r\n############################".to_string();
207 let footer = "############################".to_string();
208
209 let metadata_string: String = self.metadata.to_string();
210 let states_string: String = self.states.to_string();
211 let settings_string: String = self.settings.to_string();
212
213 let sample_slots_string = self.slots.to_string();
214
215 let v: Vec<String> = vec![
216 settings_header,
219 metadata_string,
220 settings_string,
221 states_header,
222 states_string,
223 slots_header,
224 sample_slots_string,
225 footer,
226 ];
227 let mut project_string = v.join("\r\n\r\n");
228 project_string.push_str("\r\n\r\n");
229
230 write!(f, "{project_string}")
231 }
232}
233
234impl Decode for ProjectFile {
237 fn decode(bytes: &[u8]) -> RBoxErr<Self> {
238 let s = std::str::from_utf8(bytes)?.to_string();
239
240 let metadata = OsMetadata::from_str(&s)?;
241 let states = State::from_str(&s)?;
242 let settings = Settings::from_str(&s)?;
243 let slots = SlotsAttributes::from_str(&s)?;
244
245 Ok(Self {
246 metadata,
247 settings,
248 states,
249 slots,
250 })
251 }
252}
253
254impl Encode for ProjectFile {
256 fn encode(&self) -> RBoxErr<Vec<u8>> {
257 let data = self.to_string();
258 let bytes: Vec<u8> = data.bytes().collect::<Vec<u8>>();
259 Ok(bytes)
260 }
261}
262
263#[cfg(test)]
264#[allow(unused_imports)]
265mod tests {
266 use super::*;
267
268 const DEFAULT_STR_FILE: &str = "############################\r\n# Project Settings\r\n############################\r\n\r\n[META]\r\nTYPE=OCTATRACK DPS-1 PROJECT\r\nVERSION=19\r\nOS_VERSION=R0177 1.40B\r\n[/META]\r\n\r\n[SETTINGS]\r\nWRITEPROTECTED=0\r\nTEMPOx24=2880\r\nPATTERN_TEMPO_ENABLED=0\r\nMIDI_CLOCK_SEND=0\r\nMIDI_CLOCK_RECEIVE=0\r\nMIDI_TRANSPORT_SEND=0\r\nMIDI_TRANSPORT_RECEIVE=0\r\nMIDI_PROGRAM_CHANGE_SEND=0\r\nMIDI_PROGRAM_CHANGE_SEND_CH=-1\r\nMIDI_PROGRAM_CHANGE_RECEIVE=0\r\nMIDI_PROGRAM_CHANGE_RECEIVE_CH=-1\r\nMIDI_TRIG_CH1=0\r\nMIDI_TRIG_CH2=1\r\nMIDI_TRIG_CH3=2\r\nMIDI_TRIG_CH4=3\r\nMIDI_TRIG_CH5=4\r\nMIDI_TRIG_CH6=5\r\nMIDI_TRIG_CH7=6\r\nMIDI_TRIG_CH8=7\r\nMIDI_AUTO_CHANNEL=10\r\nMIDI_SOFT_THRU=0\r\nMIDI_AUDIO_TRK_CC_IN=1\r\nMIDI_AUDIO_TRK_CC_OUT=3\r\nMIDI_AUDIO_TRK_NOTE_IN=1\r\nMIDI_AUDIO_TRK_NOTE_OUT=3\r\nMIDI_MIDI_TRK_CC_IN=1\r\nPATTERN_CHANGE_CHAIN_BEHAVIOR=0\r\nPATTERN_CHANGE_AUTO_SILENCE_TRACKS=0\r\nPATTERN_CHANGE_AUTO_TRIG_LFOS=0\r\nLOAD_24BIT_FLEX=0\r\nDYNAMIC_RECORDERS=0\r\nRECORD_24BIT=0\r\nRESERVED_RECORDER_COUNT=8\r\nRESERVED_RECORDER_LENGTH=16\r\nINPUT_DELAY_COMPENSATION=0\r\nGATE_AB=127\r\nGATE_CD=127\r\nGAIN_AB=64\r\nGAIN_CD=64\r\nDIR_AB=0\r\nDIR_CD=0\r\nPHONES_MIX=64\r\nMAIN_TO_CUE=0\r\nMASTER_TRACK=0\r\nCUE_STUDIO_MODE=0\r\nMAIN_LEVEL=64\r\nCUE_LEVEL=64\r\nMETRONOME_TIME_SIGNATURE=3\r\nMETRONOME_TIME_SIGNATURE_DENOMINATOR=2\r\nMETRONOME_PREROLL=0\r\nMETRONOME_CUE_VOLUME=32\r\nMETRONOME_MAIN_VOLUME=0\r\nMETRONOME_PITCH=12\r\nMETRONOME_TONAL=1\r\nMETRONOME_ENABLED=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\n[/SETTINGS]\r\n\r\n############################\r\n# Project States\r\n############################\r\n\r\n[STATES]\r\nBANK=0\r\nPATTERN=0\r\nARRANGEMENT=0\r\nARRANGEMENT_MODE=0\r\nPART=0\r\nTRACK=0\r\nTRACK_OTHERMODE=0\r\nSCENE_A_MUTE=0\r\nSCENE_B_MUTE=0\r\nTRACK_CUE_MASK=0\r\nTRACK_MUTE_MASK=0\r\nTRACK_SOLO_MASK=0\r\nMIDI_TRACK_MUTE_MASK=0\r\nMIDI_TRACK_SOLO_MASK=0\r\nMIDI_MODE=0\r\n[/STATES]\r\n\r\n############################\r\n# Samples\r\n############################\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=129\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=130\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=131\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=132\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=133\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=134\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=135\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=136\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n############################\r\n\r\n";
269 const DEFAULT_STR_META: &str = "[META]\r\nTYPE=OCTATRACK DPS-1 PROJECT\r\nVERSION=19\r\nOS_VERSION=R0177 1.40B\r\n[/META]";
270 const DEFAULT_STR_STATE: &str = "[STATES]\r\nBANK=0\r\nPATTERN=0\r\nARRANGEMENT=0\r\nARRANGEMENT_MODE=0\r\nPART=0\r\nTRACK=0\r\nTRACK_OTHERMODE=0\r\nSCENE_A_MUTE=0\r\nSCENE_B_MUTE=0\r\nTRACK_CUE_MASK=0\r\nTRACK_MUTE_MASK=0\r\nTRACK_SOLO_MASK=0\r\nMIDI_TRACK_MUTE_MASK=0\r\nMIDI_TRACK_SOLO_MASK=0\r\nMIDI_MODE=0\r\n[/STATES]";
271 const DEFAULT_STR_SETTINGS: &str = "[SETTINGS]\r\nWRITEPROTECTED=0\r\nTEMPOx24=2880\r\nPATTERN_TEMPO_ENABLED=0\r\nMIDI_CLOCK_SEND=0\r\nMIDI_CLOCK_RECEIVE=0\r\nMIDI_TRANSPORT_SEND=0\r\nMIDI_TRANSPORT_RECEIVE=0\r\nMIDI_PROGRAM_CHANGE_SEND=0\r\nMIDI_PROGRAM_CHANGE_SEND_CH=-1\r\nMIDI_PROGRAM_CHANGE_RECEIVE=0\r\nMIDI_PROGRAM_CHANGE_RECEIVE_CH=-1\r\nMIDI_TRIG_CH1=0\r\nMIDI_TRIG_CH2=1\r\nMIDI_TRIG_CH3=2\r\nMIDI_TRIG_CH4=3\r\nMIDI_TRIG_CH5=4\r\nMIDI_TRIG_CH6=5\r\nMIDI_TRIG_CH7=6\r\nMIDI_TRIG_CH8=7\r\nMIDI_AUTO_CHANNEL=10\r\nMIDI_SOFT_THRU=0\r\nMIDI_AUDIO_TRK_CC_IN=1\r\nMIDI_AUDIO_TRK_CC_OUT=3\r\nMIDI_AUDIO_TRK_NOTE_IN=1\r\nMIDI_AUDIO_TRK_NOTE_OUT=3\r\nMIDI_MIDI_TRK_CC_IN=1\r\nPATTERN_CHANGE_CHAIN_BEHAVIOR=0\r\nPATTERN_CHANGE_AUTO_SILENCE_TRACKS=0\r\nPATTERN_CHANGE_AUTO_TRIG_LFOS=0\r\nLOAD_24BIT_FLEX=0\r\nDYNAMIC_RECORDERS=0\r\nRECORD_24BIT=0\r\nRESERVED_RECORDER_COUNT=8\r\nRESERVED_RECORDER_LENGTH=16\r\nINPUT_DELAY_COMPENSATION=0\r\nGATE_AB=127\r\nGATE_CD=127\r\nGAIN_AB=64\r\nGAIN_CD=64\r\nDIR_AB=0\r\nDIR_CD=0\r\nPHONES_MIX=64\r\nMAIN_TO_CUE=0\r\nMASTER_TRACK=0\r\nCUE_STUDIO_MODE=0\r\nMAIN_LEVEL=64\r\nCUE_LEVEL=64\r\nMETRONOME_TIME_SIGNATURE=3\r\nMETRONOME_TIME_SIGNATURE_DENOMINATOR=2\r\nMETRONOME_PREROLL=0\r\nMETRONOME_CUE_VOLUME=32\r\nMETRONOME_MAIN_VOLUME=0\r\nMETRONOME_PITCH=12\r\nMETRONOME_TONAL=1\r\nMETRONOME_ENABLED=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\n[/SETTINGS]";
272 const DEFAULT_STR_SLOTS: &str = "[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=129\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=130\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=131\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=132\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=133\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=134\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=135\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]\r\n\r\n[SAMPLE]\r\nTYPE=FLEX\r\nSLOT=136\r\nPATH=\r\nBPMx24=2880\r\nTSMODE=2\r\nLOOPMODE=0\r\nGAIN=72\r\nTRIGQUANTIZATION=255\r\n[/SAMPLE]";
273
274 mod test_spec {
275 use super::*;
276
277 #[test]
278 fn section_heading_from_value_no_match_is_err() {
279 assert!(ProjectRawFileSection::from_value(&"skfsdkfjskdh".to_string()).is_err())
280 }
281
282 #[test]
283 fn section_heading_from_value_uppercase_meta() {
284 assert_eq!(
285 ProjectRawFileSection::from_value(&"META".to_string()).unwrap(),
286 ProjectRawFileSection::Meta,
287 )
288 }
289
290 #[test]
291 fn section_heading_from_value_uppercase_states() {
292 assert_eq!(
293 ProjectRawFileSection::from_value(&"STATES".to_string()).unwrap(),
294 ProjectRawFileSection::States,
295 )
296 }
297
298 #[test]
299 fn section_heading_from_value_uppercase_settings() {
300 assert_eq!(
301 ProjectRawFileSection::from_value(&"SETTINGS".to_string()).unwrap(),
302 ProjectRawFileSection::Settings,
303 )
304 }
305
306 #[test]
307 fn section_heading_from_value_uppercase_samples() {
308 assert_eq!(
309 ProjectRawFileSection::from_value(&"SAMPLES".to_string()).unwrap(),
310 ProjectRawFileSection::Samples,
311 )
312 }
313
314 #[test]
315 fn section_heading_from_value_lowercase_meta() {
316 assert_eq!(
317 ProjectRawFileSection::from_value(&"meta".to_string()).unwrap(),
318 ProjectRawFileSection::Meta,
319 )
320 }
321
322 #[test]
323 fn section_heading_from_value_lowercase_states() {
324 assert_eq!(
325 ProjectRawFileSection::from_value(&"states".to_string()).unwrap(),
326 ProjectRawFileSection::States,
327 )
328 }
329
330 #[test]
331 fn section_heading_from_value_lowercase_settings() {
332 assert_eq!(
333 ProjectRawFileSection::from_value(&"settings".to_string()).unwrap(),
334 ProjectRawFileSection::Settings,
335 )
336 }
337
338 #[test]
339 fn section_heading_from_value_lowercase_samples() {
340 assert_eq!(
341 ProjectRawFileSection::from_value(&"samples".to_string()).unwrap(),
342 ProjectRawFileSection::Samples,
343 )
344 }
345
346 #[test]
347 fn section_heading_value_meta() {
348 assert_eq!(
349 ProjectRawFileSection::Meta.value().unwrap(),
350 "META".to_string(),
351 )
352 }
353
354 #[test]
355 fn section_heading_value_states() {
356 assert_eq!(
357 ProjectRawFileSection::States.value().unwrap(),
358 "STATES".to_string(),
359 )
360 }
361
362 #[test]
363 fn section_heading_value_settings() {
364 assert_eq!(
365 ProjectRawFileSection::Settings.value().unwrap(),
366 "SETTINGS".to_string(),
367 )
368 }
369
370 #[test]
371 fn section_heading_value_samples() {
372 assert_eq!(
373 ProjectRawFileSection::Samples.value().unwrap(),
374 "SAMPLES".to_string(),
375 )
376 }
377 }
378
379 mod test_to_string_display {
382 use super::*;
383
384 #[test]
385 fn test_full_to_string() {
386 assert_eq!(ProjectFile::default().to_string(), DEFAULT_STR_FILE);
387 assert_eq!(format!["{:#}", ProjectFile::default()], DEFAULT_STR_FILE);
388 }
389
390 #[test]
391 fn test_metadata_to_string() {
392 assert_eq!(OsMetadata::default().to_string(), DEFAULT_STR_META);
393 assert_eq!(format!["{:#}", OsMetadata::default()], DEFAULT_STR_META);
394 }
395
396 #[test]
397 fn test_states_to_string() {
398 assert_eq!(State::default().to_string(), DEFAULT_STR_STATE);
399 assert_eq!(format!["{:#}", State::default()], DEFAULT_STR_STATE);
400 }
401
402 #[test]
403 fn test_settings_to_string() {
404 assert_eq!(Settings::default().to_string(), DEFAULT_STR_SETTINGS);
405 assert_eq!(format!["{:#}", Settings::default()], DEFAULT_STR_SETTINGS);
406 }
407
408 #[test]
409 fn test_sample_slots_to_string() {
410 assert_eq!(SlotsAttributes::default().to_string(), DEFAULT_STR_SLOTS);
411 assert_eq!(
412 format!["{:#}", SlotsAttributes::default()],
413 DEFAULT_STR_SLOTS
414 );
415 }
416 }
417
418 mod test_to_string_debug {
420 use super::*;
421
422 #[test]
423 fn test_full_to_string() {
424 assert_ne!(
425 format!["{:#?}", ProjectFile::default()],
426 DEFAULT_STR_FILE,
427 "debug formatting should not be 'file' representation",
428 );
429 }
430
431 #[test]
432 fn test_metadata_to_string() {
433 assert_ne!(
434 format!["{:#?}", OsMetadata::default().to_string()],
435 DEFAULT_STR_META,
436 "debug formatting should not be 'file' representation",
437 );
438 }
439
440 #[test]
441 fn test_states_to_string() {
442 assert_ne!(
443 format!["{:#?}", State::default().to_string()],
444 DEFAULT_STR_STATE,
445 "debug formatting should not be 'file' representation",
446 );
447 }
448
449 #[test]
450 fn test_settings_to_string() {
451 assert_ne!(
452 format!["{:#?}", Settings::default().to_string()],
453 DEFAULT_STR_SETTINGS,
454 "debug formatting should not be 'file' representation",
455 );
456 }
457
458 #[test]
459 fn test_sample_slots_to_string() {
460 assert_ne!(
461 format!["{:#?}", SlotsAttributes::default().to_string()],
462 DEFAULT_STR_SLOTS,
463 "debug formatting should not be 'file' representation",
464 );
465 }
466 }
467}