Diff & Patch

Tyranid supports a patch format that his used by historical data but is not limited to that use -- it can be used anytime you need a compact representation of the difference between two objects or arrays.

patch format

It is not normally necessary to understand the patch format, but in case you are doing advanced work with patches, the patch format is documented here. There are two different formats, one for objects and one for arrays:

object patch format

Object Format *Indicates that the property prop (or path) ...
{
prop: 0should be deleted
path: 1is an array and its length should be truncated by 1
prop: [ inline value ]should be replaced with the inline value
prop: [ 0, array patch ]is an array and should be patched
prop: [ 1, object patch ]is an object and should be patched
}
* props must be simple property names while paths can be either a simple property name or a path.

If there are no properties to patch (no differences), then the patch object will just be an empty object: {}.

array patch format

Array FormatIndicates that ...
{
index: sourceIndexthe value in the original array at sourceIndex should be copied to index.
index: [ value ]value should be copied to index index.
index: [ sourceOffset, runLength ]runLength values in the original array starting at index + sourceOffset should be copied into the new array starting at index.
n: valuenew array length should be value (array should be truncated)
}

examples

const { diffObj, diffArr, patchObj, patchArr } = Tyr.diff;

let patch = diffObj({ a: ['i','j'], b: 3 }, { a: ['j','i'] }) returns { a: [0, { 0: 1, 1: 0 }], b: 0 }
patchObj({ a: ['i','j'], b: 3 }, { a: [0, { 0: 1, 1: 0 }], b: 0 }) first object is modified in place to be { a: ['j','i'] }

patch = diffArr([2,3,4,5], [1,2,3,4,5]) returns { 0: [1], 1: [-1, 4] }
patchArr([2,3,4,5], patch) first array is modified in place to be [1,2,3,4,5]

patch = diffArr([1,2,3], [3,2,1]) returns { 0: 2, 2: 0 }
patchArr([1,2,3], patch) first array is modified in place to be [3,2,1]

functions

The functions below are available on the Tyr.diff namespace object.

diffArr(a: array, b: array): patch

Examines the differences between the arrays a and b and generates a patch that can be applied to a to get b.

diffObj(a: object, b: object, props: object?): patch

Examines the differences between the objects a and b and generates a patch that can be applied to a to get b.

The props object can be used to indicate that only the given properties should be differenced. For example:

Tyr.diff.diffObj({ a: 'i', b: 3 }, { a: 'i' }, { a: 1 })
// returns {} ... no differences because it's only looking at a and a didn't change.

If props is not given then the entire object is differenced.

diffPropsObj(a: object, b: object, props: object?): string[]

Returns a list of which properties are different between the two objects.

The props object can be used to indicate that only the given properties should be differenced. For example:

Tyr.diff.diffPropsObj({ a: 'i', b: 3 }, { a: 'i' }, { a: 1 })
// returns [] ... no differences because it's only looking at a and a didn't change.

If props is not given then the entire object is differenced.

patchArr(a: array, patch: patch): void

This applies the patch patch to the array a in place.

patchObj(a: object, patch: patch, props: object?): void

This applies the patch patch to the object a in place.

If the props object is present, it indicates that only changes for the listed properties should be applied (by default the entire patch is applied).