1#[cfg(not(feature = "std"))]
6use crate::nostd_prelude::*;
7use crate::small_zset::{self, AddResult as ZAddResult, SmallZSetData};
8use crate::value::{SmallBytes, Value, ZSetData, zset_member_weight};
9use crate::zset_seg::{SegZSetData, Z_PROMOTE};
10use crate::{Entry, Store, StoreError};
11use alloc::sync::Arc;
12
13#[inline]
28fn fold_zero_sign(score: f64) -> f64 {
29 if score == 0.0 { 0.0 } else { score }
30}
31
32impl Store {
33 fn zset_mut(&mut self, key: &[u8], create: bool) -> Result<Option<ZRefMut<'_>>, StoreError> {
39 if self.live_entry_mut(key).is_none() {
40 if !create {
41 return Ok(None);
42 }
43 self.insert_entry(
44 SmallBytes::from_slice(key),
45 Entry::new(Value::ZSet(Arc::default()), None),
46 );
47 }
48 let needs = match self.map.get(key).map(|e| &e.value) {
50 Some(Value::SmallZSetInline(_)) => true,
51 Some(Value::ZSet(z)) => z.len() >= Z_PROMOTE,
52 _ => false,
53 };
54 if needs {
55 self.promote_zset_encoding(key);
56 }
57 match &mut self.map.get_mut(key).expect("present").value {
58 Value::ZSet(z) => Ok(Some(ZRefMut::Flat(Arc::make_mut(z)))),
59 Value::SegZSet(z) => Ok(Some(ZRefMut::Seg(Arc::make_mut(z)))),
60 _ => Err(StoreError::WrongType),
61 }
62 }
63
64 fn promote_zset_encoding(&mut self, key: &[u8]) {
67 let Some(e) = self.map.get_mut(key) else { return };
68 match &mut e.value {
69 Value::SmallZSetInline(s) => {
70 e.value = Value::ZSet(Arc::new(small_zset::promote(s)));
71 }
72 Value::ZSet(z) => {
73 e.value = Value::SegZSet(Arc::new(SegZSetData::from_flat(z)));
74 }
75 _ => return,
76 }
77 self.reweigh_entry(key);
78 }
79
80 fn zset_value_for_set(&mut self, key: &[u8]) -> Result<Option<&mut Value>, StoreError> {
82 match self.live_entry_mut(key) {
83 None => Ok(None),
84 Some(e) => match &e.value {
85 Value::ZSet(_) | Value::SegZSet(_) | Value::SmallZSetInline(_) => {
86 Ok(Some(&mut e.value))
87 }
88 _ => Err(StoreError::WrongType),
89 },
90 }
91 }
92
93 fn drop_if_empty_zset(&mut self, key: &[u8]) {
94 let empty = match self.map.get(key).map(|e| &e.value) {
95 Some(Value::ZSet(z)) => z.len() == 0,
96 Some(Value::SegZSet(z)) => z.is_empty(),
97 Some(Value::SmallZSetInline(z)) => z.is_empty(),
98 _ => false,
99 };
100 if empty {
101 self.remove_entry(key);
102 }
103 }
104
105 pub fn zadd(&mut self, key: &[u8], pairs: &[(f64, &[u8])]) -> Result<usize, StoreError> {
109 if pairs.is_empty() {
110 return Ok(0);
111 }
112 let mut added = 0usize;
113 let mut delta: i64 = 0;
114 for (score, m) in pairs {
115 match self.zadd_one(key, m, *score)? {
116 ZaddOutcome::AddedInline => added += 1,
117 ZaddOutcome::UpdatedInline => {}
118 ZaddOutcome::AddedHeap(w) => {
119 added += 1;
120 delta += w;
121 }
122 ZaddOutcome::UpdatedHeap => {}
123 }
124 }
125 self.account_delta(key, delta);
126 Ok(added)
127 }
128
129 pub fn zscore(&mut self, key: &[u8], member: &[u8]) -> Result<Option<f64>, StoreError> {
132 match self.live_entry(key) {
133 None => Ok(None),
134 Some(e) => match &e.value {
135 Value::ZSet(z) => Ok(z.by_member.get(member).copied()),
136 Value::SegZSet(z) => Ok(z.score_of(member)),
137 Value::SmallZSetInline(z) => Ok(z.score(member)),
138 _ => Err(StoreError::WrongType),
139 },
140 }
141 }
142
143 pub fn zcard(&mut self, key: &[u8]) -> Result<usize, StoreError> {
145 match self.live_entry(key) {
146 None => Ok(0),
147 Some(e) => match &e.value {
148 Value::ZSet(z) => Ok(z.len()),
149 Value::SegZSet(z) => Ok(z.len()),
150 Value::SmallZSetInline(z) => Ok(z.len()),
151 _ => Err(StoreError::WrongType),
152 },
153 }
154 }
155
156 pub fn zrem(&mut self, key: &[u8], members: &[&[u8]]) -> Result<usize, StoreError> {
158 let (removed, delta) = {
159 let mut r = 0usize;
160 let mut d: i64 = 0;
161 if let Some(e) = self.live_entry_mut(key) {
162 match &mut e.value {
163 Value::ZSet(z) => {
164 let z = Arc::make_mut(z);
166 for m in members {
167 if z.remove(m) {
168 r += 1;
169 d -= zset_member_weight(&SmallBytes::from_slice(m)) as i64;
170 }
171 }
172 }
173 Value::SegZSet(z) => {
174 let z = Arc::make_mut(z);
175 for m in members {
176 if z.remove(m) {
177 r += 1;
178 d -= zset_member_weight(&SmallBytes::from_slice(m)) as i64;
179 }
180 }
181 }
182 Value::SmallZSetInline(z) => {
183 for m in members {
184 if z.try_remove(m) {
185 r += 1;
186 }
187 }
188 }
189 _ => return Err(StoreError::WrongType),
190 }
191 }
192 (r, d)
193 };
194 self.account_delta(key, delta);
195 self.drop_if_empty_zset(key);
196 Ok(removed)
197 }
198
199 pub fn zrank(&mut self, key: &[u8], member: &[u8]) -> Result<Option<usize>, StoreError> {
202 match self.live_entry(key) {
203 None => Ok(None),
204 Some(e) => match &e.value {
205 Value::ZSet(z) => {
206 Ok(z.by_member.get(member).copied().and_then(|sc| z.rank_of(member, sc)))
207 }
208 Value::SegZSet(z) => Ok(z.score_of(member).and_then(|sc| z.rank_of(member, sc))),
209 Value::SmallZSetInline(z) => {
210 let mut entries: Vec<(&[u8], f64)> = z.iter().collect();
213 entries.sort_by(|a, b| a.1.total_cmp(&b.1).then_with(|| a.0.cmp(b.0)));
214 Ok(entries.iter().position(|(m, _)| *m == member))
215 }
216 _ => Err(StoreError::WrongType),
217 },
218 }
219 }
220
221 pub fn zincrby(&mut self, key: &[u8], incr: f64, member: &[u8]) -> Result<f64, StoreError> {
223 let mut z = self.zset_mut(key, true)?.expect("created");
224 let cur = z.score_of(member).unwrap_or(0.0);
225 let next = cur + incr;
226 let smb = SmallBytes::from_slice(member);
227 let is_new = !z.contains_member(member);
228 z.insert(member, next);
229 let d = if is_new { zset_member_weight(&smb) as i64 } else { 0 };
230 self.account_delta(key, d);
231 Ok(next)
232 }
233
234 fn zadd_one(&mut self, key: &[u8], m: &[u8], score: f64) -> Result<ZaddOutcome, StoreError> {
236 let score = fold_zero_sign(score);
237 if self.zset_value_for_set(key)?.is_none() {
238 return Ok(self.zadd_create(key, m, score));
239 }
240 let v = self.zset_value_for_set(key)?.expect("present and a zset");
241 match v {
242 Value::SmallZSetInline(z) => match z.try_set(m, score) {
243 ZAddResult::Added => Ok(ZaddOutcome::AddedInline),
244 ZAddResult::Updated => Ok(ZaddOutcome::UpdatedInline),
245 ZAddResult::NoRoom => {
246 let outcome = promote_inline_zset_and_add(v, m, score);
247 self.reweigh_entry(key);
248 Ok(outcome)
249 }
250 },
251 Value::ZSet(z) if z.len() >= Z_PROMOTE => {
252 let is_new = promote_flat_zset_and_add(v, m, score);
253 self.reweigh_entry(key);
254 if is_new { Ok(ZaddOutcome::AddedHeap(0)) } else { Ok(ZaddOutcome::UpdatedHeap) }
256 }
257 Value::ZSet(z) => {
258 let z = Arc::make_mut(z);
259 let smb = SmallBytes::from_slice(m);
260 let w = zset_member_weight(&smb) as i64;
261 if z.insert(m, score) {
262 Ok(ZaddOutcome::AddedHeap(w))
263 } else {
264 Ok(ZaddOutcome::UpdatedHeap)
265 }
266 }
267 Value::SegZSet(z) => {
268 let z = Arc::make_mut(z);
269 let smb = SmallBytes::from_slice(m);
270 let w = zset_member_weight(&smb) as i64;
271 if z.insert(m, score) {
272 Ok(ZaddOutcome::AddedHeap(w))
273 } else {
274 Ok(ZaddOutcome::UpdatedHeap)
275 }
276 }
277 _ => Err(StoreError::WrongType),
278 }
279 }
280
281 fn zadd_create(&mut self, key: &[u8], m: &[u8], score: f64) -> ZaddOutcome {
283 if let Some(inline) = SmallZSetData::with_one(m, score) {
284 self.insert_entry(
285 SmallBytes::from_slice(key),
286 Entry::new(Value::SmallZSetInline(inline), None),
287 );
288 ZaddOutcome::AddedInline
289 } else {
290 let mut z = ZSetData::default();
291 z.insert(m, score);
292 self.insert_entry(
293 SmallBytes::from_slice(key),
294 Entry::new(Value::ZSet(Arc::new(z)), None),
295 );
296 ZaddOutcome::AddedInline
297 }
298 }
299}
300
301fn promote_inline_zset_and_add(v: &mut Value, m: &[u8], score: f64) -> ZaddOutcome {
304 let Value::SmallZSetInline(z) = v else { unreachable!("matched inline") };
305 let mut promoted = small_zset::promote(z);
306 let smb = SmallBytes::from_slice(m);
307 let is_new = !promoted.by_member.contains_key(m);
308 let w = zset_member_weight(&smb) as i64;
309 promoted.insert(m, score);
310 *v = Value::ZSet(Arc::new(promoted));
311 if is_new { ZaddOutcome::AddedHeap(w) } else { ZaddOutcome::UpdatedHeap }
312}
313
314fn promote_flat_zset_and_add(v: &mut Value, m: &[u8], score: f64) -> bool {
318 let Value::ZSet(z) = v else { unreachable!("matched ZSet") };
319 let mut seg = SegZSetData::from_flat(z);
320 let is_new = seg.insert(m, score);
321 *v = Value::SegZSet(Arc::new(seg));
322 is_new
323}
324
325enum ZRefMut<'a> {
328 Flat(&'a mut ZSetData),
329 Seg(&'a mut SegZSetData),
330}
331
332impl ZRefMut<'_> {
333 fn score_of(&self, member: &[u8]) -> Option<f64> {
334 match self {
335 Self::Flat(z) => z.by_member.get(member).copied(),
336 Self::Seg(z) => z.score_of(member),
337 }
338 }
339 fn contains_member(&self, member: &[u8]) -> bool {
340 match self {
341 Self::Flat(z) => z.by_member.contains_key(member),
342 Self::Seg(z) => z.contains_member(member),
343 }
344 }
345 fn insert(&mut self, member: &[u8], score: f64) -> bool {
346 match self {
347 Self::Flat(z) => z.insert(member, score),
348 Self::Seg(z) => z.insert(member, score),
349 }
350 }
351}
352
353enum ZaddOutcome {
354 AddedInline,
355 UpdatedInline,
356 AddedHeap(i64),
357 UpdatedHeap,
358}