<commit_before>/// instead of writing functions which resemble
/// ```
/// pub fn query<'a> (&'a mut self,query: String) -> &'a mut Self{
///     self.query = Some(query);
///            self
/// }
/// ```
/// and repeating it for all the attributes; it is extracted out as a macro so that code
/// is more concise see
/// @https://doc.rust-lang.org/book/method-syntax.html
///
///
///
macro_rules! builder_opt_field {
    ($field:ident, $field_type:ty) => {
        pub fn $field(mut self,
                          $field: $field_type) -> Self {
            self.$field = Some($field);
            self
        }
    };
}

macro_rules! list_as_rust {
    ($($into_type:tt)*) => (
        impl AsRustType<Vec<$($into_type)*>> for List {
            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()
                                    // item in a list supposed to be a non-null value.
                                    // TODO: check if it's true
                                    .unwrap()
                            });

                        Ok(Some(convert))
                    },
                    _ => Err(Error::General(format!("Invalid conversion. \
                            Cannot convert {:?} into List (valid types: List, Set).",
                            self.metadata.value)))
                }
            }
        }
    );
}

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<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());

                        for &(ref key, ref val) in self.data.iter() {
                            let key_type_option = key_type_option.as_ref();
                            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)*)?;
                            if val.is_some() && key.is_some() {
                                map.insert(key.unwrap(), val.unwrap());
                            }
                        }

                        Ok(Some(map))
                    }
                    _ => unreachable!()
                }
            }
        }
    );
}

macro_rules! into_rust_by_name {
    (Row, $($into_type:tt)*) => (
        impl IntoRustByName<$($into_type)*> for Row {
            fn get_by_name(&self, name: &str) -> Result<Option<$($into_type)*>> {
                self.get_col_spec_by_name(name)
                    .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)*)
                    })
            }
        }
    );

    (UDT, $($into_type:tt)*) => (
        impl IntoRustByName<$($into_type)*> for UDT {
            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;
                    let converted = as_rust_type!(col_type, bytes, $($into_type)*);
                    converted.map_err(|err| err.into())
                })
            }
        }
    );
}

macro_rules! into_rust_by_index {
    (Tuple, $($into_type:tt)*) => (
        impl IntoRustByIndex<$($into_type)*> for Tuple {
            fn get_by_index(&self, index: usize) -> Result<Option<$($into_type)*>> {
                self.data
                    .get(index)
                    .ok_or(column_is_empty_err())
                    .and_then(|v| {
                        let &(ref col_type, ref bytes) = v;
                        let converted = as_rust_type!(col_type, bytes, $($into_type)*);
                        converted.map_err(|err| err.into())
                    })
            }
        }
    );

    (Row, $($into_type:tt)*) => (
        impl IntoRustByIndex<$($into_type)*> for Row {
            fn get_by_index(&self, index: usize) -> Result<Option<$($into_type)*>> {
                self.get_col_spec_by_index(index)
                    .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)*)
                    })
            }
        }
    );
}

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`
/// plus the matching Rust type.
macro_rules! as_rust_type {
    ($data_type_option:ident, $data_value:ident, Vec<u8>) => (
        match $data_type_option.id {
            ColType::Blob => {
                as_res_opt!($data_value, decode_blob)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into Vec<u8> (valid types: Blob).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, String) => (
        match $data_type_option.id {
            ColType::Custom => {
                as_res_opt!($data_value, decode_custom)
            }
            ColType::Ascii => {
                as_res_opt!($data_value, decode_ascii)
            }
            ColType::Varchar => {
                as_res_opt!($data_value, decode_varchar)
            }
            // TODO: clarify when to use decode_text.
            // it's not mentioned in
            // https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L582
            // ColType::XXX => decode_text($data_value)?
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into String (valid types: Custom, Ascii, Varchar).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, bool) => (
        match $data_type_option.id {
            ColType::Boolean => {
                as_res_opt!($data_value, decode_boolean)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into bool (valid types: Boolean).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, i64) => (
        match $data_type_option.id {
            ColType::Bigint => {
                as_res_opt!($data_value, decode_bigint)
            }
            ColType::Timestamp => {
                as_res_opt!($data_value, decode_timestamp)
            }
            ColType::Time => {
                as_res_opt!($data_value, decode_time)
            }
            ColType::Varint => {
                as_res_opt!($data_value, decode_varint)
            }
            ColType::Counter => {
                as_res_opt!($data_value, decode_bigint)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into i64 (valid types: Bigint, Timestamp, Time, Variant, Counter).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, i32) => (
        match $data_type_option.id {
            ColType::Int => {
                as_res_opt!($data_value, decode_int)
            }
            ColType::Date => {
                as_res_opt!($data_value, decode_date)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into i32 (valid types: Int, Date).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, i16) => (
        match $data_type_option.id {
            ColType::Smallint => {
                as_res_opt!($data_value, decode_smallint)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into i16 (valid types: Smallint).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, i8) => (
        match $data_type_option.id {
            ColType::Tinyint => {
                as_res_opt!($data_value, decode_tinyint)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into i8 (valid types: Tinyint).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, f64) => (
        match $data_type_option.id {
            ColType::Double => {
                as_res_opt!($data_value, decode_double)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into f64 (valid types: Double).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, f32) => (
        match $data_type_option.id {
            ColType::Decimal => {
                as_res_opt!($data_value, decode_decimal)
            }
            ColType::Float => {
                as_res_opt!($data_value, decode_float)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into f32 (valid types: Decimal, Float).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, IpAddr) => (
        match $data_type_option.id {
            ColType::Inet => {
                as_res_opt!($data_value, decode_inet)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into IpAddr (valid types: Inet).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, Uuid) => (
        match $data_type_option.id {
            ColType::Uuid |
            ColType::Timeuuid => {
                as_res_opt!($data_value, decode_timeuuid)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into Uuid (valid types: Uuid, Timeuuid).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, List) => (
        match $data_type_option.id {
            ColType::List |
            ColType::Set => {
                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).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, Map) => (
        match $data_type_option.id {
            ColType::Map => {
                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).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, UDT) => (
        match *$data_type_option {
            ColTypeOption {
                id: ColType::Udt,
                value: Some(ColTypeOptionValue::UdtType(ref list_type_option))
            } => {
                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).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, Tuple) => (
        match *$data_type_option {
            ColTypeOption {
                id: ColType::Tuple,
                value: Some(ColTypeOptionValue::TupleType(ref list_type_option))
            } => {
                match $data_value.as_slice() {
                    Some(ref bytes) => {
                        decode_tuple(bytes, list_type_option.types.len())
                            .map(|data| Some(Tuple::new(data, list_type_option)))
                            .map_err(Into::into)
                    },
                    None => Ok(None)
                }
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into Tuple (valid types: tuple).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, Timespec) => (
        match $data_type_option.id {
            ColType::Timestamp => {
                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).",
                    $data_type_option.id)))
        }
    );
}
<commit_msg>Fix rustfmt<commit_after>/// instead of writing functions which resemble
/// ```
/// pub fn query<'a> (&'a mut self,query: String) -> &'a mut Self{
///     self.query = Some(query);
///            self
/// }
/// ```
/// and repeating it for all the attributes; it is extracted out as a macro so that code
/// is more concise see
/// @https://doc.rust-lang.org/book/method-syntax.html
///
///
///
macro_rules! builder_opt_field {
    ($field:ident, $field_type:ty) => {
        pub fn $field(mut self,
                          $field: $field_type) -> Self {
            self.$field = Some($field);
            self
        }
    };
}

macro_rules! list_as_rust {
    ($($into_type:tt)*) => (
        impl AsRustType<Vec<$($into_type)*>> for List {
            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()
                                    // item in a list supposed to be a non-null value.
                                    // TODO: check if it's true
                                    .unwrap()
                            });

                        Ok(Some(convert))
                    },
                    _ => Err(Error::General(format!("Invalid conversion. \
                            Cannot convert {:?} into List (valid types: List, Set).",
                            self.metadata.value)))
                }
            }
        }
    );
}

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<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());

                        for &(ref key, ref val) in self.data.iter() {
                            let key_type_option = key_type_option.as_ref();
                            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)*)?;
                            if val.is_some() && key.is_some() {
                                map.insert(key.unwrap(), val.unwrap());
                            }
                        }

                        Ok(Some(map))
                    }
                    _ => unreachable!()
                }
            }
        }
    );
}

macro_rules! into_rust_by_name {
    (Row, $($into_type:tt)*) => (
        impl IntoRustByName<$($into_type)*> for Row {
            fn get_by_name(&self, name: &str) -> Result<Option<$($into_type)*>> {
                self.get_col_spec_by_name(name)
                    .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)*)
                    })
            }
        }
    );

    (UDT, $($into_type:tt)*) => (
        impl IntoRustByName<$($into_type)*> for UDT {
            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;
                    let converted = as_rust_type!(col_type, bytes, $($into_type)*);
                    converted.map_err(|err| err.into())
                })
            }
        }
    );
}

macro_rules! into_rust_by_index {
    (Tuple, $($into_type:tt)*) => (
        impl IntoRustByIndex<$($into_type)*> for Tuple {
            fn get_by_index(&self, index: usize) -> Result<Option<$($into_type)*>> {
                self.data
                    .get(index)
                    .ok_or(column_is_empty_err())
                    .and_then(|v| {
                        let &(ref col_type, ref bytes) = v;
                        let converted = as_rust_type!(col_type, bytes, $($into_type)*);
                        converted.map_err(|err| err.into())
                    })
            }
        }
    );

    (Row, $($into_type:tt)*) => (
        impl IntoRustByIndex<$($into_type)*> for Row {
            fn get_by_index(&self, index: usize) -> Result<Option<$($into_type)*>> {
                self.get_col_spec_by_index(index)
                    .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)*)
                    })
            }
        }
    );
}

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`
/// plus the matching Rust type.
macro_rules! as_rust_type {
    ($data_type_option:ident, $data_value:ident, Vec<u8>) => (
        match $data_type_option.id {
            ColType::Blob => {
                as_res_opt!($data_value, decode_blob)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into Vec<u8> (valid types: Blob).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, String) => (
        match $data_type_option.id {
            ColType::Custom => {
                as_res_opt!($data_value, decode_custom)
            }
            ColType::Ascii => {
                as_res_opt!($data_value, decode_ascii)
            }
            ColType::Varchar => {
                as_res_opt!($data_value, decode_varchar)
            }
            // TODO: clarify when to use decode_text.
            // it's not mentioned in
            // https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L582
            // ColType::XXX => decode_text($data_value)?
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into String (valid types: Custom, Ascii, Varchar).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, bool) => (
        match $data_type_option.id {
            ColType::Boolean => {
                as_res_opt!($data_value, decode_boolean)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into bool (valid types: Boolean).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, i64) => (
        match $data_type_option.id {
            ColType::Bigint => {
                as_res_opt!($data_value, decode_bigint)
            }
            ColType::Timestamp => {
                as_res_opt!($data_value, decode_timestamp)
            }
            ColType::Time => {
                as_res_opt!($data_value, decode_time)
            }
            ColType::Varint => {
                as_res_opt!($data_value, decode_varint)
            }
            ColType::Counter => {
                as_res_opt!($data_value, decode_bigint)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into i64 (valid types: Bigint, Timestamp, Time, Variant,\
                    Counter).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, i32) => (
        match $data_type_option.id {
            ColType::Int => {
                as_res_opt!($data_value, decode_int)
            }
            ColType::Date => {
                as_res_opt!($data_value, decode_date)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into i32 (valid types: Int, Date).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, i16) => (
        match $data_type_option.id {
            ColType::Smallint => {
                as_res_opt!($data_value, decode_smallint)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into i16 (valid types: Smallint).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, i8) => (
        match $data_type_option.id {
            ColType::Tinyint => {
                as_res_opt!($data_value, decode_tinyint)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into i8 (valid types: Tinyint).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, f64) => (
        match $data_type_option.id {
            ColType::Double => {
                as_res_opt!($data_value, decode_double)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into f64 (valid types: Double).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, f32) => (
        match $data_type_option.id {
            ColType::Decimal => {
                as_res_opt!($data_value, decode_decimal)
            }
            ColType::Float => {
                as_res_opt!($data_value, decode_float)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into f32 (valid types: Decimal, Float).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, IpAddr) => (
        match $data_type_option.id {
            ColType::Inet => {
                as_res_opt!($data_value, decode_inet)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into IpAddr (valid types: Inet).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, Uuid) => (
        match $data_type_option.id {
            ColType::Uuid |
            ColType::Timeuuid => {
                as_res_opt!($data_value, decode_timeuuid)
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into Uuid (valid types: Uuid, Timeuuid).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, List) => (
        match $data_type_option.id {
            ColType::List |
            ColType::Set => {
                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).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, Map) => (
        match $data_type_option.id {
            ColType::Map => {
                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).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, UDT) => (
        match *$data_type_option {
            ColTypeOption {
                id: ColType::Udt,
                value: Some(ColTypeOptionValue::UdtType(ref list_type_option))
            } => {
                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).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, Tuple) => (
        match *$data_type_option {
            ColTypeOption {
                id: ColType::Tuple,
                value: Some(ColTypeOptionValue::TupleType(ref list_type_option))
            } => {
                match $data_value.as_slice() {
                    Some(ref bytes) => {
                        decode_tuple(bytes, list_type_option.types.len())
                            .map(|data| Some(Tuple::new(data, list_type_option)))
                            .map_err(Into::into)
                    },
                    None => Ok(None)
                }
            }
            _ => Err(Error::General(format!("Invalid conversion. \
                    Cannot convert {:?} into Tuple (valid types: tuple).",
                    $data_type_option.id)))
        }
    );
    ($data_type_option:ident, $data_value:ident, Timespec) => (
        match $data_type_option.id {
            ColType::Timestamp => {
                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).",
                    $data_type_option.id)))
        }
    );
}
<|endoftext|>


<commit_before>/*
  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

use std::path::Path;
use chrono::{
    DateTime,
    Utc
};
use store;
use AplibObject;
use AplibType;
use notes::NotesProperties;
use audit::{
    audit_get_str_value, audit_get_int_value, audit_get_bool_value,
    audit_get_date_value, audit_get_array_value, audit_get_data_value,
    Report, SkipReason
};

pub struct Master {
    uuid: Option<String>,
    model_id: Option<i64>,
    project_uuid: Option<String>,

    pub alternate_master: Option<String>,
    pub original_version_uuid: Option<String>,
    pub import_group_uuid: Option<String>,
    pub filename: Option<String>,
    pub name: Option<String>,
    pub original_version_name: Option<String>,
    pub db_version: Option<i64>,
    pub master_type: Option<String>,
    pub subtype: Option<String>,
    pub image_path: Option<String>,
    pub is_reference: Option<bool>,
    pub is_truly_raw: Option<bool>,
    pub is_in_trash: Option<bool>,
    pub is_missing: Option<bool>,
    pub is_externaly_editable: Option<bool>,
    pub create_date: Option<DateTime<Utc>>,
    pub image_date: Option<DateTime<Utc>>,
    pub file_creation_date: Option<DateTime<Utc>>,
    pub file_modification_date: Option<DateTime<Utc>>,
    pub original_file_name: Option<String>,
    pub file_size: Option<i64>,
    pub file_volume_uuid: Option<String>,
    pub color_space_name: Option<String>,
    pub pixel_format: Option<i64>,
    pub has_focus_points: Option<i64>,
    pub image_format: Option<i64>, // XXX fix this is a 4char MSB
    pub notes: Option<Vec<NotesProperties>>,
    pub colour_space_definition: Option<Vec<u8>>,
}

impl AplibObject for Master {
    fn from_path(plist_path: &Path,
                 mut auditor: Option<&mut Report>) -> Option<Master> {

        use plutils::*;
        let plist = parse_plist(plist_path);
        match plist {
            Plist::Dictionary(ref dict) => {
                let notes = audit_get_array_value(dict, "notes", &mut auditor);
                let result = Some(Master {
                    uuid: audit_get_str_value(dict, "uuid", &mut auditor),
                    alternate_master: audit_get_str_value(
                        dict, "alternateMasterUuid", &mut auditor),
                    original_version_uuid: audit_get_str_value(
                        dict, "originalVersionUuid", &mut auditor),
                    project_uuid: audit_get_str_value(
                        dict, "projectUuid", &mut auditor),
                    import_group_uuid: audit_get_str_value(
                        dict, "importGroupUuid", &mut auditor),
                    filename: audit_get_str_value(dict, "fileName", &mut auditor),
                    name: audit_get_str_value(dict, "name", &mut auditor),
                    original_version_name: audit_get_str_value(
                        dict, "originalVersionName", &mut auditor),
                    original_file_name: audit_get_str_value(
                        dict, "originalFileName", &mut auditor),
                    file_volume_uuid: audit_get_str_value(
                        dict, "fileVolumeUuid", &mut auditor),
                    db_version: audit_get_int_value(dict, "version", &mut auditor),
                    master_type: audit_get_str_value(dict, "type", &mut auditor),
                    subtype: audit_get_str_value(dict, "subtype", &mut auditor),
                    model_id: audit_get_int_value(dict, "modelId", &mut auditor),
                    image_path: audit_get_str_value(dict, "imagePath", &mut auditor),
                    file_size: audit_get_int_value(dict, "fileSize", &mut auditor),
                    is_reference: audit_get_bool_value(
                        dict, "fileIsReference", &mut auditor),
                    is_externaly_editable: audit_get_bool_value(
                        dict, "isExternallyEditable", &mut auditor),
                    is_in_trash: audit_get_bool_value(
                        dict, "isInTrash", &mut auditor),
                    is_missing: audit_get_bool_value(
                        dict, "isMissing", &mut auditor),
                    is_truly_raw: audit_get_bool_value(
                        dict, "isTrulyRaw", &mut auditor),
                    color_space_name: audit_get_str_value(
                        dict, "colorSpaceName", &mut auditor),
                    create_date: audit_get_date_value(dict, "createDate", &mut auditor),
                    image_date: audit_get_date_value(dict, "imageDate", &mut auditor),
                    file_creation_date: audit_get_date_value(dict, "fileCreationDate", &mut auditor),
                    file_modification_date: audit_get_date_value(
                        dict, "fileModificationDate", &mut auditor),
                    has_focus_points: audit_get_int_value(dict, "hasFocusPoints", &mut auditor),
                    image_format: audit_get_int_value(dict, "imageFormat", &mut auditor),
                    pixel_format: audit_get_int_value(dict, "pixelFormat", &mut auditor),
                    colour_space_definition: audit_get_data_value(dict, "colorSpaceDefinition", &mut auditor),
                    notes: NotesProperties::from(&notes, &mut auditor),
                });
                if auditor.is_some() {
                    let ref mut auditor = auditor.unwrap();
                    auditor.skip("faceDetectionState", SkipReason::Ignore);
                    auditor.skip("fileAliasData", SkipReason::Ignore);
                    auditor.skip("importedBy", SkipReason::Ignore);
                    auditor.skip("importGroup", SkipReason::Ignore);
                    auditor.skip("plistWriteTimestamp", SkipReason::Ignore);

                    auditor.audit_ignored(dict, None);
                }
                result
            },
            _ =>
                None
        }
    }
    fn obj_type(&self) -> AplibType {
        AplibType::Master
    }
    fn uuid(&self) -> &Option<String> {
        &self.uuid
    }
    fn parent(&self) -> &Option<String> {
        &self.project_uuid
    }
    fn model_id(&self) -> i64 {
        self.model_id.unwrap_or(0)
    }
    fn is_valid(&self) -> bool {
        self.uuid.is_some()
    }
    fn wrap(obj: Master) -> store::Wrapper {
        store::Wrapper::Master(Box::new(obj))
    }
}

impl Master {

}

#[cfg(test)]
#[test]
fn test_master_parse() {
    use testutils;

    let master = Master::from_path(
        testutils::get_test_file_path("Master.apmaster")
            .as_path(), None);
    assert!(master.is_some());
    let master = master.unwrap();

    assert_eq!(master.uuid.as_ref().unwrap(), "JpLq7STrRMmgm5YZTm6IzA");
    assert_eq!(master.project_uuid.as_ref().unwrap(), "evHgvM2oQ3GR0j6gEMnNTQ");
    assert_eq!(master.original_version_uuid.as_ref().unwrap(), "VF%CkiTKQy+h53Oyr7KCOA");
    assert_eq!(master.color_space_name.as_ref().unwrap(), "kCGColorSpaceGenericHDR");
    assert!(master.is_reference.unwrap());
    assert_eq!(master.filename.as_ref().unwrap(), "img_8826.cr2");
    assert_eq!(master.master_type.as_ref().unwrap(), "IMGT");
    assert_eq!(master.subtype.as_ref().unwrap(), "RAWST");

    // XXX fix when have actual audit.
//    println!("report {:?}", report);
}
<commit_msg>masters: parse face detection status<commit_after>/*
  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

use std::path::Path;
use chrono::{
    DateTime,
    Utc
};
use store;
use AplibObject;
use AplibType;
use notes::NotesProperties;
use audit::{
    audit_get_str_value, audit_get_int_value, audit_get_bool_value,
    audit_get_date_value, audit_get_array_value, audit_get_data_value,
    Report, SkipReason
};

pub struct Master {
    uuid: Option<String>,
    model_id: Option<i64>,
    project_uuid: Option<String>,

    pub alternate_master: Option<String>,
    pub original_version_uuid: Option<String>,
    pub import_group_uuid: Option<String>,
    pub filename: Option<String>,
    pub name: Option<String>,
    pub original_version_name: Option<String>,
    pub db_version: Option<i64>,
    pub master_type: Option<String>,
    pub subtype: Option<String>,
    pub image_path: Option<String>,
    pub is_reference: Option<bool>,
    pub is_truly_raw: Option<bool>,
    pub is_in_trash: Option<bool>,
    pub is_missing: Option<bool>,
    pub is_externaly_editable: Option<bool>,
    pub create_date: Option<DateTime<Utc>>,
    pub image_date: Option<DateTime<Utc>>,
    pub file_creation_date: Option<DateTime<Utc>>,
    pub file_modification_date: Option<DateTime<Utc>>,
    pub original_file_name: Option<String>,
    pub file_size: Option<i64>,
    pub file_volume_uuid: Option<String>,
    pub color_space_name: Option<String>,
    pub pixel_format: Option<i64>,
    pub has_focus_points: Option<i64>,
    pub image_format: Option<i64>, // XXX fix this is a 4char MSB
    pub notes: Option<Vec<NotesProperties>>,
    pub colour_space_definition: Option<Vec<u8>>,
    pub face_detection_state: Option<i64>,
}

impl AplibObject for Master {
    fn from_path(plist_path: &Path,
                 mut auditor: Option<&mut Report>) -> Option<Master> {

        use plutils::*;
        let plist = parse_plist(plist_path);
        match plist {
            Plist::Dictionary(ref dict) => {
                let notes = audit_get_array_value(dict, "notes", &mut auditor);
                let result = Some(Master {
                    uuid: audit_get_str_value(dict, "uuid", &mut auditor),
                    alternate_master: audit_get_str_value(
                        dict, "alternateMasterUuid", &mut auditor),
                    original_version_uuid: audit_get_str_value(
                        dict, "originalVersionUuid", &mut auditor),
                    project_uuid: audit_get_str_value(
                        dict, "projectUuid", &mut auditor),
                    import_group_uuid: audit_get_str_value(
                        dict, "importGroupUuid", &mut auditor),
                    filename: audit_get_str_value(dict, "fileName", &mut auditor),
                    name: audit_get_str_value(dict, "name", &mut auditor),
                    original_version_name: audit_get_str_value(
                        dict, "originalVersionName", &mut auditor),
                    original_file_name: audit_get_str_value(
                        dict, "originalFileName", &mut auditor),
                    file_volume_uuid: audit_get_str_value(
                        dict, "fileVolumeUuid", &mut auditor),
                    db_version: audit_get_int_value(dict, "version", &mut auditor),
                    master_type: audit_get_str_value(dict, "type", &mut auditor),
                    subtype: audit_get_str_value(dict, "subtype", &mut auditor),
                    model_id: audit_get_int_value(dict, "modelId", &mut auditor),
                    image_path: audit_get_str_value(dict, "imagePath", &mut auditor),
                    file_size: audit_get_int_value(dict, "fileSize", &mut auditor),
                    is_reference: audit_get_bool_value(
                        dict, "fileIsReference", &mut auditor),
                    is_externaly_editable: audit_get_bool_value(
                        dict, "isExternallyEditable", &mut auditor),
                    is_in_trash: audit_get_bool_value(
                        dict, "isInTrash", &mut auditor),
                    is_missing: audit_get_bool_value(
                        dict, "isMissing", &mut auditor),
                    is_truly_raw: audit_get_bool_value(
                        dict, "isTrulyRaw", &mut auditor),
                    color_space_name: audit_get_str_value(
                        dict, "colorSpaceName", &mut auditor),
                    create_date: audit_get_date_value(dict, "createDate", &mut auditor),
                    image_date: audit_get_date_value(dict, "imageDate", &mut auditor),
                    file_creation_date: audit_get_date_value(dict, "fileCreationDate", &mut auditor),
                    file_modification_date: audit_get_date_value(
                        dict, "fileModificationDate", &mut auditor),
                    has_focus_points: audit_get_int_value(dict, "hasFocusPoints", &mut auditor),
                    image_format: audit_get_int_value(dict, "imageFormat", &mut auditor),
                    pixel_format: audit_get_int_value(dict, "pixelFormat", &mut auditor),
                    colour_space_definition: audit_get_data_value(dict, "colorSpaceDefinition", &mut auditor),
                    notes: NotesProperties::from(&notes, &mut auditor),
                    face_detection_state: audit_get_int_value(dict, "faceDetectionState", &mut auditor),
                });
                if auditor.is_some() {
                    let ref mut auditor = auditor.unwrap();
                    auditor.skip("fileAliasData", SkipReason::Ignore);
                    auditor.skip("importedBy", SkipReason::Ignore);
                    auditor.skip("importGroup", SkipReason::Ignore);
                    auditor.skip("plistWriteTimestamp", SkipReason::Ignore);

                    auditor.audit_ignored(dict, None);
                }
                result
            },
            _ =>
                None
        }
    }
    fn obj_type(&self) -> AplibType {
        AplibType::Master
    }
    fn uuid(&self) -> &Option<String> {
        &self.uuid
    }
    fn parent(&self) -> &Option<String> {
        &self.project_uuid
    }
    fn model_id(&self) -> i64 {
        self.model_id.unwrap_or(0)
    }
    fn is_valid(&self) -> bool {
        self.uuid.is_some()
    }
    fn wrap(obj: Master) -> store::Wrapper {
        store::Wrapper::Master(Box::new(obj))
    }
}

impl Master {

}

#[cfg(test)]
#[test]
fn test_master_parse() {
    use testutils;

    let master = Master::from_path(
        testutils::get_test_file_path("Master.apmaster")
            .as_path(), None);
    assert!(master.is_some());
    let master = master.unwrap();

    assert_eq!(master.uuid.as_ref().unwrap(), "JpLq7STrRMmgm5YZTm6IzA");
    assert_eq!(master.project_uuid.as_ref().unwrap(), "evHgvM2oQ3GR0j6gEMnNTQ");
    assert_eq!(master.original_version_uuid.as_ref().unwrap(), "VF%CkiTKQy+h53Oyr7KCOA");
    assert_eq!(master.color_space_name.as_ref().unwrap(), "kCGColorSpaceGenericHDR");
    assert!(master.is_reference.unwrap());
    assert_eq!(master.filename.as_ref().unwrap(), "img_8826.cr2");
    assert_eq!(master.master_type.as_ref().unwrap(), "IMGT");
    assert_eq!(master.subtype.as_ref().unwrap(), "RAWST");

    // XXX fix when have actual audit.
//    println!("report {:?}", report);
}
<|endoftext|>


<commit_before>#![crate_name = "touch"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Nick Platt <platt.nicholas@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE file
 * that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;
extern crate time;
extern crate filetime;

use filetime::*;
use std::fs::{self, File};
use std::io::{Error, Write};
use std::path::Path;

#[path = "../common/util.rs"]
#[macro_use]
mod util;

#[path = "../common/filesystem.rs"]
mod filesystem;

use filesystem::UUPathExt;

static NAME: &'static str = "touch";
static VERSION: &'static str = "1.0.0";

// Since touch's date/timestamp parsing doesn't account for timezone, the
// returned value from time::strptime() is UTC. We get system's timezone to
// localize the time.
macro_rules! to_local(
    ($exp:expr) => ({
        let mut tm = $exp;
        tm.tm_utcoff = time::now().tm_utcoff;
        tm
    })
);

macro_rules! local_tm_to_filetime(
    ($exp:expr) => ({
        let ts = $exp.to_timespec();
        FileTime::from_seconds_since_1970(ts.sec as u64, ts.nsec as u32)
    })
);

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optflag("a", "",               "change only the access time");
    opts.optflag("c", "no-create",      "do not create any files");
    opts.optopt( "d", "date",           "parse argument and use it instead of current time", "STRING");
    opts.optflag("h", "no-dereference", "affect each symbolic link instead of any referenced file \
                                         (only for systems that can change the timestamps of a symlink)");
    opts.optflag("m", "",               "change only the modification time");
    opts.optopt( "r", "reference",      "use this file's times instead of the current time", "FILE");
    opts.optopt( "t", "",               "use [[CC]YY]MMDDhhmm[.ss] instead of the current time", "STAMP");
    opts.optopt( "",  "time",           "change only the specified time: \"access\", \"atime\", or \
                                         \"use\" are equivalent to -a; \"modify\" or \"mtime\" are \
                                         equivalent to -m", "WORD");
    opts.optflag("h", "help",           "display this help and exit");
    opts.optflag("V", "version",        "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m)  => m,
        Err(e) => panic!("Invalid options\n{}", e)
    };

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    if matches.opt_present("help") || matches.free.is_empty() {
        println!("{} {}", NAME, VERSION);
        println!("");
        println!("Usage: {} [OPTION]... FILE...", NAME);
        println!("");
        println!("{}", opts.usage("Update the access and modification times of \
                                   each FILE to the current time."));
        if matches.free.is_empty() {
            return 1;
        }
        return 0;
    }

    if matches.opt_present("date") && matches.opts_present(&["reference".to_string(), "t".to_string()]) ||
       matches.opt_present("reference") && matches.opts_present(&["date".to_string(), "t".to_string()]) ||
       matches.opt_present("t") && matches.opts_present(&["date".to_string(), "reference".to_string()]) {
        panic!("Invalid options: cannot specify reference time from more than one source");
    }

    let (mut atime, mut mtime) =
        if matches.opt_present("reference") {
            stat(&matches.opt_str("reference").unwrap()[..], !matches.opt_present("no-dereference"))
        } else if matches.opts_present(&["date".to_string(), "t".to_string()]) {
            let timestamp = if matches.opt_present("date") {
                parse_date(matches.opt_str("date").unwrap().as_ref())
            } else {
                parse_timestamp(matches.opt_str("t").unwrap().as_ref())
            };
            (timestamp, timestamp)
        } else {
            let now = local_tm_to_filetime!(time::now());
            (now, now)
        };

    for filename in matches.free.iter() {
        let path = &filename[..];

        if !Path::new(path).uu_exists() {
            // no-dereference included here for compatibility
            if matches.opts_present(&["no-create".to_string(), "no-dereference".to_string()]) {
                continue;
            }

            match File::create(path) {
                Err(e) => {
                    show_warning!("cannot touch '{}': {}", path, e);
                    continue;
                },
                _ => (),
            };

            // Minor optimization: if no reference time was specified, we're done.
            if !matches.opts_present(&["date".to_string(), "reference".to_string(), "t".to_string()]) {
                continue;
            }
        }

        // If changing "only" atime or mtime, grab the existing value of the other.
        // Note that "-a" and "-m" may be passed together; this is not an xor.
        if matches.opts_present(&["a".to_string(), "m".to_string(), "time".to_string()]) {
            let st = stat(path, !matches.opt_present("no-dereference"));
            let time = matches.opt_strs("time");

            if !(matches.opt_present("a") ||
                 time.contains(&"access".to_string()) ||
                 time.contains(&"atime".to_string()) ||
                 time.contains(&"use".to_string())) {
                atime = st.0;
            }

            if !(matches.opt_present("m") ||
                 time.contains(&"modify".to_string()) ||
                 time.contains(&"mtime".to_string())) {
                mtime = st.1;
            }
        }

        // this follows symlinks and thus does not work correctly for the -h flag
        // need to use lutimes() c function on supported platforms
        match filetime::set_file_times(path, atime, mtime) {
            Err(e) => show_warning!("cannot touch '{}': {}", path, e),
            _ => (),
        };
    }

    0
}

fn stat(path: &str, follow: bool) -> (FileTime, FileTime) {
    let metadata = if follow {
        fs::symlink_metadata(path)
    } else {
        fs::metadata(path)
    };

    match metadata {
        Ok(m) => (
            FileTime::from_last_access_time(&m),
            FileTime::from_last_modification_time(&m)
            ),
        Err(_) => crash!(1, "failed to get attributes of '{}': {}", path, Error::last_os_error())
    }
}

fn parse_date(str: &str) -> FileTime {
    // This isn't actually compatible with GNU touch, but there doesn't seem to
    // be any simple specification for what format this parameter allows and I'm
    // not about to implement GNU parse_datetime.
    // http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob_plain;f=lib/parse-datetime.y
    match time::strptime(str, "%c") {
        Ok(tm) => local_tm_to_filetime!(to_local!(tm)),
        Err(e) => panic!("Unable to parse date\n{}", e)
    }
}

fn parse_timestamp(str: &str) -> FileTime {
    let format = match str.chars().count() {
        15 => "%Y%m%d%H%M.%S",
        12 => "%Y%m%d%H%M",
        13 => "%y%m%d%H%M.%S",
        10 => "%y%m%d%H%M",
        11 => "%m%d%H%M.%S",
         8 => "%m%d%H%M",
         _ => panic!("Unknown timestamp format")
    };

    match time::strptime(str, format) {
        Ok(tm) => local_tm_to_filetime!(to_local!(tm)),
        Err(e) => panic!("Unable to parse timestamp\n{}", e)
    }
}

<commit_msg>Fix bug when setting time w/o year.<commit_after>#![crate_name = "touch"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Nick Platt <platt.nicholas@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE file
 * that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;
extern crate time;
extern crate filetime;

use filetime::*;
use std::fs::{self, File};
use std::io::{Error, Write};
use std::path::Path;

#[path = "../common/util.rs"]
#[macro_use]
mod util;

#[path = "../common/filesystem.rs"]
mod filesystem;

use filesystem::UUPathExt;

static NAME: &'static str = "touch";
static VERSION: &'static str = "1.0.0";

// Since touch's date/timestamp parsing doesn't account for timezone, the
// returned value from time::strptime() is UTC. We get system's timezone to
// localize the time.
macro_rules! to_local(
    ($exp:expr) => ({
        let mut tm = $exp;
        tm.tm_utcoff = time::now().tm_utcoff;
        tm
    })
);

macro_rules! local_tm_to_filetime(
    ($exp:expr) => ({
        let ts = $exp.to_timespec();
        FileTime::from_seconds_since_1970(ts.sec as u64, ts.nsec as u32)
    })
);

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optflag("a", "",               "change only the access time");
    opts.optflag("c", "no-create",      "do not create any files");
    opts.optopt( "d", "date",           "parse argument and use it instead of current time", "STRING");
    opts.optflag("h", "no-dereference", "affect each symbolic link instead of any referenced file \
                                         (only for systems that can change the timestamps of a symlink)");
    opts.optflag("m", "",               "change only the modification time");
    opts.optopt( "r", "reference",      "use this file's times instead of the current time", "FILE");
    opts.optopt( "t", "",               "use [[CC]YY]MMDDhhmm[.ss] instead of the current time", "STAMP");
    opts.optopt( "",  "time",           "change only the specified time: \"access\", \"atime\", or \
                                         \"use\" are equivalent to -a; \"modify\" or \"mtime\" are \
                                         equivalent to -m", "WORD");
    opts.optflag("h", "help",           "display this help and exit");
    opts.optflag("V", "version",        "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m)  => m,
        Err(e) => panic!("Invalid options\n{}", e)
    };

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    if matches.opt_present("help") || matches.free.is_empty() {
        println!("{} {}", NAME, VERSION);
        println!("");
        println!("Usage: {} [OPTION]... FILE...", NAME);
        println!("");
        println!("{}", opts.usage("Update the access and modification times of \
                                   each FILE to the current time."));
        if matches.free.is_empty() {
            return 1;
        }
        return 0;
    }

    if matches.opt_present("date") && matches.opts_present(&["reference".to_string(), "t".to_string()]) ||
       matches.opt_present("reference") && matches.opts_present(&["date".to_string(), "t".to_string()]) ||
       matches.opt_present("t") && matches.opts_present(&["date".to_string(), "reference".to_string()]) {
        panic!("Invalid options: cannot specify reference time from more than one source");
    }

    let (mut atime, mut mtime) =
        if matches.opt_present("reference") {
            stat(&matches.opt_str("reference").unwrap()[..], !matches.opt_present("no-dereference"))
        } else if matches.opts_present(&["date".to_string(), "t".to_string()]) {
            let timestamp = if matches.opt_present("date") {
                parse_date(matches.opt_str("date").unwrap().as_ref())
            } else {
                parse_timestamp(matches.opt_str("t").unwrap().as_ref())
            };
            (timestamp, timestamp)
        } else {
            let now = local_tm_to_filetime!(time::now());
            (now, now)
        };

    for filename in matches.free.iter() {
        let path = &filename[..];

        if !Path::new(path).uu_exists() {
            // no-dereference included here for compatibility
            if matches.opts_present(&["no-create".to_string(), "no-dereference".to_string()]) {
                continue;
            }

            match File::create(path) {
                Err(e) => {
                    show_warning!("cannot touch '{}': {}", path, e);
                    continue;
                },
                _ => (),
            };

            // Minor optimization: if no reference time was specified, we're done.
            if !matches.opts_present(&["date".to_string(), "reference".to_string(), "t".to_string()]) {
                continue;
            }
        }

        // If changing "only" atime or mtime, grab the existing value of the other.
        // Note that "-a" and "-m" may be passed together; this is not an xor.
        if matches.opts_present(&["a".to_string(), "m".to_string(), "time".to_string()]) {
            let st = stat(path, !matches.opt_present("no-dereference"));
            let time = matches.opt_strs("time");

            if !(matches.opt_present("a") ||
                 time.contains(&"access".to_string()) ||
                 time.contains(&"atime".to_string()) ||
                 time.contains(&"use".to_string())) {
                atime = st.0;
            }

            if !(matches.opt_present("m") ||
                 time.contains(&"modify".to_string()) ||
                 time.contains(&"mtime".to_string())) {
                mtime = st.1;
            }
        }

        // this follows symlinks and thus does not work correctly for the -h flag
        // need to use lutimes() c function on supported platforms
        match filetime::set_file_times(path, atime, mtime) {
            Err(e) => show_warning!("cannot touch '{}': {}", path, e),
            _ => (),
        };
    }

    0
}

fn stat(path: &str, follow: bool) -> (FileTime, FileTime) {
    let metadata = if follow {
        fs::symlink_metadata(path)
    } else {
        fs::metadata(path)
    };

    match metadata {
        Ok(m) => (
            FileTime::from_last_access_time(&m),
            FileTime::from_last_modification_time(&m)
            ),
        Err(_) => crash!(1, "failed to get attributes of '{}': {}", path, Error::last_os_error())
    }
}

fn parse_date(str: &str) -> FileTime {
    // This isn't actually compatible with GNU touch, but there doesn't seem to
    // be any simple specification for what format this parameter allows and I'm
    // not about to implement GNU parse_datetime.
    // http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob_plain;f=lib/parse-datetime.y
    match time::strptime(str, "%c") {
        Ok(tm) => local_tm_to_filetime!(to_local!(tm)),
        Err(e) => panic!("Unable to parse date\n{}", e)
    }
}

fn parse_timestamp(s: &str) -> FileTime {
    let now = time::now();
    let (format, ts) = match s.chars().count() {
        15 => ("%Y%m%d%H%M.%S", s.to_string()),
        12 => ("%Y%m%d%H%M", s.to_string()),
        13 => ("%y%m%d%H%M.%S", s.to_string()),
        10 => ("%y%m%d%H%M", s.to_string()),
        11 => ("%Y%m%d%H%M.%S", format!("{}{}", now.tm_year + 1900, s)),
         8 => ("%Y%m%d%H%M", format!("{}{}", now.tm_year + 1900, s)),
         _ => panic!("Unknown timestamp format")
    };

    match time::strptime(&ts, format) {
        Ok(tm) => local_tm_to_filetime!(to_local!(tm)),
        Err(e) => panic!("Unable to parse timestamp\n{}", e)
    }
}

<|endoftext|>


<commit_before>use grammar::*;

fn visit(statement: Statement) -> Statement {
    match statement.clone() {
        Statement::VariableDeclarationStatement{kind: kind, declarations: declarations } => {
            if kind == VariableDeclarationKind::Const {
                Statement::VariableDeclarationStatement {
                    kind: VariableDeclarationKind::Var,
                    declarations: declarations
                }
            } else {
                statement
            }
        },
        _ => statement
    }
}

pub fn traverse(program: Program) -> Program {
    let mut new_statements = Vec::new();

    for statement in program.body {
        new_statements.push(visit(statement));
    }

    Program {
        body: new_statements
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use parser::*;
    use grammar::*;

    #[test]
    fn transform_const_assignment() {
        let input_program = parse("const foo = 42;".into());
        let output_program = traverse(input_program);
        let statement = output_program.body.first().unwrap().clone();
        let success = match statement {
            Statement::VariableDeclarationStatement{kind: kind, declarations: _declarations } => {
                kind == VariableDeclarationKind::Var
            },
            _ => false
        };
        assert!(success);
    }
}
<commit_msg>transform top level let statements<commit_after>use grammar::*;

fn visit(statement: Statement) -> Statement {
    match statement.clone() {
        Statement::VariableDeclarationStatement{kind: kind, declarations: declarations } => {
            if kind == VariableDeclarationKind::Const || kind == VariableDeclarationKind::Let {
                Statement::VariableDeclarationStatement {
                    kind: VariableDeclarationKind::Var,
                    declarations: declarations
                }
            } else {
                statement
            }
        },
        _ => statement
    }
}

pub fn traverse(program: Program) -> Program {
    let mut new_statements = Vec::new();

    for statement in program.body {
        new_statements.push(visit(statement));
    }

    Program {
        body: new_statements
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use parser::*;
    use grammar::*;

    #[test]
    fn transform_const_assignment() {
        let input_program = parse("const foo = 42;".into());
        let output_program = traverse(input_program);
        let statement = output_program.body.first().unwrap().clone();
        let success = match statement {
            Statement::VariableDeclarationStatement{kind: kind, declarations: _declarations } => {
                kind == VariableDeclarationKind::Var
            },
            _ => false
        };
        assert!(success);
    }

    #[test]
    fn transform_simple_let_assignment() {
        let input_program = parse("let foo = 42;".into());
        let output_program = traverse(input_program);
        let statement = output_program.body.first().unwrap().clone();
        let success = match statement {
            Statement::VariableDeclarationStatement{kind: kind, declarations: _declarations } => {
                kind == VariableDeclarationKind::Var
            },
            _ => false
        };
        assert!(success);
    }
}
<|endoftext|>


<commit_before>use std::{
    borrow::Cow,
    ffi::{OsStr, OsString},
    fmt::{self, Debug},
    str,
};

use os_str_bytes::{raw, OsStrBytes};

pub(crate) struct ArgStr<'a>(Cow<'a, [u8]>);

impl<'a> ArgStr<'a> {
    pub(crate) fn new(s: &'a OsStr) -> Self {
        Self(s.to_raw_bytes())
    }

    pub(crate) fn starts_with(&self, s: &str) -> bool {
        self.0.starts_with(s.as_bytes())
    }

    pub(crate) fn is_prefix_of(&self, s: &str) -> bool {
        raw::starts_with(s, &self.0)
    }

    fn to_borrowed(&'a self) -> Self {
        Self(Cow::Borrowed(&self.0))
    }

    pub(crate) fn contains_byte(&self, byte: u8) -> bool {
        assert!(byte.is_ascii());

        self.0.contains(&byte)
    }

    pub(crate) fn contains_char(&self, ch: char) -> bool {
        let mut bytes = [0; 4];
        let bytes = ch.encode_utf8(&mut bytes).as_bytes();
        for i in 0..self.0.len().saturating_sub(bytes.len() - 1) {
            if self.0[i..].starts_with(bytes) {
                return true;
            }
        }
        false
    }

    pub(crate) fn split_at_byte(&self, byte: u8) -> (ArgStr, ArgStr) {
        assert!(byte.is_ascii());

        for (i, b) in self.0.iter().enumerate() {
            if b == &byte {
                return self.split_at_unchecked(i);
            }
        }
        (self.to_borrowed(), Self(Cow::Borrowed(&[])))
    }

    pub(crate) fn trim_start_matches(&'a self, byte: u8) -> ArgStr {
        assert!(byte.is_ascii());

        let mut found = false;
        for (i, b) in self.0.iter().enumerate() {
            if b != &byte {
                return Self(Cow::Borrowed(&self.0[i..]));
            } else {
                found = true;
            }
        }
        if found {
            return Self(Cow::Borrowed(&[]));
        }
        self.to_borrowed()
    }

    // Like `trim_start_matches`, but trims no more than `n` matches
    #[inline]
    pub(crate) fn trim_start_n_matches(&self, n: usize, ch: u8) -> ArgStr {
        assert!(ch.is_ascii());

        let i = self.0.iter().take(n).take_while(|c| **c == ch).count();

        self.split_at_unchecked(i).1
    }

    pub(crate) fn split_at_unchecked(&'a self, i: usize) -> (ArgStr, ArgStr) {
        (
            Self(Cow::Borrowed(&self.0[..i])),
            Self(Cow::Borrowed(&self.0[i..])),
        )
    }

    pub(crate) fn split(&self, ch: char) -> ArgSplit<'_> {
        let mut sep = [0; 4];
        ArgSplit {
            sep_len: ch.encode_utf8(&mut sep).as_bytes().len(),
            sep,
            val: &self.0,
            pos: 0,
        }
    }

    #[allow(dead_code)]
    pub(crate) fn as_raw_bytes(&self) -> &[u8] {
        &self.0
    }

    pub(crate) fn len(&self) -> usize {
        self.0.len()
    }

    #[allow(dead_code)]
    pub(crate) fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    pub(crate) fn to_str(&self) -> Option<&str> {
        str::from_utf8(&self.0).ok()
    }

    pub(crate) fn to_string_lossy(&self) -> Cow<'_, str> {
        String::from_utf8_lossy(&self.0)
    }

    pub(crate) fn to_os_string(&self) -> OsString {
        self.to_borrowed().into_os_string()
    }

    pub(crate) fn into_os_string(self) -> OsString {
        OsStr::from_raw_bytes(self.0).unwrap().into_owned()
    }
}

impl<'a> Debug for ArgStr<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.to_string_lossy())
    }
}

impl<'a> PartialEq<str> for ArgStr<'a> {
    fn eq(&self, other: &str) -> bool {
        self.0 == other.as_bytes()
    }
}

impl<'a> PartialEq<&str> for ArgStr<'a> {
    fn eq(&self, other: &&str) -> bool {
        self.eq(*other)
    }
}

impl<'a> PartialEq<ArgStr<'a>> for str {
    fn eq(&self, other: &ArgStr<'a>) -> bool {
        other.eq(self)
    }
}

impl<'a> PartialEq<ArgStr<'a>> for &str {
    fn eq(&self, other: &ArgStr<'a>) -> bool {
        other.eq(self)
    }
}

#[derive(Clone, Debug)]
pub(crate) struct ArgSplit<'a> {
    sep: [u8; 4],
    sep_len: usize,
    val: &'a [u8],
    pos: usize,
}

impl<'a> Iterator for ArgSplit<'a> {
    type Item = ArgStr<'a>;

    fn next(&mut self) -> Option<ArgStr<'a>> {
        debug!("ArgSplit::next: self={:?}", self);

        if self.pos == self.val.len() {
            return None;
        }
        let start = self.pos;
        while self.pos < self.val.len() {
            if self.val[self.pos..].starts_with(&self.sep[..self.sep_len]) {
                let arg = ArgStr(Cow::Borrowed(&self.val[start..self.pos]));
                self.pos += self.sep_len;
                return Some(arg);
            }
            self.pos += 1;
        }
        Some(ArgStr(Cow::Borrowed(&self.val[start..])))
    }
}
<commit_msg>Optimize ArgStr<commit_after>use std::{
    borrow::Cow,
    ffi::{OsStr, OsString},
    fmt::{self, Debug},
    str,
};

use os_str_bytes::{raw, OsStrBytes};

#[derive(PartialEq, Eq)]
pub(crate) struct ArgStr<'a>(Cow<'a, [u8]>);

impl<'a> ArgStr<'a> {
    pub(crate) fn new(s: &'a OsStr) -> Self {
        Self(s.to_raw_bytes())
    }

    pub(crate) fn starts_with(&self, s: &str) -> bool {
        self.0.starts_with(s.as_bytes())
    }

    pub(crate) fn is_prefix_of(&self, s: &str) -> bool {
        raw::starts_with(s, &self.0)
    }

    fn to_borrowed(&'a self) -> Self {
        Self(Cow::Borrowed(&self.0))
    }

    pub(crate) fn contains_byte(&self, byte: u8) -> bool {
        debug_assert!(byte.is_ascii());

        self.0.contains(&byte)
    }

    pub(crate) fn contains_char(&self, ch: char) -> bool {
        self.to_string_lossy().contains(|x| x == ch)
    }

    pub(crate) fn split_at_byte(&self, byte: u8) -> (ArgStr, ArgStr) {
        debug_assert!(byte.is_ascii());

        if let Some(i) = self.0.iter().position(|&x| x == byte) {
            self.split_at_unchecked(i)
        } else {
            (self.to_borrowed(), Self(Cow::Borrowed(&[])))
        }
    }

    pub(crate) fn trim_start_matches(&'a self, byte: u8) -> ArgStr {
        debug_assert!(byte.is_ascii());

        if let Some(i) = self.0.iter().position(|x| x != &byte) {
            Self(Cow::Borrowed(&self.0[i..]))
        } else {
            Self(Cow::Borrowed(&[]))
        }
    }

    // Like `trim_start_matches`, but trims no more than `n` matches
    pub(crate) fn trim_start_n_matches(&'a self, n: usize, byte: u8) -> ArgStr {
        debug_assert!(byte.is_ascii());

        if let Some(i) = self.0.iter().take(n).position(|x| x != &byte) {
            Self(Cow::Borrowed(&self.0[i..]))
        } else {
            match self.0.get(n..) {
                Some(x) => Self(Cow::Borrowed(x)),
                None => Self(Cow::Borrowed(&[])),
            }
        }
    }

    pub(crate) fn split_at_unchecked(&'a self, i: usize) -> (ArgStr, ArgStr) {
        (
            Self(Cow::Borrowed(&self.0[..i])),
            Self(Cow::Borrowed(&self.0[i..])),
        )
    }

    pub(crate) fn split(&self, ch: char) -> ArgSplit<'_> {
        let mut sep = [0; 4];
        ArgSplit {
            sep_len: ch.encode_utf8(&mut sep).as_bytes().len(),
            sep,
            val: &self.0,
            pos: 0,
        }
    }

    #[allow(dead_code)]
    pub(crate) fn as_raw_bytes(&self) -> &[u8] {
        &self.0
    }

    pub(crate) fn len(&self) -> usize {
        self.0.len()
    }

    #[allow(dead_code)]
    pub(crate) fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    pub(crate) fn to_str(&self) -> Option<&str> {
        str::from_utf8(&self.0).ok()
    }

    pub(crate) fn to_string_lossy(&self) -> Cow<'_, str> {
        String::from_utf8_lossy(&self.0)
    }

    pub(crate) fn to_os_string(&self) -> OsString {
        self.to_borrowed().into_os_string()
    }

    pub(crate) fn into_os_string(self) -> OsString {
        OsStr::from_raw_bytes(self.0).unwrap().into_owned()
    }
}

impl<'a> Debug for ArgStr<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.to_string_lossy())
    }
}

impl<'a> PartialEq<str> for ArgStr<'a> {
    fn eq(&self, other: &str) -> bool {
        self.0 == other.as_bytes()
    }
}

impl<'a> PartialEq<&str> for ArgStr<'a> {
    fn eq(&self, other: &&str) -> bool {
        self.eq(*other)
    }
}

impl<'a> PartialEq<ArgStr<'a>> for str {
    fn eq(&self, other: &ArgStr<'a>) -> bool {
        other.eq(self)
    }
}

impl<'a> PartialEq<ArgStr<'a>> for &str {
    fn eq(&self, other: &ArgStr<'a>) -> bool {
        other.eq(self)
    }
}

#[derive(Clone, Debug)]
pub(crate) struct ArgSplit<'a> {
    sep: [u8; 4],
    sep_len: usize,
    val: &'a [u8],
    pos: usize,
}

impl<'a> Iterator for ArgSplit<'a> {
    type Item = ArgStr<'a>;

    fn next(&mut self) -> Option<ArgStr<'a>> {
        debug!("ArgSplit::next: self={:?}", self);

        if self.pos == self.val.len() {
            return None;
        }
        let start = self.pos;
        while self.pos < self.val.len() {
            if self.val[self.pos..].starts_with(&self.sep[..self.sep_len]) {
                let arg = ArgStr(Cow::Borrowed(&self.val[start..self.pos]));
                self.pos += self.sep_len;
                return Some(arg);
            }
            self.pos += 1;
        }
        Some(ArgStr(Cow::Borrowed(&self.val[start..])))
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    #[rustfmt::skip]
    fn test_trim_start_matches() {
        let raw = OsString::from("hello? world");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_matches(b'-');
        assert_eq!(trimmed, a);

        let raw = OsString::from("------------hello? world");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_matches(b'-');
        assert_eq!(trimmed, ArgStr::new(&OsString::from("hello? world")));

        let raw = OsString::from("------------hel-lo? -world");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_matches(b'-');
        assert_eq!(trimmed, ArgStr::new(&OsString::from("hel-lo? -world")));

        let raw = OsString::from("hel-lo? -world");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_matches(b'-');
        assert_eq!(trimmed, ArgStr::new(&OsString::from("hel-lo? -world")));

        let raw = OsString::from("");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_matches(b'-');
        assert_eq!(trimmed, ArgStr::new(&OsString::from("")));
    }

    #[test]
    #[rustfmt::skip]
    fn test_trim_start_n_matches() {
        let raw = OsString::from("hello? world");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_n_matches(2, b'-');
        assert_eq!(trimmed, a);

        let raw = OsString::from("------------hello? world");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_n_matches(2, b'-');
        assert_eq!(trimmed, ArgStr::new(&OsString::from("----------hello? world")));

        let raw = OsString::from("------------hello? world");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_n_matches(1000, b'-');
        assert_eq!(trimmed, ArgStr::new(&OsString::from("hello? world")));

        let raw = OsString::from("------------hel-lo? -world");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_n_matches(2, b'-');
        assert_eq!(trimmed, ArgStr::new(&OsString::from("----------hel-lo? -world")));

        let raw = OsString::from("-hel-lo? -world");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_n_matches(5, b'-');
        assert_eq!(trimmed, ArgStr::new(&OsString::from("hel-lo? -world")));

        let raw = OsString::from("hel-lo? -world");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_n_matches(10, b'-');
        assert_eq!(trimmed, ArgStr::new(&OsString::from("hel-lo? -world")));

        let raw = OsString::from("");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_n_matches(10, b'-');
        assert_eq!(trimmed, ArgStr::new(&OsString::from("")));

        let raw = OsString::from("");
        let a = ArgStr::new(&raw);
        let trimmed = a.trim_start_n_matches(0, b'-');
        assert_eq!(trimmed, ArgStr::new(&OsString::from("")));
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

//! The macros crate contains all useful needed macros.

/// Get the count of macro's arguments.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate tikv;
/// # fn main() {
/// assert_eq!(count_args!(), 0);
/// assert_eq!(count_args!(1), 1);
/// assert_eq!(count_args!(1, 2), 2);
/// assert_eq!(count_args!(1, 2, 3), 3);
/// # }
/// ```
#[macro_export]
macro_rules! count_args {
    () => { 0 };
    ($head:expr $(, $tail:expr)*) => { 1 + count_args!($($tail),*) };
}

/// Initial a `HashMap` with specify key-value pairs.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate tikv;
/// # fn main() {
/// // empty map
/// let m: tikv::util::collections::HashMap<u8, u8> = map!();
/// assert!(m.is_empty());
///
/// // one initial kv pairs.
/// let m = map!("key" => "value");
/// assert_eq!(m.len(), 1);
/// assert_eq!(m["key"], "value");
///
/// // initialize with multiple kv pairs.
/// let m = map!("key1" => "value1", "key2" => "value2");
/// assert_eq!(m.len(), 2);
/// assert_eq!(m["key1"], "value1");
/// assert_eq!(m["key2"], "value2");
/// # }
/// ```
///
/// This macro may be removed once
/// [official implementation](https://github.com/rust-lang/rfcs/issues/542) is provided.
#[macro_export]
macro_rules! map {
    () => {
        {
            $crate::util::collections::HashMap::default()
        }
    };
    ( $( $k:expr => $v:expr ),+ ) => {
        {
            let mut temp_map =
                $crate::util::collections::HashMap::with_capacity_and_hasher(
                    count_args!($(($k, $v)),+),
                    Default::default()
                );
            $(
                temp_map.insert($k, $v);
            )+
            temp_map
        }
    };
}

/// box try will box error first, and then do the same thing as try!.
#[macro_export]
macro_rules! box_try {
    ($expr:expr) => ({
        match $expr {
            Ok(r) => r,
            Err(e) => return Err(box_err!(e)),
        }
    })
}

/// A shortcut to box an error.
#[macro_export]
macro_rules! box_err {
    ($e:expr) => ({
        use std::error::Error;
        let e: Box<Error + Sync + Send> = ($e).into();
        e.into()
    });
    ($f:tt, $($arg:expr),+) => ({
        box_err!(format!($f, $($arg),+))
    });
}

#[allow(doc_markdown)]
/// Recover from panicable closure.
///
/// Please note that this macro assume the closure is able to be forced to implement `UnwindSafe`.
/// Also see https://doc.rust-lang.org/std/panic/struct.AssertUnwindSafe.html
// Maybe we should define a recover macro too.
#[macro_export]
macro_rules! recover_safe {
    ($e:expr) => ({
        use std::panic::{AssertUnwindSafe, catch_unwind};
        use $crate::util::panic_hook;
        panic_hook::mute();
        let res = catch_unwind(AssertUnwindSafe($e));
        panic_hook::unmute();
        res
    })
}

/// Log slow operations with warn!.
macro_rules! slow_log {
    ($t:expr, $($arg:tt)*) => {{
        if $t.is_slow() {
            warn!("{} [takes {:?}]", format_args!($($arg)*), $t.elapsed());
        }
    }}
}

/// make a thread name with additional tag inheriting from current thread.
#[macro_export]
macro_rules! thd_name {
    ($name:expr) => ({
        $crate::util::get_tag_from_thread_name().map(|tag| {
            format!("{}::{}", $name, tag)
        }).unwrap_or_else(|| $name.to_owned())
    });
}

/// Simulating go's defer.
///
/// Please note that, different from go, this defer is bound to scope.
/// When exiting the scope, its deferred calls are executed in last-in-first-out order.
#[macro_export]
macro_rules! defer {
    ($t:expr) => (
        let __ctx = $crate::util::DeferContext::new(|| $t);
    );
}

/// `wait_op!` waits for async operation. It returns `Option<Res>`
/// after the expression get executed.
#[macro_export]
macro_rules! wait_op {
    ($expr:expr) => {
        wait_op!(IMPL $expr, None)
    };
    ($expr:expr, $timeout:expr) => {
        wait_op!(IMPL $expr, Some($timeout))
    };
    (IMPL $expr:expr, $timeout:expr) => {
        {
            use std::sync::mpsc;
            let (tx, rx) = mpsc::channel();
            let cb = box move |res| {
                 // we don't care error actually.
                let _ = tx.send(res);
            };
            $expr(cb);
            match $timeout {
                None => rx.recv().ok(),
                Some(timeout) => rx.recv_timeout(timeout).ok()
            }
        }
    }
}

/// `try_opt` check `Result<Option<T>>`, return early when met `Err` or `Ok(None)`.
#[macro_export]
macro_rules! try_opt {
    ($expr:expr) => ({
        match $expr {
            Err(e) => return Err(e.into()),
            Ok(None) => return Ok(None),
            Ok(Some(res)) => res,
        }
    });
}
<commit_msg>util/macros: update map doc (#2418)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

//! The macros crate contains all useful needed macros.

/// Get the count of macro's arguments.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate tikv;
/// # fn main() {
/// assert_eq!(count_args!(), 0);
/// assert_eq!(count_args!(1), 1);
/// assert_eq!(count_args!(1, 2), 2);
/// assert_eq!(count_args!(1, 2, 3), 3);
/// # }
/// ```
#[macro_export]
macro_rules! count_args {
    () => { 0 };
    ($head:expr $(, $tail:expr)*) => { 1 + count_args!($($tail),*) };
}

/// Initial a `HashMap` with specify key-value pairs.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate tikv;
/// # fn main() {
/// // empty map
/// let m: tikv::util::collections::HashMap<u8, u8> = map!();
/// assert!(m.is_empty());
///
/// // one initial kv pairs.
/// let m = map!("key" => "value");
/// assert_eq!(m.len(), 1);
/// assert_eq!(m["key"], "value");
///
/// // initialize with multiple kv pairs.
/// let m = map!("key1" => "value1", "key2" => "value2");
/// assert_eq!(m.len(), 2);
/// assert_eq!(m["key1"], "value1");
/// assert_eq!(m["key2"], "value2");
/// # }
/// ```
#[macro_export]
macro_rules! map {
    () => {
        {
            $crate::util::collections::HashMap::default()
        }
    };
    ( $( $k:expr => $v:expr ),+ ) => {
        {
            let mut temp_map =
                $crate::util::collections::HashMap::with_capacity_and_hasher(
                    count_args!($(($k, $v)),+),
                    Default::default()
                );
            $(
                temp_map.insert($k, $v);
            )+
            temp_map
        }
    };
}

/// box try will box error first, and then do the same thing as try!.
#[macro_export]
macro_rules! box_try {
    ($expr:expr) => ({
        match $expr {
            Ok(r) => r,
            Err(e) => return Err(box_err!(e)),
        }
    })
}

/// A shortcut to box an error.
#[macro_export]
macro_rules! box_err {
    ($e:expr) => ({
        use std::error::Error;
        let e: Box<Error + Sync + Send> = ($e).into();
        e.into()
    });
    ($f:tt, $($arg:expr),+) => ({
        box_err!(format!($f, $($arg),+))
    });
}

#[allow(doc_markdown)]
/// Recover from panicable closure.
///
/// Please note that this macro assume the closure is able to be forced to implement `UnwindSafe`.
/// Also see https://doc.rust-lang.org/std/panic/struct.AssertUnwindSafe.html
// Maybe we should define a recover macro too.
#[macro_export]
macro_rules! recover_safe {
    ($e:expr) => ({
        use std::panic::{AssertUnwindSafe, catch_unwind};
        use $crate::util::panic_hook;
        panic_hook::mute();
        let res = catch_unwind(AssertUnwindSafe($e));
        panic_hook::unmute();
        res
    })
}

/// Log slow operations with warn!.
macro_rules! slow_log {
    ($t:expr, $($arg:tt)*) => {{
        if $t.is_slow() {
            warn!("{} [takes {:?}]", format_args!($($arg)*), $t.elapsed());
        }
    }}
}

/// make a thread name with additional tag inheriting from current thread.
#[macro_export]
macro_rules! thd_name {
    ($name:expr) => ({
        $crate::util::get_tag_from_thread_name().map(|tag| {
            format!("{}::{}", $name, tag)
        }).unwrap_or_else(|| $name.to_owned())
    });
}

/// Simulating go's defer.
///
/// Please note that, different from go, this defer is bound to scope.
/// When exiting the scope, its deferred calls are executed in last-in-first-out order.
#[macro_export]
macro_rules! defer {
    ($t:expr) => (
        let __ctx = $crate::util::DeferContext::new(|| $t);
    );
}

/// `wait_op!` waits for async operation. It returns `Option<Res>`
/// after the expression get executed.
#[macro_export]
macro_rules! wait_op {
    ($expr:expr) => {
        wait_op!(IMPL $expr, None)
    };
    ($expr:expr, $timeout:expr) => {
        wait_op!(IMPL $expr, Some($timeout))
    };
    (IMPL $expr:expr, $timeout:expr) => {
        {
            use std::sync::mpsc;
            let (tx, rx) = mpsc::channel();
            let cb = box move |res| {
                 // we don't care error actually.
                let _ = tx.send(res);
            };
            $expr(cb);
            match $timeout {
                None => rx.recv().ok(),
                Some(timeout) => rx.recv_timeout(timeout).ok()
            }
        }
    }
}

/// `try_opt` check `Result<Option<T>>`, return early when met `Err` or `Ok(None)`.
#[macro_export]
macro_rules! try_opt {
    ($expr:expr) => ({
        match $expr {
            Err(e) => return Err(e.into()),
            Ok(None) => return Ok(None),
            Ok(Some(res)) => res,
        }
    });
}
<|endoftext|>


<commit_before>// Copyright 2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::marker::PhantomData;
use glib::object::{Ref, Wrapper};
use glib::types::StaticType;

pub use glib::object::{Downcast, Upcast};

/// The generic type for `GObject` descendants in GTK.
pub struct Object<T>(Ref, PhantomData<T>);

impl<T> Wrapper for Object<T>
where Object<T>: StaticType {
    type GlibType = T;
    #[inline]
    unsafe fn wrap(r: Ref) -> Object<T> { Object(r, PhantomData) }
    #[inline]
    fn as_ref(&self) -> &Ref { &self.0 }
    #[inline]
    fn unwrap(self) -> Ref { self.0 }
}

impl<T> Clone for Object<T> {
    fn clone(&self) -> Object<T> {
        Object(self.0.clone(), PhantomData)
    }
}

unsafe impl<T> Upcast<::glib::object::Object> for Object<T> where Object<T>: StaticType { }
<commit_msg>Adapt to WF fixes in glib::object<commit_after>// Copyright 2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::marker::PhantomData;
use glib::object::{Ref, Wrapper};
use glib::types::StaticType;

pub use glib::object::{Downcast, Upcast};

/// The generic type for `GObject` descendants in GTK.
pub struct Object<T>(Ref, PhantomData<T>);

impl<T: 'static> Wrapper for Object<T>
where Object<T>: StaticType {
    type GlibType = T;
    #[inline]
    unsafe fn wrap(r: Ref) -> Object<T> { Object(r, PhantomData) }
    #[inline]
    fn as_ref(&self) -> &Ref { &self.0 }
    #[inline]
    fn unwrap(self) -> Ref { self.0 }
}

impl<T> Clone for Object<T> {
    fn clone(&self) -> Object<T> {
        Object(self.0.clone(), PhantomData)
    }
}

unsafe impl<T: 'static> Upcast<::glib::object::Object> for Object<T> where Object<T>: StaticType { }
<|endoftext|>