From 678d254a06dbb75f5398abaacee41d1712bf7194 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 5 Apr 2020 15:53:15 +0100 Subject: Make Deserializer functions the only functions --- serde_dhall/src/deserialize.rs | 2 +- serde_dhall/src/lib.rs | 25 ++-- serde_dhall/src/options.rs | 29 +++-- serde_dhall/src/shortcuts.rs | 272 ----------------------------------------- serde_dhall/src/static_type.rs | 4 +- serde_dhall/src/value.rs | 6 +- serde_dhall/tests/de.rs | 10 +- serde_dhall/tests/traits.rs | 2 +- 8 files changed, 36 insertions(+), 314 deletions(-) delete mode 100644 serde_dhall/src/shortcuts.rs (limited to 'serde_dhall') diff --git a/serde_dhall/src/deserialize.rs b/serde_dhall/src/deserialize.rs index 1be68c4..92be2e9 100644 --- a/serde_dhall/src/deserialize.rs +++ b/serde_dhall/src/deserialize.rs @@ -30,7 +30,7 @@ pub trait Sealed {} /// } /// /// // Convert a Dhall string to a Point. -/// let point: Point = serde_dhall::from_str("{ x = 1, y = 1 + 1 }")?; +/// let point: Point = serde_dhall::from_str("{ x = 1, y = 1 + 1 }").parse()?; /// # Ok(()) /// # } /// ``` diff --git a/serde_dhall/src/lib.rs b/serde_dhall/src/lib.rs index 9f99adb..8ad7cb3 100644 --- a/serde_dhall/src/lib.rs +++ b/serde_dhall/src/lib.rs @@ -30,7 +30,7 @@ //! let data = "{ x = 1, y = 1 + 1 } : { x: Natural, y: Natural }"; //! //! // Deserialize it to a Rust type. -//! let deserialized_map: HashMap = serde_dhall::from_str(data)?; +//! let deserialized_map: HashMap = serde_dhall::from_str(data).parse()?; //! //! let mut expected_map = HashMap::new(); //! expected_map.insert("x".to_string(), 1); @@ -57,7 +57,7 @@ //! let data = "{ x = 1, y = 1 + 1 } : { x: Natural, y: Natural }"; //! //! // Convert the Dhall string to a Point. -//! let point: Point = serde_dhall::from_str(data)?; +//! let point: Point = serde_dhall::from_str(data).parse()?; //! assert_eq!(point.x, 1); //! assert_eq!(point.y, 2); //! @@ -68,7 +68,7 @@ //! # Replacing `serde_json` or `serde_yaml` //! //! If you used to consume JSON or YAML, you only need to replace [`serde_json::from_str`] or -//! [`serde_yaml::from_str`] with [`serde_dhall::from_str`](fn.from_str.html). +//! [`serde_yaml::from_str`] with [`serde_dhall::from_str(…).parse()`](fn.from_str.html). //! //! [`serde_json::from_str`]: https://docs.serde.rs/serde_json/fn.from_str.html //! [`serde_yaml::from_str`]: https://docs.serde.rs/serde_yaml/fn.from_str.html @@ -103,13 +103,13 @@ //! let data = "{ x = 1, y = 1 + 1 }"; //! //! // Convert the Dhall string to a Point. -//! let point: Point = serde_dhall::from_str_static_type(data)?; +//! let point: Point = serde_dhall::from_str(data).static_type_annotation().parse()?; //! assert_eq!(point.x, 1); //! assert_eq!(point.y, 2); //! //! // Invalid data fails the type validation //! let invalid_data = "{ x = 1, z = 0.3 }"; -//! assert!(serde_dhall::from_str_static_type::(invalid_data).is_err()); +//! assert!(serde_dhall::from_str::(invalid_data).static_type_annotation().parse().is_err()); //! # Ok(()) //! # } //! ``` @@ -124,7 +124,7 @@ //! //! // Parse a Dhall type //! let point_type_str = "{ x: Natural, y: Natural }"; -//! let point_type: SimpleType = serde_dhall::from_str(point_type_str)?; +//! let point_type: SimpleType = serde_dhall::from_str(point_type_str).parse()?; //! //! // Some Dhall data //! let point_data = "{ x = 1, y = 1 + 1 }"; @@ -132,7 +132,7 @@ //! // Deserialize the data to a Rust type. This checks that //! // the data matches the provided type. //! let deserialized_map: HashMap = -//! serde_dhall::from_str_manual_type(point_data, &point_type)?; +//! serde_dhall::from_str(point_data).type_annotation(&point_type).parse()?; //! //! let mut expected_map = HashMap::new(); //! expected_map.insert("x".to_string(), 1); @@ -158,13 +158,9 @@ mod test_readme { doc_comment::doctest!("../../README.md"); } -/// Finer-grained control over deserializing Dhall values -pub mod options; - +mod options; mod deserialize; mod error; -/// Common patterns made easier -mod shortcuts; mod static_type; /// Dhall values mod value; @@ -176,9 +172,8 @@ pub use deserialize::FromDhall; pub(crate) use deserialize::Sealed; pub(crate) use error::ErrorKind; pub use error::{Error, Result}; -pub use shortcuts::{ - from_file, from_file_manual_type, from_file_static_type, from_str, - from_str_manual_type, from_str_static_type, +pub use options::{ + from_file, from_str, Deserializer }; pub use static_type::StaticType; pub use value::{SimpleType, Value}; diff --git a/serde_dhall/src/options.rs b/serde_dhall/src/options.rs index f3797ee..c44de90 100644 --- a/serde_dhall/src/options.rs +++ b/serde_dhall/src/options.rs @@ -27,9 +27,9 @@ enum Source<'a> { /// /// ```no_run /// # fn main() -> serde_dhall::Result<()> { -/// use serde_dhall::options; +/// use serde_dhall::from_file; /// -/// let data = options::from_file("foo.dhall").parse()?; +/// let data = from_file("foo.dhall").parse()?; /// # Ok(()) /// # } /// ``` @@ -38,10 +38,10 @@ enum Source<'a> { /// /// ```no_run /// # fn main() -> serde_dhall::Result<()> { -/// use serde_dhall::options; +/// use serde_dhall::{from_file, from_str}; /// -/// let ty = options::from_str("{ x: Natural, y: Natural }").parse()?; -/// let data = options::from_file("foo.dhall") +/// let ty = from_str("{ x: Natural, y: Natural }").parse()?; +/// let data = from_file("foo.dhall") /// .type_annotation(&ty) /// .parse()?; /// # Ok(()) @@ -91,7 +91,7 @@ impl<'a, T> Deserializer<'a, T> { /// /// let data = "12 + ./other_file.dhall : Natural"; /// assert!( - /// serde_dhall::options::from_str::(data) + /// serde_dhall::from_str::(data) /// .imports(false) /// .parse() /// .is_err() @@ -136,11 +136,11 @@ impl<'a, T> Deserializer<'a, T> { /// /// // Parse a Dhall type /// let point_type_str = "{ x: Natural, y: Optional Natural }"; - /// let point_type: SimpleType = serde_dhall::options::from_str(point_type_str).parse()?; + /// let point_type: SimpleType = serde_dhall::from_str(point_type_str).parse()?; /// /// // Parse some Dhall data to a Point. /// let data = "{ x = 1, y = Some (1 + 1) }"; - /// let point: Point = serde_dhall::options::from_str(data) + /// let point: Point = serde_dhall::from_str(data) /// .type_annotation(&point_type) /// .parse()?; /// assert_eq!(point.x, 1); @@ -149,7 +149,7 @@ impl<'a, T> Deserializer<'a, T> { /// // Invalid data fails the type validation; deserialization would have succeeded otherwise. /// let invalid_data = "{ x = 1 }"; /// assert!( - /// serde_dhall::options::from_str::(invalid_data) + /// serde_dhall::from_str::(invalid_data) /// .type_annotation(&point_type) /// .parse() /// .is_err() @@ -187,7 +187,7 @@ impl<'a, T> Deserializer<'a, T> { /// let data = "{ x = 1, y = Some (1 + 1) }"; /// /// // Convert the Dhall string to a Point. - /// let point: Point = serde_dhall::options::from_str(data) + /// let point: Point = serde_dhall::from_str(data) /// .static_type_annotation() /// .parse()?; /// assert_eq!(point.x, 1); @@ -196,7 +196,7 @@ impl<'a, T> Deserializer<'a, T> { /// // Invalid data fails the type validation; deserialization would have succeeded otherwise. /// let invalid_data = "{ x = 1 }"; /// assert!( - /// serde_dhall::options::from_str::(invalid_data) + /// serde_dhall::from_str::(invalid_data) /// .static_type_annotation() /// .parse() /// .is_err() @@ -240,8 +240,7 @@ impl<'a, T> Deserializer<'a, T> { /// /// ```no_run /// # fn main() -> serde_dhall::Result<()> { - /// use serde_dhall::options; - /// let data = options::from_file("foo.dhall").parse()?; + /// let data = serde_dhall::from_file("foo.dhall").parse()?; /// # Ok(()) /// # } /// ``` @@ -276,7 +275,7 @@ impl<'a, T> Deserializer<'a, T> { /// let data = "{ x = 1, y = 1 + 1 } : { x: Natural, y: Natural }"; /// /// // Parse the Dhall string as a Point. -/// let point: Point = serde_dhall::options::from_str(data).parse()?; +/// let point: Point = serde_dhall::from_str(data).parse()?; /// /// assert_eq!(point.x, 1); /// assert_eq!(point.y, 2); @@ -309,7 +308,7 @@ pub fn from_str(s: &str) -> Deserializer<'_, T> { /// } /// /// // Parse the Dhall file as a Point. -/// let point: Point = serde_dhall::options::from_file("foo.dhall").parse()?; +/// let point: Point = serde_dhall::from_file("foo.dhall").parse()?; /// # Ok(()) /// # } /// ``` diff --git a/serde_dhall/src/shortcuts.rs b/serde_dhall/src/shortcuts.rs deleted file mode 100644 index 9c9ce9f..0000000 --- a/serde_dhall/src/shortcuts.rs +++ /dev/null @@ -1,272 +0,0 @@ -use doc_comment::doc_comment; -use std::path::Path; - -use crate::{options, FromDhall, Result, SimpleType, StaticType}; - -// Avoid copy-pasting documentation - -#[rustfmt::skip] -macro_rules! gen_doc { - (@source_desc, str) => {"a string of Dhall text"}; - (@source_desc, file) => {"a Dhall file"}; - (@source_desc, url) => {"a remote url"}; - - (@tck_info1, none) => {""}; - (@tck_info1, manual) => {", additionally checking that it matches the supplied type"}; - (@tck_info1, static) => {", additionally checking that it matches the type of `T`"}; - - (@tck_info2, none) => {""}; - (@tck_info2, manual) => {" against the supplied type"}; - (@tck_info2, static) => {" against the type of `T`"}; - - (@tck_req, $src:tt, none) => {""}; - (@tck_req, $src:tt, manual) => {""}; - (@tck_req, $src:tt, static) => { - concat!("`T` must implement the [`StaticType`] trait. Use [`from_", stringify!($src), - "_manual_type`] to provide a type manually.\n") - }; - - (@tck_comment, $src:tt, none) => { - concat!("For additional type safety, prefer [`from_", stringify!($src), "_static_type`] - or [`from_", stringify!($src), "_manual_type`].\n") - }; - (@tck_comment, $src:tt, manual) => {concat!("See also [`from_", stringify!($src), "_static_type`].\n")}; - (@tck_comment, $src:tt, static) => {""}; - - (@run_example, str) => {""}; - (@run_example, file) => {"no_run"}; - (@run_example, url) => {"no_run"}; - - ($src:tt, $ty:tt) => {concat!(" -Deserialize an instance of type `T` from ", gen_doc!(@source_desc, $src), gen_doc!(@tck_info1, $ty),". - -", gen_doc!(@tck_req, $src, $ty), " -This will recursively resolve all imports in the expression, and typecheck it", gen_doc!(@tck_info2, $ty)," -before deserialization. Relative imports will be resolved relative to the current directory. -See [`options`] for more control over this process. - -", gen_doc!(@tck_comment, $src, $ty), " - -# Example - -```", gen_doc!(@run_example, $src), " -# fn main() -> serde_dhall::Result<()> {", -gen_example!($src, $ty), " -# Ok(()) -# } -``` - -[`options`]: options/index.html -[`from_", stringify!($src), "_manual_type`]: fn.from_", stringify!($src), "_manual_type.html -[`from_", stringify!($src), "_static_type`]: fn.from_", stringify!($src), "_static_type.html -[`StaticType`]: trait.StaticType.html -")}; -} - -#[rustfmt::skip] -macro_rules! gen_example { - (str, none) => {concat!(r#" -use serde::Deserialize; - -// We use serde's derive feature -#[derive(Deserialize)] -struct Point { - x: u64, - y: u64, -} - -// Some Dhall data -let data = "{ x = 1, y = 1 + 1 } : { x: Natural, y: Natural }"; - -// Parse the Dhall string as a Point. -let point: Point = serde_dhall::from_str(data)?; - -assert_eq!(point.x, 1); -assert_eq!(point.y, 2); -"#)}; - - (str, manual) => {concat!(r#" -use std::collections::HashMap; -use serde_dhall::SimpleType; - -// Parse a Dhall type -let point_type_str = "{ x: Natural, y: Natural }"; -let point_type: SimpleType = serde_dhall::from_str(point_type_str)?; - -// Some Dhall data -let point_data = "{ x = 1, y = 1 + 1 }"; - -// Deserialize the data to a Rust type. This checks that -// the data matches the provided type. -let deserialized_map: HashMap = - serde_dhall::from_str_manual_type(point_data, &point_type)?; - -let mut expected_map = HashMap::new(); -expected_map.insert("x".to_string(), 1); -expected_map.insert("y".to_string(), 2); - -assert_eq!(deserialized_map, expected_map); -"#)}; - - (str, static) => {concat!(r#" -use serde::Deserialize; -use serde_dhall::StaticType; - -#[derive(Deserialize, StaticType)] -struct Point { - x: u64, - y: u64, -} - -// Some Dhall data -let data = "{ x = 1, y = 1 + 1 }"; - -// Convert the Dhall string to a Point. -let point: Point = serde_dhall::from_str_static_type(data)?; -assert_eq!(point.x, 1); -assert_eq!(point.y, 2); - -// Invalid data fails the type validation -let invalid_data = "{ x = 1, z = 0.3 }"; -assert!(serde_dhall::from_str_static_type::(invalid_data).is_err()); -"#)}; - - (file, none) => {concat!(r#" -use serde::Deserialize; - -// We use serde's derive feature -#[derive(Deserialize)] -struct Point { - x: u64, - y: u64, -} - -// Parse the Dhall file as a Point. -let point: Point = serde_dhall::from_file("foo.dhall")?; -"#)}; - - (file, manual) => {concat!(r#" -use std::collections::HashMap; -use serde_dhall::SimpleType; - -// Parse a Dhall type -let point_type_str = "{ x: Natural, y: Natural }"; -let point_type: SimpleType = serde_dhall::from_str(point_type_str)?; - -// Deserialize the data to a Rust type. This checks that -// the data matches the provided type. -let deserialized_map: HashMap = - serde_dhall::from_file_manual_type("foo.dhall", &point_type)?; -"#)}; - - (file, static) => {concat!(r#" -use serde::Deserialize; -use serde_dhall::StaticType; - -#[derive(Deserialize, StaticType)] -struct Point { - x: u64, - y: u64, -} - -// Convert the Dhall string to a Point. -let point: Point = serde_dhall::from_file_static_type("foo.dhall")?; -"#)}; - - ($src:tt, $ty:tt) => {""}; -} - -macro_rules! generate_fn { - (@generate_src, - str, $ty:tt, $name:ident, - ) => { - generate_fn!(@generate_ty, - str, $ty, $name, - (), - (s: &str), - (options::from_str(s)), - ); - }; - (@generate_src, - file, $ty:tt, $name:ident, - ) => { - generate_fn!(@generate_ty, - file, $ty, $name, - (P: AsRef), - (path: P), - (options::from_file(path)), - ); - }; - - (@generate_ty, - $src:tt, none, $name:ident, - ($($ty_params:tt)*), - ($($input_args:tt)*), - ($($create_options:tt)*), - ) => { - generate_fn!(@generate, - $src, none, $name, - ($($ty_params)*), - ($($input_args)*), - (), - ($($create_options)*), - ); - }; - (@generate_ty, - $src:tt, manual, $name:ident, - ($($ty_params:tt)*), - ($($input_args:tt)*), - ($($create_options:tt)*), - ) => { - generate_fn!(@generate, - $src, manual, $name, - ($($ty_params)*), - ($($input_args)*, ty: &SimpleType), - (), - ($($create_options)* .type_annotation(ty)), - ); - }; - (@generate_ty, - $src:tt, static, $name:ident, - ($($ty_params:tt)*), - ($($input_args:tt)*), - ($($create_options:tt)*), - ) => { - generate_fn!(@generate, - $src, static, $name, - ($($ty_params)*), - ($($input_args)*), - (+ StaticType), - ($($create_options)* .static_type_annotation()), - ); - }; - - (@generate, - $src:tt, $ty:tt, $name:ident, - ($($ty_params:tt)*), - ($($input_args:tt)*), - ($($extra_bounds:tt)*), - ($($create_options:tt)*), - ) => { - doc_comment! { - gen_doc!($src, $ty), - pub fn $name ($($input_args)*) -> Result - where - T: FromDhall $($extra_bounds)*, - { - $($create_options)* .parse() - } - } - }; - - ($src:tt, $ty:tt, $name:ident) => { - generate_fn!(@generate_src, $src, $ty, $name,); - }; -} - -generate_fn!(str, none, from_str); -generate_fn!(str, manual, from_str_manual_type); -generate_fn!(str, static, from_str_static_type); -generate_fn!(file, none, from_file); -generate_fn!(file, manual, from_file_manual_type); -generate_fn!(file, static, from_file_static_type); diff --git a/serde_dhall/src/static_type.rs b/serde_dhall/src/static_type.rs index 020dfce..6e76424 100644 --- a/serde_dhall/src/static_type.rs +++ b/serde_dhall/src/static_type.rs @@ -23,7 +23,7 @@ use crate::SimpleType; /// } /// /// let ty: SimpleType = -/// serde_dhall::from_str("{ x: Bool, y: List Natural }")?; +/// serde_dhall::from_str("{ x: Bool, y: List Natural }").parse()?; /// /// assert_eq!(Foo::static_type(), ty); /// # Ok(()) @@ -71,7 +71,7 @@ pub trait StaticType { /// } /// } /// - /// let foo: Foo = serde_dhall::from_str_static_type("[ 1, 2 ]")?; + /// let foo: Foo = serde_dhall::from_str("[ 1, 2 ]").static_type_annotation().parse()?; /// /// assert_eq!(foo.0, vec![1, 2]); /// # Ok(()) diff --git a/serde_dhall/src/value.rs b/serde_dhall/src/value.rs index ea7c20a..f21e836 100644 --- a/serde_dhall/src/value.rs +++ b/serde_dhall/src/value.rs @@ -28,7 +28,7 @@ pub(crate) enum SimpleValue { Union(String, Option>), } -/// The type of a value that can be decoded by Serde, like `{ x: Bool, y: List Natural }`. +/// The type of a value that can be decoded by Serde, e.g. `{ x: Bool, y: List Natural }`. /// /// A `SimpleType` is used when deserializing values to ensure they are of the expected type. /// Rather than letting `serde` handle potential type mismatches, this uses the type-checking @@ -53,7 +53,7 @@ pub(crate) enum SimpleValue { /// use serde_dhall::SimpleType; /// /// let ty: SimpleType = -/// serde_dhall::from_str("{ x: Natural, y: Natural }")?; +/// serde_dhall::from_str("{ x: Natural, y: Natural }").parse()?; /// /// let mut map = HashMap::new(); /// map.insert("x".to_string(), SimpleType::Natural); @@ -74,7 +74,7 @@ pub(crate) enum SimpleValue { /// } /// /// let ty: SimpleType = -/// serde_dhall::from_str("{ x: Bool, y: List Natural }")?; +/// serde_dhall::from_str("{ x: Bool, y: List Natural }").parse()?; /// /// assert_eq!(Foo::static_type(), ty); /// # Ok(()) diff --git a/serde_dhall/tests/de.rs b/serde_dhall/tests/de.rs index b9a504a..970234b 100644 --- a/serde_dhall/tests/de.rs +++ b/serde_dhall/tests/de.rs @@ -1,10 +1,10 @@ use serde::Deserialize; -use serde_dhall::{from_str, from_str_static_type, FromDhall, StaticType}; +use serde_dhall::{from_str, FromDhall, StaticType}; #[test] fn test_de_typed() { fn parse(s: &str) -> T { - from_str_static_type(s).unwrap() + from_str(s).static_type_annotation().parse().unwrap() } assert_eq!(parse::("True"), true); @@ -52,13 +52,13 @@ fn test_de_typed() { } assert_eq!(parse::("< X | Y: Integer >.X"), Baz::X); - assert!(from_str_static_type::("< X | Y: Integer >.Y").is_err()); + assert!(from_str::("< X | Y: Integer >.Y").static_type_annotation().parse().is_err()); } #[test] fn test_de_untyped() { fn parse(s: &str) -> T { - from_str(s).unwrap() + from_str(s).parse().unwrap() } // Test tuples on record of wrong type @@ -94,5 +94,5 @@ fn test_de_untyped() { assert_eq!(parse::("{ x = 1 }"), Foo { x: 1, y: None }); // https://github.com/Nadrieril/dhall-rust/issues/155 - assert!(from_str::("List/length [True, 42]").is_err()); + assert!(from_str::("List/length [True, 42]").parse().is_err()); } diff --git a/serde_dhall/tests/traits.rs b/serde_dhall/tests/traits.rs index 608e6ed..3c6fbfe 100644 --- a/serde_dhall/tests/traits.rs +++ b/serde_dhall/tests/traits.rs @@ -3,7 +3,7 @@ use serde_dhall::{from_str, SimpleType, StaticType}; #[test] fn test_static_type() { fn parse(s: &str) -> SimpleType { - from_str(s).unwrap() + from_str(s).parse().unwrap() } assert_eq!(bool::static_type(), parse("Bool")); -- cgit v1.2.3