internal static async Task WriteSubscribeAsync(this Stream stream, Subscribe subscribe) { // Determine packet size var variableHeaderSize = WordSize; var payloadSize = subscribe.GetPayloadSize(); var(remainingLength, remainingLengthBuffer) = EncodeRemainingLength(variableHeaderSize + payloadSize); var fixedHeaderSize = 1 + remainingLength; // 1 => holds packet type in high nibble, reserved in low var bufferSize = fixedHeaderSize + variableHeaderSize + payloadSize; var buffer = new byte[bufferSize]; var index = 0; // Fixed header // - Packet type buffer[index++] = CombineNibbles(Subscribe.PacketType, Bit1); // - Remaining length Buffer.BlockCopy(remainingLengthBuffer, 0, buffer, index, remainingLength); index += remainingLength; // Variable header // - Message Id Buffer.BlockCopy(subscribe.PacketId.GetBigEndianBytes(), 0, buffer, index, WordSize); index += WordSize; // Payload // - Subscriptions subscribe.Subscriptions.ForEach(subscription => { index = EncodeString(subscription.TopicFilter, buffer, index); buffer[index++] = (byte)subscription.RequestedQoS; }); await stream.WriteAsync(buffer, 0, index).ConfigureAwait(false); await stream.FlushAsync().ConfigureAwait(false); }
private static int GetPayloadSize(this Subscribe subscribe) => subscribe.Subscriptions.Select(subscription => subscription.TopicFilter).Aggregate(0, (count, topicFilter) => count + topicFilter.TryGetUTF8ByteCount()) + subscribe.Subscriptions.Count;