read_write/
lib.rs

1use std::borrow::Cow;
2use std::fs::File;
3use std::io::prelude::*;
4use std::slice;
5use std::mem::{transmute, size_of, forget};
6use std::io::{Write, Result, Error, ErrorKind};
7
8/// object used to extend functionality of File
9/// used for reading and writing byte vectors to files
10pub trait VecIO {
11    fn write_slice_to_file<T>(&mut self, data: &[T]) -> Result<()>;
12    fn read_vec_from_file<T>(&mut self) -> Result<Vec<T>>;
13}
14
15impl VecIO for File {
16    /// Writes a vector of type T to file as bytes
17    fn write_slice_to_file<T>(&mut self, data: &[T]) -> Result<()> {
18        unsafe {
19            self.write_all(slice::from_raw_parts(transmute::<*const T, *const u8>(data.as_ptr()), data.len() * size_of::<T>()))?;
20        }
21        Ok(())
22    }
23    /// Reads a Vector of type T from file
24    fn read_vec_from_file<T>(&mut self) -> Result<Vec<T>> {
25        let mut buffer: Vec<T> = Vec::new();
26        let length = buffer.len();
27        let capacity = buffer.capacity();
28        unsafe {
29            let mut converted = Vec::<u8>::from_raw_parts(buffer.as_mut_ptr() as *mut u8, length * size_of::<T>(), capacity * size_of::<T>());
30            match self.read_to_end(&mut converted) {
31                Ok(size) => {
32                    if converted.len() % size_of::<T>() != 0 {
33                        converted.truncate(length * size_of::<T>());
34                        forget(converted);
35                        return Err(Error::new(
36                            ErrorKind::UnexpectedEof,
37                            format!("read_file() returned a number of bytes ({}) which is not a multiple of size ({})", size, size_of::<T>())
38                        ));
39                    }
40                },
41                Err(e) => {
42                    converted.truncate(length * size_of::<T>());
43                    forget(converted);
44                    return Err(e);
45                }
46            }
47            let new_length = converted.len() / size_of::<T>();
48            let new_capacity = converted.len() / size_of::<T>();
49            buffer = Vec::from_raw_parts(converted.as_mut_ptr() as *mut T, new_length, new_capacity);
50            forget(converted);
51            Ok(buffer)
52        }
53    }
54}
55
56/// Helper function used to unpack vectors from RustEmbed Assets
57///
58/// This is data that is embeded in the binary
59///
60/// [Rust Embed]: https://crates.io/crates/rust-embed
61pub fn unpack_vec_from_asset<T>(asset: Option<Cow<'static, [u8]>>) -> Result<Vec<T>> {
62    let buffer: Vec<T>;
63    match asset {
64        Some(data) => {
65            unsafe {
66                let mut bytes = data.into_owned();
67                if bytes.len() % size_of::<T>() != 0 {
68                    forget(bytes);
69                    return Err(Error::new(
70                        ErrorKind::UnexpectedEof,
71                        format!("read_asset() returned a number of bytes which is not a multiple of size ({})", size_of::<T>())
72                    ));
73                }
74                let length = bytes.len() / size_of::<T>();
75                let capacity = bytes.len() / size_of::<T>();
76                buffer = Vec::from_raw_parts(bytes.as_mut_ptr() as *mut T, length, capacity);
77                forget(bytes);
78            }
79        },
80        None => {
81            return Err(Error::new(
82                ErrorKind::NotFound,
83                format!("unable to read asset, file not found")
84            ));
85        }
86    }
87    Ok(buffer)
88}