|
15 | 15 | use function explode; |
16 | 16 | use function implode; |
17 | 17 | use function in_array; |
| 18 | +use function is_array; |
18 | 19 | use function is_string; |
19 | 20 | use function json_encode; |
20 | 21 | use function sprintf; |
21 | 22 | use function str_replace; |
| 23 | +use function strlen; |
22 | 24 | use function strtolower; |
23 | 25 | use function trim; |
24 | 26 |
|
@@ -101,7 +103,7 @@ public function __construct() |
101 | 103 | return $v; |
102 | 104 | } |
103 | 105 |
|
104 | | - $types = array_map(static fn ($type) => explode(' ', trim($type))[1], explode(',', $type->params)); |
| 106 | + $types = array_map(static fn ($type) => explode(' ', trim($type))[1], $this->splitTypes($type->params)); |
105 | 107 |
|
106 | 108 | return sprintf('[%s]', implode(',', array_map( |
107 | 109 | fn (array $row) => sprintf('(%s)', implode(',', array_map( |
@@ -167,17 +169,23 @@ public function __construct() |
167 | 169 | return $this->get($innerType)($v, $innerType, true); |
168 | 170 | }, $v), |
169 | 171 | )), |
170 | | - 'Tuple' => function (array|string $v, Type $type) { |
171 | | - if (is_string($v)) { |
| 172 | + 'Tuple' => function (mixed $v, Type $type) { |
| 173 | + if (! is_array($v)) { |
172 | 174 | return $v; |
173 | 175 | } |
174 | 176 |
|
175 | | - $types = array_map(static fn ($p) => trim($p), explode(',', $type->params)); |
| 177 | + $innerTypes = $this->splitTypes($type->params); |
176 | 178 |
|
177 | | - return '(' . implode( |
| 179 | + $innerExpression = implode( |
178 | 180 | ',', |
179 | | - array_map(fn (mixed $i) => $this->get($types[$i])($v[$i], null, true), array_keys($v)), |
180 | | - ) . ')'; |
| 181 | + array_map(function (int $i) use ($innerTypes, $v) { |
| 182 | + $innerType = Type::fromString($innerTypes[$i]); |
| 183 | + |
| 184 | + return $this->get($innerType)($v[$i], $innerType, true); |
| 185 | + }, array_keys($v)), |
| 186 | + ); |
| 187 | + |
| 188 | + return '(' . $innerExpression . ')'; |
181 | 189 | }, |
182 | 190 | ]; |
183 | 191 | $this->registry = $registry; |
@@ -254,4 +262,36 @@ private static function dateIntervalConverter(): Closure |
254 | 262 | { |
255 | 263 | return static fn (int|float $v) => $v; |
256 | 264 | } |
| 265 | + |
| 266 | + /** @return list<string> */ |
| 267 | + private function splitTypes(string $types): array |
| 268 | + { |
| 269 | + $result = []; |
| 270 | + $depth = 0; |
| 271 | + $current = ''; |
| 272 | + |
| 273 | + for ($i = 0; $i < strlen($types); $i++) { |
| 274 | + $char = $types[$i]; |
| 275 | + if ($char === '(') { |
| 276 | + $depth++; |
| 277 | + } elseif ($char === ')') { |
| 278 | + $depth--; |
| 279 | + } elseif ($char === ',' && $depth === 0) { |
| 280 | + $result[] = $current; |
| 281 | + $current = ''; |
| 282 | + |
| 283 | + continue; |
| 284 | + } |
| 285 | + |
| 286 | + $current .= $char; |
| 287 | + } |
| 288 | + |
| 289 | + $current = trim($current); |
| 290 | + |
| 291 | + if ($current !== '') { |
| 292 | + $result[] = $current; |
| 293 | + } |
| 294 | + |
| 295 | + return $result; |
| 296 | + } |
257 | 297 | } |
0 commit comments