Skip to content

Commit 972ba03

Browse files
authored
Merge pull request #4 from stagerightlabs/patch_for_reading_fixed_length_arrays
Fix length hangling for reading fixed length arrays
2 parents 7a63162 + f113518 commit 972ba03

File tree

4 files changed

+223
-20
lines changed

4 files changed

+223
-20
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22

33
All notable changes to `phpxdr` will be documented in this file
44

5+
## 0.0.11 - 2022-01-03
6+
7+
### Added
8+
9+
- Added more test coverage for the `XdrArray` interface methods.
10+
11+
### Changed
12+
13+
- Fixed a bug that prevented fixed length arrays from being read correctly.
14+
515
## 0.0.10 - 2022-01-03
616

717
### Changed

src/Read.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ protected function readArrayFixed(string|null $vessel, int $length = null): XdrA
367367
// Decode the array
368368
$arr = [];
369369
for ($i = 0; $i < $length; $i++) {
370-
$arr[] = $this->read($vessel::getXdrType(), $vessel::getXdrTypeLength());
370+
$arr[] = $this->read($vessel::getXdrType(), length: $vessel::getXdrTypeLength());
371371
}
372372

373373
// Return a newly instantiated vessel class
@@ -397,7 +397,7 @@ protected function readArrayVariable(string|null $vessel): XdrArray
397397
// Decode the array
398398
$arr = [];
399399
for ($i = 0; $i < $count; $i++) {
400-
$arr[] = $this->read($vessel::getXdrType(), $vessel::getXdrTypeLength());
400+
$arr[] = $this->read($vessel::getXdrType(), length: $vessel::getXdrTypeLength());
401401
}
402402

403403
// Return a newly instantiated vessel class

tests/ArrayFixedTest.php

Lines changed: 105 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,40 @@ class ArrayFixedTest extends TestCase
1212
public function it_encodes_fixed_length_arrays()
1313
{
1414
$arr = new ExampleArrayFixed([1, 2]);
15-
$bytes = XDR::fresh()->write($arr, XDR::ARRAY_FIXED)->buffer();
16-
$this->assertEquals(8, strlen($bytes));
17-
$this->assertEquals('0000000100000002', bin2hex($bytes));
15+
$buffer = XDR::fresh()->write($arr, ExampleArrayFixed::class)->buffer();
16+
$this->assertEquals('0000000100000002', bin2hex($buffer));
1817
}
1918

2019
/** @test */
2120
public function it_accepts_a_fixed_array_instance_class_name_as_a_type_parameter()
2221
{
2322
$arr = new ExampleArrayFixed([1, 2]);
24-
$bytes = XDR::fresh()->write($arr, ExampleArrayFixed::class)->buffer();
25-
$this->assertEquals(8, strlen($bytes));
26-
$this->assertEquals('0000000100000002', bin2hex($bytes));
23+
$buffer = XDR::fresh()->write($arr, ExampleArrayFixed::class)->buffer();
24+
$this->assertEquals('0000000100000002', bin2hex($buffer));
2725
}
2826

2927
/** @test */
3028
public function it_encodes_fixed_length_arrays_using_the_shorter_syntax()
3129
{
3230
$arr = new ExampleArrayFixed([1, 2]);
33-
$bytes = XDR::fresh()->write($arr)->buffer();
34-
$this->assertEquals(8, strlen($bytes));
35-
$this->assertEquals('0000000100000002', bin2hex($bytes));
31+
$buffer = XDR::fresh()->write($arr)->buffer();
32+
$this->assertEquals('0000000100000002', bin2hex($buffer));
33+
}
34+
35+
/** @test */
36+
public function it_encodes_fixed_length_arrays_with_values_of_different_lengths()
37+
{
38+
$arr = new ExampleFixedStringArray(['one', 'two', 'three']);
39+
$buffer = XDR::fresh()->write($arr, ExampleFixedStringArray::class)->buffer();
40+
$this->assertEquals('000000036f6e65000000000374776f00000000057468726565000000', bin2hex($buffer));
41+
}
42+
43+
/** @test */
44+
public function it_encodes_fixed_length_arrays_containing_values_with_a_fixed_length()
45+
{
46+
$arr = new ExampleFixedOpaqueFixedArray(['abc', 'def', 'ghi']);
47+
$buffer = XDR::fresh()->write($arr, ExampleFixedOpaqueFixedArray::class)->buffer();
48+
$this->assertEquals('616263006465660067686900', bin2hex($buffer));
3649
}
3750

3851
/** @test */
@@ -50,6 +63,23 @@ public function it_decodes_fixed_length_arrays_from_bytes_using_the_shorter_synt
5063
$this->assertInstanceOf(ExampleArrayFixed::class, $arr);
5164
$this->assertEquals([3, 4], $arr->arr);
5265
}
66+
67+
/** @test */
68+
public function it_decodes_fixed_length_arrays_containing_values_of_different_lengths()
69+
{
70+
$arr = XDR::fromHex('000000036f6e65000000000374776f00000000057468726565000000')
71+
->read(ExampleFixedStringArray::class);
72+
$this->assertInstanceOf(ExampleFixedStringArray::class, $arr);
73+
$this->assertEquals(['one', 'two', 'three'], $arr->arr);
74+
}
75+
76+
/** @test */
77+
public function it_decodes_fixed_length_arrays_containing_values_with_a_fixed_length()
78+
{
79+
$arr = XDR::fromHex('616263006465660067686900')->read(ExampleFixedOpaqueFixedArray::class);
80+
$this->assertInstanceOf(ExampleFixedOpaqueFixedArray::class, $arr);
81+
$this->assertEquals(['abc', 'def', 'ghi'], $arr->arr);
82+
}
5383
}
5484

5585
class ExampleArrayFixed implements XdrArray
@@ -84,3 +114,69 @@ public static function newFromXdr(array $arr): static
84114
return new static($arr);
85115
}
86116
}
117+
118+
class ExampleFixedStringArray implements XdrArray
119+
{
120+
public function __construct(public array $arr = [])
121+
{
122+
$this->arr = $arr;
123+
}
124+
125+
public function getXdrArray(): array
126+
{
127+
return $this->arr;
128+
}
129+
130+
public static function getXdrLength(): ?int
131+
{
132+
return 3;
133+
}
134+
135+
public static function getXdrType(): string
136+
{
137+
return XDR::STRING;
138+
}
139+
140+
public static function getXdrTypeLength(): ?int
141+
{
142+
return null;
143+
}
144+
145+
public static function newFromXdr(array $arr): static
146+
{
147+
return new static($arr);
148+
}
149+
}
150+
151+
class ExampleFixedOpaqueFixedArray implements XdrArray
152+
{
153+
public function __construct(public array $arr)
154+
{
155+
$this->arr = $arr;
156+
}
157+
158+
public function getXdrArray(): array
159+
{
160+
return $this->arr;
161+
}
162+
163+
public static function getXdrLength(): ?int
164+
{
165+
return 3;
166+
}
167+
168+
public static function getXdrType(): string
169+
{
170+
return XDR::OPAQUE_FIXED;
171+
}
172+
173+
public static function getXdrTypeLength(): ?int
174+
{
175+
return 3;
176+
}
177+
178+
public static function newFromXdr(array $arr): static
179+
{
180+
return new static($arr);
181+
}
182+
}

tests/ArrayVariableTest.php

Lines changed: 106 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,40 @@ class ArrayVariableTest extends TestCase
1212
public function it_encodes_variable_length_arrays()
1313
{
1414
$arr = new ExampleArrayVariable([1, 2]);
15-
$bytes = XDR::fresh()->write($arr, XDR::ARRAY_VARIABLE)->buffer();
16-
$this->assertEquals(12, strlen($bytes));
17-
$this->assertEquals('000000020000000100000002', bin2hex($bytes));
15+
$buffer = XDR::fresh()->write($arr, ExampleArrayVariable::class)->buffer();
16+
$this->assertEquals('000000020000000100000002', bin2hex($buffer));
1817
}
1918

2019
/** @test */
2120
public function it_encodes_variable_length_arrays_using_the_shorter_syntax()
2221
{
2322
$arr = new ExampleArrayVariable([1, 2]);
24-
$bytes = XDR::fresh()->write($arr, XDR::ARRAY_VARIABLE)->buffer();
25-
$this->assertEquals(12, strlen($bytes));
26-
$this->assertEquals('000000020000000100000002', bin2hex($bytes));
23+
$buffer = XDR::fresh()->write($arr)->buffer();
24+
$this->assertEquals('000000020000000100000002', bin2hex($buffer));
25+
}
26+
27+
/** @test */
28+
public function it_encodes_variable_length_arrays_containing_values_of_different_lengths()
29+
{
30+
$arr = new ExampleVariableStringArray(['one', 'two', 'three']);
31+
$buffer = XDR::fresh()->write($arr, ExampleVariableStringArray::class)->buffer();
32+
$this->assertEquals('00000003000000036f6e65000000000374776f00000000057468726565000000', bin2hex($buffer));
33+
}
34+
35+
/** @test */
36+
public function it_encodes_variable_length_arrays_containing_data_with_a_fixed_length()
37+
{
38+
$arr = new ExampleVariableOpaqueFixedArray(['abc', 'def', 'ghi']);
39+
$buffer = XDR::fresh()->write($arr, ExampleVariableOpaqueFixedArray::class)->buffer();
40+
$this->assertEquals('00000003616263006465660067686900', bin2hex($buffer));
2741
}
2842

2943
/** @test */
3044
public function it_accepts_a_variable_array_instance_class_name_as_a_type_parameter()
3145
{
3246
$arr = new ExampleArrayVariable([1, 2]);
33-
$bytes = XDR::fresh()->write($arr, ExampleArrayVariable::class)->buffer();
34-
$this->assertEquals(12, strlen($bytes));
35-
$this->assertEquals('000000020000000100000002', bin2hex($bytes));
47+
$buffer = XDR::fresh()->write($arr, ExampleArrayVariable::class)->buffer();
48+
$this->assertEquals('000000020000000100000002', bin2hex($buffer));
3649
}
3750

3851
/** @test */
@@ -50,6 +63,24 @@ public function it_decodes_variable_length_arrays_using_the_shorter_syntax()
5063
$this->assertInstanceOf(ExampleArrayVariable::class, $arr);
5164
$this->assertEquals([1, 2], $arr->arr);
5265
}
66+
67+
/** @test */
68+
public function it_decodes_variable_length_arrays_containing_values_of_different_lengths()
69+
{
70+
$arr = XDR::fromHex('00000003000000036f6e65000000000374776f00000000057468726565000000')
71+
->read(XDR::ARRAY_VARIABLE, ExampleVariableStringArray::class);
72+
$this->assertInstanceOf(ExampleVariableStringArray::class, $arr);
73+
$this->assertEquals(['one', 'two', 'three'], $arr->arr);
74+
}
75+
76+
/** @test */
77+
public function it_decodes_variable_length_arrays_containing_values_with_a_fixed_length()
78+
{
79+
$arr = XDR::fromHex('00000003616263006465660067686900')
80+
->read(XDR::ARRAY_VARIABLE, ExampleVariableOpaqueFixedArray::class);
81+
$this->assertInstanceOf(ExampleVariableOpaqueFixedArray::class, $arr);
82+
$this->assertEquals(['abc', 'def', 'ghi'], $arr->arr);
83+
}
5384
}
5485

5586
class ExampleArrayVariable implements XdrArray
@@ -84,3 +115,69 @@ public static function newFromXdr(array $arr): static
84115
return new static($arr);
85116
}
86117
}
118+
119+
class ExampleVariableStringArray implements XdrArray
120+
{
121+
public function __construct(public array $arr = [])
122+
{
123+
$this->arr = $arr;
124+
}
125+
126+
public function getXdrArray(): array
127+
{
128+
return $this->arr;
129+
}
130+
131+
public static function getXdrLength(): ?int
132+
{
133+
return null;
134+
}
135+
136+
public static function getXdrType(): string
137+
{
138+
return XDR::STRING;
139+
}
140+
141+
public static function getXdrTypeLength(): ?int
142+
{
143+
return null;
144+
}
145+
146+
public static function newFromXdr(array $arr): static
147+
{
148+
return new static($arr);
149+
}
150+
}
151+
152+
class ExampleVariableOpaqueFixedArray implements XdrArray
153+
{
154+
public function __construct(public array $arr)
155+
{
156+
$this->arr = $arr;
157+
}
158+
159+
public function getXdrArray(): array
160+
{
161+
return $this->arr;
162+
}
163+
164+
public static function getXdrLength(): ?int
165+
{
166+
return null;
167+
}
168+
169+
public static function getXdrType(): string
170+
{
171+
return XDR::OPAQUE_FIXED;
172+
}
173+
174+
public static function getXdrTypeLength(): ?int
175+
{
176+
return 3;
177+
}
178+
179+
public static function newFromXdr(array $arr): static
180+
{
181+
return new static($arr);
182+
}
183+
}

0 commit comments

Comments
 (0)