diff --git a/Cargo.toml b/Cargo.toml index 45b0edbc..9e31ef7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,9 +55,9 @@ spmc = "0.2" url = "1.0" #tokio-fs = "0.1" #tokio-mockstream = "1.1.0" -#serde = "1.0" -#serde_derive = "1.0" -#serde_json = "1.0" +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" [features] default = [ diff --git a/examples/client_json.rs b/examples/client_json.rs index 180306ac..861e6db1 100644 --- a/examples/client_json.rs +++ b/examples/client_json.rs @@ -1,3 +1,4 @@ +#![feature(async_await)] #![deny(warnings)] extern crate hyper; #[macro_use] @@ -6,56 +7,35 @@ extern crate serde; extern crate serde_json; use hyper::Client; -use hyper::rt::{self, Future, Stream}; +use futures_util::TryStreamExt; -fn main() { +// A simple type alias so as to DRY. +type Result = std::result::Result>; + +#[hyper::rt::main] +async fn main() -> Result<()> { let url = "http://jsonplaceholder.typicode.com/users".parse().unwrap(); + let users = fetch_json(url).await?; + // print users + println!("users: {:#?}", users); - let fut = fetch_json(url) - // use the parsed vector - .map(|users| { - // print users - println!("users: {:#?}", users); - - // print the sum of ids - let sum = users.iter().fold(0, |acc, user| acc + user.id); - println!("sum of ids: {}", sum); - }) - // if there was an error print it - .map_err(|e| { - match e { - FetchError::Http(e) => eprintln!("http error: {}", e), - FetchError::Json(e) => eprintln!("json parsing error: {}", e), - } - }); - - // Run the runtime with the future trying to fetch, parse and print json. - // - // Note that in more complicated use cases, the runtime should probably - // run on its own, and futures should just be spawned into it. - rt::run(fut); + // print the sum of ids + let sum = users.iter().fold(0, |acc, user| acc + user.id); + println!("sum of ids: {}", sum); + Ok(()) } -fn fetch_json(url: hyper::Uri) -> impl Future, Error=FetchError> { +async fn fetch_json(url: hyper::Uri) -> Result> { let client = Client::new(); - client - // Fetch the url... - .get(url) - // And then, if we get a response back... - .and_then(|res| { - // asynchronously concatenate chunks of the body - res.into_body().concat2() - }) - .from_err::() - // use the body after concatenation - .and_then(|body| { - // try to parse as json with serde_json - let users = serde_json::from_slice(&body)?; + // Fetch the url... + let res = client.get(url).await?; + // asynchronously concatenate chunks of the body + let body = res.into_body().try_concat().await?; + // try to parse as json with serde_json + let users = serde_json::from_slice(&body)?; - Ok(users) - }) - .from_err() + Ok(users) } #[derive(Deserialize, Debug)] @@ -63,21 +43,3 @@ struct User { id: i32, name: String, } - -// Define a type so we can return multiple types of errors -enum FetchError { - Http(hyper::Error), - Json(serde_json::Error), -} - -impl From for FetchError { - fn from(err: hyper::Error) -> FetchError { - FetchError::Http(err) - } -} - -impl From for FetchError { - fn from(err: serde_json::Error) -> FetchError { - FetchError::Json(err) - } -}