structurae
Advanced tools
Comparing version 1.5.0 to 1.6.0
@@ -7,2 +7,6 @@ # Changelog | ||
## [1.6.0] - 2019-08-17 | ||
### Added | ||
- Add CollectionView | ||
## [1.5.0] - 2019-06-28 | ||
@@ -9,0 +13,0 @@ ### Added |
@@ -211,3 +211,14 @@ // Type definitions for structurae | ||
declare class ArrayView extends ObjectView { | ||
declare class ExtendedDataView extends DataView { | ||
getArray(position: number, ctor: typeof ObjectView | typeof ArrayView, size: number): ArrayLike<object>; | ||
getTypedArray(position: number, ctor: typeof TypedArrayView, size: number): ArrayLike<number>; | ||
getObject(schema: ObjectViewSchema, offset: number): object; | ||
setArray(position: number, value: ArrayLike<object>, ctor: ViewType, size: number): void; | ||
setObject(position: number, value: object, ctor: ViewType): void; | ||
setString(position: number, value: string, length: number): void; | ||
setTypedArray(position: number, value: ArrayLike<number>, ctor: typeof TypedArrayView, size: number): void; | ||
setValue(field: string, value: any, schema: ObjectViewSchema, offset: number): this; | ||
} | ||
declare class ArrayView extends ExtendedDataView { | ||
size: number; | ||
@@ -226,5 +237,5 @@ | ||
type ViewType = typeof ArrayView | typeof ObjectView | typeof TypedArrayView | typeof StringView; | ||
type ViewType = typeof ArrayView | typeof ObjectView | typeof TypedArrayView | typeof StringView | typeof StringArrayView; | ||
type View = ObjectView | ArrayView | TypedArrayView | StringView; | ||
type View = ObjectView | ArrayView | TypedArrayView | StringView | StringArrayView; | ||
@@ -249,3 +260,3 @@ type PrimitiveFieldType = 'int8' | 'uint8' | 'int16' | 'uint16' | ||
export declare class ObjectView extends DataView { | ||
export declare class ObjectView extends ExtendedDataView { | ||
static fields: string[]; | ||
@@ -257,12 +268,4 @@ static schema: ObjectViewSchema; | ||
get(field: string): number | View; | ||
private getArray(position: number, ctor: typeof ObjectView | typeof ArrayView, size: number): ArrayLike<object>; | ||
private getTypedArray(position: number, ctor: typeof TypedArrayView, size: number): ArrayLike<number>; | ||
private getObject(schema: ObjectViewSchema, offset: number): object; | ||
private getView(position: number, length: number, ctor: ViewType): View; | ||
set(field: string, value: any): this; | ||
private setArray(position: number, value: ArrayLike<object>, ctor: ViewType, size: number): void; | ||
private setObject(position: number, value: object, ctor: ViewType): void; | ||
private setString(position: number, value: string, length: number): void; | ||
private setTypedArray(position: number, value: ArrayLike<number>, ctor: typeof TypedArrayView, size: number): void; | ||
private setValue(field: string, value: any, schema: ObjectViewSchema, offset: number): this; | ||
setView(field: string, value: View): this; | ||
@@ -329,2 +332,13 @@ toObject(): object; | ||
export declare class CollectionView extends DataView { | ||
static schema: ViewType[]; | ||
get(index: number): View; | ||
set(index: number, value: object): this; | ||
toObject(): object[]; | ||
static from(value: object[], array?: CollectionView): CollectionView; | ||
static getLength(sizes: number[]): number; | ||
static of(sizes: number[]): CollectionView; | ||
} | ||
export declare class BitArray extends Uint32Array { | ||
@@ -331,0 +345,0 @@ size: number; |
@@ -16,2 +16,3 @@ const BitField = require('./lib/bit-field'); | ||
const ArrayViewMixin = require('./lib/array-view'); | ||
const CollectionView = require('./lib/collection-view'); | ||
const ObjectView = require('./lib/object-view'); | ||
@@ -53,2 +54,3 @@ const StringView = require('./lib/string-view'); | ||
ArrayViewMixin, | ||
CollectionView, | ||
ObjectView, | ||
@@ -55,0 +57,0 @@ StringView, |
@@ -0,1 +1,3 @@ | ||
const ExtendedDataView = require('./extended-data-view'); | ||
/** | ||
@@ -11,3 +13,3 @@ * @param {Class<ObjectView>} ObjectViewClass | ||
*/ | ||
class ArrayView extends ObjectViewClass { | ||
class ArrayView extends ExtendedDataView { | ||
/** | ||
@@ -48,3 +50,3 @@ * Returns an object at a given index. | ||
new Uint8Array(this.buffer, this.byteOffset + (index * objectLength), objectLength) | ||
.set(new Uint8Array(value.buffer, value.byteOffset, value.length)); | ||
.set(new Uint8Array(value.buffer, value.byteOffset, value.byteLength)); | ||
return this; | ||
@@ -64,3 +66,3 @@ } | ||
/** | ||
* Allows iterating over numbers stored in the instance. | ||
* Allows iterating over objects stored in the array. | ||
* | ||
@@ -123,2 +125,18 @@ * @yields {number} | ||
/** | ||
* @private | ||
* @type {Array<ObjectViewField>} | ||
*/ | ||
ArrayView.fields = ObjectViewClass.fields; | ||
/** | ||
* @private | ||
*/ | ||
ArrayView.schema = ObjectViewClass.schema; | ||
/** | ||
* @private | ||
*/ | ||
ArrayView.objectLength = ObjectViewClass.objectLength; | ||
return ArrayView; | ||
@@ -125,0 +143,0 @@ } |
@@ -5,2 +5,3 @@ const StringView = require('./string-view'); | ||
const TypedArrayViewMixin = require('./typed-array-view'); | ||
const ExtendedDataView = require('./extended-data-view'); | ||
@@ -43,3 +44,3 @@ /** | ||
*/ | ||
class ObjectView extends DataView { | ||
class ObjectView extends ExtendedDataView { | ||
/** | ||
@@ -74,92 +75,3 @@ * Returns the value of a given field. | ||
* @param {number} position | ||
* @param {Class<ArrayView>|Class<ObjectView>} ctor | ||
* @param {number} size | ||
* @returns {Array<Object>} | ||
*/ | ||
getArray(position, ctor, size) { | ||
const { schema, objectLength } = ctor; | ||
const result = new Array(size); | ||
for (let i = 0; i < size; i++) { | ||
result[i] = this.getObject(schema, position + (i * objectLength)); | ||
} | ||
return result; | ||
} | ||
/** | ||
* @private | ||
* @param {number} position | ||
* @param {number} size | ||
* @param {number} length | ||
* @param {number} stringLength | ||
* @returns {void} | ||
*/ | ||
getStringArray(position, size, length, stringLength) { | ||
const array = new Array(size); | ||
for (let i = 0; i < size; i++) { | ||
const string = new StringView( | ||
this.buffer, this.byteOffset + position + (i * stringLength), stringLength, | ||
); | ||
array[i] = string.toString(); | ||
} | ||
return array; | ||
} | ||
/** | ||
* @private | ||
* @param {number} position | ||
* @param {Class<TypedArrayView>} ctor | ||
* @param {number} size | ||
* @returns {Array<number>} | ||
*/ | ||
getTypedArray(position, ctor, size) { | ||
const { typeGetter, offset, littleEndian } = ctor; | ||
const result = new Array(size); | ||
for (let i = 0; i < size; i++) { | ||
result[i] = this[typeGetter](position + (i << offset), littleEndian); | ||
} | ||
return result; | ||
} | ||
/** | ||
* @private | ||
* @param {object} schema | ||
* @param {number} offset | ||
* @returns {Object} | ||
*/ | ||
getObject(schema, offset) { | ||
const fields = Object.keys(schema); | ||
const result = {}; | ||
for (let i = 0; i < fields.length; i++) { | ||
const name = fields[i]; | ||
const { | ||
type, littleEndian, start, ctor: Ctor, length, size, stringLength, | ||
} = schema[name]; | ||
let value; | ||
const position = offset + start; | ||
switch (type) { | ||
case 'int8': value = this.getInt8(position); break; | ||
case 'uint8': value = this.getUint8(position); break; | ||
case 'int16': value = this.getInt16(position, littleEndian); break; | ||
case 'uint16': value = this.getUint16(position, littleEndian); break; | ||
case 'int32': value = this.getInt32(position, littleEndian); break; | ||
case 'uint32': value = this.getUint32(position, littleEndian); break; | ||
case 'float32': value = this.getFloat32(position, littleEndian); break; | ||
case 'float64': value = this.getFloat64(position, littleEndian); break; | ||
case 'bigint64': value = this.getBigInt64(position, littleEndian); break; | ||
case 'biguint64': value = this.getBigUint64(position, littleEndian); break; | ||
case 'string': value = new StringView(this.buffer, this.byteOffset + position, length).toString(); break; | ||
case 'typedarray': value = this.getTypedArray(position, Ctor, size); break; | ||
case 'stringarray': value = this.getStringArray(position, size, length, stringLength); break; | ||
case 'array': value = this.getArray(position, Ctor, size); break; | ||
default: value = this.getObject(Ctor.schema, position); | ||
} | ||
result[name] = value; | ||
} | ||
return result; | ||
} | ||
/** | ||
* @private | ||
* @param {number} position | ||
* @param {number} length | ||
* @param {Class<ArrayView>|Class<TypedArrayView> | ||
@@ -185,147 +97,2 @@ * |Class<ObjectView>|Class<StringView>} [Ctor=StringView] | ||
/** | ||
* @private | ||
* @param {number} position | ||
* @param {ArrayLike<object>} value | ||
* @param {Class<ArrayView>|Class<ObjectView>} ctor | ||
* @param {number} size | ||
* @returns {void} | ||
*/ | ||
setArray(position, value, ctor, size) { | ||
const { fields, schema } = ctor; | ||
const max = (size < value.length ? size : value.length); | ||
for (let i = 0; i < max; i++) { | ||
for (let j = 0; j < fields.length; j++) { | ||
const name = fields[j]; | ||
this.setValue(name, value[i][name], schema, position + (i * ctor.objectLength)); | ||
} | ||
} | ||
} | ||
/** | ||
* @private | ||
* @param {number} position | ||
* @param {Object} value | ||
* @param {Class<ObjectView>} ctor | ||
* @returns {void} | ||
*/ | ||
setObject(position, value, ctor) { | ||
const { fields, schema } = ctor; | ||
for (let i = 0; i < fields.length; i++) { | ||
const name = fields[i]; | ||
if (Reflect.has(value, name)) this.setValue(name, value[name], schema, position); | ||
} | ||
} | ||
/** | ||
* @private | ||
* @param {number} position | ||
* @param {string} value | ||
* @param {number} length | ||
* @returns {void} | ||
*/ | ||
setString(position, value, length) { | ||
new Uint8Array(this.buffer, this.byteOffset + position, length) | ||
.fill(0) | ||
.set(StringView.fromString(value)); | ||
} | ||
/** | ||
* @private | ||
* @param {number} position | ||
* @param {string} value | ||
* @param {number} size | ||
* @param {number} length | ||
* @param {number} stringLength | ||
* @returns {void} | ||
*/ | ||
setStringArray(position, value, size, length, stringLength) { | ||
const array = new Uint8Array(this.buffer, this.byteOffset + position, length); | ||
array.fill(0); | ||
const max = (size < value.length ? size : value.length); | ||
for (let i = 0; i < max; i++) { | ||
const string = StringView.fromString(value[i], stringLength); | ||
array.set(string, i * stringLength); | ||
} | ||
} | ||
/** | ||
* @private | ||
* @param {number} position | ||
* @param {ArrayLike<number>} value | ||
* @param {Class<TypedArrayView>} ctor | ||
* @param {number} size | ||
* @returns {void} | ||
*/ | ||
setTypedArray(position, value, ctor, size) { | ||
const { typeSetter, offset, littleEndian } = ctor; | ||
const max = (size < value.length ? size : value.length); | ||
for (let i = 0; i < max; i++) { | ||
this[typeSetter](position + (i << offset), value[i], littleEndian); | ||
} | ||
} | ||
/** | ||
* @private | ||
* @param {string} field | ||
* @param {*} value | ||
* @param {*} [schema] | ||
* @param {number} [offset=0] | ||
* @returns {ObjectView} | ||
*/ | ||
setValue(field, value, schema = this.constructor.schema, offset = 0) { | ||
const { | ||
type, littleEndian, start, ctor, length, size, stringLength, | ||
} = schema[field]; | ||
const position = offset + start; | ||
switch (type) { | ||
case 'int8': | ||
this.setInt8(position, value); | ||
break; | ||
case 'uint8': | ||
this.setUint8(position, value); | ||
break; | ||
case 'int16': | ||
this.setInt16(position, value, littleEndian); | ||
break; | ||
case 'uint16': | ||
this.setUint16(position, value, littleEndian); | ||
break; | ||
case 'int32': | ||
this.setInt32(position, value, littleEndian); | ||
break; | ||
case 'uint32': | ||
this.setUint32(position, value, littleEndian); | ||
break; | ||
case 'float32': | ||
this.setFloat32(position, value, littleEndian); | ||
break; | ||
case 'float64': | ||
this.setFloat64(position, value, littleEndian); | ||
break; | ||
case 'bigint64': | ||
this.setBigInt64(position, value, littleEndian); | ||
break; | ||
case 'biguint64': | ||
this.setBigUint64(position, value, littleEndian); | ||
break; | ||
case 'string': | ||
this.setString(position, value, length); | ||
break; | ||
case 'typedarray': | ||
this.setTypedArray(position, value, ctor, size); | ||
break; | ||
case 'array': | ||
this.setArray(position, value, ctor, size); | ||
break; | ||
case 'stringarray': | ||
this.setStringArray(position, value, size, length, stringLength); | ||
break; | ||
default: | ||
this.setObject(position, value, ctor); | ||
break; | ||
} | ||
return this; | ||
} | ||
/** | ||
* Sets an ObjectView value to a field. | ||
@@ -332,0 +99,0 @@ * |
{ | ||
"name": "structurae", | ||
"version": "1.5.0", | ||
"version": "1.6.0", | ||
"description": "Data structures for performance-sensitive modern JavaScript applications.", | ||
@@ -48,9 +48,9 @@ "main": "index.js", | ||
"devDependencies": { | ||
"@types/jest": "^24.0.14", | ||
"@types/jest": "^24.0.17", | ||
"benchmark": "^2.1.4", | ||
"codecov": "^3.5.0", | ||
"eslint": "^5.16.0", | ||
"eslint-config-airbnb-base": "^13.1.0", | ||
"eslint-plugin-import": "^2.17.3", | ||
"jest": "^24.8.0", | ||
"eslint-config-airbnb-base": "^13.2.0", | ||
"eslint-plugin-import": "^2.18.2", | ||
"jest": "^24.9.0", | ||
"jsdoc-to-markdown": "^5.0.0", | ||
@@ -57,0 +57,0 @@ "json-schema-faker": "^0.5.0-rc17" |
@@ -89,2 +89,36 @@ # Structurae | ||
#### CollectionView | ||
Whereas ArrayView requires its contents to be of a specific ObjectView class, CollectionView allows holding objects and arrays | ||
of different types as well as being optional, i.e. it does not allocate space upon creation for missing members. | ||
```javascript | ||
const { ObjectView, ArrayViewMixin, CollectionView } = require('structurae'); | ||
class Person extends ObjectView {} | ||
Person.schema = { | ||
id: { type: 'uint32' }, | ||
name: { type: 'string', length: 10 }, | ||
}; | ||
class Pet extends ObjectView {} | ||
Pet.schema = { | ||
type: { type: 'string', length: 10 }, // // string with max length of 10 bytes | ||
}; | ||
const Pets = ArrayViewMixin(Pet); | ||
class PersonWithPets extends CollectionView {} | ||
PersonWithPets.schema = [Person, Pets]; | ||
// create a person with one pet | ||
const arthur = PersonWithPets.from([{ id: 1, name: 'Artur'}, [{ type: 'dog'}]]); | ||
arthur.byteLength | ||
//=> 24 | ||
// create a person with no pets | ||
const arthur = PersonWithPets.from([{ id: 1, name: 'Artur'}, undefined]); | ||
arthur.byteLength | ||
//=> 14 | ||
``` | ||
#### ObjectView | ||
@@ -107,3 +141,3 @@ Extends DataView to implement C-like struct. The fields are defined in ObjectView.schema an can be of any primitive type supported by DataView, | ||
Person.schema = { | ||
name: { type: 'string', length: 10 } | ||
name: { type: 'string', length: 10 }, | ||
scores: { type: 'uint32', size: 10 }, // a an array of 10 numbers | ||
@@ -110,0 +144,0 @@ house: { type: House }, // another object view |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
197244
30
5520
875