1use crate::util::*;
4use crate::value::*;
5use crate::{Entry, Store, StoreError};
6use std::time::Instant;
7
8impl Store {
9 fn hash_mut(&mut self, key: &[u8], create: bool) -> Result<Option<&mut HashData>, StoreError> {
14 if self.live_entry_mut(key).is_none() {
15 if !create {
16 return Ok(None);
17 }
18 self.insert_entry(
19 SmallBytes::from_slice(key),
20 Entry::new(Value::Hash(Box::default()), None),
21 );
22 }
23 match &mut self.map.get_mut(key).expect("present").value {
24 Value::Hash(h) => Ok(Some(h)),
25 _ => Err(StoreError::WrongType),
26 }
27 }
28
29 fn hash_ref(&mut self, key: &[u8]) -> Result<Option<&HashData>, StoreError> {
31 match self.live_entry(key) {
32 None => Ok(None),
33 Some(e) => match &e.value {
34 Value::Hash(h) => Ok(Some(h)),
35 _ => Err(StoreError::WrongType),
36 },
37 }
38 }
39
40 pub fn hset(&mut self, key: &[u8], pairs: &[(Vec<u8>, Vec<u8>)]) -> Result<usize, StoreError> {
42 let (added, delta) = {
43 let h = self.hash_mut(key, true)?.expect("created");
44 let mut a = 0usize;
45 let mut d: i64 = 0;
46 for (f, v) in pairs {
47 let smb = SmallBytes::from_slice(f);
48 let new_w = hash_field_weight(&smb, v.len()) as i64;
49 match h.insert(smb, v.clone()) {
50 None => {
51 a += 1;
52 d += new_w;
53 }
54 Some(old) => {
55 d += v.len() as i64 - old.len() as i64;
56 }
57 }
58 }
59 (a, d)
60 };
61 self.account_delta(key, delta);
62 Ok(added)
63 }
64
65 pub fn hsetnx(&mut self, key: &[u8], field: &[u8], val: &[u8]) -> Result<bool, StoreError> {
67 let outcome = {
68 let h = self.hash_mut(key, true)?.expect("created");
69 if h.contains_key(field) {
70 if h.is_empty() {
71 HsetnxOutcome::DropEmpty
72 } else {
73 HsetnxOutcome::AlreadyExists
74 }
75 } else {
76 let smb = SmallBytes::from_slice(field);
77 let w = hash_field_weight(&smb, val.len()) as i64;
78 h.insert(smb, val.to_vec());
79 HsetnxOutcome::Inserted(w)
80 }
81 };
82 match outcome {
83 HsetnxOutcome::DropEmpty => {
84 self.remove_entry(key);
85 Ok(false)
86 }
87 HsetnxOutcome::AlreadyExists => Ok(false),
88 HsetnxOutcome::Inserted(w) => {
89 self.account_delta(key, w);
90 Ok(true)
91 }
92 }
93 }
94
95 pub fn hget(&mut self, key: &[u8], field: &[u8]) -> Result<Option<&[u8]>, StoreError> {
96 Ok(self
97 .hash_ref(key)?
98 .and_then(|h| h.get(field))
99 .map(|v| v.as_slice()))
100 }
101
102 pub fn hexists(&mut self, key: &[u8], field: &[u8]) -> Result<bool, StoreError> {
103 Ok(self.hash_ref(key)?.is_some_and(|h| h.contains_key(field)))
104 }
105
106 pub fn hlen(&mut self, key: &[u8]) -> Result<usize, StoreError> {
107 Ok(self.hash_ref(key)?.map_or(0, |h| h.len()))
108 }
109
110 pub fn hmget(
111 &mut self,
112 key: &[u8],
113 fields: &[Vec<u8>],
114 ) -> Result<Vec<Option<Vec<u8>>>, StoreError> {
115 let h = self.hash_ref(key)?;
116 Ok(fields
117 .iter()
118 .map(|f| h.and_then(|h| h.get(f.as_slice())).cloned())
119 .collect())
120 }
121
122 pub fn hgetall(&mut self, key: &[u8]) -> Result<Vec<Vec<u8>>, StoreError> {
124 match self.hash_ref(key)? {
125 None => Ok(Vec::new()),
126 Some(h) => {
127 let mut out = Vec::with_capacity(h.len() * 2);
128 for (f, v) in h {
129 out.push(f.to_vec());
130 out.push(v.clone());
131 }
132 Ok(out)
133 }
134 }
135 }
136
137 pub fn hkeys(&mut self, key: &[u8]) -> Result<Vec<Vec<u8>>, StoreError> {
138 Ok(self
139 .hash_ref(key)?
140 .map_or(Vec::new(), |h| h.keys().map(|k| k.to_vec()).collect()))
141 }
142
143 pub fn hvals(&mut self, key: &[u8]) -> Result<Vec<Vec<u8>>, StoreError> {
144 Ok(self
145 .hash_ref(key)?
146 .map_or(Vec::new(), |h| h.values().cloned().collect()))
147 }
148
149 pub fn hdel(&mut self, key: &[u8], fields: &[Vec<u8>]) -> Result<usize, StoreError> {
151 let now = Instant::now();
152 if !self.reap(key, now) {
153 return Ok(0);
154 }
155 let (removed, delta, drop_key) = {
156 let h_entry = self.map.get_mut(key).expect("live");
157 match &mut h_entry.value {
158 Value::Hash(h) => {
159 let mut r = 0usize;
160 let mut d: i64 = 0;
161 for f in fields {
162 if let Some(old_v) = h.remove(f.as_slice()) {
163 r += 1;
164 let smb = SmallBytes::from_slice(f);
168 d -= hash_field_weight(&smb, old_v.len()) as i64;
169 }
170 }
171 let drop_now = h.is_empty();
172 (r, d, drop_now)
173 }
174 _ => return Err(StoreError::WrongType),
175 }
176 };
177 if drop_key {
178 self.remove_entry(key);
179 } else {
180 self.account_delta(key, delta);
181 }
182 Ok(removed)
183 }
184
185 pub fn hincrby(&mut self, key: &[u8], field: &[u8], delta: i64) -> Result<i64, StoreError> {
187 let (next, weight_delta) = {
188 let h = self.hash_mut(key, true)?.expect("created");
189 let cur = match h.get(field) {
190 Some(v) => parse_i64(v).ok_or(StoreError::NotInteger)?,
191 None => 0,
192 };
193 let next = cur.checked_add(delta).ok_or(StoreError::Overflow)?;
194 let new_bytes = next.to_string().into_bytes();
195 let smb = SmallBytes::from_slice(field);
196 let new_field_w = hash_field_weight(&smb, new_bytes.len()) as i64;
197 let new_value_len = new_bytes.len();
198 let wd = match h.insert(smb, new_bytes) {
199 None => new_field_w,
200 Some(old) => new_value_len as i64 - old.len() as i64,
201 };
202 (next, wd)
203 };
204 self.account_delta(key, weight_delta);
205 Ok(next)
206 }
207}
208
209enum HsetnxOutcome {
210 DropEmpty,
211 AlreadyExists,
212 Inserted(i64),
213}