3

我正在使用nom解码Rust 中的AIS消息。

AIS 消息由位向量组成;每条消息中的各个字段都是任意数量的位长,并且它们并不总是在字节边界上对齐。

然后这个位向量被 ASCII 编码,并嵌入到NMEA语句中。

来自http://catb.org/gpsd/AIVDM.html

数据有效载荷是一个 ASCII 编码的位向量。每个字符代表六位数据。要恢复六位,请从 ASCII 字符值中减去 48;如果结果大于 40,则减去 8。根据 [IEC-PAS],此编码的有效 ASCII 字符以“0”(64)开头,以“w”(87)结尾;但是,不使用中间范围“X”(88)到“_”(95)。

例子

  • !AIVDM,1,1,,A,D03Ovk1T1N>5N8ffqMhNfp0,0*68是 NMEA 句子
  • D03Ovk1T1N>5N8ffqMhNfp0是编码的 AIS 数据
  • 010100000000000011011111111110110011000001100100000001011110001110000101011110001000101110101110111001011101110000011110101110111000000000是解码后的 AIS 数据作为位向量

问题

我把这些列在一起是因为我认为它们可能是相关的……

1. 将 ASCII 解码为位向量

我可以手动完成,通过迭代字符,减去适当的值,并通过做大量的位移工作来构建一个字节数组,等等。这很好,但似乎我应该能够在 nom 中执行此操作,并将其与实际的 AIS 位解析器链接起来,从而消除临时字节数组。

2.读取任意位数

例如,可以从 nom 字节数组中读取 3 位。但是,每次调用bits!似乎一次消耗一个完整的字节(如果读入 a u8)。

例如:

named!(take_3_bits<u8>, bits!(take_bits!(u8, 3)));

将 3 位读入u8. 但如果我运行take_3_bits两次,我将消耗 16 位流。

我可以结合阅读:

named!(get_field_1_and_2<(u8, u8)>, bits!(pair!(take_bits!(u8, 2), take_bits!(u8, 3))));

调用get_field_1_and_2会给我一个(u8, u8)元组,其中第一项包含前 2 位,第二项包含接下来的 3 位,但 nom 在读取后仍将前进一个完整字节。

我可以peek用来阻止 nom 的读取指针前进,然后手动管理它,但同样,这似乎是不必要的额外工作。

4

0 回答 0