use std::ops::Deref;
use std::ptr;
use crate::{read_int, write_int, Bytes, RedisRocksdb, RrError, Stack};
impl Stack for RedisRocksdb {
fn index<K: Bytes>(&self, key: &K, _index: i64) -> Result<Vec<u8>, RrError> {
let stack = StackHeader::get_stack(&self.db, key.as_ref())?;
match stack {
None => Ok(vec![]),
Some(v) => Ok(v.size.to_vec()),
}
}
fn len<K: Bytes>(&self, _key: &K) -> Result<i64, RrError> {
todo!()
}
fn push<K: Bytes, V: Bytes>(&mut self, _key: &K, _value: &V) -> Result<i64, RrError> {
todo!()
}
fn pushs<K: Bytes, V: Bytes>(&mut self, _key: &K, _values: &[&V]) -> Result<i64, RrError> {
todo!()
}
fn push_exists<K: Bytes, V: Bytes>(&mut self, _key: &K, _value: &V) -> Result<i64, RrError> {
todo!()
}
fn range<K: Bytes>(&self, _key: &K, _start: i64, _stop: i64) -> Result<Vec<Vec<u8>>, RrError> {
todo!()
}
fn set<K: Bytes, V: Bytes>(&mut self, _key: &K, _index: i64, _value: &V) -> Result<Vec<u8>, RrError> {
todo!()
}
fn pop<K: Bytes>(&self, _key: &K) -> Result<Vec<u8>, RrError> {
todo!()
}
fn pops<K: Bytes>(&self, _key: &K, _amount: u64) -> Result<Vec<Vec<u8>>, RrError> {
todo!()
}
fn poplpush<K: Bytes, V: Bytes>(&mut self, _key: &K, _dstkey: &K) -> Result<V, RrError> {
todo!()
}
fn clear<K: Bytes>(&mut self, _key: &K) -> Result<i64, RrError> {
todo!()
}
}
struct StackHeader {
size: [u8; 8],
}
impl StackHeader {
fn size_i64(&self) -> i64 {
read_int(&self.size)
}
fn add_1(&mut self) -> i64 {
let mut t = read_int(&self.size);
t += 1;
write_int(&mut self.size, t);
t
}
fn add(&mut self, v: i64) -> i64 {
let mut t = read_int(&self.size);
t += v;
write_int(&mut self.size, t);
t
}
fn make_key_index(key: &[u8], index: i64) -> Vec<u8> {
let mut v = Vec::with_capacity(key.len() + 9);
unsafe {
v.set_len(v.capacity());
ptr::copy(key.as_ptr(), v.as_mut_ptr(), key.len());
}
let vv = v.as_mut_slice();
vv[key.len()] = b'_';
write_int(&mut vv[key.len() + 1..], index);
v
}
fn get_stack(db: &rocksdb::TransactionDB, key: &[u8]) -> Result<Option<Self>, RrError> {
let v = db.get(key)?;
match v {
None => Ok(None),
Some(v) => {
if v.len() < 8 {
Err(RrError::data_error("key < 8"))
} else {
Ok(Some(StackHeader::from(v.deref())))
}
},
}
}
fn get_index(&self, db: &rocksdb::TransactionDB, key: &[u8], _index: i64) -> Result<Vec<u8>, RrError> {
let v = db.get(key)?;
match v {
None => Ok(vec![]),
Some(v) => {
if v.len() < 8 {
Err(RrError::data_error("key < 8"))
} else {
Ok(v.to_vec())
}
},
}
}
}
impl From<i64> for StackHeader {
fn from(value: i64) -> Self {
let mut s = StackHeader { size: [0; 8] };
write_int(&mut s.size, value);
s
}
}
impl From<&[u8]> for StackHeader {
fn from(value: &[u8]) -> Self {
let mut s = StackHeader { size: [0; 8] };
s.size.copy_from_slice(value);
s
}
}
impl AsRef<[u8]> for StackHeader {
fn as_ref(&self) -> &[u8] {
&self.size
}
}
impl Bytes for StackHeader {}