class Cborb::Decoding::State

State of processing to decode

Constants

CONTINUE
NO_RESULT

Public Class Methods

new() click to toggle source
# 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

Public Instance Methods

<<(cbor) click to toggle source

Buffering new CBOR data

@param [String] cbor

# 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) click to toggle source

@param [Class] type Class constant that inherits Cborb::Decoding::Types::Type @param [Object] value

# 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) click to toggle source

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

@param [Integer] size Size to consume @return [String]

# 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_byte() click to toggle source

Consume 1 byte(uses getbyte instead of read)

@return [Integer]

# 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?() click to toggle source

@return [Boolean]

# File lib/cborb/decoding/state.rb, line 111
def finished?
  !@result.eql?(NO_RESULT)
end
push_stack(type, im_data = nil) click to toggle source

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

@param [Class] type Class constant that inherits Cborb::Decoding::Types::Type @param [Object] im_data depends on type

# File lib/cborb/decoding/state.rb, line 81
def push_stack(type, im_data = nil)
  @stack << [type, im_data]
end
remaining_bytes() click to toggle source

@return [String]

# File lib/cborb/decoding/state.rb, line 121
def remaining_bytes
  if finished?
    @buffer.peek
  else
    ""
  end
end
result() click to toggle source

@return [Object]

# File lib/cborb/decoding/state.rb, line 116
def result
  finished? ? @result : nil
end
stack_top() click to toggle source

@return [Class] Class constant that inherits Cborb::Decoding::Types::Type on top of stack.

# File lib/cborb/decoding/state.rb, line 106
def stack_top
  @stack.last.first
end

Private Instance Methods

loop_consuming() click to toggle source
# File lib/cborb/decoding/state.rb, line 131
def loop_consuming
  until finished? do
    ib = consume_byte
    Cborb::Decoding::IB_JUMP_TABLE[ib].decode(self, ib & 0x1F)
  end
end