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}