1use bytes::Bytes;
4use chrono::{DateTime, Utc};
5
6#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct ValueBytes(Bytes);
9
10impl ValueBytes {
11 #[must_use]
13 pub fn new(bytes: impl Into<Bytes>) -> Self {
14 Self(bytes.into())
15 }
16
17 #[must_use]
19 pub fn as_slice(&self) -> &[u8] {
20 &self.0
21 }
22
23 #[must_use]
25 pub fn len(&self) -> usize {
26 self.0.len()
27 }
28
29 #[must_use]
31 pub fn is_empty(&self) -> bool {
32 self.0.is_empty()
33 }
34
35 #[must_use]
37 pub fn into_inner(self) -> Bytes {
38 self.0
39 }
40}
41
42impl From<Vec<u8>> for ValueBytes {
43 fn from(value: Vec<u8>) -> Self {
44 Self::new(value)
45 }
46}
47
48impl From<Bytes> for ValueBytes {
49 fn from(value: Bytes) -> Self {
50 Self::new(value)
51 }
52}
53
54impl AsRef<[u8]> for ValueBytes {
55 fn as_ref(&self) -> &[u8] {
56 self.as_slice()
57 }
58}
59
60#[derive(Debug, Clone, PartialEq, Eq)]
62pub struct ValueMetadata {
63 pub codec: String,
65 pub created_at: DateTime<Utc>,
67 pub updated_at: DateTime<Utc>,
69 pub expires_at: Option<DateTime<Utc>>,
71}
72
73impl ValueMetadata {
74 #[must_use]
76 pub fn new(
77 codec: impl Into<String>,
78 now: DateTime<Utc>,
79 expires_at: Option<DateTime<Utc>>,
80 ) -> Self {
81 Self {
82 codec: codec.into(),
83 created_at: now,
84 updated_at: now,
85 expires_at,
86 }
87 }
88
89 #[must_use]
91 pub fn is_expired_at(&self, now: DateTime<Utc>) -> bool {
92 self.expires_at.is_some_and(|expires_at| expires_at <= now)
93 }
94}
95
96#[derive(Debug, Clone, PartialEq, Eq)]
98pub struct StoredValue {
99 pub bytes: ValueBytes,
101 pub metadata: ValueMetadata,
103}
104
105impl StoredValue {
106 #[must_use]
108 pub fn new(bytes: ValueBytes, metadata: ValueMetadata) -> Self {
109 Self { bytes, metadata }
110 }
111
112 #[must_use]
114 pub fn is_expired(&self) -> bool {
115 self.metadata.is_expired_at(Utc::now())
116 }
117}