use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Null,
Bool(bool),
Int(i64),
Float(f64),
String(String),
Json(serde_json::Value),
Blob(BlobRef),
}
impl Serialize for Value {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
crate::result::value_to_json(self).serialize(serializer)
}
}
impl<'de> Deserialize<'de> for Value {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let json = serde_json::Value::deserialize(deserializer)?;
Ok(crate::result::json_to_value(json))
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BlobRef {
pub id: String,
pub size: u64,
pub content_type: String,
pub hash: Option<Vec<u8>>,
}
impl BlobRef {
pub fn new(id: impl Into<String>, size: u64, content_type: impl Into<String>) -> Self {
Self {
id: id.into(),
size,
content_type: content_type.into(),
hash: None,
}
}
pub fn with_hash(mut self, hash: Vec<u8>) -> Self {
self.hash = Some(hash);
self
}
pub fn path(&self) -> String {
format!("/v/blobs/{}", self.id)
}
pub fn formatted_size(&self) -> String {
const KB: u64 = 1024;
const MB: u64 = 1024 * KB;
const GB: u64 = 1024 * MB;
if self.size >= GB {
format!("{:.1}GB", self.size as f64 / GB as f64)
} else if self.size >= MB {
format!("{:.1}MB", self.size as f64 / MB as f64)
} else if self.size >= KB {
format!("{:.1}KB", self.size as f64 / KB as f64)
} else {
format!("{}B", self.size)
}
}
}