From 0abb0317174c7175d89f228dfc37aa7a6a25bacf Mon Sep 17 00:00:00 2001 From: Nicolas Kosinski Date: Fri, 3 Aug 2018 09:10:57 +0200 Subject: [PATCH] Fix #22: Fix 'unknown variant' failures Only keep used GitHub enums and set a default value for unused ones. Use tip from documentation: https://serde.rs/attr-default.html This tip has been given by @dtolnay in this issue: https://github.com/serde-rs/serde/issues/1353 --- src/github_events/mod.rs | 95 +++++++++++++---------- src/lib.rs | 14 ++-- test/github_event_with_unknown_enums.json | 19 +++++ 3 files changed, 81 insertions(+), 47 deletions(-) create mode 100644 test/github_event_with_unknown_enums.json diff --git a/src/github_events/mod.rs b/src/github_events/mod.rs index ffcffe6..d89e78c 100644 --- a/src/github_events/mod.rs +++ b/src/github_events/mod.rs @@ -5,6 +5,7 @@ extern crate serde_json; use self::reqwest::StatusCode; use chrono::{DateTime, Utc}; use regex::Regex; +use serde::{Deserialize, Deserializer}; use std::io::{Error, ErrorKind}; use std::str; @@ -112,7 +113,9 @@ fn last_page_from_link_header(link_header: &str) -> Option { pub struct RawEvent { pub actor: Actor, pub payload: Payload, - #[serde(rename = "type")] + #[serde( + rename = "type", deserialize_with = "deserialize_field_type", default = "Type::default" + )] pub event_type: Type, pub created_at: DateTime, } @@ -124,7 +127,8 @@ pub struct Actor { #[derive(Debug, Deserialize, Eq, PartialEq)] pub struct Payload { - pub action: Option, + #[serde(deserialize_with = "deserialize_field_action", default = "Action::default")] + pub action: Action, } #[derive(Debug, Deserialize, Eq, PartialEq)] @@ -134,52 +138,42 @@ pub enum Action { #[allow(non_camel_case_types)] closed, #[allow(non_camel_case_types)] - edited, - #[allow(non_camel_case_types)] opened, - #[allow(non_camel_case_types)] - started, + #[serde(skip_deserializing)] + Unknown, +} +impl Action { + fn default() -> Self { + Action::Unknown + } +} + +fn deserialize_field_action<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + Ok(Action::deserialize(deserializer).unwrap_or(Action::Unknown)) } #[derive(Debug, Deserialize, Eq, PartialEq)] pub enum Type { - CommitCommentEvent, - CreateEvent, - DeleteEvent, - DeploymentEvent, - DeploymentStatusEvent, - DownloadEvent, - FollowEvent, - ForkEvent, - ForkApplyEvent, - GistEvent, - GollumEvent, - InstallationEvent, - InstallationRepositoriesEvent, IssueCommentEvent, - IssuesEvent, - LabelEvent, - MarketplacePurchaseEvent, - MemberEvent, - MembershipEvent, - MilestoneEvent, - OrganizationEvent, - OrgBlockEvent, - PageBuildEvent, - ProjectCardEvent, - ProjectColumnEvent, - ProjectEvent, - PublicEvent, PullRequestEvent, - PullRequestReviewEvent, PullRequestReviewCommentEvent, - PushEvent, - ReleaseEvent, - RepositoryEvent, - StatusEvent, - TeamEvent, - TeamAddEvent, - WatchEvent, + #[serde(skip_deserializing)] + Unknown, +} +impl Type { + fn default() -> Self { + Type::Unknown + } +} + +fn deserialize_field_type<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + Ok(Type::deserialize(deserializer).unwrap_or(Type::Unknown)) } mod tests { @@ -200,7 +194,7 @@ mod tests { login: "alice".to_string(), }, payload: Payload { - action: Some(Action::opened), + action: Action::opened, }, event_type: Type::PullRequestEvent, created_at: Utc.ymd(2016, 12, 1).and_hms(16, 26, 43), @@ -208,6 +202,25 @@ mod tests { ); } + #[test] + fn parse_github_event_with_unknown_enums() { + assert_eq!( + raw_github_events(include_str!( + "../../test/github_event_with_unknown_enums.json" + )).unwrap()[0], + RawEvent { + actor: Actor { + login: "alice".to_string(), + }, + payload: Payload { + action: Action::Unknown, + }, + event_type: Type::Unknown, + created_at: Utc.ymd(2016, 12, 1).and_hms(16, 26, 43), + } + ); + } + #[test] fn parse_real_github_events_from_nicokosi_pullpito() { let events = raw_github_events(include_str!("../../test/pullpito_github_events.json")); diff --git a/src/lib.rs b/src/lib.rs index 3b502de..e904ae7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ use std::thread; use structopt::StructOpt; pub mod github_events; +extern crate serde; #[derive(Debug, Deserialize, PartialEq, Serialize)] pub struct Config { @@ -102,7 +103,8 @@ fn events_per_author(events: Vec) -> HashMap> { || e.event_type == Type::IssueCommentEvent }) .fold(HashMap::new(), |mut acc, event: RawEvent| { - (*acc.entry(event.actor.login.clone()) + (*acc + .entry(event.actor.login.clone()) .or_insert_with(Vec::new)) .push(event); acc @@ -116,7 +118,7 @@ fn printable(repo: &str, events_per_author: &HashMap>) -> let opened_pull_requests = events .into_iter() .filter(|e| { - e.event_type == Type::PullRequestEvent && e.payload.action == Some(Action::opened) + e.event_type == Type::PullRequestEvent && e.payload.action == Action::opened }) .count(); if opened_pull_requests > 0 { @@ -128,7 +130,7 @@ fn printable(repo: &str, events_per_author: &HashMap>) -> let commented_pull_requests = events .into_iter() .filter(|e| { - e.event_type == Type::IssueCommentEvent && e.payload.action == Some(Action::created) + e.event_type == Type::IssueCommentEvent && e.payload.action == Action::created }) .count(); if commented_pull_requests > 0 { @@ -140,7 +142,7 @@ fn printable(repo: &str, events_per_author: &HashMap>) -> let closed_pull_requests = events .into_iter() .filter(|e| { - e.event_type == Type::PullRequestEvent && e.payload.action == Some(Action::closed) + e.event_type == Type::PullRequestEvent && e.payload.action == Action::closed }) .count(); if closed_pull_requests > 0 { @@ -241,7 +243,7 @@ mod test { login: "alice".to_string(), }, payload: Payload { - action: Some(Action::opened), + action: Action::opened, }, event_type: Type::PullRequestEvent, created_at: Utc.ymd(2016, 12, 1).and_hms(16, 26, 43), @@ -263,7 +265,7 @@ mod test { login: "alice".to_string(), }, payload: Payload { - action: Some(Action::opened), + action: Action::opened, }, event_type: Type::PullRequestEvent, created_at: Utc.ymd(2016, 12, 1).and_hms(16, 26, 43), diff --git a/test/github_event_with_unknown_enums.json b/test/github_event_with_unknown_enums.json new file mode 100644 index 0000000..2005371 --- /dev/null +++ b/test/github_event_with_unknown_enums.json @@ -0,0 +1,19 @@ +[ + { + "id": "1", + "type": "ThisTypeDoesNotExist", + "actor": { + "login": "alice", + "display_login": "Alice" + }, + "repo": { + "id": 2, + "name": "softwarevidal/fake-repo" + }, + "payload": { + "action": "ThisActionDoesNotExist" + }, + "public": false, + "created_at": "2016-12-01T16:26:43Z" + } +] \ No newline at end of file