corda/experimental/cpp-serializer/bin/main.cxx
Katelyn Baker 913ba1d46e
NOTICK - Initial work on a non JVM (C++) serialiser (#5368)
Currently, it's more of a blob inspector than a full-blown
implementation, but this code does have the ability to understand a Corda
serialized blob and build a set of deserialisers to handle a blob. It
does this in the same way the native java implementation works by
interrogating the types (as per the definition in the envelope) and
building recursive type readers that are able to pull the relevant
information out of the byte stream.

Lots of future work to undertake, but as a starting point its a little
bit useful with the scope it could be made much more useful with some
work.
2019-08-15 21:16:20 +01:00

116 lines
3.0 KiB
C++

#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstddef>
#include <assert.h>
#include <string.h>
#include <proton/types.h>
#include <proton/codec.h>
#include <sys/stat.h>
#import "debug.h"
#include "proton/proton_wrapper.h"
#include "amqp/AMQPHeader.h"
#include "amqp/AMQPSectionId.h"
#include "amqp/descriptors/AMQPDescriptorRegistory.h"
#include "amqp/schema/Envelope.h"
#include "CompositeFactory.h"
/******************************************************************************/
void
data_and_stop(std::ifstream & f_, ssize_t sz) {
char * blob = new char[sz];
memset (blob, 0, sz);
f_.read(blob, sz);
pn_data_t * d = pn_data(sz);
// returns how many bytes we processed which right now we don't care
// about but I assume there is a case where it doesn't process the
// entire file
auto rtn = pn_data_decode (d, blob, sz);
assert (rtn == sz);
std::unique_ptr<amqp::internal::schema::Envelope> envelope;
if (pn_data_is_described(d)) {
proton::auto_enter p (d);
auto a = pn_data_get_ulong(d);
envelope.reset (
dynamic_cast<amqp::internal::schema::Envelope *> (
amqp::AMQPDescriptorRegistory[a]->build(d).release()));
DBG (std::cout << std::endl << "Types in schema: " << std::endl
<< *envelope << std::endl); // NOLINT
}
CompositeFactory cf;
cf.process (envelope->schema());
auto reader = cf.byDescriptor (envelope->descriptor());
assert (reader);
{
// move to the actual blob entry in the tree - ideally we'd have
// saved this on the Envelope but that's not easily doable as we
// can't grab an actual copy of our data pointer
proton::auto_enter p (d);
pn_data_next (d);
proton::is_list (d);
assert (pn_data_get_list (d) == 3);
{
proton::auto_enter p (d);
// We wrap our output like this to make sure it's valid JSON to
// facilitate easy pretty printing
std::cout
<< reader->dump ("{ Parsed", d, envelope->schema())->dump()
<< " }" << std::endl;
}
}
}
/******************************************************************************/
int
main (int argc, char **argv) {
struct stat results { };
if (stat(argv[1], &results) != 0) {
return EXIT_FAILURE;
}
std::ifstream f (argv[1], std::ios::in | std::ios::binary);
std::array<char, 7> header { };
f.read(header.data(), 7);
if (header != amqp::AMQP_HEADER) {
std::cerr << "Bad Header in blob" << std::endl;
return EXIT_FAILURE;
}
amqp::amqp_section_id_t encoding;
f.read((char *)&encoding, 1);
if (encoding == amqp::DATA_AND_STOP) {
data_and_stop(f, results.st_size - 8);
} else {
std::cerr << "BAD ENCODING " << encoding << " != " << amqp::DATA_AND_STOP << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
/******************************************************************************/