libnewbee/codec/
mod.rs

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    /// judge by prefix two bits.
15    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// Base series container of redis list type
202#[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// for List
239#[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// for zset list
256#[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// for Hash
281#[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}