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