restructure and add documentation
[Mitarbeiter/Tim-Zeitz/stud-rust-base.git] / src / io.rs
1 use std::fs;
2 use std::fs::File;
3 use std::io::prelude::*;
4 use std::io::Result;
5 use std::mem;
6 use std::slice;
7
8 pub trait DataBytes {
9     fn data_bytes(&self) -> &[u8];
10 }
11
12 pub trait DataBytesMut {
13     fn data_bytes_mut(&mut self) -> &mut [u8];
14 }
15
16 impl<T: Copy> DataBytes for [T] {
17     fn data_bytes(&self) -> &[u8] {
18         let num_bytes = self.len() * mem::size_of::<T>();
19         unsafe { slice::from_raw_parts(self.as_ptr() as *const u8, num_bytes) }
20     }
21 }
22
23 impl<T: Copy> DataBytesMut for [T] {
24     fn data_bytes_mut(&mut self) -> &mut [u8] {
25         let num_bytes = self.len() * mem::size_of::<T>();
26         unsafe { slice::from_raw_parts_mut(self.as_mut_ptr() as *mut u8, num_bytes) }
27     }
28 }
29
30 impl<T: Copy> DataBytesMut for Vec<T> {
31     fn data_bytes_mut(&mut self) -> &mut [u8] {
32         let num_bytes = self.len() * mem::size_of::<T>();
33         unsafe { slice::from_raw_parts_mut(self.as_mut_ptr() as *mut u8, num_bytes) }
34     }
35 }
36
37 pub trait Store : DataBytes {
38     fn write_to(&self, filename: &str) -> Result<()> {
39         File::create(filename)?.write_all(self.data_bytes())
40     }
41 }
42
43 impl<T: DataBytes> Store for T {}
44 impl<T> Store for [T] where [T]: DataBytes {}
45
46 pub trait Load : DataBytesMut + Sized {
47     fn new_with_bytes(num_bytes: usize) -> Self;
48
49     fn load_from(filename: &str) -> Result<Self> {
50         let metadata = fs::metadata(filename)?;
51         let mut file = File::open(filename)?;
52
53         let mut object = Self::new_with_bytes(metadata.len() as usize);
54         assert_eq!(metadata.len() as usize, object.data_bytes_mut().len());
55         file.read_exact(object.data_bytes_mut())?;
56
57         Ok(object)
58     }
59 }
60
61 impl<T: Default + Copy> Load for Vec<T> {
62     fn new_with_bytes(num_bytes: usize) -> Self {
63         assert_eq!(num_bytes % mem::size_of::<T>(), 0);
64         let num_elements = num_bytes / mem::size_of::<T>();
65         (0..num_elements).map(|_| T::default()).collect()
66     }
67 }