1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 
  8 namespace System.IO
  9 {
 10     public class MemoryReader : IOBase
 11     {
 12         public MemoryReader(byte* ptr_long count_) : base()ptr(ptr_)pos(ptr)count(count_)
 13         {
 14         }
 15         [nodiscard]
 16         public Result<bool> ReadBool()
 17         {
 18             if (Error())
 19             {
 20                 return Result<bool>(ErrorId(GetErrorId()));
 21             }
 22             auto result = ReadByte();
 23             if (result.Error())
 24             {
 25                 return Result<bool>(ErrorId(result.GetErrorId()));
 26             }
 27             return Result<bool>(cast<bool>(result.Value()));
 28         }
 29         [nodiscard]
 30         public Result<byte> ReadByte()
 31         {
 32             if (Error())
 33             {
 34                 return Result<byte>(ErrorId(GetErrorId()));
 35             }
 36             if (pos - ptr >= count)
 37             {
 38                 int errorId = AllocateError("memory reader: unexpected end of data");
 39                 SetErrorId(errorId);
 40                 return Result<byte>(ErrorId(errorId));
 41             }
 42             return Result<byte>(*pos++);
 43         }
 44         [nodiscard]
 45         public Result<sbyte> ReadSByte()
 46         {
 47             if (Error())
 48             {
 49                 return Result<sbyte>(ErrorId(GetErrorId()));
 50             }
 51             auto result = ReadByte();
 52             if (result.Error())
 53             {
 54                 return Result<sbyte>(ErrorId(result.GetErrorId()));
 55             }
 56             return cast<sbyte>(result.Value());
 57         }
 58         [nodiscard]
 59         public Result<ushort> ReadUShort()
 60         {
 61             if (Error())
 62             {
 63                 return Result<ushort>(ErrorId(GetErrorId()));
 64             }
 65             auto b0 = ReadByte();
 66             if (b0.Error())
 67             {
 68                 return Result<ushort>(ErrorId(b0.GetErrorId()));
 69             }
 70             auto b1 = ReadByte();
 71             if (b1.Error())
 72             {
 73                 return Result<ushort>(ErrorId(b1.GetErrorId()));
 74             }
 75             return Result<ushort>((cast<ushort>(b0.Value()) << 8u) | cast<ushort>(b1.Value()));
 76         }
 77         [nodiscard]
 78         public Result<short> ReadShort()
 79         {
 80             if (Error())
 81             {
 82                 return Result<short>(ErrorId(GetErrorId()));
 83             }
 84             auto result = ReadUShort();
 85             if (result.Error())
 86             {
 87                 return Result<short>(ErrorId(result.GetErrorId()));
 88             }
 89             return Result<short>(cast<short>(result.Value()));
 90         }
 91         [nodiscard]
 92         public Result<uint> ReadUInt()
 93         {
 94             if (Error())
 95             {
 96                 return Result<uint>(ErrorId(GetErrorId()));
 97             }
 98             auto b0 = ReadByte();
 99             if (b0.Error())
100             {
101                 return Result<uint>(ErrorId(b0.GetErrorId()));
102             }
103             auto b1 = ReadByte();
104             if (b1.Error())
105             {
106                 return Result<uint>(ErrorId(b1.GetErrorId()));
107             }
108             auto b2 = ReadByte();
109             if (b2.Error())
110             {
111                 return Result<uint>(ErrorId(b2.GetErrorId()));
112             }
113             auto b3 = ReadByte();
114             if (b3.Error())
115             {
116                 return Result<uint>(ErrorId(b3.GetErrorId()));
117             }
118             return Result<uint>((cast<uint>(b0.Value()) << 24u) | (cast<uint>(b1.Value()) << 16u) | (cast<uint>(b2.Value()) << 8u) | cast<uint>(b3.Value()));
119         }
120         [nodiscard]
121         public Result<int> ReadInt()
122         {
123             if (Error())
124             {
125                 return Result<int>(ErrorId(GetErrorId()));
126             }
127             auto result = ReadUInt();
128             if (result.Error())
129             {
130                 return Result<int>(ErrorId(result.GetErrorId()));
131             }
132             return Result<int>(cast<int>(result.Value()));
133         }
134         [nodiscard]
135         public Result<ulong> ReadULong()
136         {
137             if (Error())
138             {
139                 return Result<ulong>(ErrorId(GetErrorId()));
140             }
141             auto b0 = ReadByte();
142             if (b0.Error())
143             {
144                 return Result<ulong>(ErrorId(b0.GetErrorId()));
145             }
146             auto b1 = ReadByte();
147             if (b1.Error())
148             {
149                 return Result<ulong>(ErrorId(b1.GetErrorId()));
150             }
151             auto b2 = ReadByte();
152             if (b2.Error())
153             {
154                 return Result<ulong>(ErrorId(b2.GetErrorId()));
155             }
156             auto b3 = ReadByte();
157             if (b3.Error())
158             {
159                 return Result<ulong>(ErrorId(b3.GetErrorId()));
160             }
161             auto b4 = ReadByte();
162             if (b4.Error())
163             {
164                 return Result<ulong>(ErrorId(b4.GetErrorId()));
165             }
166             auto b5 = ReadByte();
167             if (b5.Error())
168             {
169                 return Result<ulong>(ErrorId(b5.GetErrorId()));
170             }
171             auto b6 = ReadByte();
172             if (b6.Error())
173             {
174                 return Result<ulong>(ErrorId(b6.GetErrorId()));
175             }
176             auto b7 = ReadByte();
177             if (b7.Error())
178             {
179                 return Result<ulong>(ErrorId(b7.GetErrorId()));
180             }
181             return Result<ulong>((cast<ulong>(b0.Value()) << 56u) | (cast<ulong>(b1.Value()) << 48u) | (cast<ulong>(b2.Value()) << 40u) | (cast<ulong>(b3.Value()) << 32u) | 
182                 (cast<ulong>(b4.Value()) << 24u) | (cast<ulong>(b5.Value()) << 16u) | (cast<ulong>(b6.Value()) << 8u) | cast<ulong>(b7.Value()));
183         }
184         [nodiscard]
185         public Result<long> ReadLong()
186         {
187             if (Error())
188             {
189                 return Result<long>(ErrorId(GetErrorId()));
190             }
191             auto result = ReadULong();
192             if (result.Error())
193             {
194                 return Result<long>(ErrorId(result.GetErrorId()));
195             }
196             return Result<long>(cast<long>(result.Value()));
197         }
198         [nodiscard]
199         public Result<float> ReadFloat()
200         {
201             if (Error())
202             {
203                 return Result<float>(ErrorId(GetErrorId()));
204             }
205             auto result = ReadUInt();
206             if (result.Error())
207             {
208                 return Result<float>(ErrorId(result.GetErrorId()));
209             }
210             uint x = result.Value();
211             return Result<float>(*cast<float*>(cast<void*>(&x)));
212         }
213         [nodiscard]
214         public Result<double> ReadDouble()
215         {
216             if (Error())
217             {
218                 return Result<double>(ErrorId(GetErrorId()));
219             }
220             auto result = ReadULong();
221             if (result.Error())
222             {
223                 return Result<double>(ErrorId(result.GetErrorId()));
224             }
225             ulong x = result.Value();
226             return Result<double>(*cast<double*>(cast<void*>(&x)));
227         }
228         [nodiscard]
229         public Result<char> ReadChar()
230         {
231             if (Error())
232             {
233                 return Result<char>(ErrorId(GetErrorId()));
234             }
235             auto result = ReadByte();
236             if (result.Error())
237             {
238                 return Result<char>(ErrorId(result.GetErrorId()));
239             }
240             return Result<char>(cast<char>(result.Value()));
241         }
242         [nodiscard]
243         public Result<wchar> ReadWChar()
244         {
245             if (Error())
246             {
247                 return Result<wchar>(ErrorId(GetErrorId()));
248             }
249             auto result = ReadUShort();
250             if (result.Error())
251             {
252                 return Result<wchar>(ErrorId(result.GetErrorId()));
253             }
254             return Result<wchar>(cast<wchar>(result.Value()));
255         }
256         [nodiscard]
257         public Result<uchar> ReadUChar()
258         {
259             if (Error())
260             {
261                 return Result<uchar>(ErrorId(GetErrorId()));
262             }
263             auto result = ReadUInt();
264             if (result.Error())
265             {
266                 return Result<uchar>(ErrorId(result.GetErrorId()));
267             }
268             return Result<uchar>(cast<uchar>(result.Value()));
269         }
270         [nodiscard]
271         public Result<Date> ReadDate()
272         {
273             if (Error())
274             {
275                 return Result<Date>(ErrorId(GetErrorId()));
276             }
277             auto year = ReadShort();
278             if (year.Error())
279             {
280                 return Result<Date>(ErrorId(year.GetErrorId()));
281             }
282             auto m = ReadSByte();
283             if (m.Error())
284             {
285                 return Result<Date>(ErrorId(m.GetErrorId()));
286             }
287             Month month = cast<Month>(m.Value());
288             auto day = ReadSByte();
289             if (day.Error())
290             {
291                 return Result<Date>(ErrorId(day.GetErrorId()));
292             }
293             Date date(year.Value()monthday.Value());
294             return Result<Date>(date);
295         }
296         [nodiscard]
297         public Result<DateTime> ReadDateTime()
298         {
299             if (Error())
300             {
301                 return Result<DateTime>(ErrorId(GetErrorId()));
302             }
303             auto date = ReadDate();
304             if (date.Error())
305             {
306                 return Result<DateTime>(ErrorId(date.GetErrorId()));
307             }
308             auto secs = ReadInt();
309             if (secs.Error())
310             {
311                 return Result<DateTime>(ErrorId(secs.GetErrorId()));
312             }
313             DateTime dt(date.Value()secs.Value());
314             return Result<DateTime>(dt);
315         }
316         [nodiscard]
317         public Result<string> ReadString()
318         {
319             if (Error())
320             {
321                 return Result<string>(ErrorId(GetErrorId()));
322             }
323             string result;
324             auto b = ReadByte();
325             if (b.Error())
326             {
327                 return Result<string>(ErrorId(b.GetErrorId()));
328             }
329             while (b.Value() != 0u)
330             {
331                 result.Append(cast<char>(b.Value()));
332                 b = ReadByte();
333                 if (b.Error())
334                 {
335                     return Result<string>(ErrorId(b.GetErrorId()));
336                 }
337             }
338             return Result<string>(result);
339         }
340         [nodiscard]
341         public Result<Uuid> ReadUuid()
342         {
343             if (Error())
344             {
345                 return Result<Uuid>(ErrorId(GetErrorId()));
346             }
347             Uuid x;
348             for (byte& b : x)
349             {
350                 auto result = ReadByte();
351                 if (result.Error())
352                 {
353                     return Result<Uuid>(ErrorId(result.GetErrorId()));
354                 }
355                 b = result.Value();
356             }
357             return Result<Uuid>(x);
358         }
359         private byte* ptr;
360         private byte* pos;
361         private long count;
362     }