From 1bd1dff6d449ab221e191679fd8ec516b7cc1d4e Mon Sep 17 00:00:00 2001 From: Patrick Spek Date: Mon, 8 Apr 2019 19:30:35 +0200 Subject: Initial commit --- lib/URL.pm6 | 126 ++++++++++++++++++++++++++++++++++++++++++++ lib/URL/Grammar.pm6 | 48 +++++++++++++++++ lib/URL/Grammar/Actions.pm6 | 47 +++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 lib/URL.pm6 create mode 100644 lib/URL/Grammar.pm6 create mode 100644 lib/URL/Grammar/Actions.pm6 (limited to 'lib') diff --git a/lib/URL.pm6 b/lib/URL.pm6 new file mode 100644 index 0000000..57235b4 --- /dev/null +++ b/lib/URL.pm6 @@ -0,0 +1,126 @@ +#! /usr/bin/env false + +use v6.d; + +use URL::Grammar; +use URL::Grammar::Actions; + +unit class URL; + +has Str $.scheme; +has Str $.username; +has Str $.password; +has Str $.hostname; +has Int $.port; +has @.path; +has %.query; +has Str $.fragment; + +multi method new ( + Str:D $url, +) { + my %match = URL::Grammar.parse($url, actions => URL::Grammar::Actions).made; + + die "'$url' failed to parse. Please report the URL you tried to p.spek+perl6@tyil.work." unless %match; + + samewith( + |%match, + path => %match.list + ); +} + +multi method new ( + Str :$scheme, + Str :$username, + Str :$password, + Str :$hostname, + Int :$port, + :@path = [], + :%query = {}, + Str :$fragment, +) { + self.bless( + :$scheme, + :$username, + :$password, + :$hostname, + :$port, + :@path, + :%query, + :$fragment, + ); +} + +method Hash ( + --> Hash +) { + { + :$!scheme, + :$!username, + :$!password, + :$!hostname, + :$!port, + :@!path, + :%!query, + :$!fragment, + } +} + +multi method Str ( + --> Str +) { + my $s = $!scheme ~ "://"; + + $s ~= "{self.Str(:userinfo)}@" if $!username; + $s ~= $!hostname; + $s ~= ":$!port" if $!port; + $s ~= "/{self.Str(:path)}" if @!path; + $s ~= "?{self.Str(:query)}" if %!query; + $s ~= "#$!fragment" if $!fragment; + + $s; +} + +multi method Str ( + :$path! where { $_ }, + + --> Str +) { + @!path.join("/"); +} + +multi method Str ( + :$query! where { $_ }, + + --> Str +) { + %!query.keys.sort.map({ "$_={%!query{$_}}" }).join("&") +} + +multi method Str ( + :$userinfo! where { $_ }, + + --> Str +) { + return "$!username:$!password" if $!password; + + $!username // ""; +} + +=begin pod + +=NAME URL +=AUTHOR Patrick Spek +=VERSION 0.1.0 + +=head1 Synopsis + +=head1 Description + +=head1 Examples + +=head1 See also + +=end pod + +# vim: ft=perl6 noet diff --git a/lib/URL/Grammar.pm6 b/lib/URL/Grammar.pm6 new file mode 100644 index 0000000..cc9f13c --- /dev/null +++ b/lib/URL/Grammar.pm6 @@ -0,0 +1,48 @@ +#! /usr/bin/env false + +use v6.d; + +unit grammar URL::Grammar; + +token TOP { + [ ":" ]? + "//"? + [ "@" ]? + ? + ? + [ "?" ]? + [ "#" ]? +} + +token scheme { <[ a..z ]> <[ a..z 0..9 . + - ]>* } +token userinfo { [ ":" ] } +token username { <-[ : @ ]>+ } +token password { <-[ @ ]>+ } +token host { [ ":" ]? } +token hostname { [ <-[ / : # ? \h ]>+ | "[" <-[ \] ]>+ "]" ] } +token port { \d ** 1..5 } +token path { "/" * % "/" } +token path-part { <-[ / ? # ]>+ } +token query { * % "&" } +token query-part { "=" } +token query-part-key { <-[ = # & ]>+ } +token query-part-value { <-[ # & ]>+ } +token fragment { <-[ \s ]>+ } + +=begin pod + +=NAME URL::Grammar +=AUTHOR Patrick Spek +=VERSION 0.1.0 + +=head1 Synopsis + +=head1 Description + +=head1 Examples + +=head1 See also + +=end pod + +# vim: ft=perl6 noet diff --git a/lib/URL/Grammar/Actions.pm6 b/lib/URL/Grammar/Actions.pm6 new file mode 100644 index 0000000..2015073 --- /dev/null +++ b/lib/URL/Grammar/Actions.pm6 @@ -0,0 +1,47 @@ +#! /usr/bin/env false + +use v6.d; + +unit class URL::Grammar::Actions; + +method TOP ($/) +{ + make { + scheme => $/.made // Str, + username => $/.made // Str, + password => $/.made // Str, + hostname => $/.made // Str, + port => $/.made // Int, + path => $/.made // [], + query => $/.made // {}, + fragment => $/.made // Str, + } +} + +method scheme ($/) { make ~$/ } +method username ($/) { make ~$/ } +method password ($/) { make ~$/ } +method hostname ($/) { make ~$/ } +method port ($/) { make +$/ } +method path ($/) { make $/».Str } +method query ($/) { make $/».made } +method query-part ($/) { make $/.Str => $/.Str } +method fragment ($/) { make ~$/ } + +=begin pod + +=NAME URL::Grammar::Actions +=AUTHOR Patrick Spek +=VERSION 0.1.0 + +=head1 Synopsis + +=head1 Description + +=head1 Examples + +=head1 See also + +=end pod + +# vim: ft=perl6 noet -- cgit v1.1