首页 > 解决方案 > 在数据的单次迭代中将二进制结构解析为结构

问题描述

我正在编写一个 rust 库,将 LTV(长度类型值)数据反序列化为 rust 结构。二进制 ltv 对象,例如

L  T  V  L  T    V
02 01 0A 03 02 00 0B

目前正在实施这样的事情:

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)?,
        })
    }
}

这个实现的问题是每次调用read_field都是循环遍历 LTV 结构来查找字段。对于大型物体,这非常慢。我想要做的是让 ltv 数据只需要迭代一次。我的想法是将解析更改为:

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)
}

但是有一些设计问题我不确定如何解决

  1. 如果 LTV 中不存在其中一个字段,则返回错误
  2. 创建没有特征的inst变量Default

在实际的库中,parse函数是从宏生成的,所以我想避免Default需要在字段类型上实现的约束。

标签: rust

解决方案


将值解析为Options,然后检查您是否拥有所有这些值。像这样的东西:

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)?,
    })
}

推荐阅读