From 90b3ae1f709f24cb95f92bf7e6e726173d491a60 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 1 Sep 2017 19:29:30 +0200 Subject: [PATCH] Add base types for the API --- lib/entry/libimagentrygps/Cargo.toml | 2 + lib/entry/libimagentrygps/src/error.rs | 11 +- lib/entry/libimagentrygps/src/lib.rs | 8 ++ lib/entry/libimagentrygps/src/types.rs | 156 +++++++++++++++++++++++++ 4 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 lib/entry/libimagentrygps/src/types.rs diff --git a/lib/entry/libimagentrygps/Cargo.toml b/lib/entry/libimagentrygps/Cargo.toml index c6c45a87..32232a26 100644 --- a/lib/entry/libimagentrygps/Cargo.toml +++ b/lib/entry/libimagentrygps/Cargo.toml @@ -12,6 +12,8 @@ license = "LGPL-2.1" [dependencies] toml = "^0.4" toml-query = "0.3.0" +serde_derive = "1" +serde = "1" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/entry/libimagentrygps/src/error.rs b/lib/entry/libimagentrygps/src/error.rs index bbf8be95..3c52e307 100644 --- a/lib/entry/libimagentrygps/src/error.rs +++ b/lib/entry/libimagentrygps/src/error.rs @@ -24,7 +24,16 @@ generate_error_module!( HeaderWriteError => "Couldn't write Header for annotation", HeaderReadError => "Couldn't read Header of Entry", - HeaderTypeError => "Header field has unexpected type" + HeaderTypeError => "Header field has unexpected type", + + TypeError => "Type Error", + DegreeMissing => "'degree' value missing", + MinutesMissing => "'minutes' value missing", + SecondsMissing => "'seconds' value missing", + LongitudeMissing => "'longitude' value missing", + LatitudeMissing => "'latitude' value missing", + + NumberConversionError => "Cannot convert number to fit into variable" ); ); diff --git a/lib/entry/libimagentrygps/src/lib.rs b/lib/entry/libimagentrygps/src/lib.rs index 511ba3f2..40fbf5e4 100644 --- a/lib/entry/libimagentrygps/src/lib.rs +++ b/lib/entry/libimagentrygps/src/lib.rs @@ -17,6 +17,14 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +extern crate toml; +extern crate toml_query; +#[macro_use] extern crate serde_derive; + +extern crate libimagstore; +#[macro_use] extern crate libimagerror; + pub mod error; pub mod result; +pub mod types; diff --git a/lib/entry/libimagentrygps/src/types.rs b/lib/entry/libimagentrygps/src/types.rs new file mode 100644 index 00000000..32412000 --- /dev/null +++ b/lib/entry/libimagentrygps/src/types.rs @@ -0,0 +1,156 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +use std::collections::BTreeMap; + +use toml::Value; + +use libimagerror::into::IntoError; + +use error::GPSErrorKind as GPSEK; +use result::Result; + +pub trait FromValue : Sized { + fn from_value(v: &Value) -> Result; +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct GPSValue { + pub degree: i8, + pub minutes: i8, + pub seconds: i8 +} + +impl GPSValue { + + pub fn new(d: i8, m: i8, s: i8) -> GPSValue { + GPSValue { + degree: d, + minutes: m, + seconds: s + } + } +} + + +impl Into for GPSValue { + + fn into(self) -> Value { + let mut map = BTreeMap::new(); + let _ = map.insert("degree".to_owned(), Value::Integer(self.degree as i64)); + let _ = map.insert("minutes".to_owned(), Value::Integer(self.minutes as i64)); + let _ = map.insert("seconds".to_owned(), Value::Integer(self.seconds as i64)); + Value::Table(map) + } + +} + +impl FromValue for GPSValue { + fn from_value(v: &Value) -> Result { + match *v { + Value::Table(ref map) => { + Ok(GPSValue::new( + map.get("degree") + .ok_or_else(|| GPSEK::DegreeMissing.into_error()) + .and_then(|v| match *v { + Value::Integer(i) => i64_to_i8(i), + _ => Err(GPSEK::HeaderTypeError.into_error()), + })?, + + map + .get("minutes") + .ok_or_else(|| GPSEK::MinutesMissing.into_error()) + .and_then(|v| match *v { + Value::Integer(i) => i64_to_i8(i), + _ => Err(GPSEK::HeaderTypeError.into_error()), + })?, + + map + .get("seconds") + .ok_or_else(|| GPSEK::SecondsMissing.into_error()) + .and_then(|v| match *v { + Value::Integer(i) => i64_to_i8(i), + _ => Err(GPSEK::HeaderTypeError.into_error()), + })? + )) + } + _ => Err(GPSEK::TypeError.into_error()) + } + } + +} + +/// Data-transfer type for transfering longitude-latitude-pairs +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct Coordinates { + pub longitude: GPSValue, + pub latitude: GPSValue, +} + +impl Coordinates { + pub fn new(long: GPSValue, lat: GPSValue) -> Coordinates { + Coordinates { + longitude: long, + latitude: lat, + } + } +} + +impl Into for Coordinates { + + fn into(self) -> Value { + let mut map = BTreeMap::new(); + let _ = map.insert("longitude".to_owned(), self.longitude.into()); + let _ = map.insert("latitude".to_owned(), self.latitude.into()); + Value::Table(map) + } + +} + +impl FromValue for Coordinates { + fn from_value(v: &Value) -> Result { + match *v { + Value::Table(ref map) => { + Ok(Coordinates::new( + match map.get("longitude") { + Some(v) => GPSValue::from_value(v), + None => Err(GPSEK::LongitudeMissing.into_error()), + }?, + + match map.get("latitude") { + Some(v) => GPSValue::from_value(v), + None => Err(GPSEK::LongitudeMissing.into_error()), + }? + )) + } + _ => Err(GPSEK::TypeError.into_error()) + } + } + +} + +/// Helper to convert a i64 to i8 or return an error if this doesn't work. +fn i64_to_i8(i: i64) -> Result { + if i > (::max_value() as i64) { + Err(GPSEK::NumberConversionError.into_error()) + } else { + Ok(i as i8) + } +} +