Skip to content

Commit aa310c2

Browse files
committed
add docs and readme
1 parent e74a123 commit aa310c2

File tree

2 files changed

+121
-4
lines changed

2 files changed

+121
-4
lines changed

README.md

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Dmidecoder parser with rust
2+
3+
Convert Dmidecoder output into properly formated data (HashMap)
4+
5+
## installation
6+
7+
add dmidecoder parser to your dependencies
8+
```toml
9+
dmidecoder = {git="https://github.com/andrewayoub/dmidecoder.git"}
10+
```
11+
12+
import as external crate
13+
```rust
14+
extern crate dmidecoder;
15+
use dmidecoder::dmidecoder::parse;
16+
```
17+
18+
pass dmidecoder raw data to parse method
19+
```rust
20+
let sample = r#"
21+
Getting SMBIOS data from sysfs.
22+
SMBIOS 2.7 present.
23+
24+
Handle 0x0000, DMI type 0, 24 bytes
25+
BIOS Information
26+
Vendor: LENOVO
27+
Version: 9BCN26WW
28+
Release Date: 07/31/2014
29+
Address: 0xE0000
30+
Runtime Size: 128 kB
31+
ROM Size: 4096 kB
32+
Characteristics:
33+
PCI is supported
34+
BIOS is upgradeable
35+
BIOS shadowing is allowed
36+
Boot from CD is supported
37+
Selectable boot is supported
38+
EDD is supported
39+
Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)
40+
Japanese floppy for Toshiba 1.2 MB is supported (int 13h)
41+
5.25"/360 kB floppy services are supported (int 13h)
42+
5.25"/1.2 MB floppy services are supported (int 13h)
43+
3.5"/720 kB floppy services are supported (int 13h)
44+
3.5"/2.88 MB floppy services are supported (int 13h)
45+
8042 keyboard services are supported (int 9h)
46+
CGA/mono video services are supported (int 10h)
47+
ACPI is supported
48+
USB legacy is supported
49+
BIOS boot specification is supported
50+
Targeted content distribution is supported
51+
UEFI is supported
52+
BIOS Revision: 0.26
53+
Firmware Revision: 0.26
54+
55+
Handle 0x0010, DMI type 13, 22 bytes
56+
BIOS Language Information
57+
Language Description Format: Long
58+
Installable Languages: 4
59+
en|US|iso8859-1
60+
fr|CA|iso8859-1
61+
ja|JP|unicode
62+
zh|TW|unicode
63+
Currently Installed Language: en|US|iso8859-1
64+
65+
"#;
66+
67+
let sections = parse(sample);
68+
println!("{:?}", sections["BIOS Information"].properties["Characteristics"].items)
69+
70+
```
71+
72+
## Contribution
73+
Feel free to contribute by any modifications or improvements.
74+
75+
## Tests
76+
you can rus tests using cargo
77+
```bash
78+
cargo test
79+
```
80+
81+
## Thanks
82+
To [xmonader](https://github.com/xmonader) for his support.

src/lib.rs

+39-4
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,75 @@
11
pub mod dmidecoder {
22
use std::collections::HashMap;
3-
3+
4+
/// Property represents a single item inside a section
5+
/// it contains value and items as vector
6+
/// you should have at least on of these fields set
47
#[derive(Debug)]
58
pub struct Property {
69
pub value: String,
710
pub items: Vec<String>,
811
}
912

1013
impl Property {
14+
/// Returns empty property
15+
/// # examples
16+
/// ```
17+
/// let property: Property = Property::new();
18+
/// ```
1119
pub fn new() -> Property {
1220
Property {
1321
value: String::new(),
1422
items: Vec::new(),
1523
}
1624
}
25+
/// Check if the property is empty
26+
/// # examples
27+
/// ```
28+
/// property.is_empty()
29+
/// ```
1730
pub fn is_empty(&self) -> bool {
1831
return self.value.is_empty() && self.items.is_empty()
1932
}
2033
}
2134

35+
/// Section represents a full section of data
2236
#[derive(Debug)]
2337
pub struct Section {
2438
pub handle_line: String,
2539
pub properties: HashMap<String, Property>,
2640
}
2741

2842
impl Section {
43+
/// Returns empty Section
44+
/// # examples
45+
/// ```
46+
/// let section: Section = Section::new();
47+
/// ```
2948
fn new() -> Section {
3049
Section {
3150
handle_line: String::new(),
3251
properties: HashMap::new(),
3352
}
3453
}
54+
/// Check if the section is empty
55+
/// # examples
56+
/// ```
57+
/// section.is_empty()
58+
/// ```
3559
fn is_empty(&self) -> bool {
3660
return self.handle_line.is_empty() && self.properties.is_empty()
3761
}
3862
}
3963

64+
/// State will be used in parsing
65+
/// will indecate how to handle the current line
4066
#[derive(Debug)]
4167
enum State {
4268
Section,
4369
Kv,
4470
List,
4571
}
46-
72+
/// clean string by removing white spaces from the begining
4773
fn clean_str(line :&str) -> String {
4874
let mut i = 0;
4975
for c in line.chars() {
@@ -55,6 +81,7 @@ pub mod dmidecoder {
5581
}
5682
return String::from(line.to_string())
5783
}
84+
/// get the current indentation level by counting the white spaces or taps
5885
fn get_indentation(line :&str) -> u8 {
5986
let mut count = 0;
6087
for c in line.chars() {
@@ -66,7 +93,7 @@ pub mod dmidecoder {
6693
}
6794
return count;
6895
}
69-
96+
/// decide the current state of the line
7097
fn get_state(state :State, line :&str, last_indentation :u8) -> State {
7198
let mut new_state = State::Section;
7299
let indentation = get_indentation(line);
@@ -93,7 +120,7 @@ pub mod dmidecoder {
93120
}
94121
return new_state;
95122
}
96-
123+
// Parse data into sections hashmap
97124
pub fn parse(data :&str) -> HashMap<String, Section> {
98125
let mut sections = HashMap::new();
99126
let mut state = State::Section;
@@ -104,12 +131,17 @@ pub mod dmidecoder {
104131
let mut last_indentation = 0;
105132

106133
for line in data.lines() {
134+
// decide state
107135
let indentation = get_indentation(line);
108136
state = get_state(state, line, last_indentation);
109137
last_indentation = indentation;
138+
// match the state to parse each line
110139
match state {
111140
State::Section => {
112141
if line.starts_with("Handle") {
142+
// when we find handle line this means it's the begining of a new section
143+
// so we will push the last section if it's not empty
144+
// and create another one with the found handle line
113145
if !current_section.is_empty() && !current_section_name.is_empty() {
114146
if !current_property.is_empty() && !current_property_name.is_empty() {
115147
current_section.properties.insert(current_property_name, current_property);
@@ -121,11 +153,13 @@ pub mod dmidecoder {
121153
current_section_name = String::new();
122154
}
123155
current_section.handle_line = clean_str(line);
156+
// if we have the handle line already we will read the follopwing line as the title
124157
} else if !current_section.handle_line.is_empty() && !line.is_empty() {
125158
current_section_name = clean_str(line);
126159
}
127160
},
128161
State::Kv => {
162+
// will check if we have current properety data to push before creating another one from the current line
129163
if !current_property.is_empty() && !current_property_name.is_empty() {
130164
current_section.properties.insert(current_property_name, current_property);
131165
current_property = Property::new();
@@ -141,6 +175,7 @@ pub mod dmidecoder {
141175
}
142176
}
143177
}
178+
// finalize by pushing the last property and the current section if there is data00
144179
if !current_property.is_empty() && !current_property_name.is_empty() {
145180
current_section.properties.insert(current_property_name, current_property);
146181
}

0 commit comments

Comments
 (0)