<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::{
    convert::TryFrom,
    fmt::{self, Debug},
    hash::{Hash, Hasher},
};

use serde_json::{Map, Value};

use libcryptsetup_rs::SafeMemHandle;

use crate::{
    engine::types::{ClevisInfo, MaybeInconsistent},
    stratis::{StratisError, StratisResult},
};

/// A handle for memory designed to safely handle Stratis passphrases. It can
/// be coerced to a slice reference for use in read-only operations.
#[allow(clippy::non_send_fields_in_send_ty)]
pub struct SizedKeyMemory {
    mem: SafeMemHandle,
    size: usize,
}

impl SizedKeyMemory {
    pub fn new(mem: SafeMemHandle, size: usize) -> SizedKeyMemory {
        SizedKeyMemory { mem, size }
    }
}

// This is safe to send across threads because the *mut c_void pointer is always
// allocated in the heap by libcryptsetup which is accessible globally to all threads
// in the process.
unsafe impl Send for SizedKeyMemory {}

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

impl AsRef<[u8]> for SizedKeyMemory {
    fn as_ref(&self) -> &[u8] {
        &self.mem.as_ref()[..self.size]
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum EncryptionInfo {
    KeyDesc(KeyDescription),
    ClevisInfo(ClevisInfo),
    Both(KeyDescription, ClevisInfo),
}

impl EncryptionInfo {
    /// Convert two optional encryption parameters into an EncryptionInfo enum.
    pub fn from_options(options: (Option<KeyDescription>, Option<ClevisInfo>)) -> Option<Self> {
        match options {
            (Some(kd), Some(ci)) => Some(EncryptionInfo::Both(kd, ci)),
            (Some(kd), _) => Some(EncryptionInfo::KeyDesc(kd)),
            (_, Some(ci)) => Some(EncryptionInfo::ClevisInfo(ci)),
            (None, None) => None,
        }
    }

    /// Set the key description.
    pub fn set_key_desc(self, key_desc: KeyDescription) -> Self {
        match self {
            EncryptionInfo::KeyDesc(_) => EncryptionInfo::KeyDesc(key_desc),
            EncryptionInfo::ClevisInfo(ci) => EncryptionInfo::Both(key_desc, ci),
            EncryptionInfo::Both(_, ci) => EncryptionInfo::Both(key_desc, ci),
        }
    }

    /// Unset the key description. If only Clevis info is set, no action is taken.
    /// Precondition: matches!(self, EncryptionInfo::Both(_, _) | EncryptonInfo::ClevisInfo(_))
    pub fn unset_key_desc(self) -> Self {
        match self {
            EncryptionInfo::KeyDesc(_) => {
                panic!("Cannot convert from encrypted to unencrypted device");
            }
            EncryptionInfo::Both(_, ci) => EncryptionInfo::ClevisInfo(ci),
            unchanged => unchanged,
        }
    }

    /// Set Clevis information.
    pub fn set_clevis_info(self, clevis_info: ClevisInfo) -> Self {
        match self {
            EncryptionInfo::ClevisInfo(_) => EncryptionInfo::ClevisInfo(clevis_info),
            EncryptionInfo::KeyDesc(kd) => EncryptionInfo::Both(kd, clevis_info),
            EncryptionInfo::Both(kd, _) => EncryptionInfo::Both(kd, clevis_info),
        }
    }

    /// Unset the Clevis info. If only the key description is set, no action is taken.
    /// Precondition: matches!(self, EncryptionInfo::Both(_, _) | EncryptonInfo::KeyDesc(_))
    pub fn unset_clevis_info(self) -> Self {
        match self {
            EncryptionInfo::ClevisInfo(_) => {
                panic!("Cannot convert from encrypted to unencrypted device");
            }
            EncryptionInfo::Both(kd, _) => EncryptionInfo::KeyDesc(kd),
            unchanged => unchanged,
        }
    }

    /// Get an optional key description from the encryption information.
    pub fn key_description(&self) -> Option<&KeyDescription> {
        match self {
            EncryptionInfo::Both(kd, _) | EncryptionInfo::KeyDesc(kd) => Some(kd),
            _ => None,
        }
    }

    /// Get optional Clevis information from the encryption information.
    pub fn clevis_info(&self) -> Option<&ClevisInfo> {
        match self {
            EncryptionInfo::Both(_, ci) | EncryptionInfo::ClevisInfo(ci) => Some(ci),
            _ => None,
        }
    }
}

impl fmt::Display for EncryptionInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let key_desc_str = if let Some(kd) = self.key_description() {
            format!("key description: \"{}\"", kd.as_application_str())
        } else {
            "no key description".to_string()
        };
        if let Some((pin, config)) = self.clevis_info() {
            write!(
                f,
                "{}, clevis pin: \"{}\", clevis configuration: \"{}\"",
                key_desc_str, pin, config
            )
        } else {
            write!(f, "{}, no Clevis information", key_desc_str)
        }
    }
}

// Implement Hash explicitly because Value does not implement Hash.
// The reason Value does not implement Hash is that some JSON is really big
// and hashing it would be expensive. This JSON probably won't be, but it
// serves no obvious purpose to stringify it and then hash it.
// Necessary Hash Property: \forall x_1, x_2 in EncryptionInfo,
// if x_1 == x_2, then hash(x_1) == hash(x_2) obviously holds.
#[allow(clippy::derive_hash_xor_eq)]
impl Hash for EncryptionInfo {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.key_description().hash(state);
        self.clevis_info().map(|(pin, _)| pin).hash(state);
    }
}

impl<'a> Into<Value> for &'a EncryptionInfo {
    fn into(self) -> Value {
        let mut json = Map::new();
        if let Some(kd) = self.key_description() {
            json.insert(
                "key_description".to_string(),
                Value::from(kd.as_application_str()),
            );
        }
        if let Some(info) = self.clevis_info() {
            json.insert("clevis_pin".to_string(), Value::from(info.0.to_owned()));
            json.insert("clevis_config".to_string(), info.1.clone());
        }
        Value::from(json)
    }
}

impl TryFrom<PoolEncryptionInfo> for EncryptionInfo {
    type Error = StratisError;

    fn try_from(pei: PoolEncryptionInfo) -> StratisResult<Self> {
        match pei {
            PoolEncryptionInfo::KeyDesc(MaybeInconsistent::No(kd)) => {
                Ok(EncryptionInfo::KeyDesc(kd))
            },
            PoolEncryptionInfo::ClevisInfo(MaybeInconsistent::No(ci)) => {
                Ok(EncryptionInfo::ClevisInfo(ci))
            },
            PoolEncryptionInfo::Both(MaybeInconsistent::No(kd), MaybeInconsistent::No(ci)) => {
                Ok(EncryptionInfo::Both(kd, ci))
            },
            _ => {
                Err(StratisError::Msg("Cannot determine encryption information from metadata that is inconsistent across devices in a pool".to_string()))
            }
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum PoolEncryptionInfo {
    KeyDesc(MaybeInconsistent<KeyDescription>),
    ClevisInfo(MaybeInconsistent<ClevisInfo>),
    Both(
        MaybeInconsistent<KeyDescription>,
        MaybeInconsistent<ClevisInfo>,
    ),
}

impl PoolEncryptionInfo {
    /// Reconcile two PoolEncryptionInfo records.
    ///
    /// Because rollback failure can result in some devices having a key description
    /// or Clevis info and some not having that information, any reconciliation
    /// for Some(_) and None will result in Some(MaybeInconsistent::Yes).
    fn add_enc_info<I>(self, info: I) -> Self
    where
        PoolEncryptionInfo: From<I>,
    {
        let pei = PoolEncryptionInfo::from(info);
        match (self, pei) {
            (PoolEncryptionInfo::KeyDesc(kd1), PoolEncryptionInfo::KeyDesc(kd2)) => {
                if kd1 != kd2 {
                    PoolEncryptionInfo::KeyDesc(MaybeInconsistent::Yes)
                } else {
                    PoolEncryptionInfo::KeyDesc(kd1)
                }
            }
            (PoolEncryptionInfo::ClevisInfo(ci1), PoolEncryptionInfo::ClevisInfo(ci2)) => {
                if ci1 != ci2 {
                    PoolEncryptionInfo::ClevisInfo(MaybeInconsistent::Yes)
                } else {
                    PoolEncryptionInfo::ClevisInfo(ci1)
                }
            }
            (PoolEncryptionInfo::Both(kd1, ci1), PoolEncryptionInfo::Both(kd2, ci2)) => {
                PoolEncryptionInfo::Both(
                    if kd1 != kd2 {
                        MaybeInconsistent::Yes
                    } else {
                        kd1
                    },
                    if ci1 != ci2 {
                        MaybeInconsistent::Yes
                    } else {
                        ci1
                    },
                )
            }
            (PoolEncryptionInfo::KeyDesc(_), PoolEncryptionInfo::ClevisInfo(_))
            | (PoolEncryptionInfo::ClevisInfo(_), PoolEncryptionInfo::KeyDesc(_)) => {
                PoolEncryptionInfo::Both(MaybeInconsistent::Yes, MaybeInconsistent::Yes)
            }
            (PoolEncryptionInfo::KeyDesc(kd1), PoolEncryptionInfo::Both(kd2, _))
            | (PoolEncryptionInfo::Both(kd1, _), PoolEncryptionInfo::KeyDesc(kd2)) => {
                PoolEncryptionInfo::Both(
                    if kd1 != kd2 {
                        MaybeInconsistent::Yes
                    } else {
                        kd1
                    },
                    MaybeInconsistent::Yes,
                )
            }
            (PoolEncryptionInfo::ClevisInfo(ci1), PoolEncryptionInfo::Both(_, ci2))
            | (PoolEncryptionInfo::Both(_, ci1), PoolEncryptionInfo::ClevisInfo(ci2)) => {
                PoolEncryptionInfo::Both(
                    MaybeInconsistent::Yes,
                    if ci1 != ci2 {
                        MaybeInconsistent::Yes
                    } else {
                        ci1
                    },
                )
            }
        }
    }

    pub fn is_inconsistent(&self) -> bool {
        matches!(
            self,
            PoolEncryptionInfo::KeyDesc(MaybeInconsistent::Yes)
                | PoolEncryptionInfo::ClevisInfo(MaybeInconsistent::Yes)
                | PoolEncryptionInfo::Both(MaybeInconsistent::Yes, _)
                | PoolEncryptionInfo::Both(_, MaybeInconsistent::Yes)
        )
    }

    pub fn key_description(&self) -> StratisResult<Option<&KeyDescription>> {
        match self {
            PoolEncryptionInfo::KeyDesc(kd) | PoolEncryptionInfo::Both(kd, _) => {
                if let MaybeInconsistent::No(ref key_description) = kd {
                    Ok(Some(key_description))
                } else {
                    Err(StratisError::Msg(
                        "Key description is inconsistent across devices".to_string(),
                    ))
                }
            }
            _ => Ok(None),
        }
    }

    pub fn clevis_info(&self) -> StratisResult<Option<&ClevisInfo>> {
        match self {
            PoolEncryptionInfo::ClevisInfo(ci) | PoolEncryptionInfo::Both(_, ci) => {
                if let MaybeInconsistent::No(ref clevis_info) = ci {
                    Ok(Some(clevis_info))
                } else {
                    Err(StratisError::Msg(
                        "Clevis information is inconsistent across devices".to_string(),
                    ))
                }
            }
            _ => Ok(None),
        }
    }
}

impl From<&EncryptionInfo> for PoolEncryptionInfo {
    fn from(enc_info: &EncryptionInfo) -> Self {
        match enc_info {
            EncryptionInfo::KeyDesc(ref kd) => {
                PoolEncryptionInfo::KeyDesc(MaybeInconsistent::No(kd.to_owned()))
            }
            EncryptionInfo::ClevisInfo(ref ci) => {
                PoolEncryptionInfo::ClevisInfo(MaybeInconsistent::No(ci.to_owned()))
            }
            EncryptionInfo::Both(ref kd, ref ci) => PoolEncryptionInfo::Both(
                MaybeInconsistent::No(kd.to_owned()),
                MaybeInconsistent::No(ci.to_owned()),
            ),
        }
    }
}

impl<'a, I> From<I> for PoolEncryptionInfo
where
    I: IntoIterator<Item = &'a EncryptionInfo>,
{
    // Precondition: Iterator must have at least one item.
    fn from(into_iterator: I) -> Self {
        let mut iterator = into_iterator.into_iter();
        match iterator.next() {
            Some(ei) => iterator.fold(PoolEncryptionInfo::from(ei), |pool_enc_info, next| {
                pool_enc_info.add_enc_info(next)
            }),
            None => panic!("Cannot supply empty iterator"),
        }
    }
}

/// A data type respresenting a key description for the kernel keyring
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct KeyDescription(String);

impl KeyDescription {
    /// Return the application-level key description (the key description with no
    /// Stratis prefix added).
    pub fn as_application_str(&self) -> &str {
        &self.0
    }
}

// Key descriptions with ';'s are disallowed because a key description
// containing a ';' will not be able to be correctly parsed from the kernel's
// describe string, which uses ';'s as field delimiters.
impl TryFrom<String> for KeyDescription {
    type Error = StratisError;

    fn try_from(s: String) -> StratisResult<KeyDescription> {
        if s.contains(';') {
            Err(StratisError::Msg(format!(
                "Key description {} contains a ';'",
                s
            )))
        } else {
            Ok(KeyDescription(s))
        }
    }
}

impl<'a> TryFrom<&'a String> for KeyDescription {
    type Error = StratisError;

    fn try_from(s: &String) -> StratisResult<KeyDescription> {
        KeyDescription::try_from(s.to_owned())
    }
}
<commit_msg>Revert "Allow clippy non_send_fields_in_send_ty for SizedKeyMemory"<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::{
    convert::TryFrom,
    fmt::{self, Debug},
    hash::{Hash, Hasher},
};

use serde_json::{Map, Value};

use libcryptsetup_rs::SafeMemHandle;

use crate::{
    engine::types::{ClevisInfo, MaybeInconsistent},
    stratis::{StratisError, StratisResult},
};

/// A handle for memory designed to safely handle Stratis passphrases. It can
/// be coerced to a slice reference for use in read-only operations.
pub struct SizedKeyMemory {
    mem: SafeMemHandle,
    size: usize,
}

impl SizedKeyMemory {
    pub fn new(mem: SafeMemHandle, size: usize) -> SizedKeyMemory {
        SizedKeyMemory { mem, size }
    }
}

// This is safe to send across threads because the *mut c_void pointer is always
// allocated in the heap by libcryptsetup which is accessible globally to all threads
// in the process.
unsafe impl Send for SizedKeyMemory {}

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

impl AsRef<[u8]> for SizedKeyMemory {
    fn as_ref(&self) -> &[u8] {
        &self.mem.as_ref()[..self.size]
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum EncryptionInfo {
    KeyDesc(KeyDescription),
    ClevisInfo(ClevisInfo),
    Both(KeyDescription, ClevisInfo),
}

impl EncryptionInfo {
    /// Convert two optional encryption parameters into an EncryptionInfo enum.
    pub fn from_options(options: (Option<KeyDescription>, Option<ClevisInfo>)) -> Option<Self> {
        match options {
            (Some(kd), Some(ci)) => Some(EncryptionInfo::Both(kd, ci)),
            (Some(kd), _) => Some(EncryptionInfo::KeyDesc(kd)),
            (_, Some(ci)) => Some(EncryptionInfo::ClevisInfo(ci)),
            (None, None) => None,
        }
    }

    /// Set the key description.
    pub fn set_key_desc(self, key_desc: KeyDescription) -> Self {
        match self {
            EncryptionInfo::KeyDesc(_) => EncryptionInfo::KeyDesc(key_desc),
            EncryptionInfo::ClevisInfo(ci) => EncryptionInfo::Both(key_desc, ci),
            EncryptionInfo::Both(_, ci) => EncryptionInfo::Both(key_desc, ci),
        }
    }

    /// Unset the key description. If only Clevis info is set, no action is taken.
    /// Precondition: matches!(self, EncryptionInfo::Both(_, _) | EncryptonInfo::ClevisInfo(_))
    pub fn unset_key_desc(self) -> Self {
        match self {
            EncryptionInfo::KeyDesc(_) => {
                panic!("Cannot convert from encrypted to unencrypted device");
            }
            EncryptionInfo::Both(_, ci) => EncryptionInfo::ClevisInfo(ci),
            unchanged => unchanged,
        }
    }

    /// Set Clevis information.
    pub fn set_clevis_info(self, clevis_info: ClevisInfo) -> Self {
        match self {
            EncryptionInfo::ClevisInfo(_) => EncryptionInfo::ClevisInfo(clevis_info),
            EncryptionInfo::KeyDesc(kd) => EncryptionInfo::Both(kd, clevis_info),
            EncryptionInfo::Both(kd, _) => EncryptionInfo::Both(kd, clevis_info),
        }
    }

    /// Unset the Clevis info. If only the key description is set, no action is taken.
    /// Precondition: matches!(self, EncryptionInfo::Both(_, _) | EncryptonInfo::KeyDesc(_))
    pub fn unset_clevis_info(self) -> Self {
        match self {
            EncryptionInfo::ClevisInfo(_) => {
                panic!("Cannot convert from encrypted to unencrypted device");
            }
            EncryptionInfo::Both(kd, _) => EncryptionInfo::KeyDesc(kd),
            unchanged => unchanged,
        }
    }

    /// Get an optional key description from the encryption information.
    pub fn key_description(&self) -> Option<&KeyDescription> {
        match self {
            EncryptionInfo::Both(kd, _) | EncryptionInfo::KeyDesc(kd) => Some(kd),
            _ => None,
        }
    }

    /// Get optional Clevis information from the encryption information.
    pub fn clevis_info(&self) -> Option<&ClevisInfo> {
        match self {
            EncryptionInfo::Both(_, ci) | EncryptionInfo::ClevisInfo(ci) => Some(ci),
            _ => None,
        }
    }
}

impl fmt::Display for EncryptionInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let key_desc_str = if let Some(kd) = self.key_description() {
            format!("key description: \"{}\"", kd.as_application_str())
        } else {
            "no key description".to_string()
        };
        if let Some((pin, config)) = self.clevis_info() {
            write!(
                f,
                "{}, clevis pin: \"{}\", clevis configuration: \"{}\"",
                key_desc_str, pin, config
            )
        } else {
            write!(f, "{}, no Clevis information", key_desc_str)
        }
    }
}

// Implement Hash explicitly because Value does not implement Hash.
// The reason Value does not implement Hash is that some JSON is really big
// and hashing it would be expensive. This JSON probably won't be, but it
// serves no obvious purpose to stringify it and then hash it.
// Necessary Hash Property: \forall x_1, x_2 in EncryptionInfo,
// if x_1 == x_2, then hash(x_1) == hash(x_2) obviously holds.
#[allow(clippy::derive_hash_xor_eq)]
impl Hash for EncryptionInfo {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.key_description().hash(state);
        self.clevis_info().map(|(pin, _)| pin).hash(state);
    }
}

impl<'a> Into<Value> for &'a EncryptionInfo {
    fn into(self) -> Value {
        let mut json = Map::new();
        if let Some(kd) = self.key_description() {
            json.insert(
                "key_description".to_string(),
                Value::from(kd.as_application_str()),
            );
        }
        if let Some(info) = self.clevis_info() {
            json.insert("clevis_pin".to_string(), Value::from(info.0.to_owned()));
            json.insert("clevis_config".to_string(), info.1.clone());
        }
        Value::from(json)
    }
}

impl TryFrom<PoolEncryptionInfo> for EncryptionInfo {
    type Error = StratisError;

    fn try_from(pei: PoolEncryptionInfo) -> StratisResult<Self> {
        match pei {
            PoolEncryptionInfo::KeyDesc(MaybeInconsistent::No(kd)) => {
                Ok(EncryptionInfo::KeyDesc(kd))
            },
            PoolEncryptionInfo::ClevisInfo(MaybeInconsistent::No(ci)) => {
                Ok(EncryptionInfo::ClevisInfo(ci))
            },
            PoolEncryptionInfo::Both(MaybeInconsistent::No(kd), MaybeInconsistent::No(ci)) => {
                Ok(EncryptionInfo::Both(kd, ci))
            },
            _ => {
                Err(StratisError::Msg("Cannot determine encryption information from metadata that is inconsistent across devices in a pool".to_string()))
            }
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum PoolEncryptionInfo {
    KeyDesc(MaybeInconsistent<KeyDescription>),
    ClevisInfo(MaybeInconsistent<ClevisInfo>),
    Both(
        MaybeInconsistent<KeyDescription>,
        MaybeInconsistent<ClevisInfo>,
    ),
}

impl PoolEncryptionInfo {
    /// Reconcile two PoolEncryptionInfo records.
    ///
    /// Because rollback failure can result in some devices having a key description
    /// or Clevis info and some not having that information, any reconciliation
    /// for Some(_) and None will result in Some(MaybeInconsistent::Yes).
    fn add_enc_info<I>(self, info: I) -> Self
    where
        PoolEncryptionInfo: From<I>,
    {
        let pei = PoolEncryptionInfo::from(info);
        match (self, pei) {
            (PoolEncryptionInfo::KeyDesc(kd1), PoolEncryptionInfo::KeyDesc(kd2)) => {
                if kd1 != kd2 {
                    PoolEncryptionInfo::KeyDesc(MaybeInconsistent::Yes)
                } else {
                    PoolEncryptionInfo::KeyDesc(kd1)
                }
            }
            (PoolEncryptionInfo::ClevisInfo(ci1), PoolEncryptionInfo::ClevisInfo(ci2)) => {
                if ci1 != ci2 {
                    PoolEncryptionInfo::ClevisInfo(MaybeInconsistent::Yes)
                } else {
                    PoolEncryptionInfo::ClevisInfo(ci1)
                }
            }
            (PoolEncryptionInfo::Both(kd1, ci1), PoolEncryptionInfo::Both(kd2, ci2)) => {
                PoolEncryptionInfo::Both(
                    if kd1 != kd2 {
                        MaybeInconsistent::Yes
                    } else {
                        kd1
                    },
                    if ci1 != ci2 {
                        MaybeInconsistent::Yes
                    } else {
                        ci1
                    },
                )
            }
            (PoolEncryptionInfo::KeyDesc(_), PoolEncryptionInfo::ClevisInfo(_))
            | (PoolEncryptionInfo::ClevisInfo(_), PoolEncryptionInfo::KeyDesc(_)) => {
                PoolEncryptionInfo::Both(MaybeInconsistent::Yes, MaybeInconsistent::Yes)
            }
            (PoolEncryptionInfo::KeyDesc(kd1), PoolEncryptionInfo::Both(kd2, _))
            | (PoolEncryptionInfo::Both(kd1, _), PoolEncryptionInfo::KeyDesc(kd2)) => {
                PoolEncryptionInfo::Both(
                    if kd1 != kd2 {
                        MaybeInconsistent::Yes
                    } else {
                        kd1
                    },
                    MaybeInconsistent::Yes,
                )
            }
            (PoolEncryptionInfo::ClevisInfo(ci1), PoolEncryptionInfo::Both(_, ci2))
            | (PoolEncryptionInfo::Both(_, ci1), PoolEncryptionInfo::ClevisInfo(ci2)) => {
                PoolEncryptionInfo::Both(
                    MaybeInconsistent::Yes,
                    if ci1 != ci2 {
                        MaybeInconsistent::Yes
                    } else {
                        ci1
                    },
                )
            }
        }
    }

    pub fn is_inconsistent(&self) -> bool {
        matches!(
            self,
            PoolEncryptionInfo::KeyDesc(MaybeInconsistent::Yes)
                | PoolEncryptionInfo::ClevisInfo(MaybeInconsistent::Yes)
                | PoolEncryptionInfo::Both(MaybeInconsistent::Yes, _)
                | PoolEncryptionInfo::Both(_, MaybeInconsistent::Yes)
        )
    }

    pub fn key_description(&self) -> StratisResult<Option<&KeyDescription>> {
        match self {
            PoolEncryptionInfo::KeyDesc(kd) | PoolEncryptionInfo::Both(kd, _) => {
                if let MaybeInconsistent::No(ref key_description) = kd {
                    Ok(Some(key_description))
                } else {
                    Err(StratisError::Msg(
                        "Key description is inconsistent across devices".to_string(),
                    ))
                }
            }
            _ => Ok(None),
        }
    }

    pub fn clevis_info(&self) -> StratisResult<Option<&ClevisInfo>> {
        match self {
            PoolEncryptionInfo::ClevisInfo(ci) | PoolEncryptionInfo::Both(_, ci) => {
                if let MaybeInconsistent::No(ref clevis_info) = ci {
                    Ok(Some(clevis_info))
                } else {
                    Err(StratisError::Msg(
                        "Clevis information is inconsistent across devices".to_string(),
                    ))
                }
            }
            _ => Ok(None),
        }
    }
}

impl From<&EncryptionInfo> for PoolEncryptionInfo {
    fn from(enc_info: &EncryptionInfo) -> Self {
        match enc_info {
            EncryptionInfo::KeyDesc(ref kd) => {
                PoolEncryptionInfo::KeyDesc(MaybeInconsistent::No(kd.to_owned()))
            }
            EncryptionInfo::ClevisInfo(ref ci) => {
                PoolEncryptionInfo::ClevisInfo(MaybeInconsistent::No(ci.to_owned()))
            }
            EncryptionInfo::Both(ref kd, ref ci) => PoolEncryptionInfo::Both(
                MaybeInconsistent::No(kd.to_owned()),
                MaybeInconsistent::No(ci.to_owned()),
            ),
        }
    }
}

impl<'a, I> From<I> for PoolEncryptionInfo
where
    I: IntoIterator<Item = &'a EncryptionInfo>,
{
    // Precondition: Iterator must have at least one item.
    fn from(into_iterator: I) -> Self {
        let mut iterator = into_iterator.into_iter();
        match iterator.next() {
            Some(ei) => iterator.fold(PoolEncryptionInfo::from(ei), |pool_enc_info, next| {
                pool_enc_info.add_enc_info(next)
            }),
            None => panic!("Cannot supply empty iterator"),
        }
    }
}

/// A data type respresenting a key description for the kernel keyring
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct KeyDescription(String);

impl KeyDescription {
    /// Return the application-level key description (the key description with no
    /// Stratis prefix added).
    pub fn as_application_str(&self) -> &str {
        &self.0
    }
}

// Key descriptions with ';'s are disallowed because a key description
// containing a ';' will not be able to be correctly parsed from the kernel's
// describe string, which uses ';'s as field delimiters.
impl TryFrom<String> for KeyDescription {
    type Error = StratisError;

    fn try_from(s: String) -> StratisResult<KeyDescription> {
        if s.contains(';') {
            Err(StratisError::Msg(format!(
                "Key description {} contains a ';'",
                s
            )))
        } else {
            Ok(KeyDescription(s))
        }
    }
}

impl<'a> TryFrom<&'a String> for KeyDescription {
    type Error = StratisError;

    fn try_from(s: &String) -> StratisResult<KeyDescription> {
        KeyDescription::try_from(s.to_owned())
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::mem;

use common::err::*;
use exec::Executor;
use io::stream::*;
use schema::Schema;
use rows::RowBlock;
use types::*;

pub struct DelimTextScanner<'a> {
  data_schema : Schema,
  read_fields : Option<Schema>,
  line_delim  : u8,
  field_delim : u8,
  reader      : Box<StreamReader>,
  marker      : PhantomData<&'a ()>
}

impl<'a> Executor for DelimTextScanner<'a> {
  fn init(&mut self) -> Void {
    self.reader.read();
    void_ok()
  }

  fn next(&self, rowblock: &mut RowBlock) -> Void {
    void_ok()
  }

  fn close(&self) -> Void {
    void_ok()
  }

  fn in_schema(&self) -> &Schema {
    &self.data_schema
  }

  fn out_schema(&self) -> &Schema {
    match self.read_fields {
      Some(ref s) => s,
      None => &self.data_schema
    }
  }
}

impl<'a> DelimTextScanner<'a> {
  pub fn new(
        data_schema: Schema,
        read_fields: Option<Schema>,
        stream: Box<StreamReader>,
        field_delim: u8) -> DelimTextScanner<'a> {

    DelimTextScanner {
      data_schema: data_schema,
      read_fields: read_fields,

      line_delim: '\n' as u8,
      field_delim: field_delim,

      reader: stream,
      marker: PhantomData
    }
  }

  fn find_first_record_index(&self, text: &str) -> Option<usize> {
    let bytes : &[u8] = unsafe { mem::transmute(text) };

    let mut pos : usize = 0;
    let mut found : bool = false;

    for c in bytes {
      if self.line_delim == *c {
        found = true;
        break;
      }

      pos = pos + 1;
    }

    match found {
      true => Some(pos + 1),
      false => None
    }
  }

  /// Return the last index of fields, which will be used for the
  /// following call
  fn next_line_indexes(&self,
    text: &str,
    delim_indexes: &mut Vec<usize>,
    max_row_num: usize) -> (usize, usize) {

    let bytes : &[u8] = unsafe { mem::transmute(text) };
    let mut cur_delim_idx: usize = 0;
    let mut cur_pos: usize = 0;

    while (cur_pos < bytes.len() && cur_delim_idx < max_row_num) {
      let c: u8  = bytes[cur_pos];

      if c == self.line_delim {
        delim_indexes.push(cur_pos);
        cur_delim_idx = cur_delim_idx + 1;
      }

      cur_pos = cur_pos + 1;
    }

    let found_line_num = cur_delim_idx;
    let last_delim = if found_line_num > 0
    { delim_indexes[found_line_num - 1] } else { -1 };

    (found_line_num, last_delim)
  }
}

#[test]
fn test_find_first_record_index() {
  let mut s = Schema::new();
  s.add_column("c1", *TEXT_TY);
  s.add_column("c2", *TEXT_TY);

  let fin = Box::new(FileInputStream::new("/home/hyunsik/tpch/lineitem/lineitem.tbl".to_string()));
  let s = DelimTextScanner::new(s, None, fin, '\n' as u8);

  assert_eq!(4, s.find_first_record_index("abc\nbb").unwrap());
  assert_eq!(1, s.find_first_record_index("\nabc\nbb").unwrap());
  assert_eq!(2, s.find_first_record_index("\r\nabc\nbb").unwrap());
  assert!(s.find_first_record_index("aaaaabcabbb").is_none());
}

#[test]
fn test_next_line_indxes() {
  let mut schema = Schema::new();
  schema.add_column("c1", *TEXT_TY);
  schema.add_column("c2", *TEXT_TY);

  let mut fin = Box::new(FileInputStream::new("/home/hyunsik/tpch/lineitem/lineitem.tbl".to_string()));
  let s = DelimTextScanner::new(schema, None, fin, '\n' as u8);

  let mut delim_indexes:Vec<usize> = Vec::new();
  let r1 =
    s.next_line_indexes("abc\nbb\nabcdef\nabcd", &mut delim_indexes, 10);
  assert_eq!(3, r1.0);
  assert_eq!(13, r1.1);

  delim_indexes.clear();

  let r2 =
    s.next_line_indexes("a\nb\nabcde\n", &mut delim_indexes, 10);
  assert_eq!(3, r2.0);
  assert_eq!(9, r2.1);
}<commit_msg>Add member variables to text_scanner.<commit_after>use std::marker::PhantomData;
use std::mem;

use common::constant::VECTOR_SIZE;
use common::err::*;
use exec::Executor;
use io::stream::*;
use schema::Schema;
use rows::RowBlock;
use types::*;

pub struct DelimTextScanner<'a> {
  data_schema : Schema,
  read_fields : Option<Schema>,
  line_delim  : u8,
  field_delim : u8,
  reader      : Box<StreamReader>,
  marker      : PhantomData<&'a ()>,

  // variable
  last_read_len: usize,
  should_parse_line: bool
}

impl<'a> Executor for DelimTextScanner<'a> {
  fn init(&mut self) -> Void {
    self.reader.read();
    void_ok()
  }

  fn next(&self, rowblock: &mut RowBlock) -> Void {

    let mut row_idx: usize = 0;

    loop {

      if self.should_parse_line {
        //next_line_indexes()
      }

      if self.last_read_len < 1 || row_idx >= VECTOR_SIZE {
        break;
      }
    }

    void_ok()
  }

  fn close(&self) -> Void {
    void_ok()
  }

  fn in_schema(&self) -> &Schema {
    &self.data_schema
  }

  fn out_schema(&self) -> &Schema {
    match self.read_fields {
      Some(ref s) => s,
      None => &self.data_schema
    }
  }
}

impl<'a> DelimTextScanner<'a> {
  pub fn new(
        data_schema: Schema,
        read_fields: Option<Schema>,
        stream: Box<StreamReader>,
        field_delim: u8) -> DelimTextScanner<'a> {

    DelimTextScanner {
      data_schema: data_schema,
      read_fields: read_fields,

      line_delim: '\n' as u8,
      field_delim: field_delim,

      reader: stream,
      marker: PhantomData,

      last_read_len: 0,
      should_parse_line: true
    }
  }

  fn find_first_record_index(&self, text: &str) -> Option<usize> {
    let bytes : &[u8] = unsafe { mem::transmute(text) };

    let mut pos : usize = 0;
    let mut found : bool = false;

    for c in bytes {
      if self.line_delim == *c {
        found = true;
        break;
      }

      pos = pos + 1;
    }

    match found {
      true => Some(pos + 1),
      false => None
    }
  }

  /// Return the last index of fields, which will be used for the
  /// following call
  fn next_line_indexes(&self,
    text: &str,
    delim_indexes: &mut Vec<usize>,
    max_row_num: usize) -> (usize, usize) {

    let bytes : &[u8] = unsafe { mem::transmute(text) };
    let mut cur_delim_idx: usize = 0;
    let mut cur_pos: usize = 0;

    while (cur_pos < bytes.len() && cur_delim_idx < max_row_num) {
      let c: u8  = bytes[cur_pos];

      if c == self.line_delim {
        delim_indexes.push(cur_pos);
        cur_delim_idx = cur_delim_idx + 1;
      }

      cur_pos = cur_pos + 1;
    }

    let found_line_num = cur_delim_idx;
    let last_delim = if found_line_num > 0
    { delim_indexes[found_line_num - 1] } else { -1 };

    (found_line_num, last_delim)
  }
}

#[test]
fn test_find_first_record_index() {
  let mut s = Schema::new();
  s.add_column("c1", *TEXT_TY);
  s.add_column("c2", *TEXT_TY);

  let fin = Box::new(FileInputStream::new("/home/hyunsik/tpch/lineitem/lineitem.tbl".to_string()));
  let s = DelimTextScanner::new(s, None, fin, '\n' as u8);

  assert_eq!(4, s.find_first_record_index("abc\nbb").unwrap());
  assert_eq!(1, s.find_first_record_index("\nabc\nbb").unwrap());
  assert_eq!(2, s.find_first_record_index("\r\nabc\nbb").unwrap());
  assert!(s.find_first_record_index("aaaaabcabbb").is_none());
}

#[test]
fn test_next_line_indxes() {
  let mut schema = Schema::new();
  schema.add_column("c1", *TEXT_TY);
  schema.add_column("c2", *TEXT_TY);

  let mut fin = Box::new(FileInputStream::new("/home/hyunsik/tpch/lineitem/lineitem.tbl".to_string()));
  let s = DelimTextScanner::new(schema, None, fin, '\n' as u8);

  let mut delim_indexes:Vec<usize> = Vec::new();
  let r1 =
    s.next_line_indexes("abc\nbb\nabcdef\nabcd", &mut delim_indexes, 10);
  assert_eq!(3, r1.0);
  assert_eq!(13, r1.1);

  delim_indexes.clear();

  let r2 =
    s.next_line_indexes("a\nb\nabcde\n", &mut delim_indexes, 10);
  assert_eq!(3, r2.0);
  assert_eq!(9, r2.1);
}<|endoftext|>


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

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Alan Andrade <alan.andradec@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;
#[cfg(windows)]
extern crate winapi;

#[macro_use]
extern crate uucore;

use std::collections::hash_set::HashSet;
use std::iter::repeat;
use std::io;
use std::str;
use std::net::ToSocketAddrs;
use getopts::Matches;

#[cfg(windows)]
use winapi::um::winsock2::{GetHostNameW, WSACleanup, WSAStartup};
#[cfg(windows)]
use winapi::um::sysinfoapi::{ComputerNamePhysicalDnsHostname, SetComputerNameExW};
#[cfg(windows)]
use winapi::shared::minwindef::MAKEWORD;
#[cfg(windows)]
use uucore::wide::*;

#[cfg(not(windows))]
use libc::gethostname;
#[cfg(not(windows))]
use libc::sethostname;

const SYNTAX: &str = "[OPTION]... [HOSTNAME]";
const SUMMARY: &str = "Print or set the system's host name.";
const LONG_HELP: &str = "";

pub fn uumain(args: Vec<String>) -> i32 {
    #[cfg(windows)]
    unsafe {
        let mut data = std::mem::uninitialized();
        if WSAStartup(MAKEWORD(2, 2), &mut data as *mut _) != 0 {
            eprintln!("Failed to start Winsock 2.2");
            return 1;
        }
    }
    let result = execute(args);
    #[cfg(windows)]
    unsafe {
        WSACleanup();
    }
    result
}

fn execute(args: Vec<String>) -> i32 {
    let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP)
        .optflag("d", "domain", "Display the name of the DNS domain if possible")
        .optflag("i", "ip-address", "Display the network address(es) of the host")
        // TODO: support --long
        .optflag("f", "fqdn", "Display the FQDN (Fully Qualified Domain Name) (default)")
        .optflag("s", "short", "Display the short hostname (the portion before the first dot) if \
                                possible")
        .parse(args);

    match matches.free.len() {
        0 => display_hostname(matches),
        1 => {
            if let Err(err) = xsethostname(matches.free.last().unwrap()) {
                show_error!("{}", err);
                1
            } else {
                0
            }
        }
        _ => {
            show_error!("{}", msg_wrong_number_of_arguments!(0, 1));
            1
        }
    }
}

fn display_hostname(matches: Matches) -> i32 {
    let hostname = return_if_err!(1, xgethostname());

    if matches.opt_present("i") {
        // XXX: to_socket_addrs needs hostname:port so append a dummy port and remove it later.
        // This was originally supposed to use std::net::lookup_host, but that seems to be
        // deprecated.  Perhaps we should use the dns-lookup crate?
        let hostname = hostname + ":1";
        match hostname.to_socket_addrs() {
            Ok(addresses) => {
                let mut hashset = HashSet::new();
                let mut output = String::new();
                for addr in addresses {
                    // XXX: not sure why this is necessary...
                    if !hashset.contains(&addr) {
                        let mut ip = format!("{}", addr);
                        if ip.ends_with(":1") {
                            let len = ip.len();
                            ip.truncate(len - 2);
                        }
                        output.push_str(&ip);
                        output.push_str(" ");
                        hashset.insert(addr);
                    }
                }
                let len = output.len();
                if len > 0 {
                    println!("{}", &output[0..len - 1]);
                }

                0
            }
            Err(f) => {
                show_error!("{}", f);

                1
            }
        }
    } else {
        if matches.opt_present("s") || matches.opt_present("d") {
            let mut it = hostname.char_indices().filter(|&ci| ci.1 == '.');
            if let Some(ci) = it.next() {
                if matches.opt_present("s") {
                    println!("{}", &hostname[0..ci.0]);
                } else {
                    println!("{}", &hostname[ci.0 + 1..]);
                }
                return 0;
            }
        }

        println!("{}", hostname);

        0
    }
}

#[cfg(not(windows))]
fn xgethostname() -> io::Result<String> {
    use std::ffi::CStr;

    let namelen = 256;
    let mut name: Vec<u8> = repeat(0).take(namelen).collect();
    let err = unsafe {
        gethostname(
            name.as_mut_ptr() as *mut libc::c_char,
            namelen as libc::size_t,
        )
    };

    if err == 0 {
        let null_pos = name.iter().position(|byte| *byte == 0).unwrap_or(namelen);
        if null_pos == namelen {
            name.push(0);
        }

        Ok(CStr::from_bytes_with_nul(&name[..=null_pos])
            .unwrap()
            .to_string_lossy()
            .into_owned())
    } else {
        Err(io::Error::last_os_error())
    }
}

#[cfg(windows)]
fn xgethostname() -> io::Result<String> {
    let namelen = 256;
    let mut name: Vec<u16> = repeat(0).take(namelen).collect();
    let err = unsafe { GetHostNameW(name.as_mut_ptr(), namelen as libc::c_int) };

    if err == 0 {
        Ok(String::from_wide_null(&name))
    } else {
        Err(io::Error::last_os_error())
    }
}

#[cfg(not(windows))]
fn xsethostname(name: &str) -> io::Result<()> {
    let vec_name: Vec<libc::c_char> = name.bytes().map(|c| c as libc::c_char).collect();

    let err = unsafe { sethostname(vec_name.as_ptr(), vec_name.len() as _) };

    if err != 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

#[cfg(windows)]
fn xsethostname(name: &str) -> io::Result<()> {
    use std::ffi::OsStr;

    let wide_name = OsStr::new(name).to_wide_null();

    let err = unsafe { SetComputerNameExW(ComputerNamePhysicalDnsHostname, wide_name.as_ptr()) };

    if err == 0 {
        // NOTE: the above is correct, failure is when the function returns 0 apparently
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}
<commit_msg>refactor/polish ~ fix `cargo clippy` complaints (allow 'let_and_return')<commit_after>#![crate_name = "uu_hostname"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Alan Andrade <alan.andradec@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;
#[cfg(windows)]
extern crate winapi;

#[macro_use]
extern crate uucore;

use std::collections::hash_set::HashSet;
use std::iter::repeat;
use std::io;
use std::str;
use std::net::ToSocketAddrs;
use getopts::Matches;

#[cfg(windows)]
use winapi::um::winsock2::{GetHostNameW, WSACleanup, WSAStartup};
#[cfg(windows)]
use winapi::um::sysinfoapi::{ComputerNamePhysicalDnsHostname, SetComputerNameExW};
#[cfg(windows)]
use winapi::shared::minwindef::MAKEWORD;
#[cfg(windows)]
use uucore::wide::*;

#[cfg(not(windows))]
use libc::gethostname;
#[cfg(not(windows))]
use libc::sethostname;

const SYNTAX: &str = "[OPTION]... [HOSTNAME]";
const SUMMARY: &str = "Print or set the system's host name.";
const LONG_HELP: &str = "";

pub fn uumain(args: Vec<String>) -> i32 {
    #![allow(clippy::let_and_return)]
    #[cfg(windows)]
    unsafe {
        let mut data = std::mem::uninitialized();
        if WSAStartup(MAKEWORD(2, 2), &mut data as *mut _) != 0 {
            eprintln!("Failed to start Winsock 2.2");
            return 1;
        }
    }
    let result = execute(args);
    #[cfg(windows)]
    unsafe {
        WSACleanup();
    }
    result
}

fn execute(args: Vec<String>) -> i32 {
    let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP)
        .optflag("d", "domain", "Display the name of the DNS domain if possible")
        .optflag("i", "ip-address", "Display the network address(es) of the host")
        // TODO: support --long
        .optflag("f", "fqdn", "Display the FQDN (Fully Qualified Domain Name) (default)")
        .optflag("s", "short", "Display the short hostname (the portion before the first dot) if \
                                possible")
        .parse(args);

    match matches.free.len() {
        0 => display_hostname(matches),
        1 => {
            if let Err(err) = xsethostname(matches.free.last().unwrap()) {
                show_error!("{}", err);
                1
            } else {
                0
            }
        }
        _ => {
            show_error!("{}", msg_wrong_number_of_arguments!(0, 1));
            1
        }
    }
}

fn display_hostname(matches: Matches) -> i32 {
    let hostname = return_if_err!(1, xgethostname());

    if matches.opt_present("i") {
        // XXX: to_socket_addrs needs hostname:port so append a dummy port and remove it later.
        // This was originally supposed to use std::net::lookup_host, but that seems to be
        // deprecated.  Perhaps we should use the dns-lookup crate?
        let hostname = hostname + ":1";
        match hostname.to_socket_addrs() {
            Ok(addresses) => {
                let mut hashset = HashSet::new();
                let mut output = String::new();
                for addr in addresses {
                    // XXX: not sure why this is necessary...
                    if !hashset.contains(&addr) {
                        let mut ip = format!("{}", addr);
                        if ip.ends_with(":1") {
                            let len = ip.len();
                            ip.truncate(len - 2);
                        }
                        output.push_str(&ip);
                        output.push_str(" ");
                        hashset.insert(addr);
                    }
                }
                let len = output.len();
                if len > 0 {
                    println!("{}", &output[0..len - 1]);
                }

                0
            }
            Err(f) => {
                show_error!("{}", f);

                1
            }
        }
    } else {
        if matches.opt_present("s") || matches.opt_present("d") {
            let mut it = hostname.char_indices().filter(|&ci| ci.1 == '.');
            if let Some(ci) = it.next() {
                if matches.opt_present("s") {
                    println!("{}", &hostname[0..ci.0]);
                } else {
                    println!("{}", &hostname[ci.0 + 1..]);
                }
                return 0;
            }
        }

        println!("{}", hostname);

        0
    }
}

#[cfg(not(windows))]
fn xgethostname() -> io::Result<String> {
    use std::ffi::CStr;

    let namelen = 256;
    let mut name: Vec<u8> = repeat(0).take(namelen).collect();
    let err = unsafe {
        gethostname(
            name.as_mut_ptr() as *mut libc::c_char,
            namelen as libc::size_t,
        )
    };

    if err == 0 {
        let null_pos = name.iter().position(|byte| *byte == 0).unwrap_or(namelen);
        if null_pos == namelen {
            name.push(0);
        }

        Ok(CStr::from_bytes_with_nul(&name[..=null_pos])
            .unwrap()
            .to_string_lossy()
            .into_owned())
    } else {
        Err(io::Error::last_os_error())
    }
}

#[cfg(windows)]
fn xgethostname() -> io::Result<String> {
    let namelen = 256;
    let mut name: Vec<u16> = repeat(0).take(namelen).collect();
    let err = unsafe { GetHostNameW(name.as_mut_ptr(), namelen as libc::c_int) };

    if err == 0 {
        Ok(String::from_wide_null(&name))
    } else {
        Err(io::Error::last_os_error())
    }
}

#[cfg(not(windows))]
fn xsethostname(name: &str) -> io::Result<()> {
    let vec_name: Vec<libc::c_char> = name.bytes().map(|c| c as libc::c_char).collect();

    let err = unsafe { sethostname(vec_name.as_ptr(), vec_name.len() as _) };

    if err != 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

#[cfg(windows)]
fn xsethostname(name: &str) -> io::Result<()> {
    use std::ffi::OsStr;

    let wide_name = OsStr::new(name).to_wide_null();

    let err = unsafe { SetComputerNameExW(ComputerNamePhysicalDnsHostname, wide_name.as_ptr()) };

    if err == 0 {
        // NOTE: the above is correct, failure is when the function returns 0 apparently
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}
<|endoftext|>


<commit_before>use crate::iter::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen};
use crate::ops::Try;
use crate::usize;

/// An iterator that links two iterators together, in a chain.
///
/// This `struct` is created by the [`chain`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`chain`]: trait.Iterator.html#method.chain
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Chain<A, B> {
    // These are "fused" with `Option` so we don't need separate state to track which part is
    // already exhausted, and we may also get niche layout for `None`. We don't use the real `Fuse`
    // adapter because its specialization for `FusedIterator` unconditionally descends into the
    // iterator, and that could be expensive to keep revisiting stuff like nested chains. It also
    // hurts compiler performance to add more iterator layers to `Chain`.
    //
    // Only the "first" iterator is actually set `None` when exhausted, depending on whether you
    // iterate forward or backward. If you mix directions, then both sides may be `None`.
    a: Option<A>,
    b: Option<B>,
}
impl<A, B> Chain<A, B> {
    pub(in super::super) fn new(a: A, b: B) -> Chain<A, B> {
        Chain { a: Some(a), b: Some(b) }
    }
}

/// Fuse the iterator if the expression is `None`.
macro_rules! fuse {
    ($self:ident . $iter:ident . $($call:tt)+) => {
        match $self.$iter {
            Some(ref mut iter) => match iter.$($call)+ {
                None => {
                    $self.$iter = None;
                    None
                }
                item => item,
            },
            None => None,
        }
    };
}

/// Try an iterator method without fusing,
/// like an inline `.as_mut().and_then(...)`
macro_rules! maybe {
    ($self:ident . $iter:ident . $($call:tt)+) => {
        match $self.$iter {
            Some(ref mut iter) => iter.$($call)+,
            None => None,
        }
    };
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A, B> Iterator for Chain<A, B>
where
    A: Iterator,
    B: Iterator<Item = A::Item>,
{
    type Item = A::Item;

    #[inline]
    fn next(&mut self) -> Option<A::Item> {
        match fuse!(self.a.next()) {
            None => maybe!(self.b.next()),
            item => item,
        }
    }

    #[inline]
    #[rustc_inherit_overflow_checks]
    fn count(self) -> usize {
        let a_count = match self.a {
            Some(a) => a.count(),
            None => 0,
        };
        let b_count = match self.b {
            Some(b) => b.count(),
            None => 0,
        };
        a_count + b_count
    }

    fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
    where
        Self: Sized,
        F: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        if let Some(ref mut a) = self.a {
            acc = a.try_fold(acc, &mut f)?;
            self.a = None;
        }
        if let Some(ref mut b) = self.b {
            acc = b.try_fold(acc, f)?;
            // we don't fuse the second iterator
        }
        Try::from_ok(acc)
    }

    fn fold<Acc, F>(self, mut acc: Acc, mut f: F) -> Acc
    where
        F: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(a) = self.a {
            acc = a.fold(acc, &mut f);
        }
        if let Some(b) = self.b {
            acc = b.fold(acc, f);
        }
        acc
    }

    #[inline]
    fn nth(&mut self, mut n: usize) -> Option<A::Item> {
        if let Some(ref mut a) = self.a {
            while let Some(x) = a.next() {
                if n == 0 {
                    return Some(x);
                }
                n -= 1;
            }
            self.a = None;
        }
        maybe!(self.b.nth(n))
    }

    #[inline]
    fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        match fuse!(self.a.find(&mut predicate)) {
            None => maybe!(self.b.find(predicate)),
            item => item,
        }
    }

    #[inline]
    fn last(self) -> Option<A::Item> {
        // Must exhaust a before b.
        let a_last = match self.a {
            Some(a) => a.last(),
            None => None,
        };
        let b_last = match self.b {
            Some(b) => b.last(),
            None => None,
        };
        b_last.or(a_last)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match self {
            Chain { a: Some(a), b: Some(b) } => {
                let (a_lower, a_upper) = a.size_hint();
                let (b_lower, b_upper) = b.size_hint();

                let lower = a_lower.saturating_add(b_lower);

                let upper = match (a_upper, b_upper) {
                    (Some(x), Some(y)) => x.checked_add(y),
                    _ => None,
                };

                (lower, upper)
            }
            Chain { a: Some(a), b: None } => a.size_hint(),
            Chain { a: None, b: Some(b) } => b.size_hint(),
            Chain { a: None, b: None } => (0, Some(0)),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A, B> DoubleEndedIterator for Chain<A, B>
where
    A: DoubleEndedIterator,
    B: DoubleEndedIterator<Item = A::Item>,
{
    #[inline]
    fn next_back(&mut self) -> Option<A::Item> {
        match fuse!(self.b.next_back()) {
            None => maybe!(self.a.next_back()),
            item => item,
        }
    }

    #[inline]
    fn nth_back(&mut self, mut n: usize) -> Option<A::Item> {
        if let Some(ref mut b) = self.b {
            while let Some(x) = b.next_back() {
                if n == 0 {
                    return Some(x);
                }
                n -= 1;
            }
            self.b = None;
        }
        maybe!(self.a.nth_back(n))
    }

    #[inline]
    fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        match fuse!(self.b.rfind(&mut predicate)) {
            None => maybe!(self.a.rfind(predicate)),
            item => item,
        }
    }

    fn try_rfold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
    where
        Self: Sized,
        F: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        if let Some(ref mut b) = self.b {
            acc = b.try_rfold(acc, &mut f)?;
            self.b = None;
        }
        if let Some(ref mut a) = self.a {
            acc = a.try_rfold(acc, f)?;
            // we don't fuse the second iterator
        }
        Try::from_ok(acc)
    }

    fn rfold<Acc, F>(self, mut acc: Acc, mut f: F) -> Acc
    where
        F: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(b) = self.b {
            acc = b.rfold(acc, &mut f);
        }
        if let Some(a) = self.a {
            acc = a.rfold(acc, f);
        }
        acc
    }
}

// Note: *both* must be fused to handle double-ended iterators.
#[stable(feature = "fused", since = "1.26.0")]
impl<A, B> FusedIterator for Chain<A, B>
where
    A: FusedIterator,
    B: FusedIterator<Item = A::Item>,
{
}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<A, B> TrustedLen for Chain<A, B>
where
    A: TrustedLen,
    B: TrustedLen<Item = A::Item>,
{
}
<commit_msg>Rollup merge of #76663 - pickfire:patch-7, r=jonas-schievink<commit_after>use crate::iter::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen};
use crate::ops::Try;
use crate::usize;

/// An iterator that links two iterators together, in a chain.
///
/// This `struct` is created by [`Iterator::chain`]. See its documentation
/// for more.
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Chain<A, B> {
    // These are "fused" with `Option` so we don't need separate state to track which part is
    // already exhausted, and we may also get niche layout for `None`. We don't use the real `Fuse`
    // adapter because its specialization for `FusedIterator` unconditionally descends into the
    // iterator, and that could be expensive to keep revisiting stuff like nested chains. It also
    // hurts compiler performance to add more iterator layers to `Chain`.
    //
    // Only the "first" iterator is actually set `None` when exhausted, depending on whether you
    // iterate forward or backward. If you mix directions, then both sides may be `None`.
    a: Option<A>,
    b: Option<B>,
}
impl<A, B> Chain<A, B> {
    pub(in super::super) fn new(a: A, b: B) -> Chain<A, B> {
        Chain { a: Some(a), b: Some(b) }
    }
}

/// Fuse the iterator if the expression is `None`.
macro_rules! fuse {
    ($self:ident . $iter:ident . $($call:tt)+) => {
        match $self.$iter {
            Some(ref mut iter) => match iter.$($call)+ {
                None => {
                    $self.$iter = None;
                    None
                }
                item => item,
            },
            None => None,
        }
    };
}

/// Try an iterator method without fusing,
/// like an inline `.as_mut().and_then(...)`
macro_rules! maybe {
    ($self:ident . $iter:ident . $($call:tt)+) => {
        match $self.$iter {
            Some(ref mut iter) => iter.$($call)+,
            None => None,
        }
    };
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A, B> Iterator for Chain<A, B>
where
    A: Iterator,
    B: Iterator<Item = A::Item>,
{
    type Item = A::Item;

    #[inline]
    fn next(&mut self) -> Option<A::Item> {
        match fuse!(self.a.next()) {
            None => maybe!(self.b.next()),
            item => item,
        }
    }

    #[inline]
    #[rustc_inherit_overflow_checks]
    fn count(self) -> usize {
        let a_count = match self.a {
            Some(a) => a.count(),
            None => 0,
        };
        let b_count = match self.b {
            Some(b) => b.count(),
            None => 0,
        };
        a_count + b_count
    }

    fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
    where
        Self: Sized,
        F: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        if let Some(ref mut a) = self.a {
            acc = a.try_fold(acc, &mut f)?;
            self.a = None;
        }
        if let Some(ref mut b) = self.b {
            acc = b.try_fold(acc, f)?;
            // we don't fuse the second iterator
        }
        Try::from_ok(acc)
    }

    fn fold<Acc, F>(self, mut acc: Acc, mut f: F) -> Acc
    where
        F: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(a) = self.a {
            acc = a.fold(acc, &mut f);
        }
        if let Some(b) = self.b {
            acc = b.fold(acc, f);
        }
        acc
    }

    #[inline]
    fn nth(&mut self, mut n: usize) -> Option<A::Item> {
        if let Some(ref mut a) = self.a {
            while let Some(x) = a.next() {
                if n == 0 {
                    return Some(x);
                }
                n -= 1;
            }
            self.a = None;
        }
        maybe!(self.b.nth(n))
    }

    #[inline]
    fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        match fuse!(self.a.find(&mut predicate)) {
            None => maybe!(self.b.find(predicate)),
            item => item,
        }
    }

    #[inline]
    fn last(self) -> Option<A::Item> {
        // Must exhaust a before b.
        let a_last = match self.a {
            Some(a) => a.last(),
            None => None,
        };
        let b_last = match self.b {
            Some(b) => b.last(),
            None => None,
        };
        b_last.or(a_last)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match self {
            Chain { a: Some(a), b: Some(b) } => {
                let (a_lower, a_upper) = a.size_hint();
                let (b_lower, b_upper) = b.size_hint();

                let lower = a_lower.saturating_add(b_lower);

                let upper = match (a_upper, b_upper) {
                    (Some(x), Some(y)) => x.checked_add(y),
                    _ => None,
                };

                (lower, upper)
            }
            Chain { a: Some(a), b: None } => a.size_hint(),
            Chain { a: None, b: Some(b) } => b.size_hint(),
            Chain { a: None, b: None } => (0, Some(0)),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A, B> DoubleEndedIterator for Chain<A, B>
where
    A: DoubleEndedIterator,
    B: DoubleEndedIterator<Item = A::Item>,
{
    #[inline]
    fn next_back(&mut self) -> Option<A::Item> {
        match fuse!(self.b.next_back()) {
            None => maybe!(self.a.next_back()),
            item => item,
        }
    }

    #[inline]
    fn nth_back(&mut self, mut n: usize) -> Option<A::Item> {
        if let Some(ref mut b) = self.b {
            while let Some(x) = b.next_back() {
                if n == 0 {
                    return Some(x);
                }
                n -= 1;
            }
            self.b = None;
        }
        maybe!(self.a.nth_back(n))
    }

    #[inline]
    fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        match fuse!(self.b.rfind(&mut predicate)) {
            None => maybe!(self.a.rfind(predicate)),
            item => item,
        }
    }

    fn try_rfold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
    where
        Self: Sized,
        F: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        if let Some(ref mut b) = self.b {
            acc = b.try_rfold(acc, &mut f)?;
            self.b = None;
        }
        if let Some(ref mut a) = self.a {
            acc = a.try_rfold(acc, f)?;
            // we don't fuse the second iterator
        }
        Try::from_ok(acc)
    }

    fn rfold<Acc, F>(self, mut acc: Acc, mut f: F) -> Acc
    where
        F: FnMut(Acc, Self::Item) -> Acc,
    {
        if let Some(b) = self.b {
            acc = b.rfold(acc, &mut f);
        }
        if let Some(a) = self.a {
            acc = a.rfold(acc, f);
        }
        acc
    }
}

// Note: *both* must be fused to handle double-ended iterators.
#[stable(feature = "fused", since = "1.26.0")]
impl<A, B> FusedIterator for Chain<A, B>
where
    A: FusedIterator,
    B: FusedIterator<Item = A::Item>,
{
}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<A, B> TrustedLen for Chain<A, B>
where
    A: TrustedLen,
    B: TrustedLen<Item = A::Item>,
{
}
<|endoftext|>


<commit_before>use crate::ffi::OsString;

pub struct Args {}

pub fn args() -> Args {
    Args {}
}

impl fmt::Debug for Args {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_list().finish()
    }
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> {
        None
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, Some(0))
    }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize {
        0
    }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<OsString> {
        None
    }
}
<commit_msg>Fix missing import in `unsupported::args`<commit_after>use crate::ffi::OsString;
use crate::fmt;

pub struct Args {}

pub fn args() -> Args {
    Args {}
}

impl fmt::Debug for Args {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_list().finish()
    }
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> {
        None
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, Some(0))
    }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize {
        0
    }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<OsString> {
        None
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

#[no_mangle]
pub extern "C" fn acos(n: f64) -> f64 {
	libm::acos(n)
}

#[no_mangle]
pub extern "C" fn acosf(n: f32) -> f32 {
	libm::acosf(n)
}

#[no_mangle]
pub extern "C" fn acosh(x: f64) -> f64 {
	libm::acosh(x)
}

#[no_mangle]
pub extern "C" fn acoshf(x: f32) -> f32 {
	libm::acoshf(x)
}

#[no_mangle]
pub extern "C" fn asin(n: f64) -> f64 {
	libm::asin(n)
}

#[no_mangle]
pub extern "C" fn asinf(n: f32) -> f32 {
	libm::asinf(n)
}

#[no_mangle]
pub extern "C" fn asinh(x: f64) -> f64 {
	libm::asinh(x)
}

#[no_mangle]
pub extern "C" fn asinhf(x: f32) -> f32 {
	libm::asinhf(x)
}

#[no_mangle]
pub extern "C" fn atan(n: f64) -> f64 {
	libm::atan(n)
}

#[no_mangle]
pub extern "C" fn atan2(a: f64, b: f64) -> f64 {
	libm::atan2(a, b)
}

#[no_mangle]
pub extern "C" fn atan2f(a: f32, b: f32) -> f32 {
	libm::atan2f(a, b)
}

#[no_mangle]
pub extern "C" fn atanf(n: f32) -> f32 {
	libm::atanf(n)
}

#[no_mangle]
pub extern "C" fn cbrt(n: f64) -> f64 {
	libm::cbrt(n)
}

#[no_mangle]
pub extern "C" fn cbrtf(n: f32) -> f32 {
	libm::cbrtf(n)
}

#[no_mangle]
pub extern "C" fn ceil(x: f64) -> f64 {
	libm::ceil(x)
}

#[no_mangle]
pub extern "C" fn ceilf(x: f32) -> f32 {
	libm::ceilf(x)
}

#[no_mangle]
pub extern "C" fn cos(x: f64) -> f64 {
	libm::cos(x)
}

#[no_mangle]
pub extern "C" fn cosf(x: f32) -> f32 {
	libm::cosf(x)
}

#[no_mangle]
pub extern "C" fn cosh(x: f64) -> f64 {
	libm::cosh(x)
}

#[no_mangle]
pub extern "C" fn coshf(x: f32) -> f32 {
	libm::coshf(x)
}

#[no_mangle]
pub extern "C" fn exp(x: f64) -> f64 {
	libm::exp(x)
}

#[no_mangle]
pub extern "C" fn expf(x: f32) -> f32 {
	libm::expf(x)
}

#[no_mangle]
pub extern "C" fn expm1(n: f64) -> f64 {
	libm::expm1(n)
}

#[no_mangle]
pub extern "C" fn expm1f(n: f32) -> f32 {
	libm::expm1f(n)
}

#[no_mangle]
pub extern "C" fn fdim(a: f64, b: f64) -> f64 {
	libm::fdim(a, b)
}

#[no_mangle]
pub extern "C" fn fdimf(a: f32, b: f32) -> f32 {
	libm::fdimf(a, b)
}

#[no_mangle]
pub extern "C" fn hypot(x: f64, y: f64) -> f64 {
	libm::hypot(x, y)
}

#[no_mangle]
pub extern "C" fn hypotf(x: f32, y: f32) -> f32 {
	libm::hypotf(x, y)
}

#[no_mangle]
pub extern "C" fn log(x: f64) -> f64 {
	libm::log(x)
}

#[no_mangle]
pub extern "C" fn logf(x: f32) -> f32 {
	libm::logf(x)
}

#[no_mangle]
pub extern "C" fn log1p(n: f64) -> f64 {
	libm::log1p(n)
}

#[no_mangle]
pub extern "C" fn log1pf(n: f32) -> f32 {
	libm::log1pf(n)
}

#[no_mangle]
pub extern "C" fn sinh(n: f64) -> f64 {
	libm::sinh(n)
}

#[no_mangle]
pub extern "C" fn sinhf(n: f32) -> f32 {
	libm::sinhf(n)
}

#[no_mangle]
pub extern "C" fn sqrt(x: f64) -> f64 {
	libm::sqrt(x)
}

#[no_mangle]
pub extern "C" fn sqrtf(x: f32) -> f32 {
	libm::sqrtf(x)
}

#[no_mangle]
pub extern "C" fn tan(n: f64) -> f64 {
	libm::tan(n)
}

#[no_mangle]
pub extern "C" fn tanf(n: f32) -> f32 {
	libm::tanf(n)
}

#[no_mangle]
pub extern "C" fn tanh(n: f64) -> f64 {
	libm::tanh(n)
}

#[no_mangle]
pub extern "C" fn tanhf(n: f32) -> f32 {
	libm::tanhf(n)
}

#[no_mangle]
pub extern "C" fn round(x: f64) -> f64 {
	libm::round(x)
}<commit_msg>minor changes to pass the format check<commit_after>#![allow(dead_code)]

#[no_mangle]
pub extern "C" fn acos(n: f64) -> f64 {
	libm::acos(n)
}

#[no_mangle]
pub extern "C" fn acosf(n: f32) -> f32 {
	libm::acosf(n)
}

#[no_mangle]
pub extern "C" fn acosh(x: f64) -> f64 {
	libm::acosh(x)
}

#[no_mangle]
pub extern "C" fn acoshf(x: f32) -> f32 {
	libm::acoshf(x)
}

#[no_mangle]
pub extern "C" fn asin(n: f64) -> f64 {
	libm::asin(n)
}

#[no_mangle]
pub extern "C" fn asinf(n: f32) -> f32 {
	libm::asinf(n)
}

#[no_mangle]
pub extern "C" fn asinh(x: f64) -> f64 {
	libm::asinh(x)
}

#[no_mangle]
pub extern "C" fn asinhf(x: f32) -> f32 {
	libm::asinhf(x)
}

#[no_mangle]
pub extern "C" fn atan(n: f64) -> f64 {
	libm::atan(n)
}

#[no_mangle]
pub extern "C" fn atan2(a: f64, b: f64) -> f64 {
	libm::atan2(a, b)
}

#[no_mangle]
pub extern "C" fn atan2f(a: f32, b: f32) -> f32 {
	libm::atan2f(a, b)
}

#[no_mangle]
pub extern "C" fn atanf(n: f32) -> f32 {
	libm::atanf(n)
}

#[no_mangle]
pub extern "C" fn cbrt(n: f64) -> f64 {
	libm::cbrt(n)
}

#[no_mangle]
pub extern "C" fn cbrtf(n: f32) -> f32 {
	libm::cbrtf(n)
}

#[no_mangle]
pub extern "C" fn ceil(x: f64) -> f64 {
	libm::ceil(x)
}

#[no_mangle]
pub extern "C" fn ceilf(x: f32) -> f32 {
	libm::ceilf(x)
}

#[no_mangle]
pub extern "C" fn cos(x: f64) -> f64 {
	libm::cos(x)
}

#[no_mangle]
pub extern "C" fn cosf(x: f32) -> f32 {
	libm::cosf(x)
}

#[no_mangle]
pub extern "C" fn cosh(x: f64) -> f64 {
	libm::cosh(x)
}

#[no_mangle]
pub extern "C" fn coshf(x: f32) -> f32 {
	libm::coshf(x)
}

#[no_mangle]
pub extern "C" fn exp(x: f64) -> f64 {
	libm::exp(x)
}

#[no_mangle]
pub extern "C" fn expf(x: f32) -> f32 {
	libm::expf(x)
}

#[no_mangle]
pub extern "C" fn expm1(n: f64) -> f64 {
	libm::expm1(n)
}

#[no_mangle]
pub extern "C" fn expm1f(n: f32) -> f32 {
	libm::expm1f(n)
}

#[no_mangle]
pub extern "C" fn fdim(a: f64, b: f64) -> f64 {
	libm::fdim(a, b)
}

#[no_mangle]
pub extern "C" fn fdimf(a: f32, b: f32) -> f32 {
	libm::fdimf(a, b)
}

#[no_mangle]
pub extern "C" fn hypot(x: f64, y: f64) -> f64 {
	libm::hypot(x, y)
}

#[no_mangle]
pub extern "C" fn hypotf(x: f32, y: f32) -> f32 {
	libm::hypotf(x, y)
}

#[no_mangle]
pub extern "C" fn log(x: f64) -> f64 {
	libm::log(x)
}

#[no_mangle]
pub extern "C" fn logf(x: f32) -> f32 {
	libm::logf(x)
}

#[no_mangle]
pub extern "C" fn log1p(n: f64) -> f64 {
	libm::log1p(n)
}

#[no_mangle]
pub extern "C" fn log1pf(n: f32) -> f32 {
	libm::log1pf(n)
}

#[no_mangle]
pub extern "C" fn sinh(n: f64) -> f64 {
	libm::sinh(n)
}

#[no_mangle]
pub extern "C" fn sinhf(n: f32) -> f32 {
	libm::sinhf(n)
}

#[no_mangle]
pub extern "C" fn sqrt(x: f64) -> f64 {
	libm::sqrt(x)
}

#[no_mangle]
pub extern "C" fn sqrtf(x: f32) -> f32 {
	libm::sqrtf(x)
}

#[no_mangle]
pub extern "C" fn tan(n: f64) -> f64 {
	libm::tan(n)
}

#[no_mangle]
pub extern "C" fn tanf(n: f32) -> f32 {
	libm::tanf(n)
}

#[no_mangle]
pub extern "C" fn tanh(n: f64) -> f64 {
	libm::tanh(n)
}

#[no_mangle]
pub extern "C" fn tanhf(n: f32) -> f32 {
	libm::tanhf(n)
}

#[no_mangle]
pub extern "C" fn round(x: f64) -> f64 {
	libm::round(x)
}
<|endoftext|>


<commit_before><commit_msg>Remove link to a concluded impl Trait discussion<commit_after><|endoftext|>


<commit_before>use std::io::{BufferedReader, File};
use material::materials::CookTorranceMaterial;
use geometry::{Mesh, Prim};
use geometry::prims::{Triangle, TriangleVertex};
use raytracer::compositor::{Surface, ColorRGBA};
use vec3::Vec3;

/// This is limited to only CookTorranceMaterials, as I couldn't get a Box<Material> to clone
/// a new material for each triangle primitive in the object model.
#[allow(dead_code)]
pub fn from_obj(material: CookTorranceMaterial /*Box<Material>*/,
                flip_normals: bool, filename: &str)
                -> Mesh {

    let path = Path::new(filename);
    let fh = File::open(&path);
    let mut file = BufferedReader::new(fh);

    let start_time = ::time::get_time();
    let print_every = 2048u;
    let mut current_line = 0;
    let mut processed_bytes = 0;
    let total_bytes = match path.stat() {
        Ok(stat) => stat.size,
        Err(e) => fail!("Could not open file {} (file missing?) : {}", filename, e)
    };

    let mut vertices: Vec<Vec3> = Vec::new();
    let mut normals : Vec<Vec3> = Vec::new();
    let mut triangles: Vec<Box<Prim+Send+Sync>> = Vec::new();
    let mut tex_coords: Vec<Vec<f64>> = Vec::new();

    for line_iter in file.lines() {
        let line = line_iter.unwrap();
        let tokens: Vec<&str> = line.as_slice().words().collect();
        if tokens.len() == 0 { continue }

        match tokens[0].as_slice() {
            "v" => {
                vertices.push(Vec3 {
                    x: from_str::<f64>(tokens[1].as_slice()).unwrap(),
                    y: from_str::<f64>(tokens[2].as_slice()).unwrap(),
                    z: from_str::<f64>(tokens[3].as_slice()).unwrap()
                });
            },
            "vt" => {
                tex_coords.push(vec![
                    from_str::<f64>(tokens[1].as_slice()).unwrap(),
                    from_str::<f64>(tokens[2].as_slice()).unwrap()
                ]);
            },
            "vn" => {
                let normal_scale = if flip_normals { -1.0 } else { 1.0 };
                normals.push(Vec3 {
                    x: from_str::<f64>(tokens[1].as_slice()).unwrap() * normal_scale,
                    y: from_str::<f64>(tokens[2].as_slice()).unwrap() * normal_scale,
                    z: from_str::<f64>(tokens[3].as_slice()).unwrap() * normal_scale
                });
            },
            "f" => {
                // ["f", "1/2/3", "2/2/2", "12//4"] => [[1, 2, 3], [2, 2, 2], [12, -1u, 4]]
                let pairs: Vec<Vec<uint>> = tokens.tail().iter().map( |token| {
                    let str_tokens: Vec<&str> = token.as_slice().split('/').collect();
                    str_tokens.iter().map( |str_tok| {
                        match from_str::<uint>(*str_tok) {
                            Some(uint_tok) => uint_tok - 1,
                            None => !0 // No data available/not supplied
                        }
                    }).collect()
                }).collect();

                // If no texture coordinates were supplied, default to zero.
                // We store nothing supplied as !0
                let (u, v) = if pairs[0][1] != !0 {
                    (vec![
                        tex_coords[pairs[0][1]][0],
                        tex_coords[pairs[1][1]][0],
                        tex_coords[pairs[2][1]][0]
                    ],
                    vec![
                        tex_coords[pairs[0][1]][1],
                        tex_coords[pairs[1][1]][1],
                        tex_coords[pairs[2][1]][1]
                    ])
                } else {
                    (vec![0.0, 0.0, 0.0],
                     vec![0.0, 0.0, 0.0])
                };

                triangles.push(box Triangle {
                    v0: TriangleVertex { pos: vertices[pairs[0][0]], n: normals[pairs[0][2]], u: u[0], v: v[0] },
                    v1: TriangleVertex { pos: vertices[pairs[1][0]], n: normals[pairs[1][2]], u: u[1], v: v[1] },
                    v2: TriangleVertex { pos: vertices[pairs[2][0]], n: normals[pairs[2][2]], u: u[2], v: v[2] },
                    material: box material.clone()
                });
            },
            _ => {}
        }

        current_line += 1;
        processed_bytes += line.as_bytes().len();
        if current_line % print_every == 0 {
            ::util::print_progress("Bytes", start_time, processed_bytes, total_bytes as uint);
        }
    }

    // Cheat the progress meter
    ::util::print_progress("Bytes", start_time, total_bytes as uint, total_bytes as uint);

    Mesh {
        triangles: triangles
    }
}

#[allow(dead_code)]
pub fn from_ppm(filename: &str) -> Surface {
    let path = Path::new(filename);
    let mut file = BufferedReader::new(File::open(&path));

    let tex = match file.read_to_string() {
        Ok(f) => f,
        Err(e) => fail!("Could not open file {} (file missing?): {}", filename, e)
    };
    let mut tokens: Vec<&str> = tex.as_slice().words().collect();

    tokens.remove(0); // PPM type
    let width  = from_str::<uint>(tokens.remove(0).unwrap()).unwrap();
    let height = from_str::<uint>(tokens.remove(0).unwrap()).unwrap();
    tokens.remove(0); // Max color value

    print!("Importing image texture {}", filename);
    println!(" {}x{}", width, height);

    let mut surface = Surface::new(width, height, ColorRGBA::new_rgb(0, 0, 0));

    let mut i = 0u;

    for chunk in tokens.as_slice().chunks(3) {
        let x = i % width;
        let y = i / width;
        i += 1;

        if x >= width || y >= height { break };

        *surface.get_mut(x, y) = ColorRGBA::new_rgb(
            from_str::<u8>(chunk[0]).unwrap(),
            from_str::<u8>(chunk[1]).unwrap(),
            from_str::<u8>(chunk[2]).unwrap()
        );
    }

    surface
}
<commit_msg>Breaking change: stat was moved to PathExtensions<commit_after>use std::io::{BufferedReader, File};
use std::io::fs::PathExtensions;
use material::materials::CookTorranceMaterial;
use geometry::{Mesh, Prim};
use geometry::prims::{Triangle, TriangleVertex};
use raytracer::compositor::{Surface, ColorRGBA};
use vec3::Vec3;

/// This is limited to only CookTorranceMaterials, as I couldn't get a Box<Material> to clone
/// a new material for each triangle primitive in the object model.
#[allow(dead_code)]
pub fn from_obj(material: CookTorranceMaterial /*Box<Material>*/,
                flip_normals: bool, filename: &str)
                -> Mesh {

    let path = Path::new(filename);
    let fh = File::open(&path);
    let mut file = BufferedReader::new(fh);

    let start_time = ::time::get_time();
    let print_every = 2048u;
    let mut current_line = 0;
    let mut processed_bytes = 0;
    let total_bytes = match path.stat() {
        Ok(stat) => stat.size,
        Err(e) => fail!("Could not open file {} (file missing?) : {}", filename, e)
    };

    let mut vertices: Vec<Vec3> = Vec::new();
    let mut normals : Vec<Vec3> = Vec::new();
    let mut triangles: Vec<Box<Prim+Send+Sync>> = Vec::new();
    let mut tex_coords: Vec<Vec<f64>> = Vec::new();

    for line_iter in file.lines() {
        let line = line_iter.unwrap();
        let tokens: Vec<&str> = line.as_slice().words().collect();
        if tokens.len() == 0 { continue }

        match tokens[0].as_slice() {
            "v" => {
                vertices.push(Vec3 {
                    x: from_str::<f64>(tokens[1].as_slice()).unwrap(),
                    y: from_str::<f64>(tokens[2].as_slice()).unwrap(),
                    z: from_str::<f64>(tokens[3].as_slice()).unwrap()
                });
            },
            "vt" => {
                tex_coords.push(vec![
                    from_str::<f64>(tokens[1].as_slice()).unwrap(),
                    from_str::<f64>(tokens[2].as_slice()).unwrap()
                ]);
            },
            "vn" => {
                let normal_scale = if flip_normals { -1.0 } else { 1.0 };
                normals.push(Vec3 {
                    x: from_str::<f64>(tokens[1].as_slice()).unwrap() * normal_scale,
                    y: from_str::<f64>(tokens[2].as_slice()).unwrap() * normal_scale,
                    z: from_str::<f64>(tokens[3].as_slice()).unwrap() * normal_scale
                });
            },
            "f" => {
                // ["f", "1/2/3", "2/2/2", "12//4"] => [[1, 2, 3], [2, 2, 2], [12, -1u, 4]]
                let pairs: Vec<Vec<uint>> = tokens.tail().iter().map( |token| {
                    let str_tokens: Vec<&str> = token.as_slice().split('/').collect();
                    str_tokens.iter().map( |str_tok| {
                        match from_str::<uint>(*str_tok) {
                            Some(uint_tok) => uint_tok - 1,
                            None => !0 // No data available/not supplied
                        }
                    }).collect()
                }).collect();

                // If no texture coordinates were supplied, default to zero.
                // We store nothing supplied as !0
                let (u, v) = if pairs[0][1] != !0 {
                    (vec![
                        tex_coords[pairs[0][1]][0],
                        tex_coords[pairs[1][1]][0],
                        tex_coords[pairs[2][1]][0]
                    ],
                    vec![
                        tex_coords[pairs[0][1]][1],
                        tex_coords[pairs[1][1]][1],
                        tex_coords[pairs[2][1]][1]
                    ])
                } else {
                    (vec![0.0, 0.0, 0.0],
                     vec![0.0, 0.0, 0.0])
                };

                triangles.push(box Triangle {
                    v0: TriangleVertex { pos: vertices[pairs[0][0]], n: normals[pairs[0][2]], u: u[0], v: v[0] },
                    v1: TriangleVertex { pos: vertices[pairs[1][0]], n: normals[pairs[1][2]], u: u[1], v: v[1] },
                    v2: TriangleVertex { pos: vertices[pairs[2][0]], n: normals[pairs[2][2]], u: u[2], v: v[2] },
                    material: box material.clone()
                });
            },
            _ => {}
        }

        current_line += 1;
        processed_bytes += line.as_bytes().len();
        if current_line % print_every == 0 {
            ::util::print_progress("Bytes", start_time, processed_bytes, total_bytes as uint);
        }
    }

    // Cheat the progress meter
    ::util::print_progress("Bytes", start_time, total_bytes as uint, total_bytes as uint);

    Mesh {
        triangles: triangles
    }
}

#[allow(dead_code)]
pub fn from_ppm(filename: &str) -> Surface {
    let path = Path::new(filename);
    let mut file = BufferedReader::new(File::open(&path));

    let tex = match file.read_to_string() {
        Ok(f) => f,
        Err(e) => fail!("Could not open file {} (file missing?): {}", filename, e)
    };
    let mut tokens: Vec<&str> = tex.as_slice().words().collect();

    tokens.remove(0); // PPM type
    let width  = from_str::<uint>(tokens.remove(0).unwrap()).unwrap();
    let height = from_str::<uint>(tokens.remove(0).unwrap()).unwrap();
    tokens.remove(0); // Max color value

    print!("Importing image texture {}", filename);
    println!(" {}x{}", width, height);

    let mut surface = Surface::new(width, height, ColorRGBA::new_rgb(0, 0, 0));

    let mut i = 0u;

    for chunk in tokens.as_slice().chunks(3) {
        let x = i % width;
        let y = i / width;
        i += 1;

        if x >= width || y >= height { break };

        *surface.get_mut(x, y) = ColorRGBA::new_rgb(
            from_str::<u8>(chunk[0]).unwrap(),
            from_str::<u8>(chunk[1]).unwrap(),
            from_str::<u8>(chunk[2]).unwrap()
        );
    }

    surface
}
<|endoftext|>


<commit_before>extern crate serde_json;

use client::Client;
use std::collections::HashMap;

#[derive(Debug)]
pub struct Customer {
}

impl Customer {

    pub fn new<S: Into<String>>(
        first_name: S,
        last_name: S,
        email: S,
        address: S,
        address_city: S,
        country_code: S,
        phone_number: S,
        metadata: Option<HashMap<String, serde_json::Value>>
    ) -> HashMap<String, serde_json::Value> {
        let mut map: HashMap<String, serde_json::Value>;
        map = HashMap::new();
        map.insert("first_name".to_string(), json!(first_name.into()));
        map.insert("last_name".to_string(), json!(last_name.into()));
        map.insert("email".to_string(), json!(email.into()));
        map.insert("address".to_string(), json!(address.into()));
        map.insert("address_city".to_string(), json!(address_city.into()));
        map.insert("country_code".to_string(), json!(country_code.into()));
        map.insert("phone_number".to_string(), json!(phone_number.into()));
        if !metadata.is_none() {
            map.insert("metadata".to_string(), json!(metadata));
        }
        return map;
    }

    pub fn create(client: &Client, customer: &HashMap<String, serde_json::Value>) -> String {
        client.post("/customers", customer)
    }

    pub fn delete(client: &Client, id: &str) -> String {
        client.delete(&format!("/customers/{}", id))
    }

    pub fn retrieve(client: &Client, id: &str) -> String {
        client.get(&format!("/customers/{}", id))
    }

    pub fn all(
        client: &Client,
        query_params: Option<HashMap<String, String>>,
        limit: Option<String>,
        before: Option<String>,
        after: Option<String>
    ) -> String {
        client.get_filter("/customers", query_params, limit, before, after)
    }

}
<commit_msg>add document for Customer<commit_after>extern crate serde_json;

use client::Client;
use std::collections::HashMap;

#[derive(Debug)]
pub struct Customer {
}

impl Customer {

    //! # Examples
    //!
    //! ```
    //! let client = culqi::Client::new("{KEY}");
    //! ```
    //!
    //! ```
    //! let new_customer = culqi::Customer::new("Will","Muro","wmuro@me.com","Av. Lima 123","LIMA","PE","999999999",None);
    //! ```
    //!
    //! ```
    //! let create_customer = culqi::Customer::create(&client, &new_customer);
    //! ```
    //!
    //! ```
    //! let get_customer = culqi::Customer::retrieve(&client, "{ID}");
    //! ```
    //!
    //! ```
    //! let delete_customer = culqi::Customer::delete(&client, "{ID}");
    //! ```
    //!
    //!
    //! Here you are the list of filters you can use for get Customers
    //!
    //! ```
    //! use std::collections::HashMap;
    //! ```
    //!
    //! ```
    //! let mut customer_filter: HashMap<String, String>;
    //! customer_filter = HashMap::new();
    //! customer_filter.insert("first_name".to_string(), "Will".to_string());
    //! customer_filter.insert("last_name".to_string(), "Muro".to_string());
    //! customer_filter.insert("email".to_string(), "will@me.com".to_string());
    //! customer_filter.insert("address".to_string(), "Av. Lima 123".to_string());
    //! customer_filter.insert("address_city".to_string(), "LIMA".to_string());
    //! customer_filter.insert("phone_number".to_string(), "99999999".to_string());
    //! customer_filter.insert("country_code".to_string(), "PE".to_string());
    //! ```
    //!
    //! ```
    //! let all_customers = culqi::Customer::all(&client, Some(customer_filter), None, None, None);
    //! ```
    //!

    pub fn new<S: Into<String>>(
        first_name: S,
        last_name: S,
        email: S,
        address: S,
        address_city: S,
        country_code: S,
        phone_number: S,
        metadata: Option<HashMap<String, serde_json::Value>>
    ) -> HashMap<String, serde_json::Value> {
        let mut map: HashMap<String, serde_json::Value>;
        map = HashMap::new();
        map.insert("first_name".to_string(), json!(first_name.into()));
        map.insert("last_name".to_string(), json!(last_name.into()));
        map.insert("email".to_string(), json!(email.into()));
        map.insert("address".to_string(), json!(address.into()));
        map.insert("address_city".to_string(), json!(address_city.into()));
        map.insert("country_code".to_string(), json!(country_code.into()));
        map.insert("phone_number".to_string(), json!(phone_number.into()));
        if !metadata.is_none() {
            map.insert("metadata".to_string(), json!(metadata));
        }
        return map;
    }

    pub fn create(client: &Client, customer: &HashMap<String, serde_json::Value>) -> String {
        client.post("/customers", customer)
    }

    pub fn delete(client: &Client, id: &str) -> String {
        client.delete(&format!("/customers/{}", id))
    }

    pub fn retrieve(client: &Client, id: &str) -> String {
        client.get(&format!("/customers/{}", id))
    }

    pub fn all(
        client: &Client,
        query_params: Option<HashMap<String, String>>,
        limit: Option<String>,
        before: Option<String>,
        after: Option<String>
    ) -> String {
        client.get_filter("/customers", query_params, limit, before, after)
    }

}
<|endoftext|>


<commit_before>use super::*;
use redox::prelude::v1::*;
use redox::fs::File;
use redox::io::Read;

pub enum OpenStatus {
    Ok,
    NotFound,
}

impl Editor {
    /// Open a file
    pub fn open(&mut self, path: &str) -> OpenStatus {
        if let Some(mut file) = File::open(path) {
            let mut con = String::new();
            file.read_to_string(&mut con);

            self.text = con.lines().map(|x| x.chars().collect::<VecDeque<char>>()).collect::<VecDeque<VecDeque<char>>>();

            OpenStatus::Ok
        } else {
            OpenStatus::NotFound
        }
    }
}
<commit_msg>Show file name in status bar<commit_after>use super::*;
use redox::prelude::v1::*;
use redox::fs::File;
use redox::io::Read;

pub enum OpenStatus {
    Ok,
    NotFound,
}

impl Editor {
    /// Open a file
    pub fn open(&mut self, path: &str) -> OpenStatus {
        self.status_bar.file = path.to_string();
        if let Some(mut file) = File::open(path) {
            let mut con = String::new();
            file.read_to_string(&mut con);

            self.text = con.lines().map(|x| x.chars().collect::<VecDeque<char>>()).collect::<VecDeque<VecDeque<char>>>();

            OpenStatus::Ok
        } else {
            OpenStatus::NotFound
        }

    }
}
<|endoftext|>