Class: Cborb::Decoding::State

Inherits:
Object
  • Object
show all
Defined in:
lib/cborb/decoding/state.rb

Overview

State of processing to decode

Constant Summary collapse

CONTINUE =
Object.new
NO_RESULT =
Object.new

Instance Method Summary collapse

Constructor Details

#initializeState

Returns a new instance of State.



7
8
9
10
11
12
13
14
15
16
# File 'lib/cborb/decoding/state.rb', line 7

def initialize
  @buffer = Cborb::Decoding::SimpleBuffer.new
  @stack = [[Cborb::Decoding::Types::Root, nil]]
  @result = NO_RESULT

  # This fiber decodes CBOR.
  # If buffer becomes empty, this fiber is stopped(#consume)
  # When new CBOR data is buffered(#<<), that is resumed.
  @decoding_fiber = Fiber.new { loop_consuming }
end

Instance Method Details

#<<(cbor) ⇒ Object

Buffering new CBOR data

Parameters:

  • cbor (String)


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/cborb/decoding/state.rb', line 21

def <<(cbor)
  @buffer.write(cbor)
  @decoding_fiber.resume

rescue FiberError => e
  msg = e.message

  # umm...
  if msg.include?("dead")
    raise Cborb::InvalidByteSequenceError
  elsif msg.include?("threads")
    raise Cborb::DecodingError, "Can't decode across threads"
  else
    raise
  end
end

#accept_value(type, value) ⇒ Object

Parameters:

  • type (Class)

    Class constant that inherits Cborb::Decoding::Types::Type

  • value (Object)


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/cborb/decoding/state.rb', line 87

def accept_value(type, value)
  loop do
    stacked_type, im_data = @stack.last
    value = stacked_type.accept(im_data, type, value)
    type = stacked_type

    if value.eql?(CONTINUE)
      break
    else
      @stack.pop
      if @stack.empty?
        @result = value
        break
      end
    end
  end
end

#consume(size) ⇒ String

Consume CBOR data. This method will be called only in fiber.

Parameters:

  • size (Integer)

    Size to consume

Returns:

  • (String)


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

def consume(size)
  data = @buffer.read(size).to_s

  # If buffered data is not enought, yield fiber until new data will be buffered.
  if data.size < size
    @buffer.reset!

    while data.size != size
      Fiber.yield
      data += @buffer.read(size - data.size)
    end
  end

  data
end

#consume_byteInteger

Consume 1 byte(uses #getbyte instead of #read)

Returns:

  • (Integer)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/cborb/decoding/state.rb', line 62

def consume_byte
  ib = @buffer.getbyte

  if ib.nil?
    @buffer.reset!

    while ib.nil?
      Fiber.yield
      ib = @buffer.getbyte
    end
  end

  ib
end

#finished?Boolean

Returns:

  • (Boolean)


111
112
113
# File 'lib/cborb/decoding/state.rb', line 111

def finished?
  !@result.eql?(NO_RESULT)
end

#push_stack(type, im_data = nil) ⇒ Object

Push type that has following data(e.g. Array) to stack

Parameters:

  • type (Class)

    Class constant that inherits Cborb::Decoding::Types::Type

  • im_data (Object) (defaults to: nil)

    depends on type



81
82
83
# File 'lib/cborb/decoding/state.rb', line 81

def push_stack(type, im_data = nil)
  @stack << [type, im_data]
end

#remaining_bytesString

Returns:

  • (String)


121
122
123
124
125
126
127
# File 'lib/cborb/decoding/state.rb', line 121

def remaining_bytes
  if finished?
    @buffer.peek
  else
    ""
  end
end

#resultObject

Returns:

  • (Object)


116
117
118
# File 'lib/cborb/decoding/state.rb', line 116

def result
  finished? ? @result : nil
end

#stack_topClass

Returns Class constant that inherits Cborb::Decoding::Types::Type on top of stack.

Returns:

  • (Class)

    Class constant that inherits Cborb::Decoding::Types::Type on top of stack.



106
107
108
# File 'lib/cborb/decoding/state.rb', line 106

def stack_top
  @stack.last.first
end