Repository: Geal/nom
Pull request #835 (2018-09-24 19:10:16)

Simplify is_hex_digit() in example.
This simplifies the `is_hex_digit()` implementation in the example in the README file by referring to the core method `char::is_digit()`.  It's not really an important change, but I think it puts more focus on the bits of the code that are specific to nom.  (I'm not sure the function is needed at all, since there's also an `is_hex_digit()` built into nom now, but I wanted to keep the change minimal – I'm not really familiar with nom.)


coveralls: 
[![Coverage Status](https://coveralls.io/builds/19162934/badge)](https://coveralls.io/builds/19162934)

Coverage increased (+0.02%) to 87.251% when pulling **faa85bf6b59ea1bfb7b1fd0874a4ba5d7ac463f8 on smarnach:smarnach/simplify-hex-digit-test** into **d77fb85e9860b0db00c7aeb1dd38899c892c6058 on Geal:master**.


Patch:
diff --git a/README.md b/README.md
index d38e8da..d21ed3c 100644
--- a/README.md
+++ b/README.md
@@ -32,10 +32,7 @@ fn from_hex(input: &str) -> Result<u8, std::num::ParseIntError> {
 }
 
 fn is_hex_digit(c: char) -> bool {
-  match c {
-    '0'..='9' | 'a'..='f' | 'A'..='F' => true,
-    _ => false,
-  }
+  c.is_digit(16)
 }
 
 named!(hex_primary<&str, u8>,
diff --git a/doc/choosing_a_combinator.md b/doc/choosing_a_combinator.md
index c1b0ccb..6a90cba 100644
--- a/doc/choosing_a_combinator.md
+++ b/doc/choosing_a_combinator.md
@@ -6,55 +6,55 @@ Those are used to recognize the lowest level elements of your grammar, like, "he
 
 | combinator|usage | input | output | comment |
 |---|---|---|---|---|
-| [char](https://docs.rs/nom/4.0.0-alpha2/nom/macro.char.html) | `char!('a')` |  `"abc"` | `Ok(("bc", 'a'))`| matches one character (works with non ASCII chars too) | 
-|[is_a](https://docs.rs/nom/4.0.0-alpha2/nom/macro.is_a.html) | ` is_a!("ab")` |  `"ababc"` | `Ok(("c", "abab"))`|matches a sequence of any of the characters passed as arguments|
-| [is_not](https://docs.rs/nom/4.0.0-alpha2/nom/macro.is_not.html) |`is_not!("cd")` |  `"ababc"` | `Ok(("c", "abab"))`|matches a sequence of none of the characters passed as arguments|
-| [one_of](https://docs.rs/nom/4.0.0-alpha2/nom/macro.one_of.html) |`one_of!("abc")` |  `"abc"` | `Ok(("bc", 'a'))`|matches one of the provided characters (works with non ASCII characters too)|
-| [none_of](https://docs.rs/nom/4.0.0-alpha2/nom/macro.none_of.html) |`none_of!("abc")` |  `"xyab"` | `Ok( ("yab", 'x') )`|matches anything but the provided characters|
-| [tag](https://docs.rs/nom/4.0.0-alpha2/nom/macro.tag.html) |`tag!("hello")` |  `"hello world"` | `Ok( (" world", "hello") )`|recognizes a specific suite of characters or bytes|
-| [tag_no_case](https://docs.rs/nom/4.0.0-alpha2/nom/macro.tag_no_case.html) |`tag_no_case!("hello")` |  `"HeLLo World"` | `Ok( (" World", "HeLLo") )`|case insensitive comparison. Note that case insensitive comparison is not well defined for unicode, and that you might have bad surprises|
-| [take](https://docs.rs/nom/4.0.0-alpha2/nom/macro.take.html) |`take!(4)` |  `"hello"` | `Ok( ("o", "hell") )`|takes a specific number of bytes or characters|
-| [take_while](https://docs.rs/nom/4.0.0-alpha2/nom/macro.take_while.html) |`take_while!(is_alphabetic)` |  `"abc123"` | `Ok( ("123", "abc") )`| returns the longest list of bytes for which the provided function returns true. `take_while1` does the same, but must return at least one character|
-| [take_till](https://docs.rs/nom/4.0.0-alpha2/nom/macro.take_till.html) |`take_till!(is_alphabetic)` |  `"123abc"` | `Ok( ("abc", "123) )`|returns the longest list of bytes or characters until the provided function returns true. `take_till1` does the same, but must return at least one character. This is the reverse behaviour from `take_while`: `take_till!(f)` is equivalent to `take_while!(|c| !f(c))`|
-|[take_until](https://docs.rs/nom/4.0.0-alpha2/nom/macro.take_until.html) | `take_until!("world")` |  `"Hello world"` | `Ok( ("world", "Hello ") )`|returns the longest list of bytes or characters until the provided tag is found. `take_until1` does the same, but must return at least one character|
-|[take_until_ and_consume](https://docs.rs/nom/4.0.0-alpha2/nom/macro.take_until_and_consume.html) | `take_until_and_consume!("world")` |  `"Hello world!"` | `Ok( ("!", "Hello ") )`| same as `take_until` but consumes the tag. `take_until_and_consume1` does the same, but must return at least one character|
-| [take_until_either](https://docs.rs/nom/4.0.0-alpha2/nom/macro.take_until_either.html) |`take_until_either!` |  `` | ``|DEPRECATED? returns the longest list of bytes until any of the provided characters are found|
-| [take_until_ either_and_consume](https://docs.rs/nom/4.0.0-alpha2/nom/macro.take_until_either_and_consume.html) |`take_until_either_and_consume` |  `` | ``|DEPRECATED? same as take_until_either!, but consumes the terminating character|
-|[value](https://docs.rs/nom/4.0.0-alpha2/nom/macro.value.html) | `value!(42, tag!("abcd"))` |`"abcdef"` | `Ok( ("ef", 42) )`|replaces the result of the child parser with the provided value. Can also be used without a child parser. `value!(42)` would return the `42` value without consuming the input|
+| [char](https://docs.rs/nom/4.0.0/nom/macro.char.html) | `char!('a')` |  `"abc"` | `Ok(("bc", 'a'))`| matches one character (works with non ASCII chars too) | 
+|[is_a](https://docs.rs/nom/4.0.0/nom/macro.is_a.html) | ` is_a!("ab")` |  `"ababc"` | `Ok(("c", "abab"))`|matches a sequence of any of the characters passed as arguments|
+| [is_not](https://docs.rs/nom/4.0.0/nom/macro.is_not.html) |`is_not!("cd")` |  `"ababc"` | `Ok(("c", "abab"))`|matches a sequence of none of the characters passed as arguments|
+| [one_of](https://docs.rs/nom/4.0.0/nom/macro.one_of.html) |`one_of!("abc")` |  `"abc"` | `Ok(("bc", 'a'))`|matches one of the provided characters (works with non ASCII characters too)|
+| [none_of](https://docs.rs/nom/4.0.0/nom/macro.none_of.html) |`none_of!("abc")` |  `"xyab"` | `Ok( ("yab", 'x') )`|matches anything but the provided characters|
+| [tag](https://docs.rs/nom/4.0.0/nom/macro.tag.html) |`tag!("hello")` |  `"hello world"` | `Ok( (" world", "hello") )`|recognizes a specific suite of characters or bytes|
+| [tag_no_case](https://docs.rs/nom/4.0.0/nom/macro.tag_no_case.html) |`tag_no_case!("hello")` |  `"HeLLo World"` | `Ok( (" World", "HeLLo") )`|case insensitive comparison. Note that case insensitive comparison is not well defined for unicode, and that you might have bad surprises|
+| [take](https://docs.rs/nom/4.0.0/nom/macro.take.html) |`take!(4)` |  `"hello"` | `Ok( ("o", "hell") )`|takes a specific number of bytes or characters|
+| [take_while](https://docs.rs/nom/4.0.0/nom/macro.take_while.html) |`take_while!(is_alphabetic)` |  `"abc123"` | `Ok( ("123", "abc") )`| returns the longest list of bytes for which the provided function returns true. `take_while1` does the same, but must return at least one character|
+| [take_till](https://docs.rs/nom/4.0.0/nom/macro.take_till.html) |`take_till!(is_alphabetic)` |  `"123abc"` | `Ok( ("abc", "123) )`|returns the longest list of bytes or characters until the provided function returns true. `take_till1` does the same, but must return at least one character. This is the reverse behaviour from `take_while`: `take_till!(f)` is equivalent to `take_while!(|c| !f(c))`|
+|[take_until](https://docs.rs/nom/4.0.0/nom/macro.take_until.html) | `take_until!("world")` |  `"Hello world"` | `Ok( ("world", "Hello ") )`|returns the longest list of bytes or characters until the provided tag is found. `take_until1` does the same, but must return at least one character|
+|[take_until_ and_consume](https://docs.rs/nom/4.0.0/nom/macro.take_until_and_consume.html) | `take_until_and_consume!("world")` |  `"Hello world!"` | `Ok( ("!", "Hello ") )`| same as `take_until` but consumes the tag. `take_until_and_consume1` does the same, but must return at least one character|
+| [take_until_either](https://docs.rs/nom/4.0.0/nom/macro.take_until_either.html) |`take_until_either!` |  `` | ``|DEPRECATED? returns the longest list of bytes until any of the provided characters are found|
+| [take_until_ either_and_consume](https://docs.rs/nom/4.0.0/nom/macro.take_until_either_and_consume.html) |`take_until_either_and_consume` |  `` | ``|DEPRECATED? same as take_until_either!, but consumes the terminating character|
+|[value](https://docs.rs/nom/4.0.0/nom/macro.value.html) | `value!(42, tag!("abcd"))` |`"abcdef"` | `Ok( ("ef", 42) )`|replaces the result of the child parser with the provided value. Can also be used without a child parser. `value!(42)` would return the `42` value without consuming the input|
 
 
 ## Choice combinators
 
 | combinator | usage | input | output | comment |
 |---|---|---|---|---|
-| [alt](https://docs.rs/nom/4.0.0-alpha2/nom/macro.alt.html) |`alt!(tag!("ab") \| tag!("cd"))` |  `"cdef"` | `Ok( ("ef", "cd") )`|try a list of parsers and return the result of the first successful one|
-| [switch](https://docs.rs/nom/4.0.0-alpha2/nom/macro.switch.html) |`switch!(take!(2), "ab" => tag!("XYZ") \| "cd" => tag!("123"))` |  `"cd1234"` | `Ok(("4", "123"))`|choose the next parser depending on the result of the first one, if successful, and returns the result of the second parser|
-|[permutation](https://docs.rs/nom/4.0.0-alpha2/nom/macro.permutation.html) | `permutation!(tag!("ab"), tag!("cd"), tag!("12"))` |  `"cd12abc"` | `Ok( ("c", ("ab", "cd", "12") )`|succeeds when all its child parser have succeeded, whatever the order|
+| [alt](https://docs.rs/nom/4.0.0/nom/macro.alt.html) |`alt!(tag!("ab") \| tag!("cd"))` |  `"cdef"` | `Ok( ("ef", "cd") )`|try a list of parsers and return the result of the first successful one|
+| [switch](https://docs.rs/nom/4.0.0/nom/macro.switch.html) |`switch!(take!(2), "ab" => tag!("XYZ") \| "cd" => tag!("123"))` |  `"cd1234"` | `Ok(("4", "123"))`|choose the next parser depending on the result of the first one, if successful, and returns the result of the second parser|
+|[permutation](https://docs.rs/nom/4.0.0/nom/macro.permutation.html) | `permutation!(tag!("ab"), tag!("cd"), tag!("12"))` |  `"cd12abc"` | `Ok( ("c", ("ab", "cd", "12") )`|succeeds when all its child parser have succeeded, whatever the order|
 
 ## Sequence combinators
 | combinator|usage | input | output | comment |
 |---|---|---|---|---|
-| [delimited](https://docs.rs/nom/4.0.0-alpha2/nom/macro.delimited.html) |`delimited!(char!('('), take(2), char!(')'))` |  `"(ab)cd"` | `Ok( ("cd", "ab") )`||
-| [preceded](https://docs.rs/nom/4.0.0-alpha2/nom/macro.preceded.html) |`preceded!(tag!("ab"), tag!("XY"))` |  `"abXYZ"` | `Ok( ("Z", "XY") )`||
-| [terminated](https://docs.rs/nom/4.0.0-alpha2/nom/macro.terminated.html) |`terminated!(tag!("ab"), tag!("XY"))` |  `"abXYZ"` | `Ok( ("Z", "ab") )`||
-| [pair](https://docs.rs/nom/4.0.0-alpha2/nom/macro.pair.html) |`pair!(tag!("ab"), tag!("XY"))` |  `"abXYZ"` | `Ok( ("Z", ("ab", "XY")) )`||
-| [separated_pair](https://docs.rs/nom/4.0.0-alpha2/nom/macro.separated_pair.html) |`separated_pair!(tag!("hello"), char!(','), tag!("world"))` |  `"hello,world!"` | `Ok( ("!", ("hello", "world")) )`||
-| [tuple](https://docs.rs/nom/4.0.0-alpha2/nom/macro.tuple.html) |`tuple!(tag!("ab"), tag!("XY"), take!(1))` |  `"abXYZ!"` | `Ok( ("!", ("ab", "XY", "Z")) )`|chains parsers and assemble the sub results in a tuple. You can use as many child parsers as you can put elements in a tuple|
-| [do_parse](https://docs.rs/nom/4.0.0-alpha2/nom/macro.do_parse.html) |`do_parse!(tag: take!(2) >> length: be_u8 >> data: take!(length) >> (Buffer { tag: tag, data: data}) )` |  `&[0, 0, 3, 1, 2, 3][..]` | `Buffer { tag: &[0, 0][..], data: &[1, 2, 3][..] }`|`do_parse` applies sub parsers in a sequence. it can store intermediary results and make them available for later parsers|
+| [delimited](https://docs.rs/nom/4.0.0/nom/macro.delimited.html) |`delimited!(char!('('), take(2), char!(')'))` |  `"(ab)cd"` | `Ok( ("cd", "ab") )`||
+| [preceded](https://docs.rs/nom/4.0.0/nom/macro.preceded.html) |`preceded!(tag!("ab"), tag!("XY"))` |  `"abXYZ"` | `Ok( ("Z", "XY") )`||
+| [terminated](https://docs.rs/nom/4.0.0/nom/macro.terminated.html) |`terminated!(tag!("ab"), tag!("XY"))` |  `"abXYZ"` | `Ok( ("Z", "ab") )`||
+| [pair](https://docs.rs/nom/4.0.0/nom/macro.pair.html) |`pair!(tag!("ab"), tag!("XY"))` |  `"abXYZ"` | `Ok( ("Z", ("ab", "XY")) )`||
+| [separated_pair](https://docs.rs/nom/4.0.0/nom/macro.separated_pair.html) |`separated_pair!(tag!("hello"), char!(','), tag!("world"))` |  `"hello,world!"` | `Ok( ("!", ("hello", "world")) )`||
+| [tuple](https://docs.rs/nom/4.0.0/nom/macro.tuple.html) |`tuple!(tag!("ab"), tag!("XY"), take!(1))` |  `"abXYZ!"` | `Ok( ("!", ("ab", "XY", "Z")) )`|chains parsers and assemble the sub results in a tuple. You can use as many child parsers as you can put elements in a tuple|
+| [do_parse](https://docs.rs/nom/4.0.0/nom/macro.do_parse.html) |`do_parse!(tag: take!(2) >> length: be_u8 >> data: take!(length) >> (Buffer { tag: tag, data: data}) )` |  `&[0, 0, 3, 1, 2, 3][..]` | `Buffer { tag: &[0, 0][..], data: &[1, 2, 3][..] }`|`do_parse` applies sub parsers in a sequence. it can store intermediary results and make them available for later parsers|
 
 ## Applying a parser multiple times
 
 | combinatoe|usage | input | output | comment |
 |---|---|---|---|---|
-| [count](https://docs.rs/nom/4.0.0-alpha2/nom/macro.count.html) |`count!(take!(2), 3)` |  `"abcdefgh"` | `Ok( ("gh", vec!("ab", "cd", "ef")) )`|applies the child parser a specified number of times|
-| [count_fixed](https://docs.rs/nom/4.0.0-alpha2/nom/macro.count_fixed.html) |`count_fixed!(&[u8], take!(2), 3)` |  `"abcdefgh"` | `Ok( ("gh", ["ab", "cd", "ef"]))`|applies the child parser a fixed number of times and returns a fixed size array. The type must be specified and it must be `Copy`|
-| [many0](https://docs.rs/nom/4.0.0-alpha2/nom/macro.many0.html) |`many0!(tag!("ab"))` |  `"abababc"` | `Ok( ("c", vec!("ab", "ab", "ab")) )`|Applies the parser 0 or more times and returns the list of results in a Vec. `many1` does the same operation but must return at least one element|
-| [many_m_n](https://docs.rs/nom/4.0.0-alpha2/nom/macro.many_m_n.html) |`many_m_n!(1, 3, tag!("ab"))` |  `"ababc"` | `Ok( ("c", vec!("ab", "ab")) )`|applies the parser between m and n times (n included) and returns the list of results in a Vec|
-| [many_till](https://docs.rs/nom/4.0.0-alpha2/nom/macro.many_till.html) |`many_till!( tag!( "ab" ), tag!( "ef" ) )` |  `"ababefg"` | `Ok( ("g", (vec!("ab", "ab"), "ef")) )`|Applies the first parser until the second applies. Returns a tuple containing the list of results from the first in a Vec and the result of the second.|
-| [separated_list](https://docs.rs/nom/4.0.0-alpha2/nom/macro.separated_list.html) |`separated_list!(tag!(","), tag!("ab"))` |  `"ab,ab,ab."` | `Ok( (".", vec!("ab", "ab", "ab")) )`|`separated_nonempty_list` works like `separated_list` but must returns at least one element|
-| [fold_many0](https://docs.rs/nom/4.0.0-alpha2/nom/macro.fold_many0.html) |`fold_many0!(be_u8, 0, \|acc, item\| acc + item)` |  `[1, 2, 3]` | `Ok( ([], 6) )`|applies the parser 0 or more times and folds the list of return values. The `fold_many1` version must apply the child parser at least one time|
-| [fold_many_m_n](https://docs.rs/nom/4.0.0-alpha2/nom/macro.fold_many_m_n.html) |`fold_many_m_n!(1, 2, be_u8, 0, \|acc, item\| acc + item)` |  `[1, 2, 3]` | `Ok( ([3], 3))`|applies the parser between m and n times (n included) and folds the list of return value|
-| [length_count](https://docs.rs/nom/4.0.0-alpha2/nom/macro.length_count.html) |`length_count!(number, tag!("ab"))` |  `"2ababab"` | `Ok( ("ab", vec!("ab", "ab")) )`|gets a number from the first parser, then applies the second parser that many times|
+| [count](https://docs.rs/nom/4.0.0/nom/macro.count.html) |`count!(take!(2), 3)` |  `"abcdefgh"` | `Ok( ("gh", vec!("ab", "cd", "ef")) )`|applies the child parser a specified number of times|
+| [count_fixed](https://docs.rs/nom/4.0.0/nom/macro.count_fixed.html) |`count_fixed!(&[u8], take!(2), 3)` |  `"abcdefgh"` | `Ok( ("gh", ["ab", "cd", "ef"]))`|applies the child parser a fixed number of times and returns a fixed size array. The type must be specified and it must be `Copy`|
+| [many0](https://docs.rs/nom/4.0.0/nom/macro.many0.html) |`many0!(tag!("ab"))` |  `"abababc"` | `Ok( ("c", vec!("ab", "ab", "ab")) )`|Applies the parser 0 or more times and returns the list of results in a Vec. `many1` does the same operation but must return at least one element|
+| [many_m_n](https://docs.rs/nom/4.0.0/nom/macro.many_m_n.html) |`many_m_n!(1, 3, tag!("ab"))` |  `"ababc"` | `Ok( ("c", vec!("ab", "ab")) )`|applies the parser between m and n times (n included) and returns the list of results in a Vec|
+| [many_till](https://docs.rs/nom/4.0.0/nom/macro.many_till.html) |`many_till!( tag!( "ab" ), tag!( "ef" ) )` |  `"ababefg"` | `Ok( ("g", (vec!("ab", "ab"), "ef")) )`|Applies the first parser until the second applies. Returns a tuple containing the list of results from the first in a Vec and the result of the second.|
+| [separated_list](https://docs.rs/nom/4.0.0/nom/macro.separated_list.html) |`separated_list!(tag!(","), tag!("ab"))` |  `"ab,ab,ab."` | `Ok( (".", vec!("ab", "ab", "ab")) )`|`separated_nonempty_list` works like `separated_list` but must returns at least one element|
+| [fold_many0](https://docs.rs/nom/4.0.0/nom/macro.fold_many0.html) |`fold_many0!(be_u8, 0, \|acc, item\| acc + item)` |  `[1, 2, 3]` | `Ok( ([], 6) )`|applies the parser 0 or more times and folds the list of return values. The `fold_many1` version must apply the child parser at least one time|
+| [fold_many_m_n](https://docs.rs/nom/4.0.0/nom/macro.fold_many_m_n.html) |`fold_many_m_n!(1, 2, be_u8, 0, \|acc, item\| acc + item)` |  `[1, 2, 3]` | `Ok( ([3], 3))`|applies the parser between m and n times (n included) and folds the list of return value|
+| [length_count](https://docs.rs/nom/4.0.0/nom/macro.length_count.html) |`length_count!(number, tag!("ab"))` |  `"2ababab"` | `Ok( ("ab", vec!("ab", "ab")) )`|gets a number from the first parser, then applies the second parser that many times|
 
 ## Integers
 
@@ -77,13 +77,6 @@ Parsing integers from binary formats can be done in two ways: with parser functi
 - separated_nonempty_list_complete!: This is equivalent to the separated_nonempty_list! combinator, except that it will return Error when either the separator or element subparser returns Incomplete.
 
 ## Modifiers
-| usage | input | output | comment |
-|---|---|---|---|
-| `` |  `` | ``||
-| `` |  `` | ``||
-| `` |  `` | ``||
-| `` |  `` | ``||
-| `` |  `` | ``||
 
 - cond!: conditional combinator
 - cond_reduce!: Conditional combinator with error
diff --git a/doc/error_management.md b/doc/error_management.md
index 8494adf..7f4063f 100644
--- a/doc/error_management.md
+++ b/doc/error_management.md
@@ -1,5 +1,3 @@
-% Error management
-
 # Error management
 
 Parser combinators are useful tools to build parsers, but they are notoriously bad at error reporting. This happens because a tree of parser acts as a single parser, and the only error you get will come from the root parser.
@@ -27,7 +25,7 @@ fn main() {
 
 Result:
 
-```ignore
+```rust
 Error(Position(0, [101, 102, 103, 104])) at l.5 by " tag ! ( "abcd" ) "
 ```
 
@@ -46,7 +44,7 @@ fn main() {
 
 It will print, along with the result and the parser, a hexdump of the input buffer passed to the parser.
 
-```ignore
+```
 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
 ```
@@ -55,7 +53,7 @@ Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by " tag ! (
 
 As a reminder, here are the basic types of nom:
 
-```ignore
+```rust
 pub type IResult<I, O, E = u32> = Result<(I, O), Err<I, E>>;
 #[derive(Debug,PartialEq,Eq,CLone,Copy)]
 pub enum Needed {
@@ -106,11 +104,7 @@ If you need more information on the errors, or want to act on them in the callin
 
 Sometimes, you want to provide an error code at a specific point in the parser tree. The `add_return_error!` macro can be used for this:
 
-```ignore
-# #[macro_use] extern crate nom;
-# use nom::ErrorKind;
-# use nom::Err::*;
-# use nom::IResult::Error;
+```rust
 named!(err_test,
   preceded!(tag!("efgh"), add_return_error!(ErrorKind::Custom(42),
       do_parse!(
@@ -121,13 +115,11 @@ named!(err_test,
     )
 ));
 
-# fn main() {
 let a = &b"efghblah"[..];
 let blah = &b"blah"[..];
 
 let res_a = err_test(a);
 assert_eq!(res_a, Error(NodePosition(ErrorKind::Custom(42), blah, Box::new(Position(ErrorKind::Tag, blah)))));
-# }
 ```
 
 If the child parser returns an error, `add_return_error!` will add its own at the head of the error chain.
@@ -140,11 +132,7 @@ If another `return_error!` call is present in the parent parsing chain, it will
 
 Here is how it works in practice:
 
-```ignore
-# #[macro_use] extern crate nom;
-# use nom::ErrorKind;
-# use nom::IResult::Error;
-# use nom::Err::*;
+```rust
 named!(err_test, alt!(
   tag!("abcd") |
   preceded!(
@@ -160,7 +148,6 @@ named!(err_test, alt!(
   )
 ));
 
-# fn main() {
 let a = &b"efghblah"[..];
 let b = &b"efghijklblah"[..];
 
@@ -178,7 +165,6 @@ assert_eq!(res_b, Error(
     ))
   )
 ));
-# }
 ```
 
 With this mechanism, you get a chain of error codes and the corresponding positions in the input slice. If the `return_error!`calls are strategically placed, they can give a lot of information about what happened during parsing.
@@ -191,8 +177,7 @@ Once you get a chain of errors with easily identifying codes, you probably want
 
 The `error_to_list` function can gather all of the error codes in a vector. This vector is essentially a signature of the parsing path and will let you distinguish between the different parsing errors.
 
-```ignore
-# #[macro_use] extern crate nom;
+```rust
 use nom::{Err,ErrorKind,error_to_list};
 
 fn error_to_string<P>(e: &Err<P>) -> &'static str {
@@ -205,17 +190,14 @@ fn error_to_string<P>(e: &Err<P>) -> &'static str {
     "unrecognized error"
   }
 }
-
-# fn main() {}
 ```
 
 ### With slice patterns
 
 If you can use the *slice patterns* feature, you can easily match on errors this way:
 
-```ignore
+```rust
 #![feature(slice_patterns)]
-# #[macro_use] extern crate nom;
 use nom::{Err,ErrorKind,error_to_list};
 
 fn error_to_string<P>(e: &Err<P>) -> &'static str {
@@ -226,19 +208,14 @@ fn error_to_string<P>(e: &Err<P>) -> &'static str {
     _            => "unrecognized error"
   }
 }
-# fn main() {}
 ```
 
 ### With box patterns
 
 If you can use box patterns, you can match directly on the error instead of filtering with `error_to_list`.
 
-```ignore
+```rust
 #![feature(box_patterns)]
-# #[macro_use] extern crate nom;
-# use nom::{add_error_pattern, error_to_list};
-# use nom::Err::*;
-# use nom::ErrorKind;
 
 use std::str;
 fn error_to_string<P>(e:Err<P>) -> String
@@ -260,7 +237,7 @@ This error reporting approach comes from the [Merr](https://github.com/pippijn/m
 
 To do this in nom, you use the `add_error_pattern` function:
 
-```ignore
+```rust
 fn add_error_pattern<'a,I,O>(h: &mut HashMap<Vec<ErrorKind>, &'a str>, res: IResult<I,O>, message: &'a str) -> bool
 ```
 
@@ -268,12 +245,10 @@ It takes as argument a mutable hashmap that will contain the correspondance betw
 
 To use it, you fill up the hashmap, before parsing, with know bad inputs (if you work with binary data, the `include_bytes!` macro might help you there). Then you can just get the error by passing the result of `error_to_list!` as key of the hashmap. 
 
-```ignore
-# #[macro_use] extern crate nom;
+```rust
 use nom::{add_error_pattern, error_to_list};
 use nom::IResult;
 
-# fn main() {
 let mut err_map = collections::HashMap::new();
 add_error_pattern(
   &mut err_map,
@@ -294,7 +269,6 @@ if let IResult::Error(e) = err_test(&b"efghblah"[..]) {
 if let IResult::Error(e) = err_test(&b"efghijklblah"[..]) {
   assert_eq!(err_map.get(&error_to_list(e)), Some(&"missing `mnop` tag after `ijkl`"));
 };
-# }
 ```
 
 ## Colored hexdump
@@ -303,8 +277,7 @@ To help in format discovery, visual tools can sometimes help. The error chain sy
 
 Let's take a parser with a few more `return_error!` calls:
 
-```ignore
-# #[macro_use] extern crate nom;
+```rust
 named!(err_test, alt!(
   tag!("abcd") |
   return_error!(ErrorKind::Custom(12),
@@ -318,12 +291,11 @@ named!(err_test, alt!(
     )
   )
 ));
-# fn main() {}
 ```
 
 We can then define the function `display_error` as follows:
 
-```ignore
+```rust
 use nom::util::{generate_colors,prepare_errors,print_codes,print_offsets};
 
 pub fn display_error<I,O>(input: &[u8], res: IResult<I,O>) {
@@ -347,7 +319,7 @@ The `nom::util::print_offsets` will print the input data in hexadecimal format,
 
 As an example, for this call:
 
-```ignore
+```rust
   let input = &b"efghijklblahblah"[..];
 
   display_error(input, err_test(input));
diff --git a/doc/home.md b/doc/home.md
index 179a96d..bb2137e 100644
--- a/doc/home.md
+++ b/doc/home.md
@@ -1,15 +1,13 @@
-% Home
-
 # Nom is an awesome parser combinators library in Rust
 
 To get started using nom, you can include it in your Rust projects from
 [crates.io](https://crates.io/crates/nom). Here are a few links you will find useful:
 
-* [Reference documentation](http://rust.unhandledexpression.com/nom/)
+* [Reference documentation](https://docs.rs/nom)
 * [Gitter chat room](https://gitter.im/Geal/nom). You can also go to the #nom IRC
 channel on irc.mozilla.org, or ping 'geal' on Mozilla, Freenode, Geeknode or oftc IRC
 * [Tutorial about parsing ISO8601 dates](https://github.com/badboy/iso8601/blob/338b3d1a9ca220372292f631a3bc2e5176cca331/docs/parsing-iso8601-dates-using-nom.md)
-* [Making a new parser from scratch](making_a_new_parser_from_scratch.html)
+* [Making a new parser from scratch](making_a_new_parser_from_scratch.md)
 (general tips on writing a parser and code architecture)
-* [How to handle parser errors](error_management.html)
-* [How nom's macro combinators work](how_nom_macros_work.html)
+* [How to handle parser errors](error_management.md)
+* [How nom's macro combinators work](how_nom_macros_work.md)
diff --git a/doc/how_nom_macros_work.md b/doc/how_nom_macros_work.md
index 5f5c97f..c99a66d 100644
--- a/doc/how_nom_macros_work.md
+++ b/doc/how_nom_macros_work.md
@@ -1,4 +1,4 @@
-% How nom macros work
+# How nom macros work
 
 nom uses Rust macros heavily to provide a nice syntax and generate parsing code. This has multiple advantages:
 
@@ -11,20 +11,12 @@ nom uses Rust macros heavily to provide a nice syntax and generate parsing code.
 Let's take the `opt!` macro as example: `opt!` returns `IResult<I,Option<O>>`, producing a `Some(o)` if the child parser succeeded, and None otherwise. Here is how you could use it:
 
 ```rust
-# #[macro_use] extern crate nom;
-# use nom::{IResult,digit};
-# fn main() {
-# }
 named!(opt_tag<Option<&[u8]>>, opt!(digit));
 ```
 
 And here is how it is defined:
 
 ```rust
-# #[macro_use] extern crate nom;
-# use nom::IResult;
-# fn main() {
-# }
 #[macro_export]
 macro_rules! opt(
   ($i:expr, $submac:ident!( $($args:tt)* )) => ({
@@ -42,7 +34,7 @@ macro_rules! opt(
 
 To define a Rust macro, you indicate the name of the macro, then each pattern it is meant to apply to:
 
-```ignore
+```rust
 macro_rules! my_macro (
   (<pattern1>) => ( <generated code for pattern1> );
   (<pattern2>) => ( <generated code for pattern2> );
@@ -53,33 +45,25 @@ macro_rules! my_macro (
 
 The first thing you can see in `opt!` is that the pattern have an additional parameter that you do not use:
 
-```ignore
+```rust
 ($i:expr, $f:expr)
 ```
 
 while you call:
 
-```ignore
+```rust
 opt!(digit)
 ```
 
 This is the first trick of nom macros: the first parameter, usually `$i` or `$input`, is the input data, passed by the parent parser. The expression using `named!` will translate like this:
 
 ```rust
-# #[macro_use] extern crate nom;
-# use nom::digit;
-# fn main() {
-# }
 named!(opt_tag<Option<&[u8]>>, opt!(digit));
 ```
 
 to
 
 ```rust
-# #[macro_use] extern crate nom;
-# use nom::{IResult,digit};
-# fn main() {
-# }
 fn opt_tag(input:&[u8]) -> IResult<&[u8], Option<&[u8]>> {
   opt!(input, digit)
 }
@@ -90,10 +74,6 @@ This is how combinators hide all the plumbing: they receive the input automatica
 When you have multiple submacros, such as this example, the input is always passed to the first, top level combinator:
 
 ```rust
-# #[macro_use] extern crate nom;
-# use nom::IResult;
-# fn main() {
-# }
 macro_rules! multispaced (
     ($i:expr, $submac:ident!( $($args:tt)* )) => (
         delimited!($i, opt!(multispace), $submac!($($args)*), opt!(multispace));
@@ -110,7 +90,7 @@ Here, `delimited!` will apply `opt!(multispace)` on the input, and if successful
 
 The second trick you can see is the two patterns:
 
-```ignore
+```rust
 #[macro_export]
 macro_rules! opt(
   ($i:expr, $submac:ident!( $($args:tt)* )) => (
@@ -124,19 +104,19 @@ macro_rules! opt(
 
 The first pattern is used to receive a macro as child parser, like this:
 
-```ignore
+```rust
 opt!(tag!("abcd"))
 ```
 
 The second pattern can receive a function, and transforms it in a macro, then calls itself again. This is done to avoid repeating code. Applying `opt!` with `digit` as argument would be transformed from this:
 
-```ignore
+```rust
 opt!(digit)
 ```
 
 transformed with the second pattern:
 
-```ignore
+```rust
 opt!(call!(digit))
 ```
 
@@ -146,7 +126,7 @@ The `call!` macro transforms `call!(input, f)` into `f(input)`. If you need to p
 
 The macro argument is decomposed into `$submac:ident!`, the macro's name and a bang, and `( $($args:tt)* )`, the tokens contained between the parenthesis of the macro call.
 
-```ignore
+```rust
 ($i:expr, $submac:ident!( $($args:tt)* )) => ({
     match $submac!($i, $($args)*) {
       Ok((i,o))          => Ok((i, Some(o))),
@@ -164,7 +144,7 @@ of `Ok((i,o))`: it is the input remaining after the first parser was applied.
 
 As an example, see how the `preceded!` macro works:
 
-```ignore
+```rust
 ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
     {
       match $submac!($i, $($args)*) {
diff --git a/doc/making_a_new_parser_from_scratch.md b/doc/making_a_new_parser_from_scratch.md
index c6b2f92..b23ee07 100644
--- a/doc/making_a_new_parser_from_scratch.md
+++ b/doc/making_a_new_parser_from_scratch.md
@@ -1,4 +1,4 @@
-% Making a new parser from scratch
+# Making a new parser from scratch
 
 Writing a parser is a very fun, interactive process, but sometimes a daunting task. How do you test it? How to  see ambiguities in specifications?
 
@@ -20,20 +20,15 @@ Usually, you can separate the parsing functions in their own module, so you coul
 
 
 ```rust
-# #[macro_use] extern crate nom;
-# use nom::IResult;
-# fn main() {
 fn take_wrapper(input: &[u8], i: u8) -> IResult<&[u8],&[u8]> {
     take!(input, i * 10)
 }
 
 // will make a parser taking 20 bytes
 named!(parser, apply!(take_wrapper, 2));
-# }
-
 ```
 
-```ignore
+```rust
 #[macro_use]
 extern crate nom;
 pub mod parser;
@@ -42,9 +37,7 @@ pub mod parser;
 And use the methods and structure from `parser` there. The `src/parser.rs` would then import nom functions and structures if needed:
 
 ```rust
-# #[macro_use] extern crate nom;
 use nom::{be_u16, be_u32};
-# fn main() {}
 ```
 
 # Writing a first parser
@@ -56,9 +49,10 @@ error type. This enum can either be `Ok((i,o))` containing the remaining input
 and the output value, or, on the `Err` side, an error or an indication that more
 data is needed.
 
-```ignore
+```rust
 pub type IResult<I, O, E = u32> = Result<(I, O), Err<I, E>>;
-#[derive(Debug,PartialEq,Eq,CLone,Copy)]
+
+#[derive(Debug, PartialEq, Eq, CLone, Copy)]
 pub enum Needed {
   Unknown,
   Size(u32)
@@ -71,18 +65,18 @@ pub enum Err<I, E = u32> {
   Failure(Context<I, E>),
 }
 
-#[derive(Debug,PartialEq,Eq,Clone)]
+#[derive(Debug, PartialEq, Eq, Clone)]
 pub enum Err<P,E=u32>{
   Code(ErrorKind<E>),
-  Node(ErrorKind<E>, Box<Err<P,E>>),
+  Node(ErrorKind<E>, Box<Err<P, E>>),
   Position(ErrorKind<E>, P),
-  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
+  NodePosition(ErrorKind<E>, P, Box<Err<P, E>>)
 }
 
-#[derive(Debug,PartialEq,Eq)]
+#[derive(Debug, PartialEq, Eq)]
 pub enum IResult<I,O,E=u32> {
-  Done(I,O),
-  Error(Err<I,E>),
+  Done(I, O),
+  Error(Err<I, E>),
   Incomplete(Needed)
 }
 
@@ -99,8 +93,6 @@ nom uses this type everywhere. Every combination of parsers will pattern match o
 nom provides a macro for function definition, called `named!`:
 
 ```rust
-# #[macro_use] extern crate nom;
-# fn main() {}
 named!(my_function(&[u8]) -> &[u8], tag!("abcd"));
 
 named!(my_function2<&[u8], &[u8]>, tag!("abcd"));
@@ -111,9 +103,6 @@ named!(my_function3, tag!("abcd"));
 But you could as easily define the function yourself like this:
 
 ```rust
-# #[macro_use] extern crate nom;
-# fn main() {}
-# use nom::IResult;
 fn my_function(input: &[u8]) -> IResult<&[u8], &[u8]> {
   tag!(input, "abcd")
 }
@@ -122,16 +111,12 @@ fn my_function(input: &[u8]) -> IResult<&[u8], &[u8]> {
 Note that we pass the input to the first parser in the manual definition, while we do not when we use `named!`. This is a macro trick specific to nom: every parser takes the input as first parameter, and the macros take care of giving the remaining input to the next parser. As an example, take a simple parser like the following one, which recognizes the word "hello" then takes the next 5 bytes:
 
 ```rust
-# #[macro_use] extern crate nom;
-# fn main() {}
 named!(prefixed, preceded!(tag!("hello"), take!(5)));
 ```
 
 Once the macros have expanded, this would correspond to:
 
-```ignore
-# #[macro_use] extern crate nom;
-# fn main() {}
+```rust
 fn prefixed(i: &[u8]) -> ::nom::IResult<&[u8], &[u8]> {
     {
         match {
@@ -184,11 +169,11 @@ Since it is easy to combine small parsers, I encourage you to write small functi
 
 # Finding the right combinator
 
-nom has a lot of different combinators, depending on the use case. They are all described in the [reference](http://rust.unhandledexpression.com/nom/).
+nom has a lot of different combinators, depending on the use case. They are all described in the [reference](https://docs.rs/nom).
 
-[Basic functions](http://rust.unhandledexpression.com/nom/#functions) are available. They deal mostly in recognizing character types, like `alphanumeric` or `digit`. They also parse big endian and little endian integers and floats of multiple sizes.
+[Basic functions](https://docs.rs/nom/#functions) are available. They deal mostly in recognizing character types, like `alphanumeric` or `digit`. They also parse big endian and little endian integers and floats of multiple sizes.
 
-Most of the macros are there to combine parsers, and they do not depend on the input type. this is the case for all of those defined in [src/macros.rs](https://github.com/Geal/nom/blob/master/src/macros.rs). The reference indicates a [possible type signature](http://rust.unhandledexpression.com/nom/#macros) for what the macros expect and return. In case of doubt, the documentation often indicates a [code example](http://rust.unhandledexpression.com/nom/macro.many0!.html) after the macro definition.
+Most of the macros are there to combine parsers, and they do not depend on the input type. this is the case for all of those defined in [src/macros.rs](https://github.com/Geal/nom/blob/master/src/macros.rs). The reference indicates a [possible type signature](https://docs.rs/nom/#macros) for what the macros expect and return. In case of doubt, the documentation often indicates a [code example](https://docs.rs/nom/macro.many0!.html) after the macro definition.
 
 ## Type specific combinators
 
@@ -204,7 +189,7 @@ Regular expression related macros are in [src/regexp.rs](https://github.com/Geal
 
 Once you have a parser function, a good trick is to test it on a lot of the samples you gathered, and integrate this to your unit tests. To that end, put all of the test files in a folder like `assets` and refer to test files like this:
 
-```ignore
+```rust
 #[test]
 fn header_test() {
   let data = include_bytes!("../assets/axolotl-piano.gif");
@@ -217,7 +202,7 @@ The `include_bytes!` macro (provided by Rust's standard library) will integrate
 
 If your parser handles textual data, you can just use a lot of strings directly in the test, like this:
 
-```ignore
+```rust
 #[test]
 fn factor_test() {
   assert_eq!(factor(&b"3"[..]),       Ok((&b""[..], 3)));
@@ -233,7 +218,7 @@ The more samples and test cases you get, the more you can experiment with your p
 
 While Rust macros are really useful to get a simpler syntax, they can sometimes give cryptic errors. As an example, `named!(manytag, many0!(take!(5)));` would result in the following error:
 
-```ignore
+```
 <nom macros>:6:38: 6:41 error: mismatched types:
  expected `&[u8]`,
     found `collections::vec::Vec<&[u8]>`
@@ -255,7 +240,7 @@ There are a few tools you can use to debug how code is generated.
 
 The `trace_macros` feature show how macros are applied. To use it, add `#![feature(trace_macros)]` at the top of your file (you need Rust nightly for this), then apply it like this:
 
-```ignore
+```rust
 trace_macros!(true);
 named!(manytag< Vec<&[u8]> >, many0!(take!(5)));
 trace_macros!(false);
@@ -263,7 +248,7 @@ trace_macros!(false);
 
 It will result in the following output during compilation:
 
-```ignore
+```rust
 named! { manytag , many0 ! ( take ! ( 5 ) ) }
 many0! { i , take ! ( 5 ) }
 take! { input , 5 }
@@ -276,8 +261,6 @@ rustc can show how code is expanded with the option `--pretty=expanded`. If you
 It will print the `manytag` function like this:
 
 ```rust
-# #[macro_use] extern crate nom;
-# fn main() {}
 fn manytag(i: &[u8]) -> ::nom::IResult<&[u8], Vec<&[u8]>> {
     let mut res = Vec::new();
     let mut input = i;
diff --git a/doc/upgrading_to_nom_1.md b/doc/upgrading_to_nom_1.md
index 2c3a201..b59cb4a 100644
--- a/doc/upgrading_to_nom_1.md
+++ b/doc/upgrading_to_nom_1.md
@@ -1,4 +1,4 @@
-% Upgrading to nom 1.0
+# Upgrading to nom 1.0
 
 The 1.0 release of nom is one of the biggest since the beginning of the project. Its goal was to rework some core parts to be more flexible, and clean code that was awkward or unclear. This resulted in breaking changes, that I hope will not happen again in the future (but hey, we are Rust developers, breaking changes are FUN for us!).
 
@@ -8,7 +8,7 @@ Here are a few tips to update your code to run with nom 1.0:
 
 `nom::Err` now depends on two generic types, the position `P` and the error type `E`:
 
-```ignore
+```rust
 pub enum Err<P,E=u32>{
   Code(ErrorKind<E>),
   Node(ErrorKind<E>, Box<Err<P,E>>),
@@ -19,20 +19,20 @@ pub enum Err<P,E=u32>{
 
 The default error type is `u32` to keep some compatibility with older code. To update your code, the first step is to **replace all usages of `nom::ErrorCode` by `nom::ErrorKind`**. `ErrorKind` is now an enum that contains the same instances as the previous `ErrorCode`, with an additional generic parameter:
 
-```ignore
+```rust
 pub enum ErrorKind<E=u32> {
   Custom(E),
   Tag,
   MapRes,
   MapOpt,
   Alt,
-[...]
+  [...]
 }
 ```
 
 `ErrorKind::Custom` is where you will store your custom error type. Note that default nom parsers like `alphabetic` use `u32` as custom type, so you may need to translate the error types coming from those parsers like this:
 
-```ignore
+```rust
 fix_error!(CustomErrorType, alphabetic)
 ```
 
@@ -42,7 +42,7 @@ Since the error type is now an enum instead of a `u32`, you can now **replace an
 
 The error type is now completely generic over the input type, so the lifetime that appeared in `IResult` is not necessary anymore. It changes function declarations like this:
 
-```ignore
+```rust
 fn parse_status<'a>(i: &'a [u8]) -> IResult<'a, &'a [u8], Status>
 
 // To this:
diff --git a/doc/upgrading_to_nom_2.md b/doc/upgrading_to_nom_2.md
index b60b908..2656ba0 100644
--- a/doc/upgrading_to_nom_2.md
+++ b/doc/upgrading_to_nom_2.md
@@ -1,5 +1,3 @@
-% Upgrading to nom 2.0
-
 # Upgrading to nom 2.0
 
 The 2.0 release of nom adds a lot of new features, but it was also time for a big cleanup of badly named functions and macros, awkwardly written features and redundant functionality. So this release has some breaking changes, but most of them are harmless.
@@ -12,7 +10,7 @@ Not everybody uses that feature, so it was moved behind a compilation feature ca
 
 For the parsers using it, you will probably get something like the following compilation error:
 
-```ignore
+```
 error: no associated item named `Code` found for type `nom::ErrorKind<_>` in the current scope
    --> src/metadata/parser.rs:309:31
     |
@@ -57,12 +55,12 @@ nom             = { version = "^2.0.0", features = ["verbose-errors"] }
 
 If you only use `Err::Code` to make your custom error codes, you could switch to the simple errors, since it replaces the `Err<Input,E=u32>` enum, which contained an `ErrorKind<E=u32>`, with the `ErrorKind<E=u32>` type directly.
 
-## the eof function was removed
+## The eof function was removed
 
 The eof implementation was linked too much to the input type. This is now a macro combinator, called `eof!()`.
 
 If you see the following error, remove the `eof` import and replace all `eof` calls by `eof!()`.
-```ìgnore
+```
 error[E0432]: unresolved import `nom::eof`
  --> src/parser.rs:1:20
   |
@@ -70,7 +68,7 @@ error[E0432]: unresolved import `nom::eof`
   |                    ^^^ no `eof` in `nom`. Did you mean to use `eol`?
 ```
 
-## parsers returning `Incomplete` instead of an error on empty input
+## Parsers returning `Incomplete` instead of an error on empty input
 
 `alpha`, `digit`, `alphanumeric`, `hex_digit`, `oct_digit`, `space`, `multispace`, `sized_buffer` will now return `Incomplete` if they get an empty input. If you get the following error message, you can wrap those calls with `complete!`, a combinator that transforms `Incomplete` to `Error`.
 
@@ -85,7 +83,7 @@ This change was implemented to make these basic parsers more consistent. Please
 
 The input types must now conform to a trait which requires changes to `take_till!`. If you get the following error:
 
-```ignore
+```
 error[E0308]: mismatched types
   --> src/linux/parser.rs:32:1
    |
@@ -114,7 +112,7 @@ The "length-value" pattern usually indicates that we get a length from the input
 - the new `length_value!` macros takes a slice of the size obtained by the first child parser, then applies the second child parser on this slice. If the second parser returns incomplete, the parser fails
 - `length_data!` gets a length from its child parser, then returns a subslice of that length
 
-```ignore
+```
 error[E0308]: mismatched types
    --> src/tls.rs:378:37
     |
@@ -158,7 +156,7 @@ It is fixed by:
         map_res!(flat_map!(take_s!(1), digit), FromStr::from_str))));
 ```
 
-## the `offset()` method was moved to the `Offset` trait
+## The `offset()` method was moved to the `Offset` trait
 
 There is now an implementation of `Offset` for `&str`. The `HexDisplay` trait is now reserved for `&[u8]`.
 
@@ -166,7 +164,7 @@ There is now an implementation of `Offset` for `&str`. The `HexDisplay` trait is
 
 This makes the method naming more consistent.
 
-## the number parsing macros with configurable endianness now take an enum as argument instead of a boolean
+## The number parsing macros with configurable endianness now take an enum as argument instead of a boolean
 
 Using a boolean to specify endianness was confusing, there is now the `nom::Endianness` enum:
 
@@ -177,6 +175,6 @@ Using a boolean to specify endianness was confusing, there is now the `nom::Endi
 +    named!(le_tst32<u32>, u32!(Endianness::Little));
 ```
 
-## end of line parsing
+## End of line parsing
 
 There were different, incompatible ways to parse line endings. Now, the `eol`, `line_ending` and `not_line_ending` all have the same behaviour. First, test for '\n', then if it is not the right character, test for "\r\n". This fixes the length issues.
diff --git a/doc/upgrading_to_nom_4.md b/doc/upgrading_to_nom_4.md
index 76c2b13..7c691c9 100644
--- a/doc/upgrading_to_nom_4.md
+++ b/doc/upgrading_to_nom_4.md
@@ -1,5 +1,3 @@
-% Upgrading to nom 4.0
-
 # Upgrading to nom 4.0
 
 The nom 4.0 is a nearly complete rewrite of nom's internal structures, along with a cleanup of a lot of parser and combinators whose semantics were unclear. Upgrading from previous nom versions can require a lot of changes, especially if you have a lot of unit tests. But most of those changes are pretty straightforward.
@@ -8,13 +6,13 @@ The nom 4.0 is a nearly complete rewrite of nom's internal structures, along wit
 
 Previous versions of nom all generated parsers with the following signature:
 
-```rust,ignore
+```rust
 fn parser(input: I) -> IResult<I,O> { ... }
 ```
 
 With the following definition for `IResult`:
 
-```rust,ignore
+```rust
 pub enum IResult<I,O,E=u32> {
   /// remaining input, result value
   Done(I,O),
@@ -49,7 +47,7 @@ pub enum Err<P,E=u32>{
 
 The new design uses the `Result` type from the standard library:
 
-```rust,ignore
+```rust
 pub type IResult<I, O, E = u32> = Result<(I, O), Err<I, E>>;
 
 pub enum Err<I, E = u32> {
@@ -109,7 +107,7 @@ result (like in a unit test), you will have to perform the following changes:
 
 For the correct result case:
 
-```rust,ignore
+```rust
 IResult::Done(i, o)
 
 // becomes
@@ -120,7 +118,7 @@ Ok((i, o))
 For the error case (note that argument position for `error_position` and other sibling macros was changed
 for the sake of consistency with the rest of the code):
 
-```rust,ignore
+```rust
 IResult::Error(error_position!(ErrorKind::OneOf, input)),
 
 // becomes
@@ -128,7 +126,7 @@ IResult::Error(error_position!(ErrorKind::OneOf, input)),
 Err(Err::Error(error_position!(input, ErrorKind::OneOf)))
 ```
 
-```rust,ignore
+```rust
 IResult::Incomplete(Needed::Size(1))
 
 // becomes
@@ -139,7 +137,7 @@ Err(Err::Incomplete(Needed::Size(1)))
 For pattern matching, you now need to handle the `Failure` case as well, which works like the error
 case:
 
-```rust,ignore
+```rust
 match result {
   Ok((remaining, value)) => { ... },
   Err(Err::Incomplete(needed)) => { ... },
@@ -190,7 +188,7 @@ Thanks to the new `AtEof` trait for input types, nom now provides the `CompleteB
 With these types, no need to put a `complete!()` combinator everywhere, you can juste apply those types
 like this:
 
-```rust,ignore
+```rust
 named!(parser<&str,ReturnType>, ... );
 
 // becomes
@@ -198,7 +196,7 @@ named!(parser<&str,ReturnType>, ... );
 named!(parser<CompleteStr,ReturnType>, ... );
 ```
 
-```rust,ignore
+```rust
 named!(parser<&str,&str>, ... );
 
 // becomes
@@ -206,7 +204,7 @@ named!(parser<&str,&str>, ... );
 named!(parser<CompleteStr,CompleteStr>, ... );
 ```
 
-```rust,ignore
+```rust
 named!(parser, ... );
 
 // becomes
@@ -216,7 +214,7 @@ named!(parser<CompleteByteSlice,CompleteByteSlice>, ... );
 
 And as an example, for a unit test:
 
-```rust,ignore
+```rust
 assert_eq!(parser("abcd123"), Ok(("123", "abcd"));
 
 // becomes
@@ -230,7 +228,7 @@ empty line or not, as seen in [one of the examples](https://github.com/Geal/nom/
 If those types feel a bit long to write everywhere in the parsers, it's possible
 to alias them like this:
 
-```rust,ignore
+```rust
 use nom::types::CompleteByteSlice as Input;
 ```
 
diff --git a/src/lib.rs b/src/lib.rs
index 908eab6..3b9c566 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -21,10 +21,7 @@
 //! }
 //!
 //! fn is_hex_digit(c: char) -> bool {
-//!   match c {
-//!     '0'..='9' | 'a'..='f' | 'A'..='F' => true,
-//!     _ => false,
-//!   }
+//!   c.is_digit(16)
 //! }
 //!
 //! named!(hex_primary<&str, u8>,
diff --git a/src/nom.rs b/src/nom.rs
index 01c6f03..bf7a151 100644
--- a/src/nom.rs
+++ b/src/nom.rs
@@ -449,6 +449,32 @@ pub fn be_u64(i: &[u8]) -> IResult<&[u8], u64, u32> {
   }
 }
 
+/// Recognizes big endian unsigned 16 bytes integer
+#[inline]
+pub fn be_u128(i: &[u8]) -> IResult<&[u8], u128, u32> {
+  if i.len() < 16 {
+    need_more(i, Needed::Size(16))
+  } else {
+    let res = ((i[0] as u128) << 120)
+      + ((i[1] as u128) << 112)
+      + ((i[2] as u128) << 104)
+      + ((i[3] as u128) << 96)
+      + ((i[4] as u128) << 88)
+      + ((i[5] as u128) << 80)
+      + ((i[6] as u128) << 72)
+      + ((i[7] as u128) << 64)
+      + ((i[8] as u128) << 56)
+      + ((i[9] as u128) << 48)
+      + ((i[10] as u128) << 40)
+      + ((i[11] as u128) << 32)
+      + ((i[12] as u128) << 24)
+      + ((i[13] as u128) << 16)
+      + ((i[14] as u128) << 8)
+      + i[15] as u128;
+    Ok((&i[16..], res))
+  }
+}
+
 /// Recognizes a signed 1 byte integer (equivalent to take!(1)
 #[inline]
 pub fn be_i8(i: &[u8]) -> IResult<&[u8], i8> {
@@ -484,6 +510,12 @@ pub fn be_i64(i: &[u8]) -> IResult<&[u8], i64> {
   map!(i, be_u64, |x| x as i64)
 }
 
+/// Recognizes big endian signed 16 bytes integer
+#[inline]
+pub fn be_i128(i: &[u8]) -> IResult<&[u8], i128> {
+  map!(i, be_u128, |x| x as i128)
+}
+
 /// Recognizes an unsigned 1 byte integer (equivalent to take!(1)
 #[inline]
 pub fn le_u8(i: &[u8]) -> IResult<&[u8], u8> {
@@ -539,6 +571,32 @@ pub fn le_u64(i: &[u8]) -> IResult<&[u8], u64> {
   }
 }
 
+/// Recognizes little endian unsigned 16 bytes integer
+#[inline]
+pub fn le_u128(i: &[u8]) -> IResult<&[u8], u128, u32> {
+  if i.len() < 16 {
+    need_more(i, Needed::Size(16))
+  } else {
+    let res = ((i[15] as u128) << 120)
+      + ((i[14] as u128) << 112)
+      + ((i[13] as u128) << 104)
+      + ((i[12] as u128) << 96)
+      + ((i[11] as u128) << 88)
+      + ((i[10] as u128) << 80)
+      + ((i[9] as u128) << 72)
+      + ((i[8] as u128) << 64)
+      + ((i[7] as u128) << 56)
+      + ((i[6] as u128) << 48)
+      + ((i[5] as u128) << 40)
+      + ((i[4] as u128) << 32)
+      + ((i[3] as u128) << 24)
+      + ((i[2] as u128) << 16)
+      + ((i[1] as u128) << 8)
+      + i[0] as u128;
+    Ok((&i[16..], res))
+  }
+}
+
 /// Recognizes a signed 1 byte integer (equivalent to take!(1)
 #[inline]
 pub fn le_i8(i: &[u8]) -> IResult<&[u8], i8> {
@@ -574,6 +632,12 @@ pub fn le_i64(i: &[u8]) -> IResult<&[u8], i64> {
   map!(i, le_u64, |x| x as i64)
 }
 
+/// Recognizes little endian signed 16 bytes integer
+#[inline]
+pub fn le_i128(i: &[u8]) -> IResult<&[u8], i128> {
+  map!(i, le_u128, |x| x as i128)
+}
+
 /// Configurable endianness
 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
 pub enum Endianness {
@@ -593,6 +657,10 @@ macro_rules! u32 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { $
 /// otherwise a little endian u64 integer
 #[macro_export]
 macro_rules! u64 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { $crate::be_u64($i) } else { $crate::le_u64($i) } } ););
+/// if the parameter is nom::Endianness::Big, parse a big endian u128 integer,
+/// otherwise a little endian u128 integer
+#[macro_export]
+macro_rules! u128 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { $crate::be_u128($i) } else { $crate::le_u128($i) } } ););
 
 /// if the parameter is nom::Endianness::Big, parse a big endian i16 integer,
 /// otherwise a little endian i16 integer
@@ -606,6 +674,10 @@ macro_rules! i32 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { $
 /// otherwise a little endian i64 integer
 #[macro_export]
 macro_rules! i64 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { $crate::be_i64($i) } else { $crate::le_i64($i) } } ););
+/// if the parameter is nom::Endianness::Big, parse a big endian i64 integer,
+/// otherwise a little endian i64 integer
+#[macro_export]
+macro_rules! i128 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { $crate::be_i128($i) } else { $crate::le_i128($i) } } ););
 
 /// Recognizes big endian 4 bytes floating point number
 #[inline]
@@ -1173,6 +1245,26 @@ mod tests {
     );
   }
 
+  #[test]
+  fn i128_tests() {
+    assert_eq!(
+      be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
+      Ok((&b""[..], 0))
+    );
+    assert_eq!(
+      be_i128(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]),
+      Ok((&b""[..], 170_141_183_460_469_231_731_687_303_715_884_105_727_i128))
+    );
+    assert_eq!(
+      be_i128(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]),
+      Ok((&b""[..], -1))
+    );
+    assert_eq!(
+      be_i128(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
+      Ok((&b""[..], -170_141_183_460_469_231_731_687_303_715_884_105_728_i128))
+    );
+  }
+
   #[test]
   fn le_i8_tests() {
     assert_eq!(le_i8(&[0x00]), Ok((&b""[..], 0)));
@@ -1237,6 +1329,26 @@ mod tests {
     );
   }
 
+  #[test]
+  fn le_i128_tests() {
+    assert_eq!(
+      le_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
+      Ok((&b""[..], 0))
+    );
+    assert_eq!(
+      le_i128(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]),
+      Ok((&b""[..], 170_141_183_460_469_231_731_687_303_715_884_105_727_i128))
+    );
+    assert_eq!(
+      le_i128(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]),
+      Ok((&b""[..], -1))
+    );
+    assert_eq!(
+      le_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]),
+      Ok((&b""[..], -170_141_183_460_469_231_731_687_303_715_884_105_728_i128))
+    );
+  }
+
   #[test]
   fn be_f32_tests() {
     assert_eq!(be_f32(&[0x00, 0x00, 0x00, 0x00]), Ok((&b""[..], 0_f32)));


Test patch:
diff --git a/tests/css.rs b/tests/css.rs
index 31b58e4..03dead8 100644
--- a/tests/css.rs
+++ b/tests/css.rs
@@ -13,10 +13,7 @@ fn from_hex(input: &str) -> Result<u8, std::num::ParseIntError> {
 }
 
 fn is_hex_digit(c: char) -> bool {
-  match c {
-    '0'..='9' | 'a'..='f' | 'A'..='F' => true,
-    _ => false,
-  }
+  c.is_digit(16)
 }
 
 named!(hex_primary<&str, u8>,