Repository: pest-parser/pest (Rust)

Issue:
Unable to get Span without consuming Pair
If getting a Span consumes a Pair, I have to choose between getting that Span and getting its inner Pairs. This is counter intuitive given that the two don't really seem related. Sometimes I want to look further into the contents of a pair and also get its position. Can we add a `span(&self)` method (or something) to get the Span of a Pair and still allow you to get its inner Pairs afterwards?

I would be happy to create a PR for this. :smile: 


Discussion:
I guess it does make sense for `into_span` to be refactored to `as_span(&self)`. However, the current API let's you do what you want by simply cloning the `Pair` which is a cheap operation.
@dragostis The PR for this is ready: #224 :smile: :tada: 
Dito, the function "Pair::into_inner(self,..)" is consuming the pair. I would like to see a function in API just borrowing the pair, something like "Pair::into_inner(&self, ..)"

This issue was about `into_span`, which got `as_span`, which actually does save an Arc clone. However, `pair.clone().into_inner()` is the exact process that a non-consuming `Pair` to inner `Pairs` would do, so adding a function just for that seems not helpful. The API today encourages the consuming option, which is cheaper, if the outside `Pair` is unneeded afterwards, which results in better code (or at the very least, less optimization work for the compiler).



Patch:
diff --git a/README.md b/README.md
index 219d022d..94cd2ae6 100644
--- a/README.md
+++ b/README.md
@@ -60,14 +60,14 @@ fn main() {
     for pair in pairs {
         // A pair is a combination of the rule which matched and a span of input
         println!("Rule:    {:?}", pair.as_rule());
-        println!("Span:    {:?}", pair.clone().into_span());
-        println!("Text:    {}", pair.clone().into_span().as_str());
+        println!("Span:    {:?}", pair.as_span());
+        println!("Text:    {}", pair.as_span().as_str());
 
         // A pair can be converted to an iterator of the tokens which make it up:
         for inner_pair in pair.into_inner() {
             match inner_pair.as_rule() {
-                Rule::alpha => println!("Letter:  {}", inner_pair.into_span().as_str()),
-                Rule::digit => println!("Digit:   {}", inner_pair.into_span().as_str()), 
+                Rule::alpha => println!("Letter:  {}", inner_pair.as_span().as_str()),
+                Rule::digit => println!("Digit:   {}", inner_pair.as_span().as_str()),
                 _ => unreachable!()
             };
         }
diff --git a/grammars/benches/json.rs b/grammars/benches/json.rs
index e044a007..087f6039 100644
--- a/grammars/benches/json.rs
+++ b/grammars/benches/json.rs
@@ -46,13 +46,13 @@ fn consume(pair: Pair<Rule>) -> Json {
                 _ => unreachable!()
             },
             Rule::number => Json::Number(pair.as_str().parse().unwrap()),
-            Rule::string => Json::String(pair.into_span()),
+            Rule::string => Json::String(pair.as_span()),
             Rule::array => Json::Array(pair.into_inner().map(value).collect()),
             Rule::object => {
                 let pairs = pair.into_inner().map(|pos| {
                     let mut pair = pos.into_inner();
 
-                    let key = pair.next().unwrap().into_span();
+                    let key = pair.next().unwrap().as_span();
                     let value = value(pair.next().unwrap());
 
                     (key, value)
diff --git a/pest/src/iterators/pair.rs b/pest/src/iterators/pair.rs
index 1987cf3f..bb5153ed 100644
--- a/pest/src/iterators/pair.rs
+++ b/pest/src/iterators/pair.rs
@@ -102,6 +102,8 @@ impl<'i, R: RuleType> Pair<'i, R> {
 
     /// Returns the `Span` defined by the `Pair`, consuming it.
     ///
+    /// **Deprecated.** Please use `as_span` instead.
+    ///
     /// # Examples
     ///
     /// ```
@@ -122,7 +124,34 @@ impl<'i, R: RuleType> Pair<'i, R> {
     /// assert_eq!(pair.into_span().as_str(), "ab");
     /// ```
     #[inline]
+    #[deprecated(since="2.0.0", note="Please use `as_span` instead")]
     pub fn into_span(self) -> Span<'i> {
+        self.as_span()
+    }
+
+    /// Returns the `Span` defined by the `Pair`, **without** consuming it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use std::rc::Rc;
+    /// # use pest;
+    /// # #[allow(non_camel_case_types)]
+    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+    /// enum Rule {
+    ///     ab
+    /// }
+    ///
+    /// let input = "ab";
+    /// let pair = pest::state(input, |state| {
+    ///     // generating Token pair with Rule::ab ...
+    /// #     state.rule(Rule::ab, |s| s.match_string("ab"))
+    /// }).unwrap().next().unwrap();
+    ///
+    /// assert_eq!(pair.as_span().as_str(), "ab");
+    /// ```
+    #[inline]
+    pub fn as_span(&self) -> Span<'i> {
         let start = self.pos(self.start);
         let end = self.pos(self.pair());
 
@@ -207,7 +236,7 @@ impl<'i, R: RuleType> fmt::Debug for Pair<'i, R> {
             f,
             "Pair {{ rule: {:?}, span: {:?}, inner: {:?} }}",
             self.as_rule(),
-            self.clone().into_span(),
+            self.clone().as_span(),
             self.clone().into_inner()
         )
     }


Test patch:
diff --git a/pest/tests/json.rs b/pest/tests/json.rs
index 752e0066..e961682d 100644
--- a/pest/tests/json.rs
+++ b/pest/tests/json.rs
@@ -271,13 +271,13 @@ fn consume(pair: Pair<Rule>) -> Json {
                 _ => unreachable!()
             },
             Rule::number => Json::Number(pair.as_str().parse().unwrap()),
-            Rule::string => Json::String(pair.into_span()),
+            Rule::string => Json::String(pair.as_span()),
             Rule::array => Json::Array(pair.into_inner().map(value).collect()),
             Rule::object => {
                 let pairs = pair.into_inner().map(|pos| {
                     let mut pair = pos.into_inner();
 
-                    let key = pair.next().unwrap().into_span();
+                    let key = pair.next().unwrap().as_span();
                     let value = value(pair.next().unwrap());
 
                     (key, value)