86a63e9d66ace066377970846d09caeb9a20aef2
[scpubgit/Tak.git] / lib / Tak / JSONChannel.pm
1 package Tak::JSONChannel;
2
3 use JSON::PP qw(encode_json decode_json);
4 use IO::Handle;
5 use Scalar::Util qw(weaken);
6 use Moo;
7
8 has read_fh => (is => 'ro', required => 1);
9 has write_fh => (is => 'ro', required => 1);
10
11 sub BUILD { shift->write_fh->autoflush(1); }
12
13 sub read_message {
14   my ($self) = @_;
15   if (defined(my $line = readline($self->read_fh))) {
16     if (my $unpacked = $self->_unpack_line($line)) {
17       return $unpacked;
18     }
19   } else {
20     return [ 'close', 'channel' ];
21   }
22 }
23
24 sub _unpack_line {
25   my ($self, $line) = @_;
26   my $data = eval { decode_json($line) };
27   unless ($data) {
28     $self->write_message(mistake => invalid_json => $@||'No data and no exception');
29     return;
30   }
31   unless (ref($data) eq 'ARRAY') {
32     $self->write_message(mistake => message_format => "Not an ARRAY");
33     return;
34   }
35   unless (@$data > 0) {
36     $self->write_message(mistake => message_format => "Empty request array");
37     return;
38   }
39   $data;
40 }
41
42 sub write_message {
43   my ($self, @msg) = @_;
44   my $json = eval { encode_json(\@msg) };
45   unless ($json) {
46     $self->_raw_write_message(
47       encode_json(
48         [ failure => invalid_message => $@||'No data and no exception' ]
49       )
50     );
51     return;
52   }
53   $self->_raw_write_message($json);
54 }
55
56 sub _raw_write_message {
57   my ($self, $raw) = @_;
58 #warn "Sending: ${raw}\n";
59   print { $self->write_fh } $raw."\n";
60 }
61
62 1;