Merge pull request #1 from woody77/master

Add `from_slice` and `from_reader` helper fn's
diff --git a/third_party/src/de.rs b/third_party/src/de.rs
index f8dec3d..a1608be 100644
--- a/third_party/src/de.rs
+++ b/third_party/src/de.rs
@@ -6,6 +6,7 @@
 use std::char;
 use std::collections::VecDeque;
 use std::f64;
+use std::io::Read;
 
 use crate::error::{self, Error, Result};
 
@@ -148,6 +149,31 @@
     T::deserialize(&mut deserializer)
 }
 
+/// Deserialize an instance of type `T` from a slice of JSON5 text. Can fail if the input is
+/// invalid JSON5, or doesn’t match the structure of the target type.
+pub fn from_slice<'a, T>(s: &'a [u8]) -> Result<T>
+where
+    T: de::Deserialize<'a>,
+{
+    let valid_utf8 = std::str::from_utf8(s)?;
+    let mut deserializer = Deserializer::from_str(valid_utf8)?;
+    T::deserialize(&mut deserializer)
+}
+
+
+/// Deserialize an instance of type `T` from any implementation of Read.  Can fail if the input is
+/// invalid JSON5, or doesn&rsquo;t match the structure of the target type.
+pub fn from_reader<T, R>(reader: &mut R) -> Result<T>
+where
+    T: serde::de::DeserializeOwned,
+    R: Read
+{
+    let mut data = String::default();
+    reader.read_to_string(&mut data)?;
+    from_str(&data)
+}
+
+
 struct Deserializer<'de> {
     pair: Option<Pair<'de, Rule>>,
 }
diff --git a/third_party/src/error.rs b/third_party/src/error.rs
index 4da921c..162a780 100644
--- a/third_party/src/error.rs
+++ b/third_party/src/error.rs
@@ -47,6 +47,18 @@
     }
 }
 
+impl From<std::io::Error> for Error {
+    fn from(err: std::io::Error) -> Self {
+        Error::Message { msg: err.to_string(), location: None}
+    }
+}
+
+impl From<std::str::Utf8Error> for Error {
+    fn from(err: std::str::Utf8Error) -> Self {
+        Error::Message { msg: err.to_string(), location: None}
+    }
+}
+
 impl ser::Error for Error {
     fn custom<T: Display>(msg: T) -> Self {
         Error::Message { msg: msg.to_string(), location: None }
diff --git a/third_party/src/lib.rs b/third_party/src/lib.rs
index 310566d..ab8f153 100644
--- a/third_party/src/lib.rs
+++ b/third_party/src/lib.rs
@@ -122,6 +122,6 @@
 mod error;
 mod ser;
 
-pub use crate::de::from_str;
+pub use crate::de::{from_str, from_slice, from_reader};
 pub use crate::error::{Error, Location, Result};
 pub use crate::ser::to_string;
diff --git a/third_party/tests/de.rs b/third_party/tests/de.rs
index c980bcb..a76fa10 100644
--- a/third_party/tests/de.rs
+++ b/third_party/tests/de.rs
@@ -758,3 +758,43 @@
         make_error("invalid type: integer `42`, expected a boolean", 2, 2),
     );
 }
+
+#[test]
+fn test_from_str() {
+    #[derive(Deserialize, PartialEq, Debug)]
+    struct S {
+        a: i32,
+        b: i32,
+        c: i32,
+    }
+
+    let data = "{ a: 5, b: 4, c: 3}";
+    assert_eq!(serde_json5::from_str(data), Ok(S{ a: 5, b:4, c:3}))
+}
+
+#[test]
+fn test_from_slice() {
+    #[derive(Deserialize, PartialEq, Debug)]
+    struct S {
+        a: i32,
+        b: i32,
+        c: i32,
+    }
+
+    let data = "{ a: 5, b: 4, c: 3}".as_bytes();
+    assert_eq!(serde_json5::from_slice(data), Ok(S{ a: 5, b:4, c:3}))
+}
+
+#[test]
+fn test_from_reader() {
+    #[derive(Deserialize, PartialEq, Debug)]
+    struct S {
+        a: i32,
+        b: i32,
+        c: i32,
+    }
+
+    let data = "{ a: 5, b: 4, c: 3}";
+    let mut reader = std::io::Cursor::new(data);
+    assert_eq!(serde_json5::from_reader(&mut reader), Ok(S{ a: 5, b:4, c:3}))
+}
\ No newline at end of file