1 //! parsers recognizing numbers 2 3 /// if the parameter is nom::Endianness::Big, parse a big endian u16 integer, 4 /// otherwise a little endian u16 integer 5 /// 6 /// ```rust 7 /// # #[macro_use] extern crate nom; 8 /// # use nom::{Err, Needed}; 9 /// use nom::number::Endianness; 10 /// 11 /// # fn main() { 12 /// named!(be<u16>, u16!(Endianness::Big)); 13 /// 14 /// assert_eq!(be(b"\x00\x01abcd"), Ok((&b"abcd"[..], 0x0001))); 15 /// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::Size(2)))); 16 /// 17 /// named!(le<u16>, u16!(Endianness::Little)); 18 /// 19 /// assert_eq!(le(b"\x00\x01abcd"), Ok((&b"abcd"[..], 0x0100))); 20 /// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::Size(2)))); 21 /// # } 22 /// ``` 23 #[macro_export(local_inner_macros)] 24 macro_rules! u16 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_u16($i) } else { $crate::number::streaming::le_u16($i) } } );); 25 26 /// if the parameter is nom::Endianness::Big, parse a big endian u32 integer, 27 /// otherwise a little endian u32 integer 28 /// 29 /// ```rust 30 /// # #[macro_use] extern crate nom; 31 /// # use nom::{Err, Needed}; 32 /// use nom::number::Endianness; 33 /// 34 /// # fn main() { 35 /// named!(be<u32>, u32!(Endianness::Big)); 36 /// 37 /// assert_eq!(be(b"\x00\x01\x02\x03abcd"), Ok((&b"abcd"[..], 0x00010203))); 38 /// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::Size(4)))); 39 /// 40 /// named!(le<u32>, u32!(Endianness::Little)); 41 /// 42 /// assert_eq!(le(b"\x00\x01\x02\x03abcd"), Ok((&b"abcd"[..], 0x03020100))); 43 /// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::Size(4)))); 44 /// # } 45 /// ``` 46 #[macro_export(local_inner_macros)] 47 macro_rules! u32 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_u32($i) } else { $crate::number::streaming::le_u32($i) } } );); 48 49 /// if the parameter is nom::Endianness::Big, parse a big endian u64 integer, 50 /// otherwise a little endian u64 integer 51 /// 52 /// ```rust 53 /// # #[macro_use] extern crate nom; 54 /// # use nom::{Err, Needed}; 55 /// use nom::number::Endianness; 56 /// 57 /// # fn main() { 58 /// named!(be<u64>, u64!(Endianness::Big)); 59 /// 60 /// assert_eq!(be(b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"), Ok((&b"abcd"[..], 0x0001020304050607))); 61 /// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::Size(8)))); 62 /// 63 /// named!(le<u64>, u64!(Endianness::Little)); 64 /// 65 /// assert_eq!(le(b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"), Ok((&b"abcd"[..], 0x0706050403020100))); 66 /// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::Size(8)))); 67 /// # } 68 /// ``` 69 #[macro_export(local_inner_macros)] 70 macro_rules! u64 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_u64($i) } else { $crate::number::streaming::le_u64($i) } } );); 71 72 /// if the parameter is nom::Endianness::Big, parse a big endian u128 integer, 73 /// otherwise a little endian u128 integer 74 /// 75 /// ```rust 76 /// # #[macro_use] extern crate nom; 77 /// # use nom::{Err, Needed}; 78 /// use nom::number::Endianness; 79 /// 80 /// # fn main() { 81 /// named!(be<u128>, u128!(Endianness::Big)); 82 /// 83 /// assert_eq!(be(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"), Ok((&b"abcd"[..], 0x00010203040506070809101112131415))); 84 /// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::Size(16)))); 85 /// 86 /// named!(le<u128>, u128!(Endianness::Little)); 87 /// 88 /// assert_eq!(le(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"), Ok((&b"abcd"[..], 0x15141312111009080706050403020100))); 89 /// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::Size(16)))); 90 /// # } 91 /// ``` 92 #[macro_export(local_inner_macros)] 93 #[cfg(stable_i128)] 94 macro_rules! u128 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_u128($i) } else { $crate::number::streaming::le_u128($i) } } );); 95 96 /// if the parameter is nom::Endianness::Big, parse a big endian i16 integer, 97 /// otherwise a little endian i16 integer 98 /// 99 /// ```rust 100 /// # #[macro_use] extern crate nom; 101 /// # use nom::{Err, Needed}; 102 /// use nom::number::Endianness; 103 /// 104 /// # fn main() { 105 /// named!(be<i16>, i16!(Endianness::Big)); 106 /// 107 /// assert_eq!(be(b"\x00\x01abcd"), Ok((&b"abcd"[..], 0x0001))); 108 /// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::Size(2)))); 109 /// 110 /// named!(le<i16>, i16!(Endianness::Little)); 111 /// 112 /// assert_eq!(le(b"\x00\x01abcd"), Ok((&b"abcd"[..], 0x0100))); 113 /// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::Size(2)))); 114 /// # } 115 /// ``` 116 #[macro_export(local_inner_macros)] 117 macro_rules! i16 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_i16($i) } else { $crate::number::streaming::le_i16($i) } } );); 118 119 /// if the parameter is nom::Endianness::Big, parse a big endian i32 integer, 120 /// otherwise a little endian i32 integer 121 /// 122 /// ```rust 123 /// # #[macro_use] extern crate nom; 124 /// # use nom::{Err, Needed}; 125 /// use nom::number::Endianness; 126 /// 127 /// # fn main() { 128 /// named!(be<i32>, i32!(Endianness::Big)); 129 /// 130 /// assert_eq!(be(b"\x00\x01\x02\x03abcd"), Ok((&b"abcd"[..], 0x00010203))); 131 /// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::Size(4)))); 132 /// 133 /// named!(le<i32>, i32!(Endianness::Little)); 134 /// 135 /// assert_eq!(le(b"\x00\x01\x02\x03abcd"), Ok((&b"abcd"[..], 0x03020100))); 136 /// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::Size(4)))); 137 /// # } 138 /// ``` 139 #[macro_export(local_inner_macros)] 140 macro_rules! i32 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_i32($i) } else { $crate::number::streaming::le_i32($i) } } );); 141 142 /// if the parameter is nom::Endianness::Big, parse a big endian i64 integer, 143 /// otherwise a little endian i64 integer 144 /// 145 /// ```rust 146 /// # #[macro_use] extern crate nom; 147 /// # use nom::{Err, Needed}; 148 /// use nom::number::Endianness; 149 /// 150 /// # fn main() { 151 /// named!(be<i64>, i64!(Endianness::Big)); 152 /// 153 /// assert_eq!(be(b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"), Ok((&b"abcd"[..], 0x0001020304050607))); 154 /// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::Size(8)))); 155 /// 156 /// named!(le<i64>, i64!(Endianness::Little)); 157 /// 158 /// assert_eq!(le(b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"), Ok((&b"abcd"[..], 0x0706050403020100))); 159 /// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::Size(8)))); 160 /// # } 161 /// ``` 162 #[macro_export(local_inner_macros)] 163 macro_rules! i64 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_i64($i) } else { $crate::number::streaming::le_i64($i) } } );); 164 165 /// if the parameter is nom::Endianness::Big, parse a big endian i64 integer, 166 /// otherwise a little endian i64 integer 167 /// 168 /// ```rust 169 /// # #[macro_use] extern crate nom; 170 /// # use nom::{Err, Needed}; 171 /// use nom::number::Endianness; 172 /// 173 /// # fn main() { 174 /// named!(be<i128>, i128!(Endianness::Big)); 175 /// 176 /// assert_eq!(be(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"), Ok((&b"abcd"[..], 0x00010203040506070809101112131415))); 177 /// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::Size(16)))); 178 /// 179 /// named!(le<i128>, i128!(Endianness::Little)); 180 /// 181 /// assert_eq!(le(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"), Ok((&b"abcd"[..], 0x15141312111009080706050403020100))); 182 /// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::Size(16)))); 183 /// # } 184 /// ``` 185 #[macro_export(local_inner_macros)] 186 #[cfg(stable_i128)] 187 macro_rules! i128 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_i128($i) } else { $crate::number::streaming::le_i128($i) } } );); 188 189 #[cfg(test)] 190 mod tests { 191 use crate::number::Endianness; 192 193 #[test] configurable_endianness()194 fn configurable_endianness() { 195 named!(be_tst16<u16>, u16!(Endianness::Big)); 196 named!(le_tst16<u16>, u16!(Endianness::Little)); 197 assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16))); 198 assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16))); 199 200 named!(be_tst32<u32>, u32!(Endianness::Big)); 201 named!(le_tst32<u32>, u32!(Endianness::Little)); 202 assert_eq!( 203 be_tst32(&[0x12, 0x00, 0x60, 0x00]), 204 Ok((&b""[..], 302_014_464_u32)) 205 ); 206 assert_eq!( 207 le_tst32(&[0x12, 0x00, 0x60, 0x00]), 208 Ok((&b""[..], 6_291_474_u32)) 209 ); 210 211 named!(be_tst64<u64>, u64!(Endianness::Big)); 212 named!(le_tst64<u64>, u64!(Endianness::Little)); 213 assert_eq!( 214 be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), 215 Ok((&b""[..], 1_297_142_246_100_992_000_u64)) 216 ); 217 assert_eq!( 218 le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), 219 Ok((&b""[..], 36_028_874_334_666_770_u64)) 220 ); 221 222 named!(be_tsti16<i16>, i16!(Endianness::Big)); 223 named!(le_tsti16<i16>, i16!(Endianness::Little)); 224 assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16))); 225 assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16))); 226 227 named!(be_tsti32<i32>, i32!(Endianness::Big)); 228 named!(le_tsti32<i32>, i32!(Endianness::Little)); 229 assert_eq!( 230 be_tsti32(&[0x00, 0x12, 0x60, 0x00]), 231 Ok((&b""[..], 1_204_224_i32)) 232 ); 233 assert_eq!( 234 le_tsti32(&[0x00, 0x12, 0x60, 0x00]), 235 Ok((&b""[..], 6_296_064_i32)) 236 ); 237 238 named!(be_tsti64<i64>, i64!(Endianness::Big)); 239 named!(le_tsti64<i64>, i64!(Endianness::Little)); 240 assert_eq!( 241 be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), 242 Ok((&b""[..], 71_881_672_479_506_432_i64)) 243 ); 244 assert_eq!( 245 le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), 246 Ok((&b""[..], 36_028_874_334_732_032_i64)) 247 ); 248 } 249 250 //FIXME 251 /* 252 #[test] 253 #[cfg(feature = "std")] 254 fn manual_configurable_endianness_test() { 255 let x = 1; 256 let int_parse: Box<Fn(&[u8]) -> IResult<&[u8], u16, (&[u8], ErrorKind)>> = if x == 2 { 257 Box::new(be_u16) 258 } else { 259 Box::new(le_u16) 260 }; 261 println!("{:?}", int_parse(&b"3"[..])); 262 assert_eq!(int_parse(&[0x80, 0x00]), Ok((&b""[..], 128_u16))); 263 } 264 */ 265 } 266