Class: Beefcake::Buffer

Inherits:
Object
  • Object
show all
Defined in:
lib/beefcake/buffer/base.rb,
lib/beefcake/buffer/decode.rb,
lib/beefcake/buffer/encode.rb

Defined Under Namespace

Classes: BufferOverflowError, OutOfRangeError, UnknownType

Constant Summary collapse

MinUint32 =
0
MaxUint32 =
(1 << 32)-1
MinInt32 =
-(1 << 31)
MaxInt32 =
(1 << 31)-1
MinUint64 =
0
MaxUint64 =
(1 << 64)-1
MinInt64 =
-(1 << 63)
MaxInt64 =
(1 << 63)-1
WIRES =
{
  :int32    => 0,
  :uint32   => 0,
  :sint32   => 0,
  :int64    => 0,
  :uint64   => 0,
  :sint64   => 0,
  :bool     => 0,
  :fixed64  => 1,
  :sfixed64 => 1,
  :double   => 1,
  :string   => 2,
  :bytes    => 2,
  :fixed32  => 5,
  :sfixed32 => 5,
  :float    => 5,
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(buf = "") ⇒ Buffer

Returns a new instance of Buffer.


75
76
77
# File 'lib/beefcake/buffer/base.rb', line 75

def initialize(buf="")
  self.buf = buf
end

Instance Attribute Details

#bufObject Also known as: to_s, to_str

Returns the value of attribute buf


52
53
54
# File 'lib/beefcake/buffer/base.rb', line 52

def buf
  @buf
end

Class Method Details

.encodable?(type) ⇒ Boolean

Returns:

  • (Boolean)

47
48
49
50
# File 'lib/beefcake/buffer/base.rb', line 47

def self.encodable?(type)
  return false if ! type.is_a?(Class)
  type.public_method_defined?(:encode)
end

.wire_for(type) ⇒ Object


33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/beefcake/buffer/base.rb', line 33

def self.wire_for(type)
  wire = WIRES[type]

  if wire
    wire
  elsif Class === type && encodable?(type)
    2
  elsif Module === type
    0
  else
    raise UnknownType, type
  end
end

Instance Method Details

#<<(bytes) ⇒ Object


89
90
91
92
# File 'lib/beefcake/buffer/base.rb', line 89

def <<(bytes)
  bytes = bytes.force_encoding('BINARY') if bytes.respond_to? :force_encoding
  buf << bytes
end

#append(type, val, fn) ⇒ Object


7
8
9
10
11
12
13
14
# File 'lib/beefcake/buffer/encode.rb', line 7

def append(type, val, fn)
  if fn != 0
    wire = Buffer.wire_for(type)
    append_info(fn, wire)
  end

  __send__("append_#{type}", val)
end

#append_bool(n) ⇒ Object


103
104
105
# File 'lib/beefcake/buffer/encode.rb', line 103

def append_bool(n)
  append_int64(n ? 1 : 0)
end

#append_double(n) ⇒ Object


99
100
101
# File 'lib/beefcake/buffer/encode.rb', line 99

def append_double(n)
  self << [n].pack("E")
end

#append_fixed32(n, tag = false) ⇒ Object


20
21
22
23
24
25
26
# File 'lib/beefcake/buffer/encode.rb', line 20

def append_fixed32(n, tag=false)
  if n < MinUint32 || n > MaxUint32
    raise OutOfRangeError, n
  end

  self << [n].pack("V")
end

#append_fixed64(n) ⇒ Object


28
29
30
31
32
33
34
# File 'lib/beefcake/buffer/encode.rb', line 28

def append_fixed64(n)
  if n < MinUint64 || n > MaxUint64
    raise OutOfRangeError, n
  end

  self << [n & 0xFFFFFFFF, n >> 32].pack("VV")
end

#append_float(n) ⇒ Object


95
96
97
# File 'lib/beefcake/buffer/encode.rb', line 95

def append_float(n)
  self << [n].pack("e")
end

#append_info(fn, wire) ⇒ Object


16
17
18
# File 'lib/beefcake/buffer/encode.rb', line 16

def append_info(fn, wire)
  append_uint32((fn << 3) | wire)
end

#append_int32(n) ⇒ Object


36
37
38
39
40
41
42
# File 'lib/beefcake/buffer/encode.rb', line 36

def append_int32(n)
  if n < MinInt32 || n > MaxInt32
    raise OutOfRangeError, n
  end

  append_int64(n)
end

#append_int64(n) ⇒ Object


52
53
54
55
56
57
58
59
60
61
62
# File 'lib/beefcake/buffer/encode.rb', line 52

def append_int64(n)
  if n < MinInt64 || n > MaxInt64
    raise OutOfRangeError, n
  end

  if n < 0
    n += (1 << 64)
  end

  append_uint64(n)
end

#append_sfixed32(n) ⇒ Object


68
69
70
# File 'lib/beefcake/buffer/encode.rb', line 68

def append_sfixed32(n)
  append_fixed32((n << 1) ^ (n >> 31))
end

#append_sfixed64(n) ⇒ Object


76
77
78
# File 'lib/beefcake/buffer/encode.rb', line 76

def append_sfixed64(n)
  append_fixed64((n << 1) ^ (n >> 63))
end

#append_sint32(n) ⇒ Object


64
65
66
# File 'lib/beefcake/buffer/encode.rb', line 64

def append_sint32(n)
  append_uint32((n << 1) ^ (n >> 31))
end

#append_sint64(n) ⇒ Object


72
73
74
# File 'lib/beefcake/buffer/encode.rb', line 72

def append_sint64(n)
  append_uint64((n << 1) ^ (n >> 63))
end

#append_string(s) ⇒ Object Also known as: append_bytes


107
108
109
110
111
112
# File 'lib/beefcake/buffer/encode.rb', line 107

def append_string(s)
  actual_string = thaw_string s
  encoded = actual_string.dup.force_encoding 'binary'
  append_uint64(encoded.length)
  self << encoded
end

#append_uint32(n) ⇒ Object


44
45
46
47
48
49
50
# File 'lib/beefcake/buffer/encode.rb', line 44

def append_uint32(n)
  if n < MinUint32 || n > MaxUint32
    raise OutOfRangeError, n
  end

  append_uint64(n)
end

#append_uint64(n) ⇒ Object


80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/beefcake/buffer/encode.rb', line 80

def append_uint64(n)
  if n < MinUint64 || n > MaxUint64
    raise OutOfRangeError, n
  end

  while true
    bits = n & 0x7F
    n >>= 7
    if n == 0
      return self << bits
    end
    self << (bits | 0x80)
  end
end

#lengthObject


84
85
86
87
# File 'lib/beefcake/buffer/base.rb', line 84

def length
  remain = buf.slice(@cursor..-1)
  remain.bytesize
end

#read(n) ⇒ Object


94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/beefcake/buffer/base.rb', line 94

def read(n)
  case n
  when Class
    n.decode(read_string)
  when Symbol
    __send__("read_#{n}")
  when Module
    read_uint64
  else
    read_slice = buf.byteslice(@cursor, n)
    @cursor += n
    return read_slice
  end
end

#read_boolObject


83
84
85
# File 'lib/beefcake/buffer/decode.rb', line 83

def read_bool
  read_int32 != 0
end

#read_bytesObject


15
16
17
# File 'lib/beefcake/buffer/decode.rb', line 15

def read_bytes
  read(read_uint64)
end

#read_doubleObject


78
79
80
81
# File 'lib/beefcake/buffer/decode.rb', line 78

def read_double
  bytes = read(8)
  bytes.unpack("E").first
end

#read_fixed32Object


23
24
25
26
# File 'lib/beefcake/buffer/decode.rb', line 23

def read_fixed32
  bytes = read(4)
  bytes.unpack("V").first
end

#read_fixed64Object


28
29
30
31
32
# File 'lib/beefcake/buffer/decode.rb', line 28

def read_fixed64
  bytes = read(8)
  x, y = bytes.unpack("VV")
  x + (y << 32)
end

#read_floatObject


73
74
75
76
# File 'lib/beefcake/buffer/decode.rb', line 73

def read_float
  bytes = read(4)
  bytes.unpack("e").first
end

#read_infoObject


7
8
9
10
11
12
13
# File 'lib/beefcake/buffer/decode.rb', line 7

def read_info
  n    = read_uint64
  fn   = n >> 3
  wire = n & 0x7

  [fn, wire]
end

#read_int64Object Also known as: read_int32


34
35
36
37
38
39
40
# File 'lib/beefcake/buffer/decode.rb', line 34

def read_int64
  n = read_uint64
  if n > MaxInt64
    n -= (1 << 64)
  end
  n
end

#read_sfixed32Object


65
66
67
# File 'lib/beefcake/buffer/decode.rb', line 65

def read_sfixed32
  decode_zigzag(read_fixed32)
end

#read_sfixed64Object


69
70
71
# File 'lib/beefcake/buffer/decode.rb', line 69

def read_sfixed64
  decode_zigzag(read_fixed64)
end

#read_sint64Object Also known as: read_sint32


60
61
62
# File 'lib/beefcake/buffer/decode.rb', line 60

def read_sint64
  decode_zigzag(read_uint64)
end

#read_stringObject


19
20
21
# File 'lib/beefcake/buffer/decode.rb', line 19

def read_string
  read_bytes.force_encoding Encoding.find('utf-8')
end

#read_uint64Object Also known as: read_uint32


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/beefcake/buffer/decode.rb', line 43

def read_uint64
  n = shift = 0
  while true
    if shift >= 64
      raise BufferOverflowError, "varint"
    end
    b = read(1).ord

    n |= ((b & 0x7F) << shift)
    shift += 7
    if (b & 0x80) == 0
      return n
    end
  end
end

#skip(wire) ⇒ Object


87
88
89
90
91
92
93
94
# File 'lib/beefcake/buffer/decode.rb', line 87

def skip(wire)
  case wire
  when 0 then read_uint64
  when 1 then read_fixed64
  when 2 then read_string
  when 5 then read_fixed32
  end
end