Open source! A powerful high-performance binary serializer bssom. Net

Time:2021-12-8

I haven’t updated my blog for a long time. I open source a high-performance binary serializer bssom. Net and a novel binary protocol bssom. Welcome to star and participate in the project!

Net open source technology exchange group 976304396, no water, only technology can be discussed. Welcome to discuss technical topics related to performance with me!
In addition, I tiktok applied for an account to record my daily life, and I want to know how I usually write code. Pay attention to me, ha ha!Tiktok: 198152455
Bssom. Net project address:https://github.com/1996v/Bssom.Net
Bssom protocol address:https://github.com/1996v/Bssom

A small, high performance, powerful serializer using bssom binary protocol

Nuget

Bssom.NetIs a useBssom structure protocolHigh performance structured binarySerializer, it has the following characteristics:,Compact, fast and functional.

  1. Compact, file onlyMore than 300 K
  2. Fast, it hasfirst-classSerialization and deserialization ofperformance
  3. Strong functionality:
    • You can get the size of the object after it is serializedNot completeserialized objects
    • You can read an element in an object andNot completeDeserialized object
    • You can change an element in an object withoutNot completeSerialization of
    • Serialized format hasSelf descriptive

Why?

At present c# there are many binary serializers, but these serializers only provide a single function of serialization and deserialization

Bssom. Net tookBssom protocol, so that the serialized data hasStructural characteristicsAnd has the function of directly grouping fields, which enables bssom. Net to do things that other serializers can’t do

  • When I want to know the size of the serialized object when serializing the object, so as to select the correct position where the object should be serialized in advance (such as the FSM algorithm of the database engine), bssom. Net can meet your needs
  • When I have a large binary data, but I only want to read one of the fields without contract to avoid complete deserialization overhead, bssom. Net can meet you
  • When I have a serialized packet, I just want to modify one of the fields without contract to avoid the cost of re serialization, then bssom. Net can meet you
  • When I want to keep the type information after the object is serialized without relying on entities, bssom. Net can satisfy you

What is the bssom protocol?

Bssom(binary search algorithm structure model object binary marshalling) is a protocol for structured grouping of objects using binary search algorithm model. The grouped data has special metadata information. According to these metadata information, only one element in the object can be read and changed efficiently, In this way, you can serialize and deserialize large objects without the complete serialization overhead caused by reading or writing only one field.

outline

1. Performance


Here are two excellent serializers with. Net platform(MessagePackandProtobuf-net)Benchmark for performance comparison

Columnar data represents the time spent performing the same task,Lower means faster performance, the polyline data represents the GC generated by performing the same task,The lower it is, the less garbage is generated during executionFrom the performance comparison results, we can see that the performance of bssom. Net is very excellent

Bssom. Net uses many technologies to improve performance

  • useMemory poolTechnology, the memory used for writing canmultiplexing
  • Using expressions and emitDynamic programmingTechnology, the type is specially treated, and the value type packing and unpacking are avoided
  • Use Generics Static cache, avoiding dictionary lookup overhead
  • Wrapped exception throwing code to increaseinlinePossibility of
  • More rightStrong typeCall instead of interface abstraction
  • PretreatmentThe metadata of MAP2 type does not need to be encoded again during serialization
  • When looking for the MAP2 key, advanceFixed local referenceInstead of standard function calls
  • When the MAP1 type is parsed, an 8-byte is automatically builtautomataJump search
  • It is worth mentioning that bssom. Net has no dependency for the purpose of reducing dependency and volumeSystem.Memory.dllTherefore, it cannot be usedSpan,MemoryAnd so on, which means that the implementation of bssom. Net will not be usedByReferenceDue to this JIT internal feature, the current reader / writer will not have the three performance optimization points of read / write localization, de virtualization and inline call (but even so, the current bssom. Net performance is still very excellent), which may be supported in the futureSpanBssom. Net will improve performance again through some additional performance skills

2. Reader / writer

Bssom. Net does not directly use native for read and write entriesByte[]Instead, a buffer interface is providedIBssomBufferAnd writer interfaceIBssomBufferWriter.
And nativebyte[]Different, the interface will be more flexible and easy to implementIBssomBufferAfter that, you can read data from any source to realizeIBssomBufferWriterThe data can be written anywhere (such as discontinuous fragments)

IBssomBuffer

IBssomBufferIs a buffer interface for serialization that provides read behavior

method describe
Position Current position in buffer
ReadRef Reads a reference to a sequence of the specified size from a location in the current buffer
Seek Sets the location of the current buffer
SeekWithOutVerify Sets the location of the current buffer and does not validate the boundary of position
TryReadFixedRef Try to read a reference of a byte sequence that can be fixed from the position in the current buffer. The reference position of the fixed byte will not be affected during the seek operation
UnFixed Used to cancel the reference fixed by tryreadfixedref. The call of this method is always symmetrical with tryreadfixedref

IBssomBufferWriter

IBssomBufferWriterIs a buffer based write interface that provides write behavior

method describe
Buffered The number of bytes written in the buffer
Advance Used to indicate the portion of the buffer that has been written
Position The current location of the writer
Seek Sets the location of the current writer
SeekWithOutVerify Sets the location of the current writer and does not validate the buffered boundary
GetRef Gets a reference to the byte sequence used for writing from the current location
CanGetSizeRefForProvidePerformanceInTryWrite In a field group, whether the current position can provide a byte sequence reference of a specified size to provide the performance of some types of internal writes
GetBssomBuffer Gets the buffer used by the current writer

Bssom. Net internalbyte[], StreamCarried outIBssomBufferandIBssomBufferWriterThe user does not need to manually encapsulate the interface

3. Formatter

formatBssom. Net is a process of converting. Net objects and bssom format to each other. Bssom. NetIBssomFormatterTo format the object

API describe
Size Gets the size of the serialized object
Serialize Serialize objects into bssom binary format
Deserialize Deserialize bssom binary format into an object

Bssom. Net has built in many formatters, such as. Net primitive types, key value pair types, iteratable types… They areBssom.Serializer.FormattersNamespace, you can find it and call it directly

If you don’t need to deal with a particular type, these formatters can basically cover most of your needs. How to find formatters is what the parser needs to do

4. Parser

analysisYes. Net type objectobtainTo the correspondingFormatterA process of. Bssom. NetIFormatterResolverTo realize the parsing of objects

API describe
GetFormatter Gets the formatter instance of the object

The parser usually has two functions: parsing type and saving formatter. The parser implemented in bssom. Net will internally find the formatter of. Net type, and then cache the found formatter through the static generic feature to complete theOne or a group. net typebindingTo the corresponding formatter

IFormatterResolverIt is the top entry for bssom.net to start serializing objects. They areBssom.Serializer.ResolversNamespace

name describe
PrimitiveResolver The parser providessbyte,Int16,Int32,Int64,byte,UInt16,UInt32,UInt64,Single,Double,bool,char,Guid,Decimal,string,DateTimeParser of type
AttributeFormatterResolver Gets and provides an instance of a user-defined formatter
BuildInResolver ProvidedStringBuilder,BitArray,DataTableAnd other types of parsers
BssomValueResolver ProvidedBssomValueType parser
IDictionaryResolver Get and generate withIDictionaryThe parser abstracts the behavior rules defined for key value pairs in BCL and generates dynamic parsing code for objects that meet the rules. Within the parser, it will be selected through runtime configuration optionsMap1orMap2Two formats of
ICollectionResolver Get and generate withIColloctionThe parser abstracts the behavior rules defined for the collector in BCL and generates dynamic parsing code for the objects that meet the rules. Within the parser, if the element type in the collection is primitive type, it will be parsed intoArray1Format, otherwise resolve toArray2format
MapCodeGenResolver Get and generate the parser for bssommap type encoding of the public fields and attributes of the object. If the object is an interface, the implementation of the interface will be automatically generated as the carrier of deserialization. Within the parser, the type will always be parsed asMap2Format and provideMap1andMap2Two formats of deserialization code
ObjectResolver ProvidedObjectType parser
CompositedResolver Composite parser, combinedObject,Primitive,Attribute,BssomValue,BuildIn,IDictionary,ICollection,MapCodeGenParser

becauseIDictionaryResolverandICollectionResolverWith sufficiently abstract rules defined in bssom. Net, bssom. Net does not need to provide new rules that may appear in. Net in the futureIDictionaryorIColloctionWrite specific parsing code for implementation

In bssom. Net, you canBssomSerializerOptionsMediumFormatterResolverProperty to inject the parser required for serialization. The default isCompositedResolver, CompositedResolverThe types will be sorted fromObject,Primitive,Attribute,BssomValue,BuildIn,IDictionary,ICollection,MapCodeGenSearch in the parser until the corresponding parser is found

5. Expansion

Let’s take a look at the process of bssom. Net serialization:

input T -> Call serialize(T) -> Find BssomResolver -> Provide type formatter -> formatter.Serialize(T);

Throughout the serialization process, each step istransparentThis means that if users are not satisfied with the parser or formatter defined in bssom. Net, they can extend it themselves

Users can implement it by themselvesIFormatterResolverandIBssomFormattercomeOverride default parser, inBssom.Serializer.Binary.BssomBinaryPrimitives(this class will be refactored in the upcoming minor version) and the public API exposed by the reader / writer itself provide low-level write and read implementation of bssom format

Simple examples can be referred toMore possible introduction

6. Advanced API

BssomSerializer

BssomSerializerIt is the top-level API of bssom. InBssom.SerializerNamespace is the entry for bssom to start workingStatic methodConstitutes the of bssom. NetMain API.

API describe heavy load
Size Get the binary data size of the serialized object without serialization (t, option),(ref context, t)
Serialize Serializes the given value to bssom binary (byte[], t, option), (stream, t, option), (IBssomBufWriter, t, option), (ref context, t)
Deserialize Deserialize bssom binary data into. Net objects (byte[], option),(stream, option),(IBssomBuf, option),(ref context)
SerializeAsync The given value for asynchronous serialization is bssom binary ditto
DeserializeAsync Asynchronously deserialize bssom binary data into. Net objects ditto

BssomSerializerOptions

BssomSerializerAs the top-level API, when we call it, we need to pass an nullableBssomSerializerOptionsOption parameter of type
BssomSerializerOptionsThis is the configuration that bssom needs to use during the whole serialization process. The default isBssomSerializerOptions.Default.

  • FormatterResolver: in option, you canFormatterResolverRegister parser, if there is no manual registration, the default is usedCompositedResolver, bssom will always passFormatterResolverTo resolve the type
  • Security: This is used during serializationsecurityRelated options. Currently, only depth verification during deserialization is provided. The default value isNo restrictions
  • IsPriorityToDeserializeObjectAsBssomValue: this option determines whether to convert object type to bssomvalue type during deserialization. If yesfalse, the default deserialization is the native typefalse.
  • IsUseStandardDateTimeBssom. Net pair:DateTimeType implements the standardBssom protocol UNIX formatandNative format of. Net platform, the local format has fewer bytes, but does not have interaction with other platforms. The default isfalse.
  • IDictionaryIsSerializeMap1TypeWith this option, theIDictionaryWhich format is used by default for serialization of the type of behavior? If yestrueThen useMap1Format, otherwiseMap2Format. Default totrue

BssomSerializeContext

BssomSerializeContextProvides context information used during serialization, which also includesBssomSerializerOptions

  • BssomSerializerOptions: used during serializationconfiguration information
  • ContextDataSlots: provides a data slot for users to store and read by themselves during serializationstorage medium
  • CancellationToken: a tag that the serialization operation cancels. The user can:Midway cancellationSerialization operation in progress

7. Field grouping

Bssom. Net has read fields insteadNo full deserializationAnd change values without full serialization becauseBssom protocolIt has good structural features. In the implementation of bssom. Net, such functions are exposed inBssomFieldMarshallerYes

BssomFieldMarshaller

BssomFieldMarshallerProvides a set of APIs for serializing the serialized dataLower granularityControl of

API describe
IndexOf Obtain the position of the specified object in bssom binary through special input format and return offset information
ReadValue Reads the entire element with the specified offset information
ReadValueType Only the element type is read through the specified offset information
ReadValueTypeCode Only the binary code of the element type is read through the specified offset information
ReadValueSize Gets the size of the element stored in the bssom binary through the specified offset information
ReadArrayCountByMapType Reads the number of elements of bssomarray through the specified offset information
ReadAllKeysByMapType Read the metadata in bssommap (including the offset of key and value) through the specified offset information
TryWrite Re write the value in bssom binary through the specified offset information. If the width of the written value is greater than the width of the written slot, it will fail

Each method providesbyte[]andIBssomBufOverload of

Simple field access language

Bssom. Net isIndexOfA simple field access language is defined. The language defines two access forms, one is accessMapType (the key of this map type must beStringType), one is accessArrayType. The two access forms can be combined freely

  • [key]: passed by the representativeKeyTo visitMapValue of type, enteredKeyOnly expressStringtype
  • $Index: represents access by subscriptArrayThe input index can only be of integer type

It is assumed that the following data are available

{
   "Postcodes" : {   
		  "WuHan" : [430070,430071,430072,430073],
		  "XiangYang" : [441000,441001,441002]
		},
   "Province" : "HuBei"
}

You can access elements in the following ways:ExampleFor more details

[Postcodes][WuHan]$1  => 4330071
[Province]  => "HuBei"

Custom field access form interface

Bssom. Net isIndexOfProvidedIIndexOfInputSourceInterface is used to receive custom field access sources. After using this interface, the key of map type will not be restricted, and the key can be any input type

IndexOfObjectsInputSourceIt is provided by bssom. Net for usersIIndexOfInputSourceInterfacedGeneral implementationIt receives a set of iteratable objects. When indexof is called, the objects will be iterated in turn

It is assumed that the following data are available

{
   2018-01-01 : {
         0 : ["Rain1","Rain2","Rain3"],
         4 : ["Rain4","Fair5","Fair6"]   
    }
}

You can access elements in the following ways:ExampleFor more details

new IndexOfObjectsInputSource(new Entry[]{ 
     new Entry(DateTime.Parse("2018-01-01"),ValueIsMapKey: true),
     new Entry(3,ValueIsMapKey: true),
     new Entry(1,ValueIsMapKey: false),
  })

output => "Fair5"

8. Dynamic code generation

Bssom. Net pairIDictionaryResolver, ICollectionResolver, MapCodeGenResolver, ObjectResolverDynamic code generation technology is usedExpression tree and emitCo generation of runtime code is not supported if the application is a pure AOT environment

stayMapCodeGenResolverMiddle pairMap1The type deserialization uses the automata lookup mode of the class prefix tree in the unit of 8 bytes (64 bit word length), which is a very effective and fast way. It avoids the overhead of complete hash operation and character comparison of stringsMapCodeGenResolver.Save()Method, you will see the automatically generated code

MapCodeGenResolverMiddle pairMap2Type deserialization uses the built-inBssom protocolMap format lookup code, which is written in state machine mode and is divided into fast and low-speed versions, depending onReader Can you provideTryReadFixedRef.

In addition, forSizeThe processing of mapcodegenresolver is also very fast, because it has calculated the size of metadata in advance and inline the fixed size of primitive field itself

9. Characteristics

Bssom. Net currently has five features

  • AliasAttribute: alias property, used to modify the field name of map format object field saved in binary
  • BssomFormatterAttribute: custom formatting property. When a field property or type is marked by this property, the formatting of this type will use the formatter specified by this property
  • IgnoreKeyAttribute: ignore a key. The marked field will be ignored during serialization. It is applicable to map format
  • OnlyIncludeAttribute: contains only one key, which is only included in serialization. It is applicable to map formatIgnoreKeyAttributeOn the contrary, the priority is higher
  • SerializationConstructorAttribute: specifies a constructor for deserialization of a type

10. More possibilities

You can write it yourselfParser, writeFormatter, you can also define your own features or encapsulate features for serializationOptionAnd bssom. Net also provides contextData slotThis can make serialization behavior diverse

If you can provide useful or high-performance services for bssom. NetExpansion pack, then please tell me

The following example writes a parser based on string type, which improves the serialization performance of string type by interacting with the context

public sealed class MyStringFormatterResolver : IFormatterResolver
{
    public static MyStringFormatterResolver Instance = new MyStringFormatterResolver();

    public IBssomFormatter GetFormatter()
    {
        return FormatterCache.Formatter;
    }

    private static class FormatterCache
    {
        public static readonly IBssomFormatter Formatter;

        static FormatterCache()
        {
            if (typeof(T) == typeof(string))
                Formatter = (IBssomFormatter)(object)MyStringFormatter.Instance;
        }
    }
}
public sealed class MyStringFormatter : IBssomFormatter
{
    public static MyStringFormatter Instance = new MyStringFormatter();

    public string Deserialize(ref BssomReader reader, ref BssomDeserializeContext context)
    {
        if (reader.TryReadNull())
        {
            return null;
        }

        reader.EnsureType(BssomType.StringCode);
        int dataLen = reader.ReadVariableNumber();
        ref byte refb = ref reader.BssomBuffer.ReadRef((int)dataLen);
        fixed (byte* pRefb = &refb)
        {
            return new string((sbyte*)pRefb, 0, (int)dataLen, UTF8Encoding.UTF8);
        }
    }

    public void Serialize(ref BssomWriter writer, ref BssomSerializeContext context, string value)
    {
        if (value == null)
        {
            writer.WriteNull();
            return;
        }

        int valueUtf8Size = context.ContextDataSlots.PopMyStringSize();

        writer.WriteBuildInType(BssomType.StringCode);
        writer.WriteVariableNumber(valueUtf8Size);

        ref byte refb = ref writer.BufferWriter.GetRef(valueUtf8Size);
        fixed (char* pValue = value)
        fixed (byte* pRefb = &refb)
        {
            UTF8Encoding.UTF8.GetBytes(pValue, value.Length, pRefb, valueUtf8Size);
        }
        writer.BufferWriter.Advance(valueUtf8Size);
    }

    public int Size(ref BssomSizeContext context, string value)
    {
        if (value == null)
            return BssomBinaryPrimitives.NullSize;

        int dataSize = UTF8Encoding.UTF8.GetByteCount(value);
        context.ContextDataSlots.PushMyStringSize(dataSize);
        return BssomBinaryPrimitives.BuildInTypeCodeSize + dataSize;
    }
}
public void MyTest()
{
     var option = BssomSerializerOptions.Default.WithFormatterResolver(MyStringFormatterResolver.Instance);
     string str = RandomHelper.RandomValue();
     BssomSizeContext sizeContext = new BssomSizeContext(option);
     int len = BssomSerializer.Size(ref sizeContext, str);
     if (len > 1000)
         throw new Exception("Size of value storage binary exceeded");

     BssomSerializeContext serContext = new BssomSerializeContext(option);
     sizeContext.ContextDataSlots.SetMyStringStack(serContext.ContextDataSlots);
     var bytes = BssomSerializer.Serialize(ref serContext, str);
     var deStr = BssomSerializer.Deserialize(bytes);

     Assert.Equal(str,deStr);
}

The above code separately defines a new parser and a new formatter for string. The formatter can store the utf8 size calculated for string in the size method in the context, so that there is no need to repeat the utf8 size calculation for string during serialization

11. How to use

Bssom. Net is non – contractual and out of the box. Here are some sample code

Size

BssomSerializer.SizeMethod is used to obtain the binary data size after the object is serialized. It is a high-performance internal implementation with almost no overhead

//Gets the size of the serialized value
object value = RandomHelper.RandomValue();
int size = BssomSerializer.Size(value, option: BssomSerializerOptions.Default);
//Use context to get the size of the serialized value
BssomSizeContext context = new BssomSizeContext(BssomSerializerOptions.Default);
object value = RandomHelper.RandomValue();
int size = BssomSerializer.Size(ref context, value);

Serialize

BssomSerializer.SerializeMethod is used to serialize the given value into bssom binary. It is a high-performance internal implementation. The following are some common methods. Each method has an overload of canceltoken

//Serializing the object directly will return a serialized byte array
object value = RandomHelper.RandomValue();
byte[] binary = BssomSerializer.Serialize(value, option: BssomSerializerOptions.Default);
//Serialize the object into the specified byte array. If the capacity is insufficient, it will be automatically expanded, and finally return the number of serialized bytes
object value = RandomHelper.RandomValue();
byte[] buf = local();
int serializeSize = BssomSerializer.Serialize(ref buf, 0, value, option: BssomSerializerOptions.Default);
//Serialize the object into a custom writer
object value = RandomHelper.RandomValue();
IBssomBufferWriter writer = new Impl();
BssomSerializer.Serialize(value, writer, option: BssomSerializerOptions.Default);
//Serialization using serialization context
object value = RandomHelper.RandomValue();
BssomSerializeContext context = new BssomSerializeContext(BssomSerializerOptions.Default);
byte[] binary = BssomSerializer.Serialize(ref context, value);
//Serialize an object into a stream
object value = RandomHelper.RandomValue();
Stream stream = new MemoryStream();
BssomSerializer.Serialize(stream, value, option: BssomSerializerOptions.Default);
//Serializing objects into streams asynchronously
object value = RandomHelper.RandomValue();
Stream stream = new MemoryStream();
await BssomSerializer.SerializeAsync(stream, value, option: BssomSerializerOptions.Default);

Deserialize

BssomSerializer.DeserializeMethod is used to deserialize a given bssom buffer into an object. It is a high-performance internal implementation. The following are some common methods. Each method has an overload of canceltoken

//Deserializes an object from the given byte array
byte[] buf = remote();
T value = BssomSerializer.Deserialize(buf, 0, out int readSize, option: BssomSerializerOptions.Default);
//Deserialize the object from the given buffer
IBssomBuffer buffer = remote();
object value = BssomSerializer.Deserialize(buffer, option: BssomSerializerOptions.Default);
//Deserialize the object from the given buffer using the context
BssomDeserializeContext context = new BssomDeserializeContext(BssomSerializerOptions.Default);
IBssomBuffer buffer = remote();
object value = BssomSerializer.Deserialize(ref context, buffer);
//Deserialize object from stream
Stream stream = remote();
object value = BssomSerializer.Deserialize(stream, option: BssomSerializerOptions.Default);
//Deserialize objects asynchronously from the stream
Stream stream = remote();
object value = await BssomSerializer.DeserializeAsync(stream, option: BssomSerializerOptions.Default);
//Pass a type to deserialize the object from the stream to the specified type
Stream stream = remote();
Type type = typeof(class);
object value = BssomSerializer.Deserialize(stream, type, option: BssomSerializerOptions.Default);
//Pass a type and asynchronously deserialize the object from the stream to the specified type
Stream stream = remote();
Type type = typeof(class);
object value = await BssomSerializer.DeserializeAsync(stream, type, option: BssomSerializerOptions.Default);

ReadValue

BssomFieldMarshaller.ReadValueMethod is used to read only a certain value in binary data. This method is very useful if you only want to read a certain value in the object without fully deserializing it

//Access the language through the embedded simple field to obtain the value corresponding to a key in dict
var val = new Dictionary() {
            { "A",(int)3},
            { "B",(DateTime)DateTime.MaxValue},
        };
var buf = BssomSerializer.Serialize(val);
var bsfm = new BssomFieldMarshaller(buf);
BssomFieldOffsetInfo fieldOffInfo = bsfm.IndexOf("[A]")
bsfm.ReadValue(fieldOffInfo).Is(3);
//Access the language through the embedded simple field to obtain the value of an attribute in the class
var val = new MyClass() {
            Name = "bssom",
            Nature = "Binary"
        };
var buf = BssomSerializer.Serialize(val);
var bsfm = new BssomFieldMarshaller(buf);
BssomFieldOffsetInfo fieldOffInfo = bsfm.IndexOf("[Name]")
bsfm.ReadValue(fieldOffInfo).Is("bssom");
//Get the value of an attribute in the array through the embedded simple field access language
var val = new object[] { (int)1,(double)2.2 }
var buf = BssomSerializer.Serialize(val);
var bsfm = new BssomFieldMarshaller(buf);
BssomFieldOffsetInfo fieldOffInfo = bsfm.IndexOf("$1")
bsfm.ReadValue(fieldOffInfo).Is((double)2.2);
//Access the language through embedded simple fields, and combine to obtain an object
var val = new MyClass() {
            Name = "bssom",
            Nature = "Binary",
            Data = new int[] { 3, 2, 1} 
        };
var buf = BssomSerializer.Serialize(val);
var bsfm = new BssomFieldMarshaller(buf);
BssomFieldOffsetInfo fieldOffInfo = bsfm.IndexOf("[Data]$1")
bsfm.ReadValue(fieldOffInfo).Is(2);
//Get an object through a combination of custom field access forms
var val = new Dictionary() {
            { DateTime.Parse("2018-01-01"), new object[]{'A','B'} },
            { "Charec",(DateTime)DateTime.MaxValue},
        };
var buf = BssomSerializer.Serialize(val);
var bsfm = new BssomFieldMarshaller(buf);
IIndexOfInputSource input = new IndexOfObjectsInputSource(new Entry[]{ 
     new Entry(DateTime.Parse("2018-01-01"),ValueIsMapKey: true),
     new Entry(1,ValueIsMapKey: false),
  })
BssomFieldOffsetInfo fieldOffInfo = bsfm.IndexOf(input)
bsfm.ReadValue(fieldOffInfo).Is('B');

ReadAllMapKeys

BssomFieldMarshaller.ReadAllMapKeysMethod is used to read all keys and value offsets in map format from binary data. This method is very useful if you want to know the key value in the binary data, but do not want to read it completely

var val = new Dictionary(){
           { "Id" , 1 },
           { "Path" , "../t.jpg" },
           { "Data" , new byte[3000] }
};
var buf = BssomSerializer.Serialize(val);
var bsfm = new BssomFieldMarshaller(buf);
bsfm.ReadAllMapKeys(BssomFieldOffsetInfo.Zero).Print();
//output
//  line 1: BssomString::"Id", BssomFieldOffsetInfo
//  line 2: BssomString::"Path", BssomFieldOffsetInfo
//  line 3: BssomString::"Data", BssomFieldOffsetInfo

TryWriteValue

BssomFieldMarshaller.TryWriteValueMethod is used to modify the value of binary data. This method is very useful when you only want to modify a value in the object without re serializing the whole object

//Modify string object
var val = "abcd";
var buf = BssomSerializer.Serialize(val);
var bsfm = new BssomFieldMarshaller(buf);
bsfm.TryWrite(BssomFieldOffsetInfo.Zero, "abc");
string upVal = BssomSerializer.Deserialize(buf);
upVal.Is("abc");
//Modify a key in an iDict object
var val = new Dictionary(){
           { "Id" , 1 },
           { "Path" , "../t.jpg" },
           { "Data" , new byte[3000] }
};
var buf = BssomSerializer.Serialize(val);
var bsfm = new BssomFieldMarshaller(buf);

bsfm.TryWrite(bsfm.IndexOf("[Id]"), 3);
var upVal = BssomSerializer.Deserialize>(buf);
upVal["Id"].Is(3);
//Modify a key in an iDict object
var val = new MyClass() {
            Name = "bssom",
            Nature = "Binary",
            Data = new int[] { 3, 2, 1} 
        };
var buf = BssomSerializer.Serialize(val);
var bsfm = new BssomFieldMarshaller(buf);

bsfm.TryWrite(bsfm.IndexOf("[Name]"), "zz");
var upVal = BssomSerializer.Deserialize(buf);
upVal["Name"].Is("zz");
//Modify an element in the array object
var val = new object[] { "abc" , 37 };
var buf = BssomSerializer.Serialize(val);
var bsfm = new BssomFieldMarshaller(buf);

bsfm.TryWrite(bsfm.IndexOf("$1"), 40);
var upVal = BssomSerializer.Deserialize(buf);
((int)upVal[1]).Is(40);
//Combine to modify an element in an object
var val = new object[] { 
        22, 
        37, 
        new MyClass() {
            Name = "bssom",
            Nature = "Binary",
            Data = new int[] { 3, 2, 1} 
        }
 };
var buf = BssomSerializer.Serialize(val);
var bsfm = new BssomFieldMarshaller(buf);

bsfm.TryWrite(bsfm.IndexOf("$2[Name]"), "zz");
var upVal = BssomSerializer.Deserialize(buf);
((MyClass)upVal[1]).Name.Is("zz");

How to use properties

How to define extensions

12. How to participate in project contribution

If you want to participate in the development of this project, I will be very honored and happy. Welcome fork or pull request, or join QQ group 976304396 to discuss open source technology

Click to join group chat. net open source technology exchange groupNo water, only technology

13. Who is using it

  • Bssomdb (to be open source)A pure c# embedded transactional document database using bssom protocol

14. Others

I like to make friends with people like me. I am not affected by the environment. I am my own teacher. Welcome to add group net open source technology exchange group 976304396 to discuss performance related topics with me!
Want to know how I write code everyday? Welcome tiktok account: 198152455.

Author: Xiao Zeng
source:https://www.cnblogs.com/1996V/p/13884968.htmlWelcome to reprint, but please keep the above complete article and display the signature and original link in a prominent place.
Net open source technology exchange group 976304396, tiktok account: 198152455