/* persist-derive.rs * * Developed by Tim Walls * Copyright (c) All Rights Reserved, Tim Walls */ // Imports =================================================================== use oxide_macros::Persist; use avr_oxide::util::persist::Persist; // Declarations ============================================================== #[derive(Persist)] struct EmptyStruct {} #[derive(Persist)] struct StructWithFourElements { one: u8, two: u16, three: u32, four: usize } #[derive(Persist)] #[persist(magicnumber = 42)] struct StructWithCustomMagic { one: u8, two: u16, } #[derive(Persist,Debug,PartialEq,Eq)] #[persist(magicnumber = 13)] enum SimpleEnumeration { One, Two } #[derive(Persist,Debug,PartialEq,Eq)] enum ComplexEnumeration { One, Unnamed(u8,u8), Named { one: u16, two: u32 } } #[derive(Persist,Debug,PartialEq,Eq)] struct AnonymousFieldStruct(u8,u16); // Code ====================================================================== struct LoopbackReadWrite { pub data: Vec } impl LoopbackReadWrite { pub fn new() -> Self { LoopbackReadWrite { data: Vec::new() } } } impl avr_oxide::io::Read for LoopbackReadWrite { fn read(&mut self, buf: &mut [u8]) -> avr_oxide::io::Result { let mut idx = 0; for _i in 0..buf.len() { if self.data.len() > 0 { buf[idx] = self.data.remove(0); idx += 1; } else { break; } } avr_oxide::OxideResult::Ok(idx) } } impl avr_oxide::io::Write for LoopbackReadWrite { fn write_buffered(&mut self, buf: &[u8]) -> avr_oxide::io::Result { self.data.extend_from_slice(buf); avr_oxide::OxideResult::Ok(buf.len()) } fn flush(&mut self) -> avr_oxide::io::Result<()> { avr_oxide::OxideResult::Ok(()) } } // Tests ===================================================================== #[test] fn persist_empty_struct() { let mut pipe = LoopbackReadWrite::new(); let data = EmptyStruct {}; Persist::save_to(&data, &mut pipe); assert_eq!(pipe.data, vec![ b'S' ]); } #[test] fn persist_numeric_struct() { let mut pipe = LoopbackReadWrite::new(); let data = StructWithFourElements { one: 1, two: 2, three: 3, four: 4 }; Persist::save_to(&data, &mut pipe); assert_eq!(pipe.data, vec![ b'S', 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04 ]); } #[test] fn persist_anonymous_struct() { let mut pipe = LoopbackReadWrite::new(); let data = AnonymousFieldStruct(0xde,0xadbe); Persist::save_to(&data, &mut pipe); assert_eq!(pipe.data, vec![ b'S', 0xde, 0xad, 0xbe ]); } #[test] fn persist_custom_magic_struct() { let mut pipe = LoopbackReadWrite::new(); let data = StructWithCustomMagic { one: 3, two: 4, }; Persist::save_to(&data, &mut pipe); assert_eq!(pipe.data, vec![ 42u8, 0x03, 0x00, 0x04 ]); } #[test] fn persist_and_load_enums() { let mut pipe = LoopbackReadWrite::new(); let simple = SimpleEnumeration::Two; Persist::save_to(&simple, &mut pipe); if let avr_oxide::OxideResult::Ok(loaded_simple) = SimpleEnumeration::load_from(&mut pipe) { println!("Deserialised: {:?}", &loaded_simple); assert_eq!(simple, loaded_simple); } else { panic!(); } let complex_1 = ComplexEnumeration::Named { one: 13u16, two: 32987u32 }; let complex_2 = ComplexEnumeration::Unnamed(12u8,49u8); Persist::save_to(&complex_1, &mut pipe); Persist::save_to(&complex_2, &mut pipe); if let avr_oxide::OxideResult::Ok(loaded_complex) = ComplexEnumeration::load_from(&mut pipe) { println!("Deserialised: {:?}", &loaded_complex); assert_eq!(complex_1, loaded_complex); } else { panic!(); } if let avr_oxide::OxideResult::Ok(loaded_complex) = ComplexEnumeration::load_from(&mut pipe) { println!("Deserialised: {:?}", &loaded_complex); assert_eq!(complex_2, loaded_complex); } else { panic!(); } }