nom
версия
Во-первых, извинения за это, игровая площадка имеет только 4.0, и, как следствие, код на этом хранилище github .
Чтобы разобрать что-то подобное, нам нужно объединить два разных анализатора:
take_until
, чтобы принимать байты долибо преамбула, либо EOF tag
, чтобы выделить преамбулу
и комбинатор, preceded
, поэтому мыможет отбросить первый элемент последовательности парсеров.
// Our preamble
const MAGIC:&[u8] = &[0x65, 0x51, 0x48, 0x54, 0x52];
// Our EOF byte sequence
const EOF:&[u8] = &[0xff];
// Shorthand to catch EOF
fn match_to_eof(data: &[u8]) -> nom::IResult<&[u8], &[u8]> {
nom::bytes::complete::take_until(EOF)(data)
}
// Shorthand to catch the preamble
fn take_until_preamble(data: &[u8]) -> nom::IResult<&[u8], &[u8]> {
nom::bytes::complete::take_until(MAGIC)(data)
}
pub fn extract_from_data(data: &[u8]) -> Option<(&[u8], &[u8])> {
let preamble_parser = nom::sequence::preceded(
// Ditch anything before the preamble
take_until_preamble,
nom::sequence::preceded(
// Ditch the preamble
nom::bytes::complete::tag(MAGIC),
// And take until the EOF (0xff)
match_to_eof
)
);
// And we swap the elements because it's confusing AF
// as a return function
preamble_parser(data).ok().map(|r| {
(r.1, r.0)
})
}
Код должен быть достаточно хорошо аннотирован, чтобы следовать. Это отбрасывает любые байты до тех пор, пока не найдет байты преамбулы, затем отбрасывает их и сохраняет все, пока не найдет последовательность байтов EOF ([0xff]
).
Затем возвращает обратное nom
результат, потому что это был пример. Вы можете отменить его, чтобы объединить с другими парсерами, если хотите. Первый элемент - это содержимое последовательности, второй - то, что было после EOF. Это означает, что вы можете выполнять итерации с помощью этой функции (я сделал это в тесте в репозитории, который я поставил на github).