81 lines
2.1 KiB
Rust
81 lines
2.1 KiB
Rust
use chrono::{DateTime, FixedOffset};
|
|
use serde::de::{self, Visitor};
|
|
use serde::{Deserialize, Deserializer};
|
|
use std::collections::HashMap;
|
|
use std::fmt;
|
|
use std::marker::PhantomData;
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
pub struct Issue {
|
|
pub comments_url: String,
|
|
pub events_url: String,
|
|
pub html_url: String,
|
|
pub node_id: String,
|
|
pub title: String,
|
|
pub user: User,
|
|
pub state: String,
|
|
pub body: String,
|
|
#[serde(deserialize_with = "deserialize_datetime")]
|
|
pub created_at: DateTime<FixedOffset>,
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
#[serde(untagged)]
|
|
pub enum EventType {
|
|
Comment(Comment),
|
|
Event(Event),
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
pub struct Comment {
|
|
pub html_url: String,
|
|
pub node_id: String,
|
|
pub user: User,
|
|
#[serde(deserialize_with = "deserialize_datetime")]
|
|
pub created_at: DateTime<FixedOffset>,
|
|
pub body: String,
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
pub struct Event {
|
|
pub url: String,
|
|
pub id: usize,
|
|
pub node_id: String,
|
|
pub actor: User,
|
|
#[serde(deserialize_with = "deserialize_datetime")]
|
|
pub created_at: DateTime<FixedOffset>,
|
|
pub event: String,
|
|
#[serde(flatten)]
|
|
pub extra: HashMap<String, serde_json::Value>,
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
pub struct User {
|
|
pub login: String,
|
|
}
|
|
|
|
fn deserialize_datetime<'de, D>(deserializer: D) -> Result<DateTime<FixedOffset>, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
struct DeserializeDateTime<T>(PhantomData<fn() -> T>);
|
|
|
|
impl<'de> Visitor<'de> for DeserializeDateTime<DateTime<FixedOffset>> {
|
|
type Value = DateTime<FixedOffset>;
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
formatter.write_str("RFC3339 datetime string")
|
|
}
|
|
|
|
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
// https://brokenco.de/2020/08/03/serde-deserialize-with-string.html
|
|
DateTime::parse_from_rfc3339(value).map_err(serde::de::Error::custom)
|
|
}
|
|
}
|
|
|
|
deserializer.deserialize_any(DeserializeDateTime(PhantomData))
|
|
}
|