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