From f072525dd41d2f1d81755b89c1dec1ed9cb54101 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Sat, 20 Jan 2024 15:28:36 +0200 Subject: [PATCH] syndesizer: add XML translator --- README.md | 20 +++++++++++++++++++ assertions.prs | 2 ++ config.prs | 4 ++++ src/schema/assertions.nim | 8 ++++++-- src/schema/config.nim | 8 ++++++++ src/syndesizer.nim | 4 +++- src/syndesizer/xml_translator.nim | 33 +++++++++++++++++++++++++++++++ syndicate_utils.nimble | 2 +- 8 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 src/syndesizer/xml_translator.nim diff --git a/README.md b/README.md index 2db3392..8d97b1b 100644 --- a/README.md +++ b/README.md @@ -249,6 +249,26 @@ $websocketspace ? [ $websocketspace #f> ] ``` +### XML translator + +Translates between Preserves and XML according to the [Conventions for Common Data Types](https://preserves.dev/conventions.html). + +Examples: +- ` hello world!" >>` +- `` +- `>" #f>` + +``` +# Configuration example +? [ + $ds ? _> $config [ + $config > + $config ? ?cap> [ + $cap + ] + ] +] +``` --- diff --git a/assertions.prs b/assertions.prs index ed283c4..158d2fb 100644 --- a/assertions.prs +++ b/assertions.prs @@ -6,3 +6,5 @@ FileSystemUsage = . # an exception for which is pulsed every periodSec. # The pulse resolution is no more than one millisecond. Pulse = . + +XmlTranslation = . diff --git a/config.prs b/config.prs index fad1099..ca5e4a2 100644 --- a/config.prs +++ b/config.prs @@ -47,5 +47,9 @@ WebsocketArguments = . +XmlTranslatorArguments = . + # Reused from syndicate-protocols/transportAddress Tcp = . diff --git a/src/schema/assertions.nim b/src/schema/assertions.nim index d43905c..afdbd85 100644 --- a/src/schema/assertions.nim +++ b/src/schema/assertions.nim @@ -7,12 +7,16 @@ type `periodSec`*: float64 `proxy`* {.preservesEmbedded.}: Value + XmlTranslation* {.preservesRecord: "xml-translation".} = object + `xml`*: string + `pr`*: Value + FileSystemUsage* {.preservesRecord: "file-system-usage".} = object `path`*: string `size`*: BiggestInt -proc `$`*(x: Pulse | FileSystemUsage): string = +proc `$`*(x: Pulse | XmlTranslation | FileSystemUsage): string = `$`(toPreserves(x)) -proc encode*(x: Pulse | FileSystemUsage): seq[byte] = +proc encode*(x: Pulse | XmlTranslation | FileSystemUsage): seq[byte] = encode(toPreserves(x)) diff --git a/src/schema/config.nim b/src/schema/config.nim index 421cbe5..3230a6d 100644 --- a/src/schema/config.nim +++ b/src/schema/config.nim @@ -54,6 +54,12 @@ type CacheArguments* {.preservesRecord: "cache".} = object `field0`*: CacheArgumentsField0 + XmlTranslatorArgumentsField0* {.preservesDictionary.} = object + `dataspace`* {.preservesEmbedded.}: EmbeddedRef + + XmlTranslatorArguments* {.preservesRecord: "xml-translator".} = object + `field0`*: XmlTranslatorArgumentsField0 + PostgreConnectionParameter* {.preservesTuple.} = object `key`*: string `val`*: string @@ -82,6 +88,7 @@ proc `$`*(x: WebsocketArguments | JsonTranslatorArguments | FileSystemUsageArguments | SqliteArguments | CacheArguments | + XmlTranslatorArguments | PostgreConnectionParameter | PostgreArguments | PulseArguments | @@ -95,6 +102,7 @@ proc encode*(x: WebsocketArguments | JsonTranslatorArguments | FileSystemUsageArguments | SqliteArguments | CacheArguments | + XmlTranslatorArguments | PostgreConnectionParameter | PostgreArguments | PulseArguments | diff --git a/src/syndesizer.nim b/src/syndesizer.nim index 79871df..66b489e 100644 --- a/src/syndesizer.nim +++ b/src/syndesizer.nim @@ -16,7 +16,8 @@ import ./syndesizer/[ json_translator, pulses, webhooks, - websockets] + websockets, + xml_translator] when withPostgre: import ./syndesizer/postgre_actor @@ -34,6 +35,7 @@ runActor("syndesizer") do (turn: var Turn; root: Cap): discard spawnPulseActor(turn, root) discard spawnWebhookActor(turn, root) discard spawnWebsocketActor(turn, root) + discard spawnXmlTranslator(turn, root) when withPostgre: discard spawnPostgreActor(turn, root) when withSqlite: diff --git a/src/syndesizer/xml_translator.nim b/src/syndesizer/xml_translator.nim new file mode 100644 index 0000000..24fdd12 --- /dev/null +++ b/src/syndesizer/xml_translator.nim @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: ☭ Emery Hemingway +# SPDX-License-Identifier: Unlicense + +import std/[options, parsexml, xmlparser, xmltree] +import preserves, preserves/xmlhooks +import syndicate + +import ../schema/[assertions, config] + +proc translateXml(s: string): XmlTranslation = + result.xml = s + try: result.pr = result.xml.parseXml({allowUnquotedAttribs}).toPreservesHook + except XmlError: discard + +proc translatePreserves(pr: Value): XmlTranslation {.gcsafe.} = + result.pr = pr + var xn = result.pr.preservesTo(XmlNode) + if xn.isSome: result.xml = $get(xn) + +proc spawnXmlTranslator*(turn: var Turn; root: Cap): Actor {.discardable.} = + spawn("xml-translator", turn) do (turn: var Turn): + during(turn, root, ?:XmlTranslatorArguments) do (ds: Cap): + let obsPat = ?Observe(pattern: !XmlTranslation) + during(turn, ds, obsPat ?? {0: grab()}) do (xs: Literal[string]): + publish(turn, ds, translateXml(xs.value)) + during(turn, ds, obsPat ?? {1: grab()}) do (pr: Literal[Value]): + publish(turn, ds, translatePreserves(pr.value)) + +when isMainModule: + import syndicate/relays + runActor("main") do (turn: var Turn; root: Cap): + connectStdio(turn, root) + spawnXmlTranslator(turn, root) diff --git a/syndicate_utils.nimble b/syndicate_utils.nimble index c86caf3..a419894 100644 --- a/syndicate_utils.nimble +++ b/syndicate_utils.nimble @@ -1,6 +1,6 @@ # Package -version = "20240118" +version = "20240120" author = "Emery Hemingway" description = "Utilites for Syndicated Actors and Synit" license = "unlicense"