1use crate::{BlobFormat, Hash, HashAndFormat};
3
4#[cfg(feature = "fs-store")]
5mod bao_file;
6pub mod mem;
7mod mutable_mem_storage;
8pub mod readonly_mem;
9
10#[cfg(feature = "fs-store")]
11pub mod fs;
12
13mod traits;
14pub use traits::*;
15
16fn new_uuid() -> [u8; 16] {
18 use rand::Rng;
19 rand::thread_rng().gen::<[u8; 16]>()
20}
21
22fn temp_name() -> String {
24 format!("{}.temp", hex::encode(new_uuid()))
25}
26
27#[derive(Debug, Default, Clone)]
28struct TempCounters {
29 raw: u64,
31 hash_seq: u64,
33}
34
35impl TempCounters {
36 fn counter(&mut self, format: BlobFormat) -> &mut u64 {
37 match format {
38 BlobFormat::Raw => &mut self.raw,
39 BlobFormat::HashSeq => &mut self.hash_seq,
40 }
41 }
42
43 fn inc(&mut self, format: BlobFormat) {
44 let counter = self.counter(format);
45 *counter = counter.checked_add(1).unwrap();
46 }
47
48 fn dec(&mut self, format: BlobFormat) {
49 let counter = self.counter(format);
50 *counter = counter.saturating_sub(1);
51 }
52
53 fn is_empty(&self) -> bool {
54 self.raw == 0 && self.hash_seq == 0
55 }
56}
57
58#[derive(Debug, Clone, Default)]
59struct TempCounterMap(std::collections::BTreeMap<Hash, TempCounters>);
60
61impl TempCounterMap {
62 fn inc(&mut self, value: &HashAndFormat) {
63 let HashAndFormat { hash, format } = value;
64 self.0.entry(*hash).or_default().inc(*format)
65 }
66
67 fn dec(&mut self, value: &HashAndFormat) {
68 let HashAndFormat { hash, format } = value;
69 let counters = self.0.get_mut(hash).unwrap();
70 counters.dec(*format);
71 if counters.is_empty() {
72 self.0.remove(hash);
73 }
74 }
75
76 fn contains(&self, hash: &Hash) -> bool {
77 self.0.contains_key(hash)
78 }
79
80 fn keys(&self) -> impl Iterator<Item = HashAndFormat> {
81 let mut res = Vec::new();
82 for (k, v) in self.0.iter() {
83 if v.raw > 0 {
84 res.push(HashAndFormat::raw(*k));
85 }
86 if v.hash_seq > 0 {
87 res.push(HashAndFormat::hash_seq(*k));
88 }
89 }
90 res.into_iter()
91 }
92}