mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
NOTICK - Initial work on a non JVM (C++) serialiser (#5368)
Currently, it's more of a blob inspector than a full-blown implementation, but this code does have the ability to understand a Corda serialized blob and build a set of deserialisers to handle a blob. It does this in the same way the native java implementation works by interrogating the types (as per the definition in the envelope) and building recursive type readers that are able to pull the relevant information out of the byte stream. Lots of future work to undertake, but as a starting point its a little bit useful with the scope it could be made much more useful with some work.
This commit is contained in:
parent
a477d59c15
commit
913ba1d46e
178
.idea/compiler.xml
generated
178
.idea/compiler.xml
generated
@ -29,6 +29,8 @@
|
||||
<module name="buildSrc_test" target="1.8" />
|
||||
<module name="canonicalizer_main" target="1.8" />
|
||||
<module name="canonicalizer_test" target="1.8" />
|
||||
<module name="capsule.net.corda.capsule.main" target="1.6" />
|
||||
<module name="capsule.net.corda.capsule.test" target="1.6" />
|
||||
<module name="checkpoint-agent_main" target="1.8" />
|
||||
<module name="checkpoint-agent_test" target="1.8" />
|
||||
<module name="cli_main" target="1.8" />
|
||||
@ -37,6 +39,8 @@
|
||||
<module name="client_test" target="1.8" />
|
||||
<module name="cliutils_main" target="1.8" />
|
||||
<module name="cliutils_test" target="1.8" />
|
||||
<module name="com.r3cev.prototyping.experimental.main" target="1.8" />
|
||||
<module name="com.r3cev.prototyping.experimental.test" target="1.8" />
|
||||
<module name="common-configuration-parsing_main" target="1.8" />
|
||||
<module name="common-configuration-parsing_test" target="1.8" />
|
||||
<module name="common-logging_main" target="1.8" />
|
||||
@ -50,6 +54,8 @@
|
||||
<module name="contracts-states_integrationTest" target="1.8" />
|
||||
<module name="contracts-states_main" target="1.8" />
|
||||
<module name="contracts-states_test" target="1.8" />
|
||||
<module name="contracts.net.corda.contracts.main" target="1.8" />
|
||||
<module name="contracts.net.corda.contracts.test" target="1.8" />
|
||||
<module name="contracts_main" target="1.8" />
|
||||
<module name="contracts_test" target="1.8" />
|
||||
<module name="corda-core_integrationTest" target="1.8" />
|
||||
@ -255,6 +261,8 @@
|
||||
<module name="corda-webserver_test" target="1.8" />
|
||||
<module name="cordapp-configuration-workflows_main" target="1.8" />
|
||||
<module name="cordapp-configuration-workflows_test" target="1.8" />
|
||||
<module name="cordapp-configuration.workflows.net.corda.workflows.main" target="1.8" />
|
||||
<module name="cordapp-configuration.workflows.net.corda.workflows.test" target="1.8" />
|
||||
<module name="cordapp-configuration_main" target="1.8" />
|
||||
<module name="cordapp-configuration_test" target="1.8" />
|
||||
<module name="cordapp_integrationTest" target="1.8" />
|
||||
@ -359,8 +367,168 @@
|
||||
<module name="net.corda-isolated_test" target="1.8" />
|
||||
<module name="net.corda-verifier_main" target="1.8" />
|
||||
<module name="net.corda-verifier_test" target="1.8" />
|
||||
<module name="net.corda.attachment-demo.integrationTest" target="1.8" />
|
||||
<module name="net.corda.attachment-demo.main" target="1.8" />
|
||||
<module name="net.corda.attachment-demo.test" target="1.8" />
|
||||
<module name="net.corda.avalanche.main" target="1.8" />
|
||||
<module name="net.corda.avalanche.test" target="1.8" />
|
||||
<module name="net.corda.bank-of-corda-demo.main" target="1.8" />
|
||||
<module name="net.corda.bank-of-corda-demo.test" target="1.8" />
|
||||
<module name="net.corda.blobinspector.main" target="1.8" />
|
||||
<module name="net.corda.blobinspector.test" target="1.8" />
|
||||
<module name="net.corda.bootstrapper.main" target="1.8" />
|
||||
<module name="net.corda.bootstrapper.test" target="1.8" />
|
||||
<module name="net.corda.buildSrc.main" target="1.8" />
|
||||
<module name="net.corda.buildSrc.test" target="1.8" />
|
||||
<module name="net.corda.capsule.main" target="1.8" />
|
||||
<module name="net.corda.capsule.test" target="1.8" />
|
||||
<module name="net.corda.checkpoint-agent.main" target="1.8" />
|
||||
<module name="net.corda.checkpoint-agent.test" target="1.8" />
|
||||
<module name="net.corda.client.main" target="1.8" />
|
||||
<module name="net.corda.client.test" target="1.8" />
|
||||
<module name="net.corda.cliutils.main" target="1.8" />
|
||||
<module name="net.corda.cliutils.test" target="1.8" />
|
||||
<module name="net.corda.common-configuration-parsing.main" target="1.8" />
|
||||
<module name="net.corda.common-configuration-parsing.test" target="1.8" />
|
||||
<module name="net.corda.common-logging.main" target="1.8" />
|
||||
<module name="net.corda.common-logging.test" target="1.8" />
|
||||
<module name="net.corda.common-validation.main" target="1.8" />
|
||||
<module name="net.corda.common-validation.test" target="1.8" />
|
||||
<module name="net.corda.confidential-identities.main" target="1.8" />
|
||||
<module name="net.corda.confidential-identities.test" target="1.8" />
|
||||
<module name="net.corda.contracts-irs.main" target="1.8" />
|
||||
<module name="net.corda.contracts-irs.test" target="1.8" />
|
||||
<module name="net.corda.contracts-states.main" target="1.8" />
|
||||
<module name="net.corda.contracts-states.test" target="1.8" />
|
||||
<module name="net.corda.contracts.main" target="1.8" />
|
||||
<module name="net.corda.contracts.test" target="1.8" />
|
||||
<module name="net.corda.corda-project.main" target="1.8" />
|
||||
<module name="net.corda.corda-project.test" target="1.8" />
|
||||
<module name="net.corda.corda-utils.integrationTest" target="1.8" />
|
||||
<module name="net.corda.corda-utils.main" target="1.8" />
|
||||
<module name="net.corda.corda-utils.test" target="1.8" />
|
||||
<module name="net.corda.cordapp-configuration.main" target="1.8" />
|
||||
<module name="net.corda.cordapp-configuration.test" target="1.8" />
|
||||
<module name="net.corda.cordapp.integrationTest" target="1.8" />
|
||||
<module name="net.corda.cordapp.main" target="1.8" />
|
||||
<module name="net.corda.cordapp.test" target="1.8" />
|
||||
<module name="net.corda.core-deterministic.main" target="1.8" />
|
||||
<module name="net.corda.core-deterministic.test" target="1.8" />
|
||||
<module name="net.corda.core-tests.integrationTest" target="1.8" />
|
||||
<module name="net.corda.core-tests.main" target="1.8" />
|
||||
<module name="net.corda.core-tests.smokeTest" target="1.8" />
|
||||
<module name="net.corda.core-tests.test" target="1.8" />
|
||||
<module name="net.corda.core.main" target="1.8" />
|
||||
<module name="net.corda.core.test" target="1.8" />
|
||||
<module name="net.corda.data.main" target="1.8" />
|
||||
<module name="net.corda.data.test" target="1.8" />
|
||||
<module name="net.corda.demobench.main" target="1.8" />
|
||||
<module name="net.corda.demobench.test" target="1.8" />
|
||||
<module name="net.corda.docker.main" target="1.8" />
|
||||
<module name="net.corda.docker.test" target="1.8" />
|
||||
<module name="net.corda.docs.main" target="1.8" />
|
||||
<module name="net.corda.docs.test" target="1.8" />
|
||||
<module name="net.corda.example-code.integrationTest" target="1.8" />
|
||||
<module name="net.corda.example-code.main" target="1.8" />
|
||||
<module name="net.corda.example-code.test" target="1.8" />
|
||||
<module name="net.corda.explorer.main" target="1.8" />
|
||||
<module name="net.corda.explorer.test" target="1.8" />
|
||||
<module name="net.corda.finance.main" target="1.8" />
|
||||
<module name="net.corda.finance.test" target="1.8" />
|
||||
<module name="net.corda.flows.main" target="1.8" />
|
||||
<module name="net.corda.flows.test" target="1.8" />
|
||||
<module name="net.corda.graphs.main" target="1.8" />
|
||||
<module name="net.corda.graphs.test" target="1.8" />
|
||||
<module name="net.corda.irs-demo.integrationTest" target="1.8" />
|
||||
<module name="net.corda.irs-demo.main" target="1.8" />
|
||||
<module name="net.corda.irs-demo.systemTest" target="1.8" />
|
||||
<module name="net.corda.irs-demo.test" target="1.8" />
|
||||
<module name="net.corda.irs-demo.web.main" target="1.8" />
|
||||
<module name="net.corda.irs-demo.web.test" target="1.8" />
|
||||
<module name="net.corda.isolated.main" target="1.8" />
|
||||
<module name="net.corda.isolated.test" target="1.8" />
|
||||
<module name="net.corda.jackson.main" target="1.8" />
|
||||
<module name="net.corda.jackson.test" target="1.8" />
|
||||
<module name="net.corda.jdk8u-deterministic.main" target="1.8" />
|
||||
<module name="net.corda.jdk8u-deterministic.test" target="1.8" />
|
||||
<module name="net.corda.jfx.integrationTest" target="1.8" />
|
||||
<module name="net.corda.jfx.main" target="1.8" />
|
||||
<module name="net.corda.jfx.test" target="1.8" />
|
||||
<module name="net.corda.loadtest.main" target="1.8" />
|
||||
<module name="net.corda.loadtest.test" target="1.8" />
|
||||
<module name="net.corda.mock.main" target="1.8" />
|
||||
<module name="net.corda.mock.test" target="1.8" />
|
||||
<module name="net.corda.netparams.main" target="1.8" />
|
||||
<module name="net.corda.netparams.test" target="1.8" />
|
||||
<module name="net.corda.network-builder.main" target="1.8" />
|
||||
<module name="net.corda.network-builder.test" target="1.8" />
|
||||
<module name="net.corda.network-verifier.main" target="1.8" />
|
||||
<module name="net.corda.network-verifier.test" target="1.8" />
|
||||
<module name="net.corda.node-api.main" target="1.8" />
|
||||
<module name="net.corda.node-api.test" target="1.8" />
|
||||
<module name="net.corda.node-driver.integrationTest" target="1.8" />
|
||||
<module name="net.corda.node-driver.main" target="1.8" />
|
||||
<module name="net.corda.node-driver.test" target="1.8" />
|
||||
<module name="net.corda.node.integrationTest" target="1.8" />
|
||||
<module name="net.corda.node.main" target="1.8" />
|
||||
<module name="net.corda.node.test" target="1.8" />
|
||||
<module name="net.corda.nodeinfo.main" target="1.8" />
|
||||
<module name="net.corda.nodeinfo.test" target="1.8" />
|
||||
<module name="net.corda.notary-demo.main" target="1.8" />
|
||||
<module name="net.corda.notary-demo.test" target="1.8" />
|
||||
<module name="net.corda.quasar-hook.main" target="1.8" />
|
||||
<module name="net.corda.quasar-hook.test" target="1.8" />
|
||||
<module name="net.corda.rpc.integrationTest" target="1.8" />
|
||||
<module name="net.corda.rpc.main" target="1.8" />
|
||||
<module name="net.corda.rpc.smokeTest" target="1.8" />
|
||||
<module name="net.corda.rpc.test" target="1.8" />
|
||||
<module name="net.corda.samples.main" target="1.8" />
|
||||
<module name="net.corda.samples.test" target="1.8" />
|
||||
<module name="net.corda.serialization-deterministic.main" target="1.8" />
|
||||
<module name="net.corda.serialization-deterministic.test" target="1.8" />
|
||||
<module name="net.corda.serialization.main" target="1.8" />
|
||||
<module name="net.corda.serialization.test" target="1.8" />
|
||||
<module name="net.corda.shell-cli.main" target="1.8" />
|
||||
<module name="net.corda.shell-cli.test" target="1.8" />
|
||||
<module name="net.corda.shell.integrationTest" target="1.8" />
|
||||
<module name="net.corda.shell.main" target="1.8" />
|
||||
<module name="net.corda.shell.test" target="1.8" />
|
||||
<module name="net.corda.simm-valuation-demo.integrationTest" target="1.8" />
|
||||
<module name="net.corda.simm-valuation-demo.main" target="1.8" />
|
||||
<module name="net.corda.simm-valuation-demo.test" target="1.8" />
|
||||
<module name="net.corda.smoke-test-utils.main" target="1.8" />
|
||||
<module name="net.corda.smoke-test-utils.test" target="1.8" />
|
||||
<module name="net.corda.test-cli.main" target="1.8" />
|
||||
<module name="net.corda.test-cli.test" target="1.8" />
|
||||
<module name="net.corda.test-common.main" target="1.8" />
|
||||
<module name="net.corda.test-common.test" target="1.8" />
|
||||
<module name="net.corda.test-db.main" target="1.8" />
|
||||
<module name="net.corda.test-db.test" target="1.8" />
|
||||
<module name="net.corda.test-utils.main" target="1.8" />
|
||||
<module name="net.corda.test-utils.test" target="1.8" />
|
||||
<module name="net.corda.testing.main" target="1.8" />
|
||||
<module name="net.corda.testing.test" target="1.8" />
|
||||
<module name="net.corda.tools.main" target="1.8" />
|
||||
<module name="net.corda.tools.test" target="1.8" />
|
||||
<module name="net.corda.trader-demo.integrationTest" target="1.8" />
|
||||
<module name="net.corda.trader-demo.main" target="1.8" />
|
||||
<module name="net.corda.trader-demo.test" target="1.8" />
|
||||
<module name="net.corda.verifier.main" target="1.8" />
|
||||
<module name="net.corda.verifier.test" target="1.8" />
|
||||
<module name="net.corda.webcapsule.main" target="1.6" />
|
||||
<module name="net.corda.webcapsule.test" target="1.6" />
|
||||
<module name="net.corda.webserver.integrationTest" target="1.8" />
|
||||
<module name="net.corda.webserver.main" target="1.8" />
|
||||
<module name="net.corda.webserver.test" target="1.8" />
|
||||
<module name="net.corda.workflows-irs.main" target="1.8" />
|
||||
<module name="net.corda.workflows-irs.test" target="1.8" />
|
||||
<module name="net.corda.workflows-trader.main" target="1.8" />
|
||||
<module name="net.corda.workflows-trader.test" target="1.8" />
|
||||
<module name="net.corda.workflows.integrationTest" target="1.8" />
|
||||
<module name="net.corda.workflows.main" target="1.8" />
|
||||
<module name="net.corda.workflows.test" target="1.8" />
|
||||
<module name="net.corda.worldmap.main" target="1.8" />
|
||||
<module name="net.corda.worldmap.test" target="1.8" />
|
||||
<module name="net.corda_buildSrc_main" target="1.8" />
|
||||
<module name="net.corda_buildSrc_test" target="1.8" />
|
||||
<module name="net.corda_canonicalizer_main" target="1.8" />
|
||||
@ -375,6 +543,10 @@
|
||||
<module name="network-verifier-contracts_test" target="1.8" />
|
||||
<module name="network-verifier-workflows_main" target="1.8" />
|
||||
<module name="network-verifier-workflows_test" target="1.8" />
|
||||
<module name="network-verifier.contracts.net.corda.contracts.main" target="1.8" />
|
||||
<module name="network-verifier.contracts.net.corda.contracts.test" target="1.8" />
|
||||
<module name="network-verifier.workflows.net.corda.workflows.main" target="1.8" />
|
||||
<module name="network-verifier.workflows.net.corda.workflows.test" target="1.8" />
|
||||
<module name="network-verifier_main" target="1.8" />
|
||||
<module name="network-verifier_test" target="1.8" />
|
||||
<module name="network-visualiser_main" target="1.8" />
|
||||
@ -400,6 +572,10 @@
|
||||
<module name="notary-demo-contracts_test" target="1.8" />
|
||||
<module name="notary-demo-workflows_main" target="1.8" />
|
||||
<module name="notary-demo-workflows_test" target="1.8" />
|
||||
<module name="notary-demo.contracts.net.corda.contracts.main" target="1.8" />
|
||||
<module name="notary-demo.contracts.net.corda.contracts.test" target="1.8" />
|
||||
<module name="notary-demo.workflows.net.corda.workflows.main" target="1.8" />
|
||||
<module name="notary-demo.workflows.net.corda.workflows.test" target="1.8" />
|
||||
<module name="notary-demo_main" target="1.8" />
|
||||
<module name="notary-demo_test" target="1.8" />
|
||||
<module name="notary-raft_main" target="1.8" />
|
||||
@ -484,6 +660,8 @@
|
||||
<module name="workflows-trader_integrationTest" target="1.8" />
|
||||
<module name="workflows-trader_main" target="1.8" />
|
||||
<module name="workflows-trader_test" target="1.8" />
|
||||
<module name="workflows.net.corda.workflows.main" target="1.8" />
|
||||
<module name="workflows.net.corda.workflows.test" target="1.8" />
|
||||
<module name="workflows_integrationTest" target="1.8" />
|
||||
<module name="workflows_main" target="1.8" />
|
||||
<module name="workflows_test" target="1.8" />
|
||||
|
38
experimental/cpp-serializer/CMakeLists.txt
Normal file
38
experimental/cpp-serializer/CMakeLists.txt
Normal file
@ -0,0 +1,38 @@
|
||||
PROJECT (BLOB-INSPECTOR)
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
SET (${PROJECT_NAME}_MAJOR_VERSION 0)
|
||||
SET (${PROJECT_NAME}_MINOR_VERSION 0)
|
||||
SET (${PROJECT_NAME}_PATCH_LEVEL 1)
|
||||
|
||||
#ADD_DEFINITIONS ("-Wall -g -ansi -pedantic")
|
||||
ADD_DEFINITIONS ("-Wall -g -ansi")
|
||||
|
||||
#ADD_DEFINITIONS ("-DSRC_DEBUG")
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
set (CMAKE_VERBOSE_MAKEFILE "FALSE" CACHE BOOL "" FORCE)
|
||||
|
||||
#
|
||||
# For "reasons" something to do with the way the comand line compiler
|
||||
# is invoked on MacOS /usr/local/include is removed from the
|
||||
# system include path so add it back in or we will fail to find
|
||||
# qpid-python files as brew installs it there
|
||||
#
|
||||
if(APPLE)
|
||||
include_directories (/usr/local/include)
|
||||
link_directories (/usr/local/lib)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Interface include files
|
||||
#
|
||||
include_directories (${BLOB-INSPECTOR_SOURCE_DIR}/include)
|
||||
|
||||
add_compile_options(-std=c++17)
|
||||
|
||||
ADD_SUBDIRECTORY (src)
|
||||
ADD_SUBDIRECTORY (bin)
|
43
experimental/cpp-serializer/README.md
Normal file
43
experimental/cpp-serializer/README.md
Normal file
@ -0,0 +1,43 @@
|
||||
# Corda Blob Inspection
|
||||
|
||||
This is a best effort attempt at a C++ implemention of the CORDA serialization framework in a non JVM language. The initial target is a working "blob inspector", that is an exe that can take a serialised blob from a vault (or other) and decode it using C++.
|
||||
|
||||
## Currently Working
|
||||
|
||||
An implementation of a "blob inspector" that can take a serialised blob and decode it into a printable JSON format where that blob contains a constrained set of types. The current limitation with this implementation is that it does not understand associative containers (maps).
|
||||
|
||||
## Fututre Work
|
||||
|
||||
* Encode and decode of local C++ types
|
||||
* Decpdable encode of native types
|
||||
* Some schema generation from the JVM canonical source
|
||||
|
||||
## Dependencies
|
||||
|
||||
* qpid-proton
|
||||
* C++17
|
||||
* gtest
|
||||
* cmake
|
||||
|
||||
## Setup
|
||||
|
||||
### MacOS
|
||||
|
||||
* brew install cmake
|
||||
* brew install qpid-proton
|
||||
|
||||
Google Test
|
||||
|
||||
* git clone https://github.com/google/googletest
|
||||
* cd googletest
|
||||
* mkdir build
|
||||
* cd build
|
||||
* cmake ..
|
||||
* make
|
||||
* make install
|
||||
|
||||
### Linux
|
||||
|
||||
* sudo apt-get install cmake
|
||||
* sudo apt-get install libqpid-proton8-dev
|
||||
* sudi apt-get install libgtest-dev
|
1
experimental/cpp-serializer/bin/.gitignore
vendored
Normal file
1
experimental/cpp-serializer/bin/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
blob-inspector
|
9
experimental/cpp-serializer/bin/CMakeLists.txt
Normal file
9
experimental/cpp-serializer/bin/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
||||
include_directories (${BLOB-INSPECTOR_SOURCE_DIR}/src)
|
||||
include_directories (${BLOB-INSPECTOR_SOURCE_DIR}/src/amqp)
|
||||
|
||||
link_directories (${BLOB-INSPECTOR_BINARY_DIR}/src/amqp)
|
||||
link_directories (${BLOB-INSPECTOR_BINARY_DIR}/src/proton)
|
||||
|
||||
add_executable (blob-inspector main)
|
||||
|
||||
target_link_libraries (blob-inspector amqp proton qpid-proton)
|
115
experimental/cpp-serializer/bin/main.cxx
Normal file
115
experimental/cpp-serializer/bin/main.cxx
Normal file
@ -0,0 +1,115 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <cstddef>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <proton/types.h>
|
||||
#include <proton/codec.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#import "debug.h"
|
||||
|
||||
#include "proton/proton_wrapper.h"
|
||||
|
||||
#include "amqp/AMQPHeader.h"
|
||||
#include "amqp/AMQPSectionId.h"
|
||||
#include "amqp/descriptors/AMQPDescriptorRegistory.h"
|
||||
|
||||
#include "amqp/schema/Envelope.h"
|
||||
#include "CompositeFactory.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
data_and_stop(std::ifstream & f_, ssize_t sz) {
|
||||
char * blob = new char[sz];
|
||||
memset (blob, 0, sz);
|
||||
f_.read(blob, sz);
|
||||
|
||||
pn_data_t * d = pn_data(sz);
|
||||
|
||||
// returns how many bytes we processed which right now we don't care
|
||||
// about but I assume there is a case where it doesn't process the
|
||||
// entire file
|
||||
auto rtn = pn_data_decode (d, blob, sz);
|
||||
assert (rtn == sz);
|
||||
|
||||
std::unique_ptr<amqp::internal::schema::Envelope> envelope;
|
||||
|
||||
if (pn_data_is_described(d)) {
|
||||
proton::auto_enter p (d);
|
||||
|
||||
auto a = pn_data_get_ulong(d);
|
||||
|
||||
envelope.reset (
|
||||
dynamic_cast<amqp::internal::schema::Envelope *> (
|
||||
amqp::AMQPDescriptorRegistory[a]->build(d).release()));
|
||||
|
||||
DBG (std::cout << std::endl << "Types in schema: " << std::endl
|
||||
<< *envelope << std::endl); // NOLINT
|
||||
}
|
||||
|
||||
CompositeFactory cf;
|
||||
|
||||
cf.process (envelope->schema());
|
||||
|
||||
auto reader = cf.byDescriptor (envelope->descriptor());
|
||||
assert (reader);
|
||||
|
||||
{
|
||||
// move to the actual blob entry in the tree - ideally we'd have
|
||||
// saved this on the Envelope but that's not easily doable as we
|
||||
// can't grab an actual copy of our data pointer
|
||||
proton::auto_enter p (d);
|
||||
pn_data_next (d);
|
||||
proton::is_list (d);
|
||||
assert (pn_data_get_list (d) == 3);
|
||||
{
|
||||
proton::auto_enter p (d);
|
||||
|
||||
// We wrap our output like this to make sure it's valid JSON to
|
||||
// facilitate easy pretty printing
|
||||
std::cout
|
||||
<< reader->dump ("{ Parsed", d, envelope->schema())->dump()
|
||||
<< " }" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
main (int argc, char **argv) {
|
||||
struct stat results { };
|
||||
|
||||
if (stat(argv[1], &results) != 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::ifstream f (argv[1], std::ios::in | std::ios::binary);
|
||||
std::array<char, 7> header { };
|
||||
f.read(header.data(), 7);
|
||||
|
||||
if (header != amqp::AMQP_HEADER) {
|
||||
std::cerr << "Bad Header in blob" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
amqp::amqp_section_id_t encoding;
|
||||
f.read((char *)&encoding, 1);
|
||||
|
||||
if (encoding == amqp::DATA_AND_STOP) {
|
||||
data_and_stop(f, results.st_size - 8);
|
||||
} else {
|
||||
std::cerr << "BAD ENCODING " << encoding << " != " << amqp::DATA_AND_STOP << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
BIN
experimental/cpp-serializer/bin/test/IntList
Normal file
BIN
experimental/cpp-serializer/bin/test/IntList
Normal file
Binary file not shown.
BIN
experimental/cpp-serializer/bin/test/IntListStringList
Normal file
BIN
experimental/cpp-serializer/bin/test/IntListStringList
Normal file
Binary file not shown.
BIN
experimental/cpp-serializer/bin/test/ListOfComposite
Normal file
BIN
experimental/cpp-serializer/bin/test/ListOfComposite
Normal file
Binary file not shown.
BIN
experimental/cpp-serializer/bin/test/ListOfComposites
Normal file
BIN
experimental/cpp-serializer/bin/test/ListOfComposites
Normal file
Binary file not shown.
BIN
experimental/cpp-serializer/bin/test/ListOfListOfComposites
Normal file
BIN
experimental/cpp-serializer/bin/test/ListOfListOfComposites
Normal file
Binary file not shown.
BIN
experimental/cpp-serializer/bin/test/ListOfListOfListOfInt
Normal file
BIN
experimental/cpp-serializer/bin/test/ListOfListOfListOfInt
Normal file
Binary file not shown.
BIN
experimental/cpp-serializer/bin/test/ListOfStringList
Normal file
BIN
experimental/cpp-serializer/bin/test/ListOfStringList
Normal file
Binary file not shown.
BIN
experimental/cpp-serializer/bin/test/OneComposite
Normal file
BIN
experimental/cpp-serializer/bin/test/OneComposite
Normal file
Binary file not shown.
BIN
experimental/cpp-serializer/bin/test/OneCompositeOneString
Normal file
BIN
experimental/cpp-serializer/bin/test/OneCompositeOneString
Normal file
Binary file not shown.
BIN
experimental/cpp-serializer/bin/test/OneInt
Normal file
BIN
experimental/cpp-serializer/bin/test/OneInt
Normal file
Binary file not shown.
BIN
experimental/cpp-serializer/bin/test/TwoIntLists
Normal file
BIN
experimental/cpp-serializer/bin/test/TwoIntLists
Normal file
Binary file not shown.
BIN
experimental/cpp-serializer/bin/test/TwoInts
Normal file
BIN
experimental/cpp-serializer/bin/test/TwoInts
Normal file
Binary file not shown.
BIN
experimental/cpp-serializer/bin/test/manyTypes
Normal file
BIN
experimental/cpp-serializer/bin/test/manyTypes
Normal file
Binary file not shown.
65
experimental/cpp-serializer/include/CompositeFactory.h
Normal file
65
experimental/cpp-serializer/include/CompositeFactory.h
Normal file
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "types.h"
|
||||
#include "amqp/schema/Schema.h"
|
||||
#include "amqp/schema/Envelope.h"
|
||||
#include "amqp/schema/Composite.h"
|
||||
#include "amqp/consumer/PropertyReader.h"
|
||||
#include "amqp/consumer/CompositeReader.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
class CompositeFactory {
|
||||
private :
|
||||
using SchemaPtr = uPtr<amqp::internal::schema::Schema>;
|
||||
using CompositePtr = uPtr<amqp::internal::schema::Composite>;
|
||||
using EnvelopePtr = uPtr<amqp::internal::schema::Envelope>;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
spStrMap_t<amqp::Reader> m_readersByType;
|
||||
spStrMap_t<amqp::Reader> m_readersByDescriptor;
|
||||
|
||||
public :
|
||||
CompositeFactory() = default;
|
||||
|
||||
void process (const SchemaPtr &);
|
||||
|
||||
const std::shared_ptr<amqp::Reader> byType (const std::string &);
|
||||
const std::shared_ptr<amqp::Reader> byDescriptor (const std::string &);
|
||||
|
||||
private :
|
||||
std::shared_ptr<amqp::Reader> process(const amqp::internal::schema::AMQPTypeNotation &);
|
||||
|
||||
std::shared_ptr<amqp::Reader>
|
||||
processComposite (const amqp::internal::schema::AMQPTypeNotation &);
|
||||
|
||||
std::shared_ptr<amqp::Reader>
|
||||
processRestricted (const amqp::internal::schema::AMQPTypeNotation &);
|
||||
|
||||
/*
|
||||
std::shared_ptr<amqp::Reader>
|
||||
process (
|
||||
amqp::internal::schema::OrderedTypeNotations::const_iterator,
|
||||
std::set<std::string> &);
|
||||
|
||||
std::shared_ptr<amqp::Reader>
|
||||
processComposite (
|
||||
amqp::internal::schema::Schema::SchemaSet::const_iterator,
|
||||
std::set<std::string> &);
|
||||
|
||||
std::shared_ptr<amqp::Reader>
|
||||
processRestricted (
|
||||
amqp::internal::schema::Schema::SchemaSet::const_iterator,
|
||||
std::set<std::string> &);
|
||||
*/
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
20
experimental/cpp-serializer/include/amqp/AMQPHeader.h
Normal file
20
experimental/cpp-serializer/include/amqp/AMQPHeader.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <array>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp {
|
||||
|
||||
/**
|
||||
* The 8th byte is used to store weather the stream is compressed or
|
||||
* not
|
||||
*/
|
||||
std::array<char, 7> AMQP_HEADER = { { 'c', 'o', 'r', 'd', 'a', 1, 0 } };
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
20
experimental/cpp-serializer/include/amqp/AMQPSectionId.h
Normal file
20
experimental/cpp-serializer/include/amqp/AMQPSectionId.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
* Once things are further along this should move into internal
|
||||
*/
|
||||
|
||||
namespace amqp {
|
||||
|
||||
enum amqp_section_id_t {
|
||||
DATA_AND_STOP = 0,
|
||||
ALT_DATA_AND_STOP = 1,
|
||||
ENCODING = 2
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
22
experimental/cpp-serializer/include/colours.h
Normal file
22
experimental/cpp-serializer/include/colours.h
Normal file
@ -0,0 +1,22 @@
|
||||
//
|
||||
// Created by Katelyn Baker on 2019-07-04.
|
||||
//
|
||||
|
||||
#ifndef BLOB_INSPECTOR_COLOURS_H
|
||||
#define BLOB_INSPECTOR_COLOURS_H
|
||||
|
||||
/* FOREGROUND */
|
||||
#define RESET "\x1B[0m"
|
||||
#define RED "\x1B[31m"
|
||||
#define GREEN "\x1B[32m"
|
||||
#define YELLOW "\x1B[33m"
|
||||
#define BLUE "\x1B[34m"
|
||||
#define MAGENTA "\x1B[35m"
|
||||
#define CYAN "\x1B[36m"
|
||||
#define WHITE "\x1B[37m"
|
||||
|
||||
|
||||
#define BOLD(x) "\x1B[1m" x RESET
|
||||
#define UNDL(x) "\x1B[4m" x RESET
|
||||
|
||||
#endif //BLOB_INSPECTOR_COLOURS_H
|
15
experimental/cpp-serializer/include/debug.h
Normal file
15
experimental/cpp-serializer/include/debug.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#define AMQP_DEBUG 0
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#if defined AMQP_DEBUG && AMQP_DEBUG >= 1
|
||||
#define DBG(X) std::cout << X
|
||||
#else
|
||||
#define DBG(X)
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
15
experimental/cpp-serializer/include/serialiser/Serialiser.h
Normal file
15
experimental/cpp-serializer/include/serialiser/Serialiser.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace serialiser {
|
||||
|
||||
class Serialiser {
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
24
experimental/cpp-serializer/include/types.h
Normal file
24
experimental/cpp-serializer/include/types.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
template<typename T>
|
||||
using uPtr = std::unique_ptr<T>;
|
||||
|
||||
template<typename T>
|
||||
using sPtr = std::shared_ptr<T>;
|
||||
|
||||
|
||||
template<typename T>
|
||||
using upStrMap_t = std::map<std::string, uPtr<T>>;
|
||||
|
||||
template<typename T>
|
||||
using spStrMap_t = std::map<std::string, sPtr<T>>;
|
||||
|
||||
/******************************************************************************/
|
||||
|
21
experimental/cpp-serializer/rem_cmake
Executable file
21
experimental/cpp-serializer/rem_cmake
Executable file
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
function cmake_rem_func {
|
||||
|
||||
rm -f $1/CMakeCache.txt
|
||||
rm $1/Makefile
|
||||
rm $1/cmake_install.cmake
|
||||
rm -rf $1/CMakeFiles
|
||||
}
|
||||
|
||||
rm -f BLOB-INSPECTOR.cbp
|
||||
|
||||
cmake_rem_func .
|
||||
cmake_rem_func ./bin
|
||||
cmake_rem_func ./src
|
||||
cmake_rem_func ./src/amqp
|
||||
cmake_rem_func ./src/amqp/test
|
||||
cmake_rem_func ./src/proton
|
||||
cmake_rem_func ./src/serialiser
|
||||
|
||||
|
1
experimental/cpp-serializer/src/.gitignore
vendored
Normal file
1
experimental/cpp-serializer/src/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
lib*.a
|
6
experimental/cpp-serializer/src/CMakeLists.txt
Normal file
6
experimental/cpp-serializer/src/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
include_directories (${BLOB-INSPECTOR_SOURCE_DIR}/src)
|
||||
|
||||
ADD_SUBDIRECTORY (proton)
|
||||
ADD_SUBDIRECTORY (amqp)
|
||||
ADD_SUBDIRECTORY (serialiser)
|
||||
|
16
experimental/cpp-serializer/src/README.md
Normal file
16
experimental/cpp-serializer/src/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Sub Dirs
|
||||
|
||||
## proton
|
||||
|
||||
C++ utility functions for the qpid-proton library and some auto objects to make working with
|
||||
the library a little nicer
|
||||
|
||||
## amqp
|
||||
|
||||
The Corda AMQP Schema represtnation, both the described versino as it exists within the
|
||||
stream and an instantiated set of C++ classes representing that structure.
|
||||
|
||||
## serialiser
|
||||
|
||||
Able to take the blob element of an Envelope and extract class data from it in a
|
||||
menainful way.
|
15
experimental/cpp-serializer/src/amqp/AMQPDescribed.h
Normal file
15
experimental/cpp-serializer/src/amqp/AMQPDescribed.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
class AMQPDescribed {
|
||||
public :
|
||||
virtual ~AMQPDescribed() { }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
54
experimental/cpp-serializer/src/amqp/AMQPDescriptor.h
Normal file
54
experimental/cpp-serializer/src/amqp/AMQPDescriptor.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "AMQPDescribed.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Forward type declarations
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
struct pn_data_t;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::AMQPDescriptor
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
class AMQPDescriptor {
|
||||
protected :
|
||||
std::string m_symbol;
|
||||
int32_t m_val;
|
||||
|
||||
public :
|
||||
AMQPDescriptor()
|
||||
: m_symbol ("ERROR")
|
||||
, m_val (-1)
|
||||
{ }
|
||||
|
||||
AMQPDescriptor(std::string symbol_, int val_)
|
||||
: m_symbol (std::move (symbol_))
|
||||
, m_val (val_)
|
||||
{ }
|
||||
|
||||
virtual ~AMQPDescriptor() = default;
|
||||
|
||||
const std::string & symbol() const { return m_symbol; }
|
||||
|
||||
void validateAndNext (pn_data_t *) const;
|
||||
|
||||
virtual std::unique_ptr<AMQPDescribed> build (pn_data_t * data_) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
26
experimental/cpp-serializer/src/amqp/CMakeLists.txt
Normal file
26
experimental/cpp-serializer/src/amqp/CMakeLists.txt
Normal file
@ -0,0 +1,26 @@
|
||||
include_directories (descriptors)
|
||||
include_directories (schema)
|
||||
include_directories (consumer)
|
||||
include_directories (.)
|
||||
|
||||
set (amqp_sources
|
||||
descriptors/AMQPDescriptors.cxx
|
||||
descriptors/AMQPDescriptorRegistory.cxx
|
||||
schema/Schema.cxx
|
||||
schema/Field.cxx
|
||||
schema/Envelope.cxx
|
||||
schema/Composite.cxx
|
||||
schema/Descriptor.cxx
|
||||
schema/restricted-types/Restricted.cxx
|
||||
schema/restricted-types/List.cxx
|
||||
schema/AMQPTypeNotation.cxx
|
||||
consumer/Reader.cxx
|
||||
consumer/PropertyReader.cxx
|
||||
consumer/RestrictedReader.cxx
|
||||
consumer/CompositeReader.cxx
|
||||
CompositeFactory.cxx
|
||||
)
|
||||
|
||||
ADD_LIBRARY ( amqp ${amqp_sources} )
|
||||
|
||||
ADD_SUBDIRECTORY (test)
|
212
experimental/cpp-serializer/src/amqp/CompositeFactory.cxx
Normal file
212
experimental/cpp-serializer/src/amqp/CompositeFactory.cxx
Normal file
@ -0,0 +1,212 @@
|
||||
#include "CompositeFactory.h"
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include "consumer/Reader.h"
|
||||
#include "consumer/PropertyReader.h"
|
||||
#include "consumer/CompositeReader.h"
|
||||
#include "consumer/RestrictedReader.h"
|
||||
|
||||
#include "schema/restricted-types/List.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template <typename T>
|
||||
std::shared_ptr<T> &
|
||||
computeIfAbsent (
|
||||
spStrMap_t<T> & map_,
|
||||
const std::string & k_,
|
||||
std::function<std::shared_ptr<T>(void)> f_
|
||||
) {
|
||||
auto it = map_.find (k_);
|
||||
|
||||
if (it == map_.end()) {
|
||||
DBG ("ComputeIfAbsent \"" << k_ << "\" - missing" << std::endl); // NOLINT
|
||||
map_[k_] = std::move (f_());
|
||||
DBG (" \"" << k_ << "\" - RTN: " << map_[k_]->name() << " : " << map_[k_]->type() << std::endl); // NOLINT
|
||||
assert (map_[k_]);
|
||||
assert (map_[k_] != nullptr);
|
||||
assert (k_ == map_[k_]->type());
|
||||
|
||||
return map_[k_];
|
||||
}
|
||||
else {
|
||||
DBG ("ComputeIfAbsent \"" << k_ << "\" - found it" << std::endl); // NOLINT
|
||||
DBG (" \"" << k_ << "\" - RTN: " << map_[k_]->name() << std::endl); // NOLINT
|
||||
|
||||
assert (it->second != nullptr);
|
||||
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* CompositeFactory
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* Walk through the types in a Schema and produce readers for them.
|
||||
*
|
||||
* We are making the large 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
|
||||
*
|
||||
*/
|
||||
void
|
||||
CompositeFactory::process (const SchemaPtr & schema_) {
|
||||
for (auto i = schema_->begin() ; i != schema_->end() ; ++i) {
|
||||
for (const auto & j : *i) {
|
||||
process(*j);
|
||||
m_readersByDescriptor[j->descriptor()] = m_readersByType[j->name()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::shared_ptr<amqp::Reader>
|
||||
CompositeFactory::process(
|
||||
const amqp::internal::schema::AMQPTypeNotation & schema_)
|
||||
{
|
||||
return computeIfAbsent<amqp::Reader> (
|
||||
m_readersByType,
|
||||
schema_.name(),
|
||||
[& schema_, this] () -> std::shared_ptr<amqp::Reader> {
|
||||
switch (schema_.type()) {
|
||||
case amqp::internal::schema::AMQPTypeNotation::Composite : {
|
||||
return processComposite(schema_);
|
||||
}
|
||||
case amqp::internal::schema::AMQPTypeNotation::Restricted : {
|
||||
return processRestricted(schema_);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::shared_ptr<amqp::Reader>
|
||||
CompositeFactory::processComposite (
|
||||
const amqp::internal::schema::AMQPTypeNotation & type_)
|
||||
{
|
||||
std::vector<std::weak_ptr<amqp::Reader>> readers;
|
||||
|
||||
const auto & fields = dynamic_cast<const amqp::internal::schema::Composite &> (
|
||||
type_).fields();
|
||||
|
||||
readers.reserve(fields.size());
|
||||
|
||||
for (const auto & field : fields) {
|
||||
DBG (" Field: " << field->name() << ": " << field->type() << std::endl); // NOLINT
|
||||
|
||||
switch (field->fieldType()) {
|
||||
case amqp::internal::schema::FieldType::PrimitiveProperty : {
|
||||
auto reader = computeIfAbsent<amqp::Reader>(
|
||||
m_readersByType,
|
||||
field->type(),
|
||||
[&field]() -> std::shared_ptr<amqp::PropertyReader> {
|
||||
return amqp::PropertyReader::make(field);
|
||||
});
|
||||
|
||||
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 amqp::internal::schema::FieldType::RestrictedProperty : {
|
||||
auto reader = m_readersByType[field->requires().front()];
|
||||
|
||||
assert (reader);
|
||||
readers.emplace_back(reader);
|
||||
assert (readers.back().lock());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert (readers.back().lock());
|
||||
}
|
||||
|
||||
return std::make_shared<amqp::CompositeReader> (type_.name(), readers);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::shared_ptr<amqp::Reader>
|
||||
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 &> (
|
||||
type_);
|
||||
|
||||
if (restricted.restrictedType() ==
|
||||
amqp::internal::schema::Restricted::RestrictedTypes::List)
|
||||
{
|
||||
const auto & list = dynamic_cast<const amqp::internal::schema::List &> (restricted);
|
||||
|
||||
DBG ("Processing List - " << list.listOf() << std::endl); // NOLINT
|
||||
|
||||
if (amqp::internal::schema::Field::typeIsPrimitive(list.listOf())) {
|
||||
DBG (" List of Primitives" << std::endl); // NOLINT
|
||||
auto reader = computeIfAbsent<amqp::Reader> (
|
||||
m_readersByType,
|
||||
list.listOf(),
|
||||
[& list] () -> std::shared_ptr<amqp::PropertyReader> {
|
||||
return amqp::PropertyReader::make (list.listOf());
|
||||
});
|
||||
|
||||
return std::make_shared<amqp::ListReader> (type_.name(), reader);
|
||||
} else {
|
||||
DBG (" List of Composite - " << list.listOf() << std::endl); // NOLINT
|
||||
auto reader = m_readersByType[list.listOf()];
|
||||
|
||||
return std::make_shared<amqp::ListReader> (list.name(), reader);
|
||||
}
|
||||
}
|
||||
|
||||
DBG (" ProcessRestricted: Returning nullptr"); // NOLINT
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::shared_ptr<amqp::Reader>
|
||||
CompositeFactory::byType (const std::string & type_) {
|
||||
auto it = m_readersByType.find (type_);
|
||||
|
||||
return (it == m_readersByType.end()) ? nullptr : it->second;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::shared_ptr<amqp::Reader>
|
||||
CompositeFactory::byDescriptor (const std::string & descriptor_) {
|
||||
auto it = m_readersByDescriptor.find (descriptor_);
|
||||
|
||||
return (it == m_readersByDescriptor.end()) ? nullptr : it->second;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,149 @@
|
||||
#include "CompositeReader.h"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
|
||||
#include <proton/codec.h>
|
||||
#include <sstream>
|
||||
#include "debug.h"
|
||||
#include "proton/proton_wrapper.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string amqp::CompositeReader::m_name { // NOLINT
|
||||
"Composite Reader"
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::
|
||||
CompositeReader::CompositeReader (
|
||||
std::string type_,
|
||||
std::vector<std::weak_ptr<amqp::Reader>> & readers_
|
||||
) : m_readers (readers_)
|
||||
, m_type (std::move (type_))
|
||||
{
|
||||
DBG ("MAKE CompositeReader: " << m_type << ": " << m_readers.size() << std::endl); // NOLINT
|
||||
for (auto reader : m_readers) {
|
||||
assert (reader.lock());
|
||||
if (auto r = reader.lock()) {
|
||||
DBG (" prop: " << r->name() << " " << r->type() << std::endl); // NOLINT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::
|
||||
CompositeReader::name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::
|
||||
CompositeReader::type() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::any
|
||||
amqp::
|
||||
CompositeReader::read (pn_data_t * data_) const {
|
||||
return std::any(1);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::
|
||||
CompositeReader::readString (pn_data_t * data_) const {
|
||||
pn_data_next (data_);
|
||||
proton::auto_enter ae (data_);
|
||||
|
||||
return "Composite";
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
std::vector<std::unique_ptr<amqp::Value>>
|
||||
amqp::
|
||||
CompositeReader::_dump (
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<amqp::internal::schema::Schema> & schema_
|
||||
) const {
|
||||
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<amqp::internal::schema::Composite &>(*(it->second.get())).fields();
|
||||
|
||||
assert (fields.size() == m_readers.size());
|
||||
|
||||
pn_data_next (data_);
|
||||
|
||||
std::vector<std::unique_ptr<amqp::Value>> read;
|
||||
read.reserve (fields.size());
|
||||
|
||||
proton::is_list (data_);
|
||||
{
|
||||
proton::auto_enter ae (data_);
|
||||
|
||||
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
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
CompositeReader::dump (
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_) const
|
||||
{
|
||||
|
||||
return std::make_unique<amqp::TypedPair<std::vector<std::unique_ptr<amqp::Value>>>> (
|
||||
name_,
|
||||
_dump(data_, schema_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
CompositeReader::dump (
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_) const
|
||||
{
|
||||
|
||||
return std::make_unique<amqp::TypedSingle<std::vector<std::unique_ptr<amqp::Value>>>> (
|
||||
_dump (data_, schema_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "Reader.h"
|
||||
|
||||
#include <any>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp {
|
||||
|
||||
class CompositeReader : public Reader {
|
||||
private :
|
||||
std::vector<std::weak_ptr<amqp::Reader>> m_readers;
|
||||
|
||||
static const std::string m_name;
|
||||
|
||||
std::string m_type;
|
||||
|
||||
std::vector<std::unique_ptr<amqp::Value>> _dump (
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<amqp::internal::schema::Schema> & schema_) const;
|
||||
|
||||
public :
|
||||
CompositeReader (
|
||||
std::string type_,
|
||||
std::vector<std::weak_ptr<amqp::Reader>> & readers_
|
||||
);
|
||||
|
||||
~CompositeReader() = default;
|
||||
|
||||
std::any read (pn_data_t *) const override;
|
||||
|
||||
std::string readString(pn_data_t *) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
const std::string &,
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &) const override;
|
||||
|
||||
const std::string & name() const override;
|
||||
const std::string & type() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
343
experimental/cpp-serializer/src/amqp/consumer/PropertyReader.cxx
Normal file
343
experimental/cpp-serializer/src/amqp/consumer/PropertyReader.cxx
Normal file
@ -0,0 +1,343 @@
|
||||
#include "PropertyReader.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
|
||||
#include <proton/codec.h>
|
||||
|
||||
#include "proton/proton_wrapper.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
std::map<std::string, std::shared_ptr<amqp::PropertyReader>(*)() > propertyMap = {
|
||||
{
|
||||
"int", []() -> std::shared_ptr<amqp::PropertyReader> {
|
||||
return std::make_shared<amqp::IntPropertyReader> ();
|
||||
}
|
||||
},
|
||||
{
|
||||
"string", []() -> std::shared_ptr<amqp::PropertyReader> {
|
||||
return std::make_shared<amqp::StringPropertyReader> (
|
||||
amqp::StringPropertyReader());
|
||||
}
|
||||
},
|
||||
{
|
||||
"boolean", []() -> std::shared_ptr<amqp::PropertyReader> {
|
||||
return std::make_shared<amqp::BoolPropertyReader> (
|
||||
amqp::BoolPropertyReader());
|
||||
}
|
||||
},
|
||||
{
|
||||
"long", []() -> std::shared_ptr<amqp::PropertyReader> {
|
||||
return std::make_shared<amqp::LongPropertyReader> (
|
||||
amqp::LongPropertyReader());
|
||||
}
|
||||
},
|
||||
{
|
||||
"double", []() -> std::shared_ptr<amqp::PropertyReader> {
|
||||
return std::make_shared<amqp::DoublePropertyReader> (
|
||||
amqp::DoublePropertyReader());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string amqp::StringPropertyReader::m_name { // NOLINT
|
||||
"String Reader"
|
||||
};
|
||||
|
||||
const std::string amqp::StringPropertyReader::m_type { // NOLINT
|
||||
"string"
|
||||
};
|
||||
|
||||
const std::string amqp::IntPropertyReader::m_name { // NOLINT
|
||||
"Int Reader"
|
||||
};
|
||||
|
||||
const std::string amqp::IntPropertyReader::m_type { // NOLINT
|
||||
"int"
|
||||
};
|
||||
|
||||
const std::string amqp::BoolPropertyReader::m_name { // NOLINT
|
||||
"Bool Reader"
|
||||
};
|
||||
|
||||
const std::string amqp::BoolPropertyReader::m_type { // NOLINT
|
||||
"bool"
|
||||
};
|
||||
|
||||
const std::string amqp::LongPropertyReader::m_name { // NOLINT
|
||||
"Long Reader"
|
||||
};
|
||||
|
||||
const std::string amqp::LongPropertyReader::m_type { // NOLINT
|
||||
"long"
|
||||
};
|
||||
|
||||
const std::string amqp::DoublePropertyReader::m_name { // NOLINT
|
||||
"Double Reader"
|
||||
};
|
||||
|
||||
const std::string amqp::DoublePropertyReader::m_type { // NOLINT
|
||||
"double"
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Static factory method
|
||||
*/
|
||||
std::shared_ptr<amqp::PropertyReader>
|
||||
amqp::
|
||||
PropertyReader::make (const FieldPtr & field_) {
|
||||
return propertyMap[field_->type()]();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::shared_ptr<amqp::PropertyReader>
|
||||
amqp::
|
||||
PropertyReader::make (const std::string & type_) {
|
||||
return propertyMap[type_]();
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* StringPropertyReader
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
std::any
|
||||
amqp::
|
||||
StringPropertyReader::read (pn_data_t * data_) const {
|
||||
return std::any ("hello");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::
|
||||
StringPropertyReader::readString (pn_data_t * data_) const {
|
||||
return proton::readAndNext<std::string> (data_);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
StringPropertyReader::dump (
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedPair<std::string>> (
|
||||
name_,
|
||||
"\"" + proton::readAndNext<std::string> (data_) + "\"");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
StringPropertyReader::dump (
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedSingle<std::string>> (
|
||||
"\"" + proton::readAndNext<std::string> (data_) + "\"");
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* IntPropertyReader
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
std::any
|
||||
amqp::
|
||||
IntPropertyReader::read (pn_data_t * data_) const {
|
||||
return std::any (1);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::
|
||||
IntPropertyReader::readString (pn_data_t * data_) const {
|
||||
return std::to_string (proton::readAndNext<int> (data_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
IntPropertyReader::dump (
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedPair<std::string>> (
|
||||
name_,
|
||||
std::to_string (proton::readAndNext<int> (data_)));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
IntPropertyReader::dump (
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedSingle<std::string>> (
|
||||
std::to_string (proton::readAndNext<int> (data_)));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* BoolPropertyReader
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
std::any
|
||||
amqp::
|
||||
BoolPropertyReader::read (pn_data_t * data_) const {
|
||||
return std::any (true);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::
|
||||
BoolPropertyReader::readString (pn_data_t * data_) const {
|
||||
return std::to_string (proton::readAndNext<bool> (data_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
BoolPropertyReader::dump (
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedPair<std::string>> (
|
||||
name_,
|
||||
std::to_string (proton::readAndNext<bool> (data_)));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
BoolPropertyReader::dump (
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedSingle<std::string>> (
|
||||
std::to_string (proton::readAndNext<bool> (data_)));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* LongPropertyReader
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
std::any
|
||||
amqp::
|
||||
LongPropertyReader::read (pn_data_t * data_) const {
|
||||
return std::any (10L);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::
|
||||
LongPropertyReader::readString (pn_data_t * data_) const {
|
||||
return std::to_string (proton::readAndNext<long> (data_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
LongPropertyReader::dump (
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedPair<std::string>> (
|
||||
name_,
|
||||
std::to_string (proton::readAndNext<long> (data_)));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
LongPropertyReader::dump (
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedSingle<std::string>> (
|
||||
std::to_string (proton::readAndNext<long> (data_)));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* DoublePropertyReader
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
std::any
|
||||
amqp::
|
||||
DoublePropertyReader::read (pn_data_t * data_) const {
|
||||
return std::any (10.0);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::
|
||||
DoublePropertyReader::readString (pn_data_t * data_) const {
|
||||
return std::to_string (proton::readAndNext<double> (data_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
DoublePropertyReader::dump (
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedPair<std::string>> (
|
||||
name_,
|
||||
std::to_string (proton::readAndNext<double> (data_)));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
DoublePropertyReader::dump (
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_) const
|
||||
{
|
||||
return std::make_unique<TypedSingle<std::string>> (
|
||||
std::to_string (proton::readAndNext<double> (data_)));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
204
experimental/cpp-serializer/src/amqp/consumer/PropertyReader.h
Normal file
204
experimental/cpp-serializer/src/amqp/consumer/PropertyReader.h
Normal file
@ -0,0 +1,204 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include "Reader.h"
|
||||
|
||||
#include "amqp/schema/Field.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp {
|
||||
|
||||
class PropertyReader : public Reader {
|
||||
private :
|
||||
using FieldPtr = std::unique_ptr<internal::schema::Field>;
|
||||
|
||||
public :
|
||||
/**
|
||||
* Static Factory method for creating appropriate derived types
|
||||
*/
|
||||
static std::shared_ptr<PropertyReader> make (const FieldPtr &);
|
||||
static std::shared_ptr<PropertyReader> make (const std::string &);
|
||||
|
||||
~PropertyReader() override = default;
|
||||
|
||||
std::string readString(pn_data_t *) const override = 0;
|
||||
|
||||
std::any read (pn_data_t *) const override = 0;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
const std::string &,
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &
|
||||
) const override = 0;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &
|
||||
) const override = 0;
|
||||
|
||||
const std::string & name() const override = 0;
|
||||
|
||||
const std::string & type() const override = 0;
|
||||
};
|
||||
|
||||
|
||||
class StringPropertyReader : public PropertyReader {
|
||||
private :
|
||||
static const std::string m_name;
|
||||
static const std::string m_type;
|
||||
|
||||
public :
|
||||
std::string readString (pn_data_t *) const override;
|
||||
|
||||
std::any read (pn_data_t *) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
const std::string &,
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &
|
||||
) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &
|
||||
) const override;
|
||||
|
||||
const std::string & name() const override {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const std::string & type() const override {
|
||||
return m_type;
|
||||
}
|
||||
};
|
||||
|
||||
class IntPropertyReader : public PropertyReader {
|
||||
private :
|
||||
static const std::string m_name;
|
||||
static const std::string m_type;
|
||||
|
||||
public :
|
||||
~IntPropertyReader() override = default;
|
||||
|
||||
std::string readString (pn_data_t *) const override;
|
||||
|
||||
std::any read (pn_data_t *) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
const std::string &,
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &
|
||||
) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &
|
||||
) const override;
|
||||
|
||||
const std::string & name() const override {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const std::string & type() const override {
|
||||
return m_type;
|
||||
}
|
||||
};
|
||||
|
||||
class BoolPropertyReader : public PropertyReader {
|
||||
private :
|
||||
static const std::string m_name;
|
||||
static const std::string m_type;
|
||||
|
||||
public :
|
||||
std::string readString (pn_data_t *) const override;
|
||||
|
||||
std::any read (pn_data_t *) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
const std::string &,
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &
|
||||
) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &
|
||||
) const override;
|
||||
|
||||
const std::string & name() const override {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const std::string & type() const override {
|
||||
return m_type;
|
||||
}
|
||||
};
|
||||
|
||||
class LongPropertyReader : public PropertyReader {
|
||||
private :
|
||||
static const std::string m_name;
|
||||
static const std::string m_type;
|
||||
|
||||
public :
|
||||
std::string readString (pn_data_t *) const override;
|
||||
|
||||
std::any read (pn_data_t *) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
const std::string &,
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &
|
||||
) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &
|
||||
) const override;
|
||||
|
||||
const std::string & name() const override {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const std::string & type() const override {
|
||||
return m_type;
|
||||
}
|
||||
};
|
||||
|
||||
class DoublePropertyReader : public PropertyReader {
|
||||
private :
|
||||
static const std::string m_name;
|
||||
static const std::string m_type;
|
||||
|
||||
public :
|
||||
std::string readString (pn_data_t *) const override;
|
||||
|
||||
std::any read (pn_data_t *) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
const std::string &,
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &
|
||||
) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &
|
||||
) const override;
|
||||
|
||||
const std::string & name() const override {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const std::string & type() const override {
|
||||
return m_type;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
136
experimental/cpp-serializer/src/amqp/consumer/Reader.cxx
Normal file
136
experimental/cpp-serializer/src/amqp/consumer/Reader.cxx
Normal file
@ -0,0 +1,136 @@
|
||||
#include "Reader.h"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
struct AutoMap {
|
||||
std::stringstream & m_stream;
|
||||
|
||||
AutoMap (const std::string & s, std::stringstream & stream_) : m_stream (stream_) {
|
||||
m_stream << s << " : { ";
|
||||
}
|
||||
|
||||
AutoMap (std::stringstream & stream_) : m_stream (stream_) {
|
||||
m_stream << "{ ";
|
||||
}
|
||||
|
||||
~AutoMap() {
|
||||
m_stream << " }";
|
||||
}
|
||||
};
|
||||
|
||||
struct AutoList {
|
||||
std::stringstream & m_stream;
|
||||
|
||||
AutoList (const std::string & s, std::stringstream & stream_) : m_stream (stream_) {
|
||||
m_stream << s << " : [ ";
|
||||
}
|
||||
|
||||
AutoList (std::stringstream & stream_) : m_stream (stream_) {
|
||||
m_stream << "[ ";
|
||||
}
|
||||
|
||||
~AutoList() {
|
||||
m_stream << " ]";
|
||||
}
|
||||
};
|
||||
|
||||
template<class Auto, class T>
|
||||
std::string
|
||||
dumpPair(const std::string & name_, const T & begin_, const T & end_) {
|
||||
std::stringstream rtn;
|
||||
{
|
||||
Auto am (name_, rtn);
|
||||
|
||||
rtn << (*(begin_))->dump();
|
||||
for (auto it(std::next(begin_)) ; it != end_; ++it) {
|
||||
rtn << ", " << (*it)->dump();
|
||||
}
|
||||
}
|
||||
|
||||
return rtn.str();
|
||||
}
|
||||
|
||||
template<class Auto, class T>
|
||||
std::string
|
||||
dumpSingle(const T & begin_, const T & end_) {
|
||||
std::stringstream rtn;
|
||||
{
|
||||
Auto am (rtn);
|
||||
|
||||
rtn << (*(begin_))->dump();
|
||||
for (auto it(std::next(begin_)) ; it != end_; ++it) {
|
||||
rtn << ", " << (*it)->dump();
|
||||
}
|
||||
}
|
||||
|
||||
return rtn.str();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedPair<std::vector<std::unique_ptr<amqp::Pair>>>::dump() const {
|
||||
return ::dumpPair<AutoMap> (m_property, m_value.begin(), m_value.end());
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedPair<std::list<std::unique_ptr<amqp::Pair>>>::dump() const {
|
||||
return ::dumpPair<AutoMap> (m_property, m_value.begin(), m_value.end());
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedPair<std::vector<std::unique_ptr<amqp::Value>>>::dump() const {
|
||||
return ::dumpPair<AutoMap> (m_property, m_value.begin(), m_value.end());
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedPair<std::list<std::unique_ptr<amqp::Value>>>::dump() const {
|
||||
return ::dumpPair<AutoList> (m_property, m_value.begin(), m_value.end());
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedSingle<std::list<std::unique_ptr<amqp::Value>>>::dump() const {
|
||||
return ::dumpSingle<AutoList> (m_value.begin(), m_value.end());
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedSingle<std::vector<std::unique_ptr<amqp::Value>>>::dump() const {
|
||||
return ::dumpSingle<AutoMap> (m_value.begin(), m_value.end());
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedSingle<std::list<std::unique_ptr<amqp::Single>>>::dump() const {
|
||||
return ::dumpSingle<AutoList> (m_value.begin(), m_value.end());
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedSingle<std::vector<std::unique_ptr<amqp::Single>>>::dump() const {
|
||||
return ::dumpSingle<AutoMap> (m_value.begin(), m_value.end());
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
211
experimental/cpp-serializer/src/amqp/consumer/Reader.h
Normal file
211
experimental/cpp-serializer/src/amqp/consumer/Reader.h
Normal file
@ -0,0 +1,211 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <any>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "schema/Schema.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct pn_data_t;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp {
|
||||
|
||||
class Value {
|
||||
public :
|
||||
virtual std::string dump() const = 0;
|
||||
|
||||
virtual ~Value() = default;
|
||||
};
|
||||
|
||||
class Single : public Value {
|
||||
public :
|
||||
std::string dump() const override = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class TypedSingle : public Single {
|
||||
private:
|
||||
T m_value;
|
||||
|
||||
public:
|
||||
explicit TypedSingle (const T & value_)
|
||||
: Single()
|
||||
, m_value (value_)
|
||||
{ }
|
||||
|
||||
explicit TypedSingle (T && value_)
|
||||
: Single()
|
||||
, m_value { std::move (value_) }
|
||||
{ }
|
||||
|
||||
TypedSingle (const TypedSingle && value_) noexcept
|
||||
: Single()
|
||||
, m_value { std::move (value_.m_value) }
|
||||
{ }
|
||||
|
||||
const T & value() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
std::string dump() const override;
|
||||
};
|
||||
|
||||
class Pair : public Value {
|
||||
protected :
|
||||
std::string m_property;
|
||||
|
||||
public:
|
||||
explicit Pair(const std::string & property_)
|
||||
: m_property (property_)
|
||||
{ }
|
||||
|
||||
virtual ~Pair() = default;
|
||||
|
||||
Pair (amqp::Pair && pair_) noexcept
|
||||
: m_property (std::move (pair_.m_property))
|
||||
{ }
|
||||
|
||||
std::string dump() const override = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class TypedPair : public Pair {
|
||||
private:
|
||||
T m_value;
|
||||
|
||||
public:
|
||||
TypedPair (const std::string & property_, T & value_)
|
||||
: Pair (property_)
|
||||
, m_value (value_)
|
||||
{ }
|
||||
|
||||
TypedPair (const std::string & property_, T && value_)
|
||||
: Pair (property_)
|
||||
, m_value (std::move (value_))
|
||||
{ }
|
||||
|
||||
TypedPair (TypedPair && pair_)
|
||||
: Pair (std::move (pair_.m_property))
|
||||
, m_value (std::move (pair_.m_value))
|
||||
{ }
|
||||
|
||||
const T & value() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
std::string dump() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::TypeSingle
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
template<typename T>
|
||||
inline std::string
|
||||
amqp::TypedSingle<T>::dump() const {
|
||||
return std::to_string(m_value);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline std::string
|
||||
amqp::TypedSingle<std::string>::dump() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedSingle<std::vector<std::unique_ptr<amqp::Value>>>::dump() const;
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedSingle<std::list<std::unique_ptr<amqp::Value>>>::dump() const;
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedSingle<std::vector<std::unique_ptr<amqp::Single>>>::dump() const;
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedSingle<std::list<std::unique_ptr<amqp::Single>>>::dump() const;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::TypedPair
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
template<typename T>
|
||||
inline std::string
|
||||
amqp::TypedPair<T>::dump() const {
|
||||
return m_property + " : " + std::to_string (m_value);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline std::string
|
||||
amqp::TypedPair<std::string>::dump() const {
|
||||
return m_property + " : " + m_value;
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedPair<std::vector<std::unique_ptr<amqp::Value>>>::dump() const;
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedPair<std::list<std::unique_ptr<amqp::Value>>>::dump() const;
|
||||
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedPair<std::vector<std::unique_ptr<amqp::Pair>>>::dump() const;
|
||||
|
||||
template<>
|
||||
std::string
|
||||
amqp::TypedPair<std::list<std::unique_ptr<amqp::Pair>>>::dump() const;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp {
|
||||
|
||||
class Reader {
|
||||
public :
|
||||
virtual ~Reader() = default;
|
||||
virtual const std::string & name() const = 0;
|
||||
virtual const std::string & type() const = 0;
|
||||
|
||||
virtual std::any read(pn_data_t *) const = 0;
|
||||
virtual std::string readString(pn_data_t *) const = 0;
|
||||
|
||||
virtual std::unique_ptr<Value> dump(
|
||||
const std::string &,
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &) const = 0;
|
||||
|
||||
virtual std::unique_ptr<Value> dump(
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -0,0 +1,116 @@
|
||||
#include "RestrictedReader.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "proton/proton_wrapper.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string amqp::RestrictedReader::m_name { // NOLINT
|
||||
"Restricted Reader"
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::any
|
||||
amqp::
|
||||
RestrictedReader::read(pn_data_t *) const {
|
||||
return std::any(1);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::
|
||||
RestrictedReader::readString(pn_data_t * data_) const {
|
||||
return "hello";
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::list<std::unique_ptr<amqp::Value>>
|
||||
amqp::
|
||||
ListReader::dump_(
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_
|
||||
) const {
|
||||
proton::is_described (data_);
|
||||
|
||||
std::list<std::unique_ptr<amqp::Value>> read;
|
||||
|
||||
{
|
||||
proton::auto_enter ae (data_);
|
||||
auto it = 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;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
ListReader::dump (
|
||||
const std::string & name_,
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_
|
||||
) const {
|
||||
proton::auto_next an (data_);
|
||||
|
||||
return std::make_unique<amqp::TypedPair<std::list<std::unique_ptr<amqp::Value>>>>(
|
||||
name_,
|
||||
dump_ (data_, schema_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::Value>
|
||||
amqp::
|
||||
ListReader::dump(
|
||||
pn_data_t * data_,
|
||||
const std::unique_ptr<internal::schema::Schema> & schema_
|
||||
) const {
|
||||
proton::auto_next an (data_);
|
||||
|
||||
return std::make_unique<amqp::TypedSingle<std::list<std::unique_ptr<amqp::Value>>>>(
|
||||
dump_ (data_, schema_));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::
|
||||
RestrictedReader::name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::
|
||||
RestrictedReader::type() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::schema::Restricted::RestrictedTypes
|
||||
amqp::
|
||||
ListReader::restrictedType() const {
|
||||
return internal::schema::Restricted::RestrictedTypes::List;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "Reader.h"
|
||||
|
||||
#include <any>
|
||||
#include <vector>
|
||||
|
||||
#include "amqp/schema/restricted-types/Restricted.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct pn_data_t;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp {
|
||||
|
||||
class RestrictedReader : public Reader {
|
||||
private :
|
||||
static const std::string m_name;
|
||||
const std::string m_type;
|
||||
|
||||
public :
|
||||
RestrictedReader (const std::string & type_)
|
||||
: m_type (type_)
|
||||
{ }
|
||||
|
||||
~RestrictedReader() = default;
|
||||
|
||||
std::any read(pn_data_t *) const override ;
|
||||
|
||||
std::string readString(pn_data_t *) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
const std::string &,
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &) const override = 0;
|
||||
|
||||
const std::string & name() const override;
|
||||
const std::string & type() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp {
|
||||
|
||||
class ListReader : public RestrictedReader {
|
||||
private :
|
||||
// How to read the underlying types
|
||||
std::weak_ptr<amqp::Reader> m_reader;
|
||||
|
||||
std::list<std::unique_ptr<amqp::Value>> dump_(
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &) const;
|
||||
|
||||
public :
|
||||
ListReader (
|
||||
const std::string & type_,
|
||||
std::weak_ptr<amqp::Reader> reader_
|
||||
) : RestrictedReader (type_)
|
||||
, m_reader (reader_)
|
||||
{ }
|
||||
|
||||
~ListReader() final = default;
|
||||
|
||||
internal::schema::Restricted::RestrictedTypes restrictedType() const;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
const std::string &,
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &) const override;
|
||||
|
||||
std::unique_ptr<Value> dump(
|
||||
pn_data_t *,
|
||||
const std::unique_ptr<internal::schema::Schema> &) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -0,0 +1,161 @@
|
||||
#include "AMQPDescriptorRegistory.h"
|
||||
#include "AMQPDescriptors.h"
|
||||
|
||||
#include <limits>
|
||||
#include <climits>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp {
|
||||
namespace internal {
|
||||
|
||||
|
||||
const uint64_t DESCRIPTOR_TOP_32BITS = 0xc562L << (32 + 16);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp {
|
||||
namespace 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 = {
|
||||
{
|
||||
1L | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::EnvelopeDescriptor> (
|
||||
internal::EnvelopeDescriptor (
|
||||
"ENVELOPE",
|
||||
internal::ENVELOPE))
|
||||
},
|
||||
{
|
||||
2L | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::SchemaDescriptor> (
|
||||
internal::SchemaDescriptor (
|
||||
"SCHEMA",
|
||||
internal::SCHEMA))
|
||||
},
|
||||
{
|
||||
3L | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::ObjectDescriptor> (
|
||||
internal::ObjectDescriptor (
|
||||
"OBJECT_DESCRIPTOR",
|
||||
internal::OBJECT))
|
||||
},
|
||||
{
|
||||
4L | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::FieldDescriptor> (
|
||||
internal::FieldDescriptor (
|
||||
"FIELD",
|
||||
internal::FIELD))
|
||||
},
|
||||
{
|
||||
5L | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::CompositeDescriptor> (
|
||||
internal::CompositeDescriptor (
|
||||
"COMPOSITE_TYPE",
|
||||
internal::COMPOSITE_TYPE))
|
||||
},
|
||||
{
|
||||
6L | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::RestrictedDescriptor> (
|
||||
internal::RestrictedDescriptor (
|
||||
"RESTRICTED_TYPE",
|
||||
internal::RESTRICTED_TYPE))
|
||||
},
|
||||
{
|
||||
7L | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::ChoiceDescriptor> (
|
||||
internal::ChoiceDescriptor (
|
||||
"CHOICE",
|
||||
internal::CHOICE))
|
||||
},
|
||||
{
|
||||
8L | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::ReferencedObjectDescriptor> (
|
||||
internal::ReferencedObjectDescriptor (
|
||||
"REFERENCED_OBJECT",
|
||||
internal::REFERENCED_OBJECT))
|
||||
},
|
||||
{
|
||||
9L | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::TransformSchemaDescriptor> (
|
||||
internal::TransformSchemaDescriptor (
|
||||
"TRANSFORM_SCHEMA",
|
||||
internal::TRANSFORM_SCHEMA))
|
||||
},
|
||||
{
|
||||
10L | internal::DESCRIPTOR_TOP_32BITS,
|
||||
std::make_shared<internal::TransformElementDescriptor> (
|
||||
internal::TransformElementDescriptor (
|
||||
"TRANSFORM_ELEMENT",
|
||||
internal::TRANSFORM_ELEMENT))
|
||||
},
|
||||
{
|
||||
11L | 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 (1L | internal::DESCRIPTOR_TOP_32BITS) : return "ENVELOPE";
|
||||
case (2L | internal::DESCRIPTOR_TOP_32BITS) : return "SCHEMA";
|
||||
case (3L | internal::DESCRIPTOR_TOP_32BITS) : return "OBJECT_DESCRIPTOR";
|
||||
case (4L | internal::DESCRIPTOR_TOP_32BITS) : return "FIELD";
|
||||
case (5L | internal::DESCRIPTOR_TOP_32BITS) : return "COMPOSITE_TYPE";
|
||||
case (6L | internal::DESCRIPTOR_TOP_32BITS) : return "RESTRICTED_TYPE";
|
||||
case (7L | internal::DESCRIPTOR_TOP_32BITS) : return "CHOICE";
|
||||
case (8L | internal::DESCRIPTOR_TOP_32BITS) : return "REFERENCED_OBJECT";
|
||||
case (9L | internal::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_SCHEMA";
|
||||
case (10L | internal::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_ELEMENT";
|
||||
case (11L | internal::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_ELEMENT_KEY";
|
||||
default : return "UNKNOWN";
|
||||
};
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
amqp::describedToString(uint32_t val_) {
|
||||
return describedToString(val_ | internal::DESCRIPTOR_TOP_32BITS);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "amqp/AMQPDescriptor.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
extern std::map<uint64_t, std::shared_ptr<internal::AMQPDescriptor>> AMQPDescriptorRegistory;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Some basic utlility functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp {
|
||||
|
||||
/**
|
||||
* the top 32 bits of a Corda AMQP descriptor is the assigned CORDA identifier.
|
||||
*
|
||||
* Utility function to strip that off and return a simple integer that maps
|
||||
* to our described types.
|
||||
*/
|
||||
uint32_t stripCorda (uint64_t id);
|
||||
|
||||
std::string describedToString(uint64_t);
|
||||
std::string describedToString(uint32_t);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -0,0 +1,398 @@
|
||||
#include "AMQPDescriptors.h"
|
||||
#include "AMQPDescriptorRegistory.h"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <proton/types.h>
|
||||
#include <proton/codec.h>
|
||||
#include "colours.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "Field.h"
|
||||
#include "Schema.h"
|
||||
#include "Envelope.h"
|
||||
#include "Composite.h"
|
||||
#include "amqp/schema/restricted-types/Restricted.h"
|
||||
#include "amqp/schema/OrderedTypeNotations.h"
|
||||
#include "AMQPDescribed.h"
|
||||
|
||||
#include "proton/proton_wrapper.h"
|
||||
#include "AMQPDescriptorRegistory.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Look up a described type by its ID in the AMQPDescriptorRegistory and
|
||||
* return the coresponding schema type. Specialised below to avoid
|
||||
* the cast and re-owning of the unigue pointer when we're happy
|
||||
* with a simple std::unique_ptr<AMQPDescribed>
|
||||
*/
|
||||
template<class T>
|
||||
std::unique_ptr<T>
|
||||
dispatchDescribed (pn_data_t * data_) {
|
||||
proton::is_described(data_);
|
||||
proton::auto_enter p (data_);
|
||||
proton::is_ulong(data_);
|
||||
|
||||
auto id = pn_data_get_ulong(data_);
|
||||
|
||||
return std::unique_ptr<T> (
|
||||
static_cast<T *>(amqp::AMQPDescriptorRegistory[id]->build(data_).release()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
amqp::internal::
|
||||
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)))
|
||||
{
|
||||
throw std::runtime_error ("Invalid Type");
|
||||
}
|
||||
|
||||
pn_data_next(data_);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace {
|
||||
const std::string
|
||||
consumeBlob (pn_data_t * data_) {
|
||||
proton::is_described (data_);
|
||||
proton::auto_enter p (data_);
|
||||
return proton::get_symbol<std::string> (data_);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::EnvelopeDescriptor
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::internal::AMQPDescribed>
|
||||
amqp::internal::
|
||||
EnvelopeDescriptor::build(pn_data_t * data_) const {
|
||||
DBG ("ENVELOPE" << std::endl); // NOLINT
|
||||
|
||||
validateAndNext(data_);
|
||||
|
||||
proton::auto_enter p (data_);
|
||||
|
||||
/*
|
||||
* The actual blob... if this was java we would use the type symbols
|
||||
* in the blob to look up serialisers in the cache... but we don't
|
||||
* have any so we are actually going to need to use the schema
|
||||
* which we parse *after* this to be able to read any data!
|
||||
*/
|
||||
std::string outerType = consumeBlob(data_);
|
||||
|
||||
pn_data_next (data_);
|
||||
|
||||
/*
|
||||
* The scehama
|
||||
*/
|
||||
auto schema = dispatchDescribed<schema::Schema> (data_);
|
||||
|
||||
pn_data_next(data_);
|
||||
|
||||
/*
|
||||
* The transforms schema
|
||||
*/
|
||||
// Skip for now
|
||||
// dispatchDescribed (data_);
|
||||
|
||||
return std::make_unique<schema::Envelope> (schema::Envelope (schema, outerType));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::internal::AMQPDescribed>
|
||||
amqp::internal::
|
||||
SchemaDescriptor::build(pn_data_t * data_) const {
|
||||
DBG ("SCHEMA" << std::endl); // NOLINT
|
||||
|
||||
validateAndNext(data_);
|
||||
|
||||
schema::OrderedTypeNotations<schema::AMQPTypeNotation> schemas;
|
||||
|
||||
/*
|
||||
* The Schema is stored as a list of lists of described objects
|
||||
*/
|
||||
{
|
||||
proton::auto_list_enter ale (data_);
|
||||
|
||||
for (int i { 1 } ; pn_data_next(data_) ; ++i) {
|
||||
DBG (" " << i << "/" << ale.elements() << std::endl); // NOLINT
|
||||
proton::auto_list_enter ale2 (data_);
|
||||
while (pn_data_next(data_)) {
|
||||
schemas.insert (dispatchDescribed<schema::AMQPTypeNotation>(data_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_unique<schema::Schema> (std::move (schemas));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::ObjectDescriptor
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
std::unique_ptr<amqp::internal::AMQPDescribed>
|
||||
amqp::internal::
|
||||
ObjectDescriptor::build(pn_data_t * data_) const {
|
||||
DBG ("DESCRIPTOR" << std::endl); // NOLINT
|
||||
|
||||
validateAndNext(data_);
|
||||
|
||||
proton::auto_enter p (data_);
|
||||
|
||||
auto symbol = proton::get_symbol<std::string> (data_);
|
||||
|
||||
return std::make_unique<schema::Descriptor> (symbol);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::FieldDescriptor
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::internal::AMQPDescribed>
|
||||
amqp::internal::
|
||||
FieldDescriptor::build(pn_data_t * data_) const {
|
||||
DBG ("FIELD" << std::endl); // NOLINT
|
||||
|
||||
validateAndNext(data_);
|
||||
|
||||
proton::auto_enter ae (data_);
|
||||
|
||||
/* name: String */
|
||||
auto name = proton::get_string(data_);
|
||||
|
||||
pn_data_next(data_);
|
||||
|
||||
/* type: String */
|
||||
auto type = proton::get_string(data_);
|
||||
|
||||
pn_data_next(data_);
|
||||
|
||||
/* requires: List<String> */
|
||||
std::list<std::string> requires;
|
||||
{
|
||||
proton::auto_list_enter ale (data_);
|
||||
while (pn_data_next(data_)) {
|
||||
requires.push_back (proton::get_string(data_));
|
||||
}
|
||||
}
|
||||
|
||||
pn_data_next(data_);
|
||||
|
||||
/* default: String? */
|
||||
auto def = proton::get_string(data_, true);
|
||||
|
||||
pn_data_next(data_);
|
||||
|
||||
/* label: String? */
|
||||
auto label = proton::get_string(data_, true);
|
||||
|
||||
pn_data_next(data_);
|
||||
|
||||
/* mandatory: Boolean - copes with the Kotlin concept of nullability.
|
||||
If something is mandatory then it cannot be null */
|
||||
auto mandatory = proton::get_boolean(data_);
|
||||
|
||||
pn_data_next(data_);
|
||||
|
||||
/* multiple: Boolean */
|
||||
auto multiple = proton::get_boolean(data_);
|
||||
|
||||
return std::make_unique<schema::Field> (name, type, requires, def, label,
|
||||
mandatory, multiple);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::CompositeDescriptor
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::internal::AMQPDescribed>
|
||||
amqp::internal::
|
||||
CompositeDescriptor::build(pn_data_t * data_) const {
|
||||
DBG ("COMPOSITE" << std::endl); // NOLINT
|
||||
|
||||
validateAndNext(data_);
|
||||
|
||||
proton::auto_enter p (data_);
|
||||
|
||||
/* Class Name - String */
|
||||
auto name = proton::get_string(data_);
|
||||
|
||||
pn_data_next(data_);
|
||||
|
||||
/* Label Name - Nullable String */
|
||||
auto label = proton::get_string(data_, true);
|
||||
|
||||
pn_data_next(data_);
|
||||
|
||||
/* provides: List<String> */
|
||||
std::list<std::string> provides;
|
||||
{
|
||||
proton::auto_list_enter p2 (data_);
|
||||
while (pn_data_next(data_)) {
|
||||
provides.push_back (proton::get_string (data_));
|
||||
}
|
||||
}
|
||||
|
||||
pn_data_next(data_);
|
||||
|
||||
/* descriptor: Descriptor */
|
||||
auto descriptor = dispatchDescribed<schema::Descriptor>(data_);
|
||||
|
||||
pn_data_next(data_);
|
||||
|
||||
/* fields: List<Described>*/
|
||||
std::vector<std::unique_ptr<schema::Field>> fields;
|
||||
fields.reserve (pn_data_get_list (data_));
|
||||
{
|
||||
proton::auto_list_enter p2 (data_);
|
||||
while (pn_data_next(data_)) {
|
||||
fields.emplace_back (dispatchDescribed<schema::Field>(data_));
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_unique<schema::Composite> (
|
||||
schema::Composite (name, label, provides, descriptor, fields));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Restricted types represent lists and maps
|
||||
*
|
||||
* NOTE: The Corda serialization scheme doesn't support all container classes
|
||||
* as it has the requiremnt that iteration order be deterministic for purposes
|
||||
* of signing over data.
|
||||
*
|
||||
* name : String
|
||||
* label : String?
|
||||
* provides : List<String>
|
||||
* source : String
|
||||
* descriptor : Descriptor
|
||||
* choices : List<Choice>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::internal::AMQPDescribed>
|
||||
amqp::internal::
|
||||
RestrictedDescriptor::build(pn_data_t * data_) const {
|
||||
DBG ("RESTRICTED" << std::endl); // NOLINT
|
||||
validateAndNext(data_);
|
||||
|
||||
proton::auto_enter ae (data_);
|
||||
|
||||
auto name = proton::readAndNext<std::string>(data_);
|
||||
auto label = proton::readAndNext<std::string>(data_, true);
|
||||
|
||||
std::vector<std::string> provides;
|
||||
{
|
||||
proton::auto_list_enter ae2 (data_);
|
||||
while (pn_data_next(data_)) {
|
||||
provides.push_back (proton::get_string (data_));
|
||||
}
|
||||
}
|
||||
|
||||
pn_data_next (data_);
|
||||
|
||||
auto source = proton::readAndNext<std::string>(data_);
|
||||
auto descriptor = dispatchDescribed<schema::Descriptor>(data_);
|
||||
|
||||
// SKIP the choices section **FOR NOW**
|
||||
|
||||
return schema::Restricted::make (descriptor, name,
|
||||
label, provides, source);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Essentially, an enum.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::internal::AMQPDescribed>
|
||||
amqp::internal::
|
||||
ChoiceDescriptor::build(pn_data_t * data_) const {
|
||||
validateAndNext(data_);
|
||||
|
||||
DBG ("CHOICE " << data_ << std::endl); // NOLINT
|
||||
|
||||
return std::unique_ptr<amqp::internal::AMQPDescribed> (nullptr);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::internal::AMQPDescribed>
|
||||
amqp::internal::
|
||||
ReferencedObjectDescriptor::build(pn_data_t * data_) const {
|
||||
validateAndNext(data_);
|
||||
|
||||
DBG ("REFERENCED OBJECT " << data_ << std::endl); // NOLINT
|
||||
|
||||
return std::unique_ptr<amqp::internal::AMQPDescribed> (nullptr);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::internal::AMQPDescribed>
|
||||
amqp::internal::
|
||||
TransformSchemaDescriptor::build(pn_data_t * data_) const {
|
||||
validateAndNext(data_);
|
||||
|
||||
DBG ("TRANSFORM SCHEMA " << data_ << std::endl); // NOLINT
|
||||
|
||||
return std::unique_ptr<amqp::internal::AMQPDescribed> (nullptr);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::internal::AMQPDescribed>
|
||||
amqp::internal::
|
||||
TransformElementDescriptor::build(pn_data_t * data_) const {
|
||||
validateAndNext(data_);
|
||||
|
||||
DBG ("TRANSFORM ELEMENT " << data_ << std::endl); // NOLINT
|
||||
|
||||
return std::unique_ptr<amqp::internal::AMQPDescribed> (nullptr);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::unique_ptr<amqp::internal::AMQPDescribed>
|
||||
amqp::internal::
|
||||
TransformElementKeyDescriptor::build(pn_data_t * data_) const {
|
||||
validateAndNext(data_);
|
||||
|
||||
DBG ("TRANSFORM ELEMENT KEY" << data_ << std::endl); // NOLINT
|
||||
|
||||
return std::unique_ptr<amqp::internal::AMQPDescribed> (nullptr);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,228 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
#include "amqp/AMQPDescriptor.h"
|
||||
#include "amqp/schema/Descriptor.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct pn_data_t;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp:: internal {
|
||||
|
||||
class EnvelopeDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
EnvelopeDescriptor() : AMQPDescriptor() { }
|
||||
|
||||
EnvelopeDescriptor(const std::string & symbol_, int val_)
|
||||
: AMQPDescriptor(symbol_, val_)
|
||||
{ }
|
||||
|
||||
~EnvelopeDescriptor() final = default;
|
||||
|
||||
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
class SchemaDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
SchemaDescriptor() : AMQPDescriptor() { }
|
||||
|
||||
SchemaDescriptor(const std::string & symbol_, int val_)
|
||||
: AMQPDescriptor(symbol_, val_)
|
||||
{ }
|
||||
|
||||
~SchemaDescriptor() final = default;
|
||||
|
||||
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
class ObjectDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
ObjectDescriptor() : AMQPDescriptor() { }
|
||||
|
||||
ObjectDescriptor(const std::string & symbol_, int val_)
|
||||
: AMQPDescriptor(symbol_, val_)
|
||||
{ }
|
||||
|
||||
~ObjectDescriptor() final = default;
|
||||
|
||||
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
class FieldDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
FieldDescriptor() : AMQPDescriptor() { }
|
||||
|
||||
FieldDescriptor(const std::string & symbol_, int val_)
|
||||
: AMQPDescriptor(symbol_, val_)
|
||||
{ }
|
||||
|
||||
~FieldDescriptor() final = default;
|
||||
|
||||
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
class CompositeDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
CompositeDescriptor() : AMQPDescriptor() { }
|
||||
|
||||
CompositeDescriptor(const std::string & symbol_, int val_)
|
||||
: AMQPDescriptor(symbol_, val_)
|
||||
{ }
|
||||
|
||||
~CompositeDescriptor() final = default;
|
||||
|
||||
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
class RestrictedDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
RestrictedDescriptor() : AMQPDescriptor() { }
|
||||
|
||||
RestrictedDescriptor(const std::string & symbol_, int val_)
|
||||
: AMQPDescriptor(symbol_, val_)
|
||||
{ }
|
||||
|
||||
~RestrictedDescriptor() final = default;
|
||||
|
||||
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
class ChoiceDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
ChoiceDescriptor() : AMQPDescriptor() { }
|
||||
|
||||
ChoiceDescriptor(const std::string & symbol_, int val_)
|
||||
: AMQPDescriptor(symbol_, val_)
|
||||
{ }
|
||||
|
||||
~ChoiceDescriptor() final = default;
|
||||
|
||||
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
class ReferencedObjectDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
ReferencedObjectDescriptor() : AMQPDescriptor() { }
|
||||
|
||||
ReferencedObjectDescriptor(const std::string & symbol_, int val_)
|
||||
: AMQPDescriptor(symbol_, val_)
|
||||
{ }
|
||||
|
||||
~ReferencedObjectDescriptor() final = default;
|
||||
|
||||
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
class TransformSchemaDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
TransformSchemaDescriptor() : AMQPDescriptor() { }
|
||||
|
||||
TransformSchemaDescriptor(const std::string & symbol_, int val_)
|
||||
: AMQPDescriptor(symbol_, val_)
|
||||
{ }
|
||||
|
||||
~TransformSchemaDescriptor() final = default;
|
||||
|
||||
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
class TransformElementDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
TransformElementDescriptor() : AMQPDescriptor() { }
|
||||
|
||||
TransformElementDescriptor(const std::string & symbol_, int val_)
|
||||
: AMQPDescriptor(symbol_, val_)
|
||||
{ }
|
||||
|
||||
~TransformElementDescriptor() final = default;
|
||||
|
||||
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal {
|
||||
|
||||
class TransformElementKeyDescriptor : public AMQPDescriptor {
|
||||
public :
|
||||
TransformElementKeyDescriptor() : AMQPDescriptor() { }
|
||||
|
||||
TransformElementKeyDescriptor(const std::string & symbol_, int val_)
|
||||
: AMQPDescriptor(symbol_, val_)
|
||||
{ }
|
||||
|
||||
~TransformElementKeyDescriptor() final = default;
|
||||
|
||||
std::unique_ptr<AMQPDescribed> build (pn_data_t *) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,62 @@
|
||||
#include <iostream>
|
||||
#include "AMQPTypeNotation.h"
|
||||
|
||||
#include "colours.h"
|
||||
|
||||
#include "Composite.h"
|
||||
#include "amqp/schema/restricted-types/Restricted.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
/**
|
||||
* Provide nice mechanism by which Composite and Restricted types, both
|
||||
* derived types of [AMQPTypeNotation], can be printed
|
||||
*
|
||||
* @param stream_ where the output should go
|
||||
* @param clazz_ what we want to print
|
||||
* @return the stream to allow proper io chaining
|
||||
*/
|
||||
std::ostream &
|
||||
operator << (std::ostream & stream_, const AMQPTypeNotation & clazz_) {
|
||||
switch (clazz_.type()) {
|
||||
case AMQPTypeNotation::Type::Composite : {
|
||||
stream_ << dynamic_cast<const Composite &>(clazz_);
|
||||
break;
|
||||
}
|
||||
case AMQPTypeNotation::Type::Restricted : {
|
||||
stream_ << dynamic_cast<const Restricted &>(clazz_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return stream_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::schema::AMQPTypeNotation
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
AMQPTypeNotation::descriptor() const {
|
||||
return m_descriptor->name();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
AMQPTypeNotation::name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <memory>
|
||||
#include <types.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "Descriptor.h"
|
||||
#include "OrderedTypeNotations.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Forward class declarations
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class Restricted;
|
||||
class Composite;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class AMQPTypeNotation : public AMQPDescribed, public OrderedTypeNotation {
|
||||
public :
|
||||
friend std::ostream & operator << (std::ostream &, const AMQPTypeNotation &);
|
||||
|
||||
enum Type { Composite, Restricted };
|
||||
|
||||
private :
|
||||
std::string m_name;
|
||||
std::unique_ptr<Descriptor> m_descriptor;
|
||||
|
||||
public :
|
||||
AMQPTypeNotation (
|
||||
const std::string & name_,
|
||||
std::unique_ptr<Descriptor> & descriptor_
|
||||
) : m_name (name_)
|
||||
, m_descriptor (std::move(descriptor_))
|
||||
{ }
|
||||
|
||||
const std::string & descriptor() const;
|
||||
|
||||
const std::string & name() const;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
148
experimental/cpp-serializer/src/amqp/schema/Composite.cxx
Normal file
148
experimental/cpp-serializer/src/amqp/schema/Composite.cxx
Normal file
@ -0,0 +1,148 @@
|
||||
#include "Composite.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "colours.h"
|
||||
|
||||
#include "amqp/schema/restricted-types/Restricted.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
std::ostream &
|
||||
operator << (std::ostream & stream_, const Composite & clazz_) {
|
||||
stream_
|
||||
<< "name : " << clazz_.name() << std::endl
|
||||
<< "label : " << clazz_.m_label << std::endl
|
||||
<< "descriptor : " << clazz_.descriptor() << std::endl
|
||||
<< "fields : ";
|
||||
|
||||
for (auto const & i : clazz_.m_fields) stream_ << *i << std::setw (13) << " ";
|
||||
stream_ << std::setw(0);
|
||||
|
||||
return stream_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::schema::Composite
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
Composite::Composite (
|
||||
const std::string & name_,
|
||||
std::string label_,
|
||||
const std::list<std::string> & provides_,
|
||||
std::unique_ptr<Descriptor> & descriptor_,
|
||||
std::vector<std::unique_ptr<Field>> & fields_
|
||||
) : AMQPTypeNotation (name_, descriptor_)
|
||||
, m_label (std::move (label_))
|
||||
, m_provides (provides_)
|
||||
, m_fields (std::move (fields_))
|
||||
{ }
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::vector<std::unique_ptr<amqp::internal::schema::Field>> &
|
||||
amqp::internal::schema::
|
||||
Composite::fields() const {
|
||||
return m_fields;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::AMQPTypeNotation::Type
|
||||
amqp::internal::schema::
|
||||
Composite::type() const {
|
||||
return AMQPTypeNotation::Type::Composite;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Use a visitor style pattern to work out weather two types, composite or
|
||||
* restricted, are "less than" one or not. In this case we define being
|
||||
* "less than" not having a type that the other depends on. This will
|
||||
* eventually give us a set ordered in such a way we can simply create
|
||||
* each element in turn
|
||||
*
|
||||
* "...This object determines the order of the elements in the container: it is
|
||||
* a function pointer or a function object that takes two arguments of the same
|
||||
* type as the container elements, and returns true if the first argument is
|
||||
* considered to go before the second in the strict weak ordering it defines,
|
||||
* and false otherwise. ..."
|
||||
|
||||
*
|
||||
* @param rhs
|
||||
* @return
|
||||
*/
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Composite::dependsOn (const OrderedTypeNotation & rhs) const {
|
||||
return dynamic_cast<const AMQPTypeNotation &>(rhs).dependsOn(*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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 rtn;
|
||||
}
|
||||
|
||||
/*********************************************************o*********************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Composite::dependsOn (const amqp::internal::schema::Composite & lhs_) const {
|
||||
auto rtn { 0 };
|
||||
|
||||
// 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
|
||||
for (const auto & field : m_fields) {
|
||||
DBG (" C/C b) " << field->resolvedType() << " == " << lhs_.name() << std::endl); // NOLINT
|
||||
|
||||
if (field->resolvedType() == lhs_.name()) {
|
||||
rtn = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
85
experimental/cpp-serializer/src/amqp/schema/Composite.h
Normal file
85
experimental/cpp-serializer/src/amqp/schema/Composite.h
Normal file
@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <types.h>
|
||||
|
||||
#include "Field.h"
|
||||
#include "Descriptor.h"
|
||||
#include "AMQPTypeNotation.h"
|
||||
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Forward class declarations
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class Restricted;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
/*
|
||||
* A Corda AMQP Schema Composite type has:
|
||||
*
|
||||
* val name: String,
|
||||
* val label: String?,
|
||||
* val provides: List<String>,
|
||||
* val descriptor: Descriptor,
|
||||
* val fields: List<Field>
|
||||
*/
|
||||
class Composite : public AMQPTypeNotation {
|
||||
public :
|
||||
friend std::ostream & operator << (std::ostream &, const Composite&);
|
||||
|
||||
private :
|
||||
// could be null in the stream... not sure that information is
|
||||
// worth preserving beyond an empty string here.
|
||||
std::string m_label;
|
||||
|
||||
// interfaces the class implements... again since we can't
|
||||
// use Karen to dynamically construct a class
|
||||
// we don't know about knowing the interfaces (java concept)
|
||||
// that this class implemented isn't al that useful but we'll
|
||||
// at least preserve the list
|
||||
std::list<std::string> m_provides;
|
||||
|
||||
/**
|
||||
* The properties of the Class
|
||||
*/
|
||||
std::vector<std::unique_ptr<Field>> m_fields;
|
||||
|
||||
public :
|
||||
Composite (
|
||||
const std::string & name_,
|
||||
std::string label_,
|
||||
const std::list<std::string> & provides_,
|
||||
std::unique_ptr<Descriptor> & descriptor_,
|
||||
std::vector<std::unique_ptr<Field>> & fields_);
|
||||
|
||||
const std::vector<std::unique_ptr<Field>> & fields() const;
|
||||
|
||||
Type type() const override;
|
||||
|
||||
int dependsOn (const OrderedTypeNotation &) const override;
|
||||
int dependsOn (const class Restricted &) const override;
|
||||
int dependsOn (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(); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
34
experimental/cpp-serializer/src/amqp/schema/Descriptor.cxx
Normal file
34
experimental/cpp-serializer/src/amqp/schema/Descriptor.cxx
Normal file
@ -0,0 +1,34 @@
|
||||
#include "Descriptor.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
std::ostream &
|
||||
operator << (std::ostream & stream_, const Descriptor & desc_) {
|
||||
stream_ << desc_.m_name;
|
||||
return stream_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Descriptor Implementation
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
Descriptor::Descriptor (std::string name_)
|
||||
: m_name (std::move (name_))
|
||||
{ }
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
Descriptor::name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
32
experimental/cpp-serializer/src/amqp/schema/Descriptor.h
Normal file
32
experimental/cpp-serializer/src/amqp/schema/Descriptor.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class Descriptor : public AMQPDescribed {
|
||||
public :
|
||||
friend std::ostream & operator << (std::ostream &, const Descriptor&);
|
||||
|
||||
private :
|
||||
std::string m_name;
|
||||
|
||||
public :
|
||||
Descriptor() = default;
|
||||
|
||||
explicit Descriptor (std::string);
|
||||
|
||||
const std::string & name() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
50
experimental/cpp-serializer/src/amqp/schema/Envelope.cxx
Normal file
50
experimental/cpp-serializer/src/amqp/schema/Envelope.cxx
Normal file
@ -0,0 +1,50 @@
|
||||
#include "Envelope.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
std::ostream &
|
||||
operator << (
|
||||
std::ostream & stream_,
|
||||
const amqp::internal::schema::Envelope & e_
|
||||
) {
|
||||
stream_ << *(e_.m_schema);
|
||||
return stream_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::schema::Envelope
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
Envelope::Envelope (
|
||||
std::unique_ptr<Schema> & schema_,
|
||||
std::string descriptor_
|
||||
) : m_schema (std::move (schema_))
|
||||
, m_descriptor (std::move (descriptor_))
|
||||
{ }
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::unique_ptr<amqp::internal::schema::Schema> &
|
||||
amqp::internal::schema::
|
||||
Envelope::schema() const {
|
||||
return m_schema;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
Envelope::descriptor() const {
|
||||
return m_descriptor;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
38
experimental/cpp-serializer/src/amqp/schema/Envelope.h
Normal file
38
experimental/cpp-serializer/src/amqp/schema/Envelope.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
|
||||
#include "Schema.h"
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class Envelope : public AMQPDescribed {
|
||||
public :
|
||||
friend std::ostream & operator << (std::ostream &, const Envelope &);
|
||||
|
||||
private :
|
||||
std::unique_ptr<Schema> m_schema;
|
||||
std::string m_descriptor;
|
||||
|
||||
public :
|
||||
Envelope() = delete;
|
||||
|
||||
Envelope (
|
||||
std::unique_ptr<Schema> & schema_,
|
||||
std::string descriptor_);
|
||||
|
||||
const std::unique_ptr<Schema> & schema() const;
|
||||
|
||||
const std::string & descriptor() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
109
experimental/cpp-serializer/src/amqp/schema/Field.cxx
Normal file
109
experimental/cpp-serializer/src/amqp/schema/Field.cxx
Normal file
@ -0,0 +1,109 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
63
experimental/cpp-serializer/src/amqp/schema/Field.h
Normal file
63
experimental/cpp-serializer/src/amqp/schema/Field.h
Normal file
@ -0,0 +1,63 @@
|
||||
#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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -0,0 +1,206 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
|
||||
#include "types.h"
|
||||
#include "colours.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Forward declarations
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
template<class T>
|
||||
class OrderedTypeNotations;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::ostream & operator << (
|
||||
std::ostream &,
|
||||
const amqp::internal::schema::OrderedTypeNotations<T> &);
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* OrderedTypeNotation
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class OrderedTypeNotation {
|
||||
public :
|
||||
virtual ~OrderedTypeNotation() = default;
|
||||
|
||||
virtual int dependsOn (const OrderedTypeNotation &) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
template<class T>
|
||||
class OrderedTypeNotations {
|
||||
private:
|
||||
std::list<std::list<uPtr<T>>> m_schemas;
|
||||
|
||||
public :
|
||||
typedef decltype(m_schemas.begin()) iterator;
|
||||
|
||||
private:
|
||||
void insert (uPtr<T> &&, iterator);
|
||||
void insertNewList (uPtr<T> &&);
|
||||
void insertNewList (
|
||||
uPtr<T> &&,
|
||||
typename std::list<std::list<uPtr<T>>>::iterator &);
|
||||
|
||||
public :
|
||||
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.crend()) end() const {
|
||||
return m_schemas.crend();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
template<class T>
|
||||
std::ostream &
|
||||
operator << (
|
||||
std::ostream &stream_,
|
||||
const amqp::internal::schema::OrderedTypeNotations<T> &otn_
|
||||
) {
|
||||
int idx1{0};
|
||||
for (const auto &i : otn_.m_schemas) {
|
||||
stream_ << "level " << ++idx1 << std::endl;
|
||||
for (const auto &j : i) {
|
||||
stream_ << " * " << j->name() << std::endl;
|
||||
}
|
||||
stream_ << std::endl;
|
||||
}
|
||||
|
||||
return stream_;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
template<class T>
|
||||
void
|
||||
amqp::internal::schema::
|
||||
OrderedTypeNotations<T>::insertNewList(uPtr<T> && ptr) {
|
||||
std::list<uPtr<T>> l;
|
||||
l.emplace_back (std::move (ptr));
|
||||
m_schemas.emplace_back(std::move (l));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* This could be a bit more space efficient by checking the previous element
|
||||
* for dependendies again as its possible we are moving multiple elements "up"
|
||||
* but the extra checks probably don't make it worth it.
|
||||
*/
|
||||
template<class T>
|
||||
void
|
||||
amqp::internal::schema::
|
||||
OrderedTypeNotations<T>::insertNewList(
|
||||
uPtr<T> && ptr,
|
||||
typename std::list<std::list<uPtr<T>>>::iterator & here_)
|
||||
{
|
||||
std::list<uPtr<T>> l;
|
||||
l.emplace_back (std::move (ptr));
|
||||
m_schemas.insert(here_, std::move (l));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
template<class T>
|
||||
void
|
||||
amqp::internal::schema::
|
||||
OrderedTypeNotations<T>::insert (uPtr<T> && ptr) {
|
||||
return insert (std::move (ptr), m_schemas.begin());
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
template<class T>
|
||||
void
|
||||
amqp::internal::schema::
|
||||
OrderedTypeNotations<T>::insert (
|
||||
uPtr<T> && ptr,
|
||||
amqp::internal::schema::OrderedTypeNotations<T>::iterator l_
|
||||
) {
|
||||
/*
|
||||
* First we find where this element needs to be added
|
||||
*/
|
||||
amqp::internal::schema::OrderedTypeNotations<T>::iterator insertionPoint { l_ };
|
||||
|
||||
for (auto i = l_ ; i != m_schemas.end() ; ++i) {
|
||||
for (const auto & j : *i) {
|
||||
/*
|
||||
* A score of 0 means no dependencies at all
|
||||
* A score of 1 means "j" has a dependency on what's being inserted
|
||||
* A score of 2 means what's being inserted depends on "j"
|
||||
*/
|
||||
auto score = j->dependsOn(*ptr);
|
||||
|
||||
if (score == 1) {
|
||||
insertionPoint = std::next(i);
|
||||
} else if (score == 2) {
|
||||
insertionPoint = i;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
||||
/*
|
||||
* Now we insert it and work out if anything requires shuffling
|
||||
*/
|
||||
if (insertionPoint == m_schemas.end()) {
|
||||
insertNewList (std::move(ptr));
|
||||
} else {
|
||||
const auto & insertedPtr = insertionPoint->emplace_front (std::move(ptr));
|
||||
|
||||
for (auto j = std::next (insertionPoint->begin()) ; j != insertionPoint->end() ; ) {
|
||||
auto toErase = j++;
|
||||
|
||||
auto score { insertedPtr->dependsOn (**toErase) };
|
||||
|
||||
if (score > 0) {
|
||||
uPtr<T> tmpPtr{std::move(*toErase)};
|
||||
insertionPoint->erase (toErase);
|
||||
switch (score) {
|
||||
// Needs to go after the element we're adding
|
||||
case 1: {
|
||||
insert(std::move(tmpPtr), std::next(insertionPoint));
|
||||
break;
|
||||
}
|
||||
// Needs to go before the element we're adding
|
||||
case 2: {
|
||||
insertNewList (std::move(tmpPtr), insertionPoint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
75
experimental/cpp-serializer/src/amqp/schema/Schema.cxx
Normal file
75
experimental/cpp-serializer/src/amqp/schema/Schema.cxx
Normal file
@ -0,0 +1,75 @@
|
||||
|
||||
#include "Schema.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Non member related functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
std::ostream &
|
||||
operator << (std::ostream & stream_, const Schema & schema_) {
|
||||
|
||||
for (auto i { schema_.m_types.begin() } ; i != schema_.m_types.end() ; ++i) {
|
||||
for (auto & j : *i) {
|
||||
stream_ << j->name() << " " << j->type() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return stream_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::schema::Schema
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
Schema::Schema (
|
||||
OrderedTypeNotations<AMQPTypeNotation> types_
|
||||
) : m_types (std::move (types_)) {
|
||||
for (auto i { m_types.begin() } ; i != m_types.end() ; ++i) {
|
||||
for (auto & j : *i) {
|
||||
DBG ("Schema: " << j->descriptor() << " " << j->name() << std::endl); // NOLINT
|
||||
m_descriptorToType.emplace(j->descriptor(), std::ref (j));
|
||||
m_typeToDescriptor.emplace(j->name(), std::ref (j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const amqp::internal::schema::OrderedTypeNotations<amqp::internal::schema::AMQPTypeNotation> &
|
||||
amqp::internal::schema::
|
||||
Schema::types() const {
|
||||
return m_types;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::Schema::SchemaMap::const_iterator
|
||||
amqp::internal::schema::
|
||||
Schema::fromType (const std::string & type_) const {
|
||||
return m_typeToDescriptor.find(type_);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::Schema::SchemaMap::const_iterator
|
||||
amqp::internal::schema::
|
||||
Schema::fromDescriptor (const std::string & descriptor_) const {
|
||||
return m_descriptorToType.find (descriptor_);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
63
experimental/cpp-serializer/src/amqp/schema/Schema.h
Normal file
63
experimental/cpp-serializer/src/amqp/schema/Schema.h
Normal file
@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <iosfwd>
|
||||
|
||||
#include "types.h"
|
||||
#include "Composite.h"
|
||||
#include "Descriptor.h"
|
||||
#include "OrderedTypeNotations.h"
|
||||
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
typedef std::function <bool(const uPtr<AMQPTypeNotation> &, const uPtr<AMQPTypeNotation> &)> const SetSort;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
/*
|
||||
*/
|
||||
class Schema : public AMQPDescribed {
|
||||
public :
|
||||
friend std::ostream & operator << (std::ostream &, const Schema &);
|
||||
|
||||
typedef std::map<std::string, const std::reference_wrapper<const uPtr<AMQPTypeNotation>>> SchemaMap;
|
||||
|
||||
private :
|
||||
OrderedTypeNotations<AMQPTypeNotation> m_types;
|
||||
SchemaMap m_descriptorToType;
|
||||
SchemaMap m_typeToDescriptor;
|
||||
|
||||
public :
|
||||
Schema (OrderedTypeNotations<AMQPTypeNotation> types_);
|
||||
|
||||
const OrderedTypeNotations<AMQPTypeNotation> & types() const;
|
||||
|
||||
SchemaMap::const_iterator fromType (const std::string &) const;
|
||||
SchemaMap::const_iterator fromDescriptor (const std::string &) const;
|
||||
|
||||
decltype(m_types.begin()) begin() const { return m_types.begin(); }
|
||||
decltype(m_types.end()) end() const { return m_types.end(); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -0,0 +1,116 @@
|
||||
#include <iostream>
|
||||
#include "List.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "colours.h"
|
||||
|
||||
#include "schema/Composite.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
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) }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
List::List (
|
||||
uPtr<Descriptor> & descriptor_,
|
||||
const std::string & name_,
|
||||
const std::string & label_,
|
||||
const std::vector<std::string> & provides_,
|
||||
const std::string & source_
|
||||
) : Restricted (
|
||||
descriptor_,
|
||||
name_,
|
||||
label_,
|
||||
provides_,
|
||||
amqp::internal::schema::Restricted::RestrictedTypes::List)
|
||||
, m_listOf { listType(name_).second }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::vector<std::string>::const_iterator
|
||||
amqp::internal::schema::
|
||||
List::begin() const {
|
||||
return m_listOf.begin();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::vector<std::string>::const_iterator
|
||||
amqp::internal::schema::
|
||||
List::end() const {
|
||||
return m_listOf.end();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const std::string &
|
||||
amqp::internal::schema::
|
||||
List::listOf() const {
|
||||
return m_listOf[0];
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
List::dependsOn (const amqp::internal::schema::Composite & lhs_) const {
|
||||
auto rtn { 0 };
|
||||
for (const auto & field : lhs_.fields()) {
|
||||
DBG (" L/C a) " << field->resolvedType() << " == " << name() << std::endl); // NOLINT
|
||||
if (field->resolvedType() == name()) {
|
||||
rtn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
DBG (" L/C b) " << listOf() << " == " << lhs_.name() << std::endl); // NOLINT
|
||||
if (listOf() == lhs_.name()) {
|
||||
rtn = 2;
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/*********************************************************o*********************/
|
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "Restricted.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class List : public Restricted {
|
||||
private :
|
||||
std::vector<std::string> m_listOf;
|
||||
|
||||
public :
|
||||
List (
|
||||
uPtr<Descriptor> & descriptor_,
|
||||
const std::string &,
|
||||
const std::string &,
|
||||
const std::vector<std::string> &,
|
||||
const std::string &);
|
||||
|
||||
std::vector<std::string>::const_iterator begin() const override;
|
||||
std::vector<std::string>::const_iterator end() const override;
|
||||
|
||||
const std::string & listOf() const;
|
||||
|
||||
int dependsOn (const Restricted &) const override;
|
||||
int dependsOn (const class Composite &) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
@ -0,0 +1,131 @@
|
||||
#include "Restricted.h"
|
||||
#include "List.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
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;
|
||||
|
||||
for (auto & provides : clazz_.m_provides) {
|
||||
stream_ << " " << provides << std::endl;
|
||||
}
|
||||
stream_<< " ]" << std::endl;
|
||||
|
||||
return stream_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return stream_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* amqp::internal::schema::Restricted
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Named constructor
|
||||
*
|
||||
* @param descriptor_
|
||||
* @param name_
|
||||
* @param label_
|
||||
* @param provides_
|
||||
* @param source_
|
||||
* @return
|
||||
*/
|
||||
std::unique_ptr<amqp::internal::schema::Restricted>
|
||||
amqp::internal::schema::
|
||||
Restricted::make(
|
||||
uPtr<Descriptor> & descriptor_,
|
||||
const std::string & name_,
|
||||
const std::string & label_,
|
||||
const std::vector<std::string> & provides_,
|
||||
const std::string & source_)
|
||||
{
|
||||
if (source_ == "list") {
|
||||
return std::make_unique<amqp::internal::schema::List> (
|
||||
descriptor_, name_, label_, provides_, source_);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::
|
||||
Restricted::Restricted (
|
||||
uPtr<Descriptor> & descriptor_,
|
||||
const std::string & name_,
|
||||
std::string label_,
|
||||
const std::vector<std::string> & provides_,
|
||||
const amqp::internal::schema::Restricted::RestrictedTypes & source_
|
||||
) : AMQPTypeNotation (name_, descriptor_)
|
||||
, m_label (std::move (label_))
|
||||
, m_provides (provides_)
|
||||
, m_source (source_)
|
||||
{
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::AMQPTypeNotation::Type
|
||||
amqp::internal::schema::
|
||||
Restricted::type() const {
|
||||
return AMQPTypeNotation::Type::Restricted;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
amqp::internal::schema::Restricted::RestrictedTypes
|
||||
amqp::internal::schema::
|
||||
Restricted::restrictedType() const {
|
||||
return m_source;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int
|
||||
amqp::internal::schema::
|
||||
Restricted::dependsOn (const OrderedTypeNotation & rhs_) const {
|
||||
return dynamic_cast<const AMQPTypeNotation &>(rhs_).dependsOn(*this);
|
||||
}
|
||||
|
||||
/*********************************************************o*********************/
|
||||
|
@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include "Field.h"
|
||||
#include "Descriptor.h"
|
||||
#include "AMQPTypeNotation.h"
|
||||
|
||||
#include "amqp/AMQPDescribed.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Forward class declarations
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class Composite;
|
||||
class OrderedTypeNotation;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp::internal::schema {
|
||||
|
||||
class Restricted : public AMQPTypeNotation {
|
||||
public :
|
||||
friend std::ostream & operator << (std::ostream &, const Restricted&);
|
||||
|
||||
enum RestrictedTypes { List, Map };
|
||||
|
||||
private :
|
||||
// could be null in the stream... not sure that information is
|
||||
// worth preserving beyond an empty string here.
|
||||
std::string m_label;
|
||||
|
||||
/**
|
||||
* Which Java interfaces the type implemented when serialised within
|
||||
* the JVM. Not really useful for C++ but we're keepign it for
|
||||
* the sense of completeness
|
||||
*/
|
||||
std::vector<std::string> m_provides;
|
||||
|
||||
/**
|
||||
* Is it a map or list
|
||||
*/
|
||||
RestrictedTypes m_source;
|
||||
|
||||
protected :
|
||||
/**
|
||||
* keep main constructor private to force use of the named constructor
|
||||
*/
|
||||
Restricted (
|
||||
std::unique_ptr<Descriptor> & descriptor_,
|
||||
const std::string &,
|
||||
std::string,
|
||||
const std::vector<std::string> &,
|
||||
const RestrictedTypes &);
|
||||
|
||||
public :
|
||||
static std::unique_ptr<Restricted> make(
|
||||
std::unique_ptr<Descriptor> & descriptor_,
|
||||
const std::string &,
|
||||
const std::string &,
|
||||
const std::vector<std::string> &,
|
||||
const std::string &);
|
||||
|
||||
Restricted (Restricted&) = delete;
|
||||
|
||||
Type type() const override;
|
||||
|
||||
RestrictedTypes restrictedType() const;
|
||||
|
||||
/**
|
||||
* @return an iterator over the types the restricted class represents.
|
||||
* In the case of a list, the element this is a list of, in the
|
||||
* case of a map the key and value types etc.
|
||||
*/
|
||||
virtual std::vector<std::string>::const_iterator begin() const = 0;
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
std::ostream & operator << (std::ostream &, const Restricted::RestrictedTypes &);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
1
experimental/cpp-serializer/src/amqp/test/.gitignore
vendored
Normal file
1
experimental/cpp-serializer/src/amqp/test/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
amqp-test
|
18
experimental/cpp-serializer/src/amqp/test/CMakeLists.txt
Normal file
18
experimental/cpp-serializer/src/amqp/test/CMakeLists.txt
Normal file
@ -0,0 +1,18 @@
|
||||
set (EXE "amqp-test")
|
||||
|
||||
set (amqp-test-sources
|
||||
main.cxx
|
||||
Pair.cxx
|
||||
Single.cxx
|
||||
OrderedTypeNotationTest.cxx
|
||||
)
|
||||
|
||||
link_directories (${BLOB-INSPECTOR_BINARY_DIR}/src/amqp)
|
||||
|
||||
add_executable (${EXE} ${amqp-test-sources})
|
||||
|
||||
target_link_libraries (${EXE} gtest amqp)
|
||||
|
||||
if (UNIX)
|
||||
target_link_libraries (${EXE} pthread qpid-proton proton)
|
||||
endif (UNIX)
|
@ -0,0 +1,222 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "OrderedTypeNotations.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
class OTN : public amqp::internal::schema::OrderedTypeNotation {
|
||||
private :
|
||||
std::string m_name;
|
||||
std::vector<std::string> m_dependsOn;
|
||||
public :
|
||||
OTN(std::string name_, std::vector<std::string> dependsOn_)
|
||||
: m_name (std::move (name_))
|
||||
, m_dependsOn (std::move (dependsOn_))
|
||||
{ }
|
||||
|
||||
|
||||
int dependsOn (const OrderedTypeNotation & otn_) const override {
|
||||
const auto & otn = dynamic_cast<const OTN &>(otn_);
|
||||
|
||||
// does the "left hand side" depend on us (in this case
|
||||
// the lhs is us as we're not inverting
|
||||
if (std::find (
|
||||
m_dependsOn.begin(),
|
||||
m_dependsOn.end(),
|
||||
otn.name()) != m_dependsOn.end())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// do we depend on the left hand side
|
||||
|
||||
|
||||
if (std::find (
|
||||
otn.begin(),
|
||||
otn.end(),
|
||||
name()) != otn.end())
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::string & name() const { return m_name; }
|
||||
|
||||
decltype(m_dependsOn.cbegin()) begin() const { return m_dependsOn.cbegin(); }
|
||||
decltype(m_dependsOn.cend()) end() const { return m_dependsOn.cend(); }
|
||||
};
|
||||
|
||||
inline
|
||||
std::string
|
||||
str (const amqp::internal::schema::OrderedTypeNotations<OTN> & list_) {
|
||||
std::stringstream ss;
|
||||
ss << list_;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Makes testing easier if we compress the list into a flat series rather than
|
||||
* being all fancy with our output
|
||||
*/
|
||||
template<>
|
||||
std::ostream &
|
||||
operator << (
|
||||
std::ostream &stream_,
|
||||
const amqp::internal::schema::OrderedTypeNotations<OTN> &otn_
|
||||
) {
|
||||
auto first { true };
|
||||
for (const auto & i : otn_.m_schemas) {
|
||||
for (const auto & j : i) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
stream_ << " ";
|
||||
}
|
||||
stream_ << j->name();
|
||||
}
|
||||
}
|
||||
|
||||
return stream_;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, singleInsert) { // NOLINT
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
list.insert(std::make_unique<OTN>("A", std::vector<std::string>()));
|
||||
ASSERT_EQ("A", str (list));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, A_depends_on_B) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { "B" };
|
||||
list.insert(std::make_unique<OTN>("A", aDeps));
|
||||
list.insert(std::make_unique<OTN>("B", std::vector<std::string>()));
|
||||
ASSERT_EQ("A B", str (list));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, B_depends_on_A) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { };
|
||||
std::vector<std::string> bDeps = { "A" };
|
||||
|
||||
list.insert(std::make_unique<OTN>("A", aDeps));
|
||||
list.insert(std::make_unique<OTN>("B", bDeps));
|
||||
|
||||
ASSERT_EQ ("B A", str (list));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, three_1) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { };
|
||||
std::vector<std::string> bDeps = { "A" };
|
||||
std::vector<std::string> cDeps = { "A" };
|
||||
|
||||
list.insert(std::make_unique<OTN>("A", aDeps));
|
||||
list.insert(std::make_unique<OTN>("B", bDeps));
|
||||
list.insert(std::make_unique<OTN>("C", cDeps));
|
||||
|
||||
ASSERT_EQ ("B C A", str (list));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, three_2) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { "B" };
|
||||
std::vector<std::string> bDeps = { "C" };
|
||||
std::vector<std::string> cDeps = { };
|
||||
|
||||
list.insert(std::make_unique<OTN>("A", aDeps));
|
||||
list.insert(std::make_unique<OTN>("B", bDeps));
|
||||
list.insert(std::make_unique<OTN>("C", cDeps));
|
||||
|
||||
EXPECT_EQ ("A B C", str (list));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, three_3) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { "B" };
|
||||
std::vector<std::string> bDeps = { "C" };
|
||||
std::vector<std::string> cDeps = { };
|
||||
|
||||
list.insert(std::make_unique<OTN>("C", cDeps));
|
||||
list.insert(std::make_unique<OTN>("A", aDeps));
|
||||
list.insert(std::make_unique<OTN>("B", bDeps));
|
||||
|
||||
EXPECT_EQ ("A B C", str (list));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, three_4) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { "B" };
|
||||
std::vector<std::string> bDeps = { "C" };
|
||||
std::vector<std::string> cDeps = { };
|
||||
|
||||
list.insert(std::make_unique<OTN>("C", cDeps));
|
||||
list.insert(std::make_unique<OTN>("B", bDeps));
|
||||
list.insert(std::make_unique<OTN>("A", aDeps));
|
||||
|
||||
EXPECT_EQ ("A B C", str (list));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (OTNTest, three_5) { // NOLINT
|
||||
std::cout << std::endl;
|
||||
amqp::internal::schema::OrderedTypeNotations<OTN> list;
|
||||
|
||||
std::vector<std::string> aDeps = { "B" };
|
||||
std::vector<std::string> bDeps = { "C" };
|
||||
std::vector<std::string> cDeps = { };
|
||||
|
||||
list.insert(std::make_unique<OTN>("B", bDeps));
|
||||
list.insert(std::make_unique<OTN>("C", cDeps));
|
||||
list.insert(std::make_unique<OTN>("A", aDeps));
|
||||
|
||||
EXPECT_EQ ("A B C", str (list));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
56
experimental/cpp-serializer/src/amqp/test/Pair.cxx
Normal file
56
experimental/cpp-serializer/src/amqp/test/Pair.cxx
Normal file
@ -0,0 +1,56 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "Reader.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (Pair, string) { // NOLINT
|
||||
amqp::TypedPair<std::string> str_test ("Left", "Hello");
|
||||
|
||||
EXPECT_EQ("Left : Hello", str_test.dump());
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (Pair, int) { // NOLINT
|
||||
amqp::TypedPair<int> int_test ("Left", 101);
|
||||
|
||||
EXPECT_EQ("Left : 101", int_test.dump());
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (Pair, UP1) { // NOLINT
|
||||
std::unique_ptr<amqp::TypedPair<double>> test =
|
||||
std::make_unique<amqp::TypedPair<double>> ("property", 10.0);
|
||||
|
||||
EXPECT_EQ("property : 10.000000", test->dump());
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
TEST (Pair, UP2) { // NOLINT
|
||||
struct builder {
|
||||
static std::unique_ptr<amqp::Pair>
|
||||
build (const std::string & prop_, int val_) {
|
||||
return std::make_unique<amqp::TypedPair<int>> (prop_, val_);
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<std::unique_ptr<amqp::Value>> vec;
|
||||
vec.reserve(2);
|
||||
|
||||
vec.emplace_back (builder::build ("first", 1));
|
||||
vec.emplace_back (builder::build ("second", 2));
|
||||
|
||||
std::unique_ptr<amqp::Pair> test =
|
||||
std::make_unique<amqp::TypedPair<std::vector<std::unique_ptr<amqp::Value>>>> (
|
||||
"Vector", std::move (vec));
|
||||
|
||||
EXPECT_EQ("Vector : { first : 1, second : 2 }", test->dump());
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
35
experimental/cpp-serializer/src/amqp/test/Single.cxx
Normal file
35
experimental/cpp-serializer/src/amqp/test/Single.cxx
Normal file
@ -0,0 +1,35 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "Reader.h"
|
||||
|
||||
TEST (Single, string) { // NOLINT
|
||||
amqp::TypedSingle<std::string> str_test ("Hello");
|
||||
|
||||
EXPECT_EQ("Hello", str_test.dump());
|
||||
}
|
||||
|
||||
TEST (Single, list) { // NOLINT
|
||||
|
||||
struct builder {
|
||||
static std::unique_ptr<amqp::Value>
|
||||
build (int val_) {
|
||||
return std::make_unique<amqp::TypedSingle<int>> (val_);
|
||||
}
|
||||
};
|
||||
|
||||
std::list<std::unique_ptr<amqp::Value>> list;
|
||||
|
||||
list.emplace_back (builder::build (1));
|
||||
list.emplace_back (builder::build (2));
|
||||
list.emplace_back (builder::build (3));
|
||||
list.emplace_back (builder::build (4));
|
||||
list.emplace_back (builder::build (5));
|
||||
|
||||
std::unique_ptr<amqp::Single> test =
|
||||
std::make_unique<amqp::TypedSingle<std::list<std::unique_ptr<amqp::Value>>>> (
|
||||
std::move (list));
|
||||
|
||||
EXPECT_EQ("[ 1, 2, 3, 4, 5 ]", test->dump());
|
||||
}
|
7
experimental/cpp-serializer/src/amqp/test/main.cxx
Normal file
7
experimental/cpp-serializer/src/amqp/test/main.cxx
Normal file
@ -0,0 +1,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int
|
||||
main (int argc, char ** argv){
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
6
experimental/cpp-serializer/src/proton/CMakeLists.txt
Normal file
6
experimental/cpp-serializer/src/proton/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
set (proton_sources
|
||||
proton_wrapper.cxx
|
||||
)
|
||||
|
||||
ADD_LIBRARY ( proton ${proton_sources} )
|
||||
|
321
experimental/cpp-serializer/src/proton/proton_wrapper.cxx
Normal file
321
experimental/cpp-serializer/src/proton/proton_wrapper.cxx
Normal file
@ -0,0 +1,321 @@
|
||||
#include "proton_wrapper.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
#include <proton/types.h>
|
||||
#include <proton/codec.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::ostream&
|
||||
operator << (std::ostream& stream, pn_data_t * data_) {
|
||||
auto type = pn_data_type(data_);
|
||||
stream << std::setw (2) << type << " " << pn_type_name (type);
|
||||
|
||||
switch (type) {
|
||||
case PN_ULONG :
|
||||
{
|
||||
stream << " " << pn_data_get_ulong (data_);
|
||||
break;
|
||||
}
|
||||
case PN_LIST :
|
||||
{
|
||||
stream << " #entries: " << pn_data_get_list (data_);
|
||||
break;
|
||||
}
|
||||
case PN_STRING :
|
||||
{
|
||||
auto str = pn_data_get_string (data_);
|
||||
|
||||
stream << " " << std::string (str.start, str.size);
|
||||
break;
|
||||
}
|
||||
case PN_INT :
|
||||
{
|
||||
stream << " " << pn_data_get_int (data_);
|
||||
break;
|
||||
}
|
||||
case PN_BOOL :
|
||||
{
|
||||
stream << " " << (pn_data_get_bool (data_) ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
case PN_SYMBOL :
|
||||
{
|
||||
stream << " " << pn_data_get_symbol (data_).size;
|
||||
stream << std::endl << " -> ";
|
||||
auto v = pn_data_get_symbol (data_);
|
||||
for (size_t i (0) ; i < v.size ; ++i) {
|
||||
stream << *(v.start + i) << " ";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default : break;
|
||||
|
||||
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* pn_data_enter always places the current pointer before the first node. This
|
||||
* is a simple convienience function to avoid having to move to the first
|
||||
* element in addition to entering a child.
|
||||
*/
|
||||
bool
|
||||
proton::pn_data_enter(pn_data_t * data_) {
|
||||
::pn_data_enter(data_);
|
||||
return pn_data_next(data_);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
proton::is_described (pn_data_t * data_) {
|
||||
if (pn_data_type(data_) != PN_DESCRIBED) {
|
||||
throw std::runtime_error ("Expected a described type");
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
proton::is_ulong (pn_data_t * data_) {
|
||||
auto t = pn_data_type(data_);
|
||||
if (t != PN_ULONG) {
|
||||
std::stringstream ss;
|
||||
ss << "Expected an unsigned long but recieved " << pn_type_name (t);
|
||||
throw std::runtime_error (ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
inline void
|
||||
proton::is_symbol (pn_data_t * data_) {
|
||||
if (pn_data_type(data_) != PN_SYMBOL) {
|
||||
throw std::runtime_error ("Expected an unsigned long");
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
proton::is_list (pn_data_t * data_) {
|
||||
if (pn_data_type(data_) != PN_LIST) {
|
||||
throw std::runtime_error ("Expected a list");
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
inline void
|
||||
proton::is_string (pn_data_t * data_, bool allowNull) {
|
||||
if (pn_data_type(data_) != PN_STRING) {
|
||||
if (allowNull && pn_data_type(data_) != PN_NULL) {
|
||||
throw std::runtime_error ("Expected a String");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
std::string
|
||||
proton::get_string (pn_data_t * data_, bool allowNull) {
|
||||
if (pn_data_type(data_) == PN_STRING) {
|
||||
auto str = pn_data_get_string (data_);
|
||||
return std::string (str.start, str.size);
|
||||
} else if (allowNull && pn_data_type(data_) == PN_NULL) {
|
||||
return "";
|
||||
}
|
||||
throw std::runtime_error ("Expected a String");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
template<>
|
||||
std::string
|
||||
proton::get_symbol<std::string> (pn_data_t * data_) {
|
||||
is_symbol (data_);
|
||||
auto symbol = pn_data_get_symbol(data_);
|
||||
return std::string (symbol.start, symbol.size);
|
||||
}
|
||||
|
||||
template<>
|
||||
pn_bytes_t
|
||||
proton::get_symbol (pn_data_t * data_) {
|
||||
is_symbol (data_);
|
||||
return pn_data_get_symbol(data_);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
bool
|
||||
proton::get_boolean (pn_data_t * data_) {
|
||||
if (pn_data_type(data_) == PN_BOOL) {
|
||||
return pn_data_get_bool (data_);
|
||||
}
|
||||
throw std::runtime_error ("Expected a boolean");
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* proton::auto_enter
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
proton::
|
||||
auto_enter::auto_enter (pn_data_t * data_, bool next_)
|
||||
: m_data (data_)
|
||||
{
|
||||
proton::pn_data_enter(m_data);
|
||||
if (next_) pn_data_next(m_data);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
proton::
|
||||
auto_enter::~auto_enter() {
|
||||
pn_data_exit(m_data);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* proton::auto_next
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
proton::
|
||||
auto_next::auto_next (
|
||||
pn_data_t * data_
|
||||
) : m_data (data_) {
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
proton::
|
||||
auto_next::~auto_next() {
|
||||
pn_data_next (m_data);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* proton::auto_list_enter
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
proton::
|
||||
auto_list_enter::auto_list_enter (pn_data_t * data_, bool next_)
|
||||
: m_elements (pn_data_get_list (data_))
|
||||
, m_data (data_)
|
||||
{
|
||||
::pn_data_enter(m_data);
|
||||
if (next_) {
|
||||
pn_data_next (m_data);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
proton::
|
||||
auto_list_enter::~auto_list_enter() {
|
||||
pn_data_exit(m_data);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
size_t
|
||||
proton::
|
||||
auto_list_enter::elements() const {
|
||||
return m_elements;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
template<>
|
||||
int32_t
|
||||
proton::
|
||||
readAndNext<int32_t> (
|
||||
pn_data_t * data_,
|
||||
bool tolerateDeviance_
|
||||
) {
|
||||
int rtn = pn_data_get_int (data_);
|
||||
pn_data_next(data_);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
template<>
|
||||
std::string
|
||||
proton::
|
||||
readAndNext<std::string> (
|
||||
pn_data_t * data_,
|
||||
bool tolerateDeviance_
|
||||
) {
|
||||
auto_next an (data_);
|
||||
|
||||
if (pn_data_type(data_) == PN_STRING) {
|
||||
auto str = pn_data_get_string(data_);
|
||||
return std::string(str.start, str.size);
|
||||
} else if (pn_data_type(data_) == PN_SYMBOL) {
|
||||
auto symbol = pn_data_get_symbol(data_);
|
||||
return std::string(symbol.start, symbol.size);
|
||||
} else if (tolerateDeviance_ && pn_data_type(data_) == PN_NULL) {
|
||||
return "";
|
||||
}
|
||||
throw std::runtime_error ("Expected a String");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
template<>
|
||||
bool
|
||||
proton::
|
||||
readAndNext<bool> (
|
||||
pn_data_t * data_,
|
||||
bool tolerateDeviance_
|
||||
) {
|
||||
bool rtn = pn_data_get_bool (data_);
|
||||
pn_data_next(data_);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
template<>
|
||||
double
|
||||
proton::
|
||||
readAndNext<double> (
|
||||
pn_data_t * data_,
|
||||
bool tolerateDeviance_
|
||||
) {
|
||||
auto_next an (data_);
|
||||
return pn_data_get_double (data_);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
template<>
|
||||
long
|
||||
proton::
|
||||
readAndNext<long> (
|
||||
pn_data_t * data_,
|
||||
bool tolerateDeviance_
|
||||
) {
|
||||
long rtn = pn_data_get_long (data_);
|
||||
pn_data_next(data_);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
90
experimental/cpp-serializer/src/proton/proton_wrapper.h
Normal file
90
experimental/cpp-serializer/src/proton/proton_wrapper.h
Normal file
@ -0,0 +1,90 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include <proton/types.h>
|
||||
#include <proton/codec.h>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* Friendly ostream operator for a pn_data_t type
|
||||
*/
|
||||
std::ostream& operator << (std::ostream& stream, pn_data_t * data_);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace proton {
|
||||
|
||||
/**
|
||||
* Wrap enter so we automatically move to the first child node rather
|
||||
* than starting on an invalid one
|
||||
*/
|
||||
bool pn_data_enter(pn_data_t *);
|
||||
|
||||
void is_list (pn_data_t *);
|
||||
void is_ulong (pn_data_t *);
|
||||
void is_symbol (pn_data_t *);
|
||||
void is_string (pn_data_t *, bool allowNull = false);
|
||||
void is_described (pn_data_t *);
|
||||
|
||||
template<typename T>
|
||||
T get_symbol (pn_data_t * data_) {
|
||||
return T {};
|
||||
}
|
||||
|
||||
std::string get_symbol (pn_data_t *);
|
||||
|
||||
bool get_boolean (pn_data_t *);
|
||||
std::string get_string (pn_data_t *, bool allowNull = false);
|
||||
|
||||
class auto_enter {
|
||||
private :
|
||||
pn_data_t * m_data;
|
||||
|
||||
public :
|
||||
auto_enter (pn_data_t *, bool next_ = false);
|
||||
~auto_enter();
|
||||
};
|
||||
|
||||
class auto_next {
|
||||
private :
|
||||
pn_data_t * m_data;
|
||||
|
||||
public :
|
||||
auto_next (pn_data_t *);
|
||||
auto_next (const auto_next &) = delete;
|
||||
|
||||
~auto_next();
|
||||
};
|
||||
|
||||
class auto_list_enter {
|
||||
private :
|
||||
size_t m_elements;
|
||||
pn_data_t * m_data;
|
||||
|
||||
public :
|
||||
auto_list_enter (pn_data_t *, bool next_ = false);
|
||||
~auto_list_enter();
|
||||
|
||||
size_t elements() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace proton {
|
||||
|
||||
template<typename T>
|
||||
T
|
||||
readAndNext (pn_data_t * data_, bool tolerateDeviance_ = false) {
|
||||
return T{};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
19
experimental/cpp-serializer/src/serialiser/Composite.h
Normal file
19
experimental/cpp-serializer/src/serialiser/Composite.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp {
|
||||
namespace internal {
|
||||
namespace serialiser {
|
||||
|
||||
template <typename T>
|
||||
class Composite : public ProtonReader<T> {
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
24
experimental/cpp-serializer/src/serialiser/ProtonReader.h
Normal file
24
experimental/cpp-serializer/src/serialiser/ProtonReader.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct pn_data_t;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
namespace amqp {
|
||||
namespace internal {
|
||||
namespace serialiser {
|
||||
|
||||
class ProtonReader {
|
||||
public :
|
||||
template<typename T>
|
||||
virtual T read (pn_data_t *) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
Loading…
Reference in New Issue
Block a user