1#[cfg(not(feature = "std"))]
8use crate::nostd_prelude::*;
9use crate::string_set::pick_value_for_set_owned;
10use crate::util::{fmt_num, format_i64_into, itoa_i64_stack, parse_f64};
11use crate::value::{SmallBytes, Value};
12use crate::{Entry, Store, StoreError};
13
14impl Store {
15 pub fn append(&mut self, key: &[u8], data: &[u8]) -> Result<usize, StoreError> {
16 self.tier_resolve(key, crate::value::COLD_TAG_STRING)?; let outcome = match self.live_entry_mut(key) {
18 Some(e) => match &mut e.value {
19 Value::Str(v) => {
20 let mut owned = core::mem::take(v).into_vec();
22 owned.extend_from_slice(data);
23 let new_len = owned.len();
24 *v = SmallBytes::from_vec(owned);
25 AppendOutcome::Reweigh(new_len)
26 }
27 Value::Int(n) => {
30 let mut buf = itoa_i64_stack();
31 let mut owned = format_i64_into(*n, &mut buf).to_vec();
32 owned.extend_from_slice(data);
33 let new_len = owned.len();
34 e.value = pick_value_for_set_owned(owned);
35 AppendOutcome::Reweigh(new_len)
36 }
37 Value::ArcBulk(a) => {
41 let mut owned: Vec<u8> = a.as_ref().to_vec();
42 owned.extend_from_slice(data);
43 let new_len = owned.len();
44 e.value = pick_value_for_set_owned(owned);
45 AppendOutcome::Reweigh(new_len)
46 }
47 _ => return Err(StoreError::WrongType),
48 },
49 None => AppendOutcome::Insert,
50 };
51 match outcome {
52 AppendOutcome::Reweigh(new_len) => {
53 self.reweigh_entry(key);
54 Ok(new_len)
55 }
56 AppendOutcome::Insert => {
57 self.insert_entry(
58 SmallBytes::from_slice(key),
59 Entry::new(Value::Str(SmallBytes::from_slice(data)), None),
60 );
61 Ok(data.len())
62 }
63 }
64 }
65 pub fn getset(&mut self, key: &[u8], val: Vec<u8>) -> Result<Option<Vec<u8>>, StoreError> {
68 self.tier_resolve(key, crate::value::COLD_TAG_STRING)?;
69 let old = match self.live_entry(key) {
70 Some(e) => match &e.value {
71 Value::Str(v) => Some(v.to_vec()),
72 Value::Int(n) => {
73 let mut buf = itoa_i64_stack();
74 Some(format_i64_into(*n, &mut buf).to_vec())
75 }
76 Value::ArcBulk(a) => Some(a.as_ref().to_vec()),
77 _ => return Err(StoreError::WrongType),
78 },
79 None => None,
80 };
81 self.insert_entry(
84 SmallBytes::from_slice(key),
85 Entry::new(pick_value_for_set_owned(val), None),
86 );
87 Ok(old)
88 }
89
90 pub fn getdel(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>, StoreError> {
92 self.tier_resolve(key, crate::value::COLD_TAG_STRING)?;
93 match self.live_entry(key) {
94 None => return Ok(None),
95 Some(e) => match &e.value {
96 Value::Str(_) | Value::Int(_) | Value::ArcBulk(_) => {}
97 _ => return Err(StoreError::WrongType),
98 },
99 }
100 match self.remove_entry(key) {
101 Some(Entry {
102 value: Value::Str(v),
103 ..
104 }) => Ok(Some(v.into_vec())),
105 Some(Entry {
106 value: Value::Int(n),
107 ..
108 }) => {
109 let mut buf = itoa_i64_stack();
110 Ok(Some(format_i64_into(n, &mut buf).to_vec()))
111 }
112 Some(Entry {
113 value: Value::ArcBulk(a),
114 ..
115 }) => Ok(Some(a.as_ref().to_vec())),
116 _ => Ok(None),
117 }
118 }
119
120 pub fn incr_by_float(&mut self, key: &[u8], delta: f64) -> Result<Vec<u8>, StoreError> {
122 self.tier_resolve(key, crate::value::COLD_TAG_STRING)?;
123 let outcome = if let Some(e) = self.live_entry_mut(key) { match &mut e.value {
124 Value::Str(v) => {
125 let cur = parse_f64(v.as_slice()).ok_or(StoreError::NotFloat)?;
126 let bytes = float_incr_bytes(cur, delta)?;
127 *v = SmallBytes::from_slice(&bytes);
128 FloatOutcome::Reweigh(bytes)
129 }
130 Value::Int(n) => {
131 let bytes = float_incr_bytes(*n as f64, delta)?;
132 e.value = Value::Str(SmallBytes::from_slice(&bytes));
133 FloatOutcome::Reweigh(bytes)
134 }
135 Value::ArcBulk(a) => {
136 let cur = parse_f64(a.as_ref()).ok_or(StoreError::NotFloat)?;
137 let bytes = float_incr_bytes(cur, delta)?;
138 e.value = Value::Str(SmallBytes::from_slice(&bytes));
139 FloatOutcome::Reweigh(bytes)
140 }
141 _ => return Err(StoreError::WrongType),
142 } } else {
143 if !delta.is_finite() {
145 return Err(StoreError::NotFloat);
146 }
147 FloatOutcome::Insert(fmt_num(delta))
148 };
149 match outcome {
150 FloatOutcome::Reweigh(bytes) => {
151 self.reweigh_entry(key);
152 Ok(bytes)
153 }
154 FloatOutcome::Insert(bytes) => {
155 self.insert_entry(
156 SmallBytes::from_slice(key),
157 Entry::new(Value::Str(SmallBytes::from_slice(&bytes)), None),
158 );
159 Ok(bytes)
160 }
161 }
162 }
163}
164
165enum AppendOutcome {
166 Reweigh(usize),
167 Insert,
168}
169
170enum FloatOutcome {
171 Reweigh(Vec<u8>),
172 Insert(Vec<u8>),
173}
174
175#[inline]
178fn float_incr_bytes(cur: f64, delta: f64) -> Result<Vec<u8>, StoreError> {
179 let next = cur + delta;
180 if !next.is_finite() {
181 return Err(StoreError::NotFloat);
182 }
183 Ok(fmt_num(next))
184}