<commit_before>// <copyright file="PredictableDataStore{T}.cs" company="<NAME>">
// Copyright (c) <NAME> with all rights reserved. Part of the IX Framework.
// </copyright>

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace IX.StandardExtensions.TestUtils
{
    /// <summary>
    /// A data store for storing items in a predictable way, such as any iteration through the store will produce the same output. This class is thread-safe, and its internal items container is immutable.
    /// </summary>
    /// <typeparam name="T">The type of items in the store.</typeparam>
    public class PredictableDataStore<T> : IEnumerable<T>
    {
        private readonly T[] items;

        private int index;

        /// <summary>
        /// Initializes a new instance of the <see cref="PredictableDataStore{T}"/> class.
        /// </summary>
        /// <param name="capacity">The capacity.</param>
        /// <param name="generator">The generator.</param>
        public PredictableDataStore(int capacity, Func<T> generator)
            : this(capacity, generator, false)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PredictableDataStore{T}" /> class.
        /// </summary>
        /// <param name="capacity">The capacity.</param>
        /// <param name="generator">The sateful generator.</param>
        /// <param name="state">The state.</param>
        public PredictableDataStore(int capacity, Func<object, T> generator, object state)
            : this(capacity, generator, state, false)
        {
        }

#pragma warning disable HAA0302 // Display class allocation to capture closure - The closures here are acceptable
#pragma warning disable HAA0301 // Closure Allocation Source
        /// <summary>
        /// Initializes a new instance of the <see cref="PredictableDataStore{T}"/> class.
        /// </summary>
        /// <param name="capacity">The capacity.</param>
        /// <param name="generator">The generator.</param>
        /// <param name="parallelGenerate">if set to <see langword="true"/>, run generation of items in parallel.</param>
        public PredictableDataStore(int capacity, Func<T> generator, bool parallelGenerate)
        {
            this.items = new T[capacity];

            if (parallelGenerate)
            {
                Parallel.For(
                    0,
                    capacity,
                    index =>
                    {
                        T item = generator();

                        this.items[index] = item;
                    });
            }
            else
            {
                for (var i = 0; i < capacity; i++)
                {
                    this.items[i] = generator();
                }
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PredictableDataStore{T}" /> class.
        /// </summary>
        /// <param name="capacity">The capacity.</param>
        /// <param name="generator">The generator.</param>
        /// <param name="state">The state.</param>
        /// <param name="parallelGenerate">if set to <see langword="true"/>, run generation of items in parallel.</param>
        public PredictableDataStore(int capacity, Func<object, T> generator, object state, bool parallelGenerate)
        {
            this.items = new T[capacity];

            if (parallelGenerate)
            {
                Parallel.For(
                    0,
                    capacity,
                    index =>
                    {
                        T item = generator(state);

                        this.items[index] = item;
                    });
            }
            else
            {
                for (var i = 0; i < capacity; i++)
                {
                    this.items[i] = generator(state);
                }
            }
        }
#pragma warning restore HAA0301 // Closure Allocation Source
#pragma warning restore HAA0302 // Display class allocation to capture closure

        /// <summary>
        /// Gets the count.
        /// </summary>
        /// <value>The count.</value>
        public int Count => this.items.Length;

        /// <summary>
        /// Takes an item from the predictable data store.
        /// </summary>
        /// <returns>T.</returns>
        public T Take()
        {
            T item;

            lock (this.items)
            {
                item = this.items[this.index];
                this.index++;
            }

            return item;
        }

        /// <summary>
        /// Resets this instance.
        /// </summary><commit_msg>#12 - Predictable data store is now a read-only collection.<commit_after>// <copyright file="PredictableDataStore{T}.cs" company="<NAME>">
// Copyright (c) <NAME> with all rights reserved. Part of the IX Framework.
// </copyright>

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;

namespace IX.StandardExtensions.TestUtils
{
    /// <summary>
    /// A data store for storing items in a predictable way, such as any iteration through the store will produce the same output. This class is thread-safe, and its internal items container is immutable.
    /// </summary>
    /// <typeparam name="T">The type of items in the store.</typeparam>
    [PublicAPI]
    public class PredictableDataStore<T> : IReadOnlyList<T>
    {
        private readonly T[] items;

        private int index;

        /// <summary>
        /// Initializes a new instance of the <see cref="PredictableDataStore{T}"/> class.
        /// </summary>
        /// <param name="capacity">The capacity.</param>
        /// <param name="generator">The generator.</param>
        public PredictableDataStore(int capacity, Func<T> generator)
            : this(capacity, generator, false)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PredictableDataStore{T}" /> class.
        /// </summary>
        /// <param name="capacity">The capacity.</param>
        /// <param name="generator">The sateful generator.</param>
        /// <param name="state">The state.</param>
        public PredictableDataStore(int capacity, Func<object, T> generator, object state)
            : this(capacity, generator, state, false)
        {
        }

#pragma warning disable HAA0302 // Display class allocation to capture closure - The closures here are acceptable
#pragma warning disable HAA0301 // Closure Allocation Source
        /// <summary>
        /// Initializes a new instance of the <see cref="PredictableDataStore{T}"/> class.
        /// </summary>
        /// <param name="capacity">The capacity.</param>
        /// <param name="generator">The generator.</param>
        /// <param name="parallelGenerate">if set to <see langword="true"/>, run generation of items in parallel.</param>
        public PredictableDataStore(int capacity, Func<T> generator, bool parallelGenerate)
        {
            this.items = new T[capacity];

            if (parallelGenerate)
            {
                Parallel.For(
                    0,
                    capacity,
                    index =>
                    {
                        T item = generator();

                        this.items[index] = item;
                    });
            }
            else
            {
                for (var i = 0; i < capacity; i++)
                {
                    this.items[i] = generator();
                }
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PredictableDataStore{T}" /> class.
        /// </summary>
        /// <param name="capacity">The capacity.</param>
        /// <param name="generator">The generator.</param>
        /// <param name="state">The state.</param>
        /// <param name="parallelGenerate">if set to <see langword="true"/>, run generation of items in parallel.</param>
        public PredictableDataStore(int capacity, Func<object, T> generator, object state, bool parallelGenerate)
        {
            this.items = new T[capacity];

            if (parallelGenerate)
            {
                Parallel.For(
                    0,
                    capacity,
                    index =>
                    {
                        T item = generator(state);

                        this.items[index] = item;
                    });
            }
            else
            {
                for (var i = 0; i < capacity; i++)
                {
                    this.items[i] = generator(state);
                }
            }
        }
#pragma warning restore HAA0301 // Closure Allocation Source
#pragma warning restore HAA0302 // Display class allocation to capture closure

        /// <summary>
        /// Gets the count.
        /// </summary>
        /// <value>The count.</value>
        public int Count => this.items.Length;

        /// <summary>Gets the element at the specified index in the read-only list.</summary>
        /// <param name="index">The zero-based index of the element to get. </param>
        /// <returns>The element at the specified index in the read-only list.</returns>
        public T this[int index] => this.items[index];

        /// <summary>
        /// Takes an item from the predictable data store.
        /// </summary>
        /// <returns>T.</returns>
        public T Take()
        {
            T item;

            lock (this.items)
            {
                item = this.items[this.index];
                this.index++;
            }

            return item;
        }

        /// <summary>
        /// Resets this instance.
        /// </summary>
{'fraction_non_alphanumeric': 0.12208532735973933, 'fraction_numerical': 0.0042765502494654314, 'mean_word_length': 1.5598123534010946, 'pattern_counts': {'":': 0, '<': 137, '<?xml version=': 0, '>': 140, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6201454', 'n_tokens_mistral': 2499, 'n_tokens_neox': 2378, 'n_words': 732}