aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/URL.pm6126
-rw-r--r--lib/URL/Grammar.pm648
-rw-r--r--lib/URL/Grammar/Actions.pm647
3 files changed, 221 insertions, 0 deletions
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<path>.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 <p.spek@tyil.work>
+=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 {
+ [ <scheme> ":" ]?
+ "//"?
+ [ <userinfo> "@" ]?
+ <host>?
+ <path>?
+ [ "?" <query> ]?
+ [ "#" <fragment> ]?
+}
+
+token scheme { <[ a..z ]> <[ a..z 0..9 . + - ]>* }
+token userinfo { <username> [ ":" <password> ] }
+token username { <-[ : @ ]>+ }
+token password { <-[ @ ]>+ }
+token host { <hostname> [ ":" <port> ]? }
+token hostname { [ <-[ / : # ? \h ]>+ | "[" <-[ \] ]>+ "]" ] }
+token port { \d ** 1..5 }
+token path { "/" <part=.path-part>* % "/" }
+token path-part { <-[ / ? # ]>+ }
+token query { <part=.query-part>* % "&" }
+token query-part { <key=.query-part-key> "=" <value=.query-part-value> }
+token query-part-key { <-[ = # & ]>+ }
+token query-part-value { <-[ # & ]>+ }
+token fragment { <-[ \s ]>+ }
+
+=begin pod
+
+=NAME URL::Grammar
+=AUTHOR Patrick Spek <p.spek@tyil.work>
+=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 => $/<scheme>.made // Str,
+ username => $/<userinfo><username>.made // Str,
+ password => $/<userinfo><password>.made // Str,
+ hostname => $/<host><hostname>.made // Str,
+ port => $/<host><port>.made // Int,
+ path => $/<path>.made // [],
+ query => $/<query>.made // {},
+ fragment => $/<fragment>.made // Str,
+ }
+}
+
+method scheme ($/) { make ~$/ }
+method username ($/) { make ~$/ }
+method password ($/) { make ~$/ }
+method hostname ($/) { make ~$/ }
+method port ($/) { make +$/ }
+method path ($/) { make $/<part>».Str }
+method query ($/) { make $/<part>».made }
+method query-part ($/) { make $/<key>.Str => $/<value>.Str }
+method fragment ($/) { make ~$/ }
+
+=begin pod
+
+=NAME URL::Grammar::Actions
+=AUTHOR Patrick Spek <p.spek@tyil.work>
+=VERSION 0.1.0
+
+=head1 Synopsis
+
+=head1 Description
+
+=head1 Examples
+
+=head1 See also
+
+=end pod
+
+# vim: ft=perl6 noet