Skip to content

CXX-3077 BSON Binary Vector accessor, sub_binary builder #1356

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
85 commits merged into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from 84 commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
826cdd8
Add binary vector subtype
Feb 20, 2025
5101593
Add an example that demonstrates most vector view API features
Mar 20, 2025
5bddf8c
Bump required libmongoc version to pre-release 2.0.0
Mar 20, 2025
fa061e8
Additional binary builder tests, including sub_binary
Mar 20, 2025
b2dd2f8
vector API tests
Mar 20, 2025
2a478bb
New error codes for use in bsoncxx::vector
Mar 20, 2025
8ed6fb9
document the bsoncxx::vector namespaces
Mar 20, 2025
b316f50
Add forwarding headers for vector and sub_binary
Mar 20, 2025
5360c23
initial implementation for bsoncxx::vector
Mar 20, 2025
f573b11
sub_binary builder and integration with core
Mar 20, 2025
2b5c35a
remove obsolete workaround for CDRIVER-5732
Mar 20, 2025
16b8e1f
avoid int32 overflow prior to bson_append_utf8 invocation
Mar 20, 2025
5c6d77e
Temporary MONGOC_VERSION_MINIMUM bump for pre-2.0.0
Mar 20, 2025
37fe267
Fixes for conversion warnings
Mar 20, 2025
d577c15
Add missing includes
Mar 20, 2025
d93b1d7
Fix endian detection for win32
Mar 20, 2025
d29c352
fixup! Fix endian detection for win32
Mar 20, 2025
5019c3d
Replace problematic operator overloads and tests
Mar 20, 2025
8bddeb6
lambda missing capture mode
Mar 20, 2025
479a5ac
Add missing include
Mar 20, 2025
37ddd51
cstdint consistency fixes
Mar 21, 2025
d2b2130
More header and name qualification fixes
Mar 21, 2025
983da6b
Revert "avoid int32 overflow prior to bson_append_utf8 invocation"
Mar 21, 2025
d1f59dd
Revert "remove obsolete workaround for CDRIVER-5732"
Mar 21, 2025
36e3f6c
Merge branch 'master' into CXX-3077
Mar 21, 2025
03af662
clang-format
Mar 21, 2025
0c26bc8
Update src/bsoncxx/include/bsoncxx/docs/v_noabi.hpp
Mar 22, 2025
6bb3376
Revert change to required libbson/libmongoc versions
Mar 22, 2025
411a643
Remove ALL_VECTOR_FORMATS
Mar 22, 2025
1a3bf3c
Update src/bsoncxx/include/bsoncxx/docs/v_noabi.hpp
Mar 24, 2025
d45eca7
Update src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/vector/formats.hpp
Mar 24, 2025
9be7d04
Replace most REQUIREs with CHECKs
Mar 24, 2025
e184ea5
Replace most REQUIRE with CHECK in bson_builder too
Mar 24, 2025
a8c285c
Update src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/builder/basic/sub_…
Mar 24, 2025
9d8e4c7
k_vector_out_of_range
Mar 24, 2025
973f7b6
doxygen suggestions
Mar 24, 2025
7194f60
Rename bsoncxx::v_noabi::vector::impl to detail
Mar 25, 2025
d38f8aa
Take the impl out of impl_data
Mar 25, 2025
fa51a16
Refactor forward declarations
Mar 25, 2025
d69d6e2
Rename vector view to vector accessor
Mar 25, 2025
61bfb59
Refactor exported symbols out of 'detail' namespace
Mar 26, 2025
c52a7f1
Fix doc comments for vector elements/iterators namespaces
Mar 26, 2025
9737bf0
Can't rely on constexpr std::array operator[]
Mar 26, 2025
53dc708
Move internal parts of format exports to detail namespace
Mar 26, 2025
6b9cd01
Update vector fwd headers
Mar 26, 2025
8b61e63
Remove extra includes
Mar 26, 2025
799c897
Add core::open_binary for symmetry
Mar 26, 2025
a581e0a
Fix duplicate forward declaration
Mar 26, 2025
da06589
Add include for completeness
Mar 26, 2025
3dfc9f1
Fix typo in test name
Mar 26, 2025
9a670cf
Comment about accessor_data constructor assumptions
Mar 26, 2025
4ca9431
Document types in vector::accessor
Mar 26, 2025
007192b
Add cbegin/cend
Mar 26, 2025
352bb73
Requested change to header order
Mar 26, 2025
165a5b7
Replace open_binary with suggestion
Mar 26, 2025
dccb2fd
Update src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/builder/basic/sub_…
Mar 26, 2025
868179a
Update src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/vector/accessor-fw…
Mar 26, 2025
b8df720
Update src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/vector.cpp
Mar 26, 2025
3422b2e
Update src/bsoncxx/test/vector.cpp
Mar 26, 2025
2ef0bb2
More header order changes
Mar 26, 2025
7ffdb17
Update src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/vector.cpp
Mar 26, 2025
66b2a02
Update src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/vector/accessor.hpp
Mar 26, 2025
e809f9f
Update src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/vector/accessor.hpp
Mar 26, 2025
b567118
Revert "Update src/bsoncxx/test/vector.cpp"
Mar 26, 2025
d170e9e
Shorten doc comments
Mar 26, 2025
9218f97
Disable gcc -Wfloat-equal warnings for comparisons in bsoncxx::vector…
Mar 27, 2025
42250ea
Update src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/vector/formats-fwd…
Mar 27, 2025
3f61ef4
Hide detail from accessor type declarations
Mar 27, 2025
bd78a37
vector example: shorter output, more comments
Mar 27, 2025
ebf3ec1
Update src/bsoncxx/test/vector.cpp
Mar 27, 2025
c147b88
Prefer CHECK_THROWS_WITH_CODE
Mar 27, 2025
5067724
Clarify comment
Mar 27, 2025
5b7c991
Unclutter the vector example some more
Mar 27, 2025
87849b3
Update src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/types.hpp
Mar 27, 2025
bb61396
Update src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/vector/elements.hpp
Mar 27, 2025
3747aae
Update src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/vector.cpp
Mar 27, 2025
107b192
Update src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/vector.cpp
Mar 27, 2025
f8ad45d
Update src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/vector/detail.hpp
Mar 27, 2025
73737dd
Update src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/vector/elements.hpp
Mar 27, 2025
14019ab
Add accessor::as_const
Mar 27, 2025
cfee0fb
Prefer {} initializers
Mar 28, 2025
e66887d
Add test for swap()
Apr 1, 2025
9872b74
Portability: replace arithmetic right shift with signed division
Apr 1, 2025
4b87eb0
Clarify test name
Apr 1, 2025
77205e5
Merge branch 'master' into CXX-3077
Apr 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# Only LIBMONGOC_DOWNLOAD_VERSION needs to be updated when pinning to an unreleased commit.
# If pinning to an unreleased commit, create a "Blocked" JIRA ticket with
# a "depends on" link to the appropriate C Driver version release ticket.
MONGOC_VERSION_MINIMUM = '57bffac11fde38d1ce097bb22fb5322a6114d644' # CXX-3103: bump to 2.0.0 once released.
MONGOC_VERSION_MINIMUM = '0b3bb26c586c8a341710b853183abe5946693931' # CXX-3103: bump to 2.0.0 once released.


class InstallCDriver(Function):
Expand Down
2 changes: 1 addition & 1 deletion .evergreen/generated_configs/functions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ functions:
type: setup
params:
updates:
- { key: mongoc_version_minimum, value: 57bffac11fde38d1ce097bb22fb5322a6114d644 }
- { key: mongoc_version_minimum, value: 0b3bb26c586c8a341710b853183abe5946693931 }
- command: subprocess.exec
type: setup
params:
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ set(LIBBSON_REQUIRED_ABI_VERSION 1.0)

# Also update etc/purls.txt.
set(LIBMONGOC_REQUIRED_VERSION 1.30.0)
set(LIBMONGOC_DOWNLOAD_VERSION 57bffac11fde38d1ce097bb22fb5322a6114d644)
set(LIBMONGOC_DOWNLOAD_VERSION 0b3bb26c586c8a341710b853183abe5946693931)
set(LIBMONGOC_REQUIRED_ABI_VERSION 1.0)

set(NEED_DOWNLOAD_C_DRIVER false)
Expand Down
205 changes: 205 additions & 0 deletions examples/bsoncxx/bson_binary_vector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
// Copyright 2009-present MongoDB, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iostream>

#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/builder/basic/kvp.hpp>
#include <bsoncxx/builder/basic/sub_binary.hpp>
#include <bsoncxx/json.hpp>
#include <bsoncxx/types.hpp>
#include <bsoncxx/vector/accessor.hpp>
#include <bsoncxx/vector/formats.hpp>

#include <examples/macros.hh>

int EXAMPLES_CDECL main() {
using bsoncxx::binary_sub_type;
using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;
using bsoncxx::builder::basic::sub_binary;
using bsoncxx::vector::accessor;
using bsoncxx::vector::formats::f_float32;
using bsoncxx::vector::formats::f_int8;
using bsoncxx::vector::formats::f_packed_bit;

bsoncxx::document::value doc = make_document(

//
// Added along with BSON Binary Vector support, the new sub_binary builder
// allows allocating any type of BSON Binary item in-place. A callback taking
// a sub_binary argument can calculate the required space before calling allocate()
// on the sub_binary to get a pointer to the new in-place allocation.
//
// Every byte of the allocated binary region must be written or the resulting BSON
// will have undefined contents. If allocate() isn't called exactly once,
// an exception will be thrown.
//
kvp("binary",
[&](sub_binary sbin) {
uint32_t len = 10;
uint8_t* data = sbin.allocate(binary_sub_type::k_binary, len);
memset(data, 0x55, len);
}),

//
// The sub_binary also provides an allocate() method for BSON Binary Vector.
// Instead of a sub_type and byte length, this takes a vector format
// and an element count.
//
// This example uses the f_int8 vector format, which has int8_t elements.
// The allocate() call here returns a bsoncxx::vector::accessor instance
// that works like a random access container but does not own memory directly.
//
kvp("vector_int8",
[&](sub_binary sbin) {
auto vec = sbin.allocate(f_int8{}, 10);
int8_t i = -5;
std::generate(vec.begin(), vec.end(), [&] { return ++i; });
}),

//
// BSON Binary Vector supports formats that do not map directly to C++
// built-in types. The f_float32 format is an unaligned little endian
// serialization of IEEE 754 32-bit binary floating point. On some platforms,
// this sort of data could be accessed using a raw float*, but for consistent
// portability we have a bsoncxx::v_noabi::vector::elements::float32 type which
// has the unaligned little-endian representation in memory but supports automatic
// conversion to and from 'float'.
//
// The vector accessor works like a container of floats. Elements can be assigned
// from float expressions or used as float expressions. Assignment operators
// operate by automatically convering to float and then back to elements::float32.
//
kvp("vector_float32",
[&](sub_binary sbin) {
auto vec = sbin.allocate(f_float32{}, 10);
// Calculate a fibonacci sequence starting near the smallest representable value
vec[0] = 0.f;
vec[1] = 1e-38f;
for (size_t i = 2; i < vec.size(); i++) {
vec[i] = vec[i - 1] + vec[i - 2];
}
// Demonstrate assignment operators
vec[0] += 1.f;
vec[1] *= 1e38f;
vec[1] /= 2.f;
vec[1] -= 1.f + vec[0];
}),

//
// packed_bit vectors support any number of single-bit elements,
// using an accessor that works like a random-access container of
// bool values. This works using a reference-proxy type
// bsoncxx::v_noabi::vector::elements::packed_bit_element and an iterator
// bsoncxx::v_noabi::vector::iterators::packed_bit_element.
//
// Every bsoncxx::vector::accessor can be accessed either in per-element
// or per-byte mode. Byte mode is particularly useful for applications that
// may want to use packed_bit vectors in the serialized format without
// accessing individual elements.
//
kvp("vector_packed_bit", [&](sub_binary sbin) {
auto vec = sbin.allocate(f_packed_bit{}, 61);
// Start by setting all bits to 1
std::fill(vec.begin(), vec.end(), true);
// Flip a bit using a boolean expression
vec[5] = !vec[5];
// Assignment of a packed_bit_element reference copies the referenced bit value
vec[6] = vec[1];
vec[7] = vec[5];
// Bits can be assigned from boolean expressions, and from zero.
vec[8] = 0;
vec[60] = false;
// Demonstrate addressing bits backward from the end of the vector
std::fill(vec.end() - 20, vec.end() - 4, false);
std::fill(vec.end() - 8, vec.end() - 5, true);
// Flip all bits, operating an entire byte at a time.
// The last byte will have bits that do not correspond to any elements, and writes to these are ignored.
for (auto i = vec.byte_begin(); i != vec.byte_end(); i++) {
*i ^= 0xFF;
}
// Demonstrate copying bit ranges and byte ranges using std::copy
std::copy(vec.byte_begin(), vec.byte_begin() + 2, vec.byte_begin() + 2);
std::copy(vec.begin() + 5, vec.begin() + 9, vec.begin() + 56);
}));

// Demonstrate extended JSON serialization of the entire document
std::cout << bsoncxx::to_json(doc) << std::endl;

// Iterate over elements in the int8 vector
{
accessor<f_int8 const> vec{doc["vector_int8"].get_binary()};
std::cout << "int8: " << vec.size() << std::endl;
for (auto&& i : vec) {
std::cout << int{i} << " ";
}
std::cout << std::endl;
}

// Iterate over bytes in the int8 vector
{
accessor<f_int8 const> vec{doc["vector_int8"].get_binary()};
std::cout << "int8 bytes: " << vec.byte_size() << std::hex << std::endl;
for (auto i = vec.byte_begin(); i != vec.byte_end(); i++) {
std::cout << int{*i} << " ";
}
std::cout << std::dec << std::endl;
}

// Iterate over elements in the float32 vector
{
accessor<f_float32 const> vec{doc["vector_float32"].get_binary()};
std::cout << "float32: " << vec.size() << std::endl;
for (auto&& i : vec) {
std::cout << i << " ";
}
std::cout << std::endl;
}

// Iterate over bytes in the float32 vector
{
accessor<f_float32 const> vec{doc["vector_float32"].get_binary()};
std::cout << "float32 bytes: " << vec.byte_size() << std::hex << std::endl;
for (auto i = vec.byte_begin(); i != vec.byte_end(); i++) {
std::cout << int{*i} << " ";
}
std::cout << std::dec << std::endl;
}

// Iterate over elements in the packed_bit vector
{
accessor<f_packed_bit const> vec{doc["vector_packed_bit"].get_binary()};
std::cout << "packed_bit: " << vec.size() << std::endl;
for (auto&& i : vec) {
std::cout << i << " ";
}
std::cout << std::endl;
}

// Iterate over bytes in the packed_bit vector
{
accessor<f_packed_bit const> vec{doc["vector_packed_bit"].get_binary()};
std::cout << "packed_bit bytes: " << vec.byte_size() << std::hex << std::endl;
for (auto i = vec.byte_begin(); i != vec.byte_end(); i++) {
std::cout << int{*i} << " ";
}
std::cout << std::dec << std::endl;
}

return 0;
}
10 changes: 10 additions & 0 deletions src/bsoncxx/include/bsoncxx/docs/top.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,13 @@
/// @namespace bsoncxx::types::bson_value
/// Declares entities representing any BSON value type.
///

///
/// @namespace bsoncxx::vector
/// Declarations related to the BSON Binary Vector subtype.
///

///
/// @namespace bsoncxx::vector::formats
/// Declares supported BSON Binary Vector formats.
///
25 changes: 25 additions & 0 deletions src/bsoncxx/include/bsoncxx/docs/v_noabi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@
/// Provides headers declaring entities in @ref bsoncxx::v_noabi::types::bson_value.
///

///
/// @dir bsoncxx/v_noabi/bsoncxx/vector
/// Provides headers declaring entities in @ref bsoncxx::v_noabi::vector.
///

///
/// @namespace bsoncxx::v_noabi
/// Declares entities whose ABI stability is NOT guaranteed.
Expand Down Expand Up @@ -148,3 +153,23 @@
/// @namespace bsoncxx::v_noabi::types::bson_value
/// Declares entities representing any BSON value type.
///

///
/// @namespace bsoncxx::v_noabi::vector
/// @copydoc bsoncxx::vector
///

///
/// @namespace bsoncxx::v_noabi::vector::formats
/// @copydoc bsoncxx::vector::formats
///

///
/// @namespace bsoncxx::v_noabi::vector::elements
/// Declares element accessor types for BSON Binary Vector.
///

///
/// @namespace bsoncxx::v_noabi::vector::iterators
/// Declares iterator types for BSON Binary Vector.
///
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@

#pragma once

#include <bsoncxx/builder/basic/array-fwd.hpp>
#include <bsoncxx/builder/basic/document-fwd.hpp>

//

#include <bsoncxx/builder/basic/array-fwd.hpp>

#include <bsoncxx/builder/basic/impl.hpp>
#include <bsoncxx/builder/basic/kvp.hpp>
#include <bsoncxx/builder/basic/sub_document.hpp>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#pragma once

#include <bsoncxx/builder/basic/sub_array.hpp>
#include <bsoncxx/builder/basic/sub_binary.hpp>
#include <bsoncxx/builder/basic/sub_document.hpp>
#include <bsoncxx/stdx/type_traits.hpp>

Expand All @@ -29,21 +30,31 @@ namespace impl {
template <typename T>
detail::requires_t<void, detail::is_invocable<T, sub_document>> generic_append(core* core, T&& func) {
core->open_document();
detail::invoke(std::forward<T>(func), sub_document(core));
detail::invoke(std::forward<T>(func), sub_document{core});
core->close_document();
}

template <typename T, typename Placeholder = void> // placeholder 'void' for VS2015 compat
detail::requires_t<void, detail::is_invocable<T, sub_array>> generic_append(core* core, T&& func) {
core->open_array();
detail::invoke(std::forward<T>(func), sub_array(core));
detail::invoke(std::forward<T>(func), sub_array{core});
core->close_array();
}

template <typename T>
detail::requires_t<void, detail::is_invocable<T, sub_binary>> generic_append(core* core, T&& func) {
// Opened by the user invoking `sub_binary::allocate()` in `func`.
detail::invoke(std::forward<T>(func), sub_binary{core});
core->close_binary();
}

template <typename T, typename = void, typename = void>
detail::requires_not_t<void, detail::is_invocable<T, sub_document>, detail::is_invocable<T, sub_array>> generic_append(
core* core,
T&& t) {
detail::requires_not_t<
void,
detail::is_invocable<T, sub_document>,
detail::is_invocable<T, sub_array>,
detail::is_invocable<T, sub_binary>>
generic_append(core* core, T&& t) {
core->append(std::forward<T>(t));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2009-present MongoDB, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

namespace bsoncxx {
namespace v_noabi {
namespace builder {
namespace basic {

class sub_binary;

} // namespace basic
} // namespace builder
} // namespace v_noabi
} // namespace bsoncxx

namespace bsoncxx {
namespace builder {
namespace basic {

using ::bsoncxx::v_noabi::builder::basic::sub_binary;

} // namespace basic
} // namespace builder
} // namespace bsoncxx

///
/// @file
/// Declares @ref bsoncxx::v_noabi::builder::basic::sub_binary
///
Loading