Я работаю над декодированием сообщений AIS в Rust, используя nom.
Сообщения AIS состоят из битового вектора; различные поля в каждом сообщении имеют произвольное количество битов и не всегда выравниваются по границам байтов.
Затем этот битовый вектор кодируется в кодировке ASCII и вставляется в предложение NMEA.
Из http://catb.org/gpsd/AIVDM.html:
Полезные данные - это битовый вектор в кодировке ASCII. Каждый символ представляет шесть бит данных. Чтобы восстановить шесть битов, вычтите 48 из значения символа ASCII; если результат больше 40, вычтите 8. Согласно [IEC-PAS] допустимые символы ASCII для этой кодировки начинаются с «0» (64) и заканчиваются «w» (87); однако промежуточный диапазон от «X» (88) до «_» (95) не используется.
Пример
!AIVDM,1,1,,A,D03Ovk1T1N>5N8ffqMhNfp0,0*68
- это предложение NMEAD03Ovk1T1N>5N8ffqMhNfp0
- это закодированные данные AIS010100000000000011011111111110110011000001100100000001011110001110000101011110001000101110101110111001011101110000011110101110111000000000
- это декодированные данные AIS в виде битового вектора
Проблемы
Я перечисляю их вместе, потому что думаю, что они могут быть связаны ...
1. Декодирование ASCII в битовый вектор
Я могу сделать это вручную, перебирая символы, вычитая соответствующие значения и создавая байтовый массив, выполняя много операций по сдвигу битов и так далее. Это нормально, но похоже, что я смогу сделать это внутри nom и связать это с фактическим битовым парсером AIS, исключив промежуточный массив байтов.
2. Чтение произвольного количества бит
Можно прочитать, скажем, 3 бита из массива байтов в ном. Но каждый вызов bits!
, кажется, потребляет сразу полный байт (при чтении в 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, а затем управлять им вручную, но опять же, это кажется ненужной дополнительной работой.
bits!
, а затем поместитьbits!
в парсер самого верхнего уровня, который я вызываю. Я напишу больше, если смогу разобраться в части 1. (Прямо сейчас я вручную создаю этот битовый вектор.) - person squidpickles   schedule 15.01.2018bits!
один раз, когда вы меняете режим. - person Dan Hulme   schedule 24.01.2018