NOTICK: Add BlobWriter and Schema Dumper

The Blob Writer is a small kotlin app that allows arbitrary things to be serialized and then those bytes written to a file, quite useful for working on non JVM parsing of such things.

Along a similar vein, add a schema dumper alongside the blob-inspector to highlight the contents of the header
This commit is contained in:
Katelyn Baker
2019-08-26 20:59:56 +01:00
committed by GitHub
parent dbce25b575
commit 7b308eb45f
46 changed files with 1290 additions and 458 deletions

View File

@ -5,8 +5,15 @@ include_directories (.)
set (amqp_sources
CompositeFactory.cxx
descriptors/AMQPDescriptor.cxx
descriptors/AMQPDescriptors.cxx
descriptors/AMQPDescriptorRegistory.cxx
descriptors/corda-descriptors/FieldDescriptor.cxx
descriptors/corda-descriptors/SchemaDescriptor.cxx
descriptors/corda-descriptors/ObjectDescriptor.cxx
descriptors/corda-descriptors/EnvelopeDescriptor.cxx
descriptors/corda-descriptors/CompositeDescriptor.cxx
descriptors/corda-descriptors/RestrictedDescriptor.cxx
schema/Schema.cxx
schema/Field.cxx
schema/Envelope.cxx
@ -16,14 +23,14 @@ set (amqp_sources
schema/restricted-types/List.cxx
schema/AMQPTypeNotation.cxx
reader/Reader.cxx
reader/RestrictedReader.cxx
reader/CompositeReader.cxx
reader/PropertyReader.cxx
reader/property-readers/StringPropertyReader.cxx
reader/CompositeReader.cxx
reader/RestrictedReader.cxx
reader/property-readers/IntPropertyReader.cxx
reader/property-readers/DoublePropertyReader.cxx
reader/property-readers/LongPropertyReader.cxx
reader/property-readers/BoolPropertyReader.cxx
reader/property-readers/DoublePropertyReader.cxx
reader/property-readers/StringPropertyReader.cxx
reader/restricted-readers/ListReader.cxx
)

View File

@ -0,0 +1,102 @@
#include "AMQPDescriptor.h"
#include <sstream>
#include <amqp/descriptors/corda-descriptors/EnvelopeDescriptor.h>
#include "proton/proton_wrapper.h"
#include "AMQPDescriptorRegistory.h"
/******************************************************************************/
namespace amqp::internal {
std::ostream &
operator<<(std::ostream &stream_, const amqp::internal::AutoIndent &ai_) {
stream_ << ai_.indent;
return stream_;
}
}
/******************************************************************************/
const std::string &
amqp::internal::
AMQPDescriptor::symbol() const {
return m_symbol;
}
/******************************************************************************/
std::unique_ptr<amqp::AMQPDescribed>
amqp::internal::
AMQPDescriptor::build (pn_data_t *) const {
throw std::runtime_error ("Should never be called");
}
/******************************************************************************/
inline void
amqp::internal::
AMQPDescriptor::read (
pn_data_t * data_,
std::stringstream & ss_
) const {
return read (data_, ss_, AutoIndent());
}
/******************************************************************************/
void
amqp::internal::
AMQPDescriptor::read (
pn_data_t * data_,
std::stringstream & ss_,
const AutoIndent & ai_
) const {
switch (pn_data_type (data_)) {
case PN_DESCRIBED : {
ss_ << ai_ << "DESCRIBED: " << std::endl;
{
AutoIndent ai { ai_ } ; // NOLINT
proton::auto_enter p (data_);
switch (pn_data_type (data_)) {
case PN_ULONG : {
auto key = proton::readAndNext<u_long>(data_);
ss_ << ai << "key : "
<< key << " :: " << amqp::stripCorda(key)
<< " -> "
<< amqp::describedToString ((uint64_t )key)
<< std::endl;
proton::is_list (data_);
ss_ << ai << "list : entries: "
<< pn_data_get_list(data_)
<< std::endl;
AMQPDescriptorRegistory[key]->read (data_, ss_, ai);
break;
}
case PN_SYMBOL : {
ss_ << ai << "blob: bytes: "
<< pn_data_get_symbol(data_).size
<< std::endl;
break;
}
default : {
throw std::runtime_error (
"Described type should only contain long or blob");
}
}
}
break;
}
default : {
throw std::runtime_error ("Can only dispatch described objects");
}
}
}
/******************************************************************************/

View File

@ -16,6 +16,30 @@
struct pn_data_t;
/******************************************************************************
*
* amqp::internal::AMQPDescribed
*
******************************************************************************/
namespace amqp::internal {
class AutoIndent {
private :
std::string indent;
public :
AutoIndent() : indent { "" } { }
AutoIndent (const AutoIndent & ai_)
: indent { ai_.indent + " "}
{ }
friend std::ostream &
operator << (std::ostream & stream_, const AutoIndent & ai_);
};
}
/******************************************************************************
*
* amqp::internal::AMQPDescriptor
@ -35,18 +59,27 @@ namespace amqp::internal {
, m_val (-1)
{ }
AMQPDescriptor(std::string symbol_, int val_)
AMQPDescriptor (std::string symbol_, int val_)
: m_symbol (std::move (symbol_))
, m_val (val_)
{ }
virtual ~AMQPDescriptor() = default;
const std::string & symbol() const { return m_symbol; }
const std::string & symbol() const;
void validateAndNext (pn_data_t *) const;
virtual std::unique_ptr<AMQPDescribed> build (pn_data_t * data_) const = 0;
virtual std::unique_ptr<AMQPDescribed> build (pn_data_t * data_) const;
virtual void read (
pn_data_t *,
std::stringstream &) const;
virtual void read (
pn_data_t *,
std::stringstream &,
const AutoIndent &) const;
};
}

View File

@ -1,6 +1,13 @@
#include "AMQPDescriptorRegistory.h"
#include "AMQPDescriptors.h"
#include "corda-descriptors/FieldDescriptor.h"
#include "corda-descriptors/SchemaDescriptor.h"
#include "corda-descriptors/ObjectDescriptor.h"
#include "corda-descriptors/EnvelopeDescriptor.h"
#include "corda-descriptors/CompositeDescriptor.h"
#include "corda-descriptors/RestrictedDescriptor.h"
#include <limits>
#include <climits>
@ -8,8 +15,7 @@
namespace amqp::internal {
const uint64_t DESCRIPTOR_TOP_32BITS = 0xc562L << (32 + 16);
constexpr uint64_t DESCRIPTOR_TOP_32BITS = 0xc562UL << (unsigned int)(32 + 16);
}
@ -41,77 +47,83 @@ namespace amqp {
std::map<uint64_t, std::shared_ptr<internal::AMQPDescriptor>>
AMQPDescriptorRegistory = {
{
1L | internal::DESCRIPTOR_TOP_32BITS,
22UL,
std::make_shared<internal::AMQPDescriptor> (
"DESCRIBED",
-1)
},
{
1UL | internal::DESCRIPTOR_TOP_32BITS,
std::make_shared<internal::EnvelopeDescriptor> (
internal::EnvelopeDescriptor (
"ENVELOPE",
internal::ENVELOPE))
},
{
2L | internal::DESCRIPTOR_TOP_32BITS,
2UL | internal::DESCRIPTOR_TOP_32BITS,
std::make_shared<internal::SchemaDescriptor> (
internal::SchemaDescriptor (
"SCHEMA",
internal::SCHEMA))
},
{
3L | internal::DESCRIPTOR_TOP_32BITS,
3UL | internal::DESCRIPTOR_TOP_32BITS,
std::make_shared<internal::ObjectDescriptor> (
internal::ObjectDescriptor (
"OBJECT_DESCRIPTOR",
internal::OBJECT))
},
{
4L | internal::DESCRIPTOR_TOP_32BITS,
4UL | internal::DESCRIPTOR_TOP_32BITS,
std::make_shared<internal::FieldDescriptor> (
internal::FieldDescriptor (
"FIELD",
internal::FIELD))
},
{
5L | internal::DESCRIPTOR_TOP_32BITS,
5UL | internal::DESCRIPTOR_TOP_32BITS,
std::make_shared<internal::CompositeDescriptor> (
internal::CompositeDescriptor (
"COMPOSITE_TYPE",
internal::COMPOSITE_TYPE))
},
{
6L | internal::DESCRIPTOR_TOP_32BITS,
6UL | internal::DESCRIPTOR_TOP_32BITS,
std::make_shared<internal::RestrictedDescriptor> (
internal::RestrictedDescriptor (
"RESTRICTED_TYPE",
internal::RESTRICTED_TYPE))
},
{
7L | internal::DESCRIPTOR_TOP_32BITS,
7UL | internal::DESCRIPTOR_TOP_32BITS,
std::make_shared<internal::ChoiceDescriptor> (
internal::ChoiceDescriptor (
"CHOICE",
internal::CHOICE))
},
{
8L | internal::DESCRIPTOR_TOP_32BITS,
8UL | internal::DESCRIPTOR_TOP_32BITS,
std::make_shared<internal::ReferencedObjectDescriptor> (
internal::ReferencedObjectDescriptor (
"REFERENCED_OBJECT",
internal::REFERENCED_OBJECT))
},
{
9L | internal::DESCRIPTOR_TOP_32BITS,
9UL | internal::DESCRIPTOR_TOP_32BITS,
std::make_shared<internal::TransformSchemaDescriptor> (
internal::TransformSchemaDescriptor (
"TRANSFORM_SCHEMA",
internal::TRANSFORM_SCHEMA))
},
{
10L | internal::DESCRIPTOR_TOP_32BITS,
10UL | internal::DESCRIPTOR_TOP_32BITS,
std::make_shared<internal::TransformElementDescriptor> (
internal::TransformElementDescriptor (
"TRANSFORM_ELEMENT",
internal::TRANSFORM_ELEMENT))
},
{
11L | internal::DESCRIPTOR_TOP_32BITS,
11UL | internal::DESCRIPTOR_TOP_32BITS,
std::make_shared<internal::TransformElementKeyDescriptor> (
internal::TransformElementKeyDescriptor (
"TRANSFORM_ELEMENT_KEY",
@ -132,19 +144,19 @@ amqp::stripCorda (uint64_t id) {
std::string
amqp::describedToString (uint64_t val_) {
switch (val_) {
case (1L | internal::DESCRIPTOR_TOP_32BITS) : return "ENVELOPE";
case (2L | internal::DESCRIPTOR_TOP_32BITS) : return "SCHEMA";
case (3L | internal::DESCRIPTOR_TOP_32BITS) : return "OBJECT_DESCRIPTOR";
case (4L | internal::DESCRIPTOR_TOP_32BITS) : return "FIELD";
case (5L | internal::DESCRIPTOR_TOP_32BITS) : return "COMPOSITE_TYPE";
case (6L | internal::DESCRIPTOR_TOP_32BITS) : return "RESTRICTED_TYPE";
case (7L | internal::DESCRIPTOR_TOP_32BITS) : return "CHOICE";
case (8L | internal::DESCRIPTOR_TOP_32BITS) : return "REFERENCED_OBJECT";
case (9L | internal::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_SCHEMA";
case (10L | internal::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_ELEMENT";
case (11L | internal::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_ELEMENT_KEY";
case (1UL | internal::DESCRIPTOR_TOP_32BITS) : return "ENVELOPE";
case (2UL | internal::DESCRIPTOR_TOP_32BITS) : return "SCHEMA";
case (3UL | internal::DESCRIPTOR_TOP_32BITS) : return "OBJECT_DESCRIPTOR";
case (4UL | internal::DESCRIPTOR_TOP_32BITS) : return "FIELD";
case (5UL | internal::DESCRIPTOR_TOP_32BITS) : return "COMPOSITE_TYPE";
case (6UL | internal::DESCRIPTOR_TOP_32BITS) : return "RESTRICTED_TYPE";
case (7UL | internal::DESCRIPTOR_TOP_32BITS) : return "CHOICE";
case (8UL | internal::DESCRIPTOR_TOP_32BITS) : return "REFERENCED_OBJECT";
case (9UL | internal::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_SCHEMA";
case (10UL | internal::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_ELEMENT";
case (11UL | internal::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_ELEMENT_KEY";
default : return "UNKNOWN";
};
}
}
/******************************************************************************/

View File

@ -7,7 +7,7 @@
/******************************************************************************/
#include "amqp/AMQPDescriptor.h"
#include "AMQPDescriptor.h"
/******************************************************************************/

View File

@ -25,31 +25,6 @@
*
******************************************************************************/
namespace {
/**
* Look up a described type by its ID in the AMQPDescriptorRegistry and
* return the corresponding schema type. Specialised below to avoid
* the cast and re-owning of the unigue pointer when we're happy
* with a simple uPtr<AMQPDescribed>
*/
template<class T>
uPtr<T>
dispatchDescribed (pn_data_t * data_) {
proton::is_described(data_);
proton::auto_enter p (data_);
proton::is_ulong(data_);
auto id = pn_data_get_ulong(data_);
return uPtr<T> (
static_cast<T *>(amqp::AMQPDescriptorRegistory[id]->build(data_).release()));
}
}
/******************************************************************************/
void
amqp::internal::
AMQPDescriptor::validateAndNext (pn_data_t * const data_) const {
@ -63,272 +38,7 @@ AMQPDescriptor::validateAndNext (pn_data_t * const data_) const {
throw std::runtime_error ("Invalid Type");
}
pn_data_next(data_);
}
/******************************************************************************/
namespace {
const std::string
consumeBlob (pn_data_t * data_) {
proton::is_described (data_);
proton::auto_enter p (data_);
return proton::get_symbol<std::string> (data_);
}
}
/******************************************************************************
*
* amqp::internal::EnvelopeDescriptor
*
******************************************************************************/
uPtr<amqp::AMQPDescribed>
amqp::internal::
EnvelopeDescriptor::build(pn_data_t * data_) const {
DBG ("ENVELOPE" << std::endl); // NOLINT
validateAndNext(data_);
proton::auto_enter p (data_);
/*
* The actual blob... if this was java we would use the type symbols
* in the blob to look up serialisers in the cache... but we don't
* have any so we are actually going to need to use the schema
* which we parse *after* this to be able to read any data!
*/
std::string outerType = consumeBlob(data_);
pn_data_next (data_);
/*
* The schema
*/
auto schema = dispatchDescribed<schema::Schema> (data_);
pn_data_next(data_);
/*
* The transforms schema
*/
// Skip for now
// dispatchDescribed (data_);
return std::make_unique<schema::Envelope> (schema::Envelope (schema, outerType));
}
/******************************************************************************/
uPtr<amqp::AMQPDescribed>
amqp::internal::
SchemaDescriptor::build(pn_data_t * data_) const {
DBG ("SCHEMA" << std::endl); // NOLINT
validateAndNext(data_);
schema::OrderedTypeNotations<schema::AMQPTypeNotation> schemas;
/*
* The Schema is stored as a list of lists of described objects
*/
{
proton::auto_list_enter ale (data_);
for (int i { 1 } ; pn_data_next(data_) ; ++i) {
DBG (" " << i << "/" << ale.elements() << std::endl); // NOLINT
proton::auto_list_enter ale2 (data_);
while (pn_data_next(data_)) {
schemas.insert (dispatchDescribed<schema::AMQPTypeNotation>(data_));
}
}
}
return std::make_unique<schema::Schema> (std::move (schemas));
}
/******************************************************************************
*
* amqp::internal::ObjectDescriptor
*
******************************************************************************/
/**
*
*/
uPtr<amqp::AMQPDescribed>
amqp::internal::
ObjectDescriptor::build(pn_data_t * data_) const {
DBG ("DESCRIPTOR" << std::endl); // NOLINT
validateAndNext(data_);
proton::auto_enter p (data_);
auto symbol = proton::get_symbol<std::string> (data_);
return std::make_unique<schema::Descriptor> (symbol);
}
/******************************************************************************
*
* amqp::internal::FieldDescriptor
*
******************************************************************************/
uPtr<amqp::AMQPDescribed>
amqp::internal::
FieldDescriptor::build(pn_data_t * data_) const {
DBG ("FIELD" << std::endl); // NOLINT
validateAndNext(data_);
proton::auto_enter ae (data_);
/* name: String */
auto name = proton::get_string (data_);
pn_data_next(data_);
/* type: String */
auto type = proton::get_string (data_);
pn_data_next(data_);
/* requires: List<String> */
std::list<std::string> requires;
{
proton::auto_list_enter ale (data_);
while (pn_data_next(data_)) {
requires.push_back (proton::get_string(data_));
}
}
pn_data_next(data_);
/* default: String? */
auto def = proton::get_string (data_, true);
pn_data_next(data_);
/* label: String? */
auto label = proton::get_string (data_, true);
pn_data_next(data_);
/* mandatory: Boolean - copes with the Kotlin concept of nullability.
If something is mandatory then it cannot be null */
auto mandatory = proton::get_boolean (data_);
pn_data_next(data_);
/* multiple: Boolean */
auto multiple = proton::get_boolean(data_);
return std::make_unique<schema::Field> (name, type, requires, def, label,
mandatory, multiple);
}
/******************************************************************************
*
* amqp::internal::CompositeDescriptor
*
******************************************************************************/
uPtr<amqp::AMQPDescribed>
amqp::internal::
CompositeDescriptor::build (pn_data_t * data_) const {
DBG ("COMPOSITE" << std::endl); // NOLINT
validateAndNext(data_);
proton::auto_enter p (data_);
/* Class Name - String */
auto name = proton::get_string(data_);
pn_data_next(data_);
/* Label Name - Nullable String */
auto label = proton::get_string (data_, true);
pn_data_next(data_);
/* provides: List<String> */
std::list<std::string> provides;
{
proton::auto_list_enter p2 (data_);
while (pn_data_next(data_)) {
provides.push_back (proton::get_string (data_));
}
}
pn_data_next(data_);
/* descriptor: Descriptor */
auto descriptor = dispatchDescribed<schema::Descriptor>(data_);
pn_data_next(data_);
/* fields: List<Described>*/
std::vector<uPtr<schema::Field>> fields;
fields.reserve (pn_data_get_list (data_));
{
proton::auto_list_enter p2 (data_);
while (pn_data_next (data_)) {
fields.emplace_back (dispatchDescribed<schema::Field>(data_));
}
}
return std::make_unique<schema::Composite> (
schema::Composite (name, label, provides, descriptor, fields));
}
/******************************************************************************
*
* Restricted types represent lists and maps
*
* NOTE: The Corda serialization scheme doesn't support all container classes
* as it has the requiremnt that iteration order be deterministic for purposes
* of signing over data.
*
* name : String
* label : String?
* provides : List<String>
* source : String
* descriptor : Descriptor
* choices : List<Choice>
*
******************************************************************************/
uPtr<amqp::AMQPDescribed>
amqp::internal::
RestrictedDescriptor::build (pn_data_t * data_) const {
DBG ("RESTRICTED" << std::endl); // NOLINT
validateAndNext(data_);
proton::auto_enter ae (data_);
auto name = proton::readAndNext<std::string>(data_);
auto label = proton::readAndNext<std::string>(data_, true);
std::vector<std::string> provides;
{
proton::auto_list_enter ae2 (data_);
while (pn_data_next(data_)) {
provides.push_back (proton::get_string (data_));
}
}
pn_data_next (data_);
auto source = proton::readAndNext<std::string> (data_);
auto descriptor = dispatchDescribed<schema::Descriptor> (data_);
// SKIP the choices section **FOR NOW**
return schema::Restricted::make (descriptor, name,
label, provides, source);
}
/******************************************************************************
@ -396,3 +106,4 @@ TransformElementKeyDescriptor::build (pn_data_t * data_) const {
}
/******************************************************************************/

View File

@ -8,9 +8,12 @@
#include <memory>
#include <iostream>
#include "types.h"
#include "amqp/AMQPDescribed.h"
#include "amqp/AMQPDescriptor.h"
#include "AMQPDescriptor.h"
#include "amqp/schema/Descriptor.h"
#include "proton/proton_wrapper.h"
#include "AMQPDescriptorRegistory.h"
/******************************************************************************/
@ -18,116 +21,26 @@ struct pn_data_t;
/******************************************************************************/
namespace amqp::internal {
namespace amqp::internal::descriptors {
class EnvelopeDescriptor : public AMQPDescriptor {
public :
EnvelopeDescriptor() : AMQPDescriptor() { }
/**
* Look up a described type by its ID in the AMQPDescriptorRegistry and
* return the corresponding schema type. Specialised below to avoid
* the cast and re-owning of the unigue pointer when we're happy
* with a simple uPtr<AMQPDescribed>
*/
template<class T>
uPtr <T>
dispatchDescribed(pn_data_t *data_) {
proton::is_described(data_);
proton::auto_enter p(data_);
proton::is_ulong(data_);
EnvelopeDescriptor(const std::string & symbol_, int val_)
: AMQPDescriptor(symbol_, val_)
{ }
~EnvelopeDescriptor() final = default;
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
};
}
/******************************************************************************/
namespace amqp::internal {
class SchemaDescriptor : public AMQPDescriptor {
public :
SchemaDescriptor() : AMQPDescriptor() { }
SchemaDescriptor(const std::string & symbol_, int val_)
: AMQPDescriptor(symbol_, val_)
{ }
~SchemaDescriptor() final = default;
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
};
}
/******************************************************************************/
namespace amqp::internal {
class ObjectDescriptor : public AMQPDescriptor {
public :
ObjectDescriptor() : AMQPDescriptor() { }
ObjectDescriptor(const std::string & symbol_, int val_)
: AMQPDescriptor(symbol_, val_)
{ }
~ObjectDescriptor() final = default;
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
};
}
/******************************************************************************/
namespace amqp::internal {
class FieldDescriptor : public AMQPDescriptor {
public :
FieldDescriptor() : AMQPDescriptor() { }
FieldDescriptor(const std::string & symbol_, int val_)
: AMQPDescriptor(symbol_, val_)
{ }
~FieldDescriptor() final = default;
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
};
}
/******************************************************************************/
namespace amqp::internal {
class CompositeDescriptor : public AMQPDescriptor {
public :
CompositeDescriptor() : AMQPDescriptor() { }
CompositeDescriptor(const std::string & symbol_, int val_)
: AMQPDescriptor(symbol_, val_)
{ }
~CompositeDescriptor() final = default;
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
};
}
/******************************************************************************/
namespace amqp::internal {
class RestrictedDescriptor : public AMQPDescriptor {
public :
RestrictedDescriptor() : AMQPDescriptor() { }
RestrictedDescriptor(const std::string & symbol_, int val_)
: AMQPDescriptor(symbol_, val_)
{ }
~RestrictedDescriptor() final = default;
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
};
auto id = pn_data_get_ulong(data_);
return uPtr<T>(
static_cast<T *>(amqp::AMQPDescriptorRegistory[id]->build(data_).release()));
}
}
/******************************************************************************/

View File

@ -0,0 +1,146 @@
#include "CompositeDescriptor.h"
#include <string>
#include <sstream>
#include <iostream>
#include "types.h"
#include "debug.h"
#include "proton/proton_wrapper.h"
#include "amqp/descriptors/AMQPDescriptors.h"
#include "amqp/schema/Field.h"
#include "amqp/schema/Composite.h"
#include "amqp/schema/Descriptor.h"
/******************************************************************************
*
* amqp::internal::CompositeDescriptor
*
******************************************************************************/
amqp::internal::
CompositeDescriptor::CompositeDescriptor (
const std::string & symbol_,
int val_
) : AMQPDescriptor (symbol_, val_) {
}
/******************************************************************************/
uPtr<amqp::AMQPDescribed>
amqp::internal::
CompositeDescriptor::build (pn_data_t * data_) const {
DBG ("COMPOSITE" << std::endl); // NOLINT
validateAndNext(data_);
proton::auto_enter p (data_);
/* Class Name - String */
auto name = proton::get_string(data_);
pn_data_next(data_);
/* Label Name - Nullable String */
auto label = proton::get_string (data_, true);
pn_data_next(data_);
/* provides: List<String> */
std::list<std::string> provides;
{
proton::auto_list_enter p2 (data_);
while (pn_data_next(data_)) {
provides.push_back (proton::get_string (data_));
}
}
pn_data_next (data_);
/* descriptor: Descriptor */
auto descriptor = descriptors::dispatchDescribed<schema::Descriptor>(data_);
pn_data_next (data_);
/* fields: List<Described>*/
std::vector<uPtr<schema::Field>> fields;
fields.reserve (pn_data_get_list (data_));
{
proton::auto_list_enter p2 (data_);
while (pn_data_next (data_)) {
fields.emplace_back (descriptors::dispatchDescribed<schema::Field>(data_));
}
}
return std::make_unique<schema::Composite> (
schema::Composite (name, label, provides, descriptor, fields));
}
/******************************************************************************/
void
amqp::internal::
CompositeDescriptor::read (
pn_data_t * data_,
std::stringstream & ss_,
const AutoIndent & ai_
) const {
proton::is_list(data_);
{
AutoIndent ai { ai_ };
proton::auto_enter p (data_);
proton::is_string (data_);
ss_ << ai
<< "1] String: ClassName: "
<< proton::readAndNext<std::string>(data_)
<< std::endl;
proton::is_string (data_);
ss_ << ai
<< "2] String: Label: \""
<< proton::readAndNext<std::string>(data_, true)
<< "\"" << std::endl;
proton::is_list (data_);
ss_ << ai << "3] List: Provides: [ ";
{
proton::auto_list_enter ale (data_);
while (pn_data_next(data_)) {
ss_ << ai << (proton::get_string (data_)) << " ";
}
}
ss_ << "]" << std::endl;
pn_data_next (data_);
proton::is_described (data_);
ss_ << ai << "4] Descriptor:" << std::endl;
AMQPDescriptorRegistory[pn_data_type(data_)]->read (
(pn_data_t *)proton::auto_next(data_), ss_, AutoIndent { ai });
ss_ << ai << "5] List: Fields: " << std::endl;
{
AutoIndent ai2 { ai };
proton::auto_list_enter ale (data_);
for (int i { 1 } ; pn_data_next (data_) ; ++i) {
ss_ << ai2 << i << "/"
<< ale.elements() << "]"
<< std::endl;
AMQPDescriptorRegistory[pn_data_type(data_)]->read (
data_, ss_, AutoIndent { ai2 });
}
}
}
}
/******************************************************************************/

View File

@ -0,0 +1,26 @@
#pragma once
#include "amqp/descriptors/AMQPDescriptor.h"
/******************************************************************************/
namespace amqp::internal {
class CompositeDescriptor : public AMQPDescriptor {
public :
CompositeDescriptor() : AMQPDescriptor() { }
CompositeDescriptor (const std::string &, int);
~CompositeDescriptor() final = default;
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
void read (
pn_data_t *,
std::stringstream &,
const AutoIndent &) const override;
};
}
/******************************************************************************/

View File

@ -0,0 +1,114 @@
#include "EnvelopeDescriptor.h"
#include "amqp/schema/Schema.h"
#include "amqp/schema/Envelope.h"
#include "proton/proton_wrapper.h"
#include "types.h"
#include "debug.h"
#include <sstream>
/******************************************************************************/
namespace {
const std::string
consumeBlob (pn_data_t * data_) {
proton::is_described (data_);
proton::auto_enter p (data_);
return proton::get_symbol<std::string> (data_);
}
}
/******************************************************************************
*
* amqp::internal::EnvelopeDescriptor
*
******************************************************************************/
/*
* Described types are a pair of a key and a list of elements. Having
* parsed this as such a type we should be in the stack at the point
* where we found the list and don't expect to have entered it before
* calling this
*/
void
amqp::internal::
EnvelopeDescriptor::read (
pn_data_t * data_, std::stringstream & ss_, const AutoIndent & ai_
) const {
// lets just make sure we haven't entered this already
proton::is_list (data_);
{
AutoIndent ai { ai_ };
proton::auto_enter p (data_);
ss_ << ai << "1]" << std::endl;
AMQPDescriptorRegistory[pn_data_type(data_)]->read (
(pn_data_t *)proton::auto_next (data_), ss_, AutoIndent { ai });
ss_ << ai << "2]" << std::endl;
AMQPDescriptorRegistory[pn_data_type(data_)]->read (
(pn_data_t *)proton::auto_next(data_), ss_, AutoIndent { ai });
}
}
/******************************************************************************/
amqp::internal::
EnvelopeDescriptor::EnvelopeDescriptor() : AMQPDescriptor() { }
/******************************************************************************/
amqp::internal::
EnvelopeDescriptor::EnvelopeDescriptor (
const std::string & symbol_,
int val_
) : AMQPDescriptor (symbol_, val_) {
}
/******************************************************************************/
uPtr<amqp::AMQPDescribed>
amqp::internal::
EnvelopeDescriptor::build (pn_data_t * data_) const {
DBG ("ENVELOPE" << std::endl); // NOLINT
validateAndNext(data_);
proton::auto_enter p (data_);
/*
* The actual blob... if this was java we would use the type symbols
* in the blob to look up serialisers in the cache... but we don't
* have any so we are actually going to need to use the schema
* which we parse *after* this to be able to read any data!
*/
std::string outerType = consumeBlob(data_);
pn_data_next (data_);
/*
* The schema
*/
auto schema = descriptors::dispatchDescribed<schema::Schema> (data_);
pn_data_next(data_);
/*
* The transforms schema
*/
// Skip for now
// dispatchDescribed (data_);
return std::make_unique<schema::Envelope> (schema::Envelope (schema, outerType));
}
/******************************************************************************/

View File

@ -0,0 +1,41 @@
#pragma once
#include <string>
#include "AMQPDescriptors.h"
/******************************************************************************
*
* Forward Class Declarations
*
******************************************************************************/
struct pn_data_t;
/******************************************************************************
*
* class amqp::internal::EnvelopeDescriptor
*
******************************************************************************/
namespace amqp::internal {
class EnvelopeDescriptor : public AMQPDescriptor {
public :
EnvelopeDescriptor();
EnvelopeDescriptor (const std::string &, int);
~EnvelopeDescriptor() final = default;
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
void read (
pn_data_t *,
std::stringstream &,
const AutoIndent &) const override;
};
}
/******************************************************************************/

View File

@ -0,0 +1,138 @@
#include "FieldDescriptor.h"
#include "debug.h"
#include "types.h"
#include "proton/proton_wrapper.h"
#include "amqp/schema/Field.h"
#include <sstream>
/******************************************************************************
*
* amqp::internal::FieldDescriptor
*
******************************************************************************/
amqp::internal::
FieldDescriptor::FieldDescriptor() : AMQPDescriptor() { }
/******************************************************************************/
amqp::internal::
FieldDescriptor::FieldDescriptor (
const std::string & symbol_,
int val_
) : AMQPDescriptor(symbol_, val_) {
}
/******************************************************************************/
uPtr<amqp::AMQPDescribed>
amqp::internal::
FieldDescriptor::build(pn_data_t * data_) const {
DBG ("FIELD" << std::endl); // NOLINT
validateAndNext(data_);
proton::auto_enter ae (data_);
/* name: String */
auto name = proton::get_string (data_);
pn_data_next (data_);
/* type: String */
auto type = proton::get_string (data_);
pn_data_next (data_);
/* requires: List<String> */
std::list<std::string> requires;
{
proton::auto_list_enter ale (data_);
while (pn_data_next(data_)) {
requires.push_back (proton::get_string(data_));
}
}
pn_data_next (data_);
/* default: String? */
auto def = proton::get_string (data_, true);
pn_data_next (data_);
/* label: String? */
auto label = proton::get_string (data_, true);
pn_data_next (data_);
/* mandatory: Boolean - copes with the Kotlin concept of nullability.
If something is mandatory then it cannot be null */
auto mandatory = proton::get_boolean (data_);
pn_data_next (data_);
/* multiple: Boolean */
auto multiple = proton::get_boolean(data_);
return std::make_unique<schema::Field> (
name, type, requires, def, label, mandatory, multiple);
}
/******************************************************************************/
void
amqp::internal::
FieldDescriptor::read (
pn_data_t * data_,
std::stringstream & ss_,
const AutoIndent & ai_
) const {
proton::is_list (data_);
proton::auto_list_enter ale (data_, true);
AutoIndent ai { ai_ };
ss_ << ai << "1/7] String: Name: "
<< proton::get_string ((pn_data_t *)proton::auto_next (data_))
<< std::endl;
ss_ << ai << "2/7] String: Type: "
<< proton::get_string ((pn_data_t *)proton::auto_next (data_))
<< std::endl;
{
proton::auto_list_enter ale2 (data_);
ss_ << ai << "3/7] List: Requires: elements " << ale2.elements()
<< std::endl;
AutoIndent ai2 { ai };
while (pn_data_next(data_)) {
ss_ << ai2 << proton::get_string (data_) << std::endl;
}
}
pn_data_next (data_);
proton::is_string (data_, true);
ss_ << ai << "4/7] String: Default: "
<< proton::get_string ((pn_data_t *)proton::auto_next (data_), true)
<< std::endl;
ss_ << ai << "5/7] String: Label: "
<< proton::get_string ((pn_data_t *)proton::auto_next (data_), true)
<< std::endl;
ss_ << ai << "6/7] Boolean: Mandatory: "
<< proton::get_boolean ((pn_data_t *)proton::auto_next (data_))
<< std::endl;
ss_ << ai << "7/7] Boolean: Multiple: "
<< proton::get_boolean ((pn_data_t *)proton::auto_next (data_))
<< std::endl;
}
/******************************************************************************/

View File

@ -0,0 +1,30 @@
#pragma once
/******************************************************************************/
#include "proton/codec.h"
#include "amqp/AMQPDescribed.h"
#include "amqp/descriptors/AMQPDescriptor.h"
/******************************************************************************/
namespace amqp::internal {
class FieldDescriptor : public AMQPDescriptor {
public :
FieldDescriptor();
FieldDescriptor (const std::string &, int);
~FieldDescriptor() final = default;
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
void read (
pn_data_t *,
std::stringstream &,
const AutoIndent &) const override;
};
}
/******************************************************************************/

View File

@ -0,0 +1,59 @@
#include "ObjectDescriptor.h"
#include "types.h"
#include "debug.h"
#include "proton/proton_wrapper.h"
#include "amqp/schema/Descriptor.h"
#include <sstream>
/******************************************************************************
*
* amqp::internal::ObjectDescriptor
*
******************************************************************************/
/**
*
*/
uPtr<amqp::AMQPDescribed>
amqp::internal::
ObjectDescriptor::build(pn_data_t * data_) const {
DBG ("DESCRIPTOR" << std::endl); // NOLINT
validateAndNext (data_);
proton::auto_enter p (data_);
auto symbol = proton::get_symbol<std::string> (data_);
return std::make_unique<schema::Descriptor> (symbol);
}
/******************************************************************************/
void
amqp::internal::
ObjectDescriptor::read (
pn_data_t * data_,
std::stringstream & ss_,
const AutoIndent & ai_
) const {
proton::is_list (data_);
{
AutoIndent ai { ai_ };
proton::auto_list_enter ale (data_);
pn_data_next(data_);
ss_ << ai << "1/2] "
<< proton::get_symbol<std::string>(
(pn_data_t *)proton::auto_next (data_))
<< std::endl;
ss_ << ai << "2/2] " << data_ << std::endl;
}
}
/******************************************************************************/

View File

@ -0,0 +1,35 @@
#pragma once
/******************************************************************************/
#include "amqp/descriptors/AMQPDescriptor.h"
/******************************************************************************/
struct pn_data_t;
/******************************************************************************/
namespace amqp::internal {
class ObjectDescriptor : public AMQPDescriptor {
public :
ObjectDescriptor() : AMQPDescriptor() { }
ObjectDescriptor(const std::string & symbol_, int val_)
: AMQPDescriptor(symbol_, val_)
{ }
~ObjectDescriptor() final = default;
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
void read (
pn_data_t *,
std::stringstream &,
const AutoIndent &) const override;
};
}
/******************************************************************************/

View File

@ -0,0 +1,98 @@
#include "RestrictedDescriptor.h"
#include "types.h"
#include "debug.h"
#include "amqp/schema/restricted-types/Restricted.h"
#include "amqp/descriptors/AMQPDescriptors.h"
#include <sstream>
/******************************************************************************
*
* Restricted types represent lists and maps
*
* NOTE: The Corda serialization scheme doesn't support all container classes
* as it has the requiremnt that iteration order be deterministic for purposes
* of signing over data.
*
* name : String
* label : String?
* provides : List<String>
* source : String
* descriptor : Descriptor
* choices : List<Choice>
*
******************************************************************************/
uPtr<amqp::AMQPDescribed>
amqp::internal::
RestrictedDescriptor::build (pn_data_t * data_) const {
DBG ("RESTRICTED" << std::endl); // NOLINT
validateAndNext(data_);
proton::auto_enter ae (data_);
auto name = proton::readAndNext<std::string>(data_);
auto label = proton::readAndNext<std::string>(data_, true);
std::vector<std::string> provides;
{
proton::auto_list_enter ae2 (data_);
while (pn_data_next(data_)) {
provides.push_back (proton::get_string (data_));
}
}
pn_data_next (data_);
auto source = proton::readAndNext<std::string> (data_);
auto descriptor = descriptors::dispatchDescribed<schema::Descriptor> (data_);
// SKIP the choices section **FOR NOW**
return schema::Restricted::make (descriptor, name,
label, provides, source);
}
/******************************************************************************/
void
amqp::internal::
RestrictedDescriptor::read (
pn_data_t * data_,
std::stringstream & ss_,
const AutoIndent & ai_
) const {
proton::is_list (data_);
proton::auto_enter ae (data_);
AutoIndent ai { ai_ };
ss_ << ai << "1] String: Name: "
<< proton::readAndNext<std::string> (data_)
<< std::endl;
ss_ << ai << "2] String: Label: "
<< proton::readAndNext<std::string> (data_, true)
<< std::endl;
ss_ << ai << "3] List: Provides: [ ";
{
proton::auto_list_enter ae2 (data_);
while (pn_data_next(data_)) {
ss_ << proton::get_string (data_) << " ";
}
ss_ << "]" << std::endl;
}
pn_data_next (data_);
ss_ << ai << "4] String: Source: "
<< proton::readAndNext<std::string> (data_)
<< std::endl;
ss_ << ai << "5] Descriptor:" << std::endl;
AMQPDescriptorRegistory[pn_data_type(data_)]->read (
(pn_data_t *)proton::auto_next(data_), ss_, AutoIndent { ai });
}
/******************************************************************************/

View File

@ -0,0 +1,34 @@
#pragma once
/******************************************************************************/
#include <string>
#include "amqp/descriptors/AMQPDescriptor.h"
/******************************************************************************/
namespace amqp::internal {
class RestrictedDescriptor : public AMQPDescriptor {
public :
RestrictedDescriptor() : AMQPDescriptor() { }
RestrictedDescriptor(const std::string & symbol_, int val_)
: AMQPDescriptor(symbol_, val_)
{ }
~RestrictedDescriptor() final = default;
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
void read (
pn_data_t *,
std::stringstream &,
const AutoIndent &) const override;
};
}
/******************************************************************************/

View File

@ -0,0 +1,93 @@
#include "SchemaDescriptor.h"
#include "types.h"
#include "debug.h"
#include "AMQPDescriptor.h"
#include "proton/codec.h"
#include "proton/proton_wrapper.h"
#include "amqp/AMQPDescribed.h"
#include "amqp/descriptors/AMQPDescriptors.h"
#include "amqp/schema/Schema.h"
#include "amqp/schema/OrderedTypeNotations.h"
#include "amqp/schema/AMQPTypeNotation.h"
#include <sstream>
/******************************************************************************/
amqp::internal::
SchemaDescriptor::SchemaDescriptor (
const std::string & symbol_,
int val_
) : AMQPDescriptor(symbol_, val_) {
}
/******************************************************************************/
uPtr<amqp::AMQPDescribed>
amqp::internal::
SchemaDescriptor::build (pn_data_t * data_) const {
DBG ("SCHEMA" << std::endl); // NOLINT
validateAndNext(data_);
schema::OrderedTypeNotations<schema::AMQPTypeNotation> schemas;
/*
* The Schema is stored as a list of lists of described objects
*/
{
proton::auto_list_enter ale (data_);
for (int i { 1 } ; pn_data_next(data_) ; ++i) {
DBG (" " << i << "/" << ale.elements() << std::endl); // NOLINT
proton::auto_list_enter ale2 (data_);
while (pn_data_next(data_)) {
schemas.insert (
descriptors::dispatchDescribed<schema::AMQPTypeNotation>(data_));
}
}
}
return std::make_unique<schema::Schema> (std::move (schemas));
}
/******************************************************************************/
void
amqp::internal::
SchemaDescriptor::read (
pn_data_t * data_,
std::stringstream & ss_,
const AutoIndent & ai_
) const {
proton::is_list (data_);
{
AutoIndent ai { ai_ };
proton::auto_list_enter ale (data_);
for (int i { 1 } ; pn_data_next (data_) ; ++i) {
proton::is_list (data_);
ss_ << ai << i << "/" << ale.elements() <<"]";
AutoIndent ai2 { ai };
proton::auto_list_enter ale2 (data_);
ss_ << " list: entries: " << ale2.elements() << std::endl;
for (int j { 1 } ; pn_data_next (data_) ; ++j) {
ss_ << ai2 << i << ":" << j << "/" << ale2.elements()
<< "] " << std::endl;
AMQPDescriptorRegistory[pn_data_type(data_)]->read (
data_, ss_,
AutoIndent { ai2 });
}
}
}
}
/******************************************************************************/

View File

@ -0,0 +1,29 @@
#pragma once
#include "amqp/descriptors/AMQPDescriptor.h"
/******************************************************************************/
struct pn_data_t;
/******************************************************************************/
namespace amqp::internal {
class SchemaDescriptor : public AMQPDescriptor {
public :
SchemaDescriptor() = default;
SchemaDescriptor (const std::string &, int);
~SchemaDescriptor() final = default;
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
void read (
pn_data_t *,
std::stringstream &,
const AutoIndent &) const override;
};
}
/******************************************************************************/

View File

@ -31,7 +31,7 @@ namespace amqp::internal::reader {
std::any read (pn_data_t *) const override;
std::string readString(pn_data_t *) const override;
std::string readString (pn_data_t *) const override;
std::unique_ptr<amqp::reader::IValue> dump(
const std::string &,