#![deny(
// missing_docs,
missing_debug_implementations,
missing_copy_implementations,
trivial_casts,
trivial_numeric_casts,
unsafe_code,
unstable_features,
unused_import_braces,
unused_qualifications
)]
use crate::entity_type::EntityType;
use crate::error::WikibaseError;
use crate::from_json;
use serde::ser::{SerializeStruct, Serializer};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Coordinate(Coordinate),
MonoLingual(MonoLingualText),
Entity(EntityValue),
EntitySchema(EntityValue),
Quantity(QuantityValue),
StringValue(String),
Time(TimeValue),
}
impl Serialize for Value {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Value::Coordinate(v) => serializer.serialize_some(&v),
Value::MonoLingual(v) => serializer.serialize_some(&v),
Value::Entity(v) => serializer.serialize_some(&v),
Value::EntitySchema(v) => serializer.serialize_some(&v),
Value::Quantity(v) => serializer.serialize_some(&v),
Value::StringValue(v) => serializer.serialize_some(&v),
Value::Time(v) => serializer.serialize_some(&v),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Coordinate {
altitude: Option<f64>,
globe: String,
latitude: f64,
longitude: f64,
precision: Option<f64>,
}
impl Coordinate {
pub fn new_from_json(
object: &serde_json::Map<String, serde_json::Value>,
) -> Result<Coordinate, WikibaseError> {
let mut altitude = None;
let mut precision = None;
if !object["altitude"].is_null() {
let altitude_string = match object["altitude"].as_str() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Altitude".to_string())),
};
let altitude_number: f64 = match altitude_string.parse() {
Ok(value) => value,
Err(error) => {
return Err(WikibaseError::Serialization(error.to_string()));
}
};
altitude = Some(altitude_number);
}
let latitude = match object["latitude"].as_f64() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Latitude".to_string())),
};
let longitude = match object["longitude"].as_f64() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Longitude".to_string())),
};
if !object["precision"].is_null() {
precision = match object["precision"].as_f64() {
Some(value) => Some(value),
None => return Err(WikibaseError::Serialization("Precision".to_string())),
};
}
let globe = match object["globe"].as_str() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Globe".to_string())),
};
Ok(Self {
altitude,
globe: globe.to_string(),
latitude,
longitude,
precision,
})
}
pub fn new(
altitude: Option<f64>,
globe: String,
latitude: f64,
longitude: f64,
precision: Option<f64>,
) -> Coordinate {
Self {
altitude,
globe,
latitude,
longitude,
precision,
}
}
pub fn altitude(&self) -> &Option<f64> {
&self.altitude
}
pub fn globe(&self) -> &str {
&self.globe
}
pub fn latitude(&self) -> &f64 {
&self.latitude
}
pub fn longitude(&self) -> &f64 {
&self.longitude
}
pub fn precision(&self) -> &Option<f64> {
&self.precision
}
pub fn set_altitude(&mut self, altitude: Option<f64>) {
self.altitude = altitude;
}
pub fn set_globe<S: Into<String>>(&mut self, globe: S) {
self.globe = globe.into();
}
pub fn set_latitude(&mut self, latitude: f64) {
self.latitude = latitude;
}
pub fn set_longitude(&mut self, longitude: f64) {
self.longitude = longitude;
}
pub fn set_precision(&mut self, precision: Option<f64>) {
self.precision = precision;
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MonoLingualText {
language: String,
text: String,
}
impl MonoLingualText {
pub fn new_from_json(
object: &serde_json::Map<String, serde_json::Value>,
) -> Result<MonoLingualText, WikibaseError> {
let language = match object["language"].as_str() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Language".to_string())),
};
let text = match object["text"].as_str() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Text".to_string())),
};
Ok(Self {
language: language.to_string(),
text: text.to_string(),
})
}
pub fn new<S: Into<String>>(text: S, language: S) -> MonoLingualText {
Self {
text: text.into(),
language: language.into(),
}
}
pub fn language(&self) -> &str {
&self.language
}
pub fn set_language<S: Into<String>>(&mut self, language: S) {
self.language = language.into();
}
pub fn set_text<S: Into<String>>(&mut self, text: S) {
self.text = text.into();
}
pub fn text(&self) -> &str {
&self.text
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct QuantityValue {
amount: f64,
lower_bound: Option<f64>,
unit: String,
upper_bound: Option<f64>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct EntityValue {
entity_type: EntityType,
id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct TimeValue {
after: u64,
before: u64,
calendarmodel: String,
precision: u64,
time: String,
timezone: u64,
}
impl QuantityValue {
pub fn new_from_object(
value: &serde_json::Map<String, serde_json::Value>,
) -> Result<QuantityValue, WikibaseError> {
let amount = match from_json::float_from_json(value, "amount") {
Some(value) => value,
None => return Err(WikibaseError::Serialization(format!("Amount: {value:?}"))),
};
let lower_bound = from_json::float_from_json(value, "lowerBound");
let upper_bound = from_json::float_from_json(value, "upperBound");
Ok(Self {
amount,
lower_bound,
unit: value["unit"].as_str().unwrap_or("").to_string(),
upper_bound,
})
}
pub fn new<S: Into<String>>(
amount: f64,
lower_bound: Option<f64>,
unit: S,
upper_bound: Option<f64>,
) -> QuantityValue {
Self {
amount,
lower_bound,
unit: unit.into(),
upper_bound,
}
}
pub fn amount(&self) -> &f64 {
&self.amount
}
pub fn lower_bound(&self) -> &Option<f64> {
&self.lower_bound
}
pub fn set_amount(&mut self, amount: f64) {
self.amount = amount;
}
pub fn set_lower_bound(&mut self, lower_bound: Option<f64>) {
self.lower_bound = lower_bound;
}
pub fn set_unit<S: Into<String>>(&mut self, unit: S) {
self.unit = unit.into();
}
pub fn set_upper_bound(&mut self, upper_bound: Option<f64>) {
self.upper_bound = upper_bound;
}
pub fn unit(&self) -> &str {
&self.unit
}
pub fn upper_bound(&self) -> &Option<f64> {
&self.upper_bound
}
}
impl TimeValue {
pub fn new_from_object(value: &serde_json::Map<String, serde_json::Value>) -> TimeValue {
Self {
after: value["after"].as_u64().unwrap_or(0),
before: value["before"].as_u64().unwrap_or(0),
calendarmodel: value["calendarmodel"].as_str().unwrap_or("").to_string(),
precision: value["precision"].as_u64().unwrap_or(0),
time: value["time"].as_str().unwrap_or("").to_string(),
timezone: value["timezone"].as_u64().unwrap_or(0),
}
}
pub fn new<S: Into<String>>(
after: u64,
before: u64,
calendarmodel: S,
precision: u64,
time: S,
timezone: u64,
) -> TimeValue {
Self {
after,
before,
calendarmodel: calendarmodel.into(),
precision,
time: time.into(),
timezone,
}
}
pub fn after(&self) -> &u64 {
&self.after
}
pub fn before(&self) -> &u64 {
&self.before
}
pub fn calendarmodel(&self) -> &str {
&self.calendarmodel
}
pub fn precision(&self) -> &u64 {
&self.precision
}
pub fn set_after(&mut self, after: u64) {
self.after = after;
}
pub fn set_before(&mut self, before: u64) {
self.before = before;
}
pub fn set_calendarmodel<S: Into<String>>(&mut self, calendarmodel: S) {
self.calendarmodel = calendarmodel.into();
}
pub fn set_precision(&mut self, precision: u64) {
self.precision = precision;
}
pub fn set_time<S: Into<String>>(&mut self, time: S) {
self.time = time.into();
}
pub fn set_timezone(&mut self, timezone: u64) {
self.timezone = timezone;
}
pub fn time(&self) -> &str {
&self.time
}
pub fn timezone(&self) -> &u64 {
&self.timezone
}
}
impl EntityValue {
pub fn new<S: Into<String>>(entity_type: EntityType, id: S) -> EntityValue {
Self {
entity_type,
id: id.into(),
}
}
pub fn new_from_object(
value: &serde_json::Map<String, serde_json::Value>,
) -> Result<EntityValue, WikibaseError> {
let entity_type_string = match value["entity-type"].as_str() {
Some(value) => value,
None => {
return Err(WikibaseError::Serialization(
"Entity type is not a string".to_string(),
));
}
};
let entity_type = match EntityType::new_from_str(entity_type_string) {
Some(value) => value,
None => {
return Err(WikibaseError::Serialization(format!(
"Entity type did not match: {}",
&entity_type_string
)));
}
};
let id = match value["id"].as_str() {
Some(value) => value,
None => {
return Err(WikibaseError::Serialization(
"Id is not a string".to_string(),
));
}
};
Ok(Self {
entity_type,
id: id.to_string(),
})
}
pub fn entity_type(&self) -> &EntityType {
&self.entity_type
}
pub fn id(&self) -> &str {
&self.id
}
pub fn set_entity_type(&mut self, entity_type: EntityType) {
self.entity_type = entity_type;
}
pub fn set_id<S: Into<String>>(&mut self, id: S) {
self.id = id.into();
}
}
impl Serialize for EntityValue {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("EntityValue", 2)?;
state.serialize_field("entity-type", &self.entity_type)?;
state.serialize_field("id", &self.id)?;
state.end()
}
}