<commit_before>//! Static files bundled with documentation output.
//!
//! All the static files are included here for centralized access in case anything other than the
//! HTML rendering code (say, the theme checker) needs to access one of these files.
//!
//! Note about types: CSS and JavaScript files are included as `&'static str` to allow for the
//! minifier to run on them. All other files are included as `&'static [u8]` so they can be
//! directly written to a `Write` handle.

/// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page.
crate static RUSTDOC_CSS: &str = include_str!("static/rustdoc.css");

/// The file contents of `settings.css`, responsible for the items on the settings page.
crate static SETTINGS_CSS: &str = include_str!("static/settings.css");

/// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled.
crate static NOSCRIPT_CSS: &str = include_str!("static/noscript.css");

/// The file contents of `normalize.css`, included to even out standard elements between browser
/// implementations.
crate static NORMALIZE_CSS: &str = include_str!("static/normalize.css");

/// The file contents of `main.js`, which contains the core JavaScript used on documentation pages,
/// including search behavior and docblock folding, among others.
crate static MAIN_JS: &str = include_str!("static/main.js");

/// The file contents of `search-index.js`, which contains the search behavior,
/// and into which is interpolated the search index.
crate static SEARCH_JS: &str = include_str!("static/search.js");

/// The file contents of `settings.js`, which contains the JavaScript used to handle the settings
/// page.
crate static SETTINGS_JS: &str = include_str!("static/settings.js");

/// The file contents of `storage.js`, which contains functionality related to browser Local
/// Storage, used to store documentation settings.
crate static STORAGE_JS: &str = include_str!("static/storage.js");

/// The file contents of `brush.svg`, the icon used for the theme-switch button.
crate static BRUSH_SVG: &[u8] = include_bytes!("static/brush.svg");

/// The file contents of `wheel.svg`, the icon used for the settings button.
crate static WHEEL_SVG: &[u8] = include_bytes!("static/wheel.svg");

/// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox.
crate static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/down-arrow.svg");

/// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
/// output.
crate static COPYRIGHT: &[u8] = include_bytes!("static/COPYRIGHT.txt");

/// The contents of `LICENSE-APACHE.txt`, the text of the Apache License, version 2.0.
crate static LICENSE_APACHE: &[u8] = include_bytes!("static/LICENSE-APACHE.txt");

/// The contents of `LICENSE-MIT.txt`, the text of the MIT License.
crate static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt");

/// The contents of `rust-logo.png`, the default icon of the documentation.
crate static RUST_LOGO: &[u8] = include_bytes!("static/rust-logo.png");
/// The default documentation favicons (SVG and PNG fallbacks)
crate static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/favicon.svg");
crate static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/favicon-16x16.png");
crate static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/favicon-32x32.png");

/// The built-in themes given to every documentation site.
crate mod themes {
    /// The "light" theme, selected by default when no setting is available. Used as the basis for
    /// the `--check-theme` functionality.
    crate static LIGHT: &str = include_str!("static/themes/light.css");

    /// The "dark" theme.
    crate static DARK: &str = include_str!("static/themes/dark.css");

    /// The "ayu" theme.
    crate static AYU: &str = include_str!("static/themes/ayu.css");
}

/// Files related to the Fira Sans font.
crate mod fira_sans {
    /// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font.
    crate static REGULAR: &[u8] = include_bytes!("static/FiraSans-Regular.woff");

    /// The file `FiraSans-Regular.woff2`, the Regular variant of the Fira Sans font in woff2.
    crate static REGULAR2: &[u8] = include_bytes!("static/FiraSans-Regular.woff2");

    /// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font.
    crate static MEDIUM: &[u8] = include_bytes!("static/FiraSans-Medium.woff");

    /// The file `FiraSans-Medium.woff2`, the Medium variant of the Fira Sans font in woff2.
    crate static MEDIUM2: &[u8] = include_bytes!("static/FiraSans-Medium.woff2");

    /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font.
    crate static LICENSE: &[u8] = include_bytes!("static/FiraSans-LICENSE.txt");
}

/// Files related to the Source Serif 4 font.
crate mod source_serif_4 {
    /// The file `SourceSerif4-Regular.ttf.woff`, the Regular variant of the Source Serif 4 font.
    crate static REGULAR: &[u8] = include_bytes!("static/SourceSerif4-Regular.ttf.woff");

    /// The file `SourceSerif4-Bold.ttf.woff`, the Bold variant of the Source Serif 4 font.
    crate static BOLD: &[u8] = include_bytes!("static/SourceSerif4-Bold.ttf.woff");

    /// The file `SourceSerif4-It.ttf.woff`, the Italic variant of the Source Serif 4 font.
    crate static ITALIC: &[u8] = include_bytes!("static/SourceSerif4-It.ttf.woff");

    /// The file `SourceSerif4-LICENSE.txt`, the license text for the Source Serif 4 font.
    crate static LICENSE: &[u8] = include_bytes!("static/SourceSerif4-LICENSE.md");
}

/// Files related to the Source Code Pro font.
crate mod source_code_pro {
    /// The file `SourceCodePro-Regular.ttf.woff`, the Regular variant of the Source Code Pro font.
    crate static REGULAR: &[u8] = include_bytes!("static/SourceCodePro-Regular.ttf.woff");

    /// The file `SourceCodePro-Semibold.ttf.woff`, the Semibold variant of the Source Code Pro
    /// font.
    crate static SEMIBOLD: &[u8] = include_bytes!("static/SourceCodePro-Semibold.ttf.woff");

    /// The file `SourceCodePro-It.ttf.woff`, the Italic variant of the Source Code Pro font.
    crate static ITALIC: &[u8] = include_bytes!("static/SourceCodePro-It.ttf.woff");

    /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font.
    crate static LICENSE: &[u8] = include_bytes!("static/SourceCodePro-LICENSE.txt");
}

/// Files related to the sidebar in rustdoc sources.
crate mod sidebar {
    /// File script to handle sidebar.
    crate static SOURCE_SCRIPT: &str = include_str!("static/source-script.js");
}
<commit_msg>Update comment on search.js static file.<commit_after>//! Static files bundled with documentation output.
//!
//! All the static files are included here for centralized access in case anything other than the
//! HTML rendering code (say, the theme checker) needs to access one of these files.
//!
//! Note about types: CSS and JavaScript files are included as `&'static str` to allow for the
//! minifier to run on them. All other files are included as `&'static [u8]` so they can be
//! directly written to a `Write` handle.

/// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page.
crate static RUSTDOC_CSS: &str = include_str!("static/rustdoc.css");

/// The file contents of `settings.css`, responsible for the items on the settings page.
crate static SETTINGS_CSS: &str = include_str!("static/settings.css");

/// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled.
crate static NOSCRIPT_CSS: &str = include_str!("static/noscript.css");

/// The file contents of `normalize.css`, included to even out standard elements between browser
/// implementations.
crate static NORMALIZE_CSS: &str = include_str!("static/normalize.css");

/// The file contents of `main.js`, which contains the core JavaScript used on documentation pages,
/// including search behavior and docblock folding, among others.
crate static MAIN_JS: &str = include_str!("static/main.js");

/// The file contents of `search.js`, which contains the search behavior.
crate static SEARCH_JS: &str = include_str!("static/search.js");

/// The file contents of `settings.js`, which contains the JavaScript used to handle the settings
/// page.
crate static SETTINGS_JS: &str = include_str!("static/settings.js");

/// The file contents of `storage.js`, which contains functionality related to browser Local
/// Storage, used to store documentation settings.
crate static STORAGE_JS: &str = include_str!("static/storage.js");

/// The file contents of `brush.svg`, the icon used for the theme-switch button.
crate static BRUSH_SVG: &[u8] = include_bytes!("static/brush.svg");

/// The file contents of `wheel.svg`, the icon used for the settings button.
crate static WHEEL_SVG: &[u8] = include_bytes!("static/wheel.svg");

/// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox.
crate static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/down-arrow.svg");

/// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
/// output.
crate static COPYRIGHT: &[u8] = include_bytes!("static/COPYRIGHT.txt");

/// The contents of `LICENSE-APACHE.txt`, the text of the Apache License, version 2.0.
crate static LICENSE_APACHE: &[u8] = include_bytes!("static/LICENSE-APACHE.txt");

/// The contents of `LICENSE-MIT.txt`, the text of the MIT License.
crate static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt");

/// The contents of `rust-logo.png`, the default icon of the documentation.
crate static RUST_LOGO: &[u8] = include_bytes!("static/rust-logo.png");
/// The default documentation favicons (SVG and PNG fallbacks)
crate static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/favicon.svg");
crate static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/favicon-16x16.png");
crate static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/favicon-32x32.png");

/// The built-in themes given to every documentation site.
crate mod themes {
    /// The "light" theme, selected by default when no setting is available. Used as the basis for
    /// the `--check-theme` functionality.
    crate static LIGHT: &str = include_str!("static/themes/light.css");

    /// The "dark" theme.
    crate static DARK: &str = include_str!("static/themes/dark.css");

    /// The "ayu" theme.
    crate static AYU: &str = include_str!("static/themes/ayu.css");
}

/// Files related to the Fira Sans font.
crate mod fira_sans {
    /// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font.
    crate static REGULAR: &[u8] = include_bytes!("static/FiraSans-Regular.woff");

    /// The file `FiraSans-Regular.woff2`, the Regular variant of the Fira Sans font in woff2.
    crate static REGULAR2: &[u8] = include_bytes!("static/FiraSans-Regular.woff2");

    /// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font.
    crate static MEDIUM: &[u8] = include_bytes!("static/FiraSans-Medium.woff");

    /// The file `FiraSans-Medium.woff2`, the Medium variant of the Fira Sans font in woff2.
    crate static MEDIUM2: &[u8] = include_bytes!("static/FiraSans-Medium.woff2");

    /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font.
    crate static LICENSE: &[u8] = include_bytes!("static/FiraSans-LICENSE.txt");
}

/// Files related to the Source Serif 4 font.
crate mod source_serif_4 {
    /// The file `SourceSerif4-Regular.ttf.woff`, the Regular variant of the Source Serif 4 font.
    crate static REGULAR: &[u8] = include_bytes!("static/SourceSerif4-Regular.ttf.woff");

    /// The file `SourceSerif4-Bold.ttf.woff`, the Bold variant of the Source Serif 4 font.
    crate static BOLD: &[u8] = include_bytes!("static/SourceSerif4-Bold.ttf.woff");

    /// The file `SourceSerif4-It.ttf.woff`, the Italic variant of the Source Serif 4 font.
    crate static ITALIC: &[u8] = include_bytes!("static/SourceSerif4-It.ttf.woff");

    /// The file `SourceSerif4-LICENSE.txt`, the license text for the Source Serif 4 font.
    crate static LICENSE: &[u8] = include_bytes!("static/SourceSerif4-LICENSE.md");
}

/// Files related to the Source Code Pro font.
crate mod source_code_pro {
    /// The file `SourceCodePro-Regular.ttf.woff`, the Regular variant of the Source Code Pro font.
    crate static REGULAR: &[u8] = include_bytes!("static/SourceCodePro-Regular.ttf.woff");

    /// The file `SourceCodePro-Semibold.ttf.woff`, the Semibold variant of the Source Code Pro
    /// font.
    crate static SEMIBOLD: &[u8] = include_bytes!("static/SourceCodePro-Semibold.ttf.woff");

    /// The file `SourceCodePro-It.ttf.woff`, the Italic variant of the Source Code Pro font.
    crate static ITALIC: &[u8] = include_bytes!("static/SourceCodePro-It.ttf.woff");

    /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font.
    crate static LICENSE: &[u8] = include_bytes!("static/SourceCodePro-LICENSE.txt");
}

/// Files related to the sidebar in rustdoc sources.
crate mod sidebar {
    /// File script to handle sidebar.
    crate static SOURCE_SCRIPT: &str = include_str!("static/source-script.js");
}
<|endoftext|>


<commit_before>// This file is @generated by no_atomic.sh.
// It is not intended for manual editing.

const NO_ATOMIC_CAS: &[&str] = &[
    "avr-unknown-gnu-atmega328",
    "bpfeb-unknown-none",
    "bpfel-unknown-none",
    "msp430-none-elf",
    "riscv32i-unknown-none-elf",
    "riscv32imc-unknown-none-elf",
    "thumbv4t-none-eabi",
    "thumbv6m-none-eabi",
];
#[allow(dead_code)]
const NO_ATOMIC_64: &[&str] = &[
    "arm-linux-androideabi",
    "armebv7r-none-eabi",
    "armebv7r-none-eabihf",
    "armv4t-unknown-linux-gnueabi",
    "armv5te-unknown-linux-gnueabi",
    "armv5te-unknown-linux-musleabi",
    "armv5te-unknown-linux-uclibceabi",
    "armv7r-none-eabi",
    "armv7r-none-eabihf",
    "hexagon-unknown-linux-musl",
    "mips-unknown-linux-gnu",
    "mips-unknown-linux-musl",
    "mips-unknown-linux-uclibc",
    "mipsel-unknown-linux-gnu",
    "mipsel-unknown-linux-musl",
    "mipsel-unknown-linux-uclibc",
    "mipsel-unknown-none",
    "mipsisa32r6-unknown-linux-gnu",
    "mipsisa32r6el-unknown-linux-gnu",
    "powerpc-unknown-freebsd",
    "powerpc-unknown-linux-gnu",
    "powerpc-unknown-linux-gnuspe",
    "powerpc-unknown-linux-musl",
    "powerpc-unknown-netbsd",
    "powerpc-unknown-openbsd",
    "powerpc-wrs-vxworks",
    "powerpc-wrs-vxworks-spe",
    "riscv32gc-unknown-linux-gnu",
    "riscv32gc-unknown-linux-musl",
    "riscv32imac-unknown-none-elf",
    "thumbv7em-none-eabi",
    "thumbv7em-none-eabihf",
    "thumbv7m-none-eabi",
    "thumbv8m.base-none-eabi",
    "thumbv8m.main-none-eabi",
    "thumbv8m.main-none-eabihf",
    "mipsel-sony-psp",
    "thumbv4t-none-eabi",
    "thumbv6m-none-eabi",
];
#[allow(dead_code)]
const NO_ATOMIC: &[&str] = &[
    "avr-unknown-gnu-atmega328",
    "msp430-none-elf",
    "riscv32i-unknown-none-elf",
    "riscv32imc-unknown-none-elf",
];
<commit_msg>Update list of targets that do not support Atomic*64<commit_after>// This file is @generated by no_atomic.sh.
// It is not intended for manual editing.

const NO_ATOMIC_CAS: &[&str] = &[
    "avr-unknown-gnu-atmega328",
    "bpfeb-unknown-none",
    "bpfel-unknown-none",
    "msp430-none-elf",
    "riscv32i-unknown-none-elf",
    "riscv32imc-unknown-none-elf",
    "thumbv4t-none-eabi",
    "thumbv6m-none-eabi",
];
#[allow(dead_code)]
const NO_ATOMIC_64: &[&str] = &[
    "arm-linux-androideabi",
    "armebv7r-none-eabi",
    "armebv7r-none-eabihf",
    "armv4t-unknown-linux-gnueabi",
    "armv5te-unknown-linux-gnueabi",
    "armv5te-unknown-linux-musleabi",
    "armv5te-unknown-linux-uclibceabi",
    "armv7r-none-eabi",
    "armv7r-none-eabihf",
    "hexagon-unknown-linux-musl",
    "mips-unknown-linux-gnu",
    "mips-unknown-linux-musl",
    "mips-unknown-linux-uclibc",
    "mipsel-unknown-linux-gnu",
    "mipsel-unknown-linux-musl",
    "mipsel-unknown-linux-uclibc",
    "mipsel-unknown-none",
    "mipsisa32r6-unknown-linux-gnu",
    "mipsisa32r6el-unknown-linux-gnu",
    "powerpc-unknown-freebsd",
    "powerpc-unknown-linux-gnu",
    "powerpc-unknown-linux-gnuspe",
    "powerpc-unknown-linux-musl",
    "powerpc-unknown-netbsd",
    "powerpc-unknown-openbsd",
    "powerpc-wrs-vxworks",
    "powerpc-wrs-vxworks-spe",
    "riscv32gc-unknown-linux-gnu",
    "riscv32gc-unknown-linux-musl",
    "riscv32imac-unknown-none-elf",
    "riscv32imc-esp-espidf",
    "thumbv7em-none-eabi",
    "thumbv7em-none-eabihf",
    "thumbv7m-none-eabi",
    "thumbv8m.base-none-eabi",
    "thumbv8m.main-none-eabi",
    "thumbv8m.main-none-eabihf",
    "mipsel-sony-psp",
    "thumbv4t-none-eabi",
    "thumbv6m-none-eabi",
];
#[allow(dead_code)]
const NO_ATOMIC: &[&str] = &[
    "avr-unknown-gnu-atmega328",
    "msp430-none-elf",
    "riscv32i-unknown-none-elf",
    "riscv32imc-unknown-none-elf",
];
<|endoftext|>


<commit_before>// Copyright 2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Support for discrete probability distributions in terms of cumulative distribution
//! functions (CDF).

use std::f64;
use std::iter;
use std::ops::Range;
use std::slice;

use itertools::Itertools;
use ordered_float::OrderedFloat;

use crate::stats::LogProb;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Entry<T: Ord> {
    pub value: T,
    pub prob: LogProb,
}

impl<T: Ord> Entry<T> {
    pub fn new(value: T, prob: LogProb) -> Self {
        Entry { value, prob }
    }
}

/// Implementation of a cumulative distribution function.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CDF<T: Ord> {
    inner: Vec<Entry<T>>,
}

impl<T: Ord> CDF<T> {
    /// Create CDF from given probability mass function (PMF). The PMF may contain duplicate values
    /// the probabilities of which are summed during generation of the CDF.
    ///
    /// # Arguments
    ///
    /// * `pmf` - the PMF as a vector of `Entry` objects
    pub fn from_pmf(mut entries: Vec<Entry<T>>) -> Self {
        entries.sort_by(|a, b| a.value.cmp(&b.value));
        let mut inner: Vec<Entry<T>> = Vec::new();
        for mut e in entries {
            let p = inner
                .last()
                .map_or(LogProb::ln_zero(), |e| e.prob)
                .ln_add_exp(e.prob);
            if !inner.is_empty() && inner.last().unwrap().value == e.value {
                inner.last_mut().unwrap().prob = p;
            } else {
                e.prob = p;
                inner.push(e);
            }
        }
        let mut cdf = CDF { inner };

        // cap at prob=1.0 if there are slightly exceeding values due to numerical issues.
        for e in &mut cdf.inner {
            if relative_eq!(*e.prob, *LogProb::ln_one(), epsilon = 0.00001)
                && *e.prob > *LogProb::ln_one()
            {
                e.prob = LogProb::ln_one();
            }
        }

        cdf
    }

    /// Create CDF from iterator. This can be used to replace the values of a CDF.
    pub fn from_cdf<I: Iterator<Item = Entry<T>>>(entries: I) -> Self {
        CDF {
            inner: entries.collect_vec(),
        }
    }

    /// Reduce CDF by omitting values with zero probability.
    pub fn reduce(self) -> Self {
        let mut inner = Vec::new();
        let mut last = LogProb::ln_zero();
        for e in self.inner {
            if last != e.prob {
                last = e.prob;
                inner.push(e);
            }
        }
        CDF { inner }
    }

    /// Downsample CDF to n entries. Panics if n <= 1 and returns identity if n is greater
    /// than the number of entries.
    pub fn sample(mut self, n: usize) -> Self {
        assert!(n > 1);
        if self.inner.len() <= n {
            self
        } else {
            let s = self.inner.len() / (n - 1);
            let last = self.inner.pop().unwrap();
            let mut inner = self.inner.into_iter().step_by(s).collect_vec();
            inner.push(last);
            CDF { inner }
        }
    }

    /// Provide iterator.
    pub fn iter(&self) -> slice::Iter<'_, Entry<T>> {
        self.inner.iter()
    }

    /// Mutable iterator over entries. This does not check for consistency. In other words, you
    /// should not change the order of the entries, nor the probabilities!
    pub fn iter_mut(&mut self) -> slice::IterMut<'_, Entry<T>> {
        self.inner.iter_mut()
    }

    /// Iterator over corresponding PMF.
    pub fn iter_pmf(&self) -> CDFPMFIter<'_, T> {
        fn cdf_to_pmf<'a, G: Ord>(
            last_prob: &mut LogProb,
            e: &'a Entry<G>,
        ) -> Option<Entry<&'a G>> {
            let prob = e.prob.ln_sub_exp(*last_prob);
            *last_prob = e.prob;
            Some(Entry::new(&e.value, prob))
        }
        self.inner.iter().scan(LogProb::ln_zero(), cdf_to_pmf)
    }

    /// Get cumulative probability for a given value. If the value is not present,
    /// return the probability of the previous value. Complexity O(log n).
    pub fn get(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        } else {
            Some(match self.inner.binary_search_by(|e| e.value.cmp(value)) {
                Ok(i) => self.inner[i].prob,
                Err(i) => {
                    if i > 0 {
                        self.inner[i - 1].prob
                    } else {
                        LogProb::ln_zero()
                    }
                }
            })
        }
    }

    /// Get probability (i.e. probability mass) for a given value. Complexity O(log n).
    pub fn get_pmf(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        } else {
            Some(match self.inner.binary_search_by(|e| e.value.cmp(value)) {
                Ok(i) => {
                    if i > 0 {
                        self.inner[i].prob.ln_sub_exp(self.inner[i - 1].prob)
                    } else {
                        self.inner[0].prob
                    }
                }
                Err(i) => {
                    if i > 0 {
                        self.inner[i - 1].prob
                    } else {
                        LogProb::ln_zero()
                    }
                }
            })
        }
    }

    /// Return total probability.
    pub fn total_prob(&self) -> LogProb {
        self.inner.last().map_or(LogProb::ln_zero(), |e| e.prob)
    }

    /// Return maximum a posteriori probability estimate (MAP).
    pub fn map(&self) -> Option<&T> {
        if let Some(mut max) = self.iter_pmf().next() {
            for e in self.iter_pmf() {
                if e.prob >= max.prob {
                    max = e;
                }
            }
            Some(max.value)
        } else {
            None
        }
    }

    /// Return w%-credible interval. The width w is a float between 0 and 1. Panics otherwise.
    /// E.g. provide `width=0.95` for the 95% credible interval.
    pub fn credible_interval(&self, width: f64) -> Option<Range<&T>> {
        assert!(width >= 0.0 && width <= 1.0);

        if self.inner.is_empty() {
            return None;
        }

        let margin = 1.0 - width;
        let p_lower = OrderedFloat((margin / 2.0).ln());
        let p_upper = OrderedFloat((1.0 - margin / 2.0).ln());
        let lower = self
            .inner
            .binary_search_by(|e| OrderedFloat(*e.prob).cmp(&p_lower))
            .unwrap_or_else(|i| if i > 0 { i - 1 } else { 0 });
        let mut upper = self
            .inner
            .binary_search_by(|e| OrderedFloat(*e.prob).cmp(&p_upper))
            .unwrap_or_else(|i| i);
        if upper == self.inner.len() {
            upper -= 1;
        }

        Some(&self.inner[lower].value..&self.inner[upper].value)
    }

    /// Number of entries in the CDF.
    pub fn len(&self) -> usize {
        self.inner.len()
    }

    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }
}

impl<T: Clone + Ord> CDF<T>
where
    f64: From<T>,
{
    /// Calculate expected value.
    pub fn expected_value(&self) -> f64 {
        self.iter_pmf()
            .map(|e| f64::from(e.value.clone()) * e.prob.exp())
            .fold(0.0f64, |s, e| s + e)
    }

    /// Calculate variance.
    pub fn variance(&self) -> f64 {
        let ev = self.expected_value();
        self.iter_pmf()
            .map(|e| (f64::from(e.value.clone()) - ev).powi(2) * e.prob.exp())
            .fold(0.0, |s, e| s + e)
    }

    /// Calculate standard deviation.
    pub fn standard_deviation(&self) -> f64 {
        self.variance().sqrt()
    }
}

pub type CDFPMFIter<'a, T> = iter::Scan<
    slice::Iter<'a, Entry<T>>,
    LogProb,
    fn(&mut LogProb, &'a Entry<T>) -> Option<Entry<&'a T>>,
>;

#[cfg(test)]
mod test {
    use super::*;
    use crate::stats::LogProb;
    use ordered_float::NotNan;

    #[test]
    fn test_cdf() {
        let mut pmf = vec![Entry::new(NotNan::new(0.0).unwrap(), LogProb(0.1f64.ln()))];
        for i in 0..9 {
            pmf.push(Entry::new(
                NotNan::new(i as f64).unwrap(),
                LogProb(0.1f64.ln()),
            ));
        }
        println!("{:?}", pmf);

        let cdf = CDF::from_pmf(pmf.clone());
        println!("{:?}", cdf);
        for e in pmf.iter().skip(2) {
            assert_relative_eq!(*e.prob, *cdf.get_pmf(&e.value).unwrap(), epsilon = 0.000003);
        }
        assert_relative_eq!(*cdf.total_prob(), 1.0f64.ln());
        assert_relative_eq!(
            *cdf.get(&NotNan::new(1.0).unwrap()).unwrap(),
            0.3f64.ln(),
            epsilon = 0.00000001
        );
        {
            let ci = cdf.credible_interval(0.95).unwrap();
            assert_relative_eq!(**ci.start, 0.0);
            assert_relative_eq!(**ci.end, 8.0);
        }

        {
            for e in cdf.iter_pmf() {
                assert_relative_eq!(
                    e.prob.exp(),
                    if **e.value == 0.0 { 0.2 } else { 0.1 },
                    epsilon = 0.0001
                );
            }
        }

        assert_relative_eq!(cdf.sample(5).total_prob().exp(), 1.0);
    }
}
<commit_msg>stats::probs::cdf improve docs (#316)<commit_after>// Copyright 2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Support for discrete probability distributions in terms of cumulative distribution
//! functions (CDF).
//!
//! # Examples
//!
//! Example usage of all CDF functions:
//! ```
//! use std::ops::Range;
//! use ordered_float::NotNan;
//! use bio::stats::probs::{LogProb, Prob};
//! use bio::stats::probs::cdf::{CDF, Entry};
//! use approx::assert_relative_eq;
//! // pmf1 is an example PMF with `LogProb(0.0)` at `0`, with `LogProb(0.1)`
//! // at `{1, 2, ..., 8}` and LogProb(0.2) at `10`
//! let mut pmf1 = vec![
//!     Entry::new( 0, LogProb( (0.0 as f64).ln() ) )
//! ];
//! for i in 1..=8 {
//!     pmf1.push(
//!         Entry::new( i, LogProb( (0.1 as f64).ln() ) )
//!     );
//! }
//! pmf1.push( Entry::new( 10, LogProb( (0.2 as f64).ln() ) ) );
//!
//! // create the cumulative distribution function from the probability mass function
//! let cdf = CDF::from_pmf(pmf1.clone());
//! assert_relative_eq!(
//!     *cdf.get(&0).unwrap(),
//!     (0.0 as f64).ln(),
//!     epsilon = 0.0
//! );
//! assert_relative_eq!(
//!     *cdf.get(&3).unwrap(),
//!     (0.3 as f64).ln(),
//!     epsilon = 0.0000000001
//! );
//!
//! // get back the original probability mass value at 7
//! assert_relative_eq!(
//!     *cdf.get_pmf(&7).unwrap(),
//!     (0.1 as f64).ln(),
//!     epsilon = 0.00001
//! );
//!
//! // Check that cdf sums up to 1.0
//! assert_relative_eq!(
//!     f64::from(cdf.total_prob()),
//!     (1.0 as f64).ln(),
//!     epsilon = 0.0
//! );
//!
//! // copy a CDF via its iter() function
//! let mut cdf_copy = CDF::from_cdf(cdf.iter().cloned());
//! assert_eq!(cdf.len(), cdf_copy.len());
//!
//! // get the maximum a posteriori probability estimate
//! assert_eq!( cdf_copy.map().unwrap(), &10 );
//!
//! // get the 50% credible interval
//! assert_eq!( cdf_copy.credible_interval(0.5).unwrap(), &2..&8 );
//!
//! // cdf_vec is an example Entry vector with `LogProb(0.0)` at `ordered_float::NotNan`
//! // values `{0.0, 1.0, 2.0}` and increasing by `LogProb(0.2)` at each to `{3.0, 4.0, ..., 7.0}`
//! let mut cdf_vec = Vec::new();
//! for i in 0..=2 {
//!     cdf_vec.push(
//!         Entry::new(
//!             NotNan::new(i as f64).unwrap(),
//!             LogProb::ln_zero()
//!         )
//!     )
//! }
//! for i in 3..=7 {
//!     cdf_vec.push(
//!         Entry::new(
//!             NotNan::new(i as f64).unwrap(),
//!             LogProb( ((i-2) as f64 * 0.2f64).ln() )
//!         )
//!     );
//! }
//!
//! // create cdf from vector of `Entry`s
//! let mut cdf_from_vec = CDF::from_cdf(cdf_vec.into_iter());
//!
//! assert_relative_eq!(
//!     *cdf_from_vec.get(&NotNan::new(2.0).unwrap()).unwrap(),
//!     LogProb::ln_zero(),
//!     epsilon = 0.0
//! );
//! assert_relative_eq!(
//!     *cdf_from_vec.get(&NotNan::new(4.0).unwrap()).unwrap(),
//!     LogProb( (0.4 as f64).ln() ),
//!     epsilon = 0.0
//! );
//!
//! // get the number of `Entry`s in cdf_from_vec
//! assert_eq!(cdf_from_vec.len(), 8);
//!
//! // remove three zero values at `{0.0, 1.0, 2.0}` with `CDF::reduce()`
//! cdf_from_vec = CDF::reduce(cdf_from_vec);
//! assert_eq!(cdf_from_vec.len(), 5);
//! ```

use std::f64;
use std::iter;
use std::ops::Range;
use std::slice;

use itertools::Itertools;
use ordered_float::OrderedFloat;

use crate::stats::LogProb;

/// An `Entry` associates a `LogProb` with a value on an ordered axis. It can for example be
/// used to set up probability mass functions or cumulative distribution functions ([CDF](struct.CDF)).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Entry<T: Ord> {
    /// A `value` on the ordered axis, which has to have the Trait [`std::cmp::Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) implemented.
    pub value: T,
    /// A probability at that `value` / point x on the x-axis.
    pub prob: LogProb,
}

impl<T: Ord> Entry<T> {
    /// Create a new `Entry` for `prob` at `value`.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::stats::probs::cdf::Entry;
    /// use bio::stats::LogProb;
    /// let entry = Entry::new(5, LogProb(0.6));
    /// assert_eq!(entry.value, 5);
    /// assert_eq!(entry.prob, LogProb(0.6));
    /// ```
    pub fn new(value: T, prob: LogProb) -> Self {
        Entry { value, prob }
    }
}

/// Implementation of a cumulative distribution function as a vector of `Entry`s.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CDF<T: Ord> {
    inner: Vec<Entry<T>>,
}

impl<T: Ord> CDF<T> {
    /// Create CDF from given probability mass function (PMF). The PMF may contain duplicate values
    /// the probabilities of which are summed during generation of the CDF.
    ///
    /// # Arguments
    ///
    /// * `pmf` - The PMF as a vector of `Entry` objects (values with an associated `LogProb`).
    ///
    pub fn from_pmf(mut entries: Vec<Entry<T>>) -> Self {
        entries.sort_by(|a, b| a.value.cmp(&b.value));
        let mut inner: Vec<Entry<T>> = Vec::new();
        for mut e in entries {
            let p = inner
                .last()
                .map_or(LogProb::ln_zero(), |e| e.prob)
                .ln_add_exp(e.prob);
            if !inner.is_empty() && inner.last().unwrap().value == e.value {
                inner.last_mut().unwrap().prob = p;
            } else {
                e.prob = p;
                inner.push(e);
            }
        }
        let mut cdf = CDF { inner };

        // cap at prob=1.0 if there are slightly exceeding values due to numerical issues.
        for e in &mut cdf.inner {
            if relative_eq!(*e.prob, *LogProb::ln_one(), epsilon = 0.00001)
                && *e.prob > *LogProb::ln_one()
            {
                e.prob = LogProb::ln_one();
            }
        }

        cdf
    }

    /// Create CDF from iterator. This can be used to replace the values of a CDF.
    ///
    /// # Arguments
    ///
    /// * `entries` - An iterator over `Entry<T>` values, where T requires
    ///
    pub fn from_cdf<I: Iterator<Item = Entry<T>>>(entries: I) -> Self {
        CDF {
            inner: entries.collect_vec(),
        }
    }

    /// Reduce CDF by omitting values with zero probability.
    pub fn reduce(self) -> Self {
        let mut inner = Vec::new();
        let mut last = LogProb::ln_zero();
        for e in self.inner {
            if last != e.prob {
                last = e.prob;
                inner.push(e);
            }
        }
        CDF { inner }
    }

    /// Downsample CDF to n entries. Panics if n <= 1 and returns identity if n is greater
    /// than the number of entries.
    pub fn sample(mut self, n: usize) -> Self {
        assert!(n > 1);
        if self.inner.len() <= n {
            self
        } else {
            let s = self.inner.len() / (n - 1);
            let last = self.inner.pop().unwrap();
            let mut inner = self.inner.into_iter().step_by(s).collect_vec();
            inner.push(last);
            CDF { inner }
        }
    }

    /// Provide an iterator for the CDF.
    pub fn iter(&self) -> slice::Iter<'_, Entry<T>> {
        self.inner.iter()
    }

    /// Provide a mutable iterator over entries.
    ///
    /// This does not check for consistency. In other words, you
    /// should not change the order of the entries, nor the probabilities!
    pub fn iter_mut(&mut self) -> slice::IterMut<'_, Entry<T>> {
        self.inner.iter_mut()
    }

    /// Provide an iterator over the PMF corresponding to this CDF.
    pub fn iter_pmf(&self) -> CDFPMFIter<'_, T> {
        fn cdf_to_pmf<'a, G: Ord>(
            last_prob: &mut LogProb,
            e: &'a Entry<G>,
        ) -> Option<Entry<&'a G>> {
            let prob = e.prob.ln_sub_exp(*last_prob);
            *last_prob = e.prob;
            Some(Entry::new(&e.value, prob))
        }
        self.inner.iter().scan(LogProb::ln_zero(), cdf_to_pmf)
    }

    /// Get cumulative probability for a given value.
    ///
    /// If the value is not present, return the probability of the previous value.
    /// Complexity: O(log n).
    ///
    /// # Arguments
    ///
    /// * `value` - A value at which you're interested in the cumulative probability.
    ///
    pub fn get(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        } else {
            Some(match self.inner.binary_search_by(|e| e.value.cmp(value)) {
                Ok(i) => self.inner[i].prob,
                Err(i) => {
                    if i > 0 {
                        self.inner[i - 1].prob
                    } else {
                        LogProb::ln_zero()
                    }
                }
            })
        }
    }

    /// Get probability (i.e. probability mass) for a given value.
    /// Time complexity: O(log n), where n is number of `Entries` in `CDF`.
    pub fn get_pmf(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        } else {
            Some(match self.inner.binary_search_by(|e| e.value.cmp(value)) {
                Ok(i) => {
                    if i > 0 {
                        self.inner[i].prob.ln_sub_exp(self.inner[i - 1].prob)
                    } else {
                        self.inner[0].prob
                    }
                }
                Err(i) => {
                    if i > 0 {
                        self.inner[i - 1].prob
                    } else {
                        LogProb::ln_zero()
                    }
                }
            })
        }
    }

    /// Return total probability of the `CDF`.
    pub fn total_prob(&self) -> LogProb {
        self.inner.last().map_or(LogProb::ln_zero(), |e| e.prob)
    }

    /// Return maximum a posteriori probability estimate (MAP).
    pub fn map(&self) -> Option<&T> {
        if let Some(mut max) = self.iter_pmf().next() {
            for e in self.iter_pmf() {
                if e.prob >= max.prob {
                    max = e;
                }
            }
            Some(max.value)
        } else {
            None
        }
    }

    /// Return w%-credible interval. The width w is a float between 0 and 1. Panics otherwise.
    /// E.g. provide `width=0.95` for the 95% credible interval.
    pub fn credible_interval(&self, width: f64) -> Option<Range<&T>> {
        assert!(width >= 0.0 && width <= 1.0);

        if self.inner.is_empty() {
            return None;
        }

        let margin = 1.0 - width;
        let p_lower = OrderedFloat((margin / 2.0).ln());
        let p_upper = OrderedFloat((1.0 - margin / 2.0).ln());
        let lower = self
            .inner
            .binary_search_by(|e| OrderedFloat(*e.prob).cmp(&p_lower))
            .unwrap_or_else(|i| if i > 0 { i - 1 } else { 0 });
        let mut upper = self
            .inner
            .binary_search_by(|e| OrderedFloat(*e.prob).cmp(&p_upper))
            .unwrap_or_else(|i| i);
        if upper == self.inner.len() {
            upper -= 1;
        }

        Some(&self.inner[lower].value..&self.inner[upper].value)
    }

    /// Number of entries in the CDF.
    pub fn len(&self) -> usize {
        self.inner.len()
    }

    /// Returns `true` if a CDF is empty, false otherwise.
    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }
}

impl<T: Clone + Ord> CDF<T>
where
    f64: From<T>,
{
    /// Calculate expected value.
    pub fn expected_value(&self) -> f64 {
        self.iter_pmf()
            .map(|e| f64::from(e.value.clone()) * e.prob.exp())
            .fold(0.0f64, |s, e| s + e)
    }

    /// Calculate variance.
    pub fn variance(&self) -> f64 {
        let ev = self.expected_value();
        self.iter_pmf()
            .map(|e| (f64::from(e.value.clone()) - ev).powi(2) * e.prob.exp())
            .fold(0.0, |s, e| s + e)
    }

    /// Calculate standard deviation.
    pub fn standard_deviation(&self) -> f64 {
        self.variance().sqrt()
    }
}

pub type CDFPMFIter<'a, T> = iter::Scan<
    slice::Iter<'a, Entry<T>>,
    LogProb,
    fn(&mut LogProb, &'a Entry<T>) -> Option<Entry<&'a T>>,
>;

#[cfg(test)]
mod test {
    use super::*;
    use crate::stats::LogProb;
    use ordered_float::NotNan;

    #[test]
    fn test_cdf() {
        let mut pmf = vec![Entry::new(NotNan::new(0.0).unwrap(), LogProb(0.1f64.ln()))];
        for i in 0..9 {
            pmf.push(Entry::new(
                NotNan::new(i as f64).unwrap(),
                LogProb(0.1f64.ln()),
            ));
        }
        println!("{:?}", pmf);

        let cdf = CDF::from_pmf(pmf.clone());
        println!("{:?}", cdf);
        for e in pmf.iter().skip(2) {
            assert_relative_eq!(*e.prob, *cdf.get_pmf(&e.value).unwrap(), epsilon = 0.000003);
        }
        assert_relative_eq!(*cdf.total_prob(), 1.0f64.ln());
        assert_relative_eq!(
            *cdf.get(&NotNan::new(1.0).unwrap()).unwrap(),
            0.3f64.ln(),
            epsilon = 0.00000001
        );
        {
            let ci = cdf.credible_interval(0.95).unwrap();
            assert_relative_eq!(**ci.start, 0.0);
            assert_relative_eq!(**ci.end, 8.0);
        }

        {
            for e in cdf.iter_pmf() {
                assert_relative_eq!(
                    e.prob.exp(),
                    if **e.value == 0.0 { 0.2 } else { 0.1 },
                    epsilon = 0.0001
                );
            }
        }

        assert_relative_eq!(cdf.sample(5).total_prob().exp(), 1.0);
    }
}
<|endoftext|>


<commit_before>//! Upload command
//!
//! It uploads issues from a CSV.

use csv;

pub type Issues = Vec<NewIssue>;

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct NewIssue {
    pub assignees: Option<Vec<String>>,
    pub body: Option<String>,
    pub labels: Option<Vec<String>>,
    pub title: String,
}

pub fn run(repopath: String,
           oauth_token: String,
           filename: String) {
    let mut records = csv::Reader::from_file(filename).unwrap();

    for record in records.decode() {
        let (title, body, labels, assignees): (String, Option<String>, Option<String>, Option<String>) =
            record.unwrap();

        let rec = NewIssue { assignees : assignees.map(split)
                           , body : body
                           , labels : labels.map(split)
                           , title : title
                           };

        println!("{:?}", rec);
    }

    println!("foo");
}

// CSV lib does not cast Vec<String> so this is a workaround.
fn split(s: String) -> Vec<String> {
   s.split(",").map(From::from).collect()
}
<commit_msg>refator(upload): Extract function from_file<commit_after>//! Upload command
//!
//! It uploads issues from a CSV.

use csv;

pub type Issues = Vec<NewIssue>;

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct NewIssue {
    pub assignees: Option<Vec<String>>,
    pub body: Option<String>,
    pub labels: Option<Vec<String>>,
    pub title: String,
}

pub fn run(repopath: String,
           oauth_token: String,
           filename: String) {

    let issues: Issues = from_file(filename);

    println!("{:?}", issues);
}

// CSV lib does not cast Vec<String> so this is a workaround.
fn split(s: String) -> Vec<String> {
   s.split(",").map(From::from).collect()
}

fn from_file(filename: String) -> Issues {
    let mut records = csv::Reader::from_file(filename).unwrap();
    let mut issues: Issues = vec![];

    for record in records.decode() {
        let (title, body, labels, assignees): (String, Option<String>, Option<String>, Option<String>) =
            record.unwrap();

        issues.push(NewIssue { assignees : assignees.map(split)
                             , body : body
                             , labels : labels.map(split)
                             , title : title
                             });
    }

    issues
}
<|endoftext|>


<commit_before>// This returns a miri pointer at type usize, if the argument is a proper pointer
fn transmute_ptr_to_int<T>(x: *const T) -> usize {
    unsafe { std::mem::transmute(x) }
}

fn cast() {
    // Some casting-to-int with arithmetic.
    let x = &42 as *const i32 as usize;
    let y = x * 2;
    assert_eq!(y, x + x);
    let z = y as u8 as usize;
    assert_eq!(z, y % 256);
}

fn format() {
    // Pointer string formatting! We can't check the output as it changes when libstd changes,
    // but we can make sure Miri does not error.
    format!("{:?}", &mut 13 as *mut _);
}

fn transmute() {
    // Check that intptrcast is triggered for explicit casts and that it is consistent with
    // transmuting.
    let a: *const i32 = &42;
    let b = transmute_ptr_to_int(a) as u8;
    let c = a as usize as u8;
    assert_eq!(b, c);
}

fn ptr_bitops1() {
    let bytes = [0i8, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    let one = bytes.as_ptr().wrapping_offset(1);
    let three = bytes.as_ptr().wrapping_offset(3);
    let res = (one as usize) | (three as usize);
    format!("{}", res);
}

fn ptr_bitops2() {
    let val = 13usize;
    let addr = &val as *const _ as usize;
    let _val = addr & 13;
}

fn ptr_eq_dangling() {
    let b = Box::new(0);
    let x = &*b as *const i32; // soon-to-be dangling
    drop(b);
    let b = Box::new(0);
    let y = &*b as *const i32; // different allocation
    // We cannot compare these even though both are inbounds -- they *could* be
    // equal if memory was reused.
    assert!(x != y);
}

fn ptr_eq_out_of_bounds() {
    let b = Box::new(0);
    let x = (&*b as *const i32).wrapping_sub(0x800); // out-of-bounds
    let b = Box::new(0);
    let y = &*b as *const i32; // different allocation
    // We cannot compare these even though both allocations are live -- they *could* be
    // equal (with the right base addresses).
    assert!(x != y);
}

fn ptr_eq_out_of_bounds_null() {
    let b = Box::new(0);
    let x = (&*b as *const i32).wrapping_sub(0x800); // out-of-bounds
    // We cannot compare this with NULL. After all, this *could* be NULL (with the right base address).
    assert!(x != std::ptr::null());
}

fn ptr_eq_integer() {
    let b = Box::new(0);
    let x = &*b as *const i32;
    // We cannot compare this with a non-NULL integer. After all, these *could* be equal (with the right base address).
    assert!(x != 64 as *const i32);
}

fn main() {
    cast();
    format();
    transmute();
    ptr_bitops1();
    ptr_bitops2();
    ptr_eq_dangling();
    ptr_eq_out_of_bounds();
    ptr_eq_out_of_bounds_null();
    ptr_eq_integer();
}
<commit_msg>test casting a dangling ptr back from an int<commit_after>// This returns a miri pointer at type usize, if the argument is a proper pointer
fn transmute_ptr_to_int<T>(x: *const T) -> usize {
    unsafe { std::mem::transmute(x) }
}

fn cast() {
    // Some casting-to-int with arithmetic.
    let x = &42 as *const i32 as usize;
    let y = x * 2;
    assert_eq!(y, x + x);
    let z = y as u8 as usize;
    assert_eq!(z, y % 256);
}

/// Test usize->ptr cast for dangling and OOB address.
/// That is safe, and thus has to work.
fn cast_dangling() {
    let b = Box::new(0);
    let x = &*b as *const i32 as usize;
    drop(b);
    let _val = x as *const i32;

    let b = Box::new(0);
    let mut x = &*b as *const i32 as usize;
    x += 0x100;
    let _val = x as *const i32;
}

fn format() {
    // Pointer string formatting! We can't check the output as it changes when libstd changes,
    // but we can make sure Miri does not error.
    format!("{:?}", &mut 13 as *mut _);
}

fn transmute() {
    // Check that intptrcast is triggered for explicit casts and that it is consistent with
    // transmuting.
    let a: *const i32 = &42;
    let b = transmute_ptr_to_int(a) as u8;
    let c = a as usize as u8;
    assert_eq!(b, c);
}

fn ptr_bitops1() {
    let bytes = [0i8, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    let one = bytes.as_ptr().wrapping_offset(1);
    let three = bytes.as_ptr().wrapping_offset(3);
    let res = (one as usize) | (three as usize);
    format!("{}", res);
}

fn ptr_bitops2() {
    let val = 13usize;
    let addr = &val as *const _ as usize;
    let _val = addr & 13;
}

fn ptr_eq_dangling() {
    let b = Box::new(0);
    let x = &*b as *const i32; // soon-to-be dangling
    drop(b);
    let b = Box::new(0);
    let y = &*b as *const i32; // different allocation
    // They *could* be equal if memory was reused, but probably are not.
    assert!(x != y);
}

fn ptr_eq_out_of_bounds() {
    let b = Box::new(0);
    let x = (&*b as *const i32).wrapping_sub(0x800); // out-of-bounds
    let b = Box::new(0);
    let y = &*b as *const i32; // different allocation
    // They *could* be equal (with the right base addresses), but probably are not.
    assert!(x != y);
}

fn ptr_eq_out_of_bounds_null() {
    let b = Box::new(0);
    let x = (&*b as *const i32).wrapping_sub(0x800); // out-of-bounds
    // This *could* be NULL (with the right base address), but probably is not.
    assert!(x != std::ptr::null());
}

fn ptr_eq_integer() {
    let b = Box::new(0);
    let x = &*b as *const i32;
    // These *could* be equal (with the right base address), but probably are not.
    assert!(x != 64 as *const i32);
}

fn main() {
    cast();
    cast_dangling();
    format();
    transmute();
    ptr_bitops1();
    ptr_bitops2();
    ptr_eq_dangling();
    ptr_eq_out_of_bounds();
    ptr_eq_out_of_bounds_null();
    ptr_eq_integer();
}
<|endoftext|>


<commit_before>use dsl::Select;
use expression::Expression;
use query_dsl::methods::SelectDsl;
use super::delete_statement::DeleteStatement;
use super::insert_statement::{Insert, Replace};
use super::{IncompleteInsertStatement, IncompleteUpdateStatement, IntoUpdateTarget,
            SelectStatement, SqlQuery};

/// Creates an `UPDATE` statement. Helpers for updating a single row can be
/// generated by deriving [`AsChangeset`](../trait.AsChangeset.html)
///
/// When a table is passed to `update`, every row in the table will be updated.
/// You can narrow this scope by calling [`filter`] on the table before passing it in,
/// which will result in `UPDATE your_table SET ... WHERE args_to_filter`.
///
/// Passing a type which implements `Identifiable` is the same as passing
/// `some_table.find(some_struct.id())`.
///
/// [`filter`]: query_builder/update_statement/struct.IncompleteUpdateStatement.html#method.filter
///
/// # Examples
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # #[cfg(feature = "postgres")]
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// let updated_row = diesel::update(users.filter(id.eq(1)))
///     .set(name.eq("James"))
///     .get_result(&connection);
/// // On backends that support it, you can call `get_result` instead of `execute`
/// // to have `RETURNING *` automatically appended to the query. Alternatively, you
/// // can explicitly return an expression by using the `returning` method before
/// // getting the result.
/// assert_eq!(Ok((1, "James".to_string())), updated_row);
/// # }
/// # #[cfg(not(feature = "postgres"))]
/// # fn main() {}
/// ```
///
/// To update multiple columns, give [`set`] a tuple argument:
///
/// [`set`]: query_builder/struct.IncompleteUpdateStatement.html#method.set
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # table! {
/// #     users {
/// #         id -> Integer,
/// #         name -> VarChar,
/// #         surname -> VarChar,
/// #     }
/// # }
/// #
/// # #[cfg(feature = "postgres")]
/// # fn main() {
/// # use users::dsl::*;
/// # let connection = establish_connection();
/// # connection.execute("DROP TABLE users").unwrap();
/// # connection.execute("CREATE TABLE users (
/// #     id SERIAL PRIMARY KEY,
/// #     name VARCHAR,
/// #     surname VARCHAR)").unwrap();
/// # connection.execute("INSERT INTO users(name, surname) VALUES('Sean', 'Griffin')").unwrap();
///
/// let updated_row = diesel::update(users.filter(id.eq(1)))
///     .set((name.eq("James"), surname.eq("Bond")))
///     .get_result(&connection);
///
/// assert_eq!(Ok((1, "James".to_string(), "Bond".to_string())), updated_row);
/// # }
/// # #[cfg(not(feature = "postgres"))]
/// # fn main() {}
/// ```
pub fn update<T: IntoUpdateTarget>(
    source: T,
) -> IncompleteUpdateStatement<T::Table, T::WhereClause> {
    IncompleteUpdateStatement::new(source.into_update_target())
}

/// Creates a `DELETE` statement.
///
/// When a table is passed to `delete`,
/// every row in the table will be deleted.
/// This scope can be narrowed by calling [`filter`]
/// on the table before it is passed in.
///
/// [`filter`]: query_builder/struct.DeleteStatement.html#method.filter
///
/// # Examples
///
/// ### Deleting a single record:
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # fn main() {
/// #     delete();
/// # }
/// #
/// # fn delete() -> QueryResult<()> {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// #     let get_count = || users.count().first::<i64>(&connection);
/// let old_count = get_count();
/// try!(diesel::delete(users.filter(id.eq(1))).execute(&connection));
/// assert_eq!(old_count.map(|count| count - 1), get_count());
/// # Ok(())
/// # }
/// ```
///
/// ### Deleting a whole table:
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # fn main() {
/// #     delete();
/// # }
/// #
/// # fn delete() -> QueryResult<()> {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// #     let get_count = || users.count().first::<i64>(&connection);
/// try!(diesel::delete(users).execute(&connection));
/// assert_eq!(Ok(0), get_count());
/// # Ok(())
/// # }
/// ```
pub fn delete<T: IntoUpdateTarget>(source: T) -> DeleteStatement<T::Table, T::WhereClause> {
    let target = source.into_update_target();
    DeleteStatement::new(target.table, target.where_clause)
}

/// Creates an `INSERT` statement for the target table.
///
/// You may add data by calling [`values()`] or [`default_values()`]
/// as shown in the examples.
///
/// [`values()`]: query_builder/insert_statement/struct.IncompleteInsertStatement.html#method.values
/// [`default_values()`]: query_builder/insert_statement/struct.IncompleteInsertStatement.html#method.default_values
///
/// Backends that support the `RETURNING` clause, such as PostgreSQL,
/// can return the inserted rows by calling [`.get_results`] instead of [`.execute`].
///
/// [`.get_results`]: query_dsl/trait.RunQueryDsl.html#method.get_results
/// [`.execute`]: query_dsl/trait.RunQueryDsl.html#tymethod.execute
///
/// # Examples
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// let rows_inserted = diesel::insert_into(users)
///     .values(&name.eq("Sean"))
///     .execute(&connection);
///
/// assert_eq!(Ok(1), rows_inserted);
///
/// let new_users = vec![
///     name.eq("Tess"),
///     name.eq("Jim"),
/// ];
///
/// let rows_inserted = diesel::insert_into(users)
///     .values(&new_users)
///     .execute(&connection);
///
/// assert_eq!(Ok(2), rows_inserted);
/// # }
/// ```
///
/// ### Using a tuple for values
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// #     diesel::delete(users).execute(&connection).unwrap();
/// let new_user = (id.eq(1), name.eq("Sean"));
/// let rows_inserted = diesel::insert_into(users)
///     .values(&new_user)
///     .execute(&connection);
///
/// assert_eq!(Ok(1), rows_inserted);
///
/// let new_users = vec![
///     (id.eq(2), name.eq("Tess")),
///     (id.eq(2), name.eq("Jim")),
/// ];
///
/// let rows_inserted = diesel::insert_into(users)
///     .values(&new_users)
///     .execute(&connection);
///
/// // assert_eq!(Ok(2), rows_inserted);
/// # }
/// ```
///
/// ### Using struct for values
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// # use schema::users;
/// #
/// #[derive(Insertable)]
/// #[table_name = "users"]
/// struct NewUser<'a> {
///     name: &'a str,
/// }
///
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// // Insert one record at a time
///
/// let new_user = NewUser { name: "Ruby Rhod" };
///
/// diesel::insert_into(users)
///     .values(&new_user)
///     .execute(&connection)
///     .unwrap();
///
/// // Insert many records
///
/// let new_users = vec![
///     NewUser { name: "Leeloo Multipass", },
///     NewUser { name: "Korben Dallas", },
/// ];
///
/// let inserted_names = diesel::insert_into(users)
///     .values(&new_users)
///     .execute(&connection)
///     .unwrap();
/// # }
/// ```
///
/// ### With return value
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # #[cfg(feature = "postgres")]
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// let inserted_names = diesel::insert_into(users)
///     .values(&vec![
///         name.eq("Diva Plavalaguna"),
///         name.eq("Father Vito Cornelius"),
///     ])
///     .returning(name)
///     .get_results(&connection);
/// assert_eq!(Ok(vec!["Diva Plavalaguna".to_string(), "Father Vito Cornelius".to_string()]), inserted_names);
/// # }
/// # #[cfg(not(feature = "postgres"))]
/// # fn main() {}
/// ```
pub fn insert_into<T>(target: T) -> IncompleteInsertStatement<T, Insert> {
    IncompleteInsertStatement::new(target, Insert)
}

/// Creates a bare select statement, with no from clause. Primarily used for
/// testing diesel itself, but likely useful for third party crates as well. The
/// given expressions must be selectable from anywhere.
pub fn select<T>(expression: T) -> Select<SelectStatement<()>, T>
where
    T: Expression,
    SelectStatement<()>: SelectDsl<T>,
{
    SelectStatement::simple(()).select(expression)
}

/// Creates a `REPLACE` statement.
///
/// If a constraint violation fails, the database will attempt to replace the
/// offending row instead. This function is only available with MySQL and
/// SQLite.
///
/// # Example
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # #[cfg(not(feature = "postgres"))]
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     use diesel::{insert_into, replace_into};
/// #
/// #     let conn = establish_connection();
/// #     conn.execute("DELETE FROM users").unwrap();
/// replace_into(users)
///     .values(&vec![
///         (id.eq(1), name.eq("Sean")),
///         (id.eq(2), name.eq("Tess")),
///     ])
///     .execute(&conn)
///     .unwrap();
///
/// replace_into(users)
///     .values((id.eq(1), name.eq("Jim")))
///     .execute(&conn)
///     .unwrap();
///
/// let names = users.select(name).order(id).load::<String>(&conn);
/// assert_eq!(Ok(vec!["Jim".into(), "Tess".into()]), names);
/// # }
/// # #[cfg(feature = "postgres")] fn main() {}
pub fn replace_into<T>(target: T) -> IncompleteInsertStatement<T, Replace> {
    IncompleteInsertStatement::new(target, Replace)
}

/// Construct a full SQL query using raw SQL.
///
/// This function exists for cases where a query needs to be written that is not
/// supported by the query builder. Unlike most queries in Diesel, `sql_query`
/// will deserialize its data by name, not by index. That means that you cannot
/// deserialize into a tuple, and structs which you deserialize from this
/// function will need to have `#[derive(QueryableByName)]`
///
/// # Safety
///
/// The implementation of `QueryableByName` will assume that columns with a
/// given name will have a certain type. The compiler will be unable to verify
/// that the given type is correct. If your query returns a column of an
/// unexpected type, the result may have the wrong value, or return an error.
///
/// # Example
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # use schema::users;
/// #
/// # #[derive(QueryableByName, Debug, PartialEq)]
/// # #[table_name="users"]
/// # struct User {
/// #     id: i32,
/// #     name: String,
/// # }
/// #
/// # fn main() {
/// #     use diesel::sql_query;
/// #
/// #     let connection = establish_connection();
/// let users = sql_query("SELECT * FROM users ORDER BY id")
///     .load(&connection);
/// let expected_users = vec![
///     User { id: 1, name: "Sean".into() },
///     User { id: 2, name: "Tess".into() },
/// ];
/// assert_eq!(Ok(expected_users), users);
/// # }
/// ```
pub fn sql_query<T: Into<String>>(query: T) -> SqlQuery {
    SqlQuery::new(query.into())
}
<commit_msg>Remove confusing line from `update`'s docs<commit_after>use dsl::Select;
use expression::Expression;
use query_dsl::methods::SelectDsl;
use super::delete_statement::DeleteStatement;
use super::insert_statement::{Insert, Replace};
use super::{IncompleteInsertStatement, IncompleteUpdateStatement, IntoUpdateTarget,
            SelectStatement, SqlQuery};

/// Creates an `UPDATE` statement.
///
/// When a table is passed to `update`, every row in the table will be updated.
/// You can narrow this scope by calling [`filter`] on the table before passing it in,
/// which will result in `UPDATE your_table SET ... WHERE args_to_filter`.
///
/// Passing a type which implements `Identifiable` is the same as passing
/// `some_table.find(some_struct.id())`.
///
/// [`filter`]: query_builder/update_statement/struct.IncompleteUpdateStatement.html#method.filter
///
/// # Examples
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # #[cfg(feature = "postgres")]
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// let updated_row = diesel::update(users.filter(id.eq(1)))
///     .set(name.eq("James"))
///     .get_result(&connection);
/// // On backends that support it, you can call `get_result` instead of `execute`
/// // to have `RETURNING *` automatically appended to the query. Alternatively, you
/// // can explicitly return an expression by using the `returning` method before
/// // getting the result.
/// assert_eq!(Ok((1, "James".to_string())), updated_row);
/// # }
/// # #[cfg(not(feature = "postgres"))]
/// # fn main() {}
/// ```
///
/// To update multiple columns, give [`set`] a tuple argument:
///
/// [`set`]: query_builder/struct.IncompleteUpdateStatement.html#method.set
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # table! {
/// #     users {
/// #         id -> Integer,
/// #         name -> VarChar,
/// #         surname -> VarChar,
/// #     }
/// # }
/// #
/// # #[cfg(feature = "postgres")]
/// # fn main() {
/// # use users::dsl::*;
/// # let connection = establish_connection();
/// # connection.execute("DROP TABLE users").unwrap();
/// # connection.execute("CREATE TABLE users (
/// #     id SERIAL PRIMARY KEY,
/// #     name VARCHAR,
/// #     surname VARCHAR)").unwrap();
/// # connection.execute("INSERT INTO users(name, surname) VALUES('Sean', 'Griffin')").unwrap();
///
/// let updated_row = diesel::update(users.filter(id.eq(1)))
///     .set((name.eq("James"), surname.eq("Bond")))
///     .get_result(&connection);
///
/// assert_eq!(Ok((1, "James".to_string(), "Bond".to_string())), updated_row);
/// # }
/// # #[cfg(not(feature = "postgres"))]
/// # fn main() {}
/// ```
pub fn update<T: IntoUpdateTarget>(
    source: T,
) -> IncompleteUpdateStatement<T::Table, T::WhereClause> {
    IncompleteUpdateStatement::new(source.into_update_target())
}

/// Creates a `DELETE` statement.
///
/// When a table is passed to `delete`,
/// every row in the table will be deleted.
/// This scope can be narrowed by calling [`filter`]
/// on the table before it is passed in.
///
/// [`filter`]: query_builder/struct.DeleteStatement.html#method.filter
///
/// # Examples
///
/// ### Deleting a single record:
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # fn main() {
/// #     delete();
/// # }
/// #
/// # fn delete() -> QueryResult<()> {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// #     let get_count = || users.count().first::<i64>(&connection);
/// let old_count = get_count();
/// try!(diesel::delete(users.filter(id.eq(1))).execute(&connection));
/// assert_eq!(old_count.map(|count| count - 1), get_count());
/// # Ok(())
/// # }
/// ```
///
/// ### Deleting a whole table:
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # fn main() {
/// #     delete();
/// # }
/// #
/// # fn delete() -> QueryResult<()> {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// #     let get_count = || users.count().first::<i64>(&connection);
/// try!(diesel::delete(users).execute(&connection));
/// assert_eq!(Ok(0), get_count());
/// # Ok(())
/// # }
/// ```
pub fn delete<T: IntoUpdateTarget>(source: T) -> DeleteStatement<T::Table, T::WhereClause> {
    let target = source.into_update_target();
    DeleteStatement::new(target.table, target.where_clause)
}

/// Creates an `INSERT` statement for the target table.
///
/// You may add data by calling [`values()`] or [`default_values()`]
/// as shown in the examples.
///
/// [`values()`]: query_builder/insert_statement/struct.IncompleteInsertStatement.html#method.values
/// [`default_values()`]: query_builder/insert_statement/struct.IncompleteInsertStatement.html#method.default_values
///
/// Backends that support the `RETURNING` clause, such as PostgreSQL,
/// can return the inserted rows by calling [`.get_results`] instead of [`.execute`].
///
/// [`.get_results`]: query_dsl/trait.RunQueryDsl.html#method.get_results
/// [`.execute`]: query_dsl/trait.RunQueryDsl.html#tymethod.execute
///
/// # Examples
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// let rows_inserted = diesel::insert_into(users)
///     .values(&name.eq("Sean"))
///     .execute(&connection);
///
/// assert_eq!(Ok(1), rows_inserted);
///
/// let new_users = vec![
///     name.eq("Tess"),
///     name.eq("Jim"),
/// ];
///
/// let rows_inserted = diesel::insert_into(users)
///     .values(&new_users)
///     .execute(&connection);
///
/// assert_eq!(Ok(2), rows_inserted);
/// # }
/// ```
///
/// ### Using a tuple for values
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// #     diesel::delete(users).execute(&connection).unwrap();
/// let new_user = (id.eq(1), name.eq("Sean"));
/// let rows_inserted = diesel::insert_into(users)
///     .values(&new_user)
///     .execute(&connection);
///
/// assert_eq!(Ok(1), rows_inserted);
///
/// let new_users = vec![
///     (id.eq(2), name.eq("Tess")),
///     (id.eq(2), name.eq("Jim")),
/// ];
///
/// let rows_inserted = diesel::insert_into(users)
///     .values(&new_users)
///     .execute(&connection);
///
/// // assert_eq!(Ok(2), rows_inserted);
/// # }
/// ```
///
/// ### Using struct for values
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// # use schema::users;
/// #
/// #[derive(Insertable)]
/// #[table_name = "users"]
/// struct NewUser<'a> {
///     name: &'a str,
/// }
///
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// // Insert one record at a time
///
/// let new_user = NewUser { name: "Ruby Rhod" };
///
/// diesel::insert_into(users)
///     .values(&new_user)
///     .execute(&connection)
///     .unwrap();
///
/// // Insert many records
///
/// let new_users = vec![
///     NewUser { name: "Leeloo Multipass", },
///     NewUser { name: "Korben Dallas", },
/// ];
///
/// let inserted_names = diesel::insert_into(users)
///     .values(&new_users)
///     .execute(&connection)
///     .unwrap();
/// # }
/// ```
///
/// ### With return value
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # #[cfg(feature = "postgres")]
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// let inserted_names = diesel::insert_into(users)
///     .values(&vec![
///         name.eq("Diva Plavalaguna"),
///         name.eq("Father Vito Cornelius"),
///     ])
///     .returning(name)
///     .get_results(&connection);
/// assert_eq!(Ok(vec!["Diva Plavalaguna".to_string(), "Father Vito Cornelius".to_string()]), inserted_names);
/// # }
/// # #[cfg(not(feature = "postgres"))]
/// # fn main() {}
/// ```
pub fn insert_into<T>(target: T) -> IncompleteInsertStatement<T, Insert> {
    IncompleteInsertStatement::new(target, Insert)
}

/// Creates a bare select statement, with no from clause. Primarily used for
/// testing diesel itself, but likely useful for third party crates as well. The
/// given expressions must be selectable from anywhere.
pub fn select<T>(expression: T) -> Select<SelectStatement<()>, T>
where
    T: Expression,
    SelectStatement<()>: SelectDsl<T>,
{
    SelectStatement::simple(()).select(expression)
}

/// Creates a `REPLACE` statement.
///
/// If a constraint violation fails, the database will attempt to replace the
/// offending row instead. This function is only available with MySQL and
/// SQLite.
///
/// # Example
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # #[cfg(not(feature = "postgres"))]
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     use diesel::{insert_into, replace_into};
/// #
/// #     let conn = establish_connection();
/// #     conn.execute("DELETE FROM users").unwrap();
/// replace_into(users)
///     .values(&vec![
///         (id.eq(1), name.eq("Sean")),
///         (id.eq(2), name.eq("Tess")),
///     ])
///     .execute(&conn)
///     .unwrap();
///
/// replace_into(users)
///     .values((id.eq(1), name.eq("Jim")))
///     .execute(&conn)
///     .unwrap();
///
/// let names = users.select(name).order(id).load::<String>(&conn);
/// assert_eq!(Ok(vec!["Jim".into(), "Tess".into()]), names);
/// # }
/// # #[cfg(feature = "postgres")] fn main() {}
pub fn replace_into<T>(target: T) -> IncompleteInsertStatement<T, Replace> {
    IncompleteInsertStatement::new(target, Replace)
}

/// Construct a full SQL query using raw SQL.
///
/// This function exists for cases where a query needs to be written that is not
/// supported by the query builder. Unlike most queries in Diesel, `sql_query`
/// will deserialize its data by name, not by index. That means that you cannot
/// deserialize into a tuple, and structs which you deserialize from this
/// function will need to have `#[derive(QueryableByName)]`
///
/// # Safety
///
/// The implementation of `QueryableByName` will assume that columns with a
/// given name will have a certain type. The compiler will be unable to verify
/// that the given type is correct. If your query returns a column of an
/// unexpected type, the result may have the wrong value, or return an error.
///
/// # Example
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// #
/// # use schema::users;
/// #
/// # #[derive(QueryableByName, Debug, PartialEq)]
/// # #[table_name="users"]
/// # struct User {
/// #     id: i32,
/// #     name: String,
/// # }
/// #
/// # fn main() {
/// #     use diesel::sql_query;
/// #
/// #     let connection = establish_connection();
/// let users = sql_query("SELECT * FROM users ORDER BY id")
///     .load(&connection);
/// let expected_users = vec![
///     User { id: 1, name: "Sean".into() },
///     User { id: 2, name: "Tess".into() },
/// ];
/// assert_eq!(Ok(expected_users), users);
/// # }
/// ```
pub fn sql_query<T: Into<String>>(query: T) -> SqlQuery {
    SqlQuery::new(query.into())
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// 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,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std;
use std::collections::HashMap;
use std::env;
use std::fmt;
use std::fs::File;
use std::io::Read;
use std::iter::{FromIterator, IntoIterator};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::vec::IntoIter;

use crate::error::{Error, Result};
use crate::package::PackageIdent;

#[cfg(not(windows))]
const ENV_PATH_SEPARATOR: char = ':';

#[cfg(windows)]
const ENV_PATH_SEPARATOR: char = ';';

pub fn parse_key_value(s: &str) -> Result<HashMap<String, String>> {
    Ok(HashMap::from_iter(
        s.lines()
            .map(|l| l.splitn(2, '=').collect::<Vec<_>>())
            .map(|kv| (kv[0].to_string(), kv[1].to_string())),
    ))
}

#[derive(Clone, Debug, Serialize)]
pub struct Bind {
    pub service: String,
    pub exports: Vec<String>,
}

impl FromStr for Bind {
    type Err = Error;

    fn from_str(line: &str) -> Result<Self> {
        let mut parts = line.split('=');
        let service = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(service) => service.to_string(),
        };
        let exports = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(exports) => exports.split(' ').map(|t| t.to_string()).collect(),
        };
        Ok(Bind {
            service: service,
            exports: exports,
        })
    }
}

impl fmt::Display for Bind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let formatted_exports = self.exports.join(" ");
        write!(f, "[{}]={}", self.service, formatted_exports)
    }
}

/// Describes a bind mapping in a composite package.
#[derive(Debug, PartialEq)]
pub struct BindMapping {
    /// The name of the bind of a given service.
    pub bind_name: String,
    /// The identifier of the service within the composite package
    /// that should satisfy the named bind.
    pub satisfying_service: PackageIdent,
}

impl FromStr for BindMapping {
    type Err = Error;

    fn from_str(line: &str) -> Result<Self> {
        let mut parts = line.split(':');
        let bind_name = parts
            .next()
            .and_then(|bn| Some(bn.to_string()))
            .ok_or(Error::MetaFileBadBind)?;
        let satisfying_service = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(satisfying_service) => satisfying_service.parse()?,
        };
        Ok(BindMapping {
            bind_name: bind_name,
            satisfying_service: satisfying_service,
        })
    }
}

#[derive(Debug, PartialEq)]
pub struct EnvVar {
    pub key: String,
    pub value: String,
    pub separator: Option<char>,
}

#[derive(Debug)]
pub struct PkgEnv {
    inner: Vec<EnvVar>,
}

impl PkgEnv {
    pub fn new(values: HashMap<String, String>, separators: HashMap<String, String>) -> Self {
        Self {
            inner: values
                .into_iter()
                .map(|(key, value)| {
                    if let Some(sep) = separators.get(&key) {
                        EnvVar {
                            key: key,
                            value: value,
                            separator: sep.to_owned().pop(),
                        }
                    } else {
                        EnvVar {
                            key: key,
                            value: value,
                            separator: None,
                        }
                    }
                })
                .collect(),
        }
    }

    pub fn from_paths(paths: Vec<PathBuf>) -> Self {
        let p = env::join_paths(&paths).expect("Failed to build path string");
        Self {
            inner: vec![EnvVar {
                key: "PATH".to_string(),
                value: p
                    .into_string()
                    .expect("Failed to convert path to utf8 string"),
                separator: Some(ENV_PATH_SEPARATOR),
            }],
        }
    }

    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }
}

impl IntoIterator for PkgEnv {
    type Item = EnvVar;
    type IntoIter = IntoIter<EnvVar>;

    fn into_iter(self) -> Self::IntoIter {
        self.inner.into_iter()
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum MetaFile {
    BindMap, // Composite-only
    Binds,
    BindsOptional,
    CFlags,
    Config,
    Deps,
    Environment,
    EnvironmentSep,
    Exports,
    Exposes,
    Ident,
    LdFlags,
    LdRunPath,
    Manifest,
    Path,
    ResolvedServices, // Composite-only
    RuntimeEnvironment,
    RuntimePath,
    Services, // Composite-only
    SvcGroup,
    SvcUser,
    Target,
    TDeps,
    Type,
}

impl fmt::Display for MetaFile {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let id = match *self {
            MetaFile::BindMap => "BIND_MAP",
            MetaFile::Binds => "BINDS",
            MetaFile::BindsOptional => "BINDS_OPTIONAL",
            MetaFile::CFlags => "CFLAGS",
            MetaFile::Config => "default.toml",
            MetaFile::Deps => "DEPS",
            MetaFile::Environment => "ENVIRONMENT",
            MetaFile::EnvironmentSep => "ENVIRONMENT_SEP",
            MetaFile::Exports => "EXPORTS",
            MetaFile::Exposes => "EXPOSES",
            MetaFile::Ident => "IDENT",
            MetaFile::LdFlags => "LDFLAGS",
            MetaFile::LdRunPath => "LD_RUN_PATH",
            MetaFile::Manifest => "MANIFEST",
            MetaFile::Path => "PATH",
            MetaFile::ResolvedServices => "RESOLVED_SERVICES",
            MetaFile::RuntimeEnvironment => "RUNTIME_ENVIRONMENT",
            MetaFile::RuntimePath => "RUNTIME_PATH",
            MetaFile::Services => "SERVICES",
            MetaFile::SvcGroup => "SVC_GROUP",
            MetaFile::SvcUser => "SVC_USER",
            MetaFile::Target => "TARGET",
            MetaFile::TDeps => "TDEPS",
            MetaFile::Type => "TYPE",
        };
        write!(f, "{}", id)
    }
}

/// Read a metadata file from within a package directory if it exists
///
/// Returns the contents of the file
pub fn read_metafile<P: AsRef<Path>>(installed_path: P, file: &MetaFile) -> Result<String> {
    match existing_metafile(installed_path, file) {
        Some(filepath) => match File::open(&filepath) {
            Ok(mut f) => {
                let mut data = String::new();
                if f.read_to_string(&mut data).is_err() {
                    return Err(Error::MetaFileMalformed(file.clone()));
                }
                Ok(data.trim().to_string())
            }
            Err(e) => Err(Error::MetaFileIO(e)),
        },
        None => Err(Error::MetaFileNotFound(file.clone())),
    }
}

/// Returns the path to a specified MetaFile in an installed path if it exists.
///
/// Useful for fallback logic for dealing with older Habitat packages.
fn existing_metafile<P: AsRef<Path>>(installed_path: P, file: &MetaFile) -> Option<PathBuf> {
    let filepath = installed_path.as_ref().join(file.to_string());
    match std::fs::metadata(&filepath) {
        Ok(_) => Some(filepath),
        Err(_) => None,
    }
}

pub enum PackageType {
    Standalone,
    Composite,
}

impl fmt::Display for PackageType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let id = match *self {
            PackageType::Standalone => "Standalone",
            PackageType::Composite => "Composite",
        };
        write!(f, "{}", id)
    }
}

impl FromStr for PackageType {
    type Err = Error;

    fn from_str(value: &str) -> Result<Self> {
        match value.as_ref() {
            "standalone" => Ok(PackageType::Standalone),
            "composite" => Ok(PackageType::Composite),
            _ => Err(Error::InvalidPackageType(value.to_string())),
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::Write;
    use tempfile::Builder;

    static ENVIRONMENT: &str = r#"PATH=/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin
PYTHONPATH=/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages
"#;
    static ENVIRONMENT_SEP: &str = r#"PATH=:
PYTHONPATH=:
"#;
    static EXPORTS: &str = r#"status-port=status.port
port=front-end.port
"#;
    static PATH: &str = "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin";

    /// Write the given contents into the specified metadata file for
    /// the package.
    fn write_metafile(install_dir: &Path, metafile: MetaFile, content: &str) {
        let path = install_dir.join(metafile.to_string());
        let mut f = File::create(path).expect("Could not create metafile");
        f.write_all(content.as_bytes())
            .expect("Could not write metafile contents");
    }

    #[test]
    #[should_panic]
    fn malformed_file() {
        parse_key_value(&"PATH").unwrap();
    }

    #[test]
    fn can_parse_environment_file() {
        let mut m: HashMap<String, String> = HashMap::new();
        m.insert(
            "PATH".to_string(),
            "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string(),
        );
        m.insert(
            "PYTHONPATH".to_string(),
            "/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages"
                .to_string(),
        );

        assert_eq!(parse_key_value(&ENVIRONMENT).unwrap(), m);
    }

    #[test]
    fn can_parse_environment_sep_file() {
        let mut m: HashMap<String, String> = HashMap::new();
        m.insert("PATH".to_string(), ":".to_string());
        m.insert("PYTHONPATH".to_string(), ":".to_string());

        assert_eq!(parse_key_value(&ENVIRONMENT_SEP).unwrap(), m);
    }

    #[test]
    fn can_parse_exports_file() {
        let mut m: HashMap<String, String> = HashMap::new();
        m.insert("status-port".to_string(), "status.port".to_string());
        m.insert("port".to_string(), "front-end.port".to_string());

        assert_eq!(parse_key_value(&EXPORTS).unwrap(), m);
    }

    #[test]
    fn build_pkg_env() {
        let mut result = PkgEnv::new(
            parse_key_value(&ENVIRONMENT).unwrap(),
            parse_key_value(&ENVIRONMENT_SEP).unwrap(),
        )
        .into_iter()
        .collect::<Vec<_>>();
        // Sort the result by key, so we have a guarantee of order
        result.sort_by_key(|v| v.key.to_owned());

        let expected = vec![
            EnvVar {
                key: "PATH".to_string(),
                value: "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string(),
                separator: Some(':'),
            },
            EnvVar {
                key: "PYTHONPATH".to_string(),
                value:
                    "/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages"
                        .to_string(),
                separator: Some(':'),
            },
        ];

        assert_eq!(result, expected);
    }

    #[test]
    fn build_pkg_env_is_empty() {
        let result = PkgEnv::new(HashMap::new(), HashMap::new());
        assert!(result.is_empty());
    }

    #[test]
    fn build_pkg_env_from_path() {
        let result = PkgEnv::from_paths(vec![PathBuf::from(PATH)])
            .into_iter()
            .collect::<Vec<_>>();

        let expected = vec![EnvVar {
            key: "PATH".to_string(),
            value: "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string(),
            separator: Some(ENV_PATH_SEPARATOR),
        }];

        assert_eq!(result, expected);
    }

    #[test]
    fn can_parse_a_valid_bind_mapping() {
        let input = "my_bind:core/test";

        let output: BindMapping = input.parse().unwrap();

        assert_eq!(output.bind_name, "my_bind");
        assert_eq!(
            output.satisfying_service,
            PackageIdent::from_str("core/test").unwrap()
        );
    }

    #[test]
    fn fails_to_parse_a_bind_mapping_with_an_invalid_service_identifier() {
        let input = "my_bind:this-is-a-bad-identifier";
        let output = input.parse::<BindMapping>();
        assert!(output.is_err());
    }

    #[test]
    fn can_read_metafile() {
        let pkg_root = Builder::new().prefix("pkg-root").tempdir().unwrap();
        let install_dir = pkg_root.path();

        let expected = "core/foo=db:core/database";
        write_metafile(install_dir, MetaFile::Binds, expected);

        let bind = MetaFile::Binds;
        let bind_map = read_metafile(install_dir, &bind).unwrap();

        assert_eq!(expected, bind_map);
    }

    #[test]
    fn reading_a_non_existing_metafile_is_an_error() {
        let pkg_root = Builder::new().prefix("pkg-root").tempdir().unwrap();
        let install_dir = pkg_root.path();

        let bind = MetaFile::Binds;
        let bind_map = read_metafile(install_dir, &bind);

        assert!(bind_map.is_err());
    }

}
<commit_msg>Examine clippy::useless_asref<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// 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,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std;
use std::collections::HashMap;
use std::env;
use std::fmt;
use std::fs::File;
use std::io::Read;
use std::iter::{FromIterator, IntoIterator};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::vec::IntoIter;

use crate::error::{Error, Result};
use crate::package::PackageIdent;

#[cfg(not(windows))]
const ENV_PATH_SEPARATOR: char = ':';

#[cfg(windows)]
const ENV_PATH_SEPARATOR: char = ';';

pub fn parse_key_value(s: &str) -> Result<HashMap<String, String>> {
    Ok(HashMap::from_iter(
        s.lines()
            .map(|l| l.splitn(2, '=').collect::<Vec<_>>())
            .map(|kv| (kv[0].to_string(), kv[1].to_string())),
    ))
}

#[derive(Clone, Debug, Serialize)]
pub struct Bind {
    pub service: String,
    pub exports: Vec<String>,
}

impl FromStr for Bind {
    type Err = Error;

    fn from_str(line: &str) -> Result<Self> {
        let mut parts = line.split('=');
        let service = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(service) => service.to_string(),
        };
        let exports = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(exports) => exports.split(' ').map(|t| t.to_string()).collect(),
        };
        Ok(Bind {
            service: service,
            exports: exports,
        })
    }
}

impl fmt::Display for Bind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let formatted_exports = self.exports.join(" ");
        write!(f, "[{}]={}", self.service, formatted_exports)
    }
}

/// Describes a bind mapping in a composite package.
#[derive(Debug, PartialEq)]
pub struct BindMapping {
    /// The name of the bind of a given service.
    pub bind_name: String,
    /// The identifier of the service within the composite package
    /// that should satisfy the named bind.
    pub satisfying_service: PackageIdent,
}

impl FromStr for BindMapping {
    type Err = Error;

    fn from_str(line: &str) -> Result<Self> {
        let mut parts = line.split(':');
        let bind_name = parts
            .next()
            .and_then(|bn| Some(bn.to_string()))
            .ok_or(Error::MetaFileBadBind)?;
        let satisfying_service = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(satisfying_service) => satisfying_service.parse()?,
        };
        Ok(BindMapping {
            bind_name: bind_name,
            satisfying_service: satisfying_service,
        })
    }
}

#[derive(Debug, PartialEq)]
pub struct EnvVar {
    pub key: String,
    pub value: String,
    pub separator: Option<char>,
}

#[derive(Debug)]
pub struct PkgEnv {
    inner: Vec<EnvVar>,
}

impl PkgEnv {
    pub fn new(values: HashMap<String, String>, separators: HashMap<String, String>) -> Self {
        Self {
            inner: values
                .into_iter()
                .map(|(key, value)| {
                    if let Some(sep) = separators.get(&key) {
                        EnvVar {
                            key: key,
                            value: value,
                            separator: sep.to_owned().pop(),
                        }
                    } else {
                        EnvVar {
                            key: key,
                            value: value,
                            separator: None,
                        }
                    }
                })
                .collect(),
        }
    }

    pub fn from_paths(paths: Vec<PathBuf>) -> Self {
        let p = env::join_paths(&paths).expect("Failed to build path string");
        Self {
            inner: vec![EnvVar {
                key: "PATH".to_string(),
                value: p
                    .into_string()
                    .expect("Failed to convert path to utf8 string"),
                separator: Some(ENV_PATH_SEPARATOR),
            }],
        }
    }

    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }
}

impl IntoIterator for PkgEnv {
    type Item = EnvVar;
    type IntoIter = IntoIter<EnvVar>;

    fn into_iter(self) -> Self::IntoIter {
        self.inner.into_iter()
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum MetaFile {
    BindMap, // Composite-only
    Binds,
    BindsOptional,
    CFlags,
    Config,
    Deps,
    Environment,
    EnvironmentSep,
    Exports,
    Exposes,
    Ident,
    LdFlags,
    LdRunPath,
    Manifest,
    Path,
    ResolvedServices, // Composite-only
    RuntimeEnvironment,
    RuntimePath,
    Services, // Composite-only
    SvcGroup,
    SvcUser,
    Target,
    TDeps,
    Type,
}

impl fmt::Display for MetaFile {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let id = match *self {
            MetaFile::BindMap => "BIND_MAP",
            MetaFile::Binds => "BINDS",
            MetaFile::BindsOptional => "BINDS_OPTIONAL",
            MetaFile::CFlags => "CFLAGS",
            MetaFile::Config => "default.toml",
            MetaFile::Deps => "DEPS",
            MetaFile::Environment => "ENVIRONMENT",
            MetaFile::EnvironmentSep => "ENVIRONMENT_SEP",
            MetaFile::Exports => "EXPORTS",
            MetaFile::Exposes => "EXPOSES",
            MetaFile::Ident => "IDENT",
            MetaFile::LdFlags => "LDFLAGS",
            MetaFile::LdRunPath => "LD_RUN_PATH",
            MetaFile::Manifest => "MANIFEST",
            MetaFile::Path => "PATH",
            MetaFile::ResolvedServices => "RESOLVED_SERVICES",
            MetaFile::RuntimeEnvironment => "RUNTIME_ENVIRONMENT",
            MetaFile::RuntimePath => "RUNTIME_PATH",
            MetaFile::Services => "SERVICES",
            MetaFile::SvcGroup => "SVC_GROUP",
            MetaFile::SvcUser => "SVC_USER",
            MetaFile::Target => "TARGET",
            MetaFile::TDeps => "TDEPS",
            MetaFile::Type => "TYPE",
        };
        write!(f, "{}", id)
    }
}

/// Read a metadata file from within a package directory if it exists
///
/// Returns the contents of the file
pub fn read_metafile<P: AsRef<Path>>(installed_path: P, file: &MetaFile) -> Result<String> {
    match existing_metafile(installed_path, file) {
        Some(filepath) => match File::open(&filepath) {
            Ok(mut f) => {
                let mut data = String::new();
                if f.read_to_string(&mut data).is_err() {
                    return Err(Error::MetaFileMalformed(file.clone()));
                }
                Ok(data.trim().to_string())
            }
            Err(e) => Err(Error::MetaFileIO(e)),
        },
        None => Err(Error::MetaFileNotFound(file.clone())),
    }
}

/// Returns the path to a specified MetaFile in an installed path if it exists.
///
/// Useful for fallback logic for dealing with older Habitat packages.
fn existing_metafile<P: AsRef<Path>>(installed_path: P, file: &MetaFile) -> Option<PathBuf> {
    let filepath = installed_path.as_ref().join(file.to_string());
    match std::fs::metadata(&filepath) {
        Ok(_) => Some(filepath),
        Err(_) => None,
    }
}

pub enum PackageType {
    Standalone,
    Composite,
}

impl fmt::Display for PackageType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let id = match *self {
            PackageType::Standalone => "Standalone",
            PackageType::Composite => "Composite",
        };
        write!(f, "{}", id)
    }
}

impl FromStr for PackageType {
    type Err = Error;

    fn from_str(value: &str) -> Result<Self> {
        match value {
            "standalone" => Ok(PackageType::Standalone),
            "composite" => Ok(PackageType::Composite),
            _ => Err(Error::InvalidPackageType(value.to_string())),
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::Write;
    use tempfile::Builder;

    static ENVIRONMENT: &str = r#"PATH=/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin
PYTHONPATH=/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages
"#;
    static ENVIRONMENT_SEP: &str = r#"PATH=:
PYTHONPATH=:
"#;
    static EXPORTS: &str = r#"status-port=status.port
port=front-end.port
"#;
    static PATH: &str = "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin";

    /// Write the given contents into the specified metadata file for
    /// the package.
    fn write_metafile(install_dir: &Path, metafile: MetaFile, content: &str) {
        let path = install_dir.join(metafile.to_string());
        let mut f = File::create(path).expect("Could not create metafile");
        f.write_all(content.as_bytes())
            .expect("Could not write metafile contents");
    }

    #[test]
    #[should_panic]
    fn malformed_file() {
        parse_key_value(&"PATH").unwrap();
    }

    #[test]
    fn can_parse_environment_file() {
        let mut m: HashMap<String, String> = HashMap::new();
        m.insert(
            "PATH".to_string(),
            "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string(),
        );
        m.insert(
            "PYTHONPATH".to_string(),
            "/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages"
                .to_string(),
        );

        assert_eq!(parse_key_value(&ENVIRONMENT).unwrap(), m);
    }

    #[test]
    fn can_parse_environment_sep_file() {
        let mut m: HashMap<String, String> = HashMap::new();
        m.insert("PATH".to_string(), ":".to_string());
        m.insert("PYTHONPATH".to_string(), ":".to_string());

        assert_eq!(parse_key_value(&ENVIRONMENT_SEP).unwrap(), m);
    }

    #[test]
    fn can_parse_exports_file() {
        let mut m: HashMap<String, String> = HashMap::new();
        m.insert("status-port".to_string(), "status.port".to_string());
        m.insert("port".to_string(), "front-end.port".to_string());

        assert_eq!(parse_key_value(&EXPORTS).unwrap(), m);
    }

    #[test]
    fn build_pkg_env() {
        let mut result = PkgEnv::new(
            parse_key_value(&ENVIRONMENT).unwrap(),
            parse_key_value(&ENVIRONMENT_SEP).unwrap(),
        )
        .into_iter()
        .collect::<Vec<_>>();
        // Sort the result by key, so we have a guarantee of order
        result.sort_by_key(|v| v.key.to_owned());

        let expected = vec![
            EnvVar {
                key: "PATH".to_string(),
                value: "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string(),
                separator: Some(':'),
            },
            EnvVar {
                key: "PYTHONPATH".to_string(),
                value:
                    "/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages"
                        .to_string(),
                separator: Some(':'),
            },
        ];

        assert_eq!(result, expected);
    }

    #[test]
    fn build_pkg_env_is_empty() {
        let result = PkgEnv::new(HashMap::new(), HashMap::new());
        assert!(result.is_empty());
    }

    #[test]
    fn build_pkg_env_from_path() {
        let result = PkgEnv::from_paths(vec![PathBuf::from(PATH)])
            .into_iter()
            .collect::<Vec<_>>();

        let expected = vec![EnvVar {
            key: "PATH".to_string(),
            value: "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string(),
            separator: Some(ENV_PATH_SEPARATOR),
        }];

        assert_eq!(result, expected);
    }

    #[test]
    fn can_parse_a_valid_bind_mapping() {
        let input = "my_bind:core/test";

        let output: BindMapping = input.parse().unwrap();

        assert_eq!(output.bind_name, "my_bind");
        assert_eq!(
            output.satisfying_service,
            PackageIdent::from_str("core/test").unwrap()
        );
    }

    #[test]
    fn fails_to_parse_a_bind_mapping_with_an_invalid_service_identifier() {
        let input = "my_bind:this-is-a-bad-identifier";
        let output = input.parse::<BindMapping>();
        assert!(output.is_err());
    }

    #[test]
    fn can_read_metafile() {
        let pkg_root = Builder::new().prefix("pkg-root").tempdir().unwrap();
        let install_dir = pkg_root.path();

        let expected = "core/foo=db:core/database";
        write_metafile(install_dir, MetaFile::Binds, expected);

        let bind = MetaFile::Binds;
        let bind_map = read_metafile(install_dir, &bind).unwrap();

        assert_eq!(expected, bind_map);
    }

    #[test]
    fn reading_a_non_existing_metafile_is_an_error() {
        let pkg_root = Builder::new().prefix("pkg-root").tempdir().unwrap();
        let install_dir = pkg_root.path();

        let bind = MetaFile::Binds;
        let bind_map = read_metafile(install_dir, &bind);

        assert!(bind_map.is_err());
    }

}
<|endoftext|>