/// <summary>
        ///     Tries to get the column with the given <see cref="Guid"/> from the builder,
        ///     if the builder has a column with the given <see cref="Guid"/>.
        /// </summary>
        /// <typeparam name="T">
        ///     The <see cref="Type"/> of data projected by the column.
        /// </typeparam>
        /// <param name="self">
        ///     The builder instance.
        /// </param>
        /// <param name="columnGuid">
        ///     The <see cref="Guid"/> of the column to retrieve.
        /// </param>
        /// <returns>
        ///     The column, if it exists; <c>null</c> otherwise.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">
        ///     <paramref name="self"/> is <c>null</c>.
        /// </exception>
        public static IDataColumn <T> GetColumnOrNull <T>(
            this ITableBuilderWithRowCount self,
            Guid columnGuid)
        {
            Guard.NotNull(self, nameof(self));

            return(self.GetColumnOrNull <T>(x => x.Configuration.Metadata.Guid == columnGuid));
        }
        /// <summary>
        ///     Adds a new column to the builder with the given
        ///     configuration and projection.
        /// </summary>
        /// <typeparam name="T">
        ///     The <see cref="Type"/> of data being projected.
        /// </typeparam>
        /// <param name="self">
        ///     The builder instance.
        /// </param>
        /// <param name="column">
        ///     The column configuration the added column is to have.
        /// </param>
        /// <param name="projection">
        ///     The projection the added column is to have.
        /// </param>
        /// <returns>
        ///     The builder instance.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">
        ///     <paramref name="column"/> is <c>null</c>.
        ///     - or -
        ///     <paramref name="projection"/> is <c>null</c>.
        ///     - or -
        ///     <paramref name="self"/> is <c>null</c>.
        /// </exception>
        public static ITableBuilderWithRowCount AddColumn <T>(
            this ITableBuilderWithRowCount self,
            ColumnConfiguration column,
            IProjection <int, T> projection)
        {
            Guard.NotNull(self, nameof(self));
            Guard.NotNull(projection, nameof(projection));

            return(self.AddColumn(new BaseDataColumn <T>(column, projection)));
        }
        /// <summary>
        ///     Adds a new hierarchical column to the builder with the given
        ///     configuration, projection, and info providers.
        /// </summary>
        /// <typeparam name="T">
        ///     The <see cref="Type"/> of data being projected.
        /// </typeparam>
        /// <param name="self">
        ///     The builder instance.
        /// </param>
        /// <param name="column">
        ///     The column configuration the added column is to have.
        /// </param>
        /// <param name="projection">
        ///     The projection the added column is to have.
        /// </param>
        /// <param name="collectionProvider">
        ///     The collection provider for the column.
        /// </param>
        /// <returns>
        ///     The builder instance.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">
        ///     <paramref name="collectionProvider"/> is <c>null</c>.
        ///     - or -
        ///     <paramref name="column"/> is <c>null</c>.
        ///     - or -
        ///     <paramref name="projection"/> is <c>null</c>.
        ///     - or -
        ///     <paramref name="self"/> is <c>null</c>.
        /// </exception>
        public static ITableBuilderWithRowCount AddHierarchicalColumn <T>(
            this ITableBuilderWithRowCount self,
            ColumnConfiguration column,
            IProjection <int, T> projection,
            ICollectionInfoProvider <T> collectionProvider)
        {
            Guard.NotNull(self, nameof(self));
            Guard.NotNull(projection, nameof(projection));
            Guard.NotNull(collectionProvider, nameof(collectionProvider));

            return(self.AddColumn(new HierarchicalDataColumn <T>(column, projection, collectionProvider)));
        }
        /// <summary>
        ///     Replaces the column in the builder with a new column
        ///     using the given projection. The current columns configuration
        ///     is used on the new column. If the old column does not exist,
        ///     then a new column is simply added.
        /// </summary>
        /// <typeparam name="T">
        ///     The <see cref="Type"/> of data in the column
        /// </typeparam>
        /// <param name="self">
        ///     The builder instance.
        /// </param>
        /// <param name="old">
        ///     The column to replace.
        /// </param>
        /// <param name="newProjection">
        ///     The projection that the replacement column should have.
        /// </param>
        /// <returns>
        ///     The builder instance.
        /// </returns>
        /// <exception cref="System.ArgumentException">
        ///     <paramref name="newProjection"/> is <c>null</c>.
        ///     - or -
        ///     <paramref name="old"/> is <c>null</c>.
        ///     - or -
        ///     <paramref name="self"/> is <c>null</c>.
        /// </exception>
        public static ITableBuilderWithRowCount ReplaceColumn <T>(
            this ITableBuilderWithRowCount self,
            IDataColumn old,
            IProjection <int, T> newProjection)
        {
            Guard.NotNull(self, nameof(self));
            Guard.NotNull(old, nameof(old));
            Guard.NotNull(newProjection, nameof(newProjection));

            var newColumn = new BaseDataColumn <T>(old.Configuration, newProjection);

            return(self.ReplaceColumn(old, newColumn));
        }
        /// <summary>
        ///     Tries to get the column that satisfies the given predicate from the builder.
        ///     This method will return the first column found that matches the predicate.
        /// </summary>
        /// <typeparam name="T">
        ///     The <see cref="Type"/> of data projected by the column.
        /// </typeparam>
        /// <param name="self">
        ///     The builder instance.
        /// </param>
        /// <param name="predicate">
        ///     The predicate to use to search for columns.
        /// </param>
        /// <returns>
        ///     The column, if it exists; <c>null</c> otherwise.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">
        ///     <paramref name="self"/> is <c>null</c>.
        ///     - or -
        ///     <paramref name="predicate"/> is <c>null</c>.
        /// </exception>
        public static IDataColumn <T> GetColumnOrNull <T>(
            this ITableBuilderWithRowCount self,
            Func <IDataColumn <T>, bool> predicate)
        {
            Guard.NotNull(self, nameof(self));
            Guard.NotNull(predicate, nameof(predicate));

            foreach (var column in self.Columns)
            {
                if (column is IDataColumn <T> castedColumn)
                {
                    if (predicate(castedColumn))
                    {
                        return(castedColumn);
                    }
                }
            }

            return(null);
        }
        internal static void BuildMetadataTable(ITableBuilder tableBuilder, LTTngSourceParser sourceParser, ITableConfigurationsSerializer serializer)
        {
            ITableBuilderWithRowCount table = tableBuilder.SetRowCount(sourceParser.TraceStats.Count);

            IReadOnlyList <string> eventNames = sourceParser.TraceStats.Keys.ToList();

            var eventNameProjection       = Projection.CreateUsingFuncAdaptor(x => eventNames[x]);
            var traceStatsProjection      = eventNameProjection.Compose(eventName => sourceParser.TraceStats[eventName]);
            var eventCountProjection      = traceStatsProjection.Compose(traceStats => traceStats.EventCount);
            var payloadBitCountProjection = traceStatsProjection.Compose(traceStats => (double)traceStats.PayloadBitCount / 8);

            table.AddColumn(
                new DataColumn <string>(
                    EventNameConfiguration,
                    eventNameProjection));

            table.AddColumn(
                new DataColumn <ulong>(
                    CountConfiguration,
                    eventCountProjection));

            table.AddColumn(
                new DataColumn <double>(
                    TotalPayloadSizeConfiguration,
                    payloadBitCountProjection));

            var configurations = TableConfigurations.GetPrebuiltTableConfigurations(
                typeof(TraceStatsTable),
                TableDescriptor.Guid,
                serializer);

            foreach (var configuration in configurations)
            {
                tableBuilder.AddTableConfiguration(configuration);
                if (StringComparer.Ordinal.Equals(configuration.Name, configurations.DefaultConfigurationName))
                {
                    tableBuilder.SetDefaultTableConfiguration(configuration);
                }
            }
        }
        public static bool TestRowTypesMatchColTypes(ITableBuilderWithRowCount tbr, int rowNumber)
        {
            for (var i = 0; i < tbr.Columns.Count; i++)
            {
                var col = tbr.Columns.ElementAt(i);
                try
                {
                    var projResult = col.Project(rowNumber);

                    if (projResult != null)
                    {
                        var projResultType = projResult.GetType();
                        throw new InvalidDataException($"Column DataType {col.DataType} does not match projected type {projResultType}");
                    }
                }
                catch (Exception)
                {
                }
            }

            return(true);
        }