Reputation: 3414
I am writing a library in rust to deserialize LTV (length type value) data into a struct in rust. An binary ltv object like
L T V L T V
02 01 0A 03 02 00 0B
is currently being implemented something like this:
struct LTVObject{
pub field_1: u8,
pub field_2: u16,
}
impl LTVObject {
pub fn parse(r: &LtvReader) -> LTVResult<Self>{
Ok(LTVObject {
field_1: r.read_field(1)?,
field_2: r.read_field(2)?,
})
}
}
The problem with this implementation is every call to read_field
is looping through the LTV structure to find the field. For large objects, this is very slow. What I want to do is make it so that ltv data only needs to be iterated once. My thinking is to change the parsing to:
pub fn parse(r: &LtvReader) -> LTVResult<Self>{
let mut inst = Self{ ... };
for field in r.get_fields(){
match field.id {
1 => inst.field_1 = field.get_value()?,
2 => inst.field_2 = field.get_value()?,
}
}
Ok(inst)
}
However there are a few design problems im unsure how to resolve
inst
variable without the Default
traitIn the actual library, the parse
function is generated from a macro so I would like to avoid having the constraint that Default
needs to be implemented on the field types.
Upvotes: 0
Views: 465
Reputation: 58735
Parse the values into Option
s and then check that you have them all. Something like this:
pub fn parse(r: &LtvReader) -> LTVResult<Self> {
let mut field_1 = None;
let mut field_2 = None;
for field in r.get_fields(){
match field.id {
1 => field_1 = Some(field.get_value()?),
2 => field_2 = Some(field.get_value()?),
}
}
Ok(LTVObject {
field_1: field_1.ok_or(Error::MissingField)?,
field_2: field_2.ok_or(Error::MissingField)?,
})
}
Upvotes: 1