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
110
111
112
113
114
115
116
117
118
119
120
121
use std::mem::size_of;
use std::io::{Read, Write};
use std::fs::File;
use std::slice;
pub trait IOExt : Read + Write {
fn write_copy<T : Copy>(&mut self, t: &T) -> std::io::Result<()> {
let buffer = unsafe {
slice::from_raw_parts(t as *const T as *const u8, size_of::<T>())
};
self.write(buffer)?;
Ok(())
}
fn read_copy<T : Copy>(&mut self) -> std::io::Result<T> {
let mut t : T = unsafe { std::mem::uninitialized() };
let mut buffer = unsafe {
slice::from_raw_parts_mut(&mut t as *mut T as *mut u8, size_of::<T>())
};
self.read_exact(buffer)?;
Ok(t)
}
fn write_str(&mut self, s: &str) -> std::io::Result<()> {
let bytes = s.as_bytes();
self.write_copy(&s.len())?;
self.write(bytes)?;
Ok(())
}
fn read_str(&mut self) -> std::io::Result<String> {
let mut buffer = vec![0u8; self.read_copy::<usize>()?];
self.read_exact(&mut buffer)?;
Ok(String::from_utf8(buffer).unwrap())
}
fn write_slice<T : Copy>(&mut self, ts : &[T]) -> std::io::Result<()> {
let size = ts.len();
let buffer = unsafe {
slice::from_raw_parts(ts.as_ptr() as *const u8, size * size_of::<T>())
};
self.write_copy(&size)?;
self.write(buffer)?;
Ok(())
}
fn read_slice<T : Copy>(&mut self) -> std::io::Result<Vec<T>> {
let size = self.read_copy::<usize>()?;
unsafe {
let mut ts = vec![std::mem::uninitialized::<T>(); size];
let mut buffer = slice::from_raw_parts_mut(
ts.as_mut_ptr() as *mut u8, size * size_of::<T>()
);
self.read(buffer)?;
Ok(ts)
}
}
}
impl IOExt for File {}
#[cfg(test)]
mod tests {
use std::mem::size_of;
use std::fs::{File, remove_file};
use std::io::Write;
use ::IOExt;
const FILE_PATH : &str = "test.txt";
const A : i32 = -4242;
const B : f64 = 42.42;
const C : u8 = 42;
const D : &str = "42";
const E : &[f64] = &[2.6125, 5.25, 10.5, 21.0, 42.0];
#[test]
fn write_read() {
println!("Creating the file");
let mut f = File::create(FILE_PATH).expect("Create file");
println!("Write started");
write(&mut f);
f.flush().expect("Flush the file");
println!("Write ended");
let mut f = File::open(FILE_PATH).expect("Reopening the file");
println!("Read started");
read(&mut f);
println!("Read ended");
remove_file(FILE_PATH).expect("Delete file");
}
fn write(f : &mut File) {
f.write_copy(&A).expect("A");
f.write_copy(&B).expect("B");
f.write_copy(&C).expect("C");
f.write_str(D).expect("D");
f.write_slice(E).expect("E");
}
fn read(f : &mut File) {
assert_eq!(f.read_copy::<i32>().expect("A"), A);
assert_eq!(f.read_copy::<f64>().expect("B"), B);
assert_eq!(f.read_copy::<u8>().expect("C"), C);
assert_eq!(&f.read_str().expect("D"), D);
assert_eq!(f.read_slice::<f64>().expect("E").as_slice(), E);
}
}