internal ReadOnlySpan <byte> EncodeBatch(KeyValuePair <byte[], ResultCacheEntry>[] operations) { if (operations.Length == 0) { throw new ArgumentException("Zero size batch", nameof(operations)); } long maxSize = 0; maxSize += 8; // sequence maxSize += 4 * operations.Length; // count foreach (KeyValuePair <byte[], ResultCacheEntry> entry in operations) { maxSize += 1; // op code maxSize += 10; // varint max maxSize += entry.Key.Length; if (entry.Value.ResultState == ResultState.Exist) { maxSize += 10; // varint max maxSize += entry.Value.Data?.Length ?? 0; } } Span <byte> data = new byte[maxSize]; // big enough to contain all data regardless of size var writer = new SpanWriter(data); // write sequence writer.Write((ulong)operations.First().Value.Sequence); // write operations count writer.Write((uint)operations.Length); foreach (KeyValuePair <byte[], ResultCacheEntry> operation in operations) { byte[] key = operation.Key; ResultCacheEntry entry = operation.Value; // write op type (byte) writer.Write(entry.ResultState == ResultState.Exist ? (byte)OperationType.Value : (byte)OperationType.Delete); // write key writer.WriteLengthPrefixed(key); if (entry.ResultState == ResultState.Exist) { // write data writer.WriteLengthPrefixed(entry.Data); } } return(data.Slice(0, writer.Position)); }
public static Span <byte> EncodeVersion(Version version) { var array = new byte[4096]; var buffer = new Span <byte>(array); var writer = new SpanWriter(buffer); // case Manifest.LogTagType.Comparator: if (!string.IsNullOrEmpty(version.Comparator)) { writer.WriteVarLong((ulong)LogTagType.Comparator); writer.Write(version.Comparator); } // case Manifest.LogTagType.LogNumber: { writer.WriteVarLong((ulong)LogTagType.LogNumber); writer.WriteVarLong((ulong)version.LogNumber); } // case Manifest.LogTagType.PrevLogNumber: { writer.WriteVarLong((ulong)LogTagType.PrevLogNumber); writer.WriteVarLong((ulong)version.PreviousLogNumber); } // case Manifest.LogTagType.NextFileNumber: { writer.WriteVarLong((ulong)LogTagType.NextFileNumber); writer.WriteVarLong((ulong)version.NextFileNumber); } // case Manifest.LogTagType.LastSequence: { writer.WriteVarLong((ulong)LogTagType.LastSequence); writer.WriteVarLong((ulong)version.LastSequenceNumber); } // case Manifest.LogTagType.CompactPointer: if (version.CompactPointers.Count > 0) { foreach (KeyValuePair <int, byte[]> pointer in version.CompactPointers) { writer.WriteVarLong((ulong)LogTagType.CompactPointer); writer.WriteVarLong((ulong)pointer.Key); writer.WriteLengthPrefixed(pointer.Value); } } // case Manifest.LogTagType.DeletedFile: //if (version.DeletedFiles.Count > 0) //{ // foreach (KeyValuePair<int, List<ulong>> files in version.DeletedFiles) // { // foreach (ulong fileNumber in files.Value) // { // writer.WriteVarLong((ulong) LogTagType.DeletedFile); // writer.WriteVarLong((ulong) files.Key); // writer.WriteVarLong(fileNumber); // } // } //} // case Manifest.LogTagType.NewFile: if (version.Levels.Count > 0) { foreach (KeyValuePair <int, List <FileMetadata> > files in version.Levels) { int level = files.Key; foreach (FileMetadata fileMeta in files.Value) { writer.WriteVarLong((ulong)LogTagType.NewFile); //int level = (int) reader.ReadVarLong(); writer.WriteVarLong((ulong)level); //ulong fileNumber = reader.ReadVarLong(); writer.WriteVarLong((ulong)fileMeta.FileNumber); //ulong fileSize = reader.ReadVarLong(); writer.WriteVarLong((ulong)fileMeta.FileSize); //var smallest = reader.ReadLengthPrefixedBytes(); writer.WriteLengthPrefixed(fileMeta.SmallestKey); //var largest = reader.ReadLengthPrefixedBytes(); writer.WriteLengthPrefixed(fileMeta.LargestKey); } } } int length = writer.Position; return(buffer.Slice(0, length).ToArray()); }