1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
module Beefcake
class Buffer
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,
}
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
def self.encodable?(type)
return false if ! type.is_a?(Class)
type.public_method_defined?(:encode)
end
attr_reader :buf
alias :to_s :buf
alias :to_str :buf
class OutOfRangeError < StandardError
def initialize(n)
super("Value of of range: %d" % [n])
end
end
class BufferOverflowError < StandardError
def initialize(s)
super("Too many bytes read for %s" % [s])
end
end
class UnknownType < StandardError
def initialize(s)
super("Unknown type '%s'" % [s])
end
end
def initialize(buf="")
self.buf = buf
end
def buf=(new_buf)
@buf = new_buf.force_encoding('BINARY')
@cursor = 0
end
def length
remain = buf.slice(@cursor..-1)
remain.bytesize
end
def <<(bytes)
bytes = bytes.force_encoding('BINARY') if bytes.respond_to? :force_encoding
buf << bytes
end
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
end
end
|