1use serde::{Deserialize, Deserializer, Serialize, Serializer};
4
5#[derive(Debug, Clone, PartialEq)]
10pub enum Value {
11 Null,
12 Bool(bool),
13 Int(i64),
14 Float(f64),
15 String(String),
16 Json(serde_json::Value),
19 Blob(BlobRef),
21}
22
23impl Serialize for Value {
24 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
25 crate::result::value_to_json(self).serialize(serializer)
28 }
29}
30
31impl<'de> Deserialize<'de> for Value {
32 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
33 let json = serde_json::Value::deserialize(deserializer)?;
34 Ok(crate::result::json_to_value(json))
35 }
36}
37
38#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
43pub struct BlobRef {
44 pub id: String,
46 pub size: u64,
48 pub content_type: String,
50 pub hash: Option<Vec<u8>>,
52}
53
54impl BlobRef {
55 pub fn new(id: impl Into<String>, size: u64, content_type: impl Into<String>) -> Self {
57 Self {
58 id: id.into(),
59 size,
60 content_type: content_type.into(),
61 hash: None,
62 }
63 }
64
65 pub fn with_hash(mut self, hash: Vec<u8>) -> Self {
67 self.hash = Some(hash);
68 self
69 }
70
71 pub fn path(&self) -> String {
73 format!("/v/blobs/{}", self.id)
74 }
75
76 pub fn formatted_size(&self) -> String {
78 const KB: u64 = 1024;
79 const MB: u64 = 1024 * KB;
80 const GB: u64 = 1024 * MB;
81
82 if self.size >= GB {
83 format!("{:.1}GB", self.size as f64 / GB as f64)
84 } else if self.size >= MB {
85 format!("{:.1}MB", self.size as f64 / MB as f64)
86 } else if self.size >= KB {
87 format!("{:.1}KB", self.size as f64 / KB as f64)
88 } else {
89 format!("{}B", self.size)
90 }
91 }
92}