private TMetadata ReadMetricMetadata(BinaryReader reader, IMetricBuilder <TMetadata> metricBuilder, ushort version, int maxMetricStringsLength, int maxMetricNamespaceStringsLength)
        {
            var metricNamespace = string.Empty;

            // In versions 0-2 Metric Namespace was part of the Metric data, from version 3 it became a part of Metric Metadata
            if (version >= 3)
            {
                metricNamespace = this.ReadStringByIndex(reader);
                if (metricNamespace.Length > maxMetricNamespaceStringsLength)
                {
                    throw new MetricSerializationException($"Namespace string in the packet exceeds preconfigured length. Packet is corrupted. MaxLength:{maxMetricNamespaceStringsLength}, Value:{metricNamespace}.", null);
                }
            }

            var metricName = this.ReadStringByIndex(reader);

            if (metricName.Length > maxMetricStringsLength)
            {
                throw new MetricSerializationException($"Metric name string in the packet exceeds preconfigured length. Packet is corrupted. MaxLength:{maxMetricStringsLength}, Value:{metricName}.", null);
            }

            var count          = SerializationUtils.ReadUInt32FromBase128(reader);
            var dimensionNames = new List <string>((int)count);

            for (var i = 0; i < count; ++i)
            {
                var dimensionName = this.ReadStringByIndex(reader);
                if (dimensionName.Length > maxMetricStringsLength)
                {
                    throw new MetricSerializationException($"Dimension name string in the packet exceeds preconfigured length. Packet is corrupted. MaxLength:{maxMetricStringsLength}, Value:{dimensionName}.", null);
                }

                dimensionNames.Add(dimensionName);
            }

            return(metricBuilder.CreateMetadata(metricNamespace, metricName, dimensionNames));
        }