# File lib/otnetstring.rb, line 28
    def parse(io, encoding = 'internal', fallback_encoding = nil)
      fallback_encoding = io.encoding if io.respond_to? :encoding
      io = StringIO.new(io) if io.respond_to? :to_str
      length, byte = "", nil

      while byte.nil? || byte =~ /\d/
        length << byte if byte
        byte = io.read(1)
      end

      if length.size > 9
        raise Error, "#{length} is longer than 9 digits"
      elsif length !~ /\d+/
        raise Error, "Expected '#{byte}' to be a digit"
      end
      length = Integer(length)

      case byte
      when '#' then Integer io.read(length)
      when ',' then with_encoding io.read(length), encoding, fallback_encoding
      when '~' then
        raise Error, "nil has length of 0, #{length} given" unless length == 0
      when '!' then io.read(length) == 'true'
      when '[', '{'
        array = []
        start = io.pos
        array << parse(io, encoding, fallback_encoding) while io.pos - start < length
        raise Error, 'Nested element longer than container' if io.pos - start != length
        byte == "{" ? Hash[*array] : array
      else
        raise Error, "Unknown type '#{byte}'"
      end
    end