nom_obj/parser/
common.rs

1use nom::{
2    digit,
3    eol,
4};
5
6use std::str;
7use std::str::FromStr;
8
9named!(pub whitespace, eat_separator!(&b" \t"[..]));
10
11#[macro_export]
12macro_rules! sp (
13   ($i:expr, $($args:tt)*) => (
14     {
15       sep!($i, whitespace, $($args)*)
16     }
17   )
18 );
19
20named!(pub slashes, eat_separator!(&b"/"[..]));
21
22#[macro_export]
23macro_rules! slash_sep (
24   ($i:expr, $($args:tt)*) => (
25     {
26       sep!($i, slashes, $($args)*)
27     }
28   )
29 );
30
31/// Meta macro, define parser for lines starting with $i, map to enum $tt type $ty
32/// Converts to &str and trims whitespace from line
33#[macro_export]
34macro_rules! def_string_line (
35   ($id:ident, $i:expr, $tt:tt, $ty:ident) => (
36       named!( $id< &[u8], $tt >, map!(
37           delimited!(tag!($i), take_until!("\n"), end_of_line),
38           |s| $tt :: $ty(str::from_utf8(s).unwrap().trim().to_string())
39       ));
40   )
41);
42
43named!(pub comment, delimited!(
44    tag!("#"),
45    take_until!("\n"),
46    alt!( eof!() | eol )
47));
48
49named!(pub end_of_line, alt!(
50    eof!()
51    |
52    eol
53    |
54    comment  // handle end of line comments - these are not kept
55));
56
57named!(pub unsigned_float <f32>, map_res!(
58  map_res!(
59    recognize!(
60      alt!(
61        delimited!(digit, complete!(tag!(".")), opt!(complete!(digit)))
62        |
63        delimited!(opt!(digit), complete!(tag!(".")), digit)
64        |
65        digit
66      )
67    ),
68    str::from_utf8
69  ),
70  FromStr::from_str
71));
72
73named!(pub float <f32>, map!(
74   pair!(
75     opt!(alt!(tag!("+") | tag!("-"))),
76     unsigned_float
77   ),
78   |(sign, value): (Option<&[u8]>, f32)| {
79     sign.and_then(|s| if s[0] == ('-' as u8) { Some(-1f32) } else { None }).unwrap_or(1f32) * value
80   }
81));
82
83named!(pub uint <u32>, map_res!(map_res!( recognize!( digit ), str::from_utf8 ), FromStr::from_str));
84
85
86named!(pub float_triple_opt_4th< &[u8], (f32,f32,f32,Option<f32>)>, sp!(
87    tuple!( float, float, float, opt!(float) )
88));
89
90named!(pub float_pair_opt_3rd< &[u8], (f32,f32,Option<f32>) >, sp!(
91    tuple!(float, float, opt!(float))
92));
93
94named!(pub float_triple< &[u8], (f32,f32,f32) >, sp!(tuple!(float, float, float)));
95named!(pub float_pair< &[u8], (f32,f32) >,  sp!(tuple!(float, float)));
96
97#[cfg(test)]
98mod tests {
99		use nom::IResult;
100    use super::*;
101
102    #[test] fn can_parse_signed_floats() {
103        let something = float("-0.00005".as_bytes());
104        assert_eq!(something, IResult::Done(&b""[..], -0.00005));
105    }
106
107    #[test]
108    fn can_parse_float_pair() {
109        let ff = float_pair("     -1.000001 7742.9 ".as_bytes());
110        let (_,b) = ff.unwrap();
111        assert_eq!(b, (-1.000001, 7742.9));
112    }
113
114    #[test]
115    fn can_parse_float_triple() {
116        let fff = float_triple("    0.95  -1.000001 42.9 ".as_bytes());
117        let (_,b) = fff.unwrap();
118        assert_eq!(b, (0.95, -1.000001, 42.9));
119    }
120
121    #[test] fn can_parse_comments() {
122        let cmt = comment("# a comment exists here \n".as_bytes());
123        let (_,b) = cmt.unwrap();
124        assert_eq!(str::from_utf8(b).unwrap(), " a comment exists here ");
125    }
126
127    #[test] fn can_parse_comments_2() {
128        let cmt = comment("# Blender v2.78 (sub 0) OBJ File: \'untitled.blend\'\n".as_bytes());
129        let (_,b) = cmt.unwrap();
130        assert_eq!(str::from_utf8(b).unwrap(), " Blender v2.78 (sub 0) OBJ File: \'untitled.blend\'");
131    }
132}