1 //
2 // Copyright (c) 2010-2022 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using System.Collections.Generic;
9 
10 namespace Antmicro.Renode.Utilities.RESD
11 {
12     public class MetadataBlock
13     {
ReadFromStream(SafeBinaryReader reader)14         public static IDictionary<String, MetadataValue> ReadFromStream(SafeBinaryReader reader)
15         {
16             var metadata = new Dictionary<string, MetadataValue>();
17 
18             var metadataLength = reader.ReadUInt64();
19             if(metadataLength == 0)
20             {
21                 return metadata;
22             }
23 
24             var startPosition = (ulong)reader.BaseStream.Position;
25 
26             while((ulong)reader.BaseStream.Position < startPosition + metadataLength)
27             {
28                 var keyName = reader.ReadCString();
29                 var valueType = (MetadataValueType)reader.ReadByte();
30                 MetadataValue value;
31                 switch(valueType)
32                 {
33                     case MetadataValueType.Int8:
34                         value = new MetadataValue(reader.ReadSByte());
35                         break;
36                     case MetadataValueType.UInt8:
37                         value = new MetadataValue(reader.ReadByte());
38                         break;
39                     case MetadataValueType.Int16:
40                         value = new MetadataValue(reader.ReadInt16());
41                         break;
42                     case MetadataValueType.UInt16:
43                         value = new MetadataValue(reader.ReadUInt16());
44                         break;
45                     case MetadataValueType.Int32:
46                         value = new MetadataValue(reader.ReadInt32());
47                         break;
48                     case MetadataValueType.UInt32:
49                         value = new MetadataValue(reader.ReadUInt32());
50                         break;
51                     case MetadataValueType.Int64:
52                         value = new MetadataValue(reader.ReadInt64());
53                         break;
54                     case MetadataValueType.UInt64:
55                         value = new MetadataValue(reader.ReadUInt64());
56                         break;
57                     case MetadataValueType.Float:
58                         value = new MetadataValue(reader.ReadSingle());
59                         break;
60                     case MetadataValueType.Double:
61                         value = new MetadataValue(reader.ReadDouble());
62                         break;
63                     case MetadataValueType.String:
64                         value = new MetadataValue(reader.ReadCString());
65                         break;
66                     case MetadataValueType.Blob:
67                         var blobLength = reader.ReadUInt32();
68                         value = new MetadataValue(reader.ReadBytes((int)blobLength));
69                         break;
70                     default:
71                         throw new RESDException($"Invalid metadata type ({valueType}), offset: {reader.BaseStream.Position - 1}");
72                 }
73 
74                 metadata.Add(keyName, value);
75             }
76 
77             if((ulong)reader.BaseStream.Position != (startPosition + metadataLength))
78             {
79                 throw new RESDException($"Invalid amount of data read, expected: {metadataLength}, actual: {(ulong)reader.BaseStream.Position - startPosition}");
80             }
81 
82             return metadata;
83         }
84     }
85 }
86