File: System\Text\Json\ValueQueue.cs
Web Access
Project: src\src\libraries\System.Text.Json\src\System.Text.Json.csproj (System.Text.Json)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
 
namespace System.Text.Json
{
    /// <summary>
    /// A struct variant of <see cref="Queue{T}"/> that only allocates for Counts > 1.
    /// </summary>
    [StructLayout(LayoutKind.Auto)]
    internal struct ValueQueue<T>
    {
        private byte _state; // 0 = empty, 1 = single, 2 = multiple
        private T? _single;
        private Queue<T>? _multiple;
 
        public readonly int Count => _state < 2 ? _state : _multiple!.Count;
 
        public void Enqueue(T value)
        {
            switch (_state)
            {
                case 0:
                    _single = value;
                    _state = 1;
                    break;
 
                case 1:
                    // Once a queue gets allocated the struct will always remain in the multiple state.
                    (_multiple ??= new()).Enqueue(_single!);
                    _single = default;
                    _state = 2;
                    goto default;
 
                default:
                    Debug.Assert(_multiple != null);
                    _multiple.Enqueue(value);
                    break;
            }
        }
 
        public bool TryDequeue([MaybeNullWhen(false)] out T? value)
        {
            switch (_state)
            {
                case 0:
                    value = default;
                    return false;
 
                case 1:
                    value = _single;
                    _single = default;
                    _state = 0;
                    return true;
 
                default:
                    Debug.Assert(_multiple != null);
                    return _multiple.TryDequeue(out value);
            }
        }
    }
}