use std::{
collections::VecDeque,
io::{self, Read, Write},
};
use parking_lot::Mutex;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum ListOperation {
Lpop = 0,
Lpush = 1,
Lpushx = 2,
Rpop = 3,
Rpush = 4,
Rpushx = 5,
Llen = 6,
Ltrim = 7,
Lrange = 8,
Lindex = 9,
Linsert = 10,
Lrem = 11,
Rpoplpush = 12,
Lmove = 13,
Lset = 14,
Brpop = 15,
Blpop = 16,
Lpos = 17,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum OperationDirection {
Left = 0,
Right = 1,
Unknown = 2,
}
pub struct ListObject {
pub list: Mutex<VecDeque<Vec<u8>>>,
}
impl ListObject {
pub fn new() -> Self {
Self {
list: Mutex::new(VecDeque::new()),
}
}
pub fn deserialize<R: Read>(reader: &mut R) -> io::Result<Self> {
let mut buf = Vec::new();
reader.read_to_end(&mut buf)?;
let list: VecDeque<Vec<u8>> =
bitcode::decode(&buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
Ok(Self {
list: Mutex::new(list),
})
}
pub fn serialize<W: Write>(&self, writer: &mut W) -> io::Result<()> {
let list = self.list.lock();
let bytes = bitcode::encode(&*list);
writer.write_all(&bytes)
}
pub fn operate(&self, op: ListOperation, item: &[u8]) -> Option<Vec<u8>> {
let mut list = self.list.lock();
match op {
ListOperation::Lpush => {
list.push_front(item.to_vec());
None
}
ListOperation::Rpush => {
list.push_back(item.to_vec());
None
}
ListOperation::Lpop => list.pop_front(),
ListOperation::Rpop => list.pop_back(),
_ => None,
}
}
pub fn index(&self, index: isize) -> Option<Vec<u8>> {
let list = self.list.lock();
let len = list.len() as isize;
let actual_idx = if index < 0 { len + index } else { index };
if actual_idx < 0 || actual_idx >= len {
None
} else {
list.get(actual_idx as usize).cloned()
}
}
pub fn range(&self, start: isize, stop: isize) -> Vec<Vec<u8>> {
let list = self.list.lock();
let len = list.len() as isize;
let mut s = if start < 0 { len + start } else { start };
let mut e = if stop < 0 { len + stop } else { stop };
if s < 0 {
s = 0;
}
if e >= len {
e = len - 1;
}
if s > e || s >= len {
return vec![];
}
list.range((s as usize)..=(e as usize)).cloned().collect()
}
pub fn trim(&self, start: isize, stop: isize) {
let mut list = self.list.lock();
let len = list.len() as isize;
let mut s = if start < 0 { len + start } else { start };
let mut e = if stop < 0 { len + stop } else { stop };
if s < 0 {
s = 0;
}
if e >= len {
e = len - 1;
}
if s > e || s >= len {
list.clear();
return;
}
list.truncate((e + 1) as usize);
for _ in 0..s {
list.pop_front();
}
}
pub fn count(&self) -> usize {
self.list.lock().len()
}
}
impl Default for ListObject {
fn default() -> Self {
Self::new()
}
}