Python Construct - использовать данные для необязательного поля - PullRequest
2 голосов
/ 29 февраля 2012

С библиотекой Python construct данные, которые я анализирую, имеют поле, которое имеет значение, только если установлен флаг.

Однако поле данных всегда присутствует.

Поэтому я хотел бы использовать данные в любом случае, но установить значение поля только на основе значения флага.

Например, если структура (неправильно) определена как:

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

Спасибо

Ответы [ 2 ]

1 голос
/ 10 июня 2012

Я не уверен, правильно ли я понимаю вашу проблему.Если ваша проблема только в том, что заполнение не анализируется как int, то вам не нужен IFThenElse.Вы можете проверить проанализированный контейнер в вашем коде на наличие флага и выбрать игнорирование поля Additional_data.

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

Если ваша проблема заключается в том, что вы хотите, чтобы имя Дополнительные данные использовалось только тогда, когда установлен флаг, ноимя пустышки, которое будет использоваться, когда флаг не установлен, тогда вам нужно определить два Ifs

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")
)
0 голосов
/ 25 марта 2012

Возможно, вы могли бы использовать Адаптер, подобный адаптеру LengthValue для последовательности

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")
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...