1extern crate serde_yaml;
2
3use std::rc::Rc;
4use std::default;
5use std::collections::HashMap;
6
7use std::path::Path;
8use std::fs;
9use std::io::Read;
10
11use crate::error::Result;
12
13#[serde(rename_all = "lowercase")]
14#[derive(Debug, Serialize, Deserialize)]
15pub enum DownloadMode {
16 Mazda1,
17 None,
18}
19
20impl default::Default for DownloadMode {
21 fn default() -> DownloadMode {
22 DownloadMode::None
23 }
24}
25
26#[serde(rename_all = "lowercase")]
27#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
28pub enum FlashMode {
29 Mazda1,
30 None,
31}
32
33impl default::Default for FlashMode {
34 fn default() -> FlashMode {
35 FlashMode::None
36 }
37}
38
39#[serde(rename_all = "lowercase")]
40#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
41pub enum LogMode {
42 Uds,
43 None,
44}
45
46impl default::Default for LogMode {
47 fn default() -> LogMode {
48 LogMode::None
49 }
50}
51
52#[serde(rename_all = "lowercase")]
53#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
54pub enum Endianness {
55 Big,
56 Little,
57}
58
59#[serde(rename_all = "lowercase")]
60#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
61pub enum DataType {
62 Uint8,
63 Uint16,
64 Uint32,
65 Uint64,
66 Float32,
67 Float64,
68 Int8,
69 Int16,
70 Int32,
71 Int64,
72}
73
74#[derive(Debug, Serialize, Deserialize)]
75pub struct Identifier {
76 pub offset: u32,
77 pub data: Vec<u8>,
78}
79
80#[derive(Debug, Serialize, Deserialize)]
81pub struct Axis {
82 pub name: String,
83 pub id: String,
84 #[serde(rename = "type")]
85 pub axis_type: String,
86
87 #[serde(default)]
88 pub start: f64,
89 #[serde(default)]
90 pub increment: f64,
91}
92
93#[derive(Debug, Deserialize, Serialize)]
94pub struct Table {
95 pub id: usize,
96 pub name: String,
97 pub description: String,
98 pub category: String,
99 pub data_type: DataType,
100
101 #[serde(default = "default_table_dimension")]
102 pub width: usize,
103 #[serde(default = "default_table_dimension")]
104 pub height: usize,
105
106 #[serde(default = "max_table_constraint")]
107 pub maximum: f64,
108 #[serde(default = "min_table_constraint")]
109 pub minimum: f64,
110
111 #[serde(default)]
112 pub axis_x_id: String,
113 #[serde(default)]
114 pub axis_y_id: String,
115}
116
117#[derive(Debug, Deserialize, Serialize, Clone)]
118pub struct Pid {
119 pub name: String,
120 pub description: String,
121 pub formula: String,
122 pub unit: String,
123 pub datatype: DataType,
124 pub id: u32,
125 pub code: u16,
126}
127
128fn default_table_dimension() -> usize {
129 1
130}
131
132fn max_table_constraint() -> f64 {
133 use std::f64;
134 f64::MAX
135}
136
137fn min_table_constraint() -> f64 {
138 use std::f64;
139 f64::MIN
140}
141
142
143#[derive(Debug, Deserialize, Serialize)]
145pub struct Model {
146 pub id: String,
147 pub name: String,
148
149 #[serde(rename = "tables")]
150 #[serde(default)]
151 pub table_offsets: HashMap<usize, usize>,
153
154 #[serde(rename = "axes")]
155 #[serde(default)]
156 pub axis_offsets: HashMap<String, usize>,
158
159 #[serde(default)]
160 pub identifiers: Vec<Identifier>,
161}
162
163#[derive(Debug, Deserialize, Serialize)]
164pub struct Transfer {
165 #[serde(default)]
166 pub download_mode: DownloadMode,
167 #[serde(default)]
168 pub flash_mode: FlashMode,
169 pub key: String,
171 pub server_id: u16,
173}
174
175#[derive(Debug, Deserialize, Serialize)]
177pub struct Main {
178 pub name: String,
179 pub id: String,
180
181 pub transfer: Transfer,
182 pub baudrate: u32,
183 #[serde(default)]
184 pub log_mode: LogMode,
185 pub endianness: Endianness,
186
187 pub flash_offset: usize,
189 pub flash_size: usize,
190
191 pub rom_size: usize,
192
193 pub tables: Vec<Table>,
194 pub pids: Vec<Pid>,
195 pub vins: Vec<String>,
196
197 #[serde(skip)]
198 pub models: Vec<Rc<Model>>,
199}
200
201impl Main {
202 pub fn find(&self, id: &str) -> Option<&Rc<Model>> {
204 self.models.iter().find(|&model| model.id == id)
205 }
206
207 pub fn find_table(&self, id: usize) -> Option<&Table> {
209 self.tables.iter().find(|ref x| x.id == id)
211 }
212
213 pub fn identify(&self, data: &[u8]) -> Option<&Rc<Model>> {
215 self.models.iter().find(|&model| model.identify(data))
216 }
217}
218
219impl Model {
220 pub fn identify(&self, data: &[u8]) -> bool {
222 for id in self.identifiers.iter() {
223 if data.len() < id.offset as usize + id.data.len() {
224 return false;
226 }
227 if id.data != &data[id.offset as usize..(id.offset as usize + id.data.len())] {
228 return false;
229 }
230 }
231 return true;
233 }
234}
235
236pub struct Definitions {
237 pub definitions: Vec<Rc<Main>>,
238}
239
240impl default::Default for Definitions {
241 fn default() -> Definitions {
242 Definitions {definitions: Vec::new()}
243 }
244}
245
246impl Definitions {
247 pub fn load(&mut self, base: &Path) -> Result<()> {
248 if !base.exists() {
249 return Ok(());
250 }
251 for entry in fs::read_dir(base)? {
252 let entry = entry?;
253 let path = entry.path();
254 if path.is_dir() {
255 let main_path = path.join("main.yaml");
257 if !main_path.is_file() {
258 continue;
259 }
260
261 let mut contents = fs::read_to_string(main_path)?;
263 let mut main: Main = serde_yaml::from_str(&contents)?;
264
265 for entry in fs::read_dir(path)? {
267 let entry = entry?;
268 let path = entry.path();
269
270 if !path.is_file() { continue; }
271 if let Some(ext) = path.extension() {
272 if ext != "yaml" { continue; }
273 } else {
274 continue;
275 }
276 if let Some(name) = path.file_name() {
277 if name == "main.yaml" { continue; }
278 }
279
280 contents.clear();
281 {
282 let mut file = fs::File::open(path)?;
283 file.read_to_string(&mut contents)?;
284 }
285 let model: Model = serde_yaml::from_str(&contents)?;
286 main.models.push(Rc::new(model));
287 }
288
289 self.definitions.push(Rc::new(main));
290 }
291 }
292
293 Ok(())
294 }
295
296 pub fn find(&self, id: &str) -> Option<&Rc<Main>> {
298 self.definitions.iter().find(|&def| def.id == id)
299 }
300}