Created
September 19, 2018 21:39
-
-
Save lizmat/0454f034b9336673cea4fb31927ca164 to your computer and use it in GitHub Desktop.
A faster JSON parser, with limited capabilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
my $meta = "META6.json".IO.slurp; | |
my $old = Rakudo::Internals::JSON.new.from-json($meta); | |
use Test; | |
use MONKEY; | |
augment class Rakudo::Internals::JSON { | |
sub parse(\item,\iterator) { | |
item.starts-with('{') | |
?? parse-hash(iterator) | |
!! item.starts-with('[') | |
?? parse-array(iterator) | |
!! item.starts-with('"') | |
?? parse-string(item,iterator) | |
!! die | |
} | |
sub parse-hash(\iterator) { | |
my %hash; | |
nqp::until( | |
nqp::eqaddr((my \item := iterator.pull-one),IterationEnd), | |
nqp::if( | |
item eq '}' || item eq '},', | |
(return %hash), # done | |
nqp::stmts( | |
nqp::if( | |
item.starts-with('"'), | |
(my $key = parse-string(item,iterator)), | |
die | |
), | |
nqp::if( | |
iterator.pull-one ne ':', | |
die, | |
%hash.push: $key, parse(iterator.pull-one,iterator) | |
) | |
) | |
) | |
); | |
die # should return with valid otherwise | |
} | |
sub parse-array(\iterator) { | |
my @array; | |
nqp::until( | |
nqp::eqaddr((my \item = iterator.pull-one),IterationEnd), | |
nqp::if( | |
item eq ']' || item eq '],', | |
(return @array), | |
@array.push: parse(item,iterator) | |
) | |
); | |
die # should return with valid otherwise | |
} | |
sub parse-string(\item, \iterator) { | |
nqp::if( | |
item.ends-with('"'), | |
item.substr(1,*-1), | |
nqp::if( | |
item.ends-with('",'), | |
item.substr(1,*-2), | |
nqp::stmts( | |
(my str @parts = item.substr(1)), | |
nqp::until( | |
nqp::eqaddr((my \part = iterator.pull-one),IterationEnd), | |
nqp::if( | |
part.ends-with('"'), | |
nqp::stmts( | |
@parts.push(part.substr(0,*-1)), | |
return @parts.join(" ") | |
), | |
nqp::if( | |
part.ends-with('",'), | |
nqp::stmts( | |
@parts.push(part.substr(0,*-2)), | |
return @parts.join(" ") | |
), | |
@parts.push(part) | |
) | |
) | |
), | |
die # should return with valid otherwise | |
) | |
) | |
) | |
} | |
method quick-from-json($text) { | |
CATCH { return Nil } | |
my \iterator = $text.words.iterator; | |
parse(iterator.pull-one, iterator) | |
} | |
} | |
my $new = Rakudo::Internals::JSON.new.quick-from-json($meta); | |
is-deeply $new, $old; | |
my \then = now; | |
Rakudo::Internals::JSON.new.quick-from-json($meta) for ^1000; | |
say now - then; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
any type of fallback will essentially make the speed improvement non-existent in the case of zef because it has to parse entire ecosystems worth of data (not pick/choose individual META6.json) where there will almost certainly be at least one case of $some-non-happy-path-content