Task <Models.Client.Decklist> ISerializer <Models.Client.Decklist> .Deserialize(
            Stream stream)
        {
            stream.Require(nameof(stream));

            return(__Deserialize());

            async Task <Models.Client.Decklist> __Deserialize()
            {
                await stream.ReadAsync(new byte[3], 0, 3).ConfigureAwait(false);

                (int heroDatabaseID, _) = (await __ParseCards(1).ConfigureAwait(false)).FirstOrDefault();
                if (heroDatabaseID == 0)
                {
                    throw new Exception("Failed to parse hero!");
                }

                string heroID = _cardInfoProvider.GetCardInfo(heroDatabaseID)?.ID;

                if (heroID == null)
                {
                    throw new Exception($"Could not resolve hero ({heroDatabaseID})!");
                }

                IEnumerable <Models.Client.DecklistCard> decklistCards =
                    (await __ParseCards(1).ConfigureAwait(false))
                    .Concat(
                        (await __ParseCards(2).ConfigureAwait(false))
                        .Concat(
                            (await __ParseCards().ConfigureAwait(false))))
                    .Select(
                        __cardData =>
                {
                    string cardID = _cardInfoProvider.GetCardInfo(__cardData.DatabaseID)?.ID;
                    if (cardID == null)
                    {
                        throw new Exception($"Could not resolve card ({__cardData.DatabaseID})!");
                    }

                    return(new Models.Client.DecklistCard(cardID, __cardData.Count));
                });

                return(new Models.Client.Decklist(heroID, decklistCards));
            }

            async Task <IEnumerable <(int DatabaseID, int Count)> > __ParseCards(
                int?count = null)
            {
                int numCards = await Varint.Parse(stream).ConfigureAwait(false);

                var parsedCards = new (int, int)[numCards];
        Task ICollectionSerializer <T> .Serialize(
            Stream stream,
            IEnumerable <T> items)
        {
            items.Require(nameof(items));

            return(__Serialize());

            async Task __Serialize()
            {
                items = items.ToList();

                byte[] header = Varint.GetBytes(items.Count()).ToArray();
                await stream.WriteAsync(header, 0, header.Length).ConfigureAwait(false);

                foreach (T item in items)
                {
                    await _itemSerializer.Serialize(stream, item).ConfigureAwait(false);
                }
            }
        }
        Task <IEnumerable <T> > ICollectionSerializer <T> .Deserialize(
            Stream stream)
        {
            stream.Require(nameof(stream));

            return(__Deserialize());

            async Task <IEnumerable <T> > __Deserialize()
            {
                var items = new List <T>();

                int count = await Varint.Parse(stream).ConfigureAwait(false);

                for (int index = 0; index < count; index++)
                {
                    items.Add(await _itemSerializer.Deserialize(stream).ConfigureAwait(false));
                }

                return(items);
            }
        }