mirror of
https://github.com/corda/corda.git
synced 2025-06-13 04:38:19 +00:00
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:
@ -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
|
||||
)
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
@ -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";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "amqp/AMQPDescriptor.h"
|
||||
#include "AMQPDescriptor.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -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 {
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -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));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -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;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -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 });
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -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 &,
|
||||
|
Reference in New Issue
Block a user