From d88ec8cd35af2c7a22b097d891ebf6525c9f3941 Mon Sep 17 00:00:00 2001 From: Aaron Piotrowski Date: Thu, 16 Jan 2020 14:12:26 -0600 Subject: [PATCH] Fix empty array parsing Closes #21. --- src/Internal/ArrayParser.php | 14 ++++++-- test/ArrayParserTest.php | 66 +++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/Internal/ArrayParser.php b/src/Internal/ArrayParser.php index fda04d2..c86dd6e 100644 --- a/src/Internal/ArrayParser.php +++ b/src/Internal/ArrayParser.php @@ -42,15 +42,23 @@ final class ArrayParser */ private function parser(string $data, callable $cast = null, string $delimiter = ','): \Generator { - if ($data[0] !== '{' || \substr($data, -1) !== '}') { - throw new ParseException("Missing opening or closing brackets"); + if ($data === '') { + throw new ParseException("Unexpected end of data"); + } + + if ($data[0] !== '{') { + throw new ParseException("Missing opening bracket"); } $data = \ltrim(\substr($data, 1)); do { if ($data === '') { - throw new ParseException("Missing closing bracket"); + throw new ParseException("Unexpected end of data"); + } + + if ($data[0] === '}') { // Empty array + return \ltrim(\substr($data, 1)); } if ($data[0] === '{') { // Array diff --git a/test/ArrayParserTest.php b/test/ArrayParserTest.php index a654a64..0f0cd48 100644 --- a/test/ArrayParserTest.php +++ b/test/ArrayParserTest.php @@ -128,15 +128,79 @@ class ArrayParserTest extends TestCase $this->assertSame($array, $this->parser->parse($string)); } + public function testEmptyArray() + { + $array = []; + $string = '{}'; + + $this->assertSame($array, $this->parser->parse($string)); + } + + public function testArrayContainingEmptyArray() + { + $array = [[], [1], []]; + $string = '{{},{1},{}}'; + + $cast = function (string $value): int { + return (int) $value; + }; + + $this->assertSame($array, $this->parser->parse($string, $cast)); + } + + public function testArrayWithEmptyString() + { + $array = ['']; + $string = '{""}'; + + $this->assertSame($array, $this->parser->parse($string)); + } + + public function testMalformedNestedArray() + { + $this->expectException(ParseException::class); + $this->expectExceptionMessage('Unexpected end of data'); + + $string = '{{}'; + $this->parser->parse($string); + } + + public function testEmptyString() + { + $this->expectException(ParseException::class); + $this->expectExceptionMessage('Unexpected end of data'); + + $string = ' '; + $this->parser->parse($string); + } + + public function testNoOpeningBracket() + { + $this->expectException(ParseException::class); + $this->expectExceptionMessage('Missing opening bracket'); + + $string = '"one", "two"}'; + $this->parser->parse($string); + } + public function testNoClosingBracket() { $this->expectException(ParseException::class); - $this->expectExceptionMessage('Missing opening or closing brackets'); + $this->expectExceptionMessage('Unexpected end of data'); $string = '{"one", "two"'; $this->parser->parse($string); } + public function testExtraClosingBracket() + { + $this->expectException(ParseException::class); + $this->expectExceptionMessage('Data left in buffer after parsing'); + + $string = '{"one", "two"}}'; + $this->parser->parse($string); + } + public function testTrailingData() { $this->expectException(ParseException::class);