+ let split rows =
+ let rec split rows =
+ bitmatch rows with
+ | { row : 36 * 8 : bitstring
+ ; rows : -1 : bitstring
+ } ->
+ row :: split rows
+ | {_ : 0 : bitstring} ->
+ []
+ in
+ if Bitstring.bitstring_length rows mod 36 = 0 then
+ split rows
+ else
+ failwith "Packet_length_invalid"
+
+ let of_bitstring bits =
+ bitmatch bits with
+ | { "DATA" : 4 * 8 : string
+ ; "@" : 1 * 8 : string
+ ; rows : -1 : bitstring
+ } ->
+ let rows = split rows in
+ List.map rows ~f:Row.of_bitstring
+ | { "DATA" : 4 * 8 : string
+ ; _ : 1 * 8 : string
+ ; _ : -1 : bitstring
+ } ->
+ failwith "Packet_index_byte_unsupported"
+ | {_} ->
+ failwith "Packet_unrecognized"
+
+ let of_string s =
+ of_bitstring (Bitstring.bitstring_of_string s)
+end
+
+let sample_packets_base64 =
+ [ "REFUQUADAAAAbcpGQLt81EBfZNlATnUoNwDAecSow2RAnCv6QLrbQTcRAAAA3i8VQFL3ZT6dPfFCx4IFQwDAecQAwHnEAMB5xADAecQUAAAA1ZciQg6ik8JGBv9AdDxoPgAAgD9G/o3CAAAgQgAAlsI="
+ ; "REFUQUADAAAAzqjrQknD60JR+O5C7ZfuQgDAecSTmAdDOoAJQyJJCUMRAAAAXRhvv591jsFLRJhDAgWfQwDAecQAwHnEAMB5xADAecQUAAAAjaMiQveok8LRbtxC6EfIQgAAAAAj2cpCAAAgQgAAlsI="
+ ; "REFUQUADAAAAzqjrQr3J60I1/+5CHLruQgDAecSTmAdDMYQJQ8JdCUMRAAAAuRT1viXUasG1IphDaeOeQwDAecQAwHnEAMB5xADAecQUAAAAoqMiQg6pk8LnP91CnEPJQgAAgD8Xo8tCAAAgQgAAlsI="
+ ; "REFUQUADAAAAzqngQlS14EJH0uNC1j3jQgDAecTaRAFDChYDQ0XjAkMRAAAAyAVbwD2F40D9o5hDw2OfQwDAecQAwHnEAMB5xADAecQUAAAAabAiQmGzk8KHqPtCUffQQgAAgD+gHOxCAAAgQgAAlsI="
+ ; "REFUQUADAAAAztfrQgj060IIWO9C3ZvuQgDAecSeswdDTLcJQx9SCUMRAAAAOHQSv6Pb98B47plDj66gQwDAecQAwHnEAMB5xADAecQUAAAAna0iQmSwk8L9HyFDSWYPQwAAgD993xhDAAAgQgAAlsI="
+ ; "REFUQUADAAAAzv7OQngMz0JiytFCPCPTQgDAecS7NO5CNGzxQj798kIRAAAAYSvYv6xFF0HmNZND+vSZQwDAecQAwHnEAMB5xADAecQUAAAAubUiQqm5k8KdoKhC7QVrQgAAgD8gY5lCAAAgQgAAlsI="
+ ; "REFUQUADAAAAzwhhQveKYUKRQ2RCrX5iQgDAecSEe4FCOleDQqlSgkIRAAAA52WSP04IoL8625ZDu56dQwDAecQAwHnEAMB5xADAecQUAAAAKIQiQlKMk8Lv3/pA6leoPgAAgD/0ZwrAAAAgQgAAlsI="
+ ; "REFUQUADAAAAzxOEQlE+hELg1oVCLBOFQgDAecTw/ZdCAwWaQusjmUIRAAAAIbAwv9Vvm8CwrJZDIXCdQwDAecQAwHnEAMB5xADAecQUAAAAqYQiQuOMk8IABAFBf1gDPwAAgD9YJve/AAAgQgAAlsI="
+ ; "REFUQUADAAAAzybdQm4t3UJ7POBC6pvfQgDAecQpf/5C8wUBQ8m7AEMRAAAAFUxfP6uiNb6HV5lDPxegQwDAecQAwHnEAMB5xADAecQUAAAA+LAiQumzk8JhAflCuZfOQgAAgD9azehCAAAgQgAAlsI="
+ ; "REFUQUADAAAAzzXpQXNs6kEZau1BalvYQQDAecTPLwZCGJsIQngD+UERAAAABIOrP1nfGr0X7qpDY6yxQwDAecQAwHnEAMB5xADAecQUAAAAlbwiQgPBk8JTQExC0iGDPgAAgD+EOi9CAAAgQgAAlsI="
+ ; "REFUQUADAAAAzzyRQNGvwUDwBcRA3GiMQADAecTpIqdAWZThQLaUoUARAAAAoQokQCjkLr5IGZZD6NycQwDAecQAwHnEAMB5xADAecQUAAAAEoMiQimLk8Jy4fZAaipjPgAAgD82RhLAAAAgQgAAlsI="
+ ]