Skip to content

Instantly share code, notes, and snippets.

@skids
Created April 8, 2015 14:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skids/cf9065039903df5047ac to your computer and use it in GitHub Desktop.
Save skids/cf9065039903df5047ac to your computer and use it in GitHub Desktop.
preview_of_x_protocol
=NAME X::Protocol - Perl6 Exception superclass for protocol result codes
=begin SYNOPSIS
=begin code
# A simple example for a protocol that just has error codes
class X::Protocol::SneakerNet is X::Protocol {
method protocol { "SneakerNet" }
}
my @errors = X::Protocol::SneakerNet.new(:code(10)),
X::Protocol::SneakerNet.new(:code("11")),
X::Protocol::SneakerNet.new(:code("12.5")),
X::Protocol::SneakerNet.new(:code("13W")),
X::Protocol::SneakerNet.new(:code("XL")),
X::Protocol::SneakerNet.new(:code("XXL"));
# A default .Numeric and .Str are provided based on :code,
# so you can handle the above errors like this:
for @errors {
when 10 { say "Matches the first one" }
when 11 { say "Matches the second one" }
when 12.5 { say "Matches the third one" }
when "13W" { say "Matches the fourth one" }
when /XL/ { say "Matches the fifth and sixth one" }
}
# You can add human readable "code-message" method and specify
# a "severity" method. You may also define your own "toss"
# method to perform a throw or fail only when appropriate.
#
# By default, .severity is always "error", and .toss
# calls .fail when .severity is "failure" and .throw when
# .severity is "error", and note(.gist) when severity
# is "warning".
#
class X::Protocol::IPoUSPO is X::Protocol {
method protocol { "IPoUSPO" }
method code-message {
given self.code {
when 500 { "Chased away by dog" }
when 400 { "A snowy, rainy, hot and gloomy night" }
when 200 { "Delivered" }
}
}
method severity { ~$.code ~~ /\d/ // "unknown" }
method toss {
if self.severity > 4 { self.fail }
elsif self.severity > 2 { self.throw }
else { note self.gist }
}
}
# The default message shows the protocol, severity, code, and code-message
X::Protocol::IPoUSPO.new(:200code).say; # IPoUSPO 2: 200 -- Delivered
# Remember .Str is just the stringified code;
print X::Protocol::IPoUSPO.new(:400code), "\n"; # 400
# For one-offs you can supply a per-instance protocol name
{
X::Protocol.new(:404code :protocol<HTTP>).toss;
"HERE".say; # gets here, because default "error" gets resumably thrown
CATCH {
$_.resume;
}
}
=end code
=end SYNOPSIS
=begin DESCRIPTION
=end DESCRIPTION
class X::Protocol is Exception {
has $.code = "ad-hoc";
has Str $.protocol = self.protocol;
method protocol {
die "A protocol name is required" unless $!protocol;
$!protocol;
}
method message {
join(" -- ",
$!protocol ~ " " ~ self.severity ~ ": $.code",
self.code-message);
}
method code-message { () }
method severity { "error" }
method Numeric {
+$.code // NaN;
}
method toss {
given self.severity {
when "failure" { self.fail }
when "error" { self.throw }
when "warning" { note(self.gist) }
default { }
}
}
method Str {
~$.code // "";
}
# Without this we get an error about not being able to create a
# backtrace in .gist. Yet, even with this, we still get backtraces
# on uncaught failures.
# method gist { self.message ~ (self.backtrace.defined)}
}
=AUTHOR Brian S. Julin
=COPYRIGHT Copyright (c) 2015 Brian S. Julin. All rights reserved.
=begin LICENSE
This program is free software; you can redistribute it and/or modify
it under the terms of the Perl Artistic License 2.0.
=end LICENSE
=SEE-ALSO C<Exception>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment