1 | //! Traits input types have to implement to work with nom combinators |
2 | use crate::error::{ErrorKind, ParseError}; |
3 | use crate::internal::{Err, IResult, Needed}; |
4 | use crate::lib::std::iter::{Copied, Enumerate}; |
5 | use crate::lib::std::ops::{Range, RangeFrom, RangeFull, RangeTo}; |
6 | use crate::lib::std::slice::Iter; |
7 | use crate::lib::std::str::from_utf8; |
8 | use crate::lib::std::str::CharIndices; |
9 | use crate::lib::std::str::Chars; |
10 | use crate::lib::std::str::FromStr; |
11 | |
12 | #[cfg (feature = "alloc" )] |
13 | use crate::lib::std::string::String; |
14 | #[cfg (feature = "alloc" )] |
15 | use crate::lib::std::vec::Vec; |
16 | |
17 | /// Abstract method to calculate the input length |
18 | pub trait InputLength { |
19 | /// Calculates the input length, as indicated by its name, |
20 | /// and the name of the trait itself |
21 | fn input_len(&self) -> usize; |
22 | } |
23 | |
24 | impl<'a, T> InputLength for &'a [T] { |
25 | #[inline ] |
26 | fn input_len(&self) -> usize { |
27 | self.len() |
28 | } |
29 | } |
30 | |
31 | impl<'a> InputLength for &'a str { |
32 | #[inline ] |
33 | fn input_len(&self) -> usize { |
34 | self.len() |
35 | } |
36 | } |
37 | |
38 | impl<'a> InputLength for (&'a [u8], usize) { |
39 | #[inline ] |
40 | fn input_len(&self) -> usize { |
41 | //println!("bit input length for ({:?}, {}):", self.0, self.1); |
42 | //println!("-> {}", self.0.len() * 8 - self.1); |
43 | self.0.len() * 8 - self.1 |
44 | } |
45 | } |
46 | |
47 | /// Useful functions to calculate the offset between slices and show a hexdump of a slice |
48 | pub trait Offset { |
49 | /// Offset between the first byte of self and the first byte of the argument |
50 | fn offset(&self, second: &Self) -> usize; |
51 | } |
52 | |
53 | impl Offset for [u8] { |
54 | fn offset(&self, second: &Self) -> usize { |
55 | let fst: *const u8 = self.as_ptr(); |
56 | let snd: *const u8 = second.as_ptr(); |
57 | |
58 | snd as usize - fst as usize |
59 | } |
60 | } |
61 | |
62 | impl<'a> Offset for &'a [u8] { |
63 | fn offset(&self, second: &Self) -> usize { |
64 | let fst: *const u8 = self.as_ptr(); |
65 | let snd: *const u8 = second.as_ptr(); |
66 | |
67 | snd as usize - fst as usize |
68 | } |
69 | } |
70 | |
71 | impl Offset for str { |
72 | fn offset(&self, second: &Self) -> usize { |
73 | let fst: *const u8 = self.as_ptr(); |
74 | let snd: *const u8 = second.as_ptr(); |
75 | |
76 | snd as usize - fst as usize |
77 | } |
78 | } |
79 | |
80 | impl<'a> Offset for &'a str { |
81 | fn offset(&self, second: &Self) -> usize { |
82 | let fst: *const u8 = self.as_ptr(); |
83 | let snd: *const u8 = second.as_ptr(); |
84 | |
85 | snd as usize - fst as usize |
86 | } |
87 | } |
88 | |
89 | /// Helper trait for types that can be viewed as a byte slice |
90 | pub trait AsBytes { |
91 | /// Casts the input type to a byte slice |
92 | fn as_bytes(&self) -> &[u8]; |
93 | } |
94 | |
95 | impl<'a> AsBytes for &'a str { |
96 | #[inline (always)] |
97 | fn as_bytes(&self) -> &[u8] { |
98 | (*self).as_bytes() |
99 | } |
100 | } |
101 | |
102 | impl AsBytes for str { |
103 | #[inline (always)] |
104 | fn as_bytes(&self) -> &[u8] { |
105 | self.as_ref() |
106 | } |
107 | } |
108 | |
109 | impl<'a> AsBytes for &'a [u8] { |
110 | #[inline (always)] |
111 | fn as_bytes(&self) -> &[u8] { |
112 | *self |
113 | } |
114 | } |
115 | |
116 | impl AsBytes for [u8] { |
117 | #[inline (always)] |
118 | fn as_bytes(&self) -> &[u8] { |
119 | self |
120 | } |
121 | } |
122 | |
123 | macro_rules! as_bytes_array_impls { |
124 | ($($N:expr)+) => { |
125 | $( |
126 | impl<'a> AsBytes for &'a [u8; $N] { |
127 | #[inline(always)] |
128 | fn as_bytes(&self) -> &[u8] { |
129 | *self |
130 | } |
131 | } |
132 | |
133 | impl AsBytes for [u8; $N] { |
134 | #[inline(always)] |
135 | fn as_bytes(&self) -> &[u8] { |
136 | self |
137 | } |
138 | } |
139 | )+ |
140 | }; |
141 | } |
142 | |
143 | as_bytes_array_impls! { |
144 | 0 1 2 3 4 5 6 7 8 9 |
145 | 10 11 12 13 14 15 16 17 18 19 |
146 | 20 21 22 23 24 25 26 27 28 29 |
147 | 30 31 32 |
148 | } |
149 | |
150 | /// Transforms common types to a char for basic token parsing |
151 | pub trait AsChar { |
152 | /// makes a char from self |
153 | fn as_char(self) -> char; |
154 | |
155 | /// Tests that self is an alphabetic character |
156 | /// |
157 | /// Warning: for `&str` it recognizes alphabetic |
158 | /// characters outside of the 52 ASCII letters |
159 | fn is_alpha(self) -> bool; |
160 | |
161 | /// Tests that self is an alphabetic character |
162 | /// or a decimal digit |
163 | fn is_alphanum(self) -> bool; |
164 | /// Tests that self is a decimal digit |
165 | fn is_dec_digit(self) -> bool; |
166 | /// Tests that self is an hex digit |
167 | fn is_hex_digit(self) -> bool; |
168 | /// Tests that self is an octal digit |
169 | fn is_oct_digit(self) -> bool; |
170 | /// Gets the len in bytes for self |
171 | fn len(self) -> usize; |
172 | } |
173 | |
174 | impl AsChar for u8 { |
175 | #[inline ] |
176 | fn as_char(self) -> char { |
177 | self as char |
178 | } |
179 | #[inline ] |
180 | fn is_alpha(self) -> bool { |
181 | (self >= 0x41 && self <= 0x5A) || (self >= 0x61 && self <= 0x7A) |
182 | } |
183 | #[inline ] |
184 | fn is_alphanum(self) -> bool { |
185 | self.is_alpha() || self.is_dec_digit() |
186 | } |
187 | #[inline ] |
188 | fn is_dec_digit(self) -> bool { |
189 | self >= 0x30 && self <= 0x39 |
190 | } |
191 | #[inline ] |
192 | fn is_hex_digit(self) -> bool { |
193 | (self >= 0x30 && self <= 0x39) |
194 | || (self >= 0x41 && self <= 0x46) |
195 | || (self >= 0x61 && self <= 0x66) |
196 | } |
197 | #[inline ] |
198 | fn is_oct_digit(self) -> bool { |
199 | self >= 0x30 && self <= 0x37 |
200 | } |
201 | #[inline ] |
202 | fn len(self) -> usize { |
203 | 1 |
204 | } |
205 | } |
206 | impl<'a> AsChar for &'a u8 { |
207 | #[inline ] |
208 | fn as_char(self) -> char { |
209 | *self as char |
210 | } |
211 | #[inline ] |
212 | fn is_alpha(self) -> bool { |
213 | (*self >= 0x41 && *self <= 0x5A) || (*self >= 0x61 && *self <= 0x7A) |
214 | } |
215 | #[inline ] |
216 | fn is_alphanum(self) -> bool { |
217 | self.is_alpha() || self.is_dec_digit() |
218 | } |
219 | #[inline ] |
220 | fn is_dec_digit(self) -> bool { |
221 | *self >= 0x30 && *self <= 0x39 |
222 | } |
223 | #[inline ] |
224 | fn is_hex_digit(self) -> bool { |
225 | (*self >= 0x30 && *self <= 0x39) |
226 | || (*self >= 0x41 && *self <= 0x46) |
227 | || (*self >= 0x61 && *self <= 0x66) |
228 | } |
229 | #[inline ] |
230 | fn is_oct_digit(self) -> bool { |
231 | *self >= 0x30 && *self <= 0x37 |
232 | } |
233 | #[inline ] |
234 | fn len(self) -> usize { |
235 | 1 |
236 | } |
237 | } |
238 | |
239 | impl AsChar for char { |
240 | #[inline ] |
241 | fn as_char(self) -> char { |
242 | self |
243 | } |
244 | #[inline ] |
245 | fn is_alpha(self) -> bool { |
246 | self.is_ascii_alphabetic() |
247 | } |
248 | #[inline ] |
249 | fn is_alphanum(self) -> bool { |
250 | self.is_alpha() || self.is_dec_digit() |
251 | } |
252 | #[inline ] |
253 | fn is_dec_digit(self) -> bool { |
254 | self.is_ascii_digit() |
255 | } |
256 | #[inline ] |
257 | fn is_hex_digit(self) -> bool { |
258 | self.is_ascii_hexdigit() |
259 | } |
260 | #[inline ] |
261 | fn is_oct_digit(self) -> bool { |
262 | self.is_digit(8) |
263 | } |
264 | #[inline ] |
265 | fn len(self) -> usize { |
266 | self.len_utf8() |
267 | } |
268 | } |
269 | |
270 | impl<'a> AsChar for &'a char { |
271 | #[inline ] |
272 | fn as_char(self) -> char { |
273 | *self |
274 | } |
275 | #[inline ] |
276 | fn is_alpha(self) -> bool { |
277 | self.is_ascii_alphabetic() |
278 | } |
279 | #[inline ] |
280 | fn is_alphanum(self) -> bool { |
281 | self.is_alpha() || self.is_dec_digit() |
282 | } |
283 | #[inline ] |
284 | fn is_dec_digit(self) -> bool { |
285 | self.is_ascii_digit() |
286 | } |
287 | #[inline ] |
288 | fn is_hex_digit(self) -> bool { |
289 | self.is_ascii_hexdigit() |
290 | } |
291 | #[inline ] |
292 | fn is_oct_digit(self) -> bool { |
293 | self.is_digit(8) |
294 | } |
295 | #[inline ] |
296 | fn len(self) -> usize { |
297 | self.len_utf8() |
298 | } |
299 | } |
300 | |
301 | /// Abstracts common iteration operations on the input type |
302 | pub trait InputIter { |
303 | /// The current input type is a sequence of that `Item` type. |
304 | /// |
305 | /// Example: `u8` for `&[u8]` or `char` for `&str` |
306 | type Item; |
307 | /// An iterator over the input type, producing the item and its position |
308 | /// for use with [Slice]. If we're iterating over `&str`, the position |
309 | /// corresponds to the byte index of the character |
310 | type Iter: Iterator<Item = (usize, Self::Item)>; |
311 | |
312 | /// An iterator over the input type, producing the item |
313 | type IterElem: Iterator<Item = Self::Item>; |
314 | |
315 | /// Returns an iterator over the elements and their byte offsets |
316 | fn iter_indices(&self) -> Self::Iter; |
317 | /// Returns an iterator over the elements |
318 | fn iter_elements(&self) -> Self::IterElem; |
319 | /// Finds the byte position of the element |
320 | fn position<P>(&self, predicate: P) -> Option<usize> |
321 | where |
322 | P: Fn(Self::Item) -> bool; |
323 | /// Get the byte offset from the element's position in the stream |
324 | fn slice_index(&self, count: usize) -> Result<usize, Needed>; |
325 | } |
326 | |
327 | /// Abstracts slicing operations |
328 | pub trait InputTake: Sized { |
329 | /// Returns a slice of `count` bytes. panics if count > length |
330 | fn take(&self, count: usize) -> Self; |
331 | /// Split the stream at the `count` byte offset. panics if count > length |
332 | fn take_split(&self, count: usize) -> (Self, Self); |
333 | } |
334 | |
335 | impl<'a> InputIter for &'a [u8] { |
336 | type Item = u8; |
337 | type Iter = Enumerate<Self::IterElem>; |
338 | type IterElem = Copied<Iter<'a, u8>>; |
339 | |
340 | #[inline ] |
341 | fn iter_indices(&self) -> Self::Iter { |
342 | self.iter_elements().enumerate() |
343 | } |
344 | #[inline ] |
345 | fn iter_elements(&self) -> Self::IterElem { |
346 | self.iter().copied() |
347 | } |
348 | #[inline ] |
349 | fn position<P>(&self, predicate: P) -> Option<usize> |
350 | where |
351 | P: Fn(Self::Item) -> bool, |
352 | { |
353 | self.iter().position(|b| predicate(*b)) |
354 | } |
355 | #[inline ] |
356 | fn slice_index(&self, count: usize) -> Result<usize, Needed> { |
357 | if self.len() >= count { |
358 | Ok(count) |
359 | } else { |
360 | Err(Needed::new(count - self.len())) |
361 | } |
362 | } |
363 | } |
364 | |
365 | impl<'a> InputTake for &'a [u8] { |
366 | #[inline ] |
367 | fn take(&self, count: usize) -> Self { |
368 | &self[0..count] |
369 | } |
370 | #[inline ] |
371 | fn take_split(&self, count: usize) -> (Self, Self) { |
372 | let (prefix: &[u8], suffix: &[u8]) = self.split_at(mid:count); |
373 | (suffix, prefix) |
374 | } |
375 | } |
376 | |
377 | impl<'a> InputIter for &'a str { |
378 | type Item = char; |
379 | type Iter = CharIndices<'a>; |
380 | type IterElem = Chars<'a>; |
381 | #[inline ] |
382 | fn iter_indices(&self) -> Self::Iter { |
383 | self.char_indices() |
384 | } |
385 | #[inline ] |
386 | fn iter_elements(&self) -> Self::IterElem { |
387 | self.chars() |
388 | } |
389 | fn position<P>(&self, predicate: P) -> Option<usize> |
390 | where |
391 | P: Fn(Self::Item) -> bool, |
392 | { |
393 | for (o, c) in self.char_indices() { |
394 | if predicate(c) { |
395 | return Some(o); |
396 | } |
397 | } |
398 | None |
399 | } |
400 | #[inline ] |
401 | fn slice_index(&self, count: usize) -> Result<usize, Needed> { |
402 | let mut cnt = 0; |
403 | for (index, _) in self.char_indices() { |
404 | if cnt == count { |
405 | return Ok(index); |
406 | } |
407 | cnt += 1; |
408 | } |
409 | if cnt == count { |
410 | return Ok(self.len()); |
411 | } |
412 | Err(Needed::Unknown) |
413 | } |
414 | } |
415 | |
416 | impl<'a> InputTake for &'a str { |
417 | #[inline ] |
418 | fn take(&self, count: usize) -> Self { |
419 | &self[..count] |
420 | } |
421 | |
422 | // return byte index |
423 | #[inline ] |
424 | fn take_split(&self, count: usize) -> (Self, Self) { |
425 | let (prefix: &str, suffix: &str) = self.split_at(mid:count); |
426 | (suffix, prefix) |
427 | } |
428 | } |
429 | |
430 | /// Dummy trait used for default implementations (currently only used for `InputTakeAtPosition` and `Compare`). |
431 | /// |
432 | /// When implementing a custom input type, it is possible to use directly the |
433 | /// default implementation: If the input type implements `InputLength`, `InputIter`, |
434 | /// `InputTake` and `Clone`, you can implement `UnspecializedInput` and get |
435 | /// a default version of `InputTakeAtPosition` and `Compare`. |
436 | /// |
437 | /// For performance reasons, you might want to write a custom implementation of |
438 | /// `InputTakeAtPosition` (like the one for `&[u8]`). |
439 | pub trait UnspecializedInput {} |
440 | |
441 | /// Methods to take as much input as possible until the provided function returns true for the current element. |
442 | /// |
443 | /// A large part of nom's basic parsers are built using this trait. |
444 | pub trait InputTakeAtPosition: Sized { |
445 | /// The current input type is a sequence of that `Item` type. |
446 | /// |
447 | /// Example: `u8` for `&[u8]` or `char` for `&str` |
448 | type Item; |
449 | |
450 | /// Looks for the first element of the input type for which the condition returns true, |
451 | /// and returns the input up to this position. |
452 | /// |
453 | /// *streaming version*: If no element is found matching the condition, this will return `Incomplete` |
454 | fn split_at_position<P, E: ParseError<Self>>(&self, predicate: P) -> IResult<Self, Self, E> |
455 | where |
456 | P: Fn(Self::Item) -> bool; |
457 | |
458 | /// Looks for the first element of the input type for which the condition returns true |
459 | /// and returns the input up to this position. |
460 | /// |
461 | /// Fails if the produced slice is empty. |
462 | /// |
463 | /// *streaming version*: If no element is found matching the condition, this will return `Incomplete` |
464 | fn split_at_position1<P, E: ParseError<Self>>( |
465 | &self, |
466 | predicate: P, |
467 | e: ErrorKind, |
468 | ) -> IResult<Self, Self, E> |
469 | where |
470 | P: Fn(Self::Item) -> bool; |
471 | |
472 | /// Looks for the first element of the input type for which the condition returns true, |
473 | /// and returns the input up to this position. |
474 | /// |
475 | /// *complete version*: If no element is found matching the condition, this will return the whole input |
476 | fn split_at_position_complete<P, E: ParseError<Self>>( |
477 | &self, |
478 | predicate: P, |
479 | ) -> IResult<Self, Self, E> |
480 | where |
481 | P: Fn(Self::Item) -> bool; |
482 | |
483 | /// Looks for the first element of the input type for which the condition returns true |
484 | /// and returns the input up to this position. |
485 | /// |
486 | /// Fails if the produced slice is empty. |
487 | /// |
488 | /// *complete version*: If no element is found matching the condition, this will return the whole input |
489 | fn split_at_position1_complete<P, E: ParseError<Self>>( |
490 | &self, |
491 | predicate: P, |
492 | e: ErrorKind, |
493 | ) -> IResult<Self, Self, E> |
494 | where |
495 | P: Fn(Self::Item) -> bool; |
496 | } |
497 | |
498 | impl<T: InputLength + InputIter + InputTake + Clone + UnspecializedInput> InputTakeAtPosition |
499 | for T |
500 | { |
501 | type Item = <T as InputIter>::Item; |
502 | |
503 | fn split_at_position<P, E: ParseError<Self>>(&self, predicate: P) -> IResult<Self, Self, E> |
504 | where |
505 | P: Fn(Self::Item) -> bool, |
506 | { |
507 | match self.position(predicate) { |
508 | Some(n) => Ok(self.take_split(n)), |
509 | None => Err(Err::Incomplete(Needed::new(1))), |
510 | } |
511 | } |
512 | |
513 | fn split_at_position1<P, E: ParseError<Self>>( |
514 | &self, |
515 | predicate: P, |
516 | e: ErrorKind, |
517 | ) -> IResult<Self, Self, E> |
518 | where |
519 | P: Fn(Self::Item) -> bool, |
520 | { |
521 | match self.position(predicate) { |
522 | Some(0) => Err(Err::Error(E::from_error_kind(self.clone(), e))), |
523 | Some(n) => Ok(self.take_split(n)), |
524 | None => Err(Err::Incomplete(Needed::new(1))), |
525 | } |
526 | } |
527 | |
528 | fn split_at_position_complete<P, E: ParseError<Self>>( |
529 | &self, |
530 | predicate: P, |
531 | ) -> IResult<Self, Self, E> |
532 | where |
533 | P: Fn(Self::Item) -> bool, |
534 | { |
535 | match self.split_at_position(predicate) { |
536 | Err(Err::Incomplete(_)) => Ok(self.take_split(self.input_len())), |
537 | res => res, |
538 | } |
539 | } |
540 | |
541 | fn split_at_position1_complete<P, E: ParseError<Self>>( |
542 | &self, |
543 | predicate: P, |
544 | e: ErrorKind, |
545 | ) -> IResult<Self, Self, E> |
546 | where |
547 | P: Fn(Self::Item) -> bool, |
548 | { |
549 | match self.split_at_position1(predicate, e) { |
550 | Err(Err::Incomplete(_)) => { |
551 | if self.input_len() == 0 { |
552 | Err(Err::Error(E::from_error_kind(self.clone(), e))) |
553 | } else { |
554 | Ok(self.take_split(self.input_len())) |
555 | } |
556 | } |
557 | res => res, |
558 | } |
559 | } |
560 | } |
561 | |
562 | impl<'a> InputTakeAtPosition for &'a [u8] { |
563 | type Item = u8; |
564 | |
565 | fn split_at_position<P, E: ParseError<Self>>(&self, predicate: P) -> IResult<Self, Self, E> |
566 | where |
567 | P: Fn(Self::Item) -> bool, |
568 | { |
569 | match self.iter().position(|c| predicate(*c)) { |
570 | Some(i) => Ok(self.take_split(i)), |
571 | None => Err(Err::Incomplete(Needed::new(1))), |
572 | } |
573 | } |
574 | |
575 | fn split_at_position1<P, E: ParseError<Self>>( |
576 | &self, |
577 | predicate: P, |
578 | e: ErrorKind, |
579 | ) -> IResult<Self, Self, E> |
580 | where |
581 | P: Fn(Self::Item) -> bool, |
582 | { |
583 | match self.iter().position(|c| predicate(*c)) { |
584 | Some(0) => Err(Err::Error(E::from_error_kind(self, e))), |
585 | Some(i) => Ok(self.take_split(i)), |
586 | None => Err(Err::Incomplete(Needed::new(1))), |
587 | } |
588 | } |
589 | |
590 | fn split_at_position_complete<P, E: ParseError<Self>>( |
591 | &self, |
592 | predicate: P, |
593 | ) -> IResult<Self, Self, E> |
594 | where |
595 | P: Fn(Self::Item) -> bool, |
596 | { |
597 | match self.iter().position(|c| predicate(*c)) { |
598 | Some(i) => Ok(self.take_split(i)), |
599 | None => Ok(self.take_split(self.input_len())), |
600 | } |
601 | } |
602 | |
603 | fn split_at_position1_complete<P, E: ParseError<Self>>( |
604 | &self, |
605 | predicate: P, |
606 | e: ErrorKind, |
607 | ) -> IResult<Self, Self, E> |
608 | where |
609 | P: Fn(Self::Item) -> bool, |
610 | { |
611 | match self.iter().position(|c| predicate(*c)) { |
612 | Some(0) => Err(Err::Error(E::from_error_kind(self, e))), |
613 | Some(i) => Ok(self.take_split(i)), |
614 | None => { |
615 | if self.is_empty() { |
616 | Err(Err::Error(E::from_error_kind(self, e))) |
617 | } else { |
618 | Ok(self.take_split(self.input_len())) |
619 | } |
620 | } |
621 | } |
622 | } |
623 | } |
624 | |
625 | impl<'a> InputTakeAtPosition for &'a str { |
626 | type Item = char; |
627 | |
628 | fn split_at_position<P, E: ParseError<Self>>(&self, predicate: P) -> IResult<Self, Self, E> |
629 | where |
630 | P: Fn(Self::Item) -> bool, |
631 | { |
632 | match self.find(predicate) { |
633 | // find() returns a byte index that is already in the slice at a char boundary |
634 | Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, |
635 | None => Err(Err::Incomplete(Needed::new(1))), |
636 | } |
637 | } |
638 | |
639 | fn split_at_position1<P, E: ParseError<Self>>( |
640 | &self, |
641 | predicate: P, |
642 | e: ErrorKind, |
643 | ) -> IResult<Self, Self, E> |
644 | where |
645 | P: Fn(Self::Item) -> bool, |
646 | { |
647 | match self.find(predicate) { |
648 | Some(0) => Err(Err::Error(E::from_error_kind(self, e))), |
649 | // find() returns a byte index that is already in the slice at a char boundary |
650 | Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, |
651 | None => Err(Err::Incomplete(Needed::new(1))), |
652 | } |
653 | } |
654 | |
655 | fn split_at_position_complete<P, E: ParseError<Self>>( |
656 | &self, |
657 | predicate: P, |
658 | ) -> IResult<Self, Self, E> |
659 | where |
660 | P: Fn(Self::Item) -> bool, |
661 | { |
662 | match self.find(predicate) { |
663 | // find() returns a byte index that is already in the slice at a char boundary |
664 | Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, |
665 | // the end of slice is a char boundary |
666 | None => unsafe { |
667 | Ok(( |
668 | self.get_unchecked(self.len()..), |
669 | self.get_unchecked(..self.len()), |
670 | )) |
671 | }, |
672 | } |
673 | } |
674 | |
675 | fn split_at_position1_complete<P, E: ParseError<Self>>( |
676 | &self, |
677 | predicate: P, |
678 | e: ErrorKind, |
679 | ) -> IResult<Self, Self, E> |
680 | where |
681 | P: Fn(Self::Item) -> bool, |
682 | { |
683 | match self.find(predicate) { |
684 | Some(0) => Err(Err::Error(E::from_error_kind(self, e))), |
685 | // find() returns a byte index that is already in the slice at a char boundary |
686 | Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) }, |
687 | None => { |
688 | if self.is_empty() { |
689 | Err(Err::Error(E::from_error_kind(self, e))) |
690 | } else { |
691 | // the end of slice is a char boundary |
692 | unsafe { |
693 | Ok(( |
694 | self.get_unchecked(self.len()..), |
695 | self.get_unchecked(..self.len()), |
696 | )) |
697 | } |
698 | } |
699 | } |
700 | } |
701 | } |
702 | } |
703 | |
704 | /// Indicates whether a comparison was successful, an error, or |
705 | /// if more data was needed |
706 | #[derive (Debug, PartialEq)] |
707 | pub enum CompareResult { |
708 | /// Comparison was successful |
709 | Ok, |
710 | /// We need more data to be sure |
711 | Incomplete, |
712 | /// Comparison failed |
713 | Error, |
714 | } |
715 | |
716 | /// Abstracts comparison operations |
717 | pub trait Compare<T> { |
718 | /// Compares self to another value for equality |
719 | fn compare(&self, t: T) -> CompareResult; |
720 | /// Compares self to another value for equality |
721 | /// independently of the case. |
722 | /// |
723 | /// Warning: for `&str`, the comparison is done |
724 | /// by lowercasing both strings and comparing |
725 | /// the result. This is a temporary solution until |
726 | /// a better one appears |
727 | fn compare_no_case(&self, t: T) -> CompareResult; |
728 | } |
729 | |
730 | fn lowercase_byte(c: u8) -> u8 { |
731 | match c { |
732 | b'A' ..=b'Z' => c - b'A' + b'a' , |
733 | _ => c, |
734 | } |
735 | } |
736 | |
737 | impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] { |
738 | #[inline (always)] |
739 | fn compare(&self, t: &'b [u8]) -> CompareResult { |
740 | let pos = self.iter().zip(t.iter()).position(|(a, b)| a != b); |
741 | |
742 | match pos { |
743 | Some(_) => CompareResult::Error, |
744 | None => { |
745 | if self.len() >= t.len() { |
746 | CompareResult::Ok |
747 | } else { |
748 | CompareResult::Incomplete |
749 | } |
750 | } |
751 | } |
752 | |
753 | /* |
754 | let len = self.len(); |
755 | let blen = t.len(); |
756 | let m = if len < blen { len } else { blen }; |
757 | let reduced = &self[..m]; |
758 | let b = &t[..m]; |
759 | |
760 | if reduced != b { |
761 | CompareResult::Error |
762 | } else if m < blen { |
763 | CompareResult::Incomplete |
764 | } else { |
765 | CompareResult::Ok |
766 | } |
767 | */ |
768 | } |
769 | |
770 | #[inline (always)] |
771 | fn compare_no_case(&self, t: &'b [u8]) -> CompareResult { |
772 | if self |
773 | .iter() |
774 | .zip(t) |
775 | .any(|(a, b)| lowercase_byte(*a) != lowercase_byte(*b)) |
776 | { |
777 | CompareResult::Error |
778 | } else if self.len() < t.len() { |
779 | CompareResult::Incomplete |
780 | } else { |
781 | CompareResult::Ok |
782 | } |
783 | } |
784 | } |
785 | |
786 | impl< |
787 | T: InputLength + InputIter<Item = u8> + InputTake + UnspecializedInput, |
788 | O: InputLength + InputIter<Item = u8> + InputTake, |
789 | > Compare<O> for T |
790 | { |
791 | #[inline (always)] |
792 | fn compare(&self, t: O) -> CompareResult { |
793 | let pos = self |
794 | .iter_elements() |
795 | .zip(t.iter_elements()) |
796 | .position(|(a, b)| a != b); |
797 | |
798 | match pos { |
799 | Some(_) => CompareResult::Error, |
800 | None => { |
801 | if self.input_len() >= t.input_len() { |
802 | CompareResult::Ok |
803 | } else { |
804 | CompareResult::Incomplete |
805 | } |
806 | } |
807 | } |
808 | } |
809 | |
810 | #[inline (always)] |
811 | fn compare_no_case(&self, t: O) -> CompareResult { |
812 | if self |
813 | .iter_elements() |
814 | .zip(t.iter_elements()) |
815 | .any(|(a, b)| lowercase_byte(a) != lowercase_byte(b)) |
816 | { |
817 | CompareResult::Error |
818 | } else if self.input_len() < t.input_len() { |
819 | CompareResult::Incomplete |
820 | } else { |
821 | CompareResult::Ok |
822 | } |
823 | } |
824 | } |
825 | |
826 | impl<'a, 'b> Compare<&'b str> for &'a [u8] { |
827 | #[inline (always)] |
828 | fn compare(&self, t: &'b str) -> CompareResult { |
829 | self.compare(AsBytes::as_bytes(self:t)) |
830 | } |
831 | #[inline (always)] |
832 | fn compare_no_case(&self, t: &'b str) -> CompareResult { |
833 | self.compare_no_case(AsBytes::as_bytes(self:t)) |
834 | } |
835 | } |
836 | |
837 | impl<'a, 'b> Compare<&'b str> for &'a str { |
838 | #[inline (always)] |
839 | fn compare(&self, t: &'b str) -> CompareResult { |
840 | self.as_bytes().compare(t.as_bytes()) |
841 | } |
842 | |
843 | //FIXME: this version is too simple and does not use the current locale |
844 | #[inline (always)] |
845 | fn compare_no_case(&self, t: &'b str) -> CompareResult { |
846 | let pos = self |
847 | .chars() |
848 | .zip(t.chars()) |
849 | .position(|(a, b)| a.to_lowercase().ne(b.to_lowercase())); |
850 | |
851 | match pos { |
852 | Some(_) => CompareResult::Error, |
853 | None => { |
854 | if self.len() >= t.len() { |
855 | CompareResult::Ok |
856 | } else { |
857 | CompareResult::Incomplete |
858 | } |
859 | } |
860 | } |
861 | } |
862 | } |
863 | |
864 | impl<'a, 'b> Compare<&'b [u8]> for &'a str { |
865 | #[inline (always)] |
866 | fn compare(&self, t: &'b [u8]) -> CompareResult { |
867 | AsBytes::as_bytes(self).compare(t) |
868 | } |
869 | #[inline (always)] |
870 | fn compare_no_case(&self, t: &'b [u8]) -> CompareResult { |
871 | AsBytes::as_bytes(self).compare_no_case(t) |
872 | } |
873 | } |
874 | |
875 | /// Look for a token in self |
876 | pub trait FindToken<T> { |
877 | /// Returns true if self contains the token |
878 | fn find_token(&self, token: T) -> bool; |
879 | } |
880 | |
881 | impl<'a> FindToken<u8> for &'a [u8] { |
882 | fn find_token(&self, token: u8) -> bool { |
883 | memchr::memchr(needle:token, self).is_some() |
884 | } |
885 | } |
886 | |
887 | impl<'a> FindToken<u8> for &'a str { |
888 | fn find_token(&self, token: u8) -> bool { |
889 | self.as_bytes().find_token(token) |
890 | } |
891 | } |
892 | |
893 | impl<'a, 'b> FindToken<&'a u8> for &'b [u8] { |
894 | fn find_token(&self, token: &u8) -> bool { |
895 | self.find_token(*token) |
896 | } |
897 | } |
898 | |
899 | impl<'a, 'b> FindToken<&'a u8> for &'b str { |
900 | fn find_token(&self, token: &u8) -> bool { |
901 | self.as_bytes().find_token(token) |
902 | } |
903 | } |
904 | |
905 | impl<'a> FindToken<char> for &'a [u8] { |
906 | fn find_token(&self, token: char) -> bool { |
907 | self.iter().any(|i: &u8| *i == token as u8) |
908 | } |
909 | } |
910 | |
911 | impl<'a> FindToken<char> for &'a str { |
912 | fn find_token(&self, token: char) -> bool { |
913 | self.chars().any(|i: char| i == token) |
914 | } |
915 | } |
916 | |
917 | impl<'a> FindToken<char> for &'a [char] { |
918 | fn find_token(&self, token: char) -> bool { |
919 | self.iter().any(|i: &char| *i == token) |
920 | } |
921 | } |
922 | |
923 | impl<'a, 'b> FindToken<&'a char> for &'b [char] { |
924 | fn find_token(&self, token: &char) -> bool { |
925 | self.find_token(*token) |
926 | } |
927 | } |
928 | |
929 | /// Look for a substring in self |
930 | pub trait FindSubstring<T> { |
931 | /// Returns the byte position of the substring if it is found |
932 | fn find_substring(&self, substr: T) -> Option<usize>; |
933 | } |
934 | |
935 | impl<'a, 'b> FindSubstring<&'b [u8]> for &'a [u8] { |
936 | fn find_substring(&self, substr: &'b [u8]) -> Option<usize> { |
937 | if substr.len() > self.len() { |
938 | return None; |
939 | } |
940 | |
941 | let (&substr_first, substr_rest) = match substr.split_first() { |
942 | Some(split) => split, |
943 | // an empty substring is found at position 0 |
944 | // This matches the behavior of str.find(""). |
945 | None => return Some(0), |
946 | }; |
947 | |
948 | if substr_rest.is_empty() { |
949 | return memchr::memchr(substr_first, self); |
950 | } |
951 | |
952 | let mut offset = 0; |
953 | let haystack = &self[..self.len() - substr_rest.len()]; |
954 | |
955 | while let Some(position) = memchr::memchr(substr_first, &haystack[offset..]) { |
956 | offset += position; |
957 | let next_offset = offset + 1; |
958 | if &self[next_offset..][..substr_rest.len()] == substr_rest { |
959 | return Some(offset); |
960 | } |
961 | |
962 | offset = next_offset; |
963 | } |
964 | |
965 | None |
966 | } |
967 | } |
968 | |
969 | impl<'a, 'b> FindSubstring<&'b str> for &'a [u8] { |
970 | fn find_substring(&self, substr: &'b str) -> Option<usize> { |
971 | self.find_substring(substr:AsBytes::as_bytes(self:substr)) |
972 | } |
973 | } |
974 | |
975 | impl<'a, 'b> FindSubstring<&'b str> for &'a str { |
976 | //returns byte index |
977 | fn find_substring(&self, substr: &'b str) -> Option<usize> { |
978 | self.find(substr) |
979 | } |
980 | } |
981 | |
982 | /// Used to integrate `str`'s `parse()` method |
983 | pub trait ParseTo<R> { |
984 | /// Succeeds if `parse()` succeeded. The byte slice implementation |
985 | /// will first convert it to a `&str`, then apply the `parse()` function |
986 | fn parse_to(&self) -> Option<R>; |
987 | } |
988 | |
989 | impl<'a, R: FromStr> ParseTo<R> for &'a [u8] { |
990 | fn parse_to(&self) -> Option<R> { |
991 | from_utf8(self).ok().and_then(|s: &str| s.parse().ok()) |
992 | } |
993 | } |
994 | |
995 | impl<'a, R: FromStr> ParseTo<R> for &'a str { |
996 | fn parse_to(&self) -> Option<R> { |
997 | self.parse().ok() |
998 | } |
999 | } |
1000 | |
1001 | /// Slicing operations using ranges. |
1002 | /// |
1003 | /// This trait is loosely based on |
1004 | /// `Index`, but can actually return |
1005 | /// something else than a `&[T]` or `&str` |
1006 | pub trait Slice<R> { |
1007 | /// Slices self according to the range argument |
1008 | fn slice(&self, range: R) -> Self; |
1009 | } |
1010 | |
1011 | macro_rules! impl_fn_slice { |
1012 | ( $ty:ty ) => { |
1013 | fn slice(&self, range: $ty) -> Self { |
1014 | &self[range] |
1015 | } |
1016 | }; |
1017 | } |
1018 | |
1019 | macro_rules! slice_range_impl { |
1020 | ( [ $for_type:ident ], $ty:ty ) => { |
1021 | impl<'a, $for_type> Slice<$ty> for &'a [$for_type] { |
1022 | impl_fn_slice!($ty); |
1023 | } |
1024 | }; |
1025 | ( $for_type:ty, $ty:ty ) => { |
1026 | impl<'a> Slice<$ty> for &'a $for_type { |
1027 | impl_fn_slice!($ty); |
1028 | } |
1029 | }; |
1030 | } |
1031 | |
1032 | macro_rules! slice_ranges_impl { |
1033 | ( [ $for_type:ident ] ) => { |
1034 | slice_range_impl! {[$for_type], Range<usize>} |
1035 | slice_range_impl! {[$for_type], RangeTo<usize>} |
1036 | slice_range_impl! {[$for_type], RangeFrom<usize>} |
1037 | slice_range_impl! {[$for_type], RangeFull} |
1038 | }; |
1039 | ( $for_type:ty ) => { |
1040 | slice_range_impl! {$for_type, Range<usize>} |
1041 | slice_range_impl! {$for_type, RangeTo<usize>} |
1042 | slice_range_impl! {$for_type, RangeFrom<usize>} |
1043 | slice_range_impl! {$for_type, RangeFull} |
1044 | }; |
1045 | } |
1046 | |
1047 | slice_ranges_impl! {str} |
1048 | slice_ranges_impl! {[T]} |
1049 | |
1050 | macro_rules! array_impls { |
1051 | ($($N:expr)+) => { |
1052 | $( |
1053 | impl InputLength for [u8; $N] { |
1054 | #[inline] |
1055 | fn input_len(&self) -> usize { |
1056 | self.len() |
1057 | } |
1058 | } |
1059 | |
1060 | impl<'a> InputLength for &'a [u8; $N] { |
1061 | #[inline] |
1062 | fn input_len(&self) -> usize { |
1063 | self.len() |
1064 | } |
1065 | } |
1066 | |
1067 | impl<'a> InputIter for &'a [u8; $N] { |
1068 | type Item = u8; |
1069 | type Iter = Enumerate<Self::IterElem>; |
1070 | type IterElem = Copied<Iter<'a, u8>>; |
1071 | |
1072 | fn iter_indices(&self) -> Self::Iter { |
1073 | (&self[..]).iter_indices() |
1074 | } |
1075 | |
1076 | fn iter_elements(&self) -> Self::IterElem { |
1077 | (&self[..]).iter_elements() |
1078 | } |
1079 | |
1080 | fn position<P>(&self, predicate: P) -> Option<usize> |
1081 | where P: Fn(Self::Item) -> bool { |
1082 | (&self[..]).position(predicate) |
1083 | } |
1084 | |
1085 | fn slice_index(&self, count: usize) -> Result<usize, Needed> { |
1086 | (&self[..]).slice_index(count) |
1087 | } |
1088 | } |
1089 | |
1090 | impl<'a> Compare<[u8; $N]> for &'a [u8] { |
1091 | #[inline(always)] |
1092 | fn compare(&self, t: [u8; $N]) -> CompareResult { |
1093 | self.compare(&t[..]) |
1094 | } |
1095 | |
1096 | #[inline(always)] |
1097 | fn compare_no_case(&self, t: [u8;$N]) -> CompareResult { |
1098 | self.compare_no_case(&t[..]) |
1099 | } |
1100 | } |
1101 | |
1102 | impl<'a,'b> Compare<&'b [u8; $N]> for &'a [u8] { |
1103 | #[inline(always)] |
1104 | fn compare(&self, t: &'b [u8; $N]) -> CompareResult { |
1105 | self.compare(&t[..]) |
1106 | } |
1107 | |
1108 | #[inline(always)] |
1109 | fn compare_no_case(&self, t: &'b [u8;$N]) -> CompareResult { |
1110 | self.compare_no_case(&t[..]) |
1111 | } |
1112 | } |
1113 | |
1114 | impl FindToken<u8> for [u8; $N] { |
1115 | fn find_token(&self, token: u8) -> bool { |
1116 | memchr::memchr(token, &self[..]).is_some() |
1117 | } |
1118 | } |
1119 | |
1120 | impl<'a> FindToken<&'a u8> for [u8; $N] { |
1121 | fn find_token(&self, token: &u8) -> bool { |
1122 | self.find_token(*token) |
1123 | } |
1124 | } |
1125 | )+ |
1126 | }; |
1127 | } |
1128 | |
1129 | array_impls! { |
1130 | 0 1 2 3 4 5 6 7 8 9 |
1131 | 10 11 12 13 14 15 16 17 18 19 |
1132 | 20 21 22 23 24 25 26 27 28 29 |
1133 | 30 31 32 |
1134 | } |
1135 | |
1136 | /// Abstracts something which can extend an `Extend`. |
1137 | /// Used to build modified input slices in `escaped_transform` |
1138 | pub trait ExtendInto { |
1139 | /// The current input type is a sequence of that `Item` type. |
1140 | /// |
1141 | /// Example: `u8` for `&[u8]` or `char` for `&str` |
1142 | type Item; |
1143 | |
1144 | /// The type that will be produced |
1145 | type Extender; |
1146 | |
1147 | /// Create a new `Extend` of the correct type |
1148 | fn new_builder(&self) -> Self::Extender; |
1149 | /// Accumulate the input into an accumulator |
1150 | fn extend_into(&self, acc: &mut Self::Extender); |
1151 | } |
1152 | |
1153 | #[cfg (feature = "alloc" )] |
1154 | impl ExtendInto for [u8] { |
1155 | type Item = u8; |
1156 | type Extender = Vec<u8>; |
1157 | |
1158 | #[inline ] |
1159 | fn new_builder(&self) -> Vec<u8> { |
1160 | Vec::new() |
1161 | } |
1162 | #[inline ] |
1163 | fn extend_into(&self, acc: &mut Vec<u8>) { |
1164 | acc.extend(self.iter().cloned()); |
1165 | } |
1166 | } |
1167 | |
1168 | #[cfg (feature = "alloc" )] |
1169 | impl ExtendInto for &[u8] { |
1170 | type Item = u8; |
1171 | type Extender = Vec<u8>; |
1172 | |
1173 | #[inline ] |
1174 | fn new_builder(&self) -> Vec<u8> { |
1175 | Vec::new() |
1176 | } |
1177 | #[inline ] |
1178 | fn extend_into(&self, acc: &mut Vec<u8>) { |
1179 | acc.extend_from_slice(self); |
1180 | } |
1181 | } |
1182 | |
1183 | #[cfg (feature = "alloc" )] |
1184 | impl ExtendInto for str { |
1185 | type Item = char; |
1186 | type Extender = String; |
1187 | |
1188 | #[inline ] |
1189 | fn new_builder(&self) -> String { |
1190 | String::new() |
1191 | } |
1192 | #[inline ] |
1193 | fn extend_into(&self, acc: &mut String) { |
1194 | acc.push_str(self); |
1195 | } |
1196 | } |
1197 | |
1198 | #[cfg (feature = "alloc" )] |
1199 | impl ExtendInto for &str { |
1200 | type Item = char; |
1201 | type Extender = String; |
1202 | |
1203 | #[inline ] |
1204 | fn new_builder(&self) -> String { |
1205 | String::new() |
1206 | } |
1207 | #[inline ] |
1208 | fn extend_into(&self, acc: &mut String) { |
1209 | acc.push_str(self); |
1210 | } |
1211 | } |
1212 | |
1213 | #[cfg (feature = "alloc" )] |
1214 | impl ExtendInto for char { |
1215 | type Item = char; |
1216 | type Extender = String; |
1217 | |
1218 | #[inline ] |
1219 | fn new_builder(&self) -> String { |
1220 | String::new() |
1221 | } |
1222 | #[inline ] |
1223 | fn extend_into(&self, acc: &mut String) { |
1224 | acc.push(*self); |
1225 | } |
1226 | } |
1227 | |
1228 | /// Helper trait to convert numbers to usize. |
1229 | /// |
1230 | /// By default, usize implements `From<u8>` and `From<u16>` but not |
1231 | /// `From<u32>` and `From<u64>` because that would be invalid on some |
1232 | /// platforms. This trait implements the conversion for platforms |
1233 | /// with 32 and 64 bits pointer platforms |
1234 | pub trait ToUsize { |
1235 | /// converts self to usize |
1236 | fn to_usize(&self) -> usize; |
1237 | } |
1238 | |
1239 | impl ToUsize for u8 { |
1240 | #[inline ] |
1241 | fn to_usize(&self) -> usize { |
1242 | *self as usize |
1243 | } |
1244 | } |
1245 | |
1246 | impl ToUsize for u16 { |
1247 | #[inline ] |
1248 | fn to_usize(&self) -> usize { |
1249 | *self as usize |
1250 | } |
1251 | } |
1252 | |
1253 | impl ToUsize for usize { |
1254 | #[inline ] |
1255 | fn to_usize(&self) -> usize { |
1256 | *self |
1257 | } |
1258 | } |
1259 | |
1260 | #[cfg (any(target_pointer_width = "32" , target_pointer_width = "64" ))] |
1261 | impl ToUsize for u32 { |
1262 | #[inline ] |
1263 | fn to_usize(&self) -> usize { |
1264 | *self as usize |
1265 | } |
1266 | } |
1267 | |
1268 | #[cfg (target_pointer_width = "64" )] |
1269 | impl ToUsize for u64 { |
1270 | #[inline ] |
1271 | fn to_usize(&self) -> usize { |
1272 | *self as usize |
1273 | } |
1274 | } |
1275 | |
1276 | /// Equivalent From implementation to avoid orphan rules in bits parsers |
1277 | pub trait ErrorConvert<E> { |
1278 | /// Transform to another error type |
1279 | fn convert(self) -> E; |
1280 | } |
1281 | |
1282 | impl<I> ErrorConvert<(I, ErrorKind)> for ((I, usize), ErrorKind) { |
1283 | fn convert(self) -> (I, ErrorKind) { |
1284 | ((self.0).0, self.1) |
1285 | } |
1286 | } |
1287 | |
1288 | impl<I> ErrorConvert<((I, usize), ErrorKind)> for (I, ErrorKind) { |
1289 | fn convert(self) -> ((I, usize), ErrorKind) { |
1290 | ((self.0, 0), self.1) |
1291 | } |
1292 | } |
1293 | |
1294 | use crate::error; |
1295 | impl<I> ErrorConvert<error::Error<I>> for error::Error<(I, usize)> { |
1296 | fn convert(self) -> error::Error<I> { |
1297 | error::Error { |
1298 | input: self.input.0, |
1299 | code: self.code, |
1300 | } |
1301 | } |
1302 | } |
1303 | |
1304 | impl<I> ErrorConvert<error::Error<(I, usize)>> for error::Error<I> { |
1305 | fn convert(self) -> error::Error<(I, usize)> { |
1306 | error::Error { |
1307 | input: (self.input, 0), |
1308 | code: self.code, |
1309 | } |
1310 | } |
1311 | } |
1312 | |
1313 | #[cfg (feature = "alloc" )] |
1314 | #[cfg_attr (feature = "docsrs" , doc(cfg(feature = "alloc" )))] |
1315 | impl<I> ErrorConvert<error::VerboseError<I>> for error::VerboseError<(I, usize)> { |
1316 | fn convert(self) -> error::VerboseError<I> { |
1317 | error::VerboseError { |
1318 | errors: self.errors.into_iter().map(|(i: (I, usize), e: VerboseErrorKind)| (i.0, e)).collect(), |
1319 | } |
1320 | } |
1321 | } |
1322 | |
1323 | #[cfg (feature = "alloc" )] |
1324 | #[cfg_attr (feature = "docsrs" , doc(cfg(feature = "alloc" )))] |
1325 | impl<I> ErrorConvert<error::VerboseError<(I, usize)>> for error::VerboseError<I> { |
1326 | fn convert(self) -> error::VerboseError<(I, usize)> { |
1327 | error::VerboseError { |
1328 | errors: self.errors.into_iter().map(|(i: I, e: VerboseErrorKind)| ((i, 0), e)).collect(), |
1329 | } |
1330 | } |
1331 | } |
1332 | |
1333 | impl ErrorConvert<()> for () { |
1334 | fn convert(self) {} |
1335 | } |
1336 | |
1337 | #[cfg (feature = "std" )] |
1338 | #[cfg_attr (feature = "docsrs" , doc(cfg(feature = "std" )))] |
1339 | /// Helper trait to show a byte slice as a hex dump |
1340 | pub trait HexDisplay { |
1341 | /// Converts the value of `self` to a hex dump, returning the owned |
1342 | /// `String`. |
1343 | fn to_hex(&self, chunk_size: usize) -> String; |
1344 | |
1345 | /// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned |
1346 | /// `String`. |
1347 | fn to_hex_from(&self, chunk_size: usize, from: usize) -> String; |
1348 | } |
1349 | |
1350 | #[cfg (feature = "std" )] |
1351 | static CHARS: &[u8] = b"0123456789abcdef" ; |
1352 | |
1353 | #[cfg (feature = "std" )] |
1354 | impl HexDisplay for [u8] { |
1355 | #[allow (unused_variables)] |
1356 | fn to_hex(&self, chunk_size: usize) -> String { |
1357 | self.to_hex_from(chunk_size, 0) |
1358 | } |
1359 | |
1360 | #[allow (unused_variables)] |
1361 | fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { |
1362 | let mut v = Vec::with_capacity(self.len() * 3); |
1363 | let mut i = from; |
1364 | for chunk in self.chunks(chunk_size) { |
1365 | let s = format!(" {:08x}" , i); |
1366 | for &ch in s.as_bytes().iter() { |
1367 | v.push(ch); |
1368 | } |
1369 | v.push(b' \t' ); |
1370 | |
1371 | i += chunk_size; |
1372 | |
1373 | for &byte in chunk { |
1374 | v.push(CHARS[(byte >> 4) as usize]); |
1375 | v.push(CHARS[(byte & 0xf) as usize]); |
1376 | v.push(b' ' ); |
1377 | } |
1378 | if chunk_size > chunk.len() { |
1379 | for j in 0..(chunk_size - chunk.len()) { |
1380 | v.push(b' ' ); |
1381 | v.push(b' ' ); |
1382 | v.push(b' ' ); |
1383 | } |
1384 | } |
1385 | v.push(b' \t' ); |
1386 | |
1387 | for &byte in chunk { |
1388 | if (byte >= 32 && byte <= 126) || byte >= 128 { |
1389 | v.push(byte); |
1390 | } else { |
1391 | v.push(b'.' ); |
1392 | } |
1393 | } |
1394 | v.push(b' \n' ); |
1395 | } |
1396 | |
1397 | String::from_utf8_lossy(&v[..]).into_owned() |
1398 | } |
1399 | } |
1400 | |
1401 | #[cfg (feature = "std" )] |
1402 | impl HexDisplay for str { |
1403 | #[allow (unused_variables)] |
1404 | fn to_hex(&self, chunk_size: usize) -> String { |
1405 | self.to_hex_from(chunk_size, from:0) |
1406 | } |
1407 | |
1408 | #[allow (unused_variables)] |
1409 | fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { |
1410 | self.as_bytes().to_hex_from(chunk_size, from) |
1411 | } |
1412 | } |
1413 | |
1414 | #[cfg (test)] |
1415 | mod tests { |
1416 | use super::*; |
1417 | |
1418 | #[test ] |
1419 | fn test_offset_u8() { |
1420 | let s = b"abcd123" ; |
1421 | let a = &s[..]; |
1422 | let b = &a[2..]; |
1423 | let c = &a[..4]; |
1424 | let d = &a[3..5]; |
1425 | assert_eq!(a.offset(b), 2); |
1426 | assert_eq!(a.offset(c), 0); |
1427 | assert_eq!(a.offset(d), 3); |
1428 | } |
1429 | |
1430 | #[test ] |
1431 | fn test_offset_str() { |
1432 | let s = "abcřèÂßÇd123" ; |
1433 | let a = &s[..]; |
1434 | let b = &a[7..]; |
1435 | let c = &a[..5]; |
1436 | let d = &a[5..9]; |
1437 | assert_eq!(a.offset(b), 7); |
1438 | assert_eq!(a.offset(c), 0); |
1439 | assert_eq!(a.offset(d), 5); |
1440 | } |
1441 | } |
1442 | |