From f35b566f933bd979c808c954c57252ef59e0369a Mon Sep 17 00:00:00 2001 From: Raphael Nestler Date: Mon, 3 Feb 2020 23:27:51 +0100 Subject: [PATCH 1/6] Make api field optional [breaking-change] The `api` field is now an `Option`. --- src/status.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/status.rs b/src/status.rs index 8b68e48..555b7cb 100644 --- a/src/status.rs +++ b/src/status.rs @@ -161,7 +161,9 @@ pub struct Stream { #[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq)] pub struct Status { // Hackerspace properties - pub api: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub api: Option, + pub space: String, pub logo: String, pub url: String, @@ -214,7 +216,7 @@ impl Status { issue_report_channels: Vec, ) -> Status { Status { - api: "0.13".into(), + api: Some("0.13".into()), space: space.into(), logo: logo.into(), url: url.into(), @@ -321,7 +323,7 @@ impl StatusBuilder { pub fn build(self) -> Result { Ok(Status { - api: "0.13".into(), // TODO: Deduplicate + api: Some("0.13".into()), // TODO: Deduplicate space: self.space, logo: self.logo.ok_or("logo missing")?, url: self.url.ok_or("url missing")?, @@ -392,7 +394,7 @@ mod test { .add_issue_report_channel(IssueReportChannel::Email) .build() .unwrap(); - assert_eq!(status.api, "0.13"); + assert_eq!(status.api, Some("0.13".into())); assert_eq!(status.space, "foo"); assert_eq!(status.logo, "bar"); assert_eq!(status.url, "foobar"); @@ -525,7 +527,7 @@ mod test { \"location\":{\"lat\":0.0,\"lon\":0.0},\"contact\":{},\"issue_report_channels\":[],\ \"state\":{\"open\":null},\"ext_aaa\":\"xxx\",\"ext_bbb\":[null,42]}"; let deserialized: Status = from_str(&data).unwrap(); - assert_eq!(&deserialized.api, "0.13"); + assert_eq!(deserialized.api, Some("0.13".into())); let keys: Vec<_> = deserialized.extensions.keys().collect(); assert_eq!(keys.len(), 2) } From f488b96f42923ab1a0100e60f4456d546d7cf7bd Mon Sep 17 00:00:00 2001 From: Raphael Nestler Date: Tue, 4 Feb 2020 17:57:23 +0100 Subject: [PATCH 2/6] Add api_compatibility field --- src/status.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/status.rs b/src/status.rs index 555b7cb..79202be 100644 --- a/src/status.rs +++ b/src/status.rs @@ -157,6 +157,12 @@ pub struct Stream { pub ustream: Option, } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub enum ApiVersion { + #[serde(rename = "14")] + V14, +} + /// The main SpaceAPI status object. #[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq)] pub struct Status { @@ -164,6 +170,9 @@ pub struct Status { #[serde(skip_serializing_if = "Option::is_none")] pub api: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub api_compatibility: Option>, + pub space: String, pub logo: String, pub url: String, From 24544913f9e53193a50a8271a6d31624e26103b6 Mon Sep 17 00:00:00 2001 From: Raphael Nestler Date: Tue, 4 Feb 2020 18:01:39 +0100 Subject: [PATCH 3/6] Add basic v14 support --- src/status.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/status.rs b/src/status.rs index 79202be..4b64346 100644 --- a/src/status.rs +++ b/src/status.rs @@ -237,9 +237,23 @@ impl Status { } } +#[derive(Debug, Clone)] +enum StatusBuilderVersion { + V0_13, + V14, + Mixed, +} + +impl Default for StatusBuilderVersion { + fn default() -> StatusBuilderVersion { + StatusBuilderVersion::V0_13 + } +} + /// Builder for the `Status` object. #[derive(Default, Debug, Clone)] pub struct StatusBuilder { + version: StatusBuilderVersion, space: String, logo: Option, url: Option, @@ -263,6 +277,30 @@ impl StatusBuilder { } } + pub fn v0_13>(space_name: S) -> StatusBuilder { + StatusBuilder { + space: space_name.into(), + version: StatusBuilderVersion::V0_13, + ..Default::default() + } + } + + pub fn v14>(space_name: S) -> StatusBuilder { + StatusBuilder { + space: space_name.into(), + version: StatusBuilderVersion::V14, + ..Default::default() + } + } + + pub fn mixed>(space_name: S) -> StatusBuilder { + StatusBuilder { + space: space_name.into(), + version: StatusBuilderVersion::Mixed, + ..Default::default() + } + } + pub fn logo>(mut self, logo: S) -> Self { self.logo = Some(logo.into()); self @@ -331,8 +369,17 @@ impl StatusBuilder { } pub fn build(self) -> Result { + let api = match self.version { + StatusBuilderVersion::V0_13 | StatusBuilderVersion::Mixed => Some("0.13".to_owned()), + _ => None, + }; + let api_compatibility = match self.version { + StatusBuilderVersion::V14 | StatusBuilderVersion::Mixed => Some(vec![ApiVersion::V14]), + _ => None, + }; Ok(Status { - api: Some("0.13".into()), // TODO: Deduplicate + api, + api_compatibility, space: self.space, logo: self.logo.ok_or("logo missing")?, url: self.url.ok_or("url missing")?, From bc61509181d2475376a401d5dae8fa871ad12d9e Mon Sep 17 00:00:00 2001 From: Raphael Nestler Date: Tue, 10 Nov 2020 18:16:30 +0100 Subject: [PATCH 4/6] Update serialization example to use mixed version support --- examples/serialization.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/serialization.rs b/examples/serialization.rs index f8548ad..a3fa11b 100644 --- a/examples/serialization.rs +++ b/examples/serialization.rs @@ -3,7 +3,7 @@ use serde_json; use spaceapi::{Contact, IssueReportChannel, Location, StatusBuilder}; fn main() { - let status = StatusBuilder::new("coredump") + let status = StatusBuilder::mixed("coredump") .logo("https://www.coredump.ch/logo.png") .url("https://www.coredump.ch/") .location(Location { From 30c3a65e6a5f9d8a41cfa989e035f4ae2de3f93d Mon Sep 17 00:00:00 2001 From: Raphael Nestler Date: Tue, 10 Nov 2020 18:18:26 +0100 Subject: [PATCH 5/6] Announce v14 support in README and CHANGELOG --- CHANGELOG.md | 2 ++ README.md | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e380de..0bf5b74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ Possible log types: - [added] The `Sensors`, `PeopleNowPresentSensor` and `TemperatureSensor` structs now derive `Default` (#84) +- [added] Basic support for the new v14 API (#85) This is a breaking change since + it changes the `api` field of `Status` to `Option`. ### v0.7.0 (2019-08-22) diff --git a/README.md b/README.md index b5459a7..4fe0818 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Crates.io Version](https://img.shields.io/crates/v/spaceapi.svg)](https://crates.io/crates/spaceapi) [![Crates.io Downloads](https://img.shields.io/crates/d/spaceapi.svg)](https://crates.io/crates/spaceapi) -This is an implementation of the [SpaceAPI](https://spaceapi.io/) v0.13 +This is an implementation of the [SpaceAPI](https://spaceapi.io/) v0.13 and v14 in Rust. It contains both the type definitions as well as tools for serialization and deserialization to/from JSON using Serde. @@ -19,7 +19,7 @@ This library requires Rust 1.31.0 or newer. Add `spaceapi` to your `Cargo.toml`: [dependencies] - spaceapi = "^0.5" + spaceapi = "^0.7" ## Docs From 459bc788982ebd6d33e76fa2f799f175743676a1 Mon Sep 17 00:00:00 2001 From: Raphael Nestler Date: Sat, 14 Nov 2020 14:46:57 +0100 Subject: [PATCH 6/6] Add tests for v14 and mixed builder --- src/status.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/status.rs b/src/status.rs index 4b64346..783c52d 100644 --- a/src/status.rs +++ b/src/status.rs @@ -434,6 +434,54 @@ mod test { assert_eq!(a, b); } + #[test] + fn test_builder_v14() { + let status = StatusBuilder::v14("foo") + .logo("bar") + .url("foobar") + .location(Location::default()) + .contact(Contact::default()) + .add_issue_report_channel(IssueReportChannel::Email) + .build() + .unwrap(); + assert_eq!( + status, + Status { + api: None, + api_compatibility: Some(vec![ApiVersion::V14]), + space: "foo".into(), + logo: "bar".into(), + url: "foobar".into(), + issue_report_channels: vec![IssueReportChannel::Email], + ..Status::default() + } + ); + } + + #[test] + fn test_builder_mixed() { + let status = StatusBuilder::mixed("foo") + .logo("bar") + .url("foobar") + .location(Location::default()) + .contact(Contact::default()) + .add_issue_report_channel(IssueReportChannel::Email) + .build() + .unwrap(); + assert_eq!( + status, + Status { + api: Some("0.13".into()), + api_compatibility: Some(vec![ApiVersion::V14]), + space: "foo".into(), + logo: "bar".into(), + url: "foobar".into(), + issue_report_channels: vec![IssueReportChannel::Email], + ..Status::default() + } + ); + } + #[test] fn test_builder() { let status = StatusBuilder::new("foo")