<commit_before>use std::collections::{Bitv, VecMap};
use std::iter::{count, repeat};

use alphabets::Alphabet;

/// Construct suffix array for given text.
///
/// # Arguments
///
/// * `text` - the text, ended by sentinel symbol (being lexicographically smallest)
///
/// # Example
///
/// ```
/// use bio::data_structures::suffix_array::get_suffix_array;
/// let text = b"GCCTTAACATTATTACGCCTA$";
/// let pos = get_suffix_array(text);
/// assert_eq!(pos, vec![
///     21, 20, 5, 6, 14, 11, 8, 7, 17, 1, 15, 18,
///     2, 16, 0, 19, 4, 13, 10, 3, 12, 9
/// ]);
/// ```
pub fn get_suffix_array(text: &[u8]) -> Vec<usize> {
    let n = text.len();
    let transformed_text = transform_text(text);
    if transformed_text[n-1] != 0 {
        panic!("Expecting extra sentinel symbol being lexicographically \
        smallest at the end of the text.");
    }

    let mut sais = SAIS::new(n);
    sais.construct(transformed_text.as_slice());

    sais.pos
}

/// Construct lcp array for given suffix array.
///
/// # Arguments
///
/// * `text` - the text ended by sentinel symbol (being lexicographically smallest)
/// * `pos` - the suffix array for the text
///
/// # Example
///
/// ```
/// use bio::data_structures::suffix_array::{get_suffix_array,get_lcp};
/// let text = b"GCCTTAACATTATTACGCCTA$";
/// let pos = get_suffix_array(text);
/// let lcp = get_lcp(text.as_slice(), pos.as_slice());
/// assert_eq!(
///     lcp,
///     vec![
///         None,    Some(0), Some(1), Some(1), Some(2), Some(1), Some(4),
///         Some(0), Some(1), Some(3), Some(1), Some(1), Some(2), Some(0),
///         Some(4), Some(0), Some(2), Some(2), Some(2), Some(1), Some(3),
///         Some(3)
///     ]
/// )
/// ```
pub fn get_lcp(text: &[u8], pos: &[usize]) -> Vec<Option<usize>> {
    assert!(text.len() == pos.len());
    let n = text.len();

    // provide the lexicographical rank for each suffix
    let mut rank: Vec<usize> = repeat(0).take(n).collect();
    for r in 0..n {
        rank[pos[r]] = r;
    }

    let mut lcp: Vec<Option<usize>> = repeat(None).take(n).collect();
    let mut l = 0us;
    for p in (0..n-1) {
        let r = rank[p];
        // since the sentinel has rank 0 and is excluded above,
        // we will never have a negative index below
        let pred = pos[r - 1];
        while
            pred + l < n &&
            p + l < n &&
            text[p + l] == text[pred + l] {
            l += 1;
        }
        lcp[r] = Some(l);
        l = if l > 0 {l - 1} else {0};
    }

    lcp
}

fn transform_text(text: &[u8]) -> Vec<usize> {
    let ranks = Alphabet::new(text).get_ranks();

    text.iter()
        .map(|&c| *ranks.get(&(c as usize)).unwrap())
        .collect()
}

struct SAIS {
    pos: Vec<usize>,
    lms_pos: Vec<usize>,
    bucket_sizes: VecMap<usize>,
    bucket_start: Vec<usize>,
    bucket_end: Vec<usize>
}

impl SAIS {
    fn new(n: usize) -> Self {
        SAIS {
            pos: Vec::with_capacity(n),
            lms_pos: Vec::with_capacity(n),
            bucket_sizes: VecMap::new(),
            bucket_start: Vec::with_capacity(n),
            bucket_end: Vec::with_capacity(n)
        }
    }

    fn init_bucket_start(&mut self, text: &[usize]) {
        self.bucket_sizes.clear();
        self.bucket_start.clear();

        for &c in text.iter() {
            if !self.bucket_sizes.contains_key(&c) {
                self.bucket_sizes.insert(c, 0);
            }
            *(self.bucket_sizes.get_mut(&c).unwrap()) += 1;
        }

        let mut sum = 0;
        for &size in self.bucket_sizes.values() {
            self.bucket_start.push(sum);
            sum += size;
        }
    }

    /// initialize pointers to the last element of the buckets
    fn init_bucket_end(&mut self, text: &[usize]) {
        self.bucket_end.clear();
        for &r in self.bucket_start[1..].iter() {
            self.bucket_end.push(r - 1);
        }
        self.bucket_end.push(text.len() - 1);
    }

    fn lms_substring_eq(
        &self,
        text: &[usize],
        pos_types: &PosTypes,
        i: usize,
        j: usize
    ) -> bool {
        for k in count(0us, 1us) {
            let lmsi = pos_types.is_lms_pos(i + k);
            let lmsj = pos_types.is_lms_pos(j + k);
            if text[i + k] != text[j + k] {
                // different symbols
                return false;
            }
            if lmsi != lmsj {
                // different length
                return false;
            }
            if k > 0 && lmsi && lmsj {
                // same symbols and same length
                return true;
            }
        }
        false
    }

    fn construct(&mut self, text: &[usize]) {
        let pos_types = PosTypes::new(text);
        self.calc_lms_pos(text, &pos_types);
        self.calc_pos(text, &pos_types);
    }

    /// Step 1 of the SAIS algorithm.
    fn calc_lms_pos(&mut self, text: &[usize], pos_types: &PosTypes) {
        let n = text.len();

        // collect LMS positions
        self.lms_pos.clear();
        for r in (0..n) {
            if pos_types.is_lms_pos(r) {
                self.lms_pos.push(r);
            }
        }

        // sort LMS substrings by applying step 2 with unsorted LMS positions
        self.calc_pos(text, pos_types);

        // obtain pre-sorted LMS positions from sorted LMS substrings
        self.lms_pos.clear();
        for &p in self.pos.iter() {
            if pos_types.is_lms_pos(p) {
                self.lms_pos.push(p);
            }
        }
        let lms_substring_count = self.lms_pos.len() - 1;

        // if less than 2 LMS substrings are present, no further sorting is needed
        if lms_substring_count > 1 {
            // sort LMS suffixes by recursively building SA on reduced text
            let mut reduced_text = Vec::with_capacity(self.lms_pos.len());
            let mut label = 0;
            reduced_text.push(label);
            let mut prev = self.lms_pos[0];
            for &p in self.lms_pos[1..].iter() {
                // choose same label if substrings are equal
                if !self.lms_substring_eq(
                    text, pos_types, prev, p
                ) {
                    label += 1;
                }
                reduced_text.push(label);
                prev = p;
            }

            // if we have less labels than substrings, we have to sort by recursion
            // because two or more substrings are equal
            if label + 1 < lms_substring_count {
                // backup lms_pos
                let lms_pos = self.lms_pos.clone();
                // recurse SA construction for reduced text
                self.construct(reduced_text.as_slice());
                // obtain sorted lms suffixes
                self.lms_pos.clear();
                for &p in self.pos.iter() {
                    self.lms_pos.push(lms_pos[p]);
                }
            }
        }
    }

    /// Step 2 of the SAIS algorithm.
    fn calc_pos(&mut self, text: &[usize], pos_types: &PosTypes) {
        let n = text.len();
        self.pos.clear();

        self.init_bucket_start(text);
        self.init_bucket_end(text);

        // init all positions as unknown (n-1 is max position)
        for _ in text.iter() {
            self.pos.push(n);
        }

        // insert LMS positions to the end of their buckets
        for &p in self.lms_pos.iter().rev() {
            let c = text[p];
            self.pos[self.bucket_end[c]] = p;
            self.bucket_end[c] -= 1;
        }

        // reset bucket ends
        self.init_bucket_end(text);

        // insert L-positions into buckets
        for r in (0..n) {
            let p = self.pos[r];
            // ignore undefined positions and the zero since it has no predecessor
            if p == n || p == 0 {
                continue;
            }
            let pred = p - 1;
            if pos_types.is_l_pos(pred) {
                let c = text[pred];
                self.pos[self.bucket_start[c]] = pred;
                self.bucket_start[c] += 1;
            }
        }

        // insert S-positions into buckets
        for r in (0..n).rev() {
            let p = self.pos[r];
            if p == 0 {
                continue;
            }
            let pred = p - 1;
            if pos_types.is_s_pos(pred) {
                let c = text[pred];
                self.pos[self.bucket_end[c]] = pred;
                self.bucket_end[c] -= 1;
            }
        }
    }
}

struct PosTypes {
    pos_types: Bitv,
}

impl PosTypes {
    /// Calculate the text position type.
    /// S-type marks suffixes being lexicographically smaller than their successor,
    /// L-type marks those being larger.
    /// This function fills a Bitv, with 1-bits denoting S-type
    /// and 0-bits denoting L-type.
    ///
    /// # Arguments
    ///
    /// * `text` - the text, ending with a sentinel.
    fn new(text: &[usize]) -> Self {
        let n = text.len();
        let mut pos_types = Bitv::from_elem(n, false);
        pos_types.set(n-1, true);

        for p in (0..n-1).rev() {
            if text[p] == text[p + 1] {
                // if the characters are equal, the next position determines
                // the lexicographical order
                let v = pos_types.get(p + 1).unwrap();
                pos_types.set(p, v);
            }
            else {
                pos_types.set(p, text[p] < text[p + 1]);
            }
        }

        PosTypes { pos_types: pos_types }
    }

    fn is_s_pos(&self, p: usize) -> bool {
        self.pos_types.get(p).unwrap()
    }

    fn is_l_pos(&self, p: usize) -> bool {
        !self.pos_types.get(p).unwrap()
    }

    fn is_lms_pos(&self, p: usize) -> bool {
        !(p == 0) && self.is_s_pos(p) && self.is_l_pos(p-1)
    }
}

#[cfg(test)]
mod tests {
    use test::Bencher;

    use super::*;
    use super::{PosTypes,SAIS,transform_text};
    use std::collections::Bitv;

    #[test]
    fn test_pos_types() {
        let text = transform_text(b"GCCTTAACATTATTACGCCTA$");
        let n = text.len();

        let pos_types = PosTypes::new(text.as_slice());
        let mut test = Bitv::from_bytes(&[0b01100110, 0b10010011,  0b01100100]);
        test.truncate(n);
        assert_eq!(pos_types.pos_types, test);
        let lms_pos: Vec<usize> = (0..n).filter(|&p| pos_types.is_lms_pos(p)).collect();
        assert_eq!(lms_pos, vec![1, 5, 8, 11, 14, 17, 21]);
    }

    #[test]
    fn test_buckets() {
        let text = transform_text(b"GCCTTAACATTATTACGCCTA$");
        let n = text.len();

        let mut sais = SAIS::new(n);
        sais.init_bucket_start(text.as_slice());
        assert_eq!(sais.bucket_start, vec![0, 1, 7, 13, 15]);
        sais.init_bucket_end(text.as_slice());
        assert_eq!(sais.bucket_end, vec![0, 6, 12, 14, 21]);
    }

    #[test]
    fn test_pos() {
        let text = transform_text(b"GCCTTAACATTATTACGCCTA$");
        let n = text.len();

        let mut sais = SAIS::new(n);
        let pos_types = PosTypes::new(text.as_slice());
        sais.lms_pos = vec![21, 5, 14, 8, 11, 17, 1];
        sais.calc_pos(text.as_slice(), &pos_types);
        assert_eq!(sais.pos, vec![
            21, 20, 5, 6, 14, 11, 8, 7, 17, 1, 15, 18,
            2, 16, 0, 19, 4, 13, 10, 3, 12, 9
        ]);
    }

    #[test]
    fn test_lms_pos() {
        let text = transform_text(b"GCCTTAACATTATTACGCCTA$");
        let n = text.len();

        let mut sais = SAIS::new(n);
        let pos_types = PosTypes::new(text.as_slice());
        sais.calc_lms_pos(text.as_slice(), &pos_types);
    }

    #[bench]
    fn bench_get_suffix_array(b: &mut Bencher) {
        b.iter(|| get_suffix_array(b"GCCTTAACATTATTACGCCTA$"));
    }
}
<commit_msg>Implemented BWT.<commit_after>use std::collections::{Bitv, VecMap};
use std::iter::{count, repeat};

use alphabets::Alphabet;

pub type SuffixArray = Vec<usize>;
pub type LCPArray = Vec<Option<usize>>;
pub type BWT = Vec<u8>;

/// Construct suffix array for given text.
///
/// # Arguments
///
/// * `text` - the text, ended by sentinel symbol (being lexicographically smallest)
///
/// # Example
///
/// ```
/// use bio::data_structures::suffix_array::get_suffix_array;
/// let text = b"GCCTTAACATTATTACGCCTA$";
/// let pos = get_suffix_array(text);
/// assert_eq!(pos, vec![
///     21, 20, 5, 6, 14, 11, 8, 7, 17, 1, 15, 18,
///     2, 16, 0, 19, 4, 13, 10, 3, 12, 9
/// ]);
/// ```
pub fn get_suffix_array(text: &[u8]) -> SuffixArray {
    let n = text.len();
    let transformed_text = transform_text(text);
    if transformed_text[n-1] != 0 {
        panic!("Expecting extra sentinel symbol being lexicographically \
        smallest at the end of the text.");
    }

    let mut sais = SAIS::new(n);
    sais.construct(transformed_text.as_slice());

    sais.pos
}

/// Construct lcp array for given suffix array.
///
/// # Arguments
///
/// * `text` - the text ended by sentinel symbol (being lexicographically smallest)
/// * `pos` - the suffix array for the text
///
/// # Example
///
/// ```
/// use bio::data_structures::suffix_array::{get_suffix_array,get_lcp};
/// let text = b"GCCTTAACATTATTACGCCTA$";
/// let pos = get_suffix_array(text);
/// let lcp = get_lcp(text.as_slice(), &pos);
/// assert_eq!(
///     lcp,
///     vec![
///         None,    Some(0), Some(1), Some(1), Some(2), Some(1), Some(4),
///         Some(0), Some(1), Some(3), Some(1), Some(1), Some(2), Some(0),
///         Some(4), Some(0), Some(2), Some(2), Some(2), Some(1), Some(3),
///         Some(3)
///     ]
/// )
/// ```
pub fn get_lcp(text: &[u8], pos: &SuffixArray) -> LCPArray {
    assert!(text.len() == pos.len());
    let n = text.len();

    // provide the lexicographical rank for each suffix
    let mut rank: Vec<usize> = repeat(0).take(n).collect();
    for r in 0..n {
        rank[pos[r]] = r;
    }

    let mut lcp: LCPArray = repeat(None).take(n).collect();
    let mut l = 0us;
    for p in (0..n-1) {
        let r = rank[p];
        // since the sentinel has rank 0 and is excluded above,
        // we will never have a negative index below
        let pred = pos[r - 1];
        while
            pred + l < n &&
            p + l < n &&
            text[p + l] == text[pred + l] {
            l += 1;
        }
        lcp[r] = Some(l);
        l = if l > 0 {l - 1} else {0};
    }

    lcp
}

/// Calculate Burrows-Wheeler-Transform of the given text.
///
/// # Arguments
///
/// * `text` - the text ended by sentinel symbol (being lexicographically smallest)
/// * `pos` - the suffix array for the text
///
/// # Example
///
/// ```
/// use bio::data_structures::suffix_array::{get_suffix_array,get_bwt};
/// let text = b"GCCTTAACATTATTACGCCTA$";
/// let pos = get_suffix_array(text);
/// let bwt = get_bwt(text, &pos);
/// assert_eq!(bwt, b"ATTATTCAGGACCC$CTTTCAA");
/// ```
pub fn get_bwt(text: &[u8], pos: &SuffixArray) -> BWT {
    assert!(text.len() == pos.len());
    let n = text.len();
    let mut bwt: BWT = repeat(0).take(n).collect();
    for r in 0..n {
        let p = pos[r];
        bwt[r] = if p > 0 {text[p-1]} else {text[n-1]};
    }

    bwt
}

fn transform_text(text: &[u8]) -> Vec<usize> {
    let ranks = Alphabet::new(text).get_ranks();

    text.iter()
        .map(|&c| *ranks.get(&(c as usize)).unwrap())
        .collect()
}

struct SAIS {
    pos: Vec<usize>,
    lms_pos: Vec<usize>,
    bucket_sizes: VecMap<usize>,
    bucket_start: Vec<usize>,
    bucket_end: Vec<usize>
}

impl SAIS {
    fn new(n: usize) -> Self {
        SAIS {
            pos: Vec::with_capacity(n),
            lms_pos: Vec::with_capacity(n),
            bucket_sizes: VecMap::new(),
            bucket_start: Vec::with_capacity(n),
            bucket_end: Vec::with_capacity(n)
        }
    }

    fn init_bucket_start(&mut self, text: &[usize]) {
        self.bucket_sizes.clear();
        self.bucket_start.clear();

        for &c in text.iter() {
            if !self.bucket_sizes.contains_key(&c) {
                self.bucket_sizes.insert(c, 0);
            }
            *(self.bucket_sizes.get_mut(&c).unwrap()) += 1;
        }

        let mut sum = 0;
        for &size in self.bucket_sizes.values() {
            self.bucket_start.push(sum);
            sum += size;
        }
    }

    /// initialize pointers to the last element of the buckets
    fn init_bucket_end(&mut self, text: &[usize]) {
        self.bucket_end.clear();
        for &r in self.bucket_start[1..].iter() {
            self.bucket_end.push(r - 1);
        }
        self.bucket_end.push(text.len() - 1);
    }

    fn lms_substring_eq(
        &self,
        text: &[usize],
        pos_types: &PosTypes,
        i: usize,
        j: usize
    ) -> bool {
        for k in count(0us, 1us) {
            let lmsi = pos_types.is_lms_pos(i + k);
            let lmsj = pos_types.is_lms_pos(j + k);
            if text[i + k] != text[j + k] {
                // different symbols
                return false;
            }
            if lmsi != lmsj {
                // different length
                return false;
            }
            if k > 0 && lmsi && lmsj {
                // same symbols and same length
                return true;
            }
        }
        false
    }

    fn construct(&mut self, text: &[usize]) {
        let pos_types = PosTypes::new(text);
        self.calc_lms_pos(text, &pos_types);
        self.calc_pos(text, &pos_types);
    }

    /// Step 1 of the SAIS algorithm.
    fn calc_lms_pos(&mut self, text: &[usize], pos_types: &PosTypes) {
        let n = text.len();

        // collect LMS positions
        self.lms_pos.clear();
        for r in (0..n) {
            if pos_types.is_lms_pos(r) {
                self.lms_pos.push(r);
            }
        }

        // sort LMS substrings by applying step 2 with unsorted LMS positions
        self.calc_pos(text, pos_types);

        // obtain pre-sorted LMS positions from sorted LMS substrings
        self.lms_pos.clear();
        for &p in self.pos.iter() {
            if pos_types.is_lms_pos(p) {
                self.lms_pos.push(p);
            }
        }
        let lms_substring_count = self.lms_pos.len() - 1;

        // if less than 2 LMS substrings are present, no further sorting is needed
        if lms_substring_count > 1 {
            // sort LMS suffixes by recursively building SA on reduced text
            let mut reduced_text = Vec::with_capacity(self.lms_pos.len());
            let mut label = 0;
            reduced_text.push(label);
            let mut prev = self.lms_pos[0];
            for &p in self.lms_pos[1..].iter() {
                // choose same label if substrings are equal
                if !self.lms_substring_eq(
                    text, pos_types, prev, p
                ) {
                    label += 1;
                }
                reduced_text.push(label);
                prev = p;
            }

            // if we have less labels than substrings, we have to sort by recursion
            // because two or more substrings are equal
            if label + 1 < lms_substring_count {
                // backup lms_pos
                let lms_pos = self.lms_pos.clone();
                // recurse SA construction for reduced text
                self.construct(reduced_text.as_slice());
                // obtain sorted lms suffixes
                self.lms_pos.clear();
                for &p in self.pos.iter() {
                    self.lms_pos.push(lms_pos[p]);
                }
            }
        }
    }

    /// Step 2 of the SAIS algorithm.
    fn calc_pos(&mut self, text: &[usize], pos_types: &PosTypes) {
        let n = text.len();
        self.pos.clear();

        self.init_bucket_start(text);
        self.init_bucket_end(text);

        // init all positions as unknown (n-1 is max position)
        for _ in text.iter() {
            self.pos.push(n);
        }

        // insert LMS positions to the end of their buckets
        for &p in self.lms_pos.iter().rev() {
            let c = text[p];
            self.pos[self.bucket_end[c]] = p;
            self.bucket_end[c] -= 1;
        }

        // reset bucket ends
        self.init_bucket_end(text);

        // insert L-positions into buckets
        for r in (0..n) {
            let p = self.pos[r];
            // ignore undefined positions and the zero since it has no predecessor
            if p == n || p == 0 {
                continue;
            }
            let pred = p - 1;
            if pos_types.is_l_pos(pred) {
                let c = text[pred];
                self.pos[self.bucket_start[c]] = pred;
                self.bucket_start[c] += 1;
            }
        }

        // insert S-positions into buckets
        for r in (0..n).rev() {
            let p = self.pos[r];
            if p == 0 {
                continue;
            }
            let pred = p - 1;
            if pos_types.is_s_pos(pred) {
                let c = text[pred];
                self.pos[self.bucket_end[c]] = pred;
                self.bucket_end[c] -= 1;
            }
        }
    }
}

struct PosTypes {
    pos_types: Bitv,
}

impl PosTypes {
    /// Calculate the text position type.
    /// S-type marks suffixes being lexicographically smaller than their successor,
    /// L-type marks those being larger.
    /// This function fills a Bitv, with 1-bits denoting S-type
    /// and 0-bits denoting L-type.
    ///
    /// # Arguments
    ///
    /// * `text` - the text, ending with a sentinel.
    fn new(text: &[usize]) -> Self {
        let n = text.len();
        let mut pos_types = Bitv::from_elem(n, false);
        pos_types.set(n-1, true);

        for p in (0..n-1).rev() {
            if text[p] == text[p + 1] {
                // if the characters are equal, the next position determines
                // the lexicographical order
                let v = pos_types.get(p + 1).unwrap();
                pos_types.set(p, v);
            }
            else {
                pos_types.set(p, text[p] < text[p + 1]);
            }
        }

        PosTypes { pos_types: pos_types }
    }

    fn is_s_pos(&self, p: usize) -> bool {
        self.pos_types.get(p).unwrap()
    }

    fn is_l_pos(&self, p: usize) -> bool {
        !self.pos_types.get(p).unwrap()
    }

    fn is_lms_pos(&self, p: usize) -> bool {
        !(p == 0) && self.is_s_pos(p) && self.is_l_pos(p-1)
    }
}

#[cfg(test)]
mod tests {
    use test::Bencher;

    use super::*;
    use super::{PosTypes,SAIS,transform_text};
    use std::collections::Bitv;

    #[test]
    fn test_pos_types() {
        let text = transform_text(b"GCCTTAACATTATTACGCCTA$");
        let n = text.len();

        let pos_types = PosTypes::new(text.as_slice());
        let mut test = Bitv::from_bytes(&[0b01100110, 0b10010011,  0b01100100]);
        test.truncate(n);
        assert_eq!(pos_types.pos_types, test);
        let lms_pos: Vec<usize> = (0..n).filter(|&p| pos_types.is_lms_pos(p)).collect();
        assert_eq!(lms_pos, vec![1, 5, 8, 11, 14, 17, 21]);
    }

    #[test]
    fn test_buckets() {
        let text = transform_text(b"GCCTTAACATTATTACGCCTA$");
        let n = text.len();

        let mut sais = SAIS::new(n);
        sais.init_bucket_start(text.as_slice());
        assert_eq!(sais.bucket_start, vec![0, 1, 7, 13, 15]);
        sais.init_bucket_end(text.as_slice());
        assert_eq!(sais.bucket_end, vec![0, 6, 12, 14, 21]);
    }

    #[test]
    fn test_pos() {
        let text = transform_text(b"GCCTTAACATTATTACGCCTA$");
        let n = text.len();

        let mut sais = SAIS::new(n);
        let pos_types = PosTypes::new(text.as_slice());
        sais.lms_pos = vec![21, 5, 14, 8, 11, 17, 1];
        sais.calc_pos(text.as_slice(), &pos_types);
        assert_eq!(sais.pos, vec![
            21, 20, 5, 6, 14, 11, 8, 7, 17, 1, 15, 18,
            2, 16, 0, 19, 4, 13, 10, 3, 12, 9
        ]);
    }

    #[test]
    fn test_lms_pos() {
        let text = transform_text(b"GCCTTAACATTATTACGCCTA$");
        let n = text.len();

        let mut sais = SAIS::new(n);
        let pos_types = PosTypes::new(text.as_slice());
        sais.calc_lms_pos(text.as_slice(), &pos_types);
    }

    #[bench]
    fn bench_get_suffix_array(b: &mut Bencher) {
        b.iter(|| get_suffix_array(b"GCCTTAACATTATTACGCCTA$"));
    }
}
<|endoftext|>


<commit_before>//! The `Default` trait for types which may have meaningful default values.

#![stable(feature = "rust1", since = "1.0.0")]

/// A trait for giving a type a useful default value.
///
/// Sometimes, you want to fall back to some kind of default value, and
/// don't particularly care what it is. This comes up often with `struct`s
/// that define a set of options:
///
/// ```
/// # #[allow(dead_code)]
/// struct SomeOptions {
///     foo: i32,
///     bar: f32,
/// }
/// ```
///
/// How can we define some default values? You can use `Default`:
///
/// ```
/// # #[allow(dead_code)]
/// #[derive(Default)]
/// struct SomeOptions {
///     foo: i32,
///     bar: f32,
/// }
///
/// fn main() {
///     let options: SomeOptions = Default::default();
/// }
/// ```
///
/// Now, you get all of the default values. Rust implements `Default` for various primitives types.
///
/// If you want to override a particular option, but still retain the other defaults:
///
/// ```
/// # #[allow(dead_code)]
/// # #[derive(Default)]
/// # struct SomeOptions {
/// #     foo: i32,
/// #     bar: f32,
/// # }
/// fn main() {
///     let options = SomeOptions { foo: 42, ..Default::default() };
/// }
/// ```
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all of the type's fields implement
/// `Default`. When `derive`d, it will use the default value for each field's type.
///
/// ## How can I implement `Default`?
///
/// Provides an implementation for the `default()` method that returns the value of
/// your type that should be the default:
///
/// ```
/// # #![allow(dead_code)]
/// enum Kind {
///     A,
///     B,
///     C,
/// }
///
/// impl Default for Kind {
///     fn default() -> Self { Kind::A }
/// }
/// ```
///
/// # Examples
///
/// ```
/// # #[allow(dead_code)]
/// #[derive(Default)]
/// struct SomeOptions {
///     foo: i32,
///     bar: f32,
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Default: Sized {
    /// Returns the "default value" for a type.
    ///
    /// Default values are often some kind of initial value, identity value, or anything else that
    /// may make sense as a default.
    ///
    /// # Examples
    ///
    /// Using built-in default values:
    ///
    /// ```
    /// let i: i8 = Default::default();
    /// let (x, y): (Option<String>, f64) = Default::default();
    /// let (a, b, (c, d)): (i32, u32, (bool, bool)) = Default::default();
    /// ```
    ///
    /// Making your own:
    ///
    /// ```
    /// # #[allow(dead_code)]
    /// enum Kind {
    ///     A,
    ///     B,
    ///     C,
    /// }
    ///
    /// impl Default for Kind {
    ///     fn default() -> Self { Kind::A }
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Self;
}

/// Derive macro generating an impl of the trait `Default`.
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro Default($item:item) {
    /* compiler built-in */
}

macro_rules! default_impl {
    ($t:ty, $v:expr, $doc:tt) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl Default for $t {
            #[inline]
            #[doc = $doc]
            fn default() -> $t { $v }
        }
    }
}

default_impl! { (), (), "Returns the default value of `()`" }
default_impl! { bool, false, "Returns the default value of `false`" }
default_impl! { char, '\x00', "Returns the default value of `\\x00`" }

default_impl! { usize, 0, "Returns the default value of `0`" }
default_impl! { u8, 0, "Returns the default value of `0`" }
default_impl! { u16, 0, "Returns the default value of `0`" }
default_impl! { u32, 0, "Returns the default value of `0`" }
default_impl! { u64, 0, "Returns the default value of `0`" }
default_impl! { u128, 0, "Returns the default value of `0`" }

default_impl! { isize, 0, "Returns the default value of `0`" }
default_impl! { i8, 0, "Returns the default value of `0`" }
default_impl! { i16, 0, "Returns the default value of `0`" }
default_impl! { i32, 0, "Returns the default value of `0`" }
default_impl! { i64, 0, "Returns the default value of `0`" }
default_impl! { i128, 0, "Returns the default value of `0`" }

default_impl! { f32, 0.0f32, "Returns the default value of `0.0`" }
default_impl! { f64, 0.0f64, "Returns the default value of `0.0`" }
<commit_msg>Rollup merge of #71225 - leocassarani:patch-1, r=jonas-schievink<commit_after>//! The `Default` trait for types which may have meaningful default values.

#![stable(feature = "rust1", since = "1.0.0")]

/// A trait for giving a type a useful default value.
///
/// Sometimes, you want to fall back to some kind of default value, and
/// don't particularly care what it is. This comes up often with `struct`s
/// that define a set of options:
///
/// ```
/// # #[allow(dead_code)]
/// struct SomeOptions {
///     foo: i32,
///     bar: f32,
/// }
/// ```
///
/// How can we define some default values? You can use `Default`:
///
/// ```
/// # #[allow(dead_code)]
/// #[derive(Default)]
/// struct SomeOptions {
///     foo: i32,
///     bar: f32,
/// }
///
/// fn main() {
///     let options: SomeOptions = Default::default();
/// }
/// ```
///
/// Now, you get all of the default values. Rust implements `Default` for various primitives types.
///
/// If you want to override a particular option, but still retain the other defaults:
///
/// ```
/// # #[allow(dead_code)]
/// # #[derive(Default)]
/// # struct SomeOptions {
/// #     foo: i32,
/// #     bar: f32,
/// # }
/// fn main() {
///     let options = SomeOptions { foo: 42, ..Default::default() };
/// }
/// ```
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all of the type's fields implement
/// `Default`. When `derive`d, it will use the default value for each field's type.
///
/// ## How can I implement `Default`?
///
/// Provide an implementation for the `default()` method that returns the value of
/// your type that should be the default:
///
/// ```
/// # #![allow(dead_code)]
/// enum Kind {
///     A,
///     B,
///     C,
/// }
///
/// impl Default for Kind {
///     fn default() -> Self { Kind::A }
/// }
/// ```
///
/// # Examples
///
/// ```
/// # #[allow(dead_code)]
/// #[derive(Default)]
/// struct SomeOptions {
///     foo: i32,
///     bar: f32,
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Default: Sized {
    /// Returns the "default value" for a type.
    ///
    /// Default values are often some kind of initial value, identity value, or anything else that
    /// may make sense as a default.
    ///
    /// # Examples
    ///
    /// Using built-in default values:
    ///
    /// ```
    /// let i: i8 = Default::default();
    /// let (x, y): (Option<String>, f64) = Default::default();
    /// let (a, b, (c, d)): (i32, u32, (bool, bool)) = Default::default();
    /// ```
    ///
    /// Making your own:
    ///
    /// ```
    /// # #[allow(dead_code)]
    /// enum Kind {
    ///     A,
    ///     B,
    ///     C,
    /// }
    ///
    /// impl Default for Kind {
    ///     fn default() -> Self { Kind::A }
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Self;
}

/// Derive macro generating an impl of the trait `Default`.
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro Default($item:item) {
    /* compiler built-in */
}

macro_rules! default_impl {
    ($t:ty, $v:expr, $doc:tt) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl Default for $t {
            #[inline]
            #[doc = $doc]
            fn default() -> $t { $v }
        }
    }
}

default_impl! { (), (), "Returns the default value of `()`" }
default_impl! { bool, false, "Returns the default value of `false`" }
default_impl! { char, '\x00', "Returns the default value of `\\x00`" }

default_impl! { usize, 0, "Returns the default value of `0`" }
default_impl! { u8, 0, "Returns the default value of `0`" }
default_impl! { u16, 0, "Returns the default value of `0`" }
default_impl! { u32, 0, "Returns the default value of `0`" }
default_impl! { u64, 0, "Returns the default value of `0`" }
default_impl! { u128, 0, "Returns the default value of `0`" }

default_impl! { isize, 0, "Returns the default value of `0`" }
default_impl! { i8, 0, "Returns the default value of `0`" }
default_impl! { i16, 0, "Returns the default value of `0`" }
default_impl! { i32, 0, "Returns the default value of `0`" }
default_impl! { i64, 0, "Returns the default value of `0`" }
default_impl! { i128, 0, "Returns the default value of `0`" }

default_impl! { f32, 0.0f32, "Returns the default value of `0.0`" }
default_impl! { f64, 0.0f64, "Returns the default value of `0.0`" }
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[test]
fn test_bool_from_str() {
    assert_eq!("true".parse().ok(), Some(true));
    assert_eq!("false".parse().ok(), Some(false));
    assert_eq!("not even a boolean".parse::<bool>().ok(), None);
}

fn check_contains_all_substrings(s: &str) {
    assert!(s.contains(""));
    for i in 0..s.len() {
        for j in range(i+1, s.len() + 1) {
            assert!(s.contains(&s[i..j]));
        }
    }
}

#[test]
fn strslice_issue_16589() {
    assert!("bananas".contains("nana"));

    // prior to the fix for #16589, x.contains("abcdabcd") returned false
    // test all substrings for good measure
    check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
}

#[test]
fn strslice_issue_16878() {
    assert!(!"1234567ah012345678901ah".contains("hah"));
    assert!(!"00abc01234567890123456789abc".contains("bcabc"));
}

#[test]
fn test_strslice_contains() {
    let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
    check_contains_all_substrings(x);
}

#[test]
fn test_rsplitn_char_iterator() {
    let data = "\nMäry häd ä little lämb\nLittle lämb\n";

    let mut split: Vec<&str> = data.rsplitn(3, ' ').collect();
    split.reverse();
    assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);

    let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == ' ').collect();
    split.reverse();
    assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);

    // Unicode
    let mut split: Vec<&str> = data.rsplitn(3, 'ä').collect();
    split.reverse();
    assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);

    let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == 'ä').collect();
    split.reverse();
    assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
}

#[test]
fn test_split_char_iterator() {
    let data = "\nMäry häd ä little lämb\nLittle lämb\n";

    let split: Vec<&str> = data.split(' ').collect();
    assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);

    let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
    rsplit.reverse();
    assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);

    let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
    assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);

    let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
    rsplit.reverse();
    assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);

    // Unicode
    let split: Vec<&str> = data.split('ä').collect();
    assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);

    let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
    rsplit.reverse();
    assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);

    let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
    assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);

    let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
    rsplit.reverse();
    assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
}

#[test]
fn test_rev_split_char_iterator_no_trailing() {
    let data = "\nMäry häd ä little lämb\nLittle lämb\n";

    let mut split: Vec<&str> = data.split('\n').rev().collect();
    split.reverse();
    assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);

    let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
    split.reverse();
    assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]);
}

#[test]
fn test_utf16_code_units() {
    use unicode::str::Utf16Encoder;
    assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
               vec![0xE9, 0xD83D, 0xDCA9])
}
<commit_msg>Added benchmarks for string pattern matching functions<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[test]
fn test_bool_from_str() {
    assert_eq!("true".parse().ok(), Some(true));
    assert_eq!("false".parse().ok(), Some(false));
    assert_eq!("not even a boolean".parse::<bool>().ok(), None);
}

fn check_contains_all_substrings(s: &str) {
    assert!(s.contains(""));
    for i in 0..s.len() {
        for j in range(i+1, s.len() + 1) {
            assert!(s.contains(&s[i..j]));
        }
    }
}

#[test]
fn strslice_issue_16589() {
    assert!("bananas".contains("nana"));

    // prior to the fix for #16589, x.contains("abcdabcd") returned false
    // test all substrings for good measure
    check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
}

#[test]
fn strslice_issue_16878() {
    assert!(!"1234567ah012345678901ah".contains("hah"));
    assert!(!"00abc01234567890123456789abc".contains("bcabc"));
}

#[test]
fn test_strslice_contains() {
    let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
    check_contains_all_substrings(x);
}

#[test]
fn test_rsplitn_char_iterator() {
    let data = "\nMäry häd ä little lämb\nLittle lämb\n";

    let mut split: Vec<&str> = data.rsplitn(3, ' ').collect();
    split.reverse();
    assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);

    let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == ' ').collect();
    split.reverse();
    assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);

    // Unicode
    let mut split: Vec<&str> = data.rsplitn(3, 'ä').collect();
    split.reverse();
    assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);

    let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == 'ä').collect();
    split.reverse();
    assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
}

#[test]
fn test_split_char_iterator() {
    let data = "\nMäry häd ä little lämb\nLittle lämb\n";

    let split: Vec<&str> = data.split(' ').collect();
    assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);

    let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
    rsplit.reverse();
    assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);

    let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
    assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);

    let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
    rsplit.reverse();
    assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);

    // Unicode
    let split: Vec<&str> = data.split('ä').collect();
    assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);

    let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
    rsplit.reverse();
    assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);

    let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
    assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);

    let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
    rsplit.reverse();
    assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
}

#[test]
fn test_rev_split_char_iterator_no_trailing() {
    let data = "\nMäry häd ä little lämb\nLittle lämb\n";

    let mut split: Vec<&str> = data.split('\n').rev().collect();
    split.reverse();
    assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);

    let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
    split.reverse();
    assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]);
}

#[test]
fn test_utf16_code_units() {
    use unicode::str::Utf16Encoder;
    assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
               vec![0xE9, 0xD83D, 0xDCA9])
}

// rm x86_64-unknown-linux-gnu/stage1/test/coretesttest-x86_64-unknown-linux-gnu; env PLEASE_BENCH=1 make check-stage1-coretest TESTNAME=str::bench

mod bench {
    macro_rules! make_test_inner {
        ($s:ident, $code:expr, $name:ident, $str:expr) => {
            #[bench]
            fn $name(bencher: &mut Bencher) {
                let mut $s = $str;
                black_box(&mut $s);
                bencher.iter(|| $code);
            }
        }
    }

    macro_rules! make_test {
        ($name:ident, $s:ident, $code:expr) => {
            mod $name {
                use test::Bencher;
                use test::black_box;

                // Short strings: 65 bytes each
                make_test_inner!($s, $code, short_ascii,
                    "Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!");
                make_test_inner!($s, $code, short_mixed,
                    "ศไทย中华Việt Nam; Mary had a little lamb, Little lam!");
                make_test_inner!($s, $code, short_pile_of_poo,
                    "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!");
                make_test_inner!($s, $code, long_lorem_ipsum,"\
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
tempus vel, gravida nec quam.

In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
interdum. Curabitur ut nisi justo.

Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
Aliquam sit amet placerat lorem.

Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
cursus accumsan.

Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
malesuada sollicitudin quam eu fermentum!");
            }
        }
    }

    make_test!(chars_count, s, s.chars().count());

    make_test!(contains_bang_str, s, s.contains("!"));
    make_test!(contains_bang_char, s, s.contains_char('!'));

    make_test!(match_indices_a_str, s, s.match_indices("a").count());

    make_test!(split_str_a_str, s, s.split_str("a").count());

    make_test!(trim_ascii_char, s, {
        use std::ascii::AsciiExt;
        s.trim_matches(|&mut: c: char| c.is_ascii())
    });
    make_test!(trim_left_ascii_char, s, {
        use std::ascii::AsciiExt;
        s.trim_left_matches(|&mut: c: char| c.is_ascii())
    });
    make_test!(trim_right_ascii_char, s, {
        use std::ascii::AsciiExt;
        s.trim_right_matches(|&mut: c: char| c.is_ascii())
    });

    make_test!(find_underscore_char, s, s.find('_'));
    make_test!(rfind_underscore_char, s, s.rfind('_'));
    make_test!(find_underscore_str, s, s.find_str("_"));

    make_test!(find_zzz_char, s, s.find('\u{1F4A4}'));
    make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
    make_test!(find_zzz_str, s, s.find_str("\u{1F4A4}"));

    make_test!(split_space_char, s, s.split(' ').count());
    make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());

    make_test!(splitn_space_char, s, s.splitn(10, ' ').count());
    make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count());

    make_test!(split_str_space_str, s, s.split_str(" ").count());
    make_test!(split_str_ad_str, s, s.split_str("ad").count());
}
<|endoftext|>


<commit_before>#![cfg(feature="std")]
#![cfg(test)]
use super::{Allocator, SliceWrapper};
use super::{AdvHasher, H5Sub, HQ7Sub,
            Struct1, BrotliHasherParams, H9Opts,
            CloneWithAlloc, AnyHasher, };
use ::alloc_stdlib::StandardAlloc;
static RANDOM_THEN_UNICODE: &'static [u8] = include_bytes!("../../../testdata/random_then_unicode");//&[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55];
#[cfg(feature="std")]
#[test]
fn test_bulk_store_range() {
  let params_hasher = BrotliHasherParams {
    type_: 5,
    block_bits: 6,
    bucket_bits: 15,
    num_last_distances_to_check:10,
    hash_len: 4,
    literal_byte_score: 540,
  };
  let block_size = 1u64 << params_hasher.block_bits;
  let bucket_size = 1u64 << params_hasher.bucket_bits;
  let mut alloc = StandardAlloc::default();
  let mut buckets = <StandardAlloc as Allocator<u32>>::alloc_cell(&mut alloc, (bucket_size * block_size) as usize);
  let mut num = <StandardAlloc as Allocator<u16>>::alloc_cell(&mut alloc, bucket_size as usize);

  let mut hasher_a = AdvHasher::<H5Sub, StandardAlloc>{
    buckets: buckets,
    h9_opts: H9Opts::new(&params_hasher),
    num: num,
    GetHasherCommon: Struct1 {
      params: params_hasher,
      is_prepared_: 1,
      dict_num_lookups: 0,
      dict_num_matches: 0,
    },
    specialization: H5Sub {
      hash_shift_: 32i32 - params_hasher.bucket_bits,
      bucket_size_: bucket_size as u32,
      block_bits_: params_hasher.block_bits as i32,
      block_mask_: block_size.wrapping_sub(1u64) as u32,
    }
  };
  buckets = <StandardAlloc as Allocator<u32>>::alloc_cell(&mut alloc, (bucket_size * block_size) as usize);
  num = <StandardAlloc as Allocator<u16>>::alloc_cell(&mut alloc, bucket_size as usize);
  let mut hasher_b = hasher_a.clone_with_alloc(&mut alloc);
  assert!(hasher_a == hasher_b);
  let mut hasher_c = AdvHasher::<HQ7Sub, StandardAlloc>{
    buckets: buckets,
    h9_opts: H9Opts::new(&params_hasher),
    num: num,
    GetHasherCommon: Struct1 {
      params: params_hasher,
      is_prepared_: 1,
      dict_num_lookups: 0,
      dict_num_matches: 0,
    },
    specialization: HQ7Sub {},
  };
  let mut hasher_d = hasher_c.clone_with_alloc(&mut alloc);
  assert!(hasher_d == hasher_c);
  hasher_a.BulkStoreRange(RANDOM_THEN_UNICODE, !0usize, 15, RANDOM_THEN_UNICODE.len() - 8);
  hasher_c.BulkStoreRange(RANDOM_THEN_UNICODE, !0usize, 15, RANDOM_THEN_UNICODE.len() - 8);
  for i in 15..RANDOM_THEN_UNICODE.len() - 8  {
    hasher_b.Store(RANDOM_THEN_UNICODE, !0usize, i);
    hasher_d.Store(RANDOM_THEN_UNICODE, !0usize, i);
  }
  assert_eq!(hasher_a.buckets.slice(), hasher_c.buckets.slice());
  assert_eq!(hasher_b.buckets.slice(), hasher_d.buckets.slice());
  assert_eq!(hasher_a.num.slice(), hasher_c.num.slice());
  assert_eq!(hasher_b.num.slice(), hasher_d.num.slice());
  assert_eq!(hasher_a.buckets.slice(), hasher_b.buckets.slice());
  assert_eq!(hasher_c.buckets.slice(), hasher_d.buckets.slice());
  assert_eq!(hasher_a.num.slice(), hasher_b.num.slice());
  assert_eq!(hasher_c.num.slice(), hasher_d.num.slice());
  assert!(hasher_a == hasher_b);
  assert!(hasher_d == hasher_c);
}
#[cfg(feature="std")]
#[test]
// does not use the fancy optimizations for q7
fn test_bulk_store_range_off_spec() {
  let params_hasher = BrotliHasherParams {
    type_: 5,
    block_bits: 6,
    bucket_bits: 15,
    num_last_distances_to_check:10,
    hash_len: 4,
    literal_byte_score: 540,
  };
  let block_size = 1u64 << params_hasher.block_bits;
  let bucket_size = 1u64 << params_hasher.bucket_bits;
  let mut alloc = StandardAlloc::default();
  let mut buckets = <StandardAlloc as Allocator<u32>>::alloc_cell(&mut alloc, (bucket_size * block_size) as usize);
  let mut num = <StandardAlloc as Allocator<u16>>::alloc_cell(&mut alloc, bucket_size as usize);

  let mut hasher_a = AdvHasher::<H5Sub, StandardAlloc>{
    buckets: buckets,
    h9_opts: H9Opts::new(&params_hasher),
    num: num,
    GetHasherCommon: Struct1 {
      params: params_hasher,
      is_prepared_: 1,
      dict_num_lookups: 0,
      dict_num_matches: 0,
    },
    specialization: H5Sub {
      hash_shift_: 32i32 - params_hasher.bucket_bits,
      bucket_size_: bucket_size as u32,
      block_bits_: params_hasher.block_bits as i32,
      block_mask_: block_size.wrapping_sub(1u64) as u32,
    }
  };
  buckets = <StandardAlloc as Allocator<u32>>::alloc_cell(&mut alloc, (bucket_size * block_size) as usize);
  num = <StandardAlloc as Allocator<u16>>::alloc_cell(&mut alloc, bucket_size as usize);
  let mut hasher_b = hasher_a.clone_with_alloc(&mut alloc);
  assert!(hasher_a == hasher_b);
  let mut hasher_c = AdvHasher::<HQ7Sub, StandardAlloc>{
    buckets: buckets,
    h9_opts: H9Opts::new(&params_hasher),
    num: num,
    GetHasherCommon: Struct1 {
      params: params_hasher,
      is_prepared_: 1,
      dict_num_lookups: 0,
      dict_num_matches: 0,
    },
    specialization: HQ7Sub {},
  };
  let mut hasher_d = hasher_c.clone_with_alloc(&mut alloc);
  assert!(hasher_d == hasher_c);
  hasher_a.BulkStoreRange(RANDOM_THEN_UNICODE, 0xfffffff, 15, RANDOM_THEN_UNICODE.len() - 8);
  hasher_c.BulkStoreRange(RANDOM_THEN_UNICODE, 0xfffffff, 15, RANDOM_THEN_UNICODE.len() - 8);
  for i in 15..RANDOM_THEN_UNICODE.len() - 8  {
    hasher_b.Store(RANDOM_THEN_UNICODE, 0xfffffff, i);
    hasher_d.Store(RANDOM_THEN_UNICODE, 0xfffffff, i);
  }
  assert_eq!(hasher_a.buckets.slice(), hasher_c.buckets.slice());
  assert_eq!(hasher_b.buckets.slice(), hasher_d.buckets.slice());
  assert_eq!(hasher_a.num.slice(), hasher_c.num.slice());
  assert_eq!(hasher_b.num.slice(), hasher_d.num.slice());
  assert!(hasher_a == hasher_b);
  assert!(hasher_d == hasher_c);
}
<commit_msg>rust 1.12 workaround<commit_after>#![cfg(feature="std")]
#![cfg(test)]
use enc::{Allocator, SliceWrapper};
use super::{AdvHasher, H5Sub, HQ7Sub,
            Struct1, BrotliHasherParams, H9Opts,
            CloneWithAlloc, AnyHasher, };
use ::alloc_stdlib::StandardAlloc;
static RANDOM_THEN_UNICODE: &'static [u8] = include_bytes!("../../../testdata/random_then_unicode");//&[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55];
#[cfg(feature="std")]
#[test]
fn test_bulk_store_range() {
  let params_hasher = BrotliHasherParams {
    type_: 5,
    block_bits: 6,
    bucket_bits: 15,
    num_last_distances_to_check:10,
    hash_len: 4,
    literal_byte_score: 540,
  };
  let block_size = 1u64 << params_hasher.block_bits;
  let bucket_size = 1u64 << params_hasher.bucket_bits;
  let mut alloc = StandardAlloc::default();
  let mut buckets = <StandardAlloc as Allocator<u32>>::alloc_cell(&mut alloc, (bucket_size * block_size) as usize);
  let mut num = <StandardAlloc as Allocator<u16>>::alloc_cell(&mut alloc, bucket_size as usize);

  let mut hasher_a = AdvHasher::<H5Sub, StandardAlloc>{
    buckets: buckets,
    h9_opts: H9Opts::new(&params_hasher),
    num: num,
    GetHasherCommon: Struct1 {
      params: params_hasher,
      is_prepared_: 1,
      dict_num_lookups: 0,
      dict_num_matches: 0,
    },
    specialization: H5Sub {
      hash_shift_: 32i32 - params_hasher.bucket_bits,
      bucket_size_: bucket_size as u32,
      block_bits_: params_hasher.block_bits as i32,
      block_mask_: block_size.wrapping_sub(1u64) as u32,
    }
  };
  buckets = <StandardAlloc as Allocator<u32>>::alloc_cell(&mut alloc, (bucket_size * block_size) as usize);
  num = <StandardAlloc as Allocator<u16>>::alloc_cell(&mut alloc, bucket_size as usize);
  let mut hasher_b = hasher_a.clone_with_alloc(&mut alloc);
  assert!(hasher_a == hasher_b);
  let mut hasher_c = AdvHasher::<HQ7Sub, StandardAlloc>{
    buckets: buckets,
    h9_opts: H9Opts::new(&params_hasher),
    num: num,
    GetHasherCommon: Struct1 {
      params: params_hasher,
      is_prepared_: 1,
      dict_num_lookups: 0,
      dict_num_matches: 0,
    },
    specialization: HQ7Sub {},
  };
  let mut hasher_d = hasher_c.clone_with_alloc(&mut alloc);
  assert!(hasher_d == hasher_c);
  hasher_a.BulkStoreRange(RANDOM_THEN_UNICODE, !0usize, 15, RANDOM_THEN_UNICODE.len() - 8);
  hasher_c.BulkStoreRange(RANDOM_THEN_UNICODE, !0usize, 15, RANDOM_THEN_UNICODE.len() - 8);
  for i in 15..RANDOM_THEN_UNICODE.len() - 8  {
    hasher_b.Store(RANDOM_THEN_UNICODE, !0usize, i);
    hasher_d.Store(RANDOM_THEN_UNICODE, !0usize, i);
  }
  assert_eq!(hasher_a.buckets.slice(), hasher_c.buckets.slice());
  assert_eq!(hasher_b.buckets.slice(), hasher_d.buckets.slice());
  assert_eq!(hasher_a.num.slice(), hasher_c.num.slice());
  assert_eq!(hasher_b.num.slice(), hasher_d.num.slice());
  assert_eq!(hasher_a.buckets.slice(), hasher_b.buckets.slice());
  assert_eq!(hasher_c.buckets.slice(), hasher_d.buckets.slice());
  assert_eq!(hasher_a.num.slice(), hasher_b.num.slice());
  assert_eq!(hasher_c.num.slice(), hasher_d.num.slice());
  assert!(hasher_a == hasher_b);
  assert!(hasher_d == hasher_c);
}
#[cfg(feature="std")]
#[test]
// does not use the fancy optimizations for q7
fn test_bulk_store_range_off_spec() {
  let params_hasher = BrotliHasherParams {
    type_: 5,
    block_bits: 6,
    bucket_bits: 15,
    num_last_distances_to_check:10,
    hash_len: 4,
    literal_byte_score: 540,
  };
  let block_size = 1u64 << params_hasher.block_bits;
  let bucket_size = 1u64 << params_hasher.bucket_bits;
  let mut alloc = StandardAlloc::default();
  let mut buckets = <StandardAlloc as Allocator<u32>>::alloc_cell(&mut alloc, (bucket_size * block_size) as usize);
  let mut num = <StandardAlloc as Allocator<u16>>::alloc_cell(&mut alloc, bucket_size as usize);

  let mut hasher_a = AdvHasher::<H5Sub, StandardAlloc>{
    buckets: buckets,
    h9_opts: H9Opts::new(&params_hasher),
    num: num,
    GetHasherCommon: Struct1 {
      params: params_hasher,
      is_prepared_: 1,
      dict_num_lookups: 0,
      dict_num_matches: 0,
    },
    specialization: H5Sub {
      hash_shift_: 32i32 - params_hasher.bucket_bits,
      bucket_size_: bucket_size as u32,
      block_bits_: params_hasher.block_bits as i32,
      block_mask_: block_size.wrapping_sub(1u64) as u32,
    }
  };
  buckets = <StandardAlloc as Allocator<u32>>::alloc_cell(&mut alloc, (bucket_size * block_size) as usize);
  num = <StandardAlloc as Allocator<u16>>::alloc_cell(&mut alloc, bucket_size as usize);
  let mut hasher_b = hasher_a.clone_with_alloc(&mut alloc);
  assert!(hasher_a == hasher_b);
  let mut hasher_c = AdvHasher::<HQ7Sub, StandardAlloc>{
    buckets: buckets,
    h9_opts: H9Opts::new(&params_hasher),
    num: num,
    GetHasherCommon: Struct1 {
      params: params_hasher,
      is_prepared_: 1,
      dict_num_lookups: 0,
      dict_num_matches: 0,
    },
    specialization: HQ7Sub {},
  };
  let mut hasher_d = hasher_c.clone_with_alloc(&mut alloc);
  assert!(hasher_d == hasher_c);
  hasher_a.BulkStoreRange(RANDOM_THEN_UNICODE, 0xfffffff, 15, RANDOM_THEN_UNICODE.len() - 8);
  hasher_c.BulkStoreRange(RANDOM_THEN_UNICODE, 0xfffffff, 15, RANDOM_THEN_UNICODE.len() - 8);
  for i in 15..RANDOM_THEN_UNICODE.len() - 8  {
    hasher_b.Store(RANDOM_THEN_UNICODE, 0xfffffff, i);
    hasher_d.Store(RANDOM_THEN_UNICODE, 0xfffffff, i);
  }
  assert_eq!(hasher_a.buckets.slice(), hasher_c.buckets.slice());
  assert_eq!(hasher_b.buckets.slice(), hasher_d.buckets.slice());
  assert_eq!(hasher_a.num.slice(), hasher_c.num.slice());
  assert_eq!(hasher_b.num.slice(), hasher_d.num.slice());
  assert!(hasher_a == hasher_b);
  assert!(hasher_d == hasher_c);
}
<|endoftext|>


<commit_before>use regex::Regex;

pub struct Entry {
    id: isize,
    content: String,
    pub status: String,
    pub color: Option<String>
}

impl Entry {
    pub fn new(id: isize, data: String) -> Entry {
        let expr    = regex!(r"(^\[(\w+)\]? (.*?) ?#?([:xdigit:]+)?$)?");
        let capture = expr.captures(data.as_slice()).unwrap();
        let status  = capture.at(2).unwrap_or("PENDING").to_string();
        let content = capture.at(3).unwrap_or(data.as_slice()).to_string();
        let color   = match capture.at(4) {
            Some(val) => Some(val.to_string()),
            None => None
        };

        Entry {
            id: id,
            content: content,
            status: status,
            color: color
        }
    }

    pub fn display(&self) -> String {
        format!("({}) {}", &self.id, &self.content)
    }
}<commit_msg>Remove unused import<commit_after>pub struct Entry {
    id: isize,
    content: String,
    pub status: String,
    pub color: Option<String>
}

impl Entry {
    pub fn new(id: isize, data: String) -> Entry {
        let expr    = regex!(r"(^\[(\w+)\]? (.*?) ?#?([:xdigit:]+)?$)?");
        let capture = expr.captures(data.as_slice()).unwrap();
        let status  = capture.at(2).unwrap_or("PENDING").to_string();
        let content = capture.at(3).unwrap_or(data.as_slice()).to_string();
        let color   = match capture.at(4) {
            Some(val) => Some(val.to_string()),
            None => None
        };

        Entry {
            id: id,
            content: content,
            status: status,
            color: color
        }
    }

    pub fn display(&self) -> String {
        format!("({}) {}", &self.id, &self.content)
    }
}<|endoftext|>


<commit_before>use std::fmt;

use super::opcode::*;

use num::FromPrimitive;

#[derive(Clone, Copy)]
pub struct Instruction(pub u32);

impl Instruction {
    #[inline(always)]
    pub fn opcode(&self) -> Opcode {
        let value = (self.0 >> 26) & 0b111111;
        Opcode::from_u32(value).unwrap_or_else(
            || panic!("Unrecognized instruction: {:#010x} (op: {:#08b})", self.0, value))
    }

    #[inline(always)]
    pub fn rs(&self) -> usize {
        ((self.0 >> 21) & 0b11111) as usize
    }

    #[inline(always)]
    pub fn rt(&self) -> usize {
        ((self.0 >> 16) & 0b11111) as usize
    }

    #[inline(always)]
    pub fn rd(&self) -> u32 {
        (self.0 >> 11) & 0b11111
    }

    #[inline(always)]
    pub fn sa(&self) -> u32 {
        (self.0 >> 6) & 0b11111
    }

    #[inline(always)]
    pub fn imm(&self) -> u32 {
        self.0 & 0xffff
    }

    #[inline(always)]
    pub fn imm_sign_extended(&self) -> u64 {
        (self.imm() as i16) as u64
    }

    #[inline(always)]
    pub fn offset(&self) -> u32 {
        self.imm()
    }

    #[inline(always)]
    pub fn offset_sign_extended(&self) -> u64 {
        (self.offset() as i16) as u64
    }

    #[inline(always)]
    pub fn special_op(&self) -> SpecialOpcode {
        let value = self.0 & 0b111111;
        SpecialOpcode::from_u32(value).unwrap_or_else(
            || panic!("Unrecognized special opcode: {:#010x} (op: {:#08b})", self.0, value))
    }
}

impl fmt::Debug for Instruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.opcode())
    }
}
<commit_msg>add special instructions to Debug trait impl<commit_after>use std::fmt;

use super::opcode::*;

use num::FromPrimitive;

#[derive(Clone, Copy)]
pub struct Instruction(pub u32);

impl Instruction {
    #[inline(always)]
    pub fn opcode(&self) -> Opcode {
        let value = (self.0 >> 26) & 0b111111;
        Opcode::from_u32(value).unwrap_or_else(
            || panic!("Unrecognized instruction: {:#010x} (op: {:#08b})", self.0, value))
    }

    #[inline(always)]
    pub fn rs(&self) -> usize {
        ((self.0 >> 21) & 0b11111) as usize
    }

    #[inline(always)]
    pub fn rt(&self) -> usize {
        ((self.0 >> 16) & 0b11111) as usize
    }

    #[inline(always)]
    pub fn rd(&self) -> u32 {
        (self.0 >> 11) & 0b11111
    }

    #[inline(always)]
    pub fn sa(&self) -> u32 {
        (self.0 >> 6) & 0b11111
    }

    #[inline(always)]
    pub fn imm(&self) -> u32 {
        self.0 & 0xffff
    }

    #[inline(always)]
    pub fn imm_sign_extended(&self) -> u64 {
        (self.imm() as i16) as u64
    }

    #[inline(always)]
    pub fn offset(&self) -> u32 {
        self.imm()
    }

    #[inline(always)]
    pub fn offset_sign_extended(&self) -> u64 {
        (self.offset() as i16) as u64
    }

    #[inline(always)]
    pub fn special_op(&self) -> SpecialOpcode {
        let value = self.0 & 0b111111;
        SpecialOpcode::from_u32(value).unwrap_or_else(
            || panic!("Unrecognized special opcode: {:#010x} (op: {:#08b})", self.0, value))
    }
}

impl fmt::Debug for Instruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.opcode() {
            Opcode::Special => write!(f, "{:?}", self.special_op()),
            _ => write!(f, "{:?}", self.opcode())
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::io::{Write, BufWriter};
use std::fs::File;
use std::path::{Path, PathBuf};

use ops::{Context, Unit};
use util::{CargoResult, internal};
use util::paths;
use ops::cargo_rustc::fingerprint;

fn render_filename<P: AsRef<Path>>(path: P, basedir: Option<&str>) -> CargoResult<String> {
    let path = path.as_ref();
    let relpath = match basedir {
        None => path,
        Some(base) => match path.strip_prefix(base) {
            Ok(relpath) => relpath,
            _ => path,
        }
    };
    relpath.to_str().ok_or_else(|| internal("path not utf-8")).map(|f| f.replace(" ", "\\ "))
}

fn add_deps_for_unit<'a, 'b>(
    deps: &mut HashSet<PathBuf>,
    context: &mut Context<'a, 'b>,
    unit: &Unit<'a>,
    visited: &mut HashSet<Unit<'a>>,
)
    -> CargoResult<()>
{
    if !visited.insert(*unit) {
        return Ok(());
    }

    // units representing the execution of a build script don't actually
    // generate a dep info file, so we just keep on going below
    if !unit.profile.run_custom_build {
        // Add dependencies from rustc dep-info output (stored in fingerprint directory)
        let dep_info_loc = fingerprint::dep_info_loc(context, unit);
        if let Some(paths) = fingerprint::parse_dep_info(unit.pkg, &dep_info_loc)? {
            for path in paths {
                deps.insert(path);
            }
        } else {
            debug!("can't find dep_info for {:?} {:?}",
                unit.pkg.package_id(), unit.profile);
            return Err(internal("dep_info missing"));
        }
    }

    // Add rerun-if-changed dependencies
    let key = (unit.pkg.package_id().clone(), unit.kind);
    if let Some(output) = context.build_state.outputs.lock().unwrap().get(&key) {
        for path in &output.rerun_if_changed {
            deps.insert(path.into());
        }
    }

    // Recursively traverse all transitive dependencies
    for dep_unit in &context.dep_targets(unit)? {
        let source_id = dep_unit.pkg.package_id().source_id();
        if source_id.is_path() {
            add_deps_for_unit(deps, context, dep_unit, visited)?;
        }
    }
    Ok(())
}

pub fn output_depinfo<'a, 'b>(context: &mut Context<'a, 'b>, unit: &Unit<'a>) -> CargoResult<()> {
    let mut deps = HashSet::new();
    let mut visited = HashSet::new();
    let success = add_deps_for_unit(&mut deps, context, unit, &mut visited).is_ok();
    let basedir_config = context.config.get_string("dep-info-basedir");
    let basedir_config_ok = basedir_config.is_ok();
    let basedir_val = basedir_config.unwrap_or(None).map(|s| s.val);
    let basedir_string = basedir_val.unwrap_or("".to_string());
    let basedir = if basedir_config_ok {
        Some(basedir_string.as_str())
    } else {
        None
    };
    for &(_, ref link_dst, _) in context.target_filenames(unit)?.iter() {
        if let Some(ref link_dst) = *link_dst {
            let output_path = link_dst.with_extension("d");
            if success {
                let mut outfile = BufWriter::new(File::create(output_path)?);
                let target_fn = render_filename(link_dst, basedir)?;
                write!(outfile, "{}:", target_fn)?;
                for dep in &deps {
                    write!(outfile, " {}", render_filename(dep, basedir)?)?;
                }
                writeln!(outfile, "")?;

            // dep-info generation failed, so delete output file. This will
            // usually cause the build system to always rerun the build
            // rule, which is correct if inefficient.
            } else if output_path.exists() {
                paths::remove_file(output_path)?;
            }
        }
    }
    Ok(())
}
<commit_msg>More idiomatic<commit_after>use std::collections::HashSet;
use std::io::{Write, BufWriter};
use std::fs::File;
use std::path::{Path, PathBuf};

use ops::{Context, Unit};
use util::{CargoResult, internal};
use util::paths;
use ops::cargo_rustc::fingerprint;

fn render_filename<P: AsRef<Path>>(path: P, basedir: Option<&str>) -> CargoResult<String> {
    let path = path.as_ref();
    let relpath = match basedir {
        None => path,
        Some(base) => match path.strip_prefix(base) {
            Ok(relpath) => relpath,
            _ => path,
        }
    };
    relpath.to_str().ok_or_else(|| internal("path not utf-8")).map(|f| f.replace(" ", "\\ "))
}

fn add_deps_for_unit<'a, 'b>(
    deps: &mut HashSet<PathBuf>,
    context: &mut Context<'a, 'b>,
    unit: &Unit<'a>,
    visited: &mut HashSet<Unit<'a>>,
)
    -> CargoResult<()>
{
    if !visited.insert(*unit) {
        return Ok(());
    }

    // units representing the execution of a build script don't actually
    // generate a dep info file, so we just keep on going below
    if !unit.profile.run_custom_build {
        // Add dependencies from rustc dep-info output (stored in fingerprint directory)
        let dep_info_loc = fingerprint::dep_info_loc(context, unit);
        if let Some(paths) = fingerprint::parse_dep_info(unit.pkg, &dep_info_loc)? {
            for path in paths {
                deps.insert(path);
            }
        } else {
            debug!("can't find dep_info for {:?} {:?}",
                unit.pkg.package_id(), unit.profile);
            return Err(internal("dep_info missing"));
        }
    }

    // Add rerun-if-changed dependencies
    let key = (unit.pkg.package_id().clone(), unit.kind);
    if let Some(output) = context.build_state.outputs.lock().unwrap().get(&key) {
        for path in &output.rerun_if_changed {
            deps.insert(path.into());
        }
    }

    // Recursively traverse all transitive dependencies
    for dep_unit in &context.dep_targets(unit)? {
        let source_id = dep_unit.pkg.package_id().source_id();
        if source_id.is_path() {
            add_deps_for_unit(deps, context, dep_unit, visited)?;
        }
    }
    Ok(())
}

pub fn output_depinfo<'a, 'b>(context: &mut Context<'a, 'b>, unit: &Unit<'a>) -> CargoResult<()> {
    let mut deps = HashSet::new();
    let mut visited = HashSet::new();
    let success = add_deps_for_unit(&mut deps, context, unit, &mut visited).is_ok();
    let basedir_string;
    let basedir = match context.config.get_string("dep-info-basedir") {
        Ok(config) => {
            match config {
                Some(value) => {
                    basedir_string = value.val;
                    Some(basedir_string.as_str())
                }
                None => None,
            }
        },
        _ => None
    };
    for &(_, ref link_dst, _) in context.target_filenames(unit)?.iter() {
        if let Some(ref link_dst) = *link_dst {
            let output_path = link_dst.with_extension("d");
            if success {
                let mut outfile = BufWriter::new(File::create(output_path)?);
                let target_fn = render_filename(link_dst, basedir)?;
                write!(outfile, "{}:", target_fn)?;
                for dep in &deps {
                    write!(outfile, " {}", render_filename(dep, basedir)?)?;
                }
                writeln!(outfile, "")?;

            // dep-info generation failed, so delete output file. This will
            // usually cause the build system to always rerun the build
            // rule, which is correct if inefficient.
            } else if output_path.exists() {
                paths::remove_file(output_path)?;
            }
        }
    }
    Ok(())
}
<|endoftext|>


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

// Methods that are shared by the cache tier and the data tier.

use std::collections::HashMap;

use devicemapper::Device;

use crate::{
    engine::{
        strat_engine::{
            backstore::blockdevmgr::{BlkDevSegment, Segment},
            serde_structs::BaseDevSave,
        },
        types::DevUuid,
    },
    stratis::{ErrorEnum, StratisError, StratisResult},
};

/// Given a function that translates a Stratis UUID to a device
/// number, and some metadata that describes a particular segment within
/// a device by means of its Stratis UUID, and its start and offset w/in the
/// device, return the corresponding BlkDevSegment structure.
// This method necessarily takes a reference to a Box because it receives
// the value from a function, and there is no other way for the function to
// be returned from a closure.
// In future, it may be possible to address this better with FnBox.
#[allow(clippy::borrowed_box)]
pub fn metadata_to_segment(
    uuid_to_devno: &HashMap<DevUuid, Device>,
    base_dev_save: &BaseDevSave,
) -> StratisResult<BlkDevSegment> {
    let parent = base_dev_save.parent;
    uuid_to_devno
        .get(&parent)
        .ok_or_else(|| {
            StratisError::Engine(
                ErrorEnum::NotFound,
                format!(
                    "No block device corresponding to stratisd UUID {:?} found",
                    &parent
                ),
            )
        })
        .map(|device| {
            BlkDevSegment::new(
                parent,
                Segment::new(*device, base_dev_save.start, base_dev_save.length),
            )
        })
}

/// Append the second list of BlkDevSegments to the first, or if the last
/// segment of the first argument is adjacent to the first segment of the
/// second argument, merge those two together.
/// Postcondition: left.len() + right.len() - 1 <= result.len()
/// Postcondition: result.len() <= left.len() + right.len()
// FIXME: There is a method that duplicates this algorithm called
// coalesce_segs. These methods should either be unified into a single method
// OR one should go away entirely in solution to:
// https://github.com/stratis-storage/stratisd/issues/762.
pub fn coalesce_blkdevsegs(left: &[BlkDevSegment], right: &[BlkDevSegment]) -> Vec<BlkDevSegment> {
    if left.is_empty() {
        return right.to_vec();
    }
    if right.is_empty() {
        return left.to_vec();
    }

    let mut segments = Vec::with_capacity(left.len() + right.len());
    segments.extend_from_slice(left);

    // Last existing and first new may be contiguous.
    let coalesced = {
        let right_first = right.first().expect("!right.is_empty()");
        let left_last = segments.last_mut().expect("!left.is_empty()");
        if left_last.uuid == right_first.uuid
            && (left_last.segment.start + left_last.segment.length == right_first.segment.start)
        {
            left_last.segment.length += right_first.segment.length;
            true
        } else {
            false
        }
    };

    if coalesced {
        segments.extend_from_slice(&right[1..]);
    } else {
        segments.extend_from_slice(right);
    }
    segments
}
<commit_msg>Remove a borrowed-box clippy allow<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Methods that are shared by the cache tier and the data tier.

use std::collections::HashMap;

use devicemapper::Device;

use crate::{
    engine::{
        strat_engine::{
            backstore::blockdevmgr::{BlkDevSegment, Segment},
            serde_structs::BaseDevSave,
        },
        types::DevUuid,
    },
    stratis::{ErrorEnum, StratisError, StratisResult},
};

/// Given a function that translates a Stratis UUID to a device
/// number, and some metadata that describes a particular segment within
/// a device by means of its Stratis UUID, and its start and offset w/in the
/// device, return the corresponding BlkDevSegment structure.
// This method necessarily takes a reference to a Box because it receives
// the value from a function, and there is no other way for the function to
// be returned from a closure.
// In future, it may be possible to address this better with FnBox.
pub fn metadata_to_segment(
    uuid_to_devno: &HashMap<DevUuid, Device>,
    base_dev_save: &BaseDevSave,
) -> StratisResult<BlkDevSegment> {
    let parent = base_dev_save.parent;
    uuid_to_devno
        .get(&parent)
        .ok_or_else(|| {
            StratisError::Engine(
                ErrorEnum::NotFound,
                format!(
                    "No block device corresponding to stratisd UUID {:?} found",
                    &parent
                ),
            )
        })
        .map(|device| {
            BlkDevSegment::new(
                parent,
                Segment::new(*device, base_dev_save.start, base_dev_save.length),
            )
        })
}

/// Append the second list of BlkDevSegments to the first, or if the last
/// segment of the first argument is adjacent to the first segment of the
/// second argument, merge those two together.
/// Postcondition: left.len() + right.len() - 1 <= result.len()
/// Postcondition: result.len() <= left.len() + right.len()
// FIXME: There is a method that duplicates this algorithm called
// coalesce_segs. These methods should either be unified into a single method
// OR one should go away entirely in solution to:
// https://github.com/stratis-storage/stratisd/issues/762.
pub fn coalesce_blkdevsegs(left: &[BlkDevSegment], right: &[BlkDevSegment]) -> Vec<BlkDevSegment> {
    if left.is_empty() {
        return right.to_vec();
    }
    if right.is_empty() {
        return left.to_vec();
    }

    let mut segments = Vec::with_capacity(left.len() + right.len());
    segments.extend_from_slice(left);

    // Last existing and first new may be contiguous.
    let coalesced = {
        let right_first = right.first().expect("!right.is_empty()");
        let left_last = segments.last_mut().expect("!left.is_empty()");
        if left_last.uuid == right_first.uuid
            && (left_last.segment.start + left_last.segment.length == right_first.segment.start)
        {
            left_last.segment.length += right_first.segment.length;
            true
        } else {
            false
        }
    };

    if coalesced {
        segments.extend_from_slice(&right[1..]);
    } else {
        segments.extend_from_slice(right);
    }
    segments
}
<|endoftext|>


<commit_before>use thiserror::Error;
use url::{self, Url};

#[derive(Debug, Error)]
pub enum ValidationError {
    #[error("the URL is not http(s): {0}")]
    NotHttps(String),
    #[error("the URL could not be parsed: {0}")]
    InvalidUrl(#[from] url::ParseError),
    #[error("the URL must not contain a username or password: {0}")]
    UserinfoPresent(Url),
    #[error("parsing and re-serializing the URL changed its representation (check for unnecessary information like default ports): {0}")]
    InconsistentSerialization(Url),
    #[error("the URL contains an invalid port: {0}")]
    InvalidPort(Url),
}

/// Test that a `redirect_uri` is valid. Returns the parsed `Url` if successful.
pub fn parse_redirect_uri(input: &str, param: &str) -> Result<Url, ValidationError> {
    if !input.starts_with("http://") && !input.starts_with("https://") {
        return Err(ValidationError::NotHttps(param.to_owned()));
    }

    let url = Url::parse(input)?;
    if url.username() != "" || url.password().is_some() {
        return Err(ValidationError::UserinfoPresent(url));
    }
    if url.port() == Some(0) {
        return Err(ValidationError::InvalidPort(url));
    }

    // Make sure the input origin matches the serialized origin.
    let origin = url.origin().ascii_serialization();
    if !input.starts_with(&origin) {
        return Err(ValidationError::InconsistentSerialization(url));
    }
    match input.as_bytes().get(origin.len()) {
        Some(&b'/') | None => {}
        _ => return Err(ValidationError::InconsistentSerialization(url)),
    }

    Ok(url)
}

/// Test that a OpenID Connect endpoint is valid.
///
/// This method is more tolerant than `parse_redirect_uri`, because we're in control of all
/// validation on the identity provider side. Note that this method also assumes the scheme was
/// already checked.
///
/// Returns the origin if successful.
pub fn parse_oidc_href(input: &Url) -> Option<String> {
    if input.port() == Some(0) {
        return None;
    }

    // Simple check to see if it's just an origin.
    // The input should be the same, with only a trailing slash.
    let origin = input.origin().ascii_serialization();
    if input.as_str().len() != origin.len() + 1 {
        return None;
    }

    Some(origin)
}

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

    #[test]
    fn valid_redirect_uris() {
        for uri in &[
            // HTTP
            "http://example.com",
            "http://localhost",
            "http://127.0.0.1",
            // HTTPS
            "https://example.com",
            "https://localhost",
            "https://127.0.0.1",
            // Non-default ports
            "http://example.com:8080",
            "http://127.0.0.1:8080",
            "http://example.com:443",
            "https://example.com:80",
            // Paths, query strings, and fragments
            "http://example.com:8080/path?foo=bar#baz",
            "http://example.com:8080/?foo=bar#baz",
            "http://example.com:8080/#baz",
            "http://example.com:8080/path#baz",
            "http://example.com:8080/path?foo=bar",
        ] {
            if let Err(err) = parse_redirect_uri(uri, "input") {
                panic!(
                    "unexpectedly rejected uri: {}. Reported: {}",
                    uri, err
                )
            }
        }
    }

    #[test]
    fn invalid_redirect_uris() {
        for uri in &[
            // Incomplete strings
            "",
            "/",
            "/index.html",
            // Other or missing schemes
            "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",
            "ws://example.com",
            "//example.com",
            // Opaque data
            "http:example.com",
            // Redundant default ports
            "http://example.com:80",
            "https://example.com:443",
            // Userinfo
            "http://user:pass@example.com",
            "http://user@example.com",
            "http://@example.com",
            // Missing host
            "http://",
            "http:///path",
            "http://:8080",
            "http://:8080/path",
            // Invalid ports
            "http://example.com:0",
            "http://example.com:65536",
            // Invalid IPv6 literals
            "http://::1",
            "http://::1:8080",
            // Weird strings
            "http://example.com:8080:8080",
            "http://:8080:8080",
            "http://»",
        ] {
            if parse_redirect_uri(uri, "input").is_ok() {
                panic!("did not reject uri: {}", uri)
            }
        }
    }

    #[test]
    fn valid_oidc_endpoints() {
        for uri in &[
            // HTTP
            "http://example.com",
            "http://localhost",
            "http://127.0.0.1",
            // HTTPS
            "https://example.com",
            "https://localhost",
            "https://127.0.0.1",
            // Odd notations
            "http:example.com",
            "http://@example.com",
            // Redundant default ports
            "http://example.com:80",
            "https://example.com:443",
            // Non-default ports
            "http://example.com:8080",
            "http://127.0.0.1:8080",
            "http://example.com:443",
            "https://example.com:80",
        ] {
            let uri = uri.parse().expect("could not parse a test uri");
            if parse_oidc_href(&uri).is_none() {
                panic!("unexpectedly rejected uri: {}", uri)
            }
        }
    }

    #[test]
    fn invalid_oidc_endpoints() {
        for uri in &[
            // Userinfo
            "http://user:pass@example.com",
            "http://user@example.com",
            // Paths, query strings, and fragments
            "http://example.com:8080/path?foo=bar#baz",
            "http://example.com:8080/?foo=bar#baz",
            "http://example.com:8080/#baz",
            "http://example.com:8080/path#baz",
            "http://example.com:8080/path?foo=bar",
            // Invalid ports
            "http://example.com:0",
        ] {
            println!("{}", uri);
            let uri = uri.parse().expect("could not parse a test uri");
            if parse_oidc_href(&uri).is_some() {
                panic!("did not reject uri: {}", uri)
            }
        }
    }
}
<commit_msg>Run rustfmt<commit_after>use thiserror::Error;
use url::{self, Url};

#[derive(Debug, Error)]
pub enum ValidationError {
    #[error("the URL is not http(s): {0}")]
    NotHttps(String),
    #[error("the URL could not be parsed: {0}")]
    InvalidUrl(#[from] url::ParseError),
    #[error("the URL must not contain a username or password: {0}")]
    UserinfoPresent(Url),
    #[error("parsing and re-serializing the URL changed its representation (check for unnecessary information like default ports): {0}")]
    InconsistentSerialization(Url),
    #[error("the URL contains an invalid port: {0}")]
    InvalidPort(Url),
}

/// Test that a `redirect_uri` is valid. Returns the parsed `Url` if successful.
pub fn parse_redirect_uri(input: &str, param: &str) -> Result<Url, ValidationError> {
    if !input.starts_with("http://") && !input.starts_with("https://") {
        return Err(ValidationError::NotHttps(param.to_owned()));
    }

    let url = Url::parse(input)?;
    if url.username() != "" || url.password().is_some() {
        return Err(ValidationError::UserinfoPresent(url));
    }
    if url.port() == Some(0) {
        return Err(ValidationError::InvalidPort(url));
    }

    // Make sure the input origin matches the serialized origin.
    let origin = url.origin().ascii_serialization();
    if !input.starts_with(&origin) {
        return Err(ValidationError::InconsistentSerialization(url));
    }
    match input.as_bytes().get(origin.len()) {
        Some(&b'/') | None => {}
        _ => return Err(ValidationError::InconsistentSerialization(url)),
    }

    Ok(url)
}

/// Test that a OpenID Connect endpoint is valid.
///
/// This method is more tolerant than `parse_redirect_uri`, because we're in control of all
/// validation on the identity provider side. Note that this method also assumes the scheme was
/// already checked.
///
/// Returns the origin if successful.
pub fn parse_oidc_href(input: &Url) -> Option<String> {
    if input.port() == Some(0) {
        return None;
    }

    // Simple check to see if it's just an origin.
    // The input should be the same, with only a trailing slash.
    let origin = input.origin().ascii_serialization();
    if input.as_str().len() != origin.len() + 1 {
        return None;
    }

    Some(origin)
}

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

    #[test]
    fn valid_redirect_uris() {
        for uri in &[
            // HTTP
            "http://example.com",
            "http://localhost",
            "http://127.0.0.1",
            // HTTPS
            "https://example.com",
            "https://localhost",
            "https://127.0.0.1",
            // Non-default ports
            "http://example.com:8080",
            "http://127.0.0.1:8080",
            "http://example.com:443",
            "https://example.com:80",
            // Paths, query strings, and fragments
            "http://example.com:8080/path?foo=bar#baz",
            "http://example.com:8080/?foo=bar#baz",
            "http://example.com:8080/#baz",
            "http://example.com:8080/path#baz",
            "http://example.com:8080/path?foo=bar",
        ] {
            if let Err(err) = parse_redirect_uri(uri, "input") {
                panic!("unexpectedly rejected uri: {}. Reported: {}", uri, err)
            }
        }
    }

    #[test]
    fn invalid_redirect_uris() {
        for uri in &[
            // Incomplete strings
            "",
            "/",
            "/index.html",
            // Other or missing schemes
            "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",
            "ws://example.com",
            "//example.com",
            // Opaque data
            "http:example.com",
            // Redundant default ports
            "http://example.com:80",
            "https://example.com:443",
            // Userinfo
            "http://user:pass@example.com",
            "http://user@example.com",
            "http://@example.com",
            // Missing host
            "http://",
            "http:///path",
            "http://:8080",
            "http://:8080/path",
            // Invalid ports
            "http://example.com:0",
            "http://example.com:65536",
            // Invalid IPv6 literals
            "http://::1",
            "http://::1:8080",
            // Weird strings
            "http://example.com:8080:8080",
            "http://:8080:8080",
            "http://»",
        ] {
            if parse_redirect_uri(uri, "input").is_ok() {
                panic!("did not reject uri: {}", uri)
            }
        }
    }

    #[test]
    fn valid_oidc_endpoints() {
        for uri in &[
            // HTTP
            "http://example.com",
            "http://localhost",
            "http://127.0.0.1",
            // HTTPS
            "https://example.com",
            "https://localhost",
            "https://127.0.0.1",
            // Odd notations
            "http:example.com",
            "http://@example.com",
            // Redundant default ports
            "http://example.com:80",
            "https://example.com:443",
            // Non-default ports
            "http://example.com:8080",
            "http://127.0.0.1:8080",
            "http://example.com:443",
            "https://example.com:80",
        ] {
            let uri = uri.parse().expect("could not parse a test uri");
            if parse_oidc_href(&uri).is_none() {
                panic!("unexpectedly rejected uri: {}", uri)
            }
        }
    }

    #[test]
    fn invalid_oidc_endpoints() {
        for uri in &[
            // Userinfo
            "http://user:pass@example.com",
            "http://user@example.com",
            // Paths, query strings, and fragments
            "http://example.com:8080/path?foo=bar#baz",
            "http://example.com:8080/?foo=bar#baz",
            "http://example.com:8080/#baz",
            "http://example.com:8080/path#baz",
            "http://example.com:8080/path?foo=bar",
            // Invalid ports
            "http://example.com:0",
        ] {
            println!("{}", uri);
            let uri = uri.parse().expect("could not parse a test uri");
            if parse_oidc_href(&uri).is_some() {
                panic!("did not reject uri: {}", uri)
            }
        }
    }
}
<|endoftext|>