rustfs_filemeta/
filemeta_inline.rs1use crate::error::{Error, Result};
16use crate::filemeta::msgp_decode::{prealloc_hint, read_exact_vec};
17use serde::{Deserialize, Serialize};
18use std::io::Cursor;
19use uuid::Uuid;
20
21#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
22pub struct InlineData(Vec<u8>);
23
24const INLINE_DATA_VER: u8 = 1;
25
26impl InlineData {
27 fn contains_key_by<F>(&self, mut should_remove: F) -> Result<bool>
28 where
29 F: FnMut(&[u8]) -> bool,
30 {
31 let buf = self.after_version();
32 if buf.is_empty() {
33 return Ok(false);
34 }
35
36 let mut scan_cur = Cursor::new(buf);
37 let mut scan_fields_len = rmp::decode::read_map_len(&mut scan_cur)? as usize;
38
39 while scan_fields_len > 0 {
40 scan_fields_len -= 1;
41
42 let str_len = rmp::decode::read_str_len(&mut scan_cur)? as usize;
43 let key_start = scan_cur.position() as usize;
44 let key_end = key_start + str_len;
45 let key = buf
46 .get(key_start..key_end)
47 .ok_or_else(|| Error::other("InlineData key out of range"))?;
48 scan_cur.set_position(key_end as u64);
49
50 let bin_len = rmp::decode::read_bin_len(&mut scan_cur)? as usize;
51 let value_start = scan_cur.position() as usize;
52 let value_end = value_start + bin_len;
53 if value_end > buf.len() {
54 return Err(Error::other("InlineData value out of range"));
55 }
56 scan_cur.set_position(value_end as u64);
57
58 if should_remove(key) {
59 return Ok(true);
60 }
61 }
62
63 Ok(false)
64 }
65
66 fn remove_keys_by<F>(&mut self, mut should_remove: F) -> Result<bool>
67 where
68 F: FnMut(&[u8]) -> bool,
69 {
70 let buf = self.after_version();
71 if buf.is_empty() {
72 return Ok(false);
73 }
74
75 let mut cur = Cursor::new(buf);
76 let mut fields_len = rmp::decode::read_map_len(&mut cur)? as usize;
77 let mut keys = Vec::with_capacity(prealloc_hint(fields_len));
78 let mut values = Vec::with_capacity(prealloc_hint(fields_len));
79 let mut found = false;
80
81 while fields_len > 0 {
82 fields_len -= 1;
83
84 let str_len = rmp::decode::read_str_len(&mut cur)? as usize;
85 let field_buf = read_exact_vec(&mut cur, str_len)?;
86
87 let bin_len = rmp::decode::read_bin_len(&mut cur)? as usize;
88 let start = cur.position() as usize;
89 let end = start + bin_len;
90 let value = buf
91 .get(start..end)
92 .ok_or_else(|| Error::other("InlineData value out of range"))?;
93 cur.set_position(end as u64);
94
95 if should_remove(field_buf.as_slice()) {
96 found = true;
97 continue;
98 }
99
100 keys.push(String::from_utf8(field_buf)?);
101 values.push(value.to_vec());
102 }
103
104 if !found {
105 return Ok(false);
106 }
107
108 if keys.is_empty() {
109 self.0 = Vec::new();
110 return Ok(true);
111 }
112
113 self.serialize(keys, values)?;
114 Ok(true)
115 }
116
117 fn remove_two_keys_by_bytes(&mut self, first_key: &[u8], second_key: &[u8]) -> Result<bool> {
118 let buf = self.after_version();
119 if buf.is_empty() {
120 return Ok(false);
121 }
122
123 let same = first_key == second_key;
124 let mut cur = Cursor::new(buf);
125 let mut fields_len = rmp::decode::read_map_len(&mut cur)? as usize;
126 let mut keys = Vec::with_capacity(prealloc_hint(fields_len) + 1);
127 let mut values = Vec::with_capacity(prealloc_hint(fields_len) + 1);
128 let mut found = false;
129
130 while fields_len > 0 {
131 fields_len -= 1;
132
133 let str_len = rmp::decode::read_str_len(&mut cur)? as usize;
134 let field_buf = read_exact_vec(&mut cur, str_len)?;
135
136 let bin_len = rmp::decode::read_bin_len(&mut cur)? as usize;
137 let start = cur.position() as usize;
138 let end = start + bin_len;
139 let value = buf
140 .get(start..end)
141 .ok_or_else(|| Error::other("InlineData value out of range"))?;
142 cur.set_position(end as u64);
143
144 let should_remove = if same {
145 field_buf.as_slice() == first_key
146 } else {
147 field_buf.as_slice() == first_key || field_buf.as_slice() == second_key
148 };
149
150 if should_remove {
151 found = true;
152 continue;
153 }
154
155 keys.push(String::from_utf8(field_buf)?);
156 values.push(value.to_vec());
157 }
158
159 if !found {
160 return Ok(false);
161 }
162
163 if keys.is_empty() {
164 self.0 = Vec::new();
165 return Ok(true);
166 }
167
168 self.serialize(keys, values)?;
169 Ok(true)
170 }
171
172 pub fn new() -> Self {
173 Self(Vec::new())
174 }
175 pub fn update(&mut self, buf: &[u8]) {
176 self.0 = buf.to_vec()
177 }
178 pub fn as_slice(&self) -> &[u8] {
179 self.0.as_slice()
180 }
181 pub fn version_ok(&self) -> bool {
182 if self.0.is_empty() {
183 return true;
184 }
185
186 self.0[0] > 0 && self.0[0] <= INLINE_DATA_VER
187 }
188
189 pub fn after_version(&self) -> &[u8] {
190 if self.0.is_empty() { &self.0 } else { &self.0[1..] }
191 }
192
193 pub fn entries(&self) -> Result<usize> {
194 if self.0.is_empty() || !self.version_ok() {
195 return Ok(0);
196 }
197
198 let buf = self.after_version();
199
200 let mut cur = Cursor::new(buf);
201
202 let fields_len = rmp::decode::read_map_len(&mut cur)?;
203
204 Ok(fields_len as usize)
205 }
206
207 pub fn find(&self, key: &str) -> Result<Option<Vec<u8>>> {
208 if self.0.is_empty() || !self.version_ok() {
209 return Ok(None);
210 }
211
212 let buf = self.after_version();
213
214 let mut cur = Cursor::new(buf);
215
216 let mut fields_len = rmp::decode::read_map_len(&mut cur)?;
217
218 while fields_len > 0 {
219 fields_len -= 1;
220
221 let str_len = rmp::decode::read_str_len(&mut cur)?;
222
223 let field_buff = read_exact_vec(&mut cur, str_len as usize)?;
224
225 let field = String::from_utf8(field_buff)?;
226
227 let bin_len = rmp::decode::read_bin_len(&mut cur)? as usize;
228 let start = cur.position() as usize;
229 let end = start + bin_len;
230 let value = buf
231 .get(start..end)
232 .ok_or_else(|| Error::other("InlineData value out of range"))?;
233 cur.set_position(end as u64);
234
235 if field.as_str() == key {
236 return Ok(Some(value.to_vec()));
237 }
238 }
239
240 Ok(None)
241 }
242
243 pub fn validate(&self) -> Result<()> {
244 if self.0.is_empty() {
245 return Ok(());
246 }
247
248 let buf = self.after_version();
249 let mut cur = Cursor::new(buf);
250
251 let mut fields_len = rmp::decode::read_map_len(&mut cur)?;
252
253 while fields_len > 0 {
254 fields_len -= 1;
255
256 let str_len = rmp::decode::read_str_len(&mut cur)?;
257
258 let field_buff = read_exact_vec(&mut cur, str_len as usize)?;
259
260 let field = String::from_utf8(field_buff)?;
261 if field.is_empty() {
262 return Err(Error::other("InlineData key empty"));
263 }
264
265 let bin_len = rmp::decode::read_bin_len(&mut cur)? as usize;
266 let start = cur.position() as usize;
267 let end = start + bin_len;
268 if end > buf.len() {
269 return Err(Error::other("InlineData value out of range"));
270 }
271 cur.set_position(end as u64);
272 }
273
274 Ok(())
275 }
276
277 pub fn replace(&mut self, key: &str, value: Vec<u8>) -> Result<()> {
278 if self.after_version().is_empty() {
279 let mut keys = Vec::with_capacity(1);
280 let mut values = Vec::with_capacity(1);
281
282 keys.push(key.to_owned());
283 values.push(value);
284
285 return self.serialize(keys, values);
286 }
287
288 let buf = self.after_version();
289 let mut cur = Cursor::new(buf);
290
291 let mut fields_len = rmp::decode::read_map_len(&mut cur)? as usize;
292 let mut keys = Vec::with_capacity(prealloc_hint(fields_len) + 1);
293 let mut values = Vec::with_capacity(prealloc_hint(fields_len) + 1);
294
295 let mut replaced = false;
296
297 while fields_len > 0 {
298 fields_len -= 1;
299
300 let str_len = rmp::decode::read_str_len(&mut cur)?;
301
302 let field_buff = read_exact_vec(&mut cur, str_len as usize)?;
303
304 let find_key = String::from_utf8(field_buff)?;
305
306 let bin_len = rmp::decode::read_bin_len(&mut cur)? as usize;
307 let start = cur.position() as usize;
308 let end = start + bin_len;
309 let find_value = buf
310 .get(start..end)
311 .ok_or_else(|| Error::other("InlineData value out of range"))?;
312 cur.set_position(end as u64);
313
314 if find_key.as_str() == key {
315 values.push(value.clone());
316 replaced = true
317 } else {
318 values.push(find_value.to_vec());
319 }
320
321 keys.push(find_key);
322 }
323
324 if !replaced {
325 keys.push(key.to_owned());
326 values.push(value);
327 }
328
329 self.serialize(keys, values)
330 }
331
332 pub fn remove_key(&mut self, key: &str) -> Result<bool> {
333 let key_bytes = key.as_bytes();
334 if !self.contains_key_by(|candidate| candidate == key_bytes)? {
335 return Ok(false);
336 }
337 self.remove_keys_by(|candidate| candidate == key_bytes)
338 }
339
340 pub fn remove(&mut self, remove_keys: Vec<Uuid>) -> Result<bool> {
341 let mut encoded_keys = Vec::with_capacity(remove_keys.len());
342 for key in remove_keys {
343 let mut buf = Uuid::encode_buffer();
344 encoded_keys.push(key.hyphenated().encode_lower(&mut buf).to_string().into_bytes());
345 }
346
347 self.remove_keys_by(|candidate| encoded_keys.iter().any(|key| candidate == key.as_slice()))
348 }
349
350 pub fn remove_two(&mut self, first: Uuid, second: Uuid) -> Result<bool> {
351 let mut first_buf = Uuid::encode_buffer();
352 let mut second_buf = Uuid::encode_buffer();
353 let first_key = first.hyphenated().encode_lower(&mut first_buf).as_bytes();
354 let second_key = second.hyphenated().encode_lower(&mut second_buf).as_bytes();
355 self.remove_two_keys_by_bytes(first_key, second_key)
356 }
357 fn serialize(&mut self, keys: Vec<String>, values: Vec<Vec<u8>>) -> Result<()> {
358 assert_eq!(keys.len(), values.len(), "InlineData serialize: keys/values not match");
359
360 if keys.is_empty() {
361 self.0 = Vec::new();
362 return Ok(());
363 }
364
365 let mut wr = Vec::new();
366
367 wr.push(INLINE_DATA_VER);
368
369 let map_len = keys.len();
370
371 rmp::encode::write_map_len(&mut wr, map_len as u32)?;
372
373 for i in 0..map_len {
374 rmp::encode::write_str(&mut wr, keys[i].as_str())?;
375 rmp::encode::write_bin(&mut wr, values[i].as_slice())?;
376 }
377
378 self.0 = wr;
379
380 Ok(())
381 }
382}
383
384#[cfg(test)]
385mod tests {
386 use super::*;
387
388 #[test]
389 fn remove_key_miss_keeps_inline_data_unchanged() {
390 let mut data = InlineData::new();
391 data.replace("keep", b"value".to_vec()).expect("seed inline data");
392 let before = data.as_slice().to_vec();
393
394 let removed = data.remove_key("missing").expect("remove_key should succeed");
395
396 assert!(!removed);
397 assert_eq!(data.as_slice(), before.as_slice());
398 }
399
400 #[test]
401 fn remove_two_removes_only_matching_keys() {
402 let first = Uuid::new_v4();
403 let second = Uuid::new_v4();
404 let keep = Uuid::new_v4();
405 let mut data = InlineData::new();
406 data.replace(first.hyphenated().to_string().as_str(), b"first".to_vec())
407 .expect("seed first key");
408 data.replace(second.hyphenated().to_string().as_str(), b"second".to_vec())
409 .expect("seed second key");
410 data.replace(keep.hyphenated().to_string().as_str(), b"keep".to_vec())
411 .expect("seed keep key");
412
413 let removed = data.remove_two(first, second).expect("remove_two should succeed");
414
415 assert!(removed);
416 assert_eq!(data.find(first.hyphenated().to_string().as_str()).expect("find first"), None);
417 assert_eq!(data.find(second.hyphenated().to_string().as_str()).expect("find second"), None);
418 assert_eq!(
419 data.find(keep.hyphenated().to_string().as_str()).expect("find keep"),
420 Some(b"keep".to_vec())
421 );
422 }
423}