Exemplo n.º 1
0
        public static CharacterCreateRequest Unmarshal(MessageEventArgs args)
        {
            var reader = new SpanReader(args.Message.Payload.Span);
            var slot   = reader.ReadByte();
            var c      = new Character();

            c.Level = 1;
            c.Name  = reader.ReadDaocString();
            reader.Skip(4);             // 0x18 0x00 0x00 0x00 - DoL notes say this is an array length
            c.Customization = reader.Read <Customizations>();
            reader.Skip(9);
            var operation = reader.ReadByte();                  // 1
            var custType  = reader.ReadByte();                  // 0

            reader.Skip(2);                                     // ???
            c.LocationDescription = reader.ReadDaocString();    // empty
            reader.ReadDaocString();                            // class description; redundant and empty
            reader.ReadDaocString();                            // race description; redundant and empty
            reader.Skip(1);                                     // ???
            c.Classification = reader.Read <Classification>();
            c.Model          = reader.ReadUInt16LittleEndian(); // 12352
            c.Region         = reader.ReadUInt16LittleEndian(); // byte? 27
            reader.Skip(4);
            c.Stats     = reader.Read <Stats>();
            c.Equipment = reader.Read <Equipment>(); // empty
            ;                                        // 4 bytes left
            return(new CharacterCreateRequest(slot, c));
        }
Exemplo n.º 2
0
        public int ExtractHuffmanPart(ref SpanReader sr, out Span <byte> outEntryData)
        {
            byte entryDataLength = sr.Span[sr.Position];

            outEntryData = new byte[entryDataLength];
            int basePos = sr.Position;

            if (entryDataLength != 0)
            {
                int totalCount = 0;
                for (int i = 0; i < entryDataLength; i++)
                {
                    int current = totalCount / 8; // >> 3
                    if (totalCount < 0 && (totalCount & 7) != 0)
                    {
                        current++;
                    }

                    sr.Position = basePos + current + 1;

                    // Bury this and never look at it. Mystic PD shit.
                    uint val = 0;
                    val  += !sr.IsEndOfSpan ? sr.ReadByte()              : 0u;
                    val  += !sr.IsEndOfSpan ? sr.ReadByte() * 0x100u     : 0u;
                    val  += !sr.IsEndOfSpan ? sr.ReadByte() * 0x10000u   : 0u;
                    val  += !sr.IsEndOfSpan ? sr.ReadByte() * 0x1000000u : 0u;
                    val >>= totalCount - (current * 8);

                    Span <byte> b = outEntryData.Slice(i);
                    totalCount += (int)ProcessHuffmanCode(val, ref b);
                }
            }
            sr.Position = basePos;
            return(entryDataLength);
        }
        private static void RewriteMessageLocalized(ReadOnlySpan <byte> input, CircularBuffer <byte> output, out int length)
        {
            var isAffix = input[0] == 0xCC;

            var reader = new SpanReader(input);

            reader.Seek(3, SeekOrigin.Current);
            var serial  = (Serial)reader.ReadUInt32();
            var graphic = reader.ReadInt16();
            var type    = (MessageType)reader.ReadByte();
            var hue     = reader.ReadInt16();
            var font    = reader.ReadInt16();
            var label   = reader.ReadInt32();
            var flags   = isAffix ? (AffixType)reader.ReadByte() : AffixType.System;
            var name    = reader.ReadAscii(30);
            var affix   = isAffix ? reader.ReadAscii() : string.Empty;
            var args    = isAffix ? reader.ReadBigUni() : reader.ReadLittleUni();

            if (!ZhConfig.Messaging.Cliloc.ContainsKey(label))
            {
                length = NetworkCompression.Compress(input, output);
                return;
            }

            var text = ClilocList.Translate(label, args);

            if (isAffix)
            {
                text = flags switch
                {
                    AffixType.Append => $"{text}{affix}",
                    AffixType.Prepend => $"{affix}{text}",
                    _ => $"{text}{affix}"
                };

                if ((flags & AffixType.System) != 0)
                {
                    type = MessageType.System;
                }
            }

            var buffer  = stackalloc byte[GetMaxMessageLength(text)].InitializePacket();
            var pLength = CreateMessage(
                buffer,
                serial,
                graphic,
                type,
                hue,
                font,
                true,
                null,
                name,
                text
                );

            buffer = buffer.SliceToLength(pLength);

            length = NetworkCompression.Compress(buffer, output);
        }
    }
Exemplo n.º 4
0
 public void Read(ref SpanReader r)
 {
     ID                   = Encoding.ASCII.GetString(r.ReadBytes(8));
     Version              = r.ReadByte();
     OutputChannelCount   = r.ReadByte();
     PreSkip              = r.ReadUShort();
     InputSampleRate      = r.ReadUInt32();
     OutputGain           = r.ReadShort();
     ChannelMappingFamily = r.ReadByte();
 }
Exemplo n.º 5
0
        public static ulong DecodeBitsAndAdvance(ref SpanReader sr)
        {
            ulong value = sr.ReadByte();
            ulong mask  = 0x80;

            while ((value & mask) != 0)
            {
                value  = ((value - mask) << 8) | (sr.ReadByte());
                mask <<= 7;
            }
            return(value);
        }
Exemplo n.º 6
0
        public static Entry ReadEntryFromBuffer(ref SpanReader sr)
        {
            Entry           entry = null;
            VolumeEntryType type  = (VolumeEntryType)sr.ReadByte();

            if (type == VolumeEntryType.CompressedFile)
            {
                entry = new CompressedFileEntry();
                ((CompressedFileEntry)entry).EntryType      = type;
                ((CompressedFileEntry)entry).PageOffset     = sr.ReadInt32();
                ((CompressedFileEntry)entry).ModifiedDate   = sr.ReadDateTimeT();
                ((CompressedFileEntry)entry).CompressedSize = sr.ReadInt32();
                ((CompressedFileEntry)entry).Size           = sr.ReadInt32();
            }
            else if (type == VolumeEntryType.File)
            {
                entry = new FileEntry();
                ((FileEntry)entry).EntryType    = type;
                ((FileEntry)entry).PageOffset   = sr.ReadInt32();
                ((FileEntry)entry).ModifiedDate = sr.ReadDateTimeT();
                ((FileEntry)entry).Size         = sr.ReadInt32();
                ((FileEntry)entry).EntryType    = type;
            }
            else if (type == VolumeEntryType.Directory)
            {
                entry = new DirEntry();
                ((DirEntry)entry).EntryType = type;
                ((DirEntry)entry).NodeID    = sr.ReadInt32();
            }

            return(entry);
        }
        private static void RewriteUnicodeMessage(ReadOnlySpan <byte> input, CircularBuffer <byte> output, out int length)
        {
            var reader = new SpanReader(input);

            reader.Seek(3, SeekOrigin.Current);

            var serial  = reader.ReadUInt32();
            var graphic = reader.ReadInt16();
            var type    = (MessageType)reader.ReadByte();
            var hue     = reader.ReadInt16();
            var font    = reader.ReadInt16();
            var lang    = reader.ReadAscii(4);
            var name    = reader.ReadAscii(30);
            var text    = reader.ReadBigUni();

            var buffer  = stackalloc byte[GetMaxMessageLength(text)].InitializePacket();
            var pLength = CreateMessage(
                buffer,
                serial,
                graphic,
                type,
                hue,
                font,
                true,
                null,
                name,
                text
                );

            buffer = buffer.SliceToLength(pLength);
            length = NetworkCompression.Compress(buffer, output);
        }
Exemplo n.º 8
0
        public static RegionRequest Unmarshall(MessageEventArgs args)
        {
            var reader = new SpanReader(args.Message.Payload.Span);
            var slot   = reader.ReadByte();

            return(new RegionRequest(slot));
        }
Exemplo n.º 9
0
 public void Deserialize(ref SpanReader sr)
 {
     Flags              = (EntryKeyFlags)sr.ReadByte();
     NameIndex          = (uint)CryptoUtils.DecodeBitsAndAdvance(ref sr);
     FileExtensionIndex = Flags.HasFlag(EntryKeyFlags.File) ? (uint)CryptoUtils.DecodeBitsAndAdvance(ref sr) : 0;
     EntryIndex         = (uint)CryptoUtils.DecodeBitsAndAdvance(ref sr);
 }
Exemplo n.º 10
0
        public static AdhocFile ReadFromFile(string path)
        {
            var bytes = File.ReadAllBytes(path);
            var sr    = new SpanReader(bytes, encoding: Encoding.UTF8);

            string magic = sr.ReadStringRaw(4);

            if (!magic.Equals(MAGIC))
            {
                throw new Exception("Invalid MAGIC, doesn't match ADCH.");
            }

            byte version = (byte)int.Parse(sr.ReadStringRaw(3));

            sr.ReadByte();
            var adc = new AdhocFile(version);

            if (adc.Version >= 9)
            {
                adc.ParseStringTable(ref sr);
            }

            adc.ParentCode = new AdhocCode();
            adc.ParentCode.Deserialize(adc, ref sr);

            return(adc);
        }
Exemplo n.º 11
0
        public static GameOpenRequest Unmarshall(MessageEventArgs args)
        {
            var  reader     = new SpanReader(args.Message.Payload.Span);
            byte confirmUdp = reader.ReadByte();

            return(new GameOpenRequest(confirmUdp));
        }
Exemplo n.º 12
0
        public static ushort ReadByteAtOffset(ref SpanReader sr, uint offset)
        {
            int curPos = sr.Position;

            sr.Position += (int)offset;
            ushort val = sr.ReadByte();

            sr.Position = curPos;
            return(val);
        }
Exemplo n.º 13
0
        public void Deserialize(ref SpanReader sr)
        {
            Flags = (FileInfoFlags)sr.ReadByte();

            FileIndex        = (uint)DecodeBitsAndAdvance(ref sr);
            CompressedSize   = (uint)DecodeBitsAndAdvance(ref sr);
            UncompressedSize = Flags.HasFlag(FileInfoFlags.Compressed) ? (uint)DecodeBitsAndAdvance(ref sr) : CompressedSize;

            SegmentIndex = (uint)DecodeBitsAndAdvance(ref sr);
        }
Exemplo n.º 14
0
        public virtual void Parse(Span <byte> span)
        {
            var spanReader = new SpanReader(span);

            TrackNumber = spanReader.ReadVInt().Value;
            TimeCode    = spanReader.ReadShort(true); // EBML integer datatypes are big-endian
            Flags       = spanReader.ReadByte();

            IsInvisible = (Flags & InvisibleBit) == InvisibleBit;
            Lacing      = (Lacing)(Flags & LacingBits);

            if (Lacing != Lacing.No)
            {
                NumFrames = spanReader.ReadByte();

                if (Lacing != Lacing.FixedSize)
                {
                    LaceCodedSizeOfEachFrame = spanReader.ReadByte();
                }
            }

            Data = span.Slice(spanReader.Position).ToArray();
        }
        //[Test]
        //public void LevelDbGetValueFromMissingKey()
        //{
        //	using var db = new Database(new DirectoryInfo(@"C:\Development\Other\bedrock-server-1.14.1.4\worlds\BedrockGeneratedLevel\db"));
        //	db.Open();

        //	int x = 15;
        //	int z = 6;

        //	Log.Warn("Looking for version");
        //	var versionKey = BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x76}).ToArray();
        //	var version = db.Get(versionKey);
        //	Assert.AreEqual(15, version.First());

        //	Log.Warn("Looking for key");
        //	Assert.NotNull(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 0}).ToArray()));
        //	Assert.NotNull(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 1}).ToArray()));
        //	Assert.NotNull(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 2}).ToArray()));
        //	Assert.NotNull(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 3}).ToArray()));
        //	Assert.NotNull(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 4}).ToArray()));
        //	Assert.NotNull(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 5}).ToArray()));
        //	Assert.Null(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 6}).ToArray()));
        //	Assert.Null(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 7}).ToArray()));
        //	Assert.Null(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 8}).ToArray())); // Fail??
        //	Assert.Null(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 9}).ToArray()));
        //	Assert.Null(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 10}).ToArray()));
        //	Assert.Null(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 11}).ToArray()));
        //	Assert.Null(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 12}).ToArray()));
        //	Assert.Null(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 13}).ToArray()));
        //	Assert.Null(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 14}).ToArray()));
        //	Assert.Null(db.Get(BitConverter.GetBytes(x).Concat(BitConverter.GetBytes(z)).Concat(new byte[] {0x2f, 15}).ToArray()));
        //}

        private void ParseChunk(ReadOnlySpan <byte> data)
        {
            var reader = new SpanReader(data);

            var version = reader.ReadByte();

            Assert.AreEqual(8, version);             // new palette-based chunk format

            var storageSize = reader.ReadByte();

            for (int i = 0; i < storageSize; i++)
            {
                var bitsPerBlock = reader.ReadByte() >> 1;
                Assert.AreEqual(4, bitsPerBlock);
                int numberOfBytes = 4096 / (32 / bitsPerBlock) * 4;
                var blockData     = reader.Read(numberOfBytes);

                Assert.AreEqual(4096 / 2, blockData.Length);

                int paletteSize = reader.ReadInt32();
                Assert.AreEqual(12, paletteSize);

                for (int j = 0; j < paletteSize; j++)
                {
                    NbtFile file = new NbtFile();
                    file.BigEndian = false;
                    file.UseVarInt = false;
                    var buffer = data.Slice(reader.Position).ToArray();

                    int numberOfBytesRead = (int)file.LoadFromStream(new MemoryStream(buffer), NbtCompression.None);
                    reader.Position += numberOfBytesRead;
                    Console.WriteLine(file.RootTag);
                    Assert.NotZero(numberOfBytesRead);
                }
            }
        }
Exemplo n.º 16
0
        public (SpecDBRowData Row, bool ReadAll) ReadRow(Span <byte> rowData, Endian endian)
        {
            var sr  = new SpanReader(rowData, endian);
            var row = new SpecDBRowData();

            foreach (var columnMeta in Columns)
            {
                switch (columnMeta.ColumnType)
                {
                case DBColumnType.Bool:
                    row.ColumnData.Add(new DBBool(sr.ReadBoolean())); break;

                case DBColumnType.Byte:
                    row.ColumnData.Add(new DBByte(sr.ReadByte())); break;

                case DBColumnType.SByte:
                    row.ColumnData.Add(new DBSByte(sr.ReadSByte())); break;

                case DBColumnType.Short:
                    row.ColumnData.Add(new DBShort(sr.ReadInt16())); break;

                case DBColumnType.UShort:
                    row.ColumnData.Add(new DBUShort(sr.ReadUInt16())); break;

                case DBColumnType.Int:
                    row.ColumnData.Add(new DBInt(sr.ReadInt32())); break;

                case DBColumnType.UInt:
                    row.ColumnData.Add(new DBUInt(sr.ReadUInt32())); break;

                case DBColumnType.Long:
                    row.ColumnData.Add(new DBLong(sr.ReadInt64())); break;

                case DBColumnType.Float:
                    row.ColumnData.Add(new DBFloat(sr.ReadSingle())); break;

                case DBColumnType.String:
                    row.ColumnData.Add(new DBString(sr.ReadInt32(), columnMeta.StringFileName)); break;

                default:
                    break;
                }
            }

            return(row, sr.IsEndOfSpan);
        }
Exemplo n.º 17
0
        private List <KeyValuePair <byte[], ResultCacheEntry> > DecodeBatch(ReadOnlySpan <byte> data)
        {
            SpanReader batchReader = new SpanReader(data);

            var sequenceNumber = batchReader.ReadInt64();
            var operationCount = batchReader.ReadInt32();

            var result = new List <KeyValuePair <byte[], ResultCacheEntry> >(operationCount);

            for (int i = 0; i < operationCount; i++)
            {
                byte operationCode = batchReader.ReadByte();

                var keyLength  = batchReader.ReadVarLong();
                var currentKey = batchReader.Read(keyLength);

                if (operationCode == (int)OperationType.Put)                  // Put
                {
                    ulong valueLength = batchReader.ReadVarLong();

                    var currentVal = batchReader.Read(valueLength);
                    result.Add(new KeyValuePair <byte[], ResultCacheEntry>(currentKey.ToArray(), new ResultCacheEntry
                    {
                        Sequence    = sequenceNumber,
                        ResultState = ResultState.Exist,
                        Data        = currentVal.ToArray()
                    }));
                }
                else if (operationCode == (int)OperationType.Delete)                  // Delete
                {
                    // says return "not found" in this case. Need to investigate since I believe there can multiple records with same key in this case.
                    result.Add(new KeyValuePair <byte[], ResultCacheEntry>(currentKey.ToArray(), new ResultCacheEntry
                    {
                        Sequence    = sequenceNumber,
                        ResultState = ResultState.Deleted
                    }));
                }
                else
                {
                    // unknown recType
                }
            }

            return(result);
        }
Exemplo n.º 18
0
        public void ReadIDIMapOffsets(SpecDB specDb)
        {
            //if (TableName.Equals("CAR_NAME_"))
            //    TableName += specDb.LocaleName;

            var        buffer = File.ReadAllBytes(Path.Combine(specDb.FolderName, TableName) + ".idi");
            SpanReader sr     = new SpanReader(buffer);

            var magic = sr.ReadStringRaw(4);

            if (magic != "GTID")
            {
                throw new InvalidDataException("IDI Table had invalid magic.");
            }

            Endian endian = sr.ReadByte() != 0 ? Endian.Little : Endian.Big;

            IDI         = new IDI(buffer, endian);
            sr.Endian   = endian;
            sr.Position = 0x0C;
            TableID     = sr.ReadInt32();
        }
Exemplo n.º 19
0
        private List <KeyValuePair <byte[], ResultCacheEntry> > DecodeBatch(ReadOnlySpan <byte> data)
        {
            var batchReader = new SpanReader(data);

            long sequenceNumber = (long)batchReader.ReadUInt64();
            int  operationCount = (int)batchReader.ReadUInt32();

            var result = new List <KeyValuePair <byte[], ResultCacheEntry> >(operationCount);

            for (int i = 0; i < operationCount; i++)
            {
                byte operationCode = batchReader.ReadByte();

                ReadOnlySpan <byte> currentKey = batchReader.ReadLengthPrefixedBytes();

                if (operationCode == (int)OperationType.Value)                  // Put
                {
                    ReadOnlySpan <byte> currentVal = batchReader.ReadLengthPrefixedBytes();
                    result.Add(new KeyValuePair <byte[], ResultCacheEntry>(currentKey.ToArray(), new ResultCacheEntry
                    {
                        Sequence    = sequenceNumber,
                        ResultState = ResultState.Exist,
                        Data        = currentVal.ToArray()
                    }));
                }
                else if (operationCode == (int)OperationType.Delete)                  // Delete
                {
                    // says return "not found" in this case. Need to investigate since I believe there can multiple records with same key in this case.
                    result.Add(new KeyValuePair <byte[], ResultCacheEntry>(currentKey.ToArray(), new ResultCacheEntry
                    {
                        Sequence    = sequenceNumber,
                        ResultState = ResultState.Deleted
                    }));
                }
            }

            return(result);
        }
Exemplo n.º 20
0
        public object Parse(byte[] filterBlock)
        {
            var reader = new SpanReader(filterBlock);

            if (reader.Length < 5)
            {
                return(null);
            }

            reader.Seek(-1, SeekOrigin.End);
            _baseLg = reader.ReadByte();
            reader.Seek(-5, SeekOrigin.End);
            _startOffsetArray = reader.ReadInt32();

            if (_startOffsetArray > reader.Length - 5)
            {
                return(null);
            }

            _filterBlock = filterBlock;

            return(null);
        }
Exemplo n.º 21
0
 public override void Deserialize(AdhocFile parent, ref SpanReader sr)
 {
     State = (AdhocRunState)sr.ReadByte();
 }
Exemplo n.º 22
0
        public void LevelDbWriteUserDataTest()
        {
            // Plan

            var operations = new KeyValuePair <byte[], MemCache.ResultCacheEntry> [3];

            for (int i = 0; i < 3; i++)
            {
                byte[] key   = TestUtils.FillArrayWithRandomBytes(20);
                var    entry = new MemCache.ResultCacheEntry();
                entry.ResultState = ResultState.Exist;
                entry.Sequence    = 10;
                entry.Data        = TestUtils.FillArrayWithRandomBytes(32768);          // 32KB is maz size for a block, not that it matters for this
                operations[i]     = new KeyValuePair <byte[], MemCache.ResultCacheEntry>(key, entry);
            }

            MemCache memCache = new MemCache();

            // Do

            ReadOnlySpan <byte> result = memCache.EncodeBatch(operations);

            // Check

            SpanReader reader = new SpanReader(result);

            Assert.AreEqual(10, reader.ReadInt64(), "Sequence number");
            Assert.AreEqual(3, reader.ReadInt32(), "Operations count");

            for (int i = 0; i < 3; i++)
            {
                var expectedKey  = operations[i].Key;
                var expectedData = operations[i].Value.Data;

                Assert.AreEqual(1, reader.ReadByte(), "Operations type PUT");
                var keyLen = reader.ReadVarLong();

                Assert.AreEqual(expectedKey.Length, keyLen, "Key len");
                Assert.AreEqual(expectedKey, reader.Read(keyLen).ToArray(), "Key");

                var dataLen = reader.ReadVarLong();
                Assert.AreEqual(expectedData.Length, dataLen, "Data len");
                Assert.AreEqual(expectedData, reader.Read(dataLen).ToArray(), "Data");
            }

            // test encoding complete blocks

            var       stream = new MemoryStream();
            LogWriter writer = new LogWriter(stream);

            writer.WriteData(result);
            Assert.Less(0, stream.Length);
            stream.Position = 0;

            // Roundtrip test by making sure i can read blocks I've encoded myself.

            LogReader logReader = new LogReader(stream);

            logReader.Open();

            MemCache memCache2 = new MemCache();

            memCache2.Load(logReader);

            var cache = memCache2._resultCache;

            Assert.AreEqual(3, cache.Count);

            int j = 0;

            foreach (var entry in cache)
            {
                var expectedKey  = operations[j].Key;
                var expectedData = operations[j].Value.Data;

                Assert.AreEqual(ResultState.Exist, entry.Value.ResultState, "Value exists");

                Assert.AreEqual(expectedKey.Length, entry.Key.Length, "Key len");
                Assert.AreEqual(expectedKey, entry.Key, "Key");

                Assert.AreEqual(expectedData.Length, entry.Value.Data.Length, "Data len");
                Assert.AreEqual(expectedData, entry.Value.Data, "Data");
                j++;
            }
        }
Exemplo n.º 23
0
 public override void Deserialize(AdhocFile parent, ref SpanReader sr)
 {
     offset = sr.Position;
     Value  = sr.ReadByte() != 0;
 }
Exemplo n.º 24
0
        public void LevelDbReadLogTest()
        {
            // https://github.com/google/leveldb/blob/master/doc/log_format.md

            DirectoryInfo directory = TestUtils.GetTestDirectory();

            LogReader logReader = new LogReader(new FileInfo(Path.Combine(directory.FullName, "000047.log")));

            BytewiseComparator comparator = new BytewiseComparator();

            bool found = false;

            while (true)
            {
                ReadOnlySpan <byte> data = logReader.ReadData();

                if (logReader.Eof)
                {
                    break;
                }

                var dataReader = new SpanReader(data);

                long sequenceNumber = dataReader.ReadInt64();
                long size           = dataReader.ReadInt32();

                while (!dataReader.Eof)
                {
                    byte recType = dataReader.ReadByte();

                    ulong v1         = dataReader.ReadVarLong();
                    var   currentKey = dataReader.Read(v1);

                    //CurrentKey = f5 ff ff ff eb ff ff ff 36

                    if (comparator.Compare(new byte[] { 0xf5, 0xff, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xff, 0x36 }, currentKey) == 0)
                    {
                        Assert.False(found);
                        found = true;
                    }

                    ulong v2 = 0;
                    ReadOnlySpan <byte> currentVal = ReadOnlySpan <byte> .Empty;
                    switch (recType)
                    {
                    case 1:                             // value
                    {
                        if (recType == 1)
                        {
                            v2         = dataReader.ReadVarLong();
                            currentVal = dataReader.Read(v2);
                        }
                        break;
                    }

                    case 0:                             // delete
                    {
                        //Assert.Fail("Unexpected delete key");
                        break;
                    }

                    default:
                        throw new Exception("Unknown record format");
                    }

                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"RecType={recType}, Sequence={sequenceNumber}, Size={size}, v1={v1}, v2={v2}\nCurrentKey={currentKey.HexDump(currentKey.Length, false, false)}\nCurrentVal=\n{currentVal.HexDump(cutAfterFive: true)} ");
                    }
                }
            }

            Assert.True(found);
        }