use crate::MicrosandboxError;
use getset::Getters;
use serde::{Deserialize, Serialize};
use std::{fmt, str::FromStr};
#[derive(Debug, Hash, Clone, PartialEq, Eq, Getters)]
#[getset(get = "pub with_prefix")]
pub struct EnvPair {
name: String,
value: String,
}
impl EnvPair {
pub fn new<S: Into<String>>(name: S, value: S) -> Self {
Self {
name: name.into(),
value: value.into(),
}
}
}
impl FromStr for EnvPair {
type Err = MicrosandboxError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (var, value) = s
.split_once('=')
.ok_or_else(|| MicrosandboxError::InvalidEnvPair(s.to_string()))?;
if var.is_empty() {
return Err(MicrosandboxError::InvalidEnvPair(s.to_string()));
}
Ok(Self::new(var, value))
}
}
impl fmt::Display for EnvPair {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}={}", self.name, self.value)
}
}
impl Serialize for EnvPair {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for EnvPair {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Self::from_str(&s).map_err(serde::de::Error::custom)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_env_pair_new() {
let env_pair = EnvPair::new("VAR", "VALUE");
assert_eq!(env_pair.name, String::from("VAR"));
assert_eq!(env_pair.value, String::from("VALUE"));
}
#[test]
fn test_env_pair_from_str() -> anyhow::Result<()> {
let env_pair: EnvPair = "VAR=VALUE".parse()?;
assert_eq!(env_pair.name, String::from("VAR"));
assert_eq!(env_pair.value, String::from("VALUE"));
let env_pair: EnvPair = "VAR=".parse()?;
assert_eq!(env_pair.name, String::from("VAR"));
assert_eq!(env_pair.value, String::from(""));
assert!("VAR".parse::<EnvPair>().is_err());
assert!("=VALUE".parse::<EnvPair>().is_err());
Ok(())
}
#[test]
fn test_env_pair_display() {
let env_pair = EnvPair::new("VAR", "VALUE");
assert_eq!(env_pair.to_string(), "VAR=VALUE");
let env_pair = EnvPair::new("VAR", "");
assert_eq!(env_pair.to_string(), "VAR=");
}
#[test]
fn test_env_pair_serialize_deserialize() -> anyhow::Result<()> {
let env_pair = EnvPair::new("VAR", "VALUE");
let serialized = serde_json::to_string(&env_pair)?;
assert_eq!(serialized, "\"VAR=VALUE\"");
let deserialized: EnvPair = serde_json::from_str(&serialized)?;
assert_eq!(deserialized, env_pair);
let env_pair = EnvPair::new("VAR", "");
let serialized = serde_json::to_string(&env_pair)?;
assert_eq!(serialized, "\"VAR=\"");
let deserialized: EnvPair = serde_json::from_str(&serialized)?;
assert_eq!(deserialized, env_pair);
Ok(())
}
#[test]
fn test_env_pair_with_special_characters() -> anyhow::Result<()> {
let env_pair: EnvPair = "VAR_WITH_UNDERSCORE=VALUE WITH SPACES".parse()?;
assert_eq!(env_pair.name, "VAR_WITH_UNDERSCORE");
assert_eq!(env_pair.value, "VALUE WITH SPACES");
let env_pair: EnvPair = "VAR.WITH.DOTS=VALUE_WITH_UNDERSCORE".parse()?;
assert_eq!(env_pair.name, "VAR.WITH.DOTS");
assert_eq!(env_pair.value, "VALUE_WITH_UNDERSCORE");
Ok(())
}
}