From 46006ae5efbf6b12fcf11c0ad4f1816029f4fe77 Mon Sep 17 00:00:00 2001 From: itsscb Date: Tue, 29 Apr 2025 21:52:43 +0200 Subject: [PATCH] feat: impl (de)serialize manually feat: extract datatype into own file --- src/script/parameter.rs | 100 ++++++++++++++++++++++++------- src/script/parameter/datatype.rs | 51 ++++++++++++++++ 2 files changed, 130 insertions(+), 21 deletions(-) create mode 100644 src/script/parameter/datatype.rs diff --git a/src/script/parameter.rs b/src/script/parameter.rs index fd8b71a..bea486e 100644 --- a/src/script/parameter.rs +++ b/src/script/parameter.rs @@ -1,18 +1,22 @@ use std::sync::Arc; +use datatype::DataType; +use serde::ser::{SerializeMap, Serializer}; use serde::{Deserialize, Serialize}; use validation::Validation; +mod datatype; mod validation; -#[derive(Deserialize, Serialize, Clone, Debug)] -#[serde(rename_all = "camelCase")] +#[derive(Clone, Debug)] pub struct Parameter { name: Arc, - #[serde(rename = "type")] + data_type: DataType, - #[serde(skip)] + + #[allow(dead_code)] is_array: bool, + aliases: Vec>, description: Option>, help_message: Option>, @@ -20,6 +24,77 @@ pub struct Parameter { validations: Vec, } +impl Serialize for Parameter { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut state = serializer.serialize_map(None)?; + + state.serialize_entry("name", &self.name)?; + + let mut type_str = format!("{}", self.data_type); + if self.is_array { + type_str.push_str("[]"); + } + state.serialize_entry("type", &type_str)?; + + state.serialize_entry("aliases", &self.aliases)?; + + if let Some(desc) = &self.description { + state.serialize_entry("description", desc)?; + } + + if let Some(help) = &self.help_message { + state.serialize_entry("helpMessage", help)?; + } + + state.serialize_entry("parameterSets", &self.parameter_sets)?; + state.serialize_entry("validations", &self.validations)?; + + state.end() + } +} + +impl<'de> Deserialize<'de> for Parameter { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + #[derive(Deserialize)] + #[serde(rename_all = "camelCase")] + struct RawParameter { + name: Arc, + #[serde(rename = "type")] + data_type: String, + aliases: Vec>, + description: Option>, + help_message: Option>, + parameter_sets: Vec, + validations: Vec, + } + + let raw = RawParameter::deserialize(deserializer)?; + + let is_array = raw.data_type.ends_with("[]"); + let type_str = raw.data_type.trim_end_matches("[]"); + + let data_type: DataType = + serde_json::from_str(&format!("\"{}\"", type_str)).map_err(serde::de::Error::custom)?; + + Ok(Parameter { + name: raw.name, + data_type, + is_array, + aliases: raw.aliases, + description: raw.description, + help_message: raw.help_message, + parameter_sets: raw.parameter_sets, + validations: raw.validations, + }) + } +} + #[derive(Deserialize, Serialize, Clone, PartialEq, Eq, Default, Debug)] pub struct ParameterSet { name: Arc, @@ -28,20 +103,3 @@ pub struct ParameterSet { value_from_pipeline: Option, value_from_pipeline_by_property_name: Option, } - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub enum DataType { - DateTime, - //TODO: Make this Variant obsolete by implementing De-/Serialize on the using Structs - #[serde(rename = "String[]")] - StringArray, - String, - Int32, - Int64, - #[serde(rename = "SwitchParameter")] - Switch, - Boolean, - #[serde(rename = "PSCredential")] - Credential, - SecureString, -} diff --git a/src/script/parameter/datatype.rs b/src/script/parameter/datatype.rs new file mode 100644 index 0000000..b0f440f --- /dev/null +++ b/src/script/parameter/datatype.rs @@ -0,0 +1,51 @@ +use std::{fmt::Display, str::FromStr}; + +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub enum DataType { + DateTime, + String, + Int32, + Int64, + #[serde(rename = "SwitchParameter")] + Switch, + Boolean, + PSCredential, + SecureString, +} + +impl Display for DataType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Self::DateTime => "DateTime", + Self::String => "String", + Self::Int32 => "Int32", + Self::Int64 => "Int64", + Self::Switch => "SwitchParameter", + Self::Boolean => "Boolean", + Self::PSCredential => "PSCredential", + Self::SecureString => "SecureString", + }) + } +} + +impl FromStr for DataType { + //TODO: Create Custom Error Type + type Err = String; + + fn from_str(s: &str) -> Result { + let s = s.to_uppercase(); + match s.as_str() { + "STRING" => Ok(Self::String), + "DATETIME" => Ok(Self::DateTime), + "INT32" => Ok(Self::Int32), + "INT64" => Ok(Self::Int64), + "SWITCHPARAMETER" => Ok(Self::Switch), + "BOOLEAN" => Ok(Self::Boolean), + "PSCREDENTIAL" => Ok(Self::PSCredential), + "SECURESTRING" => Ok(Self::SecureString), + _ => Err(String::from("Invalid Datatype")), + } + } +}