runiter_wot/operations/
file.rs1use data::NodeId;
19use std::fs;
20use std::fs::File;
21use std::io;
22use std::io::prelude::*;
23
24use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
25
26use data::WebOfTrust;
27
28#[derive(Debug)]
30pub enum WotParseError {
31 FailToOpenFile(io::Error),
33
34 IOError(io::Error),
36}
37
38impl From<io::Error> for WotParseError {
39 fn from(e: io::Error) -> WotParseError {
40 WotParseError::IOError(e)
41 }
42}
43
44#[derive(Debug)]
46pub enum WotWriteError {
47 WrongWotSize(),
49
50 FailToCreateFile(io::Error),
52
53 FailToWriteInFile(io::Error),
55}
56
57impl From<io::Error> for WotWriteError {
58 fn from(e: io::Error) -> WotWriteError {
59 WotWriteError::FailToWriteInFile(e)
60 }
61}
62
63pub trait FileFormater {
65 fn from_file<T: WebOfTrust>(
67 &self,
68 path: &str,
69 max_links: usize,
70 ) -> Result<(T, Vec<u8>), WotParseError>;
71
72 fn to_file<T: WebOfTrust>(&self, wot: &T, data: &[u8], path: &str)
74 -> Result<(), WotWriteError>;
75}
76
77#[derive(Debug, Clone, Copy)]
79pub struct BinaryFileFormater;
80
81impl FileFormater for BinaryFileFormater {
82 fn from_file<T: WebOfTrust>(
84 &self,
85 path: &str,
86 max_links: usize,
87 ) -> Result<(T, Vec<u8>), WotParseError> {
88 let mut wot = T::new(max_links);
89
90 let file_size = fs::metadata(path).expect("fail to read wotb file !").len();
91 let mut file_pointing_to_blockstamp_size: Vec<u8> = vec![0; file_size as usize];
92 match File::open(path) {
93 Ok(mut file) => {
94 file.read_exact(&mut file_pointing_to_blockstamp_size.as_mut_slice())?;
95 }
96 Err(e) => return Err(WotParseError::FailToOpenFile(e)),
97 };
98 let mut file_pointing_to_blockstamp = file_pointing_to_blockstamp_size.split_off(4);
100 let mut buf = &file_pointing_to_blockstamp_size[..];
102 let blockstamp_size = buf.read_u32::<BigEndian>().unwrap();
103 let mut file_pointing_to_nodes_count =
105 file_pointing_to_blockstamp.split_off(blockstamp_size as usize);
106 let mut file_pointing_to_nodes_states = file_pointing_to_nodes_count.split_off(4);
108 let mut buf = &file_pointing_to_nodes_count[..];
110 let nodes_count = buf.read_u32::<BigEndian>().unwrap();
111 let nodes_states_size = match nodes_count % 8 {
113 0 => nodes_count / 8,
114 _ => (nodes_count / 8) + 1,
115 };
116 let file_pointing_to_links =
118 file_pointing_to_nodes_states.split_off(nodes_states_size as usize);
119 let count_total_bytes_read = file_pointing_to_links.len()
120 + nodes_states_size as usize
121 + 4
122 + blockstamp_size as usize
123 + 4;
124 if count_total_bytes_read != file_size as usize {
125 panic!("not read all wot file !");
126 }
127 let mut count_remaining_nodes = nodes_count;
129 for byte in file_pointing_to_nodes_states {
130 let mut byte_integer = u8::from_be(byte);
131 let mut factor: u8 = 128;
132 for _i in 0..8 {
133 if count_remaining_nodes > 0 {
134 wot.add_node();
135 if byte_integer >= factor {
136 byte_integer -= factor;
137 } else {
138 let _test = wot.set_enabled(
139 NodeId((nodes_count - count_remaining_nodes) as usize),
140 false,
141 );
142 }
143 count_remaining_nodes -= 1;
144 }
145 factor /= 2;
146 }
147 }
148 let mut buffer_3b: Vec<u8> = Vec::with_capacity(3);
150 let mut count_bytes = 0;
151 let mut remaining_links: u8 = 0;
152 let mut target: u32 = 0;
153 for byte in file_pointing_to_links {
154 if remaining_links == 0 {
155 target += 1;
156 remaining_links = u8::from_be(byte);
157 count_bytes = 0;
158 } else {
159 buffer_3b.push(byte);
160 if count_bytes % 3 == 2 {
161 let mut buf = &buffer_3b.clone()[..];
162 let source = buf.read_u24::<BigEndian>().expect("fail to parse source");
163 wot.add_link(NodeId(source as usize), NodeId((target - 1) as usize));
164 remaining_links -= 1;
165 buffer_3b.clear();
166 }
167 count_bytes += 1;
168 }
169 }
170 if count_bytes % 3 != 0 {
171 panic!("not read all wot file !");
172 }
173 Ok((wot, file_pointing_to_blockstamp))
174 }
175
176 fn to_file<T: WebOfTrust>(
178 &self,
179 wot: &T,
180 data: &[u8],
181 path: &str,
182 ) -> Result<(), WotWriteError> {
183 let mut buffer: Vec<u8> = Vec::new();
184 let blockstamp_size = data.len() as u32;
186 let mut bytes: Vec<u8> = Vec::with_capacity(4);
187 bytes.write_u32::<BigEndian>(blockstamp_size).unwrap();
188 buffer.append(&mut bytes);
189 buffer.append(&mut data.to_vec());
191 let nodes_count = wot.size() as u32;
193 let mut bytes: Vec<u8> = Vec::with_capacity(4);
194 bytes.write_u32::<BigEndian>(nodes_count).unwrap();
195 buffer.append(&mut bytes);
196 let mut enable_states: u8 = 0;
198 let mut factor: u8 = 128;
199 for n in 0..nodes_count {
200 match wot.is_enabled(NodeId(n as usize)) {
201 Some(enable) => {
202 if enable {
203 enable_states += factor;
204 }
205 }
206 None => {
207 return Err(WotWriteError::WrongWotSize());
208 }
209 }
210 if n % 8 == 7 {
211 factor = 128;
212 let mut tmp_buf = Vec::with_capacity(1);
213 tmp_buf.write_u8(enable_states).unwrap();
214 buffer.append(&mut tmp_buf);
215 enable_states = 0;
216 } else {
217 factor /= 2;
218 }
219 }
220 if nodes_count % 8 != 7 {
222 let mut tmp_buf = Vec::with_capacity(1);
223 tmp_buf.write_u8(enable_states).unwrap();
224 buffer.append(&mut tmp_buf);
225 }
226 for n in 0..nodes_count {
228 if let Some(sources) = wot.get_links_source(NodeId(n as usize)) {
229 let mut bytes = Vec::with_capacity(1);
231 bytes.write_u8(sources.len() as u8).unwrap();
232 buffer.append(&mut bytes);
233 for source in &sources {
234 let mut bytes: Vec<u8> = Vec::with_capacity(3);
236 bytes.write_u24::<BigEndian>(source.0 as u32).unwrap();
237 buffer.append(&mut bytes);
238 }
239 };
240 }
241 let mut file = match File::create(path) {
243 Ok(file) => file,
244 Err(e) => return Err(WotWriteError::FailToCreateFile(e)),
245 };
246 file.write_all(&buffer)?;
248
249 Ok(())
250 }
251}