From 0fe2b81a30eb829a2cc64243aba01a51b40cca01 Mon Sep 17 00:00:00 2001 From: BudiNverse Date: Thu, 6 Apr 2023 20:38:21 +0800 Subject: [PATCH 01/21] =?UTF-8?q?=F0=9F=9A=A8=20(#19)=20Removed=20serde=5F?= =?UTF-8?q?json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d42b067..e4a8a9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,9 +15,8 @@ exclude = [ [dependencies] serde = { version = "1.0.159", features = ["derive"] } serde_repr = "0.1.12" -serde_json = "1.0.95" regex = "1.7.3" -time = { version = "0.3.20", features = ["serde-human-readable"]} +time = { version = "0.3.20", features = ["serde-human-readable", "macros"]} lazy_static = "1.4.0" fast-float = { version = "0.2", optional = true } From d232bbc3f1cebb81453e558df18ff643156d7c11 Mon Sep 17 00:00:00 2001 From: BudiNverse Date: Thu, 6 Apr 2023 20:39:01 +0800 Subject: [PATCH 02/21] =?UTF-8?q?=F0=9F=93=88=20(#18)=20More=20comprehensi?= =?UTF-8?q?ve=20tests=20for=20`NextBus`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dumped_data/bus_arrival.json | 54 ++++++++++++++++++------------------ src/lib.rs | 32 ++++++++++++++++++--- src/utils.rs | 5 ++-- 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/dumped_data/bus_arrival.json b/dumped_data/bus_arrival.json index a6bbba3..ba744a9 100644 --- a/dumped_data/bus_arrival.json +++ b/dumped_data/bus_arrival.json @@ -8,9 +8,9 @@ "NextBus": { "OriginCode": "77009", "DestinationCode": "77009", - "EstimatedArrival": "2020-09-30T19:25:55+08:00", - "Latitude": "1.3319648333333334", - "Longitude": "103.9025555", + "EstimatedArrival": "2023-04-06T14:47:57+08:00", + "Latitude": "1.314452", + "Longitude": "103.910009", "VisitNumber": "1", "Load": "SEA", "Feature": "WAB", @@ -19,9 +19,9 @@ "NextBus2": { "OriginCode": "77009", "DestinationCode": "77009", - "EstimatedArrival": "2020-09-30T19:40:55+08:00", - "Latitude": "1.3449385", - "Longitude": "103.9371435", + "EstimatedArrival": "2023-04-06T14:59:26+08:00", + "Latitude": "1.331752", + "Longitude": "103.9025825", "VisitNumber": "1", "Load": "SEA", "Feature": "WAB", @@ -30,9 +30,9 @@ "NextBus3": { "OriginCode": "77009", "DestinationCode": "77009", - "EstimatedArrival": "2020-09-30T19:57:37+08:00", - "Latitude": "1.3692186666666668", - "Longitude": "103.94679866666667", + "EstimatedArrival": "2023-04-06T15:06:08+08:00", + "Latitude": "1.3380753333333333", + "Longitude": "103.91718033333333", "VisitNumber": "1", "Load": "SEA", "Feature": "WAB", @@ -45,9 +45,9 @@ "NextBus": { "OriginCode": "82009", "DestinationCode": "82009", - "EstimatedArrival": "2020-09-30T19:23:44+08:00", - "Latitude": "1.3184525", - "Longitude": "103.90032683333334", + "EstimatedArrival": "2023-04-06T14:53:27+08:00", + "Latitude": "1.3191575", + "Longitude": "103.905094", "VisitNumber": "1", "Load": "SEA", "Feature": "WAB", @@ -56,9 +56,9 @@ "NextBus2": { "OriginCode": "82009", "DestinationCode": "82009", - "EstimatedArrival": "2020-09-30T19:33:48+08:00", - "Latitude": "0", - "Longitude": "0", + "EstimatedArrival": "2023-04-06T15:04:06+08:00", + "Latitude": "0.0", + "Longitude": "0.0", "VisitNumber": "1", "Load": "SEA", "Feature": "WAB", @@ -67,9 +67,9 @@ "NextBus3": { "OriginCode": "82009", "DestinationCode": "82009", - "EstimatedArrival": "2020-09-30T19:48:48+08:00", - "Latitude": "0", - "Longitude": "0", + "EstimatedArrival": "2023-04-06T15:19:13+08:00", + "Latitude": "0.0", + "Longitude": "0.0", "VisitNumber": "1", "Load": "SEA", "Feature": "WAB", @@ -82,9 +82,9 @@ "NextBus": { "OriginCode": "52009", "DestinationCode": "84009", - "EstimatedArrival": "2020-09-30T19:21:28+08:00", - "Latitude": "1.3187676666666666", - "Longitude": "103.902475", + "EstimatedArrival": "2023-04-06T15:00:19+08:00", + "Latitude": "1.3185713333333333", + "Longitude": "103.892022", "VisitNumber": "1", "Load": "SDA", "Feature": "WAB", @@ -93,9 +93,9 @@ "NextBus2": { "OriginCode": "52009", "DestinationCode": "84009", - "EstimatedArrival": "2020-09-30T19:33:55+08:00", - "Latitude": "1.3196455", - "Longitude": "103.88187283333333", + "EstimatedArrival": "2023-04-06T15:14:27+08:00", + "Latitude": "1.3237508333333334", + "Longitude": "103.887032", "VisitNumber": "1", "Load": "SEA", "Feature": "WAB", @@ -104,9 +104,9 @@ "NextBus3": { "OriginCode": "52009", "DestinationCode": "84009", - "EstimatedArrival": "2020-09-30T19:50:46+08:00", - "Latitude": "1.3332161666666666", - "Longitude": "103.87857", + "EstimatedArrival": "2023-04-06T15:24:09+08:00", + "Latitude": "1.3332498333333334", + "Longitude": "103.87860283333333", "VisitNumber": "1", "Load": "SEA", "Feature": "WAB", diff --git a/src/lib.rs b/src/lib.rs index 42b26ff..62fe08b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,11 +90,12 @@ pub mod prelude { #[cfg(test)] mod tests { - use crate::{prelude::*, traffic::traffic_flow::TrafficFlowRawResp}; + use crate::{prelude::*, traffic::traffic_flow::TrafficFlowRawResp, bus_enums::{Operator, BusLoad, BusFeature, BusType}, bus::bus_arrival::NextBus}; use serde::{Deserialize, Serialize}; + use time::macros::datetime; use std::fmt::Debug; - fn generate_test<'de, I, S, F>(input_fn: F) + fn generate_test<'de, I, S, F>(input_fn: F) -> (String, S) where F: FnOnce() -> &'de str, I: Deserialize<'de> + Into, @@ -106,11 +107,12 @@ mod tests { .unwrap(); let ser = serde_json::to_string(&de).unwrap(); println!("{}", ser); + (ser, de) } macro_rules! gen_test { ($a:ty, $b:ty, $c:expr) => { - generate_test::<$a, $b, _>(|| include_str!($c)); + generate_test::<$a, $b, _>(|| include_str!($c)) }; } @@ -125,11 +127,33 @@ mod tests { #[test] fn bus_arrival() { - gen_test!( + let (_, bus) = gen_test!( RawBusArrivalResp, BusArrivalResp, "../dumped_data/bus_arrival.json" ); + + assert_eq!(bus.bus_stop_code, 83139); + assert_eq!(bus.services.len(), 3); + assert_eq!(bus.services[0].operator, Operator::GAS); + assert_eq!(bus.services[1].operator, Operator::SBST); + assert_eq!(bus.services[2].operator, Operator::SBST); + + let sample_data = NextBus { + origin_code: 77009, + dest_code: 77009, + est_arrival: datetime!(2023-04-06 14:47:57 +8), + lat: 1.314452, + long: 103.910009, + visit_no: 1, + load: BusLoad::SeatsAvailable, + feature: Some(BusFeature::WheelChairAccessible), + bus_type: BusType::SingleDecker + }; + + assert_eq!(bus.services[0].next_bus[0], Some(sample_data)); + + println!("{}", std::mem::size_of::()); } #[test] diff --git a/src/utils.rs b/src/utils.rs index ec12868..00fff1a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -215,7 +215,6 @@ pub mod de { use crate::utils::{regex::*, Coordinates, Location}; use serde::de::{self, Visitor}; use serde::{Deserialize, Deserializer}; - use serde_json::Value; use std::fmt::Formatter; /// Error for wrapped data @@ -239,8 +238,8 @@ pub mod de { T: Deserialize<'de>, D: Deserializer<'de>, { - let value: Value = Deserialize::deserialize(deserializer)?; - Ok(T::deserialize(value).ok()) + // let value: Value = Deserialize::deserialize(deserializer)?; + Ok(T::deserialize(deserializer).ok()) } /// Simple conversion of `Y`,`Yes` and `N`, `No` to boolean From b2c1121cde8d2ac9a3dbc06926c2879c52d1a5e5 Mon Sep 17 00:00:00 2001 From: BudiNverse Date: Sun, 9 Apr 2023 03:04:20 +0800 Subject: [PATCH 03/21] =?UTF-8?q?=F0=9F=94=96=20Fixes=20(#20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/rust.yml | 46 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 58ed0c8..6952f86 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -10,13 +10,13 @@ jobs: rust: [stable, nightly] steps: - - uses: rui314/setup-mold@v1 - - uses: hecrj/setup-rust-action@v1 - with: - rust-version: ${{ matrix.rust }} - - uses: actions/checkout@master - - name: Run tests - run: cargo check --verbose + - uses: rui314/setup-mold@v1 + - uses: hecrj/setup-rust-action@v1 + with: + rust-version: ${{ matrix.rust }} + - uses: actions/checkout@master + - name: Run tests + run: cargo check --verbose test: if: "!contains(github.event.head_commit.message, '[SKIP CI]')" @@ -27,13 +27,13 @@ jobs: rust: [stable, nightly] steps: - - uses: rui314/setup-mold@v1 - - uses: hecrj/setup-rust-action@v1 - with: - rust-version: ${{ matrix.rust }} - - uses: actions/checkout@master - - name: Run tests - run: cargo test --verbose + - uses: rui314/setup-mold@v1 + - uses: hecrj/setup-rust-action@v1 + with: + rust-version: ${{ matrix.rust }} + - uses: actions/checkout@master + - name: Run tests + run: cargo test --verbose test-fastfloat: if: "!contains(github.event.head_commit.message, '[SKIP CI]')" @@ -44,19 +44,18 @@ jobs: rust: [stable, nightly] steps: - - uses: rui314/setup-mold@v1 - - uses: hecrj/setup-rust-action@v1 - with: - rust-version: ${{ matrix.rust }} - - uses: actions/checkout@master - - name: Run tests - run: cargo test --verbose --features fastfloat + - uses: rui314/setup-mold@v1 + - uses: hecrj/setup-rust-action@v1 + with: + rust-version: ${{ matrix.rust }} + - uses: actions/checkout@master + - name: Run tests + run: cargo test --verbose --features fastfloat rustdoc: runs-on: ubuntu-latest - + needs: [check, test, test-fastfloat] steps: - - uses: rui314/setup-mold@v1 - name: Checkout repository uses: actions/checkout@v2 @@ -65,6 +64,7 @@ jobs: - name: Deploy Docs uses: peaceiris/actions-gh-pages@364c31d33bb99327c77b3a5438a83a357a6729ad # v3.4.0 + if: success() && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[SKIP CI]') with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_branch: gh-pages From f41dd1db2c349c61740deb1e2642cef5d7ee5142 Mon Sep 17 00:00:00 2001 From: BudiNverse Date: Sun, 9 Apr 2023 03:21:17 +0800 Subject: [PATCH 04/21] =?UTF-8?q?=F0=9F=92=9A=20(#24)=20Fix=20wrong=20usag?= =?UTF-8?q?e=20of=20semver=20in=20deprecated=20tag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bus.rs | 8 ++++---- src/crowd.rs | 12 ++++++------ src/lib.rs | 4 +++- src/taxi.rs | 4 ++-- src/traffic.rs | 22 +++++++++++----------- src/train.rs | 2 +- 6 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/bus.rs b/src/bus.rs index ac37f48..7f78d45 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -19,7 +19,7 @@ pub mod bus_arrival { #[cfg(feature = "fastfloat")] use crate::utils::de::from_str_fast_float; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/BusArrivalv2"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -130,7 +130,7 @@ pub mod bus_services { use crate::utils::regex::BUS_FREQ_RE; use serde::{Deserialize, Deserializer, Serialize}; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/BusServices"; /// Both min and max are in terms of minutes @@ -242,7 +242,7 @@ pub mod bus_routes { use crate::utils::de::from_str; use crate::utils::serde_date::str_time_option::{de_str_time_opt_br, ser_str_time_opt}; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/BusRoutes"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -322,7 +322,7 @@ pub mod bus_stops { use crate::utils::de::from_str; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/BusStops"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] diff --git a/src/crowd.rs b/src/crowd.rs index 64cf477..ea3515b 100644 --- a/src/crowd.rs +++ b/src/crowd.rs @@ -13,11 +13,11 @@ pub mod crowd_density { use serde::{Deserialize, Serialize}; use time::{serde::iso8601, OffsetDateTime}; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL_CROWD_DENSITY_RT: &str = "http://datamall2.mytransport.sg/ltaodataservice/PCDRealTime"; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL_CROWD_FORECAST: &str = "http://datamall2.mytransport.sg/ltaodataservice/PCDForecast"; @@ -105,17 +105,17 @@ pub mod crowd_density { pub mod passenger_vol { use serde::{Deserialize, Serialize}; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL_BY_BUS_STOPS: &str = "http://datamall2.mytransport.sg/ltaodataservice/PV/Bus"; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL_BY_OD_BUS_STOPS: &str = "http://datamall2.mytransport.sg/ltaodataservice/PV/ODBus"; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL_BY_TRAIN: &str = "http://datamall2.mytransport.sg/ltaodataservice/PV/Train"; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL_BY_OD_TRAIN: &str = "http://datamall2.mytransport.sg/ltaodataservice/PV/ODTrain"; pub const FORMAT: &str = "%Y%m"; diff --git a/src/lib.rs b/src/lib.rs index 62fe08b..c9fe008 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -153,7 +153,9 @@ mod tests { assert_eq!(bus.services[0].next_bus[0], Some(sample_data)); - println!("{}", std::mem::size_of::()); + println!("NextBus: {}", std::mem::size_of::()); + println!("BusLoad: {}", std::mem::size_of::()); + println!("BusFeature: {}", std::mem::size_of::()); } #[test] diff --git a/src/taxi.rs b/src/taxi.rs index 1c46bea..3768e7d 100644 --- a/src/taxi.rs +++ b/src/taxi.rs @@ -14,7 +14,7 @@ pub mod taxi_avail { use crate::utils::Coordinates; use serde::{Deserialize, Serialize}; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/Taxi-Availability"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -51,7 +51,7 @@ pub mod taxi_stands { use crate::utils::de::from_str_to_bool; use serde::{Deserialize, Serialize}; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/TaxiStands"; #[allow(clippy::upper_case_acronyms)] diff --git a/src/traffic.rs b/src/traffic.rs index 1e6c8b3..1683ffa 100644 --- a/src/traffic.rs +++ b/src/traffic.rs @@ -36,7 +36,7 @@ pub mod erp_rates { }, }; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/ERPRates"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -195,7 +195,7 @@ pub mod carpark_avail { use crate::utils::de::from_str_to_coords; use crate::utils::Coordinates; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/CarParkAvailabilityv2"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -256,7 +256,7 @@ pub mod est_travel_time { use serde::{Deserialize, Serialize}; use serde_repr::*; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/EstTravelTimes"; #[allow(clippy::upper_case_acronyms)] @@ -324,7 +324,7 @@ pub mod faulty_traffic_lights { use crate::utils::serde_date::ymd_hms_option; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/FaultyTrafficLights"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -374,11 +374,11 @@ pub mod road { use crate::utils::serde_date::str_date; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL_ROAD_OPENING: &str = "http://datamall2.mytransport.sg/ltaodataservice/RoadOpenings"; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL_ROAD_WORKS: &str = "http://datamall2.mytransport.sg/ltaodataservice/RoadWorks"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -426,7 +426,7 @@ pub mod traffic_images { use crate::utils::de::from_str; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/Traffic-Imagesv2"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -459,7 +459,7 @@ pub mod traffic_images { pub mod traffic_incidents { use serde::{Deserialize, Serialize}; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/TrafficIncidents"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -528,7 +528,7 @@ pub mod traffic_speed_bands { use crate::utils::de::from_str; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/TrafficSpeedBandsv2"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -604,7 +604,7 @@ pub mod traffic_speed_bands { pub mod vms_emas { use serde::{Deserialize, Serialize}; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/VMS"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -639,7 +639,7 @@ pub mod bike_parking { use crate::utils::de::from_str_to_bool; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/BicycleParkingv2"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] diff --git a/src/train.rs b/src/train.rs index 920d760..682ff74 100644 --- a/src/train.rs +++ b/src/train.rs @@ -257,7 +257,7 @@ pub mod train_service_alert { use std::ops::Deref; use std::str::FromStr; - #[deprecated(since = "0.5", note = "Will be removed in future versions")] + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/TrainServiceAlerts"; #[allow(clippy::upper_case_acronyms)] From f2675f384dfc4cd24187e871f3fbf2ea96886255 Mon Sep 17 00:00:00 2001 From: BudiNverse Date: Sun, 9 Apr 2023 03:24:05 +0800 Subject: [PATCH 05/21] =?UTF-8?q?=F0=9F=92=9A=20(#24)=20Fixed=20fallible?= =?UTF-8?q?=20from=20impl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/crowd.rs | 4 ++-- src/lib.rs | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/crowd.rs b/src/crowd.rs index ea3515b..f31eeff 100644 --- a/src/crowd.rs +++ b/src/crowd.rs @@ -96,8 +96,8 @@ pub mod crowd_density { } impl From for CrowdDensityForecast { - fn from(mut data: CrowdDensityForecastRawResp) -> Self { - data.value.pop().unwrap() + fn from(data: CrowdDensityForecastRawResp) -> Self { + data.value[0].clone() } } } diff --git a/src/lib.rs b/src/lib.rs index c9fe008..96f8403 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,7 +47,6 @@ clippy::option_option, clippy::path_buf_push_overwrite, clippy::ptr_as_ptr, - clippy::pub_enum_variant_names, clippy::ref_option_ref, clippy::rest_pat_in_fully_bound_structs, clippy::same_functions_in_if_condition, @@ -62,7 +61,6 @@ clippy::unused_self, clippy::useless_transmute, clippy::verbose_file_reads, - clippy::wrong_pub_self_convention, clippy::zero_sized_map_values, future_incompatible, nonstandard_style, From ab6cffd099e4fc8b9e25c3fbcb492e901f790518 Mon Sep 17 00:00:00 2001 From: BudiNverse Date: Sun, 9 Apr 2023 03:43:28 +0800 Subject: [PATCH 06/21] =?UTF-8?q?=F0=9F=94=92=EF=B8=8F=20(#22)=20Added=20f?= =?UTF-8?q?astfloat=20impl=20for=20other=20f64=20conversion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 2 +- src/bus.rs | 24 +++++++++--------------- src/taxi.rs | 5 +++++ src/traffic.rs | 17 ++++++++++++----- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e4a8a9b..d8f2aac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lta_models" -version = "0.5.0" +version = "0.6.0" authors = ["budinverse "] edition = "2021" license = "MIT" diff --git a/src/bus.rs b/src/bus.rs index 7f78d45..44d4b0e 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -11,7 +11,7 @@ pub mod prelude { pub mod bus_arrival { use serde::{Deserialize, Serialize}; - use time::{OffsetDateTime, serde::iso8601}; + use time::{serde::iso8601, OffsetDateTime}; use crate::bus_enums::{BusFeature, BusLoad, BusType, Operator}; use crate::utils::de::{from_str, treat_error_as_none}; @@ -67,25 +67,19 @@ pub mod bus_arrival { #[serde(deserialize_with = "from_str", alias = "DestinationCode")] pub dest_code: u32, - + /// Time in GMT+8 #[serde(alias = "EstimatedArrival", deserialize_with = "iso8601::deserialize")] pub est_arrival: OffsetDateTime, - #[cfg(feature = "fastfloat")] - #[serde(deserialize_with = "from_str_fast_float", alias = "Latitude")] - pub lat: f64, - - #[cfg(feature = "fastfloat")] - #[serde(deserialize_with = "from_str_fast_float", alias = "Longitude")] - pub long: f64, - - #[cfg(not(feature = "fastfloat"))] - #[serde(deserialize_with = "from_str", alias = "Latitude")] + #[serde(alias = "Latitude")] + #[cfg_attr(not(feature = "fastfloat"), serde(deserialize_with = "from_str"))] + #[cfg_attr(feature = "fastfloat", serde(deserialize_with = "from_str_fast_float"))] pub lat: f64, - #[cfg(not(feature = "fastfloat"))] - #[serde(deserialize_with = "from_str", alias = "Longitude")] + #[serde(alias = "Longitude")] + #[cfg_attr(not(feature = "fastfloat"), serde(deserialize_with = "from_str"))] + #[cfg_attr(feature = "fastfloat", serde(deserialize_with = "from_str_fast_float"))] pub long: f64, #[serde(deserialize_with = "from_str", alias = "VisitNumber")] @@ -129,7 +123,7 @@ pub mod bus_services { use crate::utils::de::from_str_error_as_none; use crate::utils::regex::BUS_FREQ_RE; use serde::{Deserialize, Deserializer, Serialize}; - + #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/BusServices"; diff --git a/src/taxi.rs b/src/taxi.rs index 3768e7d..b53e2b7 100644 --- a/src/taxi.rs +++ b/src/taxi.rs @@ -19,9 +19,12 @@ pub mod taxi_avail { #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct InternalCoordinates { + + /// Original data already float #[serde(alias = "Longitude")] pub long: f64, + /// Original data already float #[serde(alias = "Latitude")] pub lat: f64, } @@ -82,9 +85,11 @@ pub mod taxi_stands { pub struct TaxiStand { pub taxi_code: String, + /// Original data already float #[serde(alias = "Latitude")] pub lat: f64, + /// Original data already float #[serde(alias = "Longitude")] pub long: f64, diff --git a/src/traffic.rs b/src/traffic.rs index 1683ffa..ece1cf4 100644 --- a/src/traffic.rs +++ b/src/traffic.rs @@ -527,6 +527,9 @@ pub mod traffic_speed_bands { use serde::{Deserialize, Serialize}; use crate::utils::de::from_str; + + #[cfg(feature = "fastfloat")] + use crate::utils::de::from_str_fast_float; #[deprecated(since = "0.5.0", note = "Will be removed in future versions")] pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/TrafficSpeedBandsv2"; @@ -575,17 +578,21 @@ pub mod traffic_speed_bands { #[serde(alias = "MaximumSpeed", deserialize_with = "from_str")] pub max_speed: u32, - - #[serde(deserialize_with = "from_str")] + + #[cfg_attr(not(feature = "fastfloat"), serde(deserialize_with = "from_str"))] + #[cfg_attr(feature = "fastfloat", serde(deserialize_with = "from_str_fast_float"))] pub start_lon: f64, - #[serde(deserialize_with = "from_str")] + #[cfg_attr(not(feature = "fastfloat"), serde(deserialize_with = "from_str"))] + #[cfg_attr(feature = "fastfloat", serde(deserialize_with = "from_str_fast_float"))] pub start_lat: f64, - #[serde(deserialize_with = "from_str")] + #[cfg_attr(not(feature = "fastfloat"), serde(deserialize_with = "from_str"))] + #[cfg_attr(feature = "fastfloat", serde(deserialize_with = "from_str_fast_float"))] pub end_lon: f64, - #[serde(deserialize_with = "from_str")] + #[cfg_attr(not(feature = "fastfloat"), serde(deserialize_with = "from_str"))] + #[cfg_attr(feature = "fastfloat", serde(deserialize_with = "from_str_fast_float"))] pub end_lat: f64 } From 07eb3ceead545895dcc6f5acc4d8dce105995921 Mon Sep 17 00:00:00 2001 From: BudiNverse Date: Sun, 9 Apr 2023 04:10:50 +0800 Subject: [PATCH 07/21] =?UTF-8?q?=F0=9F=94=92=EF=B8=8F=20(#25)=20Reduced?= =?UTF-8?q?=20BusServices=20to=2096=20bytes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bus.rs | 20 +++++++++++--------- src/lib.rs | 19 ++++++++++++++----- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/bus.rs b/src/bus.rs index 44d4b0e..f5e72ea 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -119,6 +119,8 @@ pub mod bus_arrival { } pub mod bus_services { + use std::num::NonZeroU32; + use crate::bus_enums::{BusCategory, Operator}; use crate::utils::de::from_str_error_as_none; use crate::utils::regex::BUS_FREQ_RE; @@ -130,21 +132,21 @@ pub mod bus_services { /// Both min and max are in terms of minutes #[derive(Debug, Clone, PartialEq, Serialize)] pub struct BusFreq { - pub min: Option, - pub max: Option, + pub min: Option, + pub max: Option, } impl BusFreq { pub fn new(min: u32, max: u32) -> Self { BusFreq { - min: Some(min), - max: Some(max), + min: Some(NonZeroU32::new(min).unwrap()), + max: Some(NonZeroU32::new(max).unwrap()), } } pub fn no_max(min: u32) -> Self { BusFreq { - min: Some(min), + min: Some(NonZeroU32::new(min).unwrap()), max: None, } } @@ -171,15 +173,15 @@ pub mod bus_services { pub operator: Operator, #[serde(alias = "Direction")] - pub no_direction: u32, + pub no_direction: u8, pub category: BusCategory, #[serde(deserialize_with = "from_str_error_as_none")] - pub origin_code: Option, + pub origin_code: Option, #[serde(deserialize_with = "from_str_error_as_none", alias = "DestinationCode")] - pub dest_code: Option, + pub dest_code: Option, #[serde(alias = "AM_Peak_Freq", deserialize_with = "from_str_to_bus_freq")] pub am_peak_freq: BusFreq, @@ -193,7 +195,7 @@ pub mod bus_services { #[serde(alias = "PM_Offpeak_Freq", deserialize_with = "from_str_to_bus_freq")] pub pm_offpeak_freq: BusFreq, - pub loop_desc: Option, + pub loop_desc: String, } fn from_str_to_bus_freq<'de, D>(deserializer: D) -> Result diff --git a/src/lib.rs b/src/lib.rs index 96f8403..879e57e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,10 +88,15 @@ pub mod prelude { #[cfg(test)] mod tests { - use crate::{prelude::*, traffic::traffic_flow::TrafficFlowRawResp, bus_enums::{Operator, BusLoad, BusFeature, BusType}, bus::bus_arrival::NextBus}; + use crate::{ + bus::{bus_arrival::NextBus, bus_services::BusFreq}, + bus_enums::{BusFeature, BusLoad, BusType, Operator}, + prelude::*, + traffic::traffic_flow::TrafficFlowRawResp, + }; use serde::{Deserialize, Serialize}; - use time::macros::datetime; use std::fmt::Debug; + use time::macros::datetime; fn generate_test<'de, I, S, F>(input_fn: F) -> (String, S) where @@ -130,7 +135,7 @@ mod tests { BusArrivalResp, "../dumped_data/bus_arrival.json" ); - + assert_eq!(bus.bus_stop_code, 83139); assert_eq!(bus.services.len(), 3); assert_eq!(bus.services[0].operator, Operator::GAS); @@ -146,7 +151,7 @@ mod tests { visit_no: 1, load: BusLoad::SeatsAvailable, feature: Some(BusFeature::WheelChairAccessible), - bus_type: BusType::SingleDecker + bus_type: BusType::SingleDecker, }; assert_eq!(bus.services[0].next_bus[0], Some(sample_data)); @@ -168,8 +173,12 @@ mod tests { Vec, "../dumped_data/bus_services.json" ); - } + + println!("Sz BusService: {}", std::mem::size_of::()); + println!("Sz BusFreq: {}", std::mem::size_of::()); + } + #[test] fn bus_stops() { gen_test!(BusStopsResp, Vec, "../dumped_data/bus_stops.json"); From 3d277628a03ca75884703488066fc4498bd5c240 Mon Sep 17 00:00:00 2001 From: BudiNverse Date: Sun, 9 Apr 2023 04:19:43 +0800 Subject: [PATCH 08/21] =?UTF-8?q?=F0=9F=94=92=EF=B8=8F=20(#25)=20Changed?= =?UTF-8?q?=20redundant=20Option=20type=20for=20BusFeature?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bus.rs | 4 ++-- src/lib.rs | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/bus.rs b/src/bus.rs index f5e72ea..d0b3e31 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -83,11 +83,11 @@ pub mod bus_arrival { pub long: f64, #[serde(deserialize_with = "from_str", alias = "VisitNumber")] - pub visit_no: u32, + pub visit_no: u8, pub load: BusLoad, - pub feature: Option, + pub feature: BusFeature, #[serde(alias = "Type")] pub bus_type: BusType, diff --git a/src/lib.rs b/src/lib.rs index 879e57e..b8b9604 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,7 +96,7 @@ mod tests { }; use serde::{Deserialize, Serialize}; use std::fmt::Debug; - use time::macros::datetime; + use time::{macros::datetime, OffsetDateTime}; fn generate_test<'de, I, S, F>(input_fn: F) -> (String, S) where @@ -150,7 +150,7 @@ mod tests { long: 103.910009, visit_no: 1, load: BusLoad::SeatsAvailable, - feature: Some(BusFeature::WheelChairAccessible), + feature: BusFeature::WheelChairAccessible, bus_type: BusType::SingleDecker, }; @@ -159,6 +159,7 @@ mod tests { println!("NextBus: {}", std::mem::size_of::()); println!("BusLoad: {}", std::mem::size_of::()); println!("BusFeature: {}", std::mem::size_of::()); + println!("OffsetDateTime: {}", std::mem::size_of::()); } #[test] From 5a7f604e6e093a6c81e01a8d3a3af91714d6384c Mon Sep 17 00:00:00 2001 From: BudiNverse Date: Sun, 9 Apr 2023 21:20:41 +0800 Subject: [PATCH 09/21] =?UTF-8?q?=F0=9F=9A=A8=20Partially=20fix=20(#26),?= =?UTF-8?q?=20Added=20(#21)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 1 + benches/benchmark.rs | 155 ++++++++++++++++------------- src/bus.rs | 217 +++++++++++++++++++++++++++++++--------- src/bus_enums.rs | 42 ++++---- src/crowd.rs | 83 +++++++++++----- src/facility.rs | 2 +- src/geo.rs | 2 +- src/lib.rs | 171 +++++++++++++++++++++++++++----- src/taxi.rs | 45 +++++++-- src/traffic.rs | 230 +++++++++++++++++++++++++++++++++++-------- src/train.rs | 6 +- src/utils.rs | 92 +++-------------- 12 files changed, 738 insertions(+), 308 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d8f2aac..b338acb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ fast-float = { version = "0.2", optional = true } [dev-dependencies] serde_json = "1.0.40" +bincode = "1.3.3" criterion = "0.3" mimalloc = "0.1.25" diff --git a/benches/benchmark.rs b/benches/benchmark.rs index 3aca0a4..a7770fc 100644 --- a/benches/benchmark.rs +++ b/benches/benchmark.rs @@ -1,13 +1,16 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use lta_models::{bus::bus_arrival::NextBusRaw, prelude::*}; use mimalloc::MiMalloc; +use time::macros::datetime; #[global_allocator] static GLOBAL: MiMalloc = MiMalloc; #[rustfmt::skip] mod de { - use lta_models::{prelude::*, crowd::crowd_density::{CrowdDensityForecast, CrowdDensityForecastRawResp}}; + use lta_models::prelude::*; + use lta_models::bus::bus_arrival::NextBusRaw; use serde::{Deserialize, Serialize}; pub fn generate_bench<'de, I, S, F>(input_fn: F) -> S @@ -34,23 +37,23 @@ mod de { gen!(RawBusArrivalResp, _, "../dumped_data/bus_arrival.json") } - pub fn bus_routes() -> Vec { + pub fn bus_routes() -> Vec { gen!(BusRouteResp, _, "../dumped_data/bus_route.json") } - pub fn bus_service() -> Vec { + pub fn bus_service() -> Vec { gen!(BusServiceResp, _, "../dumped_data/bus_services.json") } - pub fn bus_stops() -> Vec { + pub fn bus_stops() -> Vec { gen!(BusStopsResp, _, "../dumped_data/bus_stops.json") } - pub fn carpark_avail() -> Vec { + pub fn carpark_avail() -> Vec { gen!(CarparkAvailResp, _, "../dumped_data/carpark_avail.json") } - pub fn erp_rates() -> Vec { + pub fn erp_rates() -> Vec { gen!(ErpRatesResp, _, "../dumped_data/erp_rates.json") } @@ -78,7 +81,7 @@ mod de { gen!(TaxiAvailResp, _, "../dumped_data/taxi_avail.json") } - pub fn taxi_stands() -> Vec { + pub fn taxi_stands() -> Vec { gen!(TaxiStandsResp, _, "../dumped_data/taxi_stands.json") } @@ -86,77 +89,97 @@ mod de { gen!(TrainServiceAlertResp,_,"../dumped_data/train_service_alert.json") } - pub fn est_travel_time() -> Vec { + pub fn est_travel_time() -> Vec { gen!(EstTravelTimeResp, _, "../dumped_data/est_travel_time.json") } - pub fn crowd_density_rt() -> Vec { + pub fn crowd_density_rt() -> Vec { gen!(StationCrowdLevelRawResp, _, "../dumped_data/crowd_density_rt.json") } - pub fn crowd_density_forecast() -> CrowdDensityForecast { + pub fn crowd_density_forecast() -> CrowdDensityForecastRaw { gen!(CrowdDensityForecastRawResp, _, "../dumped_data/crowd_density_forecast.json") } + + pub fn transmute_nextbus(data: NextBusRaw) -> NextBus { + let nx = unsafe { + std::mem::transmute::<_, NextBus>(data) + }; + nx + } } #[rustfmt::skip] pub fn criterion_benchmark(c: &mut Criterion) { - c.bench_function("de::bike_parking.json", |b| b.iter(|| de::bike_parking())); - c.bench_function("de::bus_arrival.json", |b| b.iter(|| de::bus_arrival())); - c.bench_function("de::bus_route.json", |b| b.iter(|| de::bus_routes())); - c.bench_function("de::bus_services.json", |b| b.iter(|| de::bus_service())); - c.bench_function("de::bus_stops.json", |b| b.iter(|| de::bus_stops())); - c.bench_function("de::carpark_avail.json", |b| b.iter(|| de::carpark_avail())); - c.bench_function("de::erp_rates.json", |b| b.iter(|| de::erp_rates())); - c.bench_function("de::est_travel_time.json", |b| b.iter(|| de::est_travel_time())); - c.bench_function("de::faulty_traffic_lights.json", |b| b.iter(|| de::faulty_traffic_lights())); - c.bench_function("de::passenger_vol_bus_stops.json", |b| b.iter(|| de::passenger_vol_bus_stops())); - c.bench_function("de::passenger_od_bus_stops.json", |b| b.iter(|| de::passenger_vol_od_bus_stops())); - c.bench_function("de::passenger_vol_od_train.json", |b| b.iter(|| de::passenger_vol_od_train())); - c.bench_function("de::passenger_vol_train.json", |b| b.iter(|| de::passenger_vol_train())); - c.bench_function("de::taxi_avail.json", |b| b.iter(|| de::taxi_avail())); - c.bench_function("de::taxi_stands.json", |b| b.iter(|| de::taxi_stands())); - c.bench_function("de::train_service_alert.json", |b| b.iter(|| de::train_service_alert())); - c.bench_function("de::crowd_density_rt.json", |b| b.iter(|| de::crowd_density_rt())); - c.bench_function("de::crowd_density_forecast.json", |b| b.iter(|| de::crowd_density_forecast())); - - let bike_parking = de::bike_parking(); - let bus_arrival = de::bus_arrival(); - let bus_routes = de::bus_routes(); - let bus_service = de::bus_service(); - let bus_stops = de::bus_stops(); - let carpark_avail = de::carpark_avail(); - let erp_rates = de::erp_rates(); - let est_travel_time = de::est_travel_time(); - let faulty_traffic_lights = de::faulty_traffic_lights(); - let passenger_vol_bus_stops = de::passenger_vol_bus_stops(); - let passenger_vol_od_bus_stops = de::passenger_vol_od_bus_stops(); - let passenger_vol_train = de::passenger_vol_train(); - let passenger_vol_od_train = de::passenger_vol_od_train(); - let taxi_avail = de::taxi_avail(); - let taxi_stands = de::taxi_stands(); - let train_service_alert = de::train_service_alert(); - let crowd_density_rt = de::crowd_density_rt(); - let crowd_density_forecast = de::crowd_density_forecast(); - - c.bench_function("ser::bike_parking.json", |b| b.iter(|| serde_json::to_string(black_box(&bike_parking)))); - c.bench_function("ser::bus_arrival.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_arrival)))); - c.bench_function("ser::bus_route.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_routes)))); - c.bench_function("ser::bus_services.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_service)))); - c.bench_function("ser::bus_stops.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_stops)))); - c.bench_function("ser::carpark_avail.json", |b| b.iter(|| serde_json::to_string(black_box(&carpark_avail)))); - c.bench_function("ser::erp_rates.json", |b| b.iter(|| serde_json::to_string(black_box(&erp_rates)))); - c.bench_function("ser::est_travel_time.json", |b| b.iter(|| serde_json::to_string(black_box(&est_travel_time)))); - c.bench_function("ser::faulty_traffic_lights.json", |b| b.iter(|| serde_json::to_string(black_box(&faulty_traffic_lights)))); - c.bench_function("ser::passenger_vol_bus_stops.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_bus_stops)))); - c.bench_function("ser::passenger_od_bus_stops.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_od_bus_stops)))); - c.bench_function("ser::passenger_vol_od_train.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_od_train)))); - c.bench_function("ser::passenger_vol_train.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_train)))); - c.bench_function("ser::taxi_avail.json", |b| b.iter(|| serde_json::to_string(black_box(&taxi_avail)))); - c.bench_function("ser::taxi_stands.json", |b| b.iter(|| serde_json::to_string(black_box(&taxi_stands)))); - c.bench_function("ser::train_service_alert.json", |b| b.iter(|| serde_json::to_string(black_box(&train_service_alert)))); - c.bench_function("ser::crowd_density_rt.json", |b| b.iter(|| serde_json::to_string(black_box(&crowd_density_rt)))); - c.bench_function("ser::crowd_density_forecast.json", |b| b.iter(|| serde_json::to_string(black_box(&crowd_density_forecast)))); + let sample_data = NextBusRaw { + origin_code: 77009, + dest_code: 77009, + est_arrival: datetime!(2023-04-06 14:47:57 +8), + lat: 1.314452, + long: 103.910009, + visit_no: 1, + load: BusLoad::SeatsAvailable, + feature: BusFeature::WheelChairAccessible, + bus_type: BusType::SingleDecker, + }; + c.bench_function("transmute_nextbus", |b| b.iter(|| de::transmute_nextbus(black_box(sample_data.clone())))); + c.bench_function("into_nextbus", |b| b.iter(|| NextBus::from(black_box(sample_data.clone())))); + // c.bench_function("de::bike_parking.json", |b| b.iter(|| de::bike_parking())); + // c.bench_function("de::bus_arrival.json", |b| b.iter(|| de::bus_arrival())); + // c.bench_function("de::bus_route.json", |b| b.iter(|| de::bus_routes())); + // c.bench_function("de::bus_services.json", |b| b.iter(|| de::bus_service())); + // c.bench_function("de::bus_stops.json", |b| b.iter(|| de::bus_stops())); + // c.bench_function("de::carpark_avail.json", |b| b.iter(|| de::carpark_avail())); + // c.bench_function("de::erp_rates.json", |b| b.iter(|| de::erp_rates())); + // c.bench_function("de::est_travel_time.json", |b| b.iter(|| de::est_travel_time())); + // c.bench_function("de::faulty_traffic_lights.json", |b| b.iter(|| de::faulty_traffic_lights())); + // c.bench_function("de::passenger_vol_bus_stops.json", |b| b.iter(|| de::passenger_vol_bus_stops())); + // c.bench_function("de::passenger_od_bus_stops.json", |b| b.iter(|| de::passenger_vol_od_bus_stops())); + // c.bench_function("de::passenger_vol_od_train.json", |b| b.iter(|| de::passenger_vol_od_train())); + // c.bench_function("de::passenger_vol_train.json", |b| b.iter(|| de::passenger_vol_train())); + // c.bench_function("de::taxi_avail.json", |b| b.iter(|| de::taxi_avail())); + // c.bench_function("de::taxi_stands.json", |b| b.iter(|| de::taxi_stands())); + // c.bench_function("de::train_service_alert.json", |b| b.iter(|| de::train_service_alert())); + // c.bench_function("de::crowd_density_rt.json", |b| b.iter(|| de::crowd_density_rt())); + // c.bench_function("de::crowd_density_forecast.json", |b| b.iter(|| de::crowd_density_forecast())); + + // let bike_parking = de::bike_parking(); + // let bus_arrival = de::bus_arrival(); + // let bus_routes = de::bus_routes(); + // let bus_service = de::bus_service(); + // let bus_stops = de::bus_stops(); + // let carpark_avail = de::carpark_avail(); + // let erp_rates = de::erp_rates(); + // let est_travel_time = de::est_travel_time(); + // let faulty_traffic_lights = de::faulty_traffic_lights(); + // let passenger_vol_bus_stops = de::passenger_vol_bus_stops(); + // let passenger_vol_od_bus_stops = de::passenger_vol_od_bus_stops(); + // let passenger_vol_train = de::passenger_vol_train(); + // let passenger_vol_od_train = de::passenger_vol_od_train(); + // let taxi_avail = de::taxi_avail(); + // let taxi_stands = de::taxi_stands(); + // let train_service_alert = de::train_service_alert(); + // let crowd_density_rt = de::crowd_density_rt(); + // let crowd_density_forecast = de::crowd_density_forecast(); + + // c.bench_function("ser::bike_parking.json", |b| b.iter(|| serde_json::to_string(black_box(&bike_parking)))); + // c.bench_function("ser::bus_arrival.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_arrival)))); + // c.bench_function("ser::bus_route.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_routes)))); + // c.bench_function("ser::bus_services.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_service)))); + // c.bench_function("ser::bus_stops.json", |b| b.iter(|| serde_json::to_string(black_box(&bus_stops)))); + // c.bench_function("ser::carpark_avail.json", |b| b.iter(|| serde_json::to_string(black_box(&carpark_avail)))); + // c.bench_function("ser::erp_rates.json", |b| b.iter(|| serde_json::to_string(black_box(&erp_rates)))); + // c.bench_function("ser::est_travel_time.json", |b| b.iter(|| serde_json::to_string(black_box(&est_travel_time)))); + // c.bench_function("ser::faulty_traffic_lights.json", |b| b.iter(|| serde_json::to_string(black_box(&faulty_traffic_lights)))); + // c.bench_function("ser::passenger_vol_bus_stops.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_bus_stops)))); + // c.bench_function("ser::passenger_od_bus_stops.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_od_bus_stops)))); + // c.bench_function("ser::passenger_vol_od_train.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_od_train)))); + // c.bench_function("ser::passenger_vol_train.json", |b| b.iter(|| serde_json::to_string(black_box(&passenger_vol_train)))); + // c.bench_function("ser::taxi_avail.json", |b| b.iter(|| serde_json::to_string(black_box(&taxi_avail)))); + // c.bench_function("ser::taxi_stands.json", |b| b.iter(|| serde_json::to_string(black_box(&taxi_stands)))); + // c.bench_function("ser::train_service_alert.json", |b| b.iter(|| serde_json::to_string(black_box(&train_service_alert)))); + // c.bench_function("ser::crowd_density_rt.json", |b| b.iter(|| serde_json::to_string(black_box(&crowd_density_rt)))); + // c.bench_function("ser::crowd_density_forecast.json", |b| b.iter(|| serde_json::to_string(black_box(&crowd_density_forecast)))); } criterion_group!(benches, criterion_benchmark); diff --git a/src/bus.rs b/src/bus.rs index d0b3e31..331d48e 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -2,16 +2,16 @@ pub mod prelude { pub use { - crate::bus::bus_arrival::{BusArrivalResp, RawBusArrivalResp}, + crate::bus::bus_arrival::{BusArrivalResp, NextBus, RawBusArrivalResp}, crate::bus::bus_routes::{BusRoute, BusRouteResp}, - crate::bus::bus_services::{BusService, BusServiceResp}, + crate::bus::bus_services::{BusFreq, BusService, BusServiceResp}, crate::bus::bus_stops::{BusStop, BusStopsResp}, }; } pub mod bus_arrival { use serde::{Deserialize, Serialize}; - use time::{serde::iso8601, OffsetDateTime}; + use time::{serde::iso8601, serde::timestamp, OffsetDateTime}; use crate::bus_enums::{BusFeature, BusLoad, BusType, Operator}; use crate::utils::de::{from_str, treat_error_as_none}; @@ -23,29 +23,26 @@ pub mod bus_arrival { pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/BusArrivalv2"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] - #[serde(rename_all(deserialize = "PascalCase"))] + #[serde(rename_all = "PascalCase")] pub struct RawArrivalBusService { pub service_no: String, pub operator: Operator, #[serde(deserialize_with = "treat_error_as_none")] - pub next_bus: Option, + pub next_bus: Option, #[serde(deserialize_with = "treat_error_as_none")] - pub next_bus_2: Option, + pub next_bus_2: Option, #[serde(deserialize_with = "treat_error_as_none")] - pub next_bus_3: Option, + pub next_bus_3: Option, } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] - #[serde(rename_all(deserialize = "PascalCase"))] pub struct ArrivalBusService { pub service_no: String, - pub operator: Operator, - pub next_bus: [Option; 3], } @@ -54,35 +51,43 @@ pub mod bus_arrival { Self { service_no: data.service_no, operator: data.operator, - next_bus: [data.next_bus, data.next_bus_2, data.next_bus_3], + next_bus: [ + data.next_bus.map(Into::into), + data.next_bus_2.map(Into::into), + data.next_bus_3.map(Into::into), + ], } } } #[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize, Serialize)] - #[serde(rename_all(deserialize = "PascalCase"))] - pub struct NextBus { + #[serde(rename_all = "PascalCase")] + pub struct NextBusRaw { #[serde(deserialize_with = "from_str")] pub origin_code: u32, - #[serde(deserialize_with = "from_str", alias = "DestinationCode")] + #[serde(deserialize_with = "from_str", rename = "DestinationCode")] pub dest_code: u32, /// Time in GMT+8 - #[serde(alias = "EstimatedArrival", deserialize_with = "iso8601::deserialize")] + #[serde( + rename = "EstimatedArrival", + deserialize_with = "iso8601::deserialize", + serialize_with = "iso8601::serialize" + )] pub est_arrival: OffsetDateTime, - #[serde(alias = "Latitude")] + #[serde(rename = "Latitude")] #[cfg_attr(not(feature = "fastfloat"), serde(deserialize_with = "from_str"))] #[cfg_attr(feature = "fastfloat", serde(deserialize_with = "from_str_fast_float"))] pub lat: f64, - #[serde(alias = "Longitude")] + #[serde(rename = "Longitude")] #[cfg_attr(not(feature = "fastfloat"), serde(deserialize_with = "from_str"))] #[cfg_attr(feature = "fastfloat", serde(deserialize_with = "from_str_fast_float"))] pub long: f64, - #[serde(deserialize_with = "from_str", alias = "VisitNumber")] + #[serde(deserialize_with = "from_str", rename = "VisitNumber")] pub visit_no: u8, pub load: BusLoad, @@ -93,8 +98,40 @@ pub mod bus_arrival { pub bus_type: BusType, } + #[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize, Serialize)] + pub struct NextBus { + pub origin_code: u32, + pub dest_code: u32, + /// Time in GMT+8 + #[serde(with = "timestamp")] + pub est_arrival: OffsetDateTime, + pub lat: f64, + pub long: f64, + pub visit_no: u8, + pub load: BusLoad, + pub feature: BusFeature, + pub bus_type: BusType, + } + + impl From for NextBus { + #[inline(always)] + fn from(r: NextBusRaw) -> Self { + Self { + origin_code: r.origin_code, + dest_code: r.dest_code, + est_arrival: r.est_arrival, + lat: r.lat, + long: r.long, + visit_no: r.visit_no, + load: r.load, + feature: r.feature, + bus_type: r.bus_type, + } + } + } + #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] - #[serde(rename_all(deserialize = "PascalCase"))] + #[serde(rename_all = "PascalCase")] pub struct RawBusArrivalResp { #[serde(deserialize_with = "from_str")] pub bus_stop_code: u32, @@ -102,7 +139,6 @@ pub mod bus_arrival { } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] - #[serde(rename_all(deserialize = "PascalCase"))] pub struct BusArrivalResp { pub bus_stop_code: u32, pub services: Vec, @@ -119,7 +155,7 @@ pub mod bus_arrival { } pub mod bus_services { - use std::num::NonZeroU32; + use std::num::NonZeroU8; use crate::bus_enums::{BusCategory, Operator}; use crate::utils::de::from_str_error_as_none; @@ -130,23 +166,23 @@ pub mod bus_services { pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/BusServices"; /// Both min and max are in terms of minutes - #[derive(Debug, Clone, PartialEq, Serialize)] + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct BusFreq { - pub min: Option, - pub max: Option, + pub min: Option, + pub max: Option, } impl BusFreq { - pub fn new(min: u32, max: u32) -> Self { + pub fn new(min: u8, max: u8) -> Self { BusFreq { - min: Some(NonZeroU32::new(min).unwrap()), - max: Some(NonZeroU32::new(max).unwrap()), + min: Some(NonZeroU8::new(min).unwrap()), + max: Some(NonZeroU8::new(max).unwrap()), } } - pub fn no_max(min: u32) -> Self { + pub fn no_max(min: u8) -> Self { BusFreq { - min: Some(NonZeroU32::new(min).unwrap()), + min: Some(NonZeroU8::new(min).unwrap()), max: None, } } @@ -166,8 +202,8 @@ pub mod bus_services { } #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] - #[serde(rename_all(deserialize = "PascalCase"))] - pub struct BusService { + #[serde(rename_all = "PascalCase")] + pub struct BusServiceRaw { pub service_no: String, pub operator: Operator, @@ -178,10 +214,10 @@ pub mod bus_services { pub category: BusCategory, #[serde(deserialize_with = "from_str_error_as_none")] - pub origin_code: Option, + pub origin_code: Option, #[serde(deserialize_with = "from_str_error_as_none", alias = "DestinationCode")] - pub dest_code: Option, + pub dest_code: Option, #[serde(alias = "AM_Peak_Freq", deserialize_with = "from_str_to_bus_freq")] pub am_peak_freq: BusFreq, @@ -198,6 +234,21 @@ pub mod bus_services { pub loop_desc: String, } + #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] + pub struct BusService { + pub service_no: String, + pub operator: Operator, + pub no_direction: u8, + pub category: BusCategory, + pub origin_code: Option, + pub dest_code: Option, + pub am_peak_freq: BusFreq, + pub am_offpeak_freq: BusFreq, + pub pm_peak_freq: BusFreq, + pub pm_offpeak_freq: BusFreq, + pub loop_desc: String, + } + fn from_str_to_bus_freq<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, @@ -219,14 +270,32 @@ pub mod bus_services { Ok(bus_freq) } + impl From for BusService { + fn from(r: BusServiceRaw) -> Self { + Self { + service_no: r.service_no, + operator: r.operator, + no_direction: r.no_direction, + category: r.category, + origin_code: r.origin_code, + dest_code: r.dest_code, + am_offpeak_freq: r.am_offpeak_freq, + am_peak_freq: r.am_peak_freq, + pm_offpeak_freq: r.pm_offpeak_freq, + pm_peak_freq: r.pm_peak_freq, + loop_desc: r.loop_desc, + } + } + } + #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct BusServiceResp { - pub value: Vec, + pub value: Vec, } impl From for Vec { fn from(data: BusServiceResp) -> Self { - data.value + data.value.into_iter().map(Into::into).collect() } } } @@ -242,16 +311,16 @@ pub mod bus_routes { pub const URL: &str = "http://datamall2.mytransport.sg/ltaodataservice/BusRoutes"; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] - #[serde(rename_all(deserialize = "PascalCase"))] - pub struct BusRoute { + #[serde(rename_all = "PascalCase")] + pub struct BusRouteRaw { pub service_no: String, pub operator: Operator, - pub direction: u32, + pub direction: u8, #[serde(alias = "StopSequence")] - pub stop_seq: u32, + pub stop_seq: u8, #[serde(deserialize_with = "from_str")] pub bus_stop_code: u32, @@ -302,14 +371,50 @@ pub mod bus_routes { pub sun_last: Option