mirror of
https://github.com/corda/corda.git
synced 2024-12-22 06:17:55 +00:00
913ba1d46e
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.
116 lines
3.0 KiB
C++
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;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|