use {
Endianness,
Error,
NamedValue,
Result,
Val,
raw,
unsigned,
};
pub fn dissect(data : &[u8]) -> Result {
if data.len() < 20 {
return Err(Error::Underflow { expected: 20, have: data.len(),
message: "An IP packet must be at least 20 B".to_string() })
}
let mut values:Vec<NamedValue> = vec![];
let version = data[0] >> 4;
values.push(("Version".to_string(), Ok(Val::Unsigned(version as u64))));
let words = data[0] & 0x0f;
values.push(("IHL".to_string(), Ok(Val::Unsigned(words as u64))));
let dscp = data[1] >> 2;
values.push(("DSCP".to_string(), Ok(Val::Unsigned(dscp as u64))));
let ecn = data[1] & 0x03;
values.push(("ECN".to_string(), Ok(Val::Unsigned(ecn as u64))));
let length = unsigned(&data[2..4], Endianness::BigEndian);
values.push(("Length".to_string(), length.map(|v| Val::Unsigned(v))));
values.push(("Identification".to_string(), Ok(Val::Unsigned(data[8] as u64))));
let protocol = data[9];
values.push(("Protocol".to_string(), Ok(Val::Unsigned(protocol as u64))));
values.push(("Checksum".to_string(), Ok(Val::Bytes(data[10..12].to_vec()))));
let source = &data[12..16];
values.push(("Source".to_string(), Ok(Val::Address {
bytes: source.to_vec(),
encoded: source.iter().map(|b| b.to_string()).collect::<Vec<_>>().connect("."),
})));
let dest = &data[16..20];
values.push(("Destination".to_string(), Ok(Val::Address {
bytes: dest.to_vec(),
encoded: dest.iter().map(|b| b.to_string()).collect::<Vec<_>>().connect("."),
})));
let remainder = &data[20..];
let dissect_pdu = match protocol {
_ => raw,
};
values.push(("Protocol Data".to_string(), dissect_pdu(remainder)));
Ok(Val::Object(values))
}