Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 09af2a8

Browse files
authored
Merge pull request #5910 from matrix-org/travis/tests/array-obj-utils
Add unit tests for various collection-based utility functions
2 parents e088118 + 2c459c4 commit 09af2a8

File tree

11 files changed

+1242
-17
lines changed

11 files changed

+1242
-17
lines changed

src/utils/arrays.ts

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2020 The Matrix.org Foundation C.I.C.
2+
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -15,23 +15,47 @@ limitations under the License.
1515
*/
1616

1717
/**
18-
* Quickly resample an array to have less data points. This isn't a perfect representation,
19-
* though this does work best if given a large array to downsample to a much smaller array.
20-
* @param {number[]} input The input array to downsample.
18+
* Quickly resample an array to have less/more data points. If an input which is larger
19+
* than the desired size is provided, it will be downsampled. Similarly, if the input
20+
* is smaller than the desired size then it will be upsampled.
21+
* @param {number[]} input The input array to resample.
2122
* @param {number} points The number of samples to end up with.
22-
* @returns {number[]} The downsampled array.
23+
* @returns {number[]} The resampled array.
2324
*/
2425
export function arrayFastResample(input: number[], points: number): number[] {
25-
// Heavily inpired by matrix-media-repo (used with permission)
26+
if (input.length === points) return input; // short-circuit a complicated call
27+
28+
// Heavily inspired by matrix-media-repo (used with permission)
2629
// https://github.com/turt2live/matrix-media-repo/blob/abe72c87d2e29/util/util_audio/fastsample.go#L10
27-
const everyNth = Math.round(input.length / points);
28-
const samples: number[] = [];
29-
for (let i = 0; i < input.length; i += everyNth) {
30-
samples.push(input[i]);
30+
let samples: number[] = [];
31+
if (input.length > points) {
32+
// Danger: this loop can cause out of memory conditions if the input is too small.
33+
const everyNth = Math.round(input.length / points);
34+
for (let i = 0; i < input.length; i += everyNth) {
35+
samples.push(input[i]);
36+
}
37+
} else {
38+
// Smaller inputs mean we have to spread the values over the desired length. We
39+
// end up overshooting the target length in doing this, so we'll resample down
40+
// before returning. This recursion is risky, but mathematically should not go
41+
// further than 1 level deep.
42+
const spreadFactor = Math.ceil(points / input.length);
43+
for (const val of input) {
44+
samples.push(...arraySeed(val, spreadFactor));
45+
}
46+
samples = arrayFastResample(samples, points);
3147
}
48+
49+
// Sanity fill, just in case
3250
while (samples.length < points) {
3351
samples.push(input[input.length - 1]);
3452
}
53+
54+
// Sanity trim, just in case
55+
if (samples.length > points) {
56+
samples = samples.slice(0, points);
57+
}
58+
3559
return samples;
3660
}
3761

@@ -178,6 +202,13 @@ export class GroupedArray<K, T> {
178202
constructor(private val: Map<K, T[]>) {
179203
}
180204

205+
/**
206+
* The value of this group, after all applicable alterations.
207+
*/
208+
public get value(): Map<K, T[]> {
209+
return this.val;
210+
}
211+
181212
/**
182213
* Orders the grouping into an array using the provided key order.
183214
* @param keyOrder The key order.

src/utils/enums.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2020 The Matrix.org Foundation C.I.C.
2+
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -19,11 +19,23 @@ limitations under the License.
1919
* @param e The enum.
2020
* @returns The enum values.
2121
*/
22-
export function getEnumValues<T>(e: any): T[] {
22+
export function getEnumValues(e: any): (string | number)[] {
23+
// String-based enums will simply be objects ({Key: "value"}), but number-based
24+
// enums will instead map themselves twice: in one direction for {Key: 12} and
25+
// the reverse for easy lookup, presumably ({12: Key}). In the reverse mapping,
26+
// the key is a string, not a number.
27+
//
28+
// For this reason, we try to determine what kind of enum we're dealing with.
29+
2330
const keys = Object.keys(e);
24-
return keys
25-
.filter(k => ['string', 'number'].includes(typeof(e[k])))
26-
.map(k => e[k]);
31+
const values: (string | number)[] = [];
32+
for (const key of keys) {
33+
const value = e[key];
34+
if (Number.isFinite(value) || e[value.toString()] !== Number(key)) {
35+
values.push(value);
36+
}
37+
}
38+
return values;
2739
}
2840

2941
/**

src/utils/objects.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2020 The Matrix.org Foundation C.I.C.
2+
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -141,3 +141,21 @@ export function objectKeyChanges<O extends {}>(a: O, b: O): (keyof O)[] {
141141
export function objectClone<O extends {}>(obj: O): O {
142142
return JSON.parse(JSON.stringify(obj));
143143
}
144+
145+
/**
146+
* Converts a series of entries to an object.
147+
* @param entries The entries to convert.
148+
* @returns The converted object.
149+
*/
150+
// NOTE: Deprecated once we have Object.fromEntries() support.
151+
// @ts-ignore - return type is complaining about non-string keys, but we know better
152+
export function objectFromEntries<K, V>(entries: Iterable<[K, V]>): {[k: K]: V} {
153+
const obj: {
154+
// @ts-ignore - same as return type
155+
[k: K]: V} = {};
156+
for (const e of entries) {
157+
// @ts-ignore - same as return type
158+
obj[e[0]] = e[1];
159+
}
160+
return obj;
161+
}

test/Singleflight-test.ts renamed to test/utils/Singleflight-test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import {Singleflight} from "../src/utils/Singleflight";
17+
import {Singleflight} from "../../src/utils/Singleflight";
1818

1919
describe('Singleflight', () => {
2020
afterEach(() => {

0 commit comments

Comments
 (0)