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#[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 ));
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}