asciidoc_parser/span/mod.rs
1// Adapted from nom-span, which comes with the following license:
2
3// Copyright 2023 Jules Guesnon
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the “Software”), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23use std::ops::Deref;
24
25/// Represents a subset of the overall UTF-8 input stream.
26///
27/// Annotated with 1-based line and column numbers relative to the
28/// beginning of the overall input stream.
29///
30/// Called `Span` because its [`data()`] member can be consumed
31/// to yield another `Span` with annotations for the end of the
32/// syntactic element in question.
33///
34/// ## How to use it?
35///
36/// Here is a basic example of how to create the input and how to retrieve all
37/// the informations you need.
38///
39/// ```
40/// # use asciidoc_parser::Span;
41/// #
42/// fn main() {
43/// let span = Span::new(r#"{"hello": "world 🙌"}"#);
44///
45/// assert_eq!(span.line(), 1);
46/// assert_eq!(span.col(), 1);
47/// assert_eq!(span.byte_offset(), 0);
48/// }
49/// ```
50///
51/// [`data()`]: Self::data
52#[derive(Clone, Copy, Debug, Eq, PartialEq)]
53pub struct Span<'src> {
54 data: &'src str,
55 line: usize,
56 col: usize,
57 offset: usize,
58}
59
60impl<'src> Span<'src> {
61 /// Create a new `Span` that describes an entire UTF-8 input stream.
62 pub const fn new(data: &'src str) -> Self {
63 Self {
64 data,
65 line: 1,
66 col: 1,
67 offset: 0,
68 }
69 }
70
71 /// Get the current line number.
72 pub fn line(&self) -> usize {
73 self.line
74 }
75
76 /// Get the current column number.
77 pub fn col(&self) -> usize {
78 self.col
79 }
80
81 /// Get the current byte offset.
82 pub fn byte_offset(&self) -> usize {
83 self.offset
84 }
85
86 /// Get the current data in the span.
87 pub fn data(&self) -> &'src str {
88 self.data
89 }
90}
91
92impl AsRef<str> for Span<'_> {
93 fn as_ref(&self) -> &str {
94 self.data
95 }
96}
97
98impl<'src> Deref for Span<'src> {
99 type Target = &'src str;
100
101 fn deref(&self) -> &Self::Target {
102 &self.data
103 }
104}
105
106// NOTE: The `Span` API is large. Only the public interface is implemented here.
107// The other modules referenced below implement additional APIs that are
108// available inside this crate only. (Exception: `Content` is defined here and
109// exported publicly.)
110
111mod discard;
112mod line;
113mod matched_item;
114mod primitives;
115mod r#slice;
116mod split;
117mod take;
118mod trim;
119
120pub(crate) use matched_item::MatchedItem;
121
122/// Any syntactic element can describe its location
123/// within the source material using this trait.
124pub trait HasSpan<'src> {
125 /// Return a [`Span`] describing the syntactic element's
126 /// location within the source string/file.
127 fn span(&self) -> Span<'src>;
128}