1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Collections;
  8 
  9 namespace System.IO
 10 {
 11     public class BinaryReader : IOBase
 12     {
 13         public BinaryReader() : base()stream(null) {}
 14         public BinaryReader(Stream* stream_) : base()stream(stream_)
 15         {
 16         }
 17         suppress BinaryReader(const BinaryReader&);
 18         suppress void operator=(const BinaryReader&);
 19         public BinaryReader(BinaryReader&& that) : stream(that.stream)streams(Rvalue(that.streams))
 20         {
 21             that.stream = null;
 22         }
 23         public default void operator=(BinaryReader&&);
 24         public override ~BinaryReader()
 25         {
 26             long n = streams.Count();
 27             for (long i = n - 1; i >= 0; --i;)
 28             {
 29                 streams[i].Reset();
 30             }
 31         }
 32         public Stream* GetStream()
 33         {
 34             return stream;
 35         }
 36         public void SetStream(Stream* stream_)
 37         {
 38             stream = stream_;
 39         }
 40         public void Own(Stream* strm)
 41         {
 42             streams.Add(UniquePtr<Stream>(strm));
 43         }
 44         [nodiscard]
 45         public Result<bool> ReadBool()
 46         {
 47             if (Error())
 48             {
 49                 return Result<bool>(ErrorId(GetErrorId()));
 50             }
 51             auto result = ReadByte();
 52             if (result.Error())
 53             {
 54                 return Result<bool>(ErrorId(result.GetErrorId()));
 55             }
 56             return Result<bool>(cast<bool>(result.Value()));
 57         }
 58         [nodiscard]
 59         public Result<char> ReadChar()
 60         {
 61             if (Error())
 62             {
 63                 return Result<char>(ErrorId(GetErrorId()));
 64             }
 65             auto result = ReadByte();
 66             if (result.Error())
 67             {
 68                 return Result<char>(ErrorId(result.GetErrorId()));
 69             }
 70             return Result<char>(cast<char>(result.Value()));
 71         }
 72         [nodiscard]
 73         public Result<wchar> ReadWChar()
 74         {
 75             if (Error())
 76             {
 77                 return Result<wchar>(ErrorId(GetErrorId()));
 78             }
 79             auto result = ReadUShort();
 80             if (result.Error())
 81             {
 82                 return Result<wchar>(ErrorId(result.GetErrorId()));
 83             }
 84             return Result<wchar>(cast<wchar>(result.Value()));
 85         }
 86         [nodiscard]
 87         public Result<uchar> ReadUChar()
 88         {
 89             if (Error())
 90             {
 91                 return Result<uchar>(ErrorId(GetErrorId()));
 92             }
 93             auto result = ReadUInt();
 94             if (result.Error())
 95             {
 96                 return Result<uchar>(ErrorId(result.GetErrorId()));
 97             }
 98             return Result<uchar>(cast<uchar>(result.Value()));
 99         }
100         [nodiscard]
101         public Result<sbyte> ReadSByte()
102         {
103             if (Error())
104             {
105                 return Result<sbyte>(ErrorId(GetErrorId()));
106             }
107             auto result = ReadByte();
108             if (result.Error())
109             {
110                 return Result<sbyte>(ErrorId(result.GetErrorId()));
111             }
112             return Result<sbyte>(cast<sbyte>(result.Value()));
113         }
114         [nodiscard]
115         public Result<int> ReadByteOrEnd()
116         {
117             if (Error())
118             {
119                 return Result<int>(ErrorId(GetErrorId()));
120             }
121             if (stream == null)
122             {
123                 int errorId = RtmAllocateError("BinaryReader.ReadByteOrEnd: stream is null");
124                 SetErrorId(errorId);
125                 return Result<int>(ErrorId(errorId));
126             }
127             auto result = stream->ReadByte();
128             if (result.Error())
129             {
130                 SetErrorId(result.GetErrorId());
131                 return result;
132             }
133             return result;
134         }
135         [nodiscard]
136         public Result<byte> ReadByte()
137         {
138             if (Error())
139             {
140                 return Result<byte>(ErrorId(GetErrorId()));
141             }
142             if (stream == null)
143             {
144                 int errorId = RtmAllocateError("BinaryReader.ReadByte: stream is null");
145                 SetErrorId(errorId);
146                 return Result<byte>(ErrorId(errorId));
147             }
148             auto readResult = stream->ReadByte();
149             if (readResult.Error())
150             {
151                 SetErrorId(readResult.GetErrorId());
152                 return Result<byte>(ErrorId(readResult.GetErrorId()));
153             }
154             int x = readResult.Value();
155             if (x == -1)
156             {
157                 int errorId = RtmAllocateError("unexpected end of binary byte stream");
158                 SetErrorId(errorId);
159                 return Result<byte>(ErrorId(errorId));
160             }
161             return Result<byte>(cast<byte>(x));
162         }
163         [nodiscard]
164         public Result<short> ReadShort()
165         {
166             if (Error())
167             {
168                 return Result<short>(ErrorId(GetErrorId()));
169             }
170             auto result = ReadUShort();
171             if (result.Error())
172             {
173                 return Result<short>(ErrorId(result.GetErrorId()));
174             }
175             return Result<short>(cast<short>(result.Value()));
176         }
177         [nodiscard]
178         public Result<ushort> ReadUShort()
179         {
180             if (Error())
181             {
182                 return Result<ushort>(ErrorId(GetErrorId()));
183             }
184             auto x0 = ReadByte();
185             if (x0.Error())
186             {
187                 return Result<ushort>(ErrorId(x0.GetErrorId()));
188             }
189             auto x1 = ReadByte();
190             if (x1.Error())
191             {
192                 return Result<ushort>(ErrorId(x1.GetErrorId()));
193             }
194             ushort x = cast<ushort>(x0.Value()) << 8u | cast<ushort>(x1.Value());
195             return Result<ushort>(x);
196         }
197         [nodiscard]
198         public Result<int> ReadInt()
199         {
200             if (Error())
201             {
202                 return Result<int>(ErrorId(GetErrorId()));
203             }
204             auto x = ReadUInt();
205             if (x.Error())
206             {
207                 return Result<int>(ErrorId(x.GetErrorId()));
208             }
209             return Result<int>(cast<int>(x.Value()));
210         }
211         [nodiscard]
212         public Result<uint> ReadUInt()
213         {
214             if (Error())
215             {
216                 return Result<uint>(ErrorId(GetErrorId()));
217             }
218             auto x0 = ReadByte();
219             if (x0.Error())
220             {
221                 return Result<uint>(ErrorId(x0.GetErrorId()));
222             }
223             auto x1 = ReadByte();
224             if (x1.Error())
225             {
226                 return Result<uint>(ErrorId(x1.GetErrorId()));
227             }
228             auto x2 = ReadByte();
229             if (x2.Error())
230             {
231                 return Result<uint>(ErrorId(x2.GetErrorId()));
232             }
233             auto x3 = ReadByte();
234             if (x3.Error())
235             {
236                 return Result<uint>(ErrorId(x3.GetErrorId()));
237             }
238             uint x = cast<uint>(x0.Value()) << 24u | cast<uint>(x1.Value()) << 16u | cast<uint>(x2.Value()) << 8u | cast<uint>(x3.Value());
239             return Result<uint>(x);
240         }
241         [nodiscard]
242         public Result<long> ReadLong()
243         {
244             if (Error())
245             {
246                 return Result<long>(ErrorId(GetErrorId()));
247             }
248             auto x = ReadULong();
249             if (x.Error())
250             {
251                 return Result<long>(ErrorId(x.GetErrorId()));
252             }
253             return Result<long>(cast<long>(x.Value()));
254         }
255         [nodiscard]
256         public Result<ulong> ReadULong()
257         {
258             if (Error())
259             {
260                 return Result<ulong>(ErrorId(GetErrorId()));
261             }
262             auto x0 = ReadByte();
263             if (x0.Error())
264             {
265                 return Result<ulong>(ErrorId(x0.GetErrorId()));
266             }
267             auto x1 = ReadByte();
268             if (x1.Error())
269             {
270                 return Result<ulong>(ErrorId(x1.GetErrorId()));
271             }
272             auto x2 = ReadByte();
273             if (x2.Error())
274             {
275                 return Result<ulong>(ErrorId(x2.GetErrorId()));
276             }
277             auto x3 = ReadByte();
278             if (x3.Error())
279             {
280                 return Result<ulong>(ErrorId(x3.GetErrorId()));
281             }
282             auto x4 = ReadByte();
283             if (x4.Error())
284             {
285                 return Result<ulong>(ErrorId(x4.GetErrorId()));
286             }
287             auto x5 = ReadByte();
288             if (x5.Error())
289             {
290                 return Result<ulong>(ErrorId(x5.GetErrorId()));
291             }
292             auto x6 = ReadByte();
293             if (x6.Error())
294             {
295                 return Result<ulong>(ErrorId(x6.GetErrorId()));
296             }
297             auto x7 = ReadByte();
298             if (x7.Error())
299             {
300                 return Result<ulong>(ErrorId(x7.GetErrorId()));
301             }
302             ulong x = cast<ulong>(x0.Value()) << 56u | cast<ulong>(x1.Value()) << 48u | cast<ulong>(x2.Value()) << 40u | cast<ulong>(x3.Value()) << 32u | 
303                 cast<ulong>(x4.Value()) << 24u | cast<ulong>(x5.Value()) << 16u | cast<ulong>(x6.Value()) << 8u | cast<ulong>(x7.Value());
304             return Result<ulong>(x);
305         }
306         [nodiscard]
307         public Result<float> ReadFloat()
308         {
309             if (Error())
310             {
311                 return Result<float>(ErrorId(GetErrorId()));
312             }
313             auto x = ReadUInt();
314             if (x.Error())
315             {
316                 return Result<float>(ErrorId(x.GetErrorId()));
317             }
318             void* u = &x;
319             return Result<float>(*cast<float*>(u));
320         }
321         [nodiscard]
322         public Result<double> ReadDouble()
323         {
324             if (Error())
325             {
326                 return Result<double>(ErrorId(GetErrorId()));
327             }
328             auto x = ReadULong();
329             if (x.Error())
330             {
331                 return Result<double>(ErrorId(x.GetErrorId()));
332             }
333             void* u = &x;
334             return Result<double>(*cast<double*>(u));
335         }
336         [nodiscard]
337         public Result<string> ReadString()
338         {
339             if (Error())
340             {
341                 return Result<string>(ErrorId(GetErrorId()));
342             }
343             string s;
344             auto c = ReadChar();
345             if (c.Error())
346             {
347                 return Result<string>(ErrorId(c.GetErrorId()));
348             }
349             while (c.Value() != '\0')
350             {
351                 s.Append(c.Value());
352                 c = ReadChar();
353                 if (c.Error())
354                 {
355                     return Result<string>(ErrorId(c.GetErrorId()));
356                 }
357             }
358             return Result<string>(s);
359         }
360         [nodiscard]
361         public Result<wstring> ReadWString()
362         {
363             if (Error())
364             {
365                 return Result<wstring>(ErrorId(GetErrorId()));
366             }
367             auto s = ReadString();
368             if (s.Error())
369             {
370                 return Result<wstring>(ErrorId(s.GetErrorId()));
371             }
372             return Result<wstring>(ToUtf16(s.Value()));
373         }
374         [nodiscard]
375         public Result<ustring> ReadUString()
376         {
377             if (Error())
378             {
379                 return Result<ustring>(ErrorId(GetErrorId()));
380             }
381             auto s = ReadString();
382             if (s.Error())
383             {
384                 return Result<ustring>(ErrorId(s.GetErrorId()));
385             }
386             return Result<ustring>(ToUtf32(s.Value()));
387         }
388         [nodiscard]
389         public Result<Uuid> ReadUuid()
390         {
391             if (Error())
392             {
393                 return Result<Uuid>(ErrorId(GetErrorId()));
394             }
395             Uuid uuid;
396             for (byte& b : uuid)
397             {
398                 auto result = ReadByte();
399                 if (result.Error())
400                 {
401                     return Result<Uuid>(ErrorId(result.GetErrorId()));
402                 }
403                 b = result.Value();
404             }
405             return Result<Uuid>(uuid);
406         }
407         [nodiscard]
408         public Result<bool> Read(byte* bufferint size)
409         {
410             if (Error())
411             {
412                 return Result<bool>(ErrorId(GetErrorId()));
413             }
414             for (int i = 0; i < size; ++i;)
415             {
416                 auto result = ReadByte();
417                 if (result.Error())
418                 {
419                     return Result<bool>(ErrorId(result.GetErrorId()));
420                 }
421                 buffer[i] = result.Value();
422             }
423             return Result<bool>(true);
424         }
425         [nodiscard]
426         public Result<bool> Seek(long posOrigin origin)
427         {
428             if (Error())
429             {
430                 return Result<bool>(ErrorId(GetErrorId()));
431             }
432             if (stream == null)
433             {
434                 int errorId = RtmAllocateError("BinaryReader.Seek: stream is null");
435                 SetErrorId(errorId);
436                 return Result<bool>(ErrorId(errorId));
437             }
438             auto result = stream->Seek(posorigin);
439             if (result.Error())
440             {
441                 SetErrorId(result.GetErrorId());
442                 return result;
443             }
444             return result;
445         }
446         [nodiscard]
447         public Result<long> Tell()
448         {
449             if (Error())
450             {
451                 return Result<long>(ErrorId(GetErrorId()));
452             }
453             if (stream == null)
454             {
455                 int errorId = RtmAllocateError("BinaryReader.Tell: stream is null");
456                 SetErrorId(errorId);
457                 return Result<long>(ErrorId(errorId));
458             }
459             auto result = stream->Tell();
460             if (result.Error())
461             {
462                 SetErrorId(result.GetErrorId());
463                 return result;
464             }
465             return result;
466         }
467         [nodiscard]
468         public Result<long> Size()
469         {
470             if (Error())
471             {
472                 return Result<long>(ErrorId(GetErrorId()));
473             }
474             auto pos = Tell();
475             if (pos.Error())
476             {
477                 return pos;
478             }
479             auto seekResult = Seek(0Origin.seekEnd);
480             if (seekResult.Error())
481             {
482                 return Result<long>(ErrorId(seekResult.GetErrorId()));
483             }
484             auto size = Tell();
485             if (size.Error())
486             {
487                 return Result<long>(ErrorId(size.GetErrorId()));
488             }
489             auto seekResult2 = Seek(pos.Value()Origin.seekSet);
490             if (seekResult2.Error())
491             {
492                 return Result<long>(ErrorId(seekResult2.GetErrorId()));
493             }
494             return size;
495         }
496         private Stream* stream;
497         private List<UniquePtr<Stream>> streams;
498     }