use std::io;
use byteorder::{ByteOrder, LE};
use std::net::SocketAddrV4;
mod udp;
pub use self::udp::UdpSource;
mod pcap;
pub use self::pcap::PcapSource;
const PACKET_SIZE: usize = 1206;
const BLOCKS: usize = 12;
const LASERS: usize = 32;
const POINT_SIZE: usize = 3;
const HEADER_SIZE: usize = 2;
const AZIMUTH_SIZE: usize = 2;
const BLOCK_SIZE: usize = HEADER_SIZE + AZIMUTH_SIZE + POINT_SIZE*LASERS; const BLOCKS_SIZE: usize = BLOCKS*BLOCK_SIZE; const STATUS_ID: usize = 1204;
const STATUS_VALUE: usize = 1205;
pub type RawPacket = [u8; PACKET_SIZE];
#[derive(Copy, Clone, Debug)]
pub struct StatusBytes {
pub id: u8,
pub value: u8,
}
#[derive(Debug, Copy, Clone)]
pub struct RawPoint {
pub distance: u16,
pub intensity: u8,
pub laser: u8,
}
#[derive(Debug, Copy, Clone)]
pub struct PacketMeta {
pub azimuth: u16,
pub timestamp: u32,
pub status: StatusBytes,
}
pub fn get_status(data: &RawPacket) -> StatusBytes {
StatusBytes { id: data[STATUS_ID], value: data[STATUS_VALUE] }
}
pub fn parse_packet<'a>(data: &'a RawPacket) -> (
PacketMeta,
impl Iterator<Item=([u8; 2], u16, impl Iterator<Item=RawPoint> + 'a)> + 'a,
) {
let timestamp = LE::read_u32(&data[BLOCKS_SIZE..BLOCKS_SIZE + 4]);
let a0 = LE::read_u16(&data[HEADER_SIZE..HEADER_SIZE+AZIMUTH_SIZE]);
let iter = data[..1200]
.chunks_exact(100)
.map(|block| {
let header = [block[0], block[1]];
let azimuth = LE::read_u16(&block[2..4]);
let block_iter = block[4..100]
.chunks_exact(3)
.enumerate()
.map(|(laser, chunk)| {
let distance = LE::read_u16(&chunk[..2]);
let intensity = chunk[2];
let laser = laser as u8;
RawPoint { distance, intensity, laser }
})
.filter(|point| point.distance != 0);
(header, azimuth, block_iter)
});
let status = get_status(data);
let meta = PacketMeta { azimuth: a0, timestamp, status };
(meta, iter)
}
pub trait PacketSource {
fn next_packet(&mut self) -> io::Result<Option<(SocketAddrV4, &RawPacket)>>;
}