diff --git a/services/identity/src/error.rs b/services/identity/src/error.rs --- a/services/identity/src/error.rs +++ b/services/identity/src/error.rs @@ -1,4 +1,5 @@ use aws_sdk_dynamodb::{model::AttributeValue, Error as DynamoDBError}; +use std::collections::hash_map::HashMap; use std::fmt::{Display, Formatter, Result as FmtResult}; #[derive( @@ -51,3 +52,90 @@ #[display(...)] InvalidValue, } + +pub trait FromAttributeValue { + fn to_vec( + &self, + attr_name: &str, + ) -> Result<&Vec, DBItemError>; + fn to_string(&self, attr_name: &str) -> Result<&String, DBItemError>; + fn to_hashmap( + &self, + attr_name: &str, + ) -> Result<&HashMap, DBItemError>; +} + +fn handle_attr_failure(value: &AttributeValue, attr_name: &str) -> DBItemError { + DBItemError { + attribute_name: attr_name.to_string(), + attribute_value: Some(value.clone()), + attribute_error: DBItemAttributeError::IncorrectType, + } +} + +impl FromAttributeValue for AttributeValue { + fn to_vec( + &self, + attr_name: &str, + ) -> Result<&Vec, DBItemError> { + self.as_l().map_err(|e| handle_attr_failure(e, attr_name)) + } + + fn to_string(&self, attr_name: &str) -> Result<&String, DBItemError> { + self.as_s().map_err(|e| handle_attr_failure(e, attr_name)) + } + + fn to_hashmap( + &self, + attr_name: &str, + ) -> Result<&HashMap, DBItemError> { + self.as_m().map_err(|e| handle_attr_failure(e, attr_name)) + } +} + +pub trait AttributeValueFromHashMap { + fn get_string(&self, key: &str) -> Result<&String, DBItemError>; + fn get_map( + &self, + key: &str, + ) -> Result<&HashMap, DBItemError>; + fn get_vec(&self, key: &str) -> Result<&Vec, DBItemError>; +} + +impl AttributeValueFromHashMap for HashMap { + fn get_string(&self, key: &str) -> Result<&String, DBItemError> { + self + .get(key) + .ok_or(DBItemError { + attribute_name: key.to_string(), + attribute_value: None, + attribute_error: DBItemAttributeError::Missing, + })? + .to_string(key) + } + + fn get_map( + &self, + key: &str, + ) -> Result<&HashMap, DBItemError> { + self + .get(key) + .ok_or(DBItemError { + attribute_name: key.to_string(), + attribute_value: None, + attribute_error: DBItemAttributeError::Missing, + })? + .to_hashmap(key) + } + + fn get_vec(&self, key: &str) -> Result<&Vec, DBItemError> { + self + .get(key) + .ok_or(DBItemError { + attribute_name: key.to_string(), + attribute_value: None, + attribute_error: DBItemAttributeError::Missing, + })? + .to_vec(key) + } +}