File Coverage

blib/lib/App/EvalServerAdvanced/Protocol.pm
Criterion Covered Total %
statement 12 14 85.7
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 17 19 89.4


line stmt bran cond sub pod time code
1             package App::EvalServerAdvanced::Protocol;
2 2     2   25647 use strict;
  2         4  
  2         51  
3 2     2   10 use warnings;
  2         4  
  2         95  
4              
5             our $VERSION = '0.104';
6             # ABSTRACT: Protocol abstraction for App::EvalServerAdvanced
7             my $protocol_version = 1;
8              
9 2     2   27 use v5.24.0;
  2         7  
10 2     2   12 no warnings 'experimental';
  2         6  
  2         80  
11              
12 2     2   1534 use Google::ProtocolBuffers::Dynamic;
  0            
  0            
13             use Path::Tiny qw/path/;
14             use Function::Parameters;
15             use Encode qw/encode decode/;
16              
17             use Exporter 'import';
18             our @EXPORT = qw/decode_message encode_message/;
19              
20             my $path = path(__FILE__)->parent->child("protocol.proto");
21              
22             # load_file tries to allocate >100TB of ram. Not sure why, so we'll just read it ourselves
23             my $proto = $path->slurp_utf8;
24              
25             my $gpb = Google::ProtocolBuffers::Dynamic->new();
26              
27             $gpb->load_string("protocol.proto", $proto);
28              
29             $gpb->map({ pb_prefix => "messages", prefix => "App::EvalServerAdvanced::Protocol", options => {accessor_style => 'single_accessor'} });
30              
31             fun handle_encoding($type, $obj) {
32             given($type) {
33             when("eval") {
34             for my $file ($obj->{files}->@*) {
35             my $f_encoding = $file->{encoding};
36              
37             if (defined $f_encoding && $f_encoding ne "raw" && $f_encoding ne "") {
38             $file->{contents} = encode($f_encoding, $file->{contents});
39             }
40             }
41             }
42             when("warning") {
43             if ($obj->{encoding}) {
44             $obj->{message} = encode($obj->{encoding}, $obj->{message});
45             }
46             }
47             when("response") {
48             if ($obj->{encoding}) {
49             $obj->{contents} = encode($obj->{encoding}, $obj->{contents});
50             }
51             }
52             }
53             }
54              
55             fun encode_message($type, $obj) {
56             handle_encoding($type, $obj);
57             my $message = App::EvalServerAdvanced::Protocol::Packet->encode({$type => $obj});
58              
59             # 8 byte header, 0x0000_0001 0x1234_5678
60             # first 4 bytes are the protocol version, last 4 are length of the message in octets
61             my $header = pack "NN", $protocol_version, length($message);
62             return ($header . $message);
63             };
64              
65             fun decode_message($buffer) {
66             return (0, undef, undef) if length $buffer < 8; # can't have a message without a header
67              
68             my $header = substr($buffer, 0, 8); # grab the header
69             my ($reserved, $length) = unpack("NN", $header);
70              
71             die "Undecodable header" if ($reserved != $protocol_version);
72            
73             # Packet isn't ready yet
74             return (0, undef, undef) if (length($buffer) - 8 < $length);
75              
76             my $message_bytes = substr($buffer, 8, $length);
77             substr($buffer, 0, $length+8, "");
78              
79             my $message = App::EvalServerAdvanced::Protocol::Packet->decode($message_bytes);
80             my ($k) = keys %$message;
81              
82             die "Undecodable message" unless ($k);
83             my $real_message = $message->$k;
84              
85             return (1, $real_message, $buffer);
86             };
87              
88             package
89             App::EvalServerAdvanced::Protocol::EvalResponse;
90             use Encode qw//;
91              
92             method get_contents() {
93             if ($self->encoding && $self->encoding ne "raw") {
94             return Encode::decode($self->encoding, $self->contents);
95             }
96             return $self->contents;
97             }
98              
99             package
100             App::EvalServerAdvanced::Protocol::Eval::File;
101             use Encode qw//;
102              
103             method get_contents() {
104             if ($self->encoding && $self->encoding ne "raw") {
105             return Encode::decode($self->encoding, $self->contents);
106             }
107             return $self->contents;
108             }
109              
110              
111             # given($type) {
112             # when("Eval") {
113             # # I can't decide if I should decode these or not. Keeping them as raw bytes seems safer
114             # # for my $file ($obj->files->@*) {
115             # # my $f_encoding = $file->encoding;
116              
117             # # if ($f_encoding ne "raw" && $f_encoding ne "") {
118             # # $file->contents(decode($f_encoding, $file->contents));
119             # # }
120             # # }
121             # }
122              
123              
124             1;