#[derive(Debug, Clone)]
pub enum DecryptedValue<'a> {
Json(&'a serde_json::Value),
Yaml(&'a serde_norway::Value),
Toml(&'a ::toml::Value),
}
impl<'a> DecryptedValue<'a> {
pub fn as_str(&self) -> Option<&'a str> {
match self {
DecryptedValue::Json(v) => v.as_str(),
DecryptedValue::Yaml(v) => v.as_str(),
DecryptedValue::Toml(v) => v.as_str(),
}
}
pub fn as_string_map(
&self,
) -> Option<Box<dyn Iterator<Item = (&'a str, DecryptedValue<'a>)> + 'a>> {
match self {
DecryptedValue::Json(v) => v.as_object().map(|obj| {
Box::new(
obj.iter()
.map(|(k, v)| (k.as_str(), DecryptedValue::Json(v))),
) as Box<dyn Iterator<Item = (&'a str, DecryptedValue<'a>)> + 'a>
}),
DecryptedValue::Yaml(v) => v.as_mapping().map(|mapping| {
Box::new(
mapping
.iter()
.filter_map(|(k, v)| k.as_str().map(|key| (key, DecryptedValue::Yaml(v)))),
) as Box<dyn Iterator<Item = (&'a str, DecryptedValue<'a>)> + 'a>
}),
DecryptedValue::Toml(v) => v.as_table().map(|table| {
Box::new(
table
.iter()
.map(|(k, v)| (k.as_str(), DecryptedValue::Toml(v))),
) as Box<dyn Iterator<Item = (&'a str, DecryptedValue<'a>)> + 'a>
}),
}
}
pub fn as_i64(&self) -> Option<i64> {
match self {
DecryptedValue::Json(v) => v.as_i64(),
DecryptedValue::Yaml(v) => v.as_i64(),
DecryptedValue::Toml(v) => v.as_integer(),
}
}
pub fn as_f64(&self) -> Option<f64> {
match self {
DecryptedValue::Json(v) => v.as_f64(),
DecryptedValue::Yaml(v) => v.as_f64(),
DecryptedValue::Toml(v) => v.as_float(),
}
}
pub fn as_bool(&self) -> Option<bool> {
match self {
DecryptedValue::Json(v) => v.as_bool(),
DecryptedValue::Yaml(v) => v.as_bool(),
DecryptedValue::Toml(v) => v.as_bool(),
}
}
pub fn is_null(&self) -> bool {
match self {
DecryptedValue::Json(v) => v.is_null(),
DecryptedValue::Yaml(v) => v.is_null(),
DecryptedValue::Toml(_) => false, }
}
pub fn as_array(&self) -> Option<Box<dyn Iterator<Item = DecryptedValue<'a>> + 'a>> {
match self {
DecryptedValue::Json(v) => v.as_array().map(|arr| {
Box::new(arr.iter().map(DecryptedValue::Json))
as Box<dyn Iterator<Item = DecryptedValue<'a>> + 'a>
}),
DecryptedValue::Yaml(v) => v.as_sequence().map(|seq| {
Box::new(seq.iter().map(DecryptedValue::Yaml))
as Box<dyn Iterator<Item = DecryptedValue<'a>> + 'a>
}),
DecryptedValue::Toml(v) => v.as_array().map(|arr| {
Box::new(arr.iter().map(DecryptedValue::Toml))
as Box<dyn Iterator<Item = DecryptedValue<'a>> + 'a>
}),
}
}
pub fn get(&self, key: &str) -> Option<DecryptedValue<'a>> {
match self {
DecryptedValue::Json(v) => v.get(key).map(DecryptedValue::Json),
DecryptedValue::Yaml(v) => v.get(key).map(DecryptedValue::Yaml),
DecryptedValue::Toml(v) => v.get(key).map(DecryptedValue::Toml),
}
}
}
#[derive(Debug, Clone)]
pub enum DecryptedContent {
Json(serde_json::Value),
Yaml(serde_norway::Value),
Toml(::toml::Value),
}
impl DecryptedContent {
pub fn get(&self, key: &str) -> Option<DecryptedValue<'_>> {
match self {
DecryptedContent::Json(v) => v.get(key).map(DecryptedValue::Json),
DecryptedContent::Yaml(v) => v.get(key).map(DecryptedValue::Yaml),
DecryptedContent::Toml(v) => v.get(key).map(DecryptedValue::Toml),
}
}
pub fn as_value(&self) -> DecryptedValue<'_> {
match self {
DecryptedContent::Json(v) => DecryptedValue::Json(v),
DecryptedContent::Yaml(v) => DecryptedValue::Yaml(v),
DecryptedContent::Toml(v) => DecryptedValue::Toml(v),
}
}
pub fn as_string_map(
&self,
) -> Option<Box<dyn Iterator<Item = (&str, DecryptedValue<'_>)> + '_>> {
self.as_value().as_string_map()
}
pub fn as_json(&self) -> Option<&serde_json::Value> {
match self {
DecryptedContent::Json(v) => Some(v),
_ => None,
}
}
pub fn as_yaml(&self) -> Option<&serde_norway::Value> {
match self {
DecryptedContent::Yaml(v) => Some(v),
_ => None,
}
}
pub fn as_toml(&self) -> Option<&::toml::Value> {
match self {
DecryptedContent::Toml(v) => Some(v),
_ => None,
}
}
pub fn into_json(self) -> Option<serde_json::Value> {
match self {
DecryptedContent::Json(v) => Some(v),
_ => None,
}
}
pub fn into_yaml(self) -> Option<serde_norway::Value> {
match self {
DecryptedContent::Yaml(v) => Some(v),
_ => None,
}
}
pub fn into_toml(self) -> Option<::toml::Value> {
match self {
DecryptedContent::Toml(v) => Some(v),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_decrypted_value_json_as_str() {
let json = serde_json::json!({"key": "value"});
let value = DecryptedValue::Json(&json["key"]);
assert_eq!(value.as_str(), Some("value"));
}
#[test]
fn test_decrypted_value_json_as_string_map() {
let json = serde_json::json!({"a": "1", "b": "2"});
let value = DecryptedValue::Json(&json);
let map: Vec<_> = value.as_string_map().unwrap().collect();
assert_eq!(map.len(), 2);
}
#[test]
fn test_decrypted_content_get() {
let json = serde_json::json!({"environment": {"FOO": "bar"}});
let content = DecryptedContent::Json(json);
let env = content.get("environment").unwrap();
let foo = env.get("FOO").unwrap();
assert_eq!(foo.as_str(), Some("bar"));
}
#[test]
fn test_decrypted_value_yaml_as_str() {
let yaml: serde_norway::Value = serde_norway::from_str("key: value").unwrap();
let value = DecryptedValue::Yaml(&yaml["key"]);
assert_eq!(value.as_str(), Some("value"));
}
#[test]
fn test_decrypted_value_toml_as_str() {
let toml: ::toml::Value = ::toml::from_str("key = \"value\"").unwrap();
let value = DecryptedValue::Toml(toml.get("key").unwrap());
assert_eq!(value.as_str(), Some("value"));
}
#[test]
fn test_nested_access() {
let json = serde_json::json!({
"environment": {
"DATABASE_URL": "postgres://localhost",
"API_KEY": "secret123"
}
});
let content = DecryptedContent::Json(json);
let env = content.get("environment").unwrap();
let db_url = env.get("DATABASE_URL").unwrap();
assert_eq!(db_url.as_str(), Some("postgres://localhost"));
}
#[test]
fn test_string_map_iteration() {
let json = serde_json::json!({
"environment": {
"FOO": "bar",
"BAZ": "qux"
}
});
let content = DecryptedContent::Json(json);
let env = content.get("environment").unwrap();
let pairs: Vec<_> = env
.as_string_map()
.unwrap()
.filter_map(|(k, v)| v.as_str().map(|s| (k.to_string(), s.to_string())))
.collect();
assert_eq!(pairs.len(), 2);
assert!(pairs.contains(&("FOO".to_string(), "bar".to_string())));
assert!(pairs.contains(&("BAZ".to_string(), "qux".to_string())));
}
}