An extensible system for specifying diff/patch based replication schemas. In
mudb schemas are used to define RPC and message interfaces as well as define state layouts. Schemas allow for run time reflection on type information, and are necessary to support serialization and memory management.
Here is a somewhat contrived example showing how all of the methods of the schemas work.
constMuStructMuStringMuFloat64MuInt32MuDictionary} =// Define an entity schemaconst EntitySchema =x:y:dx:dy:hp: 10name: 'entity'const EntitySet = EntitySchema// create a new entity set object using the schemaconst entities = EntitySet// create a new entity and add it to the schemaconst player = EntitySchemaplayerx = 10playery = 10playerdx = -10playerdy = -20playername = 'player'entities'foo' = player// now make a copy of all entitiesconst otherEntities = EntitySet// modify player entityotherEntitiesfoohp = 1// compute a patchconst patch = EntitySet// apply a patch to a set of entitiesconst entityCopy = EntitySet// release memoryEntitySet
table of contents
- 1 install
- 2 api
- 3 more examples
npm i muschema
muschema is an object which implements the following interface.
identityThe default value of an object in the schema.
muTypeA string encoding some runtime information about the schema.
muData(optional) Additional runtime information about the schema. May include subtype schemas, etc.
alloc()Creates a new value from scratch
free(value)Returns a value to the internal memory pool.
clone(value)Makes a copy of a value.
diff(base, target)Computes a patch from
basereturning a new value
patch obey the following semantics:
const delta =const result =// now: result === target
To serialize an arbitrary object without a base, use the identity element. For example:
const serialized = schema
Schemas can be composed recursively by calling submethods.
muschema provides several common schemas for primitive types and some functions for combining them together into structs, tuples and other common data structures. If necessary user defined applications can specify custom serialization and diffing/patching methods for various common types.
a note for typescript
For typescript users, a generic interface for schemas can be found in the
muschema/schema module. It exports the interface
MuSchema<ValueType> which any
muschema should implement.
Out of the box
An empty value type. Useful for specifying arguments to messages which do not need to be serialized.
const MuVoid =
false boolean value
const MuBoolean =
muschema supports binary serialization
// Signed integers 8, 16 and 32-bitconst MuInt8 =const MuInt16 =const MuInt32 =// Unsigned integersconst MuUint8 =const MuUint16 =const MuUint32 =// Floating pointconst MuFloat32 =const MuFloat64 =
For generic numbers, use
MuFloat64. If you know the size of your number in advance, then use a more specific datatype.
String data type
const MuString =
Primitive data types in
muschema can be composed using functors. These take in multiple sub-schemas and construct new schemas.
A struct is a collection of multiple subtypes. Structs are constructed by passing in a dictionary of schemas. Struct schemas may be nested as follows:
const MuFloat64 =const MuStruct =const Vec2 =x: 0y: 0const Particle =position: Vec2velocity: Vec2// example usage:const p = Particleppositionx = 10ppositiony = 10// Particle.free recursively calls Vec2.freeParticle
A discriminated union of several subtypes. Each subtype must be given a label.
const MuFloat64 =const MuString =const MuUnion =const FloatOrString =float: 'foo'string: 'bar';// create a new valueconst x = FloatOrString;xtype = 'float';xdata = 1// compute a deltaconst p = FloatOrString;// apply a patchconst y = FloatOrString;
A dictionary is a labelled collection of values.
const MuUint32 =const MuDictionary =const NumberDictionary = 0// create a dictionaryconst dict = NumberDictionarydict'foo' = 3
mudb for some examples of using
- binary serialization
- automated testing
- diff speed benchmark
- patch speed benchmark
- patch size benchmark
- memory pool stats
- fixed point numbers
- fixed size vectors
- variable length arrays
- multidimensional arrays
- should models define constructors?
- should pool allocation be optional?
- some types don't need a pool
- pooled allocation can be cumbersome
- do we need JSON and RPC serialization for debugging?
Development supported by Shenzhen DianMao Digital Technology Co., Ltd.
Written in Shenzhen, China.
(c) 2017 Mikola Lysenko, Shenzhen DianMao Digital Technology Co., Ltd.