33
33
* @internal Do not use directly this class as it's behaviour and return type
34
34
* MAY change significantly even during a major release cycle.
35
35
*
36
- * @phpstan-import-type SfType from StructuredFieldProvider
36
+ * @phpstan-type SfValue Bytes|Token|DisplayString|DateTimeImmutable|string|int|float|bool
37
+ * @phpstan-type SfParameter array<array{0:string, 1:SfValue}>
38
+ * @phpstan-type SfItem array{0:SfValue, 1: SfParameter}
39
+ * @phpstan-type SfInnerList array{0:array<SfItem>, 1: SfParameter}
37
40
*/
38
41
final class Parser
39
42
{
40
- private const REGEXP_BYTE_SEQUENCE = '/^(?<sequence>:(?<byte>[a-z\d+\/=]*):)/i ' ;
43
+ private const REGEXP_BYTES = '/^(?<sequence>:(?<byte>[a-z\d+\/=]*):)/i ' ;
41
44
private const REGEXP_BOOLEAN = '/^\?[01]/ ' ;
42
45
private const REGEXP_DATE = '/^@(?<date>-?\d{1,15})(?:[^\d.]|$)/ ' ;
43
46
private const REGEXP_DECIMAL = '/^-?\d{1,12}\.\d{1,3}$/ ' ;
@@ -59,36 +62,14 @@ public function __construct(private readonly Ietf $rfc)
59
62
}
60
63
61
64
/**
62
- * Returns the data type value represented as a PHP type from an HTTP textual representation.
65
+ * Returns an Item as a PHP list array from an HTTP textual representation.
63
66
*
64
- * @see https://www.rfc-editor.org/rfc/rfc9651.html#section-4.2.4
65
- * @see https://www.rfc-editor.org/rfc/rfc9651.html#section-4.2.5
66
- * @see https://www.rfc-editor.org/rfc/rfc9651.html#section-4.2.6
67
- * @see https://www.rfc-editor.org/rfc/rfc9651.html#section-4.2.7
68
- * @see https://www.rfc-editor.org/rfc/rfc9651.html#section-4.2.8
67
+ * @see https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-an-item
69
68
*
70
- * @throws Exception|SyntaxError
71
- */
72
- public function parseValue (Stringable |string $ httpValue ): Bytes |Token |DisplayString |DateTimeImmutable |string |int |float |bool
73
- {
74
- $ remainder = trim ((string ) $ httpValue , ' ' );
75
- if ('' === $ remainder || 1 === preg_match (self ::REGEXP_INVALID_CHARACTERS , $ remainder )) {
76
- throw new SyntaxError ("The HTTP textual representation \"$ httpValue \" for an item value contains invalid characters. " );
77
- }
78
-
79
- [$ value , $ offset ] = $ this ->extractValue ($ remainder );
80
- if ('' !== substr ($ remainder , $ offset )) {
81
- throw new SyntaxError ("The HTTP textual representation \"$ httpValue \" for an item value contains invalid characters. " );
82
- }
83
-
84
- return $ value ;
85
- }
86
-
87
- /**
88
69
*
89
70
* @throws Exception|SyntaxError
90
71
*
91
- * @return array{0:SfType, 1:array<string, SfType>}
72
+ * @return SfItem
92
73
*/
93
74
public function parseItem (Stringable |string $ httpValue ): array
94
75
{
@@ -103,17 +84,17 @@ public function parseItem(Stringable|string $httpValue): array
103
84
throw new SyntaxError ("The HTTP textual representation \"$ httpValue \" for an item contains invalid characters. " );
104
85
}
105
86
106
- return [$ value , $ this ->parseParameters ($ remainder )];
87
+ return [$ value , $ this ->parseParameters ($ remainder )]; /* @phpstan-ignore-line */
107
88
}
108
89
109
90
/**
110
- * Returns an instance from an HTTP textual representation.
91
+ * Returns a Parameters ordered map container as a PHP list array from an HTTP textual representation.
111
92
*
112
93
* @see https://www.rfc-editor.org/rfc/rfc9651.html#section-3.1.2
113
94
*
114
95
* @throws SyntaxError|Exception
115
96
*
116
- * @return array<string, SfType >
97
+ * @return array<SfParameter >
117
98
*/
118
99
public function parseParameters (Stringable |string $ httpValue ): array
119
100
{
@@ -123,7 +104,7 @@ public function parseParameters(Stringable|string $httpValue): array
123
104
throw new SyntaxError ("The HTTP textual representation \"$ httpValue \" for Parameters contains invalid characters. " );
124
105
}
125
106
126
- return $ parameters ;
107
+ return $ parameters ; /* @phpstan-ignore-line */
127
108
}
128
109
129
110
/**
@@ -133,7 +114,7 @@ public function parseParameters(Stringable|string $httpValue): array
133
114
*
134
115
* @throws SyntaxError|Exception
135
116
*
136
- * @return array<array{0:SfType|array<array{0:SfType, 1:array<string, SfType>}>, 1:array<string, SfType>} >
117
+ * @return array<SfInnerList|SfItem >
137
118
*/
138
119
public function parseList (Stringable |string $ httpValue ): array
139
120
{
@@ -148,13 +129,13 @@ public function parseList(Stringable|string $httpValue): array
148
129
}
149
130
150
131
/**
151
- * Returns an ordered map represented as a PHP associative array from an HTTP textual representation.
132
+ * Returns a Dictionary represented as a PHP list array from an HTTP textual representation.
152
133
*
153
134
* @see https://www.rfc-editor.org/rfc/rfc9651.html#section-4.2.2
154
135
*
155
136
* @throws SyntaxError|Exception
156
137
*
157
- * @return array<string, array{0:SfType|array<array{0:SfType, 1:array< string, SfType>}>, 1:array<string, SfType> }>
138
+ * @return array<array{0:string, 1:SfInnerList|SfItem }>
158
139
*/
159
140
public function parseDictionary (Stringable |string $ httpValue ): array
160
141
{
@@ -166,9 +147,11 @@ public function parseDictionary(Stringable|string $httpValue): array
166
147
if ('' === $ remainder || '= ' !== $ remainder [0 ]) {
167
148
$ remainder = '=?1 ' .$ remainder ;
168
149
}
150
+ $ member = [$ name ];
169
151
170
- [$ map [ $ name ], $ offset ] = $ this ->extractItemOrInnerList (substr ($ remainder , 1 ));
152
+ [$ member [ 1 ], $ offset ] = $ this ->extractItemOrInnerList (substr ($ remainder , 1 ));
171
153
$ remainder = self ::removeCommaSeparatedWhiteSpaces ($ remainder , ++$ offset );
154
+ $ map [] = $ member ;
172
155
}
173
156
174
157
return $ map ;
@@ -181,7 +164,7 @@ public function parseDictionary(Stringable|string $httpValue): array
181
164
*
182
165
* @throws SyntaxError|Exception
183
166
*
184
- * @return array{0:array<array{0:SfType, 1:array<string, SfType>}>, 1:array<string, SfType>}
167
+ * @return SfInnerList
185
168
*/
186
169
public function parseInnerList (Stringable |string $ httpValue ): array
187
170
{
@@ -241,7 +224,7 @@ private static function removeOptionalWhiteSpaces(string $httpValue): string
241
224
*
242
225
* @throws SyntaxError|Exception
243
226
*
244
- * @return array{0:array{0:SfType|array<array{0:SfType, 1:array<string, SfType>}>, 1:array<string, SfType>} , 1:int}
227
+ * @return array{0: SfInnerList|SfItem , 1:int}
245
228
*/
246
229
private function extractItemOrInnerList (string $ httpValue ): array
247
230
{
@@ -261,7 +244,7 @@ private function extractItemOrInnerList(string $httpValue): array
261
244
*
262
245
* @throws SyntaxError|Exception
263
246
*
264
- * @return array{0:array{0:array<array{0:SfType, 1:array<string, SfType>}>, 1:array<string, SfType>}, 1 :int}
247
+ * @return array{0: SfInnerList, 1 :int}
265
248
*/
266
249
private function extractInnerList (string $ httpValue ): array
267
250
{
@@ -293,7 +276,7 @@ private function extractInnerList(string $httpValue): array
293
276
*
294
277
* @throws SyntaxError|Exception
295
278
*
296
- * @return array{0:array{0:SfType, 1:array<string, SfType>} , 1:string}
279
+ * @return array{0:SfItem , 1:string}
297
280
*/
298
281
private function extractItem (string $ remainder ): array
299
282
{
@@ -311,13 +294,13 @@ private function extractItem(string $remainder): array
311
294
*
312
295
* @throws SyntaxError|Exception
313
296
*
314
- * @return array{0:SfType , 1:int}
297
+ * @return array{0:SfValue , 1:int}
315
298
*/
316
299
private function extractValue (string $ httpValue ): array
317
300
{
318
301
return match (true ) {
319
302
'" ' === $ httpValue [0 ] => self ::extractString ($ httpValue ),
320
- ': ' === $ httpValue [0 ] => self ::extractByteSequence ($ httpValue ),
303
+ ': ' === $ httpValue [0 ] => self ::extractBytes ($ httpValue ),
321
304
'? ' === $ httpValue [0 ] => self ::extractBoolean ($ httpValue ),
322
305
'@ ' === $ httpValue [0 ] => self ::extractDate ($ httpValue , $ this ->rfc ),
323
306
str_starts_with ($ httpValue , '%" ' ) => self ::extractDisplayString ($ httpValue , $ this ->rfc ),
@@ -334,7 +317,7 @@ private function extractValue(string $httpValue): array
334
317
*
335
318
* @throws SyntaxError|Exception
336
319
*
337
- * @return array{0:array<string, SfType> , 1:int}
320
+ * @return array{0:SfParameter , 1:int}
338
321
*/
339
322
private function extractParametersValues (Stringable |string $ httpValue ): array
340
323
{
@@ -344,13 +327,15 @@ private function extractParametersValues(Stringable|string $httpValue): array
344
327
while ('' !== $ remainder && '; ' === $ remainder [0 ]) {
345
328
$ remainder = ltrim (substr ($ remainder , 1 ), ' ' );
346
329
$ name = MapKey::fromStringBeginning ($ remainder )->value ;
347
- $ map [$ name] = true ;
330
+ $ member = [$ name, true ] ;
348
331
$ remainder = substr ($ remainder , strlen ($ name ));
349
332
if ('' !== $ remainder && '= ' === $ remainder [0 ]) {
350
333
$ remainder = substr ($ remainder , 1 );
351
- [$ map [ $ name ], $ offset ] = $ this ->extractValue ($ remainder );
334
+ [$ member [ 1 ], $ offset ] = $ this ->extractValue ($ remainder );
352
335
$ remainder = substr ($ remainder , $ offset );
353
336
}
337
+
338
+ $ map [] = $ member ;
354
339
}
355
340
356
341
return [$ map , strlen ($ httpValue ) - strlen ($ remainder )];
@@ -519,7 +504,7 @@ private static function extractToken(string $httpValue): array
519
504
{
520
505
preg_match (self ::REGEXP_TOKEN , $ httpValue , $ found );
521
506
522
- $ token = $ found ['token ' ] ?? '' ;
507
+ $ token = $ found ['token ' ] ?? throw new SyntaxError ( " The HTTP textual representation \" $ httpValue \" for a Token contains invalid characters. " ) ;
523
508
524
509
return [Token::fromString ($ token ), strlen ($ token )];
525
510
}
@@ -531,9 +516,9 @@ private static function extractToken(string $httpValue): array
531
516
*
532
517
* @return array{0:Bytes, 1:int}
533
518
*/
534
- private static function extractByteSequence (string $ httpValue ): array
519
+ private static function extractBytes (string $ httpValue ): array
535
520
{
536
- if (1 !== preg_match (self ::REGEXP_BYTE_SEQUENCE , $ httpValue , $ matches )) {
521
+ if (1 !== preg_match (self ::REGEXP_BYTES , $ httpValue , $ matches )) {
537
522
throw new SyntaxError ("The HTTP textual representation \"$ httpValue \" for a Byte Sequence contains invalid characters. " );
538
523
}
539
524
0 commit comments