Repository: pest-parser/pest (language: rust)

Issue:
Make error message accessible
Currently the `Error::message` function is private. If one wants to expose custom errors from pest it seems useful to be able to access this conveniently.

What about making it public and return a `Message<'a>` object that implements `fmt::Display`?


Discussion / hints:
As is, `Error::message` returns a `String`. Instead of making `Error::message` public, a better solution would probably be to move this functionality to `ErrorVariant` and return a `String`. Having a specialized type doesn't seem to be useful in `ErrorVariant`'s current form, since `String` implements `fmt::Display`.
I don't mind it returning a `String` directly but I think it could in theory be optimized for some cases.

Fix patch:
diff --git a/pest/src/error.rs b/pest/src/error.rs
index d6b76a82..41a10b64 100644
--- a/pest/src/error.rs
+++ b/pest/src/error.rs
@@ -13,6 +13,7 @@ use std::cmp;
 use std::error;
 use std::fmt;
 use std::mem;
+use std::borrow::Cow;
 
 use position::Position;
 use span::Span;
@@ -314,13 +315,7 @@ impl<R: RuleType> Error<R> {
     }
 
     fn message(&self) -> String {
-        match self.variant {
-            ErrorVariant::ParsingError {
-                ref positives,
-                ref negatives,
-            } => Error::parsing_error_message(positives, negatives, |r| format!("{:?}", r)),
-            ErrorVariant::CustomError { ref message } => message.clone(),
-        }
+        self.variant.message().to_string()
     }
 
     fn parsing_error_message<F>(positives: &[R], negatives: &[R], mut f: F) -> String
@@ -431,6 +426,40 @@ impl<R: RuleType> Error<R> {
     }
 }
 
+impl<R: RuleType> ErrorVariant<R> {
+    ///
+    /// Returns the error message for [`ErrorVariant`]
+    ///
+    /// If [`ErrorVariant`] is [`CustomError`], it returns a 
+    /// [`Cow::Borrowed`] reference to [`message`]. If [`ErrorVariant`] is [`ParsingError`], a
+    /// [`Cow::Owned`] containing "expected [positives] [negatives]" is returned. 
+    ///
+    /// [`ErrorVariant`]: enum.ErrorVariant.html
+    /// [`CustomError`]: enum.ErrorVariant.html#variant.CustomError
+    /// [`ParsingError`]: enum.ErrorVariant.html#variant.ParsingError
+    /// [`Cow::Owned`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html#variant.Owned
+    /// [`Cow::Borrowed`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html#variant.Borrowed
+    /// [`message`]: enum.ErrorVariant.html#variant.CustomError.field.message
+    /// # Examples
+    ///
+    /// ```
+    /// # use pest::error::ErrorVariant;
+    /// let variant = ErrorVariant::CustomError {
+    ///     message: String::from("unexpected error")
+    /// };
+    ///
+    /// println!("{}", variant.message());
+    pub fn message(&self) -> Cow<str> {
+        match self {
+            ErrorVariant::ParsingError {
+                ref positives,
+                ref negatives,
+            } => Cow::Owned(Error::parsing_error_message(positives, negatives, |r| format!("{:?}", r))),
+            ErrorVariant::CustomError { ref message } => Cow::Borrowed(message),
+        }
+    }
+}
+
 impl<R: RuleType> fmt::Display for Error<R> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{}", self.format())


Test patch: