Files
node-metaverse/lib/classes/llsd/LLSDXML.ts
2025-01-17 23:53:31 +00:00

284 lines
8.1 KiB
TypeScript

import type { LLSDType } from "./LLSDType";
import { LLSDMap } from "./LLSDMap";
import { LLSDArray } from "./LLSDArray";
import { LLSDInteger } from "./LLSDInteger";
import { LLSDReal } from "./LLSDReal";
import { UUID } from "../UUID";
import { LLSDURI } from "./LLSDURI";
export class LLSDXML
{
public static parseValue(element: Record<string, unknown>[]): LLSDType
{
if (element.length !== 1)
{
throw new Error('Exactly one key expected')
}
const keys = Object.keys(element[0]);
switch(keys[0])
{
case 'map':
{
return LLSDMap.parseXML(element[0].map as Record<string, unknown>[]);
}
case 'string':
{
const strNode = element[0].string as Record<string, unknown>[];
if (strNode.length !== 1)
{
return '';
}
const [node] = strNode;
if (node['#text'] === undefined)
{
throw new Error('String is not a text node')
}
return String(node['#text']);
}
case 'uuid':
{
const strNode = element[0].uuid as Record<string, unknown>[];
if (strNode.length !== 1)
{
return UUID.zero();
}
const [node] = strNode;
if (node['#text'] === undefined)
{
throw new Error('UUID is not a text node')
}
return new UUID(String(node['#text']));
}
case 'uri':
{
const strNode = element[0].uri as Record<string, unknown>[];
if (strNode.length !== 1)
{
return new LLSDURI('');
}
const [node] = strNode;
if (node['#text'] === undefined)
{
throw new Error('URI is not a text node')
}
return new LLSDURI(String(node['#text']));
}
case 'date':
{
const strNode = element[0].date as Record<string, unknown>[];
if (strNode.length !== 1)
{
return new Date(0);
}
const [node] = strNode;
if (node['#text'] === undefined)
{
throw new Error('Date is not a text node')
}
return new Date(String(node['#text']));
}
case 'undef':
{
return null;
}
case 'binary':
{
const strNode = element[0].binary as Record<string, unknown>[];
if (strNode.length !== 1)
{
return Buffer.alloc(0);
}
const [node] = strNode;
if (node['#text'] === undefined)
{
throw new Error('Binary is not a text node')
}
return Buffer.from(String(node['#text']), 'base64');
}
case 'boolean':
{
const strNode = element[0].boolean as Record<string, unknown>[];
if (strNode.length !== 1)
{
return false;
}
const [node] = strNode;
if (node['#text'] === undefined)
{
throw new Error('Boolean is not a text node')
}
const val = String(node['#text']);
return val.toLowerCase() === '1' || val === 'true';
}
case 'integer':
{
const strNode = element[0].integer as Record<string, unknown>[];
if (strNode.length !== 1)
{
return new LLSDInteger(0);
}
const [node] = strNode;
if (node['#text'] === undefined)
{
throw new Error('Integer is not a text node')
}
return new LLSDInteger(parseInt(String(node['#text']), 10));
}
case 'real':
{
const strNode = element[0].real as Record<string, unknown>[];
if (strNode.length !== 1)
{
return new LLSDReal(0);
}
const [node] = strNode;
if (node['#text'] === undefined)
{
throw new Error('Real is not a text node')
}
return new LLSDReal(String(node['#text']));
}
case 'array':
{
return LLSDArray.parseXML(element[0].array as Record<string, unknown>[]);
}
default:
throw new Error('Unexpected XML element: ' + keys[0]);
}
}
public static encodeValue(value: LLSDType): unknown
{
if (value instanceof LLSDMap)
{
return value.toXML();
}
else if (value instanceof LLSDInteger)
{
return {
'integer': [{
'#text': value.valueOf()
}]
};
}
else if (value instanceof LLSDReal)
{
const val = value.valueOf();
if (isNaN(val))
{
return {
'real': [{
'#text': 'NaNQ'
}]
};
}
else if (val === -Infinity)
{
return {
'real': [{
'#text': '-Infinity'
}]
};
}
else if (val === Infinity)
{
return {
'real': [{
'#text': '+Infinity'
}]
};
}
else if (Object.is(val, -0))
{
return {
'real': [{
'#text': '-Zero'
}]
};
}
else if (val === 0)
{
return {
'real': [{
'#text': '+Zero'
}]
};
}
return {
'real': [{
'#text': val
}]
};
}
else if (value instanceof UUID)
{
return {
'uuid': [{
'#text': value.toString()
}]
};
}
else if (value instanceof LLSDURI)
{
return {
'uri': [{
'#text': value.valueOf()
}]
};
}
else if (value instanceof Buffer)
{
return {
'binary': [{
'#text': value.toString('base64')
}]
};
}
else if (value instanceof Date)
{
return {
'date': [{
'#text': value.toISOString()
}]
};
}
else if (value === null)
{
return {
'undef': []
};
}
else if (value === true)
{
return {
'boolean': [{
'#text': true
}]
};
}
else if (value === false)
{
return {
'boolean': []
};
}
else if (typeof value === 'string')
{
return {
'string': [{
'#text': value.toString()
}]
};
}
else if (Array.isArray(value))
{
return LLSDArray.toXML(value);
}
else
{
throw new Error('Unknown type: ' + String(value));
}
}
}