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
use std::io::{self, Read};
use std::mem;
use std::str;
use std::ops::Range;
use std::slice;
use num_traits::ToPrimitive;
use file::FileDb;
use object::Object;
use types;
#[derive(Debug,Clone)]
#[repr(C)]
struct Header<AddressType>{
code: [u8; 4],
size: i32,
address: AddressType,
sdna_index: i32,
count: i32,
}
#[derive(Debug,Clone)]
#[repr(C)]
pub struct FileBlock{
pub code: [u8; 4],
pub size: i32,
pub address: u64,
pub sdna_index: i32,
pub count: i32,
pub data: Vec<u8>,
}
fn read_struct<T, R: Read>(read: &mut R) -> io::Result<T> {
let num_bytes = ::std::mem::size_of::<T>();
unsafe {
let mut s = ::std::mem::uninitialized();
let buffer = slice::from_raw_parts_mut(&mut s as *mut T as *mut u8, num_bytes);
match read.read_exact(buffer) {
Ok(()) => Ok(s),
Err(e) => {
::std::mem::forget(s);
Err(e)
}
}
}
}
impl FileBlock{
pub fn parse<R: Read>(file: &mut R, pointer_size: u8) -> io::Result<Option<FileBlock>>{
if pointer_size == 32{
FileBlock::parse_::<u32,R>(file)
}else{
FileBlock::parse_::<u64,R>(file)
}
}
fn parse_<AddressType: ToPrimitive, R: Read>(file: &mut R) -> io::Result<Option<FileBlock>>{
let header: io::Result<Header<AddressType>> = read_struct(file);
match header{
Ok(header) =>
match FileBlock::read_data(header, file){
Ok(block) => Ok(Some(block)),
Err(err) => Err(err)
},
Err(_) => Ok(None),
}
}
fn read_data<AddressType: ToPrimitive, R: Read>(header: Header<AddressType>, file: &mut R) -> io::Result<FileBlock>{
let mut data = Vec::with_capacity(header.size as usize);
unsafe{ data.set_len(header.size as usize) };
file.read_exact(&mut data)?;
Ok(FileBlock{
code: header.code,
size: header.size,
address: header.address.to_u64().unwrap(),
sdna_index: header.sdna_index,
count: header.count,
data: data,
})
}
pub fn code(&self) -> &str{
str::from_utf8(&self.code).unwrap()
}
pub fn object<'a>(&'a self, file_db: FileDb<'a>) -> Object{
Object::new(file_db, self)
}
pub fn slice<'a>(&'a self, dim: usize, file_db: FileDb<'a>) -> Vec<Object>{
Range{ start: 0, end: dim }
.map(|i| Object::new_with_index(file_db.clone(), self, i))
.collect()
}
pub fn data_slice<T>(&self, len: usize) -> types::Result<&[T]>{
if len * mem::size_of::<T>() > self.data.len(){
Err(types::Error::from(format!("Size of data slice {} * {} = {} is more than block size {}", len, mem::size_of::<T>(), len * mem::size_of::<T>(), self.data.len())))
}else{
Ok(unsafe{slice::from_raw_parts(mem::transmute(self.data.as_ptr()), len)})
}
}
pub fn size(&self) -> usize{
self.size as usize
}
pub fn data(&self) -> &[u8]{
&self.data
}
pub fn cast<T>(&self) -> types::Result<&T>{
if mem::size_of::<T>() > self.data.len() {
Err(types::Error::from(format!("Size of type {} is more than block size {}", mem::size_of::<T>(), self.data.len())))
}else{
Ok(unsafe{ mem::transmute(self.data.as_ptr()) })
}
}
}