Skip to content

Commit a237193

Browse files
authored
BSON class implementations (#1387)
* Extract bson to json conversion logic * PHPC-326: Add class to represent raw BSON document * PHPC-326: Add class to represent raw BSON array * Typemaps now support raw BSON type * Short-circuit encoding of BSON zvals * PHPC-324: Add BSONIterator class * Polyfill zend_array_is_list on PHP < 8.1 * Add offset accessors to BSON classes * Add more tests around iterators and fetching offsets * Remove compare handler for BSONIterator * Rename BSONArray to ArrayList * Rename BSONDocument to Document * Rename BSONIterator to Iterator * Implement Document::fromBSONString * Test BSON document in bson-corpus tests * Fix ArrayList handling of BSON arrays with wrong keys * Address code review for bson-corpus tests * Address code review in ArrayList * Address code review for Document * Address code review for Iterator * Allow BSON iterators to be rewound * Address code review in tests * Fix comment explaining php_phongo_bson_append_object * Remove obsolete php_phongo_bson_append_zval * More review changes to tests * Return base64 encoded data when debugging BSON classes * Allow serialisation of Document and ArrayList * Add test for iterating past the end of a structure * Update exception message to contain class name * Make BSON pclass handling test more complete * Fix wrong handling of type map in nested structures * Ensure objects are backed by actual memory * Validate UTF-8 BSON data before returning it * Allow ArrayList::toPHP() to accept a different root type map * Ignore null return type for invalid BSON iterators on PHP < 8 * Throw when calling get on non-existing BSON offsets * Remove unnecessary length from serialised output * Refactor names around type map handling * Use short array syntax in new tests * Improve test descriptions * Restructure BSON iterator tests * Expand BSON class serialisation tests * Throw exception when iterator is exhausted The previous method relied on the type system of PHP to throw an exception when accessing the key of an exhausted iterator, but this does not work on non-debug versions of PHP. * Update test description * Rename ArrayList class to PackedArray
1 parent 9351cca commit a237193

File tree

814 files changed

+15838
-115
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

814 files changed

+15838
-115
lines changed

config.m4

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ if test "$PHP_MONGODB" != "no"; then
120120
src/phongo_util.c \
121121
src/BSON/Binary.c \
122122
src/BSON/BinaryInterface.c \
123+
src/BSON/Document.c \
124+
src/BSON/Iterator.c \
123125
src/BSON/DBPointer.c \
124126
src/BSON/Decimal128.c \
125127
src/BSON/Decimal128Interface.c \
@@ -132,6 +134,7 @@ if test "$PHP_MONGODB" != "no"; then
132134
src/BSON/MinKeyInterface.c \
133135
src/BSON/ObjectId.c \
134136
src/BSON/ObjectIdInterface.c \
137+
src/BSON/PackedArray.c \
135138
src/BSON/Persistable.c \
136139
src/BSON/Regex.c \
137140
src/BSON/RegexInterface.c \

config.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ if (PHP_MONGODB != "no") {
121121

122122
EXTENSION("mongodb", "php_phongo.c", null, PHP_MONGODB_CFLAGS);
123123
MONGODB_ADD_SOURCES("/src", "phongo_apm.c phongo_bson.c phongo_bson_encode.c phongo_client.c phongo_compat.c phongo_error.c phongo_execute.c phongo_ini.c phongo_util.c");
124-
MONGODB_ADD_SOURCES("/src/BSON", "Binary.c BinaryInterface.c DBPointer.c Decimal128.c Decimal128Interface.c Int64.c Javascript.c JavascriptInterface.c MaxKey.c MaxKeyInterface.c MinKey.c MinKeyInterface.c ObjectId.c ObjectIdInterface.c Persistable.c Regex.c RegexInterface.c Serializable.c Symbol.c Timestamp.c TimestampInterface.c Type.c Undefined.c Unserializable.c UTCDateTime.c UTCDateTimeInterface.c functions.c");
124+
MONGODB_ADD_SOURCES("/src/BSON", "Binary.c BinaryInterface.c Document.c Iterator.c DBPointer.c Decimal128.c Decimal128Interface.c Int64.c Javascript.c JavascriptInterface.c MaxKey.c MaxKeyInterface.c MinKey.c MinKeyInterface.c ObjectId.c ObjectIdInterface.c PackedArray.c Persistable.c Regex.c RegexInterface.c Serializable.c Symbol.c Timestamp.c TimestampInterface.c Type.c Undefined.c Unserializable.c UTCDateTime.c UTCDateTimeInterface.c functions.c");
125125
MONGODB_ADD_SOURCES("/src/MongoDB", "BulkWrite.c ClientEncryption.c Command.c Cursor.c CursorId.c CursorInterface.c Manager.c Query.c ReadConcern.c ReadPreference.c Server.c ServerApi.c ServerDescription.c Session.c TopologyDescription.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c");
126126
MONGODB_ADD_SOURCES("/src/MongoDB/Exception", "AuthenticationException.c BulkWriteException.c CommandException.c ConnectionException.c ConnectionTimeoutException.c EncryptionException.c Exception.c ExecutionTimeoutException.c InvalidArgumentException.c LogicException.c RuntimeException.c ServerException.c SSLConnectionException.c UnexpectedValueException.c WriteException.c");
127127
MONGODB_ADD_SOURCES("/src/MongoDB/Monitoring", "CommandFailedEvent.c CommandStartedEvent.c CommandSubscriber.c CommandSucceededEvent.c SDAMSubscriber.c Subscriber.c ServerChangedEvent.c ServerClosedEvent.c ServerHeartbeatFailedEvent.c ServerHeartbeatStartedEvent.c ServerHeartbeatSucceededEvent.c ServerOpeningEvent.c TopologyChangedEvent.c TopologyClosedEvent.c TopologyOpeningEvent.c functions.c");

php_phongo.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ PHP_MINIT_FUNCTION(mongodb) /* {{{ */
207207
php_phongo_timestamp_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
208208
php_phongo_utcdatetime_interface_init_ce(INIT_FUNC_ARGS_PASSTHRU);
209209

210+
php_phongo_iterator_init_ce(INIT_FUNC_ARGS_PASSTHRU);
211+
php_phongo_packedarray_init_ce(INIT_FUNC_ARGS_PASSTHRU);
212+
php_phongo_document_init_ce(INIT_FUNC_ARGS_PASSTHRU);
213+
210214
php_phongo_binary_init_ce(INIT_FUNC_ARGS_PASSTHRU);
211215
php_phongo_dbpointer_init_ce(INIT_FUNC_ARGS_PASSTHRU);
212216
php_phongo_decimal128_init_ce(INIT_FUNC_ARGS_PASSTHRU);

scripts/convert-bson-corpus-tests.php

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,34 +151,62 @@ function getParamsForValid(array $test, array $case)
151151
$code .= 'echo bin2hex(fromPHP(toPHP($canonicalBson))), "\n";' . "\n";
152152
$expect .= $expectedCanonicalBson . "\n";
153153

154+
$code .= "\n// Canonical BSON -> BSON object -> Canonical BSON\n";
155+
$code .= 'echo bin2hex((string) MongoDB\BSON\Document::fromBSON($canonicalBson)), "\n";' . "\n";
156+
$expect .= $expectedCanonicalBson . "\n";
157+
154158
$code .= "\n// Canonical BSON -> Canonical extJSON\n";
155-
$code .= 'echo json_canonicalize(toCanonicalExtendedJSON($canonicalBson)), "\n";' . "\n";;
159+
$code .= 'echo json_canonicalize(toCanonicalExtendedJSON($canonicalBson)), "\n";' . "\n";
160+
$expect .= $expectedCanonicalExtJson . "\n";
161+
162+
$code .= "\n// Canonical BSON -> BSON object -> Canonical extJSON\n";
163+
$code .= 'echo json_canonicalize(MongoDB\BSON\Document::fromBSON($canonicalBson)->toCanonicalExtendedJSON()), "\n";' . "\n";
156164
$expect .= $expectedCanonicalExtJson . "\n";
157165

158166
if (isset($relaxedExtJson)) {
159167
$code .= "\n// Canonical BSON -> Relaxed extJSON\n";
160-
$code .= 'echo json_canonicalize(toRelaxedExtendedJSON($canonicalBson)), "\n";' . "\n";;
168+
$code .= 'echo json_canonicalize(toRelaxedExtendedJSON($canonicalBson)), "\n";' . "\n";
169+
$expect .= $expectedRelaxedExtJson . "\n";
170+
171+
$code .= "\n// Canonical BSON -> BSON object -> Relaxed extJSON\n";
172+
$code .= 'echo json_canonicalize(MongoDB\BSON\Document::fromBSON($canonicalBson)->toRelaxedExtendedJSON()), "\n";' . "\n";
161173
$expect .= $expectedRelaxedExtJson . "\n";
162174
}
163175

164176
if (!$lossy) {
165177
$code .= "\n// Canonical extJSON -> Canonical BSON\n";
166178
$code .= 'echo bin2hex(fromJSON($canonicalExtJson)), "\n";' . "\n";
167179
$expect .= $expectedCanonicalBson . "\n";
180+
181+
$code .= "\n// Canonical extJSON -> BSON object -> Canonical BSON\n";
182+
$code .= 'echo bin2hex((string) MongoDB\BSON\Document::fromJSON($canonicalExtJson)), "\n";' . "\n";
183+
$expect .= $expectedCanonicalBson . "\n";
168184
}
169185

170186
if (isset($degenerateBson)) {
171187
$code .= "\n// Degenerate BSON -> Native -> Canonical BSON\n";
172188
$code .= 'echo bin2hex(fromPHP(toPHP($degenerateBson))), "\n";' . "\n";
173189
$expect .= $expectedCanonicalBson . "\n";
174190

191+
$code .= "\n// Degenerate BSON -> BSON object -> Canonical BSON\n";
192+
$code .= 'echo bin2hex(fromPHP(MongoDB\BSON\Document::fromBSON($degenerateBson)->toPHP())), "\n";' . "\n";
193+
$expect .= $expectedCanonicalBson . "\n";
194+
175195
$code .= "\n// Degenerate BSON -> Canonical extJSON\n";
176-
$code .= 'echo json_canonicalize(toCanonicalExtendedJSON($degenerateBson)), "\n";' . "\n";;
196+
$code .= 'echo json_canonicalize(toCanonicalExtendedJSON($degenerateBson)), "\n";' . "\n";
197+
$expect .= $expectedCanonicalExtJson . "\n";
198+
199+
$code .= "\n// Degenerate BSON -> BSON object -> Canonical extJSON\n";
200+
$code .= 'echo json_canonicalize(MongoDB\BSON\Document::fromBSON($degenerateBson)->toCanonicalExtendedJSON()), "\n";' . "\n";
177201
$expect .= $expectedCanonicalExtJson . "\n";
178202

179203
if (isset($relaxedExtJson)) {
180204
$code .= "\n// Degenerate BSON -> Relaxed extJSON\n";
181-
$code .= 'echo json_canonicalize(toRelaxedExtendedJSON($degenerateBson)), "\n";' . "\n";;
205+
$code .= 'echo json_canonicalize(toRelaxedExtendedJSON($degenerateBson)), "\n";' . "\n";
206+
$expect .= $expectedRelaxedExtJson . "\n";
207+
208+
$code .= "\n// Degenerate BSON -> BSON object -> Relaxed extJSON\n";
209+
$code .= 'echo json_canonicalize(MongoDB\BSON\Document::fromBSON($degenerateBson)->toRelaxedExtendedJSON()), "\n";' . "\n";
182210
$expect .= $expectedRelaxedExtJson . "\n";
183211
}
184212
}
@@ -187,12 +215,20 @@ function getParamsForValid(array $test, array $case)
187215
$code .= "\n// Degenerate extJSON -> Canonical BSON\n";
188216
$code .= 'echo bin2hex(fromJSON($degenerateExtJson)), "\n";' . "\n";
189217
$expect .= $expectedCanonicalBson . "\n";
218+
219+
$code .= "\n// Degenerate extJSON -> BSON object -> Canonical BSON\n";
220+
$code .= 'echo bin2hex((string) MongoDB\BSON\Document::fromJSON($degenerateExtJson)), "\n";' . "\n";
221+
$expect .= $expectedCanonicalBson . "\n";
190222
}
191223

192224
if (isset($relaxedExtJson)) {
193225
$code .= "\n// Relaxed extJSON -> BSON -> Relaxed extJSON\n";
194226
$code .= 'echo json_canonicalize(toRelaxedExtendedJSON(fromJSON($relaxedExtJson))), "\n";' . "\n";
195227
$expect .= $expectedRelaxedExtJson . "\n";
228+
229+
$code .= "\n// Relaxed extJSON -> BSON object -> Relaxed extJSON\n";
230+
$code .= 'echo json_canonicalize(MongoDB\BSON\Document::fromJSON($relaxedExtJson)->toRelaxedExtendedJSON()), "\n";' . "\n";
231+
$expect .= $expectedRelaxedExtJson . "\n";
196232
}
197233

198234
return [

0 commit comments

Comments
 (0)