summaryrefslogtreecommitdiff
path: root/buildscripts
diff options
context:
space:
mode:
authorGregory Noma <gregory.noma@gmail.com>2022-01-26 22:50:27 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-01-26 23:43:54 +0000
commit90239f246867eb632ad03520dbe6856af50e5c7e (patch)
tree4e3c0c2853168f8191010194216d0bae8f6f2b92 /buildscripts
parent9b3c10f0baba2522c37db5dfdb1d41c78522c20b (diff)
downloadmongo-90239f246867eb632ad03520dbe6856af50e5c7e.tar.gz
SERVER-63002 Support bindata types for variants in IDL
Diffstat (limited to 'buildscripts')
-rw-r--r--buildscripts/idl/idl/binder.py16
-rw-r--r--buildscripts/idl/idl/generator.py33
-rw-r--r--buildscripts/idl/tests/test_binder.py71
3 files changed, 83 insertions, 37 deletions
diff --git a/buildscripts/idl/idl/binder.py b/buildscripts/idl/idl/binder.py
index d615f4a633b..49fab8a39e1 100644
--- a/buildscripts/idl/idl/binder.py
+++ b/buildscripts/idl/idl/binder.py
@@ -87,15 +87,15 @@ def _validate_bson_types_list(ctxt, idl_type, syntax_type):
ctxt.add_bad_bson_type_error(idl_type, syntax_type, idl_type.name, bson_type)
return False
- # V1 restiction: cannot mix bindata into list of types
- if bson_type == "bindata":
- ctxt.add_bad_bson_type_error(idl_type, syntax_type, idl_type.name, bson_type)
- return False
+ if not isinstance(idl_type, syntax.VariantType):
+ if bson_type == "bindata":
+ ctxt.add_bad_bson_type_error(idl_type, syntax_type, idl_type.name, bson_type)
+ return False
- # Cannot mix non-scalar types into the list of types
- if not isinstance(idl_type, syntax.VariantType) and not bson.is_scalar_bson_type(bson_type):
- ctxt.add_bad_bson_scalar_type_error(idl_type, syntax_type, idl_type.name, bson_type)
- return False
+ # Cannot mix non-scalar types into the list of types
+ if not bson.is_scalar_bson_type(bson_type):
+ ctxt.add_bad_bson_scalar_type_error(idl_type, syntax_type, idl_type.name, bson_type)
+ return False
return True
diff --git a/buildscripts/idl/idl/generator.py b/buildscripts/idl/idl/generator.py
index d9879e97109..ff9da001069 100644
--- a/buildscripts/idl/idl/generator.py
+++ b/buildscripts/idl/idl/generator.py
@@ -30,6 +30,7 @@
import hashlib
import io
+import itertools
import os
import re
import sys
@@ -1962,11 +1963,26 @@ class _CppSourceFileWriter(_CppFileWriterBase):
}
with self._with_template(template_params):
- # See https://en.cppreference.com/w/cpp/utility/variant/visit
- # This lambda is a template instantiated for each alternate type. Use "if constexpr"
- # to compile the appropriate serialization code for each.
- with self._block('stdx::visit([builder](auto&& arg) {', '}, ${access_member});'):
- self._writer.write_template('idl::idlSerialize(builder, ${field_name}, arg);')
+ with self._block('stdx::visit(visit_helper::Overloaded{', '}, ${access_member});'):
+ for variant_type in itertools.chain(
+ field.type.variant_types,
+ [field.type.variant_struct_type] if field.type.variant_struct_type else []):
+
+ template_params[
+ 'cpp_type'] = 'std::vector<' + variant_type.cpp_type + '>' if variant_type.is_array else variant_type.cpp_type
+
+ with self._block('[builder](const ${cpp_type}& value) {', '},'):
+ bson_cpp_type = cpp_types.get_bson_cpp_type(variant_type)
+ if bson_cpp_type and bson_cpp_type.has_serializer():
+ assert not field.type.is_array
+ expression = bson_cpp_type.gen_serializer_expression(
+ self._writer, 'value')
+ template_params['expression'] = expression
+ self._writer.write_template(
+ 'builder->append(${field_name}, ${expression});')
+ else:
+ self._writer.write_template(
+ 'idl::idlSerialize(builder, ${field_name}, value);')
def _gen_serializer_method_common(self, field):
# type: (ast.Field) -> None
@@ -2604,10 +2620,9 @@ class _CppSourceFileWriter(_CppFileWriterBase):
# Generate mongo includes third
header_list = [
- 'mongo/bson/bsonobjbuilder.h',
- 'mongo/db/auth/authorization_contract.h',
- 'mongo/db/commands.h',
- 'mongo/idl/command_generic_argument.h',
+ 'mongo/bson/bsonobjbuilder.h', 'mongo/db/auth/authorization_contract.h',
+ 'mongo/db/commands.h', 'mongo/idl/command_generic_argument.h',
+ 'mongo/util/visit_helper.h'
]
if spec.server_parameters:
diff --git a/buildscripts/idl/tests/test_binder.py b/buildscripts/idl/tests/test_binder.py
index 47f6d62efa4..b1f809ff5c7 100644
--- a/buildscripts/idl/tests/test_binder.py
+++ b/buildscripts/idl/tests/test_binder.py
@@ -602,6 +602,57 @@ class TestBinder(testcase.IDLTestcase):
foo: array<int>
"""))
+ def test_variant_positive(self):
+ # type: () -> None
+ """Positive variant test cases."""
+
+ # Setup some common types
+ test_preamble = textwrap.dedent("""
+ types:
+ string:
+ description: foo
+ cpp_type: foo
+ bson_serialization_type: string
+ serializer: foo
+ deserializer: foo
+ default: foo
+ int:
+ description: foo
+ cpp_type: std::int32_t
+ bson_serialization_type: int
+ deserializer: mongo::BSONElement::_numberInt
+ bindata_function:
+ bson_serialization_type: bindata
+ bindata_subtype: function
+ description: "A BSON bindata of function sub type"
+ cpp_type: "std::vector<std::uint8_t>"
+ deserializer: "mongo::BSONElement::_binDataVector"
+ """)
+
+ self.assert_bind(test_preamble + textwrap.dedent("""
+ structs:
+ foo:
+ description: foo
+ fields:
+ my_variant_field:
+ type:
+ variant:
+ - string
+ - int
+ """))
+
+ self.assert_bind(test_preamble + textwrap.dedent("""
+ structs:
+ foo:
+ description: foo
+ fields:
+ my_variant_field:
+ type:
+ variant:
+ - string
+ - bindata_function
+ """))
+
def test_variant_negative(self):
# type: () -> None
"""Negative variant test cases."""
@@ -637,12 +688,6 @@ class TestBinder(testcase.IDLTestcase):
description: foo
cpp_type: "std::int32_t"
deserializer: "mongo::BSONElement::safeNumberInt"
- bindata_function:
- bson_serialization_type: bindata
- bindata_subtype: function
- description: "A BSON bindata of function sub type"
- cpp_type: "std::vector<std::uint8_t>"
- deserializer: "mongo::BSONElement::_binDataVector"
""")
self.assert_bind_fail(
@@ -685,20 +730,6 @@ class TestBinder(testcase.IDLTestcase):
default: 1
"""), idl.errors.ERROR_ID_VARIANT_NO_DEFAULT)
- # Bindata is banned in variants for now.
- self.assert_bind_fail(
- test_preamble + textwrap.dedent("""
- structs:
- foo:
- description: foo
- fields:
- my_variant_field:
- type:
- variant:
- - string
- - bindata_function
- """), idl.errors.ERROR_ID_BAD_BSON_TYPE)
-
# Enums are banned in variants for now.
self.assert_bind_fail(
test_preamble + textwrap.dedent("""