1use std::fs::File;
4use std::iter::IntoIterator;
5use std::io::{BufReader, Read};
6use std::path::Path;
7use std::str;
8
9use byteorder;
10use byteorder::{LittleEndian, ReadBytesExt};
11
12use error::Error;
13use point::{Point, TargetType};
14use result::Result;
15
16#[derive(Debug)]
20pub struct Reader<R: Read> {
21 reader: R,
22 version: Version,
23 header_information: Vec<u8>,
24}
25
26#[derive(Clone, Copy, Debug)]
28pub struct Version {
29 pub major: u16,
31 pub minor: u16,
33}
34
35impl Reader<BufReader<File>> {
36 pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Reader<BufReader<File>>> {
45 let reader = BufReader::new(try!(File::open(path)));
46 Reader::new(reader)
47 }
48}
49
50impl<R: Read> Reader<R> {
51 pub fn new(mut reader: R) -> Result<Reader<R>> {
62 let header_size = try!(reader.read_u32::<LittleEndian>());
63 let major = try!(reader.read_u16::<LittleEndian>());
64 if major != 5 {
65 return Err(Error::InvalidMajorVersion(major));
66 }
67 let minor = try!(reader.read_u16::<LittleEndian>());
68 let header_information_size = header_size - 8;
69 let mut header_information = Vec::with_capacity(header_information_size as usize);
70 if try!(reader.by_ref()
71 .take(header_information_size as u64)
72 .read_to_end(&mut header_information)) !=
73 header_information_size as usize {
74 return Err(Error::InvalidHeaderInformation);
75 }
76 Ok(Reader {
77 reader: reader,
78 version: Version { major: major, minor: minor, },
79 header_information: header_information,
80 })
81 }
82
83 pub fn next_point(&mut self) -> Result<Option<Point>> {
93 let time = match self.reader.read_f64::<LittleEndian>() {
96 Ok(time) => time,
97 Err(byteorder::Error::UnexpectedEOF) => return Ok(None),
98 Err(err) => return Err(Error::from(err)),
99 };
100 let range = try!(self.reader.read_f32::<LittleEndian>());
101 let theta = try!(self.reader.read_f32::<LittleEndian>());
102 let x = try!(self.reader.read_f32::<LittleEndian>());
103 let y = try!(self.reader.read_f32::<LittleEndian>());
104 let z = try!(self.reader.read_f32::<LittleEndian>());
105 let amplitude = try!(self.reader.read_u16::<LittleEndian>());
106 let width = try!(self.reader.read_u16::<LittleEndian>());
107 let target_type = try!(TargetType::from_u8(try!(self.reader.read_u8())));
108 let target = try!(self.reader.read_u8());
109 let num_target = try!(self.reader.read_u8());
110 let rg_index = try!(self.reader.read_u16::<LittleEndian>());
111 let channel_desc_byte = try!(self.reader.read_u8());
112 let mut class_id = None;
113 let mut rho = None;
114 let mut reflectance = None;
115 if self.version.major >= 5 && self.version.minor >= 2 {
116 class_id = Some(try!(self.reader.read_u8()));
117 }
118 if self.version.major >= 5 && self.version.minor >= 3 {
120 rho = Some(try!(self.reader.read_f32::<LittleEndian>()));
121 }
122 if self.version.major >= 5 && self.version.minor >= 4 {
123 reflectance = Some(try!(self.reader.read_i16::<LittleEndian>()));
124 }
125 Ok(Some(Point {
126 time: time,
127 range: range,
128 theta: theta,
129 x: x,
130 y: y,
131 z: z,
132 amplitude: amplitude,
133 width: width,
134 target_type: target_type,
135 target: target,
136 num_target: num_target,
137 rg_index: rg_index,
138 facet_number: channel_desc_byte & 0x3,
139 high_channel: (channel_desc_byte & 0b01000000) == 0b01000000,
140 class_id: class_id,
141 rho: rho,
142 reflectance: reflectance
143 }))
144 }
145
146 pub fn version(&self) -> Version {
156 self.version
157 }
158
159 pub fn header_information_as_str(&self) -> Result<&str> {
169 str::from_utf8(&self.header_information[..]).map_err(|e| Error::from(e))
170 }
171}
172
173impl<R: Read> IntoIterator for Reader<R> {
174 type Item = Point;
175 type IntoIter = PointIterator<R>;
176 fn into_iter(self) -> Self::IntoIter {
177 PointIterator { reader: self }
178 }
179}
180
181#[derive(Debug)]
183pub struct PointIterator<R: Read> {
184 reader: Reader<R>,
185}
186
187impl<R: Read> Iterator for PointIterator<R> {
188 type Item = Point;
189 fn next(&mut self) -> Option<Self::Item> {
190 self.reader.next_point().unwrap()
191 }
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197
198 #[test]
199 fn read_points() {
200 let reader = Reader::from_path("data/4-points-5.0.sdc").unwrap();
201 let points: Vec<_> = reader.into_iter().collect();
202 assert_eq!(4, points.len());
203 }
204
205 #[test]
206 fn read_52() {
207 let reader = Reader::from_path("data/4-points-5.2.sdc").unwrap();
208 let points: Vec<_> = reader.into_iter().collect();
209 assert_eq!(4, points.len());
210 assert_eq!(4, points[0].class_id.unwrap());
211 }
212}