From ddc1d65befcc98da57c0a29d314de4f11e3c0760 Mon Sep 17 00:00:00 2001 From: Philippe Pittoli Date: Fri, 3 Feb 2023 04:06:52 +0100 Subject: [PATCH] Crystal bindings: CBOR utils. --- zig-impl/crystal/some-crystal-app/src/cbor.cr | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 zig-impl/crystal/some-crystal-app/src/cbor.cr diff --git a/zig-impl/crystal/some-crystal-app/src/cbor.cr b/zig-impl/crystal/some-crystal-app/src/cbor.cr new file mode 100644 index 0000000..5dec5e9 --- /dev/null +++ b/zig-impl/crystal/some-crystal-app/src/cbor.cr @@ -0,0 +1,71 @@ +require "cbor" + +# IPC::CBOR is the root class for all exchanged messages (using CBOR). +# IPC::CBOR inherited classes have a common 'type' class attribute, +# which enables to find the right IPC::CBOR+ class given a TypedMessage's type. + +# All transfered messages are typed messages. +# TypedMessage = u8 type (= IPC::CBOR+ class type) + CBOR content. +# 'CBOR content' being a serialized IPC::CBOR+ class. + +# Conventionally, IPC::CBOR+ classes have a 'handle' method to process incoming messages. +class IPC::CBOR + include ::CBOR::Serializable + + class_property type = -1 + property id : ::CBOR::Any? + + def type + @@type + end + + macro message(id, type, &block) + class {{id}} < ::IPC::CBOR + include ::CBOR::Serializable + + @@type = {{type}} + + {{yield}} + end + end +end + +class IPC + # Schedule messages contained into IPC::CBOR+. + def schedule(fd : Int32, message : IPC::CBOR) + typed_msg = IPCMessage::TypedMessage.new message.type.to_u8, message.to_cbor + schedule fd, typed_msg + end + def write(fd : Int32, message : IPC::CBOR) + typed_msg = IPCMessage::TypedMessage.new message.type.to_u8, message.to_cbor + write fd, typed_msg + end +end + +# CAUTION: Only use this method on an Array(IPC::CBOR.class) +class Array(T) + def parse_ipc_cbor(message : IPC::Message) : IPC::CBOR? + message_type = find &.type.==(message.utype) + + if message_type.nil? + raise "invalid message type (#{message.utype})" + end + + message_type.from_cbor message.payload + end +end + +# CAUTION: only use this method on an Array(IPC::CBOR.class). +class Array(T) + def parse_ipc_cbor(message : IPCMessage::TypedMessage) : IPC::CBOR? + message_type = find &.type.==(message.type) + + payload = message.payload + + if message_type.nil? + raise "invalid message type (#{message.type})" + end + + message_type.from_cbor payload + end +end