extend readme
[Mitarbeiter/Tim-Zeitz/stud-rust-base.git] / src / io.rs
1 //! This module contains a few traits and blanket implementations
2 //! for (de)serializing and writing/reading numeric data to/from the disc.
3 //! To use it you should import the `Load` and `Store` traits and use the
4 //! `load_from` and `write_to` methods.
5 //!
6 //! # Example
7 //!
8 //! ```
9 //! use stud_rust_base::io::*;
10 //!
11 //! fn test() {
12 //!     let head = Vec::<u32>::load_from("head_file_name").expect("could not read head");
13 //!     let lat = Vec::<f32>::load_from("node_latitude_file_name").expect("could not read lat");
14 //!     head.write_to("output_file").expect("could not write head");
15 //! }
16 //! ```
17
18 use std::fs;
19 use std::fs::File;
20 use std::io::prelude::*;
21 use std::io::Result;
22 use std::mem;
23 use std::slice;
24
25 /// A trait which allows accessing the data of an object as a slice of bytes.
26 /// The bytes should represent a serialization of the object and allow
27 /// recreating it when reading these bytes again from the disk.
28 ///
29 /// Do not use this Trait but rather the `Store` trait.
30 pub trait DataBytes {
31     /// Should return the serialized object as a slice of bytes
32     fn data_bytes(&self) -> &[u8];
33 }
34
35 /// A trait which mutably exposes the internal data of an object so that
36 /// a serialized object can be loaded from disk and written back into a precreated
37 /// object of the right size.
38 ///
39 /// Do not use this Trait but rather the `Load` trait.
40 pub trait DataBytesMut {
41     /// Should return a mutable slice of the internal data of the object
42     fn data_bytes_mut(&mut self) -> &mut [u8];
43 }
44
45 impl<T: Copy> DataBytes for [T] {
46     fn data_bytes(&self) -> &[u8] {
47         let num_bytes = self.len() * mem::size_of::<T>();
48         unsafe { slice::from_raw_parts(self.as_ptr() as *const u8, num_bytes) }
49     }
50 }
51
52 impl<T: Copy> DataBytesMut for [T] {
53     fn data_bytes_mut(&mut self) -> &mut [u8] {
54         let num_bytes = self.len() * mem::size_of::<T>();
55         unsafe { slice::from_raw_parts_mut(self.as_mut_ptr() as *mut u8, num_bytes) }
56     }
57 }
58
59 impl<T: Copy> DataBytesMut for Vec<T> {
60     fn data_bytes_mut(&mut self) -> &mut [u8] {
61         let num_bytes = self.len() * mem::size_of::<T>();
62         unsafe { slice::from_raw_parts_mut(self.as_mut_ptr() as *mut u8, num_bytes) }
63     }
64 }
65
66 /// A trait which extends the `DataBytes` trait and exposes a method to write objects to disk.
67 pub trait Store : DataBytes {
68     /// Writes the serialized object to the file with the given filename
69     fn write_to(&self, filename: &str) -> Result<()> {
70         File::create(filename)?.write_all(self.data_bytes())
71     }
72 }
73
74 impl<T: DataBytes> Store for T {}
75 impl<T> Store for [T] where [T]: DataBytes {}
76
77 /// A trait to load serialized data back into objects.
78 pub trait Load : DataBytesMut + Sized {
79     /// This method must create an object of the correct size for serialized data with the given number of bytes.
80     /// It should not be necessary to call this method directly.
81     fn new_with_bytes(num_bytes: usize) -> Self;
82
83     /// This method will load serialized data from the disk, create an object of the appropriate size,
84     /// deserialize the bytes into the object and return the object.
85     fn load_from(filename: &str) -> Result<Self> {
86         let metadata = fs::metadata(filename)?;
87         let mut file = File::open(filename)?;
88
89         let mut object = Self::new_with_bytes(metadata.len() as usize);
90         assert_eq!(metadata.len() as usize, object.data_bytes_mut().len());
91         file.read_exact(object.data_bytes_mut())?;
92
93         Ok(object)
94     }
95 }
96
97 impl<T: Default + Copy> Load for Vec<T> {
98     fn new_with_bytes(num_bytes: usize) -> Self {
99         assert_eq!(num_bytes % mem::size_of::<T>(), 0);
100         let num_elements = num_bytes / mem::size_of::<T>();
101         (0..num_elements).map(|_| T::default()).collect()
102     }
103 }