2

使用 Python构造库,我正在解析的数据有一个字段,该字段仅在设置标志时才有意义。

但是,数据字段始终存在。

因此,无论如何我都想使用数据,但只根据标志的值设置字段值。

例如,如果结构(错误地)定义为:

struct = Struct("struct",
    Flag("flag"),
    UBInt8("optional_data"),
    UBInt8("mandatory")
)

对于数据:

>>> struct.parse("010203".decode("hex"))

结果应该是:

Container({'flag': True, 'mandatory': 3, 'optional_data': 2})

对于数据:

>>> struct.parse("000203".decode("hex"))

期望的结果是:

Container({'flag': False, 'mandatory': 3, 'optional_data': None})

我尝试了以下方法:

struct = Struct("struct",
    Flag("flag"),
    IfThenElse("optional_data", lambda ctx: ctx.flag,
        UBInt8("dummy"),
        Padding(1)
    ),
    UBInt8("mandatory")
)

但是,Padding() 将原始数据放在字段中,如下所示:

>>> struct.parse("000203".decode("hex"))
Container({'flag': False, 'mandatory': 3, 'optional_data': '\x02'})

谢谢

4

2 回答 2

1

我不确定我是否正确理解了您的问题。如果您的问题只是填充没有被解析为 int,那么您不需要 IFthenElse。您可以在代码中检查已解析容器的标志并选择忽略 optional_data 字段。

struct = Struct("struct",
    Flag("flag"),
    UBInt8("optional_data"),
    UBInt8("mandatory")
)

如果您的问题是您希望仅在设置标志时使用名称 Optional Data 而在未设置标志时使用名称 dummy,那么您需要定义两个 If

struct = Struct("struct",
    Flag("flag"),
    If("optional_data", lambda ctx: ctx.flag,
        UBInt8("useful_byte"),
    ),
    If("dummy", lambda ctx: !ctx.flag,
        UBInt8("ignore_byte"),
    ),
    UBInt8("mandatory")
)
于 2012-06-10T17:24:39.660 回答
0

也许您可以将类似于 LengthValueAdapter 的适配器用于序列

class LengthValueAdapter(Adapter):
"""
Adapter for length-value pairs. It extracts only the value from the 
pair, and calculates the length based on the value.
See PrefixedArray and PascalString.

Parameters:
* subcon - the subcon returning a length-value pair
"""
__slots__ = []
def _encode(self, obj, context):
    return (len(obj), obj)
def _decode(self, obj, context):
    return obj[1]

class OptionalDataAdapter(Adapter):
__slots__ = []
def _decode(self, obj, context):
  if context.flag:
    return obj
  else
    return None

所以

struct = Struct("struct",
    Flag("flag"),
    OptionalDataAdapter(UBInt8("optional_data")),
    UBInt8("mandatory")
)
于 2012-03-25T08:40:44.967 回答