use json;
use json::Value;
use data::{Listing, Thing};
use errors::ParseError;
use failure::{err_msg, Error};
use App;
#[derive(Debug, Clone)]
pub enum Thread {
Comment(Box<Comment>),
More(Vec<String>),
}
#[derive(Debug, Clone)]
pub struct Comment {
pub edited: Option<f64>,
pub id: String,
pub parent_id: String,
pub link_id: String,
pub author: String,
pub ups: i64,
pub downs: i64,
pub score: i64,
pub body: String,
pub is_submitter: bool,
pub stickied: bool,
pub subreddit: String,
pub score_hidden: bool,
pub name: String,
pub replies: Listing<Comment>,
}
impl Thing for Comment {
fn from_value(val: &Value, app: &App) -> Result<Comment, Error> {
macro_rules! out {
($val:ident) => {
return Err(Error::from(ParseError {
thing_type: "Comment".to_string(),
json: json::to_string_pretty($val).unwrap(),
}));
};
}
let val = &val["data"];
let edited = match val["edited"] {
Value::Bool(_) | Value::Null => None,
Value::Number(ref num) => num.as_f64(),
_ => return Err(format_err!("Unexpected value for \"edited\": {}", val["edited"])),
};
let id: String = match val["id"].as_str() {
Some(t) => t.to_string(),
None => out!(val),
};
let parent_id: String = match val["parent_id"].as_str() {
Some(t) => t.to_string(),
None => out!(val),
};
let link_id: String = match val["link_id"].as_str() {
Some(t) => t.to_string(),
None => out!(val),
};
let author: String = match val["author"].as_str() {
Some(t) => t.to_string(),
None => out!(val),
};
let ups: i64 = match val["ups"].as_i64() {
Some(t) => t,
None => out!(val),
};
let downs: i64 = match val["downs"].as_i64() {
Some(t) => t,
None => out!(val),
};
let score: i64 = match val["score"].as_i64() {
Some(t) => t,
None => out!(val),
};
let body: String = match val["body"].as_str() {
Some(t) => t.to_string(),
None => out!(val),
};
let is_submitter: bool = match val["is_submitter"].as_bool() {
Some(t) => t,
None => out!(val),
};
let stickied: bool = match val["stickied"].as_bool() {
Some(t) => t,
None => out!(val),
};
let subreddit: String = match val["subreddit"].as_str() {
Some(t) => t.to_string(),
None => out!(val),
};
let score_hidden: bool = match val["score_hidden"].as_bool() {
Some(t) => t,
None => out!(val),
};
let name: String = match val["name"].as_str() {
Some(t) => t.to_string(),
None => out!(val),
};
let replies: Listing<Comment> = match val["replies"] {
Value::String(_) => Listing::new(),
Value::Object(_) => Listing::from_value(&val["replies"]["data"]["children"], &link_id, app).unwrap(),
_ => return Err(err_msg(format!("Unexpected value for \"replies\": {}", val["replies"]))),
};
Ok(Comment {
edited,
id,
parent_id,
link_id,
author,
ups,
downs,
score,
body,
is_submitter,
stickied,
subreddit,
score_hidden,
name,
replies,
})
}
}