syndesizer: add XML translator

This commit is contained in:
Emery Hemingway 2024-01-20 15:28:36 +02:00
parent 2d3189288f
commit f072525dd4
8 changed files with 77 additions and 4 deletions

View File

@ -249,6 +249,26 @@ $websocketspace ? <connected $websocketUrl> [
<bind <ref { oid: "websocket" key: #x"" }> $websocketspace #f>
]
```
### XML translator
Translates between Preserves and XML according to the [Conventions for Common Data Types](https://preserves.dev/conventions.html).
Examples:
- `<xml-translation "<foo a=\"1\"> <bar>hello world!</bar></foo>" <foo {"a": 1}<bar "hello world!">>>`
- `<xml-translation "" [#t #f]>`
- `<xml-translation "<<</>>" #f>`
```
# Configuration example
? <sharedspace ?ds> [
$ds ? <Observe <rec xml-translation _> _> $config [
$config <require-service <daemon syndesizer>>
$config ? <service-object <daemon syndesizer> ?cap> [
$cap <xml-translator { dataspace: $ds }>
]
]
]
```
---

View File

@ -6,3 +6,5 @@ FileSystemUsage = <file-system-usage @path string @size int>.
# an exception for <Observe …> which is pulsed every periodSec.
# The pulse resolution is no more than one millisecond.
Pulse = <pulse @periodSec double @proxy #!any>.
XmlTranslation = <xml-translation @xml string @pr any>.

View File

@ -47,5 +47,9 @@ WebsocketArguments = <websocket {
url: string
}>.
XmlTranslatorArguments = <xml-translator {
dataspace: #!any
}>.
# Reused from syndicate-protocols/transportAddress
Tcp = <tcp @host string @port int>.

View File

@ -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))

View File

@ -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 |

View File

@ -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:

View File

@ -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)

View File

@ -1,6 +1,6 @@
# Package
version = "20240118"
version = "20240120"
author = "Emery Hemingway"
description = "Utilites for Syndicated Actors and Synit"
license = "unlicense"