Skip to content

Commit

Permalink
refactor applyFilters() for simplicity. #75 #66 #61
Browse files Browse the repository at this point in the history
  • Loading branch information
endel committed Jun 8, 2020
1 parent 827ebbb commit 7f56394
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 75 deletions.
104 changes: 42 additions & 62 deletions src/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,28 +187,20 @@ export abstract class Schema {
if (byte === SWITCH_TO_STRUCTURE) {
const refId = decode.number(bytes, it);

console.log("SWITCH_TO_STRUCTURE", { refId });

if (!$root.refs.has(refId)) {
console.log("refId", refId, "does not exist.");
$root.refs.set(refId, this);
ref = this;

} else {
console.log("refId", refId, "exists!");
ref = $root.refs.get(refId) as Schema;
}

continue;
}

console.log({ byte, ref });

const operation = byte;
const fieldIndex = decode.number(bytes, it);

console.log({ fieldIndex, operation: OPERATION[operation] });

const field = (ref['_fieldsByIndex'] && ref['_fieldsByIndex'][fieldIndex]) || fieldIndex;
const _field = `_${field}`;

Expand All @@ -226,8 +218,6 @@ export abstract class Schema {
ref['setIndex'](field, dynamicIndex as string);
}

console.log("WILL DECODE FIELD:", { field });

if (field === undefined) {
continue;

Expand All @@ -241,7 +231,6 @@ export abstract class Schema {

} else if (Schema.is(type)) {
const refId = decode.number(bytes, it);
console.log("decode =>", { refId, offset: it.offset });

if (operation === OPERATION.ADD) {
value = this.createTypeInstance(bytes, it, type as typeof Schema);
Expand Down Expand Up @@ -380,8 +369,6 @@ export abstract class Schema {
});
}

console.log("SET", field, "TO", value);

if (ref instanceof Schema) {
ref[_field] = value;

Expand Down Expand Up @@ -438,14 +425,10 @@ export abstract class Schema {
const _field = `_${field}`;

const type = changeTree.childType || ref._schema[field];
console.log("FIELD TYPE:", {field, type});
console.log("changeTree.childType =>", changeTree.childType);

// const type = changeTree.getType(fieldIndex);
const value = changeTree.getValue(fieldIndex);

console.log({ field, type, value, operation });

// cache begin index if `useFilters`
const beginIndex = bytes.length;

Expand Down Expand Up @@ -577,62 +560,59 @@ export abstract class Schema {
return this.encode(this, true, bytes);
}

applyFilters(encodedBytes: number[], client: Client, root = this, childFilter?: FilterCallback) {
applyFilters(encodedBytes: number[], client: Client, root = this) {
let filteredBytes: number[] = [];

const enqueuedRefs: ({ ref: Ref, childFilter?: FilterCallback })[] = [];
const filters = this._filters;
console.log("applyFilters(), CHANGES => ", this.$changes.changes);

encode.uint8(filteredBytes, SWITCH_TO_STRUCTURE);
encode.number(filteredBytes, this.$changes.refId);
const changeTrees = Array.from(this.$changes.root.changes);

this.$changes.changes.forEach((change, fieldIndex) => {
const cache = this.$changes.caches[fieldIndex];
const value = this.$changes.getValue(fieldIndex);
for (let i = 0, l = changeTrees.length; i < l; i++) {
const changeTree = changeTrees[i];
const ref = changeTree.ref as Schema;
const filters = ref._filters;

if (childFilter) {
const ref = this as any as MapSchema;
const parent = ref['$changes'].parent.ref;
encode.uint8(filteredBytes, SWITCH_TO_STRUCTURE);
encode.number(filteredBytes, ref.$changes.refId);

if (!childFilter.call(parent, client, ref['$indexes'].get(fieldIndex), value, root)) {
console.log("SKIPPING", fieldIndex)
return;
}
changeTree.changes.forEach((change, fieldIndex) => {
const cache = ref.$changes.caches[fieldIndex];
const value = ref.$changes.getValue(fieldIndex);

} else {
const filter = (filters && filters[fieldIndex]);
console.log("HAS FILTER?", filter);
if (filter && !filter.call(this, client, value, root)) {
console.log("SKIPPING", fieldIndex)
return;
}
}
if (
ref instanceof MapSchema ||
ref instanceof ArraySchema
) {
const parent = ref['$changes'].parent.ref as Schema;
// parent._childFilters[]

if (change.op === OPERATION.DELETE) {
encode.uint8(filteredBytes, change.op);
encode.number(filteredBytes, fieldIndex);
return;
// TODO: get filter from previous structure
const filter = undefined;

} else {
filteredBytes = [...filteredBytes, ...encodedBytes.slice(cache.beginIndex, cache.endIndex)];
}
if (filter && !filter.call(parent, client, ref['$indexes'].get(fieldIndex), value, root)) {
console.log("SKIPPING", fieldIndex)
return;
}

//
// value is a Ref (Schema, MapSchema, etc)
// enqueue it for applying filters too.
//
if (value['$changes'] !== undefined) {
enqueuedRefs.push({ ref: value, childFilter: this._childFilters[fieldIndex] });
}
});
} else {
const filter = (filters && filters[fieldIndex]);

if (filter && !filter.call(this, client, value, root)) {
console.log("SKIPPING", fieldIndex)
return;
}
}

if (change.op === OPERATION.DELETE) {
encode.uint8(filteredBytes, change.op);
encode.number(filteredBytes, fieldIndex);
return;

console.log("Enqueued structures =>", enqueuedRefs);
enqueuedRefs.forEach((ref) => {
filteredBytes = [
...filteredBytes,
...Schema.prototype.applyFilters.call(ref.ref, encodedBytes, client, root, ref.childFilter)
];
})
} else {
filteredBytes = [...filteredBytes, ...encodedBytes.slice(cache.beginIndex, cache.endIndex)];
}
});
}

return filteredBytes;
}
Expand Down
7 changes: 2 additions & 5 deletions src/annotations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ export class SchemaDefinition {
fieldsByIndex: { [index: number]: string };

filters: { [field: string]: FilterCallback };
// childFilters are used on Map/Array/Set items.
childFilters: { [field: string]: FilterCallback };
childFilters: { [field: string]: FilterCallback }; // childFilters are used on Map, Array, Set items.

deprecated: { [field: string]: boolean };
descriptors: PropertyDescriptorMap & ThisType<any>;
Expand Down Expand Up @@ -87,9 +86,7 @@ export class SchemaDefinition {
ArraySchema.is(type) ||
MapSchema.is(type)
) {
if (!this.childFilters) {
this.childFilters = {};
}
if (!this.childFilters) { this.childFilters = {}; }

this.childFilters[index] = cb;

Expand Down
8 changes: 0 additions & 8 deletions src/changes/ChangeTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ export interface FieldCache {

export class ChangeTree {
refId: number;

dynamicIndexes: boolean; // FIXME: maybe this is not necessary.
childType: PrimitiveType;

changes = new Map<number, ChangeOperation>();
Expand All @@ -37,12 +35,6 @@ export class ChangeTree {
protected _root?: Root,
) {
this.setParent(parent, _root || new Root());

//
// Use "dynamic indexes" for:
// MapSchema / ArraySchema / SetSchema
//
this.dynamicIndexes = !(ref instanceof Schema);
}

setParent(
Expand Down
5 changes: 5 additions & 0 deletions test/NextIterationTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,15 @@ describe("Next Iteration", () => {
assert.equal(decoded3.map.size, 1);
assert.equal(decoded3.map.get("three"), 3);

// discard previous changes
state.discardAllChanges();

// mutate "two" key.
state.map.set("two", 22);
encoded = state.encode(undefined, undefined, undefined, true);

console.log("\n\n>> PREVIOUS CHANGES HAVE BEEN DISCARDED\n\n");

encoded1 = state.applyFilters(encoded, client1);
console.log("ENCODED (CLIENT 1)", encoded1.length, encoded1);

Expand Down

0 comments on commit 7f56394

Please sign in to comment.