UNPKG

@hpx7/delta-pack

Version:

A TypeScript code generator and runtime for binary serialization based on schemas.

78 lines (77 loc) 3.15 kB
import yaml from "yaml"; import { ArrayType, BooleanType, EnumType, FloatType, IntType, ObjectType, OptionalType, RecordType, ReferenceType, StringType, UIntType, UnionType, } from "./schema"; import { mapValues } from "./helpers"; export function parseSchemaYml(yamlContent) { // the yaml schema is a mapping from type names to type definitions const schema = yaml.parse(yamlContent); // recursive function to parse a type definition function parseType(value) { if (Array.isArray(value)) { // could be a union type or an enum type const values = value; // it's a union type if all values are references to other types in the schema if (values.every((v) => v in schema)) { return UnionType(values.map((v) => ReferenceType(v))); } // otherwise, it's an enum type return EnumType(values); } if (typeof value === "object") { // object type const properties = {}; for (const [propKey, propValue] of Object.entries(value)) { properties[propKey] = parseType(propValue); } return ObjectType(properties); } if (typeof value === "string") { // map type, array type, optional type, reference type, or primitive type if (value.includes(",")) { // map type const parts = value.split(",").map((s) => s.trim()); if (parts.length !== 2) { throw new Error(`Map type must have exactly 2 types, got: ${value}`); } const [keyTypeStr, valueTypeStr] = parts; const keyType = parseType(keyTypeStr); const valueType = parseType(valueTypeStr); return RecordType(keyType, valueType); } if (value.endsWith("[]")) { // array type const itemTypeStr = value.slice(0, -2); const childType = parseType(itemTypeStr); return ArrayType(childType); } if (value.endsWith("?")) { // optional type const itemTypeStr = value.slice(0, -1); const childType = parseType(itemTypeStr); return OptionalType(childType); } if (value in schema) { // reference type return ReferenceType(value); } // primitive type if (value === "string") { return StringType(); } else if (value === "int") { return IntType(); } else if (value === "uint") { return UIntType(); } else if (value === "float") { return FloatType(); } else if (value === "boolean") { return BooleanType(); } } throw new Error(`Unsupported type format: ${value}`); } // parse the type definitions return mapValues(schema, (value) => parseType(value)); }