mirror of
https://github.com/corda/corda.git
synced 2025-06-13 04:38:19 +00:00
NOTICK - Add C++ Serialiser Support for Maps and Arrays (#5775)
Adds support for understanding both Maps and Arrays Irritatingly, whilst arrays are mostly serialized as lists, we cannot simply use a restricted List reader to deserialize them because there are subtle differences in the way we need to work out if its actually a restricted type or not. Rather than add a bunch of random logic into the factory method I've isolated it in the class hierarchy. So a little bit more code makes the implementations a lot neater. We also need to deal with the fact arras of unboxed primitives exist, which whilst Java really gets excited about, we don't need to care about. An int, is an int, is an int!. Map support required we add a slightly better Value dumper, essentially the "key" component of the KV pair needs to be more flexible than a simple string when we're dumping out param:value pairs. Testing Added a lot more unit tests to both the ordered type notation code to ensure we build up the schema dependency struct in the correct order. Quite important as we rely on that in the composite factory to be strictly ordered to ensure we're not constructing a reader for a type we don't yet understand... and there were some small bugs in the version that predates this PR Also added a lot higher level tests to ensure actual reading out of the blob works
This commit is contained in:
@ -1,30 +1,42 @@
|
||||
include_directories (descriptors)
|
||||
include_directories (schema/descriptors)
|
||||
include_directories (schema/field-types)
|
||||
include_directories (schema/described-types)
|
||||
include_directories (schema)
|
||||
include_directories (reader)
|
||||
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/ChoiceDescriptor.cxx
|
||||
descriptors/corda-descriptors/EnvelopeDescriptor.cxx
|
||||
descriptors/corda-descriptors/CompositeDescriptor.cxx
|
||||
descriptors/corda-descriptors/RestrictedDescriptor.cxx
|
||||
schema/Field.cxx
|
||||
schema/Schema.cxx
|
||||
schema/Choice.cxx
|
||||
schema/Envelope.cxx
|
||||
schema/Composite.cxx
|
||||
schema/Descriptor.cxx
|
||||
schema/AMQPTypeNotation.cxx
|
||||
set (amqp_schema_sources
|
||||
schema/descriptors/AMQPDescriptor.cxx
|
||||
schema/descriptors/AMQPDescriptors.cxx
|
||||
schema/descriptors/AMQPDescriptorRegistory.cxx
|
||||
schema/descriptors/corda-descriptors/FieldDescriptor.cxx
|
||||
schema/descriptors/corda-descriptors/SchemaDescriptor.cxx
|
||||
schema/descriptors/corda-descriptors/ObjectDescriptor.cxx
|
||||
schema/descriptors/corda-descriptors/ChoiceDescriptor.cxx
|
||||
schema/descriptors/corda-descriptors/EnvelopeDescriptor.cxx
|
||||
schema/descriptors/corda-descriptors/CompositeDescriptor.cxx
|
||||
schema/descriptors/corda-descriptors/RestrictedDescriptor.cxx
|
||||
schema/field-types/Field.cxx
|
||||
schema/field-types/PrimitiveField.cxx
|
||||
schema/field-types/CompositeField.cxx
|
||||
schema/field-types/RestrictedField.cxx
|
||||
schema/field-types/ArrayField.cxx
|
||||
schema/described-types/Schema.cxx
|
||||
schema/described-types/Choice.cxx
|
||||
schema/described-types/Envelope.cxx
|
||||
schema/described-types/Composite.cxx
|
||||
schema/described-types/Descriptor.cxx
|
||||
schema/restricted-types/Restricted.cxx
|
||||
schema/restricted-types/List.cxx
|
||||
schema/restricted-types/Enum.cxx
|
||||
schema/restricted-types/Map.cxx
|
||||
schema/restricted-types/Array.cxx
|
||||
schema/AMQPTypeNotation.cxx
|
||||
schema/Descriptors.cxx
|
||||
)
|
||||
|
||||
set (amqp_sources
|
||||
CompositeFactory.cxx
|
||||
reader/Reader.cxx
|
||||
reader/PropertyReader.cxx
|
||||
reader/CompositeReader.cxx
|
||||
@ -34,10 +46,12 @@ set (amqp_sources
|
||||
reader/property-readers/BoolPropertyReader.cxx
|
||||
reader/property-readers/DoublePropertyReader.cxx
|
||||
reader/property-readers/StringPropertyReader.cxx
|
||||
reader/restricted-readers/MapReader.cxx
|
||||
reader/restricted-readers/ListReader.cxx
|
||||
reader/restricted-readers/ArrayReader.cxx
|
||||
reader/restricted-readers/EnumReader.cxx
|
||||
)
|
||||
|
||||
ADD_LIBRARY ( amqp ${amqp_sources} )
|
||||
ADD_LIBRARY ( amqp ${amqp_sources} ${amqp_schema_sources})
|
||||
|
||||
ADD_SUBDIRECTORY (test)
|
||||
|
@ -16,11 +16,15 @@
|
||||
#include "reader/Reader.h"
|
||||
#include "reader/CompositeReader.h"
|
||||
#include "reader/RestrictedReader.h"
|
||||
#include "reader/restricted-readers/MapReader.h"
|
||||
#include "reader/restricted-readers/ListReader.h"
|
||||
#include "reader/restricted-readers/ArrayReader.h"
|
||||
#include "reader/restricted-readers/EnumReader.h"
|
||||
|
||||
#include "schema/restricted-types/Map.h"
|
||||
#include "schema/restricted-types/List.h"
|
||||
#include "schema/restricted-types/Enum.h"
|
||||
#include "schema/restricted-types/Array.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@ -40,11 +44,12 @@ namespace {
|
||||
|
||||
if (it == map_.end()) {
|
||||
DBG ("ComputeIfAbsent \"" << k_ << "\" - missing" << std::endl); // NOLINT
|
||||
map_[k_] = std::move(f_());
|
||||
map_[k_] = std::move (f_());
|
||||
DBG (" \"" << k_ << "\" - RTN: " << map_[k_]->name() << " : " << map_[k_]->type()
|
||||
<< std::endl); // NOLINT
|
||||
assert (map_[k_]);
|
||||
assert (map_[k_] != nullptr);
|
||||
DBG (k_ << " =?= " << map_[k_]->type() << std::endl);
|
||||
assert (k_ == map_[k_]->type());
|
||||
|
||||
return map_[k_];
|
||||
@ -70,18 +75,20 @@ namespace {
|
||||
*
|
||||
* Walk through the types in a Schema and produce readers for them.
|
||||
*
|
||||
* We are making the large assumption that the contents of [schema_]
|
||||
* We are making the assumption that the contents of [schema_]
|
||||
* are strictly ordered by dependency so we can construct types
|
||||
* as we go without needing to provide look ahead for types
|
||||
* we haven't built yet
|
||||
* we haven't built yet.
|
||||
*
|
||||
*/
|
||||
void
|
||||
amqp::internal::
|
||||
CompositeFactory::process (const SchemaType & schema_) {
|
||||
DBG ("process schema" << std::endl);
|
||||
|
||||
for (const auto & i : dynamic_cast<const schema::Schema &>(schema_)) {
|
||||
for (const auto & j : i) {
|
||||
process(*j);
|
||||
process (*j);
|
||||
m_readersByDescriptor[j->descriptor()] = m_readersByType[j->name()];
|
||||
}
|
||||
}
|
||||
@ -92,17 +99,19 @@ CompositeFactory::process (const SchemaType & schema_) {
|
||||
std::shared_ptr<amqp::internal::reader::Reader>
|
||||
amqp::internal::
|
||||
CompositeFactory::process (
|
||||
const amqp::internal::schema::AMQPTypeNotation & schema_)
|
||||
const amqp::internal::schema::AMQPTypeNotation & schema_)
|
||||
{
|
||||
DBG ("process::" << schema_.name() << std::endl);
|
||||
|
||||
return computeIfAbsent<reader::Reader> (
|
||||
m_readersByType,
|
||||
schema_.name(),
|
||||
[& schema_, this] () -> std::shared_ptr<reader::Reader> {
|
||||
switch (schema_.type()) {
|
||||
case amqp::internal::schema::AMQPTypeNotation::Composite : {
|
||||
case schema::AMQPTypeNotation::composite_t : {
|
||||
return processComposite (schema_);
|
||||
}
|
||||
case amqp::internal::schema::AMQPTypeNotation::Restricted : {
|
||||
case schema::AMQPTypeNotation::restricted_t : {
|
||||
return processRestricted (schema_);
|
||||
}
|
||||
}
|
||||
@ -116,48 +125,38 @@ amqp::internal::
|
||||
CompositeFactory::processComposite (
|
||||
const amqp::internal::schema::AMQPTypeNotation & type_
|
||||
) {
|
||||
DBG ("processComposite - " << type_.name() << std::endl);
|
||||
std::vector<std::weak_ptr<reader::Reader>> readers;
|
||||
|
||||
const auto & fields = dynamic_cast<const amqp::internal::schema::Composite &> (
|
||||
const auto & fields = dynamic_cast<const schema::Composite &> (
|
||||
type_).fields();
|
||||
|
||||
readers.reserve(fields.size());
|
||||
readers.reserve (fields.size());
|
||||
|
||||
for (const auto & field : fields) {
|
||||
DBG (" Field: " << field->name() << ": " << field->type() << std::endl); // NOLINT
|
||||
DBG (" Field: " << field->name() << ": \"" << field->type()
|
||||
<< "\" {" << field->resolvedType() << "} "
|
||||
<< field->fieldType() << std::endl); // NOLINT
|
||||
|
||||
switch (field->fieldType()) {
|
||||
case schema::FieldType::PrimitiveProperty : {
|
||||
auto reader = computeIfAbsent<reader::Reader>(
|
||||
m_readersByType,
|
||||
field->type(),
|
||||
[&field]() -> std::shared_ptr<reader::PropertyReader> {
|
||||
return reader::PropertyReader::make(field);
|
||||
});
|
||||
decltype (m_readersByType)::mapped_type reader;
|
||||
|
||||
assert (reader);
|
||||
readers.emplace_back(reader);
|
||||
assert (readers.back().lock());
|
||||
break;
|
||||
}
|
||||
case amqp::internal::schema::FieldType::CompositeProperty : {
|
||||
auto reader = m_readersByType[field->type()];
|
||||
|
||||
assert (reader);
|
||||
readers.emplace_back(reader);
|
||||
assert (readers.back().lock());
|
||||
break;
|
||||
}
|
||||
case schema::FieldType::RestrictedProperty : {
|
||||
auto reader = m_readersByType[field->requires().front()];
|
||||
|
||||
assert (reader);
|
||||
readers.emplace_back(reader);
|
||||
assert (readers.back().lock());
|
||||
break;
|
||||
}
|
||||
if (field->primitive()) {
|
||||
reader = computeIfAbsent<reader::Reader> (
|
||||
m_readersByType,
|
||||
field->resolvedType(),
|
||||
[&field]() -> std::shared_ptr<reader::PropertyReader> {
|
||||
return reader::PropertyReader::make (field);
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Insertion sorting ensures any type we depend on will have
|
||||
// already been created and thus exist in the map
|
||||
reader = m_readersByType[field->resolvedType()];
|
||||
}
|
||||
|
||||
|
||||
assert (reader);
|
||||
readers.emplace_back (reader);
|
||||
assert (readers.back().lock());
|
||||
}
|
||||
|
||||
@ -174,8 +173,55 @@ CompositeFactory::processEnum (
|
||||
DBG ("Processing Enum - " << enum_.name() << std::endl); // NOLINT
|
||||
|
||||
return std::make_shared<reader::EnumReader> (
|
||||
enum_.name(),
|
||||
enum_.makeChoices());
|
||||
enum_.name(),
|
||||
enum_.makeChoices());
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::shared_ptr<amqp::internal::reader::Reader>
|
||||
amqp::internal::
|
||||
CompositeFactory::fetchReaderForRestricted (const std::string & type_) {
|
||||
decltype(m_readersByType)::mapped_type rtn;
|
||||
|
||||
DBG ("fetchReaderForRestricted - " << type_ << std::endl);
|
||||
|
||||
if (schema::Field::typeIsPrimitive(type_)) {
|
||||
DBG ("It's primitive" << std::endl);
|
||||
rtn = computeIfAbsent<reader::Reader>(
|
||||
m_readersByType,
|
||||
type_,
|
||||
[& type_]() -> std::shared_ptr<reader::PropertyReader> {
|
||||
return reader::PropertyReader::make (type_);
|
||||
});
|
||||
} else {
|
||||
rtn = m_readersByType[type_];
|
||||
}
|
||||
|
||||
if (!rtn) {
|
||||
throw std::runtime_error ("Missing type in map");
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::shared_ptr<amqp::internal::reader::Reader>
|
||||
amqp::internal::
|
||||
CompositeFactory::processMap (
|
||||
const amqp::internal::schema::Map & map_
|
||||
) {
|
||||
DBG ("Processing Map - "
|
||||
<< map_.mapOf().first.get() << " "
|
||||
<< map_.mapOf().second.get() << std::endl); // NOLINT
|
||||
|
||||
const auto types = map_.mapOf();
|
||||
|
||||
return std::make_shared<reader::MapReader> (
|
||||
map_.name(),
|
||||
fetchReaderForRestricted (types.first),
|
||||
fetchReaderForRestricted (types.second));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -187,22 +233,23 @@ CompositeFactory::processList (
|
||||
) {
|
||||
DBG ("Processing List - " << list_.listOf() << std::endl); // NOLINT
|
||||
|
||||
if (schema::Field::typeIsPrimitive (list_.listOf())) {
|
||||
DBG (" List of Primitives" << std::endl); // NOLINT
|
||||
auto reader = computeIfAbsent<reader::Reader>(
|
||||
m_readersByType,
|
||||
list_.listOf(),
|
||||
[& list_]() -> std::shared_ptr<reader::PropertyReader> {
|
||||
return reader::PropertyReader::make (list_.listOf());
|
||||
});
|
||||
return std::make_shared<reader::ListReader> (
|
||||
list_.name(),
|
||||
fetchReaderForRestricted (list_.listOf()));
|
||||
}
|
||||
|
||||
return std::make_shared<reader::ListReader>(list_.name(), reader);
|
||||
} else {
|
||||
DBG (" List of Composite - " << list_.listOf() << std::endl); // NOLINT
|
||||
auto reader = m_readersByType[list_.listOf()];
|
||||
/******************************************************************************/
|
||||
|
||||
return std::make_shared<reader::ListReader>(list_.name(), reader);
|
||||
}
|
||||
std::shared_ptr<amqp::internal::reader::Reader>
|
||||
amqp::internal::
|
||||
CompositeFactory::processArray (
|
||||
const amqp::internal::schema::Array & array_
|
||||
) {
|
||||
DBG ("Processing Array - " << array_.name() << " " << array_.arrayOf() << std::endl); // NOLINT
|
||||
|
||||
return std::make_shared<reader::ArrayReader> (
|
||||
array_.name(),
|
||||
fetchReaderForRestricted (array_.arrayOf()));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -213,24 +260,29 @@ CompositeFactory::processRestricted (
|
||||
const amqp::internal::schema::AMQPTypeNotation & type_)
|
||||
{
|
||||
DBG ("processRestricted - " << type_.name() << std::endl); // NOLINT
|
||||
const auto & restricted = dynamic_cast<const amqp::internal::schema::Restricted &> (
|
||||
const auto & restricted = dynamic_cast<const schema::Restricted &> (
|
||||
type_);
|
||||
|
||||
switch (restricted.restrictedType()) {
|
||||
case schema::Restricted::RestrictedTypes::List : {
|
||||
case schema::Restricted::RestrictedTypes::list_t : {
|
||||
return processList (
|
||||
dynamic_cast<const amqp::internal::schema::List &> (restricted));
|
||||
dynamic_cast<const schema::List &> (restricted));
|
||||
}
|
||||
case schema::Restricted::RestrictedTypes::Enum : {
|
||||
case schema::Restricted::RestrictedTypes::enum_t : {
|
||||
return processEnum (
|
||||
dynamic_cast<const amqp::internal::schema::Enum &> (restricted));
|
||||
dynamic_cast<const schema::Enum &> (restricted));
|
||||
}
|
||||
case schema::Restricted::RestrictedTypes::Map :{
|
||||
throw std::runtime_error ("Cannot process maps");
|
||||
case schema::Restricted::RestrictedTypes::map_t : {
|
||||
return processMap (
|
||||
dynamic_cast<const schema::Map &> (restricted));
|
||||
}
|
||||
case schema::Restricted::RestrictedTypes::array_t : {
|
||||
DBG (" array_t" << std::endl);
|
||||
return processArray (
|
||||
dynamic_cast<const schema::Array &> (restricted));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DBG (" ProcessRestricted: Returning nullptr"); // NOLINT
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -9,10 +9,12 @@
|
||||
#include "types.h"
|
||||
|
||||
#include "amqp/ICompositeFactory.h"
|
||||
#include "amqp/schema/Schema.h"
|
||||
#include "amqp/schema/Envelope.h"
|
||||
#include "amqp/schema/Composite.h"
|
||||
#include "amqp/schema/described-types/Schema.h"
|
||||
#include "amqp/schema/described-types/Envelope.h"
|
||||
#include "amqp/schema/described-types/Composite.h"
|
||||
#include "amqp/reader/CompositeReader.h"
|
||||
#include "amqp/schema/restricted-types/Map.h"
|
||||
#include "amqp/schema/restricted-types/Array.h"
|
||||
#include "amqp/schema/restricted-types/List.h"
|
||||
#include "amqp/schema/restricted-types/Enum.h"
|
||||
|
||||
@ -56,6 +58,15 @@ namespace amqp::internal {
|
||||
|
||||
std::shared_ptr<reader::Reader> processEnum (
|
||||
const schema::Enum &);
|
||||
|
||||
std::shared_ptr<reader::Reader> processMap (
|
||||
const schema::Map &);
|
||||
|
||||
std::shared_ptr<reader::Reader> processArray (
|
||||
const schema::Array &);
|
||||
|
||||
decltype(m_readersByType)::mapped_type
|
||||
fetchReaderForRestricted (const std::string &);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,156 +0,0 @@
|
||||
#include "AMQPDescriptorRegistory.h"
|
||||
#include "AMQPDescriptors.h"
|
||||
|
||||
#include "corda-descriptors/FieldDescriptor.h"
|
||||
#include "corda-descriptors/SchemaDescriptor.h"
|
||||
#include "corda-descriptors/ObjectDescriptor.h"
|
||||
#include "corda-descriptors/ChoiceDescriptor.h"
|
||||
#include "corda-descriptors/EnvelopeDescriptor.h"
|
||||
#include "corda-descriptors/CompositeDescriptor.h"
|
||||
#include "corda-descriptors/RestrictedDescriptor.h"
|
||||
|
||||
#include <limits>
|
||||
#include <climits>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
constexpr uint64_t DESCRIPTOR_TOP_32BITS = 0xc562UL << (unsigned int)(32 + 16);
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
const int ENVELOPE = 1;
|
||||
const int SCHEMA = 2;
|
||||
const int OBJECT = 3;
|
||||
const int FIELD = 4;
|
||||
const int COMPOSITE_TYPE = 5;
|
||||
const int RESTRICTED_TYPE = 6;
|
||||
const int CHOICE = 7;
|
||||
const int REFERENCED_OBJECT = 8;
|
||||
const int TRANSFORM_SCHEMA = 9;
|
||||
const int TRANSFORM_ELEMENT = 10;
|
||||
const int TRANSFORM_ELEMENT_KEY = 11;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
namespace amqp {
|
||||
|
||||
std::map<uint64_t, std::shared_ptr<internal::AMQPDescriptor>>
|
||||
AMQPDescriptorRegistory = {
|
||||
{
|
||||
22UL,
|
||||
std::make_shared<internal::AMQPDescriptor> ("DESCRIBED", -1)
|
||||
},
|
||||
{
|
||||
1UL | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::EnvelopeDescriptor> ("ENVELOPE", internal::ENVELOPE)
|
||||
},
|
||||
{
|
||||
2UL | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::SchemaDescriptor> ("SCHEMA", internal::SCHEMA)
|
||||
},
|
||||
{
|
||||
3UL | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::ObjectDescriptor> ("OBJECT_DESCRIPTOR", internal::OBJECT)
|
||||
},
|
||||
{
|
||||
4UL | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::FieldDescriptor> (
|
||||
internal::FieldDescriptor (
|
||||
"FIELD",
|
||||
internal::FIELD))
|
||||
},
|
||||
{
|
||||
5UL | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::CompositeDescriptor> (
|
||||
internal::CompositeDescriptor (
|
||||
"COMPOSITE_TYPE",
|
||||
internal::COMPOSITE_TYPE))
|
||||
},
|
||||
{
|
||||
6UL | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::RestrictedDescriptor> (
|
||||
internal::RestrictedDescriptor (
|
||||
"RESTRICTED_TYPE",
|
||||
internal::RESTRICTED_TYPE))
|
||||
},
|
||||
{
|
||||
7UL | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::ChoiceDescriptor> ("CHOICE", internal::CHOICE)
|
||||
},
|
||||
{
|
||||
8UL | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::ReferencedObjectDescriptor> (
|
||||
internal::ReferencedObjectDescriptor (
|
||||
"REFERENCED_OBJECT",
|
||||
internal::REFERENCED_OBJECT))
|
||||
},
|
||||
{
|
||||
9UL | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::TransformSchemaDescriptor> (
|
||||
internal::TransformSchemaDescriptor (
|
||||
"TRANSFORM_SCHEMA",
|
||||
internal::TRANSFORM_SCHEMA))
|
||||
},
|
||||
{
|
||||
10UL | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::TransformElementDescriptor> (
|
||||
internal::TransformElementDescriptor (
|
||||
"TRANSFORM_ELEMENT",
|
||||
internal::TRANSFORM_ELEMENT))
|
||||
},
|
||||
{
|
||||
11UL | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::TransformElementKeyDescriptor> (
|
||||
internal::TransformElementKeyDescriptor (
|
||||
"TRANSFORM_ELEMENT_KEY",
|
||||
internal::TRANSFORM_ELEMENT_KEY))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint32_t
|
||||
amqp::stripCorda (uint64_t id) {
|
||||
return static_cast<uint32_t>(id & (uint64_t)UINT_MAX);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::describedToString (uint64_t val_) {
|
||||
switch (val_) {
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::describedToString (uint32_t val_) {
|
||||
return describedToString(val_ | internal::DESCRIPTOR_TOP_32BITS);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -84,12 +84,20 @@ CompositeReader::_dump (
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_
|
||||
) const {
|
||||
DBG ("Read Composite: " << m_name << " : " << type() << std::endl); // NOLINT
|
||||
DBG ("Read Composite: "
|
||||
<< m_name
|
||||
<< " : "
|
||||
<< type()
|
||||
<< std::endl); // NOLINT
|
||||
|
||||
proton::is_described (data_);
|
||||
proton::auto_enter ae (data_);
|
||||
|
||||
const auto & it = schema_.fromDescriptor (proton::get_symbol<std::string>(data_));
|
||||
auto & fields = dynamic_cast<schema::Composite &>(*(it->second.get())).fields();
|
||||
const auto & it = schema_.fromDescriptor (
|
||||
proton::get_symbol<std::string>(data_));
|
||||
|
||||
auto & fields = dynamic_cast<schema::Composite &> (
|
||||
*(it->second.get())).fields();
|
||||
|
||||
assert (fields.size() == m_readers.size());
|
||||
|
||||
@ -104,13 +112,14 @@ CompositeReader::_dump (
|
||||
|
||||
for (int i (0) ; i < m_readers.size() ; ++i) {
|
||||
if (auto l = m_readers[i].lock()) {
|
||||
DBG (fields[i]->name() << " " << (l ? "true" : "false") << std::endl); // NOLINT
|
||||
DBG (fields[i]->name() << " "
|
||||
<< (l ? "true" : "false") << std::endl); // NOLINT
|
||||
|
||||
read.emplace_back(l->dump(fields[i]->name(), data_, schema_));
|
||||
read.emplace_back (l->dump (fields[i]->name(), data_, schema_));
|
||||
} else {
|
||||
std::stringstream s;
|
||||
s << "null field reader: " << fields[i]->name();
|
||||
throw std::runtime_error(s.str());
|
||||
throw std::runtime_error (s.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -127,6 +136,8 @@ CompositeReader::dump (
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
{
|
||||
proton::auto_next an (data_);
|
||||
|
||||
return std::make_unique<TypedPair<sVec<uPtr<amqp::reader::IValue>>>> (
|
||||
name_,
|
||||
_dump(data_, schema_));
|
||||
@ -143,6 +154,8 @@ CompositeReader::dump (
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
{
|
||||
proton::auto_next an (data_);
|
||||
|
||||
return std::make_unique<TypedSingle<sVec<uPtr<amqp::reader::IValue>>>> (
|
||||
_dump (data_, schema_));
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <any>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <amqp/schema/Schema.h>
|
||||
#include <amqp/schema/described-types/Schema.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -54,11 +54,12 @@ namespace {
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* Static methods
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Static factory method
|
||||
*/
|
||||
std::shared_ptr<amqp::internal::reader::PropertyReader>
|
||||
amqp::internal::reader::
|
||||
PropertyReader::make (const FieldPtr & field_) {
|
||||
@ -75,4 +76,10 @@ PropertyReader::make (const std::string & type_) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::shared_ptr<amqp::internal::reader::PropertyReader>
|
||||
amqp::internal::reader::
|
||||
PropertyReader::make (const internal::schema::Field & field_) {
|
||||
return propertyMap[field_.type()]();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "Reader.h"
|
||||
|
||||
#include "amqp/schema/Field.h"
|
||||
#include "amqp/schema/field-types/Field.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@ -18,13 +18,14 @@ namespace amqp::internal::reader {
|
||||
/**
|
||||
* Static Factory method for creating appropriate derived types
|
||||
*/
|
||||
static std::shared_ptr<PropertyReader> make (const internal::schema::Field &);
|
||||
static std::shared_ptr<PropertyReader> make (const FieldPtr &);
|
||||
static std::shared_ptr<PropertyReader> make (const std::string &);
|
||||
|
||||
PropertyReader() = default;
|
||||
~PropertyReader() override = default;
|
||||
|
||||
std::string readString(pn_data_t *) const override = 0;
|
||||
std::string readString (pn_data_t *) const override = 0;
|
||||
|
||||
std::any read (pn_data_t *) const override = 0;
|
||||
|
||||
|
@ -56,9 +56,11 @@ namespace {
|
||||
{
|
||||
Auto am (name_, rtn);
|
||||
|
||||
rtn << (*(begin_))->dump();
|
||||
for (auto it(std::next(begin_)) ; it != end_; ++it) {
|
||||
rtn << ", " << (*it)->dump();
|
||||
if (begin_ != end_) {
|
||||
rtn << (*(begin_))->dump();
|
||||
for (auto it(std::next(begin_)); it != end_; ++it) {
|
||||
rtn << ", " << (*it)->dump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,9 +74,11 @@ namespace {
|
||||
{
|
||||
Auto am (rtn);
|
||||
|
||||
rtn << (*(begin_))->dump();
|
||||
for (auto it (std::next(begin_)) ; it != end_; ++it) {
|
||||
rtn << ", " << (*it)->dump();
|
||||
if (begin_ != end_) {
|
||||
rtn << (*(begin_))->dump();
|
||||
for (auto it(std::next(begin_)); it != end_; ++it) {
|
||||
rtn << ", " << (*it)->dump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,7 +89,23 @@ namespace {
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::reader::TypedValuePair
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::internal::reader::
|
||||
ValuePair::dump() const {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << m_key->dump() << " : " << m_value->dump();
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::reader::TypedPair
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "amqp/schema/Schema.h"
|
||||
#include "amqp/schema/described-types/Schema.h"
|
||||
#include "amqp/reader/IReader.h"
|
||||
|
||||
/******************************************************************************/
|
||||
@ -22,6 +22,19 @@ namespace amqp::internal::reader {
|
||||
~Value() override = default;
|
||||
};
|
||||
|
||||
/*
|
||||
* A Single represents some value read out of a proton tree that
|
||||
* exists without an association. The canonical example is an
|
||||
* element of a list. The list itself would be a pair,
|
||||
*
|
||||
* e.g. a : [ ]
|
||||
*
|
||||
* but the values of the list
|
||||
*
|
||||
* e.g. a : [ A, B, C ]
|
||||
*
|
||||
* are Singles
|
||||
*/
|
||||
class Single : public Value {
|
||||
public :
|
||||
std::string dump() const override = 0;
|
||||
@ -57,13 +70,19 @@ namespace amqp::internal::reader {
|
||||
std::string dump() const override;
|
||||
};
|
||||
|
||||
/*
|
||||
* A Pair represents an association between a property and
|
||||
* the value of the property, i.e. a : b where property
|
||||
* a has value b
|
||||
*/
|
||||
class Pair : public Value {
|
||||
protected :
|
||||
std::string m_property;
|
||||
|
||||
public:
|
||||
explicit Pair (std::string property_)
|
||||
: m_property (std::move (property_))
|
||||
: Value()
|
||||
, m_property (std::move (property_))
|
||||
{ }
|
||||
|
||||
~Pair() override = default;
|
||||
@ -104,6 +123,29 @@ namespace amqp::internal::reader {
|
||||
std::string dump() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Similar to [Pair] where k : v relationships are modelled. In this
|
||||
* case, however, rather than modelling a property : value relationship
|
||||
* we are modelling a key : value one. The primary difference is that
|
||||
* keys need not be simple strings.
|
||||
*/
|
||||
class ValuePair : public Value {
|
||||
private :
|
||||
uPtr<amqp::reader::IValue> m_key;
|
||||
uPtr<amqp::reader::IValue> m_value;
|
||||
|
||||
public :
|
||||
ValuePair (
|
||||
decltype (m_key) key_,
|
||||
decltype (m_value) value_
|
||||
) : Value ()
|
||||
, m_key (std::move (key_))
|
||||
, m_value (std::move (value_))
|
||||
{ }
|
||||
|
||||
std::string dump() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@ -116,7 +158,7 @@ template<typename T>
|
||||
inline std::string
|
||||
amqp::internal::reader::
|
||||
TypedSingle<T>::dump() const {
|
||||
return std::to_string(m_value);
|
||||
return std::to_string (m_value);
|
||||
}
|
||||
|
||||
template<>
|
||||
@ -176,7 +218,6 @@ std::string
|
||||
amqp::internal::reader::
|
||||
TypedPair<sList<uPtr<amqp::reader::IValue>>>::dump() const;
|
||||
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::internal::reader::
|
||||
@ -191,13 +232,23 @@ TypedPair<sList<uPtr<amqp::internal::reader::Pair>>>::dump() const;
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal::reader {
|
||||
|
||||
using IReader = amqp::reader::IReader<schema::SchemaMap::const_iterator>;
|
||||
|
||||
/**
|
||||
* Interface that represents an object that has the ability to consume
|
||||
* the payload of a Corda serialized blob in a way defined by some
|
||||
* prior construction. This construction will usually come from
|
||||
* analysis of the schema, although in the JVM versions it will come
|
||||
* from reflection of the type definitions.
|
||||
*
|
||||
* In other words, when encountering a graph of nodes with values, an
|
||||
* instance of [Reader] will give a sub tree of that graph contextual
|
||||
* meaning.
|
||||
*/
|
||||
class Reader : public IReader {
|
||||
public :
|
||||
~Reader() override = default;
|
||||
|
@ -31,7 +31,7 @@ BoolPropertyReader::m_type { // NOLINT
|
||||
std::any
|
||||
amqp::internal::reader::
|
||||
BoolPropertyReader::read (pn_data_t * data_) const {
|
||||
return std::any (true);
|
||||
return std::any (proton::readAndNext<bool> (data_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -29,7 +29,7 @@ DoublePropertyReader::m_type { // NOLINT
|
||||
std::any
|
||||
amqp::internal::reader::
|
||||
DoublePropertyReader::read (pn_data_t * data_) const {
|
||||
return std::any (10.0);
|
||||
return std::any { proton::readAndNext<double> (data_) };
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -45,9 +45,9 @@ DoublePropertyReader::readString (pn_data_t * data_) const {
|
||||
uPtr<amqp::reader::IValue>
|
||||
amqp::internal::reader::
|
||||
DoublePropertyReader::dump (
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedPair<std::string>> (
|
||||
name_,
|
||||
|
@ -37,7 +37,7 @@ IntPropertyReader::m_type { // NOLINT
|
||||
std::any
|
||||
amqp::internal::reader::
|
||||
IntPropertyReader::read (pn_data_t * data_) const {
|
||||
return std::any (1);
|
||||
return std::any { proton::readAndNext<int> (data_) };
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -53,9 +53,9 @@ IntPropertyReader::readString (pn_data_t * data_) const {
|
||||
uPtr<amqp::reader::IValue>
|
||||
amqp::internal::reader::
|
||||
IntPropertyReader::dump (
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedPair<std::string>> (
|
||||
name_,
|
||||
@ -67,8 +67,8 @@ IntPropertyReader::dump (
|
||||
uPtr<amqp::reader::IValue>
|
||||
amqp::internal::reader::
|
||||
IntPropertyReader::dump (
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedSingle<std::string>> (
|
||||
std::to_string (proton::readAndNext<int> (data_)));
|
||||
|
@ -31,7 +31,7 @@ LongPropertyReader::m_type { // NOLINT
|
||||
std::any
|
||||
amqp::internal::reader::
|
||||
LongPropertyReader::read (pn_data_t * data_) const {
|
||||
return std::any (10L);
|
||||
return std::any { proton::readAndNext<long> (data_) };
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -47,9 +47,9 @@ LongPropertyReader::readString (pn_data_t * data_) const {
|
||||
uPtr<amqp::reader::IValue>
|
||||
amqp::internal::reader::
|
||||
LongPropertyReader::dump (
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedPair<std::string>> (
|
||||
name_,
|
||||
@ -61,8 +61,8 @@ LongPropertyReader::dump (
|
||||
uPtr<amqp::reader::IValue>
|
||||
amqp::internal::reader::
|
||||
LongPropertyReader::dump (
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedSingle<std::string>> (
|
||||
std::to_string (proton::readAndNext<long> (data_)));
|
||||
|
@ -33,7 +33,7 @@ StringPropertyReader::m_name { // NOLINT
|
||||
std::any
|
||||
amqp::internal::reader::
|
||||
StringPropertyReader::read (pn_data_t * data_) const {
|
||||
return std::any ("hello");
|
||||
return std::any { proton::readAndNext<std::string> (data_) };
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -49,9 +49,9 @@ StringPropertyReader::readString (pn_data_t * data_) const {
|
||||
uPtr<amqp::reader::IValue>
|
||||
amqp::internal::reader::
|
||||
StringPropertyReader::dump (
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedPair<std::string>> (
|
||||
name_,
|
||||
|
@ -0,0 +1,86 @@
|
||||
#include "ArrayReader.h"
|
||||
|
||||
#include "proton/proton_wrapper.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* class ArrayReader
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::reader::
|
||||
ArrayReader::ArrayReader (
|
||||
std::string type_,
|
||||
std::weak_ptr<Reader> reader_
|
||||
) : RestrictedReader (std::move (type_))
|
||||
, m_reader (std::move (reader_))
|
||||
{ }
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::Restricted::RestrictedTypes
|
||||
amqp::internal::reader::
|
||||
ArrayReader::restrictedType() const {
|
||||
return internal::schema::Restricted::RestrictedTypes::array_t;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::reader::IValue>
|
||||
amqp::internal::reader::
|
||||
ArrayReader::dump (
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_
|
||||
) const {
|
||||
proton::auto_next an (data_);
|
||||
|
||||
return std::make_unique<TypedPair<sList<uPtr<amqp::reader::IValue>>>>(
|
||||
name_,
|
||||
dump_ (data_, schema_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::reader::IValue>
|
||||
amqp::internal::reader::
|
||||
ArrayReader::dump(
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_
|
||||
) const {
|
||||
proton::auto_next an (data_);
|
||||
|
||||
return std::make_unique<TypedSingle<sList<uPtr<amqp::reader::IValue>>>>(
|
||||
dump_ (data_, schema_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
sList<uPtr<amqp::reader::IValue>>
|
||||
amqp::internal::reader::
|
||||
ArrayReader::dump_(
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_
|
||||
) const {
|
||||
proton::is_described (data_);
|
||||
|
||||
decltype (dump_ (data_, schema_)) read;
|
||||
|
||||
{
|
||||
proton::auto_enter ae (data_);
|
||||
schema_.fromDescriptor (proton::readAndNext<std::string>(data_));
|
||||
|
||||
{
|
||||
proton::auto_list_enter ale (data_, true);
|
||||
|
||||
for (size_t i { 0 } ; i < ale.elements() ; ++i) {
|
||||
read.emplace_back (m_reader.lock()->dump (data_, schema_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "RestrictedReader.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::reader {
|
||||
|
||||
class ArrayReader : public RestrictedReader {
|
||||
private :
|
||||
// How to read the underlying types
|
||||
std::weak_ptr<Reader> m_reader;
|
||||
|
||||
std::list<uPtr<amqp::reader::IValue>> dump_(
|
||||
pn_data_t *,
|
||||
const SchemaType &) const;
|
||||
|
||||
/**
|
||||
* cope with the fact Java can box primitives
|
||||
*/
|
||||
std::string m_primType;
|
||||
|
||||
public :
|
||||
ArrayReader (std::string, std::weak_ptr<Reader>);
|
||||
|
||||
~ArrayReader() final = default;
|
||||
|
||||
internal::schema::Restricted::RestrictedTypes restrictedType() const;
|
||||
|
||||
std::unique_ptr<amqp::reader::IValue> dump(
|
||||
const std::string &,
|
||||
pn_data_t *,
|
||||
const SchemaType &) const override;
|
||||
|
||||
std::unique_ptr<amqp::reader::IValue> dump(
|
||||
pn_data_t *,
|
||||
const SchemaType &) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -1,7 +1,8 @@
|
||||
#include "EnumReader.h"
|
||||
|
||||
#include "amqp/reader/IReader.h"
|
||||
#include "amqp/descriptors/AMQPDescriptorRegistory.h"
|
||||
#include "amqp/schema/Descriptors.h"
|
||||
#include "amqp/schema/descriptors/AMQPDescriptorRegistory.h"
|
||||
#include "proton/proton_wrapper.h"
|
||||
|
||||
/******************************************************************************/
|
||||
@ -19,6 +20,7 @@ EnumReader::EnumReader (
|
||||
/******************************************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
std::string
|
||||
getValue (pn_data_t * data_) {
|
||||
proton::is_described (data_);
|
||||
@ -34,7 +36,7 @@ namespace {
|
||||
*/
|
||||
if (pn_data_type (data_) == PN_ULONG) {
|
||||
if (amqp::stripCorda(pn_data_get_ulong(data_)) ==
|
||||
amqp::internal::REFERENCED_OBJECT
|
||||
amqp::schema::descriptors::REFERENCED_OBJECT
|
||||
) {
|
||||
throw std::runtime_error (
|
||||
"Currently don't support referenced objects");
|
||||
@ -54,9 +56,7 @@ namespace {
|
||||
* here I'll forget its even a thing
|
||||
*/
|
||||
// auto idx = proton::readAndNext<int>(data_);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,7 +89,6 @@ EnumReader::dump(
|
||||
proton::is_described (data_);
|
||||
|
||||
return std::make_unique<TypedSingle<std::string>> (getValue(data_));
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -11,12 +11,12 @@
|
||||
amqp::internal::schema::Restricted::RestrictedTypes
|
||||
amqp::internal::reader::
|
||||
ListReader::restrictedType() const {
|
||||
return internal::schema::Restricted::RestrictedTypes::List;
|
||||
return internal::schema::Restricted::RestrictedTypes::list_t;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::reader::IValue>
|
||||
uPtr<amqp::reader::IValue>
|
||||
amqp::internal::reader::
|
||||
ListReader::dump (
|
||||
const std::string & name_,
|
||||
@ -32,7 +32,7 @@ ListReader::dump (
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::reader::IValue>
|
||||
uPtr<amqp::reader::IValue>
|
||||
amqp::internal::reader::
|
||||
ListReader::dump(
|
||||
pn_data_t * data_,
|
||||
@ -46,7 +46,7 @@ ListReader::dump(
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::list<std::unique_ptr<amqp::reader::IValue>>
|
||||
sList<uPtr<amqp::reader::IValue>>
|
||||
amqp::internal::reader::
|
||||
ListReader::dump_(
|
||||
pn_data_t * data_,
|
||||
@ -54,7 +54,7 @@ ListReader::dump_(
|
||||
) const {
|
||||
proton::is_described (data_);
|
||||
|
||||
std::list<std::unique_ptr<amqp::reader::IValue>> read;
|
||||
decltype (dump_(data_, schema_)) read;
|
||||
|
||||
{
|
||||
proton::auto_enter ae (data_);
|
||||
|
@ -0,0 +1,82 @@
|
||||
#include "MapReader.h"
|
||||
|
||||
#include "Reader.h"
|
||||
#include "amqp/reader/IReader.h"
|
||||
#include "proton/proton_wrapper.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::Restricted::RestrictedTypes
|
||||
amqp::internal::reader::
|
||||
MapReader::restrictedType() const {
|
||||
return schema::Restricted::Restricted::map_t;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
sVec<uPtr<amqp::reader::IValue>>
|
||||
amqp::internal::reader::
|
||||
MapReader::dump_(
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_
|
||||
) const {
|
||||
proton::is_described (data_);
|
||||
proton::auto_enter ae (data_);
|
||||
|
||||
// gloss over fetching the descriptor from the schema since
|
||||
// we don't need it, we know the types this is a reader for
|
||||
// and don't need context from the schema as there isn't
|
||||
// any. Maps have a Key and a Value, they aren't named
|
||||
// parameters, unlike composite types.
|
||||
schema_.fromDescriptor (proton::readAndNext<std::string>(data_));
|
||||
|
||||
{
|
||||
proton::auto_map_enter am (data_, true);
|
||||
|
||||
decltype (dump_(data_, schema_)) rtn;
|
||||
rtn.reserve (am.elements() / 2);
|
||||
|
||||
for (int i {0} ; i < am.elements() ; i += 2) {
|
||||
rtn.emplace_back (
|
||||
std::make_unique<ValuePair> (
|
||||
m_keyReader.lock()->dump (data_, schema_),
|
||||
m_valueReader.lock()->dump (data_, schema_)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::reader::IValue>
|
||||
amqp::internal::reader::
|
||||
MapReader::dump(
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_
|
||||
) const {
|
||||
proton::auto_next an (data_);
|
||||
|
||||
return std::make_unique<TypedPair<sVec<uPtr<amqp::reader::IValue>>>>(
|
||||
name_,
|
||||
dump_ (data_, schema_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::reader::IValue>
|
||||
amqp::internal::reader::
|
||||
MapReader::dump(
|
||||
pn_data_t * data_,
|
||||
const SchemaType & schema_
|
||||
) const {
|
||||
proton::auto_next an (data_);
|
||||
|
||||
return std::make_unique<TypedSingle<sVec<uPtr<amqp::reader::IValue>>>>(
|
||||
dump_ (data_, schema_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "RestrictedReader.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::reader {
|
||||
|
||||
class MapReader : public RestrictedReader {
|
||||
private :
|
||||
// How to read the underlying types
|
||||
std::weak_ptr<Reader> m_keyReader;
|
||||
std::weak_ptr<Reader> m_valueReader;
|
||||
|
||||
sVec<uPtr<amqp::reader::IValue>> dump_(
|
||||
pn_data_t *,
|
||||
const SchemaType &) const;
|
||||
|
||||
public :
|
||||
MapReader (
|
||||
const std::string & type_,
|
||||
std::weak_ptr<Reader> keyReader_,
|
||||
std::weak_ptr<Reader> valueReader_
|
||||
) : RestrictedReader (type_)
|
||||
, m_keyReader (std::move (keyReader_))
|
||||
, m_valueReader (std::move (valueReader_))
|
||||
{ }
|
||||
|
||||
~MapReader() final = default;
|
||||
|
||||
internal::schema::Restricted::RestrictedTypes restrictedType() const;
|
||||
|
||||
std::unique_ptr<amqp::reader::IValue> dump(
|
||||
const std::string &,
|
||||
pn_data_t *,
|
||||
const SchemaType &) const override;
|
||||
|
||||
std::unique_ptr<amqp::reader::IValue> dump(
|
||||
pn_data_t *,
|
||||
const SchemaType &) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "colours.h"
|
||||
|
||||
#include "Composite.h"
|
||||
#include "amqp/schema/described-types/Composite.h"
|
||||
#include "amqp/schema/restricted-types/Restricted.h"
|
||||
|
||||
/******************************************************************************
|
||||
@ -25,11 +25,11 @@ namespace amqp::internal::schema {
|
||||
std::ostream &
|
||||
operator << (std::ostream & stream_, const AMQPTypeNotation & clazz_) {
|
||||
switch (clazz_.type()) {
|
||||
case AMQPTypeNotation::Type::Composite : {
|
||||
case AMQPTypeNotation::Type::composite_t : {
|
||||
stream_ << dynamic_cast<const Composite &>(clazz_);
|
||||
break;
|
||||
}
|
||||
case AMQPTypeNotation::Type::Restricted : {
|
||||
case AMQPTypeNotation::Type::restricted_t : {
|
||||
stream_ << dynamic_cast<const Restricted &>(clazz_);
|
||||
break;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <memory>
|
||||
#include <types.h>
|
||||
|
||||
#include "Descriptor.h"
|
||||
#include "amqp/schema/described-types/Descriptor.h"
|
||||
#include "OrderedTypeNotations.h"
|
||||
|
||||
/******************************************************************************
|
||||
@ -37,16 +37,16 @@ namespace amqp::internal::schema {
|
||||
std::ostream &,
|
||||
const AMQPTypeNotation &);
|
||||
|
||||
enum Type { Composite, Restricted };
|
||||
enum Type { composite_t, restricted_t };
|
||||
|
||||
private :
|
||||
std::string m_name;
|
||||
std::unique_ptr<Descriptor> m_descriptor;
|
||||
std::string m_name;
|
||||
uPtr<Descriptor> m_descriptor;
|
||||
|
||||
public :
|
||||
AMQPTypeNotation (
|
||||
std::string name_,
|
||||
std::unique_ptr<Descriptor> descriptor_
|
||||
uPtr<Descriptor> descriptor_
|
||||
) : m_name (std::move (name_))
|
||||
, m_descriptor (std::move (descriptor_))
|
||||
{ }
|
||||
@ -57,9 +57,8 @@ namespace amqp::internal::schema {
|
||||
|
||||
virtual Type type() const = 0;
|
||||
|
||||
int dependsOn (const OrderedTypeNotation &) const override = 0;
|
||||
virtual int dependsOn (const class Restricted &) const = 0;
|
||||
virtual int dependsOn (const class Composite &) const = 0;
|
||||
virtual int dependsOnRHS (const Restricted &) const = 0;
|
||||
virtual int dependsOnRHS (const Composite &) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
21
experimental/cpp-serializer/src/amqp/schema/Descriptors.cxx
Normal file
21
experimental/cpp-serializer/src/amqp/schema/Descriptors.cxx
Normal file
@ -0,0 +1,21 @@
|
||||
#include "amqp/schema/Descriptors.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::schema::descriptors {
|
||||
|
||||
const int ENVELOPE = 1;
|
||||
const int SCHEMA = 2;
|
||||
const int OBJECT = 3;
|
||||
const int FIELD = 4;
|
||||
const int COMPOSITE_TYPE = 5;
|
||||
const int RESTRICTED_TYPE = 6;
|
||||
const int CHOICE = 7;
|
||||
const int REFERENCED_OBJECT = 8;
|
||||
const int TRANSFORM_SCHEMA = 9;
|
||||
const int TRANSFORM_ELEMENT = 10;
|
||||
const int TRANSFORM_ELEMENT_KEY = 11;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -1,109 +0,0 @@
|
||||
#include "Field.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
std::ostream &
|
||||
operator << (std::ostream & stream_, const Field & field_) {
|
||||
std::stringstream ss;
|
||||
for (auto &i: field_.m_requires) { ss << i; }
|
||||
|
||||
stream_ << field_.m_name << " : " << field_.m_type.first << " : [" << ss.str() << "]" << std::endl;
|
||||
|
||||
return stream_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
Field::Field (
|
||||
const std::string & name_,
|
||||
const std::string & type_,
|
||||
const std::list<std::string> & requires_,
|
||||
const std::string & default_,
|
||||
const std::string & label_,
|
||||
bool mandatory_,
|
||||
bool multiple_
|
||||
) : m_name (name_)
|
||||
, m_requires (requires_)
|
||||
, m_default (default_)
|
||||
, m_label (label_)
|
||||
, m_mandatory (mandatory_)
|
||||
, m_multiple (multiple_)
|
||||
{
|
||||
if (typeIsPrimitive(type_)) {
|
||||
m_type = std::make_pair(type_, FieldType::PrimitiveProperty);
|
||||
} else if (type_ == "*") {
|
||||
m_type = std::make_pair(type_, FieldType::RestrictedProperty);
|
||||
} else {
|
||||
m_type = std::make_pair(type_, FieldType::CompositeProperty);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
bool
|
||||
amqp::internal::schema::
|
||||
Field::typeIsPrimitive(const std::string & type_) {
|
||||
return (type_ == "string" ||
|
||||
type_ == "long" ||
|
||||
type_ == "boolean" ||
|
||||
type_ == "int" ||
|
||||
type_ == "double");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
Field::name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
Field::type() const {
|
||||
return m_type.first;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
Field::resolvedType() const {
|
||||
return (type() == "*") ? requires().front() : type();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::FieldType
|
||||
amqp::internal::schema::
|
||||
Field::fieldType() const {
|
||||
return m_type.second;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::list<std::string> &
|
||||
amqp::internal::schema::
|
||||
Field::requires() const {
|
||||
return m_requires;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
bool
|
||||
amqp::internal::schema::
|
||||
Field::primitive() const {
|
||||
return m_type.second == PrimitiveProperty;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -1,63 +0,0 @@
|
||||
#pragma once
|
||||
/******************************************************************************/
|
||||
|
||||
#include "Descriptor.h"
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
enum FieldType { PrimitiveProperty, CompositeProperty, RestrictedProperty };
|
||||
|
||||
/**
|
||||
*
|
||||
* A Corda AMQP Scehma Field type has:
|
||||
* - name : String
|
||||
* - type : String
|
||||
* - requires : List<String>
|
||||
* - default : nullable String
|
||||
* - label : nullable String
|
||||
* - mandatory : Boolean
|
||||
* - multiple : Boolean
|
||||
*/
|
||||
class Field : public AMQPDescribed {
|
||||
public :
|
||||
friend std::ostream & operator << (std::ostream &, const Field &);
|
||||
|
||||
static bool typeIsPrimitive(const std::string &);
|
||||
|
||||
private :
|
||||
std::string m_name;
|
||||
std::pair<std::string, FieldType> m_type;
|
||||
std::list<std::string> m_requires;
|
||||
std::string m_default;
|
||||
std::string m_label;
|
||||
bool m_mandatory;
|
||||
bool m_multiple;
|
||||
|
||||
public :
|
||||
Field (const std::string & name_,
|
||||
const std::string & type_,
|
||||
const std::list<std::string> & requires_,
|
||||
const std::string & default_,
|
||||
const std::string & label_,
|
||||
bool mandatory_,
|
||||
bool multiple_);
|
||||
|
||||
const std::string & name() const;
|
||||
const std::string & type() const;
|
||||
const std::string & resolvedType() const;
|
||||
FieldType fieldType() const;
|
||||
const std::list<std::string> & requires() const;
|
||||
bool primitive() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
|
||||
#include "debug.h"
|
||||
#include "types.h"
|
||||
#include "colours.h"
|
||||
|
||||
@ -60,18 +61,18 @@ namespace amqp::internal::schema {
|
||||
typename std::list<std::list<uPtr<T>>>::iterator &);
|
||||
|
||||
public :
|
||||
void insert(uPtr<T> && ptr);
|
||||
void insert (uPtr<T> && ptr);
|
||||
|
||||
friend std::ostream & ::operator << <> (
|
||||
std::ostream &,
|
||||
const amqp::internal::schema::OrderedTypeNotations<T> &);
|
||||
|
||||
decltype (m_schemas.crbegin()) begin() const {
|
||||
return m_schemas.crbegin();
|
||||
decltype (m_schemas.cbegin()) begin() const {
|
||||
return m_schemas.cbegin();
|
||||
}
|
||||
|
||||
decltype (m_schemas.crend()) end() const {
|
||||
return m_schemas.crend();
|
||||
decltype (m_schemas.cend()) end() const {
|
||||
return m_schemas.cend();
|
||||
}
|
||||
};
|
||||
|
||||
@ -85,7 +86,7 @@ operator << (
|
||||
std::ostream &stream_,
|
||||
const amqp::internal::schema::OrderedTypeNotations<T> &otn_
|
||||
) {
|
||||
int idx1{0};
|
||||
int idx1 {0};
|
||||
for (const auto &i : otn_.m_schemas) {
|
||||
stream_ << "level " << ++idx1 << std::endl;
|
||||
for (const auto &j : i) {
|
||||
@ -145,6 +146,7 @@ OrderedTypeNotations<T>::insert (
|
||||
uPtr<T> && ptr,
|
||||
amqp::internal::schema::OrderedTypeNotations<T>::iterator l_
|
||||
) {
|
||||
DBG ("Insert: " << ptr->name() << std::endl);
|
||||
/*
|
||||
* First we find where this element needs to be added
|
||||
*/
|
||||
|
@ -1,5 +1,16 @@
|
||||
#include "Choice.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::ostream &
|
||||
amqp::internal::schema::
|
||||
operator << (std::ostream & os_, const amqp::internal::schema::Choice & choice_) {
|
||||
os_ << choice_.m_choice;
|
||||
return os_;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
@ -1,14 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "AMQPTypeNotation.h"
|
||||
#include <iosfwd>
|
||||
|
||||
#include "schema/AMQPTypeNotation.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class Choice : public AMQPDescribed {
|
||||
public :
|
||||
friend std::ostream & operator << (std::ostream &, const Choice &);
|
||||
|
||||
private :
|
||||
std::string m_choice;
|
||||
|
||||
public :
|
||||
Choice() = delete;
|
||||
|
@ -62,7 +62,7 @@ Composite::fields() const {
|
||||
amqp::internal::schema::AMQPTypeNotation::Type
|
||||
amqp::internal::schema::
|
||||
Composite::type() const {
|
||||
return AMQPTypeNotation::Type::Composite;
|
||||
return AMQPTypeNotation::Type::composite_t;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -87,64 +87,66 @@ Composite::type() const {
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Composite::dependsOn (const OrderedTypeNotation & rhs) const {
|
||||
return dynamic_cast<const AMQPTypeNotation &>(rhs).dependsOn(*this);
|
||||
return dynamic_cast<const AMQPTypeNotation &>(rhs).dependsOnRHS(*this);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Composite::dependsOn (const amqp::internal::schema::Restricted & lhs_) const {
|
||||
// does the left hand side depend on us
|
||||
auto rtn { 0 };
|
||||
|
||||
for (const auto i : lhs_) {
|
||||
DBG (" C/R a) " << i << " == " << name() << std::endl); // NOLINT
|
||||
if (i == name()) {
|
||||
rtn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
Composite::dependsOnRHS (
|
||||
const amqp::internal::schema::Restricted & lhs_
|
||||
) const {
|
||||
// does this depend on the left hand side
|
||||
for (auto const & field : m_fields) {
|
||||
DBG (" C/R b) " << field->resolvedType() << " == " << lhs_.name() << std::endl); // NOLINT
|
||||
|
||||
if (field->resolvedType() == lhs_.name()) {
|
||||
rtn = 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return rtn;
|
||||
// does the left hand side depend on us
|
||||
for (const auto i : lhs_) {
|
||||
DBG (" C/R a) " << i << " == " << name() << std::endl); // NOLINT
|
||||
if (i == name()) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************************o*********************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Composite::dependsOn (const amqp::internal::schema::Composite & lhs_) const {
|
||||
auto rtn { 0 };
|
||||
Composite::dependsOnRHS (
|
||||
const amqp::internal::schema::Composite & lhs_
|
||||
) const {
|
||||
DBG (name() << " ?Depends on " << lhs_.name() << std::endl);
|
||||
|
||||
// do we depend on the lhs, i.e. is one of our fields it
|
||||
for (auto const & field : lhs_) {
|
||||
DBG (" C/C a) " << field->resolvedType() << " == " << name() << std::endl); // NOLINT
|
||||
if (field->resolvedType() == name()) {
|
||||
rtn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// does the left hand side depend on us. i.e. is one of it's fields
|
||||
// us
|
||||
// do we depend on the lhs
|
||||
for (const auto & field : m_fields) {
|
||||
DBG (" C/C b) " << field->resolvedType() << " == " << lhs_.name() << std::endl); // NOLINT
|
||||
DBG ("FIELD - " << name() << "::" << type() << std::endl);
|
||||
DBG (" C/C a) " << field->resolvedType() << " == " << lhs_.name() << std::endl); // NOLINT
|
||||
|
||||
if (field->resolvedType() == lhs_.name()) {
|
||||
rtn = 2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// does it depend on us
|
||||
for (auto const & field : lhs_) {
|
||||
DBG ("FIELD - " << name() << "::" << type() << std::endl);
|
||||
DBG (" C/C b) " << field->resolvedType() << " == " << name() << std::endl); // NOLINT
|
||||
if (field->resolvedType() == name()) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return rtn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -8,9 +8,9 @@
|
||||
#include <string>
|
||||
#include <types.h>
|
||||
|
||||
#include "Field.h"
|
||||
#include "schema/field-types/Field.h"
|
||||
#include "Descriptor.h"
|
||||
#include "AMQPTypeNotation.h"
|
||||
#include "schema/AMQPTypeNotation.h"
|
||||
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
|
||||
@ -73,8 +73,8 @@ namespace amqp::internal::schema {
|
||||
Type type() const override;
|
||||
|
||||
int dependsOn (const OrderedTypeNotation &) const override;
|
||||
int dependsOn (const class Restricted &) const override;
|
||||
int dependsOn (const Composite &) const override;
|
||||
int dependsOnRHS (const class Restricted &) const override;
|
||||
int dependsOnRHS (const Composite &) const override;
|
||||
|
||||
decltype(m_fields)::const_iterator begin() const { return m_fields.cbegin();}
|
||||
decltype(m_fields)::const_iterator end() const { return m_fields.cend(); }
|
@ -19,8 +19,6 @@ namespace amqp::internal::schema {
|
||||
std::string m_name;
|
||||
|
||||
public :
|
||||
Descriptor() = default;
|
||||
|
||||
explicit Descriptor (std::string);
|
||||
|
||||
const std::string & name() const;
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "amqp/schema/Schema.h"
|
||||
#include "amqp/schema/described-types/Schema.h"
|
||||
#include "amqp/schema/ISchema.h"
|
||||
|
||||
/******************************************************************************/
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
|
||||
#include "Schema.h"
|
||||
#include "amqp/schema/described-types/Schema.h"
|
||||
|
||||
#include <iosfwd>
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "types.h"
|
||||
#include "Composite.h"
|
||||
#include "Descriptor.h"
|
||||
#include "OrderedTypeNotations.h"
|
||||
#include "schema/OrderedTypeNotations.h"
|
||||
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
#include "amqp/schema/ISchema.h"
|
||||
@ -20,10 +20,16 @@ namespace amqp::internal::schema {
|
||||
|
||||
using SchemaMap = std::map<
|
||||
std::string,
|
||||
const std::reference_wrapper<const uPtr<AMQPTypeNotation>>>;
|
||||
const std::reference_wrapper<const uPtr <AMQPTypeNotation>>>;
|
||||
|
||||
using ISchemaType = amqp::schema::ISchema<SchemaMap::const_iterator>;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class Schema
|
||||
: public amqp::schema::ISchema<SchemaMap::const_iterator>
|
||||
, public amqp::AMQPDescribed
|
@ -1,17 +1,17 @@
|
||||
#include "AMQPDescriptor.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <amqp/descriptors/corda-descriptors/EnvelopeDescriptor.h>
|
||||
#include <amqp/schema/descriptors/corda-descriptors/EnvelopeDescriptor.h>
|
||||
|
||||
#include "proton/proton_wrapper.h"
|
||||
#include "AMQPDescriptorRegistory.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
std::ostream &
|
||||
operator<<(std::ostream &stream_, const amqp::internal::AutoIndent &ai_) {
|
||||
operator<<(std::ostream &stream_, const AutoIndent &ai_) {
|
||||
stream_ << ai_.indent;
|
||||
return stream_;
|
||||
}
|
||||
@ -21,7 +21,7 @@ namespace amqp::internal {
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
AMQPDescriptor::symbol() const {
|
||||
return m_symbol;
|
||||
}
|
||||
@ -29,7 +29,7 @@ AMQPDescriptor::symbol() const {
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::AMQPDescribed>
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
AMQPDescriptor::build (pn_data_t *) const {
|
||||
throw std::runtime_error ("Should never be called");
|
||||
}
|
||||
@ -37,7 +37,7 @@ AMQPDescriptor::build (pn_data_t *) const {
|
||||
/******************************************************************************/
|
||||
|
||||
inline void
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
AMQPDescriptor::read (
|
||||
pn_data_t * data_,
|
||||
std::stringstream & ss_
|
||||
@ -48,7 +48,7 @@ AMQPDescriptor::read (
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
AMQPDescriptor::read (
|
||||
pn_data_t * data_,
|
||||
std::stringstream & ss_,
|
@ -23,22 +23,21 @@ struct pn_data_t;
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class AutoIndent {
|
||||
private :
|
||||
std::string indent;
|
||||
public :
|
||||
AutoIndent() : indent { "" } { }
|
||||
private :
|
||||
std::string indent;
|
||||
public :
|
||||
AutoIndent() : indent { "" } { }
|
||||
|
||||
AutoIndent (const AutoIndent & ai_)
|
||||
: indent { ai_.indent + " "}
|
||||
{ }
|
||||
AutoIndent (const AutoIndent & ai_)
|
||||
: indent { ai_.indent + " "}
|
||||
{ }
|
||||
|
||||
friend std::ostream &
|
||||
operator << (std::ostream & stream_, const AutoIndent & ai_);
|
||||
|
||||
};
|
||||
friend std::ostream &
|
||||
operator << (std::ostream & stream_, const AutoIndent & ai_);
|
||||
};
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@ -47,7 +46,7 @@ namespace amqp::internal {
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class AMQPDescriptor {
|
||||
protected :
|
@ -0,0 +1,133 @@
|
||||
#include "AMQPDescriptorRegistory.h"
|
||||
#include "AMQPDescriptors.h"
|
||||
|
||||
#include "amqp/schema/Descriptors.h"
|
||||
|
||||
#include "corda-descriptors/FieldDescriptor.h"
|
||||
#include "corda-descriptors/SchemaDescriptor.h"
|
||||
#include "corda-descriptors/ObjectDescriptor.h"
|
||||
#include "corda-descriptors/ChoiceDescriptor.h"
|
||||
#include "corda-descriptors/EnvelopeDescriptor.h"
|
||||
#include "corda-descriptors/CompositeDescriptor.h"
|
||||
#include "corda-descriptors/RestrictedDescriptor.h"
|
||||
|
||||
#include <limits>
|
||||
#include <climits>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
namespace amqp::internal {
|
||||
|
||||
std::map<uint64_t, std::shared_ptr<internal::schema::descriptors::AMQPDescriptor>>
|
||||
AMQPDescriptorRegistory = {
|
||||
{
|
||||
22UL,
|
||||
std::make_shared<internal::schema::descriptors::AMQPDescriptor> ("DESCRIBED", -1)
|
||||
},
|
||||
{
|
||||
1UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::schema::descriptors::EnvelopeDescriptor> (
|
||||
"ENVELOPE",
|
||||
::amqp::schema::descriptors::ENVELOPE)
|
||||
},
|
||||
{
|
||||
2UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::schema::descriptors::SchemaDescriptor> (
|
||||
"SCHEMA",
|
||||
::amqp::schema::descriptors::SCHEMA)
|
||||
},
|
||||
{
|
||||
3UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::schema::descriptors::ObjectDescriptor> (
|
||||
"OBJECT_DESCRIPTOR",
|
||||
::amqp::schema::descriptors::OBJECT)
|
||||
},
|
||||
{
|
||||
4UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::schema::descriptors::FieldDescriptor> (
|
||||
"FIELD",
|
||||
::amqp::schema::descriptors::FIELD)
|
||||
},
|
||||
{
|
||||
5UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::schema::descriptors::CompositeDescriptor> (
|
||||
"COMPOSITE_TYPE",
|
||||
::amqp::schema::descriptors::COMPOSITE_TYPE)
|
||||
},
|
||||
{
|
||||
6UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::schema::descriptors::RestrictedDescriptor> (
|
||||
"RESTRICTED_TYPE",
|
||||
::amqp::schema::descriptors::RESTRICTED_TYPE)
|
||||
},
|
||||
{
|
||||
7UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::schema::descriptors::ChoiceDescriptor> (
|
||||
"CHOICE",
|
||||
::amqp::schema::descriptors::CHOICE)
|
||||
},
|
||||
{
|
||||
8UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::schema::descriptors::ReferencedObjectDescriptor> (
|
||||
"REFERENCED_OBJECT",
|
||||
::amqp::schema::descriptors::REFERENCED_OBJECT)
|
||||
},
|
||||
{
|
||||
9UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::schema::descriptors::TransformSchemaDescriptor> (
|
||||
"TRANSFORM_SCHEMA",
|
||||
::amqp::schema::descriptors::TRANSFORM_SCHEMA)
|
||||
},
|
||||
{
|
||||
10UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::schema::descriptors::TransformElementDescriptor> (
|
||||
"TRANSFORM_ELEMENT",
|
||||
::amqp::schema::descriptors::TRANSFORM_ELEMENT)
|
||||
},
|
||||
{
|
||||
11UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::schema::descriptors::TransformElementKeyDescriptor> (
|
||||
"TRANSFORM_ELEMENT_KEY",
|
||||
::amqp::schema::descriptors::TRANSFORM_ELEMENT_KEY)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint32_t
|
||||
amqp::stripCorda (uint64_t id) {
|
||||
return static_cast<uint32_t>(id & (uint64_t)UINT_MAX);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::describedToString (uint64_t val_) {
|
||||
switch (val_) {
|
||||
case (1UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "ENVELOPE";
|
||||
case (2UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "SCHEMA";
|
||||
case (3UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "OBJECT_DESCRIPTOR";
|
||||
case (4UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "FIELD";
|
||||
case (5UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "COMPOSITE_TYPE";
|
||||
case (6UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "RESTRICTED_TYPE";
|
||||
case (7UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "CHOICE";
|
||||
case (8UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "REFERENCED_OBJECT";
|
||||
case (9UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_SCHEMA";
|
||||
case (10UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_ELEMENT";
|
||||
case (11UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_ELEMENT_KEY";
|
||||
default : return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::describedToString (uint32_t val_) {
|
||||
return describedToString(val_ | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -11,46 +11,15 @@
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* R3 AMQP assigned enterprise number
|
||||
*
|
||||
* see [here](https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers)
|
||||
*
|
||||
* Repeated here for brevity:
|
||||
* 50530 - R3 - Mike Hearn - mike&r3.com
|
||||
*/
|
||||
namespace amqp::internal {
|
||||
|
||||
extern const uint64_t DESCRIPTOR_TOP_32BITS;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
extern const int ENVELOPE;
|
||||
extern const int SCHEMA;
|
||||
extern const int OBJECT_DESCRIPTOR;
|
||||
extern const int FIELD;
|
||||
extern const int COMPOSITE_TYPE;
|
||||
extern const int RESTRICTED_TYPE;
|
||||
extern const int CHOICE;
|
||||
extern const int REFERENCED_OBJECT;
|
||||
extern const int TRANSFORM_SCHEMA;
|
||||
extern const int TRANSFORM_ELEMENT;
|
||||
extern const int TRANSFORM_ELEMENT_KEY;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
namespace amqp {
|
||||
namespace amqp::internal {
|
||||
|
||||
extern std::map<uint64_t, std::shared_ptr<internal::AMQPDescriptor>> AMQPDescriptorRegistory;
|
||||
extern std::map<uint64_t, std::shared_ptr<internal::schema::descriptors::AMQPDescriptor>> AMQPDescriptorRegistory;
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "AMQPDescriptors.h"
|
||||
#include "AMQPDescriptorRegistory.h"
|
||||
#include "amqp/schema/Descriptors.h"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
@ -8,10 +9,10 @@
|
||||
#include "colours.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "Field.h"
|
||||
#include "Schema.h"
|
||||
#include "Envelope.h"
|
||||
#include "Composite.h"
|
||||
#include "field-types/Field.h"
|
||||
#include "amqp/schema/described-types/Schema.h"
|
||||
#include "amqp/schema/described-types/Envelope.h"
|
||||
#include "amqp/schema/described-types/Composite.h"
|
||||
#include "amqp/schema/restricted-types/Restricted.h"
|
||||
#include "amqp/schema/OrderedTypeNotations.h"
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
@ -26,14 +27,14 @@
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
AMQPDescriptor::validateAndNext (pn_data_t * const data_) const {
|
||||
if (pn_data_type(data_) != PN_ULONG) {
|
||||
throw std::runtime_error ("Bad type for a descriptor");
|
||||
}
|
||||
|
||||
if ( (m_val == -1)
|
||||
|| (pn_data_get_ulong(data_) != (static_cast<uint32_t>(m_val) | amqp::internal::DESCRIPTOR_TOP_32BITS)))
|
||||
|| (pn_data_get_ulong(data_) != (static_cast<uint32_t>(m_val) | amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS)))
|
||||
{
|
||||
throw std::runtime_error ("Invalid Type");
|
||||
}
|
||||
@ -44,7 +45,7 @@ AMQPDescriptor::validateAndNext (pn_data_t * const data_) const {
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::AMQPDescribed>
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
ReferencedObjectDescriptor::build (pn_data_t * data_) const {
|
||||
validateAndNext (data_);
|
||||
|
||||
@ -56,7 +57,7 @@ ReferencedObjectDescriptor::build (pn_data_t * data_) const {
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::AMQPDescribed>
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
TransformSchemaDescriptor::build (pn_data_t * data_) const {
|
||||
validateAndNext (data_);
|
||||
|
||||
@ -68,7 +69,7 @@ TransformSchemaDescriptor::build (pn_data_t * data_) const {
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::AMQPDescribed>
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
TransformElementDescriptor::build (pn_data_t * data_) const {
|
||||
validateAndNext (data_);
|
||||
|
||||
@ -80,7 +81,7 @@ TransformElementDescriptor::build (pn_data_t * data_) const {
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::AMQPDescribed>
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
TransformElementKeyDescriptor::build (pn_data_t * data_) const {
|
||||
validateAndNext (data_);
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "types.h"
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
#include "AMQPDescriptor.h"
|
||||
#include "amqp/schema/Descriptor.h"
|
||||
#include "amqp/schema/described-types/Descriptor.h"
|
||||
#include "proton/proton_wrapper.h"
|
||||
#include "AMQPDescriptorRegistory.h"
|
||||
|
||||
@ -21,7 +21,7 @@ struct pn_data_t;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::descriptors {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
/**
|
||||
* Look up a described type by its ID in the AMQPDescriptorRegistry and
|
||||
@ -40,20 +40,13 @@ namespace amqp::internal::descriptors {
|
||||
|
||||
return uPtr<T>(
|
||||
static_cast<T *>(
|
||||
amqp::AMQPDescriptorRegistory[id]->build(data_).release()));
|
||||
AMQPDescriptorRegistory[id]->build(data_).release()));
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class ReferencedObjectDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
@ -72,7 +65,7 @@ namespace amqp::internal {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class TransformSchemaDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
@ -91,7 +84,7 @@ namespace amqp::internal {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class TransformElementDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
@ -110,7 +103,7 @@ namespace amqp::internal {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class TransformElementKeyDescriptor : public AMQPDescriptor {
|
||||
public :
|
@ -1,4 +1,4 @@
|
||||
#include "amqp/schema/Choice.h"
|
||||
#include "amqp/schema/described-types/Choice.h"
|
||||
#include "ChoiceDescriptor.h"
|
||||
|
||||
#include "types.h"
|
||||
@ -7,17 +7,17 @@
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
ChoiceDescriptor::ChoiceDescriptor (
|
||||
const std::string & symbol_,
|
||||
std::string symbol_,
|
||||
int val_
|
||||
) : AMQPDescriptor (symbol_, val_) {
|
||||
) : AMQPDescriptor (std::move (symbol_), val_) {
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::AMQPDescribed>
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
ChoiceDescriptor::build (pn_data_t * data_) const {
|
||||
validateAndNext (data_);
|
||||
proton::auto_enter ae (data_);
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "amqp/descriptors/AMQPDescriptor.h"
|
||||
#include "amqp/schema/descriptors/AMQPDescriptor.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
@ -8,13 +8,13 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class ChoiceDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
ChoiceDescriptor() = delete;
|
||||
|
||||
ChoiceDescriptor (const std::string &, int);
|
||||
ChoiceDescriptor (std::string, int);
|
||||
|
||||
~ChoiceDescriptor() final = default;
|
||||
|
@ -9,30 +9,30 @@
|
||||
|
||||
#include "proton/proton_wrapper.h"
|
||||
|
||||
#include "amqp/descriptors/AMQPDescriptors.h"
|
||||
#include "amqp/schema/descriptors/AMQPDescriptors.h"
|
||||
|
||||
#include "amqp/schema/Field.h"
|
||||
#include "amqp/schema/Composite.h"
|
||||
#include "amqp/schema/Descriptor.h"
|
||||
#include "amqp/schema/field-types/Field.h"
|
||||
#include "amqp/schema/described-types/Composite.h"
|
||||
#include "amqp/schema/described-types/Descriptor.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::CompositeDescriptor
|
||||
* amqp::internal::schema::descriptors::CompositeDescriptor
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
CompositeDescriptor::CompositeDescriptor (
|
||||
const std::string & symbol_,
|
||||
std::string symbol_,
|
||||
int val_
|
||||
) : AMQPDescriptor (symbol_, val_) {
|
||||
) : AMQPDescriptor (std::move (symbol_), val_) {
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::AMQPDescribed>
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
CompositeDescriptor::build (pn_data_t * data_) const {
|
||||
DBG ("COMPOSITE" << std::endl); // NOLINT
|
||||
|
||||
@ -88,7 +88,7 @@ CompositeDescriptor::build (pn_data_t * data_) const {
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
CompositeDescriptor::read (
|
||||
pn_data_t * data_,
|
||||
std::stringstream & ss_,
|
@ -1,15 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "amqp/descriptors/AMQPDescriptor.h"
|
||||
#include "amqp/schema/descriptors/AMQPDescriptor.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class CompositeDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
CompositeDescriptor() = delete;
|
||||
CompositeDescriptor (const std::string &, int);
|
||||
CompositeDescriptor (std::string, int);
|
||||
|
||||
~CompositeDescriptor() final = default;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "EnvelopeDescriptor.h"
|
||||
|
||||
#include "amqp/schema/Schema.h"
|
||||
#include "amqp/schema/Envelope.h"
|
||||
#include "amqp/schema/described-types/Schema.h"
|
||||
#include "amqp/schema/described-types/Envelope.h"
|
||||
#include "proton/proton_wrapper.h"
|
||||
|
||||
#include "types.h"
|
||||
@ -24,7 +24,7 @@ namespace {
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::EnvelopeDescriptor
|
||||
* amqp::internal::schema::descriptors::EnvelopeDescriptor
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
@ -35,9 +35,11 @@ namespace {
|
||||
* calling this
|
||||
*/
|
||||
void
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
EnvelopeDescriptor::read (
|
||||
pn_data_t * data_, std::stringstream & ss_, const AutoIndent & ai_
|
||||
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_);
|
||||
@ -60,18 +62,18 @@ EnvelopeDescriptor::read (
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
EnvelopeDescriptor::EnvelopeDescriptor (
|
||||
const std::string & symbol_,
|
||||
std::string symbol_,
|
||||
int val_
|
||||
) : AMQPDescriptor (symbol_, val_) {
|
||||
) : AMQPDescriptor (std::move (symbol_), val_) {
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::AMQPDescribed>
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
EnvelopeDescriptor::build (pn_data_t * data_) const {
|
||||
DBG ("ENVELOPE" << std::endl); // NOLINT
|
||||
|
@ -19,12 +19,12 @@ struct pn_data_t;
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class EnvelopeDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
EnvelopeDescriptor() = delete;
|
||||
EnvelopeDescriptor (const std::string &, int);
|
||||
EnvelopeDescriptor (std::string, int);
|
||||
|
||||
~EnvelopeDescriptor() final = default;
|
||||
|
@ -5,29 +5,29 @@
|
||||
|
||||
#include "proton/proton_wrapper.h"
|
||||
|
||||
#include "amqp/schema/Field.h"
|
||||
#include "amqp/schema/field-types/Field.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::FieldDescriptor
|
||||
* amqp::internal::schema::descriptors::FieldDescriptor
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
FieldDescriptor::FieldDescriptor (
|
||||
const std::string & symbol_,
|
||||
std::string symbol_,
|
||||
int val_
|
||||
) : AMQPDescriptor(symbol_, val_) {
|
||||
) : AMQPDescriptor (std::move (symbol_), val_) {
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::AMQPDescribed>
|
||||
amqp::internal::
|
||||
FieldDescriptor::build(pn_data_t * data_) const {
|
||||
amqp::internal::schema::descriptors::
|
||||
FieldDescriptor::build (pn_data_t * data_) const {
|
||||
DBG ("FIELD" << std::endl); // NOLINT
|
||||
|
||||
validateAndNext (data_);
|
||||
@ -37,11 +37,15 @@ FieldDescriptor::build(pn_data_t * data_) const {
|
||||
/* name: String */
|
||||
auto name = proton::get_string (data_);
|
||||
|
||||
DBG ("FIELD::name: \"" << name << "\"" << std::endl); // NOLINT
|
||||
|
||||
pn_data_next (data_);
|
||||
|
||||
/* type: String */
|
||||
auto type = proton::get_string (data_);
|
||||
|
||||
DBG ("FIELD::type: \"" << type << "\"" << std::endl); // NOLINT
|
||||
|
||||
pn_data_next (data_);
|
||||
|
||||
/* requires: List<String> */
|
||||
@ -74,14 +78,14 @@ FieldDescriptor::build(pn_data_t * data_) const {
|
||||
/* multiple: Boolean */
|
||||
auto multiple = proton::get_boolean(data_);
|
||||
|
||||
return std::make_unique<schema::Field> (
|
||||
return schema::Field::make (
|
||||
name, type, requires, def, label, mandatory, multiple);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
FieldDescriptor::read (
|
||||
pn_data_t * data_,
|
||||
std::stringstream & ss_,
|
@ -4,16 +4,16 @@
|
||||
|
||||
#include "proton/codec.h"
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
#include "amqp/descriptors/AMQPDescriptor.h"
|
||||
#include "amqp/schema/descriptors/AMQPDescriptor.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class FieldDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
FieldDescriptor() = delete;
|
||||
FieldDescriptor (const std::string &, int);
|
||||
FieldDescriptor (std::string, int);
|
||||
|
||||
~FieldDescriptor() final = default;
|
||||
|
@ -4,21 +4,21 @@
|
||||
#include "debug.h"
|
||||
|
||||
#include "proton/proton_wrapper.h"
|
||||
#include "amqp/schema/Descriptor.h"
|
||||
#include "amqp/schema/described-types/Descriptor.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::ObjectDescriptor
|
||||
* amqp::internal::schema::descriptors::ObjectDescriptor
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
ObjectDescriptor::ObjectDescriptor (
|
||||
const std::string & symbol_,
|
||||
std::string symbol_,
|
||||
int val_
|
||||
) : AMQPDescriptor (symbol_, val_) {
|
||||
) : AMQPDescriptor (std::move (symbol_), val_) {
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -27,8 +27,8 @@ ObjectDescriptor::ObjectDescriptor (
|
||||
*
|
||||
*/
|
||||
uPtr<amqp::AMQPDescribed>
|
||||
amqp::internal::
|
||||
ObjectDescriptor::build(pn_data_t * data_) const {
|
||||
amqp::internal::schema::descriptors::
|
||||
ObjectDescriptor::build (pn_data_t * data_) const {
|
||||
DBG ("DESCRIPTOR" << std::endl); // NOLINT
|
||||
|
||||
validateAndNext (data_);
|
||||
@ -43,7 +43,7 @@ ObjectDescriptor::build(pn_data_t * data_) const {
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
ObjectDescriptor::read (
|
||||
pn_data_t * data_,
|
||||
std::stringstream & ss_,
|
@ -2,7 +2,7 @@
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "amqp/descriptors/AMQPDescriptor.h"
|
||||
#include "amqp/schema/descriptors/AMQPDescriptor.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@ -10,13 +10,13 @@ struct pn_data_t;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class ObjectDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
ObjectDescriptor() = delete;
|
||||
|
||||
ObjectDescriptor(const std::string &, int);
|
||||
ObjectDescriptor (std::string, int);
|
||||
|
||||
~ObjectDescriptor() final = default;
|
||||
|
@ -3,12 +3,83 @@
|
||||
#include "types.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "amqp/schema/Choice.h"
|
||||
#include "amqp/schema/described-types/Choice.h"
|
||||
#include "amqp/schema/restricted-types/Restricted.h"
|
||||
#include "amqp/descriptors/AMQPDescriptors.h"
|
||||
#include "amqp/schema/descriptors/AMQPDescriptors.h"
|
||||
|
||||
#include <map>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
const std::map<std::string, std::pair<std::regex, std::string>> regexs {
|
||||
{
|
||||
"java.lang.Integer",
|
||||
std::pair { std::regex { "java.lang.Integer"}, "int"}
|
||||
},
|
||||
{
|
||||
"java.lang.Boolean",
|
||||
std::pair { std::regex { "java.lang.Boolean"}, "bool"}
|
||||
},
|
||||
{
|
||||
"java.lang.Byte",
|
||||
std::pair { std::regex { "java.lang.Byte"}, "char"}
|
||||
},
|
||||
{
|
||||
"java.lang.Short",
|
||||
std::pair { std::regex { "java.lang.Short"}, "short"}
|
||||
},
|
||||
{
|
||||
"java.lang.Character",
|
||||
std::pair { std::regex { "java.lang.Character"}, "char"}
|
||||
},
|
||||
{
|
||||
"java.lang.Float",
|
||||
std::pair { std::regex { "java.lang.Float"}, "float"}
|
||||
},
|
||||
{
|
||||
"java.lang.Long",
|
||||
std::pair { std::regex { "java.lang.Long"}, "long"}
|
||||
},
|
||||
{
|
||||
"java.lang.Double",
|
||||
std::pair { std::regex { "java.lang.Double"}, "double"}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
std::string
|
||||
RestrictedDescriptor::makePrim (const std::string & name_) {
|
||||
std::string name { name_ };
|
||||
for (const auto & i: regexs) {
|
||||
name = std::regex_replace (name, i.second.first, i.second.second);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::descriptors::
|
||||
RestrictedDescriptor::RestrictedDescriptor (
|
||||
std::string symbol_,
|
||||
int val_
|
||||
) : AMQPDescriptor (std::move (symbol_)
|
||||
, val_
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Restricted types represent lists and maps
|
||||
@ -27,14 +98,14 @@
|
||||
******************************************************************************/
|
||||
|
||||
uPtr<amqp::AMQPDescribed>
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
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 name = makePrim (proton::readAndNext<std::string>(data_));
|
||||
auto label = proton::readAndNext<std::string>(data_, true);
|
||||
|
||||
DBG (" name: " << name << ", label: \"" << label << "\"" << std::endl);
|
||||
@ -86,7 +157,7 @@ RestrictedDescriptor::build (pn_data_t * data_) const {
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
RestrictedDescriptor::read (
|
||||
pn_data_t * data_,
|
||||
std::stringstream & ss_,
|
@ -4,19 +4,24 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "amqp/descriptors/AMQPDescriptor.h"
|
||||
#include "amqp/schema/descriptors/AMQPDescriptor.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class RestrictedDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
/**
|
||||
* This could just live as a stand alone function in the
|
||||
* anonymous namespace... but for testing purposes lets
|
||||
* just make it a static members of the class
|
||||
*/
|
||||
static std::string makePrim (const std::string &);
|
||||
|
||||
public :
|
||||
RestrictedDescriptor() = delete;
|
||||
|
||||
RestrictedDescriptor(const std::string & symbol_, int val_)
|
||||
: AMQPDescriptor(symbol_, val_)
|
||||
{ }
|
||||
RestrictedDescriptor (std::string, int);
|
||||
|
||||
~RestrictedDescriptor() final = default;
|
||||
|
@ -7,8 +7,8 @@
|
||||
#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/descriptors/AMQPDescriptors.h"
|
||||
#include "amqp/schema/described-types/Schema.h"
|
||||
#include "amqp/schema/OrderedTypeNotations.h"
|
||||
#include "amqp/schema/AMQPTypeNotation.h"
|
||||
|
||||
@ -16,17 +16,17 @@
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
SchemaDescriptor::SchemaDescriptor (
|
||||
const std::string & symbol_,
|
||||
std::string symbol_,
|
||||
int val_
|
||||
) : AMQPDescriptor (symbol_, val_) {
|
||||
) : AMQPDescriptor (std::move (symbol_), val_) {
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::AMQPDescribed>
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
SchemaDescriptor::build (pn_data_t * data_) const {
|
||||
DBG ("SCHEMA" << std::endl); // NOLINT
|
||||
|
||||
@ -41,12 +41,14 @@ SchemaDescriptor::build (pn_data_t * data_) const {
|
||||
proton::auto_list_enter ale (data_);
|
||||
|
||||
for (int i { 1 } ; pn_data_next(data_) ; ++i) {
|
||||
DBG (" " << i << "/" << ale.elements() << std::endl); // NOLINT
|
||||
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_));
|
||||
|
||||
DBG("=======" << std::endl << schemas << "======" << std::endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -58,7 +60,7 @@ SchemaDescriptor::build (pn_data_t * data_) const {
|
||||
|
||||
|
||||
void
|
||||
amqp::internal::
|
||||
amqp::internal::schema::descriptors::
|
||||
SchemaDescriptor::read (
|
||||
pn_data_t * data_,
|
||||
std::stringstream & ss_,
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "amqp/descriptors/AMQPDescriptor.h"
|
||||
#include "amqp/schema/descriptors/AMQPDescriptor.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@ -8,12 +8,12 @@ struct pn_data_t;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
namespace amqp::internal::schema::descriptors {
|
||||
|
||||
class SchemaDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
SchemaDescriptor() = delete;
|
||||
SchemaDescriptor (const std::string &, int);
|
||||
SchemaDescriptor (std::string, int);
|
||||
~SchemaDescriptor() final = default;
|
||||
|
||||
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
|
@ -0,0 +1,54 @@
|
||||
#include "ArrayField.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string
|
||||
amqp::internal::schema::
|
||||
ArrayField::m_fieldType {
|
||||
"array"
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
ArrayField::ArrayField (
|
||||
std::string name_,
|
||||
std::string type_,
|
||||
std::list<std::string> requires_,
|
||||
std::string default_,
|
||||
std::string label_,
|
||||
bool mandatory_,
|
||||
bool multiple_
|
||||
) : RestrictedField (
|
||||
std::move (name_),
|
||||
std::move (type_),
|
||||
std::move (requires_),
|
||||
std::move (default_),
|
||||
std::move (label_),
|
||||
mandatory_,
|
||||
multiple_
|
||||
) {
|
||||
DBG ("ArrayField::ArrayField - name: " << name() << ", type: " << type() << std::endl);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
ArrayField::resolvedType() const {
|
||||
return type();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
ArrayField::fieldType() const {
|
||||
return m_fieldType;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "RestrictedField.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class ArrayField : public RestrictedField {
|
||||
private :
|
||||
static const std::string m_fieldType;
|
||||
|
||||
public :
|
||||
ArrayField (
|
||||
std::string, std::string, std::list<std::string>,
|
||||
std::string, std::string, bool, bool);
|
||||
|
||||
const std::string & fieldType() const override;
|
||||
const std::string & resolvedType() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,63 @@
|
||||
#include "CompositeField.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "Field.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string
|
||||
amqp::internal::schema::CompositeField::m_fieldType {
|
||||
"composite"
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
CompositeField::CompositeField (
|
||||
std::string name_,
|
||||
std::string type_,
|
||||
std::list<std::string> requires_,
|
||||
std::string default_,
|
||||
std::string label_,
|
||||
bool mandatory_,
|
||||
bool multiple_
|
||||
) : Field (
|
||||
std::move (name_),
|
||||
std::move (type_),
|
||||
std::move (requires_),
|
||||
std::move (default_),
|
||||
std::move (label_),
|
||||
mandatory_,
|
||||
multiple_)
|
||||
{
|
||||
DBG ("FIELD::FIELD - name: " << name() << ", type: " << type() << std::endl);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
bool
|
||||
amqp::internal::schema::
|
||||
CompositeField::primitive() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
CompositeField::fieldType() const {
|
||||
return m_fieldType;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
CompositeField::resolvedType() const {
|
||||
return type();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "Field.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class CompositeField : public Field {
|
||||
private :
|
||||
static const std::string m_fieldType;
|
||||
|
||||
public :
|
||||
CompositeField (
|
||||
std::string, std::string, std::list<std::string>,
|
||||
std::string, std::string, bool, bool);
|
||||
|
||||
bool primitive() const override;
|
||||
const std::string & fieldType() const override;
|
||||
const std::string & resolvedType() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,153 @@
|
||||
#include "Field.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include "ArrayField.h"
|
||||
#include "PrimitiveField.h"
|
||||
#include "CompositeField.h"
|
||||
#include "RestrictedField.h"
|
||||
|
||||
#include "../restricted-types/Array.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
std::ostream &
|
||||
operator << (std::ostream & stream_, const Field & field_) {
|
||||
std::stringstream ss;
|
||||
for (auto &i: field_.m_requires) { ss << i; }
|
||||
|
||||
stream_ << field_.m_name
|
||||
<< " : " << field_.m_type
|
||||
<< " : [" << ss.str() << "]" << std::endl;
|
||||
|
||||
return stream_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::internal::schema::Field>
|
||||
amqp::internal::schema::
|
||||
Field::make (
|
||||
std::string name_,
|
||||
std::string type_,
|
||||
std::list<std::string> requires_,
|
||||
std::string default_,
|
||||
std::string label_,
|
||||
bool mandatory_,
|
||||
bool multiple_
|
||||
) {
|
||||
if (typeIsPrimitive (type_)) {
|
||||
DBG ("-> primitive" << std::endl);
|
||||
return std::make_unique<PrimitiveField>(
|
||||
std::move (name_),
|
||||
std::move (type_),
|
||||
std::move (default_),
|
||||
std::move (label_),
|
||||
mandatory_,
|
||||
multiple_);
|
||||
} else if (Array::isArrayType (type_)) {
|
||||
DBG ("-> array" << std::endl);
|
||||
return std::make_unique<ArrayField>(
|
||||
std::move (name_),
|
||||
std::move (type_),
|
||||
std::move (requires_),
|
||||
std::move (default_),
|
||||
std::move (label_),
|
||||
mandatory_,
|
||||
multiple_);
|
||||
|
||||
} else if (type_ == "*") {
|
||||
DBG ("-> restricted" << std::endl);
|
||||
return std::make_unique<RestrictedField>(
|
||||
std::move (name_),
|
||||
std::move (type_),
|
||||
std::move (requires_),
|
||||
std::move (default_),
|
||||
std::move (label_),
|
||||
mandatory_,
|
||||
multiple_);
|
||||
} else {
|
||||
DBG ("-> composite" << std::endl);
|
||||
return std::make_unique<CompositeField>(
|
||||
std::move (name_),
|
||||
std::move (type_),
|
||||
std::move (requires_),
|
||||
std::move (default_),
|
||||
std::move (label_),
|
||||
mandatory_,
|
||||
multiple_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
Field::Field (
|
||||
std::string name_,
|
||||
std::string type_,
|
||||
std::list<std::string> requires_,
|
||||
std::string default_,
|
||||
std::string label_,
|
||||
bool mandatory_,
|
||||
bool multiple_
|
||||
) : m_name (std::move (name_))
|
||||
, m_type (std::move (type_))
|
||||
, m_requires (std::move (requires_))
|
||||
, m_default (std::move (default_))
|
||||
, m_label (std::move (label_))
|
||||
, m_mandatory (mandatory_)
|
||||
, m_multiple (multiple_)
|
||||
{
|
||||
DBG ("FIELD::FIELD - name: " << name() << ", type: " << type_ << std::endl);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
bool
|
||||
amqp::internal::schema::
|
||||
Field::typeIsPrimitive (const std::string & type_) {
|
||||
return (type_ == "string" ||
|
||||
type_ == "long" ||
|
||||
type_ == "boolean" ||
|
||||
type_ == "int" ||
|
||||
type_ == "double");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
Field::name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
Field::type() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::list<std::string> &
|
||||
amqp::internal::schema::
|
||||
Field::requires() const {
|
||||
return m_requires;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "amqp/schema/described-types/Descriptor.h"
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
/**
|
||||
*
|
||||
* A Corda AMQP Scehma Field type has:
|
||||
* - name : String
|
||||
* - type : String
|
||||
* - requires : List<String>
|
||||
* - default : nullable String
|
||||
* - label : nullable String
|
||||
* - mandatory : Boolean
|
||||
* - multiple : Boolean
|
||||
*/
|
||||
class Field : public AMQPDescribed {
|
||||
public :
|
||||
friend std::ostream & operator << (std::ostream &, const Field &);
|
||||
|
||||
static bool typeIsPrimitive (const std::string &);
|
||||
|
||||
static uPtr<Field> make (
|
||||
std::string, std::string, std::list<std::string>,
|
||||
std::string, std::string, bool, bool);
|
||||
|
||||
private :
|
||||
std::string m_name;
|
||||
std::string m_type;
|
||||
std::list<std::string> m_requires;
|
||||
std::string m_default;
|
||||
std::string m_label;
|
||||
bool m_mandatory;
|
||||
bool m_multiple;
|
||||
|
||||
protected :
|
||||
Field (std::string, std::string, std::list<std::string>,
|
||||
std::string, std::string, bool, bool);
|
||||
|
||||
public :
|
||||
const std::string & name() const;
|
||||
const std::string & type() const;
|
||||
const std::list<std::string> & requires() const;
|
||||
|
||||
virtual bool primitive() const = 0;
|
||||
virtual const std::string & fieldType() const = 0;
|
||||
virtual const std::string & resolvedType() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -0,0 +1,55 @@
|
||||
#include "PrimitiveField.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string
|
||||
amqp::internal::schema::PrimitiveField::m_fieldType {
|
||||
"primitive"
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
PrimitiveField::PrimitiveField (
|
||||
std::string name_,
|
||||
std::string type_,
|
||||
std::string default_,
|
||||
std::string label_,
|
||||
bool mandatory_,
|
||||
bool multiple_
|
||||
) : Field (
|
||||
std::move (name_),
|
||||
std::move (type_),
|
||||
{ }, // requires
|
||||
std::move (default_),
|
||||
std::move (label_),
|
||||
mandatory_,
|
||||
multiple_
|
||||
) {
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
bool
|
||||
amqp::internal::schema::
|
||||
PrimitiveField::primitive() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
PrimitiveField::fieldType() const {
|
||||
return m_fieldType;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
PrimitiveField::resolvedType() const {
|
||||
return type();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "Field.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class PrimitiveField : public Field {
|
||||
private :
|
||||
static const std::string m_fieldType;
|
||||
|
||||
public :
|
||||
PrimitiveField (
|
||||
std::string, std::string, std::string,
|
||||
std::string, bool, bool);
|
||||
|
||||
bool primitive() const override;
|
||||
const std::string & fieldType() const override;
|
||||
const std::string & resolvedType() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,56 @@
|
||||
#include "RestrictedField.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string
|
||||
amqp::internal::schema::RestrictedField::m_fieldType {
|
||||
"restricted"
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
RestrictedField::RestrictedField (
|
||||
std::string name_,
|
||||
std::string type_,
|
||||
std::list<std::string> requires_,
|
||||
std::string default_,
|
||||
std::string label_,
|
||||
bool mandatory_,
|
||||
bool multiple_
|
||||
) : Field (
|
||||
std::move (name_),
|
||||
std::move (type_),
|
||||
std::move (requires_),
|
||||
std::move (default_),
|
||||
std::move (label_),
|
||||
mandatory_,
|
||||
multiple_)
|
||||
{
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
bool
|
||||
amqp::internal::schema::
|
||||
RestrictedField::primitive() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
RestrictedField::fieldType() const {
|
||||
return m_fieldType;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
RestrictedField::resolvedType() const {
|
||||
return requires().front();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "Field.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class RestrictedField : public Field {
|
||||
private :
|
||||
static const std::string m_fieldType;
|
||||
|
||||
public :
|
||||
RestrictedField (
|
||||
std::string, std::string, std::list<std::string>,
|
||||
std::string, std::string, bool, bool);
|
||||
|
||||
bool primitive() const override;
|
||||
const std::string & fieldType() const override;
|
||||
const std::string & resolvedType() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,169 @@
|
||||
#include "Array.h"
|
||||
|
||||
#include "Map.h"
|
||||
#include "List.h"
|
||||
#include "Enum.h"
|
||||
#include "amqp/schema/described-types/Composite.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Static member functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
const std::string array { "[]" };
|
||||
const std::string primArray { "[p]" };
|
||||
|
||||
}
|
||||
|
||||
std::string
|
||||
amqp::internal::schema::
|
||||
Array::arrayType (const std::string & array_) {
|
||||
auto pos = array_.find ('[');
|
||||
return std::string { array_.substr (0, pos) };
|
||||
}
|
||||
|
||||
/**
|
||||
* when C++20 is done we can use .endswith, until then we have to do a reverse search
|
||||
*/
|
||||
bool
|
||||
amqp::internal::schema::
|
||||
Array::isArrayType (const std::string & type_) {
|
||||
return (std::equal (
|
||||
type_.rbegin(), type_.rbegin() + array.size(),
|
||||
array.rbegin(), array.rend())
|
||||
|| std::equal (
|
||||
type_.rbegin(), type_.rbegin() + primArray.size(),
|
||||
primArray.rbegin(), primArray.rend()));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Non static member functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
Array::Array (
|
||||
uPtr<Descriptor> descriptor_,
|
||||
std::string name_,
|
||||
std::string label_,
|
||||
std::vector<std::string> provides_,
|
||||
std::string source_
|
||||
) : Restricted (
|
||||
std::move (descriptor_),
|
||||
std::move (name_),
|
||||
std::move (label_),
|
||||
std::move (provides_),
|
||||
amqp::internal::schema::Restricted::RestrictedTypes::array_t)
|
||||
, m_arrayOf { unbox (arrayType (name())) }
|
||||
, m_source { std::move (source_) }
|
||||
{
|
||||
DBG ("ARRAY OF::" << arrayOf() << ", name::" << name() << std::endl);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::vector<std::string>::const_iterator
|
||||
amqp::internal::schema::
|
||||
Array::begin() const {
|
||||
return m_arrayOf.begin();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::vector<std::string>::const_iterator
|
||||
amqp::internal::schema::
|
||||
Array::end() const {
|
||||
return m_arrayOf.end();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
Array::arrayOf() const {
|
||||
return m_arrayOf[0];
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Array::dependsOnMap (const amqp::internal::schema::Map & map_) const {
|
||||
// do we depend on the lhs
|
||||
if (arrayOf() == map_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// does lhs_ depend on us
|
||||
auto lhsMapOf { map_.mapOf() };
|
||||
|
||||
if (lhsMapOf.first.get() == name() || lhsMapOf.second.get() == name()) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Array::dependsOnList (const amqp::internal::schema::List & list_) const {
|
||||
// do we depend on the lhs
|
||||
if (arrayOf() == list_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// does the left hand side depend on us
|
||||
if (list_.listOf() == name()) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Array::dependsOnArray (const amqp::internal::schema::Array & array_) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Array::dependsOnEnum (const amqp::internal::schema::Enum & enum_) const {
|
||||
// an enum cannot depend on us so don't bother checking, lets just check
|
||||
// if we depend on it
|
||||
if (arrayOf() == enum_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Array::dependsOnRHS (const amqp::internal::schema::Composite & lhs_) const {
|
||||
if (arrayOf() == lhs_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (const auto & field : lhs_.fields()) {
|
||||
if (field->resolvedType() == name()) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************************o*********************/
|
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "Restricted.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class Array : public Restricted {
|
||||
public :
|
||||
static std::string arrayType (const std::string &);
|
||||
static bool isArrayType (const std::string &);
|
||||
|
||||
private :
|
||||
std::vector<std::string> m_arrayOf;
|
||||
std::string m_source;
|
||||
|
||||
int dependsOnMap (const Map &) const override;
|
||||
int dependsOnList (const List &) const override;
|
||||
int dependsOnEnum (const Enum &) const override;
|
||||
int dependsOnArray (const Array &) const override;
|
||||
|
||||
public :
|
||||
Array (
|
||||
uPtr<Descriptor> descriptor_,
|
||||
std::string,
|
||||
std::string,
|
||||
std::vector<std::string>,
|
||||
std::string);
|
||||
|
||||
std::vector<std::string>::const_iterator begin() const override;
|
||||
std::vector<std::string>::const_iterator end() const override;
|
||||
|
||||
const std::string & arrayOf() const;
|
||||
|
||||
int dependsOnRHS (const Composite &) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -2,12 +2,14 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include "Map.h"
|
||||
#include "List.h"
|
||||
#include "Composite.h"
|
||||
#include "amqp/schema/described-types/Composite.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
amqp::internal::schema::
|
||||
Enum::Enum (
|
||||
uPtr<Descriptor> descriptor_,
|
||||
@ -21,11 +23,11 @@ Enum::Enum (
|
||||
std::move (name_),
|
||||
std::move (label_),
|
||||
std::move (provides_),
|
||||
amqp::internal::schema::Restricted::RestrictedTypes::Enum)
|
||||
amqp::internal::schema::Restricted::RestrictedTypes::enum_t)
|
||||
, m_source { std::move (source_) }
|
||||
, m_enum { name_ }
|
||||
, m_choices (std::move (choices_))
|
||||
, m_choices { std::move (choices_) }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -48,57 +50,65 @@ Enum::end() const {
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Enum::dependsOn (const amqp::internal::schema::Restricted & lhs_) const {
|
||||
auto rtn { 0 };
|
||||
switch (lhs_.restrictedType()) {
|
||||
case RestrictedTypes::List : {
|
||||
const auto & list { dynamic_cast<const class List &>(lhs_) };
|
||||
|
||||
// does the left hand side depend on us
|
||||
// DBG (" L/L a) " << list.listOf() << " == " << name() << std::endl); // NOLINT
|
||||
if (list.listOf() == name()) {
|
||||
rtn = 1;
|
||||
}
|
||||
|
||||
// do we depend on the lhs
|
||||
//DBG (" L/L b) " << name() << " == " << list.name() << std::endl); // NOLINT
|
||||
if (name() == list.name()) {
|
||||
rtn = 2;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case RestrictedTypes::Enum : {
|
||||
break;
|
||||
}
|
||||
case RestrictedTypes::Map : {
|
||||
|
||||
}
|
||||
|
||||
Enum::dependsOnMap (const amqp::internal::schema::Map & map_) const {
|
||||
// does lhs_ depend on us
|
||||
auto lhsMapOf { map_.mapOf() };
|
||||
if (lhsMapOf.first.get() == name() || lhsMapOf.second.get() == name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return rtn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Enum::dependsOn (const amqp::internal::schema::Composite & lhs_) const {
|
||||
auto rtn { 0 };
|
||||
Enum::dependsOnList (const amqp::internal::schema::List & list_) const {
|
||||
// does the left hand side depend on us
|
||||
if (list_.listOf() == name()) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
// we can never depend on the left hand side so don't bother checking
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Enum::dependsOnArray (const amqp::internal::schema::Array & array_) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Enum::dependsOnEnum (const amqp::internal::schema::Enum &) const {
|
||||
// enums should never depend on one another so just return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************************o*********************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Enum::dependsOnRHS (const amqp::internal::schema::Composite & lhs_) const {
|
||||
if (name() == lhs_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (const auto & field : lhs_.fields()) {
|
||||
// DBG (" L/C a) " << field->resolvedType() << " == " << name() << std::endl); // NOLINT
|
||||
if (field->resolvedType() == name()) {
|
||||
rtn = 1;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
// DBG (" L/C b) " << name() << " == " << lhs_.name() << std::endl); // NOLINT
|
||||
if (name() == lhs_.name()) {
|
||||
rtn = 2;
|
||||
}
|
||||
|
||||
return rtn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************************o*********************/
|
||||
@ -117,3 +127,4 @@ Enum::makeChoices() const {
|
||||
}
|
||||
|
||||
/*********************************************************o*********************/
|
||||
|
||||
|
@ -2,13 +2,21 @@
|
||||
|
||||
#include "Restricted.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class Enum : public Restricted {
|
||||
private :
|
||||
std::string m_source;
|
||||
std::vector<std::string> m_enum;
|
||||
std::vector<uPtr<Choice>> m_choices;
|
||||
|
||||
int dependsOnMap (const Map &) const override;
|
||||
int dependsOnList (const List &) const override;
|
||||
int dependsOnEnum (const Enum &) const override;
|
||||
int dependsOnArray (const Array &) const override;
|
||||
|
||||
public :
|
||||
Enum (
|
||||
uPtr<Descriptor> descriptor_,
|
||||
@ -21,8 +29,7 @@ namespace amqp::internal::schema {
|
||||
std::vector<std::string>::const_iterator begin() const override;
|
||||
std::vector<std::string>::const_iterator end() const override;
|
||||
|
||||
int dependsOn (const Restricted &) const override;
|
||||
int dependsOn (const class Composite &) const override;
|
||||
int dependsOnRHS (const Composite &) const override;
|
||||
|
||||
std::vector<std::string> makeChoices() const;
|
||||
};
|
||||
|
@ -1,27 +1,35 @@
|
||||
#include <iostream>
|
||||
#include "List.h"
|
||||
#include "Map.h"
|
||||
#include "Enum.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "colours.h"
|
||||
|
||||
#include "schema/Composite.h"
|
||||
#include "amqp/schema/described-types/Composite.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* Static member functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace {
|
||||
std::pair<std::string, std::string>
|
||||
amqp::internal::schema::
|
||||
List::listType (const std::string & list_) {
|
||||
auto pos = list_.find ('<');
|
||||
|
||||
std::pair<std::string, std::string>
|
||||
listType (const std::string & list_) {
|
||||
auto pos = list_.find ('<');
|
||||
|
||||
return std::make_pair (
|
||||
std::string { list_.substr (0, pos) },
|
||||
std::string { list_.substr(pos + 1, list_.size() - pos - 2) }
|
||||
);
|
||||
}
|
||||
return std::make_pair (
|
||||
std::string { unbox (list_.substr (0, pos)) },
|
||||
std::string { unbox (list_.substr(pos + 1, list_.size() - pos - 2)) }
|
||||
);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* Non static member functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
List::List (
|
||||
@ -35,10 +43,10 @@ List::List (
|
||||
std::move (name_),
|
||||
std::move (label_),
|
||||
std::move (provides_),
|
||||
amqp::internal::schema::Restricted::RestrictedTypes::List)
|
||||
, m_listOf { listType(name_).second }
|
||||
amqp::internal::schema::Restricted::RestrictedTypes::list_t)
|
||||
, m_listOf { listType (name()).second }
|
||||
, m_source { std::move (source_) }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -69,48 +77,78 @@ List::listOf() const {
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
List::dependsOn (const amqp::internal::schema::Restricted & lhs_) const {
|
||||
auto rtn { 0 };
|
||||
switch (lhs_.restrictedType()) {
|
||||
case RestrictedTypes::List : {
|
||||
const auto & list { dynamic_cast<const List &>(lhs_) };
|
||||
|
||||
// does the left hand side depend on us
|
||||
DBG (" L/L a) " << list.listOf() << " == " << name() << std::endl); // NOLINT
|
||||
if (list.listOf() == name()) {
|
||||
rtn = 1;
|
||||
}
|
||||
|
||||
// do we depend on the lhs
|
||||
DBG (" L/L b) " << listOf() << " == " << list.name() << std::endl); // NOLINT
|
||||
if (listOf() == list.name()) {
|
||||
rtn = 2;
|
||||
}
|
||||
}
|
||||
List::dependsOnMap (const amqp::internal::schema::Map & map_) const {
|
||||
// do we depend on the lhs
|
||||
if (listOf() == map_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return rtn;
|
||||
// does lhs_ depend on us
|
||||
auto lhsMapOf { map_.mapOf() };
|
||||
|
||||
if (lhsMapOf.first.get() == name() || lhsMapOf.second.get() == name()) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
List::dependsOn (const amqp::internal::schema::Composite & lhs_) const {
|
||||
auto rtn { 0 };
|
||||
List::dependsOnList (const amqp::internal::schema::List & list_) const {
|
||||
// do we depend on the lhs
|
||||
if (listOf() == list_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// does the left hand side depend on us
|
||||
if (list_.listOf() == name()) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
List::dependsOnArray (const amqp::internal::schema::Array & array_) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
List::dependsOnEnum (const amqp::internal::schema::Enum & enum_) const {
|
||||
// an enum cannot depend on us so don't bother checking, lets just check
|
||||
// if we depend on it
|
||||
if (listOf() == enum_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
List::dependsOnRHS (const amqp::internal::schema::Composite & lhs_) const {
|
||||
if (listOf() == lhs_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (const auto & field : lhs_.fields()) {
|
||||
DBG (" L/C a) " << field->resolvedType() << " == " << name() << std::endl); // NOLINT
|
||||
if (field->resolvedType() == name()) {
|
||||
rtn = 1;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
DBG (" L/C b) " << listOf() << " == " << lhs_.name() << std::endl); // NOLINT
|
||||
if (listOf() == lhs_.name()) {
|
||||
rtn = 2;
|
||||
}
|
||||
|
||||
return rtn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************************o*********************/
|
||||
|
@ -7,8 +7,18 @@
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class List : public Restricted {
|
||||
public :
|
||||
static std::pair<std::string, std::string> listType (
|
||||
const std::string &);
|
||||
|
||||
private :
|
||||
std::vector<std::string> m_listOf;
|
||||
std::string m_source;
|
||||
|
||||
int dependsOnMap (const Map &) const override;
|
||||
int dependsOnList (const List &) const override;
|
||||
int dependsOnEnum (const Enum &) const override;
|
||||
int dependsOnArray (const Array &) const override;
|
||||
|
||||
public :
|
||||
List (
|
||||
@ -23,8 +33,7 @@ namespace amqp::internal::schema {
|
||||
|
||||
const std::string & listOf() const;
|
||||
|
||||
int dependsOn (const Restricted &) const override;
|
||||
int dependsOn (const class Composite &) const override;
|
||||
int dependsOnRHS (const Composite &) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,171 @@
|
||||
#include "Map.h"
|
||||
#include "List.h"
|
||||
#include "Enum.h"
|
||||
#include "amqp/schema/described-types/Composite.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Map Static Member Functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
std::tuple<std::string, std::string, std::string>
|
||||
amqp::internal::schema::
|
||||
Map::mapType (const std::string & map_) {
|
||||
uint pos = map_.find ('<');
|
||||
|
||||
uint idx { pos + 1 };
|
||||
for (uint nesting { 0 } ; idx < map_.size(); ++idx) {
|
||||
if (map_[idx] == '<') {
|
||||
++nesting;
|
||||
} else if (map_[idx] == '>') {
|
||||
--nesting;
|
||||
} else if (map_[idx] == ',' && nesting == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto map = std::string { map_.substr (0, pos) };
|
||||
auto of = std::string { map_.substr (pos + 1, idx - pos - 1) };
|
||||
of = of.erase(0, of.find_first_not_of(' '));
|
||||
auto to = std::string { map_.substr (idx + 1, map_.size() - (idx + 2)) };
|
||||
to = to.erase(0, to.find_first_not_of(' '));
|
||||
|
||||
return { map, unbox (of), unbox (to) };
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Map Member Functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
Map::Map (
|
||||
uPtr<Descriptor> descriptor_,
|
||||
std::string name_,
|
||||
std::string label_,
|
||||
std::vector<std::string> provides_,
|
||||
std::string source_
|
||||
) : Restricted (
|
||||
std::move (descriptor_),
|
||||
std::move (name_),
|
||||
std::move (label_),
|
||||
std::move (provides_),
|
||||
amqp::internal::schema::Restricted::RestrictedTypes::map_t)
|
||||
, m_source { std::move (source_) }
|
||||
{
|
||||
auto [map, of, to] = mapType (name());
|
||||
m_mapOf = { of, to };
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::vector<std::string>::const_iterator
|
||||
amqp::internal::schema::
|
||||
Map::begin() const {
|
||||
return m_mapOf.begin();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::vector<std::string>::const_iterator
|
||||
amqp::internal::schema::
|
||||
Map::end() const {
|
||||
return m_mapOf.end();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::pair<
|
||||
std::reference_wrapper<const std::string>,
|
||||
std::reference_wrapper<const std::string>>
|
||||
amqp::internal::schema::
|
||||
Map::mapOf() const {
|
||||
return std::pair { std::cref (m_mapOf[0]), std::cref (m_mapOf[1]) };
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Map::dependsOnMap (const amqp::internal::schema::Map & lhs_) const {
|
||||
// do we depend on the lhs
|
||||
if (m_mapOf[0] == lhs_.name() || m_mapOf[1] == lhs_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// does lhs_ depend on us
|
||||
auto lhsMapOf { lhs_.mapOf() };
|
||||
if (lhsMapOf.first.get() == name() || lhsMapOf.second.get() == name()) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Map::dependsOnList (const amqp::internal::schema::List & lhs_) const {
|
||||
// do we depend on the lhs
|
||||
if (m_mapOf[0] == lhs_.name() || m_mapOf[1] == lhs_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// does lhs_ depend on us
|
||||
if (lhs_.listOf() == name()) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Map::dependsOnArray (const amqp::internal::schema::Array & lhs_) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Map::dependsOnEnum (const amqp::internal::schema::Enum & lhs_) const {
|
||||
// do we depend on the lhs
|
||||
if (m_mapOf[0] == lhs_.name() || m_mapOf[1] == lhs_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// does lhs_ depend on us
|
||||
if (lhs_.name() == name()) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Map::dependsOnRHS (const amqp::internal::schema::Composite & lhs_) const {
|
||||
// do we depend on the lhs
|
||||
if (m_mapOf[0] == lhs_.name() || m_mapOf[1] == lhs_.name()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// does lhs_ depend on us
|
||||
for (const auto & field : lhs_.fields()) {
|
||||
if (field->resolvedType() == name()) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "Restricted.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class Map : public Restricted {
|
||||
public :
|
||||
static std::tuple<std::string, std::string, std::string>
|
||||
mapType (const std::string &);
|
||||
|
||||
private :
|
||||
std::vector<std::string> m_mapOf;
|
||||
std::string m_source;
|
||||
|
||||
int dependsOnMap (const Map &) const override;
|
||||
int dependsOnList (const List &) const override;
|
||||
int dependsOnEnum (const Enum &) const override;
|
||||
int dependsOnArray (const Array &) const override;
|
||||
|
||||
public :
|
||||
Map (
|
||||
uPtr<Descriptor> descriptor_,
|
||||
std::string,
|
||||
std::string,
|
||||
std::vector<std::string>,
|
||||
std::string);
|
||||
|
||||
std::vector<std::string>::const_iterator begin() const override;
|
||||
std::vector<std::string>::const_iterator end() const override;
|
||||
|
||||
std::pair<
|
||||
std::reference_wrapper<const std::string>,
|
||||
std::reference_wrapper<const std::string>> mapOf() const;
|
||||
|
||||
int dependsOnRHS (const Composite &) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -1,34 +1,41 @@
|
||||
#include "Restricted.h"
|
||||
|
||||
#include "Map.h"
|
||||
#include "List.h"
|
||||
#include "Enum.h"
|
||||
#include "Array.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* ostream overloads
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
std::ostream &
|
||||
operator << (
|
||||
std::ostream & stream_,
|
||||
const amqp::internal::schema::Restricted & clazz_)
|
||||
{
|
||||
stream_
|
||||
<< "name : " << clazz_.name() << std::endl
|
||||
<< "label : " << clazz_.m_label << std::endl
|
||||
<< "descriptor : " << clazz_.descriptor() << std::endl
|
||||
<< "source : " << clazz_.m_source << std::endl
|
||||
<< "provides : [" << std::endl;
|
||||
std::ostream &
|
||||
operator << (
|
||||
std::ostream & stream_,
|
||||
const amqp::internal::schema::Restricted & clazz_)
|
||||
{
|
||||
stream_
|
||||
<< "name : " << clazz_.name() << std::endl
|
||||
<< "label : " << clazz_.m_label << std::endl
|
||||
<< "descriptor : " << clazz_.descriptor() << std::endl
|
||||
<< "source : " << clazz_.m_source << std::endl
|
||||
<< "provides : [" << std::endl;
|
||||
|
||||
for (auto & provides : clazz_.m_provides) {
|
||||
stream_ << " " << provides << std::endl;
|
||||
for (auto & provides : clazz_.m_provides) {
|
||||
stream_ << " " << provides << std::endl;
|
||||
}
|
||||
stream_<< " ]" << std::endl;
|
||||
|
||||
return stream_;
|
||||
}
|
||||
stream_<< " ]" << std::endl;
|
||||
|
||||
return stream_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -36,31 +43,73 @@ operator << (
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
std::ostream &
|
||||
operator << (
|
||||
std::ostream & stream_,
|
||||
const amqp::internal::schema::Restricted::RestrictedTypes & type_)
|
||||
{
|
||||
switch (type_) {
|
||||
case Restricted::RestrictedTypes::List : {
|
||||
stream_ << "list";
|
||||
break;
|
||||
}
|
||||
case Restricted::RestrictedTypes::Map : {
|
||||
stream_ << "map";
|
||||
break;
|
||||
}
|
||||
case Restricted::RestrictedTypes::Enum : {
|
||||
stream_ << "enum";
|
||||
break;
|
||||
std::ostream &
|
||||
operator << (
|
||||
std::ostream & stream_,
|
||||
const amqp::internal::schema::Restricted::RestrictedTypes & type_)
|
||||
{
|
||||
switch (type_) {
|
||||
case Restricted::RestrictedTypes::list_t : {
|
||||
stream_ << "list";
|
||||
break;
|
||||
}
|
||||
case Restricted::RestrictedTypes::map_t : {
|
||||
stream_ << "map";
|
||||
break;
|
||||
}
|
||||
case Restricted::RestrictedTypes::enum_t : {
|
||||
stream_ << "enum";
|
||||
break;
|
||||
}
|
||||
case Restricted::RestrictedTypes::array_t : {
|
||||
stream_ << "array";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return stream_;
|
||||
}
|
||||
|
||||
return stream_;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Static member functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
std::map<std::string, std::string> boxedToUnboxed = {
|
||||
{ "java.lang.Integer", "int" },
|
||||
{ "java.lang.Boolean", "bool" },
|
||||
{ "java.lang.Byte", "char" },
|
||||
{ "java.lang.Short", "short" },
|
||||
{ "java.lang.Character", "char" },
|
||||
{ "java.lang.Float", "float" },
|
||||
{ "java.lang.Long", "long" },
|
||||
{ "java.lang.Double", "double" }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Java gas two types of primitive, boxed and unboxed, essentially actual
|
||||
* primitives and classes representing those primitives. Of course, we
|
||||
* don't care about that, so treat boxed primitives as their underlying
|
||||
* type.
|
||||
*/
|
||||
std::string
|
||||
amqp::internal::schema::
|
||||
Restricted::unbox (const std::string & type_) {
|
||||
auto it = boxedToUnboxed.find (type_);
|
||||
if (it == boxedToUnboxed.end()) return type_;
|
||||
else return it->second;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::schema::Restricted
|
||||
@ -77,7 +126,7 @@ operator << (
|
||||
* @param source_
|
||||
* @return
|
||||
*/
|
||||
std::unique_ptr<amqp::internal::schema::Restricted>
|
||||
uPtr<amqp::internal::schema::Restricted>
|
||||
amqp::internal::schema::
|
||||
Restricted::make(
|
||||
uPtr<Descriptor> descriptor_,
|
||||
@ -87,22 +136,40 @@ Restricted::make(
|
||||
std::string source_,
|
||||
std::vector<uPtr<Choice>> choices_)
|
||||
{
|
||||
DBG ("RESTRICTED::MAKE - " << name_ << std::endl);
|
||||
/*
|
||||
* Lists represent both actual lists and enumerations. We differentiate
|
||||
* between them as enums have choices ans lists don't. Pretty certain
|
||||
* things are done this was as AMQP doesn't really have the concept
|
||||
* of an enum.
|
||||
* AMQP Lists represent actual lists, arrays, and enumerations.
|
||||
*
|
||||
* Enumerations are serialised as lists that have a set of Choices
|
||||
* Arrays are serialized as lists of types. Because java cares about the difference between
|
||||
* boxed and un-boxed primitives an unboxed array ends with [p] whilst an array of classes
|
||||
* ends with []
|
||||
*/
|
||||
if (source_ == "list") {
|
||||
if (choices_.empty()) {
|
||||
return std::make_unique<amqp::internal::schema::List>(
|
||||
std::move (descriptor_),
|
||||
std::move (name_),
|
||||
std::move (label_),
|
||||
std::move (provides_),
|
||||
std::move (source_));
|
||||
const std::string array { "[]" };
|
||||
const std::string primArray { "[p]" };
|
||||
|
||||
// when C++20 is done we can use .endswith, until then we have to do a reverse search
|
||||
if ( std::equal (name_.rbegin(), name_.rbegin() + array.size(), array.rbegin(), array.rend())
|
||||
|| std::equal (name_.rbegin(), name_.rbegin() + primArray.size(), primArray.rbegin(), primArray.rend()))
|
||||
{
|
||||
return std::make_unique<Array>(
|
||||
std::move (descriptor_),
|
||||
std::move (name_),
|
||||
std::move (label_),
|
||||
std::move (provides_),
|
||||
std::move (source_));
|
||||
} else {
|
||||
return std::make_unique<List>(
|
||||
std::move (descriptor_),
|
||||
std::move (name_),
|
||||
std::move (label_),
|
||||
std::move (provides_),
|
||||
std::move (source_));
|
||||
}
|
||||
} else {
|
||||
return std::make_unique<amqp::internal::schema::Enum>(
|
||||
return std::make_unique<Enum>(
|
||||
std::move (descriptor_),
|
||||
std::move (name_),
|
||||
std::move (label_),
|
||||
@ -111,7 +178,14 @@ Restricted::make(
|
||||
std::move (choices_));
|
||||
}
|
||||
} else if (source_ == "map") {
|
||||
throw std::runtime_error ("maps not supported");
|
||||
return std::make_unique<Map> (
|
||||
std::move (descriptor_),
|
||||
std::move (name_),
|
||||
std::move (label_),
|
||||
std::move (provides_),
|
||||
std::move (source_));
|
||||
} else {
|
||||
throw std::runtime_error ("Unknown restricted type");
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,9 +201,9 @@ Restricted::Restricted (
|
||||
) : AMQPTypeNotation (
|
||||
std::move (name_),
|
||||
std::move (descriptor_))
|
||||
, m_label (std::move (label_))
|
||||
, m_provides (std::move (provides_))
|
||||
, m_source (source_)
|
||||
, m_label { std::move (label_) }
|
||||
, m_provides { std::move (provides_) }
|
||||
, m_source { source_ }
|
||||
{
|
||||
}
|
||||
|
||||
@ -138,7 +212,7 @@ Restricted::Restricted (
|
||||
amqp::internal::schema::AMQPTypeNotation::Type
|
||||
amqp::internal::schema::
|
||||
Restricted::type() const {
|
||||
return AMQPTypeNotation::Type::Restricted;
|
||||
return AMQPTypeNotation::Type::restricted_t;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -154,8 +228,34 @@ Restricted::restrictedType() const {
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Restricted::dependsOn (const OrderedTypeNotation & rhs_) const {
|
||||
return dynamic_cast<const AMQPTypeNotation &>(rhs_).dependsOn(*this);
|
||||
return dynamic_cast<const AMQPTypeNotation &>(rhs_).dependsOnRHS (*this);
|
||||
}
|
||||
|
||||
/*********************************************************o*********************/
|
||||
|
||||
/*
|
||||
* If the left hand side of the original call, restricted_ in this case,
|
||||
* depends on this instance then we return 1.
|
||||
*
|
||||
* If this instance of a map depends on the parameter we return 2
|
||||
*/
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Restricted::dependsOnRHS (const Restricted & lhs_) const {
|
||||
switch (lhs_.restrictedType()) {
|
||||
case Restricted::RestrictedTypes::map_t :
|
||||
return dependsOnMap (
|
||||
static_cast<const amqp::internal::schema::Map &>(lhs_)); // NOLINT
|
||||
case Restricted::RestrictedTypes::list_t :
|
||||
return dependsOnList (
|
||||
static_cast<const amqp::internal::schema::List &>(lhs_)); // NOLINT
|
||||
case Restricted::RestrictedTypes::enum_t :
|
||||
return dependsOnEnum (
|
||||
static_cast<const amqp::internal::schema::Enum &>(lhs_)); // NOLINT
|
||||
case Restricted::RestrictedTypes::array_t :
|
||||
return dependsOnArray (
|
||||
static_cast<const amqp::internal::schema::Array &>(lhs_)); // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************o*********************/
|
||||
|
@ -7,9 +7,9 @@
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include "schema/Field.h"
|
||||
#include "schema/Choice.h"
|
||||
#include "schema/Descriptor.h"
|
||||
#include "schema/field-types/Field.h"
|
||||
#include "amqp/schema/described-types/Choice.h"
|
||||
#include "amqp/schema/described-types/Descriptor.h"
|
||||
#include "schema/AMQPTypeNotation.h"
|
||||
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
@ -25,9 +25,18 @@ namespace amqp::internal::schema {
|
||||
class Composite;
|
||||
class OrderedTypeNotation;
|
||||
|
||||
class Map;
|
||||
class Enum;
|
||||
class List;
|
||||
class Array;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* class Restricted
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
@ -35,7 +44,9 @@ namespace amqp::internal::schema {
|
||||
public :
|
||||
friend std::ostream & operator << (std::ostream &, const Restricted&);
|
||||
|
||||
enum RestrictedTypes { List, Map, Enum };
|
||||
enum RestrictedTypes { list_t, map_t, enum_t, array_t };
|
||||
|
||||
static std::string unbox (const std::string &);
|
||||
|
||||
private :
|
||||
// could be null in the stream... not sure that information is
|
||||
@ -65,6 +76,11 @@ namespace amqp::internal::schema {
|
||||
std::vector<std::string>,
|
||||
RestrictedTypes);
|
||||
|
||||
virtual int dependsOnMap (const Map &) const = 0;
|
||||
virtual int dependsOnList (const List &) const = 0;
|
||||
virtual int dependsOnArray (const Array &) const = 0;
|
||||
virtual int dependsOnEnum (const Enum &) const = 0;
|
||||
|
||||
public :
|
||||
static std::unique_ptr<Restricted> make(
|
||||
std::unique_ptr<Descriptor>,
|
||||
@ -89,8 +105,13 @@ namespace amqp::internal::schema {
|
||||
virtual std::vector<std::string>::const_iterator end() const = 0;
|
||||
|
||||
int dependsOn (const OrderedTypeNotation &) const override;
|
||||
int dependsOn (const Restricted &) const override = 0;
|
||||
int dependsOn (const class Composite &) const override = 0;
|
||||
int dependsOnRHS (const Restricted &) const override;
|
||||
|
||||
int dependsOnRHS (const Composite &) const override = 0;
|
||||
|
||||
const decltype (m_provides) & provides() const { return m_provides; }
|
||||
const decltype (m_label) & label() const { return m_label; }
|
||||
const decltype (m_source) & source() const { return m_source; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -2,8 +2,12 @@ set (EXE "amqp-test")
|
||||
|
||||
set (amqp-test-sources
|
||||
main.cxx
|
||||
Map.cxx
|
||||
Pair.cxx
|
||||
List.cxx
|
||||
Single.cxx
|
||||
TestUtils.cxx
|
||||
RestrictedDescriptor.cxx
|
||||
OrderedTypeNotationTest.cxx
|
||||
)
|
||||
|
||||
|
26
experimental/cpp-serializer/src/amqp/test/List.cxx
Normal file
26
experimental/cpp-serializer/src/amqp/test/List.cxx
Normal file
@ -0,0 +1,26 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "restricted-types/List.h"
|
||||
#include "restricted-types/Restricted.h"
|
||||
#include "TestUtils.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (List, name) {
|
||||
auto rtn = amqp::internal::schema::List::listType("java.util.list<int>");
|
||||
|
||||
ASSERT_EQ ("java.util.list", rtn.first);
|
||||
ASSERT_EQ ("int", rtn.second);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (List, dependsOn1) {
|
||||
auto list1 = test::list ("string");
|
||||
auto list2 = test::list (list1->name());
|
||||
|
||||
ASSERT_EQ (1, list1->dependsOn (*list2));
|
||||
ASSERT_EQ (2, list2->dependsOn (*list1));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
212
experimental/cpp-serializer/src/amqp/test/Map.cxx
Normal file
212
experimental/cpp-serializer/src/amqp/test/Map.cxx
Normal file
@ -0,0 +1,212 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "TestUtils.h"
|
||||
|
||||
#include "amqp/schema/described-types/Descriptor.h"
|
||||
#include "restricted-types/Map.h"
|
||||
#include "restricted-types/List.h"
|
||||
#include "restricted-types/Enum.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* mapType Tests
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
TEST (Map, name1) {
|
||||
auto [map, of, to] = amqp::internal::schema::Map::mapType (
|
||||
"java.util.Map<int, string>");
|
||||
|
||||
ASSERT_EQ ("java.util.Map", map);
|
||||
ASSERT_EQ ("int", of);
|
||||
ASSERT_EQ ("string", to);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (Map, name2) {
|
||||
auto [map, of, to] = amqp::internal::schema::Map::mapType (
|
||||
"java.util.Map<int, java.util.List<string>>");
|
||||
|
||||
ASSERT_EQ ("java.util.Map", map);
|
||||
ASSERT_EQ ("int", of);
|
||||
ASSERT_EQ ("java.util.List<string>", to);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (Map, name3) {
|
||||
auto [map, of, to] = amqp::internal::schema::Map::mapType (
|
||||
"java.util.Map<java.util.Pair<int, int>, java.util.List<string>>");
|
||||
|
||||
ASSERT_EQ ("java.util.Map", map);
|
||||
ASSERT_EQ ("java.util.Pair<int, int>", of);
|
||||
ASSERT_EQ ("java.util.List<string>", to);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
using namespace amqp::internal::schema;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (Map, dependsOn1) {
|
||||
auto result {
|
||||
"level 1\n"
|
||||
" * java.util.List<string>\n"
|
||||
"\n"
|
||||
"level 2\n"
|
||||
" * java.util.Map<int, java.util.List<string>>\n\n"
|
||||
};
|
||||
|
||||
{
|
||||
OrderedTypeNotations<Restricted> otn;
|
||||
|
||||
auto l = test::list("string");
|
||||
auto m = test::map("int", l->name());
|
||||
|
||||
otn.insert (std::move (l));
|
||||
otn.insert (std::move (m));
|
||||
|
||||
std::stringstream ss;
|
||||
ss << otn;
|
||||
|
||||
ASSERT_EQ (result, ss.str());
|
||||
}
|
||||
|
||||
// Same test but reverse the insertion order
|
||||
{
|
||||
OrderedTypeNotations<Restricted> otn;
|
||||
|
||||
auto l = test::list("string");
|
||||
auto m = test::map("int", l->name());
|
||||
|
||||
otn.insert(std::move(m));
|
||||
otn.insert(std::move(l));
|
||||
|
||||
std::stringstream ss;
|
||||
ss << otn;
|
||||
|
||||
ASSERT_EQ (result, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (Map, dependsOn2) {
|
||||
auto result {
|
||||
"level 1\n"
|
||||
" * net.corda.eee\n"
|
||||
"\n"
|
||||
"level 2\n"
|
||||
" * java.util.List<net.corda.eee>\n"
|
||||
"\n"
|
||||
"level 3\n"
|
||||
" * java.util.Map<int, java.util.List<net.corda.eee>>\n\n"
|
||||
};
|
||||
|
||||
{
|
||||
OrderedTypeNotations<Restricted> otn;
|
||||
|
||||
auto e = test::eNum("eee");
|
||||
auto l = test::list(e->name());
|
||||
auto m = test::map("int", l->name());
|
||||
|
||||
otn.insert(std::move(l));
|
||||
otn.insert(std::move(m));
|
||||
otn.insert(std::move(e));
|
||||
|
||||
std::stringstream ss;
|
||||
ss << otn;
|
||||
|
||||
ASSERT_EQ (result, ss.str());
|
||||
}
|
||||
{
|
||||
OrderedTypeNotations<Restricted> otn;
|
||||
|
||||
auto e = test::eNum("eee");
|
||||
auto l = test::list(e->name());
|
||||
auto m = test::map("int", l->name());
|
||||
|
||||
otn.insert(std::move(l));
|
||||
otn.insert(std::move(e));
|
||||
otn.insert(std::move(m));
|
||||
|
||||
std::stringstream ss;
|
||||
ss << otn;
|
||||
|
||||
ASSERT_EQ (result, ss.str());
|
||||
}
|
||||
{
|
||||
OrderedTypeNotations<Restricted> otn;
|
||||
|
||||
auto e = test::eNum("eee");
|
||||
auto l = test::list(e->name());
|
||||
auto m = test::map("int", l->name());
|
||||
|
||||
otn.insert(std::move(m));
|
||||
otn.insert(std::move(l));
|
||||
otn.insert(std::move(e));
|
||||
|
||||
std::stringstream ss;
|
||||
ss << otn;
|
||||
|
||||
ASSERT_EQ (result, ss.str());
|
||||
}
|
||||
{
|
||||
OrderedTypeNotations<Restricted> otn;
|
||||
|
||||
auto e = test::eNum ("eee");
|
||||
auto l = test::list (e->name());
|
||||
auto m = test::map ("int", l->name());
|
||||
|
||||
otn.insert (std::move (m));
|
||||
|
||||
otn.insert (std::move (e));
|
||||
otn.insert (std::move (l));
|
||||
|
||||
std::stringstream ss;
|
||||
ss << otn;
|
||||
|
||||
ASSERT_EQ (result, ss.str());
|
||||
}
|
||||
{
|
||||
OrderedTypeNotations<Restricted> otn;
|
||||
|
||||
auto e = test::eNum("eee");
|
||||
auto l = test::list(e->name());
|
||||
auto m = test::map("int", l->name());
|
||||
|
||||
otn.insert (std::move (e));
|
||||
otn.insert (std::move (l));
|
||||
otn.insert (std::move (m));
|
||||
|
||||
std::stringstream ss;
|
||||
ss << otn;
|
||||
|
||||
ASSERT_EQ (result, ss.str());
|
||||
}
|
||||
{
|
||||
OrderedTypeNotations<Restricted> otn;
|
||||
|
||||
auto e = test::eNum ("eee");
|
||||
auto l = test::list (e->name());
|
||||
auto m = test::map ("int", l->name());
|
||||
|
||||
otn.insert (std::move (e));
|
||||
otn.insert (std::move (m));
|
||||
otn.insert (std::move (l));
|
||||
|
||||
std::stringstream ss;
|
||||
ss << otn;
|
||||
|
||||
ASSERT_EQ (result, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -109,18 +109,21 @@ TEST (OTNTest, singleInsert) { // NOLINT
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, twoInserts) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
list.insert(std::make_unique<OTN>("A", std::vector<std::string>()));
|
||||
list.insert(std::make_unique<OTN>("B", std::vector<std::string>()));
|
||||
ASSERT_EQ("A B", str (list));
|
||||
|
||||
// Inserting B after A with no dependencies between the two will force
|
||||
// B to be recorded before A since elements added at the same
|
||||
// level are always added to the front of the list to ensrue we can
|
||||
// inspect the rest of that level
|
||||
ASSERT_EQ ("B A", str (list));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, A_depends_on_B) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { "B" };
|
||||
@ -132,7 +135,6 @@ TEST (OTNTest, A_depends_on_B) { // NOLINT
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, B_depends_on_A) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { };
|
||||
@ -147,7 +149,6 @@ TEST (OTNTest, B_depends_on_A) { // NOLINT
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, three_1) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { };
|
||||
@ -164,7 +165,6 @@ TEST (OTNTest, three_1) { // NOLINT
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, three_2) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { "B" };
|
||||
@ -181,7 +181,6 @@ TEST (OTNTest, three_2) { // NOLINT
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, three_3) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { "B" };
|
||||
@ -198,7 +197,6 @@ TEST (OTNTest, three_3) { // NOLINT
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, three_4) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { "B" };
|
||||
@ -215,7 +213,6 @@ TEST (OTNTest, three_4) { // NOLINT
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, three_5) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { "B" };
|
||||
|
@ -0,0 +1,25 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "descriptors/corda-descriptors/RestrictedDescriptor.h"
|
||||
|
||||
using namespace amqp::internal::schema::descriptors;
|
||||
|
||||
TEST (RestrictedDescriptor, makePrim1) { // NOLINT
|
||||
EXPECT_EQ ("int", RestrictedDescriptor::makePrim ("int"));
|
||||
}
|
||||
|
||||
TEST (RestrictedDescriptor, makePrim2) { // NOLINT
|
||||
EXPECT_EQ ("int[]", RestrictedDescriptor::makePrim ("int[]"));
|
||||
}
|
||||
|
||||
TEST (RestrictedDescriptor, makePrim3) { // NOLINT
|
||||
EXPECT_EQ ("java.lang.integer", RestrictedDescriptor::makePrim ("int"));
|
||||
}
|
||||
|
||||
TEST (RestrictedDescriptor, makePrim4) { // NOLINT
|
||||
EXPECT_EQ ("java.lang.integer[]", RestrictedDescriptor::makePrim ("int[]"));
|
||||
}
|
||||
|
||||
TEST (RestrictedDescriptor, makePrim5) { // NOLINT§
|
||||
EXPECT_EQ ("int[], int", RestrictedDescriptor::makePrim ("java.lang.Integer[], java.lang.Integer"));
|
||||
}
|
@ -4,15 +4,21 @@
|
||||
|
||||
#include "Reader.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
using namespace amqp::reader;
|
||||
using namespace amqp::internal::reader;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (Single, string) { // NOLINT
|
||||
TypedSingle<std::string> str_test ("Hello");
|
||||
|
||||
EXPECT_EQ("Hello", str_test.dump());
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (Single, list) { // NOLINT
|
||||
|
||||
struct builder {
|
||||
@ -36,3 +42,4 @@ TEST (Single, list) { // NOLINT
|
||||
|
||||
EXPECT_EQ("[ 1, 2, 3, 4, 5 ]", test->dump());
|
||||
}
|
||||
/******************************************************************************/
|
||||
|
126
experimental/cpp-serializer/src/amqp/test/TestUtils.cxx
Normal file
126
experimental/cpp-serializer/src/amqp/test/TestUtils.cxx
Normal file
@ -0,0 +1,126 @@
|
||||
#include "TestUtils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include "types.h"
|
||||
|
||||
#include "restricted-types/Map.h"
|
||||
#include "restricted-types/List.h"
|
||||
#include "restricted-types/Enum.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
using namespace amqp::internal::schema;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
std::string fingerprint() {
|
||||
auto randchar = []() -> char {
|
||||
const char charset[] =
|
||||
"0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
const size_t max_index = (sizeof(charset) - 1);
|
||||
return charset[rand() % max_index];
|
||||
};
|
||||
std::string str(20, 0);
|
||||
std::generate_n(str.begin(), 20, randchar);
|
||||
|
||||
return "net.corda:" + str;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<Map>
|
||||
test::
|
||||
map (const std::string & of_, const std::string & to_) {
|
||||
auto desc = std::make_unique<Descriptor> (
|
||||
fingerprint());
|
||||
|
||||
std::vector<std::string> provides { };
|
||||
|
||||
return std::make_unique<Map>(
|
||||
std::move (desc),
|
||||
"java.util.Map<" + of_ + ", " + to_ + ">",
|
||||
"label",
|
||||
std::move (provides),
|
||||
"map"
|
||||
);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr <amqp::internal::schema::List>
|
||||
test::
|
||||
list (const std::string & of_) {
|
||||
auto desc = std::make_unique<Descriptor> (
|
||||
fingerprint());
|
||||
|
||||
std::vector<std::string> provides { };
|
||||
|
||||
std::cout << "FAKE LIST: " << of_ << std::endl;
|
||||
|
||||
return std::make_unique<List> (
|
||||
std::move (desc),
|
||||
"java.util.List<" + of_ + ">",
|
||||
"label",
|
||||
std::move (provides),
|
||||
"map"
|
||||
);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr <amqp::internal::schema::Enum>
|
||||
test::
|
||||
eNum (const std::string & e_) {
|
||||
auto desc = std::make_unique<amqp::internal::schema::Descriptor> (
|
||||
fingerprint());
|
||||
|
||||
sVec<std::string> provides { };
|
||||
|
||||
sVec<uPtr<Choice>> choices (2);
|
||||
choices.emplace_back(
|
||||
(std::make_unique<Choice>(Choice ("a"))));
|
||||
choices.emplace_back(
|
||||
(std::make_unique<Choice>(Choice ("b"))));
|
||||
|
||||
return std::make_unique<amqp::internal::schema::Enum>(
|
||||
std::move (desc),
|
||||
"net.corda." + e_,
|
||||
"label",
|
||||
std::move (provides),
|
||||
"enum",
|
||||
std::move (choices)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uPtr<amqp::internal::schema::Composite>
|
||||
test::
|
||||
comp (
|
||||
const std::string & name_,
|
||||
const std::vector<std::string> & fields_
|
||||
) {
|
||||
/*
|
||||
auto desc = std::make_unique<Descriptor> (
|
||||
fingerprint());
|
||||
|
||||
std::vector<std::string> provides { };
|
||||
|
||||
Composite (
|
||||
name_,
|
||||
"label",
|
||||
provides,
|
||||
desc,
|
||||
std::vector<std::unique_ptr<Field>> & fields_);
|
||||
*/
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
23
experimental/cpp-serializer/src/amqp/test/TestUtils.h
Normal file
23
experimental/cpp-serializer/src/amqp/test/TestUtils.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "restricted-types/List.h"
|
||||
#include "restricted-types/Map.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace test {
|
||||
uPtr <amqp::internal::schema::Map>
|
||||
map (const std::string &, const std::string &);
|
||||
|
||||
uPtr <amqp::internal::schema::List>
|
||||
list (const std::string & of_);
|
||||
|
||||
uPtr <amqp::internal::schema::Enum>
|
||||
eNum (const std::string & e_);
|
||||
|
||||
uPtr <amqp::internal::schema::Composite>
|
||||
comp (const std::string & name_, const std::vector<std::string> &);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
Reference in New Issue
Block a user