mbpr/
request.rs

1//everything inside a nom macro is dead code
2#![allow(dead_code)]
3
4use super::{
5  ParseResult,
6  Encoding,
7  PacketVal,
8  Encoder
9};
10use super::opcode::{
11  OpCode,
12  opcode_parse
13};
14use super::nom::{
15  be_u8,
16  be_u16,
17  be_u32,
18  be_u64
19};
20
21
22/// Memcached Request Packet Header
23///
24/// This is the first 24 bytes of the packet
25#[derive(Clone,Debug,PartialEq,Eq)]
26pub struct ReqHeader {
27  code: OpCode,
28  extralen: u8,
29  vbucket_id: u16,
30  keylen: u16,
31  bodylen: u32,
32  opaque: u32,
33  cas: u64
34}
35impl ReqHeader {
36  /// Parse a request header
37  #[inline]
38  pub fn parse(buffer: &[u8]) -> ParseResult<Self> {
39    ParseResult::from(parse_req_header(buffer))
40  }
41  #[inline(always)]
42  pub fn get_opaque(&self) -> u32 {
43      self.opaque
44  }
45  #[inline(always)]
46  pub fn get_cas(&self) -> u64 {
47      self.cas
48  }
49  #[inline(always)]
50  pub fn get_opcode(&self) -> OpCode {
51    self.code
52  }
53  #[inline(always)]
54  pub fn get_vbucket_id(&self) -> u16 {
55    self.vbucket_id
56  }
57}
58impl PacketVal for ReqHeader {
59  #[inline(always)]
60  fn get_keylen(&self) -> usize {
61      self.keylen as usize
62  }
63  #[inline(always)]
64  fn get_bodylen(&self) -> usize {
65      self.bodylen as usize
66  }
67  #[inline(always)]
68  fn get_extralen(&self) -> usize {
69      self.extralen as usize
70  }
71}
72impl Encoding for ReqHeader {
73  /// Fast encoding method
74  #[inline(always)]
75  fn encode(&self, buffer: &mut Encoder) {
76    let magic = 0x80u8;
77    let datatype = 0x00u8;
78    magic.encode(buffer);
79    self.code.encode(buffer);
80    self.keylen.encode(buffer);
81    self.extralen.encode(buffer);
82    datatype.encode(buffer);
83    self.vbucket_id.encode(buffer);
84    ( (
85        self.get_bodylen() +
86        self.get_keylen()  +
87        self.get_extralen()
88      ) as u32).encode(buffer);
89    self.opaque.encode(buffer);
90    self.cas.encode(buffer);
91  }
92}
93
94///Parse only the header
95named!(pub parse_req_header<ReqHeader>, do_parse!(
96  tag!(b"\x80")     >>
97  o: opcode_parse   >>
98  kl: be_u16        >>
99  el: be_u8         >>
100  tag!(b"\x00")     >>
101  vb_id: be_u16     >>
102  bl: be_u32        >>
103  op: be_u32        >>
104  cas: be_u64       >>
105  (
106    ReqHeader{
107    code: o,
108    extralen: el,
109    vbucket_id: vb_id,
110    keylen: kl,
111    bodylen: bl - (kl as u32 + el as u32),
112    opaque: op,
113    cas: cas
114  }
115)));
116
117
118#[inline(always)]
119fn get_len(x: &Option<&[u8]>) -> usize {
120  match x {
121    &Option::Some(ref b) => b.len(),
122    _ => 0
123  }
124}
125
126/*
127 *Request Packet
128 */
129
130/// Memcached Request Packet
131///
132/// The whole thing
133#[derive(Clone,Debug)]
134pub struct Request<'a> {
135  header: ReqHeader,
136  extra: Option<&'a [u8]>,
137  key: Option<&'a [u8]>,
138  body: Option<&'a [u8]>
139}
140impl<'a> Request<'a> {
141  
142  /// Parse and borrow a packet from a buffer
143  pub fn parse(x: &'a [u8]) -> ParseResult<Self> {
144    
145    #[inline(always)]
146    fn to_opt<'b>(z: &'b [u8]) -> Option<&'b [u8]> {
147      if z.len() == 0 {
148        None
149      } else {
150        Some(z)
151      }
152    }
153    named!(parse_request<Request>, do_parse!(
154      h: parse_req_header         >>
155      e: take!(h.get_extralen())  >>
156      k: take!(h.get_keylen())    >>
157      b: take!(h.get_bodylen())   >>
158      (Request{
159        header: h,
160        extra: to_opt(e),
161        key: to_opt(k),
162        body: to_opt(b)
163      })
164    ));
165    ParseResult::from(parse_request(x))
166  }
167  /// This interface does ABSOLUTELY NO verfication of the packet
168  /// it is expected if you are calling this method you understand
169  /// the memcached protocol and you are going to use this to generate
170  /// a valid packet.
171  ///
172  /// The goal of this interface is to be fast. Encoding a packet
173  /// with this interface + Encode trait involves very few branches
174  ///
175  /// Memcached only allows Keys that are ASCII and non-white space
176  /// this interface does not do ANY assertions of this. Please be
177  /// aware.
178  #[inline]
179  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> {
180    let e = get_len(&extra);
181    let k = get_len(&key);
182    let b = get_len(&body);
183    let bl = b + k + e;
184    Request {
185      header:ReqHeader {
186        code: opcode,
187        vbucket_id: vbucket,
188        extralen: e as u8,
189        keylen: k as u16,
190        bodylen: bl as u32,
191        opaque: opaque,
192        cas: cas
193      },
194      extra: extra,
195      key: key,
196      body: body
197    }
198  }
199  /// Over write an existing request
200  ///
201  /// This is provided to allow for easier interfacing with SLAB's. The
202  /// semantics of this method are identical to the above. The primary
203  /// difference is this doesn't push ~100 bytes to the stack.
204  ///
205  /// This interface does ABSOLUTELY NO verfication of the packet
206  /// it is expected if you are calling this method you understand
207  /// the memcached protocol and you are going to use this to generate
208  /// a valid packet.
209  ///
210  /// The goal of this interface is to be fast. Encoding a packet
211  /// with this interface + Encode trait involves very few branches
212  ///
213  /// Memcached only allows Keys that are ASCII and non-white space
214  /// this interface does not do ANY assertions of this. Please be
215  /// aware.
216  #[inline]
217  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]>){
218    use std::mem::replace;
219    
220    let e = get_len(&extra);
221    let k = get_len(&key);
222    let b = get_len(&body);
223    let bl = b + k + e;
224    self.header.code = opcode;
225    self.header.vbucket_id = vbucket;
226    self.header.extralen = e as u8;
227    self.header.keylen = k as u16;
228    self.header.bodylen = bl as u32;
229    self.header.opaque = opaque;
230    self.header.cas = cas;
231    let _ = replace(&mut self.extra, extra);
232    let _ = replace(&mut self.key, key);
233    let _ = replace(&mut self.body, body);
234  } 
235  /// Allocates a new buffer and encodes this packets contents into it.
236  /// this method works out to a handful of `memcp` primatives and is
237  /// fairly quick as their is no bounds checking (buffer length is
238  /// asserted on construction).
239  #[inline]
240  pub fn encode_self(&self) -> Encoder {
241    let mut e = Encoder::new(self);
242    self.encode(&mut e);
243    e
244  }
245  /// If you are using a slab to avoid making too many allocations
246  /// this method will check check the `Vec<u8>` it is passed
247  /// only reserving additional capacity if necessary. If the `Vec<u8>`
248  /// has enough capacity no action is taken.
249  #[inline]
250  pub fn encode_into_buffer(&self, x: Vec<u8>) -> Encoder {
251    let mut e = Encoder::from_vec(self, x);
252    self.encode(&mut e);
253    e
254  }
255  #[inline(always)]
256  pub fn get_opcode(&self) -> OpCode {
257    self.header.get_opcode()
258  }
259  #[inline(always)]
260  pub fn get_opaque(&self) -> u32 {
261    self.header.opaque
262  }
263  #[inline(always)]
264  pub fn get_cas(&self) -> u64 {
265    self.header.cas
266  }
267  #[inline(always)]
268  pub fn get_vbucket_id(&self) -> u16 {
269    self.header.vbucket_id
270  }
271  #[inline(always)]
272  pub fn has_extra(&self) -> bool {
273    self.extra.is_some()
274  }
275  #[inline(always)]
276  pub fn has_key(&self) -> bool {
277    self.key.is_some()
278  }
279  #[inline(always)]
280  pub fn get_extra(&'a self) -> Option<&'a [u8]> {
281    self.extra
282  }
283  #[inline(always)]
284  pub fn get_key(&'a self) -> Option<&'a [u8]> {
285    self.key
286  }
287  /// The standard states the key should be an ASCII compatible string
288  /// so this method preforms that conversion without checking for
289  /// correctness.
290  ///
291  /// This isnt a _problem_ as the key will be hash/stored as a byte
292  /// buffer anyways.
293  ///
294  /// This really only opens the door to non standard things.
295  #[inline(always)]
296  pub fn get_key_str(&'a self) -> Option<&'a str> {
297    use std::str::from_utf8_unchecked;
298    unsafe{ self.key.map(|x| from_utf8_unchecked(x)) }
299  }
300  #[inline(always)]
301  pub fn has_body(&self) -> bool {
302    self.body.is_some()
303  }
304  #[inline(always)]
305  pub fn get_body(&'a self) -> Option<&'a [u8]> {
306    self.body
307  }
308  /// Consume this item and take ownership
309  ///
310  /// If a field is `Option::None` the resulting
311  /// vector will be a `Vec::with_capacity(0)` which
312  /// does not allocate. So this method can be
313  /// cheap depending on the messages contents.
314  #[inline]
315  pub fn to_owned(self) -> OwnedRequest {
316    fn to_vec(x: Option<&[u8]>) -> Vec<u8> {
317      match x {
318        Option::Some(ref b) => {
319          let mut v = Vec::with_capacity(b.len());
320          v.extend_from_slice(b);
321          v
322        },
323        _ => Vec::with_capacity(0)
324      }
325    }
326    OwnedRequest {
327      body: to_vec(self.get_body()),
328      key: to_vec(self.get_key()),
329      extra: to_vec(self.get_extra()),
330      header: self.header,
331    }
332  }
333}
334impl<'a> PacketVal for Request<'a> {
335  /// Get size of Packet's Key Field
336  #[inline(always)]
337  fn get_keylen(&self) -> usize {
338    self.header.keylen as usize
339  }
340  /// Get size of Packet's Body Field (Raw Data)
341  #[inline(always)]
342  fn get_bodylen(&self) -> usize {
343    self.header.bodylen as usize
344  }
345  /// Get size of Packet's Extra Field (Flags, Arguments, Etc. command specific)
346  #[inline(always)]
347  fn get_extralen(&self) -> usize {
348    self.header.extralen as usize
349  }
350}
351impl<'a> Encoding for Request<'a> {
352  /// Encode a packet
353  fn encode(&self, buffer: &mut Encoder) {
354    self.header.encode(buffer);
355    self.extra.encode(buffer);
356    self.key.encode(buffer);
357    self.body.encode(buffer);
358  }
359}
360
361/// Clones Buffers
362///
363/// This behaves identical to Request other then the fact
364/// that the internal `body`/`key`/`extra` fields are owned
365/// vectors NOT borrowed slices. 
366///
367/// This makes life a lot easier when working with the borrow
368/// checker, and concurrent programming.
369#[derive(Clone)]
370pub struct OwnedRequest {
371  header: ReqHeader,
372  pub key: Vec<u8>,
373  pub extra: Vec<u8>,
374  pub body: Vec<u8>
375}
376impl OwnedRequest {
377  
378  /// Reads a full packet and COPIES it's buffers into its own.
379  /// Allocation is lazy. Fields that are not used are not allocated.
380  /// Fields are not allocated WHILE parsing, only when complete.
381  pub fn parse(x: &[u8]) -> ParseResult<Self> {
382    named!(parse_owned_request<OwnedRequest>, do_parse!(
383      h: parse_req_header         >>
384      e: take!(h.get_extralen())  >>
385      k: take!(h.get_keylen())    >>
386      b: take!(h.get_bodylen())   >>
387      (OwnedRequest{
388        header: h,
389        extra: if e.len() == 0 { Vec::with_capacity(0) } else {e.to_vec()},
390        key: if k.len() == 0 { Vec::with_capacity(0) } else { k.to_vec() },
391        body: if b.len() == 0 { Vec::with_capacity(0) } else { b.to_vec() }
392      })
393    ));
394    ParseResult::from(parse_owned_request(x))
395  }
396  /// This interface does ABSOLUTELY NO verfication of the packet
397  /// it is expected if you are calling this method you understand
398  /// the memcached protocol and you are going to use this to generate
399  /// a valid packet.
400  ///
401  /// The goal of this interface is to be fast. Encoding a packet
402  /// with this interface + Encode trait involves very few branches
403  ///
404  /// Memcached only allows Keys that are ASCII and non-white space
405  /// this interface does not do ANY assertions of this. Please be
406  /// aware.
407  #[inline]
408  pub fn new(opcode: OpCode, vbucket: u16, opaque: u32, cas: u64, extra: Vec<u8>, key: Vec<u8>, body: Vec<u8>) -> Self {
409    let e = extra.len();
410    let k = key.len();
411    let b = body.len();
412    let bl = b + k + e;
413    OwnedRequest {
414      header:ReqHeader {
415        code: opcode,
416        vbucket_id: vbucket,
417        extralen: e as u8,
418        keylen: k as u16,
419        bodylen: bl as u32,
420        opaque: opaque,
421        cas: cas
422      },
423      extra: extra,
424      key: key,
425      body: body
426    }
427  }
428  /// Over write an existing request
429  ///
430  /// This is provided to allow for easier interfacing with SLAB's. The
431  /// semantics of this method are identical to the above. The primary
432  /// difference is this doesn't push ~100 bytes to the stack.
433  ///
434  /// This interface does ABSOLUTELY NO verfication of the packet
435  /// it is expected if you are calling this method you understand
436  /// the memcached protocol and you are going to use this to generate
437  /// a valid packet.
438  ///
439  /// The goal of this interface is to be fast. Encoding a packet
440  /// with this interface + Encode trait involves very few branches
441  ///
442  /// Memcached only allows Keys that are ASCII and non-white space
443  /// this interface does not do ANY assertions of this. Please be
444  /// aware.
445  #[inline]
446  pub fn rebuild(&mut self, opcode: OpCode, vbucket: u16, opaque: u32, cas: u64, extra: Vec<u8>, key: Vec<u8>, body: Vec<u8>){
447    use std::mem::replace;
448    
449    let e = extra.len();
450    let k = key.len();
451    let b = body.len();
452    let bl = b + k + e;
453    self.header.code = opcode;
454    self.header.vbucket_id = vbucket;
455    self.header.extralen = e as u8;
456    self.header.keylen = k as u16;
457    self.header.bodylen = bl as u32;
458    self.header.opaque = opaque;
459    self.header.cas = cas;
460    let _ = replace(&mut self.extra, extra);
461    let _ = replace(&mut self.key, key);
462    let _ = replace(&mut self.body, body);
463  } 
464  /// Allocates a new buffer and encodes this packets contents into it.
465  /// this method works out to a handful of `memcp` primatives and is
466  /// fairly quick as their is no bounds checking (buffer length is
467  /// asserted on construction).
468  #[inline]
469  pub fn encode_self(&self) -> Encoder {
470    let mut e = Encoder::new(self);
471    self.encode(&mut e);
472    e
473  }
474  /// If you are using a slab to avoid making too many allocations
475  /// this method will check check the `Vec<u8>` it is passed
476  /// only reserving additional capacity if necessary. If the `Vec<u8>`
477  /// has enough capacity no action is taken.
478  #[inline]
479  pub fn encode_into_buffer(&self, x: Vec<u8>) -> Encoder {
480    let mut e = Encoder::from_vec(self, x);
481    self.encode(&mut e);
482    e
483  }
484  #[inline(always)]
485  pub fn get_opcode(&self) -> OpCode {
486    self.header.code
487  }
488  #[inline(always)]
489  pub fn get_opaque(&self) -> u32 {
490    self.header.opaque
491  }
492  #[inline(always)]
493  pub fn get_cas(&self) -> u64 {
494    self.header.cas
495  }
496  #[inline(always)]
497  pub fn get_vbucket_id(&self) -> u16 {
498    self.header.vbucket_id
499  }
500  #[inline(always)]
501  pub fn has_extra(&self) -> bool {
502    self.extra.len() != 0
503  }
504  #[inline(always)]
505  pub fn get_extra<'a>(&'a self) -> Option<&'a [u8]> {
506    if self.has_extra() {
507      Some(self.extra.as_slice())
508    } else {
509      None
510    }
511  }
512  #[inline(always)]
513  pub fn has_key(&self) -> bool {
514    self.key.len() != 0
515  }
516  #[inline(always)]
517  pub fn get_key<'a>(&'a self) -> Option<&'a [u8]> {
518    if self.has_key() {
519      Some(self.key.as_slice())
520    } else {
521      None
522    }
523  }
524  /// The standard states the key should be an ASCII compatible string
525  /// so this method preforms that conversion without checking for
526  /// correctness.
527  ///
528  /// This isnt a _problem_ as the key will be hash/stored as a byte
529  /// buffer anyways.
530  ///
531  /// This really only opens the door to non standard things.
532  #[inline(always)]
533  pub fn get_key_str<'a>(&'a self) -> Option<&'a str> {
534    use std::str::from_utf8_unchecked;
535    unsafe{ self.get_key().map(|x| from_utf8_unchecked(x)) }
536  }
537  #[inline(always)]
538  pub fn has_body(&self) -> bool {
539    self.body.len() != 0
540  }
541  #[inline(always)]
542  pub fn get_body<'a>(&'a self) -> Option<&'a [u8]> {
543    if self.has_body() {
544      Some(self.body.as_slice())
545    } else {
546      None
547    }
548  }
549}
550impl PacketVal for OwnedRequest {
551 /// Get size of Packet's Key Field
552 #[inline(always)]
553 fn get_keylen(&self) -> usize {
554    self.header.keylen as usize
555  }
556  /// Get size of Packet's Body Field (Raw Data)
557  #[inline(always)]
558  fn get_bodylen(&self) -> usize {
559    self.header.bodylen as usize
560  }
561  /// Get size of Packet's Extra Field (Flags, Arguments, Etc. command specific)
562  #[inline(always)]
563  fn get_extralen(&self) -> usize {
564    self.header.extralen as usize
565  }
566}
567impl Encoding for OwnedRequest {
568  /// Encode a packet
569  fn encode(&self, buffer: &mut Encoder) {
570    self.header.encode(buffer);
571    self.extra.encode(buffer);
572    self.key.encode(buffer);
573    self.body.encode(buffer);
574  }
575}
576
577