open_archery_format/
session.rs

1use std::fs::File;
2use std::hash::{Hash, Hasher};
3use std::io::{self, Read, Write};
4// structs should implement the Binary trait
5use crate::buffer::{Buffer, BufferError};
6
7trait Serialisable<T> {
8    /// Returns a Buffer containing self as bytes
9    fn serialise(&self) -> Result<Buffer, BufferError>;
10    /// Returns a copy of self built from the bytes in the provided Buffer
11    fn deserialise(data: &mut Buffer) -> Result<T, BufferError>;
12}
13
14#[derive(Debug, PartialEq)]
15pub struct Session {
16    pub date: String,
17    pub location: String,
18    // pub bow: Bow,
19    // pub archer: Archer,
20    pub rounds: Vec<Round>,
21}
22
23#[derive(Debug)]
24pub enum FileError {
25    BufferError(BufferError),
26    IOError(io::Error),
27}
28
29impl From<BufferError> for FileError {
30    fn from(err: BufferError) -> Self {
31        Self::BufferError(err)
32    }
33}
34
35impl From<io::Error> for FileError {
36    fn from(err: io::Error) -> Self {
37        Self::IOError(err)
38    }
39}
40
41impl Session {
42    pub fn encode(&self, filename: String) -> Result<(), FileError> {
43        let mut res = Buffer::new();
44
45        // Magic bytes: 4F 41 46 46 (OAFF)
46        res.append_u8(0x4f); // O
47        res.append_u8(0x41); // A
48        res.append_u8(0x46); // F
49        res.append_u8(0x46); // F
50
51        // Version: 0.1.0
52        res.append_u8(0); // 0
53        res.append_u8(1); // 1
54        res.append_u8(0); // 0
55
56        let mut data = self.serialise()?;
57
58        res.append_u64(data.length() as u64);
59        res.append(&mut data);
60
61        let mut f = File::create(filename)?;
62        Ok(f.write_all(res.take_underlying_buffer().as_slice())?)
63    }
64
65    pub fn decode(filename: String) -> Result<Self, FileError> {
66        let mut f = File::open(filename)?;
67
68        let mut data = vec![];
69
70        f.read_to_end(&mut data)?;
71
72        let mut buf = Buffer::from(data);
73        buf.pop_n_bytes(4)?;
74
75        let v1 = buf.pop_u8()?;
76        let v2 = buf.pop_u8()?;
77        let v3 = buf.pop_u8()?;
78
79        println!("Encoded with v{v1}.{v2}.{v3}");
80
81        println!("Session has length {:?}", buf.pop_u64()?);
82
83        Ok(Session::deserialise(&mut buf)?)
84    }
85}
86
87impl Serialisable<Session> for Session {
88    fn serialise(&self) -> Result<Buffer, BufferError> {
89        let mut res = Buffer::new();
90
91        res.append_string(&self.date)?;
92
93        res.append_string(&self.location)?;
94
95        res.append_usize(self.rounds.len())?;
96        for round in &self.rounds {
97            res.append(&mut round.serialise()?);
98        }
99
100        Ok(res)
101    }
102
103    fn deserialise(data: &mut Buffer) -> Result<Self, BufferError> {
104        let date = data.pop_string()?;
105        let location = data.pop_string()?;
106
107        let mut rounds = vec![];
108        let read = data.pop_usize()?;
109
110        for _ in 0..read {
111            rounds.push(Round::deserialise(data)?);
112        }
113
114        Ok(Session {
115            date,
116            location,
117            rounds,
118        })
119    }
120}
121
122#[derive(Debug, PartialEq)]
123pub struct Round {
124    pub name: String,
125    pub targets: Vec<Target>,
126}
127
128impl Serialisable<Round> for Round {
129    fn serialise(&self) -> Result<Buffer, BufferError> {
130        let mut res = Buffer::new();
131
132        res.append_string(&self.name)?;
133
134        res.append_usize(self.targets.len())?;
135        for target in &self.targets {
136            res.append(&mut target.serialise()?);
137        }
138
139        Ok(res)
140    }
141
142    fn deserialise(data: &mut Buffer) -> Result<Self, BufferError> {
143        let name = data.pop_string()?;
144
145        let mut targets = vec![];
146        let read = data.pop_usize()?;
147
148        for _ in 0..read {
149            targets.push(Target::deserialise(data)?);
150        }
151
152        Ok(Round {
153            name,
154            targets,
155        })
156    }
157}
158
159#[derive(Debug, PartialEq)]
160pub struct Target {
161    pub name: String,
162    pub distance: u32,
163    pub distance_unit: String,
164    pub face_size: u32,
165    pub face_size_unit: String,
166    pub inclination: u32,
167    pub ends: Vec<End>,
168}
169
170impl Serialisable<Target> for Target {
171    fn serialise(&self) -> Result<Buffer, BufferError> {
172        let mut res = Buffer::new();
173
174        res.append_string(&self.name)?;
175
176        res.append_u32(self.distance);
177        res.append_string(&self.distance_unit)?;
178
179        res.append_u32(self.face_size);
180        res.append_string(&self.face_size_unit)?;
181
182        res.append_u32(self.inclination);
183
184        res.append_usize(self.ends.len())?;
185        for end in &self.ends {
186            res.append(&mut end.serialise()?);
187        }
188
189        Ok(res)
190    }
191
192    fn deserialise(data: &mut Buffer) -> Result<Self, BufferError> {
193        let name = data.pop_string()?;
194
195        let dist = data.pop_u32()?;
196        let dist_unit = data.pop_string()?;
197
198        let face = data.pop_u32()?;
199        let face_unit = data.pop_string()?;
200
201        let inclination = data.pop_u32()?;
202
203        let mut ends = vec![];
204        let read = data.pop_usize()?;
205
206        for _ in 0..read {
207            ends.push(End::deserialise(data)?);
208        }
209
210        Ok(Target {
211            name,
212            distance: dist,
213            distance_unit: dist_unit,
214            face_size: face,
215            face_size_unit: face_unit,
216            inclination,
217            ends,
218        })
219    }
220}
221
222#[derive(Debug, PartialEq)]
223pub enum End {
224    Scored(Vec<ValueScore>),
225    Measured(Vec<MeasuredScore>),
226    Blank(u32),
227    ShotTrainer(u32),
228    BareShaft(Vec<BareShaft>),
229    BowDraws(u32),
230}
231
232impl Serialisable<End> for End {
233    fn serialise(&self) -> Result<Buffer, BufferError> {
234        Ok(match self {
235            End::Scored(scores) => {
236                let mut res = Buffer::from(vec![0]);
237
238                res.append_usize(scores.len())?;
239                for score in scores {
240                    res.append(&mut score.serialise()?);
241                }
242
243                res
244            },
245            End::Measured(scores) => {
246                let mut res = Buffer::from(vec![1]);
247
248                res.append_usize(scores.len())?;
249                for score in scores {
250                    res.append(&mut score.serialise()?);
251                }
252
253                res
254            },
255            End::Blank(count) => {
256                let mut res = Buffer::from(vec![2]);
257
258                res.append_u32(*count);
259
260                res
261            },
262            End::ShotTrainer(count) => {
263                let mut res = Buffer::from(vec![3]);
264
265                res.append_u32(*count);
266
267                res
268            },
269            End::BareShaft(scores) => {
270                let mut res = Buffer::from(vec![4]);
271
272                res.append_usize(scores.len())?;
273                for score in scores {
274                    res.append(&mut score.serialise()?);
275                }
276
277                res
278            },
279            End::BowDraws(count) => {
280                let mut res = Buffer::from(vec![5]);
281
282                res.append_u32(*count);
283
284                res
285            },
286        })
287    }
288
289    fn deserialise(data: &mut Buffer) -> Result<Self, BufferError> {
290        let t = data.pop_u8()?;
291        Ok(match t {
292            0 => {
293                let mut scores = vec![];
294                let read = data.pop_usize()?;
295
296                for _ in 0..read {
297                    let s = ValueScore::deserialise(data)?;
298                    scores.push(s);
299                }
300
301                End::Scored(scores)
302            },
303            1 => {
304                let mut scores = vec![];
305                let read = data.pop_usize()?;
306
307                for _ in 0..read {
308                    let s = MeasuredScore::deserialise(data)?;
309                    scores.push(s);
310                }
311
312                End::Measured(scores)
313            },
314            2 => {
315                End::Blank(data.pop_u32()?)
316            },
317            3 => {
318                End::ShotTrainer(data.pop_u32()?)
319            },
320            4 => {
321                let mut scores = vec![];
322                let read = data.pop_usize()?;
323
324                for _ in 0..read {
325                    let s = BareShaft::deserialise(data)?;
326                    scores.push(s);
327                }
328
329                End::BareShaft(scores)
330            },
331            5 => {
332                End::BowDraws(data.pop_u32()?)
333            },
334            other => {
335                panic!("unknown end type: {}", other)
336            }
337        })
338    }
339}
340
341#[derive(Debug, PartialEq)]
342pub struct ValueScore {
343    pub value: u8,
344    pub value_name: String,
345}
346
347#[derive(Debug, PartialEq)]
348pub struct MeasuredScore {
349    pub value: u8,
350    pub value_name: String,
351    pub r: u32,
352    pub theta: u32,
353}
354
355#[derive(Debug, PartialEq)]
356pub struct BareShaft {
357    pub r: u32,
358    pub theta: u32,
359}
360
361impl Serialisable<ValueScore> for ValueScore {
362    fn serialise(&self) -> Result<Buffer, BufferError> {
363        let mut res = Buffer::from(vec![self.value]);
364
365        res.append_string(&self.value_name)?;
366
367        Ok(res)
368    }
369
370    fn deserialise(data: &mut Buffer) -> Result<Self, BufferError> {
371        Ok(Self {
372            value: data.pop_u8()?,
373            value_name: data.pop_string()?,
374        })
375    }
376}
377
378impl Serialisable<MeasuredScore> for MeasuredScore {
379    fn serialise(&self) -> Result<Buffer, BufferError> {
380        let mut res = Buffer::from(vec![self.value]);
381
382        res.append_string(&self.value_name)?;
383
384        res.append_u32(self.r);
385        res.append_u32(self.theta);
386
387        Ok(res)
388    }
389
390    fn deserialise(data: &mut Buffer) -> Result<Self, BufferError> {
391        Ok(Self {
392            value: data.pop_u8()?,
393            value_name: data.pop_string()?,
394            r: data.pop_u32()?,
395            theta: data.pop_u32()?,
396        })
397    }
398}
399
400impl Serialisable<BareShaft> for BareShaft {
401    fn serialise(&self) -> Result<Buffer, BufferError> {
402        let mut res = Buffer::from(vec![]);
403
404        res.append_u32(self.r);
405        res.append_u32(self.theta);
406
407        Ok(res)
408    }
409
410    fn deserialise(data: &mut Buffer) -> Result<Self, BufferError> {
411        Ok(Self {
412            r: data.pop_u32()?,
413            theta: data.pop_u32()?,
414        })
415    }
416}
417
418
419#[cfg(test)]
420mod tests {
421    use super::*;
422
423    #[test]
424    fn test_files() {
425        let s = Session {
426            date: "2024-01-02".to_string(),
427            location: "Home".to_string(),
428            rounds: vec![
429                Round {
430                    name: "Portsmouth".to_string(),
431                    targets: vec![
432                        Target {
433                            name: "WA 60cm Indoor".to_string(),
434                            distance: 18,
435                            distance_unit: "m".to_string(),
436                            face_size: 60,
437                            face_size_unit: "cm".to_string(),
438                            inclination: 0,
439                            ends: vec![
440                                End::Scored(vec![
441                                    ValueScore {
442                                        value: 10,
443                                        value_name: "ten".to_string(),
444                                    },
445                                    ValueScore {
446                                        value: 10,
447                                        value_name: "ten".to_string(),
448                                    },
449                                    ValueScore {
450                                        value: 10,
451                                        value_name: "ten".to_string(),
452                                    },
453                                ])
454                            ],
455                        }
456                    ],
457                }
458            ],
459        };
460
461        s.encode("tmp.oaf".to_string()).unwrap();
462
463        let decoded_s = Session::decode("tmp.oaf".to_string()).unwrap();
464
465        assert_eq!(s, decoded_s)
466    }
467
468    #[test]
469    fn test_full() {
470        let s = Session {
471            date: "4/12/2023".to_string(),
472            location: "St Andrews".to_string(),
473            rounds: vec![
474                Round {
475                    name: "Portsmouth".to_string(),
476                    targets: vec![
477                        Target {
478                            name: "WA 60cm Indoor".to_string(),
479                            distance: 18,
480                            distance_unit: "m".to_string(),
481                            face_size: 60,
482                            face_size_unit: "cm".to_string(),
483                            inclination: 0,
484                            ends: vec![
485                                End::Scored(vec![
486                                    ValueScore {
487                                        value: 10,
488                                        value_name: "10".to_string(),
489                                    },
490                                    ValueScore {
491                                        value: 10,
492                                        value_name: "10".to_string(),
493                                    },
494                                    ValueScore {
495                                        value: 9,
496                                        value_name: "9".to_string(),
497                                    }
498                                ]),
499                                End::Scored(vec![
500                                    ValueScore {
501                                        value: 10,
502                                        value_name: "10".to_string(),
503                                    },
504                                    ValueScore {
505                                        value: 9,
506                                        value_name: "9".to_string(),
507                                    },
508                                    ValueScore {
509                                        value: 9,
510                                        value_name: "9".to_string(),
511                                    }
512                                ])
513                            ],
514                        }
515                    ],
516                }
517            ],
518        };
519
520        assert_eq!(s, Session::deserialise(&mut s.serialise().unwrap()).unwrap())
521    }
522
523    #[test]
524    fn test_measured_score_serialise() {
525        let data = MeasuredScore {
526            value: 7,
527            value_name: "seven".to_string(),
528            r: 255,
529            theta: 6000,
530        }.serialise().unwrap();
531        assert_eq!(
532            data,
533            vec![7, 5, 0, 115, 101, 118, 101, 110, 255, 0, 0, 0, 112, 23, 0, 0]
534        )
535    }
536
537    #[test]
538    fn test_measured_score_deserialise() {
539        let data = MeasuredScore::deserialise(&mut Buffer::from(vec![7, 5, 0, 115, 101, 118, 101, 110, 255, 0, 0, 0, 112, 23, 0, 0])).unwrap();
540        let s = MeasuredScore {
541            value: 7,
542            value_name: "seven".to_string(),
543            r: 255,
544            theta: 6000,
545        };
546        assert_eq!(
547            data,
548            s,
549        )
550    }
551
552    #[test]
553    fn test_value_score_serialise() {
554        let data = ValueScore {
555            value: 7,
556            value_name: "seven".to_string(),
557        }.serialise().unwrap();
558        assert_eq!(
559            data,
560            vec![7, 5, 0, 115, 101, 118, 101, 110]
561        )
562    }
563
564    #[test]
565    fn test_value_score_deserialise() {
566        let data = ValueScore::deserialise(&mut Buffer::from(vec![7, 5, 0, 115, 101, 118, 101, 110])).unwrap();
567        let s = ValueScore {
568            value: 7,
569            value_name: "seven".to_string(),
570        };
571        assert_eq!(
572            data,
573            s,
574        )
575    }
576
577    #[test]
578    fn test_measured_end_serialise() {
579        let data = End::Measured( vec![
580            MeasuredScore {
581                value: 7,
582                value_name: "seven".to_string(),
583                r: 255,
584                theta: 6000,
585            },
586            MeasuredScore {
587                value: 6,
588                value_name: "six".to_string(),
589                r: 1000,
590                theta: 3000,
591            },
592            MeasuredScore {
593                value: 5,
594                value_name: "five".to_string(),
595                r: 1500,
596                theta: 50,
597            }
598        ] ).serialise().unwrap();
599        assert_eq!(
600            data,
601            vec![1, 3, 0,
602                7, 5, 0, 115, 101, 118, 101, 110, 255, 0, 0, 0, 112, 23, 0, 0,
603                6, 3, 0, 115, 105, 120, 232, 3, 0, 0, 184, 11, 0, 0,
604                5, 4, 0, 102, 105, 118, 101, 220, 5, 0, 0, 50, 0, 0, 0,
605            ]
606        )
607    }
608
609    #[test]
610    fn test_measured_end_deserialise() {
611        let data = End::deserialise(
612            &mut Buffer::from(
613                vec![1, 3, 0,
614                        7, 5, 0, 115, 101, 118, 101, 110, 255, 0, 0, 0, 112, 23, 0, 0,
615                        6, 3, 0, 115, 105, 120, 232, 3, 0, 0, 184, 11, 0, 0,
616                        5, 4, 0, 102, 105, 118, 101, 220, 5, 0, 0, 50, 0, 0, 0,
617                ]
618            )).unwrap();
619        let s = End::Measured( vec![
620            MeasuredScore {
621                value: 7,
622                value_name: "seven".to_string(),
623                r: 255,
624                theta: 6000,
625            },
626            MeasuredScore {
627                value: 6,
628                value_name: "six".to_string(),
629                r: 1000,
630                theta: 3000,
631            },
632            MeasuredScore {
633                value: 5,
634                value_name: "five".to_string(),
635                r: 1500,
636                theta: 50,
637            }
638        ] );
639        assert_eq!(
640            data,
641            s,
642        )
643    }
644    #[test]
645    fn test_value_end_serialise() {
646        let data = End::Scored( vec![
647            ValueScore {
648                value: 7,
649                value_name: "seven".to_string(),
650            },
651            ValueScore {
652                value: 6,
653                value_name: "six".to_string(),
654            },
655            ValueScore {
656                value: 5,
657                value_name: "five".to_string(),
658            }
659        ] ).serialise().unwrap();
660        assert_eq!(
661            data,
662            vec![0, 3, 0,
663                7, 5, 0, 115, 101, 118, 101, 110,
664                6, 3, 0, 115, 105, 120,
665                5, 4, 0, 102, 105, 118, 101,
666            ]
667        )
668    }
669
670    #[test]
671    fn test_value_end_deserialise() {
672        let data = End::deserialise(
673            &mut Buffer::from(
674                vec![0, 3, 0,
675                        7, 5, 0, 115, 101, 118, 101, 110,
676                        6, 3, 0, 115, 105, 120,
677                        5, 4, 0, 102, 105, 118, 101,
678                ]
679            )).unwrap();
680        let s = End::Scored( vec![
681            ValueScore {
682                value: 7,
683                value_name: "seven".to_string(),
684            },
685            ValueScore {
686                value: 6,
687                value_name: "six".to_string(),
688            },
689            ValueScore {
690                value: 5,
691                value_name: "five".to_string(),
692            }
693        ] );
694        assert_eq!(
695            data,
696            s,
697        )
698    }
699}