-
-
Notifications
You must be signed in to change notification settings - Fork 81
Implemented classifier transform #67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
9706d8b
progress on classifier transform
ErikBjare 4b2981b
added classify as a query function
ErikBjare 50b3b3e
added query test for classify, changed tuple order
ErikBjare cdd61b1
fixed issue in travis config
ErikBjare 2747c2f
renamed Event::new_test -> Event::new (and removed test-specific beha…
ErikBjare b2543c0
avoided unecessary clone
ErikBjare 41dd23d
prefixed computed data properties with '$', implemented Default trait…
ErikBjare 32b0374
fixed test
ErikBjare 391186f
added test for classifying event without matching category
ErikBjare 4f059d5
started splitting classify into categorize and autotag
ErikBjare 825f50b
added categorize as a query2 function
ErikBjare 8540430
added proper/extended parsing of category rules
ErikBjare eefda15
made tag function fully functional in query2, changed to using TryFro…
ErikBjare 73b52bf
moved all DataType-related things to seperate file, removed unused im…
ErikBjare f65d6ec
cleaned up TryFrom traits
ErikBjare 7bf15f5
removed old way of specifying rules for categorize and tag
ErikBjare File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,247 @@ | ||
| use std::collections::HashMap; | ||
| use std::fmt; | ||
| use std::convert::{TryFrom,TryInto}; | ||
|
|
||
| use crate::models::Event; | ||
| use crate::transform::classify::Rule; | ||
| use super::QueryError; | ||
| use super::functions; | ||
|
|
||
| use serde::Serializer; | ||
| use serde_json::value::Value; | ||
| use serde_json::Number; | ||
|
|
||
|
|
||
| // TODO: greater/less comparisons | ||
|
|
||
| #[derive(Clone,Serialize)] | ||
| #[serde(untagged)] | ||
| pub enum DataType { | ||
| None(), | ||
| Bool(bool), | ||
| Number(f64), | ||
| String(String), | ||
| Event(Event), | ||
| List(Vec<DataType>), | ||
| Dict(HashMap<String, DataType>), | ||
| #[serde(serialize_with = "serialize_function")] | ||
| Function(String, functions::QueryFn), | ||
| } | ||
|
|
||
| fn serialize_function<S>(_element: &String, _fun: &functions::QueryFn, _serializer: S) -> Result<S::Ok, S::Error> | ||
| where S: Serializer | ||
| { | ||
| panic!("Query function was unevaluated and was attempted to be serialized, panic!"); | ||
| //element.id.serialize(serializer) | ||
| } | ||
|
|
||
|
|
||
| // Needed because of a limitation in rust where you cannot derive(Debug) on a | ||
| // enum which has a fn with reference parameters which our QueryFn has | ||
| // https://stackoverflow.com/questions/53380040/function-pointer-with-a-reference-argument-cannot-derive-debug | ||
| impl fmt::Debug for DataType { | ||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| match self { | ||
| DataType::None() => write!(f, "None()"), | ||
| DataType::Bool(b) => write!(f, "Bool({})", b), | ||
| DataType::Number(n) => write!(f, "Number({})", n), | ||
| DataType::String(s) => write!(f, "String({})", s), | ||
| DataType::Event(e) => write!(f, "Event({:?})", e), | ||
| DataType::List(l) => write!(f, "List({:?})", l), | ||
| DataType::Dict(d) => write!(f, "Dict({:?})", d), | ||
| DataType::Function(name, _fun) => write!(f, "Function({})", name), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /* Like eq, but raises an error when comparing between different types. | ||
| * Should be used as often as possible */ | ||
| impl DataType { | ||
| pub fn query_eq(&self, other: &DataType) -> Result<bool, QueryError> { | ||
| match (self, other) { | ||
| // TODO: Comparisons of bool == num, bool == str | ||
| (DataType::None(), DataType::None()) => Ok(false), | ||
| (DataType::Bool(b1), DataType::Bool(b2)) => Ok(b1 == b2), | ||
| (DataType::Number(n1), DataType::Number(n2)) => Ok(n1 == n2), | ||
| (DataType::String(s1), DataType::String(s2)) => Ok(s1 == s2), | ||
| (DataType::Event(e1), DataType::Event(e2)) => Ok(e1 == e2), | ||
| (DataType::List(l1), DataType::List(l2)) => Ok(l1 == l2), | ||
| (DataType::Dict(d1), DataType::Dict(d2)) => Ok(d1 == d2), | ||
| // We do not care about comparing functions | ||
| _ => Err(QueryError::InvalidType(format!("Cannot compare values of different types {:?} and {:?}", self, other))), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /* Required for query_eq when comparing two dicts */ | ||
| impl PartialEq for DataType { | ||
| fn eq(&self, other: &DataType) -> bool { | ||
| match (self, other) { | ||
| (DataType::None(), DataType::None()) => true, | ||
| // TODO: Comparisons of bool == num, bool == str | ||
| (DataType::Bool(b1), DataType::Bool(b2)) => b1 == b2, | ||
| (DataType::Number(n1), DataType::Number(n2)) => n1 == n2, | ||
| (DataType::String(s1), DataType::String(s2)) => s1 == s2, | ||
| (DataType::Event(e1), DataType::Event(e2)) => e1 == e2, | ||
| (DataType::List(l1), DataType::List(l2)) => l1 == l2, | ||
| (DataType::Dict(d1), DataType::Dict(d2)) => d1 == d2, | ||
| // We do not care about comparing functions | ||
| _ => false | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&DataType> for Vec<DataType> { | ||
| type Error = QueryError; | ||
| fn try_from(value: &DataType) -> Result<Self, Self::Error> { | ||
| match value { | ||
| DataType::List(ref s) => Ok(s.clone()), | ||
| ref invalid_type => Err(QueryError::InvalidFunctionParameters( | ||
| format!("Expected function parameter of type List, got {:?}", invalid_type) | ||
| )) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&DataType> for String { | ||
| type Error = QueryError; | ||
| fn try_from(value: &DataType) -> Result<Self, Self::Error> { | ||
| match value { | ||
| DataType::String(s) => Ok(s.clone()), | ||
| ref invalid_type => Err(QueryError::InvalidFunctionParameters( | ||
| format!("Expected function parameter of type List of Strings, list contains {:?}", invalid_type) | ||
| )) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&DataType> for Vec<String> { | ||
| type Error = QueryError; | ||
| fn try_from(value: &DataType) -> Result<Self, Self::Error> { | ||
| let mut tagged_strings: Vec<DataType> = value.try_into()?; | ||
| let mut strings = Vec::new(); | ||
| for string in tagged_strings.drain(..) { | ||
| let s: String = (&string).try_into()?; | ||
| strings.push(s); | ||
| } | ||
| return Ok(strings); | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&DataType> for Rule { | ||
| type Error = QueryError; | ||
| fn try_from(value: &DataType) -> Result<Self, Self::Error> { | ||
| let rulemap: HashMap<String, String> = (match value { | ||
| DataType::Dict(d) => { | ||
| let map: HashMap<String, String> = d.iter().map(|(k, v)| { | ||
| let s: String = v.try_into().unwrap(); | ||
| (k.clone(), s.clone()) | ||
| }).collect(); | ||
| Ok(map) | ||
| }, | ||
| _ => Err(QueryError::InvalidFunctionParameters( | ||
| format!("Expected rule, found something else") | ||
| )) | ||
| })?; | ||
| Ok(Rule::from(rulemap)) | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&DataType> for Vec<Event> { | ||
| type Error = QueryError; | ||
| fn try_from(value: &DataType) -> Result<Self, Self::Error> { | ||
| let mut tagged_events: Vec<DataType> = value.try_into()?; | ||
| let mut events = Vec::new(); | ||
| for event in tagged_events.drain(..) { | ||
| match event { | ||
| DataType::Event(e) => events.push(e.clone()), | ||
| ref invalid_type => return Err(QueryError::InvalidFunctionParameters( | ||
| format!("Expected function parameter of type List of Events, list contains {:?}", invalid_type) | ||
| )) | ||
| } | ||
| } | ||
| return Ok(events); | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&DataType> for Vec<(String, Rule)> { | ||
| type Error = QueryError; | ||
| fn try_from(value: &DataType) -> Result<Self, Self::Error> { | ||
| let mut tagged_lists: Vec<DataType> = value.try_into()?; | ||
| let mut lists: Vec<(String, Rule)> = Vec::new(); | ||
| for list in tagged_lists.drain(..) { | ||
| match list { | ||
| DataType::List(ref l) => { | ||
| let tag: String = l.get(0).unwrap().try_into()?; | ||
| let rule: Rule = l.get(1).unwrap().try_into()?; | ||
| lists.push((tag, rule)); | ||
| }, | ||
| ref invalid_type => return Err(QueryError::InvalidFunctionParameters( | ||
| format!("Expected function parameter of type list of (tag, rule) tuples, list contains {:?}", invalid_type) | ||
| )) | ||
| } | ||
| } | ||
| return Ok(lists); | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&DataType> for Vec<(Vec<String>, Rule)> { | ||
| type Error = QueryError; | ||
| fn try_from(value: &DataType) -> Result<Self, Self::Error> { | ||
| let mut tagged_lists: Vec<DataType> = value.try_into()?; | ||
| let mut lists: Vec<(Vec<String>, Rule)> = Vec::new(); | ||
| for list in tagged_lists.drain(..) { | ||
| match list { | ||
| DataType::List(ref l) => { | ||
| let category: Vec<String> = l.get(0).unwrap().try_into()?; | ||
| let rule: Rule = l.get(1).unwrap().try_into()?; | ||
| lists.push((category, rule)); | ||
| }, | ||
| ref invalid_type => return Err(QueryError::InvalidFunctionParameters( | ||
| format!("Expected function parameter of type list of (category, rule) tuples, list contains {:?}", invalid_type) | ||
| )) | ||
| } | ||
| } | ||
| return Ok(lists); | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&DataType> for f64 { | ||
| type Error = QueryError; | ||
| fn try_from(value: &DataType) -> Result<Self, Self::Error> { | ||
| match value { | ||
| DataType::Number(f) => Ok(*f), | ||
| ref invalid_type => Err(QueryError::InvalidFunctionParameters( | ||
| format!("Expected function parameter of type Number, got {:?}", invalid_type) | ||
| )) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&DataType> for usize { | ||
| type Error = QueryError; | ||
| fn try_from(value: &DataType) -> Result<Self, Self::Error> { | ||
| let f: f64 = value.try_into()?; | ||
| Ok(f as usize) | ||
| } | ||
| } | ||
|
|
||
| impl TryFrom<&DataType> for Vec<Value> { | ||
| type Error = QueryError; | ||
| fn try_from(value: &DataType) -> Result<Self, Self::Error> { | ||
| let mut tagged_strings: Vec<DataType> = value.try_into()?; | ||
| let mut strings = Vec::new(); | ||
| for string in tagged_strings.drain(..) { | ||
| match string { | ||
| DataType::String(s) => strings.push(Value::String(s)), | ||
| DataType::Number(n) => strings.push(Value::Number(Number::from_f64(n).unwrap())), | ||
| //DataType::Bool(b) => strings.push(json!(b)), | ||
| DataType::None() => strings.push(Value::Null), | ||
| ref invalid_type => return Err(QueryError::InvalidFunctionParameters( | ||
| format!("Query2 support for parsing values is limited and only supports strings, numbers and null, list contains {:?}", invalid_type) | ||
| )) | ||
| } | ||
| } | ||
| return Ok(strings); | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome with all these TryFrom!
Also nice that you moved types to a seperate file.