1 
2 #[cfg(feature = "verbose-errors")]
3 use internal::IResult;
4 
5 #[cfg(feature = "verbose-errors")]
6 use verbose_errors::Err;
7 
8 #[cfg(feature = "std")]
9 use std::collections::HashMap;
10 
11 #[cfg(not(feature = "std"))]
12 use std::prelude::v1::*;
13 
14 use std::vec::Vec;
15 use std::string::ToString;
16 
17 /// useful functions to calculate the offset between slices and show a hexdump of a slice
18 pub trait Offset {
19   /// offset between the first byte of self and the first byte of the argument
offset(&self, second:&Self) -> usize20   fn offset(&self, second:&Self) -> usize;
21 }
22 
23 #[cfg(feature = "std")]
24 pub trait HexDisplay {
25   /// Converts the value of `self` to a hex dump, returning the owned
26   /// string.
to_hex(&self, chunk_size: usize) -> String27   fn to_hex(&self, chunk_size: usize) -> String;
28 
29   /// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned
30   /// string.
to_hex_from(&self, chunk_size: usize, from: usize) -> String31   fn to_hex_from(&self, chunk_size: usize, from: usize) -> String;
32 }
33 
34 static CHARS: &'static[u8] = b"0123456789abcdef";
35 
36 impl Offset for [u8] {
offset(&self, second:&[u8]) -> usize37   fn offset(&self, second:&[u8]) -> usize {
38     let fst = self.as_ptr();
39     let snd = second.as_ptr();
40 
41     snd as usize - fst as usize
42   }
43 }
44 
45 impl Offset for str {
offset(&self, second: &Self) -> usize46     fn offset(&self, second: &Self) -> usize {
47       let fst = self.as_ptr();
48       let snd = second.as_ptr();
49 
50       snd as usize - fst as usize
51     }
52 }
53 
54 #[cfg(feature = "std")]
55 impl HexDisplay for [u8] {
56   #[allow(unused_variables)]
to_hex(&self, chunk_size: usize) -> String57   fn to_hex(&self, chunk_size: usize) -> String {
58     self.to_hex_from(chunk_size, 0)
59   }
60 
61   #[allow(unused_variables)]
to_hex_from(&self, chunk_size: usize, from: usize) -> String62   fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
63     let mut v = Vec::with_capacity(self.len() * 3);
64     let mut i = from;
65     for chunk in self.chunks(chunk_size) {
66       let s = format!("{:08x}", i);
67       for &ch in s.as_bytes().iter() {
68         v.push(ch);
69       }
70       v.push('\t' as u8);
71 
72       i = i + chunk_size;
73 
74       for &byte in chunk {
75         v.push(CHARS[(byte >> 4) as usize]);
76         v.push(CHARS[(byte & 0xf) as usize]);
77         v.push(' ' as u8);
78       }
79       if chunk_size > chunk.len() {
80         for j in 0..(chunk_size - chunk.len()) {
81           v.push(' ' as u8);
82           v.push(' ' as u8);
83           v.push(' ' as u8);
84         }
85       }
86       v.push('\t' as u8);
87 
88       for &byte in chunk {
89         if (byte >=32 && byte <= 126) || byte >= 128 {
90           v.push(byte);
91         } else {
92           v.push('.' as u8);
93         }
94       }
95       v.push('\n' as u8);
96     }
97 
98     String::from_utf8_lossy(&v[..]).into_owned()
99   }
100 }
101 
102 /// Prints a message if the parser fails
103 ///
104 /// The message prints the `Error` or `Incomplete`
105 /// and the parser's calling code
106 ///
107 /// ```
108 /// # #[macro_use] extern crate nom;
109 /// # fn main() {
110 ///    named!(f, dbg!( tag!( "abcd" ) ) );
111 ///
112 ///    let a = &b"efgh"[..];
113 ///
114 ///    // Will print the following message:
115 ///    // Error(Position(0, [101, 102, 103, 104])) at l.5 by ' tag ! ( "abcd" ) '
116 ///    f(a);
117 /// # }
118 /// ```
119 #[macro_export]
120 macro_rules! dbg (
121   ($i: expr, $submac:ident!( $($args:tt)* )) => (
122     {
123       let l = line!();
124       match $submac!($i, $($args)*) {
125         $crate::IResult::Error(a) => {
126           println!("Error({:?}) at l.{} by ' {} '", a, l, stringify!($submac!($($args)*)));
127           $crate::IResult::Error(a)
128         },
129         $crate::IResult::Incomplete(a) => {
130           println!("Incomplete({:?}) at {} by ' {} '", a, l, stringify!($submac!($($args)*)));
131           $crate::IResult::Incomplete(a)
132         },
133         a => a
134       }
135     }
136   );
137 
138   ($i:expr, $f:ident) => (
139       dbg!($i, call!($f));
140   );
141 );
142 
143 /// Prints a message and the input if the parser fails
144 ///
145 /// The message prints the `Error` or `Incomplete`
146 /// and the parser's calling code.
147 ///
148 /// It also displays the input in hexdump format
149 ///
150 /// ```ignore
151 /// # #[macro_use] extern crate nom;
152 /// # fn main() {
153 ///    named!(f, dbg_dmp!( tag!( "abcd" ) ) );
154 ///
155 ///    let a = &b"efghijkl"[..];
156 ///
157 ///    // Will print the following message:
158 ///    // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) '
159 ///    // 00000000        65 66 67 68 69 6a 6b 6c         efghijkl
160 ///    f(a);
161 /// # }
162 #[macro_export]
163 macro_rules! dbg_dmp (
164   ($i: expr, $submac:ident!( $($args:tt)* )) => (
165     {
166       use $crate::HexDisplay;
167       let l = line!();
168       match $submac!($i, $($args)*) {
169         $crate::IResult::Error(a) => {
170           println!("Error({:?}) at l.{} by ' {} '\n{}", a, l, stringify!($submac!($($args)*)), $i.to_hex(8));
171           $crate::IResult::Error(a)
172         },
173         $crate::IResult::Incomplete(a) => {
174           println!("Incomplete({:?}) at {} by ' {} '\n{}", a, l, stringify!($submac!($($args)*)), $i.to_hex(8));
175           $crate::IResult::Incomplete(a)
176         },
177         a => a
178       }
179     }
180   );
181 
182   ($i:expr, $f:ident) => (
183       dbg_dmp!($i, call!($f));
184   );
185 );
186 
187 #[cfg(feature = "verbose-errors")]
error_to_list<P,E:Clone>(e:&Err<P,E>) -> Vec<ErrorKind<E>>188 pub fn error_to_list<P,E:Clone>(e:&Err<P,E>) -> Vec<ErrorKind<E>> {
189   let mut v:Vec<ErrorKind<E>> = Vec::new();
190   match e {
191      &Err::Code(ref i) | &Err::Position(ref i,_) => {
192         v.push(i.clone());
193         return v;
194      },
195      &Err::Node(ref i, ref next) | &Err::NodePosition(ref i, _, ref next) => {
196        //v.push(i.clone());
197        for error in next.iter() {
198          if let &Err::Code(ref i2) = error {
199            v.push(i2.clone());
200          }
201          if let &Err::Position(ref i2,_) = error {
202            v.push(i2.clone());
203          }
204        }
205        v.push(i.clone());
206        v.reverse()
207      }
208   }
209 
210   v
211 }
212 
213 #[cfg(feature = "verbose-errors")]
compare_error_paths<P,E:Clone+PartialEq>(e1:&Err<P,E>, e2:&Err<P,E>) -> bool214 pub fn compare_error_paths<P,E:Clone+PartialEq>(e1:&Err<P,E>, e2:&Err<P,E>) -> bool {
215   error_to_list(e1) == error_to_list(e2)
216 }
217 
218 
219 #[cfg(feature = "std")]
220 #[cfg(feature = "verbose-errors")]
221 use std::hash::Hash;
222 
223 #[cfg(feature = "std")]
224 #[cfg(feature = "verbose-errors")]
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) -> bool225 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 {
226   if let IResult::Error(e) = res {
227     h.insert(error_to_list(&e), message);
228     true
229   } else {
230     false
231   }
232 }
233 
slice_to_offsets(input: &[u8], s: &[u8]) -> (usize, usize)234 pub fn slice_to_offsets(input: &[u8], s: &[u8]) -> (usize, usize) {
235   let start = input.as_ptr();
236   let off1  = s.as_ptr() as usize - start as usize;
237   let off2  = off1 + s.len();
238   (off1, off2)
239 }
240 
241 #[cfg(feature = "std")]
242 #[cfg(feature = "verbose-errors")]
prepare_errors<O,E: Clone>(input: &[u8], res: IResult<&[u8],O,E>) -> Option<Vec<(ErrorKind<E>, usize, usize)> >243 pub fn prepare_errors<O,E: Clone>(input: &[u8], res: IResult<&[u8],O,E>) -> Option<Vec<(ErrorKind<E>, usize, usize)> > {
244   if let IResult::Error(e) = res {
245     let mut v:Vec<(ErrorKind<E>, usize, usize)> = Vec::new();
246 
247     match e {
248        Err::Code(_) => {},
249        Err::Position(i, p) => {
250          let (o1, o2) = slice_to_offsets(input, p);
251           v.push((i, o1, o2));
252        },
253        Err::Node(_, _) => {},
254        Err::NodePosition(i, p, next) => {
255          //v.push(i.clone());
256          for error in next.iter() {
257            if let &Err::Position(ref i2, ref p2) = error {
258               let (o1, o2) = slice_to_offsets(input, p2);
259              v.push((i2.clone(), o1, o2));
260            }
261          }
262         let (o1, o2) = slice_to_offsets(input, p);
263          v.push((i, o1, o2));
264          v.reverse()
265        }
266     }
267 
268     v.sort_by(|a, b| a.1.cmp(&b.1));
269     Some(v)
270   } else {
271     None
272   }
273 }
274 
275 #[cfg(feature = "std")]
276 #[cfg(feature = "verbose-errors")]
print_error<O,E:Clone>(input: &[u8], res: IResult<&[u8],O,E>)277 pub fn print_error<O,E:Clone>(input: &[u8], res: IResult<&[u8],O,E>) {
278   if let Some(v) = prepare_errors(input, res) {
279     let colors = generate_colors(&v);
280     println!("parser codes: {}",   print_codes(colors, HashMap::new()));
281     println!("{}",   print_offsets(input, 0, &v));
282 
283   } else {
284     println!("not an error");
285   }
286 }
287 
288 #[cfg(feature = "std")]
289 #[cfg(feature = "verbose-errors")]
generate_colors<E>(v: &[(ErrorKind<E>, usize, usize)]) -> HashMap<u32, u8>290 pub fn generate_colors<E>(v: &[(ErrorKind<E>, usize, usize)]) -> HashMap<u32, u8> {
291   let mut h: HashMap<u32, u8> = HashMap::new();
292   let mut color = 0;
293 
294   for &(ref c,_,_) in v.iter() {
295     h.insert(error_to_u32(c), color + 31);
296     color = color + 1 % 7;
297   }
298 
299   h
300 }
301 
code_from_offset<E>(v: &[(ErrorKind<E>, usize, usize)], offset: usize) -> Option<u32>302 pub fn code_from_offset<E>(v: &[(ErrorKind<E>, usize, usize)], offset: usize) -> Option<u32> {
303   let mut acc: Option<(u32, usize, usize)> = None;
304   for &(ref ek, s, e) in v.iter() {
305     let c = error_to_u32(ek);
306     if s <= offset && offset <=e {
307       if let Some((_, start, end)) = acc {
308         if start <= s && e <= end {
309           acc = Some((c, s, e));
310         }
311       } else {
312         acc = Some((c, s, e));
313       }
314     }
315   }
316   if let Some((code, _, _)) = acc {
317     return Some(code);
318   } else {
319     return None;
320   }
321 }
322 
reset_color(v: &mut Vec<u8>)323 pub fn reset_color(v: &mut Vec<u8>) {
324   v.push(0x1B);
325   v.push('[' as u8);
326   v.push(0);
327   v.push('m' as u8);
328 }
329 
write_color(v: &mut Vec<u8>, color: u8)330 pub fn write_color(v: &mut Vec<u8>, color: u8) {
331   v.push(0x1B);
332   v.push('[' as u8);
333   v.push(1);
334   v.push(';' as u8);
335   let s = color.to_string();
336   let bytes = s.as_bytes();
337   v.extend(bytes.iter().cloned());
338   v.push('m' as u8);
339 }
340 
341 #[cfg(feature = "std")]
print_codes(colors: HashMap<u32, u8>, names: HashMap<u32, &str>) -> String342 pub fn print_codes(colors: HashMap<u32, u8>, names: HashMap<u32, &str>) -> String {
343   let mut v = Vec::new();
344   for (code, &color) in &colors {
345     if let Some(&s) = names.get(&code) {
346       let bytes = s.as_bytes();
347       write_color(&mut v, color);
348       v.extend(bytes.iter().cloned());
349     } else {
350       let s = code.to_string();
351       let bytes = s.as_bytes();
352       write_color(&mut v, color);
353       v.extend(bytes.iter().cloned());
354     }
355     reset_color(&mut v);
356     v.push(' ' as u8);
357   }
358   reset_color(&mut v);
359 
360   String::from_utf8_lossy(&v[..]).into_owned()
361 }
362 
363 #[cfg(feature = "std")]
364 #[cfg(feature = "verbose-errors")]
print_offsets<E>(input: &[u8], from: usize, offsets: &[(ErrorKind<E>, usize, usize)]) -> String365 pub fn print_offsets<E>(input: &[u8], from: usize, offsets: &[(ErrorKind<E>, usize, usize)]) -> String {
366   let mut v = Vec::with_capacity(input.len() * 3);
367   let mut i = from;
368   let chunk_size = 8;
369   let mut current_code:  Option<u32> = None;
370   let mut current_code2: Option<u32> = None;
371 
372   let colors = generate_colors(&offsets);
373 
374   for chunk in input.chunks(chunk_size) {
375     let s = format!("{:08x}", i);
376     for &ch in s.as_bytes().iter() {
377       v.push(ch);
378     }
379     v.push('\t' as u8);
380 
381     let mut k = i;
382     let mut l = i;
383     for &byte in chunk {
384       if let Some(code) = code_from_offset(&offsets, k) {
385         if let Some(current) = current_code {
386           if current != code {
387             reset_color(&mut v);
388             current_code = Some(code);
389             if let Some(&color) = colors.get(&code) {
390               write_color(&mut v, color);
391             }
392           }
393         } else {
394           current_code = Some(code);
395           if let Some(&color) = colors.get(&code) {
396             write_color(&mut v, color);
397           }
398         }
399       }
400       v.push(CHARS[(byte >> 4) as usize]);
401       v.push(CHARS[(byte & 0xf) as usize]);
402       v.push(' ' as u8);
403       k = k + 1;
404     }
405 
406     reset_color(&mut v);
407 
408     if chunk_size > chunk.len() {
409       for _ in 0..(chunk_size - chunk.len()) {
410         v.push(' ' as u8);
411         v.push(' ' as u8);
412         v.push(' ' as u8);
413       }
414     }
415     v.push('\t' as u8);
416 
417     for &byte in chunk {
418       if let Some(code) = code_from_offset(&offsets, l) {
419         if let Some(current) = current_code2 {
420           if current != code {
421             reset_color(&mut v);
422             current_code2 = Some(code);
423             if let Some(&color) = colors.get(&code) {
424               write_color(&mut v, color);
425             }
426           }
427         } else {
428           current_code2 = Some(code);
429           if let Some(&color) = colors.get(&code) {
430             write_color(&mut v, color);
431           }
432         }
433       }
434       if (byte >=32 && byte <= 126) || byte >= 128 {
435         v.push(byte);
436       } else {
437         v.push('.' as u8);
438       }
439       l = l + 1;
440     }
441     reset_color(&mut v);
442 
443     v.push('\n' as u8);
444     i = i + chunk_size;
445   }
446 
447   String::from_utf8_lossy(&v[..]).into_owned()
448 }
449 
450 pub trait AsBytes {
as_bytes(&self) -> &[u8]451   fn as_bytes(&self) -> &[u8];
452 }
453 
454 impl<'a> AsBytes for &'a str {
455   #[inline(always)]
as_bytes(&self) -> &[u8]456   fn as_bytes(&self) -> &[u8] {
457     str::as_bytes(self)
458   }
459 }
460 
461 impl AsBytes for str {
462   #[inline(always)]
as_bytes(&self) -> &[u8]463   fn as_bytes(&self) -> &[u8] {
464     str::as_bytes(self)
465   }
466 }
467 
468 impl<'a> AsBytes for &'a [u8] {
469   #[inline(always)]
as_bytes(&self) -> &[u8]470   fn as_bytes(&self) -> &[u8] {
471     *self
472   }
473 }
474 
475 impl AsBytes for [u8] {
476   #[inline(always)]
as_bytes(&self) -> &[u8]477   fn as_bytes(&self) -> &[u8] {
478     self
479   }
480 }
481 
482 macro_rules! array_impls {
483   ($($N:expr)+) => {
484     $(
485       impl<'a> AsBytes for &'a [u8; $N] {
486         #[inline(always)]
487         fn as_bytes(&self) -> &[u8] {
488           *self
489         }
490       }
491 
492       impl AsBytes for [u8; $N] {
493         #[inline(always)]
494         fn as_bytes(&self) -> &[u8] {
495           self
496         }
497       }
498     )+
499   };
500 }
501 
502 
503 array_impls! {
504      0  1  2  3  4  5  6  7  8  9
505     10 11 12 13 14 15 16 17 18 19
506     20 21 22 23 24 25 26 27 28 29
507     30 31 32
508 }
509 
510 /// indicates which parser returned an error
511 #[derive(Debug,PartialEq,Eq,Hash,Clone)]
512 pub enum ErrorKind<E=u32> {
513   Custom(E),
514   Tag,
515   MapRes,
516   MapOpt,
517   Alt,
518   IsNot,
519   IsA,
520   SeparatedList,
521   SeparatedNonEmptyList,
522   Many0,
523   Many1,
524   ManyTill,
525   Count,
526   TakeUntilAndConsume,
527   TakeUntil,
528   TakeUntilEitherAndConsume,
529   TakeUntilEither,
530   LengthValue,
531   TagClosure,
532   Alpha,
533   Digit,
534   HexDigit,
535   OctDigit,
536   AlphaNumeric,
537   Space,
538   MultiSpace,
539   LengthValueFn,
540   Eof,
541   ExprOpt,
542   ExprRes,
543   CondReduce,
544   Switch,
545   TagBits,
546   OneOf,
547   NoneOf,
548   Char,
549   CrLf,
550   RegexpMatch,
551   RegexpMatches,
552   RegexpFind,
553   RegexpCapture,
554   RegexpCaptures,
555   TakeWhile1,
556   Complete,
557   Fix,
558   Escaped,
559   EscapedTransform,
560   TagStr,
561   IsNotStr,
562   IsAStr,
563   TakeWhile1Str,
564   NonEmpty,
565   ManyMN,
566   TakeUntilAndConsumeStr,
567   TakeUntilStr,
568   Not,
569   Permutation,
570   Verify,
571   TakeTill1,
572 }
573 
error_to_u32<E>(e: &ErrorKind<E>) -> u32574 pub fn error_to_u32<E>(e: &ErrorKind<E>) -> u32 {
575   match *e {
576     ErrorKind::Custom(_)                 => 0,
577     ErrorKind::Tag                       => 1,
578     ErrorKind::MapRes                    => 2,
579     ErrorKind::MapOpt                    => 3,
580     ErrorKind::Alt                       => 4,
581     ErrorKind::IsNot                     => 5,
582     ErrorKind::IsA                       => 6,
583     ErrorKind::SeparatedList             => 7,
584     ErrorKind::SeparatedNonEmptyList     => 8,
585     ErrorKind::Many1                     => 9,
586     ErrorKind::Count                     => 10,
587     ErrorKind::TakeUntilAndConsume       => 11,
588     ErrorKind::TakeUntil                 => 12,
589     ErrorKind::TakeUntilEitherAndConsume => 13,
590     ErrorKind::TakeUntilEither           => 14,
591     ErrorKind::LengthValue               => 15,
592     ErrorKind::TagClosure                => 16,
593     ErrorKind::Alpha                     => 17,
594     ErrorKind::Digit                     => 18,
595     ErrorKind::AlphaNumeric              => 19,
596     ErrorKind::Space                     => 20,
597     ErrorKind::MultiSpace                => 21,
598     ErrorKind::LengthValueFn             => 22,
599     ErrorKind::Eof                       => 23,
600     ErrorKind::ExprOpt                   => 24,
601     ErrorKind::ExprRes                   => 25,
602     ErrorKind::CondReduce                => 26,
603     ErrorKind::Switch                    => 27,
604     ErrorKind::TagBits                   => 28,
605     ErrorKind::OneOf                     => 29,
606     ErrorKind::NoneOf                    => 30,
607     ErrorKind::Char                      => 40,
608     ErrorKind::CrLf                      => 41,
609     ErrorKind::RegexpMatch               => 42,
610     ErrorKind::RegexpMatches             => 43,
611     ErrorKind::RegexpFind                => 44,
612     ErrorKind::RegexpCapture             => 45,
613     ErrorKind::RegexpCaptures            => 46,
614     ErrorKind::TakeWhile1                => 47,
615     ErrorKind::Complete                  => 48,
616     ErrorKind::Fix                       => 49,
617     ErrorKind::Escaped                   => 50,
618     ErrorKind::EscapedTransform          => 51,
619     ErrorKind::TagStr                    => 52,
620     ErrorKind::IsNotStr                  => 53,
621     ErrorKind::IsAStr                    => 54,
622     ErrorKind::TakeWhile1Str             => 55,
623     ErrorKind::NonEmpty                  => 56,
624     ErrorKind::ManyMN                    => 57,
625     ErrorKind::TakeUntilAndConsumeStr    => 58,
626     ErrorKind::HexDigit                  => 59,
627     ErrorKind::TakeUntilStr              => 60,
628     ErrorKind::OctDigit                  => 61,
629     ErrorKind::Many0                     => 62,
630     ErrorKind::Not                       => 63,
631     ErrorKind::Permutation               => 64,
632     ErrorKind::ManyTill                  => 65,
633     ErrorKind::Verify                    => 66,
634     ErrorKind::TakeTill1                 => 67,
635   }
636 }
637 
638   impl<E> ErrorKind<E> {
description(&self) -> &str639     pub fn description(&self) -> &str {
640       match *self {
641         ErrorKind::Custom(_)                 => "Custom error",
642         ErrorKind::Tag                       => "Tag",
643         ErrorKind::MapRes                    => "Map on Result",
644         ErrorKind::MapOpt                    => "Map on Option",
645         ErrorKind::Alt                       => "Alternative",
646         ErrorKind::IsNot                     => "IsNot",
647         ErrorKind::IsA                       => "IsA",
648         ErrorKind::SeparatedList             => "Separated list",
649         ErrorKind::SeparatedNonEmptyList     => "Separated non empty list",
650         ErrorKind::Many0                     => "Many0",
651         ErrorKind::Many1                     => "Many1",
652         ErrorKind::Count                     => "Count",
653         ErrorKind::TakeUntilAndConsume       => "Take until and consume",
654         ErrorKind::TakeUntil                 => "Take until",
655         ErrorKind::TakeUntilEitherAndConsume => "Take until either and consume",
656         ErrorKind::TakeUntilEither           => "Take until either",
657         ErrorKind::LengthValue               => "Length followed by value",
658         ErrorKind::TagClosure                => "Tag closure",
659         ErrorKind::Alpha                     => "Alphabetic",
660         ErrorKind::Digit                     => "Digit",
661         ErrorKind::AlphaNumeric              => "AlphaNumeric",
662         ErrorKind::Space                     => "Space",
663         ErrorKind::MultiSpace                => "Multiple spaces",
664         ErrorKind::LengthValueFn             => "LengthValueFn",
665         ErrorKind::Eof                       => "End of file",
666         ErrorKind::ExprOpt                   => "Evaluate Option",
667         ErrorKind::ExprRes                   => "Evaluate Result",
668         ErrorKind::CondReduce                => "Condition reduce",
669         ErrorKind::Switch                    => "Switch",
670         ErrorKind::TagBits                   => "Tag on bitstream",
671         ErrorKind::OneOf                     => "OneOf",
672         ErrorKind::NoneOf                    => "NoneOf",
673         ErrorKind::Char                      => "Char",
674         ErrorKind::CrLf                      => "CrLf",
675         ErrorKind::RegexpMatch               => "RegexpMatch",
676         ErrorKind::RegexpMatches             => "RegexpMatches",
677         ErrorKind::RegexpFind                => "RegexpFind",
678         ErrorKind::RegexpCapture             => "RegexpCapture",
679         ErrorKind::RegexpCaptures            => "RegexpCaptures",
680         ErrorKind::TakeWhile1                => "TakeWhile1",
681         ErrorKind::Complete                  => "Complete",
682         ErrorKind::Fix                       => "Fix",
683         ErrorKind::Escaped                   => "Escaped",
684         ErrorKind::EscapedTransform          => "EscapedTransform",
685         ErrorKind::TagStr                    => "Tag on strings",
686         ErrorKind::IsNotStr                  => "IsNot on strings",
687         ErrorKind::IsAStr                    => "IsA on strings",
688         ErrorKind::TakeWhile1Str             => "TakeWhile1 on strings",
689         ErrorKind::NonEmpty                  => "NonEmpty",
690         ErrorKind::ManyMN                    => "Many(m, n)",
691         ErrorKind::TakeUntilAndConsumeStr    => "Take until and consume on strings",
692         ErrorKind::HexDigit                  => "Hexadecimal Digit",
693         ErrorKind::TakeUntilStr              => "Take until on strings",
694         ErrorKind::OctDigit                  => "Octal digit",
695         ErrorKind::Not                       => "Negation",
696         ErrorKind::Permutation               => "Permutation",
697         ErrorKind::ManyTill                  => "ManyTill",
698         ErrorKind::Verify                    => "predicate verification",
699         ErrorKind::TakeTill1                 => "TakeTill1",
700       }
701 
702     }
703     /// Convert Err into an ErrorKind.
704     ///
705     /// This allows application code to use ErrorKind and stay independent from the `verbose-errors` features activation.
into_error_kind(self) -> ErrorKind<E>706     pub fn into_error_kind(self) -> ErrorKind<E> {
707       self
708     }
709   }
710 
711 #[cfg(test)]
712 mod tests {
713     use super::*;
714 
715     #[test]
test_offset_u8()716     fn test_offset_u8() {
717       let s = b"abcd123";
718       let a = &s[..];
719       let b = &a[2..];
720       let c = &a[..4];
721       let d = &a[3..5];
722       assert_eq!(a.offset(b), 2);
723       assert_eq!(a.offset(c), 0);
724       assert_eq!(a.offset(d), 3);
725     }
726 
727     #[test]
test_offset_str()728     fn test_offset_str() {
729       let s = "abcřèÂßÇd123";
730       let a = &s[..];
731       let b = &a[7..];
732       let c = &a[..5];
733       let d = &a[5..9];
734       assert_eq!(a.offset(b), 7);
735       assert_eq!(a.offset(c), 0);
736       assert_eq!(a.offset(d), 5);
737     }
738 }
739