Skip to content

Commit a4a6c6b

Browse files
committed
Initial commit
0 parents  commit a4a6c6b

File tree

3 files changed

+117
-0
lines changed

3 files changed

+117
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/target
2+
**/*.rs.bk
3+
Cargo.lock

Cargo.toml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "mbrman"
3+
version = "0.1.0"
4+
authors = ["Cecile Tonglet <[email protected]>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
bitvec = "0.13"
11+
bincode = "1.0.1"
12+
serde_derive = "1.0.83"
13+
serde = "1.0.83"
14+
err-derive = "0.1.5"

src/lib.rs

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
2+
use serde::de;
3+
use bitvec::prelude::*;
4+
use std::iter::repeat;
5+
use std::convert::TryFrom;
6+
7+
#[derive(Debug, Copy, Clone, PartialEq)]
8+
pub struct CHS {
9+
cylinder: u16,
10+
head: u8,
11+
sector: u8,
12+
}
13+
14+
enum Error {
15+
LBAExceedsMaximumCHS,
16+
}
17+
18+
impl CHS {
19+
fn from_lba(lba: u32, cylinders: u16, heads: u8, sectors: u8) -> Result<CHS, Error> {
20+
// NOTE: code inspired from libfdisk (long2chs)
21+
let cylinders = u32::from(cylinders);
22+
let heads = u32::from(heads);
23+
let sectors = u32::from(sectors);
24+
25+
let cylinder = lba / (heads * sectors);
26+
let rem = lba % (heads * sectors);
27+
let head = rem / sectors;
28+
let sector = rem % sectors + 1;
29+
30+
if cylinder > 1023 {
31+
return Err(Error::LBAExceedsMaximumCHS)
32+
}
33+
34+
Ok(CHS {
35+
cylinder: u16::try_from(cylinder).unwrap(),
36+
head: u8::try_from(head).unwrap(),
37+
sector: u8::try_from(sector).unwrap(),
38+
})
39+
}
40+
}
41+
42+
struct CHSVisitor;
43+
44+
impl<'de> Visitor<'de> for CHSVisitor {
45+
type Value = CHS;
46+
47+
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
48+
formatter.write_str("CHS addressing")
49+
}
50+
51+
fn visit_seq<A>(self, mut seq: A) -> std::result::Result<CHS, A::Error>
52+
where
53+
A: SeqAccess<'de>,
54+
{
55+
let head = BitVec::<BigEndian, u8>::from_element(seq.next_element::<u8>()?.unwrap());
56+
let mut bv = BitVec::<BigEndian, u8>::from_element(seq.next_element::<u8>()?.unwrap());
57+
let mut cylinder = BitVec::<BigEndian, u16>::with_capacity(10);
58+
cylinder.extend(repeat(false).take(6));
59+
cylinder.extend(bv.drain(..2));
60+
cylinder.extend(BitVec::<BigEndian, u8>::from_element(seq.next_element::<u8>()?.unwrap()));
61+
let mut sector = BitVec::<BigEndian, u8>::with_capacity(8);
62+
sector.push(false);
63+
sector.push(false);
64+
sector.extend(bv.drain(..));
65+
66+
Ok(CHS {
67+
cylinder: cylinder.as_slice()[0],
68+
head: head.as_slice()[0],
69+
sector: sector.as_slice()[0],
70+
})
71+
}
72+
}
73+
74+
impl<'de> Deserialize<'de> for CHS {
75+
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
76+
where
77+
D: Deserializer<'de>,
78+
{
79+
deserializer.deserialize_tuple(3, CHSVisitor)
80+
}
81+
}
82+
83+
#[cfg(test)]
84+
mod tests {
85+
use super::*;
86+
use std::io::Cursor;
87+
88+
#[test]
89+
fn it_works() {
90+
let data = &[0xff, 0xff, 0xff, 0xff];
91+
let mut cur = Cursor::new(data);
92+
let chs: CHS = bincode::deserialize_from(&mut cur).unwrap();
93+
assert_eq!(cur.position(), 3);
94+
assert_eq!(chs, CHS {
95+
cylinder: 1023,
96+
head: 255,
97+
sector: 63,
98+
});
99+
}
100+
}

0 commit comments

Comments
 (0)