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
use ffi;
use std::{fs, mem};
use std::path::Path;
use analysis::{self, Analysis};
use die::{self, Die};
use dimensions::{self, Dimensions};
use output::{self, Output};
use {Raw, Result};
pub struct Stack {
pub dimensions: Dimensions,
pub elements: Vec<StackElement>,
raw: ffi::StackDescription_t,
}
#[derive(Clone, Debug, PartialEq)]
pub enum StackElement {
Channel,
Die(Die),
HeatSink,
Layer,
None,
}
impl Drop for Stack {
fn drop(&mut self) {
unsafe { ffi::stack_description_destroy(&mut self.raw) };
}
}
implement_raw!(Stack, ffi::StackDescription_t);
pub unsafe fn new(path: &Path) -> Result<(Stack, Analysis, Output)> {
if fs::metadata(path).is_err() {
raise!("the stack-description file does not exist");
}
let mut raw = mem::uninitialized();
ffi::stack_description_init(&mut raw);
let mut analysis = try!(analysis::new());
let mut output = try!(output::new());
success!(ffi::parse_stack_description_file(path_to_cstr!(path).as_ptr() as *mut _, &mut raw,
analysis.raw_mut(), output.raw_mut()),
"parse the stack-description file");
let stack = Stack {
dimensions: dimensions::new(raw.Dimensions),
elements: extract_elements(&raw),
raw: raw,
};
Ok((stack, analysis, output))
}
unsafe fn extract_elements(raw: &ffi::StackDescription_t) -> Vec<StackElement> {
let mut elements = vec![];
let mut cursor = raw.StackElements.First;
for _ in 0..raw.StackElements.Size {
assert!(!cursor.is_null());
let element = &(*cursor).Data;
match element.Type {
ffi::TDICE_STACK_ELEMENT_CHANNEL => {
elements.push(StackElement::Channel);
},
ffi::TDICE_STACK_ELEMENT_DIE => {
elements.push(StackElement::Die(die::new(&*element.Pointer.Die())));
},
ffi::TDICE_STACK_ELEMENT_HEATSINK => {
elements.push(StackElement::HeatSink);
},
ffi::TDICE_STACK_ELEMENT_LAYER => {
elements.push(StackElement::Layer);
},
ffi::TDICE_STACK_ELEMENT_NONE => {
elements.push(StackElement::None);
},
}
cursor = (*cursor).Next;
}
elements
}