Files
herolib/lib/data/resp/resp_decode.v
2024-12-25 09:23:31 +01:00

214 lines
3.9 KiB
V

module resp
// mut r := io.new_buffered_reader(reader: io.make_reader(conn))
// for {
// l := r.read_line() or { break }
// console.print_debug('$l')
// // Make it nice and obvious that we are doing this line by line
// time.sleep(100 * time.millisecond)
// }
// }
pub fn (mut r StringLineReader) get_response() !RValue {
line_ := r.read_line()
line := line_.bytestr()
if line.starts_with('-') {
return RError{
value: line[1..]
}
}
if line.starts_with(':') {
return RInt{
value: line[1..].int()
}
}
if line.starts_with('+') {
return RString{
value: line[1..]
}
}
if line.starts_with('$') {
mut bulkstring_size := line[1..].int()
if bulkstring_size == -1 {
return RNil{}
}
if bulkstring_size == 0 {
// extract final \r\n and not reading
// any payload
r.read_line()
return RString{
value: ''
}
}
// read payload
buffer := r.read(bulkstring_size)
// extract final \r\n
r.read_line()
return RBString{
value: buffer
} // FIXME: won't support binary (afaik)
}
if line.starts_with('*') {
mut arr := RArray{
values: []RValue{}
}
items := line[1..].int()
// proceed each entries, they can be of any types
for _ in 0 .. items {
value := r.get_response()!
arr.values << value
}
return arr
}
return error('unsupported response type')
}
pub fn decode(data []u8) ![]RValue {
mut r := new_line_reader(data)
mut res := []RValue{}
for {
v := r.get_response() or { break }
res << v
}
return res
}
pub fn (mut r StringLineReader) get_int() !int {
line_ := r.read_line()
line := line_.bytestr()
if line.starts_with(':') {
return line[1..].int()
} else {
return error("Did not find int, did find:'${line}'")
}
}
pub fn (mut r StringLineReader) get_list_int() ![]int {
line_ := r.read_line()
line := line_.bytestr()
mut res := []int{}
if line.starts_with('*') {
items := line[1..].int()
// proceed each entries, they can be of any types
for _ in 0 .. items {
value := r.get_int()!
res << value
}
return res
} else {
return error("Did not find int, did find:'${line}'")
}
}
pub fn (mut r StringLineReader) get_string() !string {
line_ := r.read_line()
line := line_.bytestr()
if line.starts_with('+') {
return line[1..]
} else {
return error("Did not find string, did find:'${line}'")
}
}
pub fn (mut r StringLineReader) get_bool() !bool {
i := r.get_int()!
return i == 1
}
pub fn (mut r StringLineReader) get_bytes() ![]u8 {
line_ := r.read_line()
line := line_.bytestr()
if line.starts_with('$') {
mut bulkstring_size := line[1..].int()
if bulkstring_size == -1 {
return []u8{}
}
if bulkstring_size == 0 {
// extract final \r\n and not reading
// any payload
r.read_line()
return ''.bytes()
}
// read payload
buffer := r.read(bulkstring_size)
// extract final \r\n
return buffer
} else {
return error("Did not find bulkstring, did find:'${line}'")
}
}
pub fn get_redis_value(rv RValue) string {
if rv is RArray || rv is RNil {
rv_type := rv.type_name()
panic("Can't get value for ${rv_type}")
}
return match rv {
RInt {
rv.value.str()
}
RString, RError {
rv.value
}
RBString {
rv.value.bytestr()
}
else {
''
}
}
}
pub fn get_redis_value_by_index(rv RValue, i int) string {
if rv !is RArray {
panic('This functions used with RArray only, use get_value instead')
}
return match rv {
RArray {
get_redis_value(rv.values[i])
}
else {
''
}
}
}
pub fn get_redis_array(rv RValue) []RValue {
if rv !is RArray {
panic('This functions used with RArray only, use get_value instead')
}
return match rv {
RArray {
rv.values
}
else {
[]RValue{}
}
}
}
pub fn get_redis_array_len(rv RValue) int {
if rv !is RArray {
panic('This functions used with RArray only')
}
return match rv {
RArray {
rv.values.len
}
else {
result := -1
result
}
}
}
pub fn get_array_value(rv RValue, index int) string {
return get_redis_value(get_redis_array(rv)[index])
}