Class: Arf::Wire::Frame

Inherits:
Object
  • Object
show all
Defined in:
lib/arf/wire/frame.rb

Constant Summary collapse

MAGIC =
"arf"
MAGIC_SIZE =
3
STREAM_ID_SIZE =
4
FRAME_KIND_SIZE =
1
FLAGS_SIZE =
1
LENGTH_SIZE =
2
FRAME_SIZE =
MAGIC_SIZE + STREAM_ID_SIZE + FRAME_KIND_SIZE + FLAGS_SIZE + LENGTH_SIZE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#flagsObject

Returns the value of attribute flags.



14
15
16
# File 'lib/arf/wire/frame.rb', line 14

def flags
  @flags
end

#frame_kindObject

Returns the value of attribute frame_kind.



14
15
16
# File 'lib/arf/wire/frame.rb', line 14

def frame_kind
  @frame_kind
end

#lengthObject

Returns the value of attribute length.



14
15
16
# File 'lib/arf/wire/frame.rb', line 14

def length
  @length
end

#payloadObject

Returns the value of attribute payload.



15
16
17
# File 'lib/arf/wire/frame.rb', line 15

def payload
  @payload
end

#stream_idObject

Returns the value of attribute stream_id.



14
15
16
# File 'lib/arf/wire/frame.rb', line 14

def stream_id
  @stream_id
end

Class Method Details

.from_io(io) ⇒ Object



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
# File 'lib/arf/wire/frame.rb', line 26

def self.from_io(io)
  buf = StringIO.new
  read_exactly(io, buf, FRAME_SIZE)
  raise MagicNumberMismatchError if buf.read(3) != Frame::MAGIC

  stream_id = Wire.decode_uint32(buf)
  raw_kind = buf.readbyte
  frame_kind = Wire::FRAME_TO_SYMBOL[raw_kind]
  raise UnknownFrameKindError, raw_kind unless frame_kind

  flags = buf.readbyte
  length = Wire.decode_uint16(buf)
  payload = nil
  if length.positive?
    payload = StringIO.new
    read_exactly(io, payload, length)
  end

  new.tap do |f|
    f.stream_id = stream_id
    f.frame_kind = frame_kind
    f.flags = flags
    f.payload = payload
    f.length = length
  end
end

.read_exactly(io, into, n) ⇒ Object



19
20
21
22
23
24
# File 'lib/arf/wire/frame.rb', line 19

def self.read_exactly(io, into, n)
  into.truncate(0)
  into.write(io.read(n - into.length)) until into.length == n
  into.rewind
  into
end

Instance Method Details

#bytes(compressor) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/arf/wire/frame.rb', line 53

def bytes(compressor)
  @payload = IO::COMPRESSOR[compressor].compress(@payload)
  @length = @payload&.length || 0

  IO::Buffer.new
    .write_raw(MAGIC)
    .write_raw(Wire.encode_uint32(@stream_id || 0))
    .write_raw([SYMBOL_TO_FRAME[@frame_kind]].pack("C*"))
    .write_raw(@flags || 0)
    .write_raw(Wire.encode_uint16(@length))
    .write_raw(@payload&.string || "")
    .string
end

#decompress(compressor) ⇒ Object



84
85
86
87
# File 'lib/arf/wire/frame.rb', line 84

def decompress(compressor)
  @payload = IO::COMPRESSOR[compressor].decompress(@payload)
  @length = @payload&.length || 0
end

#empty?Boolean

Returns:

  • (Boolean)


17
# File 'lib/arf/wire/frame.rb', line 17

def empty? = length ? length.zero? : true

#specialize(compressor) ⇒ Object



102
103
104
105
106
107
108
# File 'lib/arf/wire/frame.rb', line 102

def specialize(compressor)
  cls = BaseFrame.frame_by_kind(@frame_kind)
  raise UnknownFrameKindError, @frame_kind if cls.nil?

  decompress(compressor)
  cls.new(self)
end

#validate_kind(expected, associated) ⇒ Object

Raises:



67
68
69
70
71
72
73
74
75
# File 'lib/arf/wire/frame.rb', line 67

def validate_kind(expected, associated)
  raise FrameMismatchError.new(expected, @frame_kind) if @frame_kind != expected

  if associated && (@stream_id.nil? || @stream_id.zero?)
    raise UnexpectedUnassociatedFrameError, @frame_kind
  elsif !associated && (!@stream_id.nil? && @stream_id != 0)
    raise UnexpectedAssociatedFrameError, @frame_kind
  end
end

#validate_size(size) ⇒ Object



77
78
79
80
81
82
# File 'lib/arf/wire/frame.rb', line 77

def validate_size(size)
  return unless @length != size

  raise InvalidFrameLengthError, "invalid length for frame #{@frame_kind} " \
                                 "#{size} bytes are required, received #{@length}"
end