Skip to content

Commit

Permalink
Refactor, type fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
Smoren committed Mar 10, 2024
1 parent 80a2bdf commit ff798cb
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 32 deletions.
10 changes: 5 additions & 5 deletions src/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ArrayViewInterface } from "./types";
* with a subset of elements from the original array or ArrayView.
*
* @template T
* @param {Array<T> | ArrayView<T>} source - The source array or ArrayView to create a view from.
* @param {Array<T> | ArrayViewInterface<T>} source - The source array or ArrayView to create a view from.
* @param {boolean} [readonly] - Optional flag to indicate whether the view should be readonly.
* @returns {ArrayView<T>} The created ArrayView instance.
*
Expand Down Expand Up @@ -61,7 +61,7 @@ export function slice(slice: string | Array<number | undefined> | Slice): SliceS
*
* This function allows you to create a selector that masks elements based on a boolean mask array.
*
* @param {Array<boolean> | ArrayView<boolean>} mask - The boolean mask array or ArrayView to create the selector from.
* @param {Array<boolean> | ArrayViewInterface<boolean>} mask - The boolean mask array or ArrayView to create the selector from.
*
* @returns {MaskSelector} The created MaskSelector instance.
*
Expand All @@ -73,7 +73,7 @@ export function slice(slice: string | Array<number | undefined> | Slice): SliceS
* console.log(filteredView);
* // [1, 3, 4]
*/
export function mask(mask: Array<boolean> | ArrayView<boolean>): MaskSelector {
export function mask(mask: Array<boolean> | ArrayViewInterface<boolean>): MaskSelector {
return new MaskSelector(mask);
}

Expand All @@ -82,7 +82,7 @@ export function mask(mask: Array<boolean> | ArrayView<boolean>): MaskSelector {
*
* This function allows you to create a selector for specifying a list of indexes to include in the selection.
*
* @param {Array<number> | ArrayView<number>} indexes - The array of indexes or IndexList to create the selector from.
* @param {Array<number> | ArrayViewInterface<number>} indexes - The array of indexes or IndexList to create the selector from.
*
* @returns {IndexListSelector} The created IndexListSelector instance.
*
Expand All @@ -94,6 +94,6 @@ export function mask(mask: Array<boolean> | ArrayView<boolean>): MaskSelector {
* console.log(filteredView);
* // [1, 3, 5]
*/
export function select(indexes: Array<number> | ArrayView<number>): IndexListSelector {
export function select(indexes: Array<number> | ArrayViewInterface<number>): IndexListSelector {
return new IndexListSelector(indexes);
}
22 changes: 11 additions & 11 deletions src/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ArrayMaskView, ArrayIndexListView, ArraySliceView, ArrayView } from "./views";
import { Slice } from "./structs";
import { ArraySelectorInterface } from "./types";
import { ArraySelectorInterface, ArrayViewInterface } from "./types";

/**
* Represents an index list selector that selects elements based on the provided array of indexes.
Expand All @@ -16,9 +16,9 @@ export class IndexListSelector implements ArraySelectorInterface {
/**
* Creates a new IndexListSelector instance with the provided array of indexes.
*
* @param {Array<number> | ArrayView<number>} value - The array of indexes or array view containing indexes.
* @param {Array<number> | ArrayViewInterface<number>} value - The array of indexes or array view containing indexes.
*/
constructor(value: Array<number> | ArrayView<number>) {
constructor(value: Array<number> | ArrayViewInterface<number>) {
this.value = value instanceof Array ? value : value.toArray();
}

Expand All @@ -27,12 +27,12 @@ export class IndexListSelector implements ArraySelectorInterface {
*
* @template T - The type of elements in the source array view.
*
* @param {ArrayView<T>} source - The source array view to select elements from.
* @param {ArrayViewInterface<T>} source - The source array view to select elements from.
* @param {boolean} [readonly] - Whether the selection should be read-only.
*
* @returns {ArrayIndexListView<T>} The view containing the selected elements.
*/
public select<T>(source: ArrayView<T>, readonly?: boolean): ArrayIndexListView<T> {
public select<T>(source: ArrayViewInterface<T>, readonly?: boolean): ArrayIndexListView<T> {
return new ArrayIndexListView<T>(source, { indexes: this.value, readonly: readonly ?? source.readonly });
}
}
Expand All @@ -51,9 +51,9 @@ export class MaskSelector implements ArraySelectorInterface {
/**
* Creates a new MaskSelector instance with the provided array of boolean mask values.
*
* @param {Array<boolean> | ArrayView<boolean>} value - The array or array view of boolean mask values.
* @param {Array<boolean> | ArrayViewInterface<boolean>} value - The array or array view of boolean mask values.
*/
constructor(value: Array<boolean> | ArrayView<boolean>) {
constructor(value: Array<boolean> | ArrayViewInterface<boolean>) {
this.value = value instanceof Array ? value : value.toArray();
}

Expand All @@ -62,12 +62,12 @@ export class MaskSelector implements ArraySelectorInterface {
*
* @template T - The type of elements in the source array view.
*
* @param {ArrayView<T>} source - The source array to select elements from.
* @param {ArrayViewInterface<T>} source - The source array to select elements from.
* @param {boolean} [readonly] - Whether the selection should be read-only.
*
* @returns {ArrayMaskView<T>} The view containing the selected elements.
*/
public select<T>(source: ArrayView<T>, readonly?: boolean): ArrayMaskView<T> {
public select<T>(source: ArrayViewInterface<T>, readonly?: boolean): ArrayMaskView<T> {
return new ArrayMaskView<T>(source, { mask: this.value, readonly: readonly ?? source.readonly });
}
}
Expand Down Expand Up @@ -95,12 +95,12 @@ export class SliceSelector extends Slice implements ArraySelectorInterface {
*
* @template T - The type of elements in the source array.
*
* @param {ArrayView<T>} source - The source array to select elements from.
* @param {ArrayViewInterface<T>} source - The source array to select elements from.
* @param {boolean} [readonly] - Whether the selection should be read-only.
*
* @returns {ArraySliceView<T>} The view containing the selected elements.
*/
public select<T>(source: ArrayView<T>, readonly?: boolean): ArraySliceView<T> {
public select<T>(source: ArrayViewInterface<T>, readonly?: boolean): ArraySliceView<T> {
return new ArraySliceView<T>(source, { slice: this, readonly: readonly ?? source.readonly });
}
}
6 changes: 3 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ export interface ArrayViewInterface<T> {
/**
* Sets new values for the elements in the view.
*
* @param {Array<T> | ArrayViewInterface<T>} newValues - The new values to set.
* @param {Array<T> | ArrayViewInterface<T> | T} newValue - The new values to set.
*
* @returns {ArrayViewInterface<T>} this view.
*/
set(newValues: Array<T> | ArrayViewInterface<T>): ArrayViewInterface<T>;
set(newValue: Array<T> | ArrayViewInterface<T> | T): ArrayViewInterface<T>;

/**
* Returns an iterator for the elements in the view.
Expand Down Expand Up @@ -128,5 +128,5 @@ export interface ArraySelectorInterface {
* @template T - The type of elements in the array.
*/
export type SliceableArray<T> = Array<T> & {
[index: string]: Array<T>
[index: string]: Array<T>;
}
4 changes: 4 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ export function normalizeIndex(index: number, containerLength: number, throwErro
}
return index < 0 ? containerLength + index : index;
}

export function isCountable(target: any): boolean {
return target.length !== undefined;
}
34 changes: 23 additions & 11 deletions src/views.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MaskSelector, SliceSelector } from "./selectors";
import { normalizeIndex } from "./utils";
import { isCountable, normalizeIndex } from "./utils";
import { KeyError, LengthError, ReadonlyError } from "./excpetions";
import { NormalizedSlice, Slice } from "./structs";
import type { ArrayViewInterface, ArraySelectorInterface, SliceableArray } from "./types";
Expand Down Expand Up @@ -57,7 +57,7 @@ export class ArrayView<T> implements ArrayViewInterface<T> {
/**
* Constructs a new ArrayView instance based on the provided source array or ArrayView.
*
* @param {Array<T> | ArrayView<T>} source - The source array or ArrayView to create a view from.
* @param {Array<T> | ArrayViewInterface<T>} source - The source array or ArrayView to create a view from.
* @param {object} options - Options for configuring the view.
* @param {boolean} [options.readonly=false] - Optional flag to indicate whether the view should be readonly.
*
Expand All @@ -70,7 +70,7 @@ export class ArrayView<T> implements ArrayViewInterface<T> {
const loc = Array.isArray(source) ? source : source.loc;
this.source = Array.isArray(source) ? source : source.source;
this.parentView = Array.isArray(source) ? undefined : source;
this.readonly = readonly ?? ((source instanceof ArrayView) ? (source as ArrayView<T>).readonly : false);
this.readonly = readonly ?? (Array.isArray(source) ? false : (source as ArrayViewInterface<T>).readonly);

if ((source instanceof ArrayView) && source.readonly && !this.readonly) {
throw new ReadonlyError("Cannot create non-readonly view for readonly source.");
Expand Down Expand Up @@ -156,7 +156,10 @@ export class ArrayView<T> implements ArrayViewInterface<T> {
}

/** @inheritDoc */
public applyWith<U>(data: Array<U> | ArrayView<U>, mapper: (lhs: T, rhs: U, index: number) => T): ArrayView<T> {
public applyWith<U>(
data: Array<U> | ArrayViewInterface<U>,
mapper: (lhs: T, rhs: U, index: number) => T,
): ArrayView<T> {
if (data.length !== this.length) {
throw new LengthError(`Length of values array not equal to view length (${data.length} != ${this.length}).`);
}
Expand All @@ -171,7 +174,16 @@ export class ArrayView<T> implements ArrayViewInterface<T> {
}

/** @inheritDoc */
public set(newValues: Array<T> | ArrayView<T>): ArrayView<T> {
public set(newValue: Array<T> | ArrayViewInterface<T> | T): ArrayView<T> {
if (!isCountable(newValue)) {
for (let i = 0; i < this.length; ++i) {
this.loc[i] = newValue as T;
}
return this;
}

const newValues = newValue as Array<T> | ArrayViewInterface<T>;

if (newValues.length !== this.length) {
throw new LengthError(`Length of values array not equal to view length (${newValues.length} != ${this.length}).`);
}
Expand Down Expand Up @@ -236,15 +248,15 @@ export class ArrayIndexListView<T> extends ArrayView<T> {
/**
* Constructs a new ArrayIndexListView instance with the specified source array or ArrayView and indexes array.
*
* @param {Array<T> | ArrayView<T>} source - The source array or ArrayView to create a view from.
* @param {Array<T> | ArrayViewInterface<T>} source - The source array or ArrayView to create a view from.
* @param {object} options - Options for configuring the view.
* @param {number[]} options.indexes - The indexes array specifying the indexes of elements in the source array.
* @param {boolean} [options.readonly] - Optional flag to indicate whether the view should be readonly.
*
* @constructor
*/
constructor(
source: Array<T> | ArrayView<T>,
source: Array<T> | ArrayViewInterface<T>,
{
indexes,
readonly,
Expand Down Expand Up @@ -297,15 +309,15 @@ export class ArrayMaskView<T> extends ArrayIndexListView<T> {
/**
* Constructs a new ArrayMaskView instance with the specified source array or ArrayView and boolean mask.
*
* @param {Array<T> | ArrayView<T>} source - The source array or ArrayView to create a view from.
* @param {Array<T> | ArrayViewInterface<T>} source - The source array or ArrayView to create a view from.
* @param {object} options - Options for configuring the view.
* @param {boolean[]} options.mask - The boolean mask for including or excluding elements from the source array.
* @param {boolean} [options.readonly] - Optional flag to indicate whether the view should be readonly.
*
* @constructor
*/
constructor(
source: Array<T> | ArrayView<T>,
source: Array<T> | ArrayViewInterface<T>,
{
mask,
readonly,
Expand Down Expand Up @@ -343,15 +355,15 @@ export class ArraySliceView<T> extends ArrayView<T> {
/**
* Constructs a new ArraySliceView instance with the specified source array or ArrayView and slice range.
*
* @param {Array<T> | ArrayView<T>} source - The source array or ArrayView to create a view from.
* @param {Array<T> | ArrayViewInterface<T>} source - The source array or ArrayView to create a view from.
* @param {object} options - Options for configuring the view.
* @param {Slice} options.slice - The slice range specifying the subset of elements to include in the view.
* @param {boolean} [options.readonly] - Optional flag to indicate whether the view should be readonly.
*
* @constructor
*/
constructor(
source: Array<T> | ArrayView<T>,
source: Array<T> | ArrayViewInterface<T>,
{
slice,
readonly,
Expand Down
14 changes: 12 additions & 2 deletions tests/views/array-view.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ describe.each([
(
source: Array<number>,
viewGetter: (source: Array<number>) => ArrayView<number>,
toWrite: Array<number>,
toWrite: Array<number> | number,
expected: Array<number>,
) => {
it("", () => {
Expand All @@ -339,14 +339,15 @@ describe.each([
(
source: Array<number>,
viewGetter: (source: Array<number>) => ArrayView<number>,
toWrite: Array<number>,
toWrite: Array<number> | number,
expected: Array<number>,
) => {
it("", () => {
// Given
const v = viewGetter(source);

// When
// @ts-ignore
v.loc[':'] = toWrite;

// Then
Expand Down Expand Up @@ -439,6 +440,15 @@ function dataProviderForCombineWrite(): Array<unknown> {
[11, 99],
[11, 2, 3, 4, 5, 6, 7, 8, 99, 10],
],
[
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
(source: Array<number>) => view(source)
.subview(slice(new Slice(undefined, undefined, 2)))
.subview(slice('::2'))
.subview('::2'),
111,
[111, 2, 3, 4, 5, 6, 7, 8, 111, 10],
],
];
}

Expand Down

0 comments on commit ff798cb

Please sign in to comment.