forked from Zeroloop/lasso-redis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresp_decode.lasso
104 lines (84 loc) · 2.45 KB
/
resp_decode.lasso
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
<?lasso
/////////////////////////////////////////////////////////
//
// RESP.decode — http://redis.io/topics/protocol
//
/////////////////////////////////////////////////////////
define resp_decode => type {
data
private raw,
private i = 0
public oncreate(p::string) => .consume(#p)
public oncreate(p0::string,p1::string,...) => (with p in params select .consume(#p))->asstaticarray
public consume(p::string) => {
local(out) = array
// Dealing with lines reduces iterations
.raw = #p->split('\r\n')->asstaticarray
.i = 1
// Deal with multiple responses (pipeline)
while(.i < .raw->size) => {
#out->insert(
.consume_line
)
}
return (
// Return sole result or all results
#out->size == 1
? #out->first
| #out->asstaticarray
)
}
public consume_line(p::string = .raw->get(.i++)) => {
match(#p->get(1)) => {
case('$') return .consume_string(#p)
case('+') return .consume_simple(#p)
case('*') return .consume_array(#p)
case(':') return .consume_integer(#p)
case('-') return .consume_error(#p)
}
}
public consume_integer(p::string) => {
return integer(#p->sub(2,20))
}
public consume_simple(p::string) => {
return #p->sub(2,1024)
}
public consume_error(p::string) => {
local(error) = #p->sub(2,1024)
// Throw the error
fail(-1,#error)
}
public consume_string(p::string) => {
// Establish size
local(
size = integer(#p->sub(2,20)),
out
)
// Deal with null values
#size == -1 ? return null
// Grab first component
#out = .raw->get(.i++)
// Check for carrage returns in string
#out->size != #size
? {
#out->append('\r\n')
#out->append(.raw->get(.i++))
#out->size != #size ? currentcapture->restart
}()
// Return string
return #out
}
public consume_array(p::string) => {
local(
// Establish size
size = integer(#p->sub(2,40)),
out = array
)
while(#size--) => {
#out->insert(.consume_line)
}
// Return array
return #out
}
}
?>