Skip to content

Commit e695287

Browse files
committed
More performant ObjectEncoder
1 parent f498276 commit e695287

File tree

1 file changed

+40
-59
lines changed

1 file changed

+40
-59
lines changed

src/Encoder/ObjectEncoder.php

Lines changed: 40 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace Soap\Encoding\Encoder;
55

66
use Closure;
7+
use Exception;
78
use Soap\Encoding\Normalizer\PhpPropertyNameNormalizer;
89
use Soap\Encoding\TypeInference\ComplexTypeBuilder;
910
use Soap\Encoding\TypeInference\XsiTypeDetector;
@@ -13,7 +14,7 @@
1314
use Soap\Encoding\Xml\Writer\XsdTypeXmlElementWriter;
1415
use Soap\Encoding\Xml\Writer\XsiAttributeBuilder;
1516
use Soap\Engine\Metadata\Model\Property;
16-
use Soap\Engine\Metadata\Model\XsdType;
17+
use Soap\Engine\Metadata\Model\TypeMeta;
1718
use VeeWee\Reflecta\Iso\Iso;
1819
use VeeWee\Reflecta\Lens\Lens;
1920
use function is_array;
@@ -100,30 +101,27 @@ private function to(Context $context, array $properties, object|array $data): st
100101
$properties,
101102
function (Property $property) use ($context, $data, $defaultAction) : Closure {
102103
$type = $property->getType();
103-
$lens = $this->decorateLensForType(
104+
$meta = $type->getMeta();
105+
$isAttribute = $meta->isAttribute()->unwrapOr(false);
106+
107+
/** @var mixed $value */
108+
$value = $this->runLens(
104109
property(PhpPropertyNameNormalizer::normalize($property->getName())),
105-
$type
110+
$meta,
111+
$data,
112+
null
106113
);
107-
/**
108-
* @psalm-var mixed $value
109-
* @psalm-suppress PossiblyInvalidArgument - Psalm gets lost in the lens.
110-
*/
111-
$value = $lens
112-
->tryGet($data)
113-
->catch(static fn () => null)
114-
->getResult();
115-
116-
return $this->handleProperty(
117-
$property,
118-
onAttribute: fn (): Closure => $value ? (new AttributeBuilder(
114+
115+
return match(true) {
116+
$isAttribute => $value ? (new AttributeBuilder(
119117
$type,
120118
$this->grabIsoForProperty($context, $property)->to($value)
121119
))(...) : $defaultAction,
122-
onValue: fn (): Closure => $value
120+
$property->getName() === '_' => $value
123121
? buildValue($this->grabIsoForProperty($context, $property)->to($value))
124122
: (new NilAttributeBuilder())(...),
125-
onElements: fn (): Closure => $value ? raw($this->grabIsoForProperty($context, $property)->to($value)) : $defaultAction,
126-
);
123+
default => $value ? raw($this->grabIsoForProperty($context, $property)->to($value)) : $defaultAction
124+
};
127125
}
128126
)
129127
]
@@ -149,23 +147,21 @@ private function from(Context $context, array $properties, string $data): object
149147
function (Property $property) use ($context, $nodes): mixed {
150148
$type = $property->getType();
151149
$meta = $type->getMeta();
152-
$isList = $meta->isList()->unwrapOr(false);
153-
/** @psalm-var string|null $value */
154-
$value = $this->decorateLensForType(
150+
151+
/** @var string|null $value */
152+
$value = $this->runLens(
155153
index($property->getName()),
156-
$type
157-
)
158-
->tryGet($nodes)
159-
->catch(static fn () => null)
160-
->getResult();
161-
$defaultValue = $isList ? [] : null;
162-
163-
return $this->handleProperty(
164-
$property,
165-
onAttribute: fn (): mixed => /** @psalm-suppress PossiblyNullArgument */$this->grabIsoForProperty($context, $property)->from($value),
166-
onValue: fn (): mixed => $value !== null ? $this->grabIsoForProperty($context, $property)->from($value) : $defaultValue,
167-
onElements: fn (): mixed => $value !== null ? $this->grabIsoForProperty($context, $property)->from($value) : $defaultValue,
154+
$meta,
155+
$nodes,
156+
null
168157
);
158+
$defaultValue = $meta->isList()->unwrapOr(false) ? [] : null;
159+
160+
/** @psalm-suppress PossiblyNullArgument */
161+
return match(true) {
162+
$meta->isAttribute()->unwrapOr(false) => $this->grabIsoForProperty($context, $property)->from($value),
163+
default => $value !== null ? $this->grabIsoForProperty($context, $property)->from($value) : $defaultValue,
164+
};
169165
},
170166
static fn (Property $property) => PhpPropertyNameNormalizer::normalize($property->getName()),
171167
)
@@ -183,27 +179,14 @@ private function grabIsoForProperty(Context $context, Property $property): Iso
183179
return $encoder->iso($propertyContext);
184180
}
185181

186-
/**
187-
* @template X
188-
*
189-
* @param Closure(): X $onAttribute
190-
* @param Closure(): X $onValue
191-
* @param Closure(): X $onElements
192-
* @return X
193-
*/
194-
private function handleProperty(
195-
Property $property,
196-
Closure $onAttribute,
197-
Closure $onValue,
198-
Closure $onElements,
199-
) {
200-
$meta = $property->getType()->getMeta();
201-
202-
return match(true) {
203-
$meta->isAttribute()->unwrapOr(false) => $onAttribute(),
204-
$property->getName() === '_' => $onValue(),
205-
default => $onElements()
206-
};
182+
private function runLens(Lens $lens, TypeMeta $meta, mixed $data, mixed $default): mixed
183+
{
184+
try {
185+
/** @var mixed */
186+
return $this->decorateLensForType($lens, $meta)->get($data);
187+
} catch (Exception $e) {
188+
return $default;
189+
}
207190
}
208191

209192
/**
@@ -214,9 +197,8 @@ private function handleProperty(
214197
*
215198
* @return Lens<S, A>
216199
*/
217-
private function decorateLensForType(Lens $lens, XsdType $type): Lens
200+
private function decorateLensForType(Lens $lens, TypeMeta $meta): Lens
218201
{
219-
$meta = $type->getMeta();
220202
if ($meta->isNullable()->unwrapOr(false)) {
221203
return optional($lens);
222204
}
@@ -237,14 +219,13 @@ private function decorateLensForType(Lens $lens, XsdType $type): Lens
237219
private function detectProperties(Context $context): array
238220
{
239221
$type = (new ComplexTypeBuilder())($context);
240-
$properties = reindex(
222+
223+
return reindex(
241224
sort_by(
242225
$type->getProperties(),
243226
static fn (Property $property): bool => !$property->getType()->getMeta()->isAttribute()->unwrapOr(false),
244227
),
245228
static fn (Property $property): string => $property->getName(),
246229
);
247-
248-
return $properties;
249230
}
250231
}

0 commit comments

Comments
 (0)