LinkParse(String, String), // url, parsing error message
JSONParse(String, String), // url, parsing error message
+ InvalidJSONSyntax(String, String), // url, parsing error message
+ UnexpectedJSONContent(String, String, String), // url, deser msg, json
UrlConsistency(String, String), // url, error message
Consistency(String), // just error message
}
ClientError::JSONParse(ref url, ref msg) => {
write!(f, "{} (parsing JSON returned from URL: {})", msg, url)
}
+ ClientError::InvalidJSONSyntax(url, msg) => {
+ write!(f, "{msg} (bad JSON syntax from URL: {url})")
+ }
+ ClientError::UnexpectedJSONContent(url, msg, json) => {
+ write!(
+ f,
+ "{msg} (unexpected JSON value from URL: {url}, received {json})",
+ )
+ }
ClientError::LinkParse(ref url, ref msg) => {
write!(
f,
&mut self,
req: Req,
) -> Result<(T, String), ClientError> {
+ // There's a lot of code here that doesn't depend on T, but
+ // the generics will monomorphise it for each T. If we cared enough
+ // about binary size, we could make a non-generic inner function.
let (url, rsp) = self.api_request(req)?;
let rspstatus = rsp.status();
if !rspstatus.is_success() {
return Err(ClientError::from_response(&url, rsp));
}
- let t: T = serde_json::from_str(&rsp.text()?)
- .map_err(|e| ClientError::JSONParse(url.clone(), e.to_string()))?;
+ let text = rsp.text()?;
+ let t: T = serde_json::from_str(&text).map_err(|e0| {
+ let url = url.clone();
+ let val = match serde_json::from_str::<serde_json::Value>(&text) {
+ Ok(y) => y,
+ Err(e) => {
+ return ClientError::InvalidJSONSyntax(url, e.to_string())
+ },
+ };
+ let val_restring = serde_json::to_string(&val)
+ .unwrap_or_else(|e| format!("failed to regenerate json! {e}"));
+ let e = match serde_json::from_value::<T>(val) {
+ Err(e) => e.to_string(),
+ Ok(_wat) => format!(
+ "unexpectedly parsed Ok from Value! (earlier, from_str gave {e0}",
+ ),
+ };
+ ClientError::UnexpectedJSONContent(url, e, val_restring)
+ })?;
Ok((t, url))
}
log_msg(&mut paras, msg);
log_url(&mut paras, url);
}
+ ClientError::InvalidJSONSyntax(url, msg) => {
+ title.push_text(
+ ColouredString::plain("JSON syntax error"),
+ false,
+ );
+ log_msg(&mut paras, msg);
+ log_url(&mut paras, url);
+ }
+ ClientError::UnexpectedJSONContent(url, msg, json) => {
+ title.push_text(
+ ColouredString::plain("JSON content error"),
+ false,
+ );
+ log_msg(&mut paras, msg);
+ log_url(&mut paras, url);
+ paras.push(
+ Paragraph::new()
+ .add(ColouredString::plain("response JSON: "))
+ .add(ColouredString::uniform(&json, 'u')),
+ );
+ }
ClientError::LinkParse(url, msg) => {
title.push_text(
ColouredString::plain("Link header parsing error"),