use std::io;
use std::io::{Cursor, Error, ErrorKind, Read};
use byteorder::{LittleEndian, ReadBytesExt};
use crate::rdb::{read_zip_list_entry, read_zm_len, Field, Item, RDBDecode};
pub(crate) trait Iter {
fn next(&mut self) -> io::Result<Vec<u8>>;
}
pub(crate) struct StrValIter<'a> {
pub(crate) count: isize,
pub(crate) input: &'a mut dyn Read,
}
impl Iter for StrValIter<'_> {
fn next(&mut self) -> io::Result<Vec<u8>> {
while self.count > 0 {
let val = self.input.read_string()?;
self.count -= 1;
return Ok(val);
}
Err(Error::new(ErrorKind::NotFound, "No element left"))
}
}
pub(crate) struct QuickListIter<'a> {
pub(crate) len: isize,
pub(crate) count: isize,
pub(crate) input: &'a mut dyn Read,
pub(crate) cursor: Option<Cursor<Vec<u8>>>,
}
impl Iter for QuickListIter<'_> {
fn next(&mut self) -> io::Result<Vec<u8>> {
if self.len == -1 && self.count > 0 {
let data = self.input.read_string()?;
self.cursor = Option::Some(Cursor::new(data));
let cursor = self.cursor.as_mut().unwrap();
cursor.set_position(8);
self.len = cursor.read_i16::<LittleEndian>()? as isize;
if self.len == 0 {
self.len = -1;
self.count -= 1;
}
if self.has_more() {
return self.next();
}
} else {
if self.count > 0 {
let val = read_zip_list_entry(self.cursor.as_mut().unwrap())?;
self.len -= 1;
if self.len == 0 {
self.len = -1;
self.count -= 1;
}
return Ok(val);
}
}
Err(Error::new(ErrorKind::NotFound, "No element left"))
}
}
impl QuickListIter<'_> {
fn has_more(&self) -> bool {
self.len > 0 || self.count > 0
}
}
pub(crate) struct ZipListIter<'a> {
pub(crate) count: isize,
pub(crate) cursor: &'a mut Cursor<Vec<u8>>,
}
impl Iter for ZipListIter<'_> {
fn next(&mut self) -> io::Result<Vec<u8>> {
if self.count > 0 {
let val = read_zip_list_entry(self.cursor)?;
self.count -= 1;
return Ok(val);
}
Err(Error::new(ErrorKind::NotFound, "No element left"))
}
}
pub(crate) struct SortedSetIter<'a> {
pub(crate) count: isize,
pub(crate) v: u8,
pub(crate) input: &'a mut dyn Read,
}
impl SortedSetIter<'_> {
pub(crate) fn next(&mut self) -> io::Result<Item> {
if self.count > 0 {
let member = self.input.read_string()?;
let score;
if self.v == 1 {
score = self.input.read_double()?;
} else {
let score_u64 = self.input.read_u64::<LittleEndian>()?;
score = f64::from_bits(score_u64);
}
self.count -= 1;
return Ok(Item { member, score });
}
Err(Error::new(ErrorKind::NotFound, "No element left"))
}
}
pub(crate) struct ZipMapIter<'a> {
pub(crate) has_more: bool,
pub(crate) cursor: &'a mut Cursor<&'a Vec<u8>>,
}
impl ZipMapIter<'_> {
pub(crate) fn next(&mut self) -> io::Result<Field> {
if !self.has_more {
return Err(Error::new(ErrorKind::NotFound, "No element left"));
}
let zm_len = read_zm_len(self.cursor)?;
if zm_len == 255 {
self.has_more = false;
return Err(Error::new(ErrorKind::NotFound, "No element left"));
}
let mut field = vec![0; zm_len];
self.cursor.read_exact(&mut field)?;
let zm_len = read_zm_len(self.cursor)?;
if zm_len == 255 {
self.has_more = false;
return Ok(Field {
name: field,
value: Vec::new(),
});
};
let free = self.cursor.read_i8()?;
let mut val = vec![0; zm_len];
self.cursor.read_exact(&mut val)?;
self.cursor.set_position(self.cursor.position() + free as u64);
return Ok(Field {
name: field,
value: val,
});
}
}
pub(crate) struct IntSetIter<'a> {
pub(crate) encoding: i32,
pub(crate) count: isize,
pub(crate) cursor: &'a mut Cursor<&'a Vec<u8>>,
}
impl Iter for IntSetIter<'_> {
fn next(&mut self) -> io::Result<Vec<u8>> {
if self.count > 0 {
let val;
match self.encoding {
2 => {
let member = self.cursor.read_i16::<LittleEndian>()?;
let member = member.to_string().into_bytes();
val = member;
}
4 => {
let member = self.cursor.read_i32::<LittleEndian>()?;
let member = member.to_string().into_bytes();
val = member;
}
8 => {
let member = self.cursor.read_i64::<LittleEndian>()?;
let member = member.to_string().into_bytes();
val = member;
}
_ => panic!("Invalid integer size: {}", self.encoding),
}
self.count -= 1;
return Ok(val);
}
return Err(Error::new(ErrorKind::NotFound, "No element left"));
}
}