Skip to content

Instantly share code, notes, and snippets.

@petrroll
Created September 9, 2018 06:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save petrroll/6a78112a676b8bfc2260dcdab07f64b5 to your computer and use it in GitHub Desktop.
Save petrroll/6a78112a676b8bfc2260dcdab07f64b5 to your computer and use it in GitHub Desktop.
namespace netcore Messages
struct PingMsg{
}
struct OtherMsg{
}
union MsgEnvelope {
1: PingMsg ping
2: OtherMsg other
}
using System;
using System.Threading.Tasks;
using Messages;
using static System.Console;
namespace tst
{
class Program
{
static async Task Main(string[] args)
{
var msg = CreatePingMessage();
var buffer = await Serialization.Encode(msg);
// Do something with the message encoded in buffer
// Get buffer with whole message from somewhere & deserialize it
var recMsg = await Serialization.Decode<MsgEnvelope>(buffer);
if (recMsg.Ping != null) { Console.WriteLine("MSG: Ping received."); };
}
private static MsgEnvelope CreatePingMessage()
{
MsgEnvelope msg = new MsgEnvelope();
msg.Ping = new PingMsg();
return msg;
}
}
}
#include <glib.h>
#include <thrift/c_glib/protocol/thrift_binary_protocol.h>
#include <thrift/c_glib/protocol/thrift_protocol.h>
#include <thrift/c_glib/transport/thrift_memory_buffer.h>
#include <thrift/c_glib/transport/thrift_transport.h>
#include <stdio.h>
#include <stdlib.h>
#include "serialization.h"
#include "gen-c_glib/messages_types.h"
int serialization_encode(MsgEnvelope* message, /*out*/ char** buffer, int* bufferLen)
{
GError* error = NULL;
// ThriftMemoryBuffer is essentially just a thin wrapper around g_byte_array it creates
// ThriftProtocol is writer that serializes our message into transport -> g_byte_array
ThriftMemoryBuffer* transport = g_object_new(THRIFT_TYPE_MEMORY_BUFFER, NULL);
ThriftMemoryBufferClass* transportCls = THRIFT_MEMORY_BUFFER_GET_CLASS(transport);
ThriftProtocol* protocol = g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL);
MsgEnvelopeClass* msgCls = MSG_ENVELOPE_GET_CLASS(message);
// write message to transport
int encLength = THRIFT_STRUCT_CLASS(msgCls)->write(THRIFT_STRUCT(message), protocol, &error);
if (error != NULL)
{
return -1;
}
// read serialized bytes from the transport to our buffer
char* buff = calloc(encLength, sizeof(char));
int copiedLen = THRIFT_TRANSPORT_CLASS(transportCls)->read(THRIFT_TRANSPORT(transport), buff, encLength, &error);
if (error != NULL || encLength != copiedLen)
{
return -1;
}
*buffer = buff;
*bufferLen = encLength;
//cleanup objects
g_object_unref(protocol);
g_object_unref(transport);
return 0;
}
int serialization_decode(/*out*/ MsgEnvelope** message, char* buffer, int bufferLen)
{
GError* error = NULL;
// ThriftMemoryBuffer is essentially just a thin wrapper around g_byte_array it creates
// ThriftProtocol is writer that deserializes our message into transport -> g_byte_array
ThriftMemoryBuffer* transport = g_object_new(THRIFT_TYPE_MEMORY_BUFFER, NULL);
ThriftMemoryBufferClass* transportCls = THRIFT_MEMORY_BUFFER_GET_CLASS(transport);
// write our buffer to transport that is then used by protocol for serialization
ThriftProtocol* protocol = g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL);
THRIFT_TRANSPORT_CLASS(transportCls)->write(THRIFT_TRANSPORT(transport), buffer, bufferLen, &error);
if (error != NULL)
{
return -1;
}
// Create envelopes the buffer gets deserialized into
MsgEnvelope* msg = g_object_new(TYPE_MSG_ENVELOPE, NULL);
MsgEnvelopeClass* msgCls = MSG_ENVELOPE_GET_CLASS(msg);
int decLength = THRIFT_STRUCT_CLASS(msgCls)->read(THRIFT_STRUCT(msg), protocol, &error);
if (error != NULL || decLength != bufferLen)
{
return -1;
}
*message = msg;
//cleanup objects
g_object_unref(protocol);
g_object_unref(transport);
return 0;
}
int main()
{
char* buff;
int len;
MsgEnvelope* msgEnv;
// Create and encode message to a buffer
msgEnv = g_object_new(TYPE_MSG_ENVELOPE, NULL);
g_object_set(msgEnv,
"ping", g_object_new(TYPE_PING_MSG, NULL), // Don't assign directly into the struct (the __isset_ping doesn't get set that way)
NULL);
serialization_encode(msgEnv, &buff, &len);
// ...send buffer through socket or smth
free(buff);
g_object_unref(msgEnv); // Also unrefs & thus frees the Ping message
// Decode message from buffer
// ...fill buffer with the whole message & set len e.g. by readong from socket
serialization_decode(&msgEnv, buff, len);
free(buff);
//...work with the msgEnv, e.g. check if it contains ping
if (msgEnv->ping != NULL) { printf("Received a ping\n"); }
g_object_unref(msgEnv);
}
using System.Threading;
using System.Threading.Tasks;
using Thrift.Protocols;
using Thrift.Transports.Client;
namespace testrunner
{
static class Serialization
{
/// <summary>
/// Deserializes a byte[] as a message.
/// </summary>
/// <remarks>
/// Requires at least enough data for the message (might be given more) otherwise blocks indefenetly.
/// </remarks>
public static async Task<TMessage> Decode<TMessage>(byte[] data) where TMessage : TBase, new()
{
TMemoryBufferClientTransport transport = new TMemoryBufferClientTransport(data);
TBinaryProtocol protocol = new TBinaryProtocol(transport);
var msg = new TMessage();
await msg.ReadAsync(protocol, new CancellationToken());
return msg;
}
/// <summary>
/// Serializes a thrift message as byte[].
/// </summary>
public static async Task<byte[]> Encode<TMessage>(TMessage msg) where TMessage : TBase
{
TMemoryBufferClientTransport transport = new TMemoryBufferClientTransport();
TProtocol protocol = new TBinaryProtocol(transport);
await msg.WriteAsync(protocol, new CancellationToken());
byte[] buff = transport.GetBuffer();
return buff;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment