@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
106 lines (78 loc) • 2.43 kB
JavaScript
import { assert } from "../../../../../core/assert.js";
import { array_push_if_unique } from "../../../../../core/collection/array/array_push_if_unique.js";
import { Codec } from "./Codec.js";
/**
* Codec that tries to decode data with multiple codecs in order.
*
* @template T
* @extends {Codec<T>}
*/
export class CodecWithFallback extends Codec {
/**
*
* @type {Codec<T>[]}
*/
children = []
/**
*
* @param {Codec<T>} codecs
*/
constructor(...codecs) {
super();
assert.isArray(codecs, 'codecs');
for (const codec of codecs) {
this.#add(codec);
}
if (this.children.length < 1) {
throw new Error('At least one codec must be provided');
}
}
/**
*
* @param {Codec<T>} codec
*/
#add(codec) {
assert.defined(codec, 'codec');
assert.isObject(codec, 'codec');
assert.isInstanceOf(codec, Codec, 'codec', 'Codec');
return array_push_if_unique(this.children, codec);
}
async test(data) {
const codecs = this.children;
const codec_count = codecs.length;
for (let i = 0; i < codec_count; i++) {
const codec = codecs[i];
const codec_supports_data = await codec.test(data);
if (codec_supports_data) {
return true;
}
}
return false;
}
async decode(data) {
const codecs = this.children;
const codec_count = codecs.length;
const errors = [];
let result;
for (let i = 0; i < codec_count; i++) {
const codec = codecs[i];
const codec_supports_data = await codec.test(data);
if (!codec_supports_data) {
errors.push({
index: i, error: "Codec doesn't support this data"
});
continue;
}
try {
result = await codec.decode(data);
} catch (e) {
errors.push({
index: i, error: e
});
continue;
}
return result;
}
throw new Error(`All codecs failed, errors: ${errors.map(a => JSON.stringify(a)).join('\n')}`);
}
}