radish_database/
list.rs

1/* Copyright (c) 2020 Dmitry Shatilov <shatilov dot diman at gmail dot com>
2 * 
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU Affero General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * GNU Affero General Public License for more details.
12
13 * You should have received a copy of the GNU Affero General Public License
14 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
15 */
16
17use std::collections::VecDeque;
18
19use super::container::Container;
20use super::container::ContainerPtr;
21use super::container::ContainerImpl;
22
23type Key = super::Key;
24type Value = super::Value;
25type Arguments = super::Arguments;
26type ExecResult = super::ExecResult;
27
28type Inner = VecDeque<Value>;
29
30impl super::Storage {
31	async fn list_get_container(&self, key: Key) -> ContainerPtr {
32		self.get_container(key, ||Container::List(ContainerImpl::<Inner>::new())).await
33	}
34	async fn list_try_get_container(&self, key: &Key) -> Option<ContainerPtr> {
35		self.try_get_container(key).await
36	}
37	async fn list_unwrap_container(container: &Container) -> Result<&ContainerImpl<Inner>, String> {
38		match container {
39			Container::List(ref c) => Ok(c),
40			_ => Err(format!("Unexpected container type")),
41		}
42	}
43	async fn list_unwrap_mut_container(container: &mut Container) -> Result<&mut ContainerImpl<Inner>, String> {
44		match container {
45			Container::List(ref mut c) => Ok(c),
46			_ => Err(format!("Unexpected container type")),
47		}
48	}
49	async fn list_lock<F: FnOnce(&Inner) -> ExecResult>(&self, key: Key, processor: F) -> ExecResult {
50		let c1 = self.list_get_container(key).await;
51		let c2 = c1.lock().await;
52		let c3 = Self::list_unwrap_container(&c2).await?;
53		processor(&c3.inner)
54	}
55	async fn list_lock_mut<F: FnOnce(&mut Inner) -> ExecResult>(&self, key: Key, processor: F) -> ExecResult {
56		let c1 = self.list_get_container(key).await;
57		let mut c2 = c1.lock().await;
58		let c3 = Self::list_unwrap_mut_container(&mut c2).await?;
59		processor(&mut c3.inner)
60	}
61	async fn list_try_lock_mut<F: FnOnce(&mut Inner) -> ExecResult>(&self, key: Key, processor: F) -> ExecResult {
62		match self.list_try_get_container(&key).await {
63			None => Ok(Value::Nill),
64			Some(c1) => {
65				let mut c2 = c1.lock().await;
66				let c3 = Self::list_unwrap_mut_container(&mut c2).await?;
67				processor(&mut c3.inner)
68			}
69		}
70	}
71
72	pub async fn list_len(&self, mut args: Arguments) -> ExecResult {
73		let key = Self::extract_key(args.pop_front())?;
74		self.list_lock(key, |list| -> ExecResult {
75			Ok(Value::Integer(list.len() as i64))
76		}).await
77	}
78
79	pub async fn list_lpush(&self, mut args: Arguments) -> ExecResult {
80		let key = Self::extract_key(args.pop_front())?;
81		self.list_lock_mut(key, |list| -> ExecResult {
82			for arg in args {
83				list.push_front(arg);
84			}
85			Ok(Value::Integer(list.len() as i64))
86		}).await
87	}
88
89	pub async fn list_rpush(&self, mut args: Arguments) -> ExecResult {
90		let key = Self::extract_key(args.pop_front())?;
91		self.list_lock_mut(key, |list| -> ExecResult {
92			for arg in args {
93				list.push_back(arg);
94			}
95			Ok(Value::Integer(list.len() as i64))
96		}).await
97	}
98
99	pub async fn list_lpushx(&self, mut args: Arguments) -> ExecResult {
100		let key = Self::extract_key(args.pop_front())?;
101		self.list_try_lock_mut(key, |list| -> ExecResult {
102			for arg in args {
103				list.push_front(arg);
104			}
105			Ok(Value::Integer(list.len() as i64))
106		}).await
107	}
108
109	pub async fn list_rpushx(&self, mut args: Arguments) -> ExecResult {
110		let key = Self::extract_key(args.pop_front())?;
111		self.list_try_lock_mut(key, |list| -> ExecResult {
112			for arg in args {
113				list.push_back(arg);
114			}
115			Ok(Value::Integer(list.len() as i64))
116		}).await
117	}
118
119	pub async fn list_lpop(&self, mut args: Arguments) -> ExecResult {
120		let key = Self::extract_key(args.pop_front())?;
121		self.list_lock_mut(key, |list| -> ExecResult {
122			match list.pop_front() {
123				Some(v) => Ok(v),
124				None => Ok(Value::Nill),
125			}
126		}).await
127	}
128
129	pub async fn list_rpop(&self, mut args: Arguments) -> ExecResult {
130		let key = Self::extract_key(args.pop_front())?;
131		self.list_lock_mut(key, |list| -> ExecResult {
132			match list.pop_back() {
133				Some(v) => Ok(v),
134				None => Ok(Value::Nill),
135			}
136		}).await
137	}
138
139	pub async fn list_rem(&self, mut args: Arguments) -> ExecResult {
140		let key = Self::extract_key(args.pop_front())?;
141		let index = Self::extract_index(args.pop_front())?;
142		self.list_lock_mut(key, |list| -> ExecResult {
143			match list.remove(index) {
144				Some(v) => Ok(v),
145				None => Err(format!("{}", "Out of index")),
146			}
147		}).await
148	}
149
150	pub async fn list_set(&self, mut args: Arguments) -> ExecResult {
151		let key = Self::extract_key(args.pop_front())?;
152		let index = Self::extract_index(args.pop_front())?;
153		let value = Self::extract(args.pop_front())?;
154		self.list_lock_mut(key, |list| -> ExecResult {
155			match list.get_mut(index) {
156				None => Err(format!("{}\r\n", "Out of index")),
157				Some(v) => {
158					let mut x = value;
159					std::mem::swap(v, &mut x);
160					Ok(x)
161				},
162			}
163		}).await
164	}
165
166	pub async fn list_index(&self, mut args: Arguments) -> ExecResult {
167		let key = Self::extract_key(args.pop_front())?;
168		let index = Self::extract_index(args.pop_front())?;
169		self.list_lock(key, |list| -> ExecResult {
170			match list.get(index) {
171				Some(v) => Ok((*v).clone()),
172				None => Err(format!("{}\r\n", "Out of index")),
173			}
174		}).await
175	}
176
177	pub async fn list_range(&self, mut args: Arguments) -> ExecResult {
178		let key = Self::extract_key(args.pop_front())?;
179		let start = Self::extract_index(args.pop_front())?;
180		let stop = Self::extract_index(args.pop_front())?;
181		self.list_lock(key, |list| -> ExecResult {
182			let start = std::cmp::min(start, list.len());
183			let end = std::cmp::min(stop+1, list.len());
184			let mut out = VecDeque::with_capacity(end - start);
185			for i in start..end {
186				if let Some(v) = list.get(i) {
187					out.push_back((*v).clone());
188				}
189			}
190			Ok(Value::Array(out))
191		}).await
192	}
193
194	pub async fn list_insert(&self, mut args: Arguments) -> ExecResult {
195		let key = Self::extract_key(args.pop_front())?;
196		let before_after = Self::extract_string(args.pop_front())?;
197		let pivot = Self::extract(args.pop_front())?;
198		let value = Self::extract(args.pop_front())?;
199		self.list_lock_mut(key, |list| -> ExecResult {
200			let shift = match &before_after.to_lowercase()[..] {
201				"before" => 0,
202				"after" => 1,
203				dir => return Err(format!("Unexpected direction {}", dir)),
204			};
205
206			let index = list.iter().position(|v| *v == pivot);
207			if let Some(index) = index {
208				list.insert(index + shift, value);
209				Ok(Value::Integer(list.len() as i64))
210			} else {
211				Ok(Value::Integer(-1))
212			}
213		}).await
214	}
215
216	pub async fn list_trim(&self, mut args: Arguments) -> ExecResult {
217		let key = Self::extract_key(args.pop_front())?;
218		let start = Self::extract_integer(args.pop_front())?;
219		let stop = Self::extract_integer(args.pop_front())?;
220		self.list_lock_mut(key, |list| -> ExecResult {
221			let start = if start < 0 {list.len() as i64 + start} else {start} as usize;
222			let start = std::cmp::min(start, list.len());
223			let stop = if stop < 0 {list.len() as i64 + stop} else {stop} as usize;
224			let stop = std::cmp::min(stop, list.len());
225			if start > stop || start >= list.len() {
226				list.clear();
227			} else if start > 0 {
228				list.rotate_left(start);
229				list.truncate(stop+1 - start);
230			} else {
231				list.truncate(stop+1);
232			}
233
234			Ok(Value::Ok)
235		}).await
236	}
237
238	pub async fn _list_rpop_lpush(&self, mut args: Arguments) -> ExecResult {
239		let source = Self::extract_key(args.pop_front())?;
240		let destination = Self::extract_key(args.pop_front())?;
241		if source == destination {
242			self.list_try_lock_mut(source, |list| -> ExecResult {
243				if let Some(v) = list.pop_back() {
244					list.push_front(v.clone());
245					Ok(v)
246				} else {
247					Ok(Value::Nill)
248				}
249			}).await
250		} else {
251			Ok(Value::Error("Should be atomic!!!".to_string()))
252		}
253	}
254}
255