def do_parse(signature)
      packet = nil
      case signature.sigtype
      when Type::BYTE
        packet = read(1).unpack("C")[0]
      when Type::UINT16
        align(2)
        packet = read(2).unpack(@uint16)[0]
      when Type::INT16
        align(2)
        packet = read(2).unpack(@uint16)[0]
        if (packet & 0x8000) != 0
          packet -= 0x10000
        end
      when Type::UINT32, Type::UNIX_FD
        align(4)
        packet = read(4).unpack(@uint32)[0]
      when Type::INT32
        align(4)
        packet = read(4).unpack(@uint32)[0]
        if (packet & 0x80000000) != 0
          packet -= 0x100000000
        end
      when Type::UINT64
        align(8)
        packet_l = read(4).unpack(@uint32)[0]
        packet_h = read(4).unpack(@uint32)[0]
        packet = if @endianness == LIL_END
                   packet_l + packet_h * 2**32
                 else
                   packet_l * 2**32 + packet_h
                 end
      when Type::INT64
        align(8)
        packet_l = read(4).unpack(@uint32)[0]
        packet_h = read(4).unpack(@uint32)[0]
        packet = if @endianness == LIL_END
                   packet_l + packet_h * 2**32
                 else
                   packet_l * 2**32 + packet_h
                 end
        if (packet & 0x8000000000000000) != 0
          packet -= 0x10000000000000000
        end
      when Type::DOUBLE
        align(8)
        packet = read(8).unpack(@double)[0]
      when Type::BOOLEAN
        align(4)
        v = read(4).unpack(@uint32)[0]
        raise InvalidPacketException if ![0, 1].member?(v)
        packet = (v == 1)
      when Type::ARRAY
        align(4)
        # checks please
        array_sz = read(4).unpack(@uint32)[0]
        raise InvalidPacketException if array_sz > 67_108_864

        align(signature.child.alignment)
        raise IncompleteBufferException if @idx + array_sz > @buffy.bytesize

        packet = []
        start_idx = @idx
        while @idx - start_idx < array_sz
          packet << do_parse(signature.child)
        end

        if signature.child.sigtype == Type::DICT_ENTRY
          packet = Hash[packet]
        end
      when Type::STRUCT
        align(8)
        packet = []
        signature.members.each do |elem|
          packet << do_parse(elem)
        end
      when Type::VARIANT
        string = read_signature
        # error checking please
        sig = Type::Parser.new(string).parse[0]
        align(sig.alignment)
        packet = do_parse(sig)
      when Type::OBJECT_PATH
        packet = read_string
      when Type::STRING
        packet = read_string
        packet.force_encoding("UTF-8")
      when Type::SIGNATURE
        packet = read_signature
      when Type::DICT_ENTRY
        align(8)
        key = do_parse(signature.members[0])
        value = do_parse(signature.members[1])
        packet = [key, value]
      else
        raise NotImplementedError,
              "sigtype: #{signature.sigtype} (#{signature.sigtype.chr})"
      end
      packet
    end
def do_parse(signature)
      packet = nil
      case signature.sigtype
      when Type::BYTE
        packet = read(1).unpack("C")[0]
      when Type::UINT16
        align(2)
        packet = read(2).unpack(@uint16)[0]
      when Type::INT16
        align(2)
        packet = read(2).unpack(@uint16)[0]
        if (packet & 0x8000) != 0
          packet -= 0x10000
        end
      when Type::UINT32, Type::UNIX_FD
        align(4)
        packet = read(4).unpack(@uint32)[0]
      when Type::INT32
        align(4)
        packet = read(4).unpack(@uint32)[0]
        if (packet & 0x80000000) != 0
          packet -= 0x100000000
        end
      when Type::UINT64
        align(8)
        packet_l = read(4).unpack(@uint32)[0]
        packet_h = read(4).unpack(@uint32)[0]
        packet = if @endianness == LIL_END
                   packet_l + packet_h * 2**32
                 else
                   packet_l * 2**32 + packet_h
                 end
      when Type::INT64
        align(8)
        packet_l = read(4).unpack(@uint32)[0]
        packet_h = read(4).unpack(@uint32)[0]
        packet = if @endianness == LIL_END
                   packet_l + packet_h * 2**32
                 else
                   packet_l * 2**32 + packet_h
                 end
        if (packet & 0x8000000000000000) != 0
          packet -= 0x10000000000000000
        end
      when Type::DOUBLE
        align(8)
        packet = read(8).unpack(@double)[0]
      when Type::BOOLEAN
        align(4)
        v = read(4).unpack(@uint32)[0]
        raise InvalidPacketException if ![0, 1].member?(v)
        packet = (v == 1)
      when Type::ARRAY
        align(4)
        # checks please
        array_sz = read(4).unpack(@uint32)[0]
        raise InvalidPacketException if array_sz > 67_108_864

        align(signature.child.alignment)
        raise IncompleteBufferException if @idx + array_sz > @buffy.bytesize

        packet = []
        start_idx = @idx
        while @idx - start_idx < array_sz
          packet << do_parse(signature.child)
        end

        if signature.child.sigtype == Type::DICT_ENTRY
          packet = Hash[packet]
        end
      when Type::STRUCT
        align(8)
        packet = []
        signature.members.each do |elem|
          packet << do_parse(elem)
        end
      when Type::VARIANT
        string = read_signature
        # error checking please
        sig = Type::Parser.new(string).parse[0]
        align(sig.alignment)
        packet = do_parse(sig)
      when Type::OBJECT_PATH
        packet = read_string
      when Type::STRING
        packet = read_string
        packet.force_encoding("UTF-8")
      when Type::SIGNATURE
        packet = read_signature
      when Type::DICT_ENTRY
        align(8)
        key = do_parse(signature.members[0])
        value = do_parse(signature.members[1])
        packet = [key, value]
      else
        raise NotImplementedError,
              "sigtype: #{signature.sigtype} (#{signature.sigtype.chr})"
      end
      packet
    end
Based on the _signature_ type, retrieve a packet from the buffer
 and return it.