#![cfg(not(tarpaulin_include))]
use std::borrow::Cow;
use geo::Geometry;
use serde_json::{Map, Value};
#[cfg(feature = "self-contained")]
use bincode::{
de::{BorrowDecoder, Decoder},
error::DecodeError,
BorrowDecode, Decode, Encode,
};
use crate::{
base::types::Float,
geo::shared::{
get_geojson_features_from_string, simplify_geometry, CanGetGeoJsonFeaturesFromSource, EncodableGeometry, EncodableOptionString, EncodableString, HasGeometry, HasProperties, IdFeaturePair,
},
};
use super::shared::IsTimezone;
#[cfg(not(feature = "extrasimplified"))]
const SIMPLIFICATION_EPSILON: Float = 0.00001;
#[cfg(feature = "extrasimplified")]
const SIMPLIFICATION_EPSILON: Float = 0.001;
#[cfg(not(target_family = "wasm"))]
pub fn get_geojson_features_from_source() -> geojson::FeatureCollection {
let response = reqwest::blocking::get(ADDRESS).unwrap();
let geojson_input = response.text().unwrap();
get_geojson_features_from_string(&geojson_input)
}
pub static ADDRESS: &str = "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_10m_time_zones.geojson";
pub static TIMEZONE_BINCODE_DESTINATION_NAME: &str = "ned_time_zones.bincode";
pub static LOOKUP_BINCODE_DESTINATION_NAME: &str = "ned_time_zone_lookup.bincode";
#[derive(Debug)]
#[cfg_attr(feature = "self-contained", derive(Encode))]
pub struct NedTimezone {
pub id: usize,
pub identifier: EncodableOptionString,
pub description: EncodableString,
pub dst_description: EncodableOptionString,
pub offset: EncodableString,
pub zone: f32,
pub raw_offset: i32,
pub geometry: EncodableGeometry,
}
#[cfg(feature = "self-contained")]
impl Decode for NedTimezone {
fn decode<D>(decoder: &mut D) -> Result<Self, DecodeError>
where
D: Decoder,
{
let id = usize::decode(decoder)?;
let identifier = EncodableOptionString::decode(decoder)?;
let description = EncodableString::decode(decoder)?;
let dst_description = EncodableOptionString::decode(decoder)?;
let offset = EncodableString::decode(decoder)?;
let zone = f32::decode(decoder)?;
let raw_offset = i32::decode(decoder)?;
let geometry = EncodableGeometry::decode(decoder)?;
Ok(NedTimezone {
id,
identifier,
description,
dst_description,
offset,
zone,
raw_offset,
geometry,
})
}
}
#[cfg(feature = "self-contained")]
impl<'de> BorrowDecode<'de> for NedTimezone
where
'de: 'static,
{
fn borrow_decode<D>(decoder: &mut D) -> Result<Self, DecodeError>
where
D: BorrowDecoder<'de>,
{
let id = usize::decode(decoder)?;
let identifier = EncodableOptionString::borrow_decode(decoder)?;
let description = EncodableString::borrow_decode(decoder)?;
let dst_description = EncodableOptionString::borrow_decode(decoder)?;
let offset = EncodableString::borrow_decode(decoder)?;
let zone = f32::decode(decoder)?;
let raw_offset = i32::decode(decoder)?;
let geometry = EncodableGeometry::borrow_decode(decoder)?;
Ok(NedTimezone {
id,
identifier,
description,
dst_description,
offset,
zone,
raw_offset,
geometry,
})
}
}
impl PartialEq for NedTimezone {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl From<IdFeaturePair> for NedTimezone {
fn from(value: IdFeaturePair) -> NedTimezone {
let id = value.0;
let properties = value.1.properties.as_ref().unwrap();
let geometry = value.1.geometry.as_ref().unwrap();
let dst_places = EncodableOptionString(properties.get("dst_places").unwrap().as_str().map(ToOwned::to_owned).map(Cow::Owned));
let places = EncodableString(Cow::Owned(properties.get("places").unwrap().as_str().unwrap().to_owned()));
let time_zone = EncodableString(Cow::Owned(properties.get("time_zone").unwrap().as_str().unwrap().to_owned()));
let tz_name1st = EncodableOptionString(properties.get("tz_name1st").unwrap().as_str().map(ToOwned::to_owned).map(Cow::Owned));
let zone = properties.get("zone").unwrap().as_f64().unwrap() as f32;
let geometry: Geometry<Float> = geometry.value.clone().try_into().unwrap();
let geometry = EncodableGeometry(simplify_geometry(geometry, SIMPLIFICATION_EPSILON));
let raw_offset = (zone * 3600.0).round() as i32;
NedTimezone {
id,
dst_description: dst_places,
description: places,
offset: time_zone,
identifier: tz_name1st,
zone,
raw_offset,
geometry,
}
}
}
impl IsTimezone for NedTimezone {
fn identifier(&self) -> &str {
self.identifier.as_deref().unwrap_or("")
}
}
impl HasGeometry for NedTimezone {
fn id(&self) -> usize {
self.id
}
fn geometry(&self) -> &Geometry<Float> {
&self.geometry.0
}
}
impl HasProperties for NedTimezone {
fn properties(&self) -> Map<String, Value> {
let mut properties = Map::new();
properties.insert("dst_description".to_string(), Value::String(self.dst_description.as_deref().unwrap_or("").to_string()));
properties.insert("description".to_string(), Value::String(self.description.to_string()));
properties.insert("offset".to_string(), Value::String(self.offset.to_string()));
properties.insert("zone".to_string(), Value::Number(serde_json::Number::from_f64(self.zone as f64).unwrap()));
properties.insert("raw_offset".to_string(), Value::Number(serde_json::Number::from_f64(self.raw_offset as f64).unwrap()));
properties
}
}
#[cfg(not(target_family = "wasm"))]
impl CanGetGeoJsonFeaturesFromSource for NedTimezone {
fn get_geojson_features_from_source() -> geojson::FeatureCollection {
get_geojson_features_from_source()
}
}