From cb2b8339a6a037a869bd5ccc9681d92741806384 Mon Sep 17 00:00:00 2001 From: CodeSteak Date: Tue, 7 May 2019 17:36:32 +0200 Subject: [PATCH] partialy implement Query, also add date --- server/texture-sync-server/src/model/date.rs | 89 +++++++++++++++++++ server/texture-sync-server/src/model/mod.rs | 6 +- .../src/persistency/search/mod.rs | 82 +++++++++++++---- .../src/protocol/implementation/connection.rs | 1 + 4 files changed, 162 insertions(+), 16 deletions(-) create mode 100644 server/texture-sync-server/src/model/date.rs diff --git a/server/texture-sync-server/src/model/date.rs b/server/texture-sync-server/src/model/date.rs new file mode 100644 index 0000000..12e4b94 --- /dev/null +++ b/server/texture-sync-server/src/model/date.rs @@ -0,0 +1,89 @@ +use serde::de::Error; +use serde::Serialize; +use serde::{Deserialize, Deserializer, Serializer}; + +#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct Date { + pub year: u16, + pub month: u8, + pub day: u8, +} + +impl Date { + #[cfg(test)] + pub fn new(year: u16, month: u8, day: u8) -> Self { + Date { year, month, day } + } + + pub fn from_str(input: &str) -> Option { + let mut parts = input.splitn(3, "-"); + + let year = parts.next()?.parse::().ok()?; + let month = parts.next()?.parse::().ok()?; + let day = parts.next()?.parse::().ok()?; + + if month > 12 { + return None; + } + + if day > 31 { + return None; + } + + Some(Date { year, month, day }) + } +} + +impl Serialize for Date { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&format!( + "{:04}-{:02}-{:02}", + self.year, self.month, self.day + )) + } +} + +impl<'de> Deserialize<'de> for Date { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let data = String::deserialize(deserializer)?; + + match Date::from_str(&data) { + Some(date) => Ok(date), + None => Err(D::Error::custom( + "Expected a String in this format: YYYY-MM-DD.", + )), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn order() { + // Other Test not needed, since the Ord is derived. + assert!(Date::new(2019, 10, 10) > Date::new(2018, 10, 10)); + assert!(Date::new(2018, 11, 10) > Date::new(2018, 10, 10)); + assert!(Date::new(2018, 10, 11) > Date::new(2018, 10, 10)); + } + + #[test] + fn from_str() { + assert_eq!(Some(Date::new(2019, 10, 10)), Date::from_str("2019-10-10")); + assert_eq!(Some(Date::new(2019, 1, 1)), Date::from_str("2019-1-1")); + assert_eq!(None, Date::from_str("2019-1-1-444")); + assert_eq!( + Some(Date::new(2019, 1, 1)), + Date::from_str("2019-0000000000001-00000001") + ); + assert_eq!(None, Date::from_str("400-400-400")); + } + +} diff --git a/server/texture-sync-server/src/model/mod.rs b/server/texture-sync-server/src/model/mod.rs index 0f1851a..54477fd 100644 --- a/server/texture-sync-server/src/model/mod.rs +++ b/server/texture-sync-server/src/model/mod.rs @@ -8,6 +8,9 @@ use std::io; mod sha256; pub use sha256::Sha256; +mod date; +pub use date::Date; + mod texture_format; pub use texture_format::TextureFormat; @@ -17,7 +20,8 @@ pub struct Texture { pub name: String, pub tags: Vec, pub format: TextureFormat, - pub resolution: (usize, usize), + pub added_on: Date, + pub resolution: (u64, u64), pub texture_hash: Sha256, } diff --git a/server/texture-sync-server/src/persistency/search/mod.rs b/server/texture-sync-server/src/persistency/search/mod.rs index 1c5b5ec..16dada5 100644 --- a/server/texture-sync-server/src/persistency/search/mod.rs +++ b/server/texture-sync-server/src/persistency/search/mod.rs @@ -1,13 +1,7 @@ -// TODO: remove on implementation -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(dead_code)] - - use crate::model::*; pub struct Query { - filters: Vec, + filters: Vec, } pub type QueryParserResult = Result; @@ -17,6 +11,18 @@ pub enum QuerySyntaxError { impl Query { pub fn parse(input: &[String]) -> QueryParserResult { + let mut result = Query { filters: vec![] }; + + for fltr in input { + let qryfltr = Self::parse_single(fltr)?; + + result.filters.push(qryfltr); + } + + Ok(result) + } + + fn parse_single(input: &str) -> Result { unimplemented!() } } @@ -25,14 +31,60 @@ pub fn search(input: &[Texture], query: &Query) -> Vec { unimplemented!() } -enum QueryFilterModifier { - None(QueryFilter), - Not(QueryFilter), +enum QueryFilter { + Not(Box), + Tag(String), + SpecialInName(String), + SpecialBeforeDate(Date), + SpecialAfterDate(Date), + SpecialMinResolution(u64), } -enum QueryFilter { - TagName(String), - InName(String), - MinResolution(usize), - BeforeDate { year: u16, month: u16, day: u16 }, +enum Score { + RequiredMatch(bool), + Match(bool), +} + +use std::ops::Not; +impl Not for Score { + type Output = Score; + + fn not(self) -> Score { + match self { + Score::RequiredMatch(b) => Score::RequiredMatch(!b), + Score::Match(b) => Score::Match(!b), + } + } +} + +impl QueryFilter { + pub fn score(&self, texture: &Texture) -> Score { + use QueryFilter::*; + match self { + Not(inner) => inner.score(texture).not(), + + Tag(tag) => Score::Match( + texture + .tags + .iter() + .find(|tt| tt.to_lowercase() == tag.to_lowercase()) + .is_some(), + ), + + SpecialInName(name) => Score::RequiredMatch( + // + texture.name.contains(name), + ), + + SpecialBeforeDate(date) => Score::RequiredMatch(texture.added_on <= *date), + + SpecialAfterDate(date) => Score::RequiredMatch(texture.added_on > *date), + + SpecialMinResolution(required) => { + let smaller_resolution = u64::min(texture.resolution.0, texture.resolution.1); + + Score::RequiredMatch(smaller_resolution >= *required) + } + } + } } diff --git a/server/texture-sync-server/src/protocol/implementation/connection.rs b/server/texture-sync-server/src/protocol/implementation/connection.rs index f885a0d..adf3155 100644 --- a/server/texture-sync-server/src/protocol/implementation/connection.rs +++ b/server/texture-sync-server/src/protocol/implementation/connection.rs @@ -228,6 +228,7 @@ mod test { name: "texture.png".to_string(), tags: vec!["Wood".to_string(), "Hair".to_string()], format: TextureFormat::PNG, + added_on: Date::new(2019, 10, 12), resolution: (512, 512), texture_hash: Sha256(HASH_BYTES), }