1use lzf;
2use com::*;
3use consts::*;
4use self::super::{FromBuf, Shift};
5
6#[derive(Debug, Clone)]
7pub enum Length {
8 Small(u8),
9 Normal(u16),
10 Large(u32),
11}
12
13impl FromBuf for Length {
14 fn from_buf(src: &[u8]) -> Result<Self> {
16 let ltype = src[0] >> 6;
17 match ltype {
18 REDIS_RDB_6BITLEN => Ok(Length::Small(src[0] & 0x3f)),
19 REDIS_RDB_14BITLEN => {
20 let value = buf_to_u16_big(src);
21 Ok(Length::Normal(value & 0x3fff))
22 }
23 REDIS_RDB_32BITLEN => {
24 more!(src.len() < 1 + 3);
25 let value = buf_to_u32_big(src);
26 Ok(Length::Large(value & 0x3fff_ffff))
27 }
28 REDIS_RDB_ENCVAL => Err(Error::Other),
29 _ => Err(Error::Faild("wrong length encode prefix")),
30 }
31 }
32}
33
34impl Length {
35 pub fn length(&self) -> usize {
36 match self {
37 &Length::Small(val) => val as usize,
38 &Length::Normal(val) => val as usize,
39 &Length::Large(val) => val as usize,
40 }
41 }
42}
43
44impl Shift for Length {
45 #[inline]
46 fn shift(&self) -> usize {
47 match self {
48 &Length::Small(_) => 1,
49 &Length::Normal(_) => 2,
50 &Length::Large(_) => 5,
51 }
52 }
53}
54
55
56#[derive(Debug, Clone)]
57pub enum RedisString {
58 LengthPrefix { len: Length, data: Vec<u8> },
59 StrInt(StrInt),
60 LZF(LZFString),
61}
62
63impl Shift for RedisString {
64 fn shift(&self) -> usize {
65 match self {
66 &RedisString::LengthPrefix { ref len, ref data } => len.shift() + data.len(),
67 &RedisString::StrInt(ref ival) => ival.shift(),
68 &RedisString::LZF(ref lzf) => lzf.shift(),
69 }
70 }
71}
72
73impl FromBuf for RedisString {
74 fn from_buf(src: &[u8]) -> Result<RedisString> {
75 choice!(RedisString::length_prefix(src));
76 choice!(RedisString::str_int(src));
77 choice!(RedisString::lzf(src));
78 Err(Error::Faild("can't parse buffer as RedisString"))
79 }
80}
81
82impl RedisString {
83 pub fn into_data(self) -> Vec<u8> {
84 match self {
85 RedisString::LengthPrefix { data, .. } => data,
86 RedisString::StrInt(v) => {
87 let strv = format!("{}", v.value());
88 strv.into_bytes()
89 }
90 RedisString::LZF(LZFString { buf, .. }) => buf,
91 }
92 }
93
94 fn length_prefix(src: &[u8]) -> Result<RedisString> {
95 let length = Length::from_buf(src)?;
96 let mut data: Vec<u8> = Vec::with_capacity(length.length());
97 data.extend_from_slice(&src[length.shift()..(length.shift() + length.length())]);
98 Ok(RedisString::LengthPrefix {
99 len: length,
100 data: data,
101 })
102 }
103
104 fn str_int(src: &[u8]) -> Result<RedisString> {
105 let sint = StrInt::from_buf(src)?;
106 Ok(RedisString::StrInt(sint))
107 }
108
109 fn lzf(src: &[u8]) -> Result<RedisString> {
110 let lzf = LZFString::from_buf(src)?;
111 Ok(RedisString::LZF(lzf))
112 }
113}
114
115
116#[derive(Debug, Clone)]
117pub struct LZFString {
118 compressed_len: Length,
119 original_len: Length,
120 buf: Vec<u8>,
121}
122
123impl FromBuf for LZFString {
124 fn from_buf(src: &[u8]) -> Result<LZFString> {
125 let ltype = src[0] & 0b11;
126 faild!(ltype != REDIS_RDB_ENC_LZF, "LZF flag not found");
127 let compressed_len = Length::from_buf(&src[1..])?;
128 let original_len = Length::from_buf(&src[(1 + compressed_len.shift())..])?;
129 let shifted = 1 + compressed_len.shift() + original_len.shift();
130 more!(src.len() < shifted + compressed_len.length());
131 let src = &src[shifted..(shifted + compressed_len.length())];
132 let buf = lzf::decompress(src, original_len.length())?;
133 Ok(LZFString {
134 compressed_len: compressed_len,
135 original_len: original_len,
136 buf: buf,
137 })
138 }
139}
140
141impl Shift for LZFString {
142 #[inline]
143 fn shift(&self) -> usize {
144 1 + self.compressed_len.shift() + self.original_len.shift() + self.compressed_len.length()
145 }
146}
147
148
149#[derive(Debug, Clone, Copy)]
150pub enum StrInt {
151 Small(i8),
152 Normal(i16),
153 Large(i32),
154}
155
156impl Shift for StrInt {
157 #[inline]
158 fn shift(&self) -> usize {
159 match self {
160 &StrInt::Small(_) => 1 + 1,
161 &StrInt::Normal(_) => 1 + 2,
162 &StrInt::Large(_) => 1 + 4,
163 }
164 }
165}
166
167impl FromBuf for StrInt {
168 fn from_buf(src: &[u8]) -> Result<StrInt> {
169 let ltype = src[0] & 0x3f;
170 match ltype {
171 REDIS_RDB_ENC_INT8 => {
172 more!(src.len() < 1 + 1);
173 Ok(StrInt::Small(src[1] as i8))
174 }
175 REDIS_RDB_ENC_INT16 => {
176 more!(src.len() < 1 + 2);
177 Ok(StrInt::Normal(buf_to_i16(&src[1..])))
178 }
179 REDIS_RDB_ENC_INT32 => {
180 more!(src.len() < 1 + 4);
181 Ok(StrInt::Large(buf_to_i32(&src[1..])))
182 }
183 REDIS_RDB_ENC_LZF => Err(Error::Other),
184 _ => panic!("not exact str int type but got:{}", ltype),
185 }
186 }
187}
188
189impl StrInt {
190 pub fn value(&self) -> i32 {
191 match self {
192 &StrInt::Small(value) => value as i32,
193 &StrInt::Normal(value) => value as i32,
194 &StrInt::Large(value) => value as i32,
195 }
196 }
197}
198
199
200
201#[derive(Clone, Debug)]
203pub struct RedisList<I>
204 where I: Shift + FromBuf
205{
206 pub length: Length,
207 pub items: Vec<I>,
208}
209
210impl<I> FromBuf for RedisList<I>
211 where I: Shift + FromBuf
212{
213 fn from_buf(src: &[u8]) -> Result<Self> {
214 let length = Length::from_buf(src)?;
215 let mut pos = length.shift();
216
217 let mut items = Vec::new();
218 for _ in 0..length.length() {
219 let item: I = FromBuf::from_buf(&src[pos..])?;
220 pos += item.shift();
221 items.push(item);
222 }
223 Ok(RedisList {
224 length: length,
225 items: items,
226 })
227 }
228}
229
230impl<I> Shift for RedisList<I>
231 where I: Shift + FromBuf
232{
233 fn shift(&self) -> usize {
234 self.length.shift() + self.items.iter().map(|x| x.shift()).fold(0, |acc, x| acc + x)
235 }
236}
237
238#[derive(Clone, Debug)]
240pub struct LinkedListItem(pub RedisString);
241
242impl Shift for LinkedListItem {
243 fn shift(&self) -> usize {
244 self.0.shift()
245 }
246}
247
248impl FromBuf for LinkedListItem {
249 fn from_buf(src: &[u8]) -> Result<Self> {
250 let rstr = RedisString::from_buf(src)?;
251 Ok(LinkedListItem(rstr))
252 }
253}
254
255#[derive(Clone, Debug)]
257pub struct ZSetItem {
258 pub member: RedisString,
259 pub score: RedisString,
260}
261
262impl Shift for ZSetItem {
263 fn shift(&self) -> usize {
264 self.member.shift() + self.score.shift()
265 }
266}
267
268impl FromBuf for ZSetItem {
269 fn from_buf(src: &[u8]) -> Result<ZSetItem> {
270 let member = RedisString::from_buf(src)?;
271 let score = RedisString::from_buf(&src[member.shift()..])?;
272 Ok(ZSetItem {
273 member: member,
274 score: score,
275 })
276 }
277}
278
279
280#[derive(Clone, Debug)]
282pub struct HashItem {
283 pub key: RedisString,
284 pub value: RedisString,
285}
286
287impl Shift for HashItem {
288 fn shift(&self) -> usize {
289 self.key.shift() + self.value.shift()
290 }
291}
292
293impl FromBuf for HashItem {
294 fn from_buf(src: &[u8]) -> Result<Self> {
295 let key = RedisString::from_buf(src)?;
296 let value = RedisString::from_buf(&src[key.shift()..])?;
297 Ok(HashItem {
298 key: key,
299 value: value,
300 })
301 }
302}
303
304#[derive(Copy, Clone, Debug)]
305pub struct ZipListTail(u32);
306
307impl Shift for ZipListTail {
308 fn shift(&self) -> usize {
309 4
310 }
311}
312
313impl FromBuf for ZipListTail {
314 fn from_buf(src: &[u8]) -> Result<Self> {
315 more!(src.len() < 4);
316 let val = buf_to_u32(src);
317 Ok(ZipListTail(val))
318 }
319}
320
321
322#[derive(Copy, Clone, Debug)]
323pub struct ZipListLen(u16);
324
325impl Shift for ZipListLen {
326 fn shift(&self) -> usize {
327 2
328 }
329}
330
331impl FromBuf for ZipListLen {
332 fn from_buf(src: &[u8]) -> Result<Self> {
333 more!(src.len() < 2);
334 let val = buf_to_u16(src);
335 Ok(ZipListLen(val))
336 }
337}
338
339
340#[derive(Clone, Debug)]
341pub enum ZLELen {
342 Small(u8),
343 Large(u32),
344}
345
346impl Shift for ZLELen {
347 fn shift(&self) -> usize {
348 match self {
349 &ZLELen::Small(_) => 1,
350 &ZLELen::Large(_) => 5,
351 }
352 }
353}
354
355impl FromBuf for ZLELen {
356 fn from_buf(src: &[u8]) -> Result<Self> {
357 more!(src.len() < 1);
358 let flag = src[0];
359 if flag <= REDIS_RDB_FLAG_ZIPLIST_ENTRY_LEN_MAX {
360 return Ok(ZLELen::Small(flag));
361 }
362 more!(src.len() < 1 + 4);
363 let value = buf_to_u32(&src[1..]);
364 Ok(ZLELen::Large(value))
365 }
366}
367
368#[derive(Clone, Debug)]
369pub enum ZLESpData {
370 SmallStr(Vec<u8>),
371 NormalStr(Vec<u8>),
372 LargeStr(Vec<u8>),
373 ExSmallInt(u8),
374 SmallInt(i8),
375 NormalInt(i16),
376 LargeTrimInt(i32),
377 LargeInt(i32),
378 ExLargeInt(i64),
379}
380
381impl ZLESpData {
382 pub fn into_data(self) -> Vec<u8> {
383 match self {
384 ZLESpData::SmallStr(v) => v,
385 ZLESpData::NormalStr(v) => v,
386 ZLESpData::LargeStr(v) => v,
387 ZLESpData::ExSmallInt(v) => format!("{}", v).into_bytes(),
388 ZLESpData::SmallInt(v) => format!("{}", v).into_bytes(),
389 ZLESpData::NormalInt(v) => format!("{}", v).into_bytes(),
390 ZLESpData::LargeTrimInt(v) => format!("{}", v).into_bytes(),
391 ZLESpData::LargeInt(v) => format!("{}", v).into_bytes(),
392 ZLESpData::ExLargeInt(v) => format!("{}", v).into_bytes(),
393 }
394 }
395}
396
397impl Shift for ZLESpData {
398 fn shift(&self) -> usize {
399 match self {
400 &ZLESpData::SmallStr(ref v) => 1 + v.len(),
401 &ZLESpData::NormalStr(ref v) => 2 + v.len(),
402 &ZLESpData::LargeStr(ref v) => 1 + 4 + v.len(),
403 &ZLESpData::ExSmallInt(_) => 1,
404 &ZLESpData::SmallInt(_) => 1 + 1,
405 &ZLESpData::NormalInt(_) => 1 + 2,
406 &ZLESpData::LargeTrimInt(_) => 1 + 3,
407 &ZLESpData::LargeInt(_) => 1 + 4,
408 &ZLESpData::ExLargeInt(_) => 1 + 8,
409 }
410 }
411}
412
413impl ZLESpData {
414 fn to_special_int(src: &[u8]) -> Result<ZLESpData> {
415 let flag = src[0] & 0x0f;
416 match flag {
417 REDIS_RDB_FLAG_ZIPLIST_ENTRY_LARGE_TRIM_INT => {
418 more!(src.len() < 1 + 3);
419 Ok(ZLESpData::LargeTrimInt(buf_to_i32_trim(&src[1..])))
420 }
421 REDIS_RDB_FLAG_ZIPLIST_ENTRY_SMALL_INT => {
422 more!(src.len() < 1 + 1);
423 Ok(ZLESpData::SmallInt(src[1] as i8))
424 }
425 val if 1 <= val && val <= 13 => Ok(ZLESpData::ExSmallInt(val - 1)),
426 _ => Err(Error::Other),
427 }
428 }
429
430 fn to_usual_int(src: &[u8]) -> Result<ZLESpData> {
431 let flag = (src[0] << 2) >> 6;
432 match flag {
433 REDIS_RDB_FLAG_ZIPLIST_ENTRY_NORMAL_INT => {
434 let req = 1 + 2;
435 more!(src.len() < req);
436 Ok(ZLESpData::NormalInt(buf_to_i16(&src[1..])))
437 }
438
439 REDIS_RDB_FLAG_ZIPLIST_ENTRY_LARGE_INT => {
440 more!(src.len() < 1 + 4);
441 Ok(ZLESpData::LargeInt(buf_to_i32(&src[1..])))
442 }
443 REDIS_RDB_FLAG_ZIPLIST_ENTRY_EXLARGE_INT => {
444 more!(src.len() < 1 + 8);
445 Ok(ZLESpData::ExLargeInt(buf_to_i64(&src[1..])))
446 }
447 _ => Err(Error::Other),
448 }
449 }
450
451 fn to_str(src: &[u8]) -> Result<ZLESpData> {
452 let flag = src[0] >> 6;
453 match flag {
454 REDIS_RDB_FLAG_ZIPLIST_ENTRY_SMALL_STR => {
455 let req = 1;
456 let len = (src[0] & 0x3f) as usize;
457 more!(src.len() < req + len);
458 Ok(ZLESpData::SmallStr((&src[req..req + len]).to_vec()))
459 }
460 REDIS_RDB_FLAG_ZIPLIST_ENTRY_NORMAL_STR => {
461 let req = 1 + 1;
462 more!(src.len() < req);
463 let len = (buf_to_u16(&src[1..]) & 0x3fff) as usize;
464 more!(src.len() < req + len);
465 Ok(ZLESpData::NormalStr(src[req..req + len].to_vec()))
466 }
467 REDIS_RDB_FLAG_ZIPLIST_ENTRY_LARGE_STR => {
468 let req = 1 + 4;
469 more!(src.len() < req);
470 let len = (buf_to_u64(&src[1..]) & 0x3fff_ffff) as usize;
471 more!(src.len() < req + len);
472 Ok(ZLESpData::LargeStr(src[req..req + len].to_vec()))
473 }
474 _ => Err(Error::Other),
475 }
476 }
477}
478
479impl FromBuf for ZLESpData {
480 fn from_buf(src: &[u8]) -> Result<ZLESpData> {
481 more!(src.len() == 0);
482 choice!(ZLESpData::to_str(src));
483 choice!(ZLESpData::to_usual_int(src));
484 choice!(ZLESpData::to_special_int(src));
485 Err(Error::Faild("not regular ZipListSpecialFlag"))
486 }
487}
488
489#[derive(Clone, Debug)]
490pub struct ZipListEntry {
491 pub prev_len: ZLELen,
492 pub sp: ZLESpData,
493}
494
495impl Shift for ZipListEntry {
496 fn shift(&self) -> usize {
497 self.prev_len.shift() + self.sp.shift()
498 }
499}
500
501impl FromBuf for ZipListEntry {
502 fn from_buf(src: &[u8]) -> Result<Self> {
503 let len = ZLELen::from_buf(src)?;
504 let sp = ZLESpData::from_buf(&src[len.shift()..])?;
505 Ok(ZipListEntry {
506 prev_len: len,
507 sp: sp,
508 })
509 }
510}
511
512#[derive(Clone, Debug)]
513pub struct ZipList {
514 zlbytes: u32,
515 zltails: u32,
516 zllen: u16,
517 pub entries: Vec<ZipListEntry>,
518 zlend: u8,
519}
520
521impl Shift for ZipList {
522 fn shift(&self) -> usize {
523 self.zlbytes.shift() + self.zltails.shift() + self.zllen.shift() + self.zlend.shift() +
524 self.entries.iter().map(|x| x.shift()).fold(0, |acc, x| acc + x)
525 }
526}
527
528
529impl FromBuf for ZipList {
530 fn from_buf(src: &[u8]) -> Result<Self> {
531 let zlbytes: u32 = FromBuf::from_buf(src)?;
532 let zltails: u32 = FromBuf::from_buf(&src[zlbytes.shift()..])?;
533 let zllen: u16 = FromBuf::from_buf(&src[zlbytes.shift() + zltails.shift()..])?;
534 more!(src.len() < (zlbytes as usize));
535 let mut entries = Vec::new();
536 let mut pos = zlbytes.shift() + zltails.shift() + zllen.shift();
537
538 for _ in 0..zllen as usize {
539 let entry = ZipListEntry::from_buf(&src[pos..])?;
540 pos += entry.shift();
541 entries.push(entry);
542 }
543 let zlend = src[pos];
544 assert_eq!(zlend, 0xff);
545 Ok(ZipList {
546 zlbytes: zlbytes,
547 zltails: zltails,
548 zllen: zllen,
549 entries: entries,
550 zlend: zlend,
551 })
552 }
553}
554
555
556
557pub trait To<T>
558 where T: Shift + FromBuf
559{
560 fn to(&mut self) -> Result<RedisList<T>>;
561}
562
563impl To<LinkedListItem> for ZipList {
564 fn to(&mut self) -> Result<RedisList<LinkedListItem>> {
565 unimplemented!()
566 }
567}
568
569
570#[derive(Debug, Clone)]
571pub enum IntSetEncoding {
572 Normal,
573 Large,
574 ExLarge,
575}
576
577impl Shift for IntSetEncoding {
578 fn shift(&self) -> usize {
579 4
580 }
581}
582
583impl FromBuf for IntSetEncoding {
584 fn from_buf(src: &[u8]) -> Result<Self> {
585 more!(src.len() < 4);
586 let encoding = buf_to_u32(src);
587 match encoding {
588 2 => Ok(IntSetEncoding::Normal),
589 4 => Ok(IntSetEncoding::Large),
590 8 => Ok(IntSetEncoding::ExLarge),
591 _ => Err(Error::Faild("wrong IntSet encoding")),
592 }
593 }
594}
595
596impl IntSetEncoding {
597 pub fn encoding(&self) -> usize {
598 match self {
599 &IntSetEncoding::Normal => 2,
600 &IntSetEncoding::Large => 4,
601 &IntSetEncoding::ExLarge => 8,
602 }
603 }
604}
605
606#[derive(Debug, Clone)]
607pub struct IntSetCount(u32);
608
609impl Shift for IntSetCount {
610 fn shift(&self) -> usize {
611 4
612 }
613}
614
615impl FromBuf for IntSetCount {
616 fn from_buf(src: &[u8]) -> Result<Self> {
617 more!(src.len() < 4);
618 Ok(IntSetCount(buf_to_u32(src)))
619 }
620}
621
622#[derive(Debug, Clone)]
623pub struct IntSet {
624 pub encoding: IntSetEncoding,
625 pub count: IntSetCount,
626 pub ints: Vec<i64>,
627}
628
629impl Shift for IntSet {
630 fn shift(&self) -> usize {
631 self.encoding.shift() + self.count.shift() +
632 self.encoding.encoding() * (self.count.0 as usize)
633 }
634}
635
636impl FromBuf for IntSet {
637 fn from_buf(src: &[u8]) -> Result<Self> {
638 let encoding = IntSetEncoding::from_buf(&src[0..])?;
639 let count = IntSetCount::from_buf(&src[encoding.shift()..])?;
640 let mut ints = Vec::new();
641 let e = encoding.encoding();
642 let mut pos = encoding.shift() + count.shift();
643
644 for _ in 0..count.0 as usize {
645 more!(src.len() < pos + e);
646 let val = if e == 4 {
647 let uv = buf_to_u32(&src[pos..]);
648 (uv as i32) as i64
649 } else if e == 2 {
650 let uv = buf_to_u16(&src[pos..]);
651 (uv as i16) as i64
652 } else if e == 8 {
653 let uv = buf_to_u64(&src[pos..]);
654 uv as i64
655 } else {
656 panic!("not valid encoding")
657 };
658 ints.push(val);
659 pos += e;
660 }
661 Ok(IntSet {
662 encoding: encoding,
663 count: count,
664 ints: ints,
665 })
666 }
667}