structurae
Advanced tools
Comparing version 1.3.1 to 1.4.0
@@ -7,2 +7,7 @@ # Changelog | ||
## [1.4.0] - 2019-06-20 | ||
### Added | ||
- Support setting endiannes for TypedArrayViews | ||
- Make TypedArrayViews public | ||
## [1.3.1] - 2019-06-19 | ||
@@ -9,0 +14,0 @@ ### Added |
@@ -213,10 +213,10 @@ // Type definitions for structurae | ||
type ViewType = typeof ArrayView | typeof ObjectView | typeof TypedArrayView | typeof StringView; | ||
type ArrayViewType = typeof ArrayView | typeof TypedArrayView; | ||
type View = ObjectView | ArrayView | TypedArrayView | StringView; | ||
type ObjectViewFieldType = 'int8' | 'uint8' | 'int16' | 'uint16' | ||
| 'int32' | 'uint32' | 'float32' | 'float64' | 'bigint64' | 'biguint64' | ||
| 'string' | 'array' | 'object' | 'typedarray' | ViewType; | ||
type PrimitiveFieldType = 'int8' | 'uint8' | 'int16' | 'uint16' | ||
| 'int32' | 'uint32' | 'float32' | 'float64' | 'bigint64' | 'biguint64'; | ||
type ObjectViewFieldType = PrimitiveFieldType | 'string' | 'array' | 'object' | 'typedarray' | ViewType; | ||
interface ObjectViewField { | ||
@@ -259,3 +259,3 @@ type: ObjectViewFieldType; | ||
export declare class ArrayView extends ObjectView { | ||
declare class ArrayView extends ObjectView { | ||
size: number; | ||
@@ -274,7 +274,8 @@ | ||
export declare class TypedArrayView extends DataView { | ||
declare class TypedArrayView extends DataView { | ||
size: number; | ||
static typeGetter: string; | ||
static typeSetter: string; | ||
static offset: number; | ||
private static typeGetter: string; | ||
private static typeSetter: string; | ||
private static offset: number; | ||
private static littleEndian: boolean; | ||
@@ -284,17 +285,8 @@ get(index: number): number; | ||
toObject(): object; | ||
static getLength(size: number): number; | ||
static from(value: ArrayLike<number>, array?: TypedArrayView): TypedArrayView; | ||
static of(size: number): TypedArrayView; | ||
static getLength(size: number): number; | ||
} | ||
export declare class Int8View extends TypedArrayView {} | ||
export declare class Uint8View extends TypedArrayView {} | ||
export declare class Int16View extends TypedArrayView {} | ||
export declare class Uint16View extends TypedArrayView {} | ||
export declare class Int32View extends TypedArrayView {} | ||
export declare class Uint32View extends TypedArrayView {} | ||
export declare class Float32View extends TypedArrayView {} | ||
export declare class Float64View extends TypedArrayView {} | ||
export declare class BigInt64View extends TypedArrayView {} | ||
export declare class BigUint64View extends TypedArrayView {} | ||
export declare function TypedArrayViewMixin(type: PrimitiveFieldType, littleEndian: boolean): TypedArrayView; | ||
@@ -301,0 +293,0 @@ export declare class BitArray extends Uint32Array { |
@@ -10,3 +10,2 @@ const BitField = require('./lib/bit-field'); | ||
const SortedMixin = require('./lib/sorted-collection'); | ||
const StringView = require('./lib/string-view'); | ||
const SymmetricGridMixin = require('./lib/symmetric-grid'); | ||
@@ -19,2 +18,4 @@ const UnweightedAdjacencyList = require('./lib/unweighted-adjacency-list'); | ||
const ObjectView = require('./lib/object-view'); | ||
const StringView = require('./lib/string-view'); | ||
const TypedArrayViewMixin = require('./lib/typed-array-view'); | ||
@@ -46,3 +47,2 @@ /** | ||
SortedMixin, | ||
StringView, | ||
SymmetricGridMixin, | ||
@@ -55,2 +55,4 @@ UnweightedAdjacencyList, | ||
ObjectView, | ||
StringView, | ||
TypedArrayViewMixin, | ||
}; |
@@ -13,2 +13,4 @@ /** | ||
/** | ||
* Returns an object at a given index. | ||
* | ||
* @param {number} index | ||
@@ -25,2 +27,4 @@ * @returns {ObjectView} | ||
/** | ||
* Sets an object at a given index. | ||
* | ||
* @param {number} index | ||
@@ -36,2 +40,4 @@ * @param {Object} value | ||
/** | ||
* Sets an object view at a given index. | ||
* | ||
* @param {number} index | ||
@@ -49,3 +55,3 @@ * @param {ObjectView} value | ||
/** | ||
* Returns the amount of available bits in the array. | ||
* Returns the amount of available objects in the array. | ||
* | ||
@@ -72,2 +78,4 @@ * @type {number} | ||
/** | ||
* Returns an array representation of the array view. | ||
* | ||
* @returns {Array<Object>} | ||
@@ -80,2 +88,4 @@ */ | ||
/** | ||
* Creates an array view from a given array of objects. | ||
* | ||
* @param {ArrayLike<Object>} value | ||
@@ -87,7 +97,4 @@ * @param {ArrayView} [array] | ||
const arrayView = array || this.of(value.length); | ||
const { length } = value; | ||
if (!length) return arrayView; | ||
const { size } = arrayView; | ||
const max = size < length ? size : length; | ||
for (let i = 0; i < max; i++) { | ||
for (let i = 0; i < size; i++) { | ||
arrayView.set(i, value[i]); | ||
@@ -99,2 +106,4 @@ } | ||
/** | ||
* Returns the byte length of an array view to hold a given amount of objects. | ||
* | ||
* @param {number} size | ||
@@ -108,6 +117,8 @@ * @returns {number} | ||
/** | ||
* Creates an empty array view of specified size. | ||
* | ||
* @param {number} size | ||
* @returns {ArrayView} | ||
*/ | ||
static of(size) { | ||
static of(size = 1) { | ||
const buffer = new ArrayBuffer(this.getLength(size)); | ||
@@ -114,0 +125,0 @@ return new this(buffer); |
const StringView = require('./string-view'); | ||
const DataArrayMixin = require('./array-view'); | ||
const { | ||
Int8View, | ||
Uint8View, | ||
Int16View, | ||
Uint16View, | ||
Int32View, | ||
Uint32View, | ||
Float32View, | ||
Float64View, | ||
BigInt64View, | ||
BigUint64View, | ||
} = require('./typed-array-view'); | ||
const TypedArrayViewMixin = require('./typed-array-view'); | ||
@@ -51,18 +40,2 @@ /** | ||
/** | ||
* @private | ||
*/ | ||
const arrayClasses = { | ||
int8: Int8View, | ||
uint8: Uint8View, | ||
int16: Int16View, | ||
uint16: Uint16View, | ||
int32: Int32View, | ||
uint32: Uint32View, | ||
float32: Float32View, | ||
float64: Float64View, | ||
bigint64: BigInt64View, | ||
biguint64: BigUint64View, | ||
}; | ||
/** | ||
* @extends DataView | ||
@@ -120,6 +93,6 @@ */ | ||
getTypedArray(position, ctor, size) { | ||
const { typeGetter, offset } = ctor; | ||
const { typeGetter, offset, littleEndian } = ctor; | ||
const result = new Array(size); | ||
for (let i = 0; i < size; i++) { | ||
result[i] = this[typeGetter](position + (i << offset)); | ||
result[i] = this[typeGetter](position + (i << offset), littleEndian); | ||
} | ||
@@ -156,3 +129,2 @@ return result; | ||
case 'biguint64': value = this.getBigUint64(position, littleEndian); break; | ||
// todo optimize string trimming | ||
case 'string': value = new StringView(this.buffer, this.byteOffset + position, length).toString(); break; | ||
@@ -247,5 +219,6 @@ case 'typedarray': value = this.getTypedArray(position, Ctor, size); break; | ||
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[ctor.typeSetter](position + (i << ctor.offset), value[i]); | ||
this[typeSetter](position + (i << offset), value[i], littleEndian); | ||
} | ||
@@ -375,3 +348,3 @@ } | ||
const field = schema[name]; | ||
const { type, size } = field; | ||
const { type, size, littleEndian } = field; | ||
let byteSize = 0; | ||
@@ -386,3 +359,3 @@ const isPrimitive = typeof type === 'string'; | ||
if (isTypedArray) { | ||
field.ctor = arrayClasses[type]; | ||
field.ctor = TypedArrayViewMixin(type, littleEndian); | ||
field.type = 'typedarray'; | ||
@@ -389,0 +362,0 @@ byteSize = field.ctor.getLength(size); |
@@ -67,2 +67,3 @@ const utilities = require('./utilities'); | ||
* | ||
* @deprecated | ||
* @extends DataView | ||
@@ -69,0 +70,0 @@ */ |
/** | ||
* @private | ||
*/ | ||
const ZERO_CHAR = String.fromCharCode(0); | ||
/** | ||
* Extends Uint8Array to handle C-like representation of UTF-8 encoded strings. | ||
@@ -278,3 +283,5 @@ * | ||
toString() { | ||
return this.constructor.decoder.decode(this.trim()); | ||
const decoded = this.constructor.decoder.decode(this); | ||
const end = decoded.indexOf(ZERO_CHAR); | ||
return ~end ? decoded.slice(0, end) : decoded; | ||
} | ||
@@ -281,0 +288,0 @@ |
/** | ||
* @extends DataView | ||
* @private | ||
*/ | ||
class TypedArrayView extends DataView { | ||
/** | ||
* @param {number} index | ||
* @returns {number} | ||
*/ | ||
get(index) { | ||
return this[this.constructor.typeGetter](index << this.constructor.offset); | ||
} | ||
const getters = { | ||
int8: 'getInt8', | ||
uint8: 'getUint8', | ||
int16: 'getInt16', | ||
uint16: 'getUint16', | ||
int32: 'getInt32', | ||
uint32: 'getUint32', | ||
float32: 'getFloat32', | ||
float64: 'getFloat64', | ||
bigint64: 'getBigInt64', | ||
biguint64: 'getBigUint64', | ||
}; | ||
/** | ||
* @param {number} index | ||
* @param {number} value | ||
* @returns {TypedArrayView} | ||
*/ | ||
set(index, value) { | ||
this[this.constructor.typeSetter](index << this.constructor.offset, value); | ||
return this; | ||
} | ||
/** | ||
* @private | ||
*/ | ||
const setters = { | ||
int8: 'setInt8', | ||
uint8: 'setUint8', | ||
int16: 'setInt16', | ||
uint16: 'setUint16', | ||
int32: 'setInt32', | ||
uint32: 'setUint32', | ||
float32: 'setFloat32', | ||
float64: 'setFloat64', | ||
bigint64: 'setBigInt64', | ||
biguint64: 'setBigUint64', | ||
}; | ||
/** | ||
* Returns the amount of available bits in the array. | ||
* | ||
* @type {number} | ||
*/ | ||
get size() { | ||
return this.byteLength >> this.constructor.offset; | ||
} | ||
/** | ||
* @private | ||
*/ | ||
const offsets = { | ||
int8: 0, | ||
uint8: 0, | ||
int16: 1, | ||
uint16: 1, | ||
int32: 2, | ||
uint32: 2, | ||
float32: 2, | ||
float64: 3, | ||
bigint64: 3, | ||
biguint64: 3, | ||
}; | ||
/** | ||
* @param {string} type | ||
* @param {boolean} [littleEndian] | ||
* @returns {Class<TypedArrayView>} | ||
*/ | ||
function TypedArrayViewMixin(type, littleEndian) { | ||
/** | ||
* Allows iterating over numbers stored in the instance. | ||
* | ||
* @yields {number} | ||
* @extends DataView | ||
*/ | ||
* [Symbol.iterator]() { | ||
const { size } = this; | ||
for (let i = 0; i < size; i++) { | ||
yield this.get(i); | ||
class TypedArrayView extends DataView { | ||
/** | ||
* Returns a number at a given index. | ||
* | ||
* @param {number} index | ||
* @returns {number} | ||
*/ | ||
get(index) { | ||
const { typeGetter, offset, littleEndian: le } = this.constructor; | ||
return this[typeGetter](index << offset, le); | ||
} | ||
} | ||
toObject() { | ||
return [...this]; | ||
} | ||
/** | ||
* Sets a number at a given index. | ||
* | ||
* @param {number} index | ||
* @param {number} value | ||
* @returns {TypedArrayView} | ||
*/ | ||
set(index, value) { | ||
const { typeSetter, offset, littleEndian: le } = this.constructor; | ||
this[typeSetter](index << offset, value, le); | ||
return this; | ||
} | ||
static getLength(size) { | ||
return size << this.offset; | ||
} | ||
static from(value, array) { | ||
const dataArray = array || this.of(value.length); | ||
if (!value.length) return dataArray; | ||
const { size } = dataArray; | ||
for (let i = 0; i < size; i++) { | ||
dataArray.set(i, value[i]); | ||
/** | ||
* Returns the amount of available numbers in the array. | ||
* | ||
* @type {number} | ||
*/ | ||
get size() { | ||
return this.byteLength >> this.constructor.offset; | ||
} | ||
return dataArray; | ||
} | ||
static of(size) { | ||
const buffer = new ArrayBuffer(this.getLength(size)); | ||
return new this(buffer); | ||
} | ||
} | ||
/** @type {string} */ | ||
TypedArrayView.typeGetter = ''; | ||
/** | ||
* Allows iterating over numbers stored in the instance. | ||
* | ||
* @yields {number} | ||
*/ | ||
* [Symbol.iterator]() { | ||
const { size } = this; | ||
for (let i = 0; i < size; i++) { | ||
yield this.get(i); | ||
} | ||
} | ||
/** @type {string} */ | ||
TypedArrayView.typeSetter = ''; | ||
/** | ||
* Returns an array representation of the array view. | ||
* | ||
* @returns {Array<number>} | ||
*/ | ||
toObject() { | ||
return [...this]; | ||
} | ||
/** @type {number} */ | ||
TypedArrayView.offset = 0; | ||
/** | ||
* Returns the byte length of an array view to hold a given amount of numbers. | ||
* | ||
* @param {number} size | ||
* @returns {number} | ||
*/ | ||
static getLength(size) { | ||
return size << this.offset; | ||
} | ||
/** @extends TypedArrayView */ | ||
class Int8View extends TypedArrayView {} | ||
/** @type {string} */ | ||
Int8View.typeGetter = 'getInt8'; | ||
/** | ||
* Creates an array view from a given array of numbers. | ||
* | ||
* @param {ArrayLike<number>} value | ||
* @param {TypedArrayView} [array] | ||
* @returns {TypedArrayView} | ||
*/ | ||
static from(value, array) { | ||
const dataArray = array || this.of(value.length); | ||
const { size } = dataArray; | ||
for (let i = 0; i < size; i++) { | ||
dataArray.set(i, value[i]); | ||
} | ||
return dataArray; | ||
} | ||
/** @type {string} */ | ||
Int8View.typeSetter = 'setInt8'; | ||
/** | ||
* Creates an empty array view of specified size. | ||
* | ||
* @param {number} size | ||
* @returns {TypedArrayView} | ||
*/ | ||
static of(size = 1) { | ||
const buffer = new ArrayBuffer(this.getLength(size)); | ||
return new this(buffer); | ||
} | ||
} | ||
/** @type {number} */ | ||
Int8View.offset = 0; | ||
/** | ||
* @private | ||
* @type {string} | ||
*/ | ||
TypedArrayView.typeGetter = getters[type]; | ||
/** @extends TypedArrayView */ | ||
class Uint8View extends TypedArrayView {} | ||
/** @type {string} */ | ||
Uint8View.typeGetter = 'getUint8'; | ||
/** | ||
* @private | ||
* @type {string} | ||
*/ | ||
TypedArrayView.typeSetter = setters[type]; | ||
/** @type {string} */ | ||
Uint8View.typeSetter = 'setUint8'; | ||
/** | ||
* @private | ||
* @type {number} | ||
*/ | ||
TypedArrayView.offset = offsets[type]; | ||
/** @type {number} */ | ||
Uint8View.offset = 0; | ||
/** | ||
* @private | ||
* @type {boolean} | ||
*/ | ||
TypedArrayView.littleEndian = !!littleEndian; | ||
/** @extends TypedArrayView */ | ||
class Int16View extends TypedArrayView {} | ||
/** @type {string} */ | ||
Int16View.typeGetter = 'getInt16'; | ||
return TypedArrayView; | ||
} | ||
/** @type {string} */ | ||
Int16View.typeSetter = 'setInt16'; | ||
/** @type {number} */ | ||
Int16View.offset = 1; | ||
/** @extends TypedArrayView */ | ||
class Uint16View extends TypedArrayView {} | ||
/** @type {string} */ | ||
Uint16View.typeGetter = 'getUint16'; | ||
/** @type {string} */ | ||
Uint16View.typeSetter = 'setUint16'; | ||
/** @type {number} */ | ||
Uint16View.offset = 1; | ||
/** @extends TypedArrayView */ | ||
class Int32View extends TypedArrayView {} | ||
/** @type {string} */ | ||
Int32View.typeGetter = 'getInt32'; | ||
/** @type {string} */ | ||
Int32View.typeSetter = 'setInt32'; | ||
/** @type {number} */ | ||
Int32View.offset = 2; | ||
/** @extends TypedArrayView */ | ||
class Uint32View extends TypedArrayView {} | ||
/** @type {string} */ | ||
Uint32View.typeGetter = 'getUint32'; | ||
/** @type {string} */ | ||
Uint32View.typeSetter = 'setUint32'; | ||
/** @type {number} */ | ||
Uint32View.offset = 2; | ||
/** @extends TypedArrayView */ | ||
class Float32View extends TypedArrayView {} | ||
/** @type {string} */ | ||
Float32View.typeGetter = 'getFloat32'; | ||
/** @type {string} */ | ||
Float32View.typeSetter = 'setFloat32'; | ||
/** @type {number} */ | ||
Float32View.offset = 2; | ||
/** @extends TypedArrayView */ | ||
class Float64View extends TypedArrayView {} | ||
/** @type {string} */ | ||
Float64View.typeGetter = 'getFloat64'; | ||
/** @type {string} */ | ||
Float64View.typeSetter = 'setFloat64'; | ||
/** @type {number} */ | ||
Float64View.offset = 3; | ||
/** @extends TypedArrayView */ | ||
class BigInt64View extends TypedArrayView {} | ||
/** @type {string} */ | ||
BigInt64View.typeGetter = 'getBigInt64'; | ||
/** @type {string} */ | ||
BigInt64View.typeSetter = 'setBigInt64'; | ||
/** @type {number} */ | ||
BigInt64View.offset = 3; | ||
/** @extends TypedArrayView */ | ||
class BigUint64View extends TypedArrayView {} | ||
/** @type {string} */ | ||
BigUint64View.typeGetter = 'getBigUint64'; | ||
/** @type {string} */ | ||
BigUint64View.typeSetter = 'setBigUint64'; | ||
/** @type {number} */ | ||
BigUint64View.offset = 3; | ||
module.exports = { | ||
TypedArrayView, | ||
Int8View, | ||
Uint8View, | ||
Int16View, | ||
Uint16View, | ||
Int32View, | ||
Uint32View, | ||
Float32View, | ||
Float64View, | ||
BigInt64View, | ||
BigUint64View, | ||
}; | ||
module.exports = TypedArrayViewMixin; |
{ | ||
"name": "structurae", | ||
"version": "1.3.1", | ||
"version": "1.4.0", | ||
"description": "Data structures for performance-sensitive modern JavaScript applications.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
333
README.md
@@ -9,5 +9,11 @@ # Structurae | ||
- Bits: | ||
- [Binary Structures](https://github.com/zandaqo/structurae#Binary_Structures): | ||
- [ArrayView](https://github.com/zandaqo/structurae#ArrayView) - an array of C-like structs, ObjectViews, implemented with DataView | ||
- [ObjectView](https://github.com/zandaqo/structurae#ObjectView) - extends DataView to implement C-like struct. | ||
- [StringView](https://github.com/zandaqo/structurae#StringView) - extends Uint8Array to handle C-like representation of UTF-8 encoded strings. | ||
- [TypedArrayView](https://github.com/zandaqo/structurae#TypedArrayView) - a DataView based TypedArray that supports endianness and can be set at any offset. | ||
- Bit Structures: | ||
- [BitField](https://github.com/zandaqo/structurae#BitField) - stores and operates on data in Numbers and BigInts treating them as bitfields. | ||
- [BitArray](https://github.com/zandaqo/structurae#BitArray) - an array of bits implemented with Uint32Array. | ||
- [Pool](https://github.com/zandaqo/structurae#Pool) - manages availability of objects in object pools. | ||
- [RankedBitArray](https://github.com/zandaqo/structurae#RankedBitArray) - extends BitArray with O(1) time rank and O(logN) select methods. | ||
@@ -23,4 +29,2 @@ - [Graphs](https://github.com/zandaqo/structurae#Graphs): | ||
- [SymmetricGrid](https://github.com/zandaqo/structurae#SymmetricGrid) - a grid to handle symmetric or triangular matrices using half the space required for a normal grid. | ||
- [Pool](https://github.com/zandaqo/structurae#Pool) - manages availability of objects in object pools. | ||
- [RecordArray](https://github.com/zandaqo/structurae#RecordArray) - extends DataView to use ArrayBuffer as an array of records or C-like structs. | ||
- [Sorted Structures](https://github.com/zandaqo/structurae#sorted-structures): | ||
@@ -30,3 +34,2 @@ - [BinaryHeap](https://github.com/zandaqo/structurae#BinaryHeap) - extends Array to implement the Binary Heap data structure. | ||
- [SortedArray](https://github.com/zandaqo/structurae#SortedArray) - extends Array to handle sorted data. | ||
- [StringView](https://github.com/zandaqo/structurae#StringView) - extends Uint8Array to handle C-like representation of UTF-8 encoded strings. | ||
@@ -45,3 +48,167 @@ ## Installation | ||
## Overview | ||
### BitField | ||
### Binary Structures | ||
Binary data in JavaScript is represented by ArrayBuffer and accessed through "view" objects--TypedArrays and DataView. | ||
However, both of those interfaces are limited to working with numbers. Structurae offers a set of classes that extend these interfaces to | ||
support using ArrayBuffers for strings, objects, and arrays of objects defined with schema akin to C-like structs. | ||
Useful on their own, when combined, these classes form the basis for a simple, zero-copy binary protocol that is smaller and faster than | ||
other binary formats used in JavaScript, such as BSON or MessagePack. | ||
#### ArrayView | ||
DataView based array of ObjectViews (aka C-like structs): | ||
```javascript | ||
const { ObjectView, ArrayViewMixin } = require('structurae'); | ||
class Person extends ObjectView {} | ||
Person.schema = { | ||
id: { type: 'uint32' }, | ||
name: { type: 'string', length: 10 }, | ||
}; | ||
// an array class for Person objects | ||
const PeopleArray = ArrayViewMixin(Person); | ||
// create an empty array view of 10 Person objects | ||
const people = PeopleArray.of(10); | ||
// create an array view from a given array | ||
const hitchhikers = PeopleArray.from([ | ||
{ id: 1, name: 'Arthur' }, | ||
{ id: 2, name: 'Ford' }, | ||
]); | ||
const arthur = hitchhikers.get(0); | ||
//=> Person [14] | ||
arthur.toObject(); | ||
//=> { id: 1, name: 'Arthur' } | ||
// set the first object data | ||
hitchhikers.set(0, { id: 3, name: 'Trillian' }); | ||
hitchhikers.get(0).toObject(); | ||
//=> { id: 3, name: 'Trillian' } | ||
hitchhikers.toObject(); | ||
//=> [{ id: 1, name: 'Arthur' }, { id: 2, name: 'Ford' }] | ||
``` | ||
#### ObjectView | ||
Extends DataView to implement C-like struct. The fields are defined in ObjectView.schema an can be of any primitive type supported by DataView, | ||
their arrays, strings, or other objects and arrays of objects. | ||
```javascript | ||
class House extends ObjectView {} | ||
House.schema = { | ||
size: { type: 'uint32' }, // a primitive type | ||
}; | ||
class Pet extends ObjectView {} | ||
Pet.schema = { | ||
type: { type: 'string', length: 10 }, // // string with max length of 10 bytes | ||
}; | ||
class Person extends ObjectView {} | ||
Person.schema = { | ||
name: { type: 'string', length: 10 } | ||
scores: { type: 'uint32', size: 10 }, // a an array of 10 numbers | ||
house: { type: House }, // another object view | ||
pets: { type: Pet, size: 3 }, // an array of 3 pet objects | ||
}; | ||
const person = Person.from({ | ||
name: 'Zaphod', | ||
scores: [1, 2, 3], | ||
house: { | ||
size: 1, | ||
}, | ||
pets: [ | ||
{ type: 'dog' }, { type: 'cat' } | ||
], | ||
}); | ||
person.byteLength | ||
//=> 44 | ||
person.get('scores').get(0) | ||
//=> 1 | ||
person.get('name'); | ||
//=> Zaphod | ||
person.get('scores').toObject() | ||
//=> [1, 2, 3, 0, 0, 0, 0, 0, 0, 0,] | ||
person.set('house', { size: 5 }); | ||
person.get('house').get('size'); | ||
//=> 5 | ||
person.toObject() | ||
//=> { name: 'Zaphod', scores: [1, 2, 3, 0, 0, 0, 0, 0, 0, 0,], house: { size: 5 }, pets: [{ type: 'dog' }, { type: 'cat' }, { type: '' }] } | ||
``` | ||
#### StringView | ||
Encoding API (available both in modern browsers and Node.js) allows us to convert JavaScript strings to | ||
(and from) UTF-8 encoded stream of bytes represented by a Uint8Array. StringView extends Uint8Array with string related methods | ||
and relies on Encoding API internally for conversions. | ||
You can use `StringView.fromString` to create an encoded string, and `StringView#toString` to convert it back to a string: | ||
```javascript | ||
const { StringView } = require('structurae'); | ||
const stringView = StringView.fromString('abc😀a'); | ||
//=> StringView [ 97, 98, 99, 240, 159, 152, 128, 97 ] | ||
stringView.toString(); | ||
//=> 'abc😀a' | ||
stringView == 'abc😀a'; | ||
//=> true | ||
``` | ||
While the array itself holds code points, StringView provides methods to operate on characters of the underlying string: | ||
```javascript | ||
const stringView = StringView.fromString('abc😀'); | ||
stringView.length; // length of the view in bytes | ||
//=> 8 | ||
stringView.size; // the amount of characters in the string | ||
//=> 4 | ||
stringView.charAt(0); // get the first character in the string | ||
//=> 'a' | ||
stringView.charAt(3); // get the fourth character in the string | ||
//=> '😀' | ||
[...stringView.characters()] // iterate over characters | ||
//=> ['a', 'b', 'c', '😀'] | ||
stringView.substring(0, 4); | ||
//=> 'abc😀' | ||
``` | ||
StringView also offers methods for searching and in-place changing the underlying string without decoding: | ||
```javascript | ||
const stringView = StringView.fromString('abc😀a'); | ||
const searchValue = StringView.fromString('😀'); | ||
stringView.search(searchValue); // equivalent of String#indexOf | ||
//=> 3 | ||
const replacement = StringView.fromString('d'); | ||
stringView.replace(searchValue, replacement).toString(); | ||
//=> 'abcda' | ||
stringView.reverse().toString(); | ||
//=> 'adcba' | ||
``` | ||
#### TypedArrayView | ||
TypedArrays in JavaScript have two limitations that make them cumbersome to use in conjunction with DataView. | ||
First, there is no way to specify the endianness of numbers in TypedArrays unlike DataView, | ||
second, TypedArrays require their offset (byteOffset) to be a multiple of their element size (BYTES_PER_ELEMENT), | ||
which means that they often cannot "view" into existing ArrayBuffer starting from cirtain positions. | ||
TypedArrayViews are essentially TypedArrays that circumvent both issues by using DataView. | ||
You can specify endianness and instantiate them at any position in an existing ArrayBuffer. | ||
TypedArrayViews are internally used by ObjectView to handle arrays of numbers, although, they can be used on their own: | ||
```javascript | ||
const { TypedArrayViewMixin } = require('structurae'); | ||
// create a class for little endian doubles | ||
const Float64View = TypedArrayViewMixin('float64', true); | ||
const buffer = new ArrayBuffer(11); | ||
const doubles = new Float64View(buffer, 3, 8); | ||
doubles.byteLength | ||
//=> 20 | ||
doubles.byteOffset | ||
//=> 3 | ||
doubles.set(0, 5).set(1, 10); | ||
[...doubles] | ||
//=> [5, 10] | ||
``` | ||
### Bit Structures | ||
#### BitField | ||
BitField uses JavaScript Numbers and BigInts as bitfields to store and operate on data using bitwise operations. | ||
@@ -208,3 +375,3 @@ By default, BitField operates on 31 bit long bitfield where bits are indexed from least significant to most: | ||
### BitArray | ||
#### BitArray | ||
BitArray uses Uint32Array as an array or vector of bits. It's a simpler version of BitField that only sets and checks individual bits: | ||
@@ -227,3 +394,26 @@ | ||
### RankedBitArray | ||
#### Pool | ||
Implements a fast algorithm to manage availability of objects in an object pool using a BitArray. | ||
```javascript | ||
const { Pool } = require('structurae'); | ||
// create a pool of 1600 indexes | ||
const pool = new Pool(100 * 16); | ||
// get the next available index and make it unavailable | ||
pool.get(); | ||
//=> 0 | ||
pool.get(); | ||
//=> 1 | ||
// set index available | ||
pool.free(0); | ||
pool.get(); | ||
//=> 0 | ||
pool.get(); | ||
//=> 2 | ||
``` | ||
#### RankedBitArray | ||
RankedBitArray is an extension of BitArray with methods to efficiently calculate rank and select. | ||
@@ -244,3 +434,2 @@ The rank is calculated in constant time where as select has O(logN) time complexity. | ||
### Graphs | ||
@@ -496,82 +685,2 @@ Structurae offers classes that implement Adjacency List (`UnweightedAdjacencyList`, `WeightedAdjacencyList`) and Adjacency Matrix (`UnweightedAdjacencyMatrix`, | ||
### Pool | ||
Implements a fast algorithm to manage availability of objects in an object pool. | ||
```javascript | ||
const { Pool } = require('structurae'); | ||
// create a pool of 1600 indexes | ||
const pool = new Pool(100 * 16); | ||
// get the next available index and make it unavailable | ||
pool.get(); | ||
//=> 0 | ||
pool.get(); | ||
//=> 1 | ||
// set index available | ||
pool.free(0); | ||
pool.get(); | ||
//=> 0 | ||
pool.get(); | ||
//=> 2 | ||
``` | ||
### RecordArray | ||
RecordArray extends DataView to use ArrayBuffer as an array of records or C-like structs. | ||
Records can contain fields of any type supported by DataView, strings, and TypedArrays. | ||
For a string, the maximum size in bytes should be defined, for typed array fields size property specifies | ||
the length of the array. | ||
```javascript | ||
const { RecordArray } = require('structurae'); | ||
// create an array of 20 records where each has 'age', 'score', and 'name' fields | ||
const people = new RecordArray([ | ||
{ name: 'age', type: 'Uint8' }, | ||
{ name: 'score', type: 'Float32' }, | ||
{ name: 'name', type: 'String', size: 10 }, | ||
], 20); | ||
// get the 'age' field value for the first struct in the array | ||
people.get(0, 'age'); | ||
//=> 0 | ||
// set the 'age' and 'score' field values for the first struct | ||
people.set(0, 'age', 10).set(0, 'score', 5.0); | ||
people.toObject(0); | ||
//=> { age: 10, score: 5.0, name: '' } | ||
// populate record from an object | ||
people.fromObject(0, { age: 15, score: 6.0, name: ''}) | ||
people.toObject(0); | ||
//=> { age: 15, score: 6.0, name: '' } | ||
``` | ||
The String type is handled with [StringView](https://github.com/zandaqo/structurae#StringView). | ||
You can use its methods to convert them to and from strings. | ||
```javascript | ||
people.get(0, 'name'); | ||
//=> StringView(10) [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | ||
const name = StringView.fromString('Smith'); | ||
people.set(0, name).get(0, 'name'); | ||
//=> StringView(10) [83, 109, 105, 116, 104, 0, 0, 0, 0, 0] | ||
people.get(0, 'name').toString(); | ||
//=> Smith | ||
``` | ||
Getting a TypedArray field will return a new TypedArray that uses the same buffer as the RecordArray, | ||
that is, any change made on the new TypedArray will reflect in the RecordArray and vice versa: | ||
```javascript | ||
const people = new RecordArray([ | ||
{ name: 'age', type: 'Uint8' }, | ||
{ name: 'scores', type: 'Float32Array', size: 2 }, | ||
], 10); | ||
const scores = people.get(0, 'scores'); | ||
//=> Float32Array [0, 0]; | ||
scores[1] = 1.2; | ||
people.get(0, 'scores'); | ||
//=> Float32Array [0, 1.2] | ||
people.set(0, 'scores', [2, 3]); | ||
scores[0]; | ||
//=> 2 | ||
``` | ||
### Sorted Structures | ||
@@ -713,51 +822,3 @@ #### BinaryHeap | ||
### StringView | ||
Encoding API (available both in modern browsers and Node.js) allows us to convert JavaScript strings to | ||
(and from) UTF-8 encoded stream of bytes represented by a Uint8Array. StringView extends Uint8Array with string related methods | ||
and relies on Encoding API internally for conversions. | ||
You can use `StringView.fromString` to create an encoded string, and `StringView#toString` to convert it back to a string: | ||
```javascript | ||
const { StringView } = require('structurae'); | ||
const stringView = StringView.fromString('abc😀a'); | ||
//=> StringView [ 97, 98, 99, 240, 159, 152, 128, 97 ] | ||
stringView.toString(); | ||
//=> 'abc😀a' | ||
stringView == 'abc😀a'; | ||
//=> true | ||
``` | ||
While the array itself holds code points, StringView provides methods to operate on characters of the underlying string: | ||
```javascript | ||
const stringView = StringView.fromString('abc😀'); | ||
stringView.length; // length of the view in bytes | ||
//=> 8 | ||
stringView.size; // the amount of characters in the string | ||
//=> 4 | ||
stringView.charAt(0); // get the first character in the string | ||
//=> 'a' | ||
stringView.charAt(3); // get the fourth character in the string | ||
//=> '😀' | ||
[...stringView.characters()] // iterate over characters | ||
//=> ['a', 'b', 'c', '😀'] | ||
stringView.substring(0, 4); | ||
//=> 'abc😀' | ||
``` | ||
StringView also offers methods for searching and in-place changing the underlying string without decoding: | ||
```javascript | ||
const stringView = StringView.fromString('abc😀a'); | ||
const searchValue = StringView.fromString('😀'); | ||
stringView.search(searchValue); // equivalent of String#indexOf | ||
//=> 3 | ||
const replacement = StringView.fromString('d'); | ||
stringView.replace(searchValue, replacement).toString(); | ||
//=> 'abcda' | ||
stringView.reverse().toString(); | ||
//=> 'adcba' | ||
``` | ||
## License | ||
MIT © [Maga D. Zandaqo](http://maga.name) |
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
185897
815
5189