Skip to content

Commit 3e59ebe

Browse files
committed
PHPC-2350: Implement JSON methods for PackedArray
1 parent 7ba3371 commit 3e59ebe

11 files changed

+387
-4
lines changed

src/BSON/PackedArray.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,58 @@ static HashTable* php_phongo_packedarray_get_properties_hash(phongo_compat_objec
8181
return props;
8282
}
8383

84+
static bool php_phongo_packedarray_to_json(zval* return_value, bson_json_mode_t mode, const bson_t* bson)
85+
{
86+
char* json = NULL;
87+
size_t json_len;
88+
bson_json_opts_t* opts = bson_json_opts_new(mode, BSON_MAX_LEN_UNLIMITED);
89+
bool ret = false;
90+
91+
bson_json_opts_set_outermost_array(opts, true);
92+
93+
json = bson_as_json_with_opts(bson, &json_len, opts);
94+
95+
if (json) {
96+
ZVAL_STRINGL(return_value, json, json_len);
97+
bson_free(json);
98+
ret = true;
99+
} else {
100+
ZVAL_UNDEF(return_value);
101+
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "Could not convert BSON array to a JSON string");
102+
}
103+
104+
bson_json_opts_destroy(opts);
105+
106+
return ret;
107+
}
108+
84109
PHONGO_DISABLED_CONSTRUCTOR(MongoDB_BSON_PackedArray)
85110

111+
static PHP_METHOD(MongoDB_BSON_PackedArray, fromJSON)
112+
{
113+
zval zv;
114+
php_phongo_packedarray_t* intern;
115+
zend_string* json;
116+
bson_t* bson;
117+
bson_error_t error;
118+
119+
PHONGO_PARSE_PARAMETERS_START(1, 1)
120+
Z_PARAM_STR(json)
121+
PHONGO_PARSE_PARAMETERS_END();
122+
123+
bson = bson_new_from_json((const uint8_t*) ZSTR_VAL(json), ZSTR_LEN(json), &error);
124+
if (!bson) {
125+
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE, "%s", error.domain == BSON_ERROR_JSON ? error.message : "Error parsing JSON");
126+
return;
127+
}
128+
129+
object_init_ex(&zv, php_phongo_packedarray_ce);
130+
intern = Z_PACKEDARRAY_OBJ_P(&zv);
131+
intern->bson = bson;
132+
133+
RETURN_ZVAL(&zv, 1, 1);
134+
}
135+
86136
static PHP_METHOD(MongoDB_BSON_PackedArray, fromPHP)
87137
{
88138
zval zv;
@@ -192,6 +242,28 @@ static PHP_METHOD(MongoDB_BSON_PackedArray, has)
192242
RETURN_BOOL(php_phongo_packedarray_has(intern, index));
193243
}
194244

245+
static PHP_METHOD(MongoDB_BSON_PackedArray, toCanonicalExtendedJSON)
246+
{
247+
php_phongo_packedarray_t* intern;
248+
249+
PHONGO_PARSE_PARAMETERS_NONE();
250+
251+
intern = Z_PACKEDARRAY_OBJ_P(getThis());
252+
253+
php_phongo_packedarray_to_json(return_value, BSON_JSON_MODE_CANONICAL, intern->bson);
254+
}
255+
256+
static PHP_METHOD(MongoDB_BSON_PackedArray, toRelaxedExtendedJSON)
257+
{
258+
php_phongo_packedarray_t* intern;
259+
260+
PHONGO_PARSE_PARAMETERS_NONE();
261+
262+
intern = Z_PACKEDARRAY_OBJ_P(getThis());
263+
264+
php_phongo_packedarray_to_json(return_value, BSON_JSON_MODE_RELAXED, intern->bson);
265+
}
266+
195267
static PHP_METHOD(MongoDB_BSON_PackedArray, toPHP)
196268
{
197269
php_phongo_packedarray_t* intern;

src/BSON/PackedArray.stub.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ final class PackedArray implements \IteratorAggregate, \Serializable, \ArrayAcce
1111
{
1212
private function __construct() {}
1313

14+
final static public function fromJSON(string $json): PackedArray {}
15+
1416
final static public function fromPHP(array $value): PackedArray {}
1517

1618
#if PHP_VERSION_ID >= 80000
@@ -31,6 +33,10 @@ final public function toPHP(?array $typeMap = null): array|object {}
3133
final public function toPHP(?array $typeMap = null) {}
3234
#endif
3335

36+
final public function toCanonicalExtendedJSON(): string {}
37+
38+
final public function toRelaxedExtendedJSON(): string {}
39+
3440
#if PHP_VERSION_ID >= 80000
3541
public function offsetExists(mixed $offset): bool {}
3642
# else

src/BSON/PackedArray_arginfo.h

Lines changed: 18 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
MongoDB\BSON\PackedArray::fromJSON(): Decoding JSON
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/basic.inc';
7+
8+
$tests = [
9+
'[]',
10+
'[ 1, 2, 3 ]',
11+
'[[ 1, 2, 3 ]]',
12+
'[{ "bar": 1 }]',
13+
];
14+
15+
foreach ($tests as $json) {
16+
printf("Test %s\n", $json);
17+
$bson = MongoDB\BSON\PackedArray::fromJSON($json);
18+
hex_dump((string) $bson);
19+
}
20+
21+
?>
22+
===DONE===
23+
<?php exit(0); ?>
24+
--EXPECT--
25+
Test []
26+
0 : 05 00 00 00 00 [.....]
27+
Test [ 1, 2, 3 ]
28+
0 : 1a 00 00 00 10 30 00 01 00 00 00 10 31 00 02 00 [.....0......1...]
29+
10 : 00 00 10 32 00 03 00 00 00 00 [...2......]
30+
Test [[ 1, 2, 3 ]]
31+
0 : 22 00 00 00 04 30 00 1a 00 00 00 10 30 00 01 00 ["....0......0...]
32+
10 : 00 00 10 31 00 02 00 00 00 10 32 00 03 00 00 00 [...1......2.....]
33+
20 : 00 00 [..]
34+
Test [{ "bar": 1 }]
35+
0 : 16 00 00 00 03 30 00 0e 00 00 00 10 62 61 72 00 [.....0......bar.]
36+
10 : 01 00 00 00 00 00 [......]
37+
===DONE===
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
MongoDB\BSON\PackedArray::fromJSON(): Decoding extended JSON types
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/basic.inc';
7+
8+
$tests = [
9+
'[{ "$oid": "56315a7c6118fd1b920270b1" }]',
10+
'[{ "$binary": "Zm9v", "$type": "00" }]',
11+
'[{ "$date": "2015-10-28T00:00:00Z" }]',
12+
'[{ "$timestamp": { "t": 1446084619, "i": 0 }}]',
13+
'[{ "$regex": "pattern", "$options": "i" }]',
14+
'[{ "$undefined": true }]',
15+
'[{ "$minKey": 1 }]',
16+
'[{ "$maxKey": 1 }]',
17+
'[{ "$numberLong": "1234" }]',
18+
];
19+
20+
foreach ($tests as $json) {
21+
printf("Test %s\n", $json);
22+
$bson = MongoDB\BSON\PackedArray::fromJSON($json);
23+
hex_dump((string) $bson);
24+
}
25+
26+
?>
27+
===DONE===
28+
<?php exit(0); ?>
29+
--EXPECT--
30+
Test [{ "$oid": "56315a7c6118fd1b920270b1" }]
31+
0 : 14 00 00 00 07 30 00 56 31 5a 7c 61 18 fd 1b 92 [.....0.V1Z|a....]
32+
10 : 02 70 b1 00 [.p..]
33+
Test [{ "$binary": "Zm9v", "$type": "00" }]
34+
0 : 10 00 00 00 05 30 00 03 00 00 00 00 66 6f 6f 00 [.....0......foo.]
35+
Test [{ "$date": "2015-10-28T00:00:00Z" }]
36+
0 : 10 00 00 00 09 30 00 00 80 be ab 50 01 00 00 00 [.....0.....P....]
37+
Test [{ "$timestamp": { "t": 1446084619, "i": 0 }}]
38+
0 : 10 00 00 00 11 30 00 00 00 00 00 0b 80 31 56 00 [.....0.......1V.]
39+
Test [{ "$regex": "pattern", "$options": "i" }]
40+
0 : 12 00 00 00 0b 30 00 70 61 74 74 65 72 6e 00 69 [.....0.pattern.i]
41+
10 : 00 00 [..]
42+
Test [{ "$undefined": true }]
43+
0 : 08 00 00 00 06 30 00 00 [.....0..]
44+
Test [{ "$minKey": 1 }]
45+
0 : 08 00 00 00 ff 30 00 00 [.....0..]
46+
Test [{ "$maxKey": 1 }]
47+
0 : 08 00 00 00 7f 30 00 00 [.....0..]
48+
Test [{ "$numberLong": "1234" }]
49+
0 : 10 00 00 00 12 30 00 d2 04 00 00 00 00 00 00 00 [.....0..........]
50+
===DONE===
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
MongoDB\BSON\PackedArray::fromJSON(): Decoding JSON object
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/basic.inc';
7+
8+
$bson = MongoDB\BSON\PackedArray::fromJSON('{ "foo": "bar" }');
9+
var_dump($bson);
10+
hex_dump((string) $bson);
11+
echo $bson->toCanonicalExtendedJSON(), PHP_EOL;
12+
echo MongoDB\BSON\Document::fromPHP(['array' => $bson])->toCanonicalExtendedJSON(), PHP_EOL;
13+
14+
?>
15+
===DONE===
16+
<?php exit(0); ?>
17+
--EXPECTF--
18+
object(MongoDB\BSON\PackedArray)#%d (%d) {
19+
["data"]=>
20+
string(24) "EgAAAAJmb28ABAAAAGJhcgAA"
21+
["value"]=>
22+
array(1) {
23+
[0]=>
24+
string(3) "bar"
25+
}
26+
}
27+
0 : 12 00 00 00 02 66 6f 6f 00 04 00 00 00 62 61 72 [.....foo.....bar]
28+
10 : 00 00 [..]
29+
[ "bar" ]
30+
{ "array" : [ "bar" ] }
31+
===DONE===
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
MongoDB\BSON\PackedArray::fromJSON(): invalid JSON
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/basic.inc';
7+
8+
throws(function() {
9+
MongoDB\BSON\PackedArray::fromJSON('foo');
10+
}, 'MongoDB\Driver\Exception\UnexpectedValueException');
11+
12+
?>
13+
===DONE===
14+
<?php exit(0); ?>
15+
--EXPECT--
16+
OK: Got MongoDB\Driver\Exception\UnexpectedValueException
17+
===DONE===
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
MongoDB\BSON\PackedArray::toCanonicalExtendedJSON(): Encoding JSON
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/basic.inc';
7+
8+
$tests = [
9+
[],
10+
[ null ],
11+
[ true ],
12+
[ 'foo' ],
13+
[ 123 ],
14+
[ 1.0, ],
15+
[ NAN ],
16+
[ INF ],
17+
[ -INF ],
18+
[ [ 'foo', 'bar' ]],
19+
[ [ 'foo' => 'bar' ]],
20+
];
21+
22+
foreach ($tests as $value) {
23+
echo MongoDB\BSON\PackedArray::fromPHP($value)->toCanonicalExtendedJSON(), "\n";
24+
}
25+
26+
?>
27+
===DONE===
28+
<?php exit(0); ?>
29+
--EXPECT--
30+
[ ]
31+
[ null ]
32+
[ true ]
33+
[ "foo" ]
34+
[ { "$numberInt" : "123" } ]
35+
[ { "$numberDouble" : "1.0" } ]
36+
[ { "$numberDouble" : "NaN" } ]
37+
[ { "$numberDouble" : "Infinity" } ]
38+
[ { "$numberDouble" : "-Infinity" } ]
39+
[ [ "foo", "bar" ] ]
40+
[ { "foo" : "bar" } ]
41+
===DONE===

0 commit comments

Comments
 (0)