Bug 1486815 - Remove nom 1 from dependencies. r=emilio

This commit is contained in:
Bastien Orivel 2018-08-28 16:46:35 +02:00 коммит произвёл Emilio Cobos Álvarez
Родитель f78d708b01
Коммит 3946c67f0c
63 изменённых файлов: 304 добавлений и 25054 удалений

14
Cargo.lock сгенерированный
Просмотреть файл

@ -172,7 +172,7 @@ name = "bindgen"
version = "0.37.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -280,10 +280,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cexpr"
version = "0.2.0"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1489,11 +1489,6 @@ name = "nodrop"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "nom"
version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "nom"
version = "3.2.1"
@ -2860,7 +2855,7 @@ dependencies = [
"checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24"
"checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b"
"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275"
"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
"checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00"
"checksum clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7f7c04e52c35222fffcc3a115b5daf5f7e2bfb71c13c4e2321afe1fc71859c2"
@ -2969,7 +2964,6 @@ dependencies = [
"checksum new-ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8ccbebba6fb53a6d2bdcfaf79cb339bc136dee3bfff54dc337a334bafe36476a"
"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b"
"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525"
"checksum num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2c31b75c36a993d30c7a13d70513cb93f02acafdd5b7ba250f9b0e18615de7"

2
third_party/rust/cexpr/.cargo-checksum.json поставляемый
Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"fb51f35c4be7c1a6768ab026c11092cbf8b81aebaaa970e19f0b0033f7a26b88","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"d9771b8c6cf4426d3846de54c1febe20907f1eeadf7adfb5ade89a83bd9ea77f","src/expr.rs":"dc3e299b02b33e1441d6e82482409272554cfae8f271e3b5664a216ecf1fecdc","src/lib.rs":"a37cca356d761557bd27e08ce46044b758bd21d523d039105e71597f64da9ba1","src/literal.rs":"deddad795a6788a78533f49b6afa784702e2dbfd9848d6fad60ec5cecabfb840","src/token.rs":"85d63f778a438ba9f39dac643473d457103bad2f2d4b53dd62e65ded65b1a83d","tests/clang.rs":"125058defb8166679019475d72a76804ac2dbfc09f50c3fad5b908970d652f02","tests/input/chars.h":"69c8141870872b795b5174bad125b748732c2b01d0e98ffcfc37b19f3f791f69","tests/input/fail.h":"b0b6cffd2dd17410b5eb02ee79ab75754820480b960db8a9866cc9983bd36b65","tests/input/floats.h":"28ec664e793c494e1a31f3bc5b790014e9921fc741bf475a86319b9a9eee5915","tests/input/int_signed.h":"934199eded85dd7820ca08c0beb1381ee6d9339970d2720a69c23025571707ce","tests/input/int_unsigned.h":"3cdf9782a6e74796833ea0dfcb35b6ab6ca76a89080e82ed39bac0d55064d88c","tests/input/strings.h":"27de768b506a1aedfdb750ac53b7a395cc20395958ff3263af1ab5851e2c412c"},"package":"393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"}
{"files":{"Cargo.toml":"22914a43154e0b38bbe265a67024c1f98af9087ca561448ac0f13ed57c9311ae","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"d9771b8c6cf4426d3846de54c1febe20907f1eeadf7adfb5ade89a83bd9ea77f","src/expr.rs":"b888963ab9eb344c93c0654286231b4204809a971682155fade5c69a4493636f","src/lib.rs":"78bbde89e803cf931216e38bdd992e13894cd898868478a258eac5155bdf4de9","src/literal.rs":"fb80a7b43d96bedfd47bc2d39eaf588c5cef6a2374132fbdfe5146dd56a1894c","src/token.rs":"52d42deb2a2575bb8631e2e821593d8288fed16e21bab3ceeacb6a7b06c40087","tests/clang.rs":"a650cde69ab2e801f994f15e4cb32c538e53abefcdd862865ce277ce9a055242","tests/input/chars.h":"69c8141870872b795b5174bad125b748732c2b01d0e98ffcfc37b19f3f791f69","tests/input/fail.h":"b0b6cffd2dd17410b5eb02ee79ab75754820480b960db8a9866cc9983bd36b65","tests/input/floats.h":"28ec664e793c494e1a31f3bc5b790014e9921fc741bf475a86319b9a9eee5915","tests/input/int_signed.h":"934199eded85dd7820ca08c0beb1381ee6d9339970d2720a69c23025571707ce","tests/input/int_unsigned.h":"f47c1ccb6c69856162639277d7552090055420155df55f65581e57217cccce76","tests/input/strings.h":"75c60527068172b97983d2b8361938e856ea394002d5bef05de1adc6a0f5fc01","tests/input/test_llvm_bug_9069.h":"8d9ae1d1eadc8f6d5c14296f984547fe894d0f2ce5cd6d7aa8caad40a56bc5e1"},"package":"42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c"}

31
third_party/rust/cexpr/Cargo.toml поставляемый
Просмотреть файл

@ -1,15 +1,26 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g. crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
[package]
name = "cexpr"
version = "0.2.0"
version = "0.2.3"
authors = ["Jethro Beekman <jethro@jbeekman.nl>"]
license = "Apache-2.0/MIT"
description = "A C expression parser and evaluator"
documentation = "https://jethrogb.github.io/rust-cexpr/cexpr"
documentation = "https://docs.rs/cexpr/"
keywords = ["C", "expression", "parser"]
license = "Apache-2.0/MIT"
repository = "https://github.com/jethrogb/rust-cexpr"
keywords = ["C","expression","parser"]
[dependencies]
nom = "^1"
[dev-dependencies]
clang-sys = "0.11.0"
[dependencies.nom]
version = "^3"
features = ["verbose-errors"]
[dev-dependencies.clang-sys]
version = "0.11.0"

196
third_party/rust/cexpr/src/expr.rs поставляемый
Просмотреть файл

@ -14,7 +14,7 @@
//!
//! The `sizeof` operator is not supported.
//!
//! String concatenation is supported, but width prefixes are ignored all
//! String concatenation is supported, but width prefixes are ignored; all
//! strings are treated as narrow strings.
//!
//! Use the `IdentifierParser` to substitute identifiers found in expressions.
@ -85,9 +85,9 @@ impl From<Vec<u8>> for EvalResult {
// ===========================================
macro_rules! exact_token (
($i:expr, $k: ident, $c: expr) => ({
($i:expr, $k:ident, $c:expr) => ({
if $i.is_empty() {
let res: CResult<&[u8]> = IResult::Incomplete(Needed::Size(1));
let res: CResult<&[u8]> = IResult::Incomplete(Needed::Size($c.len()));
res
} else {
if $i[0].kind==TokenKind::$k && &$i[0].raw[..]==$c {
@ -100,7 +100,7 @@ macro_rules! exact_token (
);
macro_rules! typed_token (
($i:expr, $k: ident) => ({
($i:expr, $k:ident) => ({
if $i.is_empty() {
let res: CResult<&[u8]> = IResult::Incomplete(Needed::Size(1));
res
@ -114,6 +114,7 @@ macro_rules! typed_token (
});
);
#[allow(unused_macros)]
macro_rules! any_token (
($i:expr,) => ({
if $i.is_empty() {
@ -126,7 +127,24 @@ macro_rules! any_token (
);
macro_rules! p (
($i:expr, $c: expr) => (exact_token!($i,Punctuation,$c.as_bytes()))
($i:expr, $c:expr) => (exact_token!($i,Punctuation,$c.as_bytes()))
);
macro_rules! one_of_punctuation (
($i:expr, $c:expr) => ({
if $i.is_empty() {
let min = $c.iter().map(|opt|opt.len()).min().expect("at least one option");
let res: CResult<&[u8]> = IResult::Incomplete(Needed::Size(min));
res
} else {
if $i[0].kind==TokenKind::Punctuation && $c.iter().any(|opt|opt.as_bytes()==&$i[0].raw[..]) {
IResult::Done(&$i[1..], &$i[0].raw[..])
} else {
const VAILD_VALUES: &'static [&'static str] = &$c;
IResult::Error(Err::Position(ErrorKind::Custom(::Error::ExactTokens(TokenKind::Punctuation,VAILD_VALUES)), $i))
}
}
});
);
// ==================================================
@ -264,71 +282,104 @@ impl<'a> PRef<'a> {
delimited!(p!("("),call_m!(self.numeric_expr),p!(")")) |
numeric!(call_m!(self.literal)) |
numeric!(call_m!(self.identifier)) |
map_opt!(pair!(alt!( p!("+") | p!("-") | p!("~") ),call_m!(self.unary)),unary_op)
map_opt!(pair!(one_of_punctuation!(["+", "-", "~"]),call_m!(self.unary)),unary_op)
)
);
method!(mul_div_rem<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
chain!(
mut acc: call_m!(self.unary) ~
many0!(alt!(
tap!(mul: preceded!(p!("*"), call_m!(self.unary)) => acc *= &mul) |
tap!(div: preceded!(p!("/"), call_m!(self.unary)) => acc /= &div) |
tap!(rem: preceded!(p!("%"), call_m!(self.unary)) => acc %= &rem)
)),
|| { return acc }
do_parse!(
acc: call_m!(self.unary) >>
res: fold_many0!(
pair!(one_of_punctuation!(["*", "/", "%"]), call_m!(self.unary)),
acc,
|mut acc, (op, val): (&[u8], EvalResult)| {
match op[0] as char {
'*' => acc *= &val,
'/' => acc /= &val,
'%' => acc %= &val,
_ => unreachable!()
};
acc
}
) >> (res)
)
);
method!(add_sub<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
chain!(
mut acc: call_m!(self.mul_div_rem) ~
many0!(alt!(
tap!(add: preceded!(p!("+"), call_m!(self.mul_div_rem)) => acc += &add) |
tap!(sub: preceded!(p!("-"), call_m!(self.mul_div_rem)) => acc -= &sub)
)),
|| { return acc }
do_parse!(
acc: call_m!(self.mul_div_rem) >>
res: fold_many0!(
pair!(one_of_punctuation!(["+", "-"]), call_m!(self.mul_div_rem)),
acc,
|mut acc, (op, val): (&[u8], EvalResult)| {
match op[0] as char {
'+' => acc += &val,
'-' => acc -= &val,
_ => unreachable!()
};
acc
}
) >> (res)
)
);
method!(shl_shr<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
numeric!(chain!(
mut acc: call_m!(self.add_sub) ~
many0!(alt!(
tap!(shl: preceded!(p!("<<"), call_m!(self.add_sub)) => acc <<= &shl) |
tap!(shr: preceded!(p!(">>"), call_m!(self.add_sub)) => acc >>= &shr)
)),
|| { return acc }
numeric!(do_parse!(
acc: call_m!(self.add_sub) >>
res: fold_many0!(
pair!(one_of_punctuation!(["<<", ">>"]), call_m!(self.add_sub)),
acc,
|mut acc, (op, val): (&[u8], EvalResult)| {
match op {
b"<<" => acc <<= &val,
b">>" => acc >>= &val,
_ => unreachable!()
};
acc
}
) >> (res)
))
);
method!(and<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
numeric!(chain!(
mut acc: call_m!(self.shl_shr) ~
many0!(
tap!(and: preceded!(p!("&"), call_m!(self.shl_shr)) => acc &= &and)
),
|| { return acc }
numeric!(do_parse!(
acc: call_m!(self.shl_shr) >>
res: fold_many0!(
preceded!(p!("&"), call_m!(self.shl_shr)),
acc,
|mut acc, val: EvalResult| {
acc &= &val;
acc
}
) >> (res)
))
);
method!(xor<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
numeric!(chain!(
mut acc: call_m!(self.and) ~
many0!(
tap!(xor: preceded!(p!("^"), call_m!(self.and)) => acc ^= &xor)
),
|| { return acc }
numeric!(do_parse!(
acc: call_m!(self.and) >>
res: fold_many0!(
preceded!(p!("^"), call_m!(self.and)),
acc,
|mut acc, val: EvalResult| {
acc ^= &val;
acc
}
) >> (res)
))
);
method!(or<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
numeric!(chain!(
mut acc: call_m!(self.xor) ~
many0!(
tap!(or: preceded!(p!("|"), call_m!(self.xor)) => acc |= &or)
),
|| { return acc }
numeric!(do_parse!(
acc: call_m!(self.xor) >>
res: fold_many0!(
preceded!(p!("|"), call_m!(self.xor)),
acc,
|mut acc, val: EvalResult| {
acc |= &val;
acc
}
) >> (res)
))
);
@ -390,8 +441,8 @@ impl<'a> PRef<'a> {
method!(expr<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
alt!(
delimited!(p!("("),call_m!(self.expr),p!(")")) |
call_m!(self.numeric_expr) |
delimited!(p!("("),call_m!(self.expr),p!(")")) |
call_m!(self.concat_str) |
call_m!(self.literal) |
call_m!(self.identifier)
@ -474,3 +525,54 @@ pub fn expr<'a>(input: &'a [Token]) -> CResult<'a,EvalResult> {
pub fn macro_definition<'a>(input: &'a [Token]) -> CResult<'a,(&'a [u8],EvalResult)> {
IdentifierParser::new(&HashMap::new()).macro_definition(input)
}
named_attr!(
/// Parse a functional macro declaration from a list of tokens.
///
/// Returns the identifier for the macro and the argument list (in order). The
/// input should not include `#define`. The actual definition is not parsed and
/// may be obtained from the unparsed data returned.
///
/// Returns an error if the input is not a functional macro or if the token
/// stream contains comments.
///
/// # Example
/// ```
/// use cexpr::expr::{IdentifierParser, EvalResult, fn_macro_declaration};
/// use cexpr::assert_full_parse;
/// use cexpr::token::Kind::*;
/// use cexpr::token::Token;
///
/// // #define SUFFIX(arg) arg "suffix"
/// let tokens = vec![
/// (Identifier, &b"SUFFIX"[..]).into(),
/// (Punctuation, &b"("[..]).into(),
/// (Identifier, &b"arg"[..]).into(),
/// (Punctuation, &b")"[..]).into(),
/// (Identifier, &b"arg"[..]).into(),
/// (Literal, &br#""suffix""#[..]).into(),
/// ];
///
/// // Try to parse the functional part
/// let (expr, (ident, args)) = fn_macro_declaration(&tokens).unwrap();
/// assert_eq!(ident, b"SUFFIX");
///
/// // Create dummy arguments
/// let idents = args.into_iter().map(|arg|
/// (arg.to_owned(), EvalResult::Str(b"test".to_vec()))
/// ).collect();
///
/// // Evaluate the macro
/// let (_, evaluated) = assert_full_parse(IdentifierParser::new(&idents).expr(expr)).unwrap();
/// assert_eq!(evaluated, EvalResult::Str(b"testsuffix".to_vec()));
/// ```
,pub fn_macro_declaration<&[Token],(&[u8],Vec<&[u8]>),::Error>,
pair!(
typed_token!(Identifier),
delimited!(
p!("("),
separated_list!(p!(","), typed_token!(Identifier)),
p!(")")
)
)
);

2
third_party/rust/cexpr/src/lib.rs поставляемый
Просмотреть файл

@ -24,6 +24,8 @@ use nom::*;
pub enum Error {
/// Expected the specified token
ExactToken(token::Kind,&'static [u8]),
/// Expected one of the specified tokens
ExactTokens(token::Kind,&'static [&'static str]),
/// Expected a token of the specified kind
TypedToken(token::Kind),
/// An unknown identifier was encountered

53
third_party/rust/cexpr/src/literal.rs поставляемый
Просмотреть файл

@ -83,34 +83,6 @@ impl Into<Vec<u8>> for CChar {
// ======== macros that shouldn't be necessary ========
// ====================================================
fn split_off_prefix<'a,T>(full: &'a [T], suffix: &'a [T]) -> &'a [T] {
let n=::std::mem::size_of::<T>();
let start=full.as_ptr() as usize;
let end=start+(full.len()*n);
let cur=suffix.as_ptr() as usize;
assert!(start<=cur && cur<=end);
&full[..(cur-start)/n]
}
// There is a HORRIBLE BUG in nom's recognize!
// https://github.com/Geal/nom/issues/278
#[macro_export]
macro_rules! my_recognize (
($i:expr, $submac:ident!( $($args:tt)* )) => (
{
match $submac!($i, $($args)*) {
IResult::Done(i,_) => IResult::Done(i, split_off_prefix($i,i)),
IResult::Error(e) => IResult::Error(e),
IResult::Incomplete(i) => IResult::Incomplete(i)
}
}
);
($i:expr, $f:expr) => (
my_recognize!($i, call!($f))
);
);
macro_rules! force_type (
($input:expr,IResult<$i:ty,$o:ty,$e:ty>) => (IResult::Error::<$i,$o,$e>(Err::Position(ErrorKind::Fix,$input)))
);
@ -171,8 +143,8 @@ fn c_unicode_escape(n: Vec<u8>) -> Option<CChar> {
named!(escaped_char<CChar>,
preceded!(char!('\\'),alt!(
map!(one_of!(br#"'"?\"#),CChar::Char) |
map!(one_of!(b"abfnrtv"),escape2char) |
map!(one_of!(r#"'"?\"#),CChar::Char) |
map!(one_of!("abfnrtv"),escape2char) |
map_opt!(many_m_n!(1,3,octal),|v|c_raw_escape(v,8)) |
map_opt!(preceded!(char!('x'),many1!(hexadecimal)),|v|c_raw_escape(v,16)) |
map_opt!(preceded!(char!('u'),many_m_n!(4,4,hexadecimal)),c_unicode_escape) |
@ -200,13 +172,10 @@ named!(c_char<CChar>,
named!(c_string<Vec<u8> >,
delimited!(
alt!( preceded!(c_width_prefix,char!('"')) | char!('"') ),
chain!(
mut vec: value!(vec![]) ~
many0!(alt!(
map!(tap!(c: escaped_char => { let v: Vec<u8>=c.into(); vec.extend_from_slice(&v) } ),|_|()) |
map!(tap!(s: is_not!(b"\"") => vec.extend_from_slice(s) ),|_|())
)),
||{return vec}
fold_many0!(
alt!(map!(escaped_char, |c:CChar| c.into()) | map!(is_not!("\""), |c: &[u8]| c.into())),
Vec::new(),
|mut v: Vec<u8>, res:Vec<u8>| { v.extend_from_slice(&res); v }
),
char!('"')
)
@ -240,11 +209,11 @@ named!(float_exp<(Option<u8>,Vec<u8>)>,preceded!(byte!(b'e'|b'E'),pair!(opt!(byt
named!(c_float<f64>,
map_opt!(alt!(
terminated!(my_recognize!(tuple!(many1!(decimal),byte!(b'.'),many0!(decimal))),opt!(float_width)) |
terminated!(my_recognize!(tuple!(many0!(decimal),byte!(b'.'),many1!(decimal))),opt!(float_width)) |
terminated!(my_recognize!(tuple!(many0!(decimal),opt!(byte!(b'.')),many1!(decimal),float_exp)),opt!(float_width)) |
terminated!(my_recognize!(tuple!(many1!(decimal),opt!(byte!(b'.')),many0!(decimal),float_exp)),opt!(float_width)) |
terminated!(my_recognize!(many1!(decimal)),float_width)
terminated!(recognize!(tuple!(many1!(decimal),byte!(b'.'),many0!(decimal))),opt!(float_width)) |
terminated!(recognize!(tuple!(many0!(decimal),byte!(b'.'),many1!(decimal))),opt!(float_width)) |
terminated!(recognize!(tuple!(many0!(decimal),opt!(byte!(b'.')),many1!(decimal),float_exp)),opt!(float_width)) |
terminated!(recognize!(tuple!(many1!(decimal),opt!(byte!(b'.')),many0!(decimal),float_exp)),opt!(float_width)) |
terminated!(recognize!(many1!(decimal)),float_width)
),|v|str::from_utf8(v).ok().and_then(|i|f64::from_str(i).ok()))
);

9
third_party/rust/cexpr/src/token.rs поставляемый
Просмотреть файл

@ -24,6 +24,15 @@ pub struct Token {
pub raw: Box<[u8]>,
}
impl<'a> From<(Kind, &'a [u8])> for Token {
fn from((kind, value): (Kind, &'a [u8])) -> Token {
Token {
kind: kind,
raw: value.to_owned().into_boxed_slice()
}
}
}
/// Remove all comment tokens from a vector of tokens
pub fn remove_comments(v: &mut Vec<Token>) -> &mut Vec<Token> {
v.retain(|t|t.kind!=Kind::Comment);

98
third_party/rust/cexpr/tests/clang.rs поставляемый
Просмотреть файл

@ -14,25 +14,45 @@ use std::collections::HashMap;
use clang_sys::*;
use cexpr::token::Token;
use cexpr::expr::{IdentifierParser,EvalResult};
use cexpr::expr::{IdentifierParser,EvalResult,fn_macro_declaration};
use cexpr::literal::CChar;
use cexpr::assert_full_parse;
// main testing routine
fn test_definition(ident: Vec<u8>, tokens: &[Token], idents: &mut HashMap<Vec<u8>,EvalResult>) -> bool {
fn bytes_to_int(value: &[u8]) -> Option<EvalResult> {
str::from_utf8(value).ok()
.map(|s|s.replace("n","-"))
.map(|s|s.replace("_",""))
.and_then(|v|i64::from_str(&v).ok())
.map(::std::num::Wrapping)
.map(Int)
}
use cexpr::expr::EvalResult::*;
let display_name=String::from_utf8_lossy(&ident).into_owned();
let functional;
let test={
// Split name such as Str_test_string into (Str,test_string)
let pos=ident.iter().position(|c|*c==b'_').expect(&format!("Invalid definition in testcase: {}",display_name));
let expected=&ident[..pos];
let value=&ident[(pos+1)..];
let mut expected=&ident[..pos];
let mut value=&ident[(pos+1)..];
functional=expected==b"Fn";
if functional {
let ident=value;
let pos=ident.iter().position(|c|*c==b'_').expect(&format!("Invalid definition in testcase: {}",display_name));
expected=&ident[..pos];
value=&ident[(pos+1)..];
}
if expected==b"Str" {
Some(Str(value.to_owned()))
} else if expected==b"Int" {
str::from_utf8(value).ok().map(|s|s.replace("n","-")).and_then(|v|i64::from_str(&v).ok()).map(::std::num::Wrapping).map(Int)
bytes_to_int(value)
} else if expected==b"Float" {
str::from_utf8(value).ok().map(|s|s.replace("n","-").replace("p",".")).and_then(|v|f64::from_str(&v).ok()).map(Float)
} else if expected==b"CharRaw" {
@ -44,8 +64,34 @@ fn test_definition(ident: Vec<u8>, tokens: &[Token], idents: &mut HashMap<Vec<u8
}.expect(&format!("Invalid definition in testcase: {}",display_name))
};
match IdentifierParser::new(idents).macro_definition(&tokens) {
cexpr::nom::IResult::Done(_,(_,val)) => {
let result = if functional {
let mut fnidents;
let expr_tokens;
match fn_macro_declaration(&tokens) {
cexpr::nom::IResult::Done(rest,(_,args)) => {
fnidents=idents.clone();
expr_tokens=rest;
for arg in args {
let val = match test {
Int(_) => bytes_to_int(&arg),
Str(_) => Some(Str(arg.to_owned())),
_ => unimplemented!()
}.expect(&format!("Invalid argument in functional macro testcase: {}",display_name));
fnidents.insert(arg.to_owned(), val);
}
},
e => {
println!("Failed test for {}, unable to parse functional macro declaration: {:?}",display_name,e);
return false;
}
}
assert_full_parse(IdentifierParser::new(&fnidents).expr(&expr_tokens))
} else {
IdentifierParser::new(idents).macro_definition(&tokens).map(|(_,val)|val)
};
match result {
cexpr::nom::IResult::Done(_,val) => {
if val==test {
if let Some(_)=idents.insert(ident,val) {
panic!("Duplicate definition for testcase: {}",display_name);
@ -56,7 +102,7 @@ fn test_definition(ident: Vec<u8>, tokens: &[Token], idents: &mut HashMap<Vec<u8
false
}
},
e @ _ => {
e => {
if test==Invalid {
true
} else {
@ -110,9 +156,9 @@ unsafe fn location_in_scope(r: CXSourceRange) -> bool {
&& file.0!=ptr::null_mut()
}
fn test_file(file: &str) -> bool {
let mut idents=HashMap::new();
let mut all_succeeded=true;
/// tokenize_range_adjust can be used to work around LLVM bug 9069
/// https://bugs.llvm.org//show_bug.cgi?id=9069
fn file_visit_macros<F: FnMut(Vec<u8>, Vec<Token>)>(file: &str, tokenize_range_adjust: bool, mut visitor: F) {
unsafe {
let tu={
let index=clang_createIndex(true as _, false as _);
@ -132,7 +178,7 @@ fn test_file(file: &str) -> bool {
if cur.kind==CXCursor_MacroDefinition {
let mut range=clang_getCursorExtent(cur);
if !location_in_scope(range) { return CXChildVisit_Continue }
range.end_int_data-=1; // clang bug for macros only
range.end_int_data-=if tokenize_range_adjust { 1 } else { 0 };
let mut token_ptr=ptr::null_mut();
let mut num=0;
clang_tokenize(tu,range,&mut token_ptr,&mut num);
@ -146,16 +192,44 @@ fn test_file(file: &str) -> bool {
}
).collect();
clang_disposeTokens(tu,token_ptr,num);
all_succeeded&=test_definition(clang_str_to_vec(clang_getCursorSpelling(cur)),&tokens,&mut idents);
visitor(clang_str_to_vec(clang_getCursorSpelling(cur)),tokens)
}
}
CXChildVisit_Continue
});
clang_disposeTranslationUnit(tu);
};
}
fn test_file(file: &str) -> bool {
let mut idents=HashMap::new();
let mut all_succeeded=true;
file_visit_macros(file, fix_bug_9069(), |ident, tokens| all_succeeded&=test_definition(ident, &tokens, &mut idents));
all_succeeded
}
fn fix_bug_9069() -> bool {
fn check_bug_9069() -> bool {
let mut token_sets = vec![];
file_visit_macros("tests/input/test_llvm_bug_9069.h", false, |ident, tokens| {
assert_eq!(&ident, b"A");
token_sets.push(tokens);
});
assert_eq!(token_sets.len(), 2);
token_sets[0] != token_sets[1]
}
use std::sync::{Once, ONCE_INIT};
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
static CHECK_FIX: Once = ONCE_INIT;
static FIX: AtomicBool = ATOMIC_BOOL_INIT;
CHECK_FIX.call_once(|| FIX.store(check_bug_9069(), Ordering::SeqCst));
FIX.load(Ordering::SeqCst)
}
macro_rules! test_file {
($f:ident) => {
#[test] fn $f() {

Просмотреть файл

@ -10,5 +10,17 @@
#define Int_16 (((1)<<4ULL))/*comment*/
#define Int_13 1|8^6&2<<1
#define Int_47 32|15
#define Int_38 (32|15)^9
#define Int_6 ((32|15)^9)&7
#define Int_12 (((32|15)^9)&7)<<1
#define Int_17 ((((32|15)^9)&7)<<1)+5
#define Int_15 (((((32|15)^9)&7)<<1)+5)-2
#define Int_60 ((((((32|15)^9)&7)<<1)+5)-2)*4
#define Int_30 (((((((32|15)^9)&7)<<1)+5)-2)*4)/2
#define Int_39 32|15^9&7<<1+5-2*4/2
#define Int_n1 18446744073709551615 /*2^64-1*/
#define Int_n9223372036854775808 9223372036854775808
#define Fn_Int_9(_3) _3*3

Просмотреть файл

@ -5,3 +5,8 @@
#define Str_concat u"con" L"cat"
#define Str_concat_parens ("concat" U"_parens")
#define Str_concat_identifier (Str_concat L"_identifier")
#define Fn_Str_no_args() "no_args"
#define Fn_Str_no_args_concat() "no_args_" Str_concat
#define Fn_Str_prepend_arg(arg) "prepend_" arg
#define Fn_Str_two_args(two, args) two "_" args
#define Fn_Str_three_args(three, _, args) three _ args

4
third_party/rust/cexpr/tests/input/test_llvm_bug_9069.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
// The following two definitions should yield the same list of tokens.
// If https://bugs.llvm.org//show_bug.cgi?id=9069 is not fixed, they don't.
#define A 1
#define A 1

Просмотреть файл

@ -1 +0,0 @@
{"files":{".travis.yml":"6d4e81838b10c5e330749857c72c2f2b1a2e575e71abcd11c094f3b612347b2a","CHANGELOG.md":"d4722e028b2a5b88c466b0d759e463b90bdcfa1b79181a1c76cd313b0a27c615","Cargo.toml":"aebcb999933c3425db85012bea19f9ce78da8e7834dbab54d4a2966e8bc62149","LICENSE":"de730187d5563a81342a3c011d968f78dff37c934fac9b3701e8c762b6118a55","src/bits.rs":"97c9148f63e175489bb6199d039c594ddc56bdf0b7491b9f38b8d74e898bca80","src/bytes.rs":"8f29b976a5e8e6500eb618a9dead7f212688ba9eb06c7066a4016e2db99fed00","src/character.rs":"9ee081f56b508212231ff70d7455b1b85ae44722a39aa60223e8cd95c6570859","src/internal.rs":"ada499b9c178be2a7f9b56319ffb10a778f25fafcda39c78d26b364d89debd72","src/lib.rs":"34efb051214acfde2053e93a7ba718a4fd41b6e0d9edd65a1737605d99b994ab","src/macros.rs":"d39ce3a2cd2b1cb9dd57ce90c06a1ca84720a2dc75e6332cffebba6086cb75d3","src/methods.rs":"24bdbcb0e3570c8bf3fa270dd8d79dd6dfcb982276c82180a89a1e73c5e38019","src/nom.rs":"b0a9c7ce0d09388179bce8f8e23bf57df76b504d925815583c249ec3fc04baab","src/regexp.rs":"8fdae52b761dbad90179e6be87e0e66357fefa34d76af541fb0fcf550fd6ec08","src/str.rs":"198fa15d45c3636289d92c0a592002a07e5a04a431e8cfdf724266e44d484be2","src/stream.rs":"c1bd5b8e7a2061ff66eb2c954033146001f1d65a26d12efa06af8cf93ffa53e4","src/util.rs":"da40ebac865d3176567d3a37b01170234398a03e938553720ce30aa1f6005b6d","tests/arithmetic.rs":"b98936b7fa0228835ca022f6db5342b72a9c01cc3f16a4e05263bbe6424ba3e9","tests/arithmetic_ast.rs":"b18b9a46ba573ae13c40a31217425f6e8cf8fade09a75cdbbfa7146ec668f0b2","tests/cross_function_backtracking.rs":"b071d13031c1f12195473186e3775943991496b10f4590db3f36d511e9f98a1c","tests/ini.rs":"776f681542028564899e55f71533b3bcda5ed1bbb971f24b5b1b9578111ba0cb","tests/ini_str.rs":"315046d9b6dc38d6d306d3562d7ac6518c9ecce9aabcc58fb80c07577ad99789","tests/issues.rs":"2193c219397b7a417cc009b72c13adc42471e7a4917a2a4009aa0fca23c6ea8c","tests/mp4.rs":"b4bf0514fd645160851cc4da9ad6bf81d571cd14865bf134837c19578caaf6e6","tests/omnom.rs":"409d2349fa24f3503bd02e0079c1554a58ce3d40dd7eb0e5d4bb63b588afdae4","tests/test1.rs":"3e0c187bad91d822ebc113eb5cf30fc6585e53a961728304ac24e05ab2123d10"},"package":"a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"}

46
third_party/rust/nom-1.2.4/.travis.yml поставляемый
Просмотреть файл

@ -1,46 +0,0 @@
language: rust
addons:
apt:
packages:
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev
rust:
- nightly
- beta
- stable
- 1.2.0
before_script:
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
script:
- |
travis-cargo --only 1.2 test -- --features regexp &&
travis-cargo --only stable test -- --features "regexp regexp_macros" &&
travis-cargo --only beta test -- --features "regexp regexp_macros" &&
travis-cargo --only nightly build -- --features "nightly core regexp" &&
travis-cargo --only nightly test -- --features "regexp" &&
travis-cargo bench &&
travis-cargo --only stable doc -- --features "regexp"
after_success:
- travis-cargo coveralls --no-sudo
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/9c035a194ac4fd4cc061
on_success: change
on_failure: always
on_start: false
env:
global:
# override the default `--features unstable` used for the nightly branch (optional)
- TRAVIS_CARGO_NIGHTLY_FEATURE=nightly
sudo: false

555
third_party/rust/nom-1.2.4/CHANGELOG.md поставляемый
Просмотреть файл

@ -1,555 +0,0 @@
# Change Log
## [Unreleased][unreleased]
### Changed
## 1.2.4 - 2016-07-20
### Thanks
- @Phlosioneer for documentation fixes
- @sourrust for fixing offsets in `take_bits!`
- @ChrisMacNaughton for the XFS crate
- @pwoolcoc for `rest_s`
- @fitzgen for more `IResult` methods
- @gtors for the negative lookahead feature
- @frk1 and @jeandudey for little endian float parsing
- @jethrogb for fixing input usage in `many1`
- @acatton for beating me at nom golf :D
### Added
- the `rest_s` method on `IResult` returns the remaining `&str` input
- `unwrap_err` and `unwrap_inc` methods on `IResult`
- `not!` will peek at the input and return `Done` if the underlying parser returned `Error` or `Incomplete`, without consuming the input
- `le_f32` and `le_f64` parse little endian floating point numbers (IEEE 754)
-
### Fixed
- documentation fixes
- `take_bits!` is now more precise
- `many1` inccorectly used the `len` function instead of `input_len`
- the INI parser is simpler
- `recognize!` had an early `return` taht is removed now
## 1.2.3 - 2016-05-10
### Thanks
- @lu-zero for the contribution guidelines
- @GuillaumeGomez for fixes on `length_bytes` and some documentation
- @Hywan for ducomentation and test fixes
- @Xirdus for correct trait import issues
- @mspiegel for the new AST example
- @cholcombe973 for adding the `cond_with_error!` combinator
- @tstorch for refactoring `many0!`
- @panicbit for the folding combinators
- @evestera for `separated_list!` fixes
- @DanielKeep for correcting some enum imports
### Added
- Regular expression combinators starting with `re_bytes_` work on byte slices
- example parsing arithmetic expressions to an AST
- `cond_with_error!` works like `cond!` but will return `None` if the condition is false, and `Some(value)` if the underlying parser succeeded
- `fold_many0!`, `fold_many1!` and `fold_many_m_n!` will take a parser, an initial value and a combining function, and fold over the successful applications of the parser
### Fixed
- `length_bytes!` converts the result of its child parser to usize
- `take_till!` now imports `InputLength` instead of assuming it's in scope
- `separated_list!` and `separated_nonempty_list!` will not consume the separator if there's no following successfully parsed value
- no more warnings on build
### Changed
- simpler implementation of `many0!`
## 1.2.2 - 2016-03-09
### Thanks
- @conradev for fixing take_until_s!`
- @GuillaumeGomez for some documentation fixes
- @frewsxcv for some documentation fixes
- @tstorch for some test refactorings
### Added
- `nom::Err` now implements `std::error::Error`
### Fixed
- `hex_u32` does not parses more than 8 chars now
- `take_while!` and `take_while1!` will not perturb the behaviour of `recognize!` anymore
## 1.2.1 - 2016-02-23
### Thanks
- @sourrust for adding methods to `IResult`
- @tstorch for the test refactoring, and for adding methods to `IResult` and `Needed`
- @joelself for fixing the method system
### Added
- mapping methods over `IResult` and `Needed`
### Changed
- `apply_rf` is renamed to `apply_m`. This will not warrant a major version, since it is part missing from the methods feture added in the 1.2.0 release
- the `regexp_macros` feature that used `regex!` to precompile regular expressions has been replaced by the normal regex engine combined with `lazy_static`
### Fixed
- when a parser or combinator was returning an empty buffer as remaining part, it was generating one from a static empty string. This was messing with buffer offset calculation. Now, that empty slice is taken like this: `&input[input.len()..]`.
- The `regexp_macros` and `no_std` feature build again and are now tested with Travis CI
## 1.2.0 - 2016-02-08
### Thanks
- @zentner-kyle for type inference fixes
- @joelself for his work on `&str` parsing and method parsers
- @GuillaumeGomez for implementing methods on `IResult`
- @dirk for the `alt_complete!` combinator
- @tstorch for a lot of refactoring work and unit tests additions
- @jansegre for the hex digit parsers
- @belgum for some documentation fixes
- @lwandrebeck for some documentation fixes and code fixes in `hex_digit`
### Added
- `take_until_and_consume_s!` for consumption of string data until a tag
- more function patterns in `named!`. The error type can now be specified
- `alt_complete!` works like the `alt!` combinator, but tries the next branch if the current one returned `Incomplete`, instead of returning directly
- more unit tests for a lot of combinators
- hexadecimal digit parsers
- the `tuple!` combinator takes a list of parsers as argument, and applies them serially on the input. If all of them are successful, it willr eturn a tuple accumulating all the values. This combinator will (hopefully) replace most uses of `chain!`
- parsers can now be implemented as a method for a struct thanks to the `method!`, `call_m!` and `apply_rf!` combinators
### Fixed
- there were type inference issues in a few combinators. They will now be easier to compile
- `peek!` compilation with bare functions
- `&str` parsers were splitting data at the byte level, not at the char level, which can result in inconsistencies in parsing UTF-8 characters. They now use character indexes
- some method implementations were missing on `ÌResult<I,O,E>` (with specified error type instead of implicit)
## 1.1.0 - 2016-01-01
This release adds a lot of features related to `&str` parsing. The previous versions
were focused on `&[u8]` and bit streams parsing, but there's a need for more text
parsing with nom. The parsing functions like `alpha`, `digit` and others will now
accept either a `&[u8]` or a `&str`, so there is no breaking change on that part.
There are also a few performance improvements and documentation fixes.
### Thanks
- @Binero for pushing the work on `&str` parsing
- @meh for fixing `Option` and `Vec` imports
- @hoodie for a documentation fix
- @joelself for some documentation fixes
- @vberger for his traits magic making `nom functions more generic
### Added
- string related parsers: `tag_s!`, `take_s!`, `is_a_s!`, `is_not_s!`, `take_while_s!`, `take_while1_s!`, `take_till_s!
- `value!` is a combinator that always returns the same value. If a child parser is passed as second argument, that value is returned when the child parser succeeds
### Changed
- `tag!` will now compare even on partial input. If it expects "abcd" but receives "ef", it will now return an `Error` instead of `Incomplete`
- `many0!` and others will preallocate a larger vector to avoid some copies and reallocations
- `alpha`, `digit`, `alphanumeric`, `space` and `multispace` now accept as input a `&[u8]` or a `&str`. Additionally, they return an error if they receive an empty input
- `take_while!`, `take_while1!`, `take_while_s!`, `take_while1_s!` wilreturn an error on empty input
### Fixed
- if the child parser of `many0!` or `many1!` returns `Incomplete`, it will return `Incomplete` too, possibly updating the needed size
- `Option,` `Some`, `None` and `Vec` are now used with full path imports
## 1.0.1 - 2015-11-22
This releases makes the 1.0 version compatible with Rust 1.2 and 1.3
### Thanks
- @steveklabnik for fixing lifetime issues in Producers and Consumers
## 1.0.0 - 2015-11-16
Stable release for nom. A lot of new features, a few breaking changes
### Thanks
- @ahenry for macro fixes
- @bluss for fixing documentation
- @sourrust for cleaning code and debugging the new streaming utilities
- @meh for inline optimizations
- @ccmtaylor for fixing function imports
- @soro for improvements to the streaming utilities
- @breard-r for catching my typos
- @nelsonjchen for catching my typos too
- @divarvel for hex string parsers
- @mrordinaire for the `length_bytes!` combinator
### Breaking changes
- `IResult::Error` can now use custom error types, and is generic over the input type
- Producers and consumers have been replaced. The new implementation uses less memory and integrates more with parsers
- `nom::ErrorCode` is now `nom::ErrorKind`
- `filter!` has been renamed to `take_while!`
- `chain!` will count how much data is consumed and use that number to calculate how much data is needed if a parser returned `Incomplete`
- `alt!` returns `Incomplete` if a child parser returned `Incomplete`, instead of skipping to the next parser
- `IResult` does not require a lifetime tag anymore, yay!
### Added
- `complete!` will return an error if the child parser returned `Incomplete`
- `add_error!` will wrap an error, but allow backtracking
- `hex_u32` parser
### Fixed
- the behaviour around `Incomplete` is better for most parsers now
## 0.5.0 - 2015-10-16
This release fixes a few issues and stabilizes the code.
### Thanks
- @nox for documentation fixes
- @daboross for linting fixes
- @ahenry for fixing `tap!` and extending `dbg!` and `dbg_dmp!`
- @bluss for tracking down and fixing issues with unsafe code
- @meh for inlining parser functions
- @ccmtaylor for fixing import of `str::from_utf8`
### Fixed
- `tap!`, `dbg!` and `dbg_dmp!` now accept function parameters
### Changed
- the type used in `count_fixed!` must be `Copy`
- `chain!` calculates how much data is needed if one of the parsers returns `Incomplete
- optional parsers in `chain!` can return `Incomplete`
## 0.4.0 - 2015-09-08
Considering the number of changes since the last release, this version can contain breaking changes, so the version number becomes 0.4.0. A lot of new features and performance improvements!
### Thanks
- @frewsxcv for documentation fixes
- @ngrewe for his work on producers and consumers
- @meh for fixes on `chain!` and for the `rest` parser
- @daboross for refactoring `many0!` and `many1!`
- @aleksander for the `switch!` combinator idea
- @TechnoMancer for his help with bit level parsing
- @sxeraverx for pointing out a bug in `is_a!`
### Fixed
- `count_fixed!` must take an explicit type as argument to generate the fixed-size array
- optional parsing behaviour in `chain!`
- `count!` can take 0 elements
- `is_a!` and `is_not!` can now consume the whole input
### Added
- it is now possible to seek to the end of a `MemProducer`
- `opt!` returns `Done(input, None)` if `the child parser returned `Incomplete`
- `rest` will return the remaining input
- consumers can now seek to and from the end of input
- `switch!` applies a first parser then matches on its result to choose the next parser
- bit-level parsers
- character-level parsers
- regular expression parsers
- implementation of `take_till!`, `take_while!` and `take_while1!`
### Changed
- `alt!` can return `Incomplete`
- the error analysis functions will now take references to functions instead of moving them
- performance improvements on producers
- performance improvement for `filter!`
- performance improvement for `count!`: a `Vec` of the right size is directly allocated
## 0.3.11 - 2015-08-04
### Thanks
- @bluss for remarking that the crate included random junk lying non commited in my local repository
### Fixed
- cleanup of my local repository will ship less files in the crates, resulting in a smaller download
## 0.3.10 - 2015-08-03
### Added
- `bits!` for bit level parsing. It indicates that all child parsers will take a `(&[u8], usize)`as input, with the second parameter indicating the bit offset in the first byte. This allows viewing a byte slice as a bit stream. Most combinators can be used directly under `bits!`
- `take_bits!` takes an integer type and a number of bits, consumes that number of bits and updates the offset, possibly by crossing byte boundaries
- bit level parsers are all written in `src/bits.rs`
### Changed
- Parsers that specifically handle bytes have been moved to src/bytes.rs`. This applies to `tag!`, `is_not!`, `is_a!`, `filter!`, `take!`, `take_str!`, `take_until_and_consume!`, `take_until!`, `take_until_either_and_consume!`, `take_until_either!`
## 0.3.9 - 2015-07-20
### Thanks
- @badboy for fixing `filter!`
- @idmit for some documentation fixes
### Added
- `opt_res!` applies a parser and transform its result in a Result. This parser never fails
- `cond_reduce!` takes an expression as parameter, applies the parser if the expression is true, and returns an error if the expression is false
- `tap!` pass the result of a parser to a block to manipulate it, but do not affect the parser's result
- `AccReader` is a Read+BufRead that supports data accumulation and partial consumption. The `consume` method must be called afterwardsto indicate how much was consumed
- Arithmetic expression evaluation and parsing example
- `u16!`, `u32!`, `u64!`, `i16!`, `i32!`, `i64!` take an expression as parameter, if the expression is true, apply the big endian integer parser, if false, the little endian version
- type information for combinators. This will make the documentation a bit easier to navigate
### Fixed
- `map_opt!` and `map_res!` had issues with argument order due to bad macros
- `delimited!` did not compile for certain combinations of arguments
- `filter!` did not return a byte slice but a fixed array
## 0.3.8 - 2015-07-03
### Added
- code coverage is now calculated automatically on Travis CI
- `Stepper`: wrap a `Producer`, and call the method `step` with a parser. This method will buffer data if there is not enough, apply the parser if there is, and keep the rest of the input in memory for the next call
- `ReadProducer`: takes something implementing `Read`, and makes a `Producer` out of it
### Fixed
- the combinators `separated_pair!` and `delimited!` did not work because an implementation macro was not exported
- if a `MemProducer` reached its end, it should always return `Eof`
- `map!` had issues with argument matching
## 0.3.7 - 2015-06-24
### Added
- `expr_res!` and `expr_opt!` evaluate an expression returning a Result or Opt and convert it to IResult
- `AsBytes` is implemented for fixed size arrays. This allows `tag!([41u8, 42u8])`
### Fixed
- `count_fixed!` argument parsing works again
## 0.3.6 - 2015-06-15
### Added
- documentation for a few functions
- the consumer trait now requires the `failed(&self, error_code)` method in case of parsing error
- `named!` now handles thge alternative `named!(pub fun_name<OutputType>, ...)`
### Fixed
- `filter!` now returns the whole input if the filter function never returned false
- `take!` casts its argument as usize, so it can accepts any integer type now
## 0.3.5 - 2015-06-10
### Thanks
- @cmr for some documentation fixes
### Added
- `count_fixed!` returns a fixed array
### Fixed
- `count!` is back to the previous behaviour, returning a `Vec` for sizes known at runtime
### Changed
- functions and traits exported from `nom::util` are now directly in `nom::`
## 0.3.4 - 2015-06-09
### Thanks
- @andrew-d for fixes on `cond!`
- @keruspe for features in `chain!`
### Added
- `chain!` can now have mutable fields
### Fixed
- `cond!` had an infinite macro recursion
### Changed
- `chain!` generates less code now. No apprent compilation time improvement
## 0.3.3 - 2015-06-09
### Thanks
- @andrew-d for the little endian signed integer parsers
- @keruspe for fixes on `count!`
### Added
- `le_i8`, `le_i16`, `le_i32`, `le_i64`: little endian signed integer parsers
### Changed
- the `alt!` parser compiles much faster, even with more than 8 branches
- `count!` can now return a fixed size array instead of a growable vector
## 0.3.2 - 2015-05-31
### Thanks
- @keruspe for the `take_str` parser and the function application combinator
### Added
- `take_str!`: takes the specified number of bytes and return a UTF-8 string
- `apply!`: do partial application on the parameters of a function
### Changed
- `Needed::Size` now contains a `usize` instead of a `u32`
## 0.3.1 - 2015-05-21
### Thanks
- @divarvel for the big endian signed integer parsers
### Added
- `be_i8`, `be_i16`, `be_i32`, `be_i64`: big endian signed integer parsers
- the `core` feature can be passed to cargo to build with `no_std`
- colored hexdump can be generated from error chains
## 0.3.0 - 2015-05-07
### Thanks
- @filipegoncalves for some documentation and the new eof parser
- @CrimsonVoid for putting fully qualified types in the macros
- @lu_zero for some documentation fixes
### Added
- new error types that can contain an error code, an input slice, and a list of following errors
- `error!` will cut backtracking and return directly from the parser, with a specified error code
- `eof` parser, successful if there is no more input
- specific error codes for the parsers provided by nom
### Changed
- fully qualified types in macros. A lot of imports are not needed anymore
### Removed
- `FlatMap`, `FlatpMapOpt` and `Functor` traits (replaced by `map!`, `map_opt!` and `map_res!`)
## 0.2.2 - 2015-04-12
### Thanks
- @filipegoncalves and @thehydroimpulse for debugging an infinite loop in many0 and many1
- @thehydroimpulse for suggesting public named parsers
- @skade for removing the dependency on the collections gate
### Added
- `named!` can now declare public functions like this: `named!(pub tst, tag!("abcd"));`
- `pair!(X,Y)` returns a tuple `(x, y)`
- `separated_pair!(X, sep, Y)` returns a tuple `(x, y)`
- `preceded!(opening, X)` returns `x`
- `terminated!(X, closing)` returns `x`
- `delimited(opening, X, closing)` returns `x`
- `separated_list(sep, X)` returns a `Vec<X>`
- `separated_nonempty_list(sep, X)` returns a `Vec<X>` of at list one element
### Changed
- `many0!` and `many1!` forbid parsers that do not consume input
- `is_a!`, `is_not!`, `alpha`, `digit`, `space`, `multispace` will now return an error if they do not consume at least one byte
## 0.2.1 - 2015-04-04
### Thanks
- @mtsr for catching the remaining debug println!
- @jag426 who killed a lot of warnings
- @skade for removing the dependency on the core feature gate
### Added
- little endian unsigned int parsers le_u8, le_u16, le_u32, le_u64
- `count!` to apply a parser a specified number of times
- `cond!` applies a parser if the condition is met
- more parser development tools in `util::*`
### Fixed
- in one case, `opt!` would not compile
### Removed
- most of the feature gates are now removed. The only one still needed is `collections`
## 0.2.0 - 2015-03-24
*works with `rustc 1.0.0-dev (81e2396c7 2015-03-19) (built 2015-03-19)`*
### Thanks
- Ryman for the AsBytes implementation
- jag426 and jaredly for documentation fixes
- eternaleye on #rust IRC for his help on the new macro syntax
### Changed
- the AsBytes trait improves readability, no more b"...", but "..." instead
- Incomplete will now hold either Needed;;Unknown, or Needed::Size(u32). Matching on Incomplete without caring for the value is done with `Incomplete(_)`, but if more granularity is mandatory, `Needed` can be matched too
- `alt!` can pass the result of the parser to a closure
- the `take_*` macros changed behaviour, the default case is now not to consume the separator. The macros have been renamed as follows: `take_until!` -> `take_until_and_consume!`, `take_until_and_leave!` -> `take_until!`, `take_until_either_and_leave!` -> `take_until_either!`, `take_until_either!` -> `take_until_either_and_consume!`
### Added
- `peek!` macro: matches the future input but does not consume it
- `length_value!` macro: the first argument is a parser returning a `n` that can cast to usize, then applies the second parser `n` times. The macro has a variant with a third argument indicating the expected input size for the second parser
- benchmarks are available at https://github.com/Geal/nom_benchmarks
- more documentation
- **Unnamed parser syntax**: warning, this is a breaking change. With this new syntax, the macro combinators do not generate functions anymore, they create blocks. That way, they can be nested, for better readability. The `named!` macro is provided to create functions from parsers. Please be aware that nesting parsers comes with a small cost of compilation time, negligible in most cases, but can quickly get to the minutes scale if not careful. If this happens, separate your parsers in multiple subfunctions.
- `named!`, `closure!` and `call!` macros used to support the unnamed syntax
- `map!`, `map_opt!` and `map_res!` to combine a parser with a normal function, transforming the input directly, or returning an `Option` or `Result`
### Fixed
- `is_a!` is now working properly
### Removed
- the `o!` macro does less than `chain!`, so it has been removed
- the `fold0!` and `fold1!` macros were too complex and awkward to use, the `many*` combinators will be useful for most uses for now
## 0.1.6 - 2015-02-24
### Changed
- consumers must have an end method that will be called after parsing
### Added
- big endian unsigned int and float parsers: be_u8, be_u16, be_u32, be_u64, be_f32, be_f64
- producers can seek
- function and macros documentation
- README documentation
### Fixed
- lifetime declarations
- tag! can return Incomplete
## 0.1.5 - 2015-02-17
### Changed
- traits were renamed: FlatMapper -> FlatMap, Mapper -> FlatMapOpt, Mapper2 -> Functor
### Fixed
- woeks with rustc f1bb6c2f4
## 0.1.4 - 2015-02-17
### Changed
- the chaining macro can take optional arguments with '?'
## 0.1.3 - 2015-02-16
### Changed
- the chaining macro now takes the closure at the end of the argument list
## 0.1.2 - 2015-02-16
### Added
- flat_map implementation for <&[u8], &[u8]>
- chaining macro
- partial MP4 parser example
## 0.1.1 - 2015-02-06
### Fixed
- closure syntax change
## Compare code
* [unreleased]: https://github.com/Geal/nom/compare/1.2.4...HEAD
* [1.2.3]: https://github.com/Geal/nom/compare/1.2.3...1.2.4
* [1.2.3]: https://github.com/Geal/nom/compare/1.2.2...1.2.3
* [1.2.2]: https://github.com/Geal/nom/compare/1.2.1...1.2.2
* [1.2.1]: https://github.com/Geal/nom/compare/1.2.0...1.2.1
* [1.2.0]: https://github.com/Geal/nom/compare/1.1.0...1.2.0
* [1.1.0]: https://github.com/Geal/nom/compare/1.0.1...1.1.0
* [1.0.1]: https://github.com/Geal/nom/compare/1.0.0...1.0.1
* [1.0.0]: https://github.com/Geal/nom/compare/0.5.0...1.0.0
* [0.5.0]: https://github.com/geal/nom/compare/0.4.0...0.5.0
* [0.4.0]: https://github.com/geal/nom/compare/0.3.11...0.4.0
* [0.3.11]: https://github.com/geal/nom/compare/0.3.10...0.3.11
* [0.3.10]: https://github.com/geal/nom/compare/0.3.9...0.3.10
* [0.3.9]: https://github.com/geal/nom/compare/0.3.8...0.3.9
* [0.3.8]: https://github.com/Geal/nom/compare/0.3.7...0.3.8
* [0.3.7]: https://github.com/Geal/nom/compare/0.3.6...0.3.7
* [0.3.6]: https://github.com/Geal/nom/compare/0.3.5...0.3.6
* [0.3.5]: https://github.com/Geal/nom/compare/0.3.4...0.3.5
* [0.3.4]: https://github.com/Geal/nom/compare/0.3.3...0.3.4
* [0.3.3]: https://github.com/Geal/nom/compare/0.3.2...0.3.3
* [0.3.2]: https://github.com/Geal/nom/compare/0.3.1...0.3.2
* [0.3.1]: https://github.com/Geal/nom/compare/0.3.0...0.3.1
* [0.3.0]: https://github.com/Geal/nom/compare/0.2.2...0.3.0
* [0.2.2]: https://github.com/Geal/nom/compare/0.2.1...0.2.2
* [0.2.1]: https://github.com/Geal/nom/compare/0.2.0...0.2.1
* [0.2.0]: https://github.com/Geal/nom/compare/0.1.6...0.2.0
* [0.1.6]: https://github.com/Geal/nom/compare/0.1.5...0.1.6
* [0.1.5]: https://github.com/Geal/nom/compare/0.1.4...0.1.5
* [0.1.4]: https://github.com/Geal/nom/compare/0.1.3...0.1.4
* [0.1.3]: https://github.com/Geal/nom/compare/0.1.2...0.1.3
* [0.1.2]: https://github.com/Geal/nom/compare/0.1.1...0.1.2
* [0.1.1]: https://github.com/Geal/nom/compare/0.1.0...0.1.1

38
third_party/rust/nom-1.2.4/Cargo.toml поставляемый
Просмотреть файл

@ -1,38 +0,0 @@
[package]
name = "nom"
version = "1.2.4"
authors = [ "contact@geoffroycouprie.com" ]
description = "A byte-oriented, zero-copy, parser combinators library"
license = "MIT"
repository = "https://github.com/Geal/nom"
readme = "README.md"
documentation = "http://rust.unhandledexpression.com/nom/"
keywords = ["parser", "parser-combinators", "parsing", "streaming", "bit"]
include = [
"CHANGELOG.md",
"LICENSE",
".gitignore",
".travis.yml",
"Cargo.toml",
"src/*.rs",
"tests/*.rs"
]
[features]
core = []
nightly = []
default = ["stream"]
regexp = ["regex"]
regexp_macros = ["regexp", "lazy_static"]
stream = []
[dependencies.regex]
version = "^0.1.56"
optional = true
[dependencies.lazy_static]
version = "^0.2.1"
optional = true

20
third_party/rust/nom-1.2.4/LICENSE поставляемый
Просмотреть файл

@ -1,20 +0,0 @@
Copyright (c) 2015 Geoffroy Couprie
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Просмотреть файл

@ -1 +0,0 @@
{"files":{".travis.yml":"6d4e81838b10c5e330749857c72c2f2b1a2e575e71abcd11c094f3b612347b2a","CHANGELOG.md":"d4722e028b2a5b88c466b0d759e463b90bdcfa1b79181a1c76cd313b0a27c615","Cargo.toml":"aebcb999933c3425db85012bea19f9ce78da8e7834dbab54d4a2966e8bc62149","LICENSE":"de730187d5563a81342a3c011d968f78dff37c934fac9b3701e8c762b6118a55","src/bits.rs":"97c9148f63e175489bb6199d039c594ddc56bdf0b7491b9f38b8d74e898bca80","src/bytes.rs":"8f29b976a5e8e6500eb618a9dead7f212688ba9eb06c7066a4016e2db99fed00","src/character.rs":"9ee081f56b508212231ff70d7455b1b85ae44722a39aa60223e8cd95c6570859","src/internal.rs":"ada499b9c178be2a7f9b56319ffb10a778f25fafcda39c78d26b364d89debd72","src/lib.rs":"34efb051214acfde2053e93a7ba718a4fd41b6e0d9edd65a1737605d99b994ab","src/macros.rs":"d39ce3a2cd2b1cb9dd57ce90c06a1ca84720a2dc75e6332cffebba6086cb75d3","src/methods.rs":"24bdbcb0e3570c8bf3fa270dd8d79dd6dfcb982276c82180a89a1e73c5e38019","src/nom.rs":"b0a9c7ce0d09388179bce8f8e23bf57df76b504d925815583c249ec3fc04baab","src/regexp.rs":"8fdae52b761dbad90179e6be87e0e66357fefa34d76af541fb0fcf550fd6ec08","src/str.rs":"198fa15d45c3636289d92c0a592002a07e5a04a431e8cfdf724266e44d484be2","src/stream.rs":"c1bd5b8e7a2061ff66eb2c954033146001f1d65a26d12efa06af8cf93ffa53e4","src/util.rs":"da40ebac865d3176567d3a37b01170234398a03e938553720ce30aa1f6005b6d","tests/arithmetic.rs":"b98936b7fa0228835ca022f6db5342b72a9c01cc3f16a4e05263bbe6424ba3e9","tests/arithmetic_ast.rs":"b18b9a46ba573ae13c40a31217425f6e8cf8fade09a75cdbbfa7146ec668f0b2","tests/cross_function_backtracking.rs":"b071d13031c1f12195473186e3775943991496b10f4590db3f36d511e9f98a1c","tests/ini.rs":"776f681542028564899e55f71533b3bcda5ed1bbb971f24b5b1b9578111ba0cb","tests/ini_str.rs":"315046d9b6dc38d6d306d3562d7ac6518c9ecce9aabcc58fb80c07577ad99789","tests/issues.rs":"2193c219397b7a417cc009b72c13adc42471e7a4917a2a4009aa0fca23c6ea8c","tests/mp4.rs":"b4bf0514fd645160851cc4da9ad6bf81d571cd14865bf134837c19578caaf6e6","tests/omnom.rs":"409d2349fa24f3503bd02e0079c1554a58ce3d40dd7eb0e5d4bb63b588afdae4","tests/test1.rs":"3e0c187bad91d822ebc113eb5cf30fc6585e53a961728304ac24e05ab2123d10"},"package":"a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"}

46
third_party/rust/nom-1.2.4/nom/.travis.yml поставляемый
Просмотреть файл

@ -1,46 +0,0 @@
language: rust
addons:
apt:
packages:
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev
rust:
- nightly
- beta
- stable
- 1.2.0
before_script:
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
script:
- |
travis-cargo --only 1.2 test -- --features regexp &&
travis-cargo --only stable test -- --features "regexp regexp_macros" &&
travis-cargo --only beta test -- --features "regexp regexp_macros" &&
travis-cargo --only nightly build -- --features "nightly core regexp" &&
travis-cargo --only nightly test -- --features "regexp" &&
travis-cargo bench &&
travis-cargo --only stable doc -- --features "regexp"
after_success:
- travis-cargo coveralls --no-sudo
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/9c035a194ac4fd4cc061
on_success: change
on_failure: always
on_start: false
env:
global:
# override the default `--features unstable` used for the nightly branch (optional)
- TRAVIS_CARGO_NIGHTLY_FEATURE=nightly
sudo: false

555
third_party/rust/nom-1.2.4/nom/CHANGELOG.md поставляемый
Просмотреть файл

@ -1,555 +0,0 @@
# Change Log
## [Unreleased][unreleased]
### Changed
## 1.2.4 - 2016-07-20
### Thanks
- @Phlosioneer for documentation fixes
- @sourrust for fixing offsets in `take_bits!`
- @ChrisMacNaughton for the XFS crate
- @pwoolcoc for `rest_s`
- @fitzgen for more `IResult` methods
- @gtors for the negative lookahead feature
- @frk1 and @jeandudey for little endian float parsing
- @jethrogb for fixing input usage in `many1`
- @acatton for beating me at nom golf :D
### Added
- the `rest_s` method on `IResult` returns the remaining `&str` input
- `unwrap_err` and `unwrap_inc` methods on `IResult`
- `not!` will peek at the input and return `Done` if the underlying parser returned `Error` or `Incomplete`, without consuming the input
- `le_f32` and `le_f64` parse little endian floating point numbers (IEEE 754)
-
### Fixed
- documentation fixes
- `take_bits!` is now more precise
- `many1` inccorectly used the `len` function instead of `input_len`
- the INI parser is simpler
- `recognize!` had an early `return` taht is removed now
## 1.2.3 - 2016-05-10
### Thanks
- @lu-zero for the contribution guidelines
- @GuillaumeGomez for fixes on `length_bytes` and some documentation
- @Hywan for ducomentation and test fixes
- @Xirdus for correct trait import issues
- @mspiegel for the new AST example
- @cholcombe973 for adding the `cond_with_error!` combinator
- @tstorch for refactoring `many0!`
- @panicbit for the folding combinators
- @evestera for `separated_list!` fixes
- @DanielKeep for correcting some enum imports
### Added
- Regular expression combinators starting with `re_bytes_` work on byte slices
- example parsing arithmetic expressions to an AST
- `cond_with_error!` works like `cond!` but will return `None` if the condition is false, and `Some(value)` if the underlying parser succeeded
- `fold_many0!`, `fold_many1!` and `fold_many_m_n!` will take a parser, an initial value and a combining function, and fold over the successful applications of the parser
### Fixed
- `length_bytes!` converts the result of its child parser to usize
- `take_till!` now imports `InputLength` instead of assuming it's in scope
- `separated_list!` and `separated_nonempty_list!` will not consume the separator if there's no following successfully parsed value
- no more warnings on build
### Changed
- simpler implementation of `many0!`
## 1.2.2 - 2016-03-09
### Thanks
- @conradev for fixing take_until_s!`
- @GuillaumeGomez for some documentation fixes
- @frewsxcv for some documentation fixes
- @tstorch for some test refactorings
### Added
- `nom::Err` now implements `std::error::Error`
### Fixed
- `hex_u32` does not parses more than 8 chars now
- `take_while!` and `take_while1!` will not perturb the behaviour of `recognize!` anymore
## 1.2.1 - 2016-02-23
### Thanks
- @sourrust for adding methods to `IResult`
- @tstorch for the test refactoring, and for adding methods to `IResult` and `Needed`
- @joelself for fixing the method system
### Added
- mapping methods over `IResult` and `Needed`
### Changed
- `apply_rf` is renamed to `apply_m`. This will not warrant a major version, since it is part missing from the methods feture added in the 1.2.0 release
- the `regexp_macros` feature that used `regex!` to precompile regular expressions has been replaced by the normal regex engine combined with `lazy_static`
### Fixed
- when a parser or combinator was returning an empty buffer as remaining part, it was generating one from a static empty string. This was messing with buffer offset calculation. Now, that empty slice is taken like this: `&input[input.len()..]`.
- The `regexp_macros` and `no_std` feature build again and are now tested with Travis CI
## 1.2.0 - 2016-02-08
### Thanks
- @zentner-kyle for type inference fixes
- @joelself for his work on `&str` parsing and method parsers
- @GuillaumeGomez for implementing methods on `IResult`
- @dirk for the `alt_complete!` combinator
- @tstorch for a lot of refactoring work and unit tests additions
- @jansegre for the hex digit parsers
- @belgum for some documentation fixes
- @lwandrebeck for some documentation fixes and code fixes in `hex_digit`
### Added
- `take_until_and_consume_s!` for consumption of string data until a tag
- more function patterns in `named!`. The error type can now be specified
- `alt_complete!` works like the `alt!` combinator, but tries the next branch if the current one returned `Incomplete`, instead of returning directly
- more unit tests for a lot of combinators
- hexadecimal digit parsers
- the `tuple!` combinator takes a list of parsers as argument, and applies them serially on the input. If all of them are successful, it willr eturn a tuple accumulating all the values. This combinator will (hopefully) replace most uses of `chain!`
- parsers can now be implemented as a method for a struct thanks to the `method!`, `call_m!` and `apply_rf!` combinators
### Fixed
- there were type inference issues in a few combinators. They will now be easier to compile
- `peek!` compilation with bare functions
- `&str` parsers were splitting data at the byte level, not at the char level, which can result in inconsistencies in parsing UTF-8 characters. They now use character indexes
- some method implementations were missing on `ÌResult<I,O,E>` (with specified error type instead of implicit)
## 1.1.0 - 2016-01-01
This release adds a lot of features related to `&str` parsing. The previous versions
were focused on `&[u8]` and bit streams parsing, but there's a need for more text
parsing with nom. The parsing functions like `alpha`, `digit` and others will now
accept either a `&[u8]` or a `&str`, so there is no breaking change on that part.
There are also a few performance improvements and documentation fixes.
### Thanks
- @Binero for pushing the work on `&str` parsing
- @meh for fixing `Option` and `Vec` imports
- @hoodie for a documentation fix
- @joelself for some documentation fixes
- @vberger for his traits magic making `nom functions more generic
### Added
- string related parsers: `tag_s!`, `take_s!`, `is_a_s!`, `is_not_s!`, `take_while_s!`, `take_while1_s!`, `take_till_s!
- `value!` is a combinator that always returns the same value. If a child parser is passed as second argument, that value is returned when the child parser succeeds
### Changed
- `tag!` will now compare even on partial input. If it expects "abcd" but receives "ef", it will now return an `Error` instead of `Incomplete`
- `many0!` and others will preallocate a larger vector to avoid some copies and reallocations
- `alpha`, `digit`, `alphanumeric`, `space` and `multispace` now accept as input a `&[u8]` or a `&str`. Additionally, they return an error if they receive an empty input
- `take_while!`, `take_while1!`, `take_while_s!`, `take_while1_s!` wilreturn an error on empty input
### Fixed
- if the child parser of `many0!` or `many1!` returns `Incomplete`, it will return `Incomplete` too, possibly updating the needed size
- `Option,` `Some`, `None` and `Vec` are now used with full path imports
## 1.0.1 - 2015-11-22
This releases makes the 1.0 version compatible with Rust 1.2 and 1.3
### Thanks
- @steveklabnik for fixing lifetime issues in Producers and Consumers
## 1.0.0 - 2015-11-16
Stable release for nom. A lot of new features, a few breaking changes
### Thanks
- @ahenry for macro fixes
- @bluss for fixing documentation
- @sourrust for cleaning code and debugging the new streaming utilities
- @meh for inline optimizations
- @ccmtaylor for fixing function imports
- @soro for improvements to the streaming utilities
- @breard-r for catching my typos
- @nelsonjchen for catching my typos too
- @divarvel for hex string parsers
- @mrordinaire for the `length_bytes!` combinator
### Breaking changes
- `IResult::Error` can now use custom error types, and is generic over the input type
- Producers and consumers have been replaced. The new implementation uses less memory and integrates more with parsers
- `nom::ErrorCode` is now `nom::ErrorKind`
- `filter!` has been renamed to `take_while!`
- `chain!` will count how much data is consumed and use that number to calculate how much data is needed if a parser returned `Incomplete`
- `alt!` returns `Incomplete` if a child parser returned `Incomplete`, instead of skipping to the next parser
- `IResult` does not require a lifetime tag anymore, yay!
### Added
- `complete!` will return an error if the child parser returned `Incomplete`
- `add_error!` will wrap an error, but allow backtracking
- `hex_u32` parser
### Fixed
- the behaviour around `Incomplete` is better for most parsers now
## 0.5.0 - 2015-10-16
This release fixes a few issues and stabilizes the code.
### Thanks
- @nox for documentation fixes
- @daboross for linting fixes
- @ahenry for fixing `tap!` and extending `dbg!` and `dbg_dmp!`
- @bluss for tracking down and fixing issues with unsafe code
- @meh for inlining parser functions
- @ccmtaylor for fixing import of `str::from_utf8`
### Fixed
- `tap!`, `dbg!` and `dbg_dmp!` now accept function parameters
### Changed
- the type used in `count_fixed!` must be `Copy`
- `chain!` calculates how much data is needed if one of the parsers returns `Incomplete
- optional parsers in `chain!` can return `Incomplete`
## 0.4.0 - 2015-09-08
Considering the number of changes since the last release, this version can contain breaking changes, so the version number becomes 0.4.0. A lot of new features and performance improvements!
### Thanks
- @frewsxcv for documentation fixes
- @ngrewe for his work on producers and consumers
- @meh for fixes on `chain!` and for the `rest` parser
- @daboross for refactoring `many0!` and `many1!`
- @aleksander for the `switch!` combinator idea
- @TechnoMancer for his help with bit level parsing
- @sxeraverx for pointing out a bug in `is_a!`
### Fixed
- `count_fixed!` must take an explicit type as argument to generate the fixed-size array
- optional parsing behaviour in `chain!`
- `count!` can take 0 elements
- `is_a!` and `is_not!` can now consume the whole input
### Added
- it is now possible to seek to the end of a `MemProducer`
- `opt!` returns `Done(input, None)` if `the child parser returned `Incomplete`
- `rest` will return the remaining input
- consumers can now seek to and from the end of input
- `switch!` applies a first parser then matches on its result to choose the next parser
- bit-level parsers
- character-level parsers
- regular expression parsers
- implementation of `take_till!`, `take_while!` and `take_while1!`
### Changed
- `alt!` can return `Incomplete`
- the error analysis functions will now take references to functions instead of moving them
- performance improvements on producers
- performance improvement for `filter!`
- performance improvement for `count!`: a `Vec` of the right size is directly allocated
## 0.3.11 - 2015-08-04
### Thanks
- @bluss for remarking that the crate included random junk lying non commited in my local repository
### Fixed
- cleanup of my local repository will ship less files in the crates, resulting in a smaller download
## 0.3.10 - 2015-08-03
### Added
- `bits!` for bit level parsing. It indicates that all child parsers will take a `(&[u8], usize)`as input, with the second parameter indicating the bit offset in the first byte. This allows viewing a byte slice as a bit stream. Most combinators can be used directly under `bits!`
- `take_bits!` takes an integer type and a number of bits, consumes that number of bits and updates the offset, possibly by crossing byte boundaries
- bit level parsers are all written in `src/bits.rs`
### Changed
- Parsers that specifically handle bytes have been moved to src/bytes.rs`. This applies to `tag!`, `is_not!`, `is_a!`, `filter!`, `take!`, `take_str!`, `take_until_and_consume!`, `take_until!`, `take_until_either_and_consume!`, `take_until_either!`
## 0.3.9 - 2015-07-20
### Thanks
- @badboy for fixing `filter!`
- @idmit for some documentation fixes
### Added
- `opt_res!` applies a parser and transform its result in a Result. This parser never fails
- `cond_reduce!` takes an expression as parameter, applies the parser if the expression is true, and returns an error if the expression is false
- `tap!` pass the result of a parser to a block to manipulate it, but do not affect the parser's result
- `AccReader` is a Read+BufRead that supports data accumulation and partial consumption. The `consume` method must be called afterwardsto indicate how much was consumed
- Arithmetic expression evaluation and parsing example
- `u16!`, `u32!`, `u64!`, `i16!`, `i32!`, `i64!` take an expression as parameter, if the expression is true, apply the big endian integer parser, if false, the little endian version
- type information for combinators. This will make the documentation a bit easier to navigate
### Fixed
- `map_opt!` and `map_res!` had issues with argument order due to bad macros
- `delimited!` did not compile for certain combinations of arguments
- `filter!` did not return a byte slice but a fixed array
## 0.3.8 - 2015-07-03
### Added
- code coverage is now calculated automatically on Travis CI
- `Stepper`: wrap a `Producer`, and call the method `step` with a parser. This method will buffer data if there is not enough, apply the parser if there is, and keep the rest of the input in memory for the next call
- `ReadProducer`: takes something implementing `Read`, and makes a `Producer` out of it
### Fixed
- the combinators `separated_pair!` and `delimited!` did not work because an implementation macro was not exported
- if a `MemProducer` reached its end, it should always return `Eof`
- `map!` had issues with argument matching
## 0.3.7 - 2015-06-24
### Added
- `expr_res!` and `expr_opt!` evaluate an expression returning a Result or Opt and convert it to IResult
- `AsBytes` is implemented for fixed size arrays. This allows `tag!([41u8, 42u8])`
### Fixed
- `count_fixed!` argument parsing works again
## 0.3.6 - 2015-06-15
### Added
- documentation for a few functions
- the consumer trait now requires the `failed(&self, error_code)` method in case of parsing error
- `named!` now handles thge alternative `named!(pub fun_name<OutputType>, ...)`
### Fixed
- `filter!` now returns the whole input if the filter function never returned false
- `take!` casts its argument as usize, so it can accepts any integer type now
## 0.3.5 - 2015-06-10
### Thanks
- @cmr for some documentation fixes
### Added
- `count_fixed!` returns a fixed array
### Fixed
- `count!` is back to the previous behaviour, returning a `Vec` for sizes known at runtime
### Changed
- functions and traits exported from `nom::util` are now directly in `nom::`
## 0.3.4 - 2015-06-09
### Thanks
- @andrew-d for fixes on `cond!`
- @keruspe for features in `chain!`
### Added
- `chain!` can now have mutable fields
### Fixed
- `cond!` had an infinite macro recursion
### Changed
- `chain!` generates less code now. No apprent compilation time improvement
## 0.3.3 - 2015-06-09
### Thanks
- @andrew-d for the little endian signed integer parsers
- @keruspe for fixes on `count!`
### Added
- `le_i8`, `le_i16`, `le_i32`, `le_i64`: little endian signed integer parsers
### Changed
- the `alt!` parser compiles much faster, even with more than 8 branches
- `count!` can now return a fixed size array instead of a growable vector
## 0.3.2 - 2015-05-31
### Thanks
- @keruspe for the `take_str` parser and the function application combinator
### Added
- `take_str!`: takes the specified number of bytes and return a UTF-8 string
- `apply!`: do partial application on the parameters of a function
### Changed
- `Needed::Size` now contains a `usize` instead of a `u32`
## 0.3.1 - 2015-05-21
### Thanks
- @divarvel for the big endian signed integer parsers
### Added
- `be_i8`, `be_i16`, `be_i32`, `be_i64`: big endian signed integer parsers
- the `core` feature can be passed to cargo to build with `no_std`
- colored hexdump can be generated from error chains
## 0.3.0 - 2015-05-07
### Thanks
- @filipegoncalves for some documentation and the new eof parser
- @CrimsonVoid for putting fully qualified types in the macros
- @lu_zero for some documentation fixes
### Added
- new error types that can contain an error code, an input slice, and a list of following errors
- `error!` will cut backtracking and return directly from the parser, with a specified error code
- `eof` parser, successful if there is no more input
- specific error codes for the parsers provided by nom
### Changed
- fully qualified types in macros. A lot of imports are not needed anymore
### Removed
- `FlatMap`, `FlatpMapOpt` and `Functor` traits (replaced by `map!`, `map_opt!` and `map_res!`)
## 0.2.2 - 2015-04-12
### Thanks
- @filipegoncalves and @thehydroimpulse for debugging an infinite loop in many0 and many1
- @thehydroimpulse for suggesting public named parsers
- @skade for removing the dependency on the collections gate
### Added
- `named!` can now declare public functions like this: `named!(pub tst, tag!("abcd"));`
- `pair!(X,Y)` returns a tuple `(x, y)`
- `separated_pair!(X, sep, Y)` returns a tuple `(x, y)`
- `preceded!(opening, X)` returns `x`
- `terminated!(X, closing)` returns `x`
- `delimited(opening, X, closing)` returns `x`
- `separated_list(sep, X)` returns a `Vec<X>`
- `separated_nonempty_list(sep, X)` returns a `Vec<X>` of at list one element
### Changed
- `many0!` and `many1!` forbid parsers that do not consume input
- `is_a!`, `is_not!`, `alpha`, `digit`, `space`, `multispace` will now return an error if they do not consume at least one byte
## 0.2.1 - 2015-04-04
### Thanks
- @mtsr for catching the remaining debug println!
- @jag426 who killed a lot of warnings
- @skade for removing the dependency on the core feature gate
### Added
- little endian unsigned int parsers le_u8, le_u16, le_u32, le_u64
- `count!` to apply a parser a specified number of times
- `cond!` applies a parser if the condition is met
- more parser development tools in `util::*`
### Fixed
- in one case, `opt!` would not compile
### Removed
- most of the feature gates are now removed. The only one still needed is `collections`
## 0.2.0 - 2015-03-24
*works with `rustc 1.0.0-dev (81e2396c7 2015-03-19) (built 2015-03-19)`*
### Thanks
- Ryman for the AsBytes implementation
- jag426 and jaredly for documentation fixes
- eternaleye on #rust IRC for his help on the new macro syntax
### Changed
- the AsBytes trait improves readability, no more b"...", but "..." instead
- Incomplete will now hold either Needed;;Unknown, or Needed::Size(u32). Matching on Incomplete without caring for the value is done with `Incomplete(_)`, but if more granularity is mandatory, `Needed` can be matched too
- `alt!` can pass the result of the parser to a closure
- the `take_*` macros changed behaviour, the default case is now not to consume the separator. The macros have been renamed as follows: `take_until!` -> `take_until_and_consume!`, `take_until_and_leave!` -> `take_until!`, `take_until_either_and_leave!` -> `take_until_either!`, `take_until_either!` -> `take_until_either_and_consume!`
### Added
- `peek!` macro: matches the future input but does not consume it
- `length_value!` macro: the first argument is a parser returning a `n` that can cast to usize, then applies the second parser `n` times. The macro has a variant with a third argument indicating the expected input size for the second parser
- benchmarks are available at https://github.com/Geal/nom_benchmarks
- more documentation
- **Unnamed parser syntax**: warning, this is a breaking change. With this new syntax, the macro combinators do not generate functions anymore, they create blocks. That way, they can be nested, for better readability. The `named!` macro is provided to create functions from parsers. Please be aware that nesting parsers comes with a small cost of compilation time, negligible in most cases, but can quickly get to the minutes scale if not careful. If this happens, separate your parsers in multiple subfunctions.
- `named!`, `closure!` and `call!` macros used to support the unnamed syntax
- `map!`, `map_opt!` and `map_res!` to combine a parser with a normal function, transforming the input directly, or returning an `Option` or `Result`
### Fixed
- `is_a!` is now working properly
### Removed
- the `o!` macro does less than `chain!`, so it has been removed
- the `fold0!` and `fold1!` macros were too complex and awkward to use, the `many*` combinators will be useful for most uses for now
## 0.1.6 - 2015-02-24
### Changed
- consumers must have an end method that will be called after parsing
### Added
- big endian unsigned int and float parsers: be_u8, be_u16, be_u32, be_u64, be_f32, be_f64
- producers can seek
- function and macros documentation
- README documentation
### Fixed
- lifetime declarations
- tag! can return Incomplete
## 0.1.5 - 2015-02-17
### Changed
- traits were renamed: FlatMapper -> FlatMap, Mapper -> FlatMapOpt, Mapper2 -> Functor
### Fixed
- woeks with rustc f1bb6c2f4
## 0.1.4 - 2015-02-17
### Changed
- the chaining macro can take optional arguments with '?'
## 0.1.3 - 2015-02-16
### Changed
- the chaining macro now takes the closure at the end of the argument list
## 0.1.2 - 2015-02-16
### Added
- flat_map implementation for <&[u8], &[u8]>
- chaining macro
- partial MP4 parser example
## 0.1.1 - 2015-02-06
### Fixed
- closure syntax change
## Compare code
* [unreleased]: https://github.com/Geal/nom/compare/1.2.4...HEAD
* [1.2.3]: https://github.com/Geal/nom/compare/1.2.3...1.2.4
* [1.2.3]: https://github.com/Geal/nom/compare/1.2.2...1.2.3
* [1.2.2]: https://github.com/Geal/nom/compare/1.2.1...1.2.2
* [1.2.1]: https://github.com/Geal/nom/compare/1.2.0...1.2.1
* [1.2.0]: https://github.com/Geal/nom/compare/1.1.0...1.2.0
* [1.1.0]: https://github.com/Geal/nom/compare/1.0.1...1.1.0
* [1.0.1]: https://github.com/Geal/nom/compare/1.0.0...1.0.1
* [1.0.0]: https://github.com/Geal/nom/compare/0.5.0...1.0.0
* [0.5.0]: https://github.com/geal/nom/compare/0.4.0...0.5.0
* [0.4.0]: https://github.com/geal/nom/compare/0.3.11...0.4.0
* [0.3.11]: https://github.com/geal/nom/compare/0.3.10...0.3.11
* [0.3.10]: https://github.com/geal/nom/compare/0.3.9...0.3.10
* [0.3.9]: https://github.com/geal/nom/compare/0.3.8...0.3.9
* [0.3.8]: https://github.com/Geal/nom/compare/0.3.7...0.3.8
* [0.3.7]: https://github.com/Geal/nom/compare/0.3.6...0.3.7
* [0.3.6]: https://github.com/Geal/nom/compare/0.3.5...0.3.6
* [0.3.5]: https://github.com/Geal/nom/compare/0.3.4...0.3.5
* [0.3.4]: https://github.com/Geal/nom/compare/0.3.3...0.3.4
* [0.3.3]: https://github.com/Geal/nom/compare/0.3.2...0.3.3
* [0.3.2]: https://github.com/Geal/nom/compare/0.3.1...0.3.2
* [0.3.1]: https://github.com/Geal/nom/compare/0.3.0...0.3.1
* [0.3.0]: https://github.com/Geal/nom/compare/0.2.2...0.3.0
* [0.2.2]: https://github.com/Geal/nom/compare/0.2.1...0.2.2
* [0.2.1]: https://github.com/Geal/nom/compare/0.2.0...0.2.1
* [0.2.0]: https://github.com/Geal/nom/compare/0.1.6...0.2.0
* [0.1.6]: https://github.com/Geal/nom/compare/0.1.5...0.1.6
* [0.1.5]: https://github.com/Geal/nom/compare/0.1.4...0.1.5
* [0.1.4]: https://github.com/Geal/nom/compare/0.1.3...0.1.4
* [0.1.3]: https://github.com/Geal/nom/compare/0.1.2...0.1.3
* [0.1.2]: https://github.com/Geal/nom/compare/0.1.1...0.1.2
* [0.1.1]: https://github.com/Geal/nom/compare/0.1.0...0.1.1

38
third_party/rust/nom-1.2.4/nom/Cargo.toml поставляемый
Просмотреть файл

@ -1,38 +0,0 @@
[package]
name = "nom"
version = "1.2.4"
authors = [ "contact@geoffroycouprie.com" ]
description = "A byte-oriented, zero-copy, parser combinators library"
license = "MIT"
repository = "https://github.com/Geal/nom"
readme = "README.md"
documentation = "http://rust.unhandledexpression.com/nom/"
keywords = ["parser", "parser-combinators", "parsing", "streaming", "bit"]
include = [
"CHANGELOG.md",
"LICENSE",
".gitignore",
".travis.yml",
"Cargo.toml",
"src/*.rs",
"tests/*.rs"
]
[features]
core = []
nightly = []
default = ["stream"]
regexp = ["regex"]
regexp_macros = ["regexp", "lazy_static"]
stream = []
[dependencies.regex]
version = "^0.1.56"
optional = true
[dependencies.lazy_static]
version = "^0.2.1"
optional = true

20
third_party/rust/nom-1.2.4/nom/LICENSE поставляемый
Просмотреть файл

@ -1,20 +0,0 @@
Copyright (c) 2015 Geoffroy Couprie
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

220
third_party/rust/nom-1.2.4/nom/src/bits.rs поставляемый
Просмотреть файл

@ -1,220 +0,0 @@
//! Bit level parsers and combinators
//!
//! Bit parsing is handled by tweaking the input in most macros.
//! In byte level parsing, the input is generally a `&[u8]` passed from combinator
//! to combinator until the slices are manipulated.
//!
//! Bit parsers take a `(&[u8], usize)` as input. The first part of the tuple is an byte slice,
//! the second part is a bit offset in the first byte of the slice.
//!
//! By passing a pair like this, we can leverage most of the combinators, and avoid
//! transforming the whole slice to a vector of booleans. This should make it easy
//! to see a byte slice as a bit stream, and parse code points of arbitrary bit length.
/// `bits!( parser ) => ( &[u8], (&[u8], usize) -> IResult<(&[u8], usize), T> ) -> IResult<&[u8], T>`
/// transforms its byte slice input into a bit stream for the underlying parsers
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
/// named!( take_3_bits<u8>, bits!( take_bits!( u8, 3 ) ) );
///
/// let input = vec![0b10101010, 0b11110000, 0b00110011];
/// let sl = &input[..];
///
/// assert_eq!(take_3_bits( sl ), Done(&sl[1..], 5) );
/// # }
#[macro_export]
macro_rules! bits (
($i:expr, $submac:ident!( $($args:tt)* )) => (
bits_impl!($i, $submac!($($args)*));
);
($i:expr, $f:expr) => (
bits_impl!($i, call!($f));
);
);
/// Internal parser, do not use directly
#[doc(hidden)]
#[macro_export]
macro_rules! bits_impl (
($i:expr, $submac:ident!( $($args:tt)* )) => (
{
let input = ($i, 0usize);
match $submac!(input, $($args)*) {
$crate::IResult::Error(e) => {
let err = match e {
$crate::Err::Code(k) | $crate::Err::Node(k, _) => $crate::Err::Code(k),
$crate::Err::Position(k, (i,b)) | $crate::Err::NodePosition(k, (i,b), _) => {
$crate::Err::Position(k, &i[b/8..])
}
};
$crate::IResult::Error(err)
}
$crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
//println!("bits parser returned Needed::Size({})", i);
$crate::IResult::Incomplete($crate::Needed::Size(i / 8 + 1))
},
$crate::IResult::Done((i, bit_index), o) => {
let byte_index = bit_index / 8 + if bit_index % 8 == 0 { 0 } else { 1 } ;
//println!("bit index=={} => byte index=={}", bit_index, byte_index);
$crate::IResult::Done(&i[byte_index..], o)
}
}
}
);
);
/// `take_bits!(type, nb) => ( (&[T], usize), U, usize) -> IResult<(&[T], usize), U>`
/// generates a parser consuming the specified number of bits.
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
/// named!( take_pair<(u8, u8)>, bits!( pair!( take_bits!( u8, 3 ), take_bits!(u8, 5) ) ) );
///
/// let input = vec![0b10101010, 0b11110000, 0b00110011];
/// let sl = &input[..];
///
/// assert_eq!(take_pair( sl ), Done(&sl[1..], (5, 10)) );
/// assert_eq!(take_pair( &sl[1..] ), Done(&sl[2..], (7, 16)) );
/// # }
/// ```
#[macro_export]
macro_rules! take_bits (
($i:expr, $t:ty, $count:expr) => (
{
use std::ops::Div;
//println!("taking {} bits from {:?}", $count, $i);
let (input, bit_offset) = $i;
let res : $crate::IResult<(&[u8],usize), $t> = if $count == 0 {
$crate::IResult::Done( (input, bit_offset), 0)
} else {
let cnt = ($count as usize + bit_offset).div(8);
if input.len() * 8 < $count as usize + bit_offset {
//println!("returning incomplete: {}", $count as usize + bit_offset);
$crate::IResult::Incomplete($crate::Needed::Size($count as usize))
} else {
let mut acc:$t = 0;
let mut offset: usize = bit_offset;
let mut remaining: usize = $count;
let mut end_offset: usize = 0;
for byte in input.iter().take(cnt + 1) {
if remaining == 0 {
break;
}
let val: $t = if offset == 0 {
*byte as $t
} else {
((*byte << offset) as u8 >> offset) as $t
};
if remaining < 8 - offset {
acc += val >> (8 - offset - remaining);
end_offset = remaining + offset;
break;
} else {
acc += val << (remaining - (8 - offset));
remaining -= 8 - offset;
offset = 0;
}
}
$crate::IResult::Done( (&input[cnt..], end_offset) , acc)
}
};
res
}
);
);
/// matches an integer pattern to a bitstream. The number of bits of the input to compare must be specified
#[macro_export]
macro_rules! tag_bits (
($i:expr, $t:ty, $count:expr, $p: pat) => (
{
match take_bits!($i, $t, $count) {
$crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
$crate::IResult::Done(i, o) => {
if let $p = o {
let res: $crate::IResult<(&[u8],usize),$t> = $crate::IResult::Done(i, o);
res
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TagBits, $i))
}
},
_ => {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TagBits, $i))
}
}
}
)
);
#[cfg(test)]
mod tests {
use internal::{IResult,Needed,Err};
use ErrorKind;
#[test]
fn take_bits() {
let input = vec![0b10101010, 0b11110000, 0b00110011];
let sl = &input[..];
assert_eq!(take_bits!( (sl, 0), u8, 0 ), IResult::Done((sl, 0), 0));
assert_eq!(take_bits!( (sl, 0), u8, 8 ), IResult::Done((&sl[1..], 0), 170));
assert_eq!(take_bits!( (sl, 0), u8, 3 ), IResult::Done((&sl[0..], 3), 5));
assert_eq!(take_bits!( (sl, 0), u8, 6 ), IResult::Done((&sl[0..], 6), 42));
assert_eq!(take_bits!( (sl, 1), u8, 1 ), IResult::Done((&sl[0..], 2), 0));
assert_eq!(take_bits!( (sl, 1), u8, 2 ), IResult::Done((&sl[0..], 3), 1));
assert_eq!(take_bits!( (sl, 1), u8, 3 ), IResult::Done((&sl[0..], 4), 2));
assert_eq!(take_bits!( (sl, 6), u8, 3 ), IResult::Done((&sl[1..], 1), 5));
assert_eq!(take_bits!( (sl, 0), u16, 10 ), IResult::Done((&sl[1..], 2), 683));
assert_eq!(take_bits!( (sl, 0), u16, 8 ), IResult::Done((&sl[1..], 0), 170));
assert_eq!(take_bits!( (sl, 6), u16, 10 ), IResult::Done((&sl[2..], 0), 752));
assert_eq!(take_bits!( (sl, 6), u16, 11 ), IResult::Done((&sl[2..], 1), 1504));
assert_eq!(take_bits!( (sl, 0), u32, 20 ), IResult::Done((&sl[2..], 4), 700163));
assert_eq!(take_bits!( (sl, 4), u32, 20 ), IResult::Done((&sl[3..], 0), 716851));
assert_eq!(take_bits!( (sl, 4), u32, 22 ), IResult::Incomplete(Needed::Size(22)));
}
#[test]
fn tag_bits() {
let input = vec![0b10101010, 0b11110000, 0b00110011];
let sl = &input[..];
assert_eq!(tag_bits!( (sl, 0), u8, 3, 0b101), IResult::Done((&sl[0..], 3), 5));
assert_eq!(tag_bits!( (sl, 0), u8, 4, 0b1010), IResult::Done((&sl[0..], 4), 10));
}
named!(ch<(&[u8],usize),(u8,u8)>,
chain!(
tag_bits!(u8, 3, 0b101) ~
x: take_bits!(u8, 4) ~
y: take_bits!(u8, 5) ,
|| { (x,y) }
)
);
#[test]
fn chain_bits() {
let input = vec![0b10101010, 0b11110000, 0b00110011];
let sl = &input[..];
assert_eq!(ch((&input[..],0)), IResult::Done((&sl[1..], 4), (5,15)));
assert_eq!(ch((&input[..],4)), IResult::Done((&sl[2..], 0), (7,16)));
assert_eq!(ch((&input[..1],0)), IResult::Incomplete(Needed::Size(12)));
}
named!(ch_bytes<(u8,u8)>, bits!(ch));
#[test]
fn bits_to_bytes() {
let input = vec![0b10101010, 0b11110000, 0b00110011];
assert_eq!(ch_bytes(&input[..]), IResult::Done(&input[2..], (5,15)));
assert_eq!(ch_bytes(&input[..1]), IResult::Incomplete(Needed::Size(2)));
assert_eq!(ch_bytes(&input[1..]), IResult::Error(Err::Position(ErrorKind::TagBits, &input[1..])));
}
}

1027
third_party/rust/nom-1.2.4/nom/src/bytes.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,184 +0,0 @@
/// Character level parsers
use internal::{IResult,Needed,Err};
use util::ErrorKind;
/// matches one of the provided characters
#[macro_export]
macro_rules! one_of (
($i:expr, $inp: expr) => (
{
if $i.is_empty() {
$crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
} else {
#[inline(always)]
fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
b.as_bytes()
}
let expected = $inp;
let bytes = as_bytes(&expected);
one_of_bytes!($i, bytes)
}
}
);
);
#[doc(hidden)]
#[macro_export]
macro_rules! one_of_bytes (
($i:expr, $bytes: expr) => (
{
if $i.is_empty() {
$crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
} else {
let mut found = false;
for &i in $bytes {
if i == $i[0] {
found = true;
break;
}
}
if found {
$crate::IResult::Done(&$i[1..], $i[0] as char)
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::OneOf, $i))
}
}
}
);
);
/// matches anything but the provided characters
#[macro_export]
macro_rules! none_of (
($i:expr, $inp: expr) => (
{
if $i.is_empty() {
$crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
} else {
#[inline(always)]
fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
b.as_bytes()
}
let expected = $inp;
let bytes = as_bytes(&expected);
none_of_bytes!($i, bytes)
}
}
);
);
#[doc(hidden)]
#[macro_export]
macro_rules! none_of_bytes (
($i:expr, $bytes: expr) => (
{
if $i.is_empty() {
$crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
} else {
let mut found = false;
for &i in $bytes {
if i == $i[0] {
found = true;
break;
}
}
if !found {
$crate::IResult::Done(&$i[1..], $i[0] as char)
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::NoneOf, $i))
}
}
}
);
);
/// matches one character: `char!(char) => &[u8] -> IResult<&[u8], char>
#[macro_export]
macro_rules! char (
($i:expr, $c: expr) => (
{
if $i.is_empty() {
let res: $crate::IResult<&[u8], char> = $crate::IResult::Incomplete($crate::Needed::Size(1));
res
} else {
if $i[0] == $c as u8 {
$crate::IResult::Done(&$i[1..], $i[0] as char)
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::Char, $i))
}
}
}
);
);
named!(pub newline<char>, char!('\n'));
pub fn crlf(input:&[u8]) -> IResult<&[u8], char> {
if input.len() < 2 {
IResult::Incomplete(Needed::Size(2))
} else {
if &input[0..2] == &b"\r\n"[..] {
IResult::Done(&input[2..], '\n')
} else {
IResult::Error(Err::Position(ErrorKind::CrLf, input))
}
}
}
named!(pub eol<char>, alt!(crlf | newline));
named!(pub tab<char>, char!('\t'));
pub fn anychar(input:&[u8]) -> IResult<&[u8], char> {
if input.is_empty() {
IResult::Incomplete(Needed::Size(1))
} else {
IResult::Done(&input[1..], input[0] as char)
}
}
#[cfg(test)]
mod tests {
use internal::IResult::*;
use internal::Err::*;
use util::ErrorKind;
#[test]
fn one_of() {
named!(f<char>, one_of!("ab"));
let a = &b"abcd"[..];
assert_eq!(f(a), Done(&b"bcd"[..], 'a'));
let b = &b"cde"[..];
assert_eq!(f(b), Error(Position(ErrorKind::OneOf, b)));
}
#[test]
fn none_of() {
named!(f<char>, none_of!("ab"));
let a = &b"abcd"[..];
assert_eq!(f(a), Error(Position(ErrorKind::NoneOf, a)));
let b = &b"cde"[..];
assert_eq!(f(b), Done(&b"de"[..], 'c'));
}
#[test]
fn char() {
named!(f<char>, char!('c'));
let a = &b"abcd"[..];
assert_eq!(f(a), Error(Position(ErrorKind::Char, a)));
let b = &b"cde"[..];
assert_eq!(f(b), Done(&b"de"[..], 'c'));
}
}

347
third_party/rust/nom-1.2.4/nom/src/internal.rs поставляемый
Просмотреть файл

@ -1,347 +0,0 @@
//! Basic types to build the parsers
use self::IResult::*;
use self::Needed::*;
use util::ErrorKind;
#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;
/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
/// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
Code(ErrorKind<E>),
/// An error code, and the next error
Node(ErrorKind<E>, Box<Err<P,E>>),
/// An error code, and the input position
Position(ErrorKind<E>, P),
/// An error code, the input position and the next error
NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}
/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
/// needs more data, but we do not know how much
Unknown,
/// contains the required data size
Size(usize)
}
impl Needed {
pub fn is_known(&self) -> bool {
*self != Unknown
}
/// Maps a `Needed` to `Needed` by appling a function to a contained `Size` value.
#[inline]
pub fn map<F: FnOnce(usize) -> usize>(self, f: F) -> Needed {
match self {
Unknown => Unknown,
Size(n) => Size(f(n)),
}
}
}
/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
/// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
Done(I,O),
/// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
Error(Err<I,E>),
/// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
Incomplete(Needed)
}
impl<I,O,E> IResult<I,O,E> {
pub fn is_done(&self) -> bool {
match *self {
Done(_,_) => true,
_ => false
}
}
pub fn is_err(&self) -> bool {
match *self {
Error(_) => true,
_ => false
}
}
pub fn is_incomplete(&self) -> bool {
match *self {
Incomplete(_) => true,
_ => false
}
}
/// Maps a `IResult<I, O, E>` to `IResult<I, N, E>` by appling a function
/// to a contained `Done` value, leaving `Error` and `Incomplete` value
/// untouched.
#[inline]
pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
match self {
Done(i, o) => Done(i, f(o)),
Error(e) => Error(e),
Incomplete(n) => Incomplete(n),
}
}
/// Maps a `IResult<I, O, E>` to `IResult<I, O, E>` by appling a function
/// to a contained `Incomplete` value, leaving `Done` and `Error` value
/// untouched.
#[inline]
pub fn map_inc<F>(self, f: F) -> IResult<I, O, E>
where F: FnOnce(Needed) -> Needed {
match self {
Error(e) => Error(e),
Incomplete(n) => Incomplete(f(n)),
Done(i, o) => Done(i, o),
}
}
/// Maps a `IResult<I, O, E>` to `IResult<I, O, N>` by appling a function
/// to a contained `Error` value, leaving `Done` and `Incomplete` value
/// untouched.
#[inline]
pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
where F: FnOnce(Err<I, E>) -> Err<I, N> {
match self {
Error(e) => Error(f(e)),
Incomplete(n) => Incomplete(n),
Done(i, o) => Done(i, o),
}
}
/// Unwrap the contained `Done(I, O)` value, or panic if the `IResult` is not
/// `Done`.
pub fn unwrap(self) -> (I, O) {
match self {
Done(i, o) => (i, o),
Incomplete(_) => panic!("unwrap() called on an IResult that is Incomplete"),
Error(_) => panic!("unwrap() called on an IResult that is Error")
}
}
/// Unwrap the contained `Done(I, O)` value, or panic if the `IResult` is not
/// `Done`.
pub fn unwrap_inc(self) -> Needed {
match self {
Incomplete(n) => n,
Done(_, _) => panic!("unwrap_inc() called on an IResult that is Done"),
Error(_) => panic!("unwrap_inc() called on an IResult that is Error")
}
}
/// Unwrap the contained `Done(I, O)` value, or panic if the `IResult` is not
/// `Done`.
pub fn unwrap_err(self) -> Err<I, E> {
match self {
Error(e) => e,
Done(_, _) => panic!("unwrap_err() called on an IResult that is Done"),
Incomplete(_) => panic!("unwrap_err() called on an IResult that is Incomplete"),
}
}
}
pub trait GetInput<I> {
fn remaining_input(&self) -> Option<I>;
}
pub trait GetOutput<O> {
fn output(&self) -> Option<O>;
}
impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
fn remaining_input(&self) -> Option<&'a[I]> {
match *self {
Done(ref i,_) => Some(*i),
_ => None
}
}
}
impl<O,E> GetInput<()> for IResult<(),O,E> {
fn remaining_input(&self) -> Option<()> {
match *self {
Done((),_) => Some(()),
_ => None
}
}
}
impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
fn remaining_input(&self) -> Option<&'a str> {
match *self {
Done(ref i,_) => Some(*i),
_ => None
}
}
}
impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
fn output(&self) -> Option<&'a[O]> {
match *self {
Done(_, ref o) => Some(*o),
_ => None
}
}
}
impl<I,E> GetOutput<()> for IResult<I,(),E> {
fn output(&self) -> Option<()> {
match *self {
Done(_,()) => Some(()),
_ => None
}
}
}
impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
fn output(&self) -> Option<&'a str> {
match *self {
Done(_,ref o) => Some(*o),
_ => None
}
}
}
#[cfg(not(feature = "core"))]
use std::any::Any;
#[cfg(not(feature = "core"))]
use std::{error,fmt};
#[cfg(not(feature = "core"))]
use std::fmt::Debug;
#[cfg(not(feature = "core"))]
impl<P:Debug+Any,E:Debug+Any> error::Error for Err<P,E> {
fn description(&self) -> &str {
let kind = match *self {
Err::Code(ref e) | Err::Node(ref e, _) | Err::Position(ref e, _) | Err::NodePosition(ref e, _, _) => e
};
kind.description()
}
}
#[cfg(not(feature = "core"))]
impl<P:fmt::Debug,E:fmt::Debug> fmt::Display for Err<P,E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Err::Code(ref e) | Err::Node(ref e, _) => {
write!(f, "{:?}", e)
},
Err::Position(ref e, ref p) | Err::NodePosition(ref e, ref p, _) => {
write!(f, "{:?}:{:?}", p, e)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use util::ErrorKind;
const REST: [u8; 0] = [];
const DONE: IResult<&'static [u8], u32> = IResult::Done(&REST, 5);
const ERROR: IResult<&'static [u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
const INCOMPLETE: IResult<&'static [u8], u32> = IResult::Incomplete(Needed::Unknown);
#[test]
fn needed_map() {
let unknown = Needed::Unknown;
let size = Needed::Size(5);
assert_eq!(size.map(|x| x * 2), Needed::Size(10));
assert_eq!(unknown.map(|x| x * 2), Needed::Unknown);
}
#[test]
fn iresult_map() {
assert_eq!(DONE.map(|x| x * 2), IResult::Done(&b""[..], 10));
assert_eq!(ERROR.map(|x| x * 2), IResult::Error(Err::Code(ErrorKind::Tag)));
assert_eq!(INCOMPLETE.map(|x| x * 2), IResult::Incomplete(Needed::Unknown));
}
#[test]
fn iresult_map_inc() {
let inc_unknown: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);
let inc_size: IResult<&[u8], u32> = IResult::Incomplete(Needed::Size(5));
assert_eq!(DONE.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Done(&b""[..], 5));
assert_eq!(ERROR.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Error(Err::Code(ErrorKind::Tag)));
assert_eq!(inc_unknown.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Incomplete(Needed::Unknown));
assert_eq!(inc_size.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Incomplete(Needed::Size(6)));
}
#[test]
fn iresult_map_err() {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct Error(u32);
let error_kind = Err::Code(ErrorKind::Custom(Error(5)));
assert_eq!(DONE.map_err(|_| error_kind.clone()), IResult::Done(&b""[..], 5));
assert_eq!(ERROR.map_err(|x| {println!("err: {:?}", x); error_kind.clone()}), IResult::Error(error_kind.clone()));
assert_eq!(INCOMPLETE.map_err(|x| {println!("err: {:?}", x); error_kind.clone()}), IResult::Incomplete(Needed::Unknown));
}
#[test]
fn iresult_unwrap_on_done() {
assert_eq!(DONE.unwrap(), (&b""[..], 5));
}
#[test]
#[should_panic]
fn iresult_unwrap_on_err() {
ERROR.unwrap();
}
#[test]
#[should_panic]
fn iresult_unwrap_on_inc() {
INCOMPLETE.unwrap();
}
#[test]
#[should_panic]
fn iresult_unwrap_err_on_done() {
DONE.unwrap_err();
}
#[test]
fn iresult_unwrap_err_on_err() {
assert_eq!(ERROR.unwrap_err(), Err::Code(ErrorKind::Tag));
}
#[test]
#[should_panic]
fn iresult_unwrap_err_on_inc() {
INCOMPLETE.unwrap_err();
}
#[test]
#[should_panic]
fn iresult_unwrap_inc_on_done() {
DONE.unwrap_inc();
}
#[test]
#[should_panic]
fn iresult_unwrap_inc_on_err() {
ERROR.unwrap_inc();
}
#[test]
fn iresult_unwrap_inc_on_inc() {
assert_eq!(INCOMPLETE.unwrap_inc(), Needed::Unknown);
}
}

151
third_party/rust/nom-1.2.4/nom/src/lib.rs поставляемый
Просмотреть файл

@ -1,151 +0,0 @@
//! nom, eating data byte by byte
//!
//! nom is a parser combinator library with a focus on safe parsing,
//! streaming patterns, and as much as possible zero copy.
//!
//! The code is available on [Github](https://github.com/Geal/nom)
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate nom;
//!
//! use nom::{IResult,digit};
//! use nom::IResult::*;
//!
//! // Parser definition
//!
//! use std::str;
//! use std::str::FromStr;
//!
//! named!(parens<i64>, delimited!(
//! char!('('),
//! expr,
//! char!(')')
//! )
//! );
//!
//! named!(i64_digit<i64>,
//! map_res!(
//! map_res!(
//! digit,
//! str::from_utf8
//! ),
//! FromStr::from_str
//! )
//! );
//!
//! // We transform an integer string into a i64
//! // we look for a digit suite, and try to convert it.
//! // if either str::from_utf8 or FromStr::from_str fail,
//! // the parser will fail
//! named!(factor<i64>,
//! alt!(
//! i64_digit
//! | parens
//! )
//! );
//!
//! // we define acc as mutable to update its value whenever a new term is found
//! named!(term <i64>,
//! chain!(
//! mut acc: factor ~
//! many0!(
//! alt!(
//! tap!(mul: preceded!(tag!("*"), factor) => acc = acc * mul) |
//! tap!(div: preceded!(tag!("/"), factor) => acc = acc / div)
//! )
//! ),
//! || { return acc }
//! )
//! );
//!
//! named!(expr <i64>,
//! chain!(
//! mut acc: term ~
//! many0!(
//! alt!(
//! tap!(add: preceded!(tag!("+"), term) => acc = acc + add) |
//! tap!(sub: preceded!(tag!("-"), term) => acc = acc - sub)
//! )
//! ),
//! || { return acc }
//! )
//! );
//!
//! fn main() {
//! assert_eq!(expr(b"1+2"), IResult::Done(&b""[..], 3));
//! assert_eq!(expr(b"12+6-4+3"), IResult::Done(&b""[..], 17));
//! assert_eq!(expr(b"1+2*3+4"), IResult::Done(&b""[..], 11));
//!
//! assert_eq!(expr(b"(2)"), IResult::Done(&b""[..], 2));
//! assert_eq!(expr(b"2*(3+4)"), IResult::Done(&b""[..], 14));
//! assert_eq!(expr(b"2*2/(5-1)+3"), IResult::Done(&b""[..], 4));
//! }
//! ```
#![cfg_attr(feature = "core", feature(no_std))]
#![cfg_attr(feature = "core", feature(collections))]
#![cfg_attr(feature = "core", no_std)]
#![cfg_attr(feature = "nightly", feature(test))]
#![cfg_attr(feature = "nightly", feature(const_fn))]
#[cfg(feature = "core")]
extern crate collections;
#[cfg(feature = "regexp")]
extern crate regex;
#[cfg(feature = "regexp_macros")]
#[macro_use] extern crate lazy_static;
#[cfg(feature = "nightly")]
extern crate test;
#[cfg(feature = "core")]
mod std {
#[macro_use]
pub use core::{fmt, iter, option, ops, slice, mem};
pub use collections::{boxed, vec, string};
pub mod prelude {
pub use core::prelude as v1;
}
}
pub use self::util::*;
pub use self::internal::*;
pub use self::macros::*;
pub use self::methods::*;
pub use self::bytes::*;
pub use self::bits::*;
pub use self::nom::*;
pub use self::character::*;
#[cfg(feature = "regexp")]
pub use self::regexp::*;
#[cfg(not(feature = "core"))]
#[cfg(feature = "stream")]
pub use self::stream::*;
#[cfg(not(feature = "core"))]
pub use self::str::*;
#[macro_use] mod util;
mod internal;
#[macro_use] mod macros;
#[macro_use] mod methods;
#[macro_use] mod bytes;
#[macro_use] mod bits;
#[macro_use] mod nom;
#[macro_use] mod character;
#[cfg(feature = "regexp")]
#[macro_use] mod regexp;
#[macro_use]
#[cfg(not(feature = "core"))]
#[cfg(feature = "stream")]
mod stream;
#[cfg(not(feature = "core"))]
mod str;

3561
third_party/rust/nom-1.2.4/nom/src/macros.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

480
third_party/rust/nom-1.2.4/nom/src/methods.rs поставляемый
Просмотреть файл

@ -1,480 +0,0 @@
//! Method macro combinators
//!
//! These macros make parsers as methods of structs
//! and that can take methods of structs to call
//! as parsers.
//!
//! There is a trick to make them easier to assemble,
//! combinators are defined like this:
//!
//! ```ignore
//! macro_rules! tag (
//! ($i:expr, $inp: expr) => (
//! {
//! ...
//! }
//! );
//! );
//! ```
//!
//! But when used as methods in other combinators, are used
//! like this:
//!
//! ```ignore
//! method!(my_function<Parser<'a> >, self, tag!("abcd"));
//! ```
//!
//! Internally, other combinators will rewrite
//! that call to pass the input as second argument:
//!
//! ```ignore
//! macro_rules! method (
//! ($name:ident<$a:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
//! fn $name( $self_: $a, i: &[u8] ) -> $crate::IResult<&[u8], &[u8]> {
//! $submac!(i, $($args)*)
//! }
//! );
//! );
//! ```
//!
//! The `method!` macro is similar to the `named!` macro in the macros module.
//! While `named!` will create a parser function, `method!` will create a parser
//! method on the struct it is defined in.
//!
//! Compared to the `named!` macro there are a few differences in how they are
//! invoked. A `method!` invocation always has to have the type of `self`
//! declared and it can't be a reference due to Rust's borrow lifetime
//! restrictions:
//! ```ignore
//! // -`self`'s type-
//! method!(method_name< Parser<'a> >, ...);
//! ```
//! `self`'s type always comes first.
//! The next difference is you have to input the self struct. Due to Rust's
//! macro hygiene the macro can't declare it on it's own.
//! ```ignore
//! // -self-
//! method!(method_name<Parser<'a>, &'a str, &'a str>, self, ...);
//! ```
//! When making a parsing struct with parsing methods, due to the static borrow
//! checker,calling any parsing methods on self (or any other parsing struct)
//! will cause self to be moved for the rest of the method.To get around this
//! restriction all self is moved into the called method and then the called
//! method will return self to the caller.
//!
//! To call a method on self you need to use the `call_m!` macro. For example:
//! ```ignore
//! struct<'a> Parser<'a> {
//! parsed: &'a str,
//! }
//! impl<'a> Parser<'a> {
//! // Constructor omitted for brevity
//! method!(take4<Parser<'a>, &'a str, &'a str>, self, take!(4));
//! method!(caller<Parser<'a>, &'a str, &'a str>, self, call_m!(self.take4));
//! }
//! ```
//! More complicated combinations still mostly look the same as their `named!`
//! counterparts:
//! ```ignore
//! method!(pub simple_chain<&mut Parser<'a>, &'a str, &'a str>, self,
//! chain!(
//! call_m!(self.tag_abc) ~
//! call_m!(self.tag_def) ~
//! call_m!(self.tag_ghi) ~
//! last: call_m!(self.simple_peek) ,
//! ||{sb.parsed = last; last}
//! )
//! );
//! ```
//! The three additions to method definitions to remember are:
//! 1. Specify `self`'s type
//! 2. Pass `self` to the macro
//! 4. Call parser methods using the `call_m!` macro.
/// Makes a method from a parser combination
///
/// The must be set up because the compiler needs
/// the information
///
/// ```ignore
/// method!(my_function<Parser<'a> >( &[u8] ) -> &[u8], tag!("abcd"));
/// // first type parameter is `self`'s type, second is input, third is output
/// method!(my_function<Parser<'a>, &[u8], &[u8]>, tag!("abcd"));
/// //prefix them with 'pub' to make the methods public
/// method!(pub my_function<Parser<'a>,&[u8], &[u8]>, tag!("abcd"));
/// ```
#[macro_export]
macro_rules! method (
// Non-public immutable self
($name:ident<$a:ty>( $i:ty ) -> $o:ty, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty,$i:ty,$o:ty,$e:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i, $o, $e>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty,$i:ty,$o:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty,$o:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name<'a>( $self_: $a, i: &'a[u8] ) -> ($a, $crate::IResult<&'a [u8], $o, u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( $self_: $a, i: &[u8] ) -> ($a, $crate::IResult<&[u8], &[u8], u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
// Public immutable self
(pub $name:ident<$a:ty>( $i:ty ) -> $o:ty, $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty,$i:ty,$o:ty,$e:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i, $o, $e>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty,$i:ty,$o:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name( $self_: $a,i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty,$o:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name<'a>( $self_: $a, i: &'a[u8] ) -> ($a, $crate::IResult<&'a [u8], $o, u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name( $self_: $a, i: &[u8] ) -> ($a, $crate::IResult<&[u8], &[u8], u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
// Non-public mutable self
($name:ident<$a:ty>( $i:ty ) -> $o:ty, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty,$i:ty,$o:ty,$e:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i, $o, $e>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty,$i:ty,$o:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty,$o:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name<'a>( mut $self_: $a, i: &'a[u8] ) -> ($a, $crate::IResult<&'a [u8], $o, u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( mut $self_: $a, i: &[u8] ) -> ($a, $crate::IResult<&[u8], &[u8], u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
// Public mutable self
(pub $name:ident<$a:ty>( $i:ty ) -> $o:ty, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty,$i:ty,$o:ty,$e:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i, $o, $e>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty,$i:ty,$o:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name( mut $self_: $a,i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty,$o:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name<'a>( mut $self_: $a, i: &'a[u8] ) -> ($a, $crate::IResult<&'a [u8], $o, u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name( mut $self_: $a, i: &[u8] ) -> ($a, $crate::IResult<&[u8], &[u8], u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
);
/// Used to called methods then move self back into self
#[macro_export]
macro_rules! call_m (
($i:expr, $self_:ident.$method:ident) => (
{
let (tmp, res) = $self_.$method($i);
$self_ = tmp;
res
}
);
($i:expr, $self_:ident.$method:ident, $($args:expr),* ) => (
{
let (tmp, res) = $self_.$method($i, $($args),*);
$self_ = tmp;
res
}
);
);
/// emulate function currying for method calls on structs
/// `apply!(self.my_function, arg1, arg2, ...)` becomes `self.my_function(input, arg1, arg2, ...)`
///
/// Supports up to 6 arguments
#[macro_export]
macro_rules! apply_m (
($i:expr, $self_:ident.$method:ident, $($args:expr),* ) => ( { let (tmp, res) = $self_.$method( $i, $($args),* ); $self_ = tmp; res } );
);
#[cfg(test)]
mod tests {
use internal::IResult::*;
// reproduce the tag_s and take_s macros, because of module import order
macro_rules! tag_s (
($i:expr, $tag: expr) => (
{
let res: $crate::IResult<_,_> = if $tag.len() > $i.len() {
$crate::IResult::Incomplete($crate::Needed::Size($tag.len()))
//} else if &$i[0..$tag.len()] == $tag {
} else if ($i).starts_with($tag) {
$crate::IResult::Done(&$i[$tag.len()..], &$i[0..$tag.len()])
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TagStr, $i))
};
res
}
);
);
macro_rules! take_s (
($i:expr, $count:expr) => (
{
let cnt = $count as usize;
let res: $crate::IResult<_,_> = if $i.chars().count() < cnt {
$crate::IResult::Incomplete($crate::Needed::Size(cnt))
} else {
let mut offset = $i.len();
let mut count = 0;
for (o, _) in $i.char_indices() {
if count == cnt {
offset = o;
break;
}
count += 1;
}
$crate::IResult::Done(&$i[offset..], &$i[..offset])
};
res
}
);
);
struct Parser<'a> {
bcd: &'a str,
}
impl<'a> Parser<'a> {
pub fn new() -> Parser<'a> {
Parser{bcd: ""}
}
method!(tag_abc<Parser<'a>, &'a str, &'a str>, self, tag_s!("áβç"));
method!(tag_bcd<Parser<'a> >(&'a str) -> &'a str, self, tag_s!("βçδ"));
method!(pub tag_hij<Parser<'a> >(&'a str) -> &'a str, self, tag_s!("λïJ"));
method!(pub tag_ijk<Parser<'a>, &'a str, &'a str>, self, tag_s!("ïJƙ"));
method!(take3<Parser<'a>, &'a str, &'a str>, self, take_s!(3));
method!(pub simple_call<Parser<'a>, &'a str, &'a str>, mut self,
call_m!(self.tag_abc)
);
method!(pub simple_peek<Parser<'a>, &'a str, &'a str>, mut self,
peek!(call_m!(self.take3))
);
method!(pub simple_chain<Parser<'a>, &'a str, &'a str>, mut self,
chain!(
bcd: call_m!(self.tag_bcd) ~
last: call_m!(self.simple_peek) ,
||{self.bcd = bcd; last}
)
);
fn tag_stuff(mut self: Parser<'a>, input: &'a str, something: &'a str) -> (Parser<'a>, ::IResult<&'a str, &'a str>) {
self.bcd = something;
let(tmp, res) = self.tag_abc(input);
self = tmp;
(self, res)
}
method!(use_apply<Parser<'a>, &'a str, &'a str>, mut self, apply_m!(self.tag_stuff, "βçδ"));
}
#[test]
fn test_method_call_abc() {
let p = Parser::new();
let input: &str = "áβçδèƒϱλïJƙ";
let consumed: &str = "áβç";
let leftover: &str = "δèƒϱλïJƙ";
let(_, res) = p.tag_abc(input);
match res {
Done(extra, output) => { assert!(extra == leftover, "`Parser.tag_abc` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.tag_abc` doesnt return the string it consumed \
on success. Expected `{}`, got `{}`.", consumed, output);
},
other => panic!("`Parser.tag_abc` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_method_call_bcd() {
let p = Parser::new();
let input: &str = "βçδèƒϱλïJƙ";
let consumed: &str = "βçδ";
let leftover: &str = "èƒϱλïJƙ";
let(_, res) = p.tag_bcd(input);
match res {
Done(extra, output) => { assert!(extra == leftover, "`Parser.tag_bcd` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.tag_bcd` doesn't return the string it consumed \
on success. Expected `{}`, got `{}`.", consumed, output);
},
other => panic!("`Parser.tag_bcd` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_method_call_hij() {
let p = Parser::new();
let input: &str = "λïJƙ₥ñôƥ9řƨ";
let consumed: &str = "λïJ";
let leftover: &str = "ƙ₥ñôƥ9řƨ";
let(_, res) = p.tag_hij(input);
match res {
Done(extra, output) => { assert!(extra == leftover, "`Parser.tag_hij` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.tag_hij` doesn't return the string it consumed \
on success. Expected `{}`, got `{}`.", consumed, output);
},
other => panic!("`Parser.tag_hij` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_method_call_ijk() {
let p = Parser::new();
let input: &str = "ïJƙ₥ñôƥ9řƨ";
let consumed: &str = "ïJƙ";
let leftover: &str = "₥ñôƥ9řƨ";
let(_, res) = p.tag_ijk(input);
match res {
Done(extra, output) => { assert!(extra == leftover, "`Parser.tag_ijk` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.tag_ijk` doesn't return the string it consumed \
on success. Expected `{}`, got `{}`.", consumed, output);
},
other => panic!("`Parser.tag_ijk` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_method_simple_call() {
let p = Parser::new();
let input: &str = "áβçδèƒϱλïJƙ";
let consumed: &str = "áβç";
let leftover: &str = "δèƒϱλïJƙ";
let(_, res) = p.simple_call(input);
match res {
Done(extra, output) => { assert!(extra == leftover, "`Parser.simple_call` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.simple_call` doesn't return the string it consumed \
on success. Expected `{}`, got `{}`.", consumed, output);
},
other => panic!("`Parser.simple_call` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_apply_m() {
let mut p = Parser::new();
let input: &str = "áβçδèƒϱλïJƙ";
let consumed: &str = "áβç";
let leftover: &str = "δèƒϱλïJƙ";
let(tmp, res) = p.use_apply(input);
p = tmp;
match res {
Done(extra, output) => { assert!(extra == leftover, "`Parser.use_apply` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.use_apply` doesn't return the string it was supposed to \
on success. Expected `{}`, got `{}`.", leftover, output);
assert!(p.bcd == "βçδ", "Parser.use_apply didn't modify the parser field correctly: {}", p.bcd);
},
other => panic!("`Parser.use_apply` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_method_call_peek() {
let p = Parser::new();
let input: &str = "ж¥ƺáβçδèƒϱλïJƙ";
let consumed: &str = "ж¥ƺ";
let(_, res) = p.simple_peek(input);
match res {
Done(extra, output) => { assert!(extra == input, "`Parser.simple_peek` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.simple_peek` doesn't return the string it consumed \
on success. Expected `{}`, got `{}`.", consumed, output);
},
other => panic!("`Parser.simple_peek` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_method_call_chain() {
let mut p = Parser::new();
let input : &str = "βçδδèƒϱλïJƙ";
let leftover : &str = "δèƒϱλïJƙ";
let output : &str = "늟";
let(tmp, res) = p.simple_chain(input);
p = tmp;
match res {
Done(extra, out) => { assert!(extra == leftover, "`Parser.simple_chain` consumed leftover input. leftover: {}", extra);
assert!(out == output, "`Parser.simple_chain` doesn't return the string it was supposed to \
on success. Expected `{}`, got `{}`.", output, out);
assert!(p.bcd == "βçδ", "Parser.simple_chain didn't modify the parser field correctly: {}", p.bcd);
},
other => panic!("`Parser.simple_chain` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
}

950
third_party/rust/nom-1.2.4/nom/src/nom.rs поставляемый
Просмотреть файл

@ -1,950 +0,0 @@
//! Useful parser combinators
//!
//! A number of useful parser combinators have already been implemented.
//! Some of them use macros, other are implemented through functions.
//! Hopefully, the syntax will converge to onely one way in the future,
//! but the macros system makes no promises.
//!
#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;
use std::fmt::Debug;
use internal::*;
use internal::IResult::*;
use internal::Err::*;
use util::{ErrorKind,IterIndices,AsChar,InputLength};
use std::mem::transmute;
#[inline]
pub fn tag_cl<'a,'b>(rec:&'a[u8]) -> Box<Fn(&'b[u8]) -> IResult<&'b[u8], &'b[u8]> + 'a> {
Box::new(move |i: &'b[u8]| -> IResult<&'b[u8], &'b[u8]> {
if i.len() >= rec.len() && &i[0..rec.len()] == rec {
Done(&i[rec.len()..], &i[0..rec.len()])
} else {
Error(Position(ErrorKind::TagClosure, i))
}
})
}
#[cfg(not(feature = "core"))]
#[inline]
pub fn print<T: Debug>(input: T) -> IResult<T, ()> {
println!("{:?}", input);
Done(input, ())
}
#[inline]
pub fn begin(input: &[u8]) -> IResult<(), &[u8]> {
Done((), input)
}
// FIXME: when rust-lang/rust#17436 is fixed, macros will be able to export
// public methods
//pub is_not!(line_ending b"\r\n")
pub fn not_line_ending(input:&[u8]) -> IResult<&[u8], &[u8]> {
for (idx, item) in input.iter().enumerate() {
for &i in b"\r\n".iter() {
if *item == i {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input.len()..], input)
}
named!(tag_ln, tag!("\n"));
/// Recognizes a line feed
#[inline]
pub fn line_ending(input:&[u8]) -> IResult<&[u8], &[u8]> {
tag_ln(input)
}
#[inline]
pub fn is_alphabetic(chr:u8) -> bool {
(chr >= 0x41 && chr <= 0x5A) || (chr >= 0x61 && chr <= 0x7A)
}
#[inline]
pub fn is_digit(chr: u8) -> bool {
chr >= 0x30 && chr <= 0x39
}
#[inline]
pub fn is_hex_digit(chr: u8) -> bool {
(chr >= 0x30 && chr <= 0x39) ||
(chr >= 0x41 && chr <= 0x46) ||
(chr >= 0x61 && chr <= 0x66)
}
#[inline]
pub fn is_oct_digit(chr: u8) -> bool {
chr >= 0x30 && chr <= 0x37
}
#[inline]
pub fn is_alphanumeric(chr: u8) -> bool {
is_alphabetic(chr) || is_digit(chr)
}
#[inline]
pub fn is_space(chr:u8) -> bool {
chr == ' ' as u8 || chr == '\t' as u8
}
// FIXME: when rust-lang/rust#17436 is fixed, macros will be able to export
//pub filter!(alpha is_alphabetic)
//pub filter!(digit is_digit)
//pub filter!(hex_digit is_hex_digit)
//pub filter!(oct_digit is_oct_digit)
//pub filter!(alphanumeric is_alphanumeric)
use std::ops::{Index,Range,RangeFrom};
/// Recognizes lowercase and uppercase alphabetic characters: a-zA-Z
pub fn alpha<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::Alpha, input))
}
for (idx, item) in input.iter_indices() {
if ! item.is_alpha() {
if idx == 0 {
return Error(Position(ErrorKind::Alpha, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
/// Recognizes numerical characters: 0-9
pub fn digit<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::Digit, input))
}
for (idx, item) in input.iter_indices() {
if ! item.is_0_to_9() {
if idx == 0 {
return Error(Position(ErrorKind::Digit, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
/// Recognizes hexadecimal numerical characters: 0-9, A-F, a-f
pub fn hex_digit<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::HexDigit, input))
}
for (idx, item) in input.iter_indices() {
if ! item.is_hex_digit() {
if idx == 0 {
return Error(Position(ErrorKind::HexDigit, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
/// Recognizes octal characters: 0-7
pub fn oct_digit<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::OctDigit, input))
}
for (idx, item) in input.iter_indices() {
if ! item.is_oct_digit() {
if idx == 0 {
return Error(Position(ErrorKind::OctDigit, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
/// Recognizes numerical and alphabetic characters: 0-9a-zA-Z
pub fn alphanumeric<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::AlphaNumeric, input));
}
for (idx, item) in input.iter_indices() {
if ! item.is_alphanum() {
if idx == 0 {
return Error(Position(ErrorKind::AlphaNumeric, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
/// Recognizes spaces and tabs
pub fn space<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::Space, input));
}
for (idx, item) in input.iter_indices() {
let chr = item.as_char();
if ! (chr == ' ' || chr == '\t') {
if idx == 0 {
return Error(Position(ErrorKind::Space, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
/// Recognizes spaces, tabs, carriage returns and line feeds
pub fn multispace<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::MultiSpace, input));
}
for (idx, item) in input.iter_indices() {
let chr = item.as_char();
if ! (chr == ' ' || chr == '\t' || chr == '\r' || chr == '\n') {
if idx == 0 {
return Error(Position(ErrorKind::MultiSpace, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
pub fn sized_buffer(input:&[u8]) -> IResult<&[u8], &[u8]> {
if input.is_empty() {
return Incomplete(Needed::Unknown)
}
let len = input[0] as usize;
if input.len() >= len + 1 {
Done(&input[len+1..], &input[1..len+1])
} else {
Incomplete(Needed::Size(1 + len))
}
}
pub fn length_value(input:&[u8]) -> IResult<&[u8], &[u8]> {
let input_len = input.len();
if input_len == 0 {
return Error(Position(ErrorKind::LengthValueFn, input))
}
let len = input[0] as usize;
if input_len - 1 >= len {
IResult::Done(&input[len+1..], &input[1..len+1])
} else {
IResult::Incomplete(Needed::Size(1+len))
}
}
/// Recognizes an unsigned 1 byte integer (equivalent to take!(1)
#[inline]
pub fn be_u8(i: &[u8]) -> IResult<&[u8], u8> {
if i.len() < 1 {
Incomplete(Needed::Size(1))
} else {
Done(&i[1..], i[0])
}
}
/// Recognizes big endian unsigned 2 bytes integer
#[inline]
pub fn be_u16(i: &[u8]) -> IResult<&[u8], u16> {
if i.len() < 2 {
Incomplete(Needed::Size(2))
} else {
let res = ((i[0] as u16) << 8) + i[1] as u16;
Done(&i[2..], res)
}
}
/// Recognizes big endian unsigned 4 bytes integer
#[inline]
pub fn be_u32(i: &[u8]) -> IResult<&[u8], u32> {
if i.len() < 4 {
Incomplete(Needed::Size(4))
} else {
let res = ((i[0] as u32) << 24) + ((i[1] as u32) << 16) + ((i[2] as u32) << 8) + i[3] as u32;
Done(&i[4..], res)
}
}
/// Recognizes big endian unsigned 8 bytes integer
#[inline]
pub fn be_u64(i: &[u8]) -> IResult<&[u8], u64> {
if i.len() < 8 {
Incomplete(Needed::Size(8))
} else {
let res = ((i[0] as u64) << 56) + ((i[1] as u64) << 48) + ((i[2] as u64) << 40) + ((i[3] as u64) << 32) +
((i[4] as u64) << 24) + ((i[5] as u64) << 16) + ((i[6] as u64) << 8) + i[7] as u64;
Done(&i[8..], res)
}
}
/// Recognizes a signed 1 byte integer (equivalent to take!(1)
#[inline]
pub fn be_i8(i:&[u8]) -> IResult<&[u8], i8> {
map!(i, be_u8, | x | { x as i8 })
}
/// Recognizes big endian signed 2 bytes integer
#[inline]
pub fn be_i16(i:&[u8]) -> IResult<&[u8], i16> {
map!(i, be_u16, | x | { x as i16 })
}
/// Recognizes big endian signed 4 bytes integer
#[inline]
pub fn be_i32(i:&[u8]) -> IResult<&[u8], i32> {
map!(i, be_u32, | x | { x as i32 })
}
/// Recognizes big endian signed 8 bytes integer
#[inline]
pub fn be_i64(i:&[u8]) -> IResult<&[u8], i64> {
map!(i, be_u64, | x | { x as i64 })
}
/// Recognizes an unsigned 1 byte integer (equivalent to take!(1)
#[inline]
pub fn le_u8(i: &[u8]) -> IResult<&[u8], u8> {
if i.len() < 1 {
Incomplete(Needed::Size(1))
} else {
Done(&i[1..], i[0])
}
}
/// Recognizes little endian unsigned 2 bytes integer
#[inline]
pub fn le_u16(i: &[u8]) -> IResult<&[u8], u16> {
if i.len() < 2 {
Incomplete(Needed::Size(2))
} else {
let res = ((i[1] as u16) << 8) + i[0] as u16;
Done(&i[2..], res)
}
}
/// Recognizes little endian unsigned 4 bytes integer
#[inline]
pub fn le_u32(i: &[u8]) -> IResult<&[u8], u32> {
if i.len() < 4 {
Incomplete(Needed::Size(4))
} else {
let res = ((i[3] as u32) << 24) + ((i[2] as u32) << 16) + ((i[1] as u32) << 8) + i[0] as u32;
Done(&i[4..], res)
}
}
/// Recognizes little endian unsigned 8 bytes integer
#[inline]
pub fn le_u64(i: &[u8]) -> IResult<&[u8], u64> {
if i.len() < 8 {
Incomplete(Needed::Size(8))
} else {
let res = ((i[7] as u64) << 56) + ((i[6] as u64) << 48) + ((i[5] as u64) << 40) + ((i[4] as u64) << 32) +
((i[3] as u64) << 24) + ((i[2] as u64) << 16) + ((i[1] as u64) << 8) + i[0] as u64;
Done(&i[8..], res)
}
}
/// Recognizes a signed 1 byte integer (equivalent to take!(1)
#[inline]
pub fn le_i8(i:&[u8]) -> IResult<&[u8], i8> {
map!(i, le_u8, | x | { x as i8 })
}
/// Recognizes little endian signed 2 bytes integer
#[inline]
pub fn le_i16(i:&[u8]) -> IResult<&[u8], i16> {
map!(i, le_u16, | x | { x as i16 })
}
/// Recognizes little endian signed 4 bytes integer
#[inline]
pub fn le_i32(i:&[u8]) -> IResult<&[u8], i32> {
map!(i, le_u32, | x | { x as i32 })
}
/// Recognizes little endian signed 8 bytes integer
#[inline]
pub fn le_i64(i:&[u8]) -> IResult<&[u8], i64> {
map!(i, le_u64, | x | { x as i64 })
}
/// if parameter is true, parse a big endian u16 integer,
/// otherwise a little endian u16 integer
#[macro_export]
macro_rules! u16 ( ($i:expr, $e:expr) => ( {if $e { $crate::be_u16($i) } else { $crate::le_u16($i) } } ););
/// if parameter is true, parse a big endian u32 integer,
/// otherwise a little endian u32 integer
#[macro_export]
macro_rules! u32 ( ($i:expr, $e:expr) => ( {if $e { $crate::be_u32($i) } else { $crate::le_u32($i) } } ););
/// if parameter is true, parse a big endian u64 integer,
/// otherwise a little endian u64 integer
#[macro_export]
macro_rules! u64 ( ($i:expr, $e:expr) => ( {if $e { $crate::be_u64($i) } else { $crate::le_u64($i) } } ););
/// if parameter is true, parse a big endian i16 integer,
/// otherwise a little endian i16 integer
#[macro_export]
macro_rules! i16 ( ($i:expr, $e:expr) => ( {if $e { $crate::be_i16($i) } else { $crate::le_i16($i) } } ););
/// if parameter is true, parse a big endian i32 integer,
/// otherwise a little endian i32 integer
#[macro_export]
macro_rules! i32 ( ($i:expr, $e:expr) => ( {if $e { $crate::be_i32($i) } else { $crate::le_i32($i) } } ););
/// if parameter is true, parse a big endian i64 integer,
/// otherwise a little endian i64 integer
#[macro_export]
macro_rules! i64 ( ($i:expr, $e:expr) => ( {if $e { $crate::be_i64($i) } else { $crate::le_i64($i) } } ););
/// Recognizes big endian 4 bytes floating point number
#[inline]
pub fn be_f32(input: &[u8]) -> IResult<&[u8], f32> {
match be_u32(input) {
Error(e) => Error(e),
Incomplete(e) => Incomplete(e),
Done(i,o) => {
unsafe {
Done(i, transmute::<u32, f32>(o))
}
}
}
}
/// Recognizes big endian 8 bytes floating point number
#[inline]
pub fn be_f64(input: &[u8]) -> IResult<&[u8], f64> {
match be_u64(input) {
Error(e) => Error(e),
Incomplete(e) => Incomplete(e),
Done(i,o) => {
unsafe {
Done(i, transmute::<u64, f64>(o))
}
}
}
}
/// Recognizes little endian 4 bytes floating point number
#[inline]
pub fn le_f32(input: &[u8]) -> IResult<&[u8], f32> {
match le_u32(input) {
Error(e) => Error(e),
Incomplete(e) => Incomplete(e),
Done(i,o) => {
unsafe {
Done(i, transmute::<u32, f32>(o))
}
}
}
}
/// Recognizes little endian 8 bytes floating point number
#[inline]
pub fn le_f64(input: &[u8]) -> IResult<&[u8], f64> {
match le_u64(input) {
Error(e) => Error(e),
Incomplete(e) => Incomplete(e),
Done(i,o) => {
unsafe {
Done(i, transmute::<u64, f64>(o))
}
}
}
}
/// Recognizes a hex-encoded integer
#[inline]
pub fn hex_u32(input: &[u8]) -> IResult<&[u8], u32> {
match is_a!(input, &b"0123456789abcdef"[..]) {
Error(e) => Error(e),
Incomplete(e) => Incomplete(e),
Done(i,o) => {
let mut res = 0u32;
// Do not parse more than 8 characters for a u32
let mut remaining = i;
let mut parsed = o;
if o.len() > 8 {
remaining = &input[8..];
parsed = &input[..8];
}
for &e in parsed {
let digit = e as char;
let value = digit.to_digit(16).unwrap_or(0);
res = value + (res << 4);
}
Done(remaining, res)
}
}
}
/// Recognizes empty input buffers
///
/// useful to verify that the previous parsers used all of the input
#[inline]
//pub fn eof(input:&[u8]) -> IResult<&[u8], &[u8]> {
pub fn eof<'a, T:?Sized>(input: &'a T) -> IResult<&'a T,&'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: InputLength {
if input.input_len() == 0 {
Done(input, input)
} else {
Error(Position(ErrorKind::Eof, input))
}
}
/// Recognizes non empty buffers
#[inline]
pub fn non_empty<'a, T:?Sized>(input: &'a T) -> IResult<&'a T,&'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: InputLength {
if input.input_len() == 0 {
Error(Position(ErrorKind::NonEmpty, input))
} else {
Done(&input[input.input_len()..], input)
}
}
/// Return the remaining input.
#[inline]
pub fn rest(input: &[u8]) -> IResult<&[u8], &[u8]> {
IResult::Done(&input[input.len()..], input)
}
/// Return the remaining input, for strings.
#[inline]
pub fn rest_s(input: &str) -> IResult<&str, &str> {
IResult::Done(&input[input.len()..], input)
}
#[cfg(test)]
mod tests {
use super::*;
use internal::{Needed,IResult};
use internal::IResult::*;
use internal::Err::*;
use util::ErrorKind;
#[test]
fn tag_closure() {
let x = tag_cl(&b"abcd"[..]);
let r = x(&b"abcdabcdefgh"[..]);
assert_eq!(r, Done(&b"abcdefgh"[..], &b"abcd"[..]));
let r2 = x(&b"abcefgh"[..]);
assert_eq!(r2, Error(Position(ErrorKind::TagClosure, &b"abcefgh"[..])));
}
#[test]
fn character() {
let empty: &[u8] = b"";
let a: &[u8] = b"abcd";
let b: &[u8] = b"1234";
let c: &[u8] = b"a123";
let d: &[u8] = "azé12".as_bytes();
let e: &[u8] = b" ";
assert_eq!(alpha(a), Done(empty, a));
assert_eq!(alpha(b), Error(Position(ErrorKind::Alpha,b)));
assert_eq!(alpha(c), Done(&c[1..], &b"a"[..]));
assert_eq!(alpha(d), Done("é12".as_bytes(), &b"az"[..]));
assert_eq!(digit(a), Error(Position(ErrorKind::Digit,a)));
assert_eq!(digit(b), Done(empty, b));
assert_eq!(digit(c), Error(Position(ErrorKind::Digit,c)));
assert_eq!(digit(d), Error(Position(ErrorKind::Digit,d)));
assert_eq!(hex_digit(a), Done(empty, a));
assert_eq!(hex_digit(b), Done(empty, b));
assert_eq!(hex_digit(c), Done(empty, c));
assert_eq!(hex_digit(d), Done("zé12".as_bytes(), &b"a"[..]));
assert_eq!(hex_digit(e), Error(Position(ErrorKind::HexDigit,e)));
assert_eq!(oct_digit(a), Error(Position(ErrorKind::OctDigit,a)));
assert_eq!(oct_digit(b), Done(empty, b));
assert_eq!(oct_digit(c), Error(Position(ErrorKind::OctDigit,c)));
assert_eq!(oct_digit(d), Error(Position(ErrorKind::OctDigit,d)));
assert_eq!(alphanumeric(a), Done(empty, a));
assert_eq!(fix_error!(b,(), alphanumeric), Done(empty, b));
assert_eq!(alphanumeric(c), Done(empty, c));
assert_eq!(alphanumeric(d), Done("é12".as_bytes(), &b"az"[..]));
assert_eq!(space(e), Done(&b""[..], &b" "[..]));
}
#[test]
fn character_s() {
let empty = "";
let a = "abcd";
let b = "1234";
let c = "a123";
let d = "azé12";
let e = " ";
assert_eq!(alpha(a), Done(empty, a));
assert_eq!(alpha(b), Error(Position(ErrorKind::Alpha,b)));
assert_eq!(alpha(c), Done(&c[1..], &"a"[..]));
assert_eq!(alpha(d), Done("12", &"azé"[..]));
assert_eq!(digit(a), Error(Position(ErrorKind::Digit,a)));
assert_eq!(digit(b), Done(empty, b));
assert_eq!(digit(c), Error(Position(ErrorKind::Digit,c)));
assert_eq!(digit(d), Error(Position(ErrorKind::Digit,d)));
assert_eq!(hex_digit(a), Done(empty, a));
assert_eq!(hex_digit(b), Done(empty, b));
assert_eq!(hex_digit(c), Done(empty, c));
assert_eq!(hex_digit(d), Done("zé12", &"a"[..]));
assert_eq!(hex_digit(e), Error(Position(ErrorKind::HexDigit,e)));
assert_eq!(oct_digit(a), Error(Position(ErrorKind::OctDigit,a)));
assert_eq!(oct_digit(b), Done(empty, b));
assert_eq!(oct_digit(c), Error(Position(ErrorKind::OctDigit,c)));
assert_eq!(oct_digit(d), Error(Position(ErrorKind::OctDigit,d)));
assert_eq!(alphanumeric(a), Done(empty, a));
assert_eq!(fix_error!(b,(), alphanumeric), Done(empty, b));
assert_eq!(alphanumeric(c), Done(empty, c));
assert_eq!(alphanumeric(d), Done("", &"azé12"[..]));
assert_eq!(space(e), Done(&""[..], &" "[..]));
}
use util::HexDisplay;
#[test]
fn offset() {
let a = &b"abcd"[..];
let b = &b"1234"[..];
let c = &b"a123"[..];
let d = &b" \t"[..];
let e = &b" \t\r\n"[..];
let f = &b"123abcDEF"[..];
match alpha(a) {
Done(i, _) => { assert_eq!(a.offset(i) + i.len(), a.len()); }
_ => { panic!("wrong return type in offset test for alpha") }
}
match digit(b) {
Done(i, _) => { assert_eq!(b.offset(i) + i.len(), b.len()); }
_ => { panic!("wrong return type in offset test for digit") }
}
match alphanumeric(c) {
Done(i, _) => { assert_eq!(c.offset(i) + i.len(), c.len()); }
_ => { panic!("wrong return type in offset test for alphanumeric") }
}
match space(d) {
Done(i, _) => { assert_eq!(d.offset(i) + i.len(), d.len()); }
_ => { panic!("wrong return type in offset test for space") }
}
match multispace(e) {
Done(i, _) => { assert_eq!(e.offset(i) + i.len(), e.len()); }
_ => { panic!("wrong return type in offset test for multispace") }
}
match hex_digit(f) {
Done(i, _) => { assert_eq!(f.offset(i) + i.len(), f.len()); }
_ => { panic!("wrong return type in offset test for hex_digit") }
}
match oct_digit(f) {
Done(i, _) => { assert_eq!(f.offset(i) + i.len(), f.len()); }
_ => { panic!("wrong return type in offset test for oct_digit") }
}
}
#[test]
fn is_not() {
let a: &[u8] = b"ab12cd\nefgh";
assert_eq!(not_line_ending(a), Done(&b"\nefgh"[..], &b"ab12cd"[..]));
let b: &[u8] = b"ab12cd\nefgh\nijkl";
assert_eq!(not_line_ending(b), Done(&b"\nefgh\nijkl"[..], &b"ab12cd"[..]));
let c: &[u8] = b"ab12cd";
assert_eq!(not_line_ending(c), Done(&b""[..], c));
}
#[test]
fn buffer_with_size() {
let i:Vec<u8> = vec![7,8];
let o:Vec<u8> = vec![4,5,6];
//let arr:[u8; 6usize] = [3, 4, 5, 6, 7, 8];
let arr:[u8; 6usize] = [3, 4, 5, 6, 7, 8];
let res = sized_buffer(&arr[..]);
assert_eq!(res, Done(&i[..], &o[..]))
}
/*#[test]
fn t1() {
let v1:Vec<u8> = vec![1,2,3];
let v2:Vec<u8> = vec![4,5,6];
let d = Done(&v1[..], &v2[..]);
let res = d.flat_map(print);
assert_eq!(res, Done(&v2[..], ()));
}*/
#[test]
fn length_value_test() {
let i1 = vec![7,8];
let o1 = vec![4, 5, 6];
let arr1:[u8; 6usize] = [3, 4, 5, 6, 7, 8];
let res1 = length_value(&arr1);
assert_eq!(Done(&i1[..], &o1[..]), res1);
let i2:Vec<u8> = vec![4,5,6,7,8];
let o2: &[u8] = b"";
let arr2:[u8; 6usize] = [0, 4, 5, 6, 7, 8];
let res2 = length_value(&arr2);
assert_eq!(Done(&i2[..], o2), res2);
let arr3:[u8; 7usize] = [8, 4, 5, 6, 7, 8, 9];
let res3 = length_value(&arr3);
//FIXME: should be incomplete
assert_eq!(Incomplete(Needed::Size(9)), res3);
}
#[test]
fn i8_tests() {
assert_eq!(be_i8(&[0x00]), Done(&b""[..], 0));
assert_eq!(be_i8(&[0x7f]), Done(&b""[..], 127));
assert_eq!(be_i8(&[0xff]), Done(&b""[..], -1));
assert_eq!(be_i8(&[0x80]), Done(&b""[..], -128));
}
#[test]
fn i16_tests() {
assert_eq!(be_i16(&[0x00, 0x00]), Done(&b""[..], 0));
assert_eq!(be_i16(&[0x7f, 0xff]), Done(&b""[..], 32767_i16));
assert_eq!(be_i16(&[0xff, 0xff]), Done(&b""[..], -1));
assert_eq!(be_i16(&[0x80, 0x00]), Done(&b""[..], -32768_i16));
}
#[test]
fn i32_tests() {
assert_eq!(be_i32(&[0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0));
assert_eq!(be_i32(&[0x7f, 0xff, 0xff, 0xff]), Done(&b""[..], 2147483647_i32));
assert_eq!(be_i32(&[0xff, 0xff, 0xff, 0xff]), Done(&b""[..], -1));
assert_eq!(be_i32(&[0x80, 0x00, 0x00, 0x00]), Done(&b""[..], -2147483648_i32));
}
#[test]
fn i64_tests() {
assert_eq!(be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0));
assert_eq!(be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), Done(&b""[..], 9223372036854775807_i64));
assert_eq!(be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), Done(&b""[..], -1));
assert_eq!(be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), Done(&b""[..], -9223372036854775808_i64));
}
#[test]
fn le_i8_tests() {
assert_eq!(le_i8(&[0x00]), Done(&b""[..], 0));
assert_eq!(le_i8(&[0x7f]), Done(&b""[..], 127));
assert_eq!(le_i8(&[0xff]), Done(&b""[..], -1));
assert_eq!(le_i8(&[0x80]), Done(&b""[..], -128));
}
#[test]
fn le_i16_tests() {
assert_eq!(le_i16(&[0x00, 0x00]), Done(&b""[..], 0));
assert_eq!(le_i16(&[0xff, 0x7f]), Done(&b""[..], 32767_i16));
assert_eq!(le_i16(&[0xff, 0xff]), Done(&b""[..], -1));
assert_eq!(le_i16(&[0x00, 0x80]), Done(&b""[..], -32768_i16));
}
#[test]
fn le_i32_tests() {
assert_eq!(le_i32(&[0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0));
assert_eq!(le_i32(&[0xff, 0xff, 0xff, 0x7f]), Done(&b""[..], 2147483647_i32));
assert_eq!(le_i32(&[0xff, 0xff, 0xff, 0xff]), Done(&b""[..], -1));
assert_eq!(le_i32(&[0x00, 0x00, 0x00, 0x80]), Done(&b""[..], -2147483648_i32));
}
#[test]
fn le_i64_tests() {
assert_eq!(le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0));
assert_eq!(le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]), Done(&b""[..], 9223372036854775807_i64));
assert_eq!(le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), Done(&b""[..], -1));
assert_eq!(le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), Done(&b""[..], -9223372036854775808_i64));
}
#[test]
fn be_f32_tests() {
assert_eq!(be_f32(&[0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0_f32));
assert_eq!(be_f32(&[0x4d, 0x31, 0x1f, 0xd8]), Done(&b""[..], 185728392_f32));
}
#[test]
fn be_f64_tests() {
assert_eq!(be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0_f64));
assert_eq!(be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00]), Done(&b""[..], 185728392_f64));
}
#[test]
fn le_f32_tests() {
assert_eq!(le_f32(&[0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0_f32));
assert_eq!(le_f32(&[0xd8, 0x1f, 0x31, 0x4d]), Done(&b""[..], 185728392_f32));
}
#[test]
fn le_f64_tests() {
assert_eq!(le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0_f64));
assert_eq!(le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41]), Done(&b""[..], 185728392_f64));
}
#[test]
fn hex_u32_tests() {
assert_eq!(hex_u32(&b""[..]), Done(&b""[..], 0));
assert_eq!(hex_u32(&b"ff"[..]), Done(&b""[..], 255));
assert_eq!(hex_u32(&b"1be2"[..]), Done(&b""[..], 7138));
assert_eq!(hex_u32(&b"c5a31be2"[..]), Done(&b""[..], 3315801058));
assert_eq!(hex_u32(&b"00c5a31be2"[..]), Done(&b"e2"[..], 12952347));
assert_eq!(hex_u32(&b"c5a31be201"[..]), Done(&b"01"[..], 3315801058));
assert_eq!(hex_u32(&b"ffffffff"[..]), Done(&b""[..], 4294967295));
assert_eq!(hex_u32(&b"0x1be2"[..]), Done(&b"x1be2"[..], 0));
}
#[test]
fn end_of_input() {
let not_over = &b"Hello, world!"[..];
let is_over = &b""[..];
let res_not_over = eof(not_over);
assert_eq!(res_not_over, Error(Position(ErrorKind::Eof, not_over)));
let res_over = eof(is_over);
assert_eq!(res_over, Done(is_over, is_over));
}
#[test]
fn configurable_endianness() {
named!(be_tst16<u16>, u16!(true));
named!(le_tst16<u16>, u16!(false));
assert_eq!(be_tst16(&[0x80, 0x00]), Done(&b""[..], 32768_u16));
assert_eq!(le_tst16(&[0x80, 0x00]), Done(&b""[..], 128_u16));
named!(be_tst32<u32>, u32!(true));
named!(le_tst32<u32>, u32!(false));
assert_eq!(be_tst32(&[0x12, 0x00, 0x60, 0x00]), Done(&b""[..], 302014464_u32));
assert_eq!(le_tst32(&[0x12, 0x00, 0x60, 0x00]), Done(&b""[..], 6291474_u32));
named!(be_tst64<u64>, u64!(true));
named!(le_tst64<u64>, u64!(false));
assert_eq!(be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), Done(&b""[..], 1297142246100992000_u64));
assert_eq!(le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), Done(&b""[..], 36028874334666770_u64));
named!(be_tsti16<i16>, i16!(true));
named!(le_tsti16<i16>, i16!(false));
assert_eq!(be_tsti16(&[0x00, 0x80]), Done(&b""[..], 128_i16));
assert_eq!(le_tsti16(&[0x00, 0x80]), Done(&b""[..], -32768_i16));
named!(be_tsti32<i32>, i32!(true));
named!(le_tsti32<i32>, i32!(false));
assert_eq!(be_tsti32(&[0x00, 0x12, 0x60, 0x00]), Done(&b""[..], 1204224_i32));
assert_eq!(le_tsti32(&[0x00, 0x12, 0x60, 0x00]), Done(&b""[..], 6296064_i32));
named!(be_tsti64<i64>, i64!(true));
named!(le_tsti64<i64>, i64!(false));
assert_eq!(be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), Done(&b""[..], 71881672479506432_i64));
assert_eq!(le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), Done(&b""[..], 36028874334732032_i64));
}
#[test]
fn manual_configurable_endianness_test() {
let x = 1;
let int_parse: Box<Fn(&[u8]) -> IResult<&[u8], u16> > = if x == 2 {
Box::new(be_u16)
} else {
Box::new(le_u16)
};
println!("{:?}", int_parse(&b"3"[..]));
assert_eq!(int_parse(&[0x80, 0x00]), Done(&b""[..], 128_u16));
}
#[allow(dead_code)]
fn custom_error(input: &[u8]) -> IResult<&[u8], &[u8], ()> {
fix_error!(input, (), alphanumeric)
}
#[test]
fn hex_digit_test() {
let empty = &b""[..];
let i = &b"0123456789abcdefABCDEF"[..];
assert_eq!(hex_digit(i), Done(empty, i));
let i = &b"g"[..];
assert_eq!(hex_digit(i), Error(Position(ErrorKind::HexDigit,i)));
let i = &b"G"[..];
assert_eq!(hex_digit(i), Error(Position(ErrorKind::HexDigit,i)));
assert!(is_hex_digit(b'0'));
assert!(is_hex_digit(b'9'));
assert!(is_hex_digit(b'a'));
assert!(is_hex_digit(b'f'));
assert!(is_hex_digit(b'A'));
assert!(is_hex_digit(b'F'));
assert!(!is_hex_digit(b'g'));
assert!(!is_hex_digit(b'G'));
assert!(!is_hex_digit(b'/'));
assert!(!is_hex_digit(b':'));
assert!(!is_hex_digit(b'@'));
assert!(!is_hex_digit(b'\x60'));
}
#[test]
fn oct_digit_test() {
let empty = &b""[..];
let i = &b"01234567"[..];
assert_eq!(oct_digit(i), Done(empty, i));
let i = &b"8"[..];
assert_eq!(oct_digit(i), Error(Position(ErrorKind::OctDigit,i)));
assert!(is_oct_digit(b'0'));
assert!(is_oct_digit(b'7'));
assert!(!is_oct_digit(b'8'));
assert!(!is_oct_digit(b'9'));
assert!(!is_oct_digit(b'a'));
assert!(!is_oct_digit(b'A'));
assert!(!is_oct_digit(b'/'));
assert!(!is_oct_digit(b':'));
assert!(!is_oct_digit(b'@'));
assert!(!is_oct_digit(b'\x60'));
}
}

644
third_party/rust/nom-1.2.4/nom/src/regexp.rs поставляемый
Просмотреть файл

@ -1,644 +0,0 @@
#[doc(hidden)]
#[macro_export]
macro_rules! regex (
($re: ident, $s:expr) => (
lazy_static! {
static ref $re: ::regex::Regex = ::regex::Regex::new($s).unwrap();
}
);
);
#[doc(hidden)]
#[macro_export]
macro_rules! regex_bytes (
($re: ident, $s:expr) => (
lazy_static! {
static ref $re: ::regex::bytes::Regex = ::regex::bytes::Regex::new($s).unwrap();
}
);
);
/// `re_match!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the whole input if a match is found
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_match (
($i:expr, $re:expr) => (
{
use $crate::InputLength;
let re = ::regex::Regex::new($re).unwrap();
if re.is_match($i) {
$crate::IResult::Done(&$i[$i.input_len()..], $i)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatch))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_match_static!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the whole input if a match is found. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_match_static (
($i:expr, $re:expr) => (
{
use $crate::InputLength;
regex!(RE, $re);
if RE.is_match($i) {
$crate::IResult::Done(&$i[$i.input_len()..], $i)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatch))
}
}
)
);
/// `re_bytes_match!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the whole input if a match is found
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_bytes_match (
($i:expr, $re:expr) => (
{
use $crate::InputLength;
let re = ::regex::bytes::Regex::new($re).unwrap();
if re.is_match($i) {
$crate::IResult::Done(&$i[$i.input_len()..], $i)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatch))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_bytes_match_static!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the whole input if a match is found. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_bytes_match_static (
($i:expr, $re:expr) => (
{
use $crate::InputLength;
regex_bytes!(RE, $re);
if RE.is_match($i) {
$crate::IResult::Done(&$i[$i.input_len()..], $i)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatch))
}
}
)
);
/// `re_find!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the first match
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_find (
($i:expr, $re:expr) => (
{
let re = ::regex::Regex::new($re).unwrap();
if let Some((begin, end)) = re.find($i) {
$crate::IResult::Done(&$i[end..], &$i[begin..end])
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpFind))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_find_static!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the first match. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_find_static (
($i:expr, $re:expr) => (
{
regex!(RE, $re);
if let Some((begin, end)) = RE.find($i) {
$crate::IResult::Done(&$i[end..], &$i[begin..end])
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpFind))
}
}
)
);
/// `re_bytes_find!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the first match
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_bytes_find (
($i:expr, $re:expr) => (
{
let re = ::regex::bytes::Regex::new($re).unwrap();
if let Some((begin, end)) = re.find($i) {
$crate::IResult::Done(&$i[end..], &$i[begin..end])
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpFind))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_bytes_find!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the first match. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_bytes_find_static (
($i:expr, $re:expr) => (
{
regex_bytes!(RE, $re);
if let Some((begin, end)) = RE.find($i) {
$crate::IResult::Done(&$i[end..], &$i[begin..end])
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpFind))
}
}
)
);
/// `re_matches!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns all the matched parts
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_matches (
($i:expr, $re:expr) => (
{
let re = ::regex::Regex::new($re).unwrap();
let v: Vec<&str> = re.find_iter($i).map(|(begin,end)| &$i[begin..end]).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatches))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_matches_static!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns all the matched parts. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_matches_static (
($i:expr, $re:expr) => (
{
regex!(RE, $re);
let v: Vec<&str> = RE.find_iter($i).map(|(begin,end)| &$i[begin..end]).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatches))
}
}
)
);
/// `re_bytes_matches!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns all the matched parts
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_bytes_matches (
($i:expr, $re:expr) => (
{
let re = ::regex::bytes::Regex::new($re).unwrap();
let v: Vec<&[u8]> = re.find_iter($i).map(|(begin,end)| &$i[begin..end]).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatches))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_bytes_matches_static!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns all the matched parts. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_bytes_matches_static (
($i:expr, $re:expr) => (
{
regex_bytes!(RE, $re);
let v: Vec<&[u8]> = RE.find_iter($i).map(|(begin,end)| &$i[begin..end]).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatches))
}
}
)
);
/// `re_capture!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns the first capture group
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_capture (
($i:expr, $re:expr) => (
{
let re = ::regex::Regex::new($re).unwrap();
if let Some(c) = re.captures($i) {
let v:Vec<&str> = c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect();
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_capture_static!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns the first capture group. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_capture_static (
($i:expr, $re:expr) => (
{
regex!(RE, $re);
if let Some(c) = RE.captures($i) {
let v:Vec<&str> = c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect();
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
/// `re_bytes_capture!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns the first capture group
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_bytes_capture (
($i:expr, $re:expr) => (
{
let re = ::regex::bytes::Regex::new($re).unwrap();
if let Some(c) = re.captures($i) {
let v:Vec<&[u8]> = c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect();
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_bytes_capture_static!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns the first capture group. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_bytes_capture_static (
($i:expr, $re:expr) => (
{
regex_bytes!(RE, $re);
if let Some(c) = RE.captures($i) {
let v:Vec<&[u8]> = c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect();
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
/// `re_captures!(regexp) => &[T] -> IResult<&[T], Vec<Vec<&[T]>>>`
/// Returns all the capture groups
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_captures (
($i:expr, $re:expr) => (
{
let re = ::regex::Regex::new($re).unwrap();
let v:Vec<Vec<&str>> = re.captures_iter($i).map(|c| c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect()).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap().last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_captures_static!(regexp) => &[T] -> IResult<&[T], Vec<Vec<&[T]>>>`
/// Returns all the capture groups. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_captures_static (
($i:expr, $re:expr) => (
{
regex!(RE, $re);
let v:Vec<Vec<&str>> = RE.captures_iter($i).map(|c| c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect()).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap().last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
/// `re_bytes_captures!(regexp) => &[T] -> IResult<&[T], Vec<Vec<&[T]>>>`
/// Returns all the capture groups
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_bytes_captures (
($i:expr, $re:expr) => (
{
let re = ::regex::bytes::Regex::new($re).unwrap();
let v:Vec<Vec<&[u8]>> = re.captures_iter($i).map(|c| c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect()).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap().last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_bytes_captures_static!(regexp) => &[T] -> IResult<&[T], Vec<Vec<&[T]>>>`
/// Returns all the capture groups. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_bytes_captures_static (
($i:expr, $re:expr) => (
{
regex_bytes!(RE, $re);
let v:Vec<Vec<&[u8]>> = RE.captures_iter($i).map(|c| c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect()).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap().last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
#[cfg(test)]
mod tests {
use internal::IResult::*;
use internal::Err::*;
use util::ErrorKind;
#[test]
fn re_match() {
named!(rm<&str,&str>, re_match!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm("2015-09-07"), Done("", "2015-09-07"));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpMatch)));
assert_eq!(rm("2015-09-07blah"), Done("", "2015-09-07blah"));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_match_static() {
named!(rm<&str,&str>, re_match_static!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm("2015-09-07"), Done("", "2015-09-07"));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpMatch)));
assert_eq!(rm("2015-09-07blah"), Done("", "2015-09-07blah"));
}
#[test]
fn re_find() {
named!(rm<&str,&str>, re_find!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm("2015-09-07"), Done("", "2015-09-07"));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpFind)));
assert_eq!(rm("2015-09-07blah"), Done("blah", "2015-09-07"));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_find_static() {
named!(rm<&str,&str>, re_find_static!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm("2015-09-07"), Done("", "2015-09-07"));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpFind)));
assert_eq!(rm("2015-09-07blah"), Done("blah", "2015-09-07"));
}
#[test]
fn re_matches() {
named!(rm< &str,Vec<&str> >, re_matches!(r"\d{4}-\d{2}-\d{2}"));
assert_eq!(rm("2015-09-07"), Done("", vec!["2015-09-07"]));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpMatches)));
assert_eq!(rm("aaa2015-09-07blah2015-09-09pouet"), Done("pouet", vec!["2015-09-07", "2015-09-09"]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_matches_static() {
named!(rm< &str,Vec<&str> >, re_matches_static!(r"\d{4}-\d{2}-\d{2}"));
assert_eq!(rm("2015-09-07"), Done("", vec!["2015-09-07"]));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpMatches)));
assert_eq!(rm("aaa2015-09-07blah2015-09-09pouet"), Done("pouet", vec!["2015-09-07", "2015-09-09"]));
}
#[test]
fn re_capture() {
named!(rm< &str,Vec<&str> >, re_capture!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm("blah nom 0.3.11pouet"), Done("pouet", vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm("hello nom 0.3.11 world regex 0.1.41"), Done(" world regex 0.1.41", vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_capture_static() {
named!(rm< &str,Vec<&str> >, re_capture_static!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm("blah nom 0.3.11pouet"), Done("pouet", vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm("hello nom 0.3.11 world regex 0.1.41"), Done(" world regex 0.1.41", vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]));
}
#[test]
fn re_captures() {
named!(rm< &str,Vec<Vec<&str>> >, re_captures!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm("blah nom 0.3.11pouet"), Done("pouet", vec![vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]]));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm("hello nom 0.3.11 world regex 0.1.41 aaa"), Done(" aaa", vec![
vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"],
vec!["regex 0.1.41", "regex", "0.1.41", "0", "1", "41"],
]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_captures_static() {
named!(rm< &str,Vec<Vec<&str>> >, re_captures_static!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm("blah nom 0.3.11pouet"), Done("pouet", vec![vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]]));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm("hello nom 0.3.11 world regex 0.1.41 aaa"), Done(" aaa", vec![
vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"],
vec!["regex 0.1.41", "regex", "0.1.41", "0", "1", "41"],
]));
}
#[test]
fn re_bytes_match() {
named!(rm, re_bytes_match!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm(&b"2015-09-07"[..]), Done(&b""[..], &b"2015-09-07"[..]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpMatch)));
assert_eq!(rm(&b"2015-09-07blah"[..]), Done(&b""[..], &b"2015-09-07blah"[..]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_bytes_match_static() {
named!(rm, re_bytes_match_static!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm(&b"2015-09-07"[..]), Done(&b""[..], &b"2015-09-07"[..]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpMatch)));
assert_eq!(rm(&b"2015-09-07blah"[..]), Done(&b""[..], &b"2015-09-07blah"[..]));
}
#[test]
fn re_bytes_find() {
named!(rm, re_bytes_find!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm(&b"2015-09-07"[..]), Done(&b""[..], &b"2015-09-07"[..]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpFind)));
assert_eq!(rm(&b"2015-09-07blah"[..]), Done(&b"blah"[..], &b"2015-09-07"[..]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_bytes_find_static() {
named!(rm, re_bytes_find_static!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm(&b"2015-09-07"[..]), Done(&b""[..], &b"2015-09-07"[..]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpFind)));
assert_eq!(rm(&b"2015-09-07blah"[..]), Done(&b"blah"[..], &b"2015-09-07"[..]));
}
#[test]
fn re_bytes_matches() {
named!(rm<Vec<&[u8]> >, re_bytes_matches!(r"\d{4}-\d{2}-\d{2}"));
assert_eq!(rm(&b"2015-09-07"[..]), Done(&b""[..], vec![&b"2015-09-07"[..]]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpMatches)));
assert_eq!(rm(&b"aaa2015-09-07blah2015-09-09pouet"[..]), Done(&b"pouet"[..], vec![&b"2015-09-07"[..], &b"2015-09-09"[..]]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_bytes_matches_static() {
named!(rm<Vec<&[u8]> >, re_bytes_matches_static!(r"\d{4}-\d{2}-\d{2}"));
assert_eq!(rm(&b"2015-09-07"[..]), Done(&b""[..], vec![&b"2015-09-07"[..]]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpMatches)));
assert_eq!(rm(&b"aaa2015-09-07blah2015-09-09pouet"[..]), Done(&b"pouet"[..], vec![&b"2015-09-07"[..], &b"2015-09-09"[..]]));
}
#[test]
fn re_bytes_capture() {
named!(rm<Vec<&[u8]> >, re_bytes_capture!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm(&b"blah nom 0.3.11pouet"[..]), Done(&b"pouet"[..], vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm(&b"hello nom 0.3.11 world regex 0.1.41"[..]), Done(&b" world regex 0.1.41"[..], vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_bytes_capture_static() {
named!(rm< Vec<&[u8]> >, re_bytes_capture_static!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm(&b"blah nom 0.3.11pouet"[..]), Done(&b"pouet"[..], vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm(&b"hello nom 0.3.11 world regex 0.1.41"[..]), Done(&b" world regex 0.1.41"[..], vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]]));
}
#[test]
fn re_bytes_captures() {
named!(rm< Vec<Vec<&[u8]>> >, re_bytes_captures!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm(&b"blah nom 0.3.11pouet"[..]), Done(&b"pouet"[..], vec![vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]]]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm(&b"hello nom 0.3.11 world regex 0.1.41 aaa"[..]), Done(&b" aaa"[..], vec![
vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]],
vec![&b"regex 0.1.41"[..], &b"regex"[..], &b"0.1.41"[..], &b"0"[..], &b"1"[..], &b"41"[..]],
]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_bytes_captures_static() {
named!(rm< Vec<Vec<&[u8]>> >, re_bytes_captures_static!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm(&b"blah nom 0.3.11pouet"[..]), Done(&b"pouet"[..], vec![vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]]]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm(&b"hello nom 0.3.11 world regex 0.1.41 aaa"[..]), Done(&b" aaa"[..], vec![
vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]],
vec![&b"regex 0.1.41"[..], &b"regex"[..], &b"0.1.41"[..], &b"0"[..], &b"1"[..], &b"41"[..]],
]));
}
}

734
third_party/rust/nom-1.2.4/nom/src/str.rs поставляемый
Просмотреть файл

@ -1,734 +0,0 @@
//! Parsers and helper functions operating on strings, especially useful when writing parsers for
//! text-based formats.
/// `tag_s!(&str) => &str -> IResult<&str, &str>`
/// declares a string as a suite to recognize
///
/// consumes the recognized characters
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::{self,Done};
/// # fn main() {
/// fn test(input: &str) -> IResult<&str, &str> {
/// tag_s!(input, "abcd")
/// }
/// let r = test("abcdefgh");
/// assert_eq!(r, Done("efgh", "abcd"));
/// # }
/// ```
#[macro_export]
macro_rules! tag_s (
($i:expr, $tag: expr) => (
{
let res: $crate::IResult<_,_> = if $tag.len() > $i.len() {
$crate::IResult::Incomplete($crate::Needed::Size($tag.len()))
//} else if &$i[0..$tag.len()] == $tag {
} else if ($i).starts_with($tag) {
$crate::IResult::Done(&$i[$tag.len()..], &$i[0..$tag.len()])
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TagStr, $i))
};
res
}
);
);
/// `take_s!(nb) => &str -> IResult<&str, &str>`
/// generates a parser consuming the specified number of characters
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
/// // Desmond parser
/// named!(take5<&str,&str>, take_s!( 5 ) );
///
/// let a = "abcdefgh";
///
/// assert_eq!(take5(a), Done("fgh", "abcde"));
/// # }
/// ```
#[macro_export]
macro_rules! take_s (
($i:expr, $count:expr) => (
{
let cnt = $count as usize;
let res: $crate::IResult<_,_> = if $i.chars().count() < cnt {
$crate::IResult::Incomplete($crate::Needed::Size(cnt))
} else {
let mut offset = $i.len();
let mut count = 0;
for (o, _) in $i.char_indices() {
if count == cnt {
offset = o;
break;
}
count += 1;
}
$crate::IResult::Done(&$i[offset..], &$i[..offset])
};
res
}
);
);
/// `is_not_s!(&str) => &str -> IResult<&str, &str>`
/// returns the longest list of characters that do not appear in the provided array
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
/// named!( not_space<&str,&str>, is_not_s!( " \t\r\n" ) );
///
/// let r = not_space("abcdefgh\nijkl");
/// assert_eq!(r, Done("\nijkl", "abcdefgh"));
/// # }
/// ```
#[macro_export]
macro_rules! is_not_s (
($input:expr, $arr:expr) => (
{
use std::collections::HashSet;
let set: HashSet<char> = $arr.chars().collect();
let mut offset = $input.len();
for (o, c) in $input.char_indices() {
if set.contains(&c) {
offset = o;
break;
}
}
if offset == 0 {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::IsAStr,$input))
} else if offset < $input.len() {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Done("", $input)
}
}
);
);
/// `is_a_s!(&str) => &str -> IResult<&str, &str>`
/// returns the longest list of characters that appear in the provided array
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
/// named!(abcd<&str, &str>, is_a_s!( "abcd" ));
///
/// let r1 = abcd("aaaaefgh");
/// assert_eq!(r1, Done("efgh", "aaaa"));
///
/// let r2 = abcd("dcbaefgh");
/// assert_eq!(r2, Done("efgh", "dcba"));
/// # }
/// ```
#[macro_export]
macro_rules! is_a_s (
($input:expr, $arr:expr) => (
{
use std::collections::HashSet;
let set: HashSet<char> = $arr.chars().collect();
let mut offset = $input.len();
for (o, c) in $input.char_indices() {
if !set.contains(&c) {
offset = o;
break;
}
}
if offset == 0 {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::IsAStr,$input))
} else if offset < $input.len() {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Done("", $input)
}
}
);
);
/// `take_while_s!(char -> bool) => &str -> IResult<&str, &str>`
/// returns the longest list of characters until the provided function fails.
///
/// The argument is either a function `char -> bool` or a macro returning a `bool
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # use nom::is_alphanumeric;
/// # fn main() {
/// fn alphabetic(chr: char) -> bool { (chr >= 0x41 as char && chr <= 0x5A as char) || (chr >= 0x61 as char && chr <= 0x7A as char) }
/// named!( alpha<&str,&str>, take_while_s!( alphabetic ) );
///
/// let r = alpha("abcd\nefgh");
/// assert_eq!(r, Done("\nefgh", "abcd"));
/// # }
/// ```
#[macro_export]
macro_rules! take_while_s (
($input:expr, $submac:ident!( $($args:tt)* )) => (
{
let mut offset = $input.len();
for (o, c) in $input.char_indices() {
if !$submac!(c, $($args)*) {
offset = o;
break;
}
}
if offset < $input.len() {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Done("", $input)
}
}
);
($input:expr, $f:expr) => (
take_while_s!($input, call!($f));
);
);
/// `take_while1_s!(char -> bool) => &str -> IResult<&str, &str>`
/// returns the longest (non empty) list of characters until the provided function fails.
///
/// The argument is either a function `char -> bool` or a macro returning a `bool`
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # use nom::is_alphanumeric;
/// # fn main() {
/// fn alphabetic(chr: char) -> bool { (chr >= 0x41 as char && chr <= 0x5A as char) || (chr >= 0x61 as char && chr <= 0x7A as char) }
/// named!( alpha<&str,&str>, take_while1_s!( alphabetic ) );
///
/// let r = alpha("abcd\nefgh");
/// assert_eq!(r, Done("\nefgh", "abcd"));
/// # }
/// ```
#[macro_export]
macro_rules! take_while1_s (
($input:expr, $submac:ident!( $($args:tt)* )) => (
{
let mut offset = $input.len();
for (o, c) in $input.char_indices() {
if !$submac!(c, $($args)*) {
offset = o;
break;
}
}
if offset == 0 {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TakeWhile1Str,$input))
} else if offset < $input.len() {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Done("", $input)
}
}
);
($input:expr, $f:expr) => (
take_while1_s!($input, call!($f));
);
);
/// `take_till_s!(&str -> bool) => &str -> IResult<&str, &str>`
/// returns the longest list of characters until the provided function succeeds
///
/// The argument is either a function `char -> bool` or a macro returning a `bool
#[macro_export]
macro_rules! take_till_s (
($input:expr, $submac:ident!( $($args:tt)* )) => (
{
let mut offset = $input.len();
for (o, c) in $input.char_indices() {
if $submac!(c, $($args)*) {
offset = o;
break;
}
}
if offset < $input.len() {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Done("", $input)
}
}
);
($input:expr, $f:expr) => (
take_till_s!($input, call!($f));
);
);
/// `take_until_and_consume_s!(&str) => &str -> IResult<&str, &str>`
/// generates a parser consuming all chars until the specified string is found and consumes it
#[macro_export]
macro_rules! take_until_and_consume_s (
($input:expr, $substr:expr) => (
{
#[inline(always)]
fn shift_window_and_cmp(window: & mut ::std::vec::Vec<char>, c: char, substr_vec: & ::std::vec::Vec<char>) -> bool {
window.push(c);
if window.len() > substr_vec.len() {
window.remove(0);
}
window == substr_vec
}
let res: $crate::IResult<_, _> = if $substr.len() > $input.len() {
$crate::IResult::Incomplete($crate::Needed::Size($substr.len()))
} else {
let substr_vec: ::std::vec::Vec<char> = $substr.chars().collect();
let mut window: ::std::vec::Vec<char> = vec![];
let mut offset = $input.len();
let mut parsed = false;
for (o, c) in $input.char_indices() {
if parsed {
// The easiest way to get the byte offset of the char after the found string
offset = o;
break;
}
if shift_window_and_cmp(& mut window, c, &substr_vec) {
parsed = true;
}
}
if parsed {
if offset < $input.len() {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Done("", $input)
}
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TakeUntilAndConsumeStr,$input))
}
};
res
}
);
);
/// `take_until_s!(&str) => &str -> IResult<&str, &str>`
/// generates a parser consuming all chars until the specified string is found and leaves it in the remaining input
#[macro_export]
macro_rules! take_until_s (
($input:expr, $substr:expr) => (
{
#[inline(always)]
fn shift_window_and_cmp(window: & mut Vec<char>, c: char, substr_vec: &Vec<char>) -> bool {
window.push(c);
if window.len() > substr_vec.len() {
window.remove(0);
}
window == substr_vec
}
let res: $crate::IResult<&str, &str> = if $substr.len() > $input.len() {
$crate::IResult::Incomplete($crate::Needed::Size($substr.len()))
} else {
let substr_vec: Vec<char> = $substr.chars().collect();
let mut window: Vec<char> = vec![];
let mut offset = $input.len();
let mut parsed = false;
for (o, c) in $input.char_indices() {
if shift_window_and_cmp(& mut window, c, &substr_vec) {
parsed = true;
window.pop();
let window_len: usize = window.iter()
.map(|x| x.len_utf8())
.fold(0, |x, y| x + y);
offset = o - window_len;
break;
}
}
if parsed {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TakeUntilStr,$input))
}
};
res
}
);
);
#[cfg(test)]
mod test {
use ::IResult;
#[test]
fn tag_str_succeed() {
const INPUT: &'static str = "Hello World!";
const TAG: &'static str = "Hello";
fn test(input: &str) -> IResult<&str, &str> {
tag_s!(input, TAG)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == " World!", "Parser `tag_s` consumed leftover input.");
assert!(output == TAG,
"Parser `tag_s` doesn't return the tag it matched on success. \
Expected `{}`, got `{}`.", TAG, output);
},
other => panic!("Parser `tag_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn tag_str_incomplete() {
const INPUT: &'static str = "Hello";
const TAG: &'static str = "Hello World!";
match tag_s!(INPUT, TAG) {
IResult::Incomplete(_) => (),
other => {
panic!("Parser `tag_s` didn't require more input when it should have. \
Got `{:?}`.", other);
}
};
}
#[test]
fn tag_str_error() {
const INPUT: &'static str = "Hello World!";
const TAG: &'static str = "Random"; // TAG must be closer than INPUT.
match tag_s!(INPUT, TAG) {
IResult::Error(_) => (),
other => {
panic!("Parser `tag_s` didn't fail when it should have. Got `{:?}`.`", other);
},
};
}
#[test]
fn take_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
match take_s!(INPUT, 9) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_s` consumed leftover input. Leftover `{}`.", extra);
assert!(output == CONSUMED,
"Parser `take_s` doens't return the string it consumed on success. Expected `{}`, got `{}`.",
CONSUMED, output);
},
other => panic!("Parser `take_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_until_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇ∂áƒƭèř";
const FIND: &'static str = "ÂßÇ∂";
const CONSUMED: &'static str = "βèƒôřè";
const LEFTOVER: &'static str = "ÂßÇ∂áƒƭèř";
match take_until_s!(INPUT, FIND) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_until_s`\
consumed leftover input. Leftover `{}`.", extra);
assert!(output == CONSUMED, "Parser `take_until_s`\
doens't return the string it consumed on success. Expected `{}`, got `{}`.",
CONSUMED, output);
}
other => panic!("Parser `take_until_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_s_incomplete() {
const INPUT: &'static str = "βèƒôřèÂßÇá";
match take_s!(INPUT, 13) {
IResult::Incomplete(_) => (),
other => panic!("Parser `take_s` didn't require more input when it should have. \
Got `{:?}`.", other),
}
}
use internal::IResult::{Done, Error};
use internal::Err::Position;
use util::ErrorKind;
pub fn is_alphabetic(c:char) -> bool {
(c as u8 >= 0x41 && c as u8 <= 0x5A) || (c as u8 >= 0x61 && c as u8 <= 0x7A)
}
#[test]
fn take_while_s() {
named!(f<&str,&str>, take_while_s!(is_alphabetic));
let a = "";
let b = "abcd";
let c = "abcd123";
let d = "123";
assert_eq!(f(&a[..]), Done(&a[..], &a[..]));
assert_eq!(f(&b[..]), Done(&a[..], &b[..]));
assert_eq!(f(&c[..]), Done(&d[..], &b[..]));
assert_eq!(f(&d[..]), Done(&d[..], &a[..]));
}
#[test]
fn take_while1_s() {
named!(f<&str,&str>, take_while1_s!(is_alphabetic));
let a = "";
let b = "abcd";
let c = "abcd123";
let d = "123";
assert_eq!(f(&a[..]), Error(Position(ErrorKind::TakeWhile1Str, &""[..])));
assert_eq!(f(&b[..]), Done(&a[..], &b[..]));
assert_eq!(f(&c[..]), Done(&"123"[..], &b[..]));
assert_eq!(f(&d[..]), Error(Position(ErrorKind::TakeWhile1Str, &d[..])));
}
#[test]
fn take_till_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
fn till_s(c: char) -> bool {
c == 'á'
}
fn test(input: &str) -> IResult<&str, &str> {
take_till_s!(input, till_s)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_till_s` consumed leftover input.");
assert!(output == CONSUMED,
"Parser `take_till_s` doesn't return the string it consumed on success. \
Expected `{}`, got `{}`.", CONSUMED, output);
},
other => panic!("Parser `take_till_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_while_s_succeed_none() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const CONSUMED: &'static str = "";
const LEFTOVER: &'static str = "βèƒôřèÂßÇáƒƭèř";
fn while_s(c: char) -> bool {
c == '9'
}
fn test(input: &str) -> IResult<&str, &str> {
take_while_s!(input, while_s)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_while_s` consumed leftover input.");
assert!(output == CONSUMED,
"Parser `take_while_s` doesn't return the string it consumed on success. \
Expected `{}`, got `{}`.", CONSUMED, output);
},
other => panic!("Parser `take_while_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn is_not_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const AVOID: &'static str = "£úçƙ¥á";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
fn test(input: &str) -> IResult<&str, &str> {
is_not_s!(input, AVOID)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `is_not_s` consumed leftover input. Leftover `{}`.", extra);
assert!(output == CONSUMED,
"Parser `is_not_s` doens't return the string it consumed on success. Expected `{}`, got `{}`.",
CONSUMED, output);
},
other => panic!("Parser `is_not_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_until_and_consume_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const FIND: &'static str = "姂";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
match take_until_and_consume_s!(INPUT, FIND) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_until_and_consume_s`\
consumed leftover input. Leftover `{}`.", extra);
assert!(output == CONSUMED, "Parser `take_until_and_consume_s`\
doens't return the string it consumed on success. Expected `{}`, got `{}`.",
CONSUMED, output);
}
other => panic!("Parser `take_until_and_consume_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_while_s_succeed_some() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
fn while_s(c: char) -> bool {
c == 'β' || c == 'è' || c == 'ƒ' || c == 'ô' || c == 'ř' ||
c == 'è' || c == 'Â' || c == 'ß' || c == 'Ç'
}
fn test(input: &str) -> IResult<&str, &str> {
take_while_s!(input, while_s)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_while_s` consumed leftover input.");
assert!(output == CONSUMED,
"Parser `take_while_s` doesn't return the string it consumed on success. \
Expected `{}`, got `{}`.", CONSUMED, output);
},
other => panic!("Parser `take_while_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn is_not_s_fail() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const AVOID: &'static str = "βúçƙ¥";
fn test(input: &str) -> IResult<&str, &str> {
is_not_s!(input, AVOID)
}
match test(INPUT) {
IResult::Error(_) => (),
other => panic!("Parser `is_not_s` didn't fail when it should have. Got `{:?}`.", other),
};
}
#[test]
fn take_while1_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
fn while1_s(c: char) -> bool {
c == 'β' || c == 'è' || c == 'ƒ' || c == 'ô' || c == 'ř' ||
c == 'è' || c == 'Â' || c == 'ß' || c == 'Ç'
}
fn test(input: &str) -> IResult<&str, &str> {
take_while1_s!(input, while1_s)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_while1_s` consumed leftover input.");
assert!(output == CONSUMED,
"Parser `take_while1_s` doesn't return the string it consumed on success. \
Expected `{}`, got `{}`.", CONSUMED, output);
},
other => panic!("Parser `take_while1_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_until_and_consume_s_incomplete() {
const INPUT: &'static str = "βèƒôřè";
const FIND: &'static str = "βèƒôřèÂßÇ";
match take_until_and_consume_s!(INPUT, FIND) {
IResult::Incomplete(_) => (),
other => panic!("Parser `take_until_and_consume_s` didn't require more input when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_until_s_incomplete() {
const INPUT: &'static str = "βèƒôřè";
const FIND: &'static str = "βèƒôřèÂßÇ";
match take_until_s!(INPUT, FIND) {
IResult::Incomplete(_) => (),
other => panic!("Parser `take_until_s` didn't require more input when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn is_a_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const MATCH: &'static str = "βèƒôřèÂßÇ";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
fn test(input: &str) -> IResult<&str, &str> {
is_a_s!(input, MATCH)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `is_a_s` consumed leftover input. Leftover `{}`.", extra);
assert!(output == CONSUMED,
"Parser `is_a_s` doens't return the string it consumed on success. Expected `{}`, got `{}`.",
CONSUMED, output);
},
other => panic!("Parser `is_a_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_while1_s_fail() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
fn while1_s(c: char) -> bool {
c == '9'
}
fn test(input: &str) -> IResult<&str, &str> {
take_while1_s!(input, while1_s)
}
match test(INPUT) {
IResult::Error(_) => (),
other => panic!("Parser `take_while1_s` didn't fail when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn is_a_s_fail() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const MATCH: &'static str = "Ûñℓúçƙ¥";
fn test(input: &str) -> IResult<&str, &str> {
is_a_s!(input, MATCH)
}
match test(INPUT) {
IResult::Error(_) => (),
other => panic!("Parser `is_a_s` didn't fail when it should have. Got `{:?}`.", other),
};
}
#[test]
fn take_until_and_consume_s_error() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const FIND: &'static str = "Ráñδô₥";
match take_until_and_consume_s!(INPUT, FIND) {
IResult::Error(_) => (),
other => panic!("Parser `take_until_and_consume_s` didn't fail when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_until_s_error() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const FIND: &'static str = "Ráñδô₥";
match take_until_s!(INPUT, FIND) {
IResult::Error(_) => (),
other => panic!("Parser `take_until_and_consume_s` didn't fail when it should have. \
Got `{:?}`.", other),
};
}
}

1031
third_party/rust/nom-1.2.4/nom/src/stream.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

769
third_party/rust/nom-1.2.4/nom/src/util.rs поставляемый
Просмотреть файл

@ -1,769 +0,0 @@
use internal::{IResult,Err};
#[cfg(not(feature = "core"))]
use std::collections::HashMap;
#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::vec::Vec;
use std::string::ToString;
/// useful functions to calculate the offset between slices and show a hexdump of a slice
#[cfg(not(feature = "core"))]
pub trait HexDisplay {
/// offset between the first byte of self and the first byte of the argument
fn offset(&self, second:&[u8]) -> usize;// OFFSET SHOULD GO TO ITS OWN TRAIT
/// Converts the value of `self` to a hex dump, returning the owned
/// string.
fn to_hex(&self, chunk_size: usize) -> String;
/// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned
/// string.
fn to_hex_from(&self, chunk_size: usize, from: usize) -> String;
}
pub trait InputLength {
#[inline]
fn input_len(&self) -> usize;
}
impl<'a, T> InputLength for &'a[T] {
#[inline]
fn input_len(&self) -> usize {
self.len()
}
}
impl<'a> InputLength for &'a str {
#[inline]
fn input_len(&self) -> usize {
self.len()
}
}
impl<'a> InputLength for (&'a [u8], usize) {
#[inline]
fn input_len(&self) -> usize {
//println!("bit input length for ({:?}, {}):", self.0, self.1);
let res = self.0.len() * 8 - self.1;
//println!("-> {}", res);
res
}
}
use std::iter::Enumerate;
#[cfg(not(feature = "core"))]
use std::str::CharIndices;
pub trait AsChar {
#[inline]
fn as_char(self) -> char;
#[inline]
fn is_alpha(self) -> bool;
#[inline]
fn is_alphanum(self) -> bool;
#[inline]
fn is_0_to_9(self) -> bool;
#[inline]
fn is_hex_digit(self) -> bool;
#[inline]
fn is_oct_digit(self) -> bool;
}
impl<'a> AsChar for &'a u8 {
#[inline]
fn as_char(self) -> char { *self as char }
#[inline]
fn is_alpha(self) -> bool {
(*self >= 0x41 && *self <= 0x5A) || (*self >= 0x61 && *self <= 0x7A)
}
#[inline]
fn is_alphanum(self) -> bool { self.is_alpha() || self.is_0_to_9() }
#[inline]
fn is_0_to_9(self) -> bool {
*self >= 0x30 && *self <= 0x39
}
#[inline]
fn is_hex_digit(self) -> bool {
(*self >= 0x30 && *self <= 0x39) ||
(*self >= 0x41 && *self <= 0x46) ||
(*self >= 0x61 && *self <= 0x66)
}
#[inline]
fn is_oct_digit(self) -> bool {
*self >= 0x30 && *self <= 0x37
}
}
impl AsChar for char {
#[inline]
fn as_char(self) -> char { self }
#[inline]
fn is_alpha(self) -> bool { self.is_alphabetic() }
#[inline]
fn is_alphanum(self) -> bool { self.is_alpha() || self.is_0_to_9() }
#[inline]
fn is_0_to_9(self) -> bool { self.is_digit(10) }
#[inline]
fn is_hex_digit(self) -> bool { self.is_digit(16) }
#[inline]
fn is_oct_digit(self) -> bool { self.is_digit(8) }
}
pub trait IterIndices {
type Item: AsChar;
type Iter : Iterator<Item=(usize, Self::Item)>;
fn iter_indices(self) -> Self::Iter;
}
impl<'a> IterIndices for &'a [u8] {
type Item = &'a u8;
type Iter = Enumerate<::std::slice::Iter<'a, u8>>;
#[inline]
fn iter_indices(self) -> Enumerate<::std::slice::Iter<'a, u8>> {
self.iter().enumerate()
}
}
#[cfg(not(feature = "core"))]
impl<'a> IterIndices for &'a str {
type Item = char;
type Iter = CharIndices<'a>;
#[inline]
fn iter_indices(self) -> CharIndices<'a> {
self.char_indices()
}
}
static CHARS: &'static[u8] = b"0123456789abcdef";
#[cfg(not(feature = "core"))]
impl HexDisplay for [u8] {
fn offset(&self, second:&[u8]) -> usize {
let fst = self.as_ptr();
let snd = second.as_ptr();
snd as usize - fst as usize
}
#[allow(unused_variables)]
fn to_hex(&self, chunk_size: usize) -> String {
self.to_hex_from(chunk_size, 0)
}
#[allow(unused_variables)]
fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
let mut v = Vec::with_capacity(self.len() * 3);
let mut i = from;
for chunk in self.chunks(chunk_size) {
let s = format!("{:08x}", i);
for &ch in s.as_bytes().iter() {
v.push(ch);
}
v.push('\t' as u8);
i = i + chunk_size;
for &byte in chunk {
v.push(CHARS[(byte >> 4) as usize]);
v.push(CHARS[(byte & 0xf) as usize]);
v.push(' ' as u8);
}
if chunk_size > chunk.len() {
for j in 0..(chunk_size - chunk.len()) {
v.push(' ' as u8);
v.push(' ' as u8);
v.push(' ' as u8);
}
}
v.push('\t' as u8);
for &byte in chunk {
if (byte >=32 && byte <= 126) || byte >= 128 {
v.push(byte);
} else {
v.push('.' as u8);
}
}
v.push('\n' as u8);
}
String::from_utf8_lossy(&v[..]).into_owned()
}
}
/// Prints a message if the parser fails
///
/// The message prints the `Error` or `Incomplete`
/// and the parser's calling code
///
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
/// named!(f, dbg!( tag!( "abcd" ) ) );
///
/// let a = &b"efgh"[..];
///
/// // Will print the following message:
/// // Error(Position(0, [101, 102, 103, 104])) at l.5 by ' tag ! ( "abcd" ) '
/// f(a);
/// # }
/// ```
#[macro_export]
macro_rules! dbg (
($i: expr, $submac:ident!( $($args:tt)* )) => (
{
let l = line!();
match $submac!($i, $($args)*) {
$crate::IResult::Error(a) => {
println!("Error({:?}) at l.{} by ' {} '", a, l, stringify!($submac!($($args)*)));
$crate::IResult::Error(a)
},
$crate::IResult::Incomplete(a) => {
println!("Incomplete({:?}) at {} by ' {} '", a, l, stringify!($submac!($($args)*)));
$crate::IResult::Incomplete(a)
},
a => a
}
}
);
($i:expr, $f:ident) => (
dbg!($i, call!($f));
);
);
/// Prints a message and the input if the parser fails
///
/// The message prints the `Error` or `Incomplete`
/// and the parser's calling code.
///
/// It also displays the input in hexdump format
///
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
/// named!(f, dbg_dmp!( tag!( "abcd" ) ) );
///
/// let a = &b"efghijkl"[..];
///
/// // Will print the following message:
/// // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) '
/// // 00000000 65 66 67 68 69 6a 6b 6c efghijkl
/// f(a);
/// # }
#[macro_export]
macro_rules! dbg_dmp (
($i: expr, $submac:ident!( $($args:tt)* )) => (
{
use $crate::HexDisplay;
let l = line!();
match $submac!($i, $($args)*) {
$crate::IResult::Error(a) => {
println!("Error({:?}) at l.{} by ' {} '\n{}", a, l, stringify!($submac!($($args)*)), $i.to_hex(8));
$crate::IResult::Error(a)
},
$crate::IResult::Incomplete(a) => {
println!("Incomplete({:?}) at {} by ' {} '\n{}", a, l, stringify!($submac!($($args)*)), $i.to_hex(8));
$crate::IResult::Incomplete(a)
},
a => a
}
}
);
($i:expr, $f:ident) => (
dbg_dmp!($i, call!($f));
);
);
pub fn error_to_list<P,E:Clone>(e:&Err<P,E>) -> Vec<ErrorKind<E>> {
let mut v:Vec<ErrorKind<E>> = Vec::new();
let mut err = e;
loop {
match *err {
Err::Code(ref i) | Err::Position(ref i,_) => {
v.push(i.clone());
return v;
},
Err::Node(ref i, ref next) | Err::NodePosition(ref i, _, ref next) => {
v.push(i.clone());
err = &*next;
}
}
}
}
pub fn compare_error_paths<P,E:Clone+PartialEq>(e1:&Err<P,E>, e2:&Err<P,E>) -> bool {
error_to_list(e1) == error_to_list(e2)
}
#[cfg(not(feature = "core"))]
use std::hash::Hash;
#[cfg(not(feature = "core"))]
pub fn add_error_pattern<'a,I,O,E: Clone+Hash+Eq>(h: &mut HashMap<Vec<ErrorKind<E>>, &'a str>, res: IResult<I,O,E>, message: &'a str) -> bool {
if let IResult::Error(e) = res {
h.insert(error_to_list(&e), message);
true
} else {
false
}
}
pub fn slice_to_offsets(input: &[u8], s: &[u8]) -> (usize, usize) {
let start = input.as_ptr();
let off1 = s.as_ptr() as usize - start as usize;
let off2 = off1 + s.len();
(off1, off2)
}
#[cfg(not(feature = "core"))]
pub fn prepare_errors<O,E: Clone>(input: &[u8], res: IResult<&[u8],O,E>) -> Option<Vec<(ErrorKind<E>, usize, usize)> > {
if let IResult::Error(e) = res {
let mut v:Vec<(ErrorKind<E>, usize, usize)> = Vec::new();
let mut err = e.clone();
loop {
match err {
Err::Position(i,s) => {
let (o1, o2) = slice_to_offsets(input, s);
v.push((i, o1, o2));
//println!("v is: {:?}", v);
break;
},
Err::NodePosition(i, s, next) => {
let (o1, o2) = slice_to_offsets(input, s);
v.push((i, o1, o2));
err = *next;
},
Err::Node(_, next) => {
err = *next;
},
Err::Code(_) => {
break;
}
}
}
v.sort_by(|a, b| a.1.cmp(&b.1));
Some(v)
} else {
None
}
}
#[cfg(not(feature = "core"))]
pub fn print_error<O,E:Clone>(input: &[u8], res: IResult<&[u8],O,E>) {
if let Some(v) = prepare_errors(input, res) {
let colors = generate_colors(&v);
println!("parser codes: {}", print_codes(colors, HashMap::new()));
println!("{}", print_offsets(input, 0, &v));
} else {
println!("not an error");
}
}
#[cfg(not(feature = "core"))]
pub fn generate_colors<E>(v: &[(ErrorKind<E>, usize, usize)]) -> HashMap<u32, u8> {
let mut h: HashMap<u32, u8> = HashMap::new();
let mut color = 0;
for &(ref c,_,_) in v.iter() {
h.insert(error_to_u32(c), color + 31);
color = color + 1 % 7;
}
h
}
pub fn code_from_offset<E>(v: &[(ErrorKind<E>, usize, usize)], offset: usize) -> Option<u32> {
let mut acc: Option<(u32, usize, usize)> = None;
for &(ref ek, s, e) in v.iter() {
let c = error_to_u32(ek);
if s <= offset && offset <=e {
if let Some((_, start, end)) = acc {
if start <= s && e <= end {
acc = Some((c, s, e));
}
} else {
acc = Some((c, s, e));
}
}
}
if let Some((code, _, _)) = acc {
return Some(code);
} else {
return None;
}
}
pub fn reset_color(v: &mut Vec<u8>) {
v.push(0x1B);
v.push('[' as u8);
v.push(0);
v.push('m' as u8);
}
pub fn write_color(v: &mut Vec<u8>, color: u8) {
v.push(0x1B);
v.push('[' as u8);
v.push(1);
v.push(';' as u8);
let s = color.to_string();
let bytes = s.as_bytes();
v.extend(bytes.iter().cloned());
v.push('m' as u8);
}
#[cfg(not(feature = "core"))]
pub fn print_codes(colors: HashMap<u32, u8>, names: HashMap<u32, &str>) -> String {
let mut v = Vec::new();
for (code, &color) in &colors {
if let Some(&s) = names.get(&code) {
let bytes = s.as_bytes();
write_color(&mut v, color);
v.extend(bytes.iter().cloned());
} else {
let s = code.to_string();
let bytes = s.as_bytes();
write_color(&mut v, color);
v.extend(bytes.iter().cloned());
}
reset_color(&mut v);
v.push(' ' as u8);
}
reset_color(&mut v);
String::from_utf8_lossy(&v[..]).into_owned()
}
#[cfg(not(feature = "core"))]
pub fn print_offsets<E>(input: &[u8], from: usize, offsets: &[(ErrorKind<E>, usize, usize)]) -> String {
let mut v = Vec::with_capacity(input.len() * 3);
let mut i = from;
let chunk_size = 8;
let mut current_code: Option<u32> = None;
let mut current_code2: Option<u32> = None;
let colors = generate_colors(&offsets);
for chunk in input.chunks(chunk_size) {
let s = format!("{:08x}", i);
for &ch in s.as_bytes().iter() {
v.push(ch);
}
v.push('\t' as u8);
let mut k = i;
let mut l = i;
for &byte in chunk {
if let Some(code) = code_from_offset(&offsets, k) {
if let Some(current) = current_code {
if current != code {
reset_color(&mut v);
current_code = Some(code);
if let Some(&color) = colors.get(&code) {
write_color(&mut v, color);
}
}
} else {
current_code = Some(code);
if let Some(&color) = colors.get(&code) {
write_color(&mut v, color);
}
}
}
v.push(CHARS[(byte >> 4) as usize]);
v.push(CHARS[(byte & 0xf) as usize]);
v.push(' ' as u8);
k = k + 1;
}
reset_color(&mut v);
if chunk_size > chunk.len() {
for _ in 0..(chunk_size - chunk.len()) {
v.push(' ' as u8);
v.push(' ' as u8);
v.push(' ' as u8);
}
}
v.push('\t' as u8);
for &byte in chunk {
if let Some(code) = code_from_offset(&offsets, l) {
if let Some(current) = current_code2 {
if current != code {
reset_color(&mut v);
current_code2 = Some(code);
if let Some(&color) = colors.get(&code) {
write_color(&mut v, color);
}
}
} else {
current_code2 = Some(code);
if let Some(&color) = colors.get(&code) {
write_color(&mut v, color);
}
}
}
if (byte >=32 && byte <= 126) || byte >= 128 {
v.push(byte);
} else {
v.push('.' as u8);
}
l = l + 1;
}
reset_color(&mut v);
v.push('\n' as u8);
i = i + chunk_size;
}
String::from_utf8_lossy(&v[..]).into_owned()
}
pub trait AsBytes {
fn as_bytes(&self) -> &[u8];
}
impl<'a> AsBytes for &'a str {
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
str::as_bytes(self)
}
}
impl AsBytes for str {
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
str::as_bytes(self)
}
}
impl<'a> AsBytes for &'a [u8] {
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
*self
}
}
impl AsBytes for [u8] {
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
self
}
}
macro_rules! array_impls {
($($N:expr)+) => {
$(
impl<'a> AsBytes for &'a [u8; $N] {
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
*self
}
}
impl AsBytes for [u8; $N] {
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
self
}
}
)+
};
}
array_impls! {
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32
}
/// indicates which parser returned an error
#[derive(Debug,PartialEq,Eq,Hash,Clone)]
pub enum ErrorKind<E=u32> {
Custom(E),
Tag,
MapRes,
MapOpt,
Alt,
IsNot,
IsA,
SeparatedList,
SeparatedNonEmptyList,
Many0,
Many1,
Count,
TakeUntilAndConsume,
TakeUntil,
TakeUntilEitherAndConsume,
TakeUntilEither,
LengthValue,
TagClosure,
Alpha,
Digit,
HexDigit,
OctDigit,
AlphaNumeric,
Space,
MultiSpace,
LengthValueFn,
Eof,
ExprOpt,
ExprRes,
CondReduce,
Switch,
TagBits,
OneOf,
NoneOf,
Char,
CrLf,
RegexpMatch,
RegexpMatches,
RegexpFind,
RegexpCapture,
RegexpCaptures,
TakeWhile1,
Complete,
Fix,
Escaped,
EscapedTransform,
TagStr,
IsNotStr,
IsAStr,
TakeWhile1Str,
NonEmpty,
ManyMN,
TakeUntilAndConsumeStr,
TakeUntilStr,
Not
}
pub fn error_to_u32<E>(e: &ErrorKind<E>) -> u32 {
match *e {
ErrorKind::Custom(_) => 0,
ErrorKind::Tag => 1,
ErrorKind::MapRes => 2,
ErrorKind::MapOpt => 3,
ErrorKind::Alt => 4,
ErrorKind::IsNot => 5,
ErrorKind::IsA => 6,
ErrorKind::SeparatedList => 7,
ErrorKind::SeparatedNonEmptyList => 8,
ErrorKind::Many1 => 9,
ErrorKind::Count => 10,
ErrorKind::TakeUntilAndConsume => 11,
ErrorKind::TakeUntil => 12,
ErrorKind::TakeUntilEitherAndConsume => 13,
ErrorKind::TakeUntilEither => 14,
ErrorKind::LengthValue => 15,
ErrorKind::TagClosure => 16,
ErrorKind::Alpha => 17,
ErrorKind::Digit => 18,
ErrorKind::AlphaNumeric => 19,
ErrorKind::Space => 20,
ErrorKind::MultiSpace => 21,
ErrorKind::LengthValueFn => 22,
ErrorKind::Eof => 23,
ErrorKind::ExprOpt => 24,
ErrorKind::ExprRes => 25,
ErrorKind::CondReduce => 26,
ErrorKind::Switch => 27,
ErrorKind::TagBits => 28,
ErrorKind::OneOf => 29,
ErrorKind::NoneOf => 30,
ErrorKind::Char => 40,
ErrorKind::CrLf => 41,
ErrorKind::RegexpMatch => 42,
ErrorKind::RegexpMatches => 43,
ErrorKind::RegexpFind => 44,
ErrorKind::RegexpCapture => 45,
ErrorKind::RegexpCaptures => 46,
ErrorKind::TakeWhile1 => 47,
ErrorKind::Complete => 48,
ErrorKind::Fix => 49,
ErrorKind::Escaped => 50,
ErrorKind::EscapedTransform => 51,
ErrorKind::TagStr => 52,
ErrorKind::IsNotStr => 53,
ErrorKind::IsAStr => 54,
ErrorKind::TakeWhile1Str => 55,
ErrorKind::NonEmpty => 56,
ErrorKind::ManyMN => 57,
ErrorKind::TakeUntilAndConsumeStr => 58,
ErrorKind::HexDigit => 59,
ErrorKind::TakeUntilStr => 60,
ErrorKind::OctDigit => 61,
ErrorKind::Many0 => 62,
ErrorKind::Not => 63,
}
}
impl<E> ErrorKind<E> {
pub fn description(&self) -> &str {
match *self {
ErrorKind::Custom(_) => "Custom error",
ErrorKind::Tag => "Tag",
ErrorKind::MapRes => "Map on Result",
ErrorKind::MapOpt => "Map on Option",
ErrorKind::Alt => "Alternative",
ErrorKind::IsNot => "IsNot",
ErrorKind::IsA => "IsA",
ErrorKind::SeparatedList => "Separated list",
ErrorKind::SeparatedNonEmptyList => "Separated non empty list",
ErrorKind::Many0 => "Many0",
ErrorKind::Many1 => "Many1",
ErrorKind::Count => "Count",
ErrorKind::TakeUntilAndConsume => "Take until and consume",
ErrorKind::TakeUntil => "Take until",
ErrorKind::TakeUntilEitherAndConsume => "Take until either and consume",
ErrorKind::TakeUntilEither => "Take until either",
ErrorKind::LengthValue => "Length followed by value",
ErrorKind::TagClosure => "Tag closure",
ErrorKind::Alpha => "Alphabetic",
ErrorKind::Digit => "Digit",
ErrorKind::AlphaNumeric => "AlphaNumeric",
ErrorKind::Space => "Space",
ErrorKind::MultiSpace => "Multiple spaces",
ErrorKind::LengthValueFn => "LengthValueFn",
ErrorKind::Eof => "End of file",
ErrorKind::ExprOpt => "Evaluate Option",
ErrorKind::ExprRes => "Evaluate Result",
ErrorKind::CondReduce => "Condition reduce",
ErrorKind::Switch => "Switch",
ErrorKind::TagBits => "Tag on bitstream",
ErrorKind::OneOf => "OneOf",
ErrorKind::NoneOf => "NoneOf",
ErrorKind::Char => "Char",
ErrorKind::CrLf => "CrLf",
ErrorKind::RegexpMatch => "RegexpMatch",
ErrorKind::RegexpMatches => "RegexpMatches",
ErrorKind::RegexpFind => "RegexpFind",
ErrorKind::RegexpCapture => "RegexpCapture",
ErrorKind::RegexpCaptures => "RegexpCaptures",
ErrorKind::TakeWhile1 => "TakeWhile1",
ErrorKind::Complete => "Complete",
ErrorKind::Fix => "Fix",
ErrorKind::Escaped => "Escaped",
ErrorKind::EscapedTransform => "EscapedTransform",
ErrorKind::TagStr => "Tag on strings",
ErrorKind::IsNotStr => "IsNot on strings",
ErrorKind::IsAStr => "IsA on strings",
ErrorKind::TakeWhile1Str => "TakeWhile1 on strings",
ErrorKind::NonEmpty => "NonEmpty",
ErrorKind::ManyMN => "Many(m, n)",
ErrorKind::TakeUntilAndConsumeStr => "Take until and consume on strings",
ErrorKind::HexDigit => "Hexadecimal Digit",
ErrorKind::TakeUntilStr => "Take until on strings",
ErrorKind::OctDigit => "Octal digit",
ErrorKind::Not => "Negation",
}
}
}

Просмотреть файл

@ -1,80 +0,0 @@
#[macro_use]
extern crate nom;
use nom::{IResult,digit, multispace};
use std::str;
use std::str::FromStr;
named!(parens<i64>, delimited!(
delimited!(opt!(multispace), tag!("("), opt!(multispace)),
expr,
delimited!(opt!(multispace), tag!(")"), opt!(multispace))
)
);
named!(factor<i64>, alt!(
map_res!(
map_res!(
delimited!(opt!(multispace), digit, opt!(multispace)),
str::from_utf8
),
FromStr::from_str
)
| parens
)
);
named!(term <i64>, chain!(
mut acc: factor ~
many0!(
alt!(
tap!(mul: preceded!(tag!("*"), factor) => acc = acc * mul) |
tap!(div: preceded!(tag!("/"), factor) => acc = acc / div)
)
),
|| { return acc }
)
);
named!(expr <i64>, chain!(
mut acc: term ~
many0!(
alt!(
tap!(add: preceded!(tag!("+"), term) => acc = acc + add) |
tap!(sub: preceded!(tag!("-"), term) => acc = acc - sub)
)
),
|| { return acc }
)
);
#[test]
fn factor_test() {
assert_eq!(factor(&b"3"[..]), IResult::Done(&b""[..], 3));
assert_eq!(factor(&b" 12"[..]), IResult::Done(&b""[..], 12));
assert_eq!(factor(&b"537 "[..]), IResult::Done(&b""[..], 537));
assert_eq!(factor(&b" 24 "[..]), IResult::Done(&b""[..], 24));
}
#[test]
fn term_test() {
assert_eq!(term(&b" 12 *2 / 3"[..]), IResult::Done(&b""[..], 8));
assert_eq!(term(&b" 2* 3 *2 *2 / 3"[..]), IResult::Done(&b""[..], 8));
assert_eq!(term(&b" 48 / 3/2"[..]), IResult::Done(&b""[..], 8));
}
#[test]
fn expr_test() {
assert_eq!(expr(&b" 1 + 2 "[..]), IResult::Done(&b""[..], 3));
assert_eq!(expr(&b" 12 + 6 - 4+ 3"[..]), IResult::Done(&b""[..], 17));
assert_eq!(expr(&b" 1 + 2*3 + 4"[..]), IResult::Done(&b""[..], 11));
}
#[test]
fn parens_test() {
assert_eq!(expr(&b" ( 2 )"[..]), IResult::Done(&b""[..], 2));
assert_eq!(expr(&b" 2* ( 3 + 4 ) "[..]), IResult::Done(&b""[..], 14));
assert_eq!(expr(&b" 2*2 / ( 5 - 1) + 3"[..]), IResult::Done(&b""[..], 4));
}

Просмотреть файл

@ -1,137 +0,0 @@
#[macro_use]
extern crate nom;
use std::fmt;
use std::fmt::{Display, Debug, Formatter};
use std::str;
use std::str::FromStr;
use nom::{IResult, digit, multispace};
pub enum Expr {
Value(i64),
Add(Box<Expr>, Box<Expr>),
Sub(Box<Expr>, Box<Expr>),
Mul(Box<Expr>, Box<Expr>),
Div(Box<Expr>, Box<Expr>),
Paren(Box<Expr>),
}
pub enum Oper {
Add,
Sub,
Mul,
Div,
}
impl Display for Expr {
fn fmt(&self, format: &mut Formatter) -> fmt::Result {
use self::Expr::*;
match *self {
Value(val) => write!(format, "{}", val),
Add(ref left, ref right) => write!(format, "{} + {}", left, right),
Sub(ref left, ref right) => write!(format, "{} - {}", left, right),
Mul(ref left, ref right) => write!(format, "{} * {}", left, right),
Div(ref left, ref right) => write!(format, "{} / {}", left, right),
Paren(ref expr) => write!(format, "({})", expr),
}
}
}
impl Debug for Expr {
fn fmt(&self, format: &mut Formatter) -> fmt::Result {
use self::Expr::*;
match *self {
Value(val) => write!(format, "{}", val),
Add(ref left, ref right) => write!(format, "({:?} + {:?})", left, right),
Sub(ref left, ref right) => write!(format, "({:?} - {:?})", left, right),
Mul(ref left, ref right) => write!(format, "({:?} * {:?})", left, right),
Div(ref left, ref right) => write!(format, "({:?} / {:?})", left, right),
Paren(ref expr) => write!(format, "[{:?}]", expr),
}
}
}
named!(parens< Expr >, delimited!(
delimited!(opt!(multispace), tag!("("), opt!(multispace)),
map!(map!(expr, Box::new), Expr::Paren),
delimited!(opt!(multispace), tag!(")"), opt!(multispace))
)
);
named!(factor< Expr >, alt_complete!(
map!(
map_res!(
map_res!(
delimited!(opt!(multispace), digit, opt!(multispace)),
str::from_utf8
),
FromStr::from_str
),
Expr::Value)
| parens
)
);
fn fold_exprs(initial: Expr, remainder: Vec<(Oper, Expr)>) -> Expr {
remainder.into_iter().fold(initial, |acc, pair| {
let (oper, expr) = pair;
match oper {
Oper::Add => Expr::Add(Box::new(acc), Box::new(expr)),
Oper::Sub => Expr::Sub(Box::new(acc), Box::new(expr)),
Oper::Mul => Expr::Mul(Box::new(acc), Box::new(expr)),
Oper::Div => Expr::Div(Box::new(acc), Box::new(expr)),
}
})
}
named!(term< Expr >, chain!(
initial: factor ~
remainder: many0!(
alt!(
chain!(tag!("*") ~ mul: factor, || { (Oper::Mul, mul) }) |
chain!(tag!("/") ~ div: factor, || { (Oper::Div, div) })
)
),
|| fold_exprs(initial, remainder))
);
named!(expr< Expr >, chain!(
initial: term ~
remainder: many0!(
alt!(
chain!(tag!("+") ~ add: term, || { (Oper::Add, add) }) |
chain!(tag!("-") ~ sub: term, || { (Oper::Sub, sub) })
)
),
|| fold_exprs(initial, remainder))
);
#[test]
fn factor_test() {
assert_eq!(factor(&b" 3 "[..]).map(|x| format!("{:?}", x)),
IResult::Done(&b""[..], String::from("3")));
}
#[test]
fn term_test() {
assert_eq!(term(&b" 3 * 5 "[..]).map(|x| format!("{:?}", x)),
IResult::Done(&b""[..], String::from("(3 * 5)")));
}
#[test]
fn expr_test() {
assert_eq!(expr(&b" 1 + 2 * 3 "[..]).map(|x| format!("{:?}", x)),
IResult::Done(&b""[..], String::from("(1 + (2 * 3))")));
assert_eq!(expr(&b" 1 + 2 * 3 / 4 - 5 "[..]).map(|x| format!("{:?}", x)),
IResult::Done(&b""[..], String::from("((1 + ((2 * 3) / 4)) - 5)")));
assert_eq!(expr(&b" 72 / 2 / 3 "[..]).map(|x| format!("{:?}", x)),
IResult::Done(&b""[..], String::from("((72 / 2) / 3)")));
}
#[test]
fn parens_test() {
assert_eq!(expr(&b" ( 1 + 2 ) * 3 "[..]).map(|x| format!("{:?}", x)),
IResult::Done(&b""[..], String::from("([(1 + 2)] * 3)")));
}

Просмотреть файл

@ -1,140 +0,0 @@
/// this file tests a different backtracking behaviour. With the current
/// `error!` macro, an early return is done in the current function, but
/// backtracking continues normally outside of that function.
///
/// The solution here wraps `IResult` in a `Result`: a `Ok` indicates usual
/// backtracking, `Err` indicates that we must "cut".
#[macro_use]
extern crate nom;
macro_rules! n (
($name:ident( $i:ty ) -> $o:ty, $submac:ident!( $($args:tt)* )) => (
fn $name( i: $i ) -> std::result::Result<nom::IResult<$i,$o,u32>, nom::Err<$i, u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
($name:ident<$i:ty,$o:ty,$e:ty>, $submac:ident!( $($args:tt)* )) => (
fn $name( i: $i ) -> std::result::Result<nom::IResult<$i, $o, $e>, nom::Err<$i, $e>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
($name:ident<$i:ty,$o:ty>, $submac:ident!( $($args:tt)* )) => (
fn $name( i: $i ) -> std::result::Result<nom::IResult<$i, $o, u32>, nom::Err<$i, u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
($name:ident<$o:ty>, $submac:ident!( $($args:tt)* )) => (
fn $name<'a>( i: &'a[u8] ) -> std::result::Result<nom::IResult<&'a [u8], $o, u32>, nom::Err<&'a [u8], u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
($name:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( i: &[u8] ) -> std::result::Result<nom::IResult<&[u8], &[u8], u32>, nom::Err<&[u8], u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
(pub $name:ident( $i:ty ) -> $o:ty, $submac:ident!( $($args:tt)* )) => (
pub fn $name( i: $i ) -> std::result::Result<nom::IResult<$i,$o, u32>, nom::Err<$i, u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
(pub $name:ident<$i:ty,$o:ty,$e:ty>, $submac:ident!( $($args:tt)* )) => (
pub fn $name( i: $i ) -> std::result::Result<nom::IResult<$i, $o, $e>, nom::Err<$i, $e>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
(pub $name:ident<$i:ty,$o:ty>, $submac:ident!( $($args:tt)* )) => (
pub fn $name( i: $i ) -> std::result::Result<nom::IResult<$i, $o, u32>, nom::Err<$i, u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
(pub $name:ident<$o:ty>, $submac:ident!( $($args:tt)* )) => (
pub fn $name( i: &[u8] ) -> std::result::Result<nom::IResult<&[u8], $o, u32>, nom::Err<&[u8], u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
(pub $name:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name<'a>( i: &'a [u8] ) -> std::result::Result<nom::IResult<&[u8], &[u8], u32>, nom::Err<&[u8], u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
);
macro_rules! cut (
($i:expr, $code:expr, $submac:ident!( $($args:tt)* )) => (
{
let cl = || {
Ok($submac!($i, $($args)*))
};
match cl() {
std::result::Result::Ok(nom::IResult::Incomplete(x)) => nom::IResult::Incomplete(x),
std::result::Result::Ok(nom::IResult::Done(i, o)) => nom::IResult::Done(i, o),
std::result::Result::Ok(nom::IResult::Error(e)) | std::result::Result::Err(e) => {
return std::result::Result::Err(nom::Err::NodePosition($code, $i, Box::new(e)))
}
}
}
);
($i:expr, $code:expr, $f:expr) => (
cut!($i, $code, call!($f));
);
);
macro_rules! c (
($i:expr, $f:expr) => (
{
match $f($i) {
std::result::Result::Ok(nom::IResult::Incomplete(x)) => nom::IResult::Incomplete(x),
std::result::Result::Ok(nom::IResult::Done(i, o)) => nom::IResult::Done(i, o),
std::result::Result::Ok(nom::IResult::Error(e)) => nom::IResult::Error(e),
std::result::Result::Err(e) => {
return std::result::Result::Err(e)
}
}
}
);
);
n!(pub foo< bool >,
chain!(
tag!("a") ~
cut!(nom::ErrorKind::Custom(42),dbg_dmp!(tag!("b"))) ,
|| { true }
)
);
n!(pub foos< Vec<bool> >,
delimited!(
tag!("("),
many0!(c!(foo)),
tag!(")")
)
);
#[test]
fn test_ok() {
let r = foos(b"(abab)");
println!("result: {:?}", r);
match r {
Ok(nom::IResult::Done(_,result)) => assert_eq!(result,vec![true,true]),
res => panic!("Oops {:?}.",res)
}
}
#[test]
fn test_err() {
let input = b"(ac)";
let r = foos(&input[..]);
println!("result: {:?}", r);
match r {
//Ok(nom::IResult::Error(nom::Err::Position(kind,_))) => assert_eq!(kind,nom::ErrorKind::Custom(42)),
Err(nom::Err::NodePosition(kind, position, _)) => {
assert_eq!(kind, nom::ErrorKind::Custom(42));
assert_eq!(position, &input[2..]);
}
res => panic!("Oops, {:?}",res)
}
}

234
third_party/rust/nom-1.2.4/nom/tests/ini.rs поставляемый
Просмотреть файл

@ -1,234 +0,0 @@
#[macro_use]
extern crate nom;
use nom::{IResult,not_line_ending, space, alphanumeric, multispace};
use std::str;
use std::collections::HashMap;
named!(category<&str>, map_res!(
terminated!(
delimited!(tag!("["), take_until!("]"), tag!("]")),
opt!(multispace)
),
str::from_utf8
));
named!(key_value <&[u8],(&str,&str)>,
chain!(
key: map_res!(alphanumeric, std::str::from_utf8) ~
space? ~
tag!("=") ~
space? ~
val: map_res!(
take_until_either!("\n;"),
str::from_utf8
) ~
space? ~
chain!(
tag!(";") ~
not_line_ending ,
||{}
) ? ~
multispace? ,
||{(key, val)}
)
);
named!(keys_and_values_aggregator<&[u8], Vec<(&str,&str)> >, many0!(key_value));
fn keys_and_values(input:&[u8]) -> IResult<&[u8], HashMap<&str, &str> > {
let mut h: HashMap<&str, &str> = HashMap::new();
match keys_and_values_aggregator(input) {
IResult::Done(i,tuple_vec) => {
for &(k,v) in &tuple_vec {
h.insert(k, v);
}
IResult::Done(i, h)
},
IResult::Incomplete(a) => IResult::Incomplete(a),
IResult::Error(a) => IResult::Error(a)
}
}
named!(category_and_keys<&[u8],(&str,HashMap<&str,&str>)>,
chain!(
category: category ~
keys: keys_and_values ,
move ||{(category, keys)}
)
);
named!(categories_aggregator<&[u8], Vec<(&str, HashMap<&str,&str>)> >, many0!(category_and_keys));
fn categories(input: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str> > > {
let mut h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
match categories_aggregator(input) {
IResult::Done(i,tuple_vec) => {
for &(k,ref v) in &tuple_vec {
h.insert(k, v.clone());
}
IResult::Done(i, h)
},
IResult::Incomplete(a) => IResult::Incomplete(a),
IResult::Error(a) => IResult::Error(a)
}
}
#[test]
fn parse_category_test() {
let ini_file = &b"[category]
parameter=value
key = value2"[..];
let ini_without_category = &b"parameter=value
key = value2"[..];
let res = category(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_category, "category"));
}
#[test]
fn parse_key_value_test() {
let ini_file = &b"parameter=value
key = value2"[..];
let ini_without_key_value = &b"key = value2"[..];
let res = key_value(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}
#[test]
fn parse_key_value_with_space_test() {
let ini_file = &b"parameter = value
key = value2"[..];
let ini_without_key_value = &b"key = value2"[..];
let res = key_value(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}
#[test]
fn parse_key_value_with_comment_test() {
let ini_file = &b"parameter=value;abc
key = value2"[..];
let ini_without_key_value = &b"key = value2"[..];
let res = key_value(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}
#[test]
fn parse_multiple_keys_and_values_test() {
let ini_file = &b"parameter=value;abc
key = value2
[category]"[..];
let ini_without_key_value = &b"[category]"[..];
let res = keys_and_values(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
_ => println!("error")
}
let mut expected: HashMap<&str, &str> = HashMap::new();
expected.insert("parameter", "value");
expected.insert("key", "value2");
assert_eq!(res, IResult::Done(ini_without_key_value, expected));
}
#[test]
fn parse_category_then_multiple_keys_and_values_test() {
//FIXME: there can be an empty line or a comment line after a category
let ini_file = &b"[abcd]
parameter=value;abc
key = value2
[category]"[..];
let ini_after_parser = &b"[category]"[..];
let res = category_and_keys(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
_ => println!("error")
}
let mut expected_h: HashMap<&str, &str> = HashMap::new();
expected_h.insert("parameter", "value");
expected_h.insert("key", "value2");
assert_eq!(res, IResult::Done(ini_after_parser, ("abcd", expected_h)));
}
#[test]
fn parse_multiple_categories_test() {
let ini_file = &b"[abcd]
parameter=value;abc
key = value2
[category]
parameter3=value3
key4 = value4
"[..];
let ini_after_parser = &b""[..];
let res = categories(ini_file);
//println!("{:?}", res);
match res {
IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
_ => println!("error")
}
let mut expected_1: HashMap<&str, &str> = HashMap::new();
expected_1.insert("parameter", "value");
expected_1.insert("key", "value2");
let mut expected_2: HashMap<&str, &str> = HashMap::new();
expected_2.insert("parameter3", "value3");
expected_2.insert("key4", "value4");
let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
expected_h.insert("abcd", expected_1);
expected_h.insert("category", expected_2);
assert_eq!(res, IResult::Done(ini_after_parser, expected_h));
}

Просмотреть файл

@ -1,251 +0,0 @@
#[macro_use]
extern crate nom;
use nom::IResult;
use std::collections::HashMap;
fn is_alphabetic(chr:char) -> bool {
(chr as u8 >= 0x41 && chr as u8 <= 0x5A) || (chr as u8 >= 0x61 && chr as u8 <= 0x7A)
}
fn is_digit(chr: char) -> bool {
chr as u8 >= 0x30 && chr as u8 <= 0x39
}
fn is_alphanumeric(chr: char) -> bool {
is_alphabetic(chr) || is_digit(chr)
}
fn is_space(chr:char) -> bool {
chr == ' ' || chr == '\t'
}
fn is_line_ending_or_comment(chr:char) -> bool {
chr == ';' || chr == '\n'
}
named!(alphanumeric<&str,&str>, take_while_s!(is_alphanumeric));
named!(not_line_ending<&str,&str>, is_not_s!("\r\n"));
named!(space<&str,&str>, take_while_s!(is_space));
named!(space_or_line_ending<&str,&str>, is_a_s!(" \r\n"));
fn right_bracket(c:char) -> bool {
c == ']'
}
named!(category <&str, &str>,
chain!(
tag_s!("[") ~
name: take_till_s!(right_bracket) ~
tag_s!("]") ~
space_or_line_ending? ,
||{ name }
)
);
named!(key_value <&str,(&str,&str)>,
chain!(
key: alphanumeric ~
space? ~
tag_s!("=") ~
space? ~
val: take_till_s!(is_line_ending_or_comment) ~
space? ~
pair!(tag_s!(";"), not_line_ending)? ~
space_or_line_ending? ,
||{(key, val)}
)
);
named!(keys_and_values_aggregator<&str, Vec<(&str,&str)> >, many0!(key_value));
fn keys_and_values(input:&str) -> IResult<&str, HashMap<&str, &str> > {
let mut h: HashMap<&str, &str> = HashMap::new();
match keys_and_values_aggregator(input) {
IResult::Done(i,tuple_vec) => {
for &(k,v) in &tuple_vec {
h.insert(k, v);
}
IResult::Done(i, h)
},
IResult::Incomplete(a) => IResult::Incomplete(a),
IResult::Error(a) => IResult::Error(a)
}
}
named!(category_and_keys<&str,(&str,HashMap<&str,&str>)>,
pair!(category, keys_and_values)
);
named!(categories_aggregator<&str, Vec<(&str, HashMap<&str,&str>)> >, many0!(category_and_keys));
fn categories(input: &str) -> IResult<&str, HashMap<&str, HashMap<&str, &str> > > {
let mut h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
match categories_aggregator(input) {
IResult::Done(i,tuple_vec) => {
for &(k,ref v) in &tuple_vec {
h.insert(k, v.clone());
}
IResult::Done(i, h)
},
IResult::Incomplete(a) => IResult::Incomplete(a),
IResult::Error(a) => IResult::Error(a)
}
}
#[test]
fn parse_category_test() {
let ini_file = "[category]
parameter=value
key = value2";
let ini_without_category = "parameter=value
key = value2";
let res = category(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, o) => println!("i: {} | o: {:?}", i, o),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_category, "category"));
}
#[test]
fn parse_key_value_test() {
let ini_file = "parameter=value
key = value2";
let ini_without_key_value = "key = value2";
let res = key_value(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, (o1, o2)) => println!("i: {} | o: ({:?},{:?})", i, o1, o2),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}
#[test]
fn parse_key_value_with_space_test() {
let ini_file = "parameter = value
key = value2";
let ini_without_key_value = "key = value2";
let res = key_value(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, (o1, o2)) => println!("i: {} | o: ({:?},{:?})", i, o1, o2),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}
#[test]
fn parse_key_value_with_comment_test() {
let ini_file = "parameter=value;abc
key = value2";
let ini_without_key_value = "key = value2";
let res = key_value(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, (o1, o2)) => println!("i: {} | o: ({:?},{:?})", i, o1, o2),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}
#[test]
fn parse_multiple_keys_and_values_test() {
let ini_file = "parameter=value;abc
key = value2
[category]";
let ini_without_key_value = "[category]";
let res = keys_and_values(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, ref o) => println!("i: {} | o: {:?}", i, o),
_ => println!("error")
}
let mut expected: HashMap<&str, &str> = HashMap::new();
expected.insert("parameter", "value");
expected.insert("key", "value2");
assert_eq!(res, IResult::Done(ini_without_key_value, expected));
}
#[test]
fn parse_category_then_multiple_keys_and_values_test() {
//FIXME: there can be an empty line or a comment line after a category
let ini_file = "[abcd]
parameter=value;abc
key = value2
[category]";
let ini_after_parser = "[category]";
let res = category_and_keys(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, ref o) => println!("i: {} | o: {:?}", i, o),
_ => println!("error")
}
let mut expected_h: HashMap<&str, &str> = HashMap::new();
expected_h.insert("parameter", "value");
expected_h.insert("key", "value2");
assert_eq!(res, IResult::Done(ini_after_parser, ("abcd", expected_h)));
}
#[test]
fn parse_multiple_categories_test() {
let ini_file = "[abcd]
parameter=value;abc
key = value2
[category]
parameter3=value3
key4 = value4
";
let res = categories(ini_file);
//println!("{:?}", res);
match res {
IResult::Done(i, ref o) => println!("i: {} | o: {:?}", i, o),
_ => println!("error")
}
let mut expected_1: HashMap<&str, &str> = HashMap::new();
expected_1.insert("parameter", "value");
expected_1.insert("key", "value2");
let mut expected_2: HashMap<&str, &str> = HashMap::new();
expected_2.insert("parameter3", "value3");
expected_2.insert("key4", "value4");
let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
expected_h.insert("abcd", expected_1);
expected_h.insert("category", expected_2);
assert_eq!(res, IResult::Done("", expected_h));
}

131
third_party/rust/nom-1.2.4/nom/tests/issues.rs поставляемый
Просмотреть файл

@ -1,131 +0,0 @@
//#![feature(trace_macros)]
#[macro_use]
extern crate nom;
use nom::{IResult,Needed,HexDisplay,space,digit,be_u16};
use std::str;
#[allow(dead_code)]
struct Range {
start: char,
end: char
}
pub fn take_char(input: &[u8]) -> IResult<&[u8], char> {
if input.len() > 0 {
IResult::Done(&input[1..], input[0] as char)
} else {
IResult::Incomplete(Needed::Size(1))
}
}
//trace_macros!(true);
#[allow(dead_code)]
named!(range<&[u8], Range>,
alt!(
chain!(
start: take_char ~
tag!("-") ~
end: take_char,
|| {
Range {
start: start,
end: end,
}
}
) |
map!(
take_char,
|c| {
Range {
start: c,
end: c,
}
}
)
)
);
#[allow(dead_code)]
named!(literal<&[u8], Vec<char> >,
map!(
many1!(take_char),
|cs| {
cs
}
)
);
#[test]
fn issue_58() {
range(&b"abcd"[..]);
literal(&b"abcd"[..]);
}
//trace_macros!(false);
named!(parse_ints< Vec<i32> >, many0!(spaces_or_int));
fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32>{
println!("{}", input.to_hex(8));
chain!(input,
opt!(space) ~
x: digit,
|| {
println!("x: {:?}", x);
let result = str::from_utf8(x).unwrap();
println!("Result: {}", result);
println!("int is empty?: {}", x.is_empty());
match result.parse(){
Ok(i) => i,
Err(_) => panic!("UH OH! NOT A DIGIT!")
}
}
)
}
#[test]
fn issue_142(){
let subject = parse_ints(&b"12 34 5689"[..]);
let expected = IResult::Done(&b""[..], vec![12, 34, 5689]);
assert_eq!(subject, expected);
let subject = parse_ints(&b"12 34 5689 "[..]);
let expected = IResult::Done(&b" "[..], vec![12, 34, 5689]);
assert_eq!(subject, expected)
}
#[test]
fn usize_length_bytes_issue(){
length_bytes!(b"012346", be_u16);
}
/*
DOES NOT COMPILE
#[test]
fn issue_152() {
named!(take4, take!(4));
named!(xyz, tag!("XYZ"));
named!(abc, tag!("abc"));
named!(sw,
switch!(take4,
b"abcd" => xyz |
b"efgh" => abc
)
);
}
*/
#[test]
fn take_till_issue() {
named!(nothing,
take_till!(call!(|_| true))
);
assert_eq!(nothing(b""), IResult::Done(&b""[..], &b""[..]));
assert_eq!(nothing(b"abc"), IResult::Done(&b"abc"[..], &b""[..]));
}

531
third_party/rust/nom-1.2.4/nom/tests/mp4.rs поставляемый
Просмотреть файл

@ -1,531 +0,0 @@
#![cfg(feature = "stream")]
#![allow(dead_code)]
#[macro_use]
extern crate nom;
use nom::{HexDisplay,Needed,IResult,be_u16,be_u32,be_u64,be_f32,ErrorKind};
use nom::{Consumer,ConsumerState,Move,Input,Producer,FileProducer,FileProducerState};
use nom::IResult::*;
use nom::Err::*;
use std::str;
use std::io::SeekFrom;
fn mp4_box(input:&[u8]) -> IResult<&[u8], &[u8]> {
match be_u32(input) {
Done(i, offset) => {
let sz: usize = offset as usize;
if i.len() >= sz - 4 {
Done(&i[(sz-4)..], &i[0..(sz-4)])
} else {
Incomplete(Needed::Size(offset as usize + 4))
}
}
Error(e) => Error(e),
Incomplete(e) => Incomplete(e)
}
}
#[derive(PartialEq,Eq,Debug)]
struct FileType<'a> {
major_brand: &'a str,
major_brand_version: &'a [u8],
compatible_brands: Vec<&'a str>
}
#[allow(non_snake_case)]
#[derive(Debug,Clone)]
pub struct Mvhd32 {
version_flags: u32, // actually:
// version: u8,
// flags: u24 // 3 bytes
created_date: u32,
modified_date: u32,
scale: u32,
duration: u32,
speed: f32,
volume: u16, // actually a 2 bytes decimal
/* 10 bytes reserved */
scaleA: f32,
rotateB: f32,
angleU: f32,
rotateC: f32,
scaleD: f32,
angleV: f32,
positionX: f32,
positionY: f32,
scaleW: f32,
preview: u64,
poster: u32,
selection: u64,
current_time: u32,
track_id: u32
}
#[allow(non_snake_case)]
#[derive(Debug,Clone)]
pub struct Mvhd64 {
version_flags: u32, // actually:
// version: u8,
// flags: u24 // 3 bytes
created_date: u64,
modified_date: u64,
scale: u32,
duration: u64,
speed: f32,
volume: u16, // actually a 2 bytes decimal
/* 10 bytes reserved */
scaleA: f32,
rotateB: f32,
angleU: f32,
rotateC: f32,
scaleD: f32,
angleV: f32,
positionX: f32,
positionY: f32,
scaleW: f32,
preview: u64,
poster: u32,
selection: u64,
current_time: u32,
track_id: u32
}
#[allow(non_snake_case)]
named!(mvhd32 <&[u8], MvhdBox>,
chain!(
version_flags: be_u32 ~
created_date: be_u32 ~
modified_date: be_u32 ~
scale: be_u32 ~
duration: be_u32 ~
speed: be_f32 ~
volume: be_u16 ~ // actually a 2 bytes decimal
take!(10) ~
scale_a: be_f32 ~
rotate_b: be_f32 ~
angle_u: be_f32 ~
rotate_c: be_f32 ~
scale_d: be_f32 ~
angle_v: be_f32 ~
position_x: be_f32 ~
position_y: be_f32 ~
scale_w: be_f32 ~
preview: be_u64 ~
poster: be_u32 ~
selection: be_u64 ~
current_time: be_u32 ~
track_id: be_u32,
||{
MvhdBox::M32(Mvhd32 {
version_flags: version_flags,
created_date: created_date,
modified_date: modified_date,
scale: scale,
duration: duration,
speed: speed,
volume: volume,
scaleA: scale_a,
rotateB: rotate_b,
angleU: angle_u,
rotateC: rotate_c,
scaleD: scale_d,
angleV: angle_v,
positionX: position_x,
positionY: position_y,
scaleW: scale_w,
preview: preview,
poster: poster,
selection: selection,
current_time: current_time,
track_id: track_id
})
}
)
);
#[allow(non_snake_case)]
named!(mvhd64 <&[u8], MvhdBox>,
chain!(
version_flags: be_u32 ~
created_date: be_u64 ~
modified_date: be_u64 ~
scale: be_u32 ~
duration: be_u64 ~
speed: be_f32 ~
volume: be_u16 ~ // actually a 2 bytes decimal
take!(10) ~
scale_a: be_f32 ~
rotate_b: be_f32 ~
angle_u: be_f32 ~
rotate_c: be_f32 ~
scale_d: be_f32 ~
angle_v: be_f32 ~
position_x: be_f32 ~
position_y: be_f32 ~
scale_w: be_f32 ~
preview: be_u64 ~
poster: be_u32 ~
selection: be_u64 ~
current_time: be_u32 ~
track_id: be_u32,
||{
MvhdBox::M64(Mvhd64 {
version_flags: version_flags,
created_date: created_date,
modified_date: modified_date,
scale: scale,
duration: duration,
speed: speed,
volume: volume,
scaleA: scale_a,
rotateB: rotate_b,
angleU: angle_u,
rotateC: rotate_c,
scaleD: scale_d,
angleV: angle_v,
positionX: position_x,
positionY: position_y,
scaleW: scale_w,
preview: preview,
poster: poster,
selection: selection,
current_time: current_time,
track_id: track_id
})
}
)
);
#[derive(Debug,Clone)]
pub enum MvhdBox {
M32(Mvhd32),
M64(Mvhd64)
}
#[derive(Debug,Clone)]
pub enum MoovBox {
Mdra,
Dref,
Cmov,
Rmra,
Iods,
Mvhd(MvhdBox),
Clip,
Trak,
Udta
}
#[derive(Debug)]
enum MP4BoxType {
Ftyp,
Moov,
Mdat,
Free,
Skip,
Wide,
Mdra,
Dref,
Cmov,
Rmra,
Iods,
Mvhd,
Clip,
Trak,
Udta,
Unknown
}
#[derive(Debug)]
struct MP4BoxHeader {
length: u32,
tag: MP4BoxType
}
named!(brand_name<&[u8],&str>, map_res!(take!(4), str::from_utf8));
named!(filetype_parser<&[u8], FileType>,
chain!(
m: brand_name ~
v: take!(4) ~
c: many0!(brand_name) ,
||{ FileType{ major_brand: m, major_brand_version:v, compatible_brands: c } }
)
);
fn mvhd_box(input:&[u8]) -> IResult<&[u8],MvhdBox> {
let res = if input.len() < 100 {
Incomplete(Needed::Size(100))
} else if input.len() == 100 {
mvhd32(input)
} else if input.len() == 112 {
mvhd64(input)
} else {
Error(Position(ErrorKind::Custom(32),input))
};
println!("res: {:?}", res);
res
}
fn unknown_box_type(input:&[u8]) -> IResult<&[u8], MP4BoxType> {
Done(input, MP4BoxType::Unknown)
}
//named!(box_type<&[u8], MP4BoxType>,
fn box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType, u32> {
alt!(input,
tag!("ftyp") => { |_| MP4BoxType::Ftyp } |
tag!("moov") => { |_| MP4BoxType::Moov } |
tag!("mdat") => { |_| MP4BoxType::Mdat } |
tag!("free") => { |_| MP4BoxType::Free } |
tag!("skip") => { |_| MP4BoxType::Skip } |
tag!("wide") => { |_| MP4BoxType::Wide } |
unknown_box_type
)
}
// warning, an alt combinator with 9 branches containing a tag combinator
// can make the compilation very slow. Use functions as sub parsers,
// or split into multiple alt! parsers if it gets slow
named!(moov_type<&[u8], MP4BoxType>,
alt!(
tag!("mdra") => { |_| MP4BoxType::Mdra } |
tag!("dref") => { |_| MP4BoxType::Dref } |
tag!("cmov") => { |_| MP4BoxType::Cmov } |
tag!("rmra") => { |_| MP4BoxType::Rmra } |
tag!("iods") => { |_| MP4BoxType::Iods } |
tag!("mvhd") => { |_| MP4BoxType::Mvhd } |
tag!("clip") => { |_| MP4BoxType::Clip } |
tag!("trak") => { |_| MP4BoxType::Trak } |
tag!("udta") => { |_| MP4BoxType::Udta }
)
);
named!(box_header<&[u8],MP4BoxHeader>,
chain!(
length: be_u32 ~
tag: box_type ,
|| { MP4BoxHeader{ length: length, tag: tag} }
)
);
named!(moov_header<&[u8],MP4BoxHeader>,
chain!(
length: be_u32 ~
tag: moov_type ,
|| { MP4BoxHeader{ length: length, tag: tag} }
)
);
#[derive(Debug,PartialEq,Eq)]
enum MP4State {
Main,
Moov,
Mvhd(usize)
}
pub struct MP4Consumer {
state: MP4State,
moov_bytes: usize,
c_state: ConsumerState<(), (), Move>
}
impl MP4Consumer {
fn new() -> MP4Consumer {
MP4Consumer { state: MP4State::Main, moov_bytes: 0, c_state: ConsumerState::Continue(Move::Consume(0)) }
}
fn consume_main(&mut self, input: Input<&[u8]>) -> ConsumerState<(), (), Move> {
//println!("\nparsing box header:\n{}", input.to_hex(8));
match input {
Input::Eof(None) => ConsumerState::Done(Move::Consume(0), ()),
Input::Empty => ConsumerState::Continue(Move::Consume(0)),
Input::Element(sl) | Input::Eof(Some(sl)) => {
match box_header(sl) {
Done(i, header) => {
match header.tag {
MP4BoxType::Ftyp => {
println!("-> FTYP");
match filetype_parser(&i[0..(header.length as usize - 8)]) {
Done(rest, filetype_header) => {
println!("filetype header: {:?}", filetype_header);
//return ConsumerState::Await(header.length as usize, header.length as usize - 8);
return ConsumerState::Continue(Move::Consume(sl.offset(rest)));
}
Error(a) => {
println!("ftyp parsing error: {:?}", a);
assert!(false);
return ConsumerState::Error(());
},
Incomplete(n) => {
println!("ftyp incomplete -> await: {}", sl.len());
return ConsumerState::Continue(Move::Await(n));
//return ConsumerState::Await(0, input.len() + 100);
}
}
},
MP4BoxType::Moov => {
println!("-> MOOV");
self.state = MP4State::Moov;
self.moov_bytes = header.length as usize - 8;
return ConsumerState::Continue(Move::Consume(sl.offset(i)));
},
MP4BoxType::Mdat => println!("-> MDAT"),
MP4BoxType::Free => println!("-> FREE"),
MP4BoxType::Skip => println!("-> SKIP"),
MP4BoxType::Wide => println!("-> WIDE"),
MP4BoxType::Unknown => {
println!("-> UNKNOWN");
println!("bytes:\n{}", (sl).to_hex(8));
//return ConsumerState::Continue(Move::Consume(sl.offset(i)));
},
_ => { println!("invalid"); return ConsumerState::Error(())}
}
return ConsumerState::Continue(Move::Seek(SeekFrom::Current((header.length) as i64)))
},
Error(a) => {
println!("mp4 parsing error: {:?}", a);
assert!(false);
return ConsumerState::Error(());
},
Incomplete(i) => {
// FIXME: incomplete should send the required size
println!("mp4 incomplete -> await: {}", sl.len());
return ConsumerState::Continue(Move::Await(i));
}
}
}
}
}
fn consume_moov(&mut self, input: Input<&[u8]>) -> ConsumerState<(), (), Move> {
//println!("\nparsing moov box(remaining {} bytes):\n{}", self.moov_bytes, input.to_hex(8));
match input {
Input::Eof(None) => return ConsumerState::Error(()),
Input::Empty => return ConsumerState::Continue(Move::Consume(0)),
Input::Element(sl) | Input::Eof(Some(sl)) => {
if self.moov_bytes == 0 {
//println!("finished parsing moov atom, continuing with main parser");
self.state = MP4State::Main;
return ConsumerState::Continue(Move::Consume(0));
}
match moov_header(sl) {
Done(i, header) => {
match header.tag {
MP4BoxType::Mvhd => {
println!("-> MVHD");
self.state = MP4State::Mvhd(header.length as usize - 8);
// TODO: check for overflow here
self.moov_bytes = self.moov_bytes - (sl.len() - i.len());
println!("remaining moov_bytes: {}", self.moov_bytes);
return ConsumerState::Continue(Move::Consume(sl.offset(i)));
},
MP4BoxType::Wide => println!("-> WIDE"),
MP4BoxType::Mdra => println!("-> MDRA"),
MP4BoxType::Dref => println!("-> DREF"),
MP4BoxType::Cmov => println!("-> CMOV"),
MP4BoxType::Rmra => println!("-> RMRA"),
MP4BoxType::Iods => println!("-> IODS"),
MP4BoxType::Clip => println!("-> CLIP"),
MP4BoxType::Trak => println!("-> TRAK"),
MP4BoxType::Udta => println!("-> UDTA"),
MP4BoxType::Unknown => println!("-> MOOV UNKNOWN"),
_ => { println!("invalid header here: {:?}", header.tag); return ConsumerState::Error(());}
};
// TODO: check for overflow here
self.moov_bytes = self.moov_bytes - header.length as usize;
println!("remaining moov_bytes: {}", self.moov_bytes);
return ConsumerState::Continue(Move::Seek(SeekFrom::Current((header.length) as i64)))
},
Error(a) => {
println!("moov parsing error: {:?}", a);
println!("data:\n{}", sl.to_hex(8));
assert!(false);
return ConsumerState::Error(());
},
Incomplete(i) => {
println!("moov incomplete -> await: {}", sl.len());
return ConsumerState::Continue(Move::Await(i));
}
}
}
};
}
}
consumer_from_parser!(MvhdConsumer<MvhdBox>, mvhd_box);
impl<'a> Consumer<&'a[u8], (), (), Move> for MP4Consumer {
fn handle(&mut self, input: Input<&[u8]>) -> &ConsumerState<(), (), Move> {
match self.state {
MP4State::Main => {
self.c_state = self.consume_main(input);
},
MP4State::Moov => {
self.c_state = self.consume_moov(input);
},
MP4State::Mvhd(sz) => {
match input {
Input::Eof(None) => self.c_state = ConsumerState::Error(()),
Input::Empty => self.c_state = ConsumerState::Continue(Move::Consume(0)),
Input::Element(sl) | Input::Eof(Some(sl)) => {
let mut c = MvhdConsumer{ state:ConsumerState::Continue(Move::Consume(0)) };
self.c_state = c.handle(Input::Element(&sl[..sz])).flat_map(|m, _| {
self.state = MP4State::Moov;
ConsumerState::Continue(m)
});
println!("found mvhd?: {:?}", c.state());
match self.c_state {
ConsumerState::Continue(Move::Consume(sz)) => self.moov_bytes = self.moov_bytes - sz,
ConsumerState::Continue(Move::Seek(SeekFrom::Current(sz))) => self.moov_bytes = self.moov_bytes - (sz as usize),
_ => ()
};
println!("remaining moov_bytes: {}", self.moov_bytes);
}
}
}
};
&self.c_state
}
fn state(&self) -> &ConsumerState<(), (), Move> {
&self.c_state
}
}
#[allow(unused_must_use)]
fn explore_mp4_file(filename: &str) {
let mut p = FileProducer::new(filename, 400).unwrap();
let mut c = MP4Consumer{state: MP4State::Main, moov_bytes: 0, c_state: ConsumerState::Continue(Move::Consume(0))};
//c.run(&mut p);
while let &ConsumerState::Continue(mv) = p.apply(&mut c) {
println!("move: {:?}", mv);
}
println!("last consumer state: {:?} | last state: {:?}", c.c_state, c.state);
if let ConsumerState::Done(Move::Consume(0), ()) = c.c_state {
println!("consumer state ok");
} else {
assert!(false, "consumer should have reached Done state");
}
assert_eq!(c.state, MP4State::Main);
assert_eq!(p.state(), FileProducerState::Eof);
//assert!(false);
}
#[test]
fn small_test() {
explore_mp4_file("assets/small.mp4");
}
#[test]
fn big_bunny_test() {
explore_mp4_file("assets/bigbuckbunny.mp4");
}

160
third_party/rust/nom-1.2.4/nom/tests/omnom.rs поставляемый
Просмотреть файл

@ -1,160 +0,0 @@
#![cfg(feature = "stream")]
#[macro_use]
extern crate nom;
use nom::{Producer,Consumer,ConsumerState,Input,Move,MemProducer,IResult,HexDisplay};
#[derive(PartialEq,Eq,Debug)]
enum State {
Beginning,
Middle,
End,
Done,
Error
}
struct TestConsumer {
state: State,
c_state: ConsumerState<usize,(),Move>,
counter: usize,
}
named!(om_parser, tag!("om"));
named!(nomnom_parser<&[u8],Vec<&[u8]> >, many1!(tag!("nom")));
named!(end_parser, tag!("kthxbye"));
impl<'a> Consumer<&'a[u8], usize, (), Move> for TestConsumer {
fn state(&self) -> &ConsumerState<usize,(),Move> {
&self.c_state
}
fn handle(&mut self, input: Input<&'a [u8]>) -> &ConsumerState<usize,(),Move> {
match self.state {
State::Beginning => {
match input {
Input::Empty | Input::Eof(None) => {
self.state = State::Error;
self.c_state = ConsumerState::Error(());
},
Input::Element(sl) | Input::Eof(Some(sl)) => {
match om_parser(sl) {
IResult::Error(_) => {
self.state = State::Error;
self.c_state = ConsumerState::Error(());
},
IResult::Incomplete(n) => {
self.c_state = ConsumerState::Continue(Move::Await(n));
},
IResult::Done(i,_) => {
self.state = State::Middle;
self.c_state = ConsumerState::Continue(Move::Consume(sl.offset(i)));
}
}
}
}
},
State::Middle => {
match input {
Input::Empty | Input::Eof(None) => {
self.state = State::Error;
self.c_state = ConsumerState::Error(());
},
Input::Element(sl) | Input::Eof(Some(sl)) => {
match nomnom_parser(sl) {
IResult::Error(_) => {
self.state = State::End;
self.c_state = ConsumerState::Continue(Move::Consume(0));
},
IResult::Incomplete(n) => {
println!("Middle got Incomplete({:?})", n);
self.c_state = ConsumerState::Continue(Move::Await(n));
},
IResult::Done(i,noms_vec) => {
self.counter = self.counter + noms_vec.len();
self.state = State::Middle;
self.c_state = ConsumerState::Continue(Move::Consume(sl.offset(i)));
}
}
}
}
},
State::End => {
match input {
Input::Empty | Input::Eof(None) => {
self.state = State::Error;
self.c_state = ConsumerState::Error(());
},
Input::Element(sl) | Input::Eof(Some(sl)) => {
match end_parser(sl) {
IResult::Error(_) => {
self.state = State::Error;
self.c_state = ConsumerState::Error(());
},
IResult::Incomplete(n) => {
self.c_state = ConsumerState::Continue(Move::Await(n));
},
IResult::Done(i,_) => {
self.state = State::Done;
self.c_state = ConsumerState::Done(Move::Consume(sl.offset(i)), self.counter);
}
}
}
}
},
State::Done | State::Error => {
// this should not be called
self.state = State::Error;
self.c_state = ConsumerState::Error(())
}
};
&self.c_state
}
}
#[test]
fn nom1() {
let mut p = MemProducer::new(&b"omnomkthxbye"[..], 8);
let mut c = TestConsumer{state: State::Beginning, counter: 0, c_state: ConsumerState::Continue(Move::Consume(0))};
while let &ConsumerState::Continue(Move::Consume(_)) = p.apply(&mut c) {
}
assert_eq!(c.counter, 1);
assert_eq!(c.state, State::Done);
}
#[test]
fn nomnomnom() {
let mut p = MemProducer::new(&b"omnomnomnomkthxbye"[..], 9);
let mut c = TestConsumer{state: State::Beginning, counter: 0, c_state: ConsumerState::Continue(Move::Consume(0))};
while let &ConsumerState::Continue(_) = p.apply(&mut c) {
}
assert_eq!(c.counter, 3);
assert_eq!(c.state, State::Done);
}
#[test]
fn no_nomnom() {
let mut p = MemProducer::new(&b"omkthxbye"[..], 8);
let mut c = TestConsumer{state: State::Beginning, counter: 0, c_state: ConsumerState::Continue(Move::Consume(0))};
while let &ConsumerState::Continue(_) = p.apply(&mut c) {
}
assert_eq!(c.counter, 0);
assert_eq!(c.state, State::Done);
}
/*
#[test]
fn impolite() {
let mut p = MemProducer::new(&b"omnomnomnom"[..], 11);
let mut c = TestConsumer{state: State::Beginning, counter: 0, c_state: ConsumerState::Continue(Move::Consume(0))};
while let &ConsumerState::Continue(cont) = p.apply(&mut c) {
println!("continue {:?}", cont);
}
assert_eq!(c.counter, 3);
assert_eq!(c.state, State::End);
}
*/

44
third_party/rust/nom-1.2.4/nom/tests/test1.rs поставляемый
Просмотреть файл

@ -1,44 +0,0 @@
#![cfg(feature = "stream")]
#[macro_use]
extern crate nom;
use nom::{IResult,Producer,FileProducer,not_line_ending};
use std::str;
use std::fmt::Debug;
#[test]
#[allow(unused_must_use)]
fn tag() {
FileProducer::new("assets/links.txt", 20).map(|producer: FileProducer| {
let mut p = producer;
p.refill();
consumer_from_parser!(PrintConsumer<()>, flat_map!(map_res!(tag!("https!"), str::from_utf8), print));
let mut cs = PrintConsumer::new();
for _ in 1..4 {
p.apply(&mut cs);
}
});
}
pub fn print<T: Debug>(input: T) -> IResult<T,()> {
println!("{:?}", input);
IResult::Done(input, ())
}
#[test]
fn is_not() {
//is_not!(foo b"\r\n");
named!(foo<&[u8],&[u8]>, is_not!(&b"\r\n"[..]));
let a = &b"ab12cd\nefgh"[..];
assert_eq!(foo(a), IResult::Done(&b"\nefgh"[..], &b"ab12cd"[..]));
}
#[test]
fn exported_public_method_defined_by_macro() {
let a = &b"ab12cd\nefgh"[..];
assert_eq!(not_line_ending(a), IResult::Done(&b"\nefgh"[..], &b"ab12cd"[..]));
}

220
third_party/rust/nom-1.2.4/src/bits.rs поставляемый
Просмотреть файл

@ -1,220 +0,0 @@
//! Bit level parsers and combinators
//!
//! Bit parsing is handled by tweaking the input in most macros.
//! In byte level parsing, the input is generally a `&[u8]` passed from combinator
//! to combinator until the slices are manipulated.
//!
//! Bit parsers take a `(&[u8], usize)` as input. The first part of the tuple is an byte slice,
//! the second part is a bit offset in the first byte of the slice.
//!
//! By passing a pair like this, we can leverage most of the combinators, and avoid
//! transforming the whole slice to a vector of booleans. This should make it easy
//! to see a byte slice as a bit stream, and parse code points of arbitrary bit length.
/// `bits!( parser ) => ( &[u8], (&[u8], usize) -> IResult<(&[u8], usize), T> ) -> IResult<&[u8], T>`
/// transforms its byte slice input into a bit stream for the underlying parsers
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
/// named!( take_3_bits<u8>, bits!( take_bits!( u8, 3 ) ) );
///
/// let input = vec![0b10101010, 0b11110000, 0b00110011];
/// let sl = &input[..];
///
/// assert_eq!(take_3_bits( sl ), Done(&sl[1..], 5) );
/// # }
#[macro_export]
macro_rules! bits (
($i:expr, $submac:ident!( $($args:tt)* )) => (
bits_impl!($i, $submac!($($args)*));
);
($i:expr, $f:expr) => (
bits_impl!($i, call!($f));
);
);
/// Internal parser, do not use directly
#[doc(hidden)]
#[macro_export]
macro_rules! bits_impl (
($i:expr, $submac:ident!( $($args:tt)* )) => (
{
let input = ($i, 0usize);
match $submac!(input, $($args)*) {
$crate::IResult::Error(e) => {
let err = match e {
$crate::Err::Code(k) | $crate::Err::Node(k, _) => $crate::Err::Code(k),
$crate::Err::Position(k, (i,b)) | $crate::Err::NodePosition(k, (i,b), _) => {
$crate::Err::Position(k, &i[b/8..])
}
};
$crate::IResult::Error(err)
}
$crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
//println!("bits parser returned Needed::Size({})", i);
$crate::IResult::Incomplete($crate::Needed::Size(i / 8 + 1))
},
$crate::IResult::Done((i, bit_index), o) => {
let byte_index = bit_index / 8 + if bit_index % 8 == 0 { 0 } else { 1 } ;
//println!("bit index=={} => byte index=={}", bit_index, byte_index);
$crate::IResult::Done(&i[byte_index..], o)
}
}
}
);
);
/// `take_bits!(type, nb) => ( (&[T], usize), U, usize) -> IResult<(&[T], usize), U>`
/// generates a parser consuming the specified number of bits.
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
/// named!( take_pair<(u8, u8)>, bits!( pair!( take_bits!( u8, 3 ), take_bits!(u8, 5) ) ) );
///
/// let input = vec![0b10101010, 0b11110000, 0b00110011];
/// let sl = &input[..];
///
/// assert_eq!(take_pair( sl ), Done(&sl[1..], (5, 10)) );
/// assert_eq!(take_pair( &sl[1..] ), Done(&sl[2..], (7, 16)) );
/// # }
/// ```
#[macro_export]
macro_rules! take_bits (
($i:expr, $t:ty, $count:expr) => (
{
use std::ops::Div;
//println!("taking {} bits from {:?}", $count, $i);
let (input, bit_offset) = $i;
let res : $crate::IResult<(&[u8],usize), $t> = if $count == 0 {
$crate::IResult::Done( (input, bit_offset), 0)
} else {
let cnt = ($count as usize + bit_offset).div(8);
if input.len() * 8 < $count as usize + bit_offset {
//println!("returning incomplete: {}", $count as usize + bit_offset);
$crate::IResult::Incomplete($crate::Needed::Size($count as usize))
} else {
let mut acc:$t = 0;
let mut offset: usize = bit_offset;
let mut remaining: usize = $count;
let mut end_offset: usize = 0;
for byte in input.iter().take(cnt + 1) {
if remaining == 0 {
break;
}
let val: $t = if offset == 0 {
*byte as $t
} else {
((*byte << offset) as u8 >> offset) as $t
};
if remaining < 8 - offset {
acc += val >> (8 - offset - remaining);
end_offset = remaining + offset;
break;
} else {
acc += val << (remaining - (8 - offset));
remaining -= 8 - offset;
offset = 0;
}
}
$crate::IResult::Done( (&input[cnt..], end_offset) , acc)
}
};
res
}
);
);
/// matches an integer pattern to a bitstream. The number of bits of the input to compare must be specified
#[macro_export]
macro_rules! tag_bits (
($i:expr, $t:ty, $count:expr, $p: pat) => (
{
match take_bits!($i, $t, $count) {
$crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
$crate::IResult::Done(i, o) => {
if let $p = o {
let res: $crate::IResult<(&[u8],usize),$t> = $crate::IResult::Done(i, o);
res
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TagBits, $i))
}
},
_ => {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TagBits, $i))
}
}
}
)
);
#[cfg(test)]
mod tests {
use internal::{IResult,Needed,Err};
use ErrorKind;
#[test]
fn take_bits() {
let input = vec![0b10101010, 0b11110000, 0b00110011];
let sl = &input[..];
assert_eq!(take_bits!( (sl, 0), u8, 0 ), IResult::Done((sl, 0), 0));
assert_eq!(take_bits!( (sl, 0), u8, 8 ), IResult::Done((&sl[1..], 0), 170));
assert_eq!(take_bits!( (sl, 0), u8, 3 ), IResult::Done((&sl[0..], 3), 5));
assert_eq!(take_bits!( (sl, 0), u8, 6 ), IResult::Done((&sl[0..], 6), 42));
assert_eq!(take_bits!( (sl, 1), u8, 1 ), IResult::Done((&sl[0..], 2), 0));
assert_eq!(take_bits!( (sl, 1), u8, 2 ), IResult::Done((&sl[0..], 3), 1));
assert_eq!(take_bits!( (sl, 1), u8, 3 ), IResult::Done((&sl[0..], 4), 2));
assert_eq!(take_bits!( (sl, 6), u8, 3 ), IResult::Done((&sl[1..], 1), 5));
assert_eq!(take_bits!( (sl, 0), u16, 10 ), IResult::Done((&sl[1..], 2), 683));
assert_eq!(take_bits!( (sl, 0), u16, 8 ), IResult::Done((&sl[1..], 0), 170));
assert_eq!(take_bits!( (sl, 6), u16, 10 ), IResult::Done((&sl[2..], 0), 752));
assert_eq!(take_bits!( (sl, 6), u16, 11 ), IResult::Done((&sl[2..], 1), 1504));
assert_eq!(take_bits!( (sl, 0), u32, 20 ), IResult::Done((&sl[2..], 4), 700163));
assert_eq!(take_bits!( (sl, 4), u32, 20 ), IResult::Done((&sl[3..], 0), 716851));
assert_eq!(take_bits!( (sl, 4), u32, 22 ), IResult::Incomplete(Needed::Size(22)));
}
#[test]
fn tag_bits() {
let input = vec![0b10101010, 0b11110000, 0b00110011];
let sl = &input[..];
assert_eq!(tag_bits!( (sl, 0), u8, 3, 0b101), IResult::Done((&sl[0..], 3), 5));
assert_eq!(tag_bits!( (sl, 0), u8, 4, 0b1010), IResult::Done((&sl[0..], 4), 10));
}
named!(ch<(&[u8],usize),(u8,u8)>,
chain!(
tag_bits!(u8, 3, 0b101) ~
x: take_bits!(u8, 4) ~
y: take_bits!(u8, 5) ,
|| { (x,y) }
)
);
#[test]
fn chain_bits() {
let input = vec![0b10101010, 0b11110000, 0b00110011];
let sl = &input[..];
assert_eq!(ch((&input[..],0)), IResult::Done((&sl[1..], 4), (5,15)));
assert_eq!(ch((&input[..],4)), IResult::Done((&sl[2..], 0), (7,16)));
assert_eq!(ch((&input[..1],0)), IResult::Incomplete(Needed::Size(12)));
}
named!(ch_bytes<(u8,u8)>, bits!(ch));
#[test]
fn bits_to_bytes() {
let input = vec![0b10101010, 0b11110000, 0b00110011];
assert_eq!(ch_bytes(&input[..]), IResult::Done(&input[2..], (5,15)));
assert_eq!(ch_bytes(&input[..1]), IResult::Incomplete(Needed::Size(2)));
assert_eq!(ch_bytes(&input[1..]), IResult::Error(Err::Position(ErrorKind::TagBits, &input[1..])));
}
}

1027
third_party/rust/nom-1.2.4/src/bytes.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

184
third_party/rust/nom-1.2.4/src/character.rs поставляемый
Просмотреть файл

@ -1,184 +0,0 @@
/// Character level parsers
use internal::{IResult,Needed,Err};
use util::ErrorKind;
/// matches one of the provided characters
#[macro_export]
macro_rules! one_of (
($i:expr, $inp: expr) => (
{
if $i.is_empty() {
$crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
} else {
#[inline(always)]
fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
b.as_bytes()
}
let expected = $inp;
let bytes = as_bytes(&expected);
one_of_bytes!($i, bytes)
}
}
);
);
#[doc(hidden)]
#[macro_export]
macro_rules! one_of_bytes (
($i:expr, $bytes: expr) => (
{
if $i.is_empty() {
$crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
} else {
let mut found = false;
for &i in $bytes {
if i == $i[0] {
found = true;
break;
}
}
if found {
$crate::IResult::Done(&$i[1..], $i[0] as char)
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::OneOf, $i))
}
}
}
);
);
/// matches anything but the provided characters
#[macro_export]
macro_rules! none_of (
($i:expr, $inp: expr) => (
{
if $i.is_empty() {
$crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
} else {
#[inline(always)]
fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
b.as_bytes()
}
let expected = $inp;
let bytes = as_bytes(&expected);
none_of_bytes!($i, bytes)
}
}
);
);
#[doc(hidden)]
#[macro_export]
macro_rules! none_of_bytes (
($i:expr, $bytes: expr) => (
{
if $i.is_empty() {
$crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
} else {
let mut found = false;
for &i in $bytes {
if i == $i[0] {
found = true;
break;
}
}
if !found {
$crate::IResult::Done(&$i[1..], $i[0] as char)
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::NoneOf, $i))
}
}
}
);
);
/// matches one character: `char!(char) => &[u8] -> IResult<&[u8], char>
#[macro_export]
macro_rules! char (
($i:expr, $c: expr) => (
{
if $i.is_empty() {
let res: $crate::IResult<&[u8], char> = $crate::IResult::Incomplete($crate::Needed::Size(1));
res
} else {
if $i[0] == $c as u8 {
$crate::IResult::Done(&$i[1..], $i[0] as char)
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::Char, $i))
}
}
}
);
);
named!(pub newline<char>, char!('\n'));
pub fn crlf(input:&[u8]) -> IResult<&[u8], char> {
if input.len() < 2 {
IResult::Incomplete(Needed::Size(2))
} else {
if &input[0..2] == &b"\r\n"[..] {
IResult::Done(&input[2..], '\n')
} else {
IResult::Error(Err::Position(ErrorKind::CrLf, input))
}
}
}
named!(pub eol<char>, alt!(crlf | newline));
named!(pub tab<char>, char!('\t'));
pub fn anychar(input:&[u8]) -> IResult<&[u8], char> {
if input.is_empty() {
IResult::Incomplete(Needed::Size(1))
} else {
IResult::Done(&input[1..], input[0] as char)
}
}
#[cfg(test)]
mod tests {
use internal::IResult::*;
use internal::Err::*;
use util::ErrorKind;
#[test]
fn one_of() {
named!(f<char>, one_of!("ab"));
let a = &b"abcd"[..];
assert_eq!(f(a), Done(&b"bcd"[..], 'a'));
let b = &b"cde"[..];
assert_eq!(f(b), Error(Position(ErrorKind::OneOf, b)));
}
#[test]
fn none_of() {
named!(f<char>, none_of!("ab"));
let a = &b"abcd"[..];
assert_eq!(f(a), Error(Position(ErrorKind::NoneOf, a)));
let b = &b"cde"[..];
assert_eq!(f(b), Done(&b"de"[..], 'c'));
}
#[test]
fn char() {
named!(f<char>, char!('c'));
let a = &b"abcd"[..];
assert_eq!(f(a), Error(Position(ErrorKind::Char, a)));
let b = &b"cde"[..];
assert_eq!(f(b), Done(&b"de"[..], 'c'));
}
}

347
third_party/rust/nom-1.2.4/src/internal.rs поставляемый
Просмотреть файл

@ -1,347 +0,0 @@
//! Basic types to build the parsers
use self::IResult::*;
use self::Needed::*;
use util::ErrorKind;
#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;
/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
/// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
Code(ErrorKind<E>),
/// An error code, and the next error
Node(ErrorKind<E>, Box<Err<P,E>>),
/// An error code, and the input position
Position(ErrorKind<E>, P),
/// An error code, the input position and the next error
NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}
/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
/// needs more data, but we do not know how much
Unknown,
/// contains the required data size
Size(usize)
}
impl Needed {
pub fn is_known(&self) -> bool {
*self != Unknown
}
/// Maps a `Needed` to `Needed` by appling a function to a contained `Size` value.
#[inline]
pub fn map<F: FnOnce(usize) -> usize>(self, f: F) -> Needed {
match self {
Unknown => Unknown,
Size(n) => Size(f(n)),
}
}
}
/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
/// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
Done(I,O),
/// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
Error(Err<I,E>),
/// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
Incomplete(Needed)
}
impl<I,O,E> IResult<I,O,E> {
pub fn is_done(&self) -> bool {
match *self {
Done(_,_) => true,
_ => false
}
}
pub fn is_err(&self) -> bool {
match *self {
Error(_) => true,
_ => false
}
}
pub fn is_incomplete(&self) -> bool {
match *self {
Incomplete(_) => true,
_ => false
}
}
/// Maps a `IResult<I, O, E>` to `IResult<I, N, E>` by appling a function
/// to a contained `Done` value, leaving `Error` and `Incomplete` value
/// untouched.
#[inline]
pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
match self {
Done(i, o) => Done(i, f(o)),
Error(e) => Error(e),
Incomplete(n) => Incomplete(n),
}
}
/// Maps a `IResult<I, O, E>` to `IResult<I, O, E>` by appling a function
/// to a contained `Incomplete` value, leaving `Done` and `Error` value
/// untouched.
#[inline]
pub fn map_inc<F>(self, f: F) -> IResult<I, O, E>
where F: FnOnce(Needed) -> Needed {
match self {
Error(e) => Error(e),
Incomplete(n) => Incomplete(f(n)),
Done(i, o) => Done(i, o),
}
}
/// Maps a `IResult<I, O, E>` to `IResult<I, O, N>` by appling a function
/// to a contained `Error` value, leaving `Done` and `Incomplete` value
/// untouched.
#[inline]
pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
where F: FnOnce(Err<I, E>) -> Err<I, N> {
match self {
Error(e) => Error(f(e)),
Incomplete(n) => Incomplete(n),
Done(i, o) => Done(i, o),
}
}
/// Unwrap the contained `Done(I, O)` value, or panic if the `IResult` is not
/// `Done`.
pub fn unwrap(self) -> (I, O) {
match self {
Done(i, o) => (i, o),
Incomplete(_) => panic!("unwrap() called on an IResult that is Incomplete"),
Error(_) => panic!("unwrap() called on an IResult that is Error")
}
}
/// Unwrap the contained `Done(I, O)` value, or panic if the `IResult` is not
/// `Done`.
pub fn unwrap_inc(self) -> Needed {
match self {
Incomplete(n) => n,
Done(_, _) => panic!("unwrap_inc() called on an IResult that is Done"),
Error(_) => panic!("unwrap_inc() called on an IResult that is Error")
}
}
/// Unwrap the contained `Done(I, O)` value, or panic if the `IResult` is not
/// `Done`.
pub fn unwrap_err(self) -> Err<I, E> {
match self {
Error(e) => e,
Done(_, _) => panic!("unwrap_err() called on an IResult that is Done"),
Incomplete(_) => panic!("unwrap_err() called on an IResult that is Incomplete"),
}
}
}
pub trait GetInput<I> {
fn remaining_input(&self) -> Option<I>;
}
pub trait GetOutput<O> {
fn output(&self) -> Option<O>;
}
impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
fn remaining_input(&self) -> Option<&'a[I]> {
match *self {
Done(ref i,_) => Some(*i),
_ => None
}
}
}
impl<O,E> GetInput<()> for IResult<(),O,E> {
fn remaining_input(&self) -> Option<()> {
match *self {
Done((),_) => Some(()),
_ => None
}
}
}
impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
fn remaining_input(&self) -> Option<&'a str> {
match *self {
Done(ref i,_) => Some(*i),
_ => None
}
}
}
impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
fn output(&self) -> Option<&'a[O]> {
match *self {
Done(_, ref o) => Some(*o),
_ => None
}
}
}
impl<I,E> GetOutput<()> for IResult<I,(),E> {
fn output(&self) -> Option<()> {
match *self {
Done(_,()) => Some(()),
_ => None
}
}
}
impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
fn output(&self) -> Option<&'a str> {
match *self {
Done(_,ref o) => Some(*o),
_ => None
}
}
}
#[cfg(not(feature = "core"))]
use std::any::Any;
#[cfg(not(feature = "core"))]
use std::{error,fmt};
#[cfg(not(feature = "core"))]
use std::fmt::Debug;
#[cfg(not(feature = "core"))]
impl<P:Debug+Any,E:Debug+Any> error::Error for Err<P,E> {
fn description(&self) -> &str {
let kind = match *self {
Err::Code(ref e) | Err::Node(ref e, _) | Err::Position(ref e, _) | Err::NodePosition(ref e, _, _) => e
};
kind.description()
}
}
#[cfg(not(feature = "core"))]
impl<P:fmt::Debug,E:fmt::Debug> fmt::Display for Err<P,E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Err::Code(ref e) | Err::Node(ref e, _) => {
write!(f, "{:?}", e)
},
Err::Position(ref e, ref p) | Err::NodePosition(ref e, ref p, _) => {
write!(f, "{:?}:{:?}", p, e)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use util::ErrorKind;
const REST: [u8; 0] = [];
const DONE: IResult<&'static [u8], u32> = IResult::Done(&REST, 5);
const ERROR: IResult<&'static [u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
const INCOMPLETE: IResult<&'static [u8], u32> = IResult::Incomplete(Needed::Unknown);
#[test]
fn needed_map() {
let unknown = Needed::Unknown;
let size = Needed::Size(5);
assert_eq!(size.map(|x| x * 2), Needed::Size(10));
assert_eq!(unknown.map(|x| x * 2), Needed::Unknown);
}
#[test]
fn iresult_map() {
assert_eq!(DONE.map(|x| x * 2), IResult::Done(&b""[..], 10));
assert_eq!(ERROR.map(|x| x * 2), IResult::Error(Err::Code(ErrorKind::Tag)));
assert_eq!(INCOMPLETE.map(|x| x * 2), IResult::Incomplete(Needed::Unknown));
}
#[test]
fn iresult_map_inc() {
let inc_unknown: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);
let inc_size: IResult<&[u8], u32> = IResult::Incomplete(Needed::Size(5));
assert_eq!(DONE.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Done(&b""[..], 5));
assert_eq!(ERROR.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Error(Err::Code(ErrorKind::Tag)));
assert_eq!(inc_unknown.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Incomplete(Needed::Unknown));
assert_eq!(inc_size.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Incomplete(Needed::Size(6)));
}
#[test]
fn iresult_map_err() {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct Error(u32);
let error_kind = Err::Code(ErrorKind::Custom(Error(5)));
assert_eq!(DONE.map_err(|_| error_kind.clone()), IResult::Done(&b""[..], 5));
assert_eq!(ERROR.map_err(|x| {println!("err: {:?}", x); error_kind.clone()}), IResult::Error(error_kind.clone()));
assert_eq!(INCOMPLETE.map_err(|x| {println!("err: {:?}", x); error_kind.clone()}), IResult::Incomplete(Needed::Unknown));
}
#[test]
fn iresult_unwrap_on_done() {
assert_eq!(DONE.unwrap(), (&b""[..], 5));
}
#[test]
#[should_panic]
fn iresult_unwrap_on_err() {
ERROR.unwrap();
}
#[test]
#[should_panic]
fn iresult_unwrap_on_inc() {
INCOMPLETE.unwrap();
}
#[test]
#[should_panic]
fn iresult_unwrap_err_on_done() {
DONE.unwrap_err();
}
#[test]
fn iresult_unwrap_err_on_err() {
assert_eq!(ERROR.unwrap_err(), Err::Code(ErrorKind::Tag));
}
#[test]
#[should_panic]
fn iresult_unwrap_err_on_inc() {
INCOMPLETE.unwrap_err();
}
#[test]
#[should_panic]
fn iresult_unwrap_inc_on_done() {
DONE.unwrap_inc();
}
#[test]
#[should_panic]
fn iresult_unwrap_inc_on_err() {
ERROR.unwrap_inc();
}
#[test]
fn iresult_unwrap_inc_on_inc() {
assert_eq!(INCOMPLETE.unwrap_inc(), Needed::Unknown);
}
}

151
third_party/rust/nom-1.2.4/src/lib.rs поставляемый
Просмотреть файл

@ -1,151 +0,0 @@
//! nom, eating data byte by byte
//!
//! nom is a parser combinator library with a focus on safe parsing,
//! streaming patterns, and as much as possible zero copy.
//!
//! The code is available on [Github](https://github.com/Geal/nom)
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate nom;
//!
//! use nom::{IResult,digit};
//! use nom::IResult::*;
//!
//! // Parser definition
//!
//! use std::str;
//! use std::str::FromStr;
//!
//! named!(parens<i64>, delimited!(
//! char!('('),
//! expr,
//! char!(')')
//! )
//! );
//!
//! named!(i64_digit<i64>,
//! map_res!(
//! map_res!(
//! digit,
//! str::from_utf8
//! ),
//! FromStr::from_str
//! )
//! );
//!
//! // We transform an integer string into a i64
//! // we look for a digit suite, and try to convert it.
//! // if either str::from_utf8 or FromStr::from_str fail,
//! // the parser will fail
//! named!(factor<i64>,
//! alt!(
//! i64_digit
//! | parens
//! )
//! );
//!
//! // we define acc as mutable to update its value whenever a new term is found
//! named!(term <i64>,
//! chain!(
//! mut acc: factor ~
//! many0!(
//! alt!(
//! tap!(mul: preceded!(tag!("*"), factor) => acc = acc * mul) |
//! tap!(div: preceded!(tag!("/"), factor) => acc = acc / div)
//! )
//! ),
//! || { return acc }
//! )
//! );
//!
//! named!(expr <i64>,
//! chain!(
//! mut acc: term ~
//! many0!(
//! alt!(
//! tap!(add: preceded!(tag!("+"), term) => acc = acc + add) |
//! tap!(sub: preceded!(tag!("-"), term) => acc = acc - sub)
//! )
//! ),
//! || { return acc }
//! )
//! );
//!
//! fn main() {
//! assert_eq!(expr(b"1+2"), IResult::Done(&b""[..], 3));
//! assert_eq!(expr(b"12+6-4+3"), IResult::Done(&b""[..], 17));
//! assert_eq!(expr(b"1+2*3+4"), IResult::Done(&b""[..], 11));
//!
//! assert_eq!(expr(b"(2)"), IResult::Done(&b""[..], 2));
//! assert_eq!(expr(b"2*(3+4)"), IResult::Done(&b""[..], 14));
//! assert_eq!(expr(b"2*2/(5-1)+3"), IResult::Done(&b""[..], 4));
//! }
//! ```
#![cfg_attr(feature = "core", feature(no_std))]
#![cfg_attr(feature = "core", feature(collections))]
#![cfg_attr(feature = "core", no_std)]
#![cfg_attr(feature = "nightly", feature(test))]
#![cfg_attr(feature = "nightly", feature(const_fn))]
#[cfg(feature = "core")]
extern crate collections;
#[cfg(feature = "regexp")]
extern crate regex;
#[cfg(feature = "regexp_macros")]
#[macro_use] extern crate lazy_static;
#[cfg(feature = "nightly")]
extern crate test;
#[cfg(feature = "core")]
mod std {
#[macro_use]
pub use core::{fmt, iter, option, ops, slice, mem};
pub use collections::{boxed, vec, string};
pub mod prelude {
pub use core::prelude as v1;
}
}
pub use self::util::*;
pub use self::internal::*;
pub use self::macros::*;
pub use self::methods::*;
pub use self::bytes::*;
pub use self::bits::*;
pub use self::nom::*;
pub use self::character::*;
#[cfg(feature = "regexp")]
pub use self::regexp::*;
#[cfg(not(feature = "core"))]
#[cfg(feature = "stream")]
pub use self::stream::*;
#[cfg(not(feature = "core"))]
pub use self::str::*;
#[macro_use] mod util;
mod internal;
#[macro_use] mod macros;
#[macro_use] mod methods;
#[macro_use] mod bytes;
#[macro_use] mod bits;
#[macro_use] mod nom;
#[macro_use] mod character;
#[cfg(feature = "regexp")]
#[macro_use] mod regexp;
#[macro_use]
#[cfg(not(feature = "core"))]
#[cfg(feature = "stream")]
mod stream;
#[cfg(not(feature = "core"))]
mod str;

3561
third_party/rust/nom-1.2.4/src/macros.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

480
third_party/rust/nom-1.2.4/src/methods.rs поставляемый
Просмотреть файл

@ -1,480 +0,0 @@
//! Method macro combinators
//!
//! These macros make parsers as methods of structs
//! and that can take methods of structs to call
//! as parsers.
//!
//! There is a trick to make them easier to assemble,
//! combinators are defined like this:
//!
//! ```ignore
//! macro_rules! tag (
//! ($i:expr, $inp: expr) => (
//! {
//! ...
//! }
//! );
//! );
//! ```
//!
//! But when used as methods in other combinators, are used
//! like this:
//!
//! ```ignore
//! method!(my_function<Parser<'a> >, self, tag!("abcd"));
//! ```
//!
//! Internally, other combinators will rewrite
//! that call to pass the input as second argument:
//!
//! ```ignore
//! macro_rules! method (
//! ($name:ident<$a:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
//! fn $name( $self_: $a, i: &[u8] ) -> $crate::IResult<&[u8], &[u8]> {
//! $submac!(i, $($args)*)
//! }
//! );
//! );
//! ```
//!
//! The `method!` macro is similar to the `named!` macro in the macros module.
//! While `named!` will create a parser function, `method!` will create a parser
//! method on the struct it is defined in.
//!
//! Compared to the `named!` macro there are a few differences in how they are
//! invoked. A `method!` invocation always has to have the type of `self`
//! declared and it can't be a reference due to Rust's borrow lifetime
//! restrictions:
//! ```ignore
//! // -`self`'s type-
//! method!(method_name< Parser<'a> >, ...);
//! ```
//! `self`'s type always comes first.
//! The next difference is you have to input the self struct. Due to Rust's
//! macro hygiene the macro can't declare it on it's own.
//! ```ignore
//! // -self-
//! method!(method_name<Parser<'a>, &'a str, &'a str>, self, ...);
//! ```
//! When making a parsing struct with parsing methods, due to the static borrow
//! checker,calling any parsing methods on self (or any other parsing struct)
//! will cause self to be moved for the rest of the method.To get around this
//! restriction all self is moved into the called method and then the called
//! method will return self to the caller.
//!
//! To call a method on self you need to use the `call_m!` macro. For example:
//! ```ignore
//! struct<'a> Parser<'a> {
//! parsed: &'a str,
//! }
//! impl<'a> Parser<'a> {
//! // Constructor omitted for brevity
//! method!(take4<Parser<'a>, &'a str, &'a str>, self, take!(4));
//! method!(caller<Parser<'a>, &'a str, &'a str>, self, call_m!(self.take4));
//! }
//! ```
//! More complicated combinations still mostly look the same as their `named!`
//! counterparts:
//! ```ignore
//! method!(pub simple_chain<&mut Parser<'a>, &'a str, &'a str>, self,
//! chain!(
//! call_m!(self.tag_abc) ~
//! call_m!(self.tag_def) ~
//! call_m!(self.tag_ghi) ~
//! last: call_m!(self.simple_peek) ,
//! ||{sb.parsed = last; last}
//! )
//! );
//! ```
//! The three additions to method definitions to remember are:
//! 1. Specify `self`'s type
//! 2. Pass `self` to the macro
//! 4. Call parser methods using the `call_m!` macro.
/// Makes a method from a parser combination
///
/// The must be set up because the compiler needs
/// the information
///
/// ```ignore
/// method!(my_function<Parser<'a> >( &[u8] ) -> &[u8], tag!("abcd"));
/// // first type parameter is `self`'s type, second is input, third is output
/// method!(my_function<Parser<'a>, &[u8], &[u8]>, tag!("abcd"));
/// //prefix them with 'pub' to make the methods public
/// method!(pub my_function<Parser<'a>,&[u8], &[u8]>, tag!("abcd"));
/// ```
#[macro_export]
macro_rules! method (
// Non-public immutable self
($name:ident<$a:ty>( $i:ty ) -> $o:ty, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty,$i:ty,$o:ty,$e:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i, $o, $e>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty,$i:ty,$o:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty,$o:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name<'a>( $self_: $a, i: &'a[u8] ) -> ($a, $crate::IResult<&'a [u8], $o, u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( $self_: $a, i: &[u8] ) -> ($a, $crate::IResult<&[u8], &[u8], u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
// Public immutable self
(pub $name:ident<$a:ty>( $i:ty ) -> $o:ty, $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty,$i:ty,$o:ty,$e:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i, $o, $e>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty,$i:ty,$o:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name( $self_: $a,i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty,$o:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name<'a>( $self_: $a, i: &'a[u8] ) -> ($a, $crate::IResult<&'a [u8], $o, u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name( $self_: $a, i: &[u8] ) -> ($a, $crate::IResult<&[u8], &[u8], u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
// Non-public mutable self
($name:ident<$a:ty>( $i:ty ) -> $o:ty, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty,$i:ty,$o:ty,$e:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i, $o, $e>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty,$i:ty,$o:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty,$o:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name<'a>( mut $self_: $a, i: &'a[u8] ) -> ($a, $crate::IResult<&'a [u8], $o, u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
($name:ident<$a:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( mut $self_: $a, i: &[u8] ) -> ($a, $crate::IResult<&[u8], &[u8], u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
// Public mutable self
(pub $name:ident<$a:ty>( $i:ty ) -> $o:ty, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty,$i:ty,$o:ty,$e:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i, $o, $e>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty,$i:ty,$o:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name( mut $self_: $a,i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty,$o:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name<'a>( mut $self_: $a, i: &'a[u8] ) -> ($a, $crate::IResult<&'a [u8], $o, u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
(pub $name:ident<$a:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name( mut $self_: $a, i: &[u8] ) -> ($a, $crate::IResult<&[u8], &[u8], u32>) {
let result = $submac!(i, $($args)*);
($self_, result)
}
);
);
/// Used to called methods then move self back into self
#[macro_export]
macro_rules! call_m (
($i:expr, $self_:ident.$method:ident) => (
{
let (tmp, res) = $self_.$method($i);
$self_ = tmp;
res
}
);
($i:expr, $self_:ident.$method:ident, $($args:expr),* ) => (
{
let (tmp, res) = $self_.$method($i, $($args),*);
$self_ = tmp;
res
}
);
);
/// emulate function currying for method calls on structs
/// `apply!(self.my_function, arg1, arg2, ...)` becomes `self.my_function(input, arg1, arg2, ...)`
///
/// Supports up to 6 arguments
#[macro_export]
macro_rules! apply_m (
($i:expr, $self_:ident.$method:ident, $($args:expr),* ) => ( { let (tmp, res) = $self_.$method( $i, $($args),* ); $self_ = tmp; res } );
);
#[cfg(test)]
mod tests {
use internal::IResult::*;
// reproduce the tag_s and take_s macros, because of module import order
macro_rules! tag_s (
($i:expr, $tag: expr) => (
{
let res: $crate::IResult<_,_> = if $tag.len() > $i.len() {
$crate::IResult::Incomplete($crate::Needed::Size($tag.len()))
//} else if &$i[0..$tag.len()] == $tag {
} else if ($i).starts_with($tag) {
$crate::IResult::Done(&$i[$tag.len()..], &$i[0..$tag.len()])
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TagStr, $i))
};
res
}
);
);
macro_rules! take_s (
($i:expr, $count:expr) => (
{
let cnt = $count as usize;
let res: $crate::IResult<_,_> = if $i.chars().count() < cnt {
$crate::IResult::Incomplete($crate::Needed::Size(cnt))
} else {
let mut offset = $i.len();
let mut count = 0;
for (o, _) in $i.char_indices() {
if count == cnt {
offset = o;
break;
}
count += 1;
}
$crate::IResult::Done(&$i[offset..], &$i[..offset])
};
res
}
);
);
struct Parser<'a> {
bcd: &'a str,
}
impl<'a> Parser<'a> {
pub fn new() -> Parser<'a> {
Parser{bcd: ""}
}
method!(tag_abc<Parser<'a>, &'a str, &'a str>, self, tag_s!("áβç"));
method!(tag_bcd<Parser<'a> >(&'a str) -> &'a str, self, tag_s!("βçδ"));
method!(pub tag_hij<Parser<'a> >(&'a str) -> &'a str, self, tag_s!("λïJ"));
method!(pub tag_ijk<Parser<'a>, &'a str, &'a str>, self, tag_s!("ïJƙ"));
method!(take3<Parser<'a>, &'a str, &'a str>, self, take_s!(3));
method!(pub simple_call<Parser<'a>, &'a str, &'a str>, mut self,
call_m!(self.tag_abc)
);
method!(pub simple_peek<Parser<'a>, &'a str, &'a str>, mut self,
peek!(call_m!(self.take3))
);
method!(pub simple_chain<Parser<'a>, &'a str, &'a str>, mut self,
chain!(
bcd: call_m!(self.tag_bcd) ~
last: call_m!(self.simple_peek) ,
||{self.bcd = bcd; last}
)
);
fn tag_stuff(mut self: Parser<'a>, input: &'a str, something: &'a str) -> (Parser<'a>, ::IResult<&'a str, &'a str>) {
self.bcd = something;
let(tmp, res) = self.tag_abc(input);
self = tmp;
(self, res)
}
method!(use_apply<Parser<'a>, &'a str, &'a str>, mut self, apply_m!(self.tag_stuff, "βçδ"));
}
#[test]
fn test_method_call_abc() {
let p = Parser::new();
let input: &str = "áβçδèƒϱλïJƙ";
let consumed: &str = "áβç";
let leftover: &str = "δèƒϱλïJƙ";
let(_, res) = p.tag_abc(input);
match res {
Done(extra, output) => { assert!(extra == leftover, "`Parser.tag_abc` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.tag_abc` doesnt return the string it consumed \
on success. Expected `{}`, got `{}`.", consumed, output);
},
other => panic!("`Parser.tag_abc` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_method_call_bcd() {
let p = Parser::new();
let input: &str = "βçδèƒϱλïJƙ";
let consumed: &str = "βçδ";
let leftover: &str = "èƒϱλïJƙ";
let(_, res) = p.tag_bcd(input);
match res {
Done(extra, output) => { assert!(extra == leftover, "`Parser.tag_bcd` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.tag_bcd` doesn't return the string it consumed \
on success. Expected `{}`, got `{}`.", consumed, output);
},
other => panic!("`Parser.tag_bcd` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_method_call_hij() {
let p = Parser::new();
let input: &str = "λïJƙ₥ñôƥ9řƨ";
let consumed: &str = "λïJ";
let leftover: &str = "ƙ₥ñôƥ9řƨ";
let(_, res) = p.tag_hij(input);
match res {
Done(extra, output) => { assert!(extra == leftover, "`Parser.tag_hij` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.tag_hij` doesn't return the string it consumed \
on success. Expected `{}`, got `{}`.", consumed, output);
},
other => panic!("`Parser.tag_hij` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_method_call_ijk() {
let p = Parser::new();
let input: &str = "ïJƙ₥ñôƥ9řƨ";
let consumed: &str = "ïJƙ";
let leftover: &str = "₥ñôƥ9řƨ";
let(_, res) = p.tag_ijk(input);
match res {
Done(extra, output) => { assert!(extra == leftover, "`Parser.tag_ijk` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.tag_ijk` doesn't return the string it consumed \
on success. Expected `{}`, got `{}`.", consumed, output);
},
other => panic!("`Parser.tag_ijk` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_method_simple_call() {
let p = Parser::new();
let input: &str = "áβçδèƒϱλïJƙ";
let consumed: &str = "áβç";
let leftover: &str = "δèƒϱλïJƙ";
let(_, res) = p.simple_call(input);
match res {
Done(extra, output) => { assert!(extra == leftover, "`Parser.simple_call` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.simple_call` doesn't return the string it consumed \
on success. Expected `{}`, got `{}`.", consumed, output);
},
other => panic!("`Parser.simple_call` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_apply_m() {
let mut p = Parser::new();
let input: &str = "áβçδèƒϱλïJƙ";
let consumed: &str = "áβç";
let leftover: &str = "δèƒϱλïJƙ";
let(tmp, res) = p.use_apply(input);
p = tmp;
match res {
Done(extra, output) => { assert!(extra == leftover, "`Parser.use_apply` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.use_apply` doesn't return the string it was supposed to \
on success. Expected `{}`, got `{}`.", leftover, output);
assert!(p.bcd == "βçδ", "Parser.use_apply didn't modify the parser field correctly: {}", p.bcd);
},
other => panic!("`Parser.use_apply` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_method_call_peek() {
let p = Parser::new();
let input: &str = "ж¥ƺáβçδèƒϱλïJƙ";
let consumed: &str = "ж¥ƺ";
let(_, res) = p.simple_peek(input);
match res {
Done(extra, output) => { assert!(extra == input, "`Parser.simple_peek` consumed leftover input. leftover: {}", extra);
assert!(output == consumed, "`Parser.simple_peek` doesn't return the string it consumed \
on success. Expected `{}`, got `{}`.", consumed, output);
},
other => panic!("`Parser.simple_peek` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
#[test]
fn test_method_call_chain() {
let mut p = Parser::new();
let input : &str = "βçδδèƒϱλïJƙ";
let leftover : &str = "δèƒϱλïJƙ";
let output : &str = "늟";
let(tmp, res) = p.simple_chain(input);
p = tmp;
match res {
Done(extra, out) => { assert!(extra == leftover, "`Parser.simple_chain` consumed leftover input. leftover: {}", extra);
assert!(out == output, "`Parser.simple_chain` doesn't return the string it was supposed to \
on success. Expected `{}`, got `{}`.", output, out);
assert!(p.bcd == "βçδ", "Parser.simple_chain didn't modify the parser field correctly: {}", p.bcd);
},
other => panic!("`Parser.simple_chain` didn't succeed when it should have. \
Got `{:?}`.", other),
}
}
}

950
third_party/rust/nom-1.2.4/src/nom.rs поставляемый
Просмотреть файл

@ -1,950 +0,0 @@
//! Useful parser combinators
//!
//! A number of useful parser combinators have already been implemented.
//! Some of them use macros, other are implemented through functions.
//! Hopefully, the syntax will converge to onely one way in the future,
//! but the macros system makes no promises.
//!
#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;
use std::fmt::Debug;
use internal::*;
use internal::IResult::*;
use internal::Err::*;
use util::{ErrorKind,IterIndices,AsChar,InputLength};
use std::mem::transmute;
#[inline]
pub fn tag_cl<'a,'b>(rec:&'a[u8]) -> Box<Fn(&'b[u8]) -> IResult<&'b[u8], &'b[u8]> + 'a> {
Box::new(move |i: &'b[u8]| -> IResult<&'b[u8], &'b[u8]> {
if i.len() >= rec.len() && &i[0..rec.len()] == rec {
Done(&i[rec.len()..], &i[0..rec.len()])
} else {
Error(Position(ErrorKind::TagClosure, i))
}
})
}
#[cfg(not(feature = "core"))]
#[inline]
pub fn print<T: Debug>(input: T) -> IResult<T, ()> {
println!("{:?}", input);
Done(input, ())
}
#[inline]
pub fn begin(input: &[u8]) -> IResult<(), &[u8]> {
Done((), input)
}
// FIXME: when rust-lang/rust#17436 is fixed, macros will be able to export
// public methods
//pub is_not!(line_ending b"\r\n")
pub fn not_line_ending(input:&[u8]) -> IResult<&[u8], &[u8]> {
for (idx, item) in input.iter().enumerate() {
for &i in b"\r\n".iter() {
if *item == i {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input.len()..], input)
}
named!(tag_ln, tag!("\n"));
/// Recognizes a line feed
#[inline]
pub fn line_ending(input:&[u8]) -> IResult<&[u8], &[u8]> {
tag_ln(input)
}
#[inline]
pub fn is_alphabetic(chr:u8) -> bool {
(chr >= 0x41 && chr <= 0x5A) || (chr >= 0x61 && chr <= 0x7A)
}
#[inline]
pub fn is_digit(chr: u8) -> bool {
chr >= 0x30 && chr <= 0x39
}
#[inline]
pub fn is_hex_digit(chr: u8) -> bool {
(chr >= 0x30 && chr <= 0x39) ||
(chr >= 0x41 && chr <= 0x46) ||
(chr >= 0x61 && chr <= 0x66)
}
#[inline]
pub fn is_oct_digit(chr: u8) -> bool {
chr >= 0x30 && chr <= 0x37
}
#[inline]
pub fn is_alphanumeric(chr: u8) -> bool {
is_alphabetic(chr) || is_digit(chr)
}
#[inline]
pub fn is_space(chr:u8) -> bool {
chr == ' ' as u8 || chr == '\t' as u8
}
// FIXME: when rust-lang/rust#17436 is fixed, macros will be able to export
//pub filter!(alpha is_alphabetic)
//pub filter!(digit is_digit)
//pub filter!(hex_digit is_hex_digit)
//pub filter!(oct_digit is_oct_digit)
//pub filter!(alphanumeric is_alphanumeric)
use std::ops::{Index,Range,RangeFrom};
/// Recognizes lowercase and uppercase alphabetic characters: a-zA-Z
pub fn alpha<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::Alpha, input))
}
for (idx, item) in input.iter_indices() {
if ! item.is_alpha() {
if idx == 0 {
return Error(Position(ErrorKind::Alpha, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
/// Recognizes numerical characters: 0-9
pub fn digit<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::Digit, input))
}
for (idx, item) in input.iter_indices() {
if ! item.is_0_to_9() {
if idx == 0 {
return Error(Position(ErrorKind::Digit, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
/// Recognizes hexadecimal numerical characters: 0-9, A-F, a-f
pub fn hex_digit<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::HexDigit, input))
}
for (idx, item) in input.iter_indices() {
if ! item.is_hex_digit() {
if idx == 0 {
return Error(Position(ErrorKind::HexDigit, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
/// Recognizes octal characters: 0-7
pub fn oct_digit<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::OctDigit, input))
}
for (idx, item) in input.iter_indices() {
if ! item.is_oct_digit() {
if idx == 0 {
return Error(Position(ErrorKind::OctDigit, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
/// Recognizes numerical and alphabetic characters: 0-9a-zA-Z
pub fn alphanumeric<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::AlphaNumeric, input));
}
for (idx, item) in input.iter_indices() {
if ! item.is_alphanum() {
if idx == 0 {
return Error(Position(ErrorKind::AlphaNumeric, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
/// Recognizes spaces and tabs
pub fn space<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::Space, input));
}
for (idx, item) in input.iter_indices() {
let chr = item.as_char();
if ! (chr == ' ' || chr == '\t') {
if idx == 0 {
return Error(Position(ErrorKind::Space, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
/// Recognizes spaces, tabs, carriage returns and line feeds
pub fn multispace<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, &'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: IterIndices+InputLength {
let input_length = input.input_len();
if input_length == 0 {
return Error(Position(ErrorKind::MultiSpace, input));
}
for (idx, item) in input.iter_indices() {
let chr = item.as_char();
if ! (chr == ' ' || chr == '\t' || chr == '\r' || chr == '\n') {
if idx == 0 {
return Error(Position(ErrorKind::MultiSpace, input))
} else {
return Done(&input[idx..], &input[0..idx])
}
}
}
Done(&input[input_length..], input)
}
pub fn sized_buffer(input:&[u8]) -> IResult<&[u8], &[u8]> {
if input.is_empty() {
return Incomplete(Needed::Unknown)
}
let len = input[0] as usize;
if input.len() >= len + 1 {
Done(&input[len+1..], &input[1..len+1])
} else {
Incomplete(Needed::Size(1 + len))
}
}
pub fn length_value(input:&[u8]) -> IResult<&[u8], &[u8]> {
let input_len = input.len();
if input_len == 0 {
return Error(Position(ErrorKind::LengthValueFn, input))
}
let len = input[0] as usize;
if input_len - 1 >= len {
IResult::Done(&input[len+1..], &input[1..len+1])
} else {
IResult::Incomplete(Needed::Size(1+len))
}
}
/// Recognizes an unsigned 1 byte integer (equivalent to take!(1)
#[inline]
pub fn be_u8(i: &[u8]) -> IResult<&[u8], u8> {
if i.len() < 1 {
Incomplete(Needed::Size(1))
} else {
Done(&i[1..], i[0])
}
}
/// Recognizes big endian unsigned 2 bytes integer
#[inline]
pub fn be_u16(i: &[u8]) -> IResult<&[u8], u16> {
if i.len() < 2 {
Incomplete(Needed::Size(2))
} else {
let res = ((i[0] as u16) << 8) + i[1] as u16;
Done(&i[2..], res)
}
}
/// Recognizes big endian unsigned 4 bytes integer
#[inline]
pub fn be_u32(i: &[u8]) -> IResult<&[u8], u32> {
if i.len() < 4 {
Incomplete(Needed::Size(4))
} else {
let res = ((i[0] as u32) << 24) + ((i[1] as u32) << 16) + ((i[2] as u32) << 8) + i[3] as u32;
Done(&i[4..], res)
}
}
/// Recognizes big endian unsigned 8 bytes integer
#[inline]
pub fn be_u64(i: &[u8]) -> IResult<&[u8], u64> {
if i.len() < 8 {
Incomplete(Needed::Size(8))
} else {
let res = ((i[0] as u64) << 56) + ((i[1] as u64) << 48) + ((i[2] as u64) << 40) + ((i[3] as u64) << 32) +
((i[4] as u64) << 24) + ((i[5] as u64) << 16) + ((i[6] as u64) << 8) + i[7] as u64;
Done(&i[8..], res)
}
}
/// Recognizes a signed 1 byte integer (equivalent to take!(1)
#[inline]
pub fn be_i8(i:&[u8]) -> IResult<&[u8], i8> {
map!(i, be_u8, | x | { x as i8 })
}
/// Recognizes big endian signed 2 bytes integer
#[inline]
pub fn be_i16(i:&[u8]) -> IResult<&[u8], i16> {
map!(i, be_u16, | x | { x as i16 })
}
/// Recognizes big endian signed 4 bytes integer
#[inline]
pub fn be_i32(i:&[u8]) -> IResult<&[u8], i32> {
map!(i, be_u32, | x | { x as i32 })
}
/// Recognizes big endian signed 8 bytes integer
#[inline]
pub fn be_i64(i:&[u8]) -> IResult<&[u8], i64> {
map!(i, be_u64, | x | { x as i64 })
}
/// Recognizes an unsigned 1 byte integer (equivalent to take!(1)
#[inline]
pub fn le_u8(i: &[u8]) -> IResult<&[u8], u8> {
if i.len() < 1 {
Incomplete(Needed::Size(1))
} else {
Done(&i[1..], i[0])
}
}
/// Recognizes little endian unsigned 2 bytes integer
#[inline]
pub fn le_u16(i: &[u8]) -> IResult<&[u8], u16> {
if i.len() < 2 {
Incomplete(Needed::Size(2))
} else {
let res = ((i[1] as u16) << 8) + i[0] as u16;
Done(&i[2..], res)
}
}
/// Recognizes little endian unsigned 4 bytes integer
#[inline]
pub fn le_u32(i: &[u8]) -> IResult<&[u8], u32> {
if i.len() < 4 {
Incomplete(Needed::Size(4))
} else {
let res = ((i[3] as u32) << 24) + ((i[2] as u32) << 16) + ((i[1] as u32) << 8) + i[0] as u32;
Done(&i[4..], res)
}
}
/// Recognizes little endian unsigned 8 bytes integer
#[inline]
pub fn le_u64(i: &[u8]) -> IResult<&[u8], u64> {
if i.len() < 8 {
Incomplete(Needed::Size(8))
} else {
let res = ((i[7] as u64) << 56) + ((i[6] as u64) << 48) + ((i[5] as u64) << 40) + ((i[4] as u64) << 32) +
((i[3] as u64) << 24) + ((i[2] as u64) << 16) + ((i[1] as u64) << 8) + i[0] as u64;
Done(&i[8..], res)
}
}
/// Recognizes a signed 1 byte integer (equivalent to take!(1)
#[inline]
pub fn le_i8(i:&[u8]) -> IResult<&[u8], i8> {
map!(i, le_u8, | x | { x as i8 })
}
/// Recognizes little endian signed 2 bytes integer
#[inline]
pub fn le_i16(i:&[u8]) -> IResult<&[u8], i16> {
map!(i, le_u16, | x | { x as i16 })
}
/// Recognizes little endian signed 4 bytes integer
#[inline]
pub fn le_i32(i:&[u8]) -> IResult<&[u8], i32> {
map!(i, le_u32, | x | { x as i32 })
}
/// Recognizes little endian signed 8 bytes integer
#[inline]
pub fn le_i64(i:&[u8]) -> IResult<&[u8], i64> {
map!(i, le_u64, | x | { x as i64 })
}
/// if parameter is true, parse a big endian u16 integer,
/// otherwise a little endian u16 integer
#[macro_export]
macro_rules! u16 ( ($i:expr, $e:expr) => ( {if $e { $crate::be_u16($i) } else { $crate::le_u16($i) } } ););
/// if parameter is true, parse a big endian u32 integer,
/// otherwise a little endian u32 integer
#[macro_export]
macro_rules! u32 ( ($i:expr, $e:expr) => ( {if $e { $crate::be_u32($i) } else { $crate::le_u32($i) } } ););
/// if parameter is true, parse a big endian u64 integer,
/// otherwise a little endian u64 integer
#[macro_export]
macro_rules! u64 ( ($i:expr, $e:expr) => ( {if $e { $crate::be_u64($i) } else { $crate::le_u64($i) } } ););
/// if parameter is true, parse a big endian i16 integer,
/// otherwise a little endian i16 integer
#[macro_export]
macro_rules! i16 ( ($i:expr, $e:expr) => ( {if $e { $crate::be_i16($i) } else { $crate::le_i16($i) } } ););
/// if parameter is true, parse a big endian i32 integer,
/// otherwise a little endian i32 integer
#[macro_export]
macro_rules! i32 ( ($i:expr, $e:expr) => ( {if $e { $crate::be_i32($i) } else { $crate::le_i32($i) } } ););
/// if parameter is true, parse a big endian i64 integer,
/// otherwise a little endian i64 integer
#[macro_export]
macro_rules! i64 ( ($i:expr, $e:expr) => ( {if $e { $crate::be_i64($i) } else { $crate::le_i64($i) } } ););
/// Recognizes big endian 4 bytes floating point number
#[inline]
pub fn be_f32(input: &[u8]) -> IResult<&[u8], f32> {
match be_u32(input) {
Error(e) => Error(e),
Incomplete(e) => Incomplete(e),
Done(i,o) => {
unsafe {
Done(i, transmute::<u32, f32>(o))
}
}
}
}
/// Recognizes big endian 8 bytes floating point number
#[inline]
pub fn be_f64(input: &[u8]) -> IResult<&[u8], f64> {
match be_u64(input) {
Error(e) => Error(e),
Incomplete(e) => Incomplete(e),
Done(i,o) => {
unsafe {
Done(i, transmute::<u64, f64>(o))
}
}
}
}
/// Recognizes little endian 4 bytes floating point number
#[inline]
pub fn le_f32(input: &[u8]) -> IResult<&[u8], f32> {
match le_u32(input) {
Error(e) => Error(e),
Incomplete(e) => Incomplete(e),
Done(i,o) => {
unsafe {
Done(i, transmute::<u32, f32>(o))
}
}
}
}
/// Recognizes little endian 8 bytes floating point number
#[inline]
pub fn le_f64(input: &[u8]) -> IResult<&[u8], f64> {
match le_u64(input) {
Error(e) => Error(e),
Incomplete(e) => Incomplete(e),
Done(i,o) => {
unsafe {
Done(i, transmute::<u64, f64>(o))
}
}
}
}
/// Recognizes a hex-encoded integer
#[inline]
pub fn hex_u32(input: &[u8]) -> IResult<&[u8], u32> {
match is_a!(input, &b"0123456789abcdef"[..]) {
Error(e) => Error(e),
Incomplete(e) => Incomplete(e),
Done(i,o) => {
let mut res = 0u32;
// Do not parse more than 8 characters for a u32
let mut remaining = i;
let mut parsed = o;
if o.len() > 8 {
remaining = &input[8..];
parsed = &input[..8];
}
for &e in parsed {
let digit = e as char;
let value = digit.to_digit(16).unwrap_or(0);
res = value + (res << 4);
}
Done(remaining, res)
}
}
}
/// Recognizes empty input buffers
///
/// useful to verify that the previous parsers used all of the input
#[inline]
//pub fn eof(input:&[u8]) -> IResult<&[u8], &[u8]> {
pub fn eof<'a, T:?Sized>(input: &'a T) -> IResult<&'a T,&'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: InputLength {
if input.input_len() == 0 {
Done(input, input)
} else {
Error(Position(ErrorKind::Eof, input))
}
}
/// Recognizes non empty buffers
#[inline]
pub fn non_empty<'a, T:?Sized>(input: &'a T) -> IResult<&'a T,&'a T> where
T:Index<Range<usize>, Output=T>+Index<RangeFrom<usize>, Output=T>,
&'a T: InputLength {
if input.input_len() == 0 {
Error(Position(ErrorKind::NonEmpty, input))
} else {
Done(&input[input.input_len()..], input)
}
}
/// Return the remaining input.
#[inline]
pub fn rest(input: &[u8]) -> IResult<&[u8], &[u8]> {
IResult::Done(&input[input.len()..], input)
}
/// Return the remaining input, for strings.
#[inline]
pub fn rest_s(input: &str) -> IResult<&str, &str> {
IResult::Done(&input[input.len()..], input)
}
#[cfg(test)]
mod tests {
use super::*;
use internal::{Needed,IResult};
use internal::IResult::*;
use internal::Err::*;
use util::ErrorKind;
#[test]
fn tag_closure() {
let x = tag_cl(&b"abcd"[..]);
let r = x(&b"abcdabcdefgh"[..]);
assert_eq!(r, Done(&b"abcdefgh"[..], &b"abcd"[..]));
let r2 = x(&b"abcefgh"[..]);
assert_eq!(r2, Error(Position(ErrorKind::TagClosure, &b"abcefgh"[..])));
}
#[test]
fn character() {
let empty: &[u8] = b"";
let a: &[u8] = b"abcd";
let b: &[u8] = b"1234";
let c: &[u8] = b"a123";
let d: &[u8] = "azé12".as_bytes();
let e: &[u8] = b" ";
assert_eq!(alpha(a), Done(empty, a));
assert_eq!(alpha(b), Error(Position(ErrorKind::Alpha,b)));
assert_eq!(alpha(c), Done(&c[1..], &b"a"[..]));
assert_eq!(alpha(d), Done("é12".as_bytes(), &b"az"[..]));
assert_eq!(digit(a), Error(Position(ErrorKind::Digit,a)));
assert_eq!(digit(b), Done(empty, b));
assert_eq!(digit(c), Error(Position(ErrorKind::Digit,c)));
assert_eq!(digit(d), Error(Position(ErrorKind::Digit,d)));
assert_eq!(hex_digit(a), Done(empty, a));
assert_eq!(hex_digit(b), Done(empty, b));
assert_eq!(hex_digit(c), Done(empty, c));
assert_eq!(hex_digit(d), Done("zé12".as_bytes(), &b"a"[..]));
assert_eq!(hex_digit(e), Error(Position(ErrorKind::HexDigit,e)));
assert_eq!(oct_digit(a), Error(Position(ErrorKind::OctDigit,a)));
assert_eq!(oct_digit(b), Done(empty, b));
assert_eq!(oct_digit(c), Error(Position(ErrorKind::OctDigit,c)));
assert_eq!(oct_digit(d), Error(Position(ErrorKind::OctDigit,d)));
assert_eq!(alphanumeric(a), Done(empty, a));
assert_eq!(fix_error!(b,(), alphanumeric), Done(empty, b));
assert_eq!(alphanumeric(c), Done(empty, c));
assert_eq!(alphanumeric(d), Done("é12".as_bytes(), &b"az"[..]));
assert_eq!(space(e), Done(&b""[..], &b" "[..]));
}
#[test]
fn character_s() {
let empty = "";
let a = "abcd";
let b = "1234";
let c = "a123";
let d = "azé12";
let e = " ";
assert_eq!(alpha(a), Done(empty, a));
assert_eq!(alpha(b), Error(Position(ErrorKind::Alpha,b)));
assert_eq!(alpha(c), Done(&c[1..], &"a"[..]));
assert_eq!(alpha(d), Done("12", &"azé"[..]));
assert_eq!(digit(a), Error(Position(ErrorKind::Digit,a)));
assert_eq!(digit(b), Done(empty, b));
assert_eq!(digit(c), Error(Position(ErrorKind::Digit,c)));
assert_eq!(digit(d), Error(Position(ErrorKind::Digit,d)));
assert_eq!(hex_digit(a), Done(empty, a));
assert_eq!(hex_digit(b), Done(empty, b));
assert_eq!(hex_digit(c), Done(empty, c));
assert_eq!(hex_digit(d), Done("zé12", &"a"[..]));
assert_eq!(hex_digit(e), Error(Position(ErrorKind::HexDigit,e)));
assert_eq!(oct_digit(a), Error(Position(ErrorKind::OctDigit,a)));
assert_eq!(oct_digit(b), Done(empty, b));
assert_eq!(oct_digit(c), Error(Position(ErrorKind::OctDigit,c)));
assert_eq!(oct_digit(d), Error(Position(ErrorKind::OctDigit,d)));
assert_eq!(alphanumeric(a), Done(empty, a));
assert_eq!(fix_error!(b,(), alphanumeric), Done(empty, b));
assert_eq!(alphanumeric(c), Done(empty, c));
assert_eq!(alphanumeric(d), Done("", &"azé12"[..]));
assert_eq!(space(e), Done(&""[..], &" "[..]));
}
use util::HexDisplay;
#[test]
fn offset() {
let a = &b"abcd"[..];
let b = &b"1234"[..];
let c = &b"a123"[..];
let d = &b" \t"[..];
let e = &b" \t\r\n"[..];
let f = &b"123abcDEF"[..];
match alpha(a) {
Done(i, _) => { assert_eq!(a.offset(i) + i.len(), a.len()); }
_ => { panic!("wrong return type in offset test for alpha") }
}
match digit(b) {
Done(i, _) => { assert_eq!(b.offset(i) + i.len(), b.len()); }
_ => { panic!("wrong return type in offset test for digit") }
}
match alphanumeric(c) {
Done(i, _) => { assert_eq!(c.offset(i) + i.len(), c.len()); }
_ => { panic!("wrong return type in offset test for alphanumeric") }
}
match space(d) {
Done(i, _) => { assert_eq!(d.offset(i) + i.len(), d.len()); }
_ => { panic!("wrong return type in offset test for space") }
}
match multispace(e) {
Done(i, _) => { assert_eq!(e.offset(i) + i.len(), e.len()); }
_ => { panic!("wrong return type in offset test for multispace") }
}
match hex_digit(f) {
Done(i, _) => { assert_eq!(f.offset(i) + i.len(), f.len()); }
_ => { panic!("wrong return type in offset test for hex_digit") }
}
match oct_digit(f) {
Done(i, _) => { assert_eq!(f.offset(i) + i.len(), f.len()); }
_ => { panic!("wrong return type in offset test for oct_digit") }
}
}
#[test]
fn is_not() {
let a: &[u8] = b"ab12cd\nefgh";
assert_eq!(not_line_ending(a), Done(&b"\nefgh"[..], &b"ab12cd"[..]));
let b: &[u8] = b"ab12cd\nefgh\nijkl";
assert_eq!(not_line_ending(b), Done(&b"\nefgh\nijkl"[..], &b"ab12cd"[..]));
let c: &[u8] = b"ab12cd";
assert_eq!(not_line_ending(c), Done(&b""[..], c));
}
#[test]
fn buffer_with_size() {
let i:Vec<u8> = vec![7,8];
let o:Vec<u8> = vec![4,5,6];
//let arr:[u8; 6usize] = [3, 4, 5, 6, 7, 8];
let arr:[u8; 6usize] = [3, 4, 5, 6, 7, 8];
let res = sized_buffer(&arr[..]);
assert_eq!(res, Done(&i[..], &o[..]))
}
/*#[test]
fn t1() {
let v1:Vec<u8> = vec![1,2,3];
let v2:Vec<u8> = vec![4,5,6];
let d = Done(&v1[..], &v2[..]);
let res = d.flat_map(print);
assert_eq!(res, Done(&v2[..], ()));
}*/
#[test]
fn length_value_test() {
let i1 = vec![7,8];
let o1 = vec![4, 5, 6];
let arr1:[u8; 6usize] = [3, 4, 5, 6, 7, 8];
let res1 = length_value(&arr1);
assert_eq!(Done(&i1[..], &o1[..]), res1);
let i2:Vec<u8> = vec![4,5,6,7,8];
let o2: &[u8] = b"";
let arr2:[u8; 6usize] = [0, 4, 5, 6, 7, 8];
let res2 = length_value(&arr2);
assert_eq!(Done(&i2[..], o2), res2);
let arr3:[u8; 7usize] = [8, 4, 5, 6, 7, 8, 9];
let res3 = length_value(&arr3);
//FIXME: should be incomplete
assert_eq!(Incomplete(Needed::Size(9)), res3);
}
#[test]
fn i8_tests() {
assert_eq!(be_i8(&[0x00]), Done(&b""[..], 0));
assert_eq!(be_i8(&[0x7f]), Done(&b""[..], 127));
assert_eq!(be_i8(&[0xff]), Done(&b""[..], -1));
assert_eq!(be_i8(&[0x80]), Done(&b""[..], -128));
}
#[test]
fn i16_tests() {
assert_eq!(be_i16(&[0x00, 0x00]), Done(&b""[..], 0));
assert_eq!(be_i16(&[0x7f, 0xff]), Done(&b""[..], 32767_i16));
assert_eq!(be_i16(&[0xff, 0xff]), Done(&b""[..], -1));
assert_eq!(be_i16(&[0x80, 0x00]), Done(&b""[..], -32768_i16));
}
#[test]
fn i32_tests() {
assert_eq!(be_i32(&[0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0));
assert_eq!(be_i32(&[0x7f, 0xff, 0xff, 0xff]), Done(&b""[..], 2147483647_i32));
assert_eq!(be_i32(&[0xff, 0xff, 0xff, 0xff]), Done(&b""[..], -1));
assert_eq!(be_i32(&[0x80, 0x00, 0x00, 0x00]), Done(&b""[..], -2147483648_i32));
}
#[test]
fn i64_tests() {
assert_eq!(be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0));
assert_eq!(be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), Done(&b""[..], 9223372036854775807_i64));
assert_eq!(be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), Done(&b""[..], -1));
assert_eq!(be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), Done(&b""[..], -9223372036854775808_i64));
}
#[test]
fn le_i8_tests() {
assert_eq!(le_i8(&[0x00]), Done(&b""[..], 0));
assert_eq!(le_i8(&[0x7f]), Done(&b""[..], 127));
assert_eq!(le_i8(&[0xff]), Done(&b""[..], -1));
assert_eq!(le_i8(&[0x80]), Done(&b""[..], -128));
}
#[test]
fn le_i16_tests() {
assert_eq!(le_i16(&[0x00, 0x00]), Done(&b""[..], 0));
assert_eq!(le_i16(&[0xff, 0x7f]), Done(&b""[..], 32767_i16));
assert_eq!(le_i16(&[0xff, 0xff]), Done(&b""[..], -1));
assert_eq!(le_i16(&[0x00, 0x80]), Done(&b""[..], -32768_i16));
}
#[test]
fn le_i32_tests() {
assert_eq!(le_i32(&[0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0));
assert_eq!(le_i32(&[0xff, 0xff, 0xff, 0x7f]), Done(&b""[..], 2147483647_i32));
assert_eq!(le_i32(&[0xff, 0xff, 0xff, 0xff]), Done(&b""[..], -1));
assert_eq!(le_i32(&[0x00, 0x00, 0x00, 0x80]), Done(&b""[..], -2147483648_i32));
}
#[test]
fn le_i64_tests() {
assert_eq!(le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0));
assert_eq!(le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]), Done(&b""[..], 9223372036854775807_i64));
assert_eq!(le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), Done(&b""[..], -1));
assert_eq!(le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), Done(&b""[..], -9223372036854775808_i64));
}
#[test]
fn be_f32_tests() {
assert_eq!(be_f32(&[0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0_f32));
assert_eq!(be_f32(&[0x4d, 0x31, 0x1f, 0xd8]), Done(&b""[..], 185728392_f32));
}
#[test]
fn be_f64_tests() {
assert_eq!(be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0_f64));
assert_eq!(be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00]), Done(&b""[..], 185728392_f64));
}
#[test]
fn le_f32_tests() {
assert_eq!(le_f32(&[0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0_f32));
assert_eq!(le_f32(&[0xd8, 0x1f, 0x31, 0x4d]), Done(&b""[..], 185728392_f32));
}
#[test]
fn le_f64_tests() {
assert_eq!(le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), Done(&b""[..], 0_f64));
assert_eq!(le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41]), Done(&b""[..], 185728392_f64));
}
#[test]
fn hex_u32_tests() {
assert_eq!(hex_u32(&b""[..]), Done(&b""[..], 0));
assert_eq!(hex_u32(&b"ff"[..]), Done(&b""[..], 255));
assert_eq!(hex_u32(&b"1be2"[..]), Done(&b""[..], 7138));
assert_eq!(hex_u32(&b"c5a31be2"[..]), Done(&b""[..], 3315801058));
assert_eq!(hex_u32(&b"00c5a31be2"[..]), Done(&b"e2"[..], 12952347));
assert_eq!(hex_u32(&b"c5a31be201"[..]), Done(&b"01"[..], 3315801058));
assert_eq!(hex_u32(&b"ffffffff"[..]), Done(&b""[..], 4294967295));
assert_eq!(hex_u32(&b"0x1be2"[..]), Done(&b"x1be2"[..], 0));
}
#[test]
fn end_of_input() {
let not_over = &b"Hello, world!"[..];
let is_over = &b""[..];
let res_not_over = eof(not_over);
assert_eq!(res_not_over, Error(Position(ErrorKind::Eof, not_over)));
let res_over = eof(is_over);
assert_eq!(res_over, Done(is_over, is_over));
}
#[test]
fn configurable_endianness() {
named!(be_tst16<u16>, u16!(true));
named!(le_tst16<u16>, u16!(false));
assert_eq!(be_tst16(&[0x80, 0x00]), Done(&b""[..], 32768_u16));
assert_eq!(le_tst16(&[0x80, 0x00]), Done(&b""[..], 128_u16));
named!(be_tst32<u32>, u32!(true));
named!(le_tst32<u32>, u32!(false));
assert_eq!(be_tst32(&[0x12, 0x00, 0x60, 0x00]), Done(&b""[..], 302014464_u32));
assert_eq!(le_tst32(&[0x12, 0x00, 0x60, 0x00]), Done(&b""[..], 6291474_u32));
named!(be_tst64<u64>, u64!(true));
named!(le_tst64<u64>, u64!(false));
assert_eq!(be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), Done(&b""[..], 1297142246100992000_u64));
assert_eq!(le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), Done(&b""[..], 36028874334666770_u64));
named!(be_tsti16<i16>, i16!(true));
named!(le_tsti16<i16>, i16!(false));
assert_eq!(be_tsti16(&[0x00, 0x80]), Done(&b""[..], 128_i16));
assert_eq!(le_tsti16(&[0x00, 0x80]), Done(&b""[..], -32768_i16));
named!(be_tsti32<i32>, i32!(true));
named!(le_tsti32<i32>, i32!(false));
assert_eq!(be_tsti32(&[0x00, 0x12, 0x60, 0x00]), Done(&b""[..], 1204224_i32));
assert_eq!(le_tsti32(&[0x00, 0x12, 0x60, 0x00]), Done(&b""[..], 6296064_i32));
named!(be_tsti64<i64>, i64!(true));
named!(le_tsti64<i64>, i64!(false));
assert_eq!(be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), Done(&b""[..], 71881672479506432_i64));
assert_eq!(le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]), Done(&b""[..], 36028874334732032_i64));
}
#[test]
fn manual_configurable_endianness_test() {
let x = 1;
let int_parse: Box<Fn(&[u8]) -> IResult<&[u8], u16> > = if x == 2 {
Box::new(be_u16)
} else {
Box::new(le_u16)
};
println!("{:?}", int_parse(&b"3"[..]));
assert_eq!(int_parse(&[0x80, 0x00]), Done(&b""[..], 128_u16));
}
#[allow(dead_code)]
fn custom_error(input: &[u8]) -> IResult<&[u8], &[u8], ()> {
fix_error!(input, (), alphanumeric)
}
#[test]
fn hex_digit_test() {
let empty = &b""[..];
let i = &b"0123456789abcdefABCDEF"[..];
assert_eq!(hex_digit(i), Done(empty, i));
let i = &b"g"[..];
assert_eq!(hex_digit(i), Error(Position(ErrorKind::HexDigit,i)));
let i = &b"G"[..];
assert_eq!(hex_digit(i), Error(Position(ErrorKind::HexDigit,i)));
assert!(is_hex_digit(b'0'));
assert!(is_hex_digit(b'9'));
assert!(is_hex_digit(b'a'));
assert!(is_hex_digit(b'f'));
assert!(is_hex_digit(b'A'));
assert!(is_hex_digit(b'F'));
assert!(!is_hex_digit(b'g'));
assert!(!is_hex_digit(b'G'));
assert!(!is_hex_digit(b'/'));
assert!(!is_hex_digit(b':'));
assert!(!is_hex_digit(b'@'));
assert!(!is_hex_digit(b'\x60'));
}
#[test]
fn oct_digit_test() {
let empty = &b""[..];
let i = &b"01234567"[..];
assert_eq!(oct_digit(i), Done(empty, i));
let i = &b"8"[..];
assert_eq!(oct_digit(i), Error(Position(ErrorKind::OctDigit,i)));
assert!(is_oct_digit(b'0'));
assert!(is_oct_digit(b'7'));
assert!(!is_oct_digit(b'8'));
assert!(!is_oct_digit(b'9'));
assert!(!is_oct_digit(b'a'));
assert!(!is_oct_digit(b'A'));
assert!(!is_oct_digit(b'/'));
assert!(!is_oct_digit(b':'));
assert!(!is_oct_digit(b'@'));
assert!(!is_oct_digit(b'\x60'));
}
}

644
third_party/rust/nom-1.2.4/src/regexp.rs поставляемый
Просмотреть файл

@ -1,644 +0,0 @@
#[doc(hidden)]
#[macro_export]
macro_rules! regex (
($re: ident, $s:expr) => (
lazy_static! {
static ref $re: ::regex::Regex = ::regex::Regex::new($s).unwrap();
}
);
);
#[doc(hidden)]
#[macro_export]
macro_rules! regex_bytes (
($re: ident, $s:expr) => (
lazy_static! {
static ref $re: ::regex::bytes::Regex = ::regex::bytes::Regex::new($s).unwrap();
}
);
);
/// `re_match!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the whole input if a match is found
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_match (
($i:expr, $re:expr) => (
{
use $crate::InputLength;
let re = ::regex::Regex::new($re).unwrap();
if re.is_match($i) {
$crate::IResult::Done(&$i[$i.input_len()..], $i)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatch))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_match_static!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the whole input if a match is found. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_match_static (
($i:expr, $re:expr) => (
{
use $crate::InputLength;
regex!(RE, $re);
if RE.is_match($i) {
$crate::IResult::Done(&$i[$i.input_len()..], $i)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatch))
}
}
)
);
/// `re_bytes_match!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the whole input if a match is found
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_bytes_match (
($i:expr, $re:expr) => (
{
use $crate::InputLength;
let re = ::regex::bytes::Regex::new($re).unwrap();
if re.is_match($i) {
$crate::IResult::Done(&$i[$i.input_len()..], $i)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatch))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_bytes_match_static!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the whole input if a match is found. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_bytes_match_static (
($i:expr, $re:expr) => (
{
use $crate::InputLength;
regex_bytes!(RE, $re);
if RE.is_match($i) {
$crate::IResult::Done(&$i[$i.input_len()..], $i)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatch))
}
}
)
);
/// `re_find!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the first match
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_find (
($i:expr, $re:expr) => (
{
let re = ::regex::Regex::new($re).unwrap();
if let Some((begin, end)) = re.find($i) {
$crate::IResult::Done(&$i[end..], &$i[begin..end])
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpFind))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_find_static!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the first match. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_find_static (
($i:expr, $re:expr) => (
{
regex!(RE, $re);
if let Some((begin, end)) = RE.find($i) {
$crate::IResult::Done(&$i[end..], &$i[begin..end])
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpFind))
}
}
)
);
/// `re_bytes_find!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the first match
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_bytes_find (
($i:expr, $re:expr) => (
{
let re = ::regex::bytes::Regex::new($re).unwrap();
if let Some((begin, end)) = re.find($i) {
$crate::IResult::Done(&$i[end..], &$i[begin..end])
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpFind))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_bytes_find!(regexp) => &[T] -> IResult<&[T], &[T]>`
/// Returns the first match. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_bytes_find_static (
($i:expr, $re:expr) => (
{
regex_bytes!(RE, $re);
if let Some((begin, end)) = RE.find($i) {
$crate::IResult::Done(&$i[end..], &$i[begin..end])
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpFind))
}
}
)
);
/// `re_matches!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns all the matched parts
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_matches (
($i:expr, $re:expr) => (
{
let re = ::regex::Regex::new($re).unwrap();
let v: Vec<&str> = re.find_iter($i).map(|(begin,end)| &$i[begin..end]).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatches))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_matches_static!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns all the matched parts. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_matches_static (
($i:expr, $re:expr) => (
{
regex!(RE, $re);
let v: Vec<&str> = RE.find_iter($i).map(|(begin,end)| &$i[begin..end]).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatches))
}
}
)
);
/// `re_bytes_matches!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns all the matched parts
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_bytes_matches (
($i:expr, $re:expr) => (
{
let re = ::regex::bytes::Regex::new($re).unwrap();
let v: Vec<&[u8]> = re.find_iter($i).map(|(begin,end)| &$i[begin..end]).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatches))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_bytes_matches_static!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns all the matched parts. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_bytes_matches_static (
($i:expr, $re:expr) => (
{
regex_bytes!(RE, $re);
let v: Vec<&[u8]> = RE.find_iter($i).map(|(begin,end)| &$i[begin..end]).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpMatches))
}
}
)
);
/// `re_capture!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns the first capture group
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_capture (
($i:expr, $re:expr) => (
{
let re = ::regex::Regex::new($re).unwrap();
if let Some(c) = re.captures($i) {
let v:Vec<&str> = c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect();
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_capture_static!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns the first capture group. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_capture_static (
($i:expr, $re:expr) => (
{
regex!(RE, $re);
if let Some(c) = RE.captures($i) {
let v:Vec<&str> = c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect();
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
/// `re_bytes_capture!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns the first capture group
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_bytes_capture (
($i:expr, $re:expr) => (
{
let re = ::regex::bytes::Regex::new($re).unwrap();
if let Some(c) = re.captures($i) {
let v:Vec<&[u8]> = c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect();
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_bytes_capture_static!(regexp) => &[T] -> IResult<&[T], Vec<&[T]>>`
/// Returns the first capture group. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_bytes_capture_static (
($i:expr, $re:expr) => (
{
regex_bytes!(RE, $re);
if let Some(c) = RE.captures($i) {
let v:Vec<&[u8]> = c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect();
let offset = {
let end = v.last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
/// `re_captures!(regexp) => &[T] -> IResult<&[T], Vec<Vec<&[T]>>>`
/// Returns all the capture groups
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_captures (
($i:expr, $re:expr) => (
{
let re = ::regex::Regex::new($re).unwrap();
let v:Vec<Vec<&str>> = re.captures_iter($i).map(|c| c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect()).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap().last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_captures_static!(regexp) => &[T] -> IResult<&[T], Vec<Vec<&[T]>>>`
/// Returns all the capture groups. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_captures_static (
($i:expr, $re:expr) => (
{
regex!(RE, $re);
let v:Vec<Vec<&str>> = RE.captures_iter($i).map(|c| c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect()).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap().last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
/// `re_bytes_captures!(regexp) => &[T] -> IResult<&[T], Vec<Vec<&[T]>>>`
/// Returns all the capture groups
///
/// requires the `regexp` feature
#[macro_export]
macro_rules! re_bytes_captures (
($i:expr, $re:expr) => (
{
let re = ::regex::bytes::Regex::new($re).unwrap();
let v:Vec<Vec<&[u8]>> = re.captures_iter($i).map(|c| c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect()).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap().last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
#[cfg(feature = "regexp_macros")]
/// `re_bytes_captures_static!(regexp) => &[T] -> IResult<&[T], Vec<Vec<&[T]>>>`
/// Returns all the capture groups. Regular expression calculated at compile time
///
/// requires the `regexp_macros` feature
#[macro_export]
macro_rules! re_bytes_captures_static (
($i:expr, $re:expr) => (
{
regex_bytes!(RE, $re);
let v:Vec<Vec<&[u8]>> = RE.captures_iter($i).map(|c| c.iter_pos().filter(|el| el.is_some()).map(|el| el.unwrap()).map(|(begin,end)| &$i[begin..end]).collect()).collect();
if v.len() != 0 {
let offset = {
let end = v.last().unwrap().last().unwrap();
end.as_ptr() as usize + end.len() - $i.as_ptr() as usize
};
$crate::IResult::Done(&$i[offset..], v)
} else {
$crate::IResult::Error($crate::Err::Code($crate::ErrorKind::RegexpCapture))
}
}
)
);
#[cfg(test)]
mod tests {
use internal::IResult::*;
use internal::Err::*;
use util::ErrorKind;
#[test]
fn re_match() {
named!(rm<&str,&str>, re_match!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm("2015-09-07"), Done("", "2015-09-07"));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpMatch)));
assert_eq!(rm("2015-09-07blah"), Done("", "2015-09-07blah"));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_match_static() {
named!(rm<&str,&str>, re_match_static!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm("2015-09-07"), Done("", "2015-09-07"));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpMatch)));
assert_eq!(rm("2015-09-07blah"), Done("", "2015-09-07blah"));
}
#[test]
fn re_find() {
named!(rm<&str,&str>, re_find!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm("2015-09-07"), Done("", "2015-09-07"));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpFind)));
assert_eq!(rm("2015-09-07blah"), Done("blah", "2015-09-07"));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_find_static() {
named!(rm<&str,&str>, re_find_static!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm("2015-09-07"), Done("", "2015-09-07"));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpFind)));
assert_eq!(rm("2015-09-07blah"), Done("blah", "2015-09-07"));
}
#[test]
fn re_matches() {
named!(rm< &str,Vec<&str> >, re_matches!(r"\d{4}-\d{2}-\d{2}"));
assert_eq!(rm("2015-09-07"), Done("", vec!["2015-09-07"]));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpMatches)));
assert_eq!(rm("aaa2015-09-07blah2015-09-09pouet"), Done("pouet", vec!["2015-09-07", "2015-09-09"]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_matches_static() {
named!(rm< &str,Vec<&str> >, re_matches_static!(r"\d{4}-\d{2}-\d{2}"));
assert_eq!(rm("2015-09-07"), Done("", vec!["2015-09-07"]));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpMatches)));
assert_eq!(rm("aaa2015-09-07blah2015-09-09pouet"), Done("pouet", vec!["2015-09-07", "2015-09-09"]));
}
#[test]
fn re_capture() {
named!(rm< &str,Vec<&str> >, re_capture!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm("blah nom 0.3.11pouet"), Done("pouet", vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm("hello nom 0.3.11 world regex 0.1.41"), Done(" world regex 0.1.41", vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_capture_static() {
named!(rm< &str,Vec<&str> >, re_capture_static!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm("blah nom 0.3.11pouet"), Done("pouet", vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm("hello nom 0.3.11 world regex 0.1.41"), Done(" world regex 0.1.41", vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]));
}
#[test]
fn re_captures() {
named!(rm< &str,Vec<Vec<&str>> >, re_captures!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm("blah nom 0.3.11pouet"), Done("pouet", vec![vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]]));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm("hello nom 0.3.11 world regex 0.1.41 aaa"), Done(" aaa", vec![
vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"],
vec!["regex 0.1.41", "regex", "0.1.41", "0", "1", "41"],
]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_captures_static() {
named!(rm< &str,Vec<Vec<&str>> >, re_captures_static!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm("blah nom 0.3.11pouet"), Done("pouet", vec![vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"]]));
assert_eq!(rm("blah"), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm("hello nom 0.3.11 world regex 0.1.41 aaa"), Done(" aaa", vec![
vec!["nom 0.3.11", "nom", "0.3.11", "0", "3", "11"],
vec!["regex 0.1.41", "regex", "0.1.41", "0", "1", "41"],
]));
}
#[test]
fn re_bytes_match() {
named!(rm, re_bytes_match!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm(&b"2015-09-07"[..]), Done(&b""[..], &b"2015-09-07"[..]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpMatch)));
assert_eq!(rm(&b"2015-09-07blah"[..]), Done(&b""[..], &b"2015-09-07blah"[..]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_bytes_match_static() {
named!(rm, re_bytes_match_static!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm(&b"2015-09-07"[..]), Done(&b""[..], &b"2015-09-07"[..]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpMatch)));
assert_eq!(rm(&b"2015-09-07blah"[..]), Done(&b""[..], &b"2015-09-07blah"[..]));
}
#[test]
fn re_bytes_find() {
named!(rm, re_bytes_find!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm(&b"2015-09-07"[..]), Done(&b""[..], &b"2015-09-07"[..]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpFind)));
assert_eq!(rm(&b"2015-09-07blah"[..]), Done(&b"blah"[..], &b"2015-09-07"[..]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_bytes_find_static() {
named!(rm, re_bytes_find_static!(r"^\d{4}-\d{2}-\d{2}"));
assert_eq!(rm(&b"2015-09-07"[..]), Done(&b""[..], &b"2015-09-07"[..]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpFind)));
assert_eq!(rm(&b"2015-09-07blah"[..]), Done(&b"blah"[..], &b"2015-09-07"[..]));
}
#[test]
fn re_bytes_matches() {
named!(rm<Vec<&[u8]> >, re_bytes_matches!(r"\d{4}-\d{2}-\d{2}"));
assert_eq!(rm(&b"2015-09-07"[..]), Done(&b""[..], vec![&b"2015-09-07"[..]]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpMatches)));
assert_eq!(rm(&b"aaa2015-09-07blah2015-09-09pouet"[..]), Done(&b"pouet"[..], vec![&b"2015-09-07"[..], &b"2015-09-09"[..]]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_bytes_matches_static() {
named!(rm<Vec<&[u8]> >, re_bytes_matches_static!(r"\d{4}-\d{2}-\d{2}"));
assert_eq!(rm(&b"2015-09-07"[..]), Done(&b""[..], vec![&b"2015-09-07"[..]]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpMatches)));
assert_eq!(rm(&b"aaa2015-09-07blah2015-09-09pouet"[..]), Done(&b"pouet"[..], vec![&b"2015-09-07"[..], &b"2015-09-09"[..]]));
}
#[test]
fn re_bytes_capture() {
named!(rm<Vec<&[u8]> >, re_bytes_capture!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm(&b"blah nom 0.3.11pouet"[..]), Done(&b"pouet"[..], vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm(&b"hello nom 0.3.11 world regex 0.1.41"[..]), Done(&b" world regex 0.1.41"[..], vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_bytes_capture_static() {
named!(rm< Vec<&[u8]> >, re_bytes_capture_static!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm(&b"blah nom 0.3.11pouet"[..]), Done(&b"pouet"[..], vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm(&b"hello nom 0.3.11 world regex 0.1.41"[..]), Done(&b" world regex 0.1.41"[..], vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]]));
}
#[test]
fn re_bytes_captures() {
named!(rm< Vec<Vec<&[u8]>> >, re_bytes_captures!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm(&b"blah nom 0.3.11pouet"[..]), Done(&b"pouet"[..], vec![vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]]]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm(&b"hello nom 0.3.11 world regex 0.1.41 aaa"[..]), Done(&b" aaa"[..], vec![
vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]],
vec![&b"regex 0.1.41"[..], &b"regex"[..], &b"0.1.41"[..], &b"0"[..], &b"1"[..], &b"41"[..]],
]));
}
#[cfg(feature = "regexp_macros")]
#[test]
fn re_bytes_captures_static() {
named!(rm< Vec<Vec<&[u8]>> >, re_bytes_captures_static!(r"([:alpha:]+)\s+((\d+).(\d+).(\d+))"));
assert_eq!(rm(&b"blah nom 0.3.11pouet"[..]), Done(&b"pouet"[..], vec![vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]]]));
assert_eq!(rm(&b"blah"[..]), Error(Code(ErrorKind::RegexpCapture)));
assert_eq!(rm(&b"hello nom 0.3.11 world regex 0.1.41 aaa"[..]), Done(&b" aaa"[..], vec![
vec![&b"nom 0.3.11"[..], &b"nom"[..], &b"0.3.11"[..], &b"0"[..], &b"3"[..], &b"11"[..]],
vec![&b"regex 0.1.41"[..], &b"regex"[..], &b"0.1.41"[..], &b"0"[..], &b"1"[..], &b"41"[..]],
]));
}
}

734
third_party/rust/nom-1.2.4/src/str.rs поставляемый
Просмотреть файл

@ -1,734 +0,0 @@
//! Parsers and helper functions operating on strings, especially useful when writing parsers for
//! text-based formats.
/// `tag_s!(&str) => &str -> IResult<&str, &str>`
/// declares a string as a suite to recognize
///
/// consumes the recognized characters
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::{self,Done};
/// # fn main() {
/// fn test(input: &str) -> IResult<&str, &str> {
/// tag_s!(input, "abcd")
/// }
/// let r = test("abcdefgh");
/// assert_eq!(r, Done("efgh", "abcd"));
/// # }
/// ```
#[macro_export]
macro_rules! tag_s (
($i:expr, $tag: expr) => (
{
let res: $crate::IResult<_,_> = if $tag.len() > $i.len() {
$crate::IResult::Incomplete($crate::Needed::Size($tag.len()))
//} else if &$i[0..$tag.len()] == $tag {
} else if ($i).starts_with($tag) {
$crate::IResult::Done(&$i[$tag.len()..], &$i[0..$tag.len()])
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TagStr, $i))
};
res
}
);
);
/// `take_s!(nb) => &str -> IResult<&str, &str>`
/// generates a parser consuming the specified number of characters
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
/// // Desmond parser
/// named!(take5<&str,&str>, take_s!( 5 ) );
///
/// let a = "abcdefgh";
///
/// assert_eq!(take5(a), Done("fgh", "abcde"));
/// # }
/// ```
#[macro_export]
macro_rules! take_s (
($i:expr, $count:expr) => (
{
let cnt = $count as usize;
let res: $crate::IResult<_,_> = if $i.chars().count() < cnt {
$crate::IResult::Incomplete($crate::Needed::Size(cnt))
} else {
let mut offset = $i.len();
let mut count = 0;
for (o, _) in $i.char_indices() {
if count == cnt {
offset = o;
break;
}
count += 1;
}
$crate::IResult::Done(&$i[offset..], &$i[..offset])
};
res
}
);
);
/// `is_not_s!(&str) => &str -> IResult<&str, &str>`
/// returns the longest list of characters that do not appear in the provided array
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
/// named!( not_space<&str,&str>, is_not_s!( " \t\r\n" ) );
///
/// let r = not_space("abcdefgh\nijkl");
/// assert_eq!(r, Done("\nijkl", "abcdefgh"));
/// # }
/// ```
#[macro_export]
macro_rules! is_not_s (
($input:expr, $arr:expr) => (
{
use std::collections::HashSet;
let set: HashSet<char> = $arr.chars().collect();
let mut offset = $input.len();
for (o, c) in $input.char_indices() {
if set.contains(&c) {
offset = o;
break;
}
}
if offset == 0 {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::IsAStr,$input))
} else if offset < $input.len() {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Done("", $input)
}
}
);
);
/// `is_a_s!(&str) => &str -> IResult<&str, &str>`
/// returns the longest list of characters that appear in the provided array
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # fn main() {
/// named!(abcd<&str, &str>, is_a_s!( "abcd" ));
///
/// let r1 = abcd("aaaaefgh");
/// assert_eq!(r1, Done("efgh", "aaaa"));
///
/// let r2 = abcd("dcbaefgh");
/// assert_eq!(r2, Done("efgh", "dcba"));
/// # }
/// ```
#[macro_export]
macro_rules! is_a_s (
($input:expr, $arr:expr) => (
{
use std::collections::HashSet;
let set: HashSet<char> = $arr.chars().collect();
let mut offset = $input.len();
for (o, c) in $input.char_indices() {
if !set.contains(&c) {
offset = o;
break;
}
}
if offset == 0 {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::IsAStr,$input))
} else if offset < $input.len() {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Done("", $input)
}
}
);
);
/// `take_while_s!(char -> bool) => &str -> IResult<&str, &str>`
/// returns the longest list of characters until the provided function fails.
///
/// The argument is either a function `char -> bool` or a macro returning a `bool
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # use nom::is_alphanumeric;
/// # fn main() {
/// fn alphabetic(chr: char) -> bool { (chr >= 0x41 as char && chr <= 0x5A as char) || (chr >= 0x61 as char && chr <= 0x7A as char) }
/// named!( alpha<&str,&str>, take_while_s!( alphabetic ) );
///
/// let r = alpha("abcd\nefgh");
/// assert_eq!(r, Done("\nefgh", "abcd"));
/// # }
/// ```
#[macro_export]
macro_rules! take_while_s (
($input:expr, $submac:ident!( $($args:tt)* )) => (
{
let mut offset = $input.len();
for (o, c) in $input.char_indices() {
if !$submac!(c, $($args)*) {
offset = o;
break;
}
}
if offset < $input.len() {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Done("", $input)
}
}
);
($input:expr, $f:expr) => (
take_while_s!($input, call!($f));
);
);
/// `take_while1_s!(char -> bool) => &str -> IResult<&str, &str>`
/// returns the longest (non empty) list of characters until the provided function fails.
///
/// The argument is either a function `char -> bool` or a macro returning a `bool`
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::IResult::Done;
/// # use nom::is_alphanumeric;
/// # fn main() {
/// fn alphabetic(chr: char) -> bool { (chr >= 0x41 as char && chr <= 0x5A as char) || (chr >= 0x61 as char && chr <= 0x7A as char) }
/// named!( alpha<&str,&str>, take_while1_s!( alphabetic ) );
///
/// let r = alpha("abcd\nefgh");
/// assert_eq!(r, Done("\nefgh", "abcd"));
/// # }
/// ```
#[macro_export]
macro_rules! take_while1_s (
($input:expr, $submac:ident!( $($args:tt)* )) => (
{
let mut offset = $input.len();
for (o, c) in $input.char_indices() {
if !$submac!(c, $($args)*) {
offset = o;
break;
}
}
if offset == 0 {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TakeWhile1Str,$input))
} else if offset < $input.len() {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Done("", $input)
}
}
);
($input:expr, $f:expr) => (
take_while1_s!($input, call!($f));
);
);
/// `take_till_s!(&str -> bool) => &str -> IResult<&str, &str>`
/// returns the longest list of characters until the provided function succeeds
///
/// The argument is either a function `char -> bool` or a macro returning a `bool
#[macro_export]
macro_rules! take_till_s (
($input:expr, $submac:ident!( $($args:tt)* )) => (
{
let mut offset = $input.len();
for (o, c) in $input.char_indices() {
if $submac!(c, $($args)*) {
offset = o;
break;
}
}
if offset < $input.len() {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Done("", $input)
}
}
);
($input:expr, $f:expr) => (
take_till_s!($input, call!($f));
);
);
/// `take_until_and_consume_s!(&str) => &str -> IResult<&str, &str>`
/// generates a parser consuming all chars until the specified string is found and consumes it
#[macro_export]
macro_rules! take_until_and_consume_s (
($input:expr, $substr:expr) => (
{
#[inline(always)]
fn shift_window_and_cmp(window: & mut ::std::vec::Vec<char>, c: char, substr_vec: & ::std::vec::Vec<char>) -> bool {
window.push(c);
if window.len() > substr_vec.len() {
window.remove(0);
}
window == substr_vec
}
let res: $crate::IResult<_, _> = if $substr.len() > $input.len() {
$crate::IResult::Incomplete($crate::Needed::Size($substr.len()))
} else {
let substr_vec: ::std::vec::Vec<char> = $substr.chars().collect();
let mut window: ::std::vec::Vec<char> = vec![];
let mut offset = $input.len();
let mut parsed = false;
for (o, c) in $input.char_indices() {
if parsed {
// The easiest way to get the byte offset of the char after the found string
offset = o;
break;
}
if shift_window_and_cmp(& mut window, c, &substr_vec) {
parsed = true;
}
}
if parsed {
if offset < $input.len() {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Done("", $input)
}
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TakeUntilAndConsumeStr,$input))
}
};
res
}
);
);
/// `take_until_s!(&str) => &str -> IResult<&str, &str>`
/// generates a parser consuming all chars until the specified string is found and leaves it in the remaining input
#[macro_export]
macro_rules! take_until_s (
($input:expr, $substr:expr) => (
{
#[inline(always)]
fn shift_window_and_cmp(window: & mut Vec<char>, c: char, substr_vec: &Vec<char>) -> bool {
window.push(c);
if window.len() > substr_vec.len() {
window.remove(0);
}
window == substr_vec
}
let res: $crate::IResult<&str, &str> = if $substr.len() > $input.len() {
$crate::IResult::Incomplete($crate::Needed::Size($substr.len()))
} else {
let substr_vec: Vec<char> = $substr.chars().collect();
let mut window: Vec<char> = vec![];
let mut offset = $input.len();
let mut parsed = false;
for (o, c) in $input.char_indices() {
if shift_window_and_cmp(& mut window, c, &substr_vec) {
parsed = true;
window.pop();
let window_len: usize = window.iter()
.map(|x| x.len_utf8())
.fold(0, |x, y| x + y);
offset = o - window_len;
break;
}
}
if parsed {
$crate::IResult::Done(&$input[offset..], &$input[..offset])
} else {
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TakeUntilStr,$input))
}
};
res
}
);
);
#[cfg(test)]
mod test {
use ::IResult;
#[test]
fn tag_str_succeed() {
const INPUT: &'static str = "Hello World!";
const TAG: &'static str = "Hello";
fn test(input: &str) -> IResult<&str, &str> {
tag_s!(input, TAG)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == " World!", "Parser `tag_s` consumed leftover input.");
assert!(output == TAG,
"Parser `tag_s` doesn't return the tag it matched on success. \
Expected `{}`, got `{}`.", TAG, output);
},
other => panic!("Parser `tag_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn tag_str_incomplete() {
const INPUT: &'static str = "Hello";
const TAG: &'static str = "Hello World!";
match tag_s!(INPUT, TAG) {
IResult::Incomplete(_) => (),
other => {
panic!("Parser `tag_s` didn't require more input when it should have. \
Got `{:?}`.", other);
}
};
}
#[test]
fn tag_str_error() {
const INPUT: &'static str = "Hello World!";
const TAG: &'static str = "Random"; // TAG must be closer than INPUT.
match tag_s!(INPUT, TAG) {
IResult::Error(_) => (),
other => {
panic!("Parser `tag_s` didn't fail when it should have. Got `{:?}`.`", other);
},
};
}
#[test]
fn take_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
match take_s!(INPUT, 9) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_s` consumed leftover input. Leftover `{}`.", extra);
assert!(output == CONSUMED,
"Parser `take_s` doens't return the string it consumed on success. Expected `{}`, got `{}`.",
CONSUMED, output);
},
other => panic!("Parser `take_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_until_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇ∂áƒƭèř";
const FIND: &'static str = "ÂßÇ∂";
const CONSUMED: &'static str = "βèƒôřè";
const LEFTOVER: &'static str = "ÂßÇ∂áƒƭèř";
match take_until_s!(INPUT, FIND) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_until_s`\
consumed leftover input. Leftover `{}`.", extra);
assert!(output == CONSUMED, "Parser `take_until_s`\
doens't return the string it consumed on success. Expected `{}`, got `{}`.",
CONSUMED, output);
}
other => panic!("Parser `take_until_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_s_incomplete() {
const INPUT: &'static str = "βèƒôřèÂßÇá";
match take_s!(INPUT, 13) {
IResult::Incomplete(_) => (),
other => panic!("Parser `take_s` didn't require more input when it should have. \
Got `{:?}`.", other),
}
}
use internal::IResult::{Done, Error};
use internal::Err::Position;
use util::ErrorKind;
pub fn is_alphabetic(c:char) -> bool {
(c as u8 >= 0x41 && c as u8 <= 0x5A) || (c as u8 >= 0x61 && c as u8 <= 0x7A)
}
#[test]
fn take_while_s() {
named!(f<&str,&str>, take_while_s!(is_alphabetic));
let a = "";
let b = "abcd";
let c = "abcd123";
let d = "123";
assert_eq!(f(&a[..]), Done(&a[..], &a[..]));
assert_eq!(f(&b[..]), Done(&a[..], &b[..]));
assert_eq!(f(&c[..]), Done(&d[..], &b[..]));
assert_eq!(f(&d[..]), Done(&d[..], &a[..]));
}
#[test]
fn take_while1_s() {
named!(f<&str,&str>, take_while1_s!(is_alphabetic));
let a = "";
let b = "abcd";
let c = "abcd123";
let d = "123";
assert_eq!(f(&a[..]), Error(Position(ErrorKind::TakeWhile1Str, &""[..])));
assert_eq!(f(&b[..]), Done(&a[..], &b[..]));
assert_eq!(f(&c[..]), Done(&"123"[..], &b[..]));
assert_eq!(f(&d[..]), Error(Position(ErrorKind::TakeWhile1Str, &d[..])));
}
#[test]
fn take_till_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
fn till_s(c: char) -> bool {
c == 'á'
}
fn test(input: &str) -> IResult<&str, &str> {
take_till_s!(input, till_s)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_till_s` consumed leftover input.");
assert!(output == CONSUMED,
"Parser `take_till_s` doesn't return the string it consumed on success. \
Expected `{}`, got `{}`.", CONSUMED, output);
},
other => panic!("Parser `take_till_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_while_s_succeed_none() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const CONSUMED: &'static str = "";
const LEFTOVER: &'static str = "βèƒôřèÂßÇáƒƭèř";
fn while_s(c: char) -> bool {
c == '9'
}
fn test(input: &str) -> IResult<&str, &str> {
take_while_s!(input, while_s)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_while_s` consumed leftover input.");
assert!(output == CONSUMED,
"Parser `take_while_s` doesn't return the string it consumed on success. \
Expected `{}`, got `{}`.", CONSUMED, output);
},
other => panic!("Parser `take_while_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn is_not_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const AVOID: &'static str = "£úçƙ¥á";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
fn test(input: &str) -> IResult<&str, &str> {
is_not_s!(input, AVOID)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `is_not_s` consumed leftover input. Leftover `{}`.", extra);
assert!(output == CONSUMED,
"Parser `is_not_s` doens't return the string it consumed on success. Expected `{}`, got `{}`.",
CONSUMED, output);
},
other => panic!("Parser `is_not_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_until_and_consume_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const FIND: &'static str = "姂";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
match take_until_and_consume_s!(INPUT, FIND) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_until_and_consume_s`\
consumed leftover input. Leftover `{}`.", extra);
assert!(output == CONSUMED, "Parser `take_until_and_consume_s`\
doens't return the string it consumed on success. Expected `{}`, got `{}`.",
CONSUMED, output);
}
other => panic!("Parser `take_until_and_consume_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_while_s_succeed_some() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
fn while_s(c: char) -> bool {
c == 'β' || c == 'è' || c == 'ƒ' || c == 'ô' || c == 'ř' ||
c == 'è' || c == 'Â' || c == 'ß' || c == 'Ç'
}
fn test(input: &str) -> IResult<&str, &str> {
take_while_s!(input, while_s)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_while_s` consumed leftover input.");
assert!(output == CONSUMED,
"Parser `take_while_s` doesn't return the string it consumed on success. \
Expected `{}`, got `{}`.", CONSUMED, output);
},
other => panic!("Parser `take_while_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn is_not_s_fail() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const AVOID: &'static str = "βúçƙ¥";
fn test(input: &str) -> IResult<&str, &str> {
is_not_s!(input, AVOID)
}
match test(INPUT) {
IResult::Error(_) => (),
other => panic!("Parser `is_not_s` didn't fail when it should have. Got `{:?}`.", other),
};
}
#[test]
fn take_while1_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
fn while1_s(c: char) -> bool {
c == 'β' || c == 'è' || c == 'ƒ' || c == 'ô' || c == 'ř' ||
c == 'è' || c == 'Â' || c == 'ß' || c == 'Ç'
}
fn test(input: &str) -> IResult<&str, &str> {
take_while1_s!(input, while1_s)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `take_while1_s` consumed leftover input.");
assert!(output == CONSUMED,
"Parser `take_while1_s` doesn't return the string it consumed on success. \
Expected `{}`, got `{}`.", CONSUMED, output);
},
other => panic!("Parser `take_while1_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_until_and_consume_s_incomplete() {
const INPUT: &'static str = "βèƒôřè";
const FIND: &'static str = "βèƒôřèÂßÇ";
match take_until_and_consume_s!(INPUT, FIND) {
IResult::Incomplete(_) => (),
other => panic!("Parser `take_until_and_consume_s` didn't require more input when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_until_s_incomplete() {
const INPUT: &'static str = "βèƒôřè";
const FIND: &'static str = "βèƒôřèÂßÇ";
match take_until_s!(INPUT, FIND) {
IResult::Incomplete(_) => (),
other => panic!("Parser `take_until_s` didn't require more input when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn is_a_s_succeed() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const MATCH: &'static str = "βèƒôřèÂßÇ";
const CONSUMED: &'static str = "βèƒôřèÂßÇ";
const LEFTOVER: &'static str = "áƒƭèř";
fn test(input: &str) -> IResult<&str, &str> {
is_a_s!(input, MATCH)
}
match test(INPUT) {
IResult::Done(extra, output) => {
assert!(extra == LEFTOVER, "Parser `is_a_s` consumed leftover input. Leftover `{}`.", extra);
assert!(output == CONSUMED,
"Parser `is_a_s` doens't return the string it consumed on success. Expected `{}`, got `{}`.",
CONSUMED, output);
},
other => panic!("Parser `is_a_s` didn't succeed when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_while1_s_fail() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
fn while1_s(c: char) -> bool {
c == '9'
}
fn test(input: &str) -> IResult<&str, &str> {
take_while1_s!(input, while1_s)
}
match test(INPUT) {
IResult::Error(_) => (),
other => panic!("Parser `take_while1_s` didn't fail when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn is_a_s_fail() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const MATCH: &'static str = "Ûñℓúçƙ¥";
fn test(input: &str) -> IResult<&str, &str> {
is_a_s!(input, MATCH)
}
match test(INPUT) {
IResult::Error(_) => (),
other => panic!("Parser `is_a_s` didn't fail when it should have. Got `{:?}`.", other),
};
}
#[test]
fn take_until_and_consume_s_error() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const FIND: &'static str = "Ráñδô₥";
match take_until_and_consume_s!(INPUT, FIND) {
IResult::Error(_) => (),
other => panic!("Parser `take_until_and_consume_s` didn't fail when it should have. \
Got `{:?}`.", other),
};
}
#[test]
fn take_until_s_error() {
const INPUT: &'static str = "βèƒôřèÂßÇáƒƭèř";
const FIND: &'static str = "Ráñδô₥";
match take_until_s!(INPUT, FIND) {
IResult::Error(_) => (),
other => panic!("Parser `take_until_and_consume_s` didn't fail when it should have. \
Got `{:?}`.", other),
};
}
}

1031
third_party/rust/nom-1.2.4/src/stream.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

769
third_party/rust/nom-1.2.4/src/util.rs поставляемый
Просмотреть файл

@ -1,769 +0,0 @@
use internal::{IResult,Err};
#[cfg(not(feature = "core"))]
use std::collections::HashMap;
#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::vec::Vec;
use std::string::ToString;
/// useful functions to calculate the offset between slices and show a hexdump of a slice
#[cfg(not(feature = "core"))]
pub trait HexDisplay {
/// offset between the first byte of self and the first byte of the argument
fn offset(&self, second:&[u8]) -> usize;// OFFSET SHOULD GO TO ITS OWN TRAIT
/// Converts the value of `self` to a hex dump, returning the owned
/// string.
fn to_hex(&self, chunk_size: usize) -> String;
/// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned
/// string.
fn to_hex_from(&self, chunk_size: usize, from: usize) -> String;
}
pub trait InputLength {
#[inline]
fn input_len(&self) -> usize;
}
impl<'a, T> InputLength for &'a[T] {
#[inline]
fn input_len(&self) -> usize {
self.len()
}
}
impl<'a> InputLength for &'a str {
#[inline]
fn input_len(&self) -> usize {
self.len()
}
}
impl<'a> InputLength for (&'a [u8], usize) {
#[inline]
fn input_len(&self) -> usize {
//println!("bit input length for ({:?}, {}):", self.0, self.1);
let res = self.0.len() * 8 - self.1;
//println!("-> {}", res);
res
}
}
use std::iter::Enumerate;
#[cfg(not(feature = "core"))]
use std::str::CharIndices;
pub trait AsChar {
#[inline]
fn as_char(self) -> char;
#[inline]
fn is_alpha(self) -> bool;
#[inline]
fn is_alphanum(self) -> bool;
#[inline]
fn is_0_to_9(self) -> bool;
#[inline]
fn is_hex_digit(self) -> bool;
#[inline]
fn is_oct_digit(self) -> bool;
}
impl<'a> AsChar for &'a u8 {
#[inline]
fn as_char(self) -> char { *self as char }
#[inline]
fn is_alpha(self) -> bool {
(*self >= 0x41 && *self <= 0x5A) || (*self >= 0x61 && *self <= 0x7A)
}
#[inline]
fn is_alphanum(self) -> bool { self.is_alpha() || self.is_0_to_9() }
#[inline]
fn is_0_to_9(self) -> bool {
*self >= 0x30 && *self <= 0x39
}
#[inline]
fn is_hex_digit(self) -> bool {
(*self >= 0x30 && *self <= 0x39) ||
(*self >= 0x41 && *self <= 0x46) ||
(*self >= 0x61 && *self <= 0x66)
}
#[inline]
fn is_oct_digit(self) -> bool {
*self >= 0x30 && *self <= 0x37
}
}
impl AsChar for char {
#[inline]
fn as_char(self) -> char { self }
#[inline]
fn is_alpha(self) -> bool { self.is_alphabetic() }
#[inline]
fn is_alphanum(self) -> bool { self.is_alpha() || self.is_0_to_9() }
#[inline]
fn is_0_to_9(self) -> bool { self.is_digit(10) }
#[inline]
fn is_hex_digit(self) -> bool { self.is_digit(16) }
#[inline]
fn is_oct_digit(self) -> bool { self.is_digit(8) }
}
pub trait IterIndices {
type Item: AsChar;
type Iter : Iterator<Item=(usize, Self::Item)>;
fn iter_indices(self) -> Self::Iter;
}
impl<'a> IterIndices for &'a [u8] {
type Item = &'a u8;
type Iter = Enumerate<::std::slice::Iter<'a, u8>>;
#[inline]
fn iter_indices(self) -> Enumerate<::std::slice::Iter<'a, u8>> {
self.iter().enumerate()
}
}
#[cfg(not(feature = "core"))]
impl<'a> IterIndices for &'a str {
type Item = char;
type Iter = CharIndices<'a>;
#[inline]
fn iter_indices(self) -> CharIndices<'a> {
self.char_indices()
}
}
static CHARS: &'static[u8] = b"0123456789abcdef";
#[cfg(not(feature = "core"))]
impl HexDisplay for [u8] {
fn offset(&self, second:&[u8]) -> usize {
let fst = self.as_ptr();
let snd = second.as_ptr();
snd as usize - fst as usize
}
#[allow(unused_variables)]
fn to_hex(&self, chunk_size: usize) -> String {
self.to_hex_from(chunk_size, 0)
}
#[allow(unused_variables)]
fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
let mut v = Vec::with_capacity(self.len() * 3);
let mut i = from;
for chunk in self.chunks(chunk_size) {
let s = format!("{:08x}", i);
for &ch in s.as_bytes().iter() {
v.push(ch);
}
v.push('\t' as u8);
i = i + chunk_size;
for &byte in chunk {
v.push(CHARS[(byte >> 4) as usize]);
v.push(CHARS[(byte & 0xf) as usize]);
v.push(' ' as u8);
}
if chunk_size > chunk.len() {
for j in 0..(chunk_size - chunk.len()) {
v.push(' ' as u8);
v.push(' ' as u8);
v.push(' ' as u8);
}
}
v.push('\t' as u8);
for &byte in chunk {
if (byte >=32 && byte <= 126) || byte >= 128 {
v.push(byte);
} else {
v.push('.' as u8);
}
}
v.push('\n' as u8);
}
String::from_utf8_lossy(&v[..]).into_owned()
}
}
/// Prints a message if the parser fails
///
/// The message prints the `Error` or `Incomplete`
/// and the parser's calling code
///
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
/// named!(f, dbg!( tag!( "abcd" ) ) );
///
/// let a = &b"efgh"[..];
///
/// // Will print the following message:
/// // Error(Position(0, [101, 102, 103, 104])) at l.5 by ' tag ! ( "abcd" ) '
/// f(a);
/// # }
/// ```
#[macro_export]
macro_rules! dbg (
($i: expr, $submac:ident!( $($args:tt)* )) => (
{
let l = line!();
match $submac!($i, $($args)*) {
$crate::IResult::Error(a) => {
println!("Error({:?}) at l.{} by ' {} '", a, l, stringify!($submac!($($args)*)));
$crate::IResult::Error(a)
},
$crate::IResult::Incomplete(a) => {
println!("Incomplete({:?}) at {} by ' {} '", a, l, stringify!($submac!($($args)*)));
$crate::IResult::Incomplete(a)
},
a => a
}
}
);
($i:expr, $f:ident) => (
dbg!($i, call!($f));
);
);
/// Prints a message and the input if the parser fails
///
/// The message prints the `Error` or `Incomplete`
/// and the parser's calling code.
///
/// It also displays the input in hexdump format
///
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
/// named!(f, dbg_dmp!( tag!( "abcd" ) ) );
///
/// let a = &b"efghijkl"[..];
///
/// // Will print the following message:
/// // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) '
/// // 00000000 65 66 67 68 69 6a 6b 6c efghijkl
/// f(a);
/// # }
#[macro_export]
macro_rules! dbg_dmp (
($i: expr, $submac:ident!( $($args:tt)* )) => (
{
use $crate::HexDisplay;
let l = line!();
match $submac!($i, $($args)*) {
$crate::IResult::Error(a) => {
println!("Error({:?}) at l.{} by ' {} '\n{}", a, l, stringify!($submac!($($args)*)), $i.to_hex(8));
$crate::IResult::Error(a)
},
$crate::IResult::Incomplete(a) => {
println!("Incomplete({:?}) at {} by ' {} '\n{}", a, l, stringify!($submac!($($args)*)), $i.to_hex(8));
$crate::IResult::Incomplete(a)
},
a => a
}
}
);
($i:expr, $f:ident) => (
dbg_dmp!($i, call!($f));
);
);
pub fn error_to_list<P,E:Clone>(e:&Err<P,E>) -> Vec<ErrorKind<E>> {
let mut v:Vec<ErrorKind<E>> = Vec::new();
let mut err = e;
loop {
match *err {
Err::Code(ref i) | Err::Position(ref i,_) => {
v.push(i.clone());
return v;
},
Err::Node(ref i, ref next) | Err::NodePosition(ref i, _, ref next) => {
v.push(i.clone());
err = &*next;
}
}
}
}
pub fn compare_error_paths<P,E:Clone+PartialEq>(e1:&Err<P,E>, e2:&Err<P,E>) -> bool {
error_to_list(e1) == error_to_list(e2)
}
#[cfg(not(feature = "core"))]
use std::hash::Hash;
#[cfg(not(feature = "core"))]
pub fn add_error_pattern<'a,I,O,E: Clone+Hash+Eq>(h: &mut HashMap<Vec<ErrorKind<E>>, &'a str>, res: IResult<I,O,E>, message: &'a str) -> bool {
if let IResult::Error(e) = res {
h.insert(error_to_list(&e), message);
true
} else {
false
}
}
pub fn slice_to_offsets(input: &[u8], s: &[u8]) -> (usize, usize) {
let start = input.as_ptr();
let off1 = s.as_ptr() as usize - start as usize;
let off2 = off1 + s.len();
(off1, off2)
}
#[cfg(not(feature = "core"))]
pub fn prepare_errors<O,E: Clone>(input: &[u8], res: IResult<&[u8],O,E>) -> Option<Vec<(ErrorKind<E>, usize, usize)> > {
if let IResult::Error(e) = res {
let mut v:Vec<(ErrorKind<E>, usize, usize)> = Vec::new();
let mut err = e.clone();
loop {
match err {
Err::Position(i,s) => {
let (o1, o2) = slice_to_offsets(input, s);
v.push((i, o1, o2));
//println!("v is: {:?}", v);
break;
},
Err::NodePosition(i, s, next) => {
let (o1, o2) = slice_to_offsets(input, s);
v.push((i, o1, o2));
err = *next;
},
Err::Node(_, next) => {
err = *next;
},
Err::Code(_) => {
break;
}
}
}
v.sort_by(|a, b| a.1.cmp(&b.1));
Some(v)
} else {
None
}
}
#[cfg(not(feature = "core"))]
pub fn print_error<O,E:Clone>(input: &[u8], res: IResult<&[u8],O,E>) {
if let Some(v) = prepare_errors(input, res) {
let colors = generate_colors(&v);
println!("parser codes: {}", print_codes(colors, HashMap::new()));
println!("{}", print_offsets(input, 0, &v));
} else {
println!("not an error");
}
}
#[cfg(not(feature = "core"))]
pub fn generate_colors<E>(v: &[(ErrorKind<E>, usize, usize)]) -> HashMap<u32, u8> {
let mut h: HashMap<u32, u8> = HashMap::new();
let mut color = 0;
for &(ref c,_,_) in v.iter() {
h.insert(error_to_u32(c), color + 31);
color = color + 1 % 7;
}
h
}
pub fn code_from_offset<E>(v: &[(ErrorKind<E>, usize, usize)], offset: usize) -> Option<u32> {
let mut acc: Option<(u32, usize, usize)> = None;
for &(ref ek, s, e) in v.iter() {
let c = error_to_u32(ek);
if s <= offset && offset <=e {
if let Some((_, start, end)) = acc {
if start <= s && e <= end {
acc = Some((c, s, e));
}
} else {
acc = Some((c, s, e));
}
}
}
if let Some((code, _, _)) = acc {
return Some(code);
} else {
return None;
}
}
pub fn reset_color(v: &mut Vec<u8>) {
v.push(0x1B);
v.push('[' as u8);
v.push(0);
v.push('m' as u8);
}
pub fn write_color(v: &mut Vec<u8>, color: u8) {
v.push(0x1B);
v.push('[' as u8);
v.push(1);
v.push(';' as u8);
let s = color.to_string();
let bytes = s.as_bytes();
v.extend(bytes.iter().cloned());
v.push('m' as u8);
}
#[cfg(not(feature = "core"))]
pub fn print_codes(colors: HashMap<u32, u8>, names: HashMap<u32, &str>) -> String {
let mut v = Vec::new();
for (code, &color) in &colors {
if let Some(&s) = names.get(&code) {
let bytes = s.as_bytes();
write_color(&mut v, color);
v.extend(bytes.iter().cloned());
} else {
let s = code.to_string();
let bytes = s.as_bytes();
write_color(&mut v, color);
v.extend(bytes.iter().cloned());
}
reset_color(&mut v);
v.push(' ' as u8);
}
reset_color(&mut v);
String::from_utf8_lossy(&v[..]).into_owned()
}
#[cfg(not(feature = "core"))]
pub fn print_offsets<E>(input: &[u8], from: usize, offsets: &[(ErrorKind<E>, usize, usize)]) -> String {
let mut v = Vec::with_capacity(input.len() * 3);
let mut i = from;
let chunk_size = 8;
let mut current_code: Option<u32> = None;
let mut current_code2: Option<u32> = None;
let colors = generate_colors(&offsets);
for chunk in input.chunks(chunk_size) {
let s = format!("{:08x}", i);
for &ch in s.as_bytes().iter() {
v.push(ch);
}
v.push('\t' as u8);
let mut k = i;
let mut l = i;
for &byte in chunk {
if let Some(code) = code_from_offset(&offsets, k) {
if let Some(current) = current_code {
if current != code {
reset_color(&mut v);
current_code = Some(code);
if let Some(&color) = colors.get(&code) {
write_color(&mut v, color);
}
}
} else {
current_code = Some(code);
if let Some(&color) = colors.get(&code) {
write_color(&mut v, color);
}
}
}
v.push(CHARS[(byte >> 4) as usize]);
v.push(CHARS[(byte & 0xf) as usize]);
v.push(' ' as u8);
k = k + 1;
}
reset_color(&mut v);
if chunk_size > chunk.len() {
for _ in 0..(chunk_size - chunk.len()) {
v.push(' ' as u8);
v.push(' ' as u8);
v.push(' ' as u8);
}
}
v.push('\t' as u8);
for &byte in chunk {
if let Some(code) = code_from_offset(&offsets, l) {
if let Some(current) = current_code2 {
if current != code {
reset_color(&mut v);
current_code2 = Some(code);
if let Some(&color) = colors.get(&code) {
write_color(&mut v, color);
}
}
} else {
current_code2 = Some(code);
if let Some(&color) = colors.get(&code) {
write_color(&mut v, color);
}
}
}
if (byte >=32 && byte <= 126) || byte >= 128 {
v.push(byte);
} else {
v.push('.' as u8);
}
l = l + 1;
}
reset_color(&mut v);
v.push('\n' as u8);
i = i + chunk_size;
}
String::from_utf8_lossy(&v[..]).into_owned()
}
pub trait AsBytes {
fn as_bytes(&self) -> &[u8];
}
impl<'a> AsBytes for &'a str {
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
str::as_bytes(self)
}
}
impl AsBytes for str {
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
str::as_bytes(self)
}
}
impl<'a> AsBytes for &'a [u8] {
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
*self
}
}
impl AsBytes for [u8] {
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
self
}
}
macro_rules! array_impls {
($($N:expr)+) => {
$(
impl<'a> AsBytes for &'a [u8; $N] {
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
*self
}
}
impl AsBytes for [u8; $N] {
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
self
}
}
)+
};
}
array_impls! {
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32
}
/// indicates which parser returned an error
#[derive(Debug,PartialEq,Eq,Hash,Clone)]
pub enum ErrorKind<E=u32> {
Custom(E),
Tag,
MapRes,
MapOpt,
Alt,
IsNot,
IsA,
SeparatedList,
SeparatedNonEmptyList,
Many0,
Many1,
Count,
TakeUntilAndConsume,
TakeUntil,
TakeUntilEitherAndConsume,
TakeUntilEither,
LengthValue,
TagClosure,
Alpha,
Digit,
HexDigit,
OctDigit,
AlphaNumeric,
Space,
MultiSpace,
LengthValueFn,
Eof,
ExprOpt,
ExprRes,
CondReduce,
Switch,
TagBits,
OneOf,
NoneOf,
Char,
CrLf,
RegexpMatch,
RegexpMatches,
RegexpFind,
RegexpCapture,
RegexpCaptures,
TakeWhile1,
Complete,
Fix,
Escaped,
EscapedTransform,
TagStr,
IsNotStr,
IsAStr,
TakeWhile1Str,
NonEmpty,
ManyMN,
TakeUntilAndConsumeStr,
TakeUntilStr,
Not
}
pub fn error_to_u32<E>(e: &ErrorKind<E>) -> u32 {
match *e {
ErrorKind::Custom(_) => 0,
ErrorKind::Tag => 1,
ErrorKind::MapRes => 2,
ErrorKind::MapOpt => 3,
ErrorKind::Alt => 4,
ErrorKind::IsNot => 5,
ErrorKind::IsA => 6,
ErrorKind::SeparatedList => 7,
ErrorKind::SeparatedNonEmptyList => 8,
ErrorKind::Many1 => 9,
ErrorKind::Count => 10,
ErrorKind::TakeUntilAndConsume => 11,
ErrorKind::TakeUntil => 12,
ErrorKind::TakeUntilEitherAndConsume => 13,
ErrorKind::TakeUntilEither => 14,
ErrorKind::LengthValue => 15,
ErrorKind::TagClosure => 16,
ErrorKind::Alpha => 17,
ErrorKind::Digit => 18,
ErrorKind::AlphaNumeric => 19,
ErrorKind::Space => 20,
ErrorKind::MultiSpace => 21,
ErrorKind::LengthValueFn => 22,
ErrorKind::Eof => 23,
ErrorKind::ExprOpt => 24,
ErrorKind::ExprRes => 25,
ErrorKind::CondReduce => 26,
ErrorKind::Switch => 27,
ErrorKind::TagBits => 28,
ErrorKind::OneOf => 29,
ErrorKind::NoneOf => 30,
ErrorKind::Char => 40,
ErrorKind::CrLf => 41,
ErrorKind::RegexpMatch => 42,
ErrorKind::RegexpMatches => 43,
ErrorKind::RegexpFind => 44,
ErrorKind::RegexpCapture => 45,
ErrorKind::RegexpCaptures => 46,
ErrorKind::TakeWhile1 => 47,
ErrorKind::Complete => 48,
ErrorKind::Fix => 49,
ErrorKind::Escaped => 50,
ErrorKind::EscapedTransform => 51,
ErrorKind::TagStr => 52,
ErrorKind::IsNotStr => 53,
ErrorKind::IsAStr => 54,
ErrorKind::TakeWhile1Str => 55,
ErrorKind::NonEmpty => 56,
ErrorKind::ManyMN => 57,
ErrorKind::TakeUntilAndConsumeStr => 58,
ErrorKind::HexDigit => 59,
ErrorKind::TakeUntilStr => 60,
ErrorKind::OctDigit => 61,
ErrorKind::Many0 => 62,
ErrorKind::Not => 63,
}
}
impl<E> ErrorKind<E> {
pub fn description(&self) -> &str {
match *self {
ErrorKind::Custom(_) => "Custom error",
ErrorKind::Tag => "Tag",
ErrorKind::MapRes => "Map on Result",
ErrorKind::MapOpt => "Map on Option",
ErrorKind::Alt => "Alternative",
ErrorKind::IsNot => "IsNot",
ErrorKind::IsA => "IsA",
ErrorKind::SeparatedList => "Separated list",
ErrorKind::SeparatedNonEmptyList => "Separated non empty list",
ErrorKind::Many0 => "Many0",
ErrorKind::Many1 => "Many1",
ErrorKind::Count => "Count",
ErrorKind::TakeUntilAndConsume => "Take until and consume",
ErrorKind::TakeUntil => "Take until",
ErrorKind::TakeUntilEitherAndConsume => "Take until either and consume",
ErrorKind::TakeUntilEither => "Take until either",
ErrorKind::LengthValue => "Length followed by value",
ErrorKind::TagClosure => "Tag closure",
ErrorKind::Alpha => "Alphabetic",
ErrorKind::Digit => "Digit",
ErrorKind::AlphaNumeric => "AlphaNumeric",
ErrorKind::Space => "Space",
ErrorKind::MultiSpace => "Multiple spaces",
ErrorKind::LengthValueFn => "LengthValueFn",
ErrorKind::Eof => "End of file",
ErrorKind::ExprOpt => "Evaluate Option",
ErrorKind::ExprRes => "Evaluate Result",
ErrorKind::CondReduce => "Condition reduce",
ErrorKind::Switch => "Switch",
ErrorKind::TagBits => "Tag on bitstream",
ErrorKind::OneOf => "OneOf",
ErrorKind::NoneOf => "NoneOf",
ErrorKind::Char => "Char",
ErrorKind::CrLf => "CrLf",
ErrorKind::RegexpMatch => "RegexpMatch",
ErrorKind::RegexpMatches => "RegexpMatches",
ErrorKind::RegexpFind => "RegexpFind",
ErrorKind::RegexpCapture => "RegexpCapture",
ErrorKind::RegexpCaptures => "RegexpCaptures",
ErrorKind::TakeWhile1 => "TakeWhile1",
ErrorKind::Complete => "Complete",
ErrorKind::Fix => "Fix",
ErrorKind::Escaped => "Escaped",
ErrorKind::EscapedTransform => "EscapedTransform",
ErrorKind::TagStr => "Tag on strings",
ErrorKind::IsNotStr => "IsNot on strings",
ErrorKind::IsAStr => "IsA on strings",
ErrorKind::TakeWhile1Str => "TakeWhile1 on strings",
ErrorKind::NonEmpty => "NonEmpty",
ErrorKind::ManyMN => "Many(m, n)",
ErrorKind::TakeUntilAndConsumeStr => "Take until and consume on strings",
ErrorKind::HexDigit => "Hexadecimal Digit",
ErrorKind::TakeUntilStr => "Take until on strings",
ErrorKind::OctDigit => "Octal digit",
ErrorKind::Not => "Negation",
}
}
}

Просмотреть файл

@ -1,80 +0,0 @@
#[macro_use]
extern crate nom;
use nom::{IResult,digit, multispace};
use std::str;
use std::str::FromStr;
named!(parens<i64>, delimited!(
delimited!(opt!(multispace), tag!("("), opt!(multispace)),
expr,
delimited!(opt!(multispace), tag!(")"), opt!(multispace))
)
);
named!(factor<i64>, alt!(
map_res!(
map_res!(
delimited!(opt!(multispace), digit, opt!(multispace)),
str::from_utf8
),
FromStr::from_str
)
| parens
)
);
named!(term <i64>, chain!(
mut acc: factor ~
many0!(
alt!(
tap!(mul: preceded!(tag!("*"), factor) => acc = acc * mul) |
tap!(div: preceded!(tag!("/"), factor) => acc = acc / div)
)
),
|| { return acc }
)
);
named!(expr <i64>, chain!(
mut acc: term ~
many0!(
alt!(
tap!(add: preceded!(tag!("+"), term) => acc = acc + add) |
tap!(sub: preceded!(tag!("-"), term) => acc = acc - sub)
)
),
|| { return acc }
)
);
#[test]
fn factor_test() {
assert_eq!(factor(&b"3"[..]), IResult::Done(&b""[..], 3));
assert_eq!(factor(&b" 12"[..]), IResult::Done(&b""[..], 12));
assert_eq!(factor(&b"537 "[..]), IResult::Done(&b""[..], 537));
assert_eq!(factor(&b" 24 "[..]), IResult::Done(&b""[..], 24));
}
#[test]
fn term_test() {
assert_eq!(term(&b" 12 *2 / 3"[..]), IResult::Done(&b""[..], 8));
assert_eq!(term(&b" 2* 3 *2 *2 / 3"[..]), IResult::Done(&b""[..], 8));
assert_eq!(term(&b" 48 / 3/2"[..]), IResult::Done(&b""[..], 8));
}
#[test]
fn expr_test() {
assert_eq!(expr(&b" 1 + 2 "[..]), IResult::Done(&b""[..], 3));
assert_eq!(expr(&b" 12 + 6 - 4+ 3"[..]), IResult::Done(&b""[..], 17));
assert_eq!(expr(&b" 1 + 2*3 + 4"[..]), IResult::Done(&b""[..], 11));
}
#[test]
fn parens_test() {
assert_eq!(expr(&b" ( 2 )"[..]), IResult::Done(&b""[..], 2));
assert_eq!(expr(&b" 2* ( 3 + 4 ) "[..]), IResult::Done(&b""[..], 14));
assert_eq!(expr(&b" 2*2 / ( 5 - 1) + 3"[..]), IResult::Done(&b""[..], 4));
}

Просмотреть файл

@ -1,137 +0,0 @@
#[macro_use]
extern crate nom;
use std::fmt;
use std::fmt::{Display, Debug, Formatter};
use std::str;
use std::str::FromStr;
use nom::{IResult, digit, multispace};
pub enum Expr {
Value(i64),
Add(Box<Expr>, Box<Expr>),
Sub(Box<Expr>, Box<Expr>),
Mul(Box<Expr>, Box<Expr>),
Div(Box<Expr>, Box<Expr>),
Paren(Box<Expr>),
}
pub enum Oper {
Add,
Sub,
Mul,
Div,
}
impl Display for Expr {
fn fmt(&self, format: &mut Formatter) -> fmt::Result {
use self::Expr::*;
match *self {
Value(val) => write!(format, "{}", val),
Add(ref left, ref right) => write!(format, "{} + {}", left, right),
Sub(ref left, ref right) => write!(format, "{} - {}", left, right),
Mul(ref left, ref right) => write!(format, "{} * {}", left, right),
Div(ref left, ref right) => write!(format, "{} / {}", left, right),
Paren(ref expr) => write!(format, "({})", expr),
}
}
}
impl Debug for Expr {
fn fmt(&self, format: &mut Formatter) -> fmt::Result {
use self::Expr::*;
match *self {
Value(val) => write!(format, "{}", val),
Add(ref left, ref right) => write!(format, "({:?} + {:?})", left, right),
Sub(ref left, ref right) => write!(format, "({:?} - {:?})", left, right),
Mul(ref left, ref right) => write!(format, "({:?} * {:?})", left, right),
Div(ref left, ref right) => write!(format, "({:?} / {:?})", left, right),
Paren(ref expr) => write!(format, "[{:?}]", expr),
}
}
}
named!(parens< Expr >, delimited!(
delimited!(opt!(multispace), tag!("("), opt!(multispace)),
map!(map!(expr, Box::new), Expr::Paren),
delimited!(opt!(multispace), tag!(")"), opt!(multispace))
)
);
named!(factor< Expr >, alt_complete!(
map!(
map_res!(
map_res!(
delimited!(opt!(multispace), digit, opt!(multispace)),
str::from_utf8
),
FromStr::from_str
),
Expr::Value)
| parens
)
);
fn fold_exprs(initial: Expr, remainder: Vec<(Oper, Expr)>) -> Expr {
remainder.into_iter().fold(initial, |acc, pair| {
let (oper, expr) = pair;
match oper {
Oper::Add => Expr::Add(Box::new(acc), Box::new(expr)),
Oper::Sub => Expr::Sub(Box::new(acc), Box::new(expr)),
Oper::Mul => Expr::Mul(Box::new(acc), Box::new(expr)),
Oper::Div => Expr::Div(Box::new(acc), Box::new(expr)),
}
})
}
named!(term< Expr >, chain!(
initial: factor ~
remainder: many0!(
alt!(
chain!(tag!("*") ~ mul: factor, || { (Oper::Mul, mul) }) |
chain!(tag!("/") ~ div: factor, || { (Oper::Div, div) })
)
),
|| fold_exprs(initial, remainder))
);
named!(expr< Expr >, chain!(
initial: term ~
remainder: many0!(
alt!(
chain!(tag!("+") ~ add: term, || { (Oper::Add, add) }) |
chain!(tag!("-") ~ sub: term, || { (Oper::Sub, sub) })
)
),
|| fold_exprs(initial, remainder))
);
#[test]
fn factor_test() {
assert_eq!(factor(&b" 3 "[..]).map(|x| format!("{:?}", x)),
IResult::Done(&b""[..], String::from("3")));
}
#[test]
fn term_test() {
assert_eq!(term(&b" 3 * 5 "[..]).map(|x| format!("{:?}", x)),
IResult::Done(&b""[..], String::from("(3 * 5)")));
}
#[test]
fn expr_test() {
assert_eq!(expr(&b" 1 + 2 * 3 "[..]).map(|x| format!("{:?}", x)),
IResult::Done(&b""[..], String::from("(1 + (2 * 3))")));
assert_eq!(expr(&b" 1 + 2 * 3 / 4 - 5 "[..]).map(|x| format!("{:?}", x)),
IResult::Done(&b""[..], String::from("((1 + ((2 * 3) / 4)) - 5)")));
assert_eq!(expr(&b" 72 / 2 / 3 "[..]).map(|x| format!("{:?}", x)),
IResult::Done(&b""[..], String::from("((72 / 2) / 3)")));
}
#[test]
fn parens_test() {
assert_eq!(expr(&b" ( 1 + 2 ) * 3 "[..]).map(|x| format!("{:?}", x)),
IResult::Done(&b""[..], String::from("([(1 + 2)] * 3)")));
}

Просмотреть файл

@ -1,140 +0,0 @@
/// this file tests a different backtracking behaviour. With the current
/// `error!` macro, an early return is done in the current function, but
/// backtracking continues normally outside of that function.
///
/// The solution here wraps `IResult` in a `Result`: a `Ok` indicates usual
/// backtracking, `Err` indicates that we must "cut".
#[macro_use]
extern crate nom;
macro_rules! n (
($name:ident( $i:ty ) -> $o:ty, $submac:ident!( $($args:tt)* )) => (
fn $name( i: $i ) -> std::result::Result<nom::IResult<$i,$o,u32>, nom::Err<$i, u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
($name:ident<$i:ty,$o:ty,$e:ty>, $submac:ident!( $($args:tt)* )) => (
fn $name( i: $i ) -> std::result::Result<nom::IResult<$i, $o, $e>, nom::Err<$i, $e>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
($name:ident<$i:ty,$o:ty>, $submac:ident!( $($args:tt)* )) => (
fn $name( i: $i ) -> std::result::Result<nom::IResult<$i, $o, u32>, nom::Err<$i, u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
($name:ident<$o:ty>, $submac:ident!( $($args:tt)* )) => (
fn $name<'a>( i: &'a[u8] ) -> std::result::Result<nom::IResult<&'a [u8], $o, u32>, nom::Err<&'a [u8], u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
($name:ident, $submac:ident!( $($args:tt)* )) => (
fn $name( i: &[u8] ) -> std::result::Result<nom::IResult<&[u8], &[u8], u32>, nom::Err<&[u8], u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
(pub $name:ident( $i:ty ) -> $o:ty, $submac:ident!( $($args:tt)* )) => (
pub fn $name( i: $i ) -> std::result::Result<nom::IResult<$i,$o, u32>, nom::Err<$i, u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
(pub $name:ident<$i:ty,$o:ty,$e:ty>, $submac:ident!( $($args:tt)* )) => (
pub fn $name( i: $i ) -> std::result::Result<nom::IResult<$i, $o, $e>, nom::Err<$i, $e>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
(pub $name:ident<$i:ty,$o:ty>, $submac:ident!( $($args:tt)* )) => (
pub fn $name( i: $i ) -> std::result::Result<nom::IResult<$i, $o, u32>, nom::Err<$i, u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
(pub $name:ident<$o:ty>, $submac:ident!( $($args:tt)* )) => (
pub fn $name( i: &[u8] ) -> std::result::Result<nom::IResult<&[u8], $o, u32>, nom::Err<&[u8], u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
(pub $name:ident, $submac:ident!( $($args:tt)* )) => (
pub fn $name<'a>( i: &'a [u8] ) -> std::result::Result<nom::IResult<&[u8], &[u8], u32>, nom::Err<&[u8], u32>> {
std::result::Result::Ok($submac!(i, $($args)*))
}
);
);
macro_rules! cut (
($i:expr, $code:expr, $submac:ident!( $($args:tt)* )) => (
{
let cl = || {
Ok($submac!($i, $($args)*))
};
match cl() {
std::result::Result::Ok(nom::IResult::Incomplete(x)) => nom::IResult::Incomplete(x),
std::result::Result::Ok(nom::IResult::Done(i, o)) => nom::IResult::Done(i, o),
std::result::Result::Ok(nom::IResult::Error(e)) | std::result::Result::Err(e) => {
return std::result::Result::Err(nom::Err::NodePosition($code, $i, Box::new(e)))
}
}
}
);
($i:expr, $code:expr, $f:expr) => (
cut!($i, $code, call!($f));
);
);
macro_rules! c (
($i:expr, $f:expr) => (
{
match $f($i) {
std::result::Result::Ok(nom::IResult::Incomplete(x)) => nom::IResult::Incomplete(x),
std::result::Result::Ok(nom::IResult::Done(i, o)) => nom::IResult::Done(i, o),
std::result::Result::Ok(nom::IResult::Error(e)) => nom::IResult::Error(e),
std::result::Result::Err(e) => {
return std::result::Result::Err(e)
}
}
}
);
);
n!(pub foo< bool >,
chain!(
tag!("a") ~
cut!(nom::ErrorKind::Custom(42),dbg_dmp!(tag!("b"))) ,
|| { true }
)
);
n!(pub foos< Vec<bool> >,
delimited!(
tag!("("),
many0!(c!(foo)),
tag!(")")
)
);
#[test]
fn test_ok() {
let r = foos(b"(abab)");
println!("result: {:?}", r);
match r {
Ok(nom::IResult::Done(_,result)) => assert_eq!(result,vec![true,true]),
res => panic!("Oops {:?}.",res)
}
}
#[test]
fn test_err() {
let input = b"(ac)";
let r = foos(&input[..]);
println!("result: {:?}", r);
match r {
//Ok(nom::IResult::Error(nom::Err::Position(kind,_))) => assert_eq!(kind,nom::ErrorKind::Custom(42)),
Err(nom::Err::NodePosition(kind, position, _)) => {
assert_eq!(kind, nom::ErrorKind::Custom(42));
assert_eq!(position, &input[2..]);
}
res => panic!("Oops, {:?}",res)
}
}

234
third_party/rust/nom-1.2.4/tests/ini.rs поставляемый
Просмотреть файл

@ -1,234 +0,0 @@
#[macro_use]
extern crate nom;
use nom::{IResult,not_line_ending, space, alphanumeric, multispace};
use std::str;
use std::collections::HashMap;
named!(category<&str>, map_res!(
terminated!(
delimited!(tag!("["), take_until!("]"), tag!("]")),
opt!(multispace)
),
str::from_utf8
));
named!(key_value <&[u8],(&str,&str)>,
chain!(
key: map_res!(alphanumeric, std::str::from_utf8) ~
space? ~
tag!("=") ~
space? ~
val: map_res!(
take_until_either!("\n;"),
str::from_utf8
) ~
space? ~
chain!(
tag!(";") ~
not_line_ending ,
||{}
) ? ~
multispace? ,
||{(key, val)}
)
);
named!(keys_and_values_aggregator<&[u8], Vec<(&str,&str)> >, many0!(key_value));
fn keys_and_values(input:&[u8]) -> IResult<&[u8], HashMap<&str, &str> > {
let mut h: HashMap<&str, &str> = HashMap::new();
match keys_and_values_aggregator(input) {
IResult::Done(i,tuple_vec) => {
for &(k,v) in &tuple_vec {
h.insert(k, v);
}
IResult::Done(i, h)
},
IResult::Incomplete(a) => IResult::Incomplete(a),
IResult::Error(a) => IResult::Error(a)
}
}
named!(category_and_keys<&[u8],(&str,HashMap<&str,&str>)>,
chain!(
category: category ~
keys: keys_and_values ,
move ||{(category, keys)}
)
);
named!(categories_aggregator<&[u8], Vec<(&str, HashMap<&str,&str>)> >, many0!(category_and_keys));
fn categories(input: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str> > > {
let mut h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
match categories_aggregator(input) {
IResult::Done(i,tuple_vec) => {
for &(k,ref v) in &tuple_vec {
h.insert(k, v.clone());
}
IResult::Done(i, h)
},
IResult::Incomplete(a) => IResult::Incomplete(a),
IResult::Error(a) => IResult::Error(a)
}
}
#[test]
fn parse_category_test() {
let ini_file = &b"[category]
parameter=value
key = value2"[..];
let ini_without_category = &b"parameter=value
key = value2"[..];
let res = category(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_category, "category"));
}
#[test]
fn parse_key_value_test() {
let ini_file = &b"parameter=value
key = value2"[..];
let ini_without_key_value = &b"key = value2"[..];
let res = key_value(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}
#[test]
fn parse_key_value_with_space_test() {
let ini_file = &b"parameter = value
key = value2"[..];
let ini_without_key_value = &b"key = value2"[..];
let res = key_value(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}
#[test]
fn parse_key_value_with_comment_test() {
let ini_file = &b"parameter=value;abc
key = value2"[..];
let ini_without_key_value = &b"key = value2"[..];
let res = key_value(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}
#[test]
fn parse_multiple_keys_and_values_test() {
let ini_file = &b"parameter=value;abc
key = value2
[category]"[..];
let ini_without_key_value = &b"[category]"[..];
let res = keys_and_values(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
_ => println!("error")
}
let mut expected: HashMap<&str, &str> = HashMap::new();
expected.insert("parameter", "value");
expected.insert("key", "value2");
assert_eq!(res, IResult::Done(ini_without_key_value, expected));
}
#[test]
fn parse_category_then_multiple_keys_and_values_test() {
//FIXME: there can be an empty line or a comment line after a category
let ini_file = &b"[abcd]
parameter=value;abc
key = value2
[category]"[..];
let ini_after_parser = &b"[category]"[..];
let res = category_and_keys(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
_ => println!("error")
}
let mut expected_h: HashMap<&str, &str> = HashMap::new();
expected_h.insert("parameter", "value");
expected_h.insert("key", "value2");
assert_eq!(res, IResult::Done(ini_after_parser, ("abcd", expected_h)));
}
#[test]
fn parse_multiple_categories_test() {
let ini_file = &b"[abcd]
parameter=value;abc
key = value2
[category]
parameter3=value3
key4 = value4
"[..];
let ini_after_parser = &b""[..];
let res = categories(ini_file);
//println!("{:?}", res);
match res {
IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
_ => println!("error")
}
let mut expected_1: HashMap<&str, &str> = HashMap::new();
expected_1.insert("parameter", "value");
expected_1.insert("key", "value2");
let mut expected_2: HashMap<&str, &str> = HashMap::new();
expected_2.insert("parameter3", "value3");
expected_2.insert("key4", "value4");
let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
expected_h.insert("abcd", expected_1);
expected_h.insert("category", expected_2);
assert_eq!(res, IResult::Done(ini_after_parser, expected_h));
}

251
third_party/rust/nom-1.2.4/tests/ini_str.rs поставляемый
Просмотреть файл

@ -1,251 +0,0 @@
#[macro_use]
extern crate nom;
use nom::IResult;
use std::collections::HashMap;
fn is_alphabetic(chr:char) -> bool {
(chr as u8 >= 0x41 && chr as u8 <= 0x5A) || (chr as u8 >= 0x61 && chr as u8 <= 0x7A)
}
fn is_digit(chr: char) -> bool {
chr as u8 >= 0x30 && chr as u8 <= 0x39
}
fn is_alphanumeric(chr: char) -> bool {
is_alphabetic(chr) || is_digit(chr)
}
fn is_space(chr:char) -> bool {
chr == ' ' || chr == '\t'
}
fn is_line_ending_or_comment(chr:char) -> bool {
chr == ';' || chr == '\n'
}
named!(alphanumeric<&str,&str>, take_while_s!(is_alphanumeric));
named!(not_line_ending<&str,&str>, is_not_s!("\r\n"));
named!(space<&str,&str>, take_while_s!(is_space));
named!(space_or_line_ending<&str,&str>, is_a_s!(" \r\n"));
fn right_bracket(c:char) -> bool {
c == ']'
}
named!(category <&str, &str>,
chain!(
tag_s!("[") ~
name: take_till_s!(right_bracket) ~
tag_s!("]") ~
space_or_line_ending? ,
||{ name }
)
);
named!(key_value <&str,(&str,&str)>,
chain!(
key: alphanumeric ~
space? ~
tag_s!("=") ~
space? ~
val: take_till_s!(is_line_ending_or_comment) ~
space? ~
pair!(tag_s!(";"), not_line_ending)? ~
space_or_line_ending? ,
||{(key, val)}
)
);
named!(keys_and_values_aggregator<&str, Vec<(&str,&str)> >, many0!(key_value));
fn keys_and_values(input:&str) -> IResult<&str, HashMap<&str, &str> > {
let mut h: HashMap<&str, &str> = HashMap::new();
match keys_and_values_aggregator(input) {
IResult::Done(i,tuple_vec) => {
for &(k,v) in &tuple_vec {
h.insert(k, v);
}
IResult::Done(i, h)
},
IResult::Incomplete(a) => IResult::Incomplete(a),
IResult::Error(a) => IResult::Error(a)
}
}
named!(category_and_keys<&str,(&str,HashMap<&str,&str>)>,
pair!(category, keys_and_values)
);
named!(categories_aggregator<&str, Vec<(&str, HashMap<&str,&str>)> >, many0!(category_and_keys));
fn categories(input: &str) -> IResult<&str, HashMap<&str, HashMap<&str, &str> > > {
let mut h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
match categories_aggregator(input) {
IResult::Done(i,tuple_vec) => {
for &(k,ref v) in &tuple_vec {
h.insert(k, v.clone());
}
IResult::Done(i, h)
},
IResult::Incomplete(a) => IResult::Incomplete(a),
IResult::Error(a) => IResult::Error(a)
}
}
#[test]
fn parse_category_test() {
let ini_file = "[category]
parameter=value
key = value2";
let ini_without_category = "parameter=value
key = value2";
let res = category(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, o) => println!("i: {} | o: {:?}", i, o),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_category, "category"));
}
#[test]
fn parse_key_value_test() {
let ini_file = "parameter=value
key = value2";
let ini_without_key_value = "key = value2";
let res = key_value(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, (o1, o2)) => println!("i: {} | o: ({:?},{:?})", i, o1, o2),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}
#[test]
fn parse_key_value_with_space_test() {
let ini_file = "parameter = value
key = value2";
let ini_without_key_value = "key = value2";
let res = key_value(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, (o1, o2)) => println!("i: {} | o: ({:?},{:?})", i, o1, o2),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}
#[test]
fn parse_key_value_with_comment_test() {
let ini_file = "parameter=value;abc
key = value2";
let ini_without_key_value = "key = value2";
let res = key_value(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, (o1, o2)) => println!("i: {} | o: ({:?},{:?})", i, o1, o2),
_ => println!("error")
}
assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}
#[test]
fn parse_multiple_keys_and_values_test() {
let ini_file = "parameter=value;abc
key = value2
[category]";
let ini_without_key_value = "[category]";
let res = keys_and_values(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, ref o) => println!("i: {} | o: {:?}", i, o),
_ => println!("error")
}
let mut expected: HashMap<&str, &str> = HashMap::new();
expected.insert("parameter", "value");
expected.insert("key", "value2");
assert_eq!(res, IResult::Done(ini_without_key_value, expected));
}
#[test]
fn parse_category_then_multiple_keys_and_values_test() {
//FIXME: there can be an empty line or a comment line after a category
let ini_file = "[abcd]
parameter=value;abc
key = value2
[category]";
let ini_after_parser = "[category]";
let res = category_and_keys(ini_file);
println!("{:?}", res);
match res {
IResult::Done(i, ref o) => println!("i: {} | o: {:?}", i, o),
_ => println!("error")
}
let mut expected_h: HashMap<&str, &str> = HashMap::new();
expected_h.insert("parameter", "value");
expected_h.insert("key", "value2");
assert_eq!(res, IResult::Done(ini_after_parser, ("abcd", expected_h)));
}
#[test]
fn parse_multiple_categories_test() {
let ini_file = "[abcd]
parameter=value;abc
key = value2
[category]
parameter3=value3
key4 = value4
";
let res = categories(ini_file);
//println!("{:?}", res);
match res {
IResult::Done(i, ref o) => println!("i: {} | o: {:?}", i, o),
_ => println!("error")
}
let mut expected_1: HashMap<&str, &str> = HashMap::new();
expected_1.insert("parameter", "value");
expected_1.insert("key", "value2");
let mut expected_2: HashMap<&str, &str> = HashMap::new();
expected_2.insert("parameter3", "value3");
expected_2.insert("key4", "value4");
let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
expected_h.insert("abcd", expected_1);
expected_h.insert("category", expected_2);
assert_eq!(res, IResult::Done("", expected_h));
}

131
third_party/rust/nom-1.2.4/tests/issues.rs поставляемый
Просмотреть файл

@ -1,131 +0,0 @@
//#![feature(trace_macros)]
#[macro_use]
extern crate nom;
use nom::{IResult,Needed,HexDisplay,space,digit,be_u16};
use std::str;
#[allow(dead_code)]
struct Range {
start: char,
end: char
}
pub fn take_char(input: &[u8]) -> IResult<&[u8], char> {
if input.len() > 0 {
IResult::Done(&input[1..], input[0] as char)
} else {
IResult::Incomplete(Needed::Size(1))
}
}
//trace_macros!(true);
#[allow(dead_code)]
named!(range<&[u8], Range>,
alt!(
chain!(
start: take_char ~
tag!("-") ~
end: take_char,
|| {
Range {
start: start,
end: end,
}
}
) |
map!(
take_char,
|c| {
Range {
start: c,
end: c,
}
}
)
)
);
#[allow(dead_code)]
named!(literal<&[u8], Vec<char> >,
map!(
many1!(take_char),
|cs| {
cs
}
)
);
#[test]
fn issue_58() {
range(&b"abcd"[..]);
literal(&b"abcd"[..]);
}
//trace_macros!(false);
named!(parse_ints< Vec<i32> >, many0!(spaces_or_int));
fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32>{
println!("{}", input.to_hex(8));
chain!(input,
opt!(space) ~
x: digit,
|| {
println!("x: {:?}", x);
let result = str::from_utf8(x).unwrap();
println!("Result: {}", result);
println!("int is empty?: {}", x.is_empty());
match result.parse(){
Ok(i) => i,
Err(_) => panic!("UH OH! NOT A DIGIT!")
}
}
)
}
#[test]
fn issue_142(){
let subject = parse_ints(&b"12 34 5689"[..]);
let expected = IResult::Done(&b""[..], vec![12, 34, 5689]);
assert_eq!(subject, expected);
let subject = parse_ints(&b"12 34 5689 "[..]);
let expected = IResult::Done(&b" "[..], vec![12, 34, 5689]);
assert_eq!(subject, expected)
}
#[test]
fn usize_length_bytes_issue(){
length_bytes!(b"012346", be_u16);
}
/*
DOES NOT COMPILE
#[test]
fn issue_152() {
named!(take4, take!(4));
named!(xyz, tag!("XYZ"));
named!(abc, tag!("abc"));
named!(sw,
switch!(take4,
b"abcd" => xyz |
b"efgh" => abc
)
);
}
*/
#[test]
fn take_till_issue() {
named!(nothing,
take_till!(call!(|_| true))
);
assert_eq!(nothing(b""), IResult::Done(&b""[..], &b""[..]));
assert_eq!(nothing(b"abc"), IResult::Done(&b"abc"[..], &b""[..]));
}

531
third_party/rust/nom-1.2.4/tests/mp4.rs поставляемый
Просмотреть файл

@ -1,531 +0,0 @@
#![cfg(feature = "stream")]
#![allow(dead_code)]
#[macro_use]
extern crate nom;
use nom::{HexDisplay,Needed,IResult,be_u16,be_u32,be_u64,be_f32,ErrorKind};
use nom::{Consumer,ConsumerState,Move,Input,Producer,FileProducer,FileProducerState};
use nom::IResult::*;
use nom::Err::*;
use std::str;
use std::io::SeekFrom;
fn mp4_box(input:&[u8]) -> IResult<&[u8], &[u8]> {
match be_u32(input) {
Done(i, offset) => {
let sz: usize = offset as usize;
if i.len() >= sz - 4 {
Done(&i[(sz-4)..], &i[0..(sz-4)])
} else {
Incomplete(Needed::Size(offset as usize + 4))
}
}
Error(e) => Error(e),
Incomplete(e) => Incomplete(e)
}
}
#[derive(PartialEq,Eq,Debug)]
struct FileType<'a> {
major_brand: &'a str,
major_brand_version: &'a [u8],
compatible_brands: Vec<&'a str>
}
#[allow(non_snake_case)]
#[derive(Debug,Clone)]
pub struct Mvhd32 {
version_flags: u32, // actually:
// version: u8,
// flags: u24 // 3 bytes
created_date: u32,
modified_date: u32,
scale: u32,
duration: u32,
speed: f32,
volume: u16, // actually a 2 bytes decimal
/* 10 bytes reserved */
scaleA: f32,
rotateB: f32,
angleU: f32,
rotateC: f32,
scaleD: f32,
angleV: f32,
positionX: f32,
positionY: f32,
scaleW: f32,
preview: u64,
poster: u32,
selection: u64,
current_time: u32,
track_id: u32
}
#[allow(non_snake_case)]
#[derive(Debug,Clone)]
pub struct Mvhd64 {
version_flags: u32, // actually:
// version: u8,
// flags: u24 // 3 bytes
created_date: u64,
modified_date: u64,
scale: u32,
duration: u64,
speed: f32,
volume: u16, // actually a 2 bytes decimal
/* 10 bytes reserved */
scaleA: f32,
rotateB: f32,
angleU: f32,
rotateC: f32,
scaleD: f32,
angleV: f32,
positionX: f32,
positionY: f32,
scaleW: f32,
preview: u64,
poster: u32,
selection: u64,
current_time: u32,
track_id: u32
}
#[allow(non_snake_case)]
named!(mvhd32 <&[u8], MvhdBox>,
chain!(
version_flags: be_u32 ~
created_date: be_u32 ~
modified_date: be_u32 ~
scale: be_u32 ~
duration: be_u32 ~
speed: be_f32 ~
volume: be_u16 ~ // actually a 2 bytes decimal
take!(10) ~
scale_a: be_f32 ~
rotate_b: be_f32 ~
angle_u: be_f32 ~
rotate_c: be_f32 ~
scale_d: be_f32 ~
angle_v: be_f32 ~
position_x: be_f32 ~
position_y: be_f32 ~
scale_w: be_f32 ~
preview: be_u64 ~
poster: be_u32 ~
selection: be_u64 ~
current_time: be_u32 ~
track_id: be_u32,
||{
MvhdBox::M32(Mvhd32 {
version_flags: version_flags,
created_date: created_date,
modified_date: modified_date,
scale: scale,
duration: duration,
speed: speed,
volume: volume,
scaleA: scale_a,
rotateB: rotate_b,
angleU: angle_u,
rotateC: rotate_c,
scaleD: scale_d,
angleV: angle_v,
positionX: position_x,
positionY: position_y,
scaleW: scale_w,
preview: preview,
poster: poster,
selection: selection,
current_time: current_time,
track_id: track_id
})
}
)
);
#[allow(non_snake_case)]
named!(mvhd64 <&[u8], MvhdBox>,
chain!(
version_flags: be_u32 ~
created_date: be_u64 ~
modified_date: be_u64 ~
scale: be_u32 ~
duration: be_u64 ~
speed: be_f32 ~
volume: be_u16 ~ // actually a 2 bytes decimal
take!(10) ~
scale_a: be_f32 ~
rotate_b: be_f32 ~
angle_u: be_f32 ~
rotate_c: be_f32 ~
scale_d: be_f32 ~
angle_v: be_f32 ~
position_x: be_f32 ~
position_y: be_f32 ~
scale_w: be_f32 ~
preview: be_u64 ~
poster: be_u32 ~
selection: be_u64 ~
current_time: be_u32 ~
track_id: be_u32,
||{
MvhdBox::M64(Mvhd64 {
version_flags: version_flags,
created_date: created_date,
modified_date: modified_date,
scale: scale,
duration: duration,
speed: speed,
volume: volume,
scaleA: scale_a,
rotateB: rotate_b,
angleU: angle_u,
rotateC: rotate_c,
scaleD: scale_d,
angleV: angle_v,
positionX: position_x,
positionY: position_y,
scaleW: scale_w,
preview: preview,
poster: poster,
selection: selection,
current_time: current_time,
track_id: track_id
})
}
)
);
#[derive(Debug,Clone)]
pub enum MvhdBox {
M32(Mvhd32),
M64(Mvhd64)
}
#[derive(Debug,Clone)]
pub enum MoovBox {
Mdra,
Dref,
Cmov,
Rmra,
Iods,
Mvhd(MvhdBox),
Clip,
Trak,
Udta
}
#[derive(Debug)]
enum MP4BoxType {
Ftyp,
Moov,
Mdat,
Free,
Skip,
Wide,
Mdra,
Dref,
Cmov,
Rmra,
Iods,
Mvhd,
Clip,
Trak,
Udta,
Unknown
}
#[derive(Debug)]
struct MP4BoxHeader {
length: u32,
tag: MP4BoxType
}
named!(brand_name<&[u8],&str>, map_res!(take!(4), str::from_utf8));
named!(filetype_parser<&[u8], FileType>,
chain!(
m: brand_name ~
v: take!(4) ~
c: many0!(brand_name) ,
||{ FileType{ major_brand: m, major_brand_version:v, compatible_brands: c } }
)
);
fn mvhd_box(input:&[u8]) -> IResult<&[u8],MvhdBox> {
let res = if input.len() < 100 {
Incomplete(Needed::Size(100))
} else if input.len() == 100 {
mvhd32(input)
} else if input.len() == 112 {
mvhd64(input)
} else {
Error(Position(ErrorKind::Custom(32),input))
};
println!("res: {:?}", res);
res
}
fn unknown_box_type(input:&[u8]) -> IResult<&[u8], MP4BoxType> {
Done(input, MP4BoxType::Unknown)
}
//named!(box_type<&[u8], MP4BoxType>,
fn box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType, u32> {
alt!(input,
tag!("ftyp") => { |_| MP4BoxType::Ftyp } |
tag!("moov") => { |_| MP4BoxType::Moov } |
tag!("mdat") => { |_| MP4BoxType::Mdat } |
tag!("free") => { |_| MP4BoxType::Free } |
tag!("skip") => { |_| MP4BoxType::Skip } |
tag!("wide") => { |_| MP4BoxType::Wide } |
unknown_box_type
)
}
// warning, an alt combinator with 9 branches containing a tag combinator
// can make the compilation very slow. Use functions as sub parsers,
// or split into multiple alt! parsers if it gets slow
named!(moov_type<&[u8], MP4BoxType>,
alt!(
tag!("mdra") => { |_| MP4BoxType::Mdra } |
tag!("dref") => { |_| MP4BoxType::Dref } |
tag!("cmov") => { |_| MP4BoxType::Cmov } |
tag!("rmra") => { |_| MP4BoxType::Rmra } |
tag!("iods") => { |_| MP4BoxType::Iods } |
tag!("mvhd") => { |_| MP4BoxType::Mvhd } |
tag!("clip") => { |_| MP4BoxType::Clip } |
tag!("trak") => { |_| MP4BoxType::Trak } |
tag!("udta") => { |_| MP4BoxType::Udta }
)
);
named!(box_header<&[u8],MP4BoxHeader>,
chain!(
length: be_u32 ~
tag: box_type ,
|| { MP4BoxHeader{ length: length, tag: tag} }
)
);
named!(moov_header<&[u8],MP4BoxHeader>,
chain!(
length: be_u32 ~
tag: moov_type ,
|| { MP4BoxHeader{ length: length, tag: tag} }
)
);
#[derive(Debug,PartialEq,Eq)]
enum MP4State {
Main,
Moov,
Mvhd(usize)
}
pub struct MP4Consumer {
state: MP4State,
moov_bytes: usize,
c_state: ConsumerState<(), (), Move>
}
impl MP4Consumer {
fn new() -> MP4Consumer {
MP4Consumer { state: MP4State::Main, moov_bytes: 0, c_state: ConsumerState::Continue(Move::Consume(0)) }
}
fn consume_main(&mut self, input: Input<&[u8]>) -> ConsumerState<(), (), Move> {
//println!("\nparsing box header:\n{}", input.to_hex(8));
match input {
Input::Eof(None) => ConsumerState::Done(Move::Consume(0), ()),
Input::Empty => ConsumerState::Continue(Move::Consume(0)),
Input::Element(sl) | Input::Eof(Some(sl)) => {
match box_header(sl) {
Done(i, header) => {
match header.tag {
MP4BoxType::Ftyp => {
println!("-> FTYP");
match filetype_parser(&i[0..(header.length as usize - 8)]) {
Done(rest, filetype_header) => {
println!("filetype header: {:?}", filetype_header);
//return ConsumerState::Await(header.length as usize, header.length as usize - 8);
return ConsumerState::Continue(Move::Consume(sl.offset(rest)));
}
Error(a) => {
println!("ftyp parsing error: {:?}", a);
assert!(false);
return ConsumerState::Error(());
},
Incomplete(n) => {
println!("ftyp incomplete -> await: {}", sl.len());
return ConsumerState::Continue(Move::Await(n));
//return ConsumerState::Await(0, input.len() + 100);
}
}
},
MP4BoxType::Moov => {
println!("-> MOOV");
self.state = MP4State::Moov;
self.moov_bytes = header.length as usize - 8;
return ConsumerState::Continue(Move::Consume(sl.offset(i)));
},
MP4BoxType::Mdat => println!("-> MDAT"),
MP4BoxType::Free => println!("-> FREE"),
MP4BoxType::Skip => println!("-> SKIP"),
MP4BoxType::Wide => println!("-> WIDE"),
MP4BoxType::Unknown => {
println!("-> UNKNOWN");
println!("bytes:\n{}", (sl).to_hex(8));
//return ConsumerState::Continue(Move::Consume(sl.offset(i)));
},
_ => { println!("invalid"); return ConsumerState::Error(())}
}
return ConsumerState::Continue(Move::Seek(SeekFrom::Current((header.length) as i64)))
},
Error(a) => {
println!("mp4 parsing error: {:?}", a);
assert!(false);
return ConsumerState::Error(());
},
Incomplete(i) => {
// FIXME: incomplete should send the required size
println!("mp4 incomplete -> await: {}", sl.len());
return ConsumerState::Continue(Move::Await(i));
}
}
}
}
}
fn consume_moov(&mut self, input: Input<&[u8]>) -> ConsumerState<(), (), Move> {
//println!("\nparsing moov box(remaining {} bytes):\n{}", self.moov_bytes, input.to_hex(8));
match input {
Input::Eof(None) => return ConsumerState::Error(()),
Input::Empty => return ConsumerState::Continue(Move::Consume(0)),
Input::Element(sl) | Input::Eof(Some(sl)) => {
if self.moov_bytes == 0 {
//println!("finished parsing moov atom, continuing with main parser");
self.state = MP4State::Main;
return ConsumerState::Continue(Move::Consume(0));
}
match moov_header(sl) {
Done(i, header) => {
match header.tag {
MP4BoxType::Mvhd => {
println!("-> MVHD");
self.state = MP4State::Mvhd(header.length as usize - 8);
// TODO: check for overflow here
self.moov_bytes = self.moov_bytes - (sl.len() - i.len());
println!("remaining moov_bytes: {}", self.moov_bytes);
return ConsumerState::Continue(Move::Consume(sl.offset(i)));
},
MP4BoxType::Wide => println!("-> WIDE"),
MP4BoxType::Mdra => println!("-> MDRA"),
MP4BoxType::Dref => println!("-> DREF"),
MP4BoxType::Cmov => println!("-> CMOV"),
MP4BoxType::Rmra => println!("-> RMRA"),
MP4BoxType::Iods => println!("-> IODS"),
MP4BoxType::Clip => println!("-> CLIP"),
MP4BoxType::Trak => println!("-> TRAK"),
MP4BoxType::Udta => println!("-> UDTA"),
MP4BoxType::Unknown => println!("-> MOOV UNKNOWN"),
_ => { println!("invalid header here: {:?}", header.tag); return ConsumerState::Error(());}
};
// TODO: check for overflow here
self.moov_bytes = self.moov_bytes - header.length as usize;
println!("remaining moov_bytes: {}", self.moov_bytes);
return ConsumerState::Continue(Move::Seek(SeekFrom::Current((header.length) as i64)))
},
Error(a) => {
println!("moov parsing error: {:?}", a);
println!("data:\n{}", sl.to_hex(8));
assert!(false);
return ConsumerState::Error(());
},
Incomplete(i) => {
println!("moov incomplete -> await: {}", sl.len());
return ConsumerState::Continue(Move::Await(i));
}
}
}
};
}
}
consumer_from_parser!(MvhdConsumer<MvhdBox>, mvhd_box);
impl<'a> Consumer<&'a[u8], (), (), Move> for MP4Consumer {
fn handle(&mut self, input: Input<&[u8]>) -> &ConsumerState<(), (), Move> {
match self.state {
MP4State::Main => {
self.c_state = self.consume_main(input);
},
MP4State::Moov => {
self.c_state = self.consume_moov(input);
},
MP4State::Mvhd(sz) => {
match input {
Input::Eof(None) => self.c_state = ConsumerState::Error(()),
Input::Empty => self.c_state = ConsumerState::Continue(Move::Consume(0)),
Input::Element(sl) | Input::Eof(Some(sl)) => {
let mut c = MvhdConsumer{ state:ConsumerState::Continue(Move::Consume(0)) };
self.c_state = c.handle(Input::Element(&sl[..sz])).flat_map(|m, _| {
self.state = MP4State::Moov;
ConsumerState::Continue(m)
});
println!("found mvhd?: {:?}", c.state());
match self.c_state {
ConsumerState::Continue(Move::Consume(sz)) => self.moov_bytes = self.moov_bytes - sz,
ConsumerState::Continue(Move::Seek(SeekFrom::Current(sz))) => self.moov_bytes = self.moov_bytes - (sz as usize),
_ => ()
};
println!("remaining moov_bytes: {}", self.moov_bytes);
}
}
}
};
&self.c_state
}
fn state(&self) -> &ConsumerState<(), (), Move> {
&self.c_state
}
}
#[allow(unused_must_use)]
fn explore_mp4_file(filename: &str) {
let mut p = FileProducer::new(filename, 400).unwrap();
let mut c = MP4Consumer{state: MP4State::Main, moov_bytes: 0, c_state: ConsumerState::Continue(Move::Consume(0))};
//c.run(&mut p);
while let &ConsumerState::Continue(mv) = p.apply(&mut c) {
println!("move: {:?}", mv);
}
println!("last consumer state: {:?} | last state: {:?}", c.c_state, c.state);
if let ConsumerState::Done(Move::Consume(0), ()) = c.c_state {
println!("consumer state ok");
} else {
assert!(false, "consumer should have reached Done state");
}
assert_eq!(c.state, MP4State::Main);
assert_eq!(p.state(), FileProducerState::Eof);
//assert!(false);
}
#[test]
fn small_test() {
explore_mp4_file("assets/small.mp4");
}
#[test]
fn big_bunny_test() {
explore_mp4_file("assets/bigbuckbunny.mp4");
}

160
third_party/rust/nom-1.2.4/tests/omnom.rs поставляемый
Просмотреть файл

@ -1,160 +0,0 @@
#![cfg(feature = "stream")]
#[macro_use]
extern crate nom;
use nom::{Producer,Consumer,ConsumerState,Input,Move,MemProducer,IResult,HexDisplay};
#[derive(PartialEq,Eq,Debug)]
enum State {
Beginning,
Middle,
End,
Done,
Error
}
struct TestConsumer {
state: State,
c_state: ConsumerState<usize,(),Move>,
counter: usize,
}
named!(om_parser, tag!("om"));
named!(nomnom_parser<&[u8],Vec<&[u8]> >, many1!(tag!("nom")));
named!(end_parser, tag!("kthxbye"));
impl<'a> Consumer<&'a[u8], usize, (), Move> for TestConsumer {
fn state(&self) -> &ConsumerState<usize,(),Move> {
&self.c_state
}
fn handle(&mut self, input: Input<&'a [u8]>) -> &ConsumerState<usize,(),Move> {
match self.state {
State::Beginning => {
match input {
Input::Empty | Input::Eof(None) => {
self.state = State::Error;
self.c_state = ConsumerState::Error(());
},
Input::Element(sl) | Input::Eof(Some(sl)) => {
match om_parser(sl) {
IResult::Error(_) => {
self.state = State::Error;
self.c_state = ConsumerState::Error(());
},
IResult::Incomplete(n) => {
self.c_state = ConsumerState::Continue(Move::Await(n));
},
IResult::Done(i,_) => {
self.state = State::Middle;
self.c_state = ConsumerState::Continue(Move::Consume(sl.offset(i)));
}
}
}
}
},
State::Middle => {
match input {
Input::Empty | Input::Eof(None) => {
self.state = State::Error;
self.c_state = ConsumerState::Error(());
},
Input::Element(sl) | Input::Eof(Some(sl)) => {
match nomnom_parser(sl) {
IResult::Error(_) => {
self.state = State::End;
self.c_state = ConsumerState::Continue(Move::Consume(0));
},
IResult::Incomplete(n) => {
println!("Middle got Incomplete({:?})", n);
self.c_state = ConsumerState::Continue(Move::Await(n));
},
IResult::Done(i,noms_vec) => {
self.counter = self.counter + noms_vec.len();
self.state = State::Middle;
self.c_state = ConsumerState::Continue(Move::Consume(sl.offset(i)));
}
}
}
}
},
State::End => {
match input {
Input::Empty | Input::Eof(None) => {
self.state = State::Error;
self.c_state = ConsumerState::Error(());
},
Input::Element(sl) | Input::Eof(Some(sl)) => {
match end_parser(sl) {
IResult::Error(_) => {
self.state = State::Error;
self.c_state = ConsumerState::Error(());
},
IResult::Incomplete(n) => {
self.c_state = ConsumerState::Continue(Move::Await(n));
},
IResult::Done(i,_) => {
self.state = State::Done;
self.c_state = ConsumerState::Done(Move::Consume(sl.offset(i)), self.counter);
}
}
}
}
},
State::Done | State::Error => {
// this should not be called
self.state = State::Error;
self.c_state = ConsumerState::Error(())
}
};
&self.c_state
}
}
#[test]
fn nom1() {
let mut p = MemProducer::new(&b"omnomkthxbye"[..], 8);
let mut c = TestConsumer{state: State::Beginning, counter: 0, c_state: ConsumerState::Continue(Move::Consume(0))};
while let &ConsumerState::Continue(Move::Consume(_)) = p.apply(&mut c) {
}
assert_eq!(c.counter, 1);
assert_eq!(c.state, State::Done);
}
#[test]
fn nomnomnom() {
let mut p = MemProducer::new(&b"omnomnomnomkthxbye"[..], 9);
let mut c = TestConsumer{state: State::Beginning, counter: 0, c_state: ConsumerState::Continue(Move::Consume(0))};
while let &ConsumerState::Continue(_) = p.apply(&mut c) {
}
assert_eq!(c.counter, 3);
assert_eq!(c.state, State::Done);
}
#[test]
fn no_nomnom() {
let mut p = MemProducer::new(&b"omkthxbye"[..], 8);
let mut c = TestConsumer{state: State::Beginning, counter: 0, c_state: ConsumerState::Continue(Move::Consume(0))};
while let &ConsumerState::Continue(_) = p.apply(&mut c) {
}
assert_eq!(c.counter, 0);
assert_eq!(c.state, State::Done);
}
/*
#[test]
fn impolite() {
let mut p = MemProducer::new(&b"omnomnomnom"[..], 11);
let mut c = TestConsumer{state: State::Beginning, counter: 0, c_state: ConsumerState::Continue(Move::Consume(0))};
while let &ConsumerState::Continue(cont) = p.apply(&mut c) {
println!("continue {:?}", cont);
}
assert_eq!(c.counter, 3);
assert_eq!(c.state, State::End);
}
*/

44
third_party/rust/nom-1.2.4/tests/test1.rs поставляемый
Просмотреть файл

@ -1,44 +0,0 @@
#![cfg(feature = "stream")]
#[macro_use]
extern crate nom;
use nom::{IResult,Producer,FileProducer,not_line_ending};
use std::str;
use std::fmt::Debug;
#[test]
#[allow(unused_must_use)]
fn tag() {
FileProducer::new("assets/links.txt", 20).map(|producer: FileProducer| {
let mut p = producer;
p.refill();
consumer_from_parser!(PrintConsumer<()>, flat_map!(map_res!(tag!("https!"), str::from_utf8), print));
let mut cs = PrintConsumer::new();
for _ in 1..4 {
p.apply(&mut cs);
}
});
}
pub fn print<T: Debug>(input: T) -> IResult<T,()> {
println!("{:?}", input);
IResult::Done(input, ())
}
#[test]
fn is_not() {
//is_not!(foo b"\r\n");
named!(foo<&[u8],&[u8]>, is_not!(&b"\r\n"[..]));
let a = &b"ab12cd\nefgh"[..];
assert_eq!(foo(a), IResult::Done(&b"\nefgh"[..], &b"ab12cd"[..]));
}
#[test]
fn exported_public_method_defined_by_macro() {
let a = &b"ab12cd\nefgh"[..];
assert_eq!(not_line_ending(a), IResult::Done(&b"\nefgh"[..], &b"ab12cd"[..]));
}