@dcl/ecs
Version:
Decentraland ECS
110 lines (109 loc) • 4.56 kB
JavaScript
import { IArray } from '../Array';
import { Bool } from '../basic/Boolean';
import { IntEnum, StringEnum } from '../basic/Enum';
import { Float32, Float64 } from '../basic/Float';
import { Int16, Int32, Int64, Int8 } from '../basic/Integer';
import { EcsString } from '../basic/String';
import { Color3Schema } from '../custom/Color3';
import { Color4Schema } from '../custom/Color4';
import { EntitySchema } from '../custom/Entity';
import { QuaternionSchema } from '../custom/Quaternion';
import { Vector3Schema } from '../custom/Vector3';
import { IMap } from '../Map';
import { IOneOf } from '../OneOf';
import { IOptional } from '../Optional';
import { getTypeAndValue, isCompoundType } from './utils';
const primitiveSchemas = {
[Bool.jsonSchema.serializationType]: Bool,
[EcsString.jsonSchema.serializationType]: EcsString,
[Float32.jsonSchema.serializationType]: Float32,
[Float64.jsonSchema.serializationType]: Float64,
[Int8.jsonSchema.serializationType]: Int8,
[Int16.jsonSchema.serializationType]: Int16,
[Int32.jsonSchema.serializationType]: Int32,
[Int64.jsonSchema.serializationType]: Int64,
[Vector3Schema.jsonSchema.serializationType]: Vector3Schema,
[QuaternionSchema.jsonSchema.serializationType]: QuaternionSchema,
[Color3Schema.jsonSchema.serializationType]: Color3Schema,
[Color4Schema.jsonSchema.serializationType]: Color4Schema,
[EntitySchema.jsonSchema.serializationType]: EntitySchema
};
/**
* Create an ISchema object from the json-schema
* @param jsonSchema
* @returns a ISchema or fail for unsupported json-schema
*/
export function jsonSchemaToSchema(jsonSchema) {
if (primitiveSchemas[jsonSchema.serializationType]) {
return primitiveSchemas[jsonSchema.serializationType];
}
if (jsonSchema.serializationType === 'map') {
const mapJsonSchema = jsonSchema;
const spec = {};
for (const key in mapJsonSchema.properties) {
spec[key] = jsonSchemaToSchema(mapJsonSchema.properties[key]);
}
return IMap(spec);
}
if (jsonSchema.serializationType === 'optional') {
const withItemsJsonSchema = jsonSchema;
return IOptional(jsonSchemaToSchema(withItemsJsonSchema.optionalJsonSchema));
}
if (jsonSchema.serializationType === 'array') {
const withItemsJsonSchema = jsonSchema;
return IArray(jsonSchemaToSchema(withItemsJsonSchema.items));
}
if (jsonSchema.serializationType === 'enum-int') {
const enumJsonSchema = jsonSchema;
return IntEnum(enumJsonSchema.enumObject, enumJsonSchema.default);
}
if (jsonSchema.serializationType === 'enum-string') {
const enumJsonSchema = jsonSchema;
return StringEnum(enumJsonSchema.enumObject, enumJsonSchema.default);
}
if (jsonSchema.serializationType === 'one-of') {
const oneOfJsonSchema = jsonSchema;
const spec = {};
for (const key in oneOfJsonSchema.properties) {
spec[key] = jsonSchemaToSchema(oneOfJsonSchema.properties[key]);
}
return IOneOf(spec);
}
throw new Error(`${jsonSchema.serializationType} is not supported as reverse schema generation.`);
}
export function mutateValues(jsonSchema, value, mutateFn) {
if (jsonSchema.serializationType === 'map') {
const { properties } = jsonSchema;
const typedValue = value;
for (const key in properties) {
const { type, value: mapValue } = getTypeAndValue(properties, typedValue, key);
if (type.serializationType === 'unknown')
continue;
if (isCompoundType(type)) {
mutateValues(type, mapValue, mutateFn);
}
else {
const newValue = mutateFn(mapValue, type);
if (newValue.changed) {
typedValue[key] = newValue.value;
}
}
}
}
else if (jsonSchema.serializationType === 'array') {
const { items } = jsonSchema;
const arrayValue = value;
for (let i = 0, n = arrayValue.length; i < n; i++) {
const { type, value } = getTypeAndValue({ items: items }, { items: arrayValue[i] }, 'items');
if (isCompoundType(type)) {
mutateValues(type, value, mutateFn);
}
else {
const newValue = mutateFn(value, type);
if (newValue.changed) {
arrayValue[i] = newValue.value;
}
}
}
}
}