-
Notifications
You must be signed in to change notification settings - Fork 0
/
lib.rs
109 lines (101 loc) · 2.94 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::convert::TryInto;
#[cfg(feature = "bitvec")]
mod bitvec;
mod dynamic_struct_index_reader;
mod dynamic_struct_index_writer;
mod dynamic_struct_reader;
#[cfg(feature = "ndarray")]
mod ndarray;
mod pointer;
mod position;
mod static_struct_reader;
mod traits;
mod types;
mod variant_reader;
mod vec_reader;
mod writer;
pub use self::{
dynamic_struct_index_reader::{
DynamicStructIndexFieldCount, DynamicStructIndexFieldId, DynamicStructIndexFieldOffset,
DynamicStructIndexPointer, DynamicStructIndexReader, DynamicStructIndexType,
},
dynamic_struct_index_writer::{DynamicStructIndexWriter, DynamicStructIndexWriterI},
dynamic_struct_reader::DynamicStructReader,
pointer::Pointer,
position::Position,
static_struct_reader::StaticStructReader,
traits::{PointerType, Read, ReadType, StaticSize, Write, WriteType},
variant_reader::VariantReader,
vec_reader::VecReader,
writer::Writer,
};
pub use buffalo_macro::{Read, Write};
pub fn read<'a, T>(bytes: &'a [u8]) -> T::Output
where
T: Read<'a>,
{
let position = bytes.len() - std::mem::size_of::<PointerType>();
let position = position.try_into().unwrap();
let position = Position::new(position);
<Pointer<T>>::read(bytes, position)
}
#[cfg(test)]
#[allow(unused)]
mod test {
use crate as buffalo;
#[derive(buffalo::Read, buffalo::Write)]
#[buffalo(size = "dynamic")]
struct AddressBook {
#[buffalo(id = 0, required)]
pub contacts: Vec<Contact>,
}
#[derive(buffalo::Read, buffalo::Write)]
#[buffalo(size = "dynamic")]
struct Contact {
#[buffalo(id = 0, required)]
pub age: u16,
#[buffalo(id = 1, required)]
pub name: String,
#[buffalo(id = 2, required)]
pub phone_numbers: Option<Vec<PhoneNumber>>,
}
#[derive(buffalo::Read, buffalo::Write)]
#[buffalo(size = "static", value_size = 8)]
enum PhoneNumber {
#[allow(unused)]
#[buffalo(id = 0)]
Home(String),
#[allow(unused)]
#[buffalo(id = 1)]
Mobile(String),
}
#[test]
fn test_address_book() {
let mut writer = buffalo::Writer::new();
let name = writer.write("John Doe");
let home = writer.write("1231231234");
let mobile = writer.write("4564564567");
let phone_numbers = writer.write(&vec![
PhoneNumberWriter::Home(home),
PhoneNumberWriter::Mobile(mobile),
]);
let contact = writer.write(&ContactWriter {
age: 28,
name,
phone_numbers: Some(phone_numbers),
});
let contacts = writer.write(&vec![contact]);
let address_book = writer.write(&AddressBookWriter { contacts });
writer.write(&address_book);
let bytes = writer.into_bytes();
let address_book = buffalo::read::<AddressBookReader>(&bytes);
let contact = address_book.contacts().get(0).unwrap();
assert_eq!(contact.name(), "John Doe");
assert_eq!(contact.age(), 28);
let phone_numbers = contact.phone_numbers();
let home = phone_numbers.unwrap().get(0).unwrap();
assert_eq!(home.as_home().unwrap(), "1231231234");
let mobile = phone_numbers.unwrap().get(1).unwrap();
assert_eq!(mobile.as_mobile().unwrap(), "4564564567");
}
}