All files / sportident/src/storage SiStorage.ts

100% Statements 24/24
100% Branches 6/6
100% Functions 8/8
100% Lines 23/23

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 7026x 26x     26x         135x 135x     135x 59289x     135x       135x 1x         134x       158x           528x 528x             49x 49x       96x 96x 1x         95x       26x     38x     135x    
import _ from 'lodash';
import Immutable from 'immutable';
import {ISiFieldValue, ISiStorage, ISiStorageData, ISiStorageDefinition, ISiStorageLocations} from './interfaces';
 
export class SiStorage<T> implements ISiStorage<T> {
    private internalData: ISiStorageData;
 
    // eslint-disable-next-line no-useless-constructor
    constructor(
                public readonly size: number,
                public readonly locations: ISiStorageLocations<T>,
                initArg?: Immutable.List<number|undefined>|Array<number|undefined>,
    ) {
        const initArrayOrList = (initArg === undefined
            ? _.range(size).map(() => undefined)
            : initArg
        ) as Immutable.List<number|undefined>|Array<number|undefined>;
        const initList = (initArrayOrList instanceof Immutable.List
            ? initArrayOrList
            : Immutable.List(initArrayOrList)
        ) as Immutable.List<number|undefined>;
        if (initList.size !== size) {
            throw new Error(
                `SiStorage constructor list "${initArg}" => "${initList}" ` +
                `must have size ${size} (but is ${initList.size})`,
            );
        }
        this.internalData = initList;
    }
 
    get data(): ISiStorageData {
        return this.internalData;
    }
 
    get<U extends keyof T>(
        fieldName: U,
    ): ISiFieldValue<T[U]>|undefined {
        const fieldDefinition = this.locations[fieldName];
        return fieldDefinition.extractFromData(this.internalData);
    }
 
    set<U extends keyof T>(
        fieldName: U,
        newValue: ISiFieldValue<T[U]>|T[U],
    ): void {
        const fieldDefinition = this.locations[fieldName];
        this.internalData = fieldDefinition.updateData(this.internalData, newValue);
    }
 
    splice(index: number, removeNum: number, ...values: number[]): void {
        const newData = this.internalData.splice(index, removeNum, ...values);
        if (newData.size !== this.internalData.size) {
            throw new Error(
                'SiStorage.splice must preserve the size of the storage data ' +
                `(${this.internalData.size} -> ${newData.size})`,
            );
        }
        this.internalData = newData;
    }
}
 
export const defineStorage = <T>(
    size: number,
    locations: ISiStorageLocations<T>,
): ISiStorageDefinition<T> => (
        initArg?: Immutable.List<number|undefined>|Array<number|undefined>,
    ): ISiStorage<T> => (
        new SiStorage<T>(size, locations, initArg)
    );