/// <summary> /// Deserializes counter (metric) data from the stream and adds all objects to provided collection. /// </summary> /// <param name="stream">Stream from which data should be deserialized. Stream should be readable and provide randon access.</param> /// <param name="metricBuilder">An object responsible for creation and further consumption of deserialized data.</param> /// <param name="maxMetricStringsLength">Maximum length of strings, which represent metric name, dimension names and values.</param> /// <param name="maxMetricNamespaceStringsLength">Maximum length of metric namespace string.</param> /// <param name="maxMetricDimensionValueStringsLength">Maximum length of metric dimension value string.</param> public void Deserialize(Stream stream, IMetricBuilder <TMetadata> metricBuilder, int maxMetricStringsLength, int maxMetricNamespaceStringsLength, int maxMetricDimensionValueStringsLength) { if (!stream.CanRead || !stream.CanSeek) { throw new ArgumentException(@"Stream should be readable and provide random access.", nameof(stream)); } try { using (var reader = new NoCloseBinaryReader(stream, Encoding.UTF8)) { var startStreamPosition = stream.Position; // Read version and type serializers info var version = reader.ReadUInt16(); if (version > MaxVersion) { throw new VersionNotSupportedMetricSerializationException( string.Format( CultureInfo.InvariantCulture, "Version is not supported. Read version:{0}, Max version:{1}.", version, MaxVersion)); } if (version >= 5) { // Read CRC. CRC check is done in upper layers. reader.ReadUInt32(); } if (reader.ReadUInt32() != TypeSerializerFlags) { throw new VersionNotSupportedMetricSerializationException("Type serializers not supported."); } metricBuilder.SetSerializationVersion(version); // Read strings var deserializerDataPosition = stream.Position; stream.Position += sizeof(long); stream.Position = startStreamPosition + reader.ReadInt64(); var count = SerializationUtils.ReadUInt32FromBase128(reader); for (uint i = 0; i < count; ++i) { this.stringsDictionary.Add(reader.ReadString()); } // Read metrics metadata stream.Position = deserializerDataPosition; stream.Position = startStreamPosition + reader.ReadInt64(); count = SerializationUtils.ReadUInt32FromBase128(reader); for (uint i = 0; i < count; ++i) { this.metadataDictionary.Add(this.ReadMetricMetadata(reader, metricBuilder, version, maxMetricStringsLength, maxMetricNamespaceStringsLength)); } // Read metrics data stream.Position = deserializerDataPosition + (2 * sizeof(long)); this.ReadMetricsData(reader, metricBuilder, version, maxMetricStringsLength, maxMetricNamespaceStringsLength, maxMetricDimensionValueStringsLength); } } catch (IOException ioException) { throw new MetricSerializationException("Failed to deserialize data. Problem with input stream.", ioException); } catch (Exception exception) { throw new MetricSerializationException("Failed to deserialize data. Likely the incoming stream contains corrupted data.", exception); } finally { this.metadataDictionary.Clear(); this.stringsDictionary.Clear(); this.histogramBuffer.Clear(); } }