Skip to content

Commit 8e818a3

Browse files
committed
Introduce codec library
1 parent e6810d1 commit 8e818a3

File tree

6 files changed

+456
-0
lines changed

6 files changed

+456
-0
lines changed

psalm-baseline.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@
7575
<code>$mergedDriver['platform']</code>
7676
</MixedAssignment>
7777
</file>
78+
<file src="src/Codec/DecodeIfSupported.php">
79+
<MixedInferredReturnType occurrences="1">
80+
<code>($value is BSONType ? NativeType : $value)</code>
81+
</MixedInferredReturnType>
82+
</file>
83+
<file src="src/Codec/EncodeIfSupported.php">
84+
<MixedInferredReturnType occurrences="1">
85+
<code>($value is NativeType ? BSONType : $value)</code>
86+
</MixedInferredReturnType>
87+
</file>
7888
<file src="src/Command/ListCollections.php">
7989
<MixedAssignment occurrences="2">
8090
<code>$cmd[$option]</code>

src/Codec/CodecLibrary.php

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
<?php
2+
/*
3+
* Copyright 2023-present MongoDB, Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace MongoDB\Codec;
19+
20+
use MongoDB\Exception\InvalidArgumentException;
21+
use MongoDB\Exception\UnexpectedValueException;
22+
23+
use function get_debug_type;
24+
use function sprintf;
25+
26+
class CodecLibrary implements Codec
27+
{
28+
use DecodeIfSupported;
29+
use EncodeIfSupported;
30+
31+
/** @var array<Decoder> */
32+
private $decoders = [];
33+
34+
/** @var array<Encoder> */
35+
private $encoders = [];
36+
37+
/** @param Decoder|Encoder $items */
38+
public function __construct(...$items)
39+
{
40+
foreach ($items as $item) {
41+
if (! $item instanceof Decoder && ! $item instanceof Encoder) {
42+
throw InvalidArgumentException::invalidType('$items', $item, [Decoder::class, Encoder::class]);
43+
}
44+
45+
if ($item instanceof Codec) {
46+
// Use attachCodec to avoid multiple calls to attachLibrary
47+
$this->attachCodec($item);
48+
49+
continue;
50+
}
51+
52+
if ($item instanceof Decoder) {
53+
$this->attachDecoder($item);
54+
}
55+
56+
if ($item instanceof Encoder) {
57+
$this->attachEncoder($item);
58+
}
59+
}
60+
}
61+
62+
/** @return static */
63+
final public function attachCodec(Codec $codec): self
64+
{
65+
$this->decoders[] = $codec;
66+
$this->encoders[] = $codec;
67+
if ($codec instanceof KnowsCodecLibrary) {
68+
$codec->attachLibrary($this);
69+
}
70+
71+
return $this;
72+
}
73+
74+
/** @return static */
75+
final public function attachDecoder(Decoder $decoder): self
76+
{
77+
$this->decoders[] = $decoder;
78+
if ($decoder instanceof KnowsCodecLibrary) {
79+
$decoder->attachLibrary($this);
80+
}
81+
82+
return $this;
83+
}
84+
85+
/** @return static */
86+
final public function attachEncoder(Encoder $encoder): self
87+
{
88+
$this->encoders[] = $encoder;
89+
if ($encoder instanceof KnowsCodecLibrary) {
90+
$encoder->attachLibrary($this);
91+
}
92+
93+
return $this;
94+
}
95+
96+
/** @param mixed $value */
97+
final public function canDecode($value): bool
98+
{
99+
foreach ($this->decoders as $decoder) {
100+
if ($decoder->canDecode($value)) {
101+
return true;
102+
}
103+
}
104+
105+
return false;
106+
}
107+
108+
/** @param mixed $value */
109+
final public function canEncode($value): bool
110+
{
111+
foreach ($this->encoders as $encoder) {
112+
if ($encoder->canEncode($value)) {
113+
return true;
114+
}
115+
}
116+
117+
return false;
118+
}
119+
120+
/**
121+
* @param mixed $value
122+
* @return mixed
123+
*/
124+
final public function decode($value)
125+
{
126+
foreach ($this->decoders as $decoder) {
127+
if ($decoder->canDecode($value)) {
128+
return $decoder->decode($value);
129+
}
130+
}
131+
132+
throw new UnexpectedValueException(sprintf('No decoder found for value of type "%s"', get_debug_type($value)));
133+
}
134+
135+
/**
136+
* @param mixed $value
137+
* @return mixed
138+
*/
139+
final public function encode($value)
140+
{
141+
foreach ($this->encoders as $encoder) {
142+
if ($encoder->canEncode($value)) {
143+
return $encoder->encode($value);
144+
}
145+
}
146+
147+
throw new UnexpectedValueException(sprintf('No encoder found for value of type "%s"', get_debug_type($value)));
148+
}
149+
}

src/Codec/DecodeIfSupported.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
/*
3+
* Copyright 2023-present MongoDB, Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace MongoDB\Codec;
19+
20+
/**
21+
* @psalm-template BSONType
22+
* @psalm-template NativeType
23+
*/
24+
trait DecodeIfSupported
25+
{
26+
/**
27+
* @param mixed $value
28+
* @psalm-assert-if-true BSONType $value
29+
*/
30+
abstract public function canDecode($value): bool;
31+
32+
/**
33+
* @param mixed $value
34+
* @psalm-param BSONType $value
35+
* @return mixed
36+
* @psalm-return NativeType
37+
*/
38+
abstract public function decode($value);
39+
40+
/**
41+
* @param mixed $value
42+
* @psalm-param mixed $value
43+
* @return mixed
44+
* @psalm-return ($value is BSONType ? NativeType : $value)
45+
*/
46+
public function decodeIfSupported($value)
47+
{
48+
return $this->canDecode($value) ? $this->decode($value) : $value;
49+
}
50+
}

src/Codec/EncodeIfSupported.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
/*
3+
* Copyright 2023-present MongoDB, Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace MongoDB\Codec;
19+
20+
/**
21+
* @psalm-template BSONType
22+
* @psalm-template NativeType
23+
*/
24+
trait EncodeIfSupported
25+
{
26+
/**
27+
* @param mixed $value
28+
* @psalm-assert-if-true NativeType $value
29+
*/
30+
abstract public function canEncode($value): bool;
31+
32+
/**
33+
* @param mixed $value
34+
* @psalm-param NativeType $value
35+
* @return mixed
36+
* @psalm-return BSONType
37+
*/
38+
abstract public function encode($value);
39+
40+
/**
41+
* @param mixed $value
42+
* @psalm-param mixed $value
43+
* @return mixed
44+
* @psalm-return ($value is NativeType ? BSONType : $value)
45+
*/
46+
public function encodeIfSupported($value)
47+
{
48+
return $this->canEncode($value) ? $this->encode($value) : $value;
49+
}
50+
}

src/Codec/KnowsCodecLibrary.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
/*
3+
* Copyright 2023-present MongoDB, Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace MongoDB\Codec;
19+
20+
interface KnowsCodecLibrary
21+
{
22+
public function attachLibrary(CodecLibrary $library): void;
23+
}

0 commit comments

Comments
 (0)