From 8f7346f84c5aa87453fbd8dbefcf45e282b6da4d Mon Sep 17 00:00:00 2001 From: Katelyn Baker Date: Fri, 13 Dec 2019 00:32:25 +0000 Subject: [PATCH] NOTICK - Add C++ Serialiser Support for Maps and Arrays (#5775) Adds support for understanding both Maps and Arrays Irritatingly, whilst arrays are mostly serialized as lists, we cannot simply use a restricted List reader to deserialize them because there are subtle differences in the way we need to work out if its actually a restricted type or not. Rather than add a bunch of random logic into the factory method I've isolated it in the class hierarchy. So a little bit more code makes the implementations a lot neater. We also need to deal with the fact arras of unboxed primitives exist, which whilst Java really gets excited about, we don't need to care about. An int, is an int, is an int!. Map support required we add a slightly better Value dumper, essentially the "key" component of the KV pair needs to be more flexible than a simple string when we're dumping out param:value pairs. Testing Added a lot more unit tests to both the ordered type notation code to ensure we build up the schema dependency struct in the correct order. Quite important as we rely on that in the composite factory to be strictly ordered to ensure we're not constructing a reader for a type we don't yet understand... and there were some small bugs in the version that predates this PR Also added a lot higher level tests to ensure actual reading out of the blob works --- .../kotlin/net/corda/blobwriter/BlobWriter.kt | 109 +++++++-- experimental/cpp-serializer/bin/.gitignore | 1 + .../bin/blob-inspector/.gitignore | 2 + .../bin/blob-inspector/BlobInspector.cxx | 73 ++++++ .../blob-inspector/BlobInspector.h} | 23 +- .../bin/blob-inspector/CMakeLists.txt | 14 +- .../bin/blob-inspector/CordaBytes.cxx | 38 ++++ .../bin/blob-inspector/CordaBytes.h | 31 +++ .../bin/blob-inspector/main.cxx | 88 +------- .../bin/blob-inspector/test/.gitignore | 1 + .../bin/blob-inspector/test/CMakeLists.txt | 17 ++ .../bin/blob-inspector/test/IntList | Bin 425 -> 0 bytes .../bin/blob-inspector/test/IntListStringList | Bin 683 -> 0 bytes .../bin/blob-inspector/test/ListOfComposite | Bin 798 -> 0 bytes .../bin/blob-inspector/test/ListOfComposites | Bin 1748 -> 0 bytes .../test/ListOfListOfComposites | Bin 2815 -> 0 bytes .../blob-inspector/test/ListOfListOfListOfInt | Bin 1103 -> 0 bytes .../bin/blob-inspector/test/ListOfStringList | Bin 689 -> 0 bytes .../bin/blob-inspector/test/OneComposite | Bin 479 -> 0 bytes .../blob-inspector/test/OneCompositeOneString | Bin 530 -> 0 bytes .../bin/blob-inspector/test/OneInt | Bin 234 -> 0 bytes .../bin/blob-inspector/test/TwoIntLists | Bin 512 -> 0 bytes .../bin/blob-inspector/test/TwoInts | Bin 268 -> 0 bytes .../test/blob-inspector-test.cxx | 171 ++++++++++++++ .../bin/blob-inspector/test/main.cxx | 7 + .../bin/blob-inspector/test/manyTypes | Bin 1354 -> 0 bytes .../cpp-serializer/bin/schema-dumper/main.cxx | 8 +- .../cpp-serializer/bin/test-files/_ALd_ | Bin 0 -> 649 bytes .../cpp-serializer/bin/test-files/_Ai_ | Bin 0 -> 364 bytes .../cpp-serializer/bin/test-files/_Ci_ | Bin 0 -> 346 bytes .../cpp-serializer/bin/test-files/_L_i__ | Bin 0 -> 679 bytes .../{blob-inspector/test => test-files}/_Le_ | Bin .../{blob-inspector/test => test-files}/_Le_2 | Bin .../{blob-inspector/test => test-files}/_Li_ | Bin .../cpp-serializer/bin/test-files/_MiLs_ | Bin 0 -> 673 bytes .../cpp-serializer/bin/test-files/_Mi_is__ | Bin 0 -> 740 bytes .../{blob-inspector/test => test-files}/_Mis_ | Bin .../cpp-serializer/bin/test-files/_Oi_ | Bin 0 -> 213 bytes .../cpp-serializer/bin/test-files/_Pls_ | Bin 0 -> 595 bytes .../bin/test-files/__i_LMis_l__ | Bin 0 -> 1087 bytes .../{blob-inspector/test => test-files}/_e_ | Bin .../cpp-serializer/bin/test-files/_i_ | Bin 0 -> 214 bytes .../test => test-files}/_i_is__ | Bin .../cpp-serializer/bin/test-files/_l_ | Bin 0 -> 222 bytes .../cpp-serializer/include/amqp/AMQPHeader.h | 2 +- .../include/amqp/reader/IReader.h | 2 +- .../include/amqp/schema/Descriptors.h | 34 +++ .../include/amqp/serializable/ISerializable.h | 10 + experimental/cpp-serializer/include/debug.h | 2 +- experimental/cpp-serializer/lines | 2 + experimental/cpp-serializer/rem_cmake | 4 + .../cpp-serializer/src/CMakeLists.txt | 1 - .../cpp-serializer/src/amqp/CMakeLists.txt | 56 +++-- .../src/amqp/CompositeFactory.cxx | 178 +++++++++------ .../src/amqp/CompositeFactory.h | 17 +- .../descriptors/AMQPDescriptorRegistory.cxx | 156 ------------- .../src/amqp/reader/CompositeReader.cxx | 25 ++- .../src/amqp/reader/CompositeReader.h | 2 +- .../src/amqp/reader/PropertyReader.cxx | 15 +- .../src/amqp/reader/PropertyReader.h | 5 +- .../cpp-serializer/src/amqp/reader/Reader.cxx | 32 ++- .../cpp-serializer/src/amqp/reader/Reader.h | 61 ++++- .../property-readers/BoolPropertyReader.cxx | 2 +- .../property-readers/DoublePropertyReader.cxx | 8 +- .../property-readers/IntPropertyReader.cxx | 12 +- .../property-readers/LongPropertyReader.cxx | 12 +- .../property-readers/StringPropertyReader.cxx | 8 +- .../reader/restricted-readers/ArrayReader.cxx | 86 +++++++ .../reader/restricted-readers/ArrayReader.h | 44 ++++ .../reader/restricted-readers/EnumReader.cxx | 9 +- .../reader/restricted-readers/ListReader.cxx | 10 +- .../reader/restricted-readers/MapReader.cxx | 82 +++++++ .../reader/restricted-readers/MapReader.h | 47 ++++ .../src/amqp/schema/AMQPTypeNotation.cxx | 6 +- .../src/amqp/schema/AMQPTypeNotation.h | 15 +- .../src/amqp/schema/Descriptors.cxx | 21 ++ .../cpp-serializer/src/amqp/schema/Field.cxx | 109 --------- .../cpp-serializer/src/amqp/schema/Field.h | 63 ------ .../src/amqp/schema/OrderedTypeNotations.h | 14 +- .../schema/{ => described-types}/Choice.cxx | 11 + .../schema/{ => described-types}/Choice.h | 8 +- .../{ => described-types}/Composite.cxx | 64 +++--- .../schema/{ => described-types}/Composite.h | 8 +- .../{ => described-types}/Descriptor.cxx | 0 .../schema/{ => described-types}/Descriptor.h | 2 - .../schema/{ => described-types}/Envelope.cxx | 2 +- .../schema/{ => described-types}/Envelope.h | 2 +- .../schema/{ => described-types}/Schema.cxx | 0 .../schema/{ => described-types}/Schema.h | 10 +- .../descriptors/AMQPDescriptor.cxx | 14 +- .../{ => schema}/descriptors/AMQPDescriptor.h | 25 +-- .../descriptors/AMQPDescriptorRegistory.cxx | 133 +++++++++++ .../descriptors/AMQPDescriptorRegistory.h | 35 +-- .../descriptors/AMQPDescriptors.cxx | 21 +- .../descriptors/AMQPDescriptors.h | 21 +- .../corda-descriptors/ChoiceDescriptor.cxx | 10 +- .../corda-descriptors/ChoiceDescriptor.h | 6 +- .../corda-descriptors/CompositeDescriptor.cxx | 20 +- .../corda-descriptors/CompositeDescriptor.h | 6 +- .../corda-descriptors/EnvelopeDescriptor.cxx | 20 +- .../corda-descriptors/EnvelopeDescriptor.h | 4 +- .../corda-descriptors/FieldDescriptor.cxx | 22 +- .../corda-descriptors/FieldDescriptor.h | 6 +- .../corda-descriptors/ObjectDescriptor.cxx | 16 +- .../corda-descriptors/ObjectDescriptor.h | 6 +- .../RestrictedDescriptor.cxx | 81 ++++++- .../corda-descriptors/RestrictedDescriptor.h | 17 +- .../corda-descriptors/SchemaDescriptor.cxx | 18 +- .../corda-descriptors/SchemaDescriptor.h | 6 +- .../amqp/schema/field-types/ArrayField.cxx | 54 +++++ .../src/amqp/schema/field-types/ArrayField.h | 24 ++ .../schema/field-types/CompositeField.cxx | 63 ++++++ .../amqp/schema/field-types/CompositeField.h | 25 +++ .../src/amqp/schema/field-types/Field.cxx | 153 +++++++++++++ .../src/amqp/schema/field-types/Field.h | 65 ++++++ .../schema/field-types/PrimitiveField.cxx | 55 +++++ .../amqp/schema/field-types/PrimitiveField.h | 25 +++ .../schema/field-types/RestrictedField.cxx | 56 +++++ .../amqp/schema/field-types/RestrictedField.h | 25 +++ .../amqp/schema/restricted-types/Array.cxx | 169 ++++++++++++++ .../src/amqp/schema/restricted-types/Array.h | 41 ++++ .../src/amqp/schema/restricted-types/Enum.cxx | 95 ++++---- .../src/amqp/schema/restricted-types/Enum.h | 11 +- .../src/amqp/schema/restricted-types/List.cxx | 128 +++++++---- .../src/amqp/schema/restricted-types/List.h | 13 +- .../src/amqp/schema/restricted-types/Map.cxx | 171 ++++++++++++++ .../src/amqp/schema/restricted-types/Map.h | 43 ++++ .../schema/restricted-types/Restricted.cxx | 208 ++++++++++++----- .../amqp/schema/restricted-types/Restricted.h | 35 ++- .../src/amqp/test/CMakeLists.txt | 4 + .../cpp-serializer/src/amqp/test/List.cxx | 26 +++ .../cpp-serializer/src/amqp/test/Map.cxx | 212 ++++++++++++++++++ .../src/amqp/test/OrderedTypeNotationTest.cxx | 15 +- .../src/amqp/test/RestrictedDescriptor.cxx | 25 +++ .../cpp-serializer/src/amqp/test/Single.cxx | 7 + .../src/amqp/test/TestUtils.cxx | 126 +++++++++++ .../cpp-serializer/src/amqp/test/TestUtils.h | 23 ++ .../src/proton/proton_wrapper.cxx | 36 ++- .../src/proton/proton_wrapper.h | 17 +- .../src/serialiser/CMakeLists.txt | 0 .../cpp-serializer/src/serialiser/Composite.h | 19 -- 141 files changed, 3322 insertions(+), 976 deletions(-) create mode 100644 experimental/cpp-serializer/bin/.gitignore create mode 100644 experimental/cpp-serializer/bin/blob-inspector/BlobInspector.cxx rename experimental/cpp-serializer/{src/serialiser/ProtonReader.h => bin/blob-inspector/BlobInspector.h} (57%) create mode 100644 experimental/cpp-serializer/bin/blob-inspector/CordaBytes.cxx create mode 100644 experimental/cpp-serializer/bin/blob-inspector/CordaBytes.h create mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/.gitignore create mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/CMakeLists.txt delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/IntList delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/IntListStringList delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/ListOfComposite delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/ListOfComposites delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/ListOfListOfComposites delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/ListOfListOfListOfInt delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/ListOfStringList delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/OneComposite delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/OneCompositeOneString delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/OneInt delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/TwoIntLists delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/TwoInts create mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/blob-inspector-test.cxx create mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/main.cxx delete mode 100644 experimental/cpp-serializer/bin/blob-inspector/test/manyTypes create mode 100644 experimental/cpp-serializer/bin/test-files/_ALd_ create mode 100644 experimental/cpp-serializer/bin/test-files/_Ai_ create mode 100644 experimental/cpp-serializer/bin/test-files/_Ci_ create mode 100644 experimental/cpp-serializer/bin/test-files/_L_i__ rename experimental/cpp-serializer/bin/{blob-inspector/test => test-files}/_Le_ (100%) rename experimental/cpp-serializer/bin/{blob-inspector/test => test-files}/_Le_2 (100%) rename experimental/cpp-serializer/bin/{blob-inspector/test => test-files}/_Li_ (100%) create mode 100644 experimental/cpp-serializer/bin/test-files/_MiLs_ create mode 100644 experimental/cpp-serializer/bin/test-files/_Mi_is__ rename experimental/cpp-serializer/bin/{blob-inspector/test => test-files}/_Mis_ (100%) create mode 100644 experimental/cpp-serializer/bin/test-files/_Oi_ create mode 100644 experimental/cpp-serializer/bin/test-files/_Pls_ create mode 100644 experimental/cpp-serializer/bin/test-files/__i_LMis_l__ rename experimental/cpp-serializer/bin/{blob-inspector/test => test-files}/_e_ (100%) create mode 100644 experimental/cpp-serializer/bin/test-files/_i_ rename experimental/cpp-serializer/bin/{blob-inspector/test => test-files}/_i_is__ (100%) create mode 100644 experimental/cpp-serializer/bin/test-files/_l_ create mode 100644 experimental/cpp-serializer/include/amqp/schema/Descriptors.h create mode 100644 experimental/cpp-serializer/include/amqp/serializable/ISerializable.h create mode 100755 experimental/cpp-serializer/lines delete mode 100644 experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptorRegistory.cxx create mode 100644 experimental/cpp-serializer/src/amqp/reader/restricted-readers/ArrayReader.cxx create mode 100644 experimental/cpp-serializer/src/amqp/reader/restricted-readers/ArrayReader.h create mode 100644 experimental/cpp-serializer/src/amqp/reader/restricted-readers/MapReader.cxx create mode 100644 experimental/cpp-serializer/src/amqp/reader/restricted-readers/MapReader.h create mode 100644 experimental/cpp-serializer/src/amqp/schema/Descriptors.cxx delete mode 100644 experimental/cpp-serializer/src/amqp/schema/Field.cxx delete mode 100644 experimental/cpp-serializer/src/amqp/schema/Field.h rename experimental/cpp-serializer/src/amqp/schema/{ => described-types}/Choice.cxx (62%) rename experimental/cpp-serializer/src/amqp/schema/{ => described-types}/Choice.h (74%) rename experimental/cpp-serializer/src/amqp/schema/{ => described-types}/Composite.cxx (83%) rename experimental/cpp-serializer/src/amqp/schema/{ => described-types}/Composite.h (91%) rename experimental/cpp-serializer/src/amqp/schema/{ => described-types}/Descriptor.cxx (100%) rename experimental/cpp-serializer/src/amqp/schema/{ => described-types}/Descriptor.h (94%) rename experimental/cpp-serializer/src/amqp/schema/{ => described-types}/Envelope.cxx (96%) rename experimental/cpp-serializer/src/amqp/schema/{ => described-types}/Envelope.h (94%) rename experimental/cpp-serializer/src/amqp/schema/{ => described-types}/Schema.cxx (100%) rename experimental/cpp-serializer/src/amqp/schema/{ => described-types}/Schema.h (86%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/AMQPDescriptor.cxx (89%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/AMQPDescriptor.h (80%) create mode 100644 experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptorRegistory.cxx rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/AMQPDescriptorRegistory.h (55%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/AMQPDescriptors.cxx (83%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/AMQPDescriptors.h (89%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/ChoiceDescriptor.cxx (76%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/ChoiceDescriptor.h (78%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/CompositeDescriptor.cxx (89%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/CompositeDescriptor.h (79%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/EnvelopeDescriptor.cxx (85%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/EnvelopeDescriptor.h (90%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/FieldDescriptor.cxx (86%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/FieldDescriptor.h (82%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/ObjectDescriptor.cxx (79%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/ObjectDescriptor.h (83%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/RestrictedDescriptor.cxx (60%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/RestrictedDescriptor.h (59%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/SchemaDescriptor.cxx (83%) rename experimental/cpp-serializer/src/amqp/{ => schema}/descriptors/corda-descriptors/SchemaDescriptor.h (81%) create mode 100644 experimental/cpp-serializer/src/amqp/schema/field-types/ArrayField.cxx create mode 100644 experimental/cpp-serializer/src/amqp/schema/field-types/ArrayField.h create mode 100644 experimental/cpp-serializer/src/amqp/schema/field-types/CompositeField.cxx create mode 100644 experimental/cpp-serializer/src/amqp/schema/field-types/CompositeField.h create mode 100644 experimental/cpp-serializer/src/amqp/schema/field-types/Field.cxx create mode 100644 experimental/cpp-serializer/src/amqp/schema/field-types/Field.h create mode 100644 experimental/cpp-serializer/src/amqp/schema/field-types/PrimitiveField.cxx create mode 100644 experimental/cpp-serializer/src/amqp/schema/field-types/PrimitiveField.h create mode 100644 experimental/cpp-serializer/src/amqp/schema/field-types/RestrictedField.cxx create mode 100644 experimental/cpp-serializer/src/amqp/schema/field-types/RestrictedField.h create mode 100644 experimental/cpp-serializer/src/amqp/schema/restricted-types/Array.cxx create mode 100644 experimental/cpp-serializer/src/amqp/schema/restricted-types/Array.h create mode 100644 experimental/cpp-serializer/src/amqp/schema/restricted-types/Map.cxx create mode 100644 experimental/cpp-serializer/src/amqp/schema/restricted-types/Map.h create mode 100644 experimental/cpp-serializer/src/amqp/test/List.cxx create mode 100644 experimental/cpp-serializer/src/amqp/test/Map.cxx create mode 100644 experimental/cpp-serializer/src/amqp/test/RestrictedDescriptor.cxx create mode 100644 experimental/cpp-serializer/src/amqp/test/TestUtils.cxx create mode 100644 experimental/cpp-serializer/src/amqp/test/TestUtils.h delete mode 100644 experimental/cpp-serializer/src/serialiser/CMakeLists.txt delete mode 100644 experimental/cpp-serializer/src/serialiser/Composite.h diff --git a/experimental/blobwriter/src/main/kotlin/net/corda/blobwriter/BlobWriter.kt b/experimental/blobwriter/src/main/kotlin/net/corda/blobwriter/BlobWriter.kt index 53c30cc72c..3594ad43a7 100644 --- a/experimental/blobwriter/src/main/kotlin/net/corda/blobwriter/BlobWriter.kt +++ b/experimental/blobwriter/src/main/kotlin/net/corda/blobwriter/BlobWriter.kt @@ -1,3 +1,5 @@ +@file:Suppress("ClassNaming", "MagicNumber") + package net.corda.blobwriter import net.corda.core.serialization.SerializationContext @@ -43,27 +45,108 @@ fun initialiseSerialization() { ) } -data class IntClass (val a: Int) -data class IntStrClass (val a: Int, val b: String) -data class IntIntStrClass (val a: Int, val b: IntStrClass) -data class IntListClass (val a: List) -data class IntStringMapClass (val a: Map) +data class _i_ (val a: Int) +@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") +data class _Oi_ (val a: Integer) +data class _l_ (val x: Long) +data class _Ai_ (val z : Array) +data class _Ci_ (val z : IntArray) +data class _is_ (val a: Int, val b: String) +data class _i_is__ (val a: Int, val b: _is_) +data class _Li_ (val a: List) +data class _Mis_ (val a: Map) +data class _Mi_is__ (val a: Map) +data class _MiLs_ (val a: Map>) +data class __i_LMis_l__ (val z : _i_, val x : List>, val y : _l_ ) +data class _LAi_ (val l : List>) + + + enum class E { A, B, C } -data class EnumClass (val e: E) -data class EnumListClass (val listy: List) + +data class _Pls_ (val a : Pair) + +data class _e_ (val e: E) +data class _Le_ (val listy: List) +data class _L_i__ (val listy: List<_i_>) + +data class _ALd_ (val a: Array>) fun main (args: Array) { initialiseSerialization() + val path = "../cpp-serializer/bin/test-files"; + File("$path/_i_").writeBytes (_i_ (69).serialize().bytes) + File("$path/_Oi_").writeBytes (_Oi_ (Integer (1)).serialize().bytes) + File("$path/_l_").writeBytes (_l_ (100000000000L).serialize().bytes) + File("$path/_Li_").writeBytes (_Li_(listOf (1, 2, 3, 4, 5, 6)).serialize().bytes) + File("$path/_Ai_").writeBytes (_Ai_(arrayOf (1, 2, 3, 4, 5, 6)).serialize().bytes) - File("../cpp-serializer/bin/blob-inspector/test/_i_is__").writeBytes(IntIntStrClass(1, IntStrClass (2, "three")).serialize().bytes) - File("../cpp-serializer/bin/blob-inspector/test/_Li_").writeBytes(IntListClass(listOf (1, 2, 3, 4, 5, 6)).serialize().bytes) - File("../cpp-serializer/bin/blob-inspector/test/_Mis_").writeBytes(IntStringMapClass( + val v = IntArray(3) + v[0] = 1; v[1] = 2; v[2] = 3 + + File("$path/_Ci_").writeBytes (_Ci_(v).serialize().bytes) + + File("$path/_Le_").writeBytes (_Le_(listOf (E.A, E.B, E.C)).serialize().bytes) + File("$path/_Le_2").writeBytes (_Le_(listOf (E.A, E.B, E.C, E.B, E.A)).serialize().bytes) + File("$path/_L_i__").writeBytes( + _L_i__(listOf ( + _i_ (1), + _i_ (2), + _i_ (3)) + ).serialize().bytes) + + File("$path/_ALd_").writeBytes( _ALd_ (arrayOf( + listOf (10.1, 11.2, 12.3), + listOf (), + listOf (13.4) + )).serialize().bytes) + + + File ("$path/_i_is__").writeBytes(_i_is__(1, _is_ (2, "three")).serialize().bytes) + File ("$path/_Mis_").writeBytes(_Mis_( mapOf (1 to "two", 3 to "four", 5 to "six")).serialize().bytes) - File("../cpp-serializer/bin/blob-inspector/test/_e_").writeBytes(EnumClass(E.A).serialize().bytes) - File("../cpp-serializer/bin/blob-inspector/test/_Le_").writeBytes(EnumListClass(listOf (E.A, E.B, E.C)).serialize().bytes) - File("../cpp-serializer/bin/blob-inspector/test/_Le_2").writeBytes(EnumListClass(listOf (E.A, E.B, E.C, E.B, E.A)).serialize().bytes) + File ("$path/_e_").writeBytes(_e_(E.A).serialize().bytes) + + File ("$path/_Pls_").writeBytes(_Pls_(Pair (1, "two")).serialize().bytes) + File ("$path/_Mi_is__").writeBytes( + _Mi_is__ (mapOf ( + 1 to _is_ (2, "three"), + 4 to _is_ (5, "six"), + 7 to _is_ (8, "nine") + ) + ).serialize().bytes) + + File ("$path/_MiLs_").writeBytes( + _MiLs_ (mapOf ( + 1 to listOf ("two", "three", "four"), + 5 to listOf ("six"), + 7 to listOf () + ) + ).serialize().bytes) + + + File ("$path/__i_LMis_l__").writeBytes ( + __i_LMis_l__ ( + _i_ (666), + listOf ( + mapOf ( + 1 to "two", + 3 to "four", + 5 to "six" + ), + mapOf ( + 7 to "eight", + 9 to "ten" + ) + ), + _l_ (1000000L) + ).serialize().bytes + + ) + + } diff --git a/experimental/cpp-serializer/bin/.gitignore b/experimental/cpp-serializer/bin/.gitignore new file mode 100644 index 0000000000..10301e28bf --- /dev/null +++ b/experimental/cpp-serializer/bin/.gitignore @@ -0,0 +1 @@ +*.a diff --git a/experimental/cpp-serializer/bin/blob-inspector/.gitignore b/experimental/cpp-serializer/bin/blob-inspector/.gitignore index d957b6a0ef..df569212ea 100644 --- a/experimental/cpp-serializer/bin/blob-inspector/.gitignore +++ b/experimental/cpp-serializer/bin/blob-inspector/.gitignore @@ -1 +1,3 @@ blob-inspector + +*.a diff --git a/experimental/cpp-serializer/bin/blob-inspector/BlobInspector.cxx b/experimental/cpp-serializer/bin/blob-inspector/BlobInspector.cxx new file mode 100644 index 0000000000..f7e65ee451 --- /dev/null +++ b/experimental/cpp-serializer/bin/blob-inspector/BlobInspector.cxx @@ -0,0 +1,73 @@ +#include "BlobInspector.h" +#include "CordaBytes.h" + +#include +#include + +#include "proton/codec.h" +#include "proton/proton_wrapper.h" + +#include "amqp/schema/descriptors/AMQPDescriptorRegistory.h" + +#include "amqp/CompositeFactory.h" +#include "amqp/schema/described-types/Envelope.h" + +/******************************************************************************/ + +BlobInspector::BlobInspector (CordaBytes & cb_) + : m_data { pn_data (cb_.size()) } +{ + // 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 (m_data, cb_.bytes(), cb_.size()); + assert (rtn == cb_.size()); +} + +/******************************************************************************/ + +std::string +BlobInspector::dump() { + std::unique_ptr envelope; + + if (pn_data_is_described (m_data)) { + proton::auto_enter p (m_data); + + auto a = pn_data_get_ulong(m_data); + + envelope.reset ( + dynamic_cast ( + amqp::internal::AMQPDescriptorRegistory[a]->build(m_data).release())); + } + + amqp::internal::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 (m_data); + pn_data_next (m_data); + proton::is_list (m_data); + assert (pn_data_get_list (m_data) == 3); + { + proton::auto_enter p (m_data); + + std::stringstream ss; + + // We wrap our output like this to make sure it's valid JSON to + // facilitate easy pretty printing + ss << reader->dump ("{ Parsed", m_data, envelope->schema())->dump() + << " }"; + + return ss.str(); + } + } +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/serialiser/ProtonReader.h b/experimental/cpp-serializer/bin/blob-inspector/BlobInspector.h similarity index 57% rename from experimental/cpp-serializer/src/serialiser/ProtonReader.h rename to experimental/cpp-serializer/bin/blob-inspector/BlobInspector.h index 74e7b8a16e..6936ed337d 100644 --- a/experimental/cpp-serializer/src/serialiser/ProtonReader.h +++ b/experimental/cpp-serializer/bin/blob-inspector/BlobInspector.h @@ -1,24 +1,23 @@ #pragma once +#include +#include "CordaBytes.h" + /******************************************************************************/ struct pn_data_t; /******************************************************************************/ -namespace amqp { -namespace internal { -namespace serialiser { +class BlobInspector { + private : + pn_data_t * m_data; - class ProtonReader { - public : - template - virtual T read (pn_data_t *) { - } - } + public : + BlobInspector (CordaBytes &); -} -} -} + std::string dump(); + +}; /******************************************************************************/ diff --git a/experimental/cpp-serializer/bin/blob-inspector/CMakeLists.txt b/experimental/cpp-serializer/bin/blob-inspector/CMakeLists.txt index fe85b44763..3e33b10704 100644 --- a/experimental/cpp-serializer/bin/blob-inspector/CMakeLists.txt +++ b/experimental/cpp-serializer/bin/blob-inspector/CMakeLists.txt @@ -4,6 +4,18 @@ 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) +set (blob-inspector-sources + BlobInspector.cxx + CordaBytes.cxx) + + +add_executable (blob-inspector main.cxx ${blob-inspector-sources}) target_link_libraries (blob-inspector amqp proton qpid-proton) + +# +# Unit tests for the blob inspector. For this to work we also need to create +# a linkable library from the code here to link into our test. +# +add_library (blob-inspector-lib ${blob-inspector-sources} ) +ADD_SUBDIRECTORY (test) diff --git a/experimental/cpp-serializer/bin/blob-inspector/CordaBytes.cxx b/experimental/cpp-serializer/bin/blob-inspector/CordaBytes.cxx new file mode 100644 index 0000000000..0942c5f9d1 --- /dev/null +++ b/experimental/cpp-serializer/bin/blob-inspector/CordaBytes.cxx @@ -0,0 +1,38 @@ +#include "CordaBytes.h" + +#include +#include +#include "amqp/AMQPHeader.h" + +/******************************************************************************/ + +CordaBytes::CordaBytes (const std::string & file_) + : m_blob { nullptr } +{ + std::ifstream file { file_, std::ios::in | std::ios::binary }; + struct stat results { }; + + if (::stat(file_.c_str(), &results) != 0) { + throw std::runtime_error ("Not a file"); + } + + // Disregard the Corda header + m_size = results.st_size - (amqp::AMQP_HEADER.size() + 1); + + std::array header { }; + file.read (header.data(), 7); + + if (header != amqp::AMQP_HEADER) { + throw std::runtime_error ("Not a Corda stream"); + } + + file.read (reinterpret_cast(&m_encoding), 1); + + m_blob = new char[m_size]; + + memset (m_blob, 0, m_size); + file.read (m_blob, m_size); +} + +/******************************************************************************/ + diff --git a/experimental/cpp-serializer/bin/blob-inspector/CordaBytes.h b/experimental/cpp-serializer/bin/blob-inspector/CordaBytes.h new file mode 100644 index 0000000000..043e35883c --- /dev/null +++ b/experimental/cpp-serializer/bin/blob-inspector/CordaBytes.h @@ -0,0 +1,31 @@ +#pragma once + +#include "string" +#include +#include "amqp/AMQPSectionId.h" + +/******************************************************************************/ + +class CordaBytes { + private : + amqp::amqp_section_id_t m_encoding; + size_t m_size; + char * m_blob; + + public : + explicit CordaBytes (const std::string &); + + ~CordaBytes() { + delete [] m_blob; + } + + const decltype (m_encoding) & encoding() const { + return m_encoding; + } + + decltype (m_size) size() const { return m_size; } + + const char * const bytes() const { return m_blob; } +}; + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/bin/blob-inspector/main.cxx b/experimental/cpp-serializer/bin/blob-inspector/main.cxx index 1ad4675f27..e2a441af83 100644 --- a/experimental/cpp-serializer/bin/blob-inspector/main.cxx +++ b/experimental/cpp-serializer/bin/blob-inspector/main.cxx @@ -9,74 +9,18 @@ #include #include -#import "debug.h" +#include "debug.h" #include "proton/proton_wrapper.h" #include "amqp/AMQPHeader.h" #include "amqp/AMQPSectionId.h" -#include "amqp/descriptors/AMQPDescriptorRegistory.h" +#include "amqp/schema/descriptors/AMQPDescriptorRegistory.h" -#include "amqp/schema/Envelope.h" +#include "amqp/schema/described-types/Envelope.h" #include "amqp/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 envelope; - - if (pn_data_is_described(d)) { - proton::auto_enter p (d); - - auto a = pn_data_get_ulong(d); - - envelope.reset ( - dynamic_cast ( - amqp::AMQPDescriptorRegistory[a]->build(d).release())); - - DBG (std::endl << "Types in schema: " << std::endl - << *envelope << std::endl); // NOLINT - } - - amqp::internal::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; - } - } -} +#include "CordaBytes.h" +#include "BlobInspector.h" /******************************************************************************/ @@ -88,22 +32,14 @@ main (int argc, char **argv) { return EXIT_FAILURE; } - std::ifstream f (argv[1], std::ios::in | std::ios::binary); - std::array 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); + CordaBytes cb (argv[1]); + + if (cb.encoding() == amqp::DATA_AND_STOP) { + BlobInspector blobInspector (cb); + auto val = blobInspector.dump(); + std::cout << val << std::endl; } else { - std::cerr << "BAD ENCODING " << encoding << " != " + std::cerr << "BAD ENCODING " << cb.encoding() << " != " << amqp::DATA_AND_STOP << std::endl; return EXIT_FAILURE; diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/.gitignore b/experimental/cpp-serializer/bin/blob-inspector/test/.gitignore new file mode 100644 index 0000000000..464efcbd02 --- /dev/null +++ b/experimental/cpp-serializer/bin/blob-inspector/test/.gitignore @@ -0,0 +1 @@ +blob-inspector-test diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/CMakeLists.txt b/experimental/cpp-serializer/bin/blob-inspector/test/CMakeLists.txt new file mode 100644 index 0000000000..650c36d53f --- /dev/null +++ b/experimental/cpp-serializer/bin/blob-inspector/test/CMakeLists.txt @@ -0,0 +1,17 @@ +set (EXE "blob-inspector-test") + +set (blob-inspector-test-sources + main.cxx + blob-inspector-test.cxx +) + +link_directories (${BLOB-INSPECTOR_BINARY_DIR}/bin/blob-inspector) +include_directories (${BLOB-INSPECTOR_BINARY_DIR}/bin/blob-inspector) + +add_executable (${EXE} ${blob-inspector-test-sources}) + +target_link_libraries (${EXE} gtest amqp blob-inspector-lib) + +if (UNIX) + target_link_libraries (${EXE} pthread qpid-proton proton) +endif (UNIX) diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/IntList b/experimental/cpp-serializer/bin/blob-inspector/test/IntList deleted file mode 100644 index f73c5b47800c2a078342592367af525c0efe1602..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 425 zcmYe!FG@*dWME)uIGO|`85kHZ0P!RsgPCEmQeJ9_UNT69RgRaXSz3~BPNKJ&S$KtC zP?1xaXIh}G?E!m66m@2PNhSFyzWE_#K`F@<*&f;DzC{)wb>gfcDTP2|PXGx<9S|`A zM0|l;%mlKS2j&81AcF}m$9iBI>q1?)YxIg!i!u{)GOH3xGV}BFGV@AOi}Dh4^b&Im z3-mnmN_;YlOB`I`x|t8CF%jbzhXV$Ta7`=+l-U%tYq!Lz+I1mI h4$vyN@#wz56{koZ$7(*zA%x7w6`4rpa~@=5008N4$y5LU diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/ListOfComposite b/experimental/cpp-serializer/bin/blob-inspector/test/ListOfComposite deleted file mode 100644 index 6124bff058815ac8d55d7c0e3c728fb5a8fbd0b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 798 zcmYe!FG@*dWME)uIGO|`85kHZFfcH)0~yQ=id)ip$;0ZEX*%WkgX|=Hj0n?CTTeR%o1G5)cuj9hey96$n(kx3ECZC$qT3Kg~Hmw;;bbvn18Q z6>bCb0W~IKLeSwr6eC;{%K=~Zg^Y;{8MO{LFfO#sN-Rs%D=o>)0o!9koRdPz^F8xQ zitQX69G&0>vmK~rqtratg)BKh@50SQ_aUyhM+y|y1M^uI>XPISB;Dv1;z}3}2P~Q3 fu4FkN01i@SV8ppDWHdky6^LBYLTqxJ2N@XvZc6*3 diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/ListOfComposites b/experimental/cpp-serializer/bin/blob-inspector/test/ListOfComposites deleted file mode 100644 index 966603d96b544b07ecd7c74b00ac8a018805c6a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1748 zcmb_c&2G~`81&j+SH1B9TsZX5fLoHP4TvDei6gm*lO|Yo;bx~!>f)a`-r6c$DkPo* zt#|;gT#%LncOHpNge-4_LkhWAEAQ-l^UXKA<7j?q1CHbFemL~Yao{J%N#E!~;66VJ zT_leei04(qs@E<@C&(Uay4yUj$2F@nY&0mE-=k=rL8tA(+gC>Kyc5?VbapYS4DC0k z6iq&|tk;3=^ruO+-!xj&VOQ0z0xxP(9OO-4vYhL%f+;ff*I}V4G1v^<9$8Q8p?aw5 zy>5Kk$`1TC)j&G~J=z(|9C)+7g{;c)?M2c_^;SQc`$rj7TmcO00~>>V zq5#~uwo_ZaL7u-X^kOqjW)|roN?s~TQ!NmWD6z93)&N%jiFgpYd8aJ9MBYpPt5(CJ zPuSneTGf<#d^{(vBDx?ka35(=p>D}XvOVeCyOspaK0P(%fuMu7L QY%1hoQFQshcfSMf7X`;M@&Et; diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/ListOfListOfComposites b/experimental/cpp-serializer/bin/blob-inspector/test/ListOfListOfComposites deleted file mode 100644 index ed50baec316406578431549e162532a6922ff8c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2815 zcmd6oNpI6Y6vsVD?9j56ecuY=Kt)6r3RF#HXC+Ou(P?QaIM_)D&SEFAlaz8nLYz4A z0g%NNBtF7$K;p=~Ux1InBv8xaV8<$<;$nIEdH(Oc|C=`@xl`r=MNzN53iwJ<;5$W4 z|G+nH>cgy5QGKNWu~7DBAFm5rfnthl&Ub?Mib}4<^}}II(`8J%2)e4u{Bl~E6U+T% z+aHm;`Ft^77}DU$2;Gb2>Z_TR^+Y=;tND#ba|M2L8Pn(u8AGj^60%h#kmWMbY9Sqo zKW~aMhdJ5>0VE@^W8Kh0L~F;=kRjMf#Oj3yh&Ao>r{J_>_8>e&u!7jDuXU5vP&%7! z`MJb)D5ombp$qQMBQ6x{Tr9?COM$2o6jIW|L`Z#+$JNCSgO4Nh{dAd=WA+R@OR)d1 ztLNZ(B2v2wT!0rHvzOpyg56J7ufVH>wp~uw;H+czI=rC|XxCumF5nG0nAEf%-+1+J z^kB2D;#ah`sLyVnQt60%L)_+7QI>q7q*gi--|+FxcFVUSDr)Z8uWM9pwq!+AD+(Le zmvp0>E++>8i*{W4PagEts{vjEw@@BvnHt~YeO*;-4CNM0kIn*xeK{qm%F+_cauI`2 z1q%rSp$(v|nN~JEIukP0!X(I`x6Gsyiff(*wn0zITym?^)Zh|>UNTyEPxtA-g@ zNvng|PzwgVX0-U83^h0KSYxfu2tznD`bKMaof&J=H>_ed*lIMhXcOqW!GkipvxEhI M+vCRWnEC>!pGd@*6#xJL diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/ListOfListOfListOfInt b/experimental/cpp-serializer/bin/blob-inspector/test/ListOfListOfListOfInt deleted file mode 100644 index 3dfc7ad4dbf93de099a600f1c3c2b0c0aa0a6e96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1103 zcmbW0%TB^T6ozL?sp4Jnmbg>n!bKG^4N*&q2oV%SbHK}P3MDC*R%*S#%2#mjrtw9_ zL^rN{B#WAcVhY5~WG3^^cm6r^Pf<5Y1S5nV-(`D52!A5PM(l|Xy)0{r$rsy-oeM$8 zm0QVd>MEa4AISBb9y$_EMbTE{kM=Q_TGMldLcXkQCiR$HDTJyQ*YSZ661_pe|hzN_u^UfTAe(WoTF_8lBY8{GdW y35%`S7j#J7xAFQ19Sz_p;jEPbJWKtGdBx0C?3A;DUB%iR=?nMDS_eGviqRJ&Xj;Vp diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/ListOfStringList b/experimental/cpp-serializer/bin/blob-inspector/test/ListOfStringList deleted file mode 100644 index acb328c64f0195d4e55d11175501c2a1e2751439..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 689 zcmYe!FG@*dWME)uIGO|`85kHZFfcI90y3Bx7AxhYmgpseR9IPNy5@SBm}L6+Rk|m+ z6<4NJ8m0x7+u9!3!HA-+w8+CE#IMq<+%ng&AkxLO)GN!!BOR!20uze50+&R`^6ac+ z?ZCi%=Lo;-WdDj(N0524tP5F6GBS%7G66AjNk-~I*0ju`;*y0dIhn;J#F?SOvXHGf zH90>o1@0}5AQlAMc_C9$DxAv%^fBXXsMi@MfxQk34b}sjSQnbXgF&x2wJ0+&C$lQC zBr`uxFEg(swJ0w!M=vqAut3iT=sy3n;F6-uymS!T!4+-=^8qy`VnWm5fHNap6UzZJ z_Jxdz3mLTzXfiHT%StRu)GIB?%mG_ugT^feTWe?M;Na*4H-YUy3LDWHU7;Zi^E$el fam6f>H`xw^uq_nB?lK2L=Hp5cNak}MWMlvUbv@Y? diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/OneComposite b/experimental/cpp-serializer/bin/blob-inspector/test/OneComposite deleted file mode 100644 index c4b159618d438133200c894b462370dcc243d894..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 479 zcmYe!FG@*dWME)uIGO|`85kHZ0PzVRgPCEmQeJ9_UNT69Rc>a1UwBElwpnFFv0Is^ zvtNEuj!C(#?E!5@6m@B(Wrg1576FmINvUaRZmwm%`T8O0Ky}QFA^C7im_U|YSfjkYAix zlIq|JH-hQZ$VUEfxnTd zLAaw~sY|)7?Ewp>h1?mbIXU?X<@rT9DJYuKO3Mnp%Pj&TeUnnt(%f9jeDn1~(t(oZZNvzaYY1@e>o2_ GG5`QRH=4}= diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/TwoInts b/experimental/cpp-serializer/bin/blob-inspector/test/TwoInts deleted file mode 100644 index ba7fef802a81ff20522267bd43a4db65312df42b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 268 zcmYe!FG@*dWME)uIGO|`85kH3{9tBStdy5pqL&Pkv&zc#O!7-FHu7`ybxsfTc5=3r2N@Xvwt-N4 diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/blob-inspector-test.cxx b/experimental/cpp-serializer/bin/blob-inspector/test/blob-inspector-test.cxx new file mode 100644 index 0000000000..aaf9689225 --- /dev/null +++ b/experimental/cpp-serializer/bin/blob-inspector/test/blob-inspector-test.cxx @@ -0,0 +1,171 @@ +#include +#include "CordaBytes.h" +#include "BlobInspector.h" + +const std::string filepath ("../../test-files/"); // NOLINT + +/****************************************************************************** + * + * mapType Tests + * + ******************************************************************************/ + +void +test (const std::string & file_, const std::string & result_) { + auto path { filepath + file_ } ; + CordaBytes cb (path); + auto val = BlobInspector (cb).dump(); + ASSERT_EQ(result_, val); +} + +/******************************************************************************/ + +/** + * int + */ +TEST (BlobInspector, _i_) { // NOLINT + test ("_i_", "{ Parsed : { a : 69 } }"); +} + +/******************************************************************************/ + +/** + * long + */ +TEST (BlobInspector, _l_) { // NOLINT + test ("_l_", "{ Parsed : { x : 100000000000 } }"); +} + +/******************************************************************************/ + +/** + * int + */ +TEST (BlobInspector, _Oi_) { // NOLINT + test ("_Oi_", "{ Parsed : { a : 1 } }"); +} + +/******************************************************************************/ + +/** + * int + */ +TEST (BlobInspector, _Ai_) { // NOLINT + test ("_Ai_", "{ Parsed : { z : [ 1, 2, 3, 4, 5, 6 ] } }"); +} + +/******************************************************************************/ + +/** + * List of ints + */ +TEST (BlobInspector, _Li_) { // NOLINT + test ("_Li_", "{ Parsed : { a : [ 1, 2, 3, 4, 5, 6 ] } }"); +} + +/******************************************************************************/ + +/** + * List of a class with a single int property + */ +TEST (BlobInspector, _L_i__) { // NOLINT + test ( + "_L_i__", + "{ Parsed : { listy : [ { a : 1 }, { a : 2 }, { a : 3 } ] } }"); +} + +/******************************************************************************/ + +TEST (BlobInspector, _Le_) { // NOLINT + test ("_Le_", "{ Parsed : { listy : [ A, B, C ] } }"); +} + +/******************************************************************************/ + +TEST (BlobInspector,_Le_2) { // NOLINT + EXPECT_THROW ( + { + test ("_Le_2", ""); + }, + std::runtime_error); +} + +/******************************************************************************/ + +/** + * A map of ints to strings + */ +TEST (BlobInspector, _Mis_) { // NOLINT + test ("_Mis_", + R"({ Parsed : { a : { 1 : "two", 3 : "four", 5 : "six" } } })"); +} + +/******************************************************************************/ + +/** + * A map of ints to lists of Strings + */ +TEST (BlobInspector, _MiLs_) { // NOLINT + test ("_MiLs_", + R"({ Parsed : { a : { 1 : [ "two", "three", "four" ], 5 : [ "six" ], 7 : [ ] } } })"); +} + +/******************************************************************************/ + +/** + * a map of ints to a composite with a n int and string property + */ +TEST (BlobInspector, _Mi_is__) { // NOLINT + test ("_Mi_is__", + R"({ Parsed : { a : { 1 : { a : 2, b : "three" }, 4 : { a : 5, b : "six" }, 7 : { a : 8, b : "nine" } } } })"); +} + +/******************************************************************************/ + +TEST (BlobInspector,_Pls_) { // NOLINT + test ("_Pls_", + R"({ Parsed : { a : { first : 1, second : "two" } } })"); +} + +/******************************************************************************/ + +TEST (BlobInspector, _e_) { // NOLINT + test ("_e_", "{ Parsed : { e : A } }"); +} + +/******************************************************************************/ + +TEST (BlobInspector, _i_is__) { // NOLINT + test ("_i_is__", + R"({ Parsed : { a : 1, b : { a : 2, b : "three" } } })"); +} + +/******************************************************************************/ + +// Array of unboxed integers +TEST (BlobInspector, _Ci_) { // NOLINT + test ("_Ci_", + R"({ Parsed : { z : [ 1, 2, 3 ] } })"); +} + +/******************************************************************************/ + +/** + * Composite with + * * one int property + * * one long property + * * one list property that is a list of Maps of int to strings + */ +TEST (BlobInspector, __i_LMis_l__) { // NOLINT + test ("__i_LMis_l__", + R"({ Parsed : { x : [ { 1 : "two", 3 : "four", 5 : "six" }, { 7 : "eight", 9 : "ten" } ], y : { x : 1000000 }, z : { a : 666 } } })"); +} + +/******************************************************************************/ + +TEST (BlobInspector, _ALd_) { // NOLINT + test ("_ALd_", + R"({ Parsed : { a : [ [ 10.100000, 11.200000, 12.300000 ], [ ], [ 13.400000 ] ] } })"); +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/main.cxx b/experimental/cpp-serializer/bin/blob-inspector/test/main.cxx new file mode 100644 index 0000000000..c24c49c028 --- /dev/null +++ b/experimental/cpp-serializer/bin/blob-inspector/test/main.cxx @@ -0,0 +1,7 @@ +#include + +int +main (int argc, char ** argv){ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/manyTypes b/experimental/cpp-serializer/bin/blob-inspector/test/manyTypes deleted file mode 100644 index 4a30f677b3955948199349aa7a0a5f7f4f921240..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1354 zcmbW0%Zk)M6oxBzT#D$zg$sp25TdcYpfHeBk{(8hI;arcNTpNVNl&ay=R&u$Qt?Gf z_dY|paPOlCZe4gXO52Hch;BlWI{#mPedp99FJdAggkFD+;ERy-1tDz&3k7|+$Y^Cw znu@#0c>jvO7&|!$?_WJ!cu8PkyxiRtU-eeqGI>}RcY?s*TNPn)&z&525B6qIXGmPF zlCmR;@X88SkF3It z4xsu)J8ypuT2^h>zSMCY(2bxl!&J?Rbn()i^yM6;wt zO0x8rRB6u4lvT7~Bs0m&#gXZGw!fAuVn-fA-)@dM569?hsVYVWKpT3jv3L38TGkzZSz{1csIBcj?>eL zZF6OdOVS3!a|YL8+S#o9`)xJxac~}td-801J+=tsPM&2N0U54lIrO!|M->+gZv3o> zxe?`gMhWw|HYHg}TO^y2)Bk0%UAHIyw)bp{_sT~88wQt&HFP-s9O@JO_5atOg? #include -#import "debug.h" +#include "debug.h" #include "proton/proton_wrapper.h" #include "amqp/AMQPHeader.h" #include "amqp/AMQPSectionId.h" -#include "amqp/descriptors/AMQPDescriptorRegistory.h" +#include "amqp/schema/descriptors/AMQPDescriptorRegistory.h" -#include "amqp/schema/Envelope.h" +#include "amqp/schema/described-types/Envelope.h" #include "amqp/CompositeFactory.h" /******************************************************************************/ @@ -28,7 +28,7 @@ printNode (pn_data_t * d_) { std::stringstream ss; if (pn_data_is_described (d_)) { - amqp::AMQPDescriptorRegistory[22UL]->read (d_, ss); + amqp::internal::AMQPDescriptorRegistory[22UL]->read (d_, ss); } std::cout << ss.str() << std::endl; diff --git a/experimental/cpp-serializer/bin/test-files/_ALd_ b/experimental/cpp-serializer/bin/test-files/_ALd_ new file mode 100644 index 0000000000000000000000000000000000000000..b488496135e2a5a127fca70a1621219795d5ff26 GIT binary patch literal 649 zcmYe!FG@*dWME)uIGO|`85kHZFfcF`0U68;i*W_=;s{hX8`Zp!$gH$VGt-Kk zsPwRil5)48r0`IuK%hDq<|YRfV=!oPP)h@YCI^j~ATSHXDqKdm5~b<@7h{uy))^2u z3->$|(DRHL&`@BE2ZsVIU|0_{vo4f^hlpNMPJU8(QD#YMkzTx`PfEOlE8H0718Pjf z1fIhI14g(emIKP{3mFp^N@OLLCF+%yWajAkWEPj$q~w<-<)qq0$GSQ=I6A?VvmHoa zTd0Jl7R=2_%uCmEf$4H^UC5FHGzYE`-Ep{L49P!i2SV5uilNyBbr(VNaYYl7`J4wC F836Vb%as5C literal 0 HcmV?d00001 diff --git a/experimental/cpp-serializer/bin/test-files/_Ai_ b/experimental/cpp-serializer/bin/test-files/_Ai_ new file mode 100644 index 0000000000000000000000000000000000000000..45acac0e373abc689ac41e5799f8f5819c31e904 GIT binary patch literal 364 zcmYe!FG@*dWME)uIGO|`85kHZ0C6ag!OXB&DKE7|FBzo5%F#H{Gb+$Mytp7SF~Yex z%g<8VJ1o%F_JAoPiaKBYROb?poGj1K>_k&TGqdCn5AUFIpgLZ*5XKOu5atk;5Y`Yj zxOGei?l2y>$pq)K9>`~1C<(V$FDWNKsk|t&B(+E{-Z3-Y!4X#S&3zddO3-C>3W`dC8_DDMbWVit_xXm VGK)*#D$%XRavo%4005NaX|ezS literal 0 HcmV?d00001 diff --git a/experimental/cpp-serializer/bin/test-files/_Ci_ b/experimental/cpp-serializer/bin/test-files/_Ci_ new file mode 100644 index 0000000000000000000000000000000000000000..be96f5581a6902c42e38b4afda9aefa5cef9b388 GIT binary patch literal 346 zcmYe!FG@*dWME)uIGO|`85kHZ0I@TW!OXB&DKE7|FBzo5%EvFy-zX~IH!s&S)4;VV zImN@n(=FZB_JBSkiaK}m3gh%d&lJCaOtZp7U$10WBMb9DpgMNu5XKOu5N5bVOb0G7 z9yrSc=d&ItU|lE)w^1)CCqJpYD6=HBNH5+wGv2`!u9EqH8WS;Yb2uQ!2-n1NK#+YQ wW7R^o%)FB5f>>7v2S+EkB-;TOHkgcq>q3^C%;FNbB)WCDyolsN&V!5$0Me;sNdN!< literal 0 HcmV?d00001 diff --git a/experimental/cpp-serializer/bin/test-files/_L_i__ b/experimental/cpp-serializer/bin/test-files/_L_i__ new file mode 100644 index 0000000000000000000000000000000000000000..314fe454c862c0a36e1181676dae4a27cca4e869 GIT binary patch literal 679 zcmYe!FG@*dWME)uIGO|`85kHZFfcGp05X^v7AxhYmgpseR9J=Oo8`HAd%C1%x^VEFGw>9@V_;u-vLBGt)4O zQ2pRY?R?K*mmC*!kUD0@5L6TKsboU28=p#MxCfbl9%Nhu^(o^_uuoy0XFV{Nb)hue z*Lq1g`AOwPnI)-3dhtH-nep)su5fdh52!H_6G9FLJQ?AdSPs~*FJ#ThEH0^B$f$Kd zn{lB=R$^JAUTH~Yj-C%t*ao}hnelcG4vtQ6bJz}~v5}zFbs-DLPPle-x8sU6B=52w t$YWh7fy;GB3enBR6)O%0WRb%~fPEoj;zH)kyb{-ij0VVlp0a0*)ps>%YFM91>% ztYq!LzQE@Vl|FD(jTMX?2^UN**s%*B}% zA?!pccZK_!3FvFacBuCm>%iWJg$V0`*{lnt;X$F7l#`!SUX)pqTBH~6o9R;=?|?9e z`G6V|F~R0=z?~6pIm-bn_Jxdz3mLTz=rS(U%1SIt)GIB?%+d2rEU?MUE74Iv2>E0d zm)I1S6lLb6+u1odI6A>iVLOn{Mv`XNh0M8$1#tc7PRA9KNWNt|5W==l47=kTToJJVPI literal 0 HcmV?d00001 diff --git a/experimental/cpp-serializer/bin/test-files/_Mi_is__ b/experimental/cpp-serializer/bin/test-files/_Mi_is__ new file mode 100644 index 0000000000000000000000000000000000000000..814a5de58b9c8f3ed07c03ac0591923a2cb4a2a7 GIT binary patch literal 740 zcmYe!FG@*dWME)uIGO|`85kHZFfcHk1u~c!7AxhYmgpseR9JZx8@n60M0uyC=9L6H zn}tNA8)jFP+u9!3&xoQfs?aysDcrz2BdR33u-K*2D8#6!%+c2N;B>YSRFzdB<*orn zZa(2gK3QS8-r=G7MOE4$6S~@WE7>QhOnR*j#CQc%u9uPoC)Z0#^cZsVB7}|0a&209$3J-P!=88NMJCMajs(#mn%(;mLa3jz?fGbjw{LFfwhjpPOPA4L%L^m8)q&gh1 tVuHJf<$wST@jw-V&w3!2b)h8O6uqRJ{G{@t%#ze1y?Fo3cn4RwPUZt@ lOvKpda6lSiJj($-_Jxdz3z;+XN?aWr9G&3CaUNu3001ZRJyiez literal 0 HcmV?d00001 diff --git a/experimental/cpp-serializer/bin/test-files/_Pls_ b/experimental/cpp-serializer/bin/test-files/_Pls_ new file mode 100644 index 0000000000000000000000000000000000000000..aea6d95eb53e5db9be29bf0d47aa8d169428b55f GIT binary patch literal 595 zcmbV~KT88K7>ASV#pG;oQf}6`fHIQ|m`*a%BshAH zgwK=64-2FokX+I6mQR^K;3SE-)%K`pJ2gEfqc)7cm^!Keb(5*qvl3#t+-C_TvE^aH z%ap~P%~g?b5_fiMj^kD}kJJMaK4b0$f;UB`vLFBe literal 0 HcmV?d00001 diff --git a/experimental/cpp-serializer/bin/test-files/__i_LMis_l__ b/experimental/cpp-serializer/bin/test-files/__i_LMis_l__ new file mode 100644 index 0000000000000000000000000000000000000000..67f6e33f4221fafed3526c0712c652198a784d9b GIT binary patch literal 1087 zcmb7C%Wl&^6rJ&_DjVnugaqOtA=H3dNT8)^E4zxJX`Dr=lhAA|CvlR2iKn$E&lUUz zyAk3)rVIA$+436*CKWPH)Tzp5G^07^o^#K=EfTi_2mtu_ttn0b;CBGD$Ks-bFAt)S znyndPt4G5LnO5KBu-7gP^7#2_NRsZ(4*xZe+t1q#w}m>#hij91b(pw^x%QhGZluiB zs}%dsI)!*VDQ#BkdB@&(UEXgB+}TaTgG{9(;;BsQkU{L}Oij@EYU~xwTVi^Mx;^SG zi!xy}#~T(r*RHI;EgX~&3i(d*s_fMows3b1emd{|`kpmM_)zOl8!unfHmhq#$2n3u zD&peCtQ`ZM0-$_OV^c(I%Fn;~DL=$TPyclOTW9yvEX^h+%~6bK7@NM2e7AxUAN#)L zqzsimQm&G|#lNa4N#k2f42~IGOxUf9{bJv_06vw$(E{AyJ>$QuIZVUCerj(q8QH#N!Zdi@V7KM{TMkqE z!HHBtwyGHkofBOa0lsXovW2wxU6>lu_{#ZUHB6$e!{B;$UOJDY(&#d2*=k$-PFDJc PkPetC7G_a-`3!L@jx{roX>h7k9DC0+!Vc}ocyHnqRf)iBE9&`cn5?=<^yU> m#8~HWKo(&-%K-uQg^Y;{nKScBTo*DLI5;}NZRR}4$N&IW89i43 literal 0 HcmV?d00001 diff --git a/experimental/cpp-serializer/bin/blob-inspector/test/_i_is__ b/experimental/cpp-serializer/bin/test-files/_i_is__ similarity index 100% rename from experimental/cpp-serializer/bin/blob-inspector/test/_i_is__ rename to experimental/cpp-serializer/bin/test-files/_i_is__ diff --git a/experimental/cpp-serializer/bin/test-files/_l_ b/experimental/cpp-serializer/bin/test-files/_l_ new file mode 100644 index 0000000000000000000000000000000000000000..56f83d200705cc5795543d625b15eed867341fb1 GIT binary patch literal 222 zcmYe!FG@*dWME)uIGO|`85kH3oML8Jtdy5pqL&Pkvnn$Q@p1Gu2r}{V_A)U}E4K6w z35#;HwLQSa*a%cF?osvvp_}PIJ>!8IM!0FL2l81LO27@%OUlVlDlf_`NiEWg&xv<% tg)3w}pvFXutqup|5T>&n5M*D-Sh0{LCqFOUbs?jHgQFANM9zbZ3;?dRK9&Fg literal 0 HcmV?d00001 diff --git a/experimental/cpp-serializer/include/amqp/AMQPHeader.h b/experimental/cpp-serializer/include/amqp/AMQPHeader.h index cd7da633b7..130d242786 100644 --- a/experimental/cpp-serializer/include/amqp/AMQPHeader.h +++ b/experimental/cpp-serializer/include/amqp/AMQPHeader.h @@ -12,7 +12,7 @@ namespace amqp { * The 8th byte is used to store weather the stream is compressed or * not */ - std::array AMQP_HEADER { { 'c', 'o', 'r', 'd', 'a', 1, 0 } }; + const std::array AMQP_HEADER { { 'c', 'o', 'r', 'd', 'a', 1, 0 } }; } diff --git a/experimental/cpp-serializer/include/amqp/reader/IReader.h b/experimental/cpp-serializer/include/amqp/reader/IReader.h index 8c53731d1f..b7a28016f1 100644 --- a/experimental/cpp-serializer/include/amqp/reader/IReader.h +++ b/experimental/cpp-serializer/include/amqp/reader/IReader.h @@ -6,7 +6,7 @@ #include "amqp/AMQPDescribed.h" -#include "amqp/schema/Schema.h" +#include "amqp/schema/described-types/Schema.h" /****************************************************************************** * diff --git a/experimental/cpp-serializer/include/amqp/schema/Descriptors.h b/experimental/cpp-serializer/include/amqp/schema/Descriptors.h new file mode 100644 index 0000000000..22b5f216e7 --- /dev/null +++ b/experimental/cpp-serializer/include/amqp/schema/Descriptors.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +/** + * 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::schema::descriptors { + + constexpr uint64_t DESCRIPTOR_TOP_32BITS = 0xc562UL << (unsigned int)(32 + 16); + +} + + +namespace amqp::schema::descriptors { + + extern const int ENVELOPE; + extern const int SCHEMA; + extern const int OBJECT; + 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; + +} diff --git a/experimental/cpp-serializer/include/amqp/serializable/ISerializable.h b/experimental/cpp-serializer/include/amqp/serializable/ISerializable.h new file mode 100644 index 0000000000..9cc6404248 --- /dev/null +++ b/experimental/cpp-serializer/include/amqp/serializable/ISerializable.h @@ -0,0 +1,10 @@ +#pragma once + +namespace amqp::serializable { + + class ISerializable { + public : + virtual char * serialize() const = 0; + }; + +} \ No newline at end of file diff --git a/experimental/cpp-serializer/include/debug.h b/experimental/cpp-serializer/include/debug.h index 733fa2e398..30a8f9690c 100644 --- a/experimental/cpp-serializer/include/debug.h +++ b/experimental/cpp-serializer/include/debug.h @@ -7,7 +7,7 @@ /******************************************************************************/ #if defined AMQP_DEBUG && AMQP_DEBUG >= 1 - #define DBG(X) std::cout << X + #define DBG(X) std::cout << __FILE__ << "::" << __LINE__ << "] " << X #else #define DBG(X) #endif diff --git a/experimental/cpp-serializer/lines b/experimental/cpp-serializer/lines new file mode 100755 index 0000000000..12e34b0bbd --- /dev/null +++ b/experimental/cpp-serializer/lines @@ -0,0 +1,2 @@ +#!/bin/bash +wc -l $(find -E . -regex ".*/*.(cxx|h)") diff --git a/experimental/cpp-serializer/rem_cmake b/experimental/cpp-serializer/rem_cmake index 6d5a44689e..c50c9f1153 100755 --- a/experimental/cpp-serializer/rem_cmake +++ b/experimental/cpp-serializer/rem_cmake @@ -9,9 +9,13 @@ function cmake_rem_func { } rm -f BLOB-INSPECTOR.cbp +rm -rf cmake-build-debug cmake_rem_func . cmake_rem_func ./bin +cmake_rem_func ./bin/blob-inspector +cmake_rem_func ./bin/blob-inspector/test +cmake_rem_func ./bin/schema-dumper cmake_rem_func ./src cmake_rem_func ./src/amqp cmake_rem_func ./src/amqp/test diff --git a/experimental/cpp-serializer/src/CMakeLists.txt b/experimental/cpp-serializer/src/CMakeLists.txt index 9b4754782a..b295725df1 100644 --- a/experimental/cpp-serializer/src/CMakeLists.txt +++ b/experimental/cpp-serializer/src/CMakeLists.txt @@ -2,5 +2,4 @@ include_directories (${BLOB-INSPECTOR_SOURCE_DIR}/src) ADD_SUBDIRECTORY (proton) ADD_SUBDIRECTORY (amqp) -ADD_SUBDIRECTORY (serialiser) diff --git a/experimental/cpp-serializer/src/amqp/CMakeLists.txt b/experimental/cpp-serializer/src/amqp/CMakeLists.txt index d4bc21097b..54230464fc 100644 --- a/experimental/cpp-serializer/src/amqp/CMakeLists.txt +++ b/experimental/cpp-serializer/src/amqp/CMakeLists.txt @@ -1,30 +1,42 @@ -include_directories (descriptors) +include_directories (schema/descriptors) +include_directories (schema/field-types) +include_directories (schema/described-types) include_directories (schema) include_directories (reader) include_directories (.) -set (amqp_sources - CompositeFactory.cxx - descriptors/AMQPDescriptor.cxx - descriptors/AMQPDescriptors.cxx - descriptors/AMQPDescriptorRegistory.cxx - descriptors/corda-descriptors/FieldDescriptor.cxx - descriptors/corda-descriptors/SchemaDescriptor.cxx - descriptors/corda-descriptors/ObjectDescriptor.cxx - descriptors/corda-descriptors/ChoiceDescriptor.cxx - descriptors/corda-descriptors/EnvelopeDescriptor.cxx - descriptors/corda-descriptors/CompositeDescriptor.cxx - descriptors/corda-descriptors/RestrictedDescriptor.cxx - schema/Field.cxx - schema/Schema.cxx - schema/Choice.cxx - schema/Envelope.cxx - schema/Composite.cxx - schema/Descriptor.cxx - schema/AMQPTypeNotation.cxx +set (amqp_schema_sources + schema/descriptors/AMQPDescriptor.cxx + schema/descriptors/AMQPDescriptors.cxx + schema/descriptors/AMQPDescriptorRegistory.cxx + schema/descriptors/corda-descriptors/FieldDescriptor.cxx + schema/descriptors/corda-descriptors/SchemaDescriptor.cxx + schema/descriptors/corda-descriptors/ObjectDescriptor.cxx + schema/descriptors/corda-descriptors/ChoiceDescriptor.cxx + schema/descriptors/corda-descriptors/EnvelopeDescriptor.cxx + schema/descriptors/corda-descriptors/CompositeDescriptor.cxx + schema/descriptors/corda-descriptors/RestrictedDescriptor.cxx + schema/field-types/Field.cxx + schema/field-types/PrimitiveField.cxx + schema/field-types/CompositeField.cxx + schema/field-types/RestrictedField.cxx + schema/field-types/ArrayField.cxx + schema/described-types/Schema.cxx + schema/described-types/Choice.cxx + schema/described-types/Envelope.cxx + schema/described-types/Composite.cxx + schema/described-types/Descriptor.cxx schema/restricted-types/Restricted.cxx schema/restricted-types/List.cxx schema/restricted-types/Enum.cxx + schema/restricted-types/Map.cxx + schema/restricted-types/Array.cxx + schema/AMQPTypeNotation.cxx + schema/Descriptors.cxx +) + +set (amqp_sources + CompositeFactory.cxx reader/Reader.cxx reader/PropertyReader.cxx reader/CompositeReader.cxx @@ -34,10 +46,12 @@ set (amqp_sources reader/property-readers/BoolPropertyReader.cxx reader/property-readers/DoublePropertyReader.cxx reader/property-readers/StringPropertyReader.cxx + reader/restricted-readers/MapReader.cxx reader/restricted-readers/ListReader.cxx + reader/restricted-readers/ArrayReader.cxx reader/restricted-readers/EnumReader.cxx ) -ADD_LIBRARY ( amqp ${amqp_sources} ) +ADD_LIBRARY ( amqp ${amqp_sources} ${amqp_schema_sources}) ADD_SUBDIRECTORY (test) diff --git a/experimental/cpp-serializer/src/amqp/CompositeFactory.cxx b/experimental/cpp-serializer/src/amqp/CompositeFactory.cxx index 0dd19e0676..7e7b9f3f8b 100644 --- a/experimental/cpp-serializer/src/amqp/CompositeFactory.cxx +++ b/experimental/cpp-serializer/src/amqp/CompositeFactory.cxx @@ -16,11 +16,15 @@ #include "reader/Reader.h" #include "reader/CompositeReader.h" #include "reader/RestrictedReader.h" +#include "reader/restricted-readers/MapReader.h" #include "reader/restricted-readers/ListReader.h" +#include "reader/restricted-readers/ArrayReader.h" #include "reader/restricted-readers/EnumReader.h" +#include "schema/restricted-types/Map.h" #include "schema/restricted-types/List.h" #include "schema/restricted-types/Enum.h" +#include "schema/restricted-types/Array.h" /******************************************************************************/ @@ -40,11 +44,12 @@ namespace { if (it == map_.end()) { DBG ("ComputeIfAbsent \"" << k_ << "\" - missing" << std::endl); // NOLINT - map_[k_] = std::move(f_()); + map_[k_] = std::move (f_()); DBG (" \"" << k_ << "\" - RTN: " << map_[k_]->name() << " : " << map_[k_]->type() << std::endl); // NOLINT assert (map_[k_]); assert (map_[k_] != nullptr); + DBG (k_ << " =?= " << map_[k_]->type() << std::endl); assert (k_ == map_[k_]->type()); return map_[k_]; @@ -70,18 +75,20 @@ namespace { * * Walk through the types in a Schema and produce readers for them. * - * We are making the large assumption that the contents of [schema_] + * We are making the assumption that the contents of [schema_] * are strictly ordered by dependency so we can construct types * as we go without needing to provide look ahead for types - * we haven't built yet + * we haven't built yet. * */ void amqp::internal:: CompositeFactory::process (const SchemaType & schema_) { + DBG ("process schema" << std::endl); + for (const auto & i : dynamic_cast(schema_)) { for (const auto & j : i) { - process(*j); + process (*j); m_readersByDescriptor[j->descriptor()] = m_readersByType[j->name()]; } } @@ -92,17 +99,19 @@ CompositeFactory::process (const SchemaType & schema_) { std::shared_ptr amqp::internal:: CompositeFactory::process ( - const amqp::internal::schema::AMQPTypeNotation & schema_) + const amqp::internal::schema::AMQPTypeNotation & schema_) { + DBG ("process::" << schema_.name() << std::endl); + return computeIfAbsent ( m_readersByType, schema_.name(), [& schema_, this] () -> std::shared_ptr { switch (schema_.type()) { - case amqp::internal::schema::AMQPTypeNotation::Composite : { + case schema::AMQPTypeNotation::composite_t : { return processComposite (schema_); } - case amqp::internal::schema::AMQPTypeNotation::Restricted : { + case schema::AMQPTypeNotation::restricted_t : { return processRestricted (schema_); } } @@ -116,48 +125,38 @@ amqp::internal:: CompositeFactory::processComposite ( const amqp::internal::schema::AMQPTypeNotation & type_ ) { + DBG ("processComposite - " << type_.name() << std::endl); std::vector> readers; - const auto & fields = dynamic_cast ( + const auto & fields = dynamic_cast ( type_).fields(); - readers.reserve(fields.size()); + readers.reserve (fields.size()); for (const auto & field : fields) { - DBG (" Field: " << field->name() << ": " << field->type() << std::endl); // NOLINT + DBG (" Field: " << field->name() << ": \"" << field->type() + << "\" {" << field->resolvedType() << "} " + << field->fieldType() << std::endl); // NOLINT - switch (field->fieldType()) { - case schema::FieldType::PrimitiveProperty : { - auto reader = computeIfAbsent( - m_readersByType, - field->type(), - [&field]() -> std::shared_ptr { - return reader::PropertyReader::make(field); - }); + decltype (m_readersByType)::mapped_type reader; - assert (reader); - readers.emplace_back(reader); - assert (readers.back().lock()); - break; - } - case amqp::internal::schema::FieldType::CompositeProperty : { - auto reader = m_readersByType[field->type()]; - - assert (reader); - readers.emplace_back(reader); - assert (readers.back().lock()); - break; - } - case schema::FieldType::RestrictedProperty : { - auto reader = m_readersByType[field->requires().front()]; - - assert (reader); - readers.emplace_back(reader); - assert (readers.back().lock()); - break; - } + if (field->primitive()) { + reader = computeIfAbsent ( + m_readersByType, + field->resolvedType(), + [&field]() -> std::shared_ptr { + return reader::PropertyReader::make (field); + }); + } + else { + // Insertion sorting ensures any type we depend on will have + // already been created and thus exist in the map + reader = m_readersByType[field->resolvedType()]; } + + assert (reader); + readers.emplace_back (reader); assert (readers.back().lock()); } @@ -174,8 +173,55 @@ CompositeFactory::processEnum ( DBG ("Processing Enum - " << enum_.name() << std::endl); // NOLINT return std::make_shared ( - enum_.name(), - enum_.makeChoices()); + enum_.name(), + enum_.makeChoices()); +} + +/******************************************************************************/ + +std::shared_ptr +amqp::internal:: +CompositeFactory::fetchReaderForRestricted (const std::string & type_) { + decltype(m_readersByType)::mapped_type rtn; + + DBG ("fetchReaderForRestricted - " << type_ << std::endl); + + if (schema::Field::typeIsPrimitive(type_)) { + DBG ("It's primitive" << std::endl); + rtn = computeIfAbsent( + m_readersByType, + type_, + [& type_]() -> std::shared_ptr { + return reader::PropertyReader::make (type_); + }); + } else { + rtn = m_readersByType[type_]; + } + + if (!rtn) { + throw std::runtime_error ("Missing type in map"); + } + + return rtn; +} + +/******************************************************************************/ + +std::shared_ptr +amqp::internal:: +CompositeFactory::processMap ( + const amqp::internal::schema::Map & map_ +) { + DBG ("Processing Map - " + << map_.mapOf().first.get() << " " + << map_.mapOf().second.get() << std::endl); // NOLINT + + const auto types = map_.mapOf(); + + return std::make_shared ( + map_.name(), + fetchReaderForRestricted (types.first), + fetchReaderForRestricted (types.second)); } /******************************************************************************/ @@ -187,22 +233,23 @@ CompositeFactory::processList ( ) { DBG ("Processing List - " << list_.listOf() << std::endl); // NOLINT - if (schema::Field::typeIsPrimitive (list_.listOf())) { - DBG (" List of Primitives" << std::endl); // NOLINT - auto reader = computeIfAbsent( - m_readersByType, - list_.listOf(), - [& list_]() -> std::shared_ptr { - return reader::PropertyReader::make (list_.listOf()); - }); + return std::make_shared ( + list_.name(), + fetchReaderForRestricted (list_.listOf())); +} - return std::make_shared(list_.name(), reader); - } else { - DBG (" List of Composite - " << list_.listOf() << std::endl); // NOLINT - auto reader = m_readersByType[list_.listOf()]; +/******************************************************************************/ - return std::make_shared(list_.name(), reader); - } +std::shared_ptr +amqp::internal:: +CompositeFactory::processArray ( + const amqp::internal::schema::Array & array_ +) { + DBG ("Processing Array - " << array_.name() << " " << array_.arrayOf() << std::endl); // NOLINT + + return std::make_shared ( + array_.name(), + fetchReaderForRestricted (array_.arrayOf())); } /******************************************************************************/ @@ -213,24 +260,29 @@ CompositeFactory::processRestricted ( const amqp::internal::schema::AMQPTypeNotation & type_) { DBG ("processRestricted - " << type_.name() << std::endl); // NOLINT - const auto & restricted = dynamic_cast ( + const auto & restricted = dynamic_cast ( type_); switch (restricted.restrictedType()) { - case schema::Restricted::RestrictedTypes::List : { + case schema::Restricted::RestrictedTypes::list_t : { return processList ( - dynamic_cast (restricted)); + dynamic_cast (restricted)); } - case schema::Restricted::RestrictedTypes::Enum : { + case schema::Restricted::RestrictedTypes::enum_t : { return processEnum ( - dynamic_cast (restricted)); + dynamic_cast (restricted)); } - case schema::Restricted::RestrictedTypes::Map :{ - throw std::runtime_error ("Cannot process maps"); + case schema::Restricted::RestrictedTypes::map_t : { + return processMap ( + dynamic_cast (restricted)); + } + case schema::Restricted::RestrictedTypes::array_t : { + DBG (" array_t" << std::endl); + return processArray ( + dynamic_cast (restricted)); } } - DBG (" ProcessRestricted: Returning nullptr"); // NOLINT return nullptr; } diff --git a/experimental/cpp-serializer/src/amqp/CompositeFactory.h b/experimental/cpp-serializer/src/amqp/CompositeFactory.h index 966a0af09f..fc78e349b8 100644 --- a/experimental/cpp-serializer/src/amqp/CompositeFactory.h +++ b/experimental/cpp-serializer/src/amqp/CompositeFactory.h @@ -9,10 +9,12 @@ #include "types.h" #include "amqp/ICompositeFactory.h" -#include "amqp/schema/Schema.h" -#include "amqp/schema/Envelope.h" -#include "amqp/schema/Composite.h" +#include "amqp/schema/described-types/Schema.h" +#include "amqp/schema/described-types/Envelope.h" +#include "amqp/schema/described-types/Composite.h" #include "amqp/reader/CompositeReader.h" +#include "amqp/schema/restricted-types/Map.h" +#include "amqp/schema/restricted-types/Array.h" #include "amqp/schema/restricted-types/List.h" #include "amqp/schema/restricted-types/Enum.h" @@ -56,6 +58,15 @@ namespace amqp::internal { std::shared_ptr processEnum ( const schema::Enum &); + + std::shared_ptr processMap ( + const schema::Map &); + + std::shared_ptr processArray ( + const schema::Array &); + + decltype(m_readersByType)::mapped_type + fetchReaderForRestricted (const std::string &); }; } diff --git a/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptorRegistory.cxx b/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptorRegistory.cxx deleted file mode 100644 index fe5ea74b15..0000000000 --- a/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptorRegistory.cxx +++ /dev/null @@ -1,156 +0,0 @@ -#include "AMQPDescriptorRegistory.h" -#include "AMQPDescriptors.h" - -#include "corda-descriptors/FieldDescriptor.h" -#include "corda-descriptors/SchemaDescriptor.h" -#include "corda-descriptors/ObjectDescriptor.h" -#include "corda-descriptors/ChoiceDescriptor.h" -#include "corda-descriptors/EnvelopeDescriptor.h" -#include "corda-descriptors/CompositeDescriptor.h" -#include "corda-descriptors/RestrictedDescriptor.h" - -#include -#include - -/******************************************************************************/ - -namespace amqp::internal { - - constexpr uint64_t DESCRIPTOR_TOP_32BITS = 0xc562UL << (unsigned int)(32 + 16); - -} - -/******************************************************************************/ - -namespace amqp::internal { - - const int ENVELOPE = 1; - const int SCHEMA = 2; - const int OBJECT = 3; - const int FIELD = 4; - const int COMPOSITE_TYPE = 5; - const int RESTRICTED_TYPE = 6; - const int CHOICE = 7; - const int REFERENCED_OBJECT = 8; - const int TRANSFORM_SCHEMA = 9; - const int TRANSFORM_ELEMENT = 10; - const int TRANSFORM_ELEMENT_KEY = 11; - -} - -/******************************************************************************/ - -/** - * - */ -namespace amqp { - - std::map> - AMQPDescriptorRegistory = { - { - 22UL, - std::make_shared ("DESCRIBED", -1) - }, - { - 1UL | internal::DESCRIPTOR_TOP_32BITS, - std::make_shared ("ENVELOPE", internal::ENVELOPE) - }, - { - 2UL | internal::DESCRIPTOR_TOP_32BITS, - std::make_shared ("SCHEMA", internal::SCHEMA) - }, - { - 3UL | internal::DESCRIPTOR_TOP_32BITS, - std::make_shared ("OBJECT_DESCRIPTOR", internal::OBJECT) - }, - { - 4UL | internal::DESCRIPTOR_TOP_32BITS, - std::make_shared ( - internal::FieldDescriptor ( - "FIELD", - internal::FIELD)) - }, - { - 5UL | internal::DESCRIPTOR_TOP_32BITS, - std::make_shared ( - internal::CompositeDescriptor ( - "COMPOSITE_TYPE", - internal::COMPOSITE_TYPE)) - }, - { - 6UL | internal::DESCRIPTOR_TOP_32BITS, - std::make_shared ( - internal::RestrictedDescriptor ( - "RESTRICTED_TYPE", - internal::RESTRICTED_TYPE)) - }, - { - 7UL | internal::DESCRIPTOR_TOP_32BITS, - std::make_shared ("CHOICE", internal::CHOICE) - }, - { - 8UL | internal::DESCRIPTOR_TOP_32BITS, - std::make_shared ( - internal::ReferencedObjectDescriptor ( - "REFERENCED_OBJECT", - internal::REFERENCED_OBJECT)) - }, - { - 9UL | internal::DESCRIPTOR_TOP_32BITS, - std::make_shared ( - internal::TransformSchemaDescriptor ( - "TRANSFORM_SCHEMA", - internal::TRANSFORM_SCHEMA)) - }, - { - 10UL | internal::DESCRIPTOR_TOP_32BITS, - std::make_shared ( - internal::TransformElementDescriptor ( - "TRANSFORM_ELEMENT", - internal::TRANSFORM_ELEMENT)) - }, - { - 11UL | internal::DESCRIPTOR_TOP_32BITS, - std::make_shared ( - internal::TransformElementKeyDescriptor ( - "TRANSFORM_ELEMENT_KEY", - internal::TRANSFORM_ELEMENT_KEY)) - } - }; -} - -/******************************************************************************/ - -uint32_t -amqp::stripCorda (uint64_t id) { - return static_cast(id & (uint64_t)UINT_MAX); -} - -/******************************************************************************/ - -std::string -amqp::describedToString (uint64_t val_) { - switch (val_) { - case (1UL | internal::DESCRIPTOR_TOP_32BITS) : return "ENVELOPE"; - case (2UL | internal::DESCRIPTOR_TOP_32BITS) : return "SCHEMA"; - case (3UL | internal::DESCRIPTOR_TOP_32BITS) : return "OBJECT_DESCRIPTOR"; - case (4UL | internal::DESCRIPTOR_TOP_32BITS) : return "FIELD"; - case (5UL | internal::DESCRIPTOR_TOP_32BITS) : return "COMPOSITE_TYPE"; - case (6UL | internal::DESCRIPTOR_TOP_32BITS) : return "RESTRICTED_TYPE"; - case (7UL | internal::DESCRIPTOR_TOP_32BITS) : return "CHOICE"; - case (8UL | internal::DESCRIPTOR_TOP_32BITS) : return "REFERENCED_OBJECT"; - case (9UL | internal::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_SCHEMA"; - case (10UL | internal::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_ELEMENT"; - case (11UL | internal::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_ELEMENT_KEY"; - default : return "UNKNOWN"; - } -} - -/******************************************************************************/ - -std::string -amqp::describedToString (uint32_t val_) { - return describedToString(val_ | internal::DESCRIPTOR_TOP_32BITS); -} - -/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/reader/CompositeReader.cxx b/experimental/cpp-serializer/src/amqp/reader/CompositeReader.cxx index 8ce375cab8..4d20b00a7d 100644 --- a/experimental/cpp-serializer/src/amqp/reader/CompositeReader.cxx +++ b/experimental/cpp-serializer/src/amqp/reader/CompositeReader.cxx @@ -84,12 +84,20 @@ CompositeReader::_dump ( pn_data_t * data_, const SchemaType & schema_ ) const { - DBG ("Read Composite: " << m_name << " : " << type() << std::endl); // NOLINT + DBG ("Read Composite: " + << m_name + << " : " + << type() + << std::endl); // NOLINT + proton::is_described (data_); proton::auto_enter ae (data_); - const auto & it = schema_.fromDescriptor (proton::get_symbol(data_)); - auto & fields = dynamic_cast(*(it->second.get())).fields(); + const auto & it = schema_.fromDescriptor ( + proton::get_symbol(data_)); + + auto & fields = dynamic_cast ( + *(it->second.get())).fields(); assert (fields.size() == m_readers.size()); @@ -104,13 +112,14 @@ CompositeReader::_dump ( for (int i (0) ; i < m_readers.size() ; ++i) { if (auto l = m_readers[i].lock()) { - DBG (fields[i]->name() << " " << (l ? "true" : "false") << std::endl); // NOLINT + DBG (fields[i]->name() << " " + << (l ? "true" : "false") << std::endl); // NOLINT - read.emplace_back(l->dump(fields[i]->name(), data_, schema_)); + read.emplace_back (l->dump (fields[i]->name(), data_, schema_)); } else { std::stringstream s; s << "null field reader: " << fields[i]->name(); - throw std::runtime_error(s.str()); + throw std::runtime_error (s.str()); } } } @@ -127,6 +136,8 @@ CompositeReader::dump ( pn_data_t * data_, const SchemaType & schema_) const { + proton::auto_next an (data_); + return std::make_unique>>> ( name_, _dump(data_, schema_)); @@ -143,6 +154,8 @@ CompositeReader::dump ( pn_data_t * data_, const SchemaType & schema_) const { + proton::auto_next an (data_); + return std::make_unique>>> ( _dump (data_, schema_)); } diff --git a/experimental/cpp-serializer/src/amqp/reader/CompositeReader.h b/experimental/cpp-serializer/src/amqp/reader/CompositeReader.h index d67bfa1c4e..ce880bc0d6 100644 --- a/experimental/cpp-serializer/src/amqp/reader/CompositeReader.h +++ b/experimental/cpp-serializer/src/amqp/reader/CompositeReader.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include /******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/reader/PropertyReader.cxx b/experimental/cpp-serializer/src/amqp/reader/PropertyReader.cxx index 9276ce714b..5d976bc62e 100644 --- a/experimental/cpp-serializer/src/amqp/reader/PropertyReader.cxx +++ b/experimental/cpp-serializer/src/amqp/reader/PropertyReader.cxx @@ -54,11 +54,12 @@ namespace { } -/******************************************************************************/ +/****************************************************************************** + * + * Static methods + * + ******************************************************************************/ -/** - * Static factory method - */ std::shared_ptr amqp::internal::reader:: PropertyReader::make (const FieldPtr & field_) { @@ -75,4 +76,10 @@ PropertyReader::make (const std::string & type_) { /******************************************************************************/ +std::shared_ptr +amqp::internal::reader:: +PropertyReader::make (const internal::schema::Field & field_) { + return propertyMap[field_.type()](); +} +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/reader/PropertyReader.h b/experimental/cpp-serializer/src/amqp/reader/PropertyReader.h index 597e404cd9..4655980c6f 100644 --- a/experimental/cpp-serializer/src/amqp/reader/PropertyReader.h +++ b/experimental/cpp-serializer/src/amqp/reader/PropertyReader.h @@ -4,7 +4,7 @@ #include "Reader.h" -#include "amqp/schema/Field.h" +#include "amqp/schema/field-types/Field.h" /******************************************************************************/ @@ -18,13 +18,14 @@ namespace amqp::internal::reader { /** * Static Factory method for creating appropriate derived types */ + static std::shared_ptr make (const internal::schema::Field &); static std::shared_ptr make (const FieldPtr &); static std::shared_ptr make (const std::string &); PropertyReader() = default; ~PropertyReader() override = default; - std::string readString(pn_data_t *) const override = 0; + std::string readString (pn_data_t *) const override = 0; std::any read (pn_data_t *) const override = 0; diff --git a/experimental/cpp-serializer/src/amqp/reader/Reader.cxx b/experimental/cpp-serializer/src/amqp/reader/Reader.cxx index 5dedd50678..522e79235b 100644 --- a/experimental/cpp-serializer/src/amqp/reader/Reader.cxx +++ b/experimental/cpp-serializer/src/amqp/reader/Reader.cxx @@ -56,9 +56,11 @@ namespace { { Auto am (name_, rtn); - rtn << (*(begin_))->dump(); - for (auto it(std::next(begin_)) ; it != end_; ++it) { - rtn << ", " << (*it)->dump(); + if (begin_ != end_) { + rtn << (*(begin_))->dump(); + for (auto it(std::next(begin_)); it != end_; ++it) { + rtn << ", " << (*it)->dump(); + } } } @@ -72,9 +74,11 @@ namespace { { Auto am (rtn); - rtn << (*(begin_))->dump(); - for (auto it (std::next(begin_)) ; it != end_; ++it) { - rtn << ", " << (*it)->dump(); + if (begin_ != end_) { + rtn << (*(begin_))->dump(); + for (auto it(std::next(begin_)); it != end_; ++it) { + rtn << ", " << (*it)->dump(); + } } } @@ -85,7 +89,23 @@ namespace { /****************************************************************************** * + * amqp::internal::reader::TypedValuePair * + ******************************************************************************/ + +std::string +amqp::internal::reader:: +ValuePair::dump() const { + std::stringstream ss; + + ss << m_key->dump() << " : " << m_value->dump(); + + return ss.str(); +} + +/****************************************************************************** + * + * amqp::internal::reader::TypedPair * ******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/reader/Reader.h b/experimental/cpp-serializer/src/amqp/reader/Reader.h index f29d86c949..90e960056c 100644 --- a/experimental/cpp-serializer/src/amqp/reader/Reader.h +++ b/experimental/cpp-serializer/src/amqp/reader/Reader.h @@ -8,7 +8,7 @@ #include #include -#include "amqp/schema/Schema.h" +#include "amqp/schema/described-types/Schema.h" #include "amqp/reader/IReader.h" /******************************************************************************/ @@ -22,6 +22,19 @@ namespace amqp::internal::reader { ~Value() override = default; }; + /* + * A Single represents some value read out of a proton tree that + * exists without an association. The canonical example is an + * element of a list. The list itself would be a pair, + * + * e.g. a : [ ] + * + * but the values of the list + * + * e.g. a : [ A, B, C ] + * + * are Singles + */ class Single : public Value { public : std::string dump() const override = 0; @@ -57,13 +70,19 @@ namespace amqp::internal::reader { std::string dump() const override; }; + /* + * A Pair represents an association between a property and + * the value of the property, i.e. a : b where property + * a has value b + */ class Pair : public Value { protected : std::string m_property; public: explicit Pair (std::string property_) - : m_property (std::move (property_)) + : Value() + , m_property (std::move (property_)) { } ~Pair() override = default; @@ -104,6 +123,29 @@ namespace amqp::internal::reader { std::string dump() const override; }; + /** + * Similar to [Pair] where k : v relationships are modelled. In this + * case, however, rather than modelling a property : value relationship + * we are modelling a key : value one. The primary difference is that + * keys need not be simple strings. + */ + class ValuePair : public Value { + private : + uPtr m_key; + uPtr m_value; + + public : + ValuePair ( + decltype (m_key) key_, + decltype (m_value) value_ + ) : Value () + , m_key (std::move (key_)) + , m_value (std::move (value_)) + { } + + std::string dump() const override; + }; + } /****************************************************************************** @@ -116,7 +158,7 @@ template inline std::string amqp::internal::reader:: TypedSingle::dump() const { - return std::to_string(m_value); + return std::to_string (m_value); } template<> @@ -176,7 +218,6 @@ std::string amqp::internal::reader:: TypedPair>>::dump() const; - template<> std::string amqp::internal::reader:: @@ -191,13 +232,23 @@ TypedPair>>::dump() const; * * * - * ******************************************************************************/ namespace amqp::internal::reader { using IReader = amqp::reader::IReader; + /** + * Interface that represents an object that has the ability to consume + * the payload of a Corda serialized blob in a way defined by some + * prior construction. This construction will usually come from + * analysis of the schema, although in the JVM versions it will come + * from reflection of the type definitions. + * + * In other words, when encountering a graph of nodes with values, an + * instance of [Reader] will give a sub tree of that graph contextual + * meaning. + */ class Reader : public IReader { public : ~Reader() override = default; diff --git a/experimental/cpp-serializer/src/amqp/reader/property-readers/BoolPropertyReader.cxx b/experimental/cpp-serializer/src/amqp/reader/property-readers/BoolPropertyReader.cxx index ec960d628a..bdd19efec5 100644 --- a/experimental/cpp-serializer/src/amqp/reader/property-readers/BoolPropertyReader.cxx +++ b/experimental/cpp-serializer/src/amqp/reader/property-readers/BoolPropertyReader.cxx @@ -31,7 +31,7 @@ BoolPropertyReader::m_type { // NOLINT std::any amqp::internal::reader:: BoolPropertyReader::read (pn_data_t * data_) const { - return std::any (true); + return std::any (proton::readAndNext (data_)); } /******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/reader/property-readers/DoublePropertyReader.cxx b/experimental/cpp-serializer/src/amqp/reader/property-readers/DoublePropertyReader.cxx index cdc37647d1..6a7b3bce23 100644 --- a/experimental/cpp-serializer/src/amqp/reader/property-readers/DoublePropertyReader.cxx +++ b/experimental/cpp-serializer/src/amqp/reader/property-readers/DoublePropertyReader.cxx @@ -29,7 +29,7 @@ DoublePropertyReader::m_type { // NOLINT std::any amqp::internal::reader:: DoublePropertyReader::read (pn_data_t * data_) const { - return std::any (10.0); + return std::any { proton::readAndNext (data_) }; } /******************************************************************************/ @@ -45,9 +45,9 @@ DoublePropertyReader::readString (pn_data_t * data_) const { uPtr amqp::internal::reader:: DoublePropertyReader::dump ( - const std::string & name_, - pn_data_t * data_, - const SchemaType & schema_) const + const std::string & name_, + pn_data_t * data_, + const SchemaType & schema_) const { return std::make_unique> ( name_, diff --git a/experimental/cpp-serializer/src/amqp/reader/property-readers/IntPropertyReader.cxx b/experimental/cpp-serializer/src/amqp/reader/property-readers/IntPropertyReader.cxx index b76506aeb6..61c5c4283e 100644 --- a/experimental/cpp-serializer/src/amqp/reader/property-readers/IntPropertyReader.cxx +++ b/experimental/cpp-serializer/src/amqp/reader/property-readers/IntPropertyReader.cxx @@ -37,7 +37,7 @@ IntPropertyReader::m_type { // NOLINT std::any amqp::internal::reader:: IntPropertyReader::read (pn_data_t * data_) const { - return std::any (1); + return std::any { proton::readAndNext (data_) }; } /******************************************************************************/ @@ -53,9 +53,9 @@ IntPropertyReader::readString (pn_data_t * data_) const { uPtr amqp::internal::reader:: IntPropertyReader::dump ( - const std::string & name_, - pn_data_t * data_, - const SchemaType & schema_) const + const std::string & name_, + pn_data_t * data_, + const SchemaType & schema_) const { return std::make_unique> ( name_, @@ -67,8 +67,8 @@ IntPropertyReader::dump ( uPtr amqp::internal::reader:: IntPropertyReader::dump ( - pn_data_t * data_, - const SchemaType & schema_) const + pn_data_t * data_, + const SchemaType & schema_) const { return std::make_unique> ( std::to_string (proton::readAndNext (data_))); diff --git a/experimental/cpp-serializer/src/amqp/reader/property-readers/LongPropertyReader.cxx b/experimental/cpp-serializer/src/amqp/reader/property-readers/LongPropertyReader.cxx index baac2ae42f..7349e38c27 100644 --- a/experimental/cpp-serializer/src/amqp/reader/property-readers/LongPropertyReader.cxx +++ b/experimental/cpp-serializer/src/amqp/reader/property-readers/LongPropertyReader.cxx @@ -31,7 +31,7 @@ LongPropertyReader::m_type { // NOLINT std::any amqp::internal::reader:: LongPropertyReader::read (pn_data_t * data_) const { - return std::any (10L); + return std::any { proton::readAndNext (data_) }; } /******************************************************************************/ @@ -47,9 +47,9 @@ LongPropertyReader::readString (pn_data_t * data_) const { uPtr amqp::internal::reader:: LongPropertyReader::dump ( - const std::string & name_, - pn_data_t * data_, - const SchemaType & schema_) const + const std::string & name_, + pn_data_t * data_, + const SchemaType & schema_) const { return std::make_unique> ( name_, @@ -61,8 +61,8 @@ LongPropertyReader::dump ( uPtr amqp::internal::reader:: LongPropertyReader::dump ( - pn_data_t * data_, - const SchemaType & schema_) const + pn_data_t * data_, + const SchemaType & schema_) const { return std::make_unique> ( std::to_string (proton::readAndNext (data_))); diff --git a/experimental/cpp-serializer/src/amqp/reader/property-readers/StringPropertyReader.cxx b/experimental/cpp-serializer/src/amqp/reader/property-readers/StringPropertyReader.cxx index 65844a9c15..3c772a4a67 100644 --- a/experimental/cpp-serializer/src/amqp/reader/property-readers/StringPropertyReader.cxx +++ b/experimental/cpp-serializer/src/amqp/reader/property-readers/StringPropertyReader.cxx @@ -33,7 +33,7 @@ StringPropertyReader::m_name { // NOLINT std::any amqp::internal::reader:: StringPropertyReader::read (pn_data_t * data_) const { - return std::any ("hello"); + return std::any { proton::readAndNext (data_) }; } /******************************************************************************/ @@ -49,9 +49,9 @@ StringPropertyReader::readString (pn_data_t * data_) const { uPtr amqp::internal::reader:: StringPropertyReader::dump ( - const std::string & name_, - pn_data_t * data_, - const SchemaType & schema_) const + const std::string & name_, + pn_data_t * data_, + const SchemaType & schema_) const { return std::make_unique> ( name_, diff --git a/experimental/cpp-serializer/src/amqp/reader/restricted-readers/ArrayReader.cxx b/experimental/cpp-serializer/src/amqp/reader/restricted-readers/ArrayReader.cxx new file mode 100644 index 0000000000..c52cb46b5f --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/reader/restricted-readers/ArrayReader.cxx @@ -0,0 +1,86 @@ +#include "ArrayReader.h" + +#include "proton/proton_wrapper.h" + +/****************************************************************************** + * + * class ArrayReader + * + ******************************************************************************/ + +amqp::internal::reader:: +ArrayReader::ArrayReader ( + std::string type_, + std::weak_ptr reader_ +) : RestrictedReader (std::move (type_)) + , m_reader (std::move (reader_)) +{ } + +/******************************************************************************/ + +amqp::internal::schema::Restricted::RestrictedTypes +amqp::internal::reader:: +ArrayReader::restrictedType() const { + return internal::schema::Restricted::RestrictedTypes::array_t; +} + +/******************************************************************************/ + +uPtr +amqp::internal::reader:: +ArrayReader::dump ( + const std::string & name_, + pn_data_t * data_, + const SchemaType & schema_ +) const { + proton::auto_next an (data_); + + return std::make_unique>>>( + name_, + dump_ (data_, schema_)); +} + +/******************************************************************************/ + +uPtr +amqp::internal::reader:: +ArrayReader::dump( + pn_data_t * data_, + const SchemaType & schema_ +) const { + proton::auto_next an (data_); + + return std::make_unique>>>( + dump_ (data_, schema_)); +} + +/******************************************************************************/ + +sList> +amqp::internal::reader:: +ArrayReader::dump_( + pn_data_t * data_, + const SchemaType & schema_ +) const { + proton::is_described (data_); + + decltype (dump_ (data_, schema_)) read; + + { + proton::auto_enter ae (data_); + schema_.fromDescriptor (proton::readAndNext(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; +} + +/******************************************************************************/ + diff --git a/experimental/cpp-serializer/src/amqp/reader/restricted-readers/ArrayReader.h b/experimental/cpp-serializer/src/amqp/reader/restricted-readers/ArrayReader.h new file mode 100644 index 0000000000..f97df2e469 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/reader/restricted-readers/ArrayReader.h @@ -0,0 +1,44 @@ +#pragma once + +/******************************************************************************/ + +#include "RestrictedReader.h" + +/******************************************************************************/ + +namespace amqp::internal::reader { + + class ArrayReader : public RestrictedReader { + private : + // How to read the underlying types + std::weak_ptr m_reader; + + std::list> dump_( + pn_data_t *, + const SchemaType &) const; + + /** + * cope with the fact Java can box primitives + */ + std::string m_primType; + + public : + ArrayReader (std::string, std::weak_ptr); + + ~ArrayReader() final = default; + + internal::schema::Restricted::RestrictedTypes restrictedType() const; + + std::unique_ptr dump( + const std::string &, + pn_data_t *, + const SchemaType &) const override; + + std::unique_ptr dump( + pn_data_t *, + const SchemaType &) const override; + }; + +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/reader/restricted-readers/EnumReader.cxx b/experimental/cpp-serializer/src/amqp/reader/restricted-readers/EnumReader.cxx index 23b5c2d8de..f5d7430d75 100644 --- a/experimental/cpp-serializer/src/amqp/reader/restricted-readers/EnumReader.cxx +++ b/experimental/cpp-serializer/src/amqp/reader/restricted-readers/EnumReader.cxx @@ -1,7 +1,8 @@ #include "EnumReader.h" #include "amqp/reader/IReader.h" -#include "amqp/descriptors/AMQPDescriptorRegistory.h" +#include "amqp/schema/Descriptors.h" +#include "amqp/schema/descriptors/AMQPDescriptorRegistory.h" #include "proton/proton_wrapper.h" /******************************************************************************/ @@ -19,6 +20,7 @@ EnumReader::EnumReader ( /******************************************************************************/ namespace { + std::string getValue (pn_data_t * data_) { proton::is_described (data_); @@ -34,7 +36,7 @@ namespace { */ if (pn_data_type (data_) == PN_ULONG) { if (amqp::stripCorda(pn_data_get_ulong(data_)) == - amqp::internal::REFERENCED_OBJECT + amqp::schema::descriptors::REFERENCED_OBJECT ) { throw std::runtime_error ( "Currently don't support referenced objects"); @@ -54,9 +56,7 @@ namespace { * here I'll forget its even a thing */ // auto idx = proton::readAndNext(data_); - } - } } @@ -89,7 +89,6 @@ EnumReader::dump( proton::is_described (data_); return std::make_unique> (getValue(data_)); - } /******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/reader/restricted-readers/ListReader.cxx b/experimental/cpp-serializer/src/amqp/reader/restricted-readers/ListReader.cxx index 3ca3c4a416..f67a7b06b0 100644 --- a/experimental/cpp-serializer/src/amqp/reader/restricted-readers/ListReader.cxx +++ b/experimental/cpp-serializer/src/amqp/reader/restricted-readers/ListReader.cxx @@ -11,12 +11,12 @@ amqp::internal::schema::Restricted::RestrictedTypes amqp::internal::reader:: ListReader::restrictedType() const { - return internal::schema::Restricted::RestrictedTypes::List; + return internal::schema::Restricted::RestrictedTypes::list_t; } /******************************************************************************/ -std::unique_ptr +uPtr amqp::internal::reader:: ListReader::dump ( const std::string & name_, @@ -32,7 +32,7 @@ ListReader::dump ( /******************************************************************************/ -std::unique_ptr +uPtr amqp::internal::reader:: ListReader::dump( pn_data_t * data_, @@ -46,7 +46,7 @@ ListReader::dump( /******************************************************************************/ -std::list> +sList> amqp::internal::reader:: ListReader::dump_( pn_data_t * data_, @@ -54,7 +54,7 @@ ListReader::dump_( ) const { proton::is_described (data_); - std::list> read; + decltype (dump_(data_, schema_)) read; { proton::auto_enter ae (data_); diff --git a/experimental/cpp-serializer/src/amqp/reader/restricted-readers/MapReader.cxx b/experimental/cpp-serializer/src/amqp/reader/restricted-readers/MapReader.cxx new file mode 100644 index 0000000000..63b11992ff --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/reader/restricted-readers/MapReader.cxx @@ -0,0 +1,82 @@ +#include "MapReader.h" + +#include "Reader.h" +#include "amqp/reader/IReader.h" +#include "proton/proton_wrapper.h" + +/******************************************************************************/ + +amqp::internal::schema::Restricted::RestrictedTypes +amqp::internal::reader:: +MapReader::restrictedType() const { + return schema::Restricted::Restricted::map_t; +} + +/******************************************************************************/ + +sVec> +amqp::internal::reader:: +MapReader::dump_( + pn_data_t * data_, + const SchemaType & schema_ +) const { + proton::is_described (data_); + proton::auto_enter ae (data_); + + // gloss over fetching the descriptor from the schema since + // we don't need it, we know the types this is a reader for + // and don't need context from the schema as there isn't + // any. Maps have a Key and a Value, they aren't named + // parameters, unlike composite types. + schema_.fromDescriptor (proton::readAndNext(data_)); + + { + proton::auto_map_enter am (data_, true); + + decltype (dump_(data_, schema_)) rtn; + rtn.reserve (am.elements() / 2); + + for (int i {0} ; i < am.elements() ; i += 2) { + rtn.emplace_back ( + std::make_unique ( + m_keyReader.lock()->dump (data_, schema_), + m_valueReader.lock()->dump (data_, schema_) + ) + ); + } + + return rtn; + } +} + +/******************************************************************************/ + +uPtr +amqp::internal::reader:: +MapReader::dump( + const std::string & name_, + pn_data_t * data_, + const SchemaType & schema_ +) const { + proton::auto_next an (data_); + + return std::make_unique>>>( + name_, + dump_ (data_, schema_)); +} + +/******************************************************************************/ + +std::unique_ptr +amqp::internal::reader:: +MapReader::dump( + pn_data_t * data_, + const SchemaType & schema_ +) const { + proton::auto_next an (data_); + + return std::make_unique>>>( + dump_ (data_, schema_)); +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/reader/restricted-readers/MapReader.h b/experimental/cpp-serializer/src/amqp/reader/restricted-readers/MapReader.h new file mode 100644 index 0000000000..74dea9c286 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/reader/restricted-readers/MapReader.h @@ -0,0 +1,47 @@ +#pragma once + +/******************************************************************************/ + +#include "RestrictedReader.h" + +/******************************************************************************/ + +namespace amqp::internal::reader { + + class MapReader : public RestrictedReader { + private : + // How to read the underlying types + std::weak_ptr m_keyReader; + std::weak_ptr m_valueReader; + + sVec> dump_( + pn_data_t *, + const SchemaType &) const; + + public : + MapReader ( + const std::string & type_, + std::weak_ptr keyReader_, + std::weak_ptr valueReader_ + ) : RestrictedReader (type_) + , m_keyReader (std::move (keyReader_)) + , m_valueReader (std::move (valueReader_)) + { } + + ~MapReader() final = default; + + internal::schema::Restricted::RestrictedTypes restrictedType() const; + + std::unique_ptr dump( + const std::string &, + pn_data_t *, + const SchemaType &) const override; + + std::unique_ptr dump( + pn_data_t *, + const SchemaType &) const override; + }; + +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/AMQPTypeNotation.cxx b/experimental/cpp-serializer/src/amqp/schema/AMQPTypeNotation.cxx index 96c833c0f4..517d9cb7bd 100644 --- a/experimental/cpp-serializer/src/amqp/schema/AMQPTypeNotation.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/AMQPTypeNotation.cxx @@ -3,7 +3,7 @@ #include "colours.h" -#include "Composite.h" +#include "amqp/schema/described-types/Composite.h" #include "amqp/schema/restricted-types/Restricted.h" /****************************************************************************** @@ -25,11 +25,11 @@ namespace amqp::internal::schema { std::ostream & operator << (std::ostream & stream_, const AMQPTypeNotation & clazz_) { switch (clazz_.type()) { - case AMQPTypeNotation::Type::Composite : { + case AMQPTypeNotation::Type::composite_t : { stream_ << dynamic_cast(clazz_); break; } - case AMQPTypeNotation::Type::Restricted : { + case AMQPTypeNotation::Type::restricted_t : { stream_ << dynamic_cast(clazz_); break; } diff --git a/experimental/cpp-serializer/src/amqp/schema/AMQPTypeNotation.h b/experimental/cpp-serializer/src/amqp/schema/AMQPTypeNotation.h index 32e89a14e4..d99f1a4e78 100644 --- a/experimental/cpp-serializer/src/amqp/schema/AMQPTypeNotation.h +++ b/experimental/cpp-serializer/src/amqp/schema/AMQPTypeNotation.h @@ -5,7 +5,7 @@ #include #include -#include "Descriptor.h" +#include "amqp/schema/described-types/Descriptor.h" #include "OrderedTypeNotations.h" /****************************************************************************** @@ -37,16 +37,16 @@ namespace amqp::internal::schema { std::ostream &, const AMQPTypeNotation &); - enum Type { Composite, Restricted }; + enum Type { composite_t, restricted_t }; private : - std::string m_name; - std::unique_ptr m_descriptor; + std::string m_name; + uPtr m_descriptor; public : AMQPTypeNotation ( std::string name_, - std::unique_ptr descriptor_ + uPtr descriptor_ ) : m_name (std::move (name_)) , m_descriptor (std::move (descriptor_)) { } @@ -57,9 +57,8 @@ namespace amqp::internal::schema { virtual Type type() const = 0; - int dependsOn (const OrderedTypeNotation &) const override = 0; - virtual int dependsOn (const class Restricted &) const = 0; - virtual int dependsOn (const class Composite &) const = 0; + virtual int dependsOnRHS (const Restricted &) const = 0; + virtual int dependsOnRHS (const Composite &) const = 0; }; } diff --git a/experimental/cpp-serializer/src/amqp/schema/Descriptors.cxx b/experimental/cpp-serializer/src/amqp/schema/Descriptors.cxx new file mode 100644 index 0000000000..c2615db543 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/Descriptors.cxx @@ -0,0 +1,21 @@ +#include "amqp/schema/Descriptors.h" + +/******************************************************************************/ + +namespace amqp::schema::descriptors { + + const int ENVELOPE = 1; + const int SCHEMA = 2; + const int OBJECT = 3; + const int FIELD = 4; + const int COMPOSITE_TYPE = 5; + const int RESTRICTED_TYPE = 6; + const int CHOICE = 7; + const int REFERENCED_OBJECT = 8; + const int TRANSFORM_SCHEMA = 9; + const int TRANSFORM_ELEMENT = 10; + const int TRANSFORM_ELEMENT_KEY = 11; + +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/Field.cxx b/experimental/cpp-serializer/src/amqp/schema/Field.cxx deleted file mode 100644 index 31183623b2..0000000000 --- a/experimental/cpp-serializer/src/amqp/schema/Field.cxx +++ /dev/null @@ -1,109 +0,0 @@ -#include "Field.h" - -#include -#include - -/******************************************************************************/ - -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 & 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 & -amqp::internal::schema:: -Field::requires() const { - return m_requires; -} - -/******************************************************************************/ - -bool -amqp::internal::schema:: -Field::primitive() const { - return m_type.second == PrimitiveProperty; -} - -/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/Field.h b/experimental/cpp-serializer/src/amqp/schema/Field.h deleted file mode 100644 index 59310b9db9..0000000000 --- a/experimental/cpp-serializer/src/amqp/schema/Field.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once -/******************************************************************************/ - -#include "Descriptor.h" -#include "amqp/AMQPDescribed.h" - -#include -#include -#include - -/******************************************************************************/ - -namespace amqp::internal::schema { - - enum FieldType { PrimitiveProperty, CompositeProperty, RestrictedProperty }; - - /** - * - * A Corda AMQP Scehma Field type has: - * - name : String - * - type : String - * - requires : List - * - 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 m_type; - std::list 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 & 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 & requires() const; - bool primitive() const; - }; - -} - -/******************************************************************************/ - diff --git a/experimental/cpp-serializer/src/amqp/schema/OrderedTypeNotations.h b/experimental/cpp-serializer/src/amqp/schema/OrderedTypeNotations.h index 5dbcfe9b1a..ed7cd8f743 100644 --- a/experimental/cpp-serializer/src/amqp/schema/OrderedTypeNotations.h +++ b/experimental/cpp-serializer/src/amqp/schema/OrderedTypeNotations.h @@ -4,6 +4,7 @@ #include #include +#include "debug.h" #include "types.h" #include "colours.h" @@ -60,18 +61,18 @@ namespace amqp::internal::schema { typename std::list>>::iterator &); public : - void insert(uPtr && ptr); + void insert (uPtr && ptr); friend std::ostream & ::operator << <> ( std::ostream &, const amqp::internal::schema::OrderedTypeNotations &); - decltype (m_schemas.crbegin()) begin() const { - return m_schemas.crbegin(); + decltype (m_schemas.cbegin()) begin() const { + return m_schemas.cbegin(); } - decltype (m_schemas.crend()) end() const { - return m_schemas.crend(); + decltype (m_schemas.cend()) end() const { + return m_schemas.cend(); } }; @@ -85,7 +86,7 @@ operator << ( std::ostream &stream_, const amqp::internal::schema::OrderedTypeNotations &otn_ ) { - int idx1{0}; + int idx1 {0}; for (const auto &i : otn_.m_schemas) { stream_ << "level " << ++idx1 << std::endl; for (const auto &j : i) { @@ -145,6 +146,7 @@ OrderedTypeNotations::insert ( uPtr && ptr, amqp::internal::schema::OrderedTypeNotations::iterator l_ ) { + DBG ("Insert: " << ptr->name() << std::endl); /* * First we find where this element needs to be added */ diff --git a/experimental/cpp-serializer/src/amqp/schema/Choice.cxx b/experimental/cpp-serializer/src/amqp/schema/described-types/Choice.cxx similarity index 62% rename from experimental/cpp-serializer/src/amqp/schema/Choice.cxx rename to experimental/cpp-serializer/src/amqp/schema/described-types/Choice.cxx index b63265f394..33e106029c 100644 --- a/experimental/cpp-serializer/src/amqp/schema/Choice.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/described-types/Choice.cxx @@ -1,5 +1,16 @@ #include "Choice.h" +#include + +/******************************************************************************/ + +std::ostream & +amqp::internal::schema:: +operator << (std::ostream & os_, const amqp::internal::schema::Choice & choice_) { + os_ << choice_.m_choice; + return os_; +} + /******************************************************************************/ amqp::internal::schema:: diff --git a/experimental/cpp-serializer/src/amqp/schema/Choice.h b/experimental/cpp-serializer/src/amqp/schema/described-types/Choice.h similarity index 74% rename from experimental/cpp-serializer/src/amqp/schema/Choice.h rename to experimental/cpp-serializer/src/amqp/schema/described-types/Choice.h index f7788433ae..04ef9a5213 100644 --- a/experimental/cpp-serializer/src/amqp/schema/Choice.h +++ b/experimental/cpp-serializer/src/amqp/schema/described-types/Choice.h @@ -1,14 +1,20 @@ #pragma once -#include "AMQPTypeNotation.h" +#include + +#include "schema/AMQPTypeNotation.h" /******************************************************************************/ namespace amqp::internal::schema { class Choice : public AMQPDescribed { + public : + friend std::ostream & operator << (std::ostream &, const Choice &); + private : std::string m_choice; + public : Choice() = delete; diff --git a/experimental/cpp-serializer/src/amqp/schema/Composite.cxx b/experimental/cpp-serializer/src/amqp/schema/described-types/Composite.cxx similarity index 83% rename from experimental/cpp-serializer/src/amqp/schema/Composite.cxx rename to experimental/cpp-serializer/src/amqp/schema/described-types/Composite.cxx index 19b9178b4b..4627453d29 100644 --- a/experimental/cpp-serializer/src/amqp/schema/Composite.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/described-types/Composite.cxx @@ -62,7 +62,7 @@ Composite::fields() const { amqp::internal::schema::AMQPTypeNotation::Type amqp::internal::schema:: Composite::type() const { - return AMQPTypeNotation::Type::Composite; + return AMQPTypeNotation::Type::composite_t; } /******************************************************************************/ @@ -87,64 +87,66 @@ Composite::type() const { int amqp::internal::schema:: Composite::dependsOn (const OrderedTypeNotation & rhs) const { - return dynamic_cast(rhs).dependsOn(*this); + return dynamic_cast(rhs).dependsOnRHS(*this); } /******************************************************************************/ int amqp::internal::schema:: -Composite::dependsOn (const amqp::internal::schema::Restricted & lhs_) const { - // does the left hand side depend on us - auto rtn { 0 }; - - for (const auto i : lhs_) { - DBG (" C/R a) " << i << " == " << name() << std::endl); // NOLINT - if (i == name()) { - rtn = 1; - } - } - +Composite::dependsOnRHS ( + const amqp::internal::schema::Restricted & lhs_ +) const { // does this depend on the left hand side for (auto const & field : m_fields) { DBG (" C/R b) " << field->resolvedType() << " == " << lhs_.name() << std::endl); // NOLINT if (field->resolvedType() == lhs_.name()) { - rtn = 2; + return 1; } - } - return rtn; + // does the left hand side depend on us + for (const auto i : lhs_) { + DBG (" C/R a) " << i << " == " << name() << std::endl); // NOLINT + if (i == name()) { + return 2; + } + } + + return 0; } /*********************************************************o*********************/ int amqp::internal::schema:: -Composite::dependsOn (const amqp::internal::schema::Composite & lhs_) const { - auto rtn { 0 }; +Composite::dependsOnRHS ( + const amqp::internal::schema::Composite & lhs_ +) const { + DBG (name() << " ?Depends on " << lhs_.name() << std::endl); - // do we depend on the lhs, i.e. is one of our fields it - for (auto const & field : lhs_) { - DBG (" C/C a) " << field->resolvedType() << " == " << name() << std::endl); // NOLINT - if (field->resolvedType() == name()) { - rtn = 1; - } - } - - // does the left hand side depend on us. i.e. is one of it's fields - // us + // do we depend on the lhs for (const auto & field : m_fields) { - DBG (" C/C b) " << field->resolvedType() << " == " << lhs_.name() << std::endl); // NOLINT + DBG ("FIELD - " << name() << "::" << type() << std::endl); + DBG (" C/C a) " << field->resolvedType() << " == " << lhs_.name() << std::endl); // NOLINT if (field->resolvedType() == lhs_.name()) { - rtn = 2; + return 1; + } + } + + // does it depend on us + for (auto const & field : lhs_) { + DBG ("FIELD - " << name() << "::" << type() << std::endl); + DBG (" C/C b) " << field->resolvedType() << " == " << name() << std::endl); // NOLINT + if (field->resolvedType() == name()) { + return 2; } } - return rtn; + return 0; } /******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/Composite.h b/experimental/cpp-serializer/src/amqp/schema/described-types/Composite.h similarity index 91% rename from experimental/cpp-serializer/src/amqp/schema/Composite.h rename to experimental/cpp-serializer/src/amqp/schema/described-types/Composite.h index 9732e87ead..b981d5985a 100644 --- a/experimental/cpp-serializer/src/amqp/schema/Composite.h +++ b/experimental/cpp-serializer/src/amqp/schema/described-types/Composite.h @@ -8,9 +8,9 @@ #include #include -#include "Field.h" +#include "schema/field-types/Field.h" #include "Descriptor.h" -#include "AMQPTypeNotation.h" +#include "schema/AMQPTypeNotation.h" #include "amqp/AMQPDescribed.h" @@ -73,8 +73,8 @@ namespace amqp::internal::schema { Type type() const override; int dependsOn (const OrderedTypeNotation &) const override; - int dependsOn (const class Restricted &) const override; - int dependsOn (const Composite &) const override; + int dependsOnRHS (const class Restricted &) const override; + int dependsOnRHS (const Composite &) const override; decltype(m_fields)::const_iterator begin() const { return m_fields.cbegin();} decltype(m_fields)::const_iterator end() const { return m_fields.cend(); } diff --git a/experimental/cpp-serializer/src/amqp/schema/Descriptor.cxx b/experimental/cpp-serializer/src/amqp/schema/described-types/Descriptor.cxx similarity index 100% rename from experimental/cpp-serializer/src/amqp/schema/Descriptor.cxx rename to experimental/cpp-serializer/src/amqp/schema/described-types/Descriptor.cxx diff --git a/experimental/cpp-serializer/src/amqp/schema/Descriptor.h b/experimental/cpp-serializer/src/amqp/schema/described-types/Descriptor.h similarity index 94% rename from experimental/cpp-serializer/src/amqp/schema/Descriptor.h rename to experimental/cpp-serializer/src/amqp/schema/described-types/Descriptor.h index 639964aeba..a1ae4fcf05 100644 --- a/experimental/cpp-serializer/src/amqp/schema/Descriptor.h +++ b/experimental/cpp-serializer/src/amqp/schema/described-types/Descriptor.h @@ -19,8 +19,6 @@ namespace amqp::internal::schema { std::string m_name; public : - Descriptor() = default; - explicit Descriptor (std::string); const std::string & name() const; diff --git a/experimental/cpp-serializer/src/amqp/schema/Envelope.cxx b/experimental/cpp-serializer/src/amqp/schema/described-types/Envelope.cxx similarity index 96% rename from experimental/cpp-serializer/src/amqp/schema/Envelope.cxx rename to experimental/cpp-serializer/src/amqp/schema/described-types/Envelope.cxx index bc896cb2d3..dbbaa8160a 100644 --- a/experimental/cpp-serializer/src/amqp/schema/Envelope.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/described-types/Envelope.cxx @@ -2,7 +2,7 @@ #include -#include "amqp/schema/Schema.h" +#include "amqp/schema/described-types/Schema.h" #include "amqp/schema/ISchema.h" /******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/Envelope.h b/experimental/cpp-serializer/src/amqp/schema/described-types/Envelope.h similarity index 94% rename from experimental/cpp-serializer/src/amqp/schema/Envelope.h rename to experimental/cpp-serializer/src/amqp/schema/described-types/Envelope.h index ede8018f84..3d182a1058 100644 --- a/experimental/cpp-serializer/src/amqp/schema/Envelope.h +++ b/experimental/cpp-serializer/src/amqp/schema/described-types/Envelope.h @@ -4,7 +4,7 @@ #include "amqp/AMQPDescribed.h" -#include "Schema.h" +#include "amqp/schema/described-types/Schema.h" #include diff --git a/experimental/cpp-serializer/src/amqp/schema/Schema.cxx b/experimental/cpp-serializer/src/amqp/schema/described-types/Schema.cxx similarity index 100% rename from experimental/cpp-serializer/src/amqp/schema/Schema.cxx rename to experimental/cpp-serializer/src/amqp/schema/described-types/Schema.cxx diff --git a/experimental/cpp-serializer/src/amqp/schema/Schema.h b/experimental/cpp-serializer/src/amqp/schema/described-types/Schema.h similarity index 86% rename from experimental/cpp-serializer/src/amqp/schema/Schema.h rename to experimental/cpp-serializer/src/amqp/schema/described-types/Schema.h index fc6fbbb4c2..ff6ea87b42 100644 --- a/experimental/cpp-serializer/src/amqp/schema/Schema.h +++ b/experimental/cpp-serializer/src/amqp/schema/described-types/Schema.h @@ -9,7 +9,7 @@ #include "types.h" #include "Composite.h" #include "Descriptor.h" -#include "OrderedTypeNotations.h" +#include "schema/OrderedTypeNotations.h" #include "amqp/AMQPDescribed.h" #include "amqp/schema/ISchema.h" @@ -20,10 +20,16 @@ namespace amqp::internal::schema { using SchemaMap = std::map< std::string, - const std::reference_wrapper>>; + const std::reference_wrapper>>; using ISchemaType = amqp::schema::ISchema; +} + +/******************************************************************************/ + +namespace amqp::internal::schema { + class Schema : public amqp::schema::ISchema , public amqp::AMQPDescribed diff --git a/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptor.cxx b/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptor.cxx similarity index 89% rename from experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptor.cxx rename to experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptor.cxx index 5d85a09717..e1398474b2 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptor.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptor.cxx @@ -1,17 +1,17 @@ #include "AMQPDescriptor.h" #include -#include +#include #include "proton/proton_wrapper.h" #include "AMQPDescriptorRegistory.h" /******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { std::ostream & - operator<<(std::ostream &stream_, const amqp::internal::AutoIndent &ai_) { + operator<<(std::ostream &stream_, const AutoIndent &ai_) { stream_ << ai_.indent; return stream_; } @@ -21,7 +21,7 @@ namespace amqp::internal { /******************************************************************************/ const std::string & -amqp::internal:: +amqp::internal::schema::descriptors:: AMQPDescriptor::symbol() const { return m_symbol; } @@ -29,7 +29,7 @@ AMQPDescriptor::symbol() const { /******************************************************************************/ std::unique_ptr -amqp::internal:: +amqp::internal::schema::descriptors:: AMQPDescriptor::build (pn_data_t *) const { throw std::runtime_error ("Should never be called"); } @@ -37,7 +37,7 @@ AMQPDescriptor::build (pn_data_t *) const { /******************************************************************************/ inline void -amqp::internal:: +amqp::internal::schema::descriptors:: AMQPDescriptor::read ( pn_data_t * data_, std::stringstream & ss_ @@ -48,7 +48,7 @@ AMQPDescriptor::read ( /******************************************************************************/ void -amqp::internal:: +amqp::internal::schema::descriptors:: AMQPDescriptor::read ( pn_data_t * data_, std::stringstream & ss_, diff --git a/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptor.h b/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptor.h similarity index 80% rename from experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptor.h rename to experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptor.h index d1a4d3dc41..55f83d71e6 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptor.h +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptor.h @@ -23,22 +23,21 @@ struct pn_data_t; * ******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class AutoIndent { - private : - std::string indent; - public : - AutoIndent() : indent { "" } { } + private : + std::string indent; + public : + AutoIndent() : indent { "" } { } - AutoIndent (const AutoIndent & ai_) - : indent { ai_.indent + " "} - { } + AutoIndent (const AutoIndent & ai_) + : indent { ai_.indent + " "} + { } - friend std::ostream & - operator << (std::ostream & stream_, const AutoIndent & ai_); - - }; + friend std::ostream & + operator << (std::ostream & stream_, const AutoIndent & ai_); + }; } /****************************************************************************** @@ -47,7 +46,7 @@ namespace amqp::internal { * ******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class AMQPDescriptor { protected : diff --git a/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptorRegistory.cxx b/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptorRegistory.cxx new file mode 100644 index 0000000000..c670eb6242 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptorRegistory.cxx @@ -0,0 +1,133 @@ +#include "AMQPDescriptorRegistory.h" +#include "AMQPDescriptors.h" + +#include "amqp/schema/Descriptors.h" + +#include "corda-descriptors/FieldDescriptor.h" +#include "corda-descriptors/SchemaDescriptor.h" +#include "corda-descriptors/ObjectDescriptor.h" +#include "corda-descriptors/ChoiceDescriptor.h" +#include "corda-descriptors/EnvelopeDescriptor.h" +#include "corda-descriptors/CompositeDescriptor.h" +#include "corda-descriptors/RestrictedDescriptor.h" + +#include +#include + +/******************************************************************************/ + +/** + * + */ +namespace amqp::internal { + + std::map> + AMQPDescriptorRegistory = { + { + 22UL, + std::make_shared ("DESCRIBED", -1) + }, + { + 1UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS, + std::make_shared ( + "ENVELOPE", + ::amqp::schema::descriptors::ENVELOPE) + }, + { + 2UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS, + std::make_shared ( + "SCHEMA", + ::amqp::schema::descriptors::SCHEMA) + }, + { + 3UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS, + std::make_shared ( + "OBJECT_DESCRIPTOR", + ::amqp::schema::descriptors::OBJECT) + }, + { + 4UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS, + std::make_shared ( + "FIELD", + ::amqp::schema::descriptors::FIELD) + }, + { + 5UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS, + std::make_shared ( + "COMPOSITE_TYPE", + ::amqp::schema::descriptors::COMPOSITE_TYPE) + }, + { + 6UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS, + std::make_shared ( + "RESTRICTED_TYPE", + ::amqp::schema::descriptors::RESTRICTED_TYPE) + }, + { + 7UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS, + std::make_shared ( + "CHOICE", + ::amqp::schema::descriptors::CHOICE) + }, + { + 8UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS, + std::make_shared ( + "REFERENCED_OBJECT", + ::amqp::schema::descriptors::REFERENCED_OBJECT) + }, + { + 9UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS, + std::make_shared ( + "TRANSFORM_SCHEMA", + ::amqp::schema::descriptors::TRANSFORM_SCHEMA) + }, + { + 10UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS, + std::make_shared ( + "TRANSFORM_ELEMENT", + ::amqp::schema::descriptors::TRANSFORM_ELEMENT) + }, + { + 11UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS, + std::make_shared ( + "TRANSFORM_ELEMENT_KEY", + ::amqp::schema::descriptors::TRANSFORM_ELEMENT_KEY) + } + }; +} + +/******************************************************************************/ + +uint32_t +amqp::stripCorda (uint64_t id) { + return static_cast(id & (uint64_t)UINT_MAX); +} + +/******************************************************************************/ + +std::string +amqp::describedToString (uint64_t val_) { + switch (val_) { + case (1UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "ENVELOPE"; + case (2UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "SCHEMA"; + case (3UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "OBJECT_DESCRIPTOR"; + case (4UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "FIELD"; + case (5UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "COMPOSITE_TYPE"; + case (6UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "RESTRICTED_TYPE"; + case (7UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "CHOICE"; + case (8UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "REFERENCED_OBJECT"; + case (9UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_SCHEMA"; + case (10UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_ELEMENT"; + case (11UL | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS) : return "TRANSFORM_ELEMENT_KEY"; + default : return "UNKNOWN"; + } +} + +/******************************************************************************/ + +std::string +amqp::describedToString (uint32_t val_) { + return describedToString(val_ | ::amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS); +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptorRegistory.h b/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptorRegistory.h similarity index 55% rename from experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptorRegistory.h rename to experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptorRegistory.h index f6ba72148a..dda49f2a70 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptorRegistory.h +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptorRegistory.h @@ -11,46 +11,15 @@ /******************************************************************************/ -/** - * R3 AMQP assigned enterprise number - * - * see [here](https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers) - * - * Repeated here for brevity: - * 50530 - R3 - Mike Hearn - mike&r3.com - */ -namespace amqp::internal { - - extern const uint64_t DESCRIPTOR_TOP_32BITS; - -} - -/******************************************************************************/ - -namespace amqp::internal { - - extern const int ENVELOPE; - extern const int SCHEMA; - extern const int OBJECT_DESCRIPTOR; - extern const int FIELD; - extern const int COMPOSITE_TYPE; - extern const int RESTRICTED_TYPE; - extern const int CHOICE; - extern const int REFERENCED_OBJECT; - extern const int TRANSFORM_SCHEMA; - extern const int TRANSFORM_ELEMENT; - extern const int TRANSFORM_ELEMENT_KEY; - -} /******************************************************************************/ /** * */ -namespace amqp { +namespace amqp::internal { - extern std::map> AMQPDescriptorRegistory; + extern std::map> AMQPDescriptorRegistory; } diff --git a/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptors.cxx b/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptors.cxx similarity index 83% rename from experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptors.cxx rename to experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptors.cxx index 8ee78c7b0e..8d9794c2f6 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptors.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptors.cxx @@ -1,5 +1,6 @@ #include "AMQPDescriptors.h" #include "AMQPDescriptorRegistory.h" +#include "amqp/schema/Descriptors.h" #include #include @@ -8,10 +9,10 @@ #include "colours.h" #include "debug.h" -#include "Field.h" -#include "Schema.h" -#include "Envelope.h" -#include "Composite.h" +#include "field-types/Field.h" +#include "amqp/schema/described-types/Schema.h" +#include "amqp/schema/described-types/Envelope.h" +#include "amqp/schema/described-types/Composite.h" #include "amqp/schema/restricted-types/Restricted.h" #include "amqp/schema/OrderedTypeNotations.h" #include "amqp/AMQPDescribed.h" @@ -26,14 +27,14 @@ ******************************************************************************/ void -amqp::internal:: +amqp::internal::schema::descriptors:: AMQPDescriptor::validateAndNext (pn_data_t * const data_) const { if (pn_data_type(data_) != PN_ULONG) { throw std::runtime_error ("Bad type for a descriptor"); } if ( (m_val == -1) - || (pn_data_get_ulong(data_) != (static_cast(m_val) | amqp::internal::DESCRIPTOR_TOP_32BITS))) + || (pn_data_get_ulong(data_) != (static_cast(m_val) | amqp::schema::descriptors::DESCRIPTOR_TOP_32BITS))) { throw std::runtime_error ("Invalid Type"); } @@ -44,7 +45,7 @@ AMQPDescriptor::validateAndNext (pn_data_t * const data_) const { /******************************************************************************/ uPtr -amqp::internal:: +amqp::internal::schema::descriptors:: ReferencedObjectDescriptor::build (pn_data_t * data_) const { validateAndNext (data_); @@ -56,7 +57,7 @@ ReferencedObjectDescriptor::build (pn_data_t * data_) const { /******************************************************************************/ uPtr -amqp::internal:: +amqp::internal::schema::descriptors:: TransformSchemaDescriptor::build (pn_data_t * data_) const { validateAndNext (data_); @@ -68,7 +69,7 @@ TransformSchemaDescriptor::build (pn_data_t * data_) const { /******************************************************************************/ uPtr -amqp::internal:: +amqp::internal::schema::descriptors:: TransformElementDescriptor::build (pn_data_t * data_) const { validateAndNext (data_); @@ -80,7 +81,7 @@ TransformElementDescriptor::build (pn_data_t * data_) const { /******************************************************************************/ uPtr -amqp::internal:: +amqp::internal::schema::descriptors:: TransformElementKeyDescriptor::build (pn_data_t * data_) const { validateAndNext (data_); diff --git a/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptors.h b/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptors.h similarity index 89% rename from experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptors.h rename to experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptors.h index 3b356e9984..4c8078b2df 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/AMQPDescriptors.h +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/AMQPDescriptors.h @@ -11,7 +11,7 @@ #include "types.h" #include "amqp/AMQPDescribed.h" #include "AMQPDescriptor.h" -#include "amqp/schema/Descriptor.h" +#include "amqp/schema/described-types/Descriptor.h" #include "proton/proton_wrapper.h" #include "AMQPDescriptorRegistory.h" @@ -21,7 +21,7 @@ struct pn_data_t; /******************************************************************************/ -namespace amqp::internal::descriptors { +namespace amqp::internal::schema::descriptors { /** * Look up a described type by its ID in the AMQPDescriptorRegistry and @@ -40,20 +40,13 @@ namespace amqp::internal::descriptors { return uPtr( static_cast( - amqp::AMQPDescriptorRegistory[id]->build(data_).release())); + AMQPDescriptorRegistory[id]->build(data_).release())); } } /******************************************************************************/ -namespace amqp::internal { - - -} - -/******************************************************************************/ - -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class ReferencedObjectDescriptor : public AMQPDescriptor { public : @@ -72,7 +65,7 @@ namespace amqp::internal { /******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class TransformSchemaDescriptor : public AMQPDescriptor { public : @@ -91,7 +84,7 @@ namespace amqp::internal { /******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class TransformElementDescriptor : public AMQPDescriptor { public : @@ -110,7 +103,7 @@ namespace amqp::internal { /******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class TransformElementKeyDescriptor : public AMQPDescriptor { public : diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/ChoiceDescriptor.cxx b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/ChoiceDescriptor.cxx similarity index 76% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/ChoiceDescriptor.cxx rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/ChoiceDescriptor.cxx index 022249fb18..7fbd56b044 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/ChoiceDescriptor.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/ChoiceDescriptor.cxx @@ -1,4 +1,4 @@ -#include "amqp/schema/Choice.h" +#include "amqp/schema/described-types/Choice.h" #include "ChoiceDescriptor.h" #include "types.h" @@ -7,17 +7,17 @@ /******************************************************************************/ -amqp::internal:: +amqp::internal::schema::descriptors:: ChoiceDescriptor::ChoiceDescriptor ( - const std::string & symbol_, + std::string symbol_, int val_ -) : AMQPDescriptor (symbol_, val_) { +) : AMQPDescriptor (std::move (symbol_), val_) { } /******************************************************************************/ std::unique_ptr -amqp::internal:: +amqp::internal::schema::descriptors:: ChoiceDescriptor::build (pn_data_t * data_) const { validateAndNext (data_); proton::auto_enter ae (data_); diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/ChoiceDescriptor.h b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/ChoiceDescriptor.h similarity index 78% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/ChoiceDescriptor.h rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/ChoiceDescriptor.h index 7a5d8e8188..c51713eed3 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/ChoiceDescriptor.h +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/ChoiceDescriptor.h @@ -1,6 +1,6 @@ #pragma once -#include "amqp/descriptors/AMQPDescriptor.h" +#include "amqp/schema/descriptors/AMQPDescriptor.h" /****************************************************************************** * @@ -8,13 +8,13 @@ * ******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class ChoiceDescriptor : public AMQPDescriptor { public : ChoiceDescriptor() = delete; - ChoiceDescriptor (const std::string &, int); + ChoiceDescriptor (std::string, int); ~ChoiceDescriptor() final = default; diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/CompositeDescriptor.cxx b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/CompositeDescriptor.cxx similarity index 89% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/CompositeDescriptor.cxx rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/CompositeDescriptor.cxx index a49689f027..1edfa0aab6 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/CompositeDescriptor.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/CompositeDescriptor.cxx @@ -9,30 +9,30 @@ #include "proton/proton_wrapper.h" -#include "amqp/descriptors/AMQPDescriptors.h" +#include "amqp/schema/descriptors/AMQPDescriptors.h" -#include "amqp/schema/Field.h" -#include "amqp/schema/Composite.h" -#include "amqp/schema/Descriptor.h" +#include "amqp/schema/field-types/Field.h" +#include "amqp/schema/described-types/Composite.h" +#include "amqp/schema/described-types/Descriptor.h" /****************************************************************************** * - * amqp::internal::CompositeDescriptor + * amqp::internal::schema::descriptors::CompositeDescriptor * ******************************************************************************/ -amqp::internal:: +amqp::internal::schema::descriptors:: CompositeDescriptor::CompositeDescriptor ( - const std::string & symbol_, + std::string symbol_, int val_ -) : AMQPDescriptor (symbol_, val_) { +) : AMQPDescriptor (std::move (symbol_), val_) { } /******************************************************************************/ uPtr -amqp::internal:: +amqp::internal::schema::descriptors:: CompositeDescriptor::build (pn_data_t * data_) const { DBG ("COMPOSITE" << std::endl); // NOLINT @@ -88,7 +88,7 @@ CompositeDescriptor::build (pn_data_t * data_) const { /******************************************************************************/ void -amqp::internal:: +amqp::internal::schema::descriptors:: CompositeDescriptor::read ( pn_data_t * data_, std::stringstream & ss_, diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/CompositeDescriptor.h b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/CompositeDescriptor.h similarity index 79% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/CompositeDescriptor.h rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/CompositeDescriptor.h index bdfc977147..8ef09581d6 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/CompositeDescriptor.h +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/CompositeDescriptor.h @@ -1,15 +1,15 @@ #pragma once -#include "amqp/descriptors/AMQPDescriptor.h" +#include "amqp/schema/descriptors/AMQPDescriptor.h" /******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class CompositeDescriptor : public AMQPDescriptor { public : CompositeDescriptor() = delete; - CompositeDescriptor (const std::string &, int); + CompositeDescriptor (std::string, int); ~CompositeDescriptor() final = default; diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/EnvelopeDescriptor.cxx b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/EnvelopeDescriptor.cxx similarity index 85% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/EnvelopeDescriptor.cxx rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/EnvelopeDescriptor.cxx index d0a08e0250..8a65f05631 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/EnvelopeDescriptor.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/EnvelopeDescriptor.cxx @@ -1,7 +1,7 @@ #include "EnvelopeDescriptor.h" -#include "amqp/schema/Schema.h" -#include "amqp/schema/Envelope.h" +#include "amqp/schema/described-types/Schema.h" +#include "amqp/schema/described-types/Envelope.h" #include "proton/proton_wrapper.h" #include "types.h" @@ -24,7 +24,7 @@ namespace { /****************************************************************************** * - * amqp::internal::EnvelopeDescriptor + * amqp::internal::schema::descriptors::EnvelopeDescriptor * ******************************************************************************/ @@ -35,9 +35,11 @@ namespace { * calling this */ void -amqp::internal:: +amqp::internal::schema::descriptors:: EnvelopeDescriptor::read ( - pn_data_t * data_, std::stringstream & ss_, const AutoIndent & ai_ + pn_data_t * data_, + std::stringstream & ss_, + const AutoIndent & ai_ ) const { // lets just make sure we haven't entered this already proton::is_list (data_); @@ -60,18 +62,18 @@ EnvelopeDescriptor::read ( /******************************************************************************/ -amqp::internal:: +amqp::internal::schema::descriptors:: EnvelopeDescriptor::EnvelopeDescriptor ( - const std::string & symbol_, + std::string symbol_, int val_ -) : AMQPDescriptor (symbol_, val_) { +) : AMQPDescriptor (std::move (symbol_), val_) { } /******************************************************************************/ uPtr -amqp::internal:: +amqp::internal::schema::descriptors:: EnvelopeDescriptor::build (pn_data_t * data_) const { DBG ("ENVELOPE" << std::endl); // NOLINT diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/EnvelopeDescriptor.h b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/EnvelopeDescriptor.h similarity index 90% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/EnvelopeDescriptor.h rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/EnvelopeDescriptor.h index ddea2933fe..12b1ac8d6e 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/EnvelopeDescriptor.h +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/EnvelopeDescriptor.h @@ -19,12 +19,12 @@ struct pn_data_t; * ******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class EnvelopeDescriptor : public AMQPDescriptor { public : EnvelopeDescriptor() = delete; - EnvelopeDescriptor (const std::string &, int); + EnvelopeDescriptor (std::string, int); ~EnvelopeDescriptor() final = default; diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/FieldDescriptor.cxx b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/FieldDescriptor.cxx similarity index 86% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/FieldDescriptor.cxx rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/FieldDescriptor.cxx index e6ef4a1799..5320d05038 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/FieldDescriptor.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/FieldDescriptor.cxx @@ -5,29 +5,29 @@ #include "proton/proton_wrapper.h" -#include "amqp/schema/Field.h" +#include "amqp/schema/field-types/Field.h" #include /****************************************************************************** * - * amqp::internal::FieldDescriptor + * amqp::internal::schema::descriptors::FieldDescriptor * ******************************************************************************/ -amqp::internal:: +amqp::internal::schema::descriptors:: FieldDescriptor::FieldDescriptor ( - const std::string & symbol_, + std::string symbol_, int val_ -) : AMQPDescriptor(symbol_, val_) { +) : AMQPDescriptor (std::move (symbol_), val_) { } /******************************************************************************/ uPtr -amqp::internal:: -FieldDescriptor::build(pn_data_t * data_) const { +amqp::internal::schema::descriptors:: +FieldDescriptor::build (pn_data_t * data_) const { DBG ("FIELD" << std::endl); // NOLINT validateAndNext (data_); @@ -37,11 +37,15 @@ FieldDescriptor::build(pn_data_t * data_) const { /* name: String */ auto name = proton::get_string (data_); + DBG ("FIELD::name: \"" << name << "\"" << std::endl); // NOLINT + pn_data_next (data_); /* type: String */ auto type = proton::get_string (data_); + DBG ("FIELD::type: \"" << type << "\"" << std::endl); // NOLINT + pn_data_next (data_); /* requires: List */ @@ -74,14 +78,14 @@ FieldDescriptor::build(pn_data_t * data_) const { /* multiple: Boolean */ auto multiple = proton::get_boolean(data_); - return std::make_unique ( + return schema::Field::make ( name, type, requires, def, label, mandatory, multiple); } /******************************************************************************/ void -amqp::internal:: +amqp::internal::schema::descriptors:: FieldDescriptor::read ( pn_data_t * data_, std::stringstream & ss_, diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/FieldDescriptor.h b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/FieldDescriptor.h similarity index 82% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/FieldDescriptor.h rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/FieldDescriptor.h index 34bc8e7953..7ef38af136 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/FieldDescriptor.h +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/FieldDescriptor.h @@ -4,16 +4,16 @@ #include "proton/codec.h" #include "amqp/AMQPDescribed.h" -#include "amqp/descriptors/AMQPDescriptor.h" +#include "amqp/schema/descriptors/AMQPDescriptor.h" /******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class FieldDescriptor : public AMQPDescriptor { public : FieldDescriptor() = delete; - FieldDescriptor (const std::string &, int); + FieldDescriptor (std::string, int); ~FieldDescriptor() final = default; diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/ObjectDescriptor.cxx b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/ObjectDescriptor.cxx similarity index 79% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/ObjectDescriptor.cxx rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/ObjectDescriptor.cxx index af5687f51d..35d4bfc0a2 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/ObjectDescriptor.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/ObjectDescriptor.cxx @@ -4,21 +4,21 @@ #include "debug.h" #include "proton/proton_wrapper.h" -#include "amqp/schema/Descriptor.h" +#include "amqp/schema/described-types/Descriptor.h" #include /****************************************************************************** * - * amqp::internal::ObjectDescriptor + * amqp::internal::schema::descriptors::ObjectDescriptor * ******************************************************************************/ -amqp::internal:: +amqp::internal::schema::descriptors:: ObjectDescriptor::ObjectDescriptor ( - const std::string & symbol_, + std::string symbol_, int val_ -) : AMQPDescriptor (symbol_, val_) { +) : AMQPDescriptor (std::move (symbol_), val_) { } /******************************************************************************/ @@ -27,8 +27,8 @@ ObjectDescriptor::ObjectDescriptor ( * */ uPtr -amqp::internal:: -ObjectDescriptor::build(pn_data_t * data_) const { +amqp::internal::schema::descriptors:: +ObjectDescriptor::build (pn_data_t * data_) const { DBG ("DESCRIPTOR" << std::endl); // NOLINT validateAndNext (data_); @@ -43,7 +43,7 @@ ObjectDescriptor::build(pn_data_t * data_) const { /******************************************************************************/ void -amqp::internal:: +amqp::internal::schema::descriptors:: ObjectDescriptor::read ( pn_data_t * data_, std::stringstream & ss_, diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/ObjectDescriptor.h b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/ObjectDescriptor.h similarity index 83% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/ObjectDescriptor.h rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/ObjectDescriptor.h index 7f7eb57c49..df374554a9 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/ObjectDescriptor.h +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/ObjectDescriptor.h @@ -2,7 +2,7 @@ /******************************************************************************/ -#include "amqp/descriptors/AMQPDescriptor.h" +#include "amqp/schema/descriptors/AMQPDescriptor.h" /******************************************************************************/ @@ -10,13 +10,13 @@ struct pn_data_t; /******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class ObjectDescriptor : public AMQPDescriptor { public : ObjectDescriptor() = delete; - ObjectDescriptor(const std::string &, int); + ObjectDescriptor (std::string, int); ~ObjectDescriptor() final = default; diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/RestrictedDescriptor.cxx b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/RestrictedDescriptor.cxx similarity index 60% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/RestrictedDescriptor.cxx rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/RestrictedDescriptor.cxx index 74f4229173..c03fe0bcea 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/RestrictedDescriptor.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/RestrictedDescriptor.cxx @@ -3,12 +3,83 @@ #include "types.h" #include "debug.h" -#include "amqp/schema/Choice.h" +#include "amqp/schema/described-types/Choice.h" #include "amqp/schema/restricted-types/Restricted.h" -#include "amqp/descriptors/AMQPDescriptors.h" +#include "amqp/schema/descriptors/AMQPDescriptors.h" +#include +#include #include +/******************************************************************************/ + +namespace { + + const std::map> regexs { + { + "java.lang.Integer", + std::pair { std::regex { "java.lang.Integer"}, "int"} + }, + { + "java.lang.Boolean", + std::pair { std::regex { "java.lang.Boolean"}, "bool"} + }, + { + "java.lang.Byte", + std::pair { std::regex { "java.lang.Byte"}, "char"} + }, + { + "java.lang.Short", + std::pair { std::regex { "java.lang.Short"}, "short"} + }, + { + "java.lang.Character", + std::pair { std::regex { "java.lang.Character"}, "char"} + }, + { + "java.lang.Float", + std::pair { std::regex { "java.lang.Float"}, "float"} + }, + { + "java.lang.Long", + std::pair { std::regex { "java.lang.Long"}, "long"} + }, + { + "java.lang.Double", + std::pair { std::regex { "java.lang.Double"}, "double"} + } + }; + +} + +/******************************************************************************/ + +namespace amqp::internal::schema::descriptors { + + std::string + RestrictedDescriptor::makePrim (const std::string & name_) { + std::string name { name_ }; + for (const auto & i: regexs) { + name = std::regex_replace (name, i.second.first, i.second.second); + } + + return name; + } + +} + +/******************************************************************************/ + +amqp::internal::schema::descriptors:: +RestrictedDescriptor::RestrictedDescriptor ( + std::string symbol_, + int val_ +) : AMQPDescriptor (std::move (symbol_) + , val_ +) { + +} + /****************************************************************************** * * Restricted types represent lists and maps @@ -27,14 +98,14 @@ ******************************************************************************/ uPtr -amqp::internal:: +amqp::internal::schema::descriptors:: RestrictedDescriptor::build (pn_data_t * data_) const { DBG ("RESTRICTED" << std::endl); // NOLINT validateAndNext(data_); proton::auto_enter ae (data_); - auto name = proton::readAndNext(data_); + auto name = makePrim (proton::readAndNext(data_)); auto label = proton::readAndNext(data_, true); DBG (" name: " << name << ", label: \"" << label << "\"" << std::endl); @@ -86,7 +157,7 @@ RestrictedDescriptor::build (pn_data_t * data_) const { /******************************************************************************/ void -amqp::internal:: +amqp::internal::schema::descriptors:: RestrictedDescriptor::read ( pn_data_t * data_, std::stringstream & ss_, diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/RestrictedDescriptor.h b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/RestrictedDescriptor.h similarity index 59% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/RestrictedDescriptor.h rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/RestrictedDescriptor.h index 66f7060c8b..9c7f02b2fa 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/RestrictedDescriptor.h +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/RestrictedDescriptor.h @@ -4,19 +4,24 @@ #include -#include "amqp/descriptors/AMQPDescriptor.h" +#include "amqp/schema/descriptors/AMQPDescriptor.h" /******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class RestrictedDescriptor : public AMQPDescriptor { + public : + /** + * This could just live as a stand alone function in the + * anonymous namespace... but for testing purposes lets + * just make it a static members of the class + */ + static std::string makePrim (const std::string &); + public : RestrictedDescriptor() = delete; - - RestrictedDescriptor(const std::string & symbol_, int val_) - : AMQPDescriptor(symbol_, val_) - { } + RestrictedDescriptor (std::string, int); ~RestrictedDescriptor() final = default; diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/SchemaDescriptor.cxx b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/SchemaDescriptor.cxx similarity index 83% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/SchemaDescriptor.cxx rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/SchemaDescriptor.cxx index 6dd0917e67..da8acfdff2 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/SchemaDescriptor.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/SchemaDescriptor.cxx @@ -7,8 +7,8 @@ #include "proton/codec.h" #include "proton/proton_wrapper.h" #include "amqp/AMQPDescribed.h" -#include "amqp/descriptors/AMQPDescriptors.h" -#include "amqp/schema/Schema.h" +#include "amqp/schema/descriptors/AMQPDescriptors.h" +#include "amqp/schema/described-types/Schema.h" #include "amqp/schema/OrderedTypeNotations.h" #include "amqp/schema/AMQPTypeNotation.h" @@ -16,17 +16,17 @@ /******************************************************************************/ -amqp::internal:: +amqp::internal::schema::descriptors:: SchemaDescriptor::SchemaDescriptor ( - const std::string & symbol_, + std::string symbol_, int val_ -) : AMQPDescriptor (symbol_, val_) { +) : AMQPDescriptor (std::move (symbol_), val_) { } /******************************************************************************/ uPtr -amqp::internal:: +amqp::internal::schema::descriptors:: SchemaDescriptor::build (pn_data_t * data_) const { DBG ("SCHEMA" << std::endl); // NOLINT @@ -41,12 +41,14 @@ SchemaDescriptor::build (pn_data_t * data_) const { proton::auto_list_enter ale (data_); for (int i { 1 } ; pn_data_next(data_) ; ++i) { - DBG (" " << i << "/" << ale.elements() << std::endl); // NOLINT + DBG (" " << i << "/" << ale.elements() << std::endl); // NOLINT proton::auto_list_enter ale2 (data_); while (pn_data_next(data_)) { schemas.insert ( descriptors::dispatchDescribed ( data_)); + + DBG("=======" << std::endl << schemas << "======" << std::endl); } } } @@ -58,7 +60,7 @@ SchemaDescriptor::build (pn_data_t * data_) const { void -amqp::internal:: +amqp::internal::schema::descriptors:: SchemaDescriptor::read ( pn_data_t * data_, std::stringstream & ss_, diff --git a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/SchemaDescriptor.h b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/SchemaDescriptor.h similarity index 81% rename from experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/SchemaDescriptor.h rename to experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/SchemaDescriptor.h index 91782efb97..bdfea1cf4e 100644 --- a/experimental/cpp-serializer/src/amqp/descriptors/corda-descriptors/SchemaDescriptor.h +++ b/experimental/cpp-serializer/src/amqp/schema/descriptors/corda-descriptors/SchemaDescriptor.h @@ -1,6 +1,6 @@ #pragma once -#include "amqp/descriptors/AMQPDescriptor.h" +#include "amqp/schema/descriptors/AMQPDescriptor.h" /******************************************************************************/ @@ -8,12 +8,12 @@ struct pn_data_t; /******************************************************************************/ -namespace amqp::internal { +namespace amqp::internal::schema::descriptors { class SchemaDescriptor : public AMQPDescriptor { public : SchemaDescriptor() = delete; - SchemaDescriptor (const std::string &, int); + SchemaDescriptor (std::string, int); ~SchemaDescriptor() final = default; std::unique_ptr build (pn_data_t *) const override; diff --git a/experimental/cpp-serializer/src/amqp/schema/field-types/ArrayField.cxx b/experimental/cpp-serializer/src/amqp/schema/field-types/ArrayField.cxx new file mode 100644 index 0000000000..65ca57e829 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/field-types/ArrayField.cxx @@ -0,0 +1,54 @@ +#include "ArrayField.h" + +#include "debug.h" + +#include + +/******************************************************************************/ + +const std::string +amqp::internal::schema:: +ArrayField::m_fieldType { + "array" +}; + +/******************************************************************************/ + +amqp::internal::schema:: +ArrayField::ArrayField ( + std::string name_, + std::string type_, + std::list requires_, + std::string default_, + std::string label_, + bool mandatory_, + bool multiple_ +) : RestrictedField ( + std::move (name_), + std::move (type_), + std::move (requires_), + std::move (default_), + std::move (label_), + mandatory_, + multiple_ +) { + DBG ("ArrayField::ArrayField - name: " << name() << ", type: " << type() << std::endl); +} + +/******************************************************************************/ + +const std::string & +amqp::internal::schema:: +ArrayField::resolvedType() const { + return type(); +} + +/******************************************************************************/ + +const std::string & +amqp::internal::schema:: +ArrayField::fieldType() const { + return m_fieldType; +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/field-types/ArrayField.h b/experimental/cpp-serializer/src/amqp/schema/field-types/ArrayField.h new file mode 100644 index 0000000000..89c480be06 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/field-types/ArrayField.h @@ -0,0 +1,24 @@ +#pragma once + +#include "RestrictedField.h" + +/******************************************************************************/ + +namespace amqp::internal::schema { + + class ArrayField : public RestrictedField { + private : + static const std::string m_fieldType; + + public : + ArrayField ( + std::string, std::string, std::list, + std::string, std::string, bool, bool); + + const std::string & fieldType() const override; + const std::string & resolvedType() const override; + }; + +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/field-types/CompositeField.cxx b/experimental/cpp-serializer/src/amqp/schema/field-types/CompositeField.cxx new file mode 100644 index 0000000000..084fe86333 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/field-types/CompositeField.cxx @@ -0,0 +1,63 @@ +#include "CompositeField.h" + +#include + +#include "Field.h" + +#include "debug.h" + +/******************************************************************************/ + +const std::string +amqp::internal::schema::CompositeField::m_fieldType { + "composite" +}; + +/******************************************************************************/ + +amqp::internal::schema:: +CompositeField::CompositeField ( + std::string name_, + std::string type_, + std::list requires_, + std::string default_, + std::string label_, + bool mandatory_, + bool multiple_ +) : Field ( + std::move (name_), + std::move (type_), + std::move (requires_), + std::move (default_), + std::move (label_), + mandatory_, + multiple_) +{ + DBG ("FIELD::FIELD - name: " << name() << ", type: " << type() << std::endl); +} + +/******************************************************************************/ + +bool +amqp::internal::schema:: +CompositeField::primitive() const { + return false; +} + +/******************************************************************************/ + +const std::string & +amqp::internal::schema:: +CompositeField::fieldType() const { + return m_fieldType; +} + +/******************************************************************************/ + +const std::string & +amqp::internal::schema:: +CompositeField::resolvedType() const { + return type(); +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/field-types/CompositeField.h b/experimental/cpp-serializer/src/amqp/schema/field-types/CompositeField.h new file mode 100644 index 0000000000..0ef4085130 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/field-types/CompositeField.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Field.h" + +/******************************************************************************/ + +namespace amqp::internal::schema { + + class CompositeField : public Field { + private : + static const std::string m_fieldType; + + public : + CompositeField ( + std::string, std::string, std::list, + std::string, std::string, bool, bool); + + bool primitive() const override; + const std::string & fieldType() const override; + const std::string & resolvedType() const override; + }; + +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/field-types/Field.cxx b/experimental/cpp-serializer/src/amqp/schema/field-types/Field.cxx new file mode 100644 index 0000000000..ac1ea70c64 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/field-types/Field.cxx @@ -0,0 +1,153 @@ +#include "Field.h" + +#include +#include + +#include "debug.h" + +#include "ArrayField.h" +#include "PrimitiveField.h" +#include "CompositeField.h" +#include "RestrictedField.h" + +#include "../restricted-types/Array.h" + +/******************************************************************************/ + +namespace amqp::internal::schema { + +std::ostream & +operator << (std::ostream & stream_, const Field & field_) { + std::stringstream ss; + for (auto &i: field_.m_requires) { ss << i; } + + stream_ << field_.m_name + << " : " << field_.m_type + << " : [" << ss.str() << "]" << std::endl; + + return stream_; +} + +} + +/******************************************************************************/ + +uPtr +amqp::internal::schema:: +Field::make ( + std::string name_, + std::string type_, + std::list requires_, + std::string default_, + std::string label_, + bool mandatory_, + bool multiple_ +) { + if (typeIsPrimitive (type_)) { + DBG ("-> primitive" << std::endl); + return std::make_unique( + std::move (name_), + std::move (type_), + std::move (default_), + std::move (label_), + mandatory_, + multiple_); + } else if (Array::isArrayType (type_)) { + DBG ("-> array" << std::endl); + return std::make_unique( + std::move (name_), + std::move (type_), + std::move (requires_), + std::move (default_), + std::move (label_), + mandatory_, + multiple_); + + } else if (type_ == "*") { + DBG ("-> restricted" << std::endl); + return std::make_unique( + std::move (name_), + std::move (type_), + std::move (requires_), + std::move (default_), + std::move (label_), + mandatory_, + multiple_); + } else { + DBG ("-> composite" << std::endl); + return std::make_unique( + std::move (name_), + std::move (type_), + std::move (requires_), + std::move (default_), + std::move (label_), + mandatory_, + multiple_); + } + +} + +/****************************************************************************** + * + * + * + ******************************************************************************/ + +amqp::internal::schema:: +Field::Field ( + std::string name_, + std::string type_, + std::list requires_, + std::string default_, + std::string label_, + bool mandatory_, + bool multiple_ +) : m_name (std::move (name_)) + , m_type (std::move (type_)) + , m_requires (std::move (requires_)) + , m_default (std::move (default_)) + , m_label (std::move (label_)) + , m_mandatory (mandatory_) + , m_multiple (multiple_) +{ + DBG ("FIELD::FIELD - name: " << name() << ", type: " << type_ << std::endl); +} + +/******************************************************************************/ + +bool +amqp::internal::schema:: +Field::typeIsPrimitive (const std::string & type_) { + return (type_ == "string" || + type_ == "long" || + type_ == "boolean" || + type_ == "int" || + type_ == "double"); +} + +/******************************************************************************/ + +const std::string & +amqp::internal::schema:: +Field::name() const { + return m_name; +} + +/******************************************************************************/ + +const std::string & +amqp::internal::schema:: +Field::type() const { + return m_type; +} + +/******************************************************************************/ + +const std::list & +amqp::internal::schema:: +Field::requires() const { + return m_requires; +} + +/******************************************************************************/ + diff --git a/experimental/cpp-serializer/src/amqp/schema/field-types/Field.h b/experimental/cpp-serializer/src/amqp/schema/field-types/Field.h new file mode 100644 index 0000000000..762951d970 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/field-types/Field.h @@ -0,0 +1,65 @@ +#pragma once + +/******************************************************************************/ + +#include "amqp/schema/described-types/Descriptor.h" +#include "amqp/AMQPDescribed.h" + +#include "types.h" + +#include +#include +#include + +/******************************************************************************/ + +namespace amqp::internal::schema { + + /** + * + * A Corda AMQP Scehma Field type has: + * - name : String + * - type : String + * - requires : List + * - default : nullable String + * - label : nullable String + * - mandatory : Boolean + * - multiple : Boolean + */ + class Field : public AMQPDescribed { + public : + friend std::ostream & operator << (std::ostream &, const Field &); + + static bool typeIsPrimitive (const std::string &); + + static uPtr make ( + std::string, std::string, std::list, + std::string, std::string, bool, bool); + + private : + std::string m_name; + std::string m_type; + std::list m_requires; + std::string m_default; + std::string m_label; + bool m_mandatory; + bool m_multiple; + + protected : + Field (std::string, std::string, std::list, + std::string, std::string, bool, bool); + + public : + const std::string & name() const; + const std::string & type() const; + const std::list & requires() const; + + virtual bool primitive() const = 0; + virtual const std::string & fieldType() const = 0; + virtual const std::string & resolvedType() const = 0; + }; + +} + +/******************************************************************************/ + diff --git a/experimental/cpp-serializer/src/amqp/schema/field-types/PrimitiveField.cxx b/experimental/cpp-serializer/src/amqp/schema/field-types/PrimitiveField.cxx new file mode 100644 index 0000000000..dad4b3fc9d --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/field-types/PrimitiveField.cxx @@ -0,0 +1,55 @@ +#include "PrimitiveField.h" + +/******************************************************************************/ + +const std::string +amqp::internal::schema::PrimitiveField::m_fieldType { + "primitive" +}; + +/******************************************************************************/ + +amqp::internal::schema:: +PrimitiveField::PrimitiveField ( + std::string name_, + std::string type_, + std::string default_, + std::string label_, + bool mandatory_, + bool multiple_ +) : Field ( + std::move (name_), + std::move (type_), + { }, // requires + std::move (default_), + std::move (label_), + mandatory_, + multiple_ +) { +} + +/******************************************************************************/ + +bool +amqp::internal::schema:: +PrimitiveField::primitive() const { + return true; +} + +/******************************************************************************/ + +const std::string & +amqp::internal::schema:: +PrimitiveField::fieldType() const { + return m_fieldType; +} + +/******************************************************************************/ + +const std::string & +amqp::internal::schema:: +PrimitiveField::resolvedType() const { + return type(); +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/field-types/PrimitiveField.h b/experimental/cpp-serializer/src/amqp/schema/field-types/PrimitiveField.h new file mode 100644 index 0000000000..bd8ea271e6 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/field-types/PrimitiveField.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Field.h" + +/******************************************************************************/ + +namespace amqp::internal::schema { + + class PrimitiveField : public Field { + private : + static const std::string m_fieldType; + + public : + PrimitiveField ( + std::string, std::string, std::string, + std::string, bool, bool); + + bool primitive() const override; + const std::string & fieldType() const override; + const std::string & resolvedType() const override; + }; + +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/field-types/RestrictedField.cxx b/experimental/cpp-serializer/src/amqp/schema/field-types/RestrictedField.cxx new file mode 100644 index 0000000000..2d8cb46fab --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/field-types/RestrictedField.cxx @@ -0,0 +1,56 @@ +#include "RestrictedField.h" + +/******************************************************************************/ + +const std::string +amqp::internal::schema::RestrictedField::m_fieldType { + "restricted" +}; + +/******************************************************************************/ + +amqp::internal::schema:: +RestrictedField::RestrictedField ( + std::string name_, + std::string type_, + std::list requires_, + std::string default_, + std::string label_, + bool mandatory_, + bool multiple_ +) : Field ( + std::move (name_), + std::move (type_), + std::move (requires_), + std::move (default_), + std::move (label_), + mandatory_, + multiple_) +{ +} + +/******************************************************************************/ + +bool +amqp::internal::schema:: +RestrictedField::primitive() const { + return false; +} + +/******************************************************************************/ + +const std::string & +amqp::internal::schema:: +RestrictedField::fieldType() const { + return m_fieldType; +} + +/******************************************************************************/ + +const std::string & +amqp::internal::schema:: +RestrictedField::resolvedType() const { + return requires().front(); +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/field-types/RestrictedField.h b/experimental/cpp-serializer/src/amqp/schema/field-types/RestrictedField.h new file mode 100644 index 0000000000..43767676e3 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/field-types/RestrictedField.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Field.h" + +/******************************************************************************/ + +namespace amqp::internal::schema { + + class RestrictedField : public Field { + private : + static const std::string m_fieldType; + + public : + RestrictedField ( + std::string, std::string, std::list, + std::string, std::string, bool, bool); + + bool primitive() const override; + const std::string & fieldType() const override; + const std::string & resolvedType() const override; + }; + +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/restricted-types/Array.cxx b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Array.cxx new file mode 100644 index 0000000000..f6168ece81 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Array.cxx @@ -0,0 +1,169 @@ +#include "Array.h" + +#include "Map.h" +#include "List.h" +#include "Enum.h" +#include "amqp/schema/described-types/Composite.h" + +/****************************************************************************** + * + * Static member functions + * + ******************************************************************************/ + +namespace { + + const std::string array { "[]" }; + const std::string primArray { "[p]" }; + +} + +std::string +amqp::internal::schema:: +Array::arrayType (const std::string & array_) { + auto pos = array_.find ('['); + return std::string { array_.substr (0, pos) }; +} + +/** + * when C++20 is done we can use .endswith, until then we have to do a reverse search + */ +bool +amqp::internal::schema:: +Array::isArrayType (const std::string & type_) { + return (std::equal ( + type_.rbegin(), type_.rbegin() + array.size(), + array.rbegin(), array.rend()) + || std::equal ( + type_.rbegin(), type_.rbegin() + primArray.size(), + primArray.rbegin(), primArray.rend())); +} + +/****************************************************************************** + * + * Non static member functions + * + ******************************************************************************/ + +amqp::internal::schema:: +Array::Array ( + uPtr descriptor_, + std::string name_, + std::string label_, + std::vector provides_, + std::string source_ +) : Restricted ( + std::move (descriptor_), + std::move (name_), + std::move (label_), + std::move (provides_), + amqp::internal::schema::Restricted::RestrictedTypes::array_t) + , m_arrayOf { unbox (arrayType (name())) } + , m_source { std::move (source_) } +{ + DBG ("ARRAY OF::" << arrayOf() << ", name::" << name() << std::endl); +} + +/******************************************************************************/ + +std::vector::const_iterator +amqp::internal::schema:: +Array::begin() const { + return m_arrayOf.begin(); +} + +/******************************************************************************/ + +std::vector::const_iterator +amqp::internal::schema:: +Array::end() const { + return m_arrayOf.end(); +} + +/******************************************************************************/ + +const std::string & +amqp::internal::schema:: +Array::arrayOf() const { + return m_arrayOf[0]; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +Array::dependsOnMap (const amqp::internal::schema::Map & map_) const { + // do we depend on the lhs + if (arrayOf() == map_.name()) { + return 1; + } + + // does lhs_ depend on us + auto lhsMapOf { map_.mapOf() }; + + if (lhsMapOf.first.get() == name() || lhsMapOf.second.get() == name()) { + return 2; + } + + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +Array::dependsOnList (const amqp::internal::schema::List & list_) const { + // do we depend on the lhs + if (arrayOf() == list_.name()) { + return 1; + } + + // does the left hand side depend on us + if (list_.listOf() == name()) { + return 2; + } + + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +Array::dependsOnArray (const amqp::internal::schema::Array & array_) const { + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +Array::dependsOnEnum (const amqp::internal::schema::Enum & enum_) const { + // an enum cannot depend on us so don't bother checking, lets just check + // if we depend on it + if (arrayOf() == enum_.name()) { + return 1; + } + + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +Array::dependsOnRHS (const amqp::internal::schema::Composite & lhs_) const { + if (arrayOf() == lhs_.name()) { + return 1; + } + + for (const auto & field : lhs_.fields()) { + if (field->resolvedType() == name()) { + return 2; + } + } + + return 0; +} + +/*********************************************************o*********************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/restricted-types/Array.h b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Array.h new file mode 100644 index 0000000000..179a666713 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Array.h @@ -0,0 +1,41 @@ +#pragma once + +#include "Restricted.h" + +/******************************************************************************/ + +namespace amqp::internal::schema { + + class Array : public Restricted { + public : + static std::string arrayType (const std::string &); + static bool isArrayType (const std::string &); + + private : + std::vector m_arrayOf; + std::string m_source; + + int dependsOnMap (const Map &) const override; + int dependsOnList (const List &) const override; + int dependsOnEnum (const Enum &) const override; + int dependsOnArray (const Array &) const override; + + public : + Array ( + uPtr descriptor_, + std::string, + std::string, + std::vector, + std::string); + + std::vector::const_iterator begin() const override; + std::vector::const_iterator end() const override; + + const std::string & arrayOf() const; + + int dependsOnRHS (const Composite &) const override; + }; + +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/restricted-types/Enum.cxx b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Enum.cxx index a7792b52da..866aeff0b0 100644 --- a/experimental/cpp-serializer/src/amqp/schema/restricted-types/Enum.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Enum.cxx @@ -2,12 +2,14 @@ #include +#include "debug.h" + +#include "Map.h" #include "List.h" -#include "Composite.h" +#include "amqp/schema/described-types/Composite.h" /******************************************************************************/ - amqp::internal::schema:: Enum::Enum ( uPtr descriptor_, @@ -21,11 +23,11 @@ Enum::Enum ( std::move (name_), std::move (label_), std::move (provides_), - amqp::internal::schema::Restricted::RestrictedTypes::Enum) + amqp::internal::schema::Restricted::RestrictedTypes::enum_t) + , m_source { std::move (source_) } , m_enum { name_ } - , m_choices (std::move (choices_)) + , m_choices { std::move (choices_) } { - } /******************************************************************************/ @@ -48,57 +50,65 @@ Enum::end() const { int amqp::internal::schema:: -Enum::dependsOn (const amqp::internal::schema::Restricted & lhs_) const { - auto rtn { 0 }; - switch (lhs_.restrictedType()) { - case RestrictedTypes::List : { - const auto & list { dynamic_cast(lhs_) }; - - // does the left hand side depend on us - // DBG (" L/L a) " << list.listOf() << " == " << name() << std::endl); // NOLINT - if (list.listOf() == name()) { - rtn = 1; - } - - // do we depend on the lhs - //DBG (" L/L b) " << name() << " == " << list.name() << std::endl); // NOLINT - if (name() == list.name()) { - rtn = 2; - } - - break; - } - case RestrictedTypes::Enum : { - break; - } - case RestrictedTypes::Map : { - - } - +Enum::dependsOnMap (const amqp::internal::schema::Map & map_) const { + // does lhs_ depend on us + auto lhsMapOf { map_.mapOf() }; + if (lhsMapOf.first.get() == name() || lhsMapOf.second.get() == name()) { + return 1; } - return rtn; + return 0; } /******************************************************************************/ int amqp::internal::schema:: -Enum::dependsOn (const amqp::internal::schema::Composite & lhs_) const { - auto rtn { 0 }; +Enum::dependsOnList (const amqp::internal::schema::List & list_) const { + // does the left hand side depend on us + if (list_.listOf() == name()) { + return 2; + } + + // we can never depend on the left hand side so don't bother checking + + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +Enum::dependsOnArray (const amqp::internal::schema::Array & array_) const { + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +Enum::dependsOnEnum (const amqp::internal::schema::Enum &) const { + // enums should never depend on one another so just return 0; + return 0; +} + +/*********************************************************o*********************/ + +int +amqp::internal::schema:: +Enum::dependsOnRHS (const amqp::internal::schema::Composite & lhs_) const { + if (name() == lhs_.name()) { + return 1; + } + for (const auto & field : lhs_.fields()) { -// DBG (" L/C a) " << field->resolvedType() << " == " << name() << std::endl); // NOLINT if (field->resolvedType() == name()) { - rtn = 1; + return 2; } } - // DBG (" L/C b) " << name() << " == " << lhs_.name() << std::endl); // NOLINT - if (name() == lhs_.name()) { - rtn = 2; - } - return rtn; + return 0; } /*********************************************************o*********************/ @@ -117,3 +127,4 @@ Enum::makeChoices() const { } /*********************************************************o*********************/ + diff --git a/experimental/cpp-serializer/src/amqp/schema/restricted-types/Enum.h b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Enum.h index 14355e81d9..624b0d48e8 100644 --- a/experimental/cpp-serializer/src/amqp/schema/restricted-types/Enum.h +++ b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Enum.h @@ -2,13 +2,21 @@ #include "Restricted.h" +/******************************************************************************/ + namespace amqp::internal::schema { class Enum : public Restricted { private : + std::string m_source; std::vector m_enum; std::vector> m_choices; + int dependsOnMap (const Map &) const override; + int dependsOnList (const List &) const override; + int dependsOnEnum (const Enum &) const override; + int dependsOnArray (const Array &) const override; + public : Enum ( uPtr descriptor_, @@ -21,8 +29,7 @@ namespace amqp::internal::schema { std::vector::const_iterator begin() const override; std::vector::const_iterator end() const override; - int dependsOn (const Restricted &) const override; - int dependsOn (const class Composite &) const override; + int dependsOnRHS (const Composite &) const override; std::vector makeChoices() const; }; diff --git a/experimental/cpp-serializer/src/amqp/schema/restricted-types/List.cxx b/experimental/cpp-serializer/src/amqp/schema/restricted-types/List.cxx index a016a505e7..d57e65532e 100644 --- a/experimental/cpp-serializer/src/amqp/schema/restricted-types/List.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/restricted-types/List.cxx @@ -1,27 +1,35 @@ #include #include "List.h" +#include "Map.h" +#include "Enum.h" #include "debug.h" #include "colours.h" -#include "schema/Composite.h" +#include "amqp/schema/described-types/Composite.h" -/******************************************************************************/ +/****************************************************************************** + * + * Static member functions + * + ******************************************************************************/ -namespace { +std::pair +amqp::internal::schema:: +List::listType (const std::string & list_) { + auto pos = list_.find ('<'); - std::pair - listType (const std::string & list_) { - auto pos = list_.find ('<'); - - return std::make_pair ( - std::string { list_.substr (0, pos) }, - std::string { list_.substr(pos + 1, list_.size() - pos - 2) } - ); - } + return std::make_pair ( + std::string { unbox (list_.substr (0, pos)) }, + std::string { unbox (list_.substr(pos + 1, list_.size() - pos - 2)) } + ); } -/******************************************************************************/ +/****************************************************************************** + * + * Non static member functions + * + ******************************************************************************/ amqp::internal::schema:: List::List ( @@ -35,10 +43,10 @@ List::List ( std::move (name_), std::move (label_), std::move (provides_), - amqp::internal::schema::Restricted::RestrictedTypes::List) - , m_listOf { listType(name_).second } + amqp::internal::schema::Restricted::RestrictedTypes::list_t) + , m_listOf { listType (name()).second } + , m_source { std::move (source_) } { - } /******************************************************************************/ @@ -69,48 +77,78 @@ List::listOf() const { int amqp::internal::schema:: -List::dependsOn (const amqp::internal::schema::Restricted & lhs_) const { - auto rtn { 0 }; - switch (lhs_.restrictedType()) { - case RestrictedTypes::List : { - const auto & list { dynamic_cast(lhs_) }; - - // does the left hand side depend on us - DBG (" L/L a) " << list.listOf() << " == " << name() << std::endl); // NOLINT - if (list.listOf() == name()) { - rtn = 1; - } - - // do we depend on the lhs - DBG (" L/L b) " << listOf() << " == " << list.name() << std::endl); // NOLINT - if (listOf() == list.name()) { - rtn = 2; - } - } +List::dependsOnMap (const amqp::internal::schema::Map & map_) const { + // do we depend on the lhs + if (listOf() == map_.name()) { + return 1; } - return rtn; + // does lhs_ depend on us + auto lhsMapOf { map_.mapOf() }; + + if (lhsMapOf.first.get() == name() || lhsMapOf.second.get() == name()) { + return 2; + } + + return 0; } /******************************************************************************/ int amqp::internal::schema:: -List::dependsOn (const amqp::internal::schema::Composite & lhs_) const { - auto rtn { 0 }; +List::dependsOnList (const amqp::internal::schema::List & list_) const { + // do we depend on the lhs + if (listOf() == list_.name()) { + return 1; + } + + // does the left hand side depend on us + if (list_.listOf() == name()) { + return 2; + } + + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +List::dependsOnArray (const amqp::internal::schema::Array & array_) const { + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +List::dependsOnEnum (const amqp::internal::schema::Enum & enum_) const { + // an enum cannot depend on us so don't bother checking, lets just check + // if we depend on it + if (listOf() == enum_.name()) { + return 1; + } + + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +List::dependsOnRHS (const amqp::internal::schema::Composite & lhs_) const { + if (listOf() == lhs_.name()) { + return 1; + } + for (const auto & field : lhs_.fields()) { - DBG (" L/C a) " << field->resolvedType() << " == " << name() << std::endl); // NOLINT if (field->resolvedType() == name()) { - rtn = 1; + return 2; } } - DBG (" L/C b) " << listOf() << " == " << lhs_.name() << std::endl); // NOLINT - if (listOf() == lhs_.name()) { - rtn = 2; - } - - return rtn; + return 0; } /*********************************************************o*********************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/restricted-types/List.h b/experimental/cpp-serializer/src/amqp/schema/restricted-types/List.h index 8e4861ce34..19a71674c0 100644 --- a/experimental/cpp-serializer/src/amqp/schema/restricted-types/List.h +++ b/experimental/cpp-serializer/src/amqp/schema/restricted-types/List.h @@ -7,8 +7,18 @@ namespace amqp::internal::schema { class List : public Restricted { + public : + static std::pair listType ( + const std::string &); + private : std::vector m_listOf; + std::string m_source; + + int dependsOnMap (const Map &) const override; + int dependsOnList (const List &) const override; + int dependsOnEnum (const Enum &) const override; + int dependsOnArray (const Array &) const override; public : List ( @@ -23,8 +33,7 @@ namespace amqp::internal::schema { const std::string & listOf() const; - int dependsOn (const Restricted &) const override; - int dependsOn (const class Composite &) const override; + int dependsOnRHS (const Composite &) const override; }; } diff --git a/experimental/cpp-serializer/src/amqp/schema/restricted-types/Map.cxx b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Map.cxx new file mode 100644 index 0000000000..cb7c58e25d --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Map.cxx @@ -0,0 +1,171 @@ +#include "Map.h" +#include "List.h" +#include "Enum.h" +#include "amqp/schema/described-types/Composite.h" + +/****************************************************************************** + * + * Map Static Member Functions + * + ******************************************************************************/ + +std::tuple +amqp::internal::schema:: +Map::mapType (const std::string & map_) { + uint pos = map_.find ('<'); + + uint idx { pos + 1 }; + for (uint nesting { 0 } ; idx < map_.size(); ++idx) { + if (map_[idx] == '<') { + ++nesting; + } else if (map_[idx] == '>') { + --nesting; + } else if (map_[idx] == ',' && nesting == 0) { + break; + } + } + + auto map = std::string { map_.substr (0, pos) }; + auto of = std::string { map_.substr (pos + 1, idx - pos - 1) }; + of = of.erase(0, of.find_first_not_of(' ')); + auto to = std::string { map_.substr (idx + 1, map_.size() - (idx + 2)) }; + to = to.erase(0, to.find_first_not_of(' ')); + + return { map, unbox (of), unbox (to) }; +} + +/****************************************************************************** + * + * Map Member Functions + * + ******************************************************************************/ + +amqp::internal::schema:: +Map::Map ( + uPtr descriptor_, + std::string name_, + std::string label_, + std::vector provides_, + std::string source_ +) : Restricted ( + std::move (descriptor_), + std::move (name_), + std::move (label_), + std::move (provides_), + amqp::internal::schema::Restricted::RestrictedTypes::map_t) + , m_source { std::move (source_) } +{ + auto [map, of, to] = mapType (name()); + m_mapOf = { of, to }; +} + +/******************************************************************************/ + +std::vector::const_iterator +amqp::internal::schema:: +Map::begin() const { + return m_mapOf.begin(); +} + +/******************************************************************************/ + +std::vector::const_iterator +amqp::internal::schema:: +Map::end() const { + return m_mapOf.end(); +} + +/******************************************************************************/ + +std::pair< + std::reference_wrapper, + std::reference_wrapper> +amqp::internal::schema:: +Map::mapOf() const { + return std::pair { std::cref (m_mapOf[0]), std::cref (m_mapOf[1]) }; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +Map::dependsOnMap (const amqp::internal::schema::Map & lhs_) const { + // do we depend on the lhs + if (m_mapOf[0] == lhs_.name() || m_mapOf[1] == lhs_.name()) { + return 1; + } + + // does lhs_ depend on us + auto lhsMapOf { lhs_.mapOf() }; + if (lhsMapOf.first.get() == name() || lhsMapOf.second.get() == name()) { + return 2; + } + + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +Map::dependsOnList (const amqp::internal::schema::List & lhs_) const { + // do we depend on the lhs + if (m_mapOf[0] == lhs_.name() || m_mapOf[1] == lhs_.name()) { + return 1; + } + + // does lhs_ depend on us + if (lhs_.listOf() == name()) { + return 2; + } + + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +Map::dependsOnArray (const amqp::internal::schema::Array & lhs_) const { + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +Map::dependsOnEnum (const amqp::internal::schema::Enum & lhs_) const { + // do we depend on the lhs + if (m_mapOf[0] == lhs_.name() || m_mapOf[1] == lhs_.name()) { + return 1; + } + + // does lhs_ depend on us + if (lhs_.name() == name()) { + return 2; + } + + return 0; +} + +/******************************************************************************/ + +int +amqp::internal::schema:: +Map::dependsOnRHS (const amqp::internal::schema::Composite & lhs_) const { + // do we depend on the lhs + if (m_mapOf[0] == lhs_.name() || m_mapOf[1] == lhs_.name()) { + return 1; + } + + // does lhs_ depend on us + for (const auto & field : lhs_.fields()) { + if (field->resolvedType() == name()) { + return 2; + } + } + + return 0; +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/restricted-types/Map.h b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Map.h new file mode 100644 index 0000000000..e4a59452c0 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Map.h @@ -0,0 +1,43 @@ +#pragma once + +#include "Restricted.h" + +/******************************************************************************/ + +namespace amqp::internal::schema { + + class Map : public Restricted { + public : + static std::tuple + mapType (const std::string &); + + private : + std::vector m_mapOf; + std::string m_source; + + int dependsOnMap (const Map &) const override; + int dependsOnList (const List &) const override; + int dependsOnEnum (const Enum &) const override; + int dependsOnArray (const Array &) const override; + + public : + Map ( + uPtr descriptor_, + std::string, + std::string, + std::vector, + std::string); + + std::vector::const_iterator begin() const override; + std::vector::const_iterator end() const override; + + std::pair< + std::reference_wrapper, + std::reference_wrapper> mapOf() const; + + int dependsOnRHS (const Composite &) const override; + }; + +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/restricted-types/Restricted.cxx b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Restricted.cxx index a87f82576b..fca0db9783 100644 --- a/experimental/cpp-serializer/src/amqp/schema/restricted-types/Restricted.cxx +++ b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Restricted.cxx @@ -1,34 +1,41 @@ #include "Restricted.h" + +#include "Map.h" #include "List.h" #include "Enum.h" +#include "Array.h" #include #include #include -/******************************************************************************/ +/****************************************************************************** + * + * ostream overloads + * + ******************************************************************************/ namespace amqp::internal::schema { -std::ostream & -operator << ( - std::ostream & stream_, - const amqp::internal::schema::Restricted & clazz_) -{ - stream_ - << "name : " << clazz_.name() << std::endl - << "label : " << clazz_.m_label << std::endl - << "descriptor : " << clazz_.descriptor() << std::endl - << "source : " << clazz_.m_source << std::endl - << "provides : [" << std::endl; + std::ostream & + operator << ( + std::ostream & stream_, + const amqp::internal::schema::Restricted & clazz_) + { + stream_ + << "name : " << clazz_.name() << std::endl + << "label : " << clazz_.m_label << std::endl + << "descriptor : " << clazz_.descriptor() << std::endl + << "source : " << clazz_.m_source << std::endl + << "provides : [" << std::endl; - for (auto & provides : clazz_.m_provides) { - stream_ << " " << provides << std::endl; + for (auto & provides : clazz_.m_provides) { + stream_ << " " << provides << std::endl; + } + stream_<< " ]" << std::endl; + + return stream_; } - stream_<< " ]" << std::endl; - - return stream_; -} } @@ -36,31 +43,73 @@ operator << ( namespace amqp::internal::schema { -std::ostream & -operator << ( - std::ostream & stream_, - const amqp::internal::schema::Restricted::RestrictedTypes & type_) -{ - switch (type_) { - case Restricted::RestrictedTypes::List : { - stream_ << "list"; - break; - } - case Restricted::RestrictedTypes::Map : { - stream_ << "map"; - break; - } - case Restricted::RestrictedTypes::Enum : { - stream_ << "enum"; - break; + std::ostream & + operator << ( + std::ostream & stream_, + const amqp::internal::schema::Restricted::RestrictedTypes & type_) + { + switch (type_) { + case Restricted::RestrictedTypes::list_t : { + stream_ << "list"; + break; + } + case Restricted::RestrictedTypes::map_t : { + stream_ << "map"; + break; + } + case Restricted::RestrictedTypes::enum_t : { + stream_ << "enum"; + break; + } + case Restricted::RestrictedTypes::array_t : { + stream_ << "array"; + break; + } } + + return stream_; } - return stream_; } +/****************************************************************************** + * + * Static member functions + * + ******************************************************************************/ + +namespace { + + std::map boxedToUnboxed = { + { "java.lang.Integer", "int" }, + { "java.lang.Boolean", "bool" }, + { "java.lang.Byte", "char" }, + { "java.lang.Short", "short" }, + { "java.lang.Character", "char" }, + { "java.lang.Float", "float" }, + { "java.lang.Long", "long" }, + { "java.lang.Double", "double" } + }; + } +/******************************************************************************/ + +/** + * Java gas two types of primitive, boxed and unboxed, essentially actual + * primitives and classes representing those primitives. Of course, we + * don't care about that, so treat boxed primitives as their underlying + * type. + */ +std::string +amqp::internal::schema:: +Restricted::unbox (const std::string & type_) { + auto it = boxedToUnboxed.find (type_); + if (it == boxedToUnboxed.end()) return type_; + else return it->second; +} + + /****************************************************************************** * * amqp::internal::schema::Restricted @@ -77,7 +126,7 @@ operator << ( * @param source_ * @return */ -std::unique_ptr +uPtr amqp::internal::schema:: Restricted::make( uPtr descriptor_, @@ -87,22 +136,40 @@ Restricted::make( std::string source_, std::vector> choices_) { + DBG ("RESTRICTED::MAKE - " << name_ << std::endl); /* - * Lists represent both actual lists and enumerations. We differentiate - * between them as enums have choices ans lists don't. Pretty certain - * things are done this was as AMQP doesn't really have the concept - * of an enum. + * AMQP Lists represent actual lists, arrays, and enumerations. + * + * Enumerations are serialised as lists that have a set of Choices + * Arrays are serialized as lists of types. Because java cares about the difference between + * boxed and un-boxed primitives an unboxed array ends with [p] whilst an array of classes + * ends with [] */ if (source_ == "list") { if (choices_.empty()) { - return std::make_unique( - std::move (descriptor_), - std::move (name_), - std::move (label_), - std::move (provides_), - std::move (source_)); + const std::string array { "[]" }; + const std::string primArray { "[p]" }; + + // when C++20 is done we can use .endswith, until then we have to do a reverse search + if ( std::equal (name_.rbegin(), name_.rbegin() + array.size(), array.rbegin(), array.rend()) + || std::equal (name_.rbegin(), name_.rbegin() + primArray.size(), primArray.rbegin(), primArray.rend())) + { + return std::make_unique( + std::move (descriptor_), + std::move (name_), + std::move (label_), + std::move (provides_), + std::move (source_)); + } else { + return std::make_unique( + std::move (descriptor_), + std::move (name_), + std::move (label_), + std::move (provides_), + std::move (source_)); + } } else { - return std::make_unique( + return std::make_unique( std::move (descriptor_), std::move (name_), std::move (label_), @@ -111,7 +178,14 @@ Restricted::make( std::move (choices_)); } } else if (source_ == "map") { - throw std::runtime_error ("maps not supported"); + return std::make_unique ( + std::move (descriptor_), + std::move (name_), + std::move (label_), + std::move (provides_), + std::move (source_)); + } else { + throw std::runtime_error ("Unknown restricted type"); } } @@ -127,9 +201,9 @@ Restricted::Restricted ( ) : AMQPTypeNotation ( std::move (name_), std::move (descriptor_)) - , m_label (std::move (label_)) - , m_provides (std::move (provides_)) - , m_source (source_) + , m_label { std::move (label_) } + , m_provides { std::move (provides_) } + , m_source { source_ } { } @@ -138,7 +212,7 @@ Restricted::Restricted ( amqp::internal::schema::AMQPTypeNotation::Type amqp::internal::schema:: Restricted::type() const { - return AMQPTypeNotation::Type::Restricted; + return AMQPTypeNotation::Type::restricted_t; } /******************************************************************************/ @@ -154,8 +228,34 @@ Restricted::restrictedType() const { int amqp::internal::schema:: Restricted::dependsOn (const OrderedTypeNotation & rhs_) const { - return dynamic_cast(rhs_).dependsOn(*this); + return dynamic_cast(rhs_).dependsOnRHS (*this); } /*********************************************************o*********************/ +/* + * If the left hand side of the original call, restricted_ in this case, + * depends on this instance then we return 1. + * + * If this instance of a map depends on the parameter we return 2 + */ +int +amqp::internal::schema:: +Restricted::dependsOnRHS (const Restricted & lhs_) const { + switch (lhs_.restrictedType()) { + case Restricted::RestrictedTypes::map_t : + return dependsOnMap ( + static_cast(lhs_)); // NOLINT + case Restricted::RestrictedTypes::list_t : + return dependsOnList ( + static_cast(lhs_)); // NOLINT + case Restricted::RestrictedTypes::enum_t : + return dependsOnEnum ( + static_cast(lhs_)); // NOLINT + case Restricted::RestrictedTypes::array_t : + return dependsOnArray ( + static_cast(lhs_)); // NOLINT + } +} + +/*********************************************************o*********************/ diff --git a/experimental/cpp-serializer/src/amqp/schema/restricted-types/Restricted.h b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Restricted.h index b329fc5501..3c1cd6b8eb 100644 --- a/experimental/cpp-serializer/src/amqp/schema/restricted-types/Restricted.h +++ b/experimental/cpp-serializer/src/amqp/schema/restricted-types/Restricted.h @@ -7,9 +7,9 @@ #include #include -#include "schema/Field.h" -#include "schema/Choice.h" -#include "schema/Descriptor.h" +#include "schema/field-types/Field.h" +#include "amqp/schema/described-types/Choice.h" +#include "amqp/schema/described-types/Descriptor.h" #include "schema/AMQPTypeNotation.h" #include "amqp/AMQPDescribed.h" @@ -25,9 +25,18 @@ namespace amqp::internal::schema { class Composite; class OrderedTypeNotation; + class Map; + class Enum; + class List; + class Array; + } -/******************************************************************************/ +/****************************************************************************** + * + * class Restricted + * + ******************************************************************************/ namespace amqp::internal::schema { @@ -35,7 +44,9 @@ namespace amqp::internal::schema { public : friend std::ostream & operator << (std::ostream &, const Restricted&); - enum RestrictedTypes { List, Map, Enum }; + enum RestrictedTypes { list_t, map_t, enum_t, array_t }; + + static std::string unbox (const std::string &); private : // could be null in the stream... not sure that information is @@ -65,6 +76,11 @@ namespace amqp::internal::schema { std::vector, RestrictedTypes); + virtual int dependsOnMap (const Map &) const = 0; + virtual int dependsOnList (const List &) const = 0; + virtual int dependsOnArray (const Array &) const = 0; + virtual int dependsOnEnum (const Enum &) const = 0; + public : static std::unique_ptr make( std::unique_ptr, @@ -89,8 +105,13 @@ namespace amqp::internal::schema { virtual std::vector::const_iterator end() const = 0; int dependsOn (const OrderedTypeNotation &) const override; - int dependsOn (const Restricted &) const override = 0; - int dependsOn (const class Composite &) const override = 0; + int dependsOnRHS (const Restricted &) const override; + + int dependsOnRHS (const Composite &) const override = 0; + + const decltype (m_provides) & provides() const { return m_provides; } + const decltype (m_label) & label() const { return m_label; } + const decltype (m_source) & source() const { return m_source; } }; diff --git a/experimental/cpp-serializer/src/amqp/test/CMakeLists.txt b/experimental/cpp-serializer/src/amqp/test/CMakeLists.txt index 92997dafda..1c3f289271 100644 --- a/experimental/cpp-serializer/src/amqp/test/CMakeLists.txt +++ b/experimental/cpp-serializer/src/amqp/test/CMakeLists.txt @@ -2,8 +2,12 @@ set (EXE "amqp-test") set (amqp-test-sources main.cxx + Map.cxx Pair.cxx + List.cxx Single.cxx + TestUtils.cxx + RestrictedDescriptor.cxx OrderedTypeNotationTest.cxx ) diff --git a/experimental/cpp-serializer/src/amqp/test/List.cxx b/experimental/cpp-serializer/src/amqp/test/List.cxx new file mode 100644 index 0000000000..b981c0cf2d --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/test/List.cxx @@ -0,0 +1,26 @@ +#include + +#include "restricted-types/List.h" +#include "restricted-types/Restricted.h" +#include "TestUtils.h" + +/******************************************************************************/ + +TEST (List, name) { + auto rtn = amqp::internal::schema::List::listType("java.util.list"); + + ASSERT_EQ ("java.util.list", rtn.first); + ASSERT_EQ ("int", rtn.second); +} + +/******************************************************************************/ + +TEST (List, dependsOn1) { + auto list1 = test::list ("string"); + auto list2 = test::list (list1->name()); + + ASSERT_EQ (1, list1->dependsOn (*list2)); + ASSERT_EQ (2, list2->dependsOn (*list1)); +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/test/Map.cxx b/experimental/cpp-serializer/src/amqp/test/Map.cxx new file mode 100644 index 0000000000..d1b3b4e1f3 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/test/Map.cxx @@ -0,0 +1,212 @@ +#include + +#include "TestUtils.h" + +#include "amqp/schema/described-types/Descriptor.h" +#include "restricted-types/Map.h" +#include "restricted-types/List.h" +#include "restricted-types/Enum.h" + +/****************************************************************************** + * + * mapType Tests + * + ******************************************************************************/ + +TEST (Map, name1) { + auto [map, of, to] = amqp::internal::schema::Map::mapType ( + "java.util.Map"); + + ASSERT_EQ ("java.util.Map", map); + ASSERT_EQ ("int", of); + ASSERT_EQ ("string", to); +} + +/******************************************************************************/ + +TEST (Map, name2) { + auto [map, of, to] = amqp::internal::schema::Map::mapType ( + "java.util.Map>"); + + ASSERT_EQ ("java.util.Map", map); + ASSERT_EQ ("int", of); + ASSERT_EQ ("java.util.List", to); +} + +/******************************************************************************/ + +TEST (Map, name3) { + auto [map, of, to] = amqp::internal::schema::Map::mapType ( + "java.util.Map, java.util.List>"); + + ASSERT_EQ ("java.util.Map", map); + ASSERT_EQ ("java.util.Pair", of); + ASSERT_EQ ("java.util.List", to); +} + +/****************************************************************************** + * + * + * + ******************************************************************************/ + +using namespace amqp::internal::schema; + +/******************************************************************************/ + +TEST (Map, dependsOn1) { + auto result { + "level 1\n" + " * java.util.List\n" + "\n" + "level 2\n" + " * java.util.Map>\n\n" + }; + + { + OrderedTypeNotations otn; + + auto l = test::list("string"); + auto m = test::map("int", l->name()); + + otn.insert (std::move (l)); + otn.insert (std::move (m)); + + std::stringstream ss; + ss << otn; + + ASSERT_EQ (result, ss.str()); + } + + // Same test but reverse the insertion order + { + OrderedTypeNotations otn; + + auto l = test::list("string"); + auto m = test::map("int", l->name()); + + otn.insert(std::move(m)); + otn.insert(std::move(l)); + + std::stringstream ss; + ss << otn; + + ASSERT_EQ (result, ss.str()); + } +} + +/******************************************************************************/ + +TEST (Map, dependsOn2) { + auto result { + "level 1\n" + " * net.corda.eee\n" + "\n" + "level 2\n" + " * java.util.List\n" + "\n" + "level 3\n" + " * java.util.Map>\n\n" + }; + + { + OrderedTypeNotations otn; + + auto e = test::eNum("eee"); + auto l = test::list(e->name()); + auto m = test::map("int", l->name()); + + otn.insert(std::move(l)); + otn.insert(std::move(m)); + otn.insert(std::move(e)); + + std::stringstream ss; + ss << otn; + + ASSERT_EQ (result, ss.str()); + } + { + OrderedTypeNotations otn; + + auto e = test::eNum("eee"); + auto l = test::list(e->name()); + auto m = test::map("int", l->name()); + + otn.insert(std::move(l)); + otn.insert(std::move(e)); + otn.insert(std::move(m)); + + std::stringstream ss; + ss << otn; + + ASSERT_EQ (result, ss.str()); + } + { + OrderedTypeNotations otn; + + auto e = test::eNum("eee"); + auto l = test::list(e->name()); + auto m = test::map("int", l->name()); + + otn.insert(std::move(m)); + otn.insert(std::move(l)); + otn.insert(std::move(e)); + + std::stringstream ss; + ss << otn; + + ASSERT_EQ (result, ss.str()); + } + { + OrderedTypeNotations otn; + + auto e = test::eNum ("eee"); + auto l = test::list (e->name()); + auto m = test::map ("int", l->name()); + + otn.insert (std::move (m)); + + otn.insert (std::move (e)); + otn.insert (std::move (l)); + + std::stringstream ss; + ss << otn; + + ASSERT_EQ (result, ss.str()); + } + { + OrderedTypeNotations otn; + + auto e = test::eNum("eee"); + auto l = test::list(e->name()); + auto m = test::map("int", l->name()); + + otn.insert (std::move (e)); + otn.insert (std::move (l)); + otn.insert (std::move (m)); + + std::stringstream ss; + ss << otn; + + ASSERT_EQ (result, ss.str()); + } + { + OrderedTypeNotations otn; + + auto e = test::eNum ("eee"); + auto l = test::list (e->name()); + auto m = test::map ("int", l->name()); + + otn.insert (std::move (e)); + otn.insert (std::move (m)); + otn.insert (std::move (l)); + + std::stringstream ss; + ss << otn; + + ASSERT_EQ (result, ss.str()); + } +} + +/******************************************************************************/ + diff --git a/experimental/cpp-serializer/src/amqp/test/OrderedTypeNotationTest.cxx b/experimental/cpp-serializer/src/amqp/test/OrderedTypeNotationTest.cxx index f554ebce17..08d5319ed3 100644 --- a/experimental/cpp-serializer/src/amqp/test/OrderedTypeNotationTest.cxx +++ b/experimental/cpp-serializer/src/amqp/test/OrderedTypeNotationTest.cxx @@ -109,18 +109,21 @@ TEST (OTNTest, singleInsert) { // NOLINT /******************************************************************************/ TEST (OTNTest, twoInserts) { // NOLINT - std::cout << std::endl; amqp::internal::schema::OrderedTypeNotations list; list.insert(std::make_unique("A", std::vector())); list.insert(std::make_unique("B", std::vector())); - ASSERT_EQ("A B", str (list)); + + // Inserting B after A with no dependencies between the two will force + // B to be recorded before A since elements added at the same + // level are always added to the front of the list to ensrue we can + // inspect the rest of that level + ASSERT_EQ ("B A", str (list)); } /******************************************************************************/ TEST (OTNTest, A_depends_on_B) { // NOLINT - std::cout << std::endl; amqp::internal::schema::OrderedTypeNotations list; std::vector aDeps = { "B" }; @@ -132,7 +135,6 @@ TEST (OTNTest, A_depends_on_B) { // NOLINT /******************************************************************************/ TEST (OTNTest, B_depends_on_A) { // NOLINT - std::cout << std::endl; amqp::internal::schema::OrderedTypeNotations list; std::vector aDeps = { }; @@ -147,7 +149,6 @@ TEST (OTNTest, B_depends_on_A) { // NOLINT /******************************************************************************/ TEST (OTNTest, three_1) { // NOLINT - std::cout << std::endl; amqp::internal::schema::OrderedTypeNotations list; std::vector aDeps = { }; @@ -164,7 +165,6 @@ TEST (OTNTest, three_1) { // NOLINT /******************************************************************************/ TEST (OTNTest, three_2) { // NOLINT - std::cout << std::endl; amqp::internal::schema::OrderedTypeNotations list; std::vector aDeps = { "B" }; @@ -181,7 +181,6 @@ TEST (OTNTest, three_2) { // NOLINT /******************************************************************************/ TEST (OTNTest, three_3) { // NOLINT - std::cout << std::endl; amqp::internal::schema::OrderedTypeNotations list; std::vector aDeps = { "B" }; @@ -198,7 +197,6 @@ TEST (OTNTest, three_3) { // NOLINT /******************************************************************************/ TEST (OTNTest, three_4) { // NOLINT - std::cout << std::endl; amqp::internal::schema::OrderedTypeNotations list; std::vector aDeps = { "B" }; @@ -215,7 +213,6 @@ TEST (OTNTest, three_4) { // NOLINT /******************************************************************************/ TEST (OTNTest, three_5) { // NOLINT - std::cout << std::endl; amqp::internal::schema::OrderedTypeNotations list; std::vector aDeps = { "B" }; diff --git a/experimental/cpp-serializer/src/amqp/test/RestrictedDescriptor.cxx b/experimental/cpp-serializer/src/amqp/test/RestrictedDescriptor.cxx new file mode 100644 index 0000000000..22c1fc604b --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/test/RestrictedDescriptor.cxx @@ -0,0 +1,25 @@ +#include + +#include "descriptors/corda-descriptors/RestrictedDescriptor.h" + +using namespace amqp::internal::schema::descriptors; + +TEST (RestrictedDescriptor, makePrim1) { // NOLINT + EXPECT_EQ ("int", RestrictedDescriptor::makePrim ("int")); +} + +TEST (RestrictedDescriptor, makePrim2) { // NOLINT + EXPECT_EQ ("int[]", RestrictedDescriptor::makePrim ("int[]")); +} + +TEST (RestrictedDescriptor, makePrim3) { // NOLINT + EXPECT_EQ ("java.lang.integer", RestrictedDescriptor::makePrim ("int")); +} + +TEST (RestrictedDescriptor, makePrim4) { // NOLINT + EXPECT_EQ ("java.lang.integer[]", RestrictedDescriptor::makePrim ("int[]")); +} + +TEST (RestrictedDescriptor, makePrim5) { // NOLINT§ + EXPECT_EQ ("int[], int", RestrictedDescriptor::makePrim ("java.lang.Integer[], java.lang.Integer")); +} diff --git a/experimental/cpp-serializer/src/amqp/test/Single.cxx b/experimental/cpp-serializer/src/amqp/test/Single.cxx index 728688eeaa..4bfbcfd315 100644 --- a/experimental/cpp-serializer/src/amqp/test/Single.cxx +++ b/experimental/cpp-serializer/src/amqp/test/Single.cxx @@ -4,15 +4,21 @@ #include "Reader.h" +/******************************************************************************/ + using namespace amqp::reader; using namespace amqp::internal::reader; +/******************************************************************************/ + TEST (Single, string) { // NOLINT TypedSingle str_test ("Hello"); EXPECT_EQ("Hello", str_test.dump()); } +/******************************************************************************/ + TEST (Single, list) { // NOLINT struct builder { @@ -36,3 +42,4 @@ TEST (Single, list) { // NOLINT EXPECT_EQ("[ 1, 2, 3, 4, 5 ]", test->dump()); } +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/test/TestUtils.cxx b/experimental/cpp-serializer/src/amqp/test/TestUtils.cxx new file mode 100644 index 0000000000..f55106b4f8 --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/test/TestUtils.cxx @@ -0,0 +1,126 @@ +#include "TestUtils.h" + +#include +#include +#include "types.h" + +#include "restricted-types/Map.h" +#include "restricted-types/List.h" +#include "restricted-types/Enum.h" + +/******************************************************************************/ + +using namespace amqp::internal::schema; + +/******************************************************************************/ + +namespace { + + std::string fingerprint() { + auto randchar = []() -> char { + const char charset[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + const size_t max_index = (sizeof(charset) - 1); + return charset[rand() % max_index]; + }; + std::string str(20, 0); + std::generate_n(str.begin(), 20, randchar); + + return "net.corda:" + str; + } + +} + +/******************************************************************************/ + +uPtr +test:: +map (const std::string & of_, const std::string & to_) { + auto desc = std::make_unique ( + fingerprint()); + + std::vector provides { }; + + return std::make_unique( + std::move (desc), + "java.util.Map<" + of_ + ", " + to_ + ">", + "label", + std::move (provides), + "map" + ); +} + +/******************************************************************************/ + +uPtr +test:: +list (const std::string & of_) { + auto desc = std::make_unique ( + fingerprint()); + + std::vector provides { }; + + std::cout << "FAKE LIST: " << of_ << std::endl; + + return std::make_unique ( + std::move (desc), + "java.util.List<" + of_ + ">", + "label", + std::move (provides), + "map" + ); +} + +/******************************************************************************/ + +uPtr +test:: +eNum (const std::string & e_) { + auto desc = std::make_unique ( + fingerprint()); + + sVec provides { }; + + sVec> choices (2); + choices.emplace_back( + (std::make_unique(Choice ("a")))); + choices.emplace_back( + (std::make_unique(Choice ("b")))); + + return std::make_unique( + std::move (desc), + "net.corda." + e_, + "label", + std::move (provides), + "enum", + std::move (choices) + ); + +} + +/******************************************************************************/ + +uPtr +test:: +comp ( + const std::string & name_, + const std::vector & fields_ +) { + /* + auto desc = std::make_unique ( + fingerprint()); + + std::vector provides { }; + + Composite ( + name_, + "label", + provides, + desc, + std::vector> & fields_); + */ +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/amqp/test/TestUtils.h b/experimental/cpp-serializer/src/amqp/test/TestUtils.h new file mode 100644 index 0000000000..1df93e559f --- /dev/null +++ b/experimental/cpp-serializer/src/amqp/test/TestUtils.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include "restricted-types/List.h" +#include "restricted-types/Map.h" + +/******************************************************************************/ + +namespace test { + uPtr + map (const std::string &, const std::string &); + + uPtr + list (const std::string & of_); + + uPtr + eNum (const std::string & e_); + + uPtr + comp (const std::string & name_, const std::vector &); +} + +/******************************************************************************/ diff --git a/experimental/cpp-serializer/src/proton/proton_wrapper.cxx b/experimental/cpp-serializer/src/proton/proton_wrapper.cxx index e897f011af..511b23eb09 100644 --- a/experimental/cpp-serializer/src/proton/proton_wrapper.cxx +++ b/experimental/cpp-serializer/src/proton/proton_wrapper.cxx @@ -235,6 +235,38 @@ auto_list_enter::elements() const { return m_elements; } +/****************************************************************************** + * + * proton::auto_map_enter + * + ******************************************************************************/ + +proton:: +auto_map_enter::auto_map_enter (pn_data_t * data_, bool next_) + : m_elements (pn_data_get_map (data_)) + , m_data (data_) +{ + ::pn_data_enter(m_data); + if (next_) { + pn_data_next (m_data); + } +} + +/******************************************************************************/ + +proton:: +auto_map_enter::~auto_map_enter() { + pn_data_exit (m_data); +} + +/******************************************************************************/ + +size_t +proton:: +auto_map_enter::elements() const { + return m_elements; +} + /****************************************************************************** * * @@ -315,7 +347,7 @@ readAndNext ( bool tolerateDeviance_ ) { long rtn = pn_data_get_long (data_); - pn_data_next(data_); + pn_data_next (data_); return rtn; } @@ -329,7 +361,7 @@ readAndNext ( bool tolerateDeviance_ ) { long rtn = pn_data_get_ulong (data_); - pn_data_next(data_); + pn_data_next (data_); return rtn; } diff --git a/experimental/cpp-serializer/src/proton/proton_wrapper.h b/experimental/cpp-serializer/src/proton/proton_wrapper.h index d9699961a4..250ffc1d81 100644 --- a/experimental/cpp-serializer/src/proton/proton_wrapper.h +++ b/experimental/cpp-serializer/src/proton/proton_wrapper.h @@ -31,8 +31,11 @@ namespace proton { void is_string (pn_data_t *, bool allowNull = false); void is_described (pn_data_t *); + /** + * Specialised in the CXX file + */ template - T get_symbol (pn_data_t * data_) { + T get_symbol (pn_data_t *) { return T {}; } @@ -77,6 +80,18 @@ namespace proton { size_t elements() const; }; + class auto_map_enter { + private : + size_t m_elements; + pn_data_t * m_data; + + public : + explicit auto_map_enter (pn_data_t *, bool next_ = false); + ~auto_map_enter(); + + size_t elements() const; + }; + } /******************************************************************************/ diff --git a/experimental/cpp-serializer/src/serialiser/CMakeLists.txt b/experimental/cpp-serializer/src/serialiser/CMakeLists.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/experimental/cpp-serializer/src/serialiser/Composite.h b/experimental/cpp-serializer/src/serialiser/Composite.h deleted file mode 100644 index b98f3707ba..0000000000 --- a/experimental/cpp-serializer/src/serialiser/Composite.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -/******************************************************************************/ - -namespace amqp { -namespace internal { -namespace serialiser { - - template - class Composite : public ProtonReader { - - }; - -} -} -} - -/******************************************************************************/ -