risingwave_storage/hummock/
value.rs1use std::fmt::Debug;
16
17use bytes::{Buf, BufMut, Bytes};
18
19use super::{HummockError, HummockResult};
20
21pub const VALUE_DELETE: u8 = 1 << 0;
22pub const VALUE_PUT: u8 = 0;
23
24#[derive(Clone)]
29pub enum HummockValue<T> {
30 Put(T),
31 Delete,
32}
33
34impl<T: AsRef<[u8]>> Debug for HummockValue<T> {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 match &self {
37 HummockValue::Put(v) => {
38 write!(f, "HummockValue {{ PUT, {} }}", hex::encode(v.as_ref()))
39 }
40 HummockValue::Delete => write!(f, "HummockValue {{ DELETE }}"),
41 }
42 }
43}
44
45impl<T> Copy for HummockValue<T> where T: Copy {}
46
47#[cfg(any(test, feature = "test"))]
48impl<T: PartialEq> PartialEq for HummockValue<T> {
49 fn eq(&self, other: &Self) -> bool {
50 match (self, other) {
51 (Self::Put(l0), Self::Put(r0)) => l0.eq(r0),
52 (Self::Delete, Self::Delete) => true,
53 _ => false,
54 }
55 }
56}
57
58#[cfg(any(test, feature = "test"))]
59impl<T: Eq> Eq for HummockValue<T> {}
60
61impl<T> HummockValue<T>
62where
63 T: AsRef<[u8]>,
64{
65 pub fn encoded_len(&self) -> usize {
66 match self {
67 HummockValue::Put(val) => 1 + val.as_ref().len(),
68 HummockValue::Delete => 1,
69 }
70 }
71
72 pub fn encode(&self, buffer: &mut impl BufMut) {
74 match self {
75 HummockValue::Put(val) => {
76 buffer.put_u8(VALUE_PUT);
78 buffer.put_slice(val.as_ref());
79 }
80 HummockValue::Delete => {
81 buffer.put_u8(VALUE_DELETE);
83 }
84 }
85 }
86
87 pub fn into_user_value(self) -> Option<T> {
90 match self {
91 Self::Put(val) => Some(val),
92 Self::Delete => None,
93 }
94 }
95
96 pub fn is_delete(&self) -> bool {
97 matches!(self, Self::Delete)
98 }
99
100 pub fn put(data: T) -> Self {
101 Self::Put(data)
102 }
103
104 pub fn delete() -> Self {
105 Self::Delete
106 }
107}
108
109impl HummockValue<Vec<u8>> {
110 pub fn decode(buffer: &mut impl Buf) -> HummockResult<Self> {
112 if buffer.remaining() == 0 {
113 return Err(HummockError::decode_error("empty value"));
114 }
115 match buffer.get_u8() {
116 VALUE_PUT => Ok(Self::Put(Vec::from(buffer.chunk()))),
117 VALUE_DELETE => Ok(Self::Delete),
118 _ => Err(HummockError::decode_error("non-empty but format error")),
119 }
120 }
121}
122
123impl<B: AsRef<[u8]>> HummockValue<B> {
124 pub fn as_slice(&self) -> HummockValue<&[u8]> {
125 match self {
126 HummockValue::Put(data) => HummockValue::Put(data.as_ref()),
127 HummockValue::Delete => HummockValue::Delete,
128 }
129 }
130}
131
132impl<'a> HummockValue<&'a [u8]> {
133 pub fn from_slice(mut buffer: &'a [u8]) -> HummockResult<Self> {
135 if buffer.remaining() == 0 {
136 return Err(HummockError::decode_error("empty value"));
137 }
138 match buffer.get_u8() {
139 VALUE_PUT => Ok(Self::Put(buffer)),
140 VALUE_DELETE => Ok(Self::Delete),
141 _ => Err(HummockError::decode_error("non-empty but format error")),
142 }
143 }
144
145 pub fn to_bytes(self) -> HummockValue<Bytes> {
147 match self {
148 HummockValue::Put(value) => HummockValue::Put(Bytes::copy_from_slice(value)),
149 HummockValue::Delete => HummockValue::Delete,
150 }
151 }
152}
153
154impl HummockValue<Bytes> {
155 pub fn to_vec(&self) -> HummockValue<Vec<u8>> {
156 match self {
157 HummockValue::Put(data) => HummockValue::Put(data.to_vec()),
158 HummockValue::Delete => HummockValue::Delete,
159 }
160 }
161}
162
163impl From<HummockValue<Vec<u8>>> for HummockValue<Bytes> {
164 fn from(data: HummockValue<Vec<u8>>) -> Self {
165 match data {
166 HummockValue::Put(data) => HummockValue::Put(data.into()),
167 HummockValue::Delete => HummockValue::Delete,
168 }
169 }
170}
171
172#[cfg(test)]
173mod tests {
174 use super::*;
175 #[test]
176 fn test_vec_decode_encode() {
177 let mut result = vec![];
178 HummockValue::Put(b"233333".to_vec()).encode(&mut result);
179 assert_eq!(
180 HummockValue::Put(b"233333".to_vec()),
181 HummockValue::decode(&mut &result[..]).unwrap()
182 );
183 }
184
185 #[test]
186 fn test_slice_decode_encode() {
187 let mut result = vec![];
188 HummockValue::Put(b"233333".to_vec()).encode(&mut result);
189 assert_eq!(
190 HummockValue::Put(b"233333".as_slice()),
191 HummockValue::from_slice(&result).unwrap()
192 );
193 }
194}