ply_rs/parser/
mod.rs

1//! Reads ascii or binary data into a `Ply`.
2
3use std::io;
4use std::io::{ Read, BufReader };
5use std::fmt::Debug;
6use std::result;
7
8use std::io::{ BufRead, Result, ErrorKind };
9
10mod ply_grammar;
11
12use self::ply_grammar::grammar;
13use self::ply_grammar::Line;
14use crate::util::LocationTracker;
15
16fn parse_ascii_rethrow<T, E: Debug>(location: &LocationTracker, line_str: &str, e: E, message: &str) -> Result<T> {
17    Err(io::Error::new(
18        ErrorKind::InvalidInput,
19        format!("Line {}: {}\n\tString: '{}'\n\tError: {:?}", location.line_index, message, line_str, e)
20    ))
21}
22fn parse_ascii_error<T>(location: &LocationTracker, line_str: &str, message: &str) -> Result<T> {
23    Err(io::Error::new(
24        ErrorKind::InvalidInput,
25        format!("Line {}: {}\n\tString: '{}'", location.line_index, message, line_str)
26    ))
27}
28
29use std::marker::PhantomData;
30
31/// Reads data given by a `Read` trait into `Ply` components.
32///
33/// In most cases `read_ply()` should suffice.
34/// If you need finer control over the read process,
35/// there are methods down to the line/element level.
36///
37/// # Examples
38///
39/// The most common case is probably to read from a file:
40///
41/// ```rust
42/// # use ply_rs::*;
43/// // set up a reader, in this case a file.
44/// let path = "example_plys/greg_turk_example1_ok_ascii.ply";
45/// let mut f = std::fs::File::open(path).unwrap();
46///
47/// // create a parser
48/// let p = parser::Parser::<ply::DefaultElement>::new();
49///
50/// // use the parser: read the entire file
51/// let ply = p.read_ply(&mut f);
52///
53/// // Did it work?
54/// assert!(ply.is_ok());
55/// ```
56///
57/// If you need finer control, you can start splitting the read operations down to the line/element level.
58///
59/// In the follwoing case we first read the header, and then continue with the payload.
60/// We need to build a Ply our selves.
61///
62/// ```rust
63/// # use ply_rs::*;
64/// // set up a reader as before.
65/// // let mut f = ... ;
66/// # let path = "example_plys/greg_turk_example1_ok_ascii.ply";
67/// # let f = std::fs::File::open(path).unwrap();
68/// // We need to wrap our `Read` into something providing `BufRead`
69/// let mut buf_read = std::io::BufReader::new(f);
70///
71/// // create a parser
72/// let p = parser::Parser::<ply::DefaultElement>::new();
73///
74/// // use the parser: read the header
75/// let header = p.read_header(&mut buf_read);
76/// // Did it work?
77/// let header = header.unwrap();
78///
79/// // read the payload
80/// let payload = p.read_payload(&mut buf_read, &header);
81/// // Did it work?
82/// let payload = payload.unwrap();
83///
84/// // May be create your own Ply:
85/// let ply = ply::Ply {
86///     header: header,
87///     payload: payload,
88/// };
89///
90/// println!("Ply: {:#?}", ply);
91/// ```
92///
93pub struct Parser<E: PropertyAccess> {
94      phantom: PhantomData<E>,
95}
96
97
98//use std::marker::PhantomData;
99//use std::io::{ Read, BufReader };
100use crate::ply::Ply;
101use crate::ply::{ Header, Payload, Encoding };
102
103impl<E: PropertyAccess> Parser<E> {
104    /// Creates a new `Parser<E>`, where `E` is the type to store the element data in.
105    ///
106    /// To get started quickly try `DefaultElement` from the `ply` module.
107    pub fn new() -> Self {
108        Parser {
109            phantom: PhantomData
110        }
111    }
112
113    /// Expects the complete content of a PLY file.
114    ///
115    /// A PLY file starts with "ply\n". `read_ply` reads until all elements have been read as
116    /// defined in the header of the PLY file.
117    pub fn read_ply<T: Read>(&self, source: &mut T) -> Result<Ply<E>> {
118        let mut source = BufReader::new(source);
119        let mut location = LocationTracker::new();
120        let header = self.__read_header(&mut source, &mut location)?;
121        let payload = self.__read_payload(&mut source, &mut location, &header)?;
122        let mut ply = Ply::new();
123        ply.header = header;
124        ply.payload = payload;
125        Ok(ply)
126    }
127}
128
129// use ply::{ Header, Encoding };
130use crate::ply::{ PropertyAccess, Version, ObjInfo, Comment, ElementDef, KeyMap, Addable };
131/*
132use util::LocationTracker;
133use super::Parser;
134use super::Line;
135use super::grammar;
136use super::{parse_ascii_error, parse_ascii_rethrow};
137use std::io;
138use std::io::{ BufRead, ErrorKind, Result };
139use std::result;
140// */
141
142// ////////////////////////
143/// #Header
144// ////////////////////////
145impl<E: PropertyAccess> Parser<E> {
146    /// Reads header until and inclusive `end_header`.
147    ///
148    /// A ply file starts with "ply\n". The header and the payload are separated by a line `end_header\n`.
149    /// This method reads all headere elemnts up to `end_header`.
150    pub fn read_header<T: BufRead>(&self, reader: &mut T) -> Result<Header> {
151        let mut line = LocationTracker::new();
152        self.__read_header(reader, &mut line)
153    }
154    pub fn read_header_line(&self, line: &str) -> Result<Line> {
155        match self.__read_header_line(line) {
156            Ok(l) => Ok(l),
157            Err(e) => Err(io::Error::new(
158                ErrorKind::InvalidInput,
159                format!("Couldn't parse line.\n\tString: {}\n\tError: {:?}", line, e)
160            )),
161        }
162    }
163
164    // private
165    fn __read_header_line(&self, line_str: &str) -> result::Result<Line, peg::error::ParseError<peg::str::LineCol>> {
166        grammar::line(line_str)
167    }
168    fn __read_header<T: BufRead>(&self, reader: &mut T, location: &mut LocationTracker) -> Result<Header> {
169        location.next_line();
170        let mut line_str = String::new();
171        reader.read_line(&mut line_str)?;
172        match self.__read_header_line(&line_str) {
173            Ok(Line::MagicNumber) => (),
174            Ok(l) => return parse_ascii_error(location, &line_str, &format!("Expected magic number 'ply', but saw '{:?}'.", l)),
175            Err(e) => return parse_ascii_rethrow(location, &line_str, e, "Expected magic number 'ply'.")
176        }
177        match grammar::line(&line_str) {
178            Err(e) => return Err(io::Error::new(ErrorKind::InvalidInput, e)),
179            Ok(l @ Line::MagicNumber) => (l),
180            Ok(ob) => return Err(io::Error::new(
181                ErrorKind::InvalidInput,
182                format!("Invalid line encountered. Expected type: 'Line::MagicNumber', found: '{:?}'", ob)
183            )),
184        };
185
186        let mut header_form_ver : Option<(Encoding, Version)> = None;
187        let mut header_obj_infos = Vec::<ObjInfo>::new();
188        let mut header_elements = KeyMap::<ElementDef>::new();
189        let mut header_comments = Vec::<Comment>::new();
190        location.next_line();
191        'readlines: loop {
192            line_str.clear();
193            reader.read_line(&mut line_str)?;
194            let line = self.__read_header_line(&line_str);
195
196            match line {
197                Err(e) => return parse_ascii_rethrow(location, &line_str, e, "Couldn't parse line."),
198                Ok(Line::MagicNumber) => return parse_ascii_error(location, &line_str, "Unexpected 'ply' found."),
199                Ok(Line::Format(ref t)) => (
200                    if header_form_ver.is_none() {
201                        header_form_ver = Some(t.clone());
202                    } else {
203                        let f = header_form_ver.unwrap();
204                        if f != *t {
205                            return parse_ascii_error(
206                                location,
207                                &line_str,
208                                &format!(
209                                    "Found contradicting format definition:\n\
210                                    \tEncoding: {:?}, Version: {:?}\n\
211                                    previous definition:\n\
212                                    \tEncoding: {:?}, Version: {:?}",
213                                    t.0, t.1, f.0, f.1)
214                            )
215                        }
216                    }
217                ),
218                Ok(Line::ObjInfo(ref o)) => (
219                    header_obj_infos.push(o.clone())
220                ),
221                Ok(Line::Comment(ref c)) => (
222                    header_comments.push(c.clone())
223                ),
224                Ok(Line::Element(ref e)) => {
225                    header_elements.add(e.clone())
226                },
227                Ok(Line::Property(p)) => (
228                    if header_elements.is_empty() {
229                        return parse_ascii_error(
230                            location,
231                            &line_str,
232                            &format!("Property '{:?}' found without preceding element.", p)
233                        );
234                    } else {
235                        let (_, mut e) = header_elements.pop_back().unwrap();
236                        e.properties.add(p);
237                        header_elements.add(e);
238                    }
239                ),
240                Ok(Line::EndHeader) => { location.next_line(); break 'readlines; },
241            };
242            location.next_line();
243        }
244        if header_form_ver.is_none() {
245            return Err(io::Error::new(
246                ErrorKind::InvalidInput,
247                "No format line found."
248            ));
249        }
250        let (encoding, version) = header_form_ver.unwrap();
251        Ok(Header{
252            encoding: encoding,
253            version: version,
254            obj_infos: header_obj_infos,
255            comments: header_comments,
256            elements: header_elements
257        })
258    }
259}
260
261// //////////////////////
262/// # Payload
263// //////////////////////
264
265impl<E: PropertyAccess> Parser<E> {
266    /// Reads payload. Encoding is chosen according to the encoding field in `header`.
267    pub fn read_payload<T: BufRead>(&self, reader: &mut T, header: &Header) -> Result<Payload<E>> {
268        let mut location = LocationTracker::new();
269        self.__read_payload(reader, &mut location, header)
270    }
271    /// Reads entire list of elements from payload. Encoding is chosen according to `header`.
272    ///
273    /// Make sure to read the elements in the order as they are defined in the header.
274    pub fn read_payload_for_element<T: BufRead>(&self, reader: &mut T, element_def: &ElementDef, header: &Header) -> Result<Vec<E>> {
275        let mut location = LocationTracker::new();
276        match header.encoding {
277            Encoding::Ascii => self.__read_ascii_payload_for_element(reader, &mut location, element_def),
278            Encoding::BinaryBigEndian => self.__read_big_endian_payload_for_element(reader, &mut location, element_def),
279            Encoding::BinaryLittleEndian => self.__read_little_endian_payload_for_element(reader, &mut location, element_def),
280        }
281    }
282    /// internal dispatcher based on the encoding
283    fn __read_payload<T: BufRead>(&self, reader: &mut T, location: &mut LocationTracker, header: &Header) -> Result<Payload<E>> {
284        let mut payload = Payload::new();
285        match header.encoding {
286            Encoding::Ascii => for (k, ref e) in &header.elements {
287                let elems = self.__read_ascii_payload_for_element(reader, location, e)?;
288                payload.insert(k.clone(), elems);
289            },
290            Encoding::BinaryBigEndian => for (k, ref e) in &header.elements {
291                let elems = self.__read_big_endian_payload_for_element(reader, location, e)?;
292                payload.insert(k.clone(), elems);
293            },
294            Encoding::BinaryLittleEndian => for (k, ref e) in &header.elements {
295                let elems = self.__read_little_endian_payload_for_element(reader, location, e)?;
296                payload.insert(k.clone(), elems);
297            }
298        }
299        Ok(payload)
300    }
301}
302
303
304
305// ////////////////////////////////////////////////////////////////
306// # Ascii
307// ////////////////////////////////////////////////////////////////
308
309/*
310use std::io;
311use std::io::{ BufRead, Result, ErrorKind };
312use super::Parser;
313use super::grammar;
314use super::parse_ascii_rethrow;
315use util::LocationTracker;
316use ply::{ PropertyAccess, ElementDef };
317// */
318
319use std::slice::Iter;
320use std::str::FromStr;
321
322use crate::ply::{ Property, PropertyType, ScalarType };
323use std::error;
324use std::marker;
325
326/// # Ascii
327impl<E: PropertyAccess> Parser<E> {
328    fn __read_ascii_payload_for_element<T: BufRead>(&self, reader: &mut T, location: &mut LocationTracker, element_def: &ElementDef) -> Result<Vec<E>> {
329        let mut elems = Vec::<E>::new();
330        let mut line_str = String::new();
331        for _ in 0..element_def.count {
332            line_str.clear();
333            reader.read_line(&mut line_str)?;
334
335            let element = match self.read_ascii_element(&line_str, element_def) {
336                Ok(e) => e,
337                Err(e) => return parse_ascii_rethrow(location, &line_str, e, "Couln't read element line.")
338            };
339            elems.push(element);
340            location.next_line();
341        }
342        Ok(elems)
343    }
344    /// Read a single element. Assume it is encoded in ascii.
345    ///
346    /// Make sure all elements are parsed in the order they are defined in the header.
347    pub fn read_ascii_element(&self, line: &str, element_def: &ElementDef) -> Result<E> {
348        let elems = match grammar::data_line(line) {
349            Ok(e) => e,
350            Err(ref e) => return Err(io::Error::new(
351                    ErrorKind::InvalidInput,
352                    format!("Couldn't parse element line.\n\tString: '{}'\n\tError: {}", line, e)
353                )),
354        };
355
356        let mut elem_it : Iter<String> = elems.iter();
357        let mut vals = E::new();
358        for (k, p) in &element_def.properties {
359            let new_p : Property = self.__read_ascii_property(&mut elem_it, &p.data_type)?;
360            vals.set_property(k.clone(), new_p);
361        }
362        Ok(vals)
363    }
364    fn __read_ascii_property(&self, elem_iter: &mut Iter<String>, data_type: &PropertyType) -> Result<Property> {
365        let s : &String = match elem_iter.next() {
366            None => return Err(io::Error::new(
367                ErrorKind::InvalidInput,
368                format!("Expected element of type '{:?}', but found nothing.", data_type)
369            )),
370            Some(x) => x
371        };
372
373        let result = match *data_type {
374            PropertyType::Scalar(ref scalar_type) => match *scalar_type {
375                ScalarType::Char => Property::Char(self.parse(s)?),
376                ScalarType::UChar => Property::UChar(self.parse(s)?),
377                ScalarType::Short => Property::Short(self.parse(s)?),
378                ScalarType::UShort => Property::UShort(self.parse(s)?),
379                ScalarType::Int => Property::Int(self.parse(s)?),
380                ScalarType::UInt => Property::UInt(self.parse(s)?),
381                ScalarType::Float => Property::Float(self.parse(s)?),
382                ScalarType::Double => Property::Double(self.parse(s)?),
383            },
384            PropertyType::List(_, ref scalar_type) => {
385                let count : usize = self.parse(s)?;
386                match *scalar_type {
387                    ScalarType::Char => Property::ListChar(self.__read_ascii_list(elem_iter, count)?),
388                    ScalarType::UChar => Property::ListUChar(self.__read_ascii_list(elem_iter, count)?),
389                    ScalarType::Short => Property::ListShort(self.__read_ascii_list(elem_iter, count)?),
390                    ScalarType::UShort => Property::ListUShort(self.__read_ascii_list(elem_iter, count)?),
391                    ScalarType::Int => Property::ListInt(self.__read_ascii_list(elem_iter, count)?),
392                    ScalarType::UInt => Property::ListUInt(self.__read_ascii_list(elem_iter, count)?),
393                    ScalarType::Float => Property::ListFloat(self.__read_ascii_list(elem_iter, count)?),
394                    ScalarType::Double => Property::ListDouble(self.__read_ascii_list(elem_iter, count)?),
395                }
396            }
397        };
398        Ok(result)
399    }
400
401    fn parse<D: FromStr>(&self, s: &str) -> Result<D>
402    where <D as FromStr>::Err: error::Error + Send + Sync + 'static {
403        let v = s.parse();
404        match v {
405            Ok(r) => Ok(r),
406            Err(e) => Err(io::Error::new(ErrorKind::InvalidInput,
407                format!("Parse error.\n\tValue: '{}'\n\tError: {:?}, ", s, e))),
408        }
409    }
410    fn __read_ascii_list<D: FromStr>(&self, elem_iter: &mut Iter<String>, count: usize) -> Result<Vec<D>>
411        where <D as FromStr>::Err: error::Error + marker::Send + marker::Sync + 'static {
412        let mut list = Vec::<D>::new();
413        for i in 0..count {
414            let s : &String = match elem_iter.next() {
415                None => return Err(io::Error::new(
416                    ErrorKind::InvalidInput,
417                    format!("Couldn't find a list element at index {}.", i)
418                )),
419                Some(x) => x
420            };
421            let value : D = self.parse(s)?;
422            list.push(value);
423        }
424        Ok(list)
425    }
426}
427
428// //////////////////////////////////////
429// # Binary
430// //////////////////////////////////////
431/*
432use std::io;
433use std::io::{ Read, Result, ErrorKind };
434use std::str::FromStr;
435use std::error;
436use std::marker;
437use ply::{ PropertyAccess, ElementDef, PropertyType, Property, ScalarType };
438use util::LocationTracker;
439use super::Parser;
440*/
441use byteorder::{ BigEndian, LittleEndian, ReadBytesExt, ByteOrder };
442use peg;
443
444/// # Binary
445impl<E: PropertyAccess> Parser<E> {
446    /// Reads a single element as declared in èlement_def. Assumes big endian encoding.
447    ///
448    /// Make sure all elements are parsed in the order they are defined in the header.
449    pub fn read_big_endian_element<T: Read>(&self, reader: &mut T, element_def: &ElementDef) -> Result<E> {
450        // Reduce coupling with ByteOrder
451        self.__read_binary_element::<T, BigEndian>(reader, element_def)
452    }
453    /// Reads a single element as declared in èlement_def. Assumes big endian encoding.
454    ///
455    /// Make sure all elements are parsed in the order they are defined in the header.
456    pub fn read_little_endian_element<T: Read>(&self, reader: &mut T, element_def: &ElementDef) -> Result<E> {
457        // Reduce coupling with ByteOrder
458        self.__read_binary_element::<T, LittleEndian>(reader, element_def)
459    }
460
461    /// internal wrapper
462    fn __read_big_endian_payload_for_element<T: Read>(&self, reader: &mut T, location: &mut LocationTracker, element_def: &ElementDef) -> Result<Vec<E>> {
463        self.__read_binary_payload_for_element::<T, BigEndian>(reader, location, element_def)
464    }
465    fn __read_little_endian_payload_for_element<T: Read>(&self, reader: &mut T, location: &mut LocationTracker, element_def: &ElementDef) -> Result<Vec<E>> {
466        self.__read_binary_payload_for_element::<T, LittleEndian>(reader, location, element_def)
467    }
468
469    fn __read_binary_payload_for_element<T: Read, B: ByteOrder>(&self, reader: &mut T, location: &mut LocationTracker, element_def: &ElementDef) -> Result<Vec<E>> {
470        let mut elems = Vec::<E>::new();
471        for _ in 0..element_def.count {
472            let element = self.__read_binary_element::<T, B>(reader, element_def)?;
473            elems.push(element);
474            location.next_line();
475        }
476        Ok(elems)
477    }
478    fn __read_binary_element<T: Read, B: ByteOrder>(&self, reader: &mut T, element_def: &ElementDef) -> Result<E> {
479        let mut raw_element = E::new();
480
481        for (k, p) in &element_def.properties {
482            let property = self.__read_binary_property::<T, B>(reader, &p.data_type)?;
483            raw_element.set_property(k.clone(), property);
484        }
485        Ok(raw_element)
486    }
487    fn __read_binary_property<T: Read, B: ByteOrder>(&self, reader: &mut T, data_type: &PropertyType) -> Result<Property> {
488        let result = match *data_type {
489            PropertyType::Scalar(ref scalar_type) => match *scalar_type {
490                ScalarType::Char => Property::Char(reader.read_i8()?),
491                ScalarType::UChar => Property::UChar(reader.read_u8()?),
492                ScalarType::Short => Property::Short(reader.read_i16::<B>()?),
493                ScalarType::UShort => Property::UShort(reader.read_u16::<B>()?),
494                ScalarType::Int => Property::Int(reader.read_i32::<B>()?),
495                ScalarType::UInt => Property::UInt(reader.read_u32::<B>()?),
496                ScalarType::Float => Property::Float(reader.read_f32::<B>()?),
497                ScalarType::Double => Property::Double(reader.read_f64::<B>()?),
498            },
499            PropertyType::List(ref index_type, ref property_type) => {
500                let count : usize = match *index_type {
501                    ScalarType::Char => reader.read_i8()? as usize,
502                    ScalarType::UChar => reader.read_u8()? as usize,
503                    ScalarType::Short => reader.read_i16::<B>()? as usize,
504                    ScalarType::UShort => reader.read_u16::<B>()? as usize,
505                    ScalarType::Int => reader.read_i32::<B>()? as usize,
506                    ScalarType::UInt => reader.read_u32::<B>()? as usize,
507                    ScalarType::Float => return Err(io::Error::new(ErrorKind::InvalidInput, "Index of list must be an integer type, float declared in ScalarType.")),
508                    ScalarType::Double => return Err(io::Error::new(ErrorKind::InvalidInput, "Index of list must be an integer type, double declared in ScalarType.")),
509                };
510                match *property_type {
511                    ScalarType::Char => Property::ListChar(self.__read_binary_list(reader, &|r| r.read_i8(), count)?),
512                    ScalarType::UChar => Property::ListUChar(self.__read_binary_list(reader, &|r| r.read_u8(), count)?),
513                    ScalarType::Short => Property::ListShort(self.__read_binary_list(reader, &|r| r.read_i16::<B>(), count)?),
514                    ScalarType::UShort => Property::ListUShort(self.__read_binary_list(reader, &|r| r.read_u16::<B>(), count)?),
515                    ScalarType::Int => Property::ListInt(self.__read_binary_list(reader, &|r| r.read_i32::<B>(), count)?),
516                    ScalarType::UInt => Property::ListUInt(self.__read_binary_list(reader, &|r| r.read_u32::<B>(), count)?),
517                    ScalarType::Float => Property::ListFloat(self.__read_binary_list(reader, &|r| r.read_f32::<B>(), count)?),
518                    ScalarType::Double => Property::ListDouble(self.__read_binary_list(reader, &|r| r.read_f64::<B>(), count)?),
519                }
520            }
521        };
522        Ok(result)
523    }
524    fn __read_binary_list<T: Read, D: FromStr>(&self, reader: &mut T, read_from: &dyn Fn(&mut T) -> Result<D>, count: usize) -> Result<Vec<D>>
525        where <D as FromStr>::Err: error::Error + marker::Send + marker::Sync + 'static {
526        let mut list = Vec::<D>::new();
527        for i in 0..count {
528            let value : D = match read_from(reader) {
529                Err(e) => return Err(io::Error::new(
530                    ErrorKind::InvalidInput,
531                    format!("Couldn't find a list element at index {}.\n\tError: {:?}", i, e)
532                )),
533                Ok(x) => x
534            };
535            list.push(value);
536        }
537        Ok(list)
538    }
539}
540
541
542
543#[cfg(test)]
544mod tests {
545    use super::grammar as g;
546    use super::Line;
547    use crate::parser::Parser;
548    use crate::ply::{ DefaultElement, PropertyDef, Version, Encoding, ScalarType, PropertyType, ElementDef, KeyMap, Addable };
549    macro_rules! assert_ok {
550        ($e:expr) => (
551            match $e {
552                Ok(obj) => (obj),
553                Err(e) => panic!("{}", e),
554            }
555        );
556        ($e:expr , $o:expr) => (
557            let obj = assert_ok!($e);
558            assert_eq!(obj, $o);
559        );
560    }
561    macro_rules! assert_err {
562        ($e:expr) => (
563            let result = $e;
564            assert!(result.is_err());
565        );
566    }
567    #[test]
568    fn parser_header_ok(){
569        let p = Parser::<DefaultElement>::new();
570        let txt = "ply\nformat ascii 1.0\nend_header\n";
571        let mut bytes = txt.as_bytes();
572        assert_ok!(p.read_header(&mut bytes));
573
574        let txt = "ply\n\
575        format ascii 1.0\n\
576        element vertex 8\n\
577        property float x\n\
578        property float y\n\
579        element face 6\n\
580        property list uchar int vertex_index\n\
581        end_header\n";
582        let mut bytes = txt.as_bytes();
583        assert_ok!(p.read_header(&mut bytes));
584    }
585    #[test]
586    fn parser_demo_ok(){
587        let txt = "ply\nformat ascii 1.0\nend_header\n";
588        let mut bytes = txt.as_bytes();
589        let p = Parser::<DefaultElement>::new();
590        assert_ok!(p.read_header(&mut bytes));
591
592        let txt = "ply\n\
593        format ascii 1.0\n\
594        element vertex 1\n\
595        property float x\n\
596        end_header\n
597        6.28318530718"; // no newline at end!
598        let mut bytes = txt.as_bytes();
599        assert_ok!(p.read_header(&mut bytes));
600    }
601    #[test]
602    fn parser_single_elements_ok(){
603        let txt = "ply\r\n\
604        format ascii 1.0\r\n\
605        comment Hi, I'm your friendly comment.\r\n\
606        obj_info And I'm your object information.\r\n\
607        element point 2\r\n\
608        property int x\r\n\
609        property int y\r\n\
610        end_header\r\n\
611        -7 5\r\n\
612        2 4\r\n";
613        let mut bytes = txt.as_bytes();
614        let p = Parser::<DefaultElement>::new();
615        assert_ok!(p.read_ply(&mut bytes));
616    }
617    #[test]
618    fn read_property_ok() {
619        let p = Parser::<DefaultElement>::new();
620        let txt = "0 1 2 3";
621        let mut prop = KeyMap::<PropertyDef>::new();
622        prop.add(PropertyDef::new("a".to_string(), PropertyType::Scalar(ScalarType::Char)));
623        prop.add(PropertyDef::new("b".to_string(), PropertyType::Scalar(ScalarType::UChar)));
624        prop.add(PropertyDef::new("c".to_string(), PropertyType::Scalar(ScalarType::Short)));
625        prop.add(PropertyDef::new("d".to_string(), PropertyType::Scalar(ScalarType::UShort)));
626        let mut elem_def = ElementDef::new("dummy".to_string());
627        elem_def.properties = prop;
628
629        let properties = p.read_ascii_element(&txt, &elem_def);
630        assert!(properties.is_ok(), format!("error: {:?}", properties));
631    }
632    #[test]
633    fn magic_number_ok() {
634        assert_ok!(g::magic_number("ply"));
635    }
636    #[test]
637    fn magic_number_err() {
638        assert_err!(g::magic_number("py"));
639        assert_err!(g::magic_number("plyhi"));
640        assert_err!(g::magic_number("hiply"));
641        assert_err!(g::magic_number(" ply"));
642        assert_err!(g::magic_number("ply "));
643    }
644    #[test]
645    fn format_ok() {
646        assert_ok!(
647            g::format("format ascii 1.0"),
648            (Encoding::Ascii, Version{major: 1, minor: 0})
649        );
650        assert_ok!(
651            g::format("format binary_big_endian 2.1"),
652            (Encoding::BinaryBigEndian, Version{major: 2, minor: 1})
653        );
654        assert_ok!(
655            g::format("format binary_little_endian 1.0"),
656            (Encoding::BinaryLittleEndian, Version{major: 1, minor: 0})
657        );
658    }
659    #[test]
660    fn format_err() {
661        assert_err!(g::format("format asciii 1.0"));
662        assert_err!(g::format("format ascii -1.0"));
663        assert_err!(g::format("format ascii 1.0.3"));
664        assert_err!(g::format("format ascii 1."));
665        assert_err!(g::format("format ascii 1"));
666        assert_err!(g::format("format ascii 1.0a"));
667    }
668    #[test]
669    fn comment_ok() {
670        assert_ok!(g::comment("comment hi"), "hi");
671        assert_ok!(
672            g::comment("comment   hi, I'm a comment!"),
673            "hi, I'm a comment!"
674        );
675        assert_ok!(g::comment("comment "), "");
676        assert_ok!(g::comment("comment\t"), "");
677        assert_ok!(g::comment("comment"), "");
678        assert_ok!(g::comment("comment\t"), "");
679        assert_ok!(g::comment("comment\thi"), "hi");
680    }
681    #[test]
682    fn comment_err() {
683        assert_err!(g::comment("commentt"));
684        assert_err!(g::comment("comment\n"));
685        assert_err!(g::comment("comment hi\na comment"));
686        assert_err!(g::comment("comment hi\r\na comment"));
687        assert_err!(g::comment("comment hi\ra comment"));
688    }
689    #[test]
690    fn obj_info_ok() {
691        assert_ok!(g::obj_info("obj_info Hi, I can help."), "Hi, I can help.");
692        assert_ok!(g::obj_info("obj_info"), "");
693        assert_ok!(g::obj_info("obj_info "), "");
694        assert_ok!(g::obj_info("obj_info\t"), "");
695    }
696    #[test]
697    fn obj_info_err() {
698        assert_err!(g::obj_info("obj_info\n"));
699    }
700    #[test]
701    fn element_ok() {
702        let mut e = ElementDef::new("vertex".to_string());
703        e.count = 8;
704        assert_ok!(
705            g::element("element vertex 8"),
706            e
707        );
708    }
709    #[test]
710    fn element_err() {
711        assert_err!(g::comment("element 8 vertex"));
712    }
713    #[test]
714    fn property_ok() {
715        assert_ok!(
716            g::property("property char c"),
717            PropertyDef::new("c".to_string(), PropertyType::Scalar(ScalarType::Char))
718        );
719    }
720    #[test]
721    fn property_list_ok() {
722        assert_ok!(
723            g::property("property list uchar int c"),
724            PropertyDef::new("c".to_string(), PropertyType::List(ScalarType::UChar, ScalarType::Int))
725        );
726    }
727    #[test]
728    fn line_ok() {
729        assert_ok!(g::line("ply "), Line::MagicNumber);
730        assert_ok!(g::line("format ascii 1.0 "), Line::Format((Encoding::Ascii, Version{major: 1, minor: 0})));
731        assert_ok!(g::line("comment a very nice comment "));
732        assert_ok!(g::line("element vertex 8 "));
733        assert_ok!(g::line("property float x "));
734        assert_ok!(g::line("element face 6 "));
735        assert_ok!(g::line("property list uchar int vertex_index "));
736        assert_ok!(g::line("end_header "));
737    }
738    #[test]
739    fn line_breaks_ok() {
740        assert_ok!(g::line("ply \n"), Line::MagicNumber); // Unix, Mac OS X
741        assert_ok!(g::line("ply \r"), Line::MagicNumber); // Mac pre OS X
742        assert_ok!(g::line("ply \r\n"), Line::MagicNumber); // Windows
743    }
744    #[test]
745    fn data_line_ok() {
746        assert_ok!(
747            g::data_line("+7 -7 7 +5.21 -5.21 5.21 +0 -0 0 \r\n"),
748            vec!["+7", "-7", "7", "+5.21", "-5.21", "5.21", "+0", "-0", "0"]
749        );
750        assert_ok!(
751            g::data_line("034 8e3 8e-3"),
752            vec!["034", "8e3", "8e-3"]
753        );
754        assert_ok!(g::data_line(""), Vec::<String>::new());
755    }
756    #[test]
757    fn data_line_err() {
758        assert_err!(g::data_line("++3"));
759        assert_err!(g::data_line("+-3"));
760        assert_err!(g::data_line("five"));
761    }
762}