Skip to content

Instantly share code, notes, and snippets.

@jsanders
Last active December 24, 2015 10:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jsanders/6784321 to your computer and use it in GitHub Desktop.
Save jsanders/6784321 to your computer and use it in GitHub Desktop.
Start of redis client implementation in rust
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