Skip to content

Commit 945bdd7

Browse files
rozzaclaude
andauthored
ByteBufBsonDocument and RawBsonDocument simplifications (#1902)
### Rationale `ByteBufBsonDocument#clone` used to return a `RawBsonDocument`. The recent changes returned a normal `BsonDocument`, which is potentially expensive depending on its usage. The `ByteBufBsonDocument` changes also added complex iterator logic, when `RawBsonDocument` deferred to `BsonDocument` iterators. As iteration is essentially a hydrating mechanism, there is opportunity for improvements for both implementations. By changing the `RawBsonDocument` iterators to be more efficient, `ByteBufBsonDocument` can now utilize these efficiency gains by proxy, relying on the `cachedDocument` iterators. This change both reduces the complexity of `ByteBufBsonDocument` and relies on an improved `RawBsonDocument` implementation. ### Summary of changes * **`ByteBufBsonDocument`**: * Simplify by returning `RawBsonDocument` from `toBsonDocument`, avoiding full BSON deserialization. When there are no sequence fields, the body bytes are cloned directly. When sequence fields exist, `BsonBinaryWriter.pipe()` merges the body with sequence arrays efficiently. * Use `toBsonDocument` for iterators. This eliminates the need for custom iterators (`IteratorMode`, `CombinedIterator`, `createBodyIterator`, and sequence iterators) since `entrySet`/`values`/`keySet` now delegate to the cached `RawBsonDocument`. * **`RawBsonDocument`**: * Renamed `toBaseBsonDocument` to override the default `toBsonDocument` implementation. * Implemented the iterators so that they don't need to fully convert the document to a `BsonDocument`. * **Tests**: * Updated `ByteBufBsonDocumentTest` iteration tests. * Updated `ByteBufBsonArrayTest#fromValues` as `entrySet` now returns `RawBsonDocument` instances. JAVA-6010 --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 98a264b commit 945bdd7

6 files changed

Lines changed: 543 additions & 849 deletions

File tree

bson/src/main/org/bson/RawBsonDocument.java

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@
3535
import java.io.StringWriter;
3636
import java.nio.ByteBuffer;
3737
import java.nio.ByteOrder;
38+
import java.util.AbstractMap;
39+
import java.util.ArrayList;
3840
import java.util.Collection;
41+
import java.util.LinkedHashSet;
42+
import java.util.List;
3943
import java.util.Map;
4044
import java.util.NoSuchElementException;
4145
import java.util.Set;
@@ -123,12 +127,13 @@ public RawBsonDocument(final byte[] bytes, final int offset, final int length) {
123127
public <T> RawBsonDocument(final T document, final Codec<T> codec) {
124128
notNull("document", document);
125129
notNull("codec", codec);
126-
BasicOutputBuffer buffer = new BasicOutputBuffer();
127-
try (BsonBinaryWriter writer = new BsonBinaryWriter(buffer)) {
128-
codec.encode(writer, document, EncoderContext.builder().build());
129-
this.bytes = buffer.getInternalBuffer();
130-
this.offset = 0;
131-
this.length = buffer.getPosition();
130+
try (BasicOutputBuffer buffer = new BasicOutputBuffer()) {
131+
try (BsonBinaryWriter writer = new BsonBinaryWriter(buffer)) {
132+
codec.encode(writer, document, EncoderContext.builder().build());
133+
this.bytes = buffer.getInternalBuffer();
134+
this.offset = 0;
135+
this.length = buffer.getPosition();
136+
}
132137
}
133138
}
134139

@@ -225,17 +230,42 @@ public int size() {
225230

226231
@Override
227232
public Set<Entry<String, BsonValue>> entrySet() {
228-
return toBaseBsonDocument().entrySet();
233+
List<Entry<String, BsonValue>> entries = new ArrayList<>();
234+
try (BsonBinaryReader bsonReader = createReader()) {
235+
bsonReader.readStartDocument();
236+
while (bsonReader.readBsonType() != BsonType.END_OF_DOCUMENT) {
237+
String key = bsonReader.readName();
238+
BsonValue value = RawBsonValueHelper.decode(bytes, bsonReader);
239+
entries.add(new AbstractMap.SimpleImmutableEntry<>(key, value));
240+
}
241+
}
242+
return new LinkedHashSet<>(entries);
229243
}
230244

231245
@Override
232246
public Collection<BsonValue> values() {
233-
return toBaseBsonDocument().values();
247+
List<BsonValue> values = new ArrayList<>();
248+
try (BsonBinaryReader bsonReader = createReader()) {
249+
bsonReader.readStartDocument();
250+
while (bsonReader.readBsonType() != BsonType.END_OF_DOCUMENT) {
251+
bsonReader.skipName();
252+
values.add(RawBsonValueHelper.decode(bytes, bsonReader));
253+
}
254+
}
255+
return values;
234256
}
235257

236258
@Override
237259
public Set<String> keySet() {
238-
return toBaseBsonDocument().keySet();
260+
List<String> keys = new ArrayList<>();
261+
try (BsonBinaryReader bsonReader = createReader()) {
262+
bsonReader.readStartDocument();
263+
while (bsonReader.readBsonType() != BsonType.END_OF_DOCUMENT) {
264+
keys.add(bsonReader.readName());
265+
bsonReader.skipValue();
266+
}
267+
}
268+
return new LinkedHashSet<>(keys);
239269
}
240270

241271
@Override
@@ -318,12 +348,19 @@ public String toJson(final JsonWriterSettings settings) {
318348

319349
@Override
320350
public boolean equals(final Object o) {
321-
return toBaseBsonDocument().equals(o);
351+
return toBsonDocument().equals(o);
322352
}
323353

324354
@Override
325355
public int hashCode() {
326-
return toBaseBsonDocument().hashCode();
356+
return toBsonDocument().hashCode();
357+
}
358+
359+
@Override
360+
public BsonDocument toBsonDocument() {
361+
try (BsonBinaryReader bsonReader = createReader()) {
362+
return new BsonDocumentCodec().decode(bsonReader, DecoderContext.builder().build());
363+
}
327364
}
328365

329366
@Override
@@ -335,13 +372,6 @@ private BsonBinaryReader createReader() {
335372
return new BsonBinaryReader(new ByteBufferBsonInput(getByteBuffer()));
336373
}
337374

338-
// Transform to an org.bson.BsonDocument instance
339-
private BsonDocument toBaseBsonDocument() {
340-
try (BsonBinaryReader bsonReader = createReader()) {
341-
return new BsonDocumentCodec().decode(bsonReader, DecoderContext.builder().build());
342-
}
343-
}
344-
345375
/**
346376
* Write the replacement object.
347377
*

0 commit comments

Comments
 (0)