/// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="metadataCustomization">Extension points for parsing metadata</param>
 /// <param name="metadataBuilder">The object used to build metadata</param>
 public CtfAntlrMetadataParser(
     ICtfMetadataCustomization metadataCustomization,
     ICtfMetadataBuilder metadataBuilder)
 {
     this.metadataCustomization = metadataCustomization;
     this.metadataBuilder       = metadataBuilder;
 }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="metadataCustomization">Extensibility points</param>
        /// <param name="metadata">The active metadata relevant to this timestamp</param>
        /// <param name="integerValue">Integer representation of the timestamp</param>
        /// <param name="timestampValue">Timestamp value in units specified by the ClockDescriptor</param>
        public CtfTimestamp(ICtfMetadataCustomization metadataCustomization, ICtfMetadata metadata, CtfIntegerValue integerValue, long timestampValue)
            : this(metadataCustomization, metadata, integerValue)
        {
            if (timestampValue < 0)
            {
                throw new ArgumentException("Negative timestamp value is not supported.", nameof(timestampValue));
            }

            this.NanosecondsFromClockBase = ConvertTimeToNanoseconds((ulong)timestampValue);
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="metadataCustomization">Extensibility points</param>
        /// <param name="metadata">The active metadata relevant to this timestamp</param>
        /// <param name="integerValue">integer representation of the timestamp</param>
        public CtfTimestamp(ICtfMetadataCustomization metadataCustomization, ICtfMetadata metadata, CtfIntegerValue integerValue)
        {
            this.BaseIntegerValue = integerValue;

            string clockName = metadataCustomization.GetTimestampClockName(integerValue);

            if (string.IsNullOrWhiteSpace(clockName))
            {
                if (!string.IsNullOrWhiteSpace(integerValue.MapValue))
                {
                    throw new CtfPlaybackException($"Unable to parse integer map value as a clock: {integerValue.MapValue}");
                }

                if (metadata.Clocks?.Count == 1)
                {
                    clockName = metadata.Clocks[0].Name;
                }
                else
                {
                    Debug.Assert(false, "Add support for default clock that increments once per nanosecond: ctf spec 1.8.2 section 8");
                    throw new NotImplementedException("This library doesn't currently support a default clock.");
                }
            }

            if (!metadata.ClocksByName.TryGetValue(clockName, out var clockDescriptor))
            {
                throw new CtfPlaybackException($"Unable to retrieve clock descriptor for timestamp value: {integerValue.MapValue}");
            }

            this.ClockDescriptor = clockDescriptor;

            if (!this.BaseIntegerValue.Value.TryGetInt64(out long value))
            {
                throw new CtfPlaybackException("Unable to retrieve timestamp as long.");
            }

            this.NanosecondsFromClockBase = ConvertIntegerValueToNanoseconds(this.BaseIntegerValue);

            this.ClockName = metadataCustomization.GetTimestampClockName(integerValue);
            this.ClockOffsetFromPosixEpochInNanoseconds = ConvertTimeToNanoseconds(this.ClockDescriptor.Offset);
        }