Skip to content

Commit

Permalink
jsdoc added
Browse files Browse the repository at this point in the history
  • Loading branch information
Smoren committed Mar 9, 2024
1 parent 661d010 commit ccff544
Show file tree
Hide file tree
Showing 2 changed files with 179 additions and 8 deletions.
84 changes: 76 additions & 8 deletions src/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,104 @@ import { ArrayMaskView, ArrayIndexListView, ArraySliceView, ArrayView } from "./
import { Slice } from "./structs";
import { ArraySelectorInterface } from "./types";

/**
* Represents an index list selector that selects elements based on the provided array of indexes.
*
* @implements {ArraySelectorInterface}
*/
export class IndexListSelector implements ArraySelectorInterface {
/**
* The array of indexes to select elements from.
*/
public readonly value: Array<number>;

public select<T>(source: ArrayView<T>, readonly?: boolean): ArrayIndexListView<T> {
return new ArrayIndexListView<T>(source, { indexes: this.value, readonly: readonly ?? source.readonly });
}

/**
* 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.
*/
constructor(value: Array<number> | ArrayView<number>) {
this.value = value instanceof Array ? value : value.toArray();
}

/**
* Selects elements from the source array based on the index list.
*
* @template T - The type of elements in the source array view.
*
* @param {ArrayView<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> {
return new ArrayIndexListView<T>(source, { indexes: this.value, readonly: readonly ?? source.readonly });
}
}

/**
* Represents a mask selector that selects elements based on the provided array of boolean mask values.
*
* @implements {ArraySelectorInterface}
*/
export class MaskSelector implements ArraySelectorInterface {
/**
* The array of boolean mask values to select elements based on.
*/
public readonly value: Array<boolean>;

public select<T>(source: ArrayView<T>, readonly?: boolean): ArrayMaskView<T> {
return new ArrayMaskView<T>(source, { mask: this.value, readonly: readonly ?? source.readonly });
}

/**
* 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.
*/
constructor(value: Array<boolean> | ArrayView<boolean>) {
this.value = value instanceof Array ? value : value.toArray();
}

/**
* Selects elements from the source array based on the mask values.
*
* @template T - The type of elements in the source array view.
*
* @param {ArrayView<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> {
return new ArrayMaskView<T>(source, { mask: this.value, readonly: readonly ?? source.readonly });
}
}

/**
* Represents a slice selector that selects elements based on the provided slice parameters.
*
* @extends Slice
*
* @implements {ArraySelectorInterface}
*/
export class SliceSelector extends Slice implements ArraySelectorInterface {
/**
* Creates a new SliceSelector instance with the provided slice parameters.
*
* @param {Slice | string} slice - The slice instance or slice string defining the selection.
*/
constructor(slice: Slice | string) {
const s = Slice.toSlice(slice);
super(s.start, s.end, s.step);
}

/**
* Selects elements from the source array based on the slice parameters.
*
* @template T - The type of elements in the source array.
*
* @param {ArrayView<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> {
return new ArraySliceView<T>(source, { slice: this, readonly: readonly ?? source.readonly });
}
Expand Down
103 changes: 103 additions & 0 deletions src/structs.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
import { IndexError, ValueError } from "./excpetions";
import { normalizeIndex } from "./utils";

/**
* Represents a slice definition for selecting a range of elements.
*/
export class Slice {
/**
* The start index of the slice range.
*/
public readonly start: number | undefined;
/**
* The end index of the slice range.
*/
public readonly end: number | undefined;
/**
* The step size for selecting elements in the slice range.
*/
public readonly step: number | undefined;

/**
* Converts a slice string or Slice object into a Slice instance.
*
* @param {string | Slice} s - The slice string or Slice object to convert.
* @returns {Slice} The converted Slice instance.
*/
public static toSlice(s: string | Slice): Slice {
if (s instanceof Slice) {
return s;
Expand All @@ -20,10 +38,24 @@ export class Slice {
return new Slice(...slice);
}

/**
* Checks if the provided value is a Slice instance or a valid slice string.
*
* @param {unknown} s - The value to check.
*
* @returns {boolean} True if the value is a Slice instance or a valid slice string, false otherwise.
*/
public static isSlice(s: unknown): boolean {
return (s instanceof Slice) || this.isSliceString(s);
}

/**
* Checks if the provided value is a valid slice string.
*
* @param {unknown} s - The value to check.
*
* @returns {boolean} True if the value is a valid slice string, false otherwise.
*/
public static isSliceString(s: unknown): boolean {
if (typeof s !== "string") {
return false;
Expand All @@ -42,12 +74,26 @@ export class Slice {
return !(slice.length < 1 || slice.length > 3);
}

/**
* Creates a new Slice instance with optional start, end, and step values.
*
* @param {number} [start] - The start index of the slice range.
* @param {number} [end] - The end index of the slice range.
* @param {number} [step] - The step size for selecting elements in the slice range.
*/
constructor(start?: number, end?: number, step?: number) {
this.start = start;
this.end = end;
this.step = step;
}

/**
* Normalizes the slice parameters based on the container length.
*
* @param {number} containerLength - The length of the container or array.
*
* @returns {NormalizedSlice} The normalized slice parameters.
*/
public normalize(containerLength: number): NormalizedSlice {
// TODO: Need refactor
let step = this.step ?? 1;
Expand Down Expand Up @@ -85,41 +131,98 @@ export class Slice {
return new NormalizedSlice(start, defaultEnd ?? end, step);
}

/**
* Returns the string representation of the Slice.
*
* @returns {string} The string representation of the Slice.
*/
public toString(): string {
return `${this.start ?? ""}:${this.end ?? ""}:${this.step ?? ""}`;
}

/**
* Parses a slice string into an array of start, end, and step values.
*
* @param {string} s - The slice string to parse.
*
* @returns {(number | undefined)[]} An array of parsed start, end, and step values.
*/
private static parseSliceString(s: string): (number | undefined)[] {
return s.split(":")
.map(x => x.trim())
.map(x => (x === "") ? undefined : parseInt(x));
}

/**
* Constrains a value within a given range.
*
* @param {number} x - The value to constrain.
* @param {number} min - The minimum allowed value.
* @param {number} max - The maximum allowed value.
*
* @returns {number} The constrained value.
*/
private squeezeInBounds(x: number, min: number, max: number): number {
return Math.max(min, Math.min(max, x));
}
}

/**
* Represents a normalized slice definition with start, end, and step values.
*/
export class NormalizedSlice extends Slice {
/**
* The start index of the normalized slice.
*/
public readonly start: number;
/**
* The end index of the normalized slice.
*/
public readonly end: number;
/**
* The step size for selecting elements in the normalized slice.
*/
public readonly step: number;

/**
* Creates a new NormalizedSlice instance with start, end, and step values.
*
* @param {number} start - The start index of the normalized slice.
* @param {number} end - The end index of the normalized slice.
* @param {number} step - The step size for selecting elements in the normalized slice.
*/
constructor(start: number, end: number, step: number) {
super();
this.start = start;
this.end = end;
this.step = step;
}

/**
* Returns the length of the normalized slice.
*
* @type {number}
*/
get length(): number {
return Math.ceil(Math.abs(((this.end - this.start) / this.step)));
}

/**
* Converts the provided index to the actual index based on the normalized slice parameters.
*
* @param {number} i - The index to convert.
*
* @returns {number} The converted index value.
*/
public convertIndex(i: number): number {
return this.start + normalizeIndex(i, this.length, false) * this.step;
}

/**
* Generate an iterator for iterating over the elements in the normalized slice range.
*
* @returns {IterableIterator<number>} An iterator for the normalized slice range.
*/
public* toRange(): IterableIterator<number> {
for (let i = 0; i < this.length; ++i) {
yield this.convertIndex(i);
Expand Down

0 comments on commit ccff544

Please sign in to comment.