diff --git a/src/elastic/examples/custom_response.rs b/src/elastic/examples/custom_response.rs index 3c7a4069ce..580bd9e19e 100644 --- a/src/elastic/examples/custom_response.rs +++ b/src/elastic/examples/custom_response.rs @@ -35,7 +35,7 @@ struct Hit { // Implement `IsOk` for our custom `SearchResponse` so it can be used in the call to `into_response`. impl IsOk for SearchResponse { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(body)), _ => Ok(MaybeOkResponse::err(body)), diff --git a/src/elastic/src/client/responses/mod.rs b/src/elastic/src/client/responses/mod.rs index 8ed05b752e..d9887f66fa 100644 --- a/src/elastic/src/client/responses/mod.rs +++ b/src/elastic/src/client/responses/mod.rs @@ -24,8 +24,5 @@ pub use elastic_responses::bulk; pub mod prelude { /*! A glob import for convenience. */ - pub use super::{BulkErrorsResponse, BulkResponse, CommandResponse, DeleteResponse, GetResponse, IndicesExistsResponse, IndexResponse, PingResponse, SearchResponse, Shards, UpdateResponse}; - - pub use super::async::AsyncResponseBuilder; - pub use super::sync::SyncResponseBuilder; + pub use super::{AsyncResponseBuilder, SyncResponseBuilder, BulkErrorsResponse, BulkResponse, CommandResponse, DeleteResponse, GetResponse, IndexResponse, IndicesExistsResponse, PingResponse, SearchResponse, Shards, UpdateResponse}; } diff --git a/src/elastic/src/client/responses/parse.rs b/src/elastic/src/client/responses/parse.rs index 54141ac925..e71cec0fb3 100644 --- a/src/elastic/src/client/responses/parse.rs +++ b/src/elastic/src/client/responses/parse.rs @@ -18,7 +18,7 @@ struct MyResponse { } impl IsOk for MyResponse { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> where B: ResponseBody { match head.status() { @@ -48,7 +48,7 @@ The `MyResponse` type can then be used for deserialising a concrete response: # took: u64 # } # impl IsOk for MyResponse { -# fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> +# fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> # where B: ResponseBody # { # match head.status() { @@ -90,4 +90,4 @@ See the [`IsOk`][IsOk] trait for more details. pub(crate) use elastic_responses::parse; pub use elastic_responses::parsing::{Buffered, HttpResponseHead, IsOk, MaybeBufferedResponse, MaybeOkResponse, ResponseBody, Unbuffered}; -pub use elastic_responses::error::ParseResponseError; +pub use elastic_responses::error::ParseError; diff --git a/src/elastic/src/client/sender/sniffed_nodes/nodes_info.rs b/src/elastic/src/client/sender/sniffed_nodes/nodes_info.rs index caa8b072a4..aa568468d7 100644 --- a/src/elastic/src/client/sender/sniffed_nodes/nodes_info.rs +++ b/src/elastic/src/client/sender/sniffed_nodes/nodes_info.rs @@ -2,7 +2,7 @@ use std::fmt; use serde::de::{Deserialize, Deserializer, MapAccess, Visitor}; -use client::responses::parse::{HttpResponseHead, IsOk, MaybeOkResponse, ParseResponseError, ResponseBody, Unbuffered}; +use client::responses::parse::{HttpResponseHead, IsOk, MaybeOkResponse, ParseError, ResponseBody, Unbuffered}; use std::iter::IntoIterator; use std::vec::IntoIter; @@ -32,7 +32,7 @@ impl IntoIterator for NodesInfoResponse { } impl IsOk for NodesInfoResponse { - fn is_ok(head: HttpResponseHead, unbuffered: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, unbuffered: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(unbuffered)), _ => Ok(MaybeOkResponse::err(unbuffered)), diff --git a/src/responses/src/bulk.rs b/src/responses/src/bulk.rs index 0e4d3383db..d90a74416e 100644 --- a/src/responses/src/bulk.rs +++ b/src/responses/src/bulk.rs @@ -521,7 +521,7 @@ pub enum Action { } impl IsOk for BulkResponse { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(body)), _ => Ok(MaybeOkResponse::err(body)), @@ -530,7 +530,7 @@ impl IsOk for BulkResponse { } impl IsOk for BulkErrorsResponse { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(body)), _ => Ok(MaybeOkResponse::err(body)), diff --git a/src/responses/src/command.rs b/src/responses/src/command.rs index e154258260..9ff653e7f7 100644 --- a/src/responses/src/command.rs +++ b/src/responses/src/command.rs @@ -23,7 +23,7 @@ impl CommandResponse { } impl IsOk for CommandResponse { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(body)), _ => Ok(MaybeOkResponse::err(body)), diff --git a/src/responses/src/delete.rs b/src/responses/src/delete.rs index 13898f4841..e974f13c08 100644 --- a/src/responses/src/delete.rs +++ b/src/responses/src/delete.rs @@ -54,7 +54,7 @@ impl DeleteResponse { } impl IsOk for DeleteResponse { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 | 404 => Ok(MaybeOkResponse::ok(body)), _ => Ok(MaybeOkResponse::err(body)), diff --git a/src/responses/src/error.rs b/src/responses/src/error.rs index ea729ecb6f..80296ae594 100644 --- a/src/responses/src/error.rs +++ b/src/responses/src/error.rs @@ -1,24 +1,89 @@ /*! -Error types from Elasticsearch +Error types from Elasticsearch. */ use serde::{Deserialize, Deserializer}; use serde_json::{Error as JsonError, Map, Value}; +use std::error::Error as StdError; use std::io::Error as IoError; +use std::fmt; + +mod inner { + use std::fmt; + use std::error::Error as StdError; + use serde_json::{Map, Value}; + + use super::ApiError; -quick_error! { - /** An error parsing a response stream. */ #[derive(Debug)] - pub enum ParseResponseError { - /** The response contains invalid json. */ - Json(err: JsonError) { - from() + pub struct UnknownApiError(pub Map); + + impl fmt::Display for UnknownApiError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (&self.0 as &fmt::Debug).fmt(f) } - /** The response caused an io error while buffering. */ - Io(err: IoError) { - from() + } + + impl StdError for UnknownApiError { + fn description(&self) -> &str { + "an unknown API error" + } + + fn cause(&self) -> Option<&StdError> { + None } } + + pub enum ParsedApiError { + Known(ApiError), + Unknown(Map) + } +} + +pub(crate) use self::inner::*; + +/** +A generic error parsing an API response. +*/ +#[derive(Debug)] +pub struct ParseError { + inner: Box, +} + +impl ParseError { + pub fn new(err: E) -> Self where E: StdError + Send + Sync + 'static { + ParseError { + inner: Box::new(err) + } + } +} + +impl From for ParseError { + fn from(err: IoError) -> Self { + ParseError::new(err) + } +} + +impl From for ParseError { + fn from(err: JsonError) -> Self { + ParseError::new(err) + } +} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.inner.fmt(f) + } +} + +impl StdError for ParseError { + fn description(&self) -> &str { + self.inner.description() + } + + fn cause(&self) -> Option<&StdError> { + Some(&*self.inner) + } } quick_error! { @@ -30,7 +95,7 @@ quick_error! { from() } /** An error parsing a response body. */ - Parse(err: ParseResponseError) { + Parse(err: ParseError) { from() } } @@ -69,24 +134,6 @@ quick_error! { display("index already exists: '{}'", index) } /** - The request body contains invalid data. - - If a Query DSL query contains invalid JSON or unrecognised properties then Elasticsearch will return a `Parsing` error. - */ - Parsing { line: u64, col: u64, reason: String } { - description("request parse error") - display("request parse error: '{}' on line: {}, col: {}", reason, line, col) - } - /** - The document mapping contains invalid data. - - If a put mapping request contains invalid JSON or unrecognised properties then Elasticsearch will return a `MapperParsing` error. - */ - MapperParsing { reason: String } { - description("mapper parse error") - display("mapper parse error: '{}'", reason) - } - /** The request body can't be processed. Some endpoints that expect certain constraints of a request to hold will return an `ActionRequestValidation` error if those constraints aren't met. @@ -95,17 +142,6 @@ quick_error! { description("action request failed validation") display("action request failed validation: '{}'", reason) } - /** - A currently unrecognised error occurred. - - **WARNING:** Don't rely on this variant to capture an error. - As new variants are introduced they will no longer be matched by `ApiError::Other`. - For this reason, this variant will disappear in the future. - */ - Other(v: Map) { - description("error response from Elasticsearch") - display("error response from Elasticsearch: {:?}", v) - } #[doc(hidden)] __NonExhaustive {} } @@ -119,13 +155,13 @@ macro_rules! error_key { match key { Some(v) => v, - _ => return ApiError::Other($obj).into() + _ => return ParsedApiError::Unknown($obj) } } ) } -impl<'de> Deserialize<'de> for ApiError { +impl<'de> Deserialize<'de> for ParsedApiError { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, @@ -136,12 +172,12 @@ impl<'de> Deserialize<'de> for ApiError { } } -impl From> for ApiError { +impl From> for ParsedApiError { fn from(mut value: Map) -> Self { let obj = { match value.remove("error") { Some(Value::Object(value)) => value, - _ => return ApiError::Other(value), + _ => return ParsedApiError::Unknown(value), } }; @@ -152,7 +188,7 @@ impl From> for ApiError { match ty { Some(ty) => ty, - _ => return ApiError::Other(obj), + _ => return ParsedApiError::Unknown(obj), } }; @@ -160,50 +196,32 @@ impl From> for ApiError { "index_not_found_exception" => { let index = error_key!(obj[index]: |v| v.as_str()); - ApiError::IndexNotFound { + ParsedApiError::Known(ApiError::IndexNotFound { index: index.into(), - } + }) } "index_already_exists_exception" => { let index = error_key!(obj[index]: |v| v.as_str()); - ApiError::IndexAlreadyExists { + ParsedApiError::Known(ApiError::IndexAlreadyExists { index: index.into(), - } + }) } "document_missing_exception" => { let index = error_key!(obj[index]: |v| v.as_str()); - ApiError::DocumentMissing { + ParsedApiError::Known(ApiError::DocumentMissing { index: index.into(), - } - } - "parsing_exception" => { - let line = error_key!(obj[line]: |v| v.as_u64()); - let col = error_key!(obj[col]: |v| v.as_u64()); - let reason = error_key!(obj[reason]: |v| v.as_str()); - - ApiError::Parsing { - line: line, - col: col, - reason: reason.into(), - } - } - "mapper_parsing_exception" => { - let reason = error_key!(obj[reason]: |v| v.as_str()); - - ApiError::MapperParsing { - reason: reason.into(), - } + }) } "action_request_validation_exception" => { let reason = error_key!(obj[reason]: |v| v.as_str()); - ApiError::ActionRequestValidation { + ParsedApiError::Known(ApiError::ActionRequestValidation { reason: reason.into(), - } + }) } - _ => ApiError::Other(obj), + _ => ParsedApiError::Unknown(obj), } } } diff --git a/src/responses/src/get.rs b/src/responses/src/get.rs index 55aa335117..989505da0f 100644 --- a/src/responses/src/get.rs +++ b/src/responses/src/get.rs @@ -57,7 +57,7 @@ impl GetResponse { } impl IsOk for GetResponse { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(body)), 404 => { diff --git a/src/responses/src/index.rs b/src/responses/src/index.rs index 8d266aa1d4..7306c34d1a 100644 --- a/src/responses/src/index.rs +++ b/src/responses/src/index.rs @@ -50,7 +50,7 @@ impl IndexResponse { } impl IsOk for IndexResponse { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(body)), _ => Ok(MaybeOkResponse::err(body)), diff --git a/src/responses/src/indices_exists.rs b/src/responses/src/indices_exists.rs index bffa297b50..895d785ed5 100644 --- a/src/responses/src/indices_exists.rs +++ b/src/responses/src/indices_exists.rs @@ -19,7 +19,7 @@ impl IndicesExistsResponse { } impl IsOk for IndicesExistsResponse { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(json!({ "exists": true }))), 404 => Ok(MaybeOkResponse::ok(json!({ "exists": false }))), diff --git a/src/responses/src/parsing.rs b/src/responses/src/parsing.rs index 129cc8519e..9e2058af51 100644 --- a/src/responses/src/parsing.rs +++ b/src/responses/src/parsing.rs @@ -53,7 +53,7 @@ Provide an explicit response type on the result ident: # fn do_request() -> (u16, Vec) { unimplemented!() } # fn main() { # let (response_status, response_body) = do_request(); -let get_response: Result, ResponseError> = parse().from_slice(response_status, response_body); +let get_response: Result, ParseError> = parse().from_slice(response_status, response_body); # } ``` @@ -67,7 +67,7 @@ If Rust can infer the concrete response type then you can avoid specifying it at # use elastic_responses::error::*; # fn do_request() -> (u16, Vec) { unimplemented!() } # fn main() { -# fn parse_response() -> Result, ResponseError> { +# fn parse_response() -> Result, ParseError> { # let (response_status, response_body) = do_request(); let get_response = parse().from_slice(response_status, response_body); # get_response @@ -135,13 +135,13 @@ where type Buffered: ResponseBody; /** Buffer the response body to a json value and return a new buffered representation. */ - fn body(self) -> Result<(Value, Self::Buffered), ParseResponseError>; + fn body(self) -> Result<(Value, Self::Buffered), ParseError>; /** Parse the body as a success result. */ - fn parse_ok(self) -> Result; + fn parse_ok(self) -> Result; /** Parse the body as an API error. */ - fn parse_err(self) -> Result; + fn parse_err(self) -> Result; } struct ReadBody(B); @@ -149,7 +149,7 @@ struct ReadBody(B); impl ResponseBody for ReadBody { type Buffered = SliceBody>; - fn body(mut self) -> Result<(Value, Self::Buffered), ParseResponseError> { + fn body(mut self) -> Result<(Value, Self::Buffered), ParseError> { let mut buf = Vec::new(); self.0.read_to_end(&mut buf)?; @@ -158,12 +158,15 @@ impl ResponseBody for ReadBody { Ok((body, SliceBody(buf))) } - fn parse_ok(self) -> Result { + fn parse_ok(self) -> Result { serde_json::from_reader(self.0).map_err(|e| e.into()) } - fn parse_err(self) -> Result { - serde_json::from_reader(self.0).map_err(|e| e.into()) + fn parse_err(self) -> Result { + match serde_json::from_reader(self.0)? { + ParsedApiError::Known(err) => Ok(err), + ParsedApiError::Unknown(err) => Err(ParseError::new(UnknownApiError(err))) + } } } @@ -172,7 +175,7 @@ struct SliceBody(B); impl> ResponseBody for SliceBody { type Buffered = Self; - fn body(self) -> Result<(Value, Self::Buffered), ParseResponseError> { + fn body(self) -> Result<(Value, Self::Buffered), ParseError> { let buf = self.0; let body: Value = serde_json::from_slice(buf.as_ref())?; @@ -180,30 +183,36 @@ impl> ResponseBody for SliceBody { Ok((body, SliceBody(buf))) } - fn parse_ok(self) -> Result { + fn parse_ok(self) -> Result { serde_json::from_slice(self.0.as_ref()).map_err(|e| e.into()) } - fn parse_err(self) -> Result { - serde_json::from_slice(self.0.as_ref()).map_err(|e| e.into()) + fn parse_err(self) -> Result { + match serde_json::from_slice(self.0.as_ref())? { + ParsedApiError::Known(err) => Ok(err), + ParsedApiError::Unknown(err) => Err(ParseError::new(UnknownApiError(err))) + } } } impl ResponseBody for Value { type Buffered = Self; - fn body(self) -> Result<(Value, Self::Buffered), ParseResponseError> { + fn body(self) -> Result<(Value, Self::Buffered), ParseError> { let value = self.clone(); Ok((self, value)) } - fn parse_ok(self) -> Result { + fn parse_ok(self) -> Result { serde_json::from_value(self).map_err(|e| e.into()) } - fn parse_err(self) -> Result { - serde_json::from_value(self).map_err(|e| e.into()) + fn parse_err(self) -> Result { + match serde_json::from_value(self)? { + ParsedApiError::Known(err) => Ok(err), + ParsedApiError::Unknown(err) => Err(ParseError::new(UnknownApiError(err))) + } } } @@ -241,7 +250,7 @@ Implement `IsOk` for a custom response type, where a http `404` might still cont # #[derive(Deserialize)] # struct MyResponse; impl IsOk for MyResponse { - fn is_ok(head: HttpResponseHead, unbuffered: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, unbuffered: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(unbuffered)), 404 => { @@ -263,11 +272,11 @@ impl IsOk for MyResponse { */ pub trait IsOk { /** Inspect the http response to determine whether or not it succeeded. */ - fn is_ok(head: HttpResponseHead, unbuffered: Unbuffered) -> Result, ParseResponseError>; + fn is_ok(head: HttpResponseHead, unbuffered: Unbuffered) -> Result, ParseError>; } impl IsOk for Value { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(body)), _ => Ok(MaybeOkResponse::err(body)), @@ -324,7 +333,7 @@ pub struct Unbuffered(B); impl Unbuffered { /** Buffer the response body to a json value and return a new buffered representation. */ - pub fn body(self) -> Result<(Value, Buffered), ParseResponseError> { + pub fn body(self) -> Result<(Value, Buffered), ParseError> { self.0.body().map(|(value, body)| (value, Buffered(body))) } } @@ -351,7 +360,7 @@ impl MaybeBufferedResponse where B: ResponseBody, { - fn parse_ok(self) -> Result { + fn parse_ok(self) -> Result { match self { MaybeBufferedResponse::Unbuffered(b) => b.parse_ok(), MaybeBufferedResponse::Buffered(b) => b.parse_ok(), @@ -359,7 +368,7 @@ where } } - fn parse_err(self) -> Result { + fn parse_err(self) -> Result { match self { MaybeBufferedResponse::Unbuffered(b) => b.parse_err(), MaybeBufferedResponse::Buffered(b) => b.parse_err(), diff --git a/src/responses/src/ping.rs b/src/responses/src/ping.rs index d0d62b718f..b25cf0d428 100644 --- a/src/responses/src/ping.rs +++ b/src/responses/src/ping.rs @@ -69,7 +69,7 @@ impl ClusterVersion { } impl IsOk for PingResponse { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(body)), _ => Ok(MaybeOkResponse::err(body)), diff --git a/src/responses/src/search.rs b/src/responses/src/search.rs index af22c7be97..5943102eeb 100644 --- a/src/responses/src/search.rs +++ b/src/responses/src/search.rs @@ -143,7 +143,7 @@ impl SearchResponse { } impl IsOk for SearchResponse { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(body)), _ => Ok(MaybeOkResponse::err(body)), diff --git a/src/responses/src/update.rs b/src/responses/src/update.rs index f7068aef41..6c279854a3 100644 --- a/src/responses/src/update.rs +++ b/src/responses/src/update.rs @@ -48,7 +48,7 @@ impl UpdateResponse { } impl IsOk for UpdateResponse { - fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseResponseError> { + fn is_ok(head: HttpResponseHead, body: Unbuffered) -> Result, ParseError> { match head.status() { 200...299 => Ok(MaybeOkResponse::ok(body)), _ => Ok(MaybeOkResponse::err(body)), diff --git a/src/responses/tests/index/mod.rs b/src/responses/tests/index/mod.rs index b732e157d6..8fd292ccf7 100644 --- a/src/responses/tests/index/mod.rs +++ b/src/responses/tests/index/mod.rs @@ -17,19 +17,6 @@ fn success_parse_response() { assert_eq!(Some(1), deserialized.version()); } -#[test] -fn error_parse_mapping() { - let f = load_file("tests/samples/error_mapper_parsing.json"); - let deserialized = parse::().from_reader(400, f).unwrap_err(); - - let valid = match deserialized { - ResponseError::Api(ApiError::MapperParsing { ref reason }) if reason == "failed to parse, document is empty" => true, - _ => false, - }; - - assert!(valid); -} - #[test] fn error_parse_index_already_exists() { let f = load_file("tests/samples/error_index_already_exists.json"); diff --git a/src/responses/tests/search/mod.rs b/src/responses/tests/search/mod.rs index f76418439f..15a1464718 100644 --- a/src/responses/tests/search/mod.rs +++ b/src/responses/tests/search/mod.rs @@ -213,45 +213,3 @@ fn error_parse_index_not_found() { assert!(valid); } - -#[test] -fn error_parse_parsing() { - let f = load_file("tests/samples/error_parsing.json"); - let deserialized = parse::>() - .from_reader(400, f) - .unwrap_err(); - - let valid = match deserialized { - ResponseError::Api(ApiError::Parsing { - line: 2, - col: 9, - ref reason, - }) if reason == "Unknown key for a START_OBJECT in [qry]." => - { - true - } - _ => false, - }; - - assert!(valid); -} - -#[test] -fn error_parse_other() { - let f = load_file("tests/samples/error_other.json"); - let deserialized = parse::>() - .from_reader(500, f) - .unwrap_err(); - - let reason = match deserialized { - ResponseError::Api(ApiError::Other(ref err)) => err.get("reason") - .and_then(|reason| reason.as_str()) - .map(|reason| reason.to_owned()), - _ => None, - }; - - assert_eq!( - Some(String::from("An error that we don't know about.")), - reason - ); -} diff --git a/src/types/src/date/formats.rs b/src/types/src/date/formats.rs index 35672b39f0..f99827e983 100644 --- a/src/types/src/date/formats.rs +++ b/src/types/src/date/formats.rs @@ -78,7 +78,7 @@ impl DateFormat for EpochMillis { #[cfg(test)] mod tests { use chrono::{DateTime, Utc}; - use date::{format, parse}; + use date::{format, parse, ParseError}; use prelude::*; #[test] diff --git a/src/types/src/date/mod.rs b/src/types/src/date/mod.rs index 0cae8abf8f..1f64cf67c4 100644 --- a/src/types/src/date/mod.rs +++ b/src/types/src/date/mod.rs @@ -93,6 +93,7 @@ You can also manually implement `DateFormat` and write your own arbitrary format # extern crate elastic_types; # extern crate chrono; # use elastic_types::prelude::*; +# use elastic_types::date::ParseError; # fn main() { use chrono::{DateTime, Utc}; @@ -135,7 +136,7 @@ pub mod prelude { */ pub use super::DefaultDateFormat; - pub use super::format::*; + pub use super::format::{DateFormat, DateValue, FormattableDateValue, FormattedDate}; pub use super::impls::*; pub use super::formats::*; pub use super::mapping::*;