Repository: AlexPikalov/cdrs (language: rust)

Issue:
Rework into Rust conversion
Basing on discussion #109 and thread on [Reddit](https://redd.it/5xcj2e) we'd like to have `Result<Option<_>>` instead of current `Option<Result<_>>`.


Discussion / hints:

Fix patch:
diff --git a/README.md b/README.md
index 5960da6..bae25f6 100644
--- a/README.md
+++ b/README.md
@@ -283,8 +283,8 @@ let rows = res_body.into_rows().unwrap();
 let messages: Vec<CResult<Message>> = rows
     .iter()
     .map(|row| Message {
-        author: row.get_by_name("author").unwrap(),
-        text: row.get_by_name("text").unwrap()
+        author: row.r_by_name("author").unwrap(),
+        text: row.r_by_name("text").unwrap()
     })
     .collect();
 
@@ -308,10 +308,10 @@ let rows = res_body.into_rows().unwrap();
 let messages: Vec<CAuthor> = rows
     .iter()
     .map(|row| {
-        let name: String = row.get_by_name("name").unwrap();
+        let name: String = row.r_by_name("name").unwrap();
         let messages: Vec<String> = row
             // unwrap Option<CResult<T>>, where T implements AsRust
-            .get_by_name("messages").unwrap().unwrap()
+            .r_by_name("messages").unwrap().unwrap()
             .as_rust().unwrap();
         return Author {
             author: name,
diff --git a/examples/all.rs b/examples/all.rs
index d5dd267..275123e 100644
--- a/examples/all.rs
+++ b/examples/all.rs
@@ -297,16 +297,10 @@ fn select_all_ints(session: &mut Session<NoneAuthenticator, TransportTcp>) -> bo
 
     for row in all {
         let _ = Ints {
-            bigint: row.get_by_name("my_bigint")
-                .expect("my_bigint")
-                .unwrap(),
-            int: row.get_by_name("my_int").expect("my_int").unwrap(),
-            smallint: row.get_by_name("my_smallint")
-                .expect("my_smallint")
-                .unwrap(),
-            tinyint: row.get_by_name("my_tinyint")
-                .expect("my_tinyint")
-                .unwrap(),
+            bigint: row.r_by_name("my_bigint").expect("my_bigint"),
+            int: row.r_by_name("my_int").expect("my_int"),
+            smallint: row.r_by_name("my_smallint").expect("my_smallint"),
+            tinyint: row.r_by_name("my_tinyint").expect("my_tinyint"),
         };
     }
 
@@ -369,11 +363,9 @@ fn select_table_str(session: &mut Session<NoneAuthenticator, TransportTcp>) -> b
 
     for row in all {
         let _ = Strings {
-            my_ascii: row.get_by_name("my_ascii").expect("my_ascii").unwrap(),
-            my_text: row.get_by_name("my_text").expect("my_text").unwrap(),
-            my_varchar: row.get_by_name("my_varchar")
-                .expect("my_ascii")
-                .unwrap(),
+            my_ascii: row.r_by_name("my_ascii").expect("my_ascii"),
+            my_text: row.r_by_name("my_text").expect("my_text"),
+            my_varchar: row.r_by_name("my_varchar").expect("my_ascii"),
         };
     }
 
@@ -420,24 +412,21 @@ fn select_table_list(session: &mut Session<NoneAuthenticator, TransportTcp>) ->
 
     for row in all {
         let _ = Lists {
-            string_list: row.by_name::<List>("my_string_list") // intermediate type is required
+            string_list: row.r_by_name::<List>("my_string_list") // intermediate type is required
                 .expect("string_list")
-                .unwrap()
-                .as_rust::<Vec<String>>() // final type is not required, it could be find
+                .as_r_rust::<Vec<String>>() // final type is not required, it could be find
                 // authomatically
                 .expect("string_list"),
-            number_list: row.by_name::<List>("my_number_list")
+            number_list: row.r_by_name::<List>("my_number_list")
                 .expect("number_list")
-                .unwrap()
-                .as_rust()
+                .as_r_rust()
                 .expect("number_list"),
-            complex_list: row.by_name::<List>("my_complex_list")
+            complex_list: row.r_by_name::<List>("my_complex_list")
                 .expect("complex_list")
-                .unwrap()
-                .as_rust::<Vec<List>>()
+                .as_r_rust::<Vec<List>>()
                 .expect("my_complex_list")
                 .iter()
-                .map(|it| it.as_rust().expect("number_list_c"))
+                .map(|it| it.as_r_rust().expect("number_list_c"))
                 .collect(),
         };
     }
@@ -493,35 +482,30 @@ fn select_table_map(session: &mut Session<NoneAuthenticator, TransportTcp>) -> b
 
     for row in all {
         let _ = Maps {
-            string_map: row.by_name::<Map>("my_string_map")
+            string_map: row.r_by_name::<Map>("my_string_map")
                 .expect("string_map")
-                .unwrap()
-                .as_rust()
+                .as_r_rust()
                 .expect("string_map"),
-            number_map: row.by_name::<Map>("my_number_map")
+            number_map: row.r_by_name::<Map>("my_number_map")
                 .expect("number_map")
-                .unwrap()
-                .as_rust()
+                .as_r_rust()
                 .expect("number_map"),
-            complex_map: row.by_name::<Map>("my_complex_map")
+            complex_map: row.r_by_name::<Map>("my_complex_map")
                 .expect("complex_map")
-                .unwrap()
-                .as_rust::<HashMap<String, Map>>()
+                .as_r_rust::<HashMap<String, Map>>()
                 .expect("my_complex_map")
                 .iter()
                 .fold(HashMap::new(), |mut hm, (k, v)| {
-                    hm.insert(k.clone(), v.as_rust().expect("complex_map_c"));
+                    hm.insert(k.clone(), v.as_r_rust().expect("complex_map_c"));
                     hm
                 }),
-            int_key_map: row.by_name::<Map>("my_int_key_map")
+            int_key_map: row.r_by_name::<Map>("my_int_key_map")
                 .expect("int_key_map")
-                .unwrap()
-                .as_rust()
+                .as_r_rust()
                 .expect("int_key_map"),
-            uuid_key_map: row.by_name::<Map>("my_uuid_key_map")
+            uuid_key_map: row.r_by_name::<Map>("my_uuid_key_map")
                 .expect("uuid_key_map")
-                .unwrap()
-                .as_rust()
+                .as_r_rust()
                 .expect("uuid_key_map"),
         };
     }
@@ -570,12 +554,10 @@ fn select_table_udt(session: &mut Session<NoneAuthenticator, TransportTcp>) -> b
 
     for row in all {
         let _ = Udt {
-            number: row.by_name::<UDT>("my_udt")
+            number: row.r_by_name::<UDT>("my_udt")
                 .expect("my_udt")
-                .unwrap()
-                .by_name("number")
-                .expect("number")
-                .unwrap(),
+                .r_by_name("number")
+                .expect("number"),
         };
     }
 
@@ -613,9 +595,7 @@ fn select_table_bool(session: &mut Session<NoneAuthenticator, TransportTcp>) ->
         .unwrap();
 
     for row in all {
-        let _: bool = row.get_by_name("my_boolean")
-            .expect("my_boolean")
-            .unwrap();
+        let _: bool = row.r_by_name("my_boolean").expect("my_boolean");
     }
 
     true
@@ -653,7 +633,7 @@ fn select_table_uuid(session: &mut Session<NoneAuthenticator, TransportTcp>) ->
         .unwrap();
 
     for row in all {
-        let _: Uuid = row.get_by_name("my_uuid").expect("my_uuid").unwrap();
+        let _: Uuid = row.r_by_name("my_uuid").expect("my_uuid");
     }
 
     true
@@ -692,10 +672,8 @@ fn select_table_float(session: &mut Session<NoneAuthenticator, TransportTcp>) ->
         .unwrap();
 
     for row in all {
-        let _: f32 = row.get_by_name("my_float").expect("my_float").unwrap();
-        let _: f64 = row.get_by_name("my_double")
-            .expect("my_double")
-            .unwrap();
+        let _: f32 = row.r_by_name("my_float").expect("my_float");
+        let _: f64 = row.r_by_name("my_double").expect("my_double");
     }
 
     true
@@ -732,7 +710,7 @@ fn select_table_blob(session: &mut Session<NoneAuthenticator, TransportTcp>) ->
         .unwrap();
 
     for row in all {
-        let _: Vec<u8> = row.get_by_name("my_blob").expect("my_blob").unwrap();
+        let _: Vec<u8> = row.r_by_name("my_blob").expect("my_blob");
     }
 
     true
@@ -771,9 +749,7 @@ fn select_table_timestamp(session: &mut Session<NoneAuthenticator, TransportTcp>
         .unwrap();
 
     for row in all {
-        let _: time::Timespec = row.get_by_name("my_timestamp")
-            .expect("my_timestamp")
-            .unwrap();
+        let _: time::Timespec = row.r_by_name("my_timestamp").expect("my_timestamp");
     }
 
     true
diff --git a/examples/read_table_into_struct.rs b/examples/read_table_into_struct.rs
index da8ad04..2e8d75d 100644
--- a/examples/read_table_into_struct.rs
+++ b/examples/read_table_into_struct.rs
@@ -64,23 +64,23 @@ fn main() {
                         let employees: Vec<Employee> = rows.iter()
                             .map(|row| {
                                 let mut employee = Employee { ..Default::default() };
-                                if let Some(Ok(id)) = row.get_by_name("emp_id") {
+                                if let Ok(Some(id)) = row.get_by_name("emp_id") {
                                     employee.id = id;
                                 }
 
-                                if let Some(Ok(emp_name)) = row.get_by_name("emp_name") {
+                                if let Ok(Some(emp_name)) = row.get_by_name("emp_name") {
                                     employee.emp_name = emp_name;
                                 }
 
-                                if let Some(Ok(emp_city)) = row.get_by_name("emp_city") {
+                                if let Ok(Some(emp_city)) = row.get_by_name("emp_city") {
                                     employee.emp_city = emp_city;
                                 }
 
-                                if let Some(Ok(emp_sal)) = row.get_by_name("emp_sal") {
+                                if let Ok(Some(emp_sal)) = row.get_by_name("emp_sal") {
                                     employee.emp_sal = emp_sal;
                                 }
 
-                                if let Some(Ok(emp_phone)) = row.get_by_name("emp_phone") {
+                                if let Ok(Some(emp_phone)) = row.get_by_name("emp_phone") {
                                     employee.emp_phone = emp_phone;
                                 }
 
diff --git a/examples/simple.rs b/examples/simple.rs
index e2f55fb..43ab624 100644
--- a/examples/simple.rs
+++ b/examples/simple.rs
@@ -64,23 +64,23 @@ fn main() {
                         let employees: Vec<Employee> = rows.iter()
                             .map(|row| {
                                 let mut employee = Employee { ..Default::default() };
-                                if let Some(Ok(id)) = row.get_by_name("emp_id") {
+                                if let Ok(Some(id)) = row.get_by_name("emp_id") {
                                     employee.id = id;
                                 }
 
-                                if let Some(Ok(emp_name)) = row.get_by_name("emp_name") {
+                                if let Ok(Some(emp_name)) = row.get_by_name("emp_name") {
                                     employee.emp_name = emp_name;
                                 }
 
-                                if let Some(Ok(emp_city)) = row.get_by_name("emp_city") {
+                                if let Ok(Some(emp_city)) = row.get_by_name("emp_city") {
                                     employee.emp_city = emp_city;
                                 }
 
-                                if let Some(Ok(emp_sal)) = row.get_by_name("emp_sal") {
+                                if let Ok(Some(emp_sal)) = row.get_by_name("emp_sal") {
                                     employee.emp_sal = emp_sal;
                                 }
 
-                                if let Some(Ok(emp_phone)) = row.get_by_name("emp_phone") {
+                                if let Ok(Some(emp_phone)) = row.get_by_name("emp_phone") {
                                     employee.emp_phone = emp_phone;
                                 }
 
diff --git a/src/authenticators.rs b/src/authenticators.rs
index d89c57c..f48d94d 100644
--- a/src/authenticators.rs
+++ b/src/authenticators.rs
@@ -80,14 +80,14 @@ mod tests {
         expected_token.push(0);
         expected_token.extend_from_slice("bar".as_bytes());
 
-        assert_eq!(auth.get_auth_token().into_plain(), expected_token);
+        assert_eq!(auth.get_auth_token().into_plain().unwrap(), expected_token);
     }
 
     #[test]
     fn test_authenticator_none_get_cassandra_name() {
         let auth = NoneAuthenticator;
         assert_eq!(auth.get_cassandra_name(), None);
-        assert_eq!(auth.get_auth_token().into_plain(), vec![0]);
+        assert_eq!(auth.get_auth_token().into_plain().unwrap(), vec![0]);
     }
 
     fn authenticator_tester<A: Authenticator>(_authenticator: Box<A>) {}
diff --git a/src/frame/frame_auth_challenge.rs b/src/frame/frame_auth_challenge.rs
index 7e0d527..6aa42ac 100644
--- a/src/frame/frame_auth_challenge.rs
+++ b/src/frame/frame_auth_challenge.rs
@@ -27,6 +27,7 @@ mod tests {
         let few_bytes = &[0, 0, 0, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
         let mut cursor: Cursor<&[u8]> = Cursor::new(few_bytes);
         let body = BodyResAuthChallenge::from_cursor(&mut cursor).unwrap();
-        assert_eq!(body.data.into_plain(), vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+        assert_eq!(body.data.into_plain().unwrap(),
+                   vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
     }
 }
diff --git a/src/macros.rs b/src/macros.rs
index 65b58e2..888bfd0 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -26,16 +26,21 @@ macro_rules! builder_opt_field {
 macro_rules! list_as_rust {
     ($($into_type:tt)*) => (
         impl AsRustType<Vec<$($into_type)*>> for List {
-            fn as_rust_type(&self) -> Result<Vec<$($into_type)*>> {
+            fn as_rust_type(&self) -> Result<Option<Vec<$($into_type)*>>> {
                 match self.metadata.value {
                     Some(ColTypeOptionValue::CList(ref type_option)) |
                     Some(ColTypeOptionValue::CSet(ref type_option)) => {
                         let type_option_ref = type_option.as_ref();
                         let convert = self
-                            .map(|bytes| as_rust_type!(type_option_ref, bytes, $($into_type)*)
-                                .unwrap());
+                            .map(|bytes| {
+                                as_rust_type!(type_option_ref, bytes, $($into_type)*)
+                                    .unwrap()
+                                    // item in a list supposed to be a non-null value.
+                                    // TODO: check if it's true
+                                    .unwrap()
+                            });
 
-                        Ok(convert)
+                        Ok(Some(convert))
                     },
                     _ => Err(Error::General(format!("Invalid conversion. \
                             Cannot convert {:?} into List (valid types: List, Set).",
@@ -52,7 +57,7 @@ macro_rules! map_as_rust {
     ($(K $key_type:tt)*, $(V $val_type:tt)*) => (
         impl AsRustType<HashMap<$($key_type)*, $($val_type)*>> for Map {
             /// Converts `Map` into `HashMap` for blob values.
-            fn as_rust_type(&self) -> Result<HashMap<$($key_type)*, $($val_type)*>> {
+            fn as_rust_type(&self) -> Result<Option<HashMap<$($key_type)*, $($val_type)*>>> {
                 match self.metadata.value {
                     Some(ColTypeOptionValue::CMap((ref key_type_option, ref val_type_option))) => {
                         let mut map = HashMap::with_capacity(self.data.len());
@@ -62,10 +67,12 @@ macro_rules! map_as_rust {
                             let val_type_option = val_type_option.as_ref();
                             let key = as_rust_type!(key_type_option, key, $($key_type)*)?;
                             let val = as_rust_type!(val_type_option, val, $($val_type)*)?;
-                            map.insert(key, val);
+                            if val.is_some() && key.is_some() {
+                                map.insert(key.unwrap(), val.unwrap());
+                            }
                         }
 
-                        Ok(map)
+                        Ok(Some(map))
                     }
                     _ => unreachable!()
                 }
@@ -80,13 +87,10 @@ macro_rules! map_as_rust {
 macro_rules! into_rust_by_name {
     (Row, $($into_type:tt)*) => (
         impl IntoRustByName<$($into_type)*> for Row {
-            fn get_by_name(&self, name: &str) -> Option<Result<$($into_type)*>> {
+            fn get_by_name(&self, name: &str) -> Result<Option<$($into_type)*>> {
                 self.get_col_spec_by_name(name)
-                    .map(|(col_spec, cbytes)| {
-                        if cbytes.is_empty() {
-                            return Err(column_is_empty_err());
-                        }
-
+                    .ok_or(column_is_empty_err())
+                    .and_then(|(col_spec, cbytes)| {
                         let ref col_type = col_spec.col_type;
                         as_rust_type!(col_type, cbytes, $($into_type)*)
                     })
@@ -96,14 +100,11 @@ macro_rules! into_rust_by_name {
 
     (UDT, $($into_type:tt)*) => (
         impl IntoRustByName<$($into_type)*> for UDT {
-            fn get_by_name(&self, name: &str) -> Option<Result<$($into_type)*>> {
-                self.data.get(name).map(|v| {
+            fn get_by_name(&self, name: &str) -> Result<Option<$($into_type)*>> {
+                self.data.get(name)
+                .ok_or(column_is_empty_err())
+                .and_then(|v| {
                     let &(ref col_type, ref bytes) = v;
-
-                    if bytes.as_plain().is_empty() {
-                        return Err(column_is_empty_err());
-                    }
-
                     let converted = as_rust_type!(col_type, bytes, $($into_type)*);
                     converted.map_err(|err| err.into())
                 })
@@ -112,8 +113,18 @@ macro_rules! into_rust_by_name {
     );
 }
 
-
-
+macro_rules! as_res_opt {
+    ($data_value:ident, $deserialize:expr) => (
+        match $data_value.as_plain() {
+            Some(ref bytes) => {
+                ($deserialize)(bytes)
+                    .map(|v| Some(v))
+                    .map_err(Into::into)
+            },
+            None => Ok(None)
+        }
+    )
+}
 
 /// Decodes any Cassandra data type into the corresponding Rust type,
 /// given the column type as `ColTypeOption` and the value as `CBytes`
@@ -122,8 +133,7 @@ macro_rules! as_rust_type {
     ($data_type_option:ident, $data_value:ident, Vec<u8>) => (
         match $data_type_option.id {
             ColType::Blob => {
-                decode_blob($data_value.as_plain())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_blob)
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into Vec<u8> (valid types: Blob).",
@@ -133,16 +143,13 @@ macro_rules! as_rust_type {
     ($data_type_option:ident, $data_value:ident, String) => (
         match $data_type_option.id {
             ColType::Custom => {
-                decode_custom($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_custom)
             }
             ColType::Ascii => {
-                decode_ascii($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_ascii)
             }
             ColType::Varchar => {
-                decode_varchar($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_varchar)
             }
             // TODO: clarify when to use decode_text.
             // it's not mentioned in
@@ -156,8 +163,7 @@ macro_rules! as_rust_type {
     ($data_type_option:ident, $data_value:ident, bool) => (
         match $data_type_option.id {
             ColType::Boolean => {
-                decode_boolean($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_boolean)
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into bool (valid types: Boolean).",
@@ -167,20 +173,16 @@ macro_rules! as_rust_type {
     ($data_type_option:ident, $data_value:ident, i64) => (
         match $data_type_option.id {
             ColType::Bigint => {
-                decode_bigint($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_bigint)
             }
             ColType::Timestamp => {
-                decode_timestamp($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_timestamp)
             }
             ColType::Time => {
-                decode_time($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_time)
             }
             ColType::Varint => {
-                decode_varint($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_varint)
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into i64 (valid types: Bigint, Timestamp, Time, Variant).",
@@ -190,12 +192,10 @@ macro_rules! as_rust_type {
     ($data_type_option:ident, $data_value:ident, i32) => (
         match $data_type_option.id {
             ColType::Int => {
-                decode_int($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_int)
             }
             ColType::Date => {
-                decode_date($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_date)
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into i32 (valid types: Int, Date).",
@@ -205,8 +205,7 @@ macro_rules! as_rust_type {
     ($data_type_option:ident, $data_value:ident, i16) => (
         match $data_type_option.id {
             ColType::Smallint => {
-                decode_smallint($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_smallint)
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into i16 (valid types: Smallint).",
@@ -216,8 +215,7 @@ macro_rules! as_rust_type {
     ($data_type_option:ident, $data_value:ident, i8) => (
         match $data_type_option.id {
             ColType::Tinyint => {
-                decode_tinyint($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_tinyint)
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into i8 (valid types: Tinyint).",
@@ -227,8 +225,7 @@ macro_rules! as_rust_type {
     ($data_type_option:ident, $data_value:ident, f64) => (
         match $data_type_option.id {
             ColType::Double => {
-                decode_double($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_double)
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into f64 (valid types: Double).",
@@ -238,12 +235,10 @@ macro_rules! as_rust_type {
     ($data_type_option:ident, $data_value:ident, f32) => (
         match $data_type_option.id {
             ColType::Decimal => {
-                decode_decimal($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_decimal)
             }
             ColType::Float => {
-                decode_float($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_float)
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into f32 (valid types: Decimal, Float).",
@@ -253,8 +248,7 @@ macro_rules! as_rust_type {
     ($data_type_option:ident, $data_value:ident, IpAddr) => (
         match $data_type_option.id {
             ColType::Inet => {
-                decode_inet($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_inet)
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into IpAddr (valid types: Inet).",
@@ -265,8 +259,7 @@ macro_rules! as_rust_type {
         match $data_type_option.id {
             ColType::Uuid |
             ColType::Timeuuid => {
-                decode_timeuuid($data_value.as_slice())
-                    .map_err(Into::into)
+                as_res_opt!($data_value, decode_timeuuid)
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into Uuid (valid types: Uuid, Timeuuid).",
@@ -277,9 +270,14 @@ macro_rules! as_rust_type {
         match $data_type_option.id {
             ColType::List |
             ColType::Set => {
-                decode_list($data_value.as_slice())
-                    .map(|data| List::new(data, $data_type_option.clone()))
-                    .map_err(Into::into)
+                match $data_value.as_slice() {
+                    Some(ref bytes) => {
+                        decode_list(bytes)
+                            .map(|data| Some(List::new(data, $data_type_option.clone())))
+                            .map_err(Into::into)
+                    },
+                    None => Ok(None)
+                }
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into List (valid types: List, Set).",
@@ -289,9 +287,14 @@ macro_rules! as_rust_type {
     ($data_type_option:ident, $data_value:ident, Map) => (
         match $data_type_option.id {
             ColType::Map => {
-                decode_map($data_value.as_slice())
-                    .map(|data| Map::new(data, $data_type_option.clone()))
-                    .map_err(Into::into)
+                match $data_value.as_slice() {
+                    Some(ref bytes) => {
+                        decode_map(bytes)
+                            .map(|data| Some(Map::new(data, $data_type_option.clone())))
+                            .map_err(Into::into)
+                    },
+                    None => Ok(None)
+                }
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into Map (valid types: Map).",
@@ -304,9 +307,14 @@ macro_rules! as_rust_type {
                 id: ColType::Udt,
                 value: Some(ColTypeOptionValue::UdtType(ref list_type_option))
             } => {
-                decode_udt($data_value.as_slice(), list_type_option.descriptions.len())
-                    .map(|data| UDT::new(data, list_type_option))
-                    .map_err(Into::into)
+                match $data_value.as_slice() {
+                    Some(ref bytes) => {
+                        decode_udt(bytes, list_type_option.descriptions.len())
+                            .map(|data| Some(UDT::new(data, list_type_option)))
+                            .map_err(Into::into)
+                    },
+                    None => Ok(None)
+                }
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into UDT (valid types: UDT).",
@@ -316,9 +324,15 @@ macro_rules! as_rust_type {
     ($data_type_option:ident, $data_value:ident, Timespec) => (
         match $data_type_option.id {
             ColType::Timestamp => {
-                decode_timestamp($data_value.as_slice())
-                    .map(|ts| Timespec::new(ts / 1_000, (ts % 1_000 * 1_000_000) as i32))
-                    .map_err(Into::into)
+                match $data_value.as_slice() {
+                    Some(ref bytes) => {
+                        decode_timestamp(bytes)
+                            .map(|ts| Some(Timespec::new(ts / 1_000,
+                                (ts % 1_000 * 1_000_000) as i32)))
+                            .map_err(Into::into)
+                    },
+                    None => Ok(None)
+                }
             }
             _ => Err(Error::General(format!("Invalid conversion. \
                     Cannot convert {:?} into Timespec (valid types: Timestamp).",
diff --git a/src/types/data_serialization_types.rs b/src/types/data_serialization_types.rs
index 47642b0..551899b 100644
--- a/src/types/data_serialization_types.rs
+++ b/src/types/data_serialization_types.rs
@@ -30,9 +30,9 @@ pub fn decode_bigint(bytes: &[u8]) -> Result<i64, io::Error> {
 }
 
 // Decodes Cassandra `blob` data (bytes) into Rust's `Result<Vec<u8>, io::Error>`
-pub fn decode_blob(bytes: Vec<u8>) -> Result<Vec<u8>, io::Error> {
+pub fn decode_blob(bytes: &Vec<u8>) -> Result<Vec<u8>, io::Error> {
     // in fact we just pass it through.
-    Ok(bytes)
+    Ok(bytes.clone())
 }
 
 // Decodes Cassandra `boolean` data (bytes) into Rust's `Result<i32, io::Error>`
@@ -221,7 +221,7 @@ mod tests {
 
     #[test]
     fn decode_blob_test() {
-        assert_eq!(decode_blob(vec![0, 0, 0, 3]).unwrap(), vec![0, 0, 0, 3]);
+        assert_eq!(decode_blob(&vec![0, 0, 0, 3]).unwrap(), vec![0, 0, 0, 3]);
     }
 
     #[test]
@@ -277,22 +277,22 @@ mod tests {
     fn decode_list_test() {
         let results = decode_list(&[0, 0, 0, 1, 0, 0, 0, 2, 1, 2]).unwrap();
         assert_eq!(results.len(), 1);
-        assert_eq!(results[0].as_plain(), vec![1, 2]);
+        assert_eq!(results[0].as_plain().unwrap(), vec![1, 2]);
     }
 
     #[test]
     fn decode_set_test() {
         let results = decode_set(&[0, 0, 0, 1, 0, 0, 0, 2, 1, 2]).unwrap();
         assert_eq!(results.len(), 1);
-        assert_eq!(results[0].as_plain(), vec![1, 2]);
+        assert_eq!(results[0].as_plain().unwrap(), vec![1, 2]);
     }
 
     #[test]
     fn decode_map_test() {
         let results = decode_map(&[0, 0, 0, 1, 0, 0, 0, 2, 1, 2, 0, 0, 0, 2, 2, 1]).unwrap();
         assert_eq!(results.len(), 1);
-        assert_eq!(results[0].0.as_plain(), vec![1, 2]);
-        assert_eq!(results[0].1.as_plain(), vec![2, 1]);
+        assert_eq!(results[0].0.as_plain().unwrap(), vec![1, 2]);
+        assert_eq!(results[0].1.as_plain().unwrap(), vec![2, 1]);
     }
 
     #[test]
@@ -332,14 +332,15 @@ mod tests {
     fn decode_udt_test() {
         let udt = decode_udt(&[0, 0, 0, 2, 1, 2], 1).unwrap();
         assert_eq!(udt.len(), 1);
-        assert_eq!(udt[0].as_plain(), vec![1, 2]);
+        assert_eq!(udt[0].as_plain().unwrap(), vec![1, 2]);
     }
 
     #[test]
     fn as_rust_blob_test() {
         let d_type = DataType { id: ColType::Blob };
         let data = CBytes::new(vec![1, 2, 3]);
-        assert_eq!(as_rust_type!(d_type, data, Vec<u8>).unwrap(), vec![1, 2, 3]);
+        assert_eq!(as_rust_type!(d_type, data, Vec<u8>).unwrap().unwrap(),
+                   vec![1, 2, 3]);
         let wrong_type = DataType { id: ColType::Map };
         assert!(as_rust_type!(wrong_type, data, Vec<u8>).is_err());
     }
@@ -350,9 +351,9 @@ mod tests {
         let type_ascii = DataType { id: ColType::Ascii };
         let type_varchar = DataType { id: ColType::Varchar };
         let data = CBytes::new(b"abc".to_vec());
-        assert_eq!(as_rust_type!(type_custom, data, String).unwrap(), "abc");
-        assert_eq!(as_rust_type!(type_ascii, data, String).unwrap(), "abc");
-        assert_eq!(as_rust_type!(type_varchar, data, String).unwrap(), "abc");
+        assert_eq!(as_rust_type!(type_custom, data, String).unwrap().unwrap(), "abc");
+        assert_eq!(as_rust_type!(type_ascii, data, String).unwrap().unwrap(), "abc");
+        assert_eq!(as_rust_type!(type_varchar, data, String).unwrap().unwrap(), "abc");
         let wrong_type = DataType { id: ColType::Map };
         assert!(as_rust_type!(wrong_type, data, String).is_err());
     }
@@ -362,8 +363,8 @@ mod tests {
         let type_boolean = DataType { id: ColType::Boolean };
         let data_true = CBytes::new(vec![1]);
         let data_false = CBytes::new(vec![0]);
-        assert_eq!(as_rust_type!(type_boolean, data_true, bool).unwrap(), true);
-        assert_eq!(as_rust_type!(type_boolean, data_false, bool).unwrap(), false);
+        assert_eq!(as_rust_type!(type_boolean, data_true, bool).unwrap().unwrap(), true);
+        assert_eq!(as_rust_type!(type_boolean, data_false, bool).unwrap().unwrap(), false);
         let wrong_type = DataType { id: ColType::Map };
         assert!(as_rust_type!(wrong_type, data_false, bool).is_err());
     }
@@ -375,10 +376,10 @@ mod tests {
         let type_time = DataType { id: ColType::Time };
         let type_varint = DataType { id: ColType::Varint };
         let data = CBytes::new(vec![0, 0, 0, 0, 0, 0, 0, 100]);
-        assert_eq!(as_rust_type!(type_bigint, data, i64).unwrap(), 100);
-        assert_eq!(as_rust_type!(type_timestamp, data, i64).unwrap(), 100);
-        assert_eq!(as_rust_type!(type_time, data, i64).unwrap(), 100);
-        assert_eq!(as_rust_type!(type_varint, data, i64).unwrap(), 100);
+        assert_eq!(as_rust_type!(type_bigint, data, i64).unwrap().unwrap(), 100);
+        assert_eq!(as_rust_type!(type_timestamp, data, i64).unwrap().unwrap(), 100);
+        assert_eq!(as_rust_type!(type_time, data, i64).unwrap().unwrap(), 100);
+        assert_eq!(as_rust_type!(type_varint, data, i64).unwrap().unwrap(), 100);
         let wrong_type = DataType { id: ColType::Map };
         assert!(as_rust_type!(wrong_type, data, i64).is_err());
     }
@@ -388,8 +389,8 @@ mod tests {
         let type_int = DataType { id: ColType::Int };
         let type_date = DataType { id: ColType::Date };
         let data = CBytes::new(vec![ 0, 0, 0, 100]);
-        assert_eq!(as_rust_type!(type_int, data, i32).unwrap(), 100);
-        assert_eq!(as_rust_type!(type_date, data, i32).unwrap(), 100);
+        assert_eq!(as_rust_type!(type_int, data, i32).unwrap().unwrap(), 100);
+        assert_eq!(as_rust_type!(type_date, data, i32).unwrap().unwrap(), 100);
         let wrong_type = DataType { id: ColType::Map };
         assert!(as_rust_type!(wrong_type, data, i32).is_err());
     }
@@ -398,7 +399,7 @@ mod tests {
     fn as_rust_i16_test() {
         let type_smallint = DataType { id: ColType::Smallint };
         let data = CBytes::new(vec![0, 100]);
-        assert_eq!(as_rust_type!(type_smallint, data, i16).unwrap(), 100);
+        assert_eq!(as_rust_type!(type_smallint, data, i16).unwrap().unwrap(), 100);
         let wrong_type = DataType { id: ColType::Map };
         assert!(as_rust_type!(wrong_type, data, i16).is_err());
     }
@@ -407,7 +408,7 @@ mod tests {
     fn as_rust_i8_test() {
         let type_tinyint = DataType { id: ColType::Tinyint };
         let data = CBytes::new(vec![100]);
-        assert_eq!(as_rust_type!(type_tinyint, data, i8).unwrap(), 100);
+        assert_eq!(as_rust_type!(type_tinyint, data, i8).unwrap().unwrap(), 100);
         let wrong_type = DataType { id: ColType::Map };
         assert!(as_rust_type!(wrong_type, data, i8).is_err());
     }
@@ -416,7 +417,7 @@ mod tests {
     fn as_rust_f64_test() {
         let type_double = DataType { id: ColType::Double };
         let data = CBytes::new(to_float_big(0.1 as f64));
-        assert_eq!(as_rust_type!(type_double, data, f64).unwrap(), 0.1);
+        assert_eq!(as_rust_type!(type_double, data, f64).unwrap().unwrap(), 0.1);
         let wrong_type = DataType { id: ColType::Map };
         assert!(as_rust_type!(wrong_type, data, f64).is_err());
     }
@@ -427,7 +428,7 @@ mod tests {
         let type_float = DataType { id: ColType::Float };
         let data = CBytes::new(to_float(0.1 as f32));
         // assert_eq!(as_rust_type!(type_decimal, data, f32).unwrap(), 100.0);
-        assert_eq!(as_rust_type!(type_float, data, f32).unwrap(), 0.1);
+        assert_eq!(as_rust_type!(type_float, data, f32).unwrap().unwrap(), 0.1);
         let wrong_type = DataType { id: ColType::Map };
         assert!(as_rust_type!(wrong_type, data, f32).is_err());
     }
@@ -438,7 +439,7 @@ mod tests {
         let data = CBytes::new(vec![0, 0, 0, 0]);
 
         match as_rust_type!(type_inet, data, IpAddr) {
-            Ok(IpAddr::V4(ref ip)) => assert_eq!(ip.octets(), [0, 0, 0, 0]),
+            Ok(Some(IpAddr::V4(ref ip))) => assert_eq!(ip.octets(), [0, 0, 0, 0]),
             _ => panic!("wrong ip v4 address"),
         }
         let wrong_type = DataType { id: ColType::Map };
diff --git a/src/types/list.rs b/src/types/list.rs
index 2c18191..0bf0f43 100644
--- a/src/types/list.rs
+++ b/src/types/list.rs
@@ -35,18 +35,25 @@ impl AsRust for List {}
 
 impl AsRustType<Vec<Vec<u8>>> for List {
     /// Converts cassandra list of blobs into Rust `Vec<Vec<u8>>`
-    fn as_rust_type(&self) -> Result<Vec<Vec<u8>>> {
+    fn as_rust_type(&self) -> Result<Option<Vec<Vec<u8>>>> {
         match self.metadata.value {
             Some(ColTypeOptionValue::CList(ref type_option)) => {
                 match type_option.id {
                     // XXX unwrap
-                    ColType::Blob => Ok(self.map(|bytes| decode_blob(bytes.as_plain()).unwrap())),
+                    ColType::Blob => {
+                        Ok(self.map(|bytes| decode_blob(&bytes.as_plain().unwrap()).unwrap()))
+                            .map(Some)
+                    }
                     _ => unreachable!(),
                 }
             }
             Some(ColTypeOptionValue::CSet(ref type_option)) => {
                 match type_option.id {
-                    ColType::Blob => Ok(self.map(|bytes| decode_blob(bytes.as_plain()).unwrap())),
+                    ColType::Blob => {
+                        // XXX unwrap
+                        Ok(self.map(|bytes| decode_blob(&bytes.as_plain().unwrap()).unwrap()))
+                            .map(Some)
+                    }
                     _ => unreachable!(),
                 }
             }
diff --git a/src/types/mod.rs b/src/types/mod.rs
index e51dd40..c66b425 100644
--- a/src/types/mod.rs
+++ b/src/types/mod.rs
@@ -10,7 +10,7 @@ use std::io::{Cursor, Read};
 use std::net::SocketAddr;
 use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt, ByteOrder};
 use {FromBytes, IntoBytes, FromCursor};
-use error::Result as CDRSResult;
+use error::{Result as CDRSResult, Error as CDRSError, column_is_empty_err};
 use types::data_serialization_types::decode_inet;
 
 #[macro_use]
@@ -22,30 +22,53 @@ pub mod udt;
 pub mod value;
 
 /// Should be used to represent a single column as a Rust value.
-// TODO: change Option to Result, create a new type of error for that.
 pub trait AsRustType<T> {
-    fn as_rust_type(&self) -> CDRSResult<T>;
+    fn as_rust_type(&self) -> CDRSResult<Option<T>>;
+
+    fn as_r_type(&self) -> CDRSResult<T> {
+        self.as_rust_type()
+            .and_then(|op| op.ok_or(CDRSError::from("Value is null or non-set")))
+    }
 }
 
 pub trait AsRust {
-    fn as_rust<R>(&self) -> CDRSResult<R>
+    fn as_rust<R>(&self) -> CDRSResult<Option<R>>
         where Self: AsRustType<R>
     {
         self.as_rust_type()
     }
+
+    fn as_r_rust<T>(&self) -> CDRSResult<T>
+        where Self: AsRustType<T>
+    {
+        self.as_rust()
+            .and_then(|op| op.ok_or("Value is null or non-set".into()))
+    }
 }
 
 /// Should be used to return a single column as Rust value by its name.
 pub trait IntoRustByName<R> {
-    fn get_by_name(&self, name: &str) -> Option<CDRSResult<R>>;
+    fn get_by_name(&self, name: &str) -> CDRSResult<Option<R>>;
+
+    fn get_r_by_name(&self, name: &str) -> CDRSResult<R> {
+        self.get_by_name(name)
+            .and_then(|op| op.ok_or(column_is_empty_err()))
+    }
 }
 
 pub trait ByName {
-    fn by_name<R>(&self, name: &str) -> Option<CDRSResult<R>>
+    fn by_name<R>(&self, name: &str) -> CDRSResult<Option<R>>
         where Self: IntoRustByName<R>
     {
         self.get_by_name(name)
     }
+
+    fn r_by_name<R>(&self, name: &str) -> CDRSResult<R>
+        where Self: IntoRustByName<R>
+    {
+        self.by_name(name)
+            .and_then(|op| op.ok_or(column_is_empty_err()))
+    }
 }
 
 /// Tries to converts u64 numerical value into array of n bytes.
@@ -410,28 +433,32 @@ impl FromCursor for CStringList {
 //
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
-/// The structure that represents Cassandra byte type
+/// The structure that represents Cassandra byte type.
 pub struct CBytes {
-    bytes: Vec<u8>,
+    bytes: Option<Vec<u8>>,
 }
 
 impl CBytes {
     pub fn new(bytes: Vec<u8>) -> CBytes {
-        CBytes { bytes: bytes }
+        CBytes { bytes: Some(bytes) }
     }
     /// Converts `CBytes` into a plain array of bytes
-    pub fn into_plain(self) -> Vec<u8> {
+    pub fn into_plain(self) -> Option<Vec<u8>> {
         self.bytes
     }
     // TODO: try to replace usage of `as_plain` by `as_slice`
-    pub fn as_plain(&self) -> Vec<u8> {
+    pub fn as_plain(&self) -> Option<Vec<u8>> {
         self.bytes.clone()
     }
-    pub fn as_slice(&self) -> &[u8] {
-        self.bytes.as_slice()
+    pub fn as_slice(&self) -> Option<&[u8]> {
+        match self.bytes {
+            Some(ref v) => Some(v.as_slice()),
+            None => None,
+        }
+        // self.bytes.map(|v| v.as_slice())
     }
     pub fn is_empty(&self) -> bool {
-        self.bytes.is_empty()
+        self.bytes.is_some()
     }
 }
 
@@ -442,7 +469,7 @@ impl FromCursor for CBytes {
         let len = CInt::from_cursor(&mut cursor)?;
         // null or not set value
         if len < 0 {
-            return Ok(CBytes { bytes: vec![] });
+            return Ok(CBytes { bytes: None });
         }
 
         cursor_next_value(&mut cursor, len as u64).map(CBytes::new)
@@ -452,26 +479,40 @@ impl FromCursor for CBytes {
 // Use extended Rust Vec<u8> as Cassandra [bytes]
 impl IntoBytes for CBytes {
     fn into_cbytes(&self) -> Vec<u8> {
-        let mut v: Vec<u8> = vec![];
-        let l = self.bytes.len() as i32;
-        v.extend_from_slice(to_int(l).as_slice());
-        v.extend_from_slice(self.bytes.as_slice());
-        v
+        match self.bytes {
+            Some(ref b) => {
+                let mut v: Vec<u8> = vec![];
+                let l = b.len() as i32;
+                v.extend_from_slice(to_int(l).as_slice());
+                v.extend_from_slice(b.as_slice());
+                v
+            }
+            None => vec![],
+        }
+        // self.bytes
+        //     .map(|b| {
+        //              let mut v: Vec<u8> = vec![];
+        //              let l = b.len() as i32;
+        //              v.extend_from_slice(to_int(l).as_slice());
+        //              v.extend_from_slice(b.as_slice());
+        //              v
+        //          })
+        //     .unwrap_or(vec![])
     }
 }
 
 /// Cassandra short bytes
 #[derive(Debug, Clone)]
 pub struct CBytesShort {
-    bytes: Vec<u8>,
+    bytes: Option<Vec<u8>>,
 }
 
 impl CBytesShort {
     pub fn new(bytes: Vec<u8>) -> CBytesShort {
-        CBytesShort { bytes: bytes }
+        CBytesShort { bytes: Some(bytes) }
     }
     /// Converts `CBytesShort` into plain vector of bytes;
-    pub fn into_plain(self) -> Vec<u8> {
+    pub fn into_plain(self) -> Option<Vec<u8>> {
         self.bytes
     }
 }
@@ -480,8 +521,13 @@ impl FromCursor for CBytesShort {
     /// from_cursor gets Cursor who's position is set such that it should be a start of a [bytes].
     /// It reads required number of bytes and returns a CBytes
     fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CBytesShort> {
-        let len: u64 = CIntShort::from_cursor(&mut cursor)? as u64;
-        cursor_next_value(&mut cursor, len)
+        let len = CIntShort::from_cursor(&mut cursor)?;
+
+        if len < 0 {
+            return Ok(CBytesShort { bytes: None });
+        }
+
+        cursor_next_value(&mut cursor, len as u64)
             .map(CBytesShort::new)
             .map_err(Into::into)
     }
@@ -490,11 +536,25 @@ impl FromCursor for CBytesShort {
 // Use extended Rust Vec<u8> as Cassandra [bytes]
 impl IntoBytes for CBytesShort {
     fn into_cbytes(&self) -> Vec<u8> {
-        let mut v: Vec<u8> = vec![];
-        let l = self.bytes.len() as i16;
-        v.extend_from_slice(to_short(l).as_slice());
-        v.extend_from_slice(self.bytes.as_slice());
-        v
+        match self.bytes {
+            Some(ref b) => {
+                let mut v: Vec<u8> = vec![];
+                let l = b.len() as i16;
+                v.extend_from_slice(to_short(l).as_slice());
+                v.extend_from_slice(b.as_slice());
+                v
+            }
+            None => vec![],
+        }
+        // self.bytes
+        //     .map(|b| {
+        //              let mut v: Vec<u8> = vec![];
+        //              let l = b.len() as i16;
+        //              v.extend_from_slice(to_short(l).as_slice());
+        //              v.extend_from_slice(b.as_slice());
+        //              v
+        //          })
+        //     .unwrap_or(vec![])
     }
 }
 
@@ -669,7 +729,7 @@ mod tests {
     #[test]
     fn test_cbytes_into_plain() {
         let cbytes = CBytes::new(vec![1, 2, 3]);
-        assert_eq!(cbytes.into_plain(), &[1, 2, 3]);
+        assert_eq!(cbytes.into_plain().unwrap(), &[1, 2, 3]);
     }
 
     #[test]
@@ -677,14 +737,14 @@ mod tests {
         let a = &[0, 0, 0, 3, 1, 2, 3];
         let mut cursor: Cursor<&[u8]> = Cursor::new(a);
         let cbytes = CBytes::from_cursor(&mut cursor).unwrap();
-        assert_eq!(cbytes.into_plain(), &[1, 2, 3]);
+        assert_eq!(cbytes.into_plain().unwrap(), vec![1, 2, 3]);
     }
 
     #[test]
     fn test_cbytes_into_cbytes() {
         let bytes_vec = vec![1, 2, 3];
         let cbytes = CBytes::new(bytes_vec);
-        assert_eq!(cbytes.into_cbytes(), &[0, 0, 0, 3, 1, 2, 3]);
+        assert_eq!(cbytes.into_cbytes(), vec![0, 0, 0, 3, 1, 2, 3]);
     }
 
     // CBytesShort
@@ -697,7 +757,7 @@ mod tests {
     #[test]
     fn test_cbytesshort_into_plain() {
         let cbytes = CBytesShort::new(vec![1, 2, 3]);
-        assert_eq!(cbytes.into_plain(), &[1, 2, 3]);
+        assert_eq!(cbytes.into_plain().unwrap(), vec![1, 2, 3]);
     }
 
     #[test]
@@ -705,14 +765,14 @@ mod tests {
         let a = &[0, 3, 1, 2, 3];
         let mut cursor: Cursor<&[u8]> = Cursor::new(a);
         let cbytes = CBytesShort::from_cursor(&mut cursor).unwrap();
-        assert_eq!(cbytes.into_plain(), &[1, 2, 3]);
+        assert_eq!(cbytes.into_plain().unwrap(), vec![1, 2, 3]);
     }
 
     #[test]
     fn test_cbytesshort_into_cbytes() {
         let bytes_vec: Vec<u8> = vec![1, 2, 3];
         let cbytes = CBytesShort::new(bytes_vec);
-        assert_eq!(cbytes.into_cbytes(), &[0, 3, 1, 2, 3]);
+        assert_eq!(cbytes.into_cbytes(), vec![0, 3, 1, 2, 3]);
     }
 
     // CInt
diff --git a/src/types/rows.rs b/src/types/rows.rs
index b02b31c..a2a82e5 100644
--- a/src/types/rows.rs
+++ b/src/types/rows.rs
@@ -44,12 +44,13 @@ impl Row {
 }
 
 impl IntoRustByName<Vec<u8>> for Row {
-    fn get_by_name(&self, name: &str) -> Option<Result<Vec<u8>>> {
+    fn get_by_name(&self, name: &str) -> Result<Option<Vec<u8>>> {
         self.get_col_spec_by_name(name)
-            .map(|(col_spec, cbytes)| {
-                     let ref col_type = col_spec.col_type;
-                     as_rust_type!(col_type, cbytes, Vec<u8>)
-                 })
+            .ok_or(column_is_empty_err())
+            .and_then(|(col_spec, cbytes)| {
+                          let ref col_type = col_spec.col_type;
+                          as_rust_type!(col_type, cbytes, Vec<u8>)
+                      })
     }
 }
 
diff --git a/src/types/udt.rs b/src/types/udt.rs
index 7a928d7..71dade2 100644
--- a/src/types/udt.rs
+++ b/src/types/udt.rs
@@ -35,14 +35,20 @@ impl UDT {
 }
 
 impl IntoRustByName<Vec<u8>> for UDT {
-    fn get_by_name(&self, name: &str) -> Option<Result<Vec<u8>>> {
+    fn get_by_name(&self, name: &str) -> Result<Option<Vec<u8>>> {
         self.data
             .get(name)
-            .map(|v| {
+            .ok_or(column_is_empty_err())
+            .and_then(|v| {
                 let &(ref col_type, ref bytes) = v;
 
                 match col_type.id {
-                    ColType::Blob => decode_blob(bytes.as_plain()).map_err(|err| err.into()),
+                    // XXX: unwrap Option
+                    ColType::Blob => {
+                        decode_blob(&bytes.as_plain().unwrap())
+                            .map(Some)
+                            .map_err(Into::into)
+                    }
                     _ => Err(Error::General(format!("Cannot parse  {:?} into UDT ", col_type.id))),
                 }
             })


Test patch:
diff --git a/tests/create_insert_table.rs b/tests/create_insert_table.rs
index 48ca0f1..d713914 100644
--- a/tests/create_insert_table.rs
+++ b/tests/create_insert_table.rs
@@ -124,32 +124,32 @@ fn read_from_user_table() {
 
     match query_op {
         Ok(res) => {
-            let res_body = res.get_body().unwrap();
+            let res_body = res.get_body().expect("shold have body");
             if let Some(rows) = res_body.into_rows() {
                 let users: Vec<User> = rows.iter()
                     .map(|row| {
                         let mut user = User { ..Default::default() };
-                        if let Some(Ok(user_name)) = row.get_by_name("user_name") {
+                        if let Ok(Some(user_name)) = row.get_by_name("user_name") {
                             user.user_name = user_name;
                         }
 
-                        if let Some(Ok(password)) = row.get_by_name("password") {
+                        if let Ok(Some(password)) = row.get_by_name("password") {
                             user.password = password;
                         }
 
-                        if let Some(Ok(gender)) = row.get_by_name("gender") {
+                        if let Ok(Some(gender)) = row.get_by_name("gender") {
                             user.gender = gender;
                         }
 
-                        if let Some(Ok(session_token)) = row.get_by_name("session_token") {
+                        if let Ok(Some(session_token)) = row.get_by_name("session_token") {
                             user.session_token = session_token;
                         }
 
-                        if let Some(Ok(state)) = row.get_by_name("state") {
+                        if let Ok(Some(state)) = row.get_by_name("state") {
                             user.state = state;
                         }
 
-                        if let Some(Ok(m)) = row.get_by_name("some_map") {
+                        if let Ok(Some(m)) = row.get_by_name("some_map") {
                             user.some_map = Some(m);
                         }
 
diff --git a/tests/crud_operations.rs b/tests/crud_operations.rs
index 334ec34..1b9e77c 100644
--- a/tests/crud_operations.rs
+++ b/tests/crud_operations.rs
@@ -307,16 +307,10 @@ fn select_all_ints(session: &mut Session<NoneAuthenticator, TransportTcp>) -> bo
 
     for row in all {
         let _ = Ints {
-            bigint: row.get_by_name("my_bigint")
-                .expect("my_bigint")
-                .unwrap(),
-            int: row.get_by_name("my_int").expect("my_int").unwrap(),
-            smallint: row.get_by_name("my_smallint")
-                .expect("my_smallint")
-                .unwrap(),
-            tinyint: row.get_by_name("my_tinyint")
-                .expect("my_tinyint")
-                .unwrap(),
+            bigint: row.r_by_name("my_bigint").expect("my_bigint"),
+            int: row.r_by_name("my_int").expect("my_int"),
+            smallint: row.r_by_name("my_smallint").expect("my_smallint"),
+            tinyint: row.r_by_name("my_tinyint").expect("my_tinyint"),
         };
     }
 
@@ -379,11 +373,9 @@ fn select_table_str(session: &mut Session<NoneAuthenticator, TransportTcp>) -> b
 
     for row in all {
         let _ = Strings {
-            my_ascii: row.get_by_name("my_ascii").expect("my_ascii").unwrap(),
-            my_text: row.get_by_name("my_text").expect("my_text").unwrap(),
-            my_varchar: row.get_by_name("my_varchar")
-                .expect("my_ascii")
-                .unwrap(),
+            my_ascii: row.r_by_name("my_ascii").expect("my_ascii"),
+            my_text: row.r_by_name("my_text").expect("my_text"),
+            my_varchar: row.r_by_name("my_varchar").expect("my_ascii"),
         };
     }
 
@@ -430,24 +422,21 @@ fn select_table_list(session: &mut Session<NoneAuthenticator, TransportTcp>) ->
 
     for row in all {
         let _ = Lists {
-            string_list: row.by_name::<List>("my_string_list") // intermediate type is required
+            string_list: row.r_by_name::<List>("my_string_list") // intermediate type is required
                 .expect("string_list")
-                .unwrap()
-                .as_rust::<Vec<String>>() // final type is not required, it could be find
+                .as_r_rust::<Vec<String>>() // final type is not required, it could be find
                 // authomatically
                 .expect("string_list"),
-            number_list: row.by_name::<List>("my_number_list")
+            number_list: row.r_by_name::<List>("my_number_list")
                 .expect("number_list")
-                .unwrap()
-                .as_rust()
+                .as_r_rust()
                 .expect("number_list"),
-            complex_list: row.by_name::<List>("my_complex_list")
+            complex_list: row.r_by_name::<List>("my_complex_list")
                 .expect("complex_list")
-                .unwrap()
-                .as_rust::<Vec<List>>()
+                .as_r_rust::<Vec<List>>()
                 .expect("my_complex_list")
                 .iter()
-                .map(|it| it.as_rust().expect("number_list_c"))
+                .map(|it| it.as_r_rust().expect("number_list_c"))
                 .collect(),
         };
     }
@@ -503,35 +492,30 @@ fn select_table_map(session: &mut Session<NoneAuthenticator, TransportTcp>) -> b
 
     for row in all {
         let _ = Maps {
-            string_map: row.by_name::<Map>("my_string_map")
+            string_map: row.r_by_name::<Map>("my_string_map")
                 .expect("string_map")
-                .unwrap()
-                .as_rust()
+                .as_r_rust()
                 .expect("string_map"),
-            number_map: row.by_name::<Map>("my_number_map")
+            number_map: row.r_by_name::<Map>("my_number_map")
                 .expect("number_map")
-                .unwrap()
-                .as_rust()
+                .as_r_rust()
                 .expect("number_map"),
-            complex_map: row.by_name::<Map>("my_complex_map")
+            complex_map: row.r_by_name::<Map>("my_complex_map")
                 .expect("complex_map")
-                .unwrap()
-                .as_rust::<HashMap<String, Map>>()
+                .as_r_rust::<HashMap<String, Map>>()
                 .expect("my_complex_map")
                 .iter()
                 .fold(HashMap::new(), |mut hm, (k, v)| {
-                    hm.insert(k.clone(), v.as_rust().expect("complex_map_c"));
+                    hm.insert(k.clone(), v.as_r_rust().expect("complex_map_c"));
                     hm
                 }),
-            int_key_map: row.by_name::<Map>("my_int_key_map")
+            int_key_map: row.r_by_name::<Map>("my_int_key_map")
                 .expect("int_key_map")
-                .unwrap()
-                .as_rust()
+                .as_r_rust()
                 .expect("int_key_map"),
-            uuid_key_map: row.by_name::<Map>("my_uuid_key_map")
+            uuid_key_map: row.r_by_name::<Map>("my_uuid_key_map")
                 .expect("uuid_key_map")
-                .unwrap()
-                .as_rust()
+                .as_r_rust()
                 .expect("uuid_key_map"),
         };
     }
@@ -580,12 +564,10 @@ fn select_table_udt(session: &mut Session<NoneAuthenticator, TransportTcp>) -> b
 
     for row in all {
         let _ = Udt {
-            number: row.by_name::<UDT>("my_udt")
+            number: row.r_by_name::<UDT>("my_udt")
                 .expect("my_udt")
-                .unwrap()
-                .by_name("number")
-                .expect("number")
-                .unwrap(),
+                .r_by_name("number")
+                .expect("number"),
         };
     }
 
@@ -623,9 +605,7 @@ fn select_table_bool(session: &mut Session<NoneAuthenticator, TransportTcp>) ->
         .unwrap();
 
     for row in all {
-        let _: bool = row.get_by_name("my_boolean")
-            .expect("my_boolean")
-            .unwrap();
+        let _: bool = row.r_by_name("my_boolean").expect("my_boolean");
     }
 
     true
@@ -663,7 +643,7 @@ fn select_table_uuid(session: &mut Session<NoneAuthenticator, TransportTcp>) ->
         .unwrap();
 
     for row in all {
-        let _: Uuid = row.get_by_name("my_uuid").expect("my_uuid").unwrap();
+        let _: Uuid = row.r_by_name("my_uuid").expect("my_uuid");
     }
 
     true
@@ -702,10 +682,8 @@ fn select_table_float(session: &mut Session<NoneAuthenticator, TransportTcp>) ->
         .unwrap();
 
     for row in all {
-        let _: f32 = row.get_by_name("my_float").expect("my_float").unwrap();
-        let _: f64 = row.get_by_name("my_double")
-            .expect("my_double")
-            .unwrap();
+        let _: f32 = row.r_by_name("my_float").expect("my_float");
+        let _: f64 = row.r_by_name("my_double").expect("my_double");
     }
 
     true
@@ -742,7 +720,7 @@ fn select_table_blob(session: &mut Session<NoneAuthenticator, TransportTcp>) ->
         .unwrap();
 
     for row in all {
-        let _: Vec<u8> = row.get_by_name("my_blob").expect("my_blob").unwrap();
+        let _: Vec<u8> = row.r_by_name("my_blob").expect("my_blob");
     }
 
     true
@@ -784,9 +762,7 @@ fn select_table_timestamp(session: &mut Session<NoneAuthenticator, TransportTcp>
         .unwrap();
 
     for row in all {
-        let timestamp: time::Timespec = row.get_by_name("my_timestamp")
-            .expect("my_timestamp")
-            .unwrap();
+        let timestamp: time::Timespec = row.r_by_name("my_timestamp").expect("my_timestamp");
         assert_eq!(timestamp,
                    time::Timespec {
                        sec: 1491938018,