nom_locate/
lib.rs

1//! nom_locate, a special input type to locate tokens
2//!
3//! The source code is available on [Github](https://github.com/fflorent/nom_locate)
4//!
5//! ## Features
6//!
7//! This crate exposes two cargo feature flags, `generic-simd` and `runtime-dispatch-simd`.
8//! These correspond to the features exposed by [bytecount](https://github.com/llogiq/bytecount).
9//!
10//! ## How to use it
11//! The explanations are given in the [README](https://github.com/fflorent/nom_locate/blob/master/README.md) of the Github repository. You may also consult the [FAQ](https://github.com/fflorent/nom_locate/blob/master/FAQ.md).
12//!
13//! ```
14//! use nom::bytes::complete::{tag, take_until};
15//! use nom::IResult;
16//! use nom_locate::{position, LocatedSpan};
17//!
18//! type Span<'a> = LocatedSpan<&'a str>;
19//!
20//! struct Token<'a> {
21//!     pub position: Span<'a>,
22//!     pub foo: &'a str,
23//!     pub bar: &'a str,
24//! }
25//!
26//! fn parse_foobar(s: Span) -> IResult<Span, Token> {
27//!     let (s, _) = take_until("foo")(s)?;
28//!     let (s, pos) = position(s)?;
29//!     let (s, foo) = tag("foo")(s)?;
30//!     let (s, bar) = tag("bar")(s)?;
31//!
32//!     Ok((
33//!         s,
34//!         Token {
35//!             position: pos,
36//!             foo: foo.fragment(),
37//!             bar: bar.fragment(),
38//!         },
39//!     ))
40//! }
41//!
42//! fn main () {
43//!     let input = Span::new("Lorem ipsum \n foobar");
44//!     let output = parse_foobar(input);
45//!     let position = output.unwrap().1.position;
46//!     assert_eq!(position.location_offset(), 14);
47//!     assert_eq!(position.location_line(), 2);
48//!     assert_eq!(position.fragment(), &"");
49//!     assert_eq!(position.get_column(), 2);
50//! }
51//! ```
52//!
53//! ## Extra information
54//!
55//! You can also add arbitrary extra information using the extra property of `LocatedSpan`.
56//! This property is not used when comparing two `LocatedSpan`s.
57//!
58//! ```ignore
59//! use nom_locate::LocatedSpan;
60//! type Span<'a> = LocatedSpan<&'a str, String>;
61//!
62//! let input = Span::new_extra("Lorem ipsum \n foobar", "filename");
63//! let output = parse_foobar(input);
64//! let extra = output.unwrap().1.extra;
65//! ```
66
67#![cfg_attr(not(feature = "std"), no_std)]
68
69#[cfg(all(not(feature = "std"), feature = "alloc"))]
70#[cfg_attr(test, macro_use)]
71extern crate alloc;
72
73#[cfg(test)]
74mod tests;
75
76mod lib {
77    #[cfg(feature = "std")]
78    pub mod std {
79        pub use std::fmt::{Display, Formatter, Result as FmtResult};
80        pub use std::hash::{Hash, Hasher};
81        pub use std::iter::{Copied, Enumerate};
82        pub use std::ops::{Range, RangeFrom, RangeFull, RangeTo};
83        pub use std::slice;
84        pub use std::slice::Iter;
85        pub use std::str::{CharIndices, Chars, FromStr};
86        pub use std::string::{String, ToString};
87        pub use std::vec::Vec;
88    }
89
90    #[cfg(not(feature = "std"))]
91    pub mod std {
92        #[cfg(feature = "alloc")]
93        pub use alloc::fmt::{Display, Formatter, Result as FmtResult};
94        #[cfg(feature = "alloc")]
95        pub use alloc::string::{String, ToString};
96        #[cfg(feature = "alloc")]
97        pub use alloc::vec::Vec;
98        pub use core::hash::{Hash, Hasher};
99        pub use core::iter::{Copied, Enumerate};
100        pub use core::ops::{Range, RangeFrom, RangeFull, RangeTo};
101        pub use core::slice;
102        pub use core::slice::Iter;
103        pub use core::str::{CharIndices, Chars, FromStr};
104    }
105}
106
107use lib::std::*;
108
109use bytecount::{naive_num_chars, num_chars};
110use memchr::Memchr;
111#[cfg(feature = "alloc")]
112use nom::ExtendInto;
113use nom::{
114    error::{ErrorKind, ParseError},
115    AsBytes, Compare, CompareResult, Err, FindSubstring, FindToken, IResult, InputIter,
116    InputLength, InputTake, InputTakeAtPosition, Offset, ParseTo, Slice,
117};
118#[cfg(feature = "stable-deref-trait")]
119use stable_deref_trait::StableDeref;
120
121/// A LocatedSpan is a set of meta information about the location of a token, including extra
122/// information.
123///
124/// The `LocatedSpan` structure can be used as an input of the nom parsers.
125/// It implements all the necessary traits for `LocatedSpan<&str,X>` and `LocatedSpan<&[u8],X>`
126#[derive(Debug, Clone, Copy)]
127pub struct LocatedSpan<T, X = ()> {
128    /// The offset represents the position of the fragment relatively to
129    /// the input of the parser. It starts at offset 0.
130    offset: usize,
131
132    /// The line number of the fragment relatively to the input of the
133    /// parser. It starts at line 1.
134    line: u32,
135
136    /// The fragment that is spanned.
137    /// The fragment represents a part of the input of the parser.
138    fragment: T,
139
140    /// Extra information that can be embedded by the user.
141    /// Example: the parsed file name
142    pub extra: X,
143}
144
145impl<T, X> core::ops::Deref for LocatedSpan<T, X> {
146    type Target = T;
147    fn deref(&self) -> &Self::Target {
148        &self.fragment
149    }
150}
151
152impl<T, U, X> core::convert::AsRef<U> for LocatedSpan<&T, X>
153where
154    T: ?Sized + core::convert::AsRef<U>,
155    U: ?Sized,
156{
157    fn as_ref(&self) -> &U {
158        self.fragment.as_ref()
159    }
160}
161
162#[cfg(feature = "stable-deref-trait")]
163/// Optionally impl StableDeref so that this type works harmoniously with other
164/// crates that rely on this marker trait, such as `rental` and `lazy_static`.
165/// LocatedSpan is largely just a wrapper around the contained type `T`, so
166/// this marker trait is safe to implement whenever T already implements
167/// StableDeref.
168unsafe impl<T: StableDeref, X> StableDeref for LocatedSpan<T, X> {}
169
170impl<T> LocatedSpan<T, ()> {
171    /// Create a span for a particular input with default `offset` and
172    /// `line` values and empty extra data.
173    /// You can compute the column through the `get_column` or `get_utf8_column`
174    /// methods.
175    ///
176    /// `offset` starts at 0, `line` starts at 1, and `column` starts at 1.
177    ///
178    /// Do not use this constructor in parser functions; `nom` and
179    /// `nom_locate` assume span offsets are relative to the beginning of the
180    /// same input. In these cases, you probably want to use the
181    /// `nom::traits::Slice` trait instead.
182    ///
183    /// # Example of use
184    ///
185    /// ```
186    /// # extern crate nom_locate;
187    /// use nom_locate::LocatedSpan;
188    ///
189    /// # fn main() {
190    /// let span = LocatedSpan::new(b"foobar");
191    ///
192    /// assert_eq!(span.location_offset(), 0);
193    /// assert_eq!(span.location_line(),   1);
194    /// assert_eq!(span.get_column(),      1);
195    /// assert_eq!(span.fragment(),        &&b"foobar"[..]);
196    /// # }
197    /// ```
198    pub fn new(program: T) -> LocatedSpan<T, ()> {
199        LocatedSpan {
200            offset: 0,
201            line: 1,
202            fragment: program,
203            extra: (),
204        }
205    }
206}
207
208impl<T, X> LocatedSpan<T, X> {
209    /// Create a span for a particular input with default `offset` and
210    /// `line` values. You can compute the column through the `get_column` or `get_utf8_column`
211    /// methods.
212    ///
213    /// `offset` starts at 0, `line` starts at 1, and `column` starts at 1.
214    ///
215    /// Do not use this constructor in parser functions; `nom` and
216    /// `nom_locate` assume span offsets are relative to the beginning of the
217    /// same input. In these cases, you probably want to use the
218    /// `nom::traits::Slice` trait instead.
219    ///
220    /// # Example of use
221    ///
222    /// ```
223    /// # extern crate nom_locate;
224    /// use nom_locate::LocatedSpan;
225    ///
226    /// # fn main() {
227    /// let span = LocatedSpan::new_extra(b"foobar", "extra");
228    ///
229    /// assert_eq!(span.location_offset(), 0);
230    /// assert_eq!(span.location_line(),   1);
231    /// assert_eq!(span.get_column(),      1);
232    /// assert_eq!(span.fragment(),        &&b"foobar"[..]);
233    /// assert_eq!(span.extra,             "extra");
234    /// # }
235    /// ```
236    pub fn new_extra(program: T, extra: X) -> LocatedSpan<T, X> {
237        LocatedSpan {
238            offset: 0,
239            line: 1,
240            fragment: program,
241            extra: extra,
242        }
243    }
244
245    /// Similar to `new_extra`, but allows overriding offset and line.
246    /// This is unsafe, because giving an offset too large may result in
247    /// undefined behavior, as some methods move back along the fragment
248    /// assuming any negative index within the offset is valid.
249    pub unsafe fn new_from_raw_offset(
250        offset: usize,
251        line: u32,
252        fragment: T,
253        extra: X,
254    ) -> LocatedSpan<T, X> {
255        LocatedSpan {
256            offset,
257            line,
258            fragment,
259            extra,
260        }
261    }
262
263    /// The offset represents the position of the fragment relatively to
264    /// the input of the parser. It starts at offset 0.
265    pub fn location_offset(&self) -> usize {
266        self.offset
267    }
268
269    /// The line number of the fragment relatively to the input of the
270    /// parser. It starts at line 1.
271    pub fn location_line(&self) -> u32 {
272        self.line
273    }
274
275    /// The fragment that is spanned.
276    /// The fragment represents a part of the input of the parser.
277    pub fn fragment(&self) -> &T {
278        &self.fragment
279    }
280
281    /// Transform the extra inside into another type
282    ///
283    /// # Example of use
284    /// ```
285    /// # extern crate nom_locate;
286    /// # extern crate nom;
287    /// # use nom_locate::LocatedSpan;
288    /// use nom::{
289    ///   IResult,
290    ///   combinator::{recognize, map_res},
291    ///   sequence::{terminated, tuple},
292    ///   character::{complete::{char, one_of}, is_digit},
293    ///   bytes::complete::{tag, take_while1}
294    /// };
295    ///
296    /// fn decimal(input: LocatedSpan<&str>) -> IResult<LocatedSpan<&str>, LocatedSpan<&str>> {
297    ///   recognize(
298    ///        take_while1(|c| is_digit(c as u8) || c == '_')
299    ///   )(input)
300    /// }
301    ///
302    /// fn main() {
303    ///     let span = LocatedSpan::new("$10");
304    ///     // matches the $ and then matches the decimal number afterwards,
305    ///     // converting it into a `u8` and putting that value in the span
306    ///     let (_, (_, n)) = tuple((
307    ///                         tag("$"),
308    ///                         map_res(
309    ///                             decimal,
310    ///                             |x| x.fragment().parse::<u8>().map(|n| x.map_extra(|_| n))
311    ///                         )
312    ///                       ))(span).unwrap();
313    ///     assert_eq!(n.extra, 10);
314    /// }
315    /// ```
316    pub fn map_extra<U, F: FnOnce(X) -> U>(self, f: F) -> LocatedSpan<T, U> {
317        LocatedSpan {
318            offset: self.offset,
319            line: self.line,
320            fragment: self.fragment,
321            extra: f(self.extra),
322        }
323    }
324
325    /// Takes ownership of the fragment without (re)borrowing it.
326    ///
327    /// # Example of use
328    /// ```
329    /// # extern crate nom_locate;
330    /// # extern crate nom;
331    /// # use nom_locate::LocatedSpan;
332    /// use nom::{
333    ///     IResult,
334    ///     bytes::complete::{take_till, tag},
335    ///     combinator::rest,
336    /// };
337    ///
338    /// fn parse_pair<'a>(input: LocatedSpan<&'a str>) -> IResult<LocatedSpan<&'a str>, (&'a str, &'a str)> {
339    ///     let (input, key) = take_till(|c| c == '=')(input)?;
340    ///     let (input, _) = tag("=")(input)?;
341    ///     let (input, value) = rest(input)?;
342    ///
343    ///     Ok((input, (key.into_fragment(), value.into_fragment())))
344    /// }
345    ///
346    /// fn main() {
347    ///     let span = LocatedSpan::new("key=value");
348    ///     let (_, pair) = parse_pair(span).unwrap();
349    ///     assert_eq!(pair, ("key", "value"));
350    /// }
351    /// ```
352    pub fn into_fragment(self) -> T {
353        self.fragment
354    }
355
356    /// Takes ownership of the fragment and extra data without (re)borrowing them.
357    pub fn into_fragment_and_extra(self) -> (T, X) {
358        (self.fragment, self.extra)
359    }
360}
361
362impl<T: AsBytes, X> LocatedSpan<T, X> {
363    // Attempt to get the "original" data slice back, by extending
364    // self.fragment backwards by self.offset.
365    // Note that any bytes truncated from after self.fragment will not
366    // be recovered.
367    fn get_unoffsetted_slice(&self) -> &[u8] {
368        let self_bytes = self.fragment.as_bytes();
369        let self_ptr = self_bytes.as_ptr();
370        unsafe {
371            assert!(
372                self.offset <= isize::max_value() as usize,
373                "offset is too big"
374            );
375            let orig_input_ptr = self_ptr.offset(-(self.offset as isize));
376            slice::from_raw_parts(orig_input_ptr, self.offset + self_bytes.len())
377        }
378    }
379
380    fn get_columns_and_bytes_before(&self) -> (usize, &[u8]) {
381        let before_self = &self.get_unoffsetted_slice()[..self.offset];
382
383        let column = match memchr::memrchr(b'\n', before_self) {
384            None => self.offset + 1,
385            Some(pos) => self.offset - pos,
386        };
387
388        (column, &before_self[self.offset - (column - 1)..])
389    }
390
391    /// Return the line that contains this LocatedSpan.
392    ///
393    /// The `get_column` and `get_utf8_column` functions returns
394    /// indexes that corresponds to the line returned by this function.
395    ///
396    /// Note that if this LocatedSpan ends before the end of the
397    /// original data, the result of calling `get_line_beginning()`
398    /// will not include any data from after the LocatedSpan.
399    ///
400    /// ```
401    /// # extern crate nom_locate;
402    /// # extern crate nom;
403    /// # use nom_locate::LocatedSpan;
404    /// # use nom::{Slice, FindSubstring};
405    /// #
406    /// # fn main() {
407    /// let program = LocatedSpan::new(
408    ///     "Hello World!\
409    ///     \nThis is a multi-line input\
410    ///     \nthat ends after this line.\n");
411    /// let multi = program.find_substring("multi").unwrap();
412    ///
413    /// assert_eq!(
414    ///     program.slice(multi..).get_line_beginning(),
415    ///     "This is a multi-line input".as_bytes(),
416    /// );
417    /// # }
418    /// ```
419    pub fn get_line_beginning(&self) -> &[u8] {
420        let column0 = self.get_column() - 1;
421        let the_line = &self.get_unoffsetted_slice()[self.offset - column0..];
422        match memchr::memchr(b'\n', &the_line[column0..]) {
423            None => the_line,
424            Some(pos) => &the_line[..column0 + pos],
425        }
426    }
427
428    /// Return the column index, assuming 1 byte = 1 column.
429    ///
430    /// Use it for ascii text, or use get_utf8_column for UTF8.
431    ///
432    /// # Example of use
433    /// ```
434    ///
435    /// # extern crate nom_locate;
436    /// # extern crate nom;
437    /// # use nom_locate::LocatedSpan;
438    /// # use nom::Slice;
439    /// #
440    /// # fn main() {
441    /// let span = LocatedSpan::new("foobar");
442    ///
443    /// assert_eq!(span.slice(3..).get_column(), 4);
444    /// # }
445    /// ```
446    pub fn get_column(&self) -> usize {
447        self.get_columns_and_bytes_before().0
448    }
449
450    /// Return the column index for UTF8 text. Return value is unspecified for non-utf8 text.
451    ///
452    /// This version uses bytecount's hyper algorithm to count characters. This is much faster
453    /// for long lines, but is non-negligibly slower for short slices (below around 100 bytes).
454    /// This is also sped up significantly more depending on architecture and enabling the simd
455    /// feature gates. If you expect primarily short lines, you may get a noticeable speedup in
456    /// parsing by using `naive_get_utf8_column` instead. Benchmark your specific use case!
457    ///
458    /// # Example of use
459    /// ```
460    ///
461    /// # extern crate nom_locate;
462    /// # extern crate nom;
463    /// # use nom_locate::LocatedSpan;
464    /// # use nom::{Slice, FindSubstring};
465    /// #
466    /// # fn main() {
467    /// let span = LocatedSpan::new("メカジキ");
468    /// let indexOf3dKanji = span.find_substring("ジ").unwrap();
469    ///
470    /// assert_eq!(span.slice(indexOf3dKanji..).get_column(), 7);
471    /// assert_eq!(span.slice(indexOf3dKanji..).get_utf8_column(), 3);
472    /// # }
473    /// ```
474    pub fn get_utf8_column(&self) -> usize {
475        let before_self = self.get_columns_and_bytes_before().1;
476        num_chars(before_self) + 1
477    }
478
479    /// Return the column index for UTF8 text. Return value is unspecified for non-utf8 text.
480    ///
481    /// A simpler implementation of `get_utf8_column` that may be faster on shorter lines.
482    /// If benchmarking shows that this is faster, you can use it instead of `get_utf8_column`.
483    /// Prefer defaulting to `get_utf8_column` unless this legitimately is a performance bottleneck.
484    ///
485    /// # Example of use
486    /// ```
487    ///
488    /// # extern crate nom_locate;
489    /// # extern crate nom;
490    /// # use nom_locate::LocatedSpan;
491    /// # use nom::{Slice, FindSubstring};
492    /// #
493    /// # fn main() {
494    /// let span = LocatedSpan::new("メカジキ");
495    /// let indexOf3dKanji = span.find_substring("ジ").unwrap();
496    ///
497    /// assert_eq!(span.slice(indexOf3dKanji..).get_column(), 7);
498    /// assert_eq!(span.slice(indexOf3dKanji..).naive_get_utf8_column(), 3);
499    /// # }
500    /// ```
501    pub fn naive_get_utf8_column(&self) -> usize {
502        let before_self = self.get_columns_and_bytes_before().1;
503        naive_num_chars(before_self) + 1
504    }
505}
506
507impl<T: Hash, X> Hash for LocatedSpan<T, X> {
508    fn hash<H: Hasher>(&self, state: &mut H) {
509        self.offset.hash(state);
510        self.line.hash(state);
511        self.fragment.hash(state);
512    }
513}
514
515impl<T: AsBytes, X: Default> From<T> for LocatedSpan<T, X> {
516    fn from(i: T) -> Self {
517        Self::new_extra(i, X::default())
518    }
519}
520
521impl<T: AsBytes + PartialEq, X> PartialEq for LocatedSpan<T, X> {
522    fn eq(&self, other: &Self) -> bool {
523        self.line == other.line && self.offset == other.offset && self.fragment == other.fragment
524    }
525}
526
527impl<T: AsBytes + Eq, X> Eq for LocatedSpan<T, X> {}
528
529impl<T: AsBytes, X> AsBytes for LocatedSpan<T, X> {
530    fn as_bytes(&self) -> &[u8] {
531        self.fragment.as_bytes()
532    }
533}
534
535impl<T: InputLength, X> InputLength for LocatedSpan<T, X> {
536    fn input_len(&self) -> usize {
537        self.fragment.input_len()
538    }
539}
540
541impl<T, X> InputTake for LocatedSpan<T, X>
542where
543    Self: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
544{
545    fn take(&self, count: usize) -> Self {
546        self.slice(..count)
547    }
548
549    fn take_split(&self, count: usize) -> (Self, Self) {
550        (self.slice(count..), self.slice(..count))
551    }
552}
553
554impl<T, X> InputTakeAtPosition for LocatedSpan<T, X>
555where
556    T: InputTakeAtPosition + InputLength + InputIter,
557    Self: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>> + Clone,
558{
559    type Item = <T as InputIter>::Item;
560
561    fn split_at_position_complete<P, E: ParseError<Self>>(
562        &self,
563        predicate: P,
564    ) -> IResult<Self, Self, E>
565    where
566        P: Fn(Self::Item) -> bool,
567    {
568        match self.split_at_position(predicate) {
569            Err(Err::Incomplete(_)) => Ok(self.take_split(self.input_len())),
570            res => res,
571        }
572    }
573
574    fn split_at_position<P, E: ParseError<Self>>(&self, predicate: P) -> IResult<Self, Self, E>
575    where
576        P: Fn(Self::Item) -> bool,
577    {
578        match self.fragment.position(predicate) {
579            Some(n) => Ok(self.take_split(n)),
580            None => Err(Err::Incomplete(nom::Needed::new(1))),
581        }
582    }
583
584    fn split_at_position1<P, E: ParseError<Self>>(
585        &self,
586        predicate: P,
587        e: ErrorKind,
588    ) -> IResult<Self, Self, E>
589    where
590        P: Fn(Self::Item) -> bool,
591    {
592        match self.fragment.position(predicate) {
593            Some(0) => Err(Err::Error(E::from_error_kind(self.clone(), e))),
594            Some(n) => Ok(self.take_split(n)),
595            None => Err(Err::Incomplete(nom::Needed::new(1))),
596        }
597    }
598
599    fn split_at_position1_complete<P, E: ParseError<Self>>(
600        &self,
601        predicate: P,
602        e: ErrorKind,
603    ) -> IResult<Self, Self, E>
604    where
605        P: Fn(Self::Item) -> bool,
606    {
607        match self.fragment.position(predicate) {
608            Some(0) => Err(Err::Error(E::from_error_kind(self.clone(), e))),
609            Some(n) => Ok(self.take_split(n)),
610            None => {
611                if self.fragment.input_len() == 0 {
612                    Err(Err::Error(E::from_error_kind(self.clone(), e)))
613                } else {
614                    Ok(self.take_split(self.input_len()))
615                }
616            }
617        }
618    }
619}
620
621#[macro_export]
622#[deprecated(
623    since = "3.1.0",
624    note = "this implementation has been generalized and no longer requires a macro"
625)]
626macro_rules! impl_input_iter {
627    () => {};
628}
629
630impl<'a, T, X> InputIter for LocatedSpan<T, X>
631where
632    T: InputIter,
633{
634    type Item = T::Item;
635    type Iter = T::Iter;
636    type IterElem = T::IterElem;
637    #[inline]
638    fn iter_indices(&self) -> Self::Iter {
639        self.fragment.iter_indices()
640    }
641    #[inline]
642    fn iter_elements(&self) -> Self::IterElem {
643        self.fragment.iter_elements()
644    }
645    #[inline]
646    fn position<P>(&self, predicate: P) -> Option<usize>
647    where
648        P: Fn(Self::Item) -> bool,
649    {
650        self.fragment.position(predicate)
651    }
652    #[inline]
653    fn slice_index(&self, count: usize) -> Result<usize, nom::Needed> {
654        self.fragment.slice_index(count)
655    }
656}
657
658impl<A: Compare<B>, B: Into<LocatedSpan<B>>, X> Compare<B> for LocatedSpan<A, X> {
659    #[inline(always)]
660    fn compare(&self, t: B) -> CompareResult {
661        self.fragment.compare(t.into().fragment)
662    }
663
664    #[inline(always)]
665    fn compare_no_case(&self, t: B) -> CompareResult {
666        self.fragment.compare_no_case(t.into().fragment)
667    }
668}
669
670#[macro_export]
671#[deprecated(
672    since = "2.1.0",
673    note = "this implementation has been generalized and no longer requires a macro"
674)]
675macro_rules! impl_compare {
676    ( $fragment_type:ty, $compare_to_type:ty ) => {};
677}
678
679#[macro_export]
680#[deprecated(
681    since = "3.1.0",
682    note = "this implementation has been generalized and no longer requires a macro"
683)]
684macro_rules! impl_slice_range {
685    ( $fragment_type:ty, $range_type:ty, $can_return_self:expr ) => {};
686}
687
688#[macro_export]
689#[deprecated(
690    since = "3.1.0",
691    note = "this implementation has been generalized and no longer requires a macro"
692)]
693macro_rules! impl_slice_ranges {
694    ( $fragment_type:ty ) => {};
695}
696
697impl<'a, T, R, X: Clone> Slice<R> for LocatedSpan<T, X>
698where
699    T: Slice<R> + Offset + AsBytes + Slice<RangeTo<usize>>,
700{
701    fn slice(&self, range: R) -> Self {
702        let next_fragment = self.fragment.slice(range);
703        let consumed_len = self.fragment.offset(&next_fragment);
704        if consumed_len == 0 {
705            return LocatedSpan {
706                line: self.line,
707                offset: self.offset,
708                fragment: next_fragment,
709                extra: self.extra.clone(),
710            };
711        }
712
713        let consumed = self.fragment.slice(..consumed_len);
714
715        let next_offset = self.offset + consumed_len;
716
717        let consumed_as_bytes = consumed.as_bytes();
718        let iter = Memchr::new(b'\n', consumed_as_bytes);
719        let number_of_lines = iter.count() as u32;
720        let next_line = self.line + number_of_lines;
721
722        LocatedSpan {
723            line: next_line,
724            offset: next_offset,
725            fragment: next_fragment,
726            extra: self.extra.clone(),
727        }
728    }
729}
730
731impl<Fragment: FindToken<Token>, Token, X> FindToken<Token> for LocatedSpan<Fragment, X> {
732    fn find_token(&self, token: Token) -> bool {
733        self.fragment.find_token(token)
734    }
735}
736
737impl<T, U, X> FindSubstring<U> for LocatedSpan<T, X>
738where
739    T: FindSubstring<U>,
740{
741    #[inline]
742    fn find_substring(&self, substr: U) -> Option<usize> {
743        self.fragment.find_substring(substr)
744    }
745}
746
747impl<R: FromStr, T, X> ParseTo<R> for LocatedSpan<T, X>
748where
749    T: ParseTo<R>,
750{
751    #[inline]
752    fn parse_to(&self) -> Option<R> {
753        self.fragment.parse_to()
754    }
755}
756
757impl<T, X> Offset for LocatedSpan<T, X> {
758    fn offset(&self, second: &Self) -> usize {
759        let fst = self.offset;
760        let snd = second.offset;
761
762        snd - fst
763    }
764}
765
766#[cfg(feature = "alloc")]
767impl<T: ToString, X> Display for LocatedSpan<T, X> {
768    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
769        fmt.write_str(&self.fragment.to_string())
770    }
771}
772
773#[macro_export]
774#[deprecated(
775    since = "3.1.0",
776    note = "this implementation has been generalized and no longer requires a macro"
777)]
778macro_rules! impl_extend_into {
779    ($fragment_type:ty, $item:ty, $extender:ty) => {
780        impl<'a, X> ExtendInto for LocatedSpan<$fragment_type, X> {
781            type Item = $item;
782            type Extender = $extender;
783
784            #[inline]
785            fn new_builder(&self) -> Self::Extender {
786                self.fragment.new_builder()
787            }
788
789            #[inline]
790            fn extend_into(&self, acc: &mut Self::Extender) {
791                self.fragment.extend_into(acc)
792            }
793        }
794    };
795}
796
797#[cfg(feature = "alloc")]
798impl<'a, T, X> ExtendInto for LocatedSpan<T, X>
799where
800    T: ExtendInto,
801{
802    type Item = T::Item;
803    type Extender = T::Extender;
804
805    #[inline]
806    fn new_builder(&self) -> Self::Extender {
807        self.fragment.new_builder()
808    }
809
810    #[inline]
811    fn extend_into(&self, acc: &mut Self::Extender) {
812        self.fragment.extend_into(acc)
813    }
814}
815
816#[cfg(feature = "std")]
817#[macro_export]
818#[deprecated(
819    since = "2.1.0",
820    note = "this implementation has been generalized and no longer requires a macro"
821)]
822macro_rules! impl_hex_display {
823    ($fragment_type:ty) => {};
824}
825
826/// Capture the position of the current fragment
827#[macro_export]
828macro_rules! position {
829    ($input:expr,) => {
830        tag!($input, "")
831    };
832}
833
834/// Capture the position of the current fragment
835pub fn position<T, E>(s: T) -> IResult<T, T, E>
836where
837    E: ParseError<T>,
838    T: InputIter + InputTake,
839{
840    nom::bytes::complete::take(0usize)(s)
841}