Serialization work in progress

This commit is contained in:
barsdeveloper
2021-10-17 21:54:40 +02:00
parent 16fd34fa84
commit 9caea42101
29 changed files with 635 additions and 242 deletions

View File

@@ -0,0 +1,9 @@
import Serializer from "./Serializer";
export default class ObjectSerializer extends Serializer {
write(object) {
let result = `Pin (${this.constructor.subWrite('', this)})`
return result
}
}

View File

@@ -0,0 +1,57 @@
import Parsimmon from "parsimmon"
import PinEntity from "../entity/PinEntity"
import Utility from "../Utility"
import ReferenceTypeName from "./ReferenceTypeName"
let P = Parsimmon
export default class PinGrammar {
static pinEntity = new PinEntity()
Null = _ => P.string("()").map(() => null).desc("null value.")
None = _ => P.string("None").map(() => new ReferenceTypeName("None")).desc('None value')
ReferencePath = _ => P.regex(/[a-zA-Z_]/).sepBy1(P.string(".")).tieWith(".").sepBy1(Parsimmon.string("/")).tieWith("/")
Reference = r => r.Word.skip(P.optWhitespace).then(r.ReferencePath)
Word = _ => P.regex(/[a-zA-Z]+/)
Guid = _ => P.regex(/[0-9a-zA-Z]{32}/).desc("a 32 digit hexadecimal value")
String = _ => P.regex(/(?:[^"\\]|\\")*/).wrap(P.string('"'), P.string('"')).desc('a string value, with possibility to escape the quote symbol (") using \"')
Boolean = _ => P.string("True").or(P.string("False")).map(v => v === "True" ? true : false).desc("either True or False")
AttributeName = r => r.Word.sepBy1(P.string(".")).tieWith(".")
AttributeValue = r => P.alt(r.Null, r.None, r.Boolean, Reference, r.String, r.Guid)
Attribute = r => P.seqMap(
r.AttributeName,
P.string("=").trim(P.optWhitespace),
r.AttributeValue,
/**
*
* @param {String} name The key PinEntity
* @param {*} _
* @param {*} value
* @returns
*/
(name, _, value) =>
/**
* Sets the property name name in the object pinEntity to the value provided
* @param {PinEntity} pinEntity
*/
(pinEntity) => Utility.objectSet(name.split('.'), value, pinEntity)
)
Pin = r => {
return P.seqObj(
P.string("Pin"),
P.optWhitespace,
P.string("("),
[
"attributes",
r.Attribute
.trim(P.optWhitespace)
.sepBy(P.string(","))
.skip(P.regex(/,?/).then(P.optWhitespace)) // Optional trailing comma
],
P.string(')')
).map(object => {
let result = new PinEntity()
object.attributes.forEach(attributeSetter => attributeSetter(result))
return result
})
}
}

View File

@@ -0,0 +1,22 @@
import Parsimmon from "parsimmon"
import PinGrammar from "./PinGrammar"
import Serializer from "./Serializer"
export default class PinSerializer extends Serializer {
static pinGrammar = Parsimmon.createLanguage(new PinGrammar())
read(value) {
const parseResult = PinSerializer.pinGrammar.Pin.parse(value)
if (!parseResult.status) {
console.error("Error when trying to parse the pin.")
return parseResult
}
return parseResult.value
}
write(object) {
let result = `Pin (${Serializer.subWrite('', object)})`
return result
}
}

View File

@@ -0,0 +1,37 @@
export default class ReferenceTypeName {
/**
*
* @param {String} reference
* @returns
*/
static splitReference(reference) {
const pathBegin = reference.search(/['"]/)
const referenceType = reference.substr(0, pathBegin > 0 ? pathBegin : undefined) // reference example Class'"/Script/Engine.PlayerCameraManager"'
const referencePath = pathBegin > 0 ? reference.substr(pathBegin) : ""
switch (referenceType) {
case "None":
if (referencePath.length > 0) {
return false // None cannot have a path
}
default:
return [referenceType, referencePath]
}
}
/**
*
* @param {String} reference
*/
constructor(reference) {
reference = ReferenceTypeName.splitReference(reference)
if (!reference) {
throw new Error('Invalid reference: ' + reference)
}
this.reference = reference
}
toString() {
return this.value
}
}

View File

@@ -0,0 +1,51 @@
import Parsimmon from "parsimmon"
import PinGrammar from "./PinGrammar"
export default class Serializer {
static writeValue(value) {
if (value?.constructor?.name === 'Function') {
return this.writeValue(value())
}
// No quotes
if (value === null) {
return '()'
}
if (value?.constructor?.name === 'Boolean') {
return value ? 'True' : 'False'
}
if (value?.constructor?.name === 'ETypesNames' || value?.constructor?.name === 'FGuid') {
return value.toString()
}
// Quotes
if (value?.constructor?.name === 'String') {
return `"${value}"`
}
}
static subWrite(prefix, object) {
let result = ""
prefix += prefix != "" ? "." : ""
const fullPropertyName = prefix + property
for (const property in object) {
if (object[property]?.constructor?.name === 'Object') {
result += Serializer.subWrite(fullPropertyName, object[property])
} else if (!object.constructor.optionalKeys.contains(fullPropertyName)) {
result += `${fullPropertyName}=${Serializer.writeValue(object[property])},`
}
}
return result
}
/**
*
* @param {String} value
*/
read(value) {
//Parsimmon.length
}
write(object) {
return ''
}
}

View File

@@ -0,0 +1,15 @@
import ObjectEntity from "../entity/ObjectEntity";
import PinEntity from "../entity/PinEntity";
import SerializeObject from "./ObjectSerialize";
import PinSerializer from "./PinSerializer";
export default class SerializerFactory {
static serializers = new Map([
[PinEntity.prototype.constructor.name, PinSerializer],
[ObjectEntity.prototype.constructor.name, SerializeObject]
])
createSerializer(object) {
return SerializerFactory.serializers.get(object.constructor.name)
}
}