use std::fmt::Display;
use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum Visibility {
Public,
Sensitive,
Secret,
}
impl Display for Visibility {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Public => f.write_str("public"),
Self::Sensitive => f.write_str("sensitive"),
Self::Secret => f.write_str("secret"),
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type", content = "value"))]
#[non_exhaustive]
pub enum Value {
String(String),
Bool(bool),
Signed(i64),
Unsigned(u64),
Float(f64),
}
impl Value {
#[must_use]
pub fn display(value: impl Display) -> Self {
Self::String(value.to_string())
}
}
impl Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::String(value) => f.write_str(value),
Self::Bool(value) => write!(f, "{value}"),
Self::Signed(value) => write!(f, "{value}"),
Self::Unsigned(value) => write!(f, "{value}"),
Self::Float(value) => write!(f, "{value}"),
}
}
}
macro_rules! impl_from_signed {
($($ty:ty),*) => {
$(impl From<$ty> for Value {
fn from(value: $ty) -> Self {
Self::Signed(i64::from(value))
}
})*
};
}
macro_rules! impl_from_unsigned {
($($ty:ty),*) => {
$(impl From<$ty> for Value {
fn from(value: $ty) -> Self {
Self::Unsigned(u64::from(value))
}
})*
};
}
impl_from_signed!(i8, i16, i32, i64);
impl_from_unsigned!(u8, u16, u32, u64);
impl From<&str> for Value {
fn from(value: &str) -> Self {
Self::String(value.to_owned())
}
}
impl From<String> for Value {
fn from(value: String) -> Self {
Self::String(value)
}
}
impl From<&String> for Value {
fn from(value: &String) -> Self {
Self::String(value.clone())
}
}
impl From<bool> for Value {
fn from(value: bool) -> Self {
Self::Bool(value)
}
}
impl From<f32> for Value {
fn from(value: f32) -> Self {
Self::Float(f64::from(value))
}
}
impl From<f64> for Value {
fn from(value: f64) -> Self {
Self::Float(value)
}
}
impl From<&Path> for Value {
fn from(value: &Path) -> Self {
Self::String(value.display().to_string())
}
}
impl From<PathBuf> for Value {
fn from(value: PathBuf) -> Self {
Self::String(value.display().to_string())
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Field {
pub key: String,
pub value: Value,
pub visibility: Visibility,
}
impl Field {
#[must_use]
pub fn public(key: impl Into<String>, value: impl Into<Value>) -> Self {
Self {
key: key.into(),
value: value.into(),
visibility: Visibility::Public,
}
}
#[must_use]
pub fn sensitive(key: impl Into<String>, value: impl Into<Value>) -> Self {
Self {
key: key.into(),
value: value.into(),
visibility: Visibility::Sensitive,
}
}
#[must_use]
pub fn secret(key: impl Into<String>, value: impl Into<Value>) -> Self {
Self {
key: key.into(),
value: value.into(),
visibility: Visibility::Secret,
}
}
}