issuerss/src/github/structs.rs

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))
}