1extern crate layout_id;
10extern crate memmap;
11
12use layout_id::layout_id;
13use memmap::MmapMut;
14use memmap::MmapOptions;
15use std::default::Default;
16use std::fs::OpenOptions;
17use std::io;
18use std::marker::PhantomData;
19use std::mem::{size_of, transmute};
20use std::ops::{Deref, DerefMut};
21use std::path::Path;
22use std::slice;
23
24const MAGIC_BYTES: &'static [u8; 4] = b"PADB";
25
26#[derive(Debug)]
27pub enum Error {
28 UnableToOpenFile(io::Error),
29 WrongMagicBytes,
30 WrongFileSize,
31 WrongTypeId,
32}
33
34pub struct PersistentArray<T: Copy> {
38 phantom_type: PhantomData<T>,
39 map: MmapMut,
40 elements: u64,
41}
42
43#[repr(C, packed)]
44struct Header {
45 magic: [u8; 4],
46 size: u64,
47 typeid: u64,
48}
49
50impl<T: Copy + Default> PersistentArray<T> {
51 pub fn new<P>(path: P, size: u64) -> Result<PersistentArray<T>, Error>
53 where
54 P: AsRef<Path>,
55 {
56 let file = match OpenOptions::new()
57 .read(true)
58 .write(true)
59 .create(true)
60 .open(&path)
61 {
62 Ok(file) => file,
63 Err(err) => return Err(Error::UnableToOpenFile(err)),
64 };
65
66 if let Err(err) = file.set_len(size * size_of::<T>() as u64 + size_of::<Header>() as u64) {
67 return Err(Error::UnableToOpenFile(err));
68 }
69
70 println!("{:?}", "Hej");
71
72 let mut map = unsafe {
73 match MmapOptions::new().map_mut(&file) {
74 Ok(map) => map,
75 Err(err) => return Err(Error::UnableToOpenFile(err)),
76 }
77 };
78
79 println!("{:?}", "Hej");
80
81 if map.len() as u64 != size * size_of::<T>() as u64 + size_of::<Header>() as u64 {
82 return Err(Error::WrongFileSize);
83 }
84
85 let header: &mut Header = unsafe { transmute(map.as_mut_ptr()) };
86
87 *header = Header {
88 magic: *MAGIC_BYTES,
89 size: size,
90 typeid: layout_id::<T>(),
91 };
92
93 let element: T = Default::default();
94
95 let elements: &mut [T] = unsafe {
96 slice::from_raw_parts_mut(
97 map.as_mut_ptr().offset(size_of::<Header>() as isize) as *mut T,
98 size as usize,
99 )
100 };
101
102 for e in elements.iter_mut() {
103 *e = element;
104 }
105
106 Ok(PersistentArray {
107 phantom_type: PhantomData,
108 map: map,
109 elements: size,
110 })
111 }
112
113 pub fn open<P>(path: P) -> Result<PersistentArray<T>, Error>
115 where
116 P: AsRef<Path>,
117 {
118 let file = match OpenOptions::new().read(true).write(true).open(&path) {
119 Ok(file) => file,
120 Err(err) => return Err(Error::UnableToOpenFile(err)),
121 };
122
123 let map = unsafe {
124 match MmapOptions::new().map_mut(&file) {
125 Ok(map) => map,
126 Err(err) => return Err(Error::UnableToOpenFile(err)),
127 }
128 };
129
130 let ptr = map.as_ptr();
131 let size = map.len();
132
133 if size < size_of::<Header>() {
134 return Err(Error::WrongFileSize);
135 }
136
137 let header: &Header = unsafe { transmute(ptr) };
138
139 if header.magic != *MAGIC_BYTES {
140 return Err(Error::WrongMagicBytes);
141 }
142
143 let elements = ((size - size_of::<Header>()) / size_of::<T>()) as u64;
144
145 if header.size != elements {
146 return Err(Error::WrongFileSize);
147 }
148
149 if header.typeid != layout_id::<T>() {
150 return Err(Error::WrongTypeId);
151 }
152
153 Ok(PersistentArray {
154 phantom_type: PhantomData,
155 map: map,
156 elements: elements,
157 })
158 }
159}
160
161impl<T: Copy> Deref for PersistentArray<T> {
162 type Target = [T];
163
164 fn deref(&self) -> &[T] {
165 unsafe {
166 slice::from_raw_parts(
167 self.map.as_ptr().offset(size_of::<Header>() as isize) as *const T,
168 self.elements as usize,
169 )
170 }
171 }
172}
173
174impl<T: Copy> DerefMut for PersistentArray<T> {
175 fn deref_mut(&mut self) -> &mut [T] {
176 unsafe {
177 slice::from_raw_parts_mut(
178 self.map.as_mut_ptr().offset(size_of::<Header>() as isize) as *mut T,
179 self.elements as usize,
180 )
181 }
182 }
183}