anchor.diff:      compare_frame("pubcomp", gen_pubcomp(123)),
   
       compare_frame("subscribe", gen_subscribe(123, "test/hello/world", 2)),
  +    compare_frame("subscribe_multi", gen_subscribe(123, [{"test/1", 1}, {"test/2", 2}])),
       compare_frame("suback", gen_suback(123, 2)),
  +    compare_frame("suback_multi", gen_suback(123, [0,1,2])),
  +    compare_frame("suback_0x80", gen_suback(123, not_allowed)),
  +    compare_frame("suback_multi_0x80", gen_suback(123, [0,not_allowed,2])),
  +
       compare_frame("unsubscribe", gen_unsubscribe(123, "test/hello/world")),
       compare_frame("unsuback", gen_unsuback(123)),
   
  
positive.code: serialise_len(N) ->
      <<1:1, (N rem ?HIGHBIT):7, (serialise_len(N div ?HIGHBIT))/binary>>.
  
  serialise_topics(_, [], Topics) ->
      Topics;
  serialise_topics(?SUBSCRIBE = Sub, [{Topic, QoS}|Rest], Acc) ->
      serialise_topics(Sub, Rest, [utf8(vmq_topic:unword(Topic)), <<0:6, QoS:2>>|Acc]);
  serialise_topics(?UNSUBSCRIBE = Sub, [Topic|Rest], Acc) ->
      serialise_topics(Sub, Rest, [utf8(vmq_topic:unword(Topic))|Acc]).
  
  serialise_acks([], Acks) ->
      Acks;
  serialise_acks([QoS|Rest], Acks) ->
      serialise_acks(Rest, [<<0:6, QoS:2>>|Acks]).
  
  proto(4) -> {4, ?PROTOCOL_MAGIC_311};
  proto(3) -> {6, ?PROTOCOL_MAGIC_31};
  
negative.code: gen_pubcomp(MId) ->
      iolist_to_binary(serialise(#mqtt_pubcomp{message_id=MId})).
  
  gen_subscribe(MId, [{_, _}|_] = Topics) ->
      BinTopics = [{ensure_binary(Topic), QoS} || {Topic, QoS} <- Topics],
      iolist_to_binary(serialise(#mqtt_subscribe{topics=BinTopics, message_id=MId})).
  gen_subscribe(MId, Topic, QoS) ->
      gen_subscribe(MId, [{Topic, QoS}]).
  
  gen_suback(MId, QoSs) when is_list(QoSs) ->
      iolist_to_binary(serialise(#mqtt_suback{qos_table=QoSs, message_id=MId}));
  gen_suback(MId, QoS) ->
      gen_suback(MId, [QoS]).
  
  gen_unsubscribe(MId, Topic) ->
      iolist_to_binary(serialise(#mqtt_unsubscribe{topics=[ensure_binary(Topic)], message_id=MId})).
  