/
Socket.pm
118 lines (105 loc) · 3.35 KB
/
Socket.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
my role IO::Socket {
has $!PIO;
has Str $.encoding = 'utf8';
has $.nl-in is rw = ["\n", "\r\n"];
has Str:D $.nl-out is rw = "\n";
has Encoding::Decoder $!decoder;
has Encoding::Encoder $!encoder;
method !ensure-coders(--> Nil) {
unless $!decoder.DEFINITE {
my $encoding = Encoding::Registry.find($!encoding);
$!decoder := $encoding.decoder();
$!decoder.set-line-separators($!nl-in.list);
$!encoder := $encoding.encoder();
}
}
# The if bin is true, will return Buf, Str otherwise
method recv(Cool $limit? is copy, :$bin) {
fail('Socket not available') unless $!PIO;
$limit = 65535 if !$limit.DEFINITE || $limit === Inf;
if $bin {
nqp::readfh($!PIO, nqp::decont(buf8.new), $limit)
}
else {
self!ensure-coders();
my $result = $!decoder.consume-exactly-chars($limit);
without $result {
$!decoder.add-bytes(nqp::readfh($!PIO, nqp::decont(buf8.new), 65535));
$result = $!decoder.consume-exactly-chars($limit);
without $result {
$result = $!decoder.consume-all-chars();
}
}
$result
}
}
method read(IO::Socket:D: Int(Cool) $bufsize) {
fail('Socket not available') unless $!PIO;
my int $toread = $bufsize;
my $res := nqp::readfh($!PIO,buf8.new,$toread);
while nqp::elems($res) < $toread {
my $buf := nqp::readfh($!PIO,buf8.new,$toread - nqp::elems($res));
nqp::elems($buf)
?? $res.append($buf)
!! return $res
}
$res
}
method nl-in is rw {
Proxy.new(
FETCH => { $!nl-in },
STORE => -> $, $nl-in {
$!nl-in = $nl-in;
with $!decoder {
.set-line-separators($!nl-in.list);
}
$nl-in
}
)
}
method get() {
self!ensure-coders();
my Str $line = $!decoder.consume-line-chars(:chomp);
if $line.DEFINITE {
$line
}
else {
loop {
my $read = nqp::readfh($!PIO, nqp::decont(buf8.new), 65535);
$!decoder.add-bytes($read);
$line = $!decoder.consume-line-chars(:chomp);
last if $line.DEFINITE;
if $read == 0 {
$line = $!decoder.consume-line-chars(:chomp, :eof);
last;
}
}
$line.DEFINITE ?? $line !! Nil
}
}
method lines() {
gather while (my $line = self.get()).DEFINITE {
take $line;
}
}
method print(Str(Cool) $string --> True) {
self!ensure-coders();
self.write($!encoder.encode-chars($string));
}
method put(Str(Cool) $string --> True) {
self.print($string ~ $!nl-out);
}
method write(Blob:D $buf --> True) {
fail('Socket not available') unless $!PIO;
nqp::writefh($!PIO, nqp::decont($buf));
}
method close(--> True) {
fail("Not connected!") unless $!PIO;
nqp::closefh($!PIO);
$!PIO := nqp::null;
}
method native-descriptor(::?CLASS:D:) {
nqp::filenofh($!PIO)
}
}
# vim: ft=perl6 expandtab sw=4