Repository: aisk/rust-memcache (language: rust)

Issue:
Client should provide interior mutability
Right now all `Client` methods take `&mut self` as a parameter. It is more convenient to take `&self` and use an internal mutability pattern like `Rc<RefCell>`or something else instead. 


Discussion / hints:

Fix patch:
diff --git a/README.md b/README.md
index 85e6965..1747e28 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ memcache = "*"
 
 ```rust
 // create connection with to memcached server node:
-let mut client = memcache::Client::connect("memcache://127.0.0.1:12345?timeout=10&tcp_nodelay=true").unwrap();
+let client = memcache::Client::connect("memcache://127.0.0.1:12345?timeout=10&tcp_nodelay=true").unwrap();
 
 // flush the database
 client.flush().unwrap();
diff --git a/src/client.rs b/src/client.rs
index e491e2c..928fff0 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -1,6 +1,7 @@
 use std::collections::hash_map::DefaultHasher;
 use std::collections::HashMap;
 use std::hash::{Hash, Hasher};
+use std::sync::Arc;
 use std::time::Duration;
 
 use url::Url;
@@ -45,11 +46,14 @@ impl Connectable for Vec<&str> {
     }
 }
 
+#[derive(Clone)]
 pub struct Client {
-    connections: Vec<Connection>,
+    connections: Arc<Vec<Connection>>,
     pub hash_function: fn(&str) -> u64,
 }
 
+unsafe impl Send for Client {}
+
 fn default_hash_function(key: &str) -> u64 {
     let mut hasher = DefaultHasher::new();
     key.hash(&mut hasher);
@@ -67,25 +71,25 @@ impl Client {
         let mut connections = vec![];
         for url in urls {
             let parsed = Url::parse(url.as_str())?;
-            let mut connection = Connection::connect(&parsed)?;
+            let connection = Connection::connect(&parsed)?;
 
             if parsed.has_authority() && parsed.username() != "" && parsed.password().is_some() {
                 let username = parsed.username();
                 let password = parsed.password().unwrap();
-                connection.protocol.auth(username, password)?;
+                connection.get_ref().auth(username, password)?;
             }
 
             connections.push(connection);
         }
         return Ok(Client {
-            connections: connections,
+            connections: Arc::new(connections),
             hash_function: default_hash_function,
         });
     }
 
-    fn get_connection(&mut self, key: &str) -> &mut Connection {
+    fn get_connection(&self, key: &str) -> Connection {
         let connections_count = self.connections.len();
-        return &mut self.connections[(self.hash_function)(key) as usize % connections_count];
+        return self.connections[(self.hash_function)(key) as usize % connections_count].clone();
     }
 
     /// Set the socket read timeout for TCP connections.
@@ -93,12 +97,12 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// client.set_read_timeout(Some(::std::time::Duration::from_secs(3))).unwrap();
     /// ```
-    pub fn set_read_timeout(&mut self, timeout: Option<Duration>) -> Result<(), MemcacheError> {
-        for conn in self.connections.iter_mut() {
-            match conn.protocol {
+    pub fn set_read_timeout(&self, timeout: Option<Duration>) -> Result<(), MemcacheError> {
+        for conn in self.connections.iter() {
+            match *conn.get_ref() {
                 Protocol::Ascii(ref mut protocol) => protocol.reader.get_mut().set_read_timeout(timeout)?,
                 Protocol::Binary(ref mut protocol) => protocol.stream.set_read_timeout(timeout)?,
             }
@@ -111,12 +115,12 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345?protocol=ascii").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345?protocol=ascii").unwrap();
     /// client.set_write_timeout(Some(::std::time::Duration::from_secs(3))).unwrap();
     /// ```
-    pub fn set_write_timeout(&mut self, timeout: Option<Duration>) -> Result<(), MemcacheError> {
-        for conn in self.connections.iter_mut() {
-            match conn.protocol {
+    pub fn set_write_timeout(&self, timeout: Option<Duration>) -> Result<(), MemcacheError> {
+        for conn in self.connections.iter() {
+            match *conn.get_ref() {
                 Protocol::Ascii(ref mut protocol) => protocol.reader.get_mut().set_read_timeout(timeout)?,
                 Protocol::Binary(ref mut protocol) => protocol.stream.set_write_timeout(timeout)?,
             }
@@ -129,13 +133,15 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// client.version().unwrap();
     /// ```
-    pub fn version(&mut self) -> Result<Vec<(String, String)>, MemcacheError> {
+    pub fn version(&self) -> Result<Vec<(String, String)>, MemcacheError> {
         let mut result = Vec::with_capacity(self.connections.len());
-        for connection in &mut self.connections {
-            result.push((connection.url.clone(), connection.protocol.version()?));
+        for connection in self.connections.iter() {
+            let mut protocol = connection.get_ref();
+            let url = connection.url.to_string();
+            result.push((url, protocol.version()?));
         }
         Ok(result)
     }
@@ -145,12 +151,12 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// client.flush().unwrap();
     /// ```
-    pub fn flush(&mut self) -> Result<(), MemcacheError> {
-        for connection in &mut self.connections {
-            connection.protocol.flush()?;
+    pub fn flush(&self) -> Result<(), MemcacheError> {
+        for connection in self.connections.iter() {
+            connection.get_ref().flush()?;
         }
         return Ok(());
     }
@@ -160,12 +166,12 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// client.flush_with_delay(10).unwrap();
     /// ```
-    pub fn flush_with_delay(&mut self, delay: u32) -> Result<(), MemcacheError> {
-        for connection in &mut self.connections {
-            connection.protocol.flush_with_delay(delay)?;
+    pub fn flush_with_delay(&self, delay: u32) -> Result<(), MemcacheError> {
+        for connection in self.connections.iter() {
+            connection.get_ref().flush_with_delay(delay)?;
         }
         return Ok(());
     }
@@ -175,11 +181,11 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// let _: Option<String> = client.get("foo").unwrap();
     /// ```
-    pub fn get<V: FromMemcacheValueExt>(&mut self, key: &str) -> Result<Option<V>, MemcacheError> {
-        return self.get_connection(key).protocol.get(key);
+    pub fn get<V: FromMemcacheValueExt>(&self, key: &str) -> Result<Option<V>, MemcacheError> {
+        return self.get_connection(key).get_ref().get(key);
     }
 
     /// Get multiple keys from memcached server. Using this function instead of calling `get` multiple times can reduce netwark workloads.
@@ -187,13 +193,13 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// client.set("foo", "42", 0).unwrap();
     /// let result: std::collections::HashMap<String, String> = client.gets(&["foo", "bar", "baz"]).unwrap();
     /// assert_eq!(result.len(), 1);
     /// assert_eq!(result["foo"], "42");
     /// ```
-    pub fn gets<V: FromMemcacheValueExt>(&mut self, keys: &[&str]) -> Result<HashMap<String, V>, MemcacheError> {
+    pub fn gets<V: FromMemcacheValueExt>(&self, keys: &[&str]) -> Result<HashMap<String, V>, MemcacheError> {
         let mut con_keys: HashMap<usize, Vec<&str>> = HashMap::new();
         let mut result: HashMap<String, V> = HashMap::new();
         let connections_count = self.connections.len();
@@ -204,8 +210,8 @@ impl Client {
             array.push(key);
         }
         for (&connection_index, keys) in con_keys.iter() {
-            let connection = &mut self.connections[connection_index];
-            result.extend(connection.protocol.gets(keys)?);
+            let connection = self.connections[connection_index].clone();
+            result.extend(connection.get_ref().gets(keys)?);
         }
         return Ok(result);
     }
@@ -215,16 +221,11 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// client.set("foo", "bar", 10).unwrap();
     /// ```
-    pub fn set<V: ToMemcacheValue<Stream>>(
-        &mut self,
-        key: &str,
-        value: V,
-        expiration: u32,
-    ) -> Result<(), MemcacheError> {
-        return self.get_connection(key).protocol.set(key, value, expiration);
+    pub fn set<V: ToMemcacheValue<Stream>>(&self, key: &str, value: V, expiration: u32) -> Result<(), MemcacheError> {
+        return self.get_connection(key).get_ref().set(key, value, expiration);
     }
 
     /// Compare and swap a key with the associate value into memcached server with expiration seconds.
@@ -234,7 +235,7 @@ impl Client {
     ///
     /// ```rust
     /// use std::collections::HashMap;
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// client.set("foo", "bar", 10).unwrap();
     /// let result: HashMap<String, (Vec<u8>, u32, Option<u64>)> = client.gets(&["foo"]).unwrap();
     /// let (_, _, cas) = result.get("foo").unwrap();
@@ -242,13 +243,13 @@ impl Client {
     /// assert_eq!(true, client.cas("foo", "bar2", 10, cas).unwrap());
     /// ```
     pub fn cas<V: ToMemcacheValue<Stream>>(
-        &mut self,
+        &self,
         key: &str,
         value: V,
         expiration: u32,
         cas_id: u64,
     ) -> Result<bool, MemcacheError> {
-        self.get_connection(key).protocol.cas(key, value, expiration, cas_id)
+        self.get_connection(key).get_ref().cas(key, value, expiration, cas_id)
     }
 
     /// Add a key with associate value into memcached server with expiration seconds.
@@ -256,18 +257,13 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// let key = "add_test";
     /// client.delete(key).unwrap();
     /// client.add(key, "bar", 100000000).unwrap();
     /// ```
-    pub fn add<V: ToMemcacheValue<Stream>>(
-        &mut self,
-        key: &str,
-        value: V,
-        expiration: u32,
-    ) -> Result<(), MemcacheError> {
-        return self.get_connection(key).protocol.add(key, value, expiration);
+    pub fn add<V: ToMemcacheValue<Stream>>(&self, key: &str, value: V, expiration: u32) -> Result<(), MemcacheError> {
+        return self.get_connection(key).get_ref().add(key, value, expiration);
     }
 
     /// Replace a key with associate value into memcached server with expiration seconds.
@@ -275,18 +271,18 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// let key = "replace_test";
     /// client.set(key, "bar", 0).unwrap();
     /// client.replace(key, "baz", 100000000).unwrap();
     /// ```
     pub fn replace<V: ToMemcacheValue<Stream>>(
-        &mut self,
+        &self,
         key: &str,
         value: V,
         expiration: u32,
     ) -> Result<(), MemcacheError> {
-        return self.get_connection(key).protocol.replace(key, value, expiration);
+        return self.get_connection(key).get_ref().replace(key, value, expiration);
     }
 
     /// Append value to the key.
@@ -294,15 +290,15 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// let key = "key_to_append";
     /// client.set(key, "hello", 0).unwrap();
     /// client.append(key, ", world!").unwrap();
     /// let result: String = client.get(key).unwrap().unwrap();
     /// assert_eq!(result, "hello, world!");
     /// ```
-    pub fn append<V: ToMemcacheValue<Stream>>(&mut self, key: &str, value: V) -> Result<(), MemcacheError> {
-        return self.get_connection(key).protocol.append(key, value);
+    pub fn append<V: ToMemcacheValue<Stream>>(&self, key: &str, value: V) -> Result<(), MemcacheError> {
+        return self.get_connection(key).get_ref().append(key, value);
     }
 
     /// Prepend value to the key.
@@ -310,15 +306,15 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// let key = "key_to_append";
     /// client.set(key, "world!", 0).unwrap();
     /// client.prepend(key, "hello, ").unwrap();
     /// let result: String = client.get(key).unwrap().unwrap();
     /// assert_eq!(result, "hello, world!");
     /// ```
-    pub fn prepend<V: ToMemcacheValue<Stream>>(&mut self, key: &str, value: V) -> Result<(), MemcacheError> {
-        return self.get_connection(key).protocol.prepend(key, value);
+    pub fn prepend<V: ToMemcacheValue<Stream>>(&self, key: &str, value: V) -> Result<(), MemcacheError> {
+        return self.get_connection(key).get_ref().prepend(key, value);
     }
 
     /// Delete a key from memcached server.
@@ -326,11 +322,11 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// client.delete("foo").unwrap();
     /// ```
-    pub fn delete(&mut self, key: &str) -> Result<bool, MemcacheError> {
-        return self.get_connection(key).protocol.delete(key);
+    pub fn delete(&self, key: &str) -> Result<bool, MemcacheError> {
+        return self.get_connection(key).get_ref().delete(key);
     }
 
     /// Increment the value with amount.
@@ -338,11 +334,11 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// client.increment("counter", 42).unwrap();
     /// ```
-    pub fn increment(&mut self, key: &str, amount: u64) -> Result<u64, MemcacheError> {
-        return self.get_connection(key).protocol.increment(key, amount);
+    pub fn increment(&self, key: &str, amount: u64) -> Result<u64, MemcacheError> {
+        return self.get_connection(key).get_ref().increment(key, amount);
     }
 
     /// Decrement the value with amount.
@@ -350,11 +346,11 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// client.decrement("counter", 42).unwrap();
     /// ```
-    pub fn decrement(&mut self, key: &str, amount: u64) -> Result<u64, MemcacheError> {
-        return self.get_connection(key).protocol.decrement(key, amount);
+    pub fn decrement(&self, key: &str, amount: u64) -> Result<u64, MemcacheError> {
+        return self.get_connection(key).get_ref().decrement(key, amount);
     }
 
     /// Set a new expiration time for a exist key.
@@ -362,27 +358,27 @@ impl Client {
     /// Example:
     ///
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// assert_eq!(client.touch("not_exists_key", 12345).unwrap(), false);
     /// client.set("foo", "bar", 123).unwrap();
     /// assert_eq!(client.touch("foo", 12345).unwrap(), true);
     /// ```
-    pub fn touch(&mut self, key: &str, expiration: u32) -> Result<bool, MemcacheError> {
-        return self.get_connection(key).protocol.touch(key, expiration);
+    pub fn touch(&self, key: &str, expiration: u32) -> Result<bool, MemcacheError> {
+        return self.get_connection(key).get_ref().touch(key, expiration);
     }
 
     /// Get all servers' statistics.
     ///
     /// Example:
     /// ```rust
-    /// let mut client = memcache::Client::connect("memcache://localhost:12345").unwrap();
+    /// let client = memcache::Client::connect("memcache://localhost:12345").unwrap();
     /// let stats = client.stats().unwrap();
     /// ```
-    pub fn stats(&mut self) -> Result<Vec<(String, Stats)>, MemcacheError> {
+    pub fn stats(&self) -> Result<Vec<(String, Stats)>, MemcacheError> {
         let mut result: Vec<(String, HashMap<String, String>)> = vec![];
-        for connection in &mut self.connections {
-            let stats_info = connection.protocol.stats()?;
-            let url = connection.url.clone();
+        for connection in self.connections.iter() {
+            let stats_info = connection.get_ref().stats()?;
+            let url = connection.url.to_string();
             result.push((url, stats_info));
         }
         return Ok(result);
@@ -394,21 +390,21 @@ mod tests {
     #[cfg(unix)]
     #[test]
     fn unix() {
-        let mut client = super::Client::connect("memcache:///tmp/memcached.sock").unwrap();
+        let client = super::Client::connect("memcache:///tmp/memcached.sock").unwrap();
         assert!(client.version().unwrap()[0].1 != "");
     }
 
     #[cfg(feature = "tls")]
     #[test]
     fn ssl_noverify() {
-        let mut client = super::Client::connect("memcache+tls://localhost:12350?verify_mode=none").unwrap();
+        let client = super::Client::connect("memcache+tls://localhost:12350?verify_mode=none").unwrap();
         assert!(client.version().unwrap()[0].1 != "");
     }
 
     #[cfg(feature = "tls")]
     #[test]
     fn ssl_verify() {
-        let mut client =
+        let client =
             super::Client::connect("memcache+tls://localhost:12350?ca_path=tests/assets/RUST_MEMCACHE_TEST_CERT.crt")
                 .unwrap();
         assert!(client.version().unwrap()[0].1 != "");
@@ -417,13 +413,13 @@ mod tests {
     #[cfg(feature = "tls")]
     #[test]
     fn ssl_client_certs() {
-        let mut client = super::Client::connect("memcache+tls://localhost:12351?key_path=tests/assets/client.key&cert_path=tests/assets/client.crt&ca_path=tests/assets/RUST_MEMCACHE_TEST_CERT.crt").unwrap();
+        let client = super::Client::connect("memcache+tls://localhost:12351?key_path=tests/assets/client.key&cert_path=tests/assets/client.crt&ca_path=tests/assets/RUST_MEMCACHE_TEST_CERT.crt").unwrap();
         assert!(client.version().unwrap()[0].1 != "");
     }
 
     #[test]
     fn delete() {
-        let mut client = super::Client::connect("memcache://localhost:12345").unwrap();
+        let client = super::Client::connect("memcache://localhost:12345").unwrap();
         client.set("an_exists_key", "value", 0).unwrap();
         assert_eq!(client.delete("an_exists_key").unwrap(), true);
         assert_eq!(client.delete("a_not_exists_key").unwrap(), false);
@@ -431,7 +427,7 @@ mod tests {
 
     #[test]
     fn increment() {
-        let mut client = super::Client::connect("memcache://localhost:12345").unwrap();
+        let client = super::Client::connect("memcache://localhost:12345").unwrap();
         client.delete("counter").unwrap();
         client.set("counter", 321, 0).unwrap();
         assert_eq!(client.increment("counter", 123).unwrap(), 444);
diff --git a/src/connection.rs b/src/connection.rs
index 23c24a5..ef52115 100644
--- a/src/connection.rs
+++ b/src/connection.rs
@@ -2,6 +2,7 @@ use std::io::BufReader;
 use std::net::TcpStream;
 #[cfg(unix)]
 use std::os::unix::net::UnixStream;
+use std::sync::{Arc, Mutex, MutexGuard};
 use std::time::Duration;
 use url::Url;
 
@@ -14,9 +15,13 @@ use stream::Stream;
 use stream::UdpStream;
 
 /// a connection to the memcached server
+#[derive(Clone)]
 pub struct Connection {
-    pub protocol: Protocol,
-    pub url: String,
+    /// Taking a lock on a `Protocol` will never fail unless the `Mutex`
+    /// is poisoned(which implies another bug in protocol module) because
+    /// all `Client` methods unlock the mutex before returning control flow.
+    pub protocol: Arc<Mutex<Protocol>>,
+    pub url: Arc<String>,
 }
 
 enum Transport {
@@ -110,9 +115,11 @@ impl Transport {
         let mut parts = url.scheme().splitn(2, "+");
         match parts.next() {
             Some(part) if part == "memcache" => (),
-            _ => return Err(MemcacheError::BadURL(
+            _ => {
+                return Err(MemcacheError::BadURL(
                     "memcache URL's scheme should start with 'memcache'".into(),
                 ))
+            }
         }
 
         // scheme has highest priority
@@ -127,7 +134,7 @@ impl Transport {
                 _ => Err(MemcacheError::BadURL(
                     "memcache URL's scheme should be 'memcache+tcp' or 'memcache+udp' or 'memcache+unix' or 'memcache+tls'".into(),
                 )),
-            }
+            };
         }
 
         let is_udp = url.query_pairs().any(|(ref k, ref v)| k == "udp" && v == "true");
@@ -147,7 +154,7 @@ impl Transport {
 }
 
 fn tcp_stream(url: &Url, opts: &TcpOptions) -> Result<TcpStream, MemcacheError> {
-    let tcp_stream = TcpStream::connect(&*url.socket_addrs(||None)?)?;
+    let tcp_stream = TcpStream::connect(&*url.socket_addrs(|| None)?)?;
     if opts.timeout.is_some() {
         tcp_stream.set_read_timeout(opts.timeout)?;
         tcp_stream.set_write_timeout(opts.timeout)?;
@@ -157,6 +164,10 @@ fn tcp_stream(url: &Url, opts: &TcpOptions) -> Result<TcpStream, MemcacheError>
 }
 
 impl Connection {
+    pub(crate) fn get_ref(&self) -> MutexGuard<Protocol> {
+        self.protocol.lock().expect("won't fail")
+    }
+
     pub(crate) fn connect(url: &Url) -> Result<Self, MemcacheError> {
         let transport = Transport::from_url(url)?;
         let is_ascii = url.query_pairs().any(|(ref k, ref v)| k == "protocol" && v == "ascii");
@@ -202,8 +213,8 @@ impl Connection {
         };
 
         Ok(Connection {
-            url: url.to_string(),
-            protocol: protocol,
+            url: Arc::new(url.to_string()),
+            protocol: Arc::new(Mutex::new(protocol)),
         })
     }
 }
@@ -217,8 +228,7 @@ mod tests {
         use url::Url;
         match Transport::from_url(&Url::parse("memcache:///tmp/memcached.sock").unwrap()).unwrap() {
             Transport::Unix => (),
-            _ => assert!(false, "transport is not unix")
+            _ => assert!(false, "transport is not unix"),
         }
     }
 }
-
diff --git a/src/lib.rs b/src/lib.rs
index fef165b..12836a5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -33,7 +33,7 @@ memcache = "*"
 
 ```rust
 // create connection with to memcached server node:
-let mut client = memcache::Client::connect("memcache://127.0.0.1:12345?timeout=10&tcp_nodelay=true").unwrap();
+let client = memcache::Client::connect("memcache://127.0.0.1:12345?timeout=10&tcp_nodelay=true").unwrap();
 
 // flush the database:
 client.flush().unwrap();


Test patch:
diff --git a/tests/test_ascii.rs b/tests/test_ascii.rs
index 7e77bb7..64fef61 100644
--- a/tests/test_ascii.rs
+++ b/tests/test_ascii.rs
@@ -5,7 +5,7 @@ use std::{thread, time};
 
 #[test]
 fn test_ascii() {
-    let mut client = memcache::Client::connect("memcache://localhost:12345?protocol=ascii").unwrap();
+    let client = memcache::Client::connect("memcache://localhost:12345?protocol=ascii").unwrap();
 
     client.flush_with_delay(1).unwrap();
     thread::sleep(time::Duration::from_secs(1));
diff --git a/tests/tests.rs b/tests/tests.rs
index 2fe8b82..a50049a 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -27,7 +27,7 @@ fn test() {
     if cfg!(unix) {
         urls.push("memcache:///tmp/memcached2.sock");
     }
-    let mut client = memcache::Client::connect(urls).unwrap();
+    let client = memcache::Client::connect(urls).unwrap();
 
     client.version().unwrap();
 
@@ -60,7 +60,7 @@ fn test() {
 #[test]
 fn issue74() {
     use memcache::{Client, CommandError, MemcacheError};
-    let mut client = Client::connect("memcache://localhost:12346?tcp_nodelay=true").unwrap();
+    let client = Client::connect("memcache://localhost:12346?tcp_nodelay=true").unwrap();
     client.delete("issue74").unwrap();
     client.add("issue74", 1, 0).unwrap();
 
@@ -92,7 +92,7 @@ fn issue74() {
 #[test]
 fn udp_test() {
     let urls = vec!["memcache+udp://localhost:22345"];
-    let mut client = memcache::Client::connect(urls).unwrap();
+    let client = memcache::Client::connect(urls).unwrap();
 
     client.version().unwrap();
 
@@ -168,7 +168,7 @@ fn udp_test() {
         handles.push(Some(thread::spawn(move || {
             let key = format!("key{}", i);
             let value = format!("value{}", i);
-            let mut client = memcache::Client::connect("memcache://localhost:22345?udp=true").unwrap();
+            let client = memcache::Client::connect("memcache://localhost:22345?udp=true").unwrap();
             for j in 0..50 {
                 let value = format!("{}{}", value, j);
                 client.set(key.as_str(), &value, 0).unwrap();
@@ -214,7 +214,7 @@ fn test_cas() {
         Client::connect("memcache://localhost:12345").unwrap(),
         Client::connect("memcache://localhost:12345?protocol=ascii").unwrap(),
     ];
-    for mut client in clients {
+    for client in clients {
         client.flush().unwrap();
 
         client.set("ascii_foo", "bar", 0).unwrap();