From d2ab2602554dbae2d8dede0f33685b4fc9270336 Mon Sep 17 00:00:00 2001 From: Philippe Pittoli Date: Wed, 1 Feb 2023 11:08:05 +0100 Subject: [PATCH] Crystal bindings: (typed|untyped) message serialization. --- .../crystal/some-crystal-app/src/message.cr | 68 +++++++++++++++---- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/zig-impl/crystal/some-crystal-app/src/message.cr b/zig-impl/crystal/some-crystal-app/src/message.cr index 7b48fc5..37f0fed 100644 --- a/zig-impl/crystal/some-crystal-app/src/message.cr +++ b/zig-impl/crystal/some-crystal-app/src/message.cr @@ -1,25 +1,69 @@ -# TODO: +# TODO: tests. + +# Serialization (and deserialization) doesn't refer to IPC format. +# IPC serialization format: 'length + value' +# IPCMessage serialization: 'value' +# 'Value' is: +# - simply the message payload for UntypedMessage +# - type (u8) + payload for TypedMessage module IPCMessage class UntypedMessage - @fd : Int32 - @payload : Bytes - def initialize(@fd, string : String) + property payload : Bytes + def initialize(string : String) @payload = Bytes.new string.to_unsafe, string.size end - def initialize(@fd, @payload) + def initialize(@payload) + end + + def self.deserialize(payload) : UntypedMessage + IPCMessage::UntypedMessage.new payload + end + + def serialize + @payload end end + # WARNING: you can only have up to 256 types. class TypedMessage < UntypedMessage - @type : UInt8? = nil - def initialize(fd, @type, string : String) - super fd, string + property type : UInt8? = nil + def initialize(@type, string : String) + super string end - def initialize(fd, @type, payload) - super fd, payload + def initialize(@type, payload) + super payload end - def initialize(fd, payload) - super fd, payload + def initialize(payload) + super payload + end + + def self.deserialize(bytes : Bytes) : TypedMessage? + if bytes.size == 0 + nil + else + type = bytes[0] + IPCMessage::TypedMessage.new type, bytes[1..] + end + end + + def serialize + bytes = Bytes.new (1 + @payload.size) + type = @type + bytes[0] = type.nil? ? 0 : type + bytes[1..].copy_from @payload + bytes end end end + +# Send both typed and untyped messages. +class IPC + def schedule(fd : Int32, m : (IPCMessage::TypedMessage | IPCMessage::UntypedMessage)) + payload = m.serialize + schedule fd, payload, payload.size + end + def write(fd : Int32, m : (IPCMessage::TypedMessage | IPCMessage::UntypedMessage)) + payload = m.serialize + write fd, payload, payload.size + end +end