summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buildscripts/idl/idl/binder.py2
-rw-r--r--buildscripts/idl/idl/bson.py2
-rw-r--r--buildscripts/idl/idl/cpp_types.py32
-rw-r--r--buildscripts/idl/idl/generator.py2
-rw-r--r--src/mongo/idl/basic_types.idl11
-rw-r--r--src/mongo/idl/idl_test.cpp68
-rw-r--r--src/mongo/idl/unittest.idl5
7 files changed, 73 insertions, 49 deletions
diff --git a/buildscripts/idl/idl/binder.py b/buildscripts/idl/idl/binder.py
index 2f1917a6f06..ab50d0bcc35 100644
--- a/buildscripts/idl/idl/binder.py
+++ b/buildscripts/idl/idl/binder.py
@@ -201,7 +201,7 @@ def _validate_type_properties(ctxt, idl_type, syntax_type):
ctxt.add_missing_ast_required_field_error(idl_type, syntax_type, idl_type.name,
"deserializer")
- elif not bson_type in ["object", "bindata"]:
+ elif not bson_type in ["array", "object", "bindata"]:
if idl_type.deserializer is None:
ctxt.add_missing_ast_required_field_error(idl_type, syntax_type, idl_type.name,
"deserializer")
diff --git a/buildscripts/idl/idl/bson.py b/buildscripts/idl/idl/bson.py
index 3d1e004dbc0..3f8e5190f9d 100644
--- a/buildscripts/idl/idl/bson.py
+++ b/buildscripts/idl/idl/bson.py
@@ -40,7 +40,7 @@ _BSON_TYPE_INFORMATION = {
"double": {'scalar': True, 'bson_type_enum': 'NumberDouble'},
"string": {'scalar': True, 'bson_type_enum': 'String'},
"object": {'scalar': False, 'bson_type_enum': 'Object'},
- # TODO: add support: "array" : { 'scalar' : False, 'bson_type_enum' : 'Array'},
+ "array": {'scalar': False, 'bson_type_enum': 'Array'},
"bindata": {'scalar': True, 'bson_type_enum': 'BinData'},
"undefined": {'scalar': True, 'bson_type_enum': 'Undefined'},
"objectid": {'scalar': True, 'bson_type_enum': 'jstOID'},
diff --git a/buildscripts/idl/idl/cpp_types.py b/buildscripts/idl/idl/cpp_types.py
index bb7ec7d0a22..8971d5715c8 100644
--- a/buildscripts/idl/idl/cpp_types.py
+++ b/buildscripts/idl/idl/cpp_types.py
@@ -652,6 +652,34 @@ class _ObjectBsonCppTypeBase(BsonCppTypeBase):
return "localObject"
+class _ArrayBsonCppTypeBase(BsonCppTypeBase):
+ """Custom C++ support for array BSON types."""
+
+ def gen_deserializer_expression(self, indented_writer, object_instance):
+ # type: (writer.IndentedTextWriter, str) -> str
+ if self._ast_type.deserializer:
+ indented_writer.write_line(
+ common.template_args('BSONArray localArray(${object_instance}.Obj());',
+ object_instance=object_instance))
+ return "localArray"
+
+ # Just pass the BSONObj through without trying to parse it.
+ return common.template_args('BSONArray(${object_instance}.Obj())',
+ object_instance=object_instance)
+
+ def has_serializer(self):
+ # type: () -> bool
+ return self._ast_type.serializer is not None
+
+ def gen_serializer_expression(self, indented_writer, expression):
+ # type: (writer.IndentedTextWriter, str) -> str
+ method_name = writer.get_method_name(self._ast_type.serializer)
+ indented_writer.write_line(
+ common.template_args('BSONArray localArray(${expression}.${method_name}());',
+ expression=expression, method_name=method_name))
+ return "localArray"
+
+
class _BinDataBsonCppTypeBase(BsonCppTypeBase):
"""Custom C++ support for all binData BSON types."""
@@ -690,6 +718,7 @@ class _BinDataBsonCppTypeBase(BsonCppTypeBase):
def get_bson_cpp_type(ast_type):
# type: (ast.Type) -> Optional[BsonCppTypeBase]
"""Get a class that provides custom serialization for the given BSON type."""
+ # pylint: disable=too-many-return-statements
# Does not support list of types
if len(ast_type.bson_serialization_type) > 1:
@@ -701,6 +730,9 @@ def get_bson_cpp_type(ast_type):
if ast_type.bson_serialization_type[0] == 'object':
return _ObjectBsonCppTypeBase(ast_type)
+ if ast_type.bson_serialization_type[0] == 'array':
+ return _ArrayBsonCppTypeBase(ast_type)
+
if ast_type.bson_serialization_type[0] == 'bindata':
return _BinDataBsonCppTypeBase(ast_type)
diff --git a/buildscripts/idl/idl/generator.py b/buildscripts/idl/idl/generator.py
index a20f64bbcd8..51569af4d4f 100644
--- a/buildscripts/idl/idl/generator.py
+++ b/buildscripts/idl/idl/generator.py
@@ -1206,7 +1206,7 @@ class _CppSourceFileWriter(_CppFileWriterBase):
method_name=method_name, expression=expression)
# BSONObjects are allowed to be pass through without deserialization
- assert ast_type.bson_serialization_type == ['object']
+ assert ast_type.bson_serialization_type in [['object'], ['array']]
return expression
# Call a static class method with the signature:
diff --git a/src/mongo/idl/basic_types.idl b/src/mongo/idl/basic_types.idl
index 37a7f86a0d0..c0037bbb446 100644
--- a/src/mongo/idl/basic_types.idl
+++ b/src/mongo/idl/basic_types.idl
@@ -187,6 +187,17 @@ types:
cpp_type: "mongo::BSONObj"
deserializer: "BSONObj::getOwned"
+ array:
+ bson_serialization_type: array
+ description: "An unowned BSONArray without custom deserialization or seialization"
+ cpp_type: "mongo::BSONArray"
+
+ array_owned:
+ bson_serialization_type: array
+ description: "An owned BSONArray"
+ cpp_type: "mongo::BSONArray"
+ deserializer: "BSONObj::getOwned"
+
date:
bson_serialization_type: date
description: "A BSON UTC DateTime"
diff --git a/src/mongo/idl/idl_test.cpp b/src/mongo/idl/idl_test.cpp
index b09aa091a71..daab2d425ee 100644
--- a/src/mongo/idl/idl_test.cpp
+++ b/src/mongo/idl/idl_test.cpp
@@ -152,17 +152,21 @@ void assert_same_types() {
template <typename ParserT, typename TestT, BSONType Test_bson_type>
void TestLoopback(TestT test_value) {
- IDLParserErrorContext ctxt("root");
-
auto testDoc = BSON("value" << test_value);
-
auto element = testDoc.firstElement();
ASSERT_EQUALS(element.type(), Test_bson_type);
- auto testStruct = ParserT::parse(ctxt, testDoc);
+ auto testStruct = ParserT::parse({"test"}, testDoc);
assert_same_types<decltype(testStruct.getValue()), TestT>();
- ASSERT_EQUALS(testStruct.getValue(), test_value);
+ // We need to use a different unittest macro for comparing obj/array.
+ constexpr bool isObjectTest = std::is_same_v<TestT, const BSONObj&>;
+ constexpr bool isArrayTest = std::is_same_v<TestT, const BSONArray&>;
+ if constexpr (isObjectTest || isArrayTest) {
+ ASSERT_BSONOBJ_EQ(testStruct.getValue(), test_value);
+ } else {
+ ASSERT_EQUALS(testStruct.getValue(), test_value);
+ }
// Positive: Test we can roundtrip from the just parsed document
{
@@ -192,7 +196,15 @@ void TestLoopback(TestT test_value) {
// Validate the operator == works
// Use ASSERT instead of ASSERT_EQ to avoid operator<<
- ASSERT(one_new == testStruct);
+ if constexpr (!isArrayTest) {
+ // BSONArray comparison not currently implemented.
+ ASSERT_TRUE(one_new == testStruct);
+ }
+
+ if constexpr (isObjectTest) {
+ // Only One_plain_object implements comparison ops
+ ASSERT_FALSE(one_new < testStruct);
+ }
}
}
@@ -207,46 +219,10 @@ TEST(IDLOneTypeTests, TestLoopbackTest) {
TestLoopback<One_objectid, const OID&, jstOID>(OID::max());
TestLoopback<One_date, const Date_t&, Date>(Date_t::now());
TestLoopback<One_timestamp, const Timestamp&, bsonTimestamp>(Timestamp::max());
-}
-
-// Test a BSONObj can be passed through an IDL type
-TEST(IDLOneTypeTests, TestObjectLoopbackTest) {
- IDLParserErrorContext ctxt("root");
-
- auto testValue = BSON("Hello"
- << "World");
- auto testDoc = BSON("value" << testValue);
-
- auto element = testDoc.firstElement();
- ASSERT_EQUALS(element.type(), Object);
-
- auto testStruct = One_plain_object::parse(ctxt, testDoc);
- assert_same_types<decltype(testStruct.getValue()), const BSONObj&>();
-
- ASSERT_BSONOBJ_EQ(testStruct.getValue(), testValue);
-
- // Positive: Test we can roundtrip from the just parsed document
- {
- BSONObjBuilder builder;
- testStruct.serialize(&builder);
- auto loopbackDoc = builder.obj();
-
- ASSERT_BSONOBJ_EQ(testDoc, loopbackDoc);
- }
-
- // Positive: Test we can serialize from nothing the same document
- {
- BSONObjBuilder builder;
- One_plain_object one_new;
- one_new.setValue(testValue);
- one_new.serialize(&builder);
-
- auto serializedDoc = builder.obj();
- ASSERT_BSONOBJ_EQ(testDoc, serializedDoc);
-
- ASSERT_TRUE(one_new == testStruct);
- ASSERT_FALSE(one_new < testStruct);
- }
+ TestLoopback<One_plain_object, const BSONObj&, Object>(BSON("Hello"
+ << "World"));
+ TestLoopback<One_plain_array, const BSONArray&, Array>(BSON_ARRAY("Hello"
+ << "World"));
}
// Test we compare an object with optional BSONObjs correctly
diff --git a/src/mongo/idl/unittest.idl b/src/mongo/idl/unittest.idl
index da3741f21cc..712a04ce4c2 100644
--- a/src/mongo/idl/unittest.idl
+++ b/src/mongo/idl/unittest.idl
@@ -126,6 +126,11 @@ structs:
fields:
value: object
+ one_plain_array:
+ description: UnitTest for a single BSONArray
+ fields:
+ value: array
+
one_plain_optional_object:
description: UnitTest for optional BSONObj
generate_comparison_operators: true