Skip to content

Commit 28ca64d

Browse files
committed
feat(CBOR): Implement decode method for TextString and improve test suite
1 parent 3957912 commit 28ca64d

File tree

2 files changed

+72
-12
lines changed

2 files changed

+72
-12
lines changed

src/CBOR/MajorTypes/TextString.php

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,40 @@ public static function encode(string $input): string
3434

3535
public static function decode(string $input): string
3636
{
37-
// TODO
37+
$initialByte = ord($input[0]);
38+
$majorType = ($initialByte >> 5) & 0x07;
39+
40+
if ($majorType !== 0x03) {
41+
throw new \ValueError('Invalid CBOR TextString major type.');
42+
}
43+
44+
$additionalInfo = $initialByte & 0x1F;
45+
$offset = 1;
46+
47+
if ($additionalInfo <= 23) {
48+
$length = $additionalInfo;
49+
} elseif ($additionalInfo === 24) {
50+
$length = ord($input[$offset]);
51+
$offset += 1;
52+
} elseif ($additionalInfo === 25) {
53+
$length = unpack('n', substr($input, $offset, 2))[1];
54+
$offset += 2;
55+
} elseif ($additionalInfo === 26) {
56+
$length = unpack('N', substr($input, $offset, 4))[1];
57+
$offset += 4;
58+
} elseif ($additionalInfo === 27) {
59+
$length = unpack('J', substr($input, $offset, 8))[1];
60+
$offset += 8;
61+
} else {
62+
throw new \ValueError('Invalid CBOR TextString length information.');
63+
}
64+
65+
$text = substr($input, $offset, $length);
66+
67+
if (strlen($text) !== $length) {
68+
throw new \ValueError('Invalid CBOR TextString length mismatch.');
69+
}
70+
71+
return $text;
3872
}
39-
}
73+
}

tests/Unit/CBOR/MajorTypes/TextStringTest.php

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,27 @@
1717

1818
class TextStringTest extends TestCase
1919
{
20-
#[DataProvider('provideCases')]
21-
public function testItCanEncodeCorrectly(string $case, string $header): void
20+
#[DataProvider('provideValidCases')]
21+
public function testEncodeProducesCorrectCBORRepresentation(string $input, string $expectedHeader): void
2222
{
23-
$actual = bin2hex(TextString::encode($case));
24-
$expected = bin2hex($header . $case);
23+
$actual = bin2hex(TextString::encode($input));
24+
$expected = bin2hex($expectedHeader . $input);
2525

2626
$this->assertSame($expected, $actual);
2727
}
2828

29-
#[DataProvider('provideCases')]
30-
public function testItCanDecodeCorrectly(string $case, string $header): void
29+
#[DataProvider('provideValidCases')]
30+
public function testDecodeExtractsOriginalStringFromCBORRepresentation(string $input, string $header): void
3131
{
32-
$target = $header . $case;
32+
$encoded = $header . $input;
3333

34-
$actual = TextString::decode($target);
35-
$expected = $case;
34+
$actual = TextString::decode($encoded);
35+
$expected = $input;
3636

3737
$this->assertSame($expected, $actual);
3838
}
3939

40-
public static function provideCases(): array
40+
public static function provideValidCases(): array
4141
{
4242
return [
4343
["f", "\x61"],
@@ -54,4 +54,30 @@ public static function provideCases(): array
5454
]
5555
];
5656
}
57+
58+
public function testDecodeThrowsExceptionForInvalidMajorType(): void
59+
{
60+
$this->expectException(\ValueError::class);
61+
$this->expectExceptionMessage("Invalid CBOR TextString major type.");
62+
63+
TextString::decode("\x0C");
64+
}
65+
66+
public function testDecodeThrowsExceptionForLengthMismatch(): void
67+
{
68+
$this->expectException(\ValueError::class);
69+
$this->expectExceptionMessage("Invalid CBOR TextString length mismatch.");
70+
71+
// Encoded length is 5, but actual length is 4
72+
TextString::decode("\x65\x66\x6F\x6F\x62");
73+
}
74+
75+
public function testDecodeThrowsExceptionForInvalidAdditionalInformation(): void
76+
{
77+
$this->expectException(\ValueError::class);
78+
$this->expectExceptionMessage("Invalid CBOR TextString length information.");
79+
80+
// Additional info 28 is invalid for text strings
81+
TextString::decode("\x7C\x01");
82+
}
5783
}

0 commit comments

Comments
 (0)