From aefba38eeafad9c18ce5b47a29d6eb45840e4ef1 Mon Sep 17 00:00:00 2001 From: dd di cesare Date: Tue, 22 Oct 2024 17:44:32 +0200 Subject: [PATCH] [wip, feature] Parsing Json scalar values * Only for boolean values and not using json crate atm Signed-off-by: dd di cesare --- src/configuration.rs | 4 ++- src/data/attribute.rs | 58 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/configuration.rs b/src/configuration.rs index ca0337f3..b2f5d14a 100644 --- a/src/configuration.rs +++ b/src/configuration.rs @@ -135,7 +135,9 @@ impl PatternExpression { ValueType::UInt => Value::UInt(AttributeValue::parse(raw_attribute)?), ValueType::Float => Value::Float(AttributeValue::parse(raw_attribute)?), ValueType::Bytes => Value::Bytes(Arc::new(AttributeValue::parse(raw_attribute)?)), - ValueType::Bool => Value::Bool(AttributeValue::parse(raw_attribute)?), + ValueType::Bool => Value::Bool( + AttributeValue::parse(raw_attribute).unwrap_or_else(AttributeValue::parse_json)?, + ), ValueType::Timestamp => Value::Timestamp(AttributeValue::parse(raw_attribute)?), // todo: Impl support for parsing these two types… Tho List/Map of what? // ValueType::List => {} diff --git a/src/data/attribute.rs b/src/data/attribute.rs index faa25356..e1bc4ab3 100644 --- a/src/data/attribute.rs +++ b/src/data/attribute.rs @@ -4,6 +4,7 @@ use chrono::{DateTime, FixedOffset}; use log::{debug, error}; use protobuf::well_known_types::Struct; use proxy_wasm::hostcalls; +use regex::Regex; pub const KUADRANT_NAMESPACE: &str = "kuadrant"; @@ -11,6 +12,9 @@ pub trait AttributeValue { fn parse(raw_attribute: Vec) -> Result where Self: Sized; + fn parse_json(raw_attribute: Vec) -> Result + where + Self: Sized; } impl AttributeValue for String { @@ -22,6 +26,10 @@ impl AttributeValue for String { ) }) } + + fn parse_json(raw_attribute: Vec) -> Result { + Self::parse(raw_attribute) + } } impl AttributeValue for i64 { @@ -38,6 +46,10 @@ impl AttributeValue for i64 { .expect("This has to be 8 bytes long!"), )) } + + fn parse_json(raw_attribute: Vec) -> Result { + Self::parse(raw_attribute) + } } impl AttributeValue for u64 { @@ -54,6 +66,10 @@ impl AttributeValue for u64 { .expect("This has to be 8 bytes long!"), )) } + + fn parse_json(raw_attribute: Vec) -> Result { + Self::parse(raw_attribute) + } } impl AttributeValue for f64 { @@ -70,12 +86,20 @@ impl AttributeValue for f64 { .expect("This has to be 8 bytes long!"), )) } + + fn parse_json(raw_attribute: Vec) -> Result { + Self::parse(raw_attribute) + } } impl AttributeValue for Vec { fn parse(raw_attribute: Vec) -> Result { Ok(raw_attribute) } + + fn parse_json(raw_attribute: Vec) -> Result { + Self::parse(raw_attribute) + } } impl AttributeValue for bool { @@ -88,6 +112,36 @@ impl AttributeValue for bool { } Ok(raw_attribute[0] & 1 == 1) } + + fn parse_json(raw_attribute: Vec) -> Result { + let json_string_result = String::from_utf8(raw_attribute).map_err(|err| { + format!( + "parse: failed to parse selector Json String value, error: {}", + err + ) + }); + + match json_string_result { + Ok(json_string) => { + let decoded_string = json_string.trim().to_lowercase(); + // Check for boolean patterns + if Regex::new(r"^(true|false)$") + .unwrap() + .is_match(&decoded_string) + { + Ok(decoded_string == <&str as Into>::into("true")) + } else if Regex::new(r"^(\s*(true|false)\s*)$") + .unwrap() + .is_match(&decoded_string) + { + Ok(decoded_string.trim() == <&str as Into>::into("true")) + } else { + Err(format!("Invalid boolean value: {}", decoded_string)) + } + } + Err(err) => Err(err), + } + } } impl AttributeValue for DateTime { @@ -106,6 +160,10 @@ impl AttributeValue for DateTime { ); Ok(DateTime::from_timestamp_nanos(nanos).into()) } + + fn parse_json(raw_attribute: Vec) -> Result { + Self::parse(raw_attribute) + } } pub fn get_attribute(path: &PropertyPath) -> Result, String>