mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-03-12 11:07:40 +08:00
Type initialization using objects
This commit is contained in:
@@ -2,11 +2,8 @@ import GeneralSerializer from "./GeneralSerializer"
|
||||
|
||||
/**
|
||||
* @typedef {import("../entity/IEntity").default} IEntity
|
||||
* @typedef {import("../entity/TypeInitialization").AnyValue} AnyValue
|
||||
*/
|
||||
/**
|
||||
* @template {AnyValue} T
|
||||
* @typedef {import("../entity/TypeInitialization").AnyValueConstructor<T>} AnyValueConstructor
|
||||
* @typedef {import("../entity/IEntity").AnyValue} AnyValue
|
||||
* @typedef {import("../entity/IEntity").AnyValueConstructor<*>} AnyValueConstructor
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -19,7 +16,7 @@ export default class CustomSerializer extends GeneralSerializer {
|
||||
|
||||
/**
|
||||
* @param {(v: T, insideString: Boolean) => String} objectWriter
|
||||
* @param {AnyValueConstructor<T>} entityType
|
||||
* @param {AnyValueConstructor} entityType
|
||||
*/
|
||||
constructor(objectWriter, entityType) {
|
||||
super(undefined, entityType)
|
||||
|
||||
@@ -3,11 +3,8 @@ import ISerializer from "./ISerializer"
|
||||
|
||||
/**
|
||||
* @typedef {import("../entity/IEntity").default} IEntity
|
||||
* @typedef {import("../entity/TypeInitialization").AnyValue} AnyValue
|
||||
*/
|
||||
/**
|
||||
* @template {AnyValue} T
|
||||
* @typedef {import("../entity/TypeInitialization").AnyValueConstructor<T>} AnyValueConstructor
|
||||
* @typedef {import("../entity/IEntity").AnyValue} AnyValue
|
||||
* @typedef {import("../entity/IEntity").AnyValueConstructor<*>} AnyValueConstructor
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -18,7 +15,7 @@ export default class GeneralSerializer extends ISerializer {
|
||||
|
||||
/**
|
||||
* @param {(value: String, entity: T) => String} wrap
|
||||
* @param {AnyValueConstructor<T>} entityType
|
||||
* @param {AnyValueConstructor} entityType
|
||||
*/
|
||||
constructor(wrap, entityType, attributePrefix, attributeSeparator, trailingSeparator, attributeValueConjunctionSign, attributeKeyPrinter) {
|
||||
wrap = wrap ?? (v => `(${v})`)
|
||||
@@ -35,7 +32,6 @@ export default class GeneralSerializer extends ISerializer {
|
||||
let grammar = Grammar.getGrammarForType(ISerializer.grammar, this.entityType)
|
||||
const parseResult = grammar.parse(value)
|
||||
if (!parseResult.status) {
|
||||
// @ts-expect-error
|
||||
throw new Error(`Error when trying to parse the entity ${this.entityType.prototype.constructor.name}.`)
|
||||
}
|
||||
return parseResult.value
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// @ts-nocheck
|
||||
import ByteEntity from "../entity/ByteEntity"
|
||||
import FunctionReferenceEntity from "../entity/FunctionReferenceEntity"
|
||||
import GuidEntity from "../entity/GuidEntity"
|
||||
import IdentifierEntity from "../entity/IdentifierEntity"
|
||||
@@ -17,17 +18,17 @@ import PinReferenceEntity from "../entity/PinReferenceEntity"
|
||||
import RealUnitEntity from "../entity/UnitRealEntity"
|
||||
import RotatorEntity from "../entity/RotatorEntity"
|
||||
import SimpleSerializationRotatorEntity from "../entity/SimpleSerializationRotatorEntity"
|
||||
import SimpleSerializationVector2DEntity from "../entity/SimpleSerializationVector2DEntity"
|
||||
import SimpleSerializationVectorEntity from "../entity/SimpleSerializationVectorEntity"
|
||||
import SymbolEntity from "../entity/SymbolEntity"
|
||||
import TypeInitialization from "../entity/TypeInitialization"
|
||||
import UnionType from "../entity/UnionType"
|
||||
import UnknownKeysEntity from "../entity/UnknownKeysEntity"
|
||||
import Utility from "../Utility"
|
||||
import VariableReferenceEntity from "../entity/VariableReferenceEntity"
|
||||
import Vector2DEntity from "../entity/Vector2DEntity"
|
||||
import VectorEntity from "../entity/VectorEntity"
|
||||
import SimpleSerializationVector2DEntity from "../entity/SimpleSerializationVector2DEntity"
|
||||
import ByteEntity from "../entity/ByteEntity"
|
||||
|
||||
/** @typedef {import ("../entity/IEntity").AttributeInformation} AttributeInformation */
|
||||
|
||||
let P = Parsimmon
|
||||
|
||||
@@ -36,30 +37,35 @@ export default class Grammar {
|
||||
/* --- Factory --- */
|
||||
|
||||
/** @param {Grammar} r */
|
||||
static getGrammarForType(r, attributeType, defaultGrammar = r.AttributeAnyValue) {
|
||||
if (attributeType instanceof TypeInitialization) {
|
||||
let result = Grammar.getGrammarForType(r, attributeType.type, defaultGrammar)
|
||||
if (attributeType.serialized && !(attributeType.type instanceof String)) {
|
||||
static getGrammarForType(r, attribute, defaultGrammar = r.AttributeAnyValue) {
|
||||
if (attribute.constructor === Object) {
|
||||
attribute = /** @type {AttributeInformation} */(attribute)
|
||||
let type = attribute.type
|
||||
let result
|
||||
if (type instanceof Array) {
|
||||
result = Grammar.getGrammarForType(r, type[0])
|
||||
.trim(P.optWhitespace)
|
||||
.sepBy(P.string(","))
|
||||
.skip(P.regex(/,?\s*/))
|
||||
.wrap(P.string("("), P.string(")"))
|
||||
} else if (type instanceof UnionType) {
|
||||
result = type.types
|
||||
.map(v => Grammar.getGrammarForType(r, Utility.getType(v)))
|
||||
.reduce((accum, cur) => !cur || accum === r.AttributeAnyValue
|
||||
? r.AttributeAnyValue
|
||||
: accum.or(cur))
|
||||
} else {
|
||||
result = Grammar.getGrammarForType(r, type, defaultGrammar)
|
||||
}
|
||||
if (attribute.serialized && !(type instanceof String)) {
|
||||
result = result.wrap(P.string('"'), P.string('"'))
|
||||
}
|
||||
if (attribute.nullable) {
|
||||
result = result.or(r.Null)
|
||||
}
|
||||
return result
|
||||
}
|
||||
switch (Utility.getType(attributeType)) {
|
||||
case Array:
|
||||
return P.seqMap(
|
||||
P.string("("),
|
||||
attributeType
|
||||
.map(v => Grammar.getGrammarForType(r, Utility.getType(v)))
|
||||
.reduce((accum, cur) => !cur || accum === r.AttributeAnyValue
|
||||
? r.AttributeAnyValue
|
||||
: accum.or(cur)
|
||||
)
|
||||
.trim(P.optWhitespace)
|
||||
.sepBy(P.string(","))
|
||||
.skip(P.regex(/,?\s*/)),
|
||||
P.string(")"),
|
||||
(_0, grammar, _2) => grammar
|
||||
)
|
||||
switch (attribute) {
|
||||
case Boolean:
|
||||
return r.Boolean
|
||||
case ByteEntity:
|
||||
@@ -102,12 +108,6 @@ export default class Grammar {
|
||||
return r.String
|
||||
case SymbolEntity:
|
||||
return r.Symbol
|
||||
case UnionType:
|
||||
return attributeType.types
|
||||
.map(v => Grammar.getGrammarForType(r, Utility.getType(v)))
|
||||
.reduce((accum, cur) => !cur || accum === r.AttributeAnyValue
|
||||
? r.AttributeAnyValue
|
||||
: accum.or(cur))
|
||||
case VariableReferenceEntity:
|
||||
return r.VariableReference
|
||||
case Vector2DEntity:
|
||||
@@ -145,7 +145,10 @@ export default class Grammar {
|
||||
// Once the attribute name is known, look into entityType.attributes to get its type
|
||||
const attributeKey = attributeName.split(".")
|
||||
const attribute = Utility.objectGet(entityType.attributes, attributeKey)
|
||||
let attributeValueGrammar = Grammar.getGrammarForType(r, attribute, r.AttributeAnyValue)
|
||||
let attributeValueGrammar =
|
||||
attribute.constructor === Object && /** @type {AttributeInformation} */(attribute).serialized
|
||||
? r.String
|
||||
: Grammar.getGrammarForType(r, attribute, r.AttributeAnyValue)
|
||||
// Returns a setter function for the attribute
|
||||
return attributeValueGrammar.map(attributeValue =>
|
||||
entity => Utility.objectSet(entity, attributeKey, attributeValue, true)
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import Grammar from "./Grammar"
|
||||
import Parsimmon from "parsimmon"
|
||||
import SerializerFactory from "./SerializerFactory"
|
||||
import TypeInitialization from "../entity/TypeInitialization"
|
||||
import Utility from "../Utility"
|
||||
import IEntity from "../entity/IEntity"
|
||||
|
||||
/**
|
||||
* @typedef {import("../entity/IEntity").EntityConstructor} EntityConstructor
|
||||
* @typedef {import("../entity/TypeInitialization").AnyValue} AnyValue
|
||||
*/
|
||||
/**
|
||||
* @template {AnyValue} T
|
||||
* @typedef {import("../entity/TypeInitialization").AnyValueConstructor<T>} AnyValueConstructor
|
||||
* @typedef {import("../entity/IEntity").AnyValue} AnyValue
|
||||
* @typedef {import("../entity/IEntity").AnyValueConstructor<*>} AnyValueConstructor
|
||||
*/
|
||||
|
||||
/** @template {AnyValue} T */
|
||||
@@ -18,7 +15,7 @@ export default class ISerializer {
|
||||
|
||||
static grammar = Parsimmon.createLanguage(new Grammar())
|
||||
|
||||
/** @param {AnyValueConstructor<T>} entityType */
|
||||
/** @param {AnyValueConstructor} entityType */
|
||||
constructor(
|
||||
entityType,
|
||||
attributePrefix = "",
|
||||
@@ -76,7 +73,11 @@ export default class ISerializer {
|
||||
if (!serializer) {
|
||||
throw new Error(`Unknown value type "${type.name}", a serializer must be registered in the SerializerFactory class, check initializeSerializerFactory.js`)
|
||||
}
|
||||
return serializer.write(entity, value, insideString)
|
||||
return serializer.write(
|
||||
value instanceof IEntity ? value : entity,
|
||||
value,
|
||||
insideString
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,13 +91,12 @@ export default class ISerializer {
|
||||
let fullKey = key.concat("")
|
||||
const last = fullKey.length - 1
|
||||
const attributes = /** @type {EntityConstructor} */(object.constructor).attributes
|
||||
const keys =
|
||||
attributes ?
|
||||
Utility.mergeArrays(
|
||||
Object.getOwnPropertyNames(attributes),
|
||||
Object.getOwnPropertyNames(object)
|
||||
)
|
||||
: Object.getOwnPropertyNames(object)
|
||||
const keys = attributes
|
||||
? Utility.mergeArrays(
|
||||
Object.getOwnPropertyNames(attributes),
|
||||
Object.getOwnPropertyNames(object)
|
||||
)
|
||||
: Object.getOwnPropertyNames(object)
|
||||
for (const property of keys) {
|
||||
fullKey[last] = property
|
||||
const value = object[property]
|
||||
@@ -125,10 +125,9 @@ export default class ISerializer {
|
||||
}
|
||||
|
||||
showProperty(entity, object, attributeKey, attributeValue) {
|
||||
// @ts-expect-error
|
||||
const attributes = /** @type {EntityConstructor} */(this.entityType).attributes
|
||||
const attribute = Utility.objectGet(attributes, attributeKey)
|
||||
if (attribute instanceof TypeInitialization) {
|
||||
if (attribute.constructor === Object) {
|
||||
if (attribute.ignored) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/**
|
||||
* @typedef {import("../entity/IEntity").default} IEntity
|
||||
* @typedef {import("../entity/TypeInitialization").AnyValue} AnyValue
|
||||
* @typedef {import("../entity/IEntity").AnyValue} AnyValue
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {import("../entity/TypeInitialization").AnyValueConstructor<T>} AnyValueConstructor
|
||||
* @template {AnyValue} T
|
||||
* @typedef {import("../entity/IEntity").AnyValueConstructor<T>} AnyValueConstructor
|
||||
*/
|
||||
/**
|
||||
* @template {AnyValue} T
|
||||
@@ -16,6 +17,11 @@ export default class SerializerFactory {
|
||||
/** @type {Map<AnyValueConstructor<AnyValue>, ISerializer<AnyValue>>} */
|
||||
static #serializers = new Map()
|
||||
|
||||
/**
|
||||
* @template {AnyValue} T
|
||||
* @param {AnyValueConstructor<T>} entity
|
||||
* @param {ISerializer<T>} object
|
||||
*/
|
||||
static registerSerializer(entity, object) {
|
||||
SerializerFactory.#serializers.set(entity, object)
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import Utility from "../Utility"
|
||||
import GeneralSerializer from "./GeneralSerializer"
|
||||
|
||||
/** @typedef {import("../entity/TypeInitialization").AnyValue} AnyValue */
|
||||
/**
|
||||
* @template {AnyValue} T
|
||||
* @typedef {import("../entity/TypeInitialization").AnyValueConstructor<T>} AnyValueConstructor
|
||||
/**
|
||||
* @typedef {import("../entity/IEntity").AnyValue} AnyValue
|
||||
* @typedef {import("../entity/IEntity").AnyValueConstructor<*>} AnyValueConstructor
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {AnyValue} T
|
||||
* @extends {GeneralSerializer<T>}
|
||||
*/
|
||||
export default class ToStringSerializer extends GeneralSerializer {
|
||||
|
||||
/** @param {AnyValueConstructor<T>} entityType */
|
||||
/** @param {AnyValueConstructor} entityType */
|
||||
constructor(entityType) {
|
||||
super(undefined, entityType)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import RealUnitEntity from "../entity/UnitRealEntity"
|
||||
import RotatorEntity from "../entity/RotatorEntity"
|
||||
import SerializerFactory from "./SerializerFactory"
|
||||
import SimpleSerializationRotatorEntity from "../entity/SimpleSerializationRotatorEntity"
|
||||
import SimpleSerializationVector2DEntity from "../entity/SimpleSerializationVector2DEntity"
|
||||
import SimpleSerializationVectorEntity from "../entity/SimpleSerializationVectorEntity"
|
||||
import SymbolEntity from "../entity/SymbolEntity"
|
||||
import ToStringSerializer from "./ToStringSerializer"
|
||||
@@ -27,7 +28,11 @@ import Utility from "../Utility"
|
||||
import VariableReferenceEntity from "../entity/VariableReferenceEntity"
|
||||
import Vector2DEntity from "../entity/Vector2DEntity"
|
||||
import VectorEntity from "../entity/VectorEntity"
|
||||
import SimpleSerializationVector2DEntity from "../entity/SimpleSerializationVector2DEntity"
|
||||
|
||||
/**
|
||||
* @typedef {import("../entity/IEntity").AnySimpleValue} AnySimpleValue
|
||||
* @typedef {import("../entity/IEntity").AnyValue} AnyValue
|
||||
*/
|
||||
|
||||
export default function initializeSerializerFactory() {
|
||||
|
||||
@@ -44,11 +49,10 @@ export default function initializeSerializerFactory() {
|
||||
SerializerFactory.registerSerializer(
|
||||
Array,
|
||||
new CustomSerializer(
|
||||
/** @param {Array} array */
|
||||
/** @param {AnySimpleValue[]} array */
|
||||
(array, insideString) =>
|
||||
`(${array
|
||||
.map(v =>
|
||||
// @ts-expect-error
|
||||
SerializerFactory.getSerializer(Utility.getType(v)).serialize(v, insideString) + ","
|
||||
)
|
||||
.join("")
|
||||
|
||||
Reference in New Issue
Block a user