Last active
December 24, 2015 10:29
-
-
Save jsanders/6784321 to your computer and use it in GitHub Desktop.
Start of redis client implementation in rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::rt::io::{Reader, Writer}; | |
use std::rt::io::net::ip::{Ipv4Addr,SocketAddr}; | |
use std::rt::io::net::tcp::TcpStream; | |
use std::str; | |
trait ToUintSafe { | |
fn to_uint_safe(&self) -> Option<uint>; | |
} | |
impl ToUintSafe for int { | |
fn to_uint_safe(&self) -> Option<uint> { | |
if *self < 0 { | |
None | |
} else { | |
Some(self.to_uint()) | |
} | |
} | |
} | |
struct Redis { | |
stream: TcpStream | |
} | |
impl Redis { | |
fn connect() -> Redis { | |
let ip_addr = Ipv4Addr(127, 0, 0, 1); | |
let tcp_addr = SocketAddr { ip: ip_addr, port: 6379 }; | |
Redis { stream: TcpStream::connect(tcp_addr).expect("Failed to connect to redis on 127.0.0.1:6379!") } | |
} | |
fn write_command(&mut self, args: &[&str]) { | |
let num_args = format!("*{:u}\r\n", args.len()); | |
self.stream.write(num_args.as_bytes()); | |
for arg in args.iter() { | |
let arg_len = format!("${:u}\r\n", arg.len()); | |
self.stream.write(arg_len.as_bytes()); | |
let arg = format!("{:s}\r\n", *arg); | |
self.stream.write(arg.as_bytes()); | |
} | |
} | |
fn read_bulk_reply(&mut self) -> Option<~str> { | |
let mut buf = ~[0u8, ..1024]; | |
let bytes_read = self.stream.read(buf).expect("Failed to get reply from redis server"); | |
let reply = str::from_utf8(buf.slice_to(bytes_read)); | |
let (len_line, rest) = match reply.find_str("\r\n") { | |
None => fail!("Invalid bulk reply"), | |
Some(index) => { | |
( reply.slice_to(index), reply.slice_from(index + 2) ) | |
} | |
}; | |
if len_line[0] != '$' as u8 { | |
fail!("Invalid bulk reply"); | |
} | |
println(len_line); | |
let len: int = from_str(len_line.slice_from(1)).expect("Invalid bulk reply"); | |
match len { | |
-1 => None, | |
_ => { | |
let len = len.to_uint_safe().expect("Invalid bulk reply"); | |
Some(rest.slice_to(len).to_owned()) | |
} | |
} | |
} | |
fn do_bulk_command(&mut self, args: &[&str]) -> Option<~str> { | |
self.write_command(args); | |
self.read_bulk_reply() | |
} | |
fn lpop(&mut self, key: &str) -> Option<~str> { | |
self.do_bulk_command(&[ &"lpop", key ]) | |
} | |
} | |
#[test] | |
fn test_connect() { | |
let mut redis = Redis::connect(); | |
println( | |
match redis.lpop("resque:queue:basic_queue") { | |
Some(value) => value, | |
None => ~"Nothing to pop!" | |
} | |
); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment