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