#![allow(dead_code)]
use super::{
ParseResult,
Encoding,
PacketVal,
Encoder
};
use super::opcode::{
OpCode,
opcode_parse
};
use super::nom::{
be_u8,
be_u16,
be_u32,
be_u64
};
#[derive(Clone,Debug,PartialEq,Eq)]
pub struct ReqHeader {
code: OpCode,
extralen: u8,
vbucket_id: u16,
keylen: u16,
bodylen: u32,
opaque: u32,
cas: u64
}
impl ReqHeader {
#[inline]
pub fn parse(buffer: &[u8]) -> ParseResult<Self> {
ParseResult::from(parse_req_header(buffer))
}
#[inline(always)]
pub fn get_opaque(&self) -> u32 {
self.opaque
}
#[inline(always)]
pub fn get_cas(&self) -> u64 {
self.cas
}
#[inline(always)]
pub fn get_opcode(&self) -> OpCode {
self.code
}
#[inline(always)]
pub fn get_vbucket_id(&self) -> u16 {
self.vbucket_id
}
}
impl PacketVal for ReqHeader {
#[inline(always)]
fn get_keylen(&self) -> usize {
self.keylen as usize
}
#[inline(always)]
fn get_bodylen(&self) -> usize {
self.bodylen as usize
}
#[inline(always)]
fn get_extralen(&self) -> usize {
self.extralen as usize
}
}
impl Encoding for ReqHeader {
#[inline(always)]
fn encode(&self, buffer: &mut Encoder) {
let magic = 0x80u8;
let datatype = 0x00u8;
magic.encode(buffer);
self.code.encode(buffer);
self.keylen.encode(buffer);
self.extralen.encode(buffer);
datatype.encode(buffer);
self.vbucket_id.encode(buffer);
( (
self.get_bodylen() +
self.get_keylen() +
self.get_extralen()
) as u32).encode(buffer);
self.opaque.encode(buffer);
self.cas.encode(buffer);
}
}
named!(pub parse_req_header<ReqHeader>, do_parse!(
tag!(b"\x80") >>
o: opcode_parse >>
kl: be_u16 >>
el: be_u8 >>
tag!(b"\x00") >>
vb_id: be_u16 >>
bl: be_u32 >>
op: be_u32 >>
cas: be_u64 >>
(
ReqHeader{
code: o,
extralen: el,
vbucket_id: vb_id,
keylen: kl,
bodylen: bl - (kl as u32 + el as u32),
opaque: op,
cas: cas
}
)));
#[inline(always)]
fn get_len(x: &Option<&[u8]>) -> usize {
match x {
&Option::Some(ref b) => b.len(),
_ => 0
}
}
#[derive(Clone,Debug)]
pub struct Request<'a> {
header: ReqHeader,
extra: Option<&'a [u8]>,
key: Option<&'a [u8]>,
body: Option<&'a [u8]>
}
impl<'a> Request<'a> {
pub fn parse(x: &'a [u8]) -> ParseResult<Self> {
#[inline(always)]
fn to_opt<'b>(z: &'b [u8]) -> Option<&'b [u8]> {
if z.len() == 0 {
None
} else {
Some(z)
}
}
named!(parse_request<Request>, do_parse!(
h: parse_req_header >>
e: take!(h.get_extralen()) >>
k: take!(h.get_keylen()) >>
b: take!(h.get_bodylen()) >>
(Request{
header: h,
extra: to_opt(e),
key: to_opt(k),
body: to_opt(b)
})
));
ParseResult::from(parse_request(x))
}
#[inline]
pub fn new( opcode: OpCode, vbucket: u16, opaque: u32,cas: u64,extra: Option<&'a [u8]>,key: Option<&'a [u8]>,body: Option<&'a [u8]>) -> Request<'a> {
let e = get_len(&extra);
let k = get_len(&key);
let b = get_len(&body);
let bl = b + k + e;
Request {
header:ReqHeader {
code: opcode,
vbucket_id: vbucket,
extralen: e as u8,
keylen: k as u16,
bodylen: bl as u32,
opaque: opaque,
cas: cas
},
extra: extra,
key: key,
body: body
}
}
#[inline]
pub fn rebuild(&mut self,opcode: OpCode, vbucket: u16, opaque: u32,cas: u64,extra: Option<&'a [u8]>,key: Option<&'a [u8]>,body: Option<&'a [u8]>){
use std::mem::replace;
let e = get_len(&extra);
let k = get_len(&key);
let b = get_len(&body);
let bl = b + k + e;
self.header.code = opcode;
self.header.vbucket_id = vbucket;
self.header.extralen = e as u8;
self.header.keylen = k as u16;
self.header.bodylen = bl as u32;
self.header.opaque = opaque;
self.header.cas = cas;
let _ = replace(&mut self.extra, extra);
let _ = replace(&mut self.key, key);
let _ = replace(&mut self.body, body);
}
#[inline]
pub fn encode_self(&self) -> Encoder {
let mut e = Encoder::new(self);
self.encode(&mut e);
e
}
#[inline]
pub fn encode_into_buffer(&self, x: Vec<u8>) -> Encoder {
let mut e = Encoder::from_vec(self, x);
self.encode(&mut e);
e
}
#[inline(always)]
pub fn get_opcode(&self) -> OpCode {
self.header.get_opcode()
}
#[inline(always)]
pub fn get_opaque(&self) -> u32 {
self.header.opaque
}
#[inline(always)]
pub fn get_cas(&self) -> u64 {
self.header.cas
}
#[inline(always)]
pub fn get_vbucket_id(&self) -> u16 {
self.header.vbucket_id
}
#[inline(always)]
pub fn has_extra(&self) -> bool {
self.extra.is_some()
}
#[inline(always)]
pub fn has_key(&self) -> bool {
self.key.is_some()
}
#[inline(always)]
pub fn get_extra(&'a self) -> Option<&'a [u8]> {
self.extra
}
#[inline(always)]
pub fn get_key(&'a self) -> Option<&'a [u8]> {
self.key
}
#[inline(always)]
pub fn get_key_str(&'a self) -> Option<&'a str> {
use std::str::from_utf8_unchecked;
unsafe{ self.key.map(|x| from_utf8_unchecked(x)) }
}
#[inline(always)]
pub fn has_body(&self) -> bool {
self.body.is_some()
}
#[inline(always)]
pub fn get_body(&'a self) -> Option<&'a [u8]> {
self.body
}
#[inline]
pub fn to_owned(self) -> OwnedRequest {
fn to_vec(x: Option<&[u8]>) -> Vec<u8> {
match x {
Option::Some(ref b) => {
let mut v = Vec::with_capacity(b.len());
v.extend_from_slice(b);
v
},
_ => Vec::with_capacity(0)
}
}
OwnedRequest {
body: to_vec(self.get_body()),
key: to_vec(self.get_key()),
extra: to_vec(self.get_extra()),
header: self.header,
}
}
}
impl<'a> PacketVal for Request<'a> {
#[inline(always)]
fn get_keylen(&self) -> usize {
self.header.keylen as usize
}
#[inline(always)]
fn get_bodylen(&self) -> usize {
self.header.bodylen as usize
}
#[inline(always)]
fn get_extralen(&self) -> usize {
self.header.extralen as usize
}
}
impl<'a> Encoding for Request<'a> {
fn encode(&self, buffer: &mut Encoder) {
self.header.encode(buffer);
self.extra.encode(buffer);
self.key.encode(buffer);
self.body.encode(buffer);
}
}
#[derive(Clone)]
pub struct OwnedRequest {
header: ReqHeader,
pub key: Vec<u8>,
pub extra: Vec<u8>,
pub body: Vec<u8>
}
impl OwnedRequest {
pub fn parse(x: &[u8]) -> ParseResult<Self> {
named!(parse_owned_request<OwnedRequest>, do_parse!(
h: parse_req_header >>
e: take!(h.get_extralen()) >>
k: take!(h.get_keylen()) >>
b: take!(h.get_bodylen()) >>
(OwnedRequest{
header: h,
extra: if e.len() == 0 { Vec::with_capacity(0) } else {e.to_vec()},
key: if k.len() == 0 { Vec::with_capacity(0) } else { k.to_vec() },
body: if b.len() == 0 { Vec::with_capacity(0) } else { b.to_vec() }
})
));
ParseResult::from(parse_owned_request(x))
}
#[inline]
pub fn new(opcode: OpCode, vbucket: u16, opaque: u32, cas: u64, extra: Vec<u8>, key: Vec<u8>, body: Vec<u8>) -> Self {
let e = extra.len();
let k = key.len();
let b = body.len();
let bl = b + k + e;
OwnedRequest {
header:ReqHeader {
code: opcode,
vbucket_id: vbucket,
extralen: e as u8,
keylen: k as u16,
bodylen: bl as u32,
opaque: opaque,
cas: cas
},
extra: extra,
key: key,
body: body
}
}
#[inline]
pub fn rebuild(&mut self, opcode: OpCode, vbucket: u16, opaque: u32, cas: u64, extra: Vec<u8>, key: Vec<u8>, body: Vec<u8>){
use std::mem::replace;
let e = extra.len();
let k = key.len();
let b = body.len();
let bl = b + k + e;
self.header.code = opcode;
self.header.vbucket_id = vbucket;
self.header.extralen = e as u8;
self.header.keylen = k as u16;
self.header.bodylen = bl as u32;
self.header.opaque = opaque;
self.header.cas = cas;
let _ = replace(&mut self.extra, extra);
let _ = replace(&mut self.key, key);
let _ = replace(&mut self.body, body);
}
#[inline]
pub fn encode_self(&self) -> Encoder {
let mut e = Encoder::new(self);
self.encode(&mut e);
e
}
#[inline]
pub fn encode_into_buffer(&self, x: Vec<u8>) -> Encoder {
let mut e = Encoder::from_vec(self, x);
self.encode(&mut e);
e
}
#[inline(always)]
pub fn get_opcode(&self) -> OpCode {
self.header.code
}
#[inline(always)]
pub fn get_opaque(&self) -> u32 {
self.header.opaque
}
#[inline(always)]
pub fn get_cas(&self) -> u64 {
self.header.cas
}
#[inline(always)]
pub fn get_vbucket_id(&self) -> u16 {
self.header.vbucket_id
}
#[inline(always)]
pub fn has_extra(&self) -> bool {
self.extra.len() != 0
}
#[inline(always)]
pub fn get_extra<'a>(&'a self) -> Option<&'a [u8]> {
if self.has_extra() {
Some(self.extra.as_slice())
} else {
None
}
}
#[inline(always)]
pub fn has_key(&self) -> bool {
self.key.len() != 0
}
#[inline(always)]
pub fn get_key<'a>(&'a self) -> Option<&'a [u8]> {
if self.has_key() {
Some(self.key.as_slice())
} else {
None
}
}
#[inline(always)]
pub fn get_key_str<'a>(&'a self) -> Option<&'a str> {
use std::str::from_utf8_unchecked;
unsafe{ self.get_key().map(|x| from_utf8_unchecked(x)) }
}
#[inline(always)]
pub fn has_body(&self) -> bool {
self.body.len() != 0
}
#[inline(always)]
pub fn get_body<'a>(&'a self) -> Option<&'a [u8]> {
if self.has_body() {
Some(self.body.as_slice())
} else {
None
}
}
}
impl PacketVal for OwnedRequest {
#[inline(always)]
fn get_keylen(&self) -> usize {
self.header.keylen as usize
}
#[inline(always)]
fn get_bodylen(&self) -> usize {
self.header.bodylen as usize
}
#[inline(always)]
fn get_extralen(&self) -> usize {
self.header.extralen as usize
}
}
impl Encoding for OwnedRequest {
fn encode(&self, buffer: &mut Encoder) {
self.header.encode(buffer);
self.extra.encode(buffer);
self.key.encode(buffer);
self.body.encode(buffer);
}
}