Условный анализ массива на основе предыдущих элементов с помощью nom
Мне нужно проанализировать массив 32-битных целых чисел (с прямым порядком байтов) из массива u8s, однако следующий тип int существует, только если установлен 31-й бит текущего типа int. Если остальные не существуют, тогда остальная часть массива должна быть установлена в нули. Я не уверен, как сделать условный анализ следующего элемента.
Допустим, поле имеет длину 4 байта. Тогда результатом функции parse_field будет то, что 4 байта будут проанализированы с le_u32, и это будет первый элемент в [u32; 8] массив. Если, однако, установлен 31-й бит этого поля. Затем существует еще 4 байта, которые также похожи на это поле, и они входят в следующий элемент массива. Если он не установлен, то функция должна возвращать массив с остальными элементами, установленными на ноль. И это продолжается для каждого существующего поля.
Например, для следующего ввода:
0x8000000a
0x8000000b
...
Вы бы получили [0x8000000a, 0x8000000b, 0, 0, 0, 0, 0, 0]
Но если вход
0x8000000a
0x8000000b
0x8000000c
0x8000000d
0x8000000e
....
Тогда вы получите [0x8000000a, 0x8000000b, 0x8000000c, 0x8000000d, 0x8000000e, 0, 0, 0]
extern crate nom;
use nom::*;
#[derive(Clone, Copy, Debug)]
struct Derp {
field: [u32; 8]
}
named!(parse_field<[u32; 8]>,
// what do I do here
);
named!(parse_derp<Derp>,
do_parse!(
field: parse_field >>
(Derp {
field: field
})
)
);
fn main() {
let temp = [0x0a, 0x00, 0x00, 0x80, 0x0b, 0x00, 0x00, 0x80];
println!("{:?}", parse_derp(&temp));
}
Также, возможно, лучше использовать Vec здесь?
1 ответ
Вот парсер, который соответствует последнему u32
вашего вклада:
named!(last_u32<u32>,
verify!(le_u32, |n:u32| (n & 0b1) != 0) // Matches iff the 31st bit is set
);
затем вы можете использовать его так:
named!(parse_field<Vec<u32>>,
map!(
many_till!(le_u32, last_u32),
|(mut v,n)| { v.push(n); v } // Add the last u32 to the vector
)
);