<commit_before>use js::value::{Value, ResultValue, VFunction, VNumber, VInteger, VObject, VBoolean};
use js::function::{NativeFunc, NativeFunction};
use collections::treemap::TreeMap;
use std::gc::Gc;
use std::cell::RefCell;
use std::f64::NAN;
/// Parse a float
pub fn parse_float(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	let parsed = from_str(args.get(0).borrow().to_str());
	return Ok(Gc::new(VNumber(match parsed {
		Some(v) => v,
		None => NAN
	})));
}
/// Parse an int
pub fn parse_int(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	let parsed = from_str(args.get(0).borrow().to_str());
	return Ok(Gc::new(match parsed {
		Some(v) => VInteger(v),
		None => VNumber(NAN)
	}));
}
/// Check if a value when converted to a number is finite
pub fn is_finite(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	if args.len() == 0 {
		Ok(Gc::new(VBoolean(false)))
	} else {
		let num = args.get(0).borrow().to_num();
		Ok(Gc::new(VBoolean(num.is_finite())))
	}
}
/// Check if a number is finite
pub fn strict_is_finite(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	if args.len() == 0 {
		Ok(Gc::new(VBoolean(false)))
	} else {
	let num = args.get(0).borrow();
		Ok(Gc::new(VBoolean(match *num {
			VNumber(v) => v.is_finite(),
			VInteger(_) => true, // integers can't be infinite
			_ => false
		})))
	}
}
/// Initialise the parse functions on a global object
pub fn init(obj:Value) {
	obj.borrow().set_field(~"parseFloat", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(parse_float, 1))))));
	obj.borrow().set_field(~"parseInt", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(parse_int, 1))))));
	obj.borrow().set_field(~"isFinite", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(is_finite, 1))))));
}
/// Create a new 'Number' object
pub fn _create() -> Value {
	let mut number = TreeMap::new();
	number.insert(~"parseFloat", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(parse_float, 1))))));
	number.insert(~"parseInt", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(parse_int, 1))))));
	number.insert(~"isFinite", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(strict_is_finite, 1))))));
	Gc::new(VObject(RefCell::new(number)))
}<commit_msg>Add Number constants<commit_after>use js::value::{Value, ResultValue, VFunction, VNumber, VInteger, VObject, VBoolean};
use js::function::{NativeFunc, NativeFunction};
use collections::treemap::TreeMap;
use std::gc::Gc;
use std::cell::RefCell;
use std::f64::{NAN, MAX_VALUE, MIN_VALUE, INFINITY, NEG_INFINITY, EPSILON};
/// Parse a float
pub fn parse_float(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	let parsed = from_str(args.get(0).borrow().to_str());
	return Ok(Gc::new(VNumber(match parsed {
		Some(v) => v,
		None => NAN
	})));
}
/// Parse an int
pub fn parse_int(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	let parsed = from_str(args.get(0).borrow().to_str());
	return Ok(Gc::new(match parsed {
		Some(v) => VInteger(v),
		None => VNumber(NAN)
	}));
}
/// Check if a value when converted to a number is finite
pub fn is_finite(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	if args.len() == 0 {
		Ok(Gc::new(VBoolean(false)))
	} else {
		let num = args.get(0).borrow().to_num();
		Ok(Gc::new(VBoolean(num.is_finite())))
	}
}
/// Check if a number is finite
pub fn strict_is_finite(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	if args.len() == 0 {
		Ok(Gc::new(VBoolean(false)))
	} else {
	let num = args.get(0).borrow();
		Ok(Gc::new(VBoolean(match *num {
			VNumber(v) => v.is_finite(),
			VInteger(_) => true, // integers can't be infinite
			_ => false
		})))
	}
}
/// Initialise the parse functions on a global object
pub fn init(obj:Value) {
	obj.borrow().set_field(~"parseFloat", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(parse_float, 1))))));
	obj.borrow().set_field(~"parseInt", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(parse_int, 1))))));
	obj.borrow().set_field(~"isFinite", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(is_finite, 1))))));
}
/// Create a new 'Number' object
pub fn _create() -> Value {
	let mut number = TreeMap::new();
	number.insert(~"NaN", Gc::new(VNumber(NAN)));
	number.insert(~"MAX_VALUE", Gc::new(VNumber(MAX_VALUE)));
	number.insert(~"MIN_VALUE", Gc::new(VNumber(MIN_VALUE)));
	number.insert(~"POSITIVE_INFINITY", Gc::new(VNumber(INFINITY)));
	number.insert(~"NEGATIVE_INFINITY", Gc::new(VNumber(NEG_INFINITY)));
	number.insert(~"EPSILON", Gc::new(VNumber(EPSILON)));
	number.insert(~"parseFloat", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(parse_float, 1))))));
	number.insert(~"parseInt", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(parse_int, 1))))));
	number.insert(~"isFinite", Gc::new(VFunction(RefCell::new(NativeFunc(NativeFunction::new(strict_is_finite, 1))))));
	Gc::new(VObject(RefCell::new(number)))
}<|endoftext|>


<commit_before>// Copyright 2014 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.

//! The Ferragina-Mancini Index for finding suffix array intervals matching a given pattern.

use std::iter::DoubleEndedIterator;

use data_structures::bwt::{Occ, Less, less, BWT};
use data_structures::suffix_array::SuffixArray;
use alphabets::{Alphabet, dna};
use std::mem::swap;

#[derive(Copy)]
pub struct Interval {
    lower: usize,
    upper: usize
}

impl Interval {
    /// Return the occurrence positions of the pattern as a slice of the suffix array.
    pub fn occ<'a>(&self, pos: &'a SuffixArray) -> &'a [usize] {
        &pos[self.lower..self.upper]
    }
}

pub struct FMIndex<'a> {
    bwt: &'a BWT,
    less: Less,
    occ: Occ
}

impl<'a> FMIndex<'a> {
    /// Construct a new instance of the FM index.
    ///
    /// # Arguments
    ///
    /// * `bwt` - the BWT
    /// * `k` - the sampling rate of the occ array: every k-th entry will be stored (higher k means
    ///   less memory usage, but worse performance)
    /// * `alphabet` - the alphabet of the underlying text, omitting the sentinel
    pub fn new(bwt: &'a BWT, k: usize, alphabet: &Alphabet) -> Self {
        FMIndex { bwt: bwt, less: less(bwt, alphabet), occ: Occ::new(bwt, k, alphabet)}
    }

    /// Perform backward search, yielding suffix array
    /// interval denoting exact occurences of the given pattern of length m in the text.
    /// Complexity: O(m).
    ///
    /// # Arguments
    ///
    /// * `pattern` - the pattern to search
    ///
    /// # Example
    ///
    /// ```
    /// use bio::data_structures::bwt::bwt;
    /// use bio::data_structures::fmindex::FMIndex;
    /// use bio::data_structures::suffix_array::suffix_array;
    /// use bio::alphabets::dna;
    ///
    /// let text = b"GCCTTAACATTATTACGCCTA$";
    /// let alphabet = dna::alphabet();
    /// let pos = suffix_array(text);
    /// let bwt = bwt(text, &pos);
    /// let fm = FMIndex::new(&bwt, 3, &alphabet);
    ///
    /// let pattern = b"TTA";
    /// let sai = fm.backward_search(pattern.iter());
    ///
    /// let occ = sai.occ(&pos);
    ///
    /// assert_eq!(occ, [3, 12, 9]);
    /// ```
    pub fn backward_search<'b, P: Iterator<Item=&'b u8> + DoubleEndedIterator>(&self, pattern: P) -> Interval {
        let (mut l, mut r) = (0, self.bwt.len() - 1);
        for &a in pattern.rev() {
            let less = self.less(a);
            l = less + if l > 0 { self.occ(l - 1, a) } else { 0 };
            r = less + self.occ(r, a) - 1;
        }

        Interval { lower: l, upper: r + 1 }
    }

    fn occ(&self, r: usize, a: u8) -> usize {
        self.occ.get(self.bwt, r, a)
    }

    fn less(&self, a: u8) -> usize {
        self.less[a as usize]
    }
}

#[derive(Copy)]
#[derive(Debug)]
pub struct BiInterval {
    lower: usize,
    lower_rev: usize,
    size: usize,
    match_size: usize,
}

impl BiInterval {
    /// Return the occurrence positions of the pattern as a slice of the suffix array.
    pub fn occ<'a>(&self, pos: &'a SuffixArray) -> &'a [usize] {
        self._pos(pos, self.lower)
    }

    /// Return the occurrence positions of the reverse complement of the pattern as a slice of the suffix array.
    pub fn occ_revcomp<'a>(&self, pos: &'a SuffixArray) -> &'a [usize] {
        self._pos(pos, self.lower_rev)
    }

    fn _pos<'a>(&self, pos: &'a SuffixArray, lower: usize) -> &'a [usize] {
        &pos[lower..lower + self.size]
    }

    fn swapped(&self) -> BiInterval {
        BiInterval {
            lower: self.lower_rev,
            lower_rev: self.lower,
            size: self.size,
            match_size: self.match_size
        }
    }
}

pub struct FMDIndex<'a> {
    fmindex: FMIndex<'a>,
    revcomp: dna::RevComp,
}

impl<'a> FMDIndex<'a> {
    /// Construct a new instance of the FMD index (see Heng Li (2012) Bioinformatics).
    /// This expects a BWT that was created from a text over the DNA alphabet with N
    /// (`alphabets::dna::n_alphabet()`) consisting of the
    /// concatenation with its reverse complement, separated by the sentinel symbol `$`.
    /// I.e., let T be the original text and R be its reverse complement.
    /// Then, the expected text is T$R$. Further, multiple concatenated texts are allowed, e.g.
    /// T1$R1$T2$R2$T3$R3$.
    ///
    /// # Arguments
    ///
    /// * `bwt` - the BWT
    /// * `k` - the sampling rate of the occ array: every k-th entry will be stored (higher k means
    ///   less memory usage, but worse performance)
    pub fn new(bwt: &'a BWT, k: usize) -> Self {
        let mut alphabet = dna::n_alphabet();
        alphabet.insert(b'$');
        assert!(
            alphabet.is_word(bwt),
            "Expecting BWT over the DNA alphabet (including N) with the sentinel $."
        );

        FMDIndex {
            fmindex: FMIndex::new(bwt, k, &alphabet),
            revcomp: dna::RevComp::new()
        }
    }

    /// Find supermaximal exact matches of given pattern overlapping position i.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::data_structures::fmindex::FMDIndex;
    /// use bio::data_structures::suffix_array::suffix_array;
    /// use bio::data_structures::bwt::bwt;
    ///
    /// let text = b"ATTC$GAAT$";
    /// let pos = suffix_array(text);
    /// let bwt = bwt(text, &pos);
    /// let fmdindex = FMDIndex::new(&bwt, 3);
    ///
    /// let pattern = b"ATT";
    /// let intervals = fmdindex.smems(pattern, 2);
    /// let occ = intervals[0].occ(&pos);
    /// let occ_revcomp = intervals[0].occ_revcomp(&pos);
    ///
    /// assert_eq!(occ, [0]);
    /// assert_eq!(occ_revcomp, [6]);
    /// ```
    pub fn smems(&self, pattern: &[u8], i: usize) -> Vec<BiInterval> {

        let curr = &mut Vec::new();
        let prev = &mut Vec::new();
        let mut matches = Vec::new();

        let mut interval = self.init_interval(pattern, i);

        for &a in pattern[i+1..].iter() {
            // forward extend interval
            let _interval = self.forward_ext(&interval, a);

            // if size changed, add last interval to list
            if interval.size != _interval.size {
                curr.push(interval);
            }
            // if new interval size is zero, stop, as no further forward extension is possible
            if _interval.size == 0 {
                break;
            }
            interval = _interval;
        }
        // add the last non-zero interval
        curr.push(interval);

        swap(curr, prev);
        let mut j = pattern.len() as isize;

        for k in (-1..i as isize).rev() {
            let a = if k == -1 { b'$' } else { pattern[k as usize] };
            curr.clear();
            // size of the last confirmed interval
            let mut last_size = -1;
            // iterate over forward extensions in reverse, as they are sorted by size
            // and we prefer longer matches
            for &interval in prev.iter().rev() {
                // backward extend interval
                let _interval = self.backward_ext(&interval, a);

                if _interval.size == 0 || k == -1 {
                    // interval could not be extended further
                    // if no interval has been extended this iteration,
                    // interval is maximal and can be added to the matches
                    if curr.is_empty() && k < j {
                        j = k;
                        matches.push(interval);
                    }
                }
                // add _interval to curr (will be further extended next iteration)
                if _interval.size != 0 && _interval.size != last_size {
                    last_size = _interval.size;
                    curr.push(_interval);
                }
            }
            if curr.is_empty() {
                break;
            }
            swap(curr, prev);
        }

        matches
    }

    fn init_interval(&self, pattern: &[u8], i: usize) -> BiInterval {
        let a = pattern[i];
        let _a = self.revcomp.comp(a);
        let lower = self.fmindex.less(a);

        BiInterval {
            lower: lower,
            lower_rev: self.fmindex.less(_a),
            size: self.fmindex.less(a + 1) - lower,
            match_size: 1,
        }
    }

    fn backward_ext(&self, interval: &BiInterval, a: u8) -> BiInterval {
        let mut s = 0;
        let mut o = 0;
        let mut l = interval.lower_rev;
        // Interval [l(c(aP)), u(c(aP))] is a subinterval of [l(c(P)), u(c(P))] for each a,
        // starting with the lexicographically smallest ($),
        // then c(T) = A, c(G) = C, c(C) = G, N, c(A) = T, ...
        // Hence, we calculate lower revcomp bounds by iterating over
        // symbols and updating from previous one.
        for &b in b"$TGCNAtgcna".iter() {
            l = l + s;
            o = self.fmindex.occ(interval.lower - 1, b);
            // calculate size
            s = self.fmindex.occ(interval.lower + interval.size - 1, b) - o;
            if b == a {
                break;
            }
        }
        // calculate lower bound
        let k = self.fmindex.less(a) + o;

        BiInterval {
            lower: k,
            lower_rev: l,
            size: s,
            match_size: interval.match_size + 1
        }
    }

    fn forward_ext(&self, interval: &BiInterval, a: u8) -> BiInterval {
        let _a = self.revcomp.comp(a);

        self.backward_ext(
            &interval.swapped(),
            _a
        ).swapped()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use alphabets::dna;
    use data_structures::suffix_array::suffix_array;
    use data_structures::bwt::bwt;

    #[test]
    fn test_smems() {
        let revcomp = dna::RevComp::new();
        let orig_text = b"GCCTTAACAT";
        let text = [orig_text, b"$", revcomp.get(orig_text).as_slice(), b"$"].concat();
        let pos = suffix_array(&text);
        println!("pos {:?}", pos);
        println!("text {:?}", text);
        let bwt = bwt(&text, &pos);
        let fmdindex = FMDIndex::new(&bwt, 3);
        {
            let pattern = b"AA";
            let intervals = fmdindex.smems(pattern, 0);
            assert_eq!(intervals[0].occ(&pos), [5, 16]);
            assert_eq!(intervals[0].occ_revcomp(&pos), [3, 14]);
        }
        {
            let pattern = b"CTTAA";
            let intervals = fmdindex.smems(pattern, 1);
            assert_eq!(intervals[0].occ(&pos), [2]);
            assert_eq!(intervals[0].occ_revcomp(&pos), [14]);
            assert_eq!(intervals[0].match_size, 5)
        }
    }

    #[test]
    fn test_init_interval() {
        let text = b"ACGT$TGCA$";
        let pos = suffix_array(text);
        let bwt = bwt(text, &pos);
        let fmdindex = FMDIndex::new(&bwt, 3);
        let pattern = b"T";
        let interval = fmdindex.init_interval(pattern, 0);
        assert_eq!(interval.occ(&pos), [3, 5]);
        assert_eq!(interval.occ_revcomp(&pos), [8, 0]);
    }
}
<commit_msg>Fixed fmindex test.<commit_after>// Copyright 2014 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.

//! The Ferragina-Mancini Index for finding suffix array intervals matching a given pattern.

use std::iter::DoubleEndedIterator;

use data_structures::bwt::{Occ, Less, less, BWT};
use data_structures::suffix_array::SuffixArray;
use alphabets::{Alphabet, dna};
use std::mem::swap;

#[derive(Copy)]
pub struct Interval {
    lower: usize,
    upper: usize
}

impl Interval {
    /// Return the occurrence positions of the pattern as a slice of the suffix array.
    pub fn occ<'a>(&self, pos: &'a SuffixArray) -> &'a [usize] {
        &pos[self.lower..self.upper]
    }
}

pub struct FMIndex<'a> {
    bwt: &'a BWT,
    less: Less,
    occ: Occ
}

impl<'a> FMIndex<'a> {
    /// Construct a new instance of the FM index.
    ///
    /// # Arguments
    ///
    /// * `bwt` - the BWT
    /// * `k` - the sampling rate of the occ array: every k-th entry will be stored (higher k means
    ///   less memory usage, but worse performance)
    /// * `alphabet` - the alphabet of the underlying text, omitting the sentinel
    pub fn new(bwt: &'a BWT, k: usize, alphabet: &Alphabet) -> Self {
        FMIndex { bwt: bwt, less: less(bwt, alphabet), occ: Occ::new(bwt, k, alphabet)}
    }

    /// Perform backward search, yielding suffix array
    /// interval denoting exact occurences of the given pattern of length m in the text.
    /// Complexity: O(m).
    ///
    /// # Arguments
    ///
    /// * `pattern` - the pattern to search
    ///
    /// # Example
    ///
    /// ```
    /// use bio::data_structures::bwt::bwt;
    /// use bio::data_structures::fmindex::FMIndex;
    /// use bio::data_structures::suffix_array::suffix_array;
    /// use bio::alphabets::dna;
    ///
    /// let text = b"GCCTTAACATTATTACGCCTA$";
    /// let alphabet = dna::alphabet();
    /// let pos = suffix_array(text);
    /// let bwt = bwt(text, &pos);
    /// let fm = FMIndex::new(&bwt, 3, &alphabet);
    ///
    /// let pattern = b"TTA";
    /// let sai = fm.backward_search(pattern.iter());
    ///
    /// let occ = sai.occ(&pos);
    ///
    /// assert_eq!(occ, [3, 12, 9]);
    /// ```
    pub fn backward_search<'b, P: Iterator<Item=&'b u8> + DoubleEndedIterator>(&self, pattern: P) -> Interval {
        let (mut l, mut r) = (0, self.bwt.len() - 1);
        for &a in pattern.rev() {
            let less = self.less(a);
            l = less + if l > 0 { self.occ(l - 1, a) } else { 0 };
            r = less + self.occ(r, a) - 1;
        }

        Interval { lower: l, upper: r + 1 }
    }

    fn occ(&self, r: usize, a: u8) -> usize {
        self.occ.get(self.bwt, r, a)
    }

    fn less(&self, a: u8) -> usize {
        self.less[a as usize]
    }
}

#[derive(Copy)]
#[derive(Debug)]
pub struct BiInterval {
    lower: usize,
    lower_rev: usize,
    size: usize,
    match_size: usize,
}

impl BiInterval {
    /// Return the occurrence positions of the pattern as a slice of the suffix array.
    pub fn occ<'a>(&self, pos: &'a SuffixArray) -> &'a [usize] {
        self._pos(pos, self.lower)
    }

    /// Return the occurrence positions of the reverse complement of the pattern as a slice of the suffix array.
    pub fn occ_revcomp<'a>(&self, pos: &'a SuffixArray) -> &'a [usize] {
        self._pos(pos, self.lower_rev)
    }

    fn _pos<'a>(&self, pos: &'a SuffixArray, lower: usize) -> &'a [usize] {
        &pos[lower..lower + self.size]
    }

    fn swapped(&self) -> BiInterval {
        BiInterval {
            lower: self.lower_rev,
            lower_rev: self.lower,
            size: self.size,
            match_size: self.match_size
        }
    }
}

pub struct FMDIndex<'a> {
    fmindex: FMIndex<'a>,
    revcomp: dna::RevComp,
}

impl<'a> FMDIndex<'a> {
    /// Construct a new instance of the FMD index (see Heng Li (2012) Bioinformatics).
    /// This expects a BWT that was created from a text over the DNA alphabet with N
    /// (`alphabets::dna::n_alphabet()`) consisting of the
    /// concatenation with its reverse complement, separated by the sentinel symbol `$`.
    /// I.e., let T be the original text and R be its reverse complement.
    /// Then, the expected text is T$R$. Further, multiple concatenated texts are allowed, e.g.
    /// T1$R1$T2$R2$T3$R3$.
    ///
    /// # Arguments
    ///
    /// * `bwt` - the BWT
    /// * `k` - the sampling rate of the occ array: every k-th entry will be stored (higher k means
    ///   less memory usage, but worse performance)
    pub fn new(bwt: &'a BWT, k: usize) -> Self {
        let mut alphabet = dna::n_alphabet();
        alphabet.insert(b'$');
        assert!(
            alphabet.is_word(bwt),
            "Expecting BWT over the DNA alphabet (including N) with the sentinel $."
        );

        FMDIndex {
            fmindex: FMIndex::new(bwt, k, &alphabet),
            revcomp: dna::RevComp::new()
        }
    }

    /// Find supermaximal exact matches of given pattern overlapping position i.
    ///
    /// # Example
    ///
    /// ```
    /// use bio::data_structures::fmindex::FMDIndex;
    /// use bio::data_structures::suffix_array::suffix_array;
    /// use bio::data_structures::bwt::bwt;
    ///
    /// let text = b"ATTC$GAAT$";
    /// let pos = suffix_array(text);
    /// let bwt = bwt(text, &pos);
    /// let fmdindex = FMDIndex::new(&bwt, 3);
    ///
    /// let pattern = b"ATT";
    /// let intervals = fmdindex.smems(pattern, 2);
    /// let occ = intervals[0].occ(&pos);
    /// let occ_revcomp = intervals[0].occ_revcomp(&pos);
    ///
    /// assert_eq!(occ, [0]);
    /// assert_eq!(occ_revcomp, [6]);
    /// ```
    pub fn smems(&self, pattern: &[u8], i: usize) -> Vec<BiInterval> {

        let curr = &mut Vec::new();
        let prev = &mut Vec::new();
        let mut matches = Vec::new();

        let mut interval = self.init_interval(pattern, i);

        for &a in pattern[i+1..].iter() {
            // forward extend interval
            let _interval = self.forward_ext(&interval, a);

            // if size changed, add last interval to list
            if interval.size != _interval.size {
                curr.push(interval);
            }
            // if new interval size is zero, stop, as no further forward extension is possible
            if _interval.size == 0 {
                break;
            }
            interval = _interval;
        }
        // add the last non-zero interval
        curr.push(interval);

        swap(curr, prev);
        let mut j = pattern.len() as isize;

        for k in (-1..i as isize).rev() {
            let a = if k == -1 { b'$' } else { pattern[k as usize] };
            curr.clear();
            // size of the last confirmed interval
            let mut last_size = -1;
            // iterate over forward extensions in reverse, as they are sorted by size
            // and we prefer longer matches
            for &interval in prev.iter().rev() {
                // backward extend interval
                let _interval = self.backward_ext(&interval, a);

                if _interval.size == 0 || k == -1 {
                    // interval could not be extended further
                    // if no interval has been extended this iteration,
                    // interval is maximal and can be added to the matches
                    if curr.is_empty() && k < j {
                        j = k;
                        matches.push(interval);
                    }
                }
                // add _interval to curr (will be further extended next iteration)
                if _interval.size != 0 && _interval.size != last_size {
                    last_size = _interval.size;
                    curr.push(_interval);
                }
            }
            if curr.is_empty() {
                break;
            }
            swap(curr, prev);
        }

        matches
    }

    fn init_interval(&self, pattern: &[u8], i: usize) -> BiInterval {
        let a = pattern[i];
        let _a = self.revcomp.comp(a);
        let lower = self.fmindex.less(a);

        BiInterval {
            lower: lower,
            lower_rev: self.fmindex.less(_a),
            size: self.fmindex.less(a + 1) - lower,
            match_size: 1,
        }
    }

    fn backward_ext(&self, interval: &BiInterval, a: u8) -> BiInterval {
        let mut s = 0;
        let mut o = 0;
        let mut l = interval.lower_rev;
        // Interval [l(c(aP)), u(c(aP))] is a subinterval of [l(c(P)), u(c(P))] for each a,
        // starting with the lexicographically smallest ($),
        // then c(T) = A, c(G) = C, c(C) = G, N, c(A) = T, ...
        // Hence, we calculate lower revcomp bounds by iterating over
        // symbols and updating from previous one.
        for &b in b"$TGCNAtgcna".iter() {
            l = l + s;
            o = self.fmindex.occ(interval.lower - 1, b);
            // calculate size
            s = self.fmindex.occ(interval.lower + interval.size - 1, b) - o;
            if b == a {
                break;
            }
        }
        // calculate lower bound
        let k = self.fmindex.less(a) + o;

        BiInterval {
            lower: k,
            lower_rev: l,
            size: s,
            match_size: interval.match_size + 1
        }
    }

    fn forward_ext(&self, interval: &BiInterval, a: u8) -> BiInterval {
        let _a = self.revcomp.comp(a);

        self.backward_ext(
            &interval.swapped(),
            _a
        ).swapped()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use alphabets::dna;
    use data_structures::suffix_array::suffix_array;
    use data_structures::bwt::bwt;

    #[test]
    fn test_smems() {
        let revcomp = dna::RevComp::new();
        let orig_text = b"GCCTTAACAT";
        let revcomp_text = revcomp.get(orig_text);
        let text_builder: Vec<&[u8]> = vec![orig_text, b"$", revcomp_text.as_slice(), b"$"];
        let text = text_builder.concat();
        let pos = suffix_array(&text);
        println!("pos {:?}", pos);
        println!("text {:?}", text);
        let bwt = bwt(&text, &pos);
        let fmdindex = FMDIndex::new(&bwt, 3);
        {
            let pattern = b"AA";
            let intervals = fmdindex.smems(pattern, 0);
            assert_eq!(intervals[0].occ(&pos), [5, 16]);
            assert_eq!(intervals[0].occ_revcomp(&pos), [3, 14]);
        }
        {
            let pattern = b"CTTAA";
            let intervals = fmdindex.smems(pattern, 1);
            assert_eq!(intervals[0].occ(&pos), [2]);
            assert_eq!(intervals[0].occ_revcomp(&pos), [14]);
            assert_eq!(intervals[0].match_size, 5)
        }
    }

    #[test]
    fn test_init_interval() {
        let text = b"ACGT$TGCA$";
        let pos = suffix_array(text);
        let bwt = bwt(text, &pos);
        let fmdindex = FMDIndex::new(&bwt, 3);
        let pattern = b"T";
        let interval = fmdindex.init_interval(pattern, 0);
        assert_eq!(interval.occ(&pos), [3, 5]);
        assert_eq!(interval.occ_revcomp(&pos), [8, 0]);
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]
#![allow(single_match, unused_assignments, unused_variables)]

fn test1() {
    let mut x = 0;
    loop { // never_loop
        x += 1;
        if x == 1 {
            return
        }
        break;
    }
}

fn test2() {
    let mut x = 0;
    loop {
        x += 1;
        if x == 1 {
            break
        }
    }
}

fn test3() {
    let mut x = 0;
    loop { // never loops
        x += 1;
        break
    }
}

fn test4() {
    let mut x = 1;
    loop {
        x += 1;
        match x {
            5 => return,
            _ => (),
        }
    }
}

fn test5() {
    let i = 0;
	loop { // never loops
        while i == 0 { // never loops
            break
        }
        return
	}
}

fn test6() {
    let mut x = 0;
    'outer: loop { // never loops
        x += 1;
		loop { // never loops
            if x == 5 { break }
			continue 'outer
		}
		return
	}
}

fn test7() {
    let mut x = 0;
    loop {
        x += 1;
        match x {
            1 => continue,
            _ => (),
        }
        return
    }
}

fn test8() {
    let mut x = 0;
    loop {
        x += 1;
        match x {
            5 => return,
            _ => continue,
        }
    }
}

fn test9() {
    let x = Some(1);
    while let Some(y) = x { // never loops
        return
    }
}

fn test10() {
    for x in 0..10 { // never loops
        match x {
            1 => break,
            _ => return,
        }
    }
}

fn main() {
    test1();
    test2();
    test3();
    test4();
    test5();
    test6();
    test7();
    test8();
    test9();
    test10();
}

<commit_msg>Add more test for #1586.<commit_after>#![feature(plugin)]
#![plugin(clippy)]
#![allow(single_match, unused_assignments, unused_variables)]

fn test1() {
    let mut x = 0;
    loop { // never_loop
        x += 1;
        if x == 1 {
            return
        }
        break;
    }
}

fn test2() {
    let mut x = 0;
    loop {
        x += 1;
        if x == 1 {
            break
        }
    }
}

fn test3() {
    let mut x = 0;
    loop { // never loops
        x += 1;
        break
    }
}

fn test4() {
    let mut x = 1;
    loop {
        x += 1;
        match x {
            5 => return,
            _ => (),
        }
    }
}

fn test5() {
    let i = 0;
	loop { // never loops
        while i == 0 { // never loops
            break
        }
        return
	}
}

fn test6() {
    let mut x = 0;
    'outer: loop { // never loops
        x += 1;
		loop { // never loops
            if x == 5 { break }
			continue 'outer
		}
		return
	}
}

fn test7() {
    let mut x = 0;
    loop {
        x += 1;
        match x {
            1 => continue,
            _ => (),
        }
        return
    }
}

fn test8() {
    let mut x = 0;
    loop {
        x += 1;
        match x {
            5 => return,
            _ => continue,
        }
    }
}

fn test9() {
    let x = Some(1);
    while let Some(y) = x { // never loops
        return
    }
}

fn test10() {
    for x in 0..10 { // never loops
        match x {
            1 => break,
            _ => return,
        }
    }
}

fn test11<F: FnMut() -> i32>(mut f: F) {
    loop {
        return match f() {
            1 => continue,
            _ => (),
        }
    }
}

fn main() {
    test1();
    test2();
    test3();
    test4();
    test5();
    test6();
    test7();
    test8();
    test9();
    test10();
    test11(|| 0);
}

<|endoftext|>


<commit_before>//! Manages the sliding windows.  Each time a tick is pushed in, the max/min price of each
//! of the monitored time perdiods is updated.  When ticks become older than the period of
//! the greatest window-newest tick, they are dropped off the structure.
//!
//! NOTE: This algorithm could be more efficiently impelented by a joint linked-list/binary-heap.
//! Traversing a Vector is currently used instead due to the complexity of implementing the
//! alternative.  However, if the latency and inefficniecy caused ever becomes a problem,
//! there are options available.

use std::collections::{HashMap, VecDeque};
use test;

use algobot_util::tick::Tick;

/// Contains the computed information about the ticks in each time monitored time frame.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Window {
    // TODO: These really don't have to be options.
    pub min_price_t: Option<Tick>,
    pub max_price_t: Option<Tick>,
    pub oldest_t:    Option<Tick>
}

impl Window {
    pub fn new_empty() -> Window {
        Window {
            min_price_t: None,
            max_price_t: None,
            oldest_t:   None
        }
    }
}

pub struct WindowManager {
    pub data: VecDeque<Tick>,
    pub windows: HashMap<i64, Window>,
    pub max_period: Option<i64>
}

/// Determines whether a tick is out of range of a window or not
fn out_of_range(period: i64, old_tick: Tick, newest_tick: Tick) -> bool {
    newest_tick.timestamp - old_tick.timestamp >= period
}

/// Checks if a tick is a max/min tick of a Window
fn is_max_min(t: Tick, window: Window) -> bool {
    if window.min_price_t.is_none() {
        // doesn't matter since we already have a recalc queued
        return false
    }
    t == window.min_price_t.unwrap() || t == window.max_price_t.unwrap()
}

impl WindowManager {
    pub fn new() -> WindowManager {
        WindowManager {
            data: VecDeque::new(),
            windows: HashMap::new(),
            max_period: None
        }
    }

    pub fn add_period(&mut self, period: i64) {
        self.windows.insert(period, Window::new_empty());
        // update max period
        match self.max_period {
            Some(_max_period) => {
                if period > _max_period {
                    self.max_period = Some(period);
                }
            },
            None => self.max_period = Some(period)
        }
    }

    pub fn remove_period(&mut self, period: i64) {
        let mut o: Option<i64> = None;
        for (k, _) in self.windows.iter() {
            if *k == period {
                o = Some(*k);
                break;
            }
        }
        if o.is_some() {
            self.windows.remove(&o.unwrap());
            // assume that max_period is already set since we're removing an element
            if self.max_period.unwrap() == period {
                // calculate new max period
                let mut max: Option<i64> = None;
                for (k, _) in self.windows.iter() {
                    if max.is_none() || *k > max.unwrap() {
                        max = Some(*k);
                    }
                }
                self.max_period = max;
            }
        }
    }

    // Processes a new tick and returns a Vec containing periods whose mins/maxes have changed.
    pub fn push(&mut self, t: Tick) -> HashMap<i64, Window> {
        // data is pushed on the back and popped off the front
        if self.data.len() > 0 {
            assert!(t.timestamp > self.data.back().unwrap().timestamp);
        }
        self.data.push_back(t);

        let mut ret = HashMap::new();
        for (period, window) in self.trim_overflow(t) {
            ret.insert(period, window);
        }

        ret
    }

    /// Removes ticks from the front of the queue until all timestamps are within
    /// the maximum period of the WindowManager.  For each tick that is removed,
    /// check to see if it was the maximum/minimum of any windows.  If it was,
    /// update that window.
    fn trim_overflow(&mut self, newest_tick: Tick) -> Vec<(i64, Window)> {
        let mut altered_periods = Vec::new();

        // iterate over all windows and check if the tick is out of their range
        //
        // NOTE: Currently windows are iterated over in an arbitrary order making it impossible to
        // do optimizations like use the max of smaller windows to avoid having to iterate over
        // those parts of larger windows.
        for (&period, &window) in self.windows.iter() {
            let mut window = window;
            let mut altered = false;
            // if it's the first tick
            if window.oldest_t.is_none() {
                window.oldest_t = Some(newest_tick);
                window.min_price_t = Some(newest_tick);
                window.max_price_t = Some(newest_tick);
                altered = true;
            } else {
                // if our current oldest tick is no longer in range of the window
                if out_of_range(period, window.oldest_t.unwrap(), newest_tick) {
                    // have to re-scan the entire array starting at the oldest
                    let mut i = 0;

                    // loop through ticks until we find one that's inside the window
                    while let Some(newer_tick) = self.data.get(i as usize) {
                        i += 1;
                        if !out_of_range(period, *newer_tick, newest_tick) {
                            // found the first in-range tick
                            window.oldest_t = Some(*newer_tick);
                            if is_max_min(*newer_tick, window) {
                                window.min_price_t = None;
                                window.max_price_t = None;
                            }
                            break;
                        }

                        // If the tick that went out of range max/min needs updating
                        if is_max_min(*newer_tick, window) {
                            window.min_price_t = None;
                            window.max_price_t = None;
                        }
                    }
                    // at this point the oldest tick for the window is either None or accurate
                    // (not accounting for the possibility of the newest tick)
                }
            }

            if window.min_price_t.is_none() || window.max_price_t.is_none() {
                // there is at least one tick so we can .unwrap()
                let extremes = self.get_extreme_ticks(period).unwrap();
                window.min_price_t = Some(extremes.0);
                window.max_price_t = Some(extremes.1);
                altered = true;
            } else {
                // check if newest_tick is a new max/min tick for the period
                if newest_tick.mid() < window.min_price_t.unwrap().mid() {
                    window.min_price_t = Some(newest_tick);
                    altered = true;
                }
                if newest_tick.mid() > window.max_price_t.unwrap().mid() {
                    window.max_price_t = Some(newest_tick);
                    altered = true;
                }
            }

            if altered {
                // Add the mutated window to the alteration list
                altered_periods.push((period, window));
            }
        }

        // make the alterations queued in the loop
        for &(period, window) in altered_periods.iter() {
            self.windows.insert(period, window);
        }

        // drop ticks that are outside of the range of the largest window
        while out_of_range(self.max_period.unwrap(), *self.data.front().unwrap(), newest_tick) {
            self.data.pop_front();
        }

        altered_periods
    }

    /// Gets the max and min tick in a window by iterating over every tick it contains.
    ///
    /// Returns Some(min_tick, max_tick)
    fn get_extreme_ticks(&self, period: i64) -> Option<(Tick, Tick)> {
        let newest_timestamp = self.data.back().unwrap().timestamp;
        let mut max_tick = Tick::null();
        let mut min_tick = Tick::null();
        let mut max_price = 0f64;
        let mut min_price = 0f64;

        // loop over all ticks, newest to oldest
        for t in self.data.iter().rev() {
            if newest_timestamp - t.timestamp >= period {
                break;
            }

            let price = t.mid();
            if price > max_price {
                max_tick = *t;
                max_price = price;
            }

            if price < min_price || min_price == 0f64 {
                min_tick = *t;
                min_price = price;
            }
        }

        if min_price == 0f64 {
            return None
        }

        Some((min_tick, max_tick))
    }
}

#[test]
fn period_addition_removal() {
    let mut wm = WindowManager::new();
    wm.add_period(2);
    wm.add_period(4);
    assert_eq!(wm.windows.len(), 2);
    wm.remove_period(2);
    wm.remove_period(4);
}

#[test]
fn min_max_accuracy() {
    let mut wm = WindowManager::new();
    wm.add_period(2);
    wm.add_period(4);

    let t1 = Tick{timestamp: 1i64, bid: 0.5f64, ask: 0.5f64};
    let wl = wm.push(t1);
    assert_eq!(*wl.get(&2).unwrap(), Window{min_price_t: Some(t1), max_price_t: Some(t1), oldest_t: Some(t1)});
    assert_eq!(*wl.get(&4).unwrap(), Window{min_price_t: Some(t1), max_price_t: Some(t1), oldest_t: Some(t1)});

    let t2 = Tick{timestamp: 2i64, bid: 2f64, ask: 2f64};
    let w2 = wm.push(t2);
    assert_eq!(*w2.get(&2).unwrap(), Window{min_price_t: Some(t1), max_price_t: Some(t2), oldest_t: Some(t1)});
    assert_eq!(*w2.get(&4).unwrap(), Window{min_price_t: Some(t1), max_price_t: Some(t2), oldest_t: Some(t1)});

    let t3 = Tick{timestamp: 3i64, bid: 4f64, ask: 4f64};
    let w3 = wm.push(t3);
    assert_eq!(*w3.get(&2).unwrap(), Window{min_price_t: Some(t2), max_price_t: Some(t3), oldest_t: Some(t2)});
    assert_eq!(*w3.get(&4).unwrap(), Window{min_price_t: Some(t1), max_price_t: Some(t3), oldest_t: Some(t1)});

    let t4 = Tick{timestamp: 6i64, bid: 5f64, ask: 5f64};
    let w4 = wm.push(t4);
    assert_eq!(*w4.get(&2).unwrap(), Window{min_price_t: Some(t4), max_price_t: Some(t4), oldest_t: Some(t4)});
    assert_eq!(*w4.get(&4).unwrap(), Window{min_price_t: Some(t3), max_price_t: Some(t4), oldest_t: Some(t3)});
}

// #[bench]
// fn large_wm_processing_speed(b: &mut test::Bencher) {
//     let mut wm = WindowManager::new();
//     wm.add_period(5000000);
//     // preload with 500,000 ticks
//     for i in 0..5000000 {
//         wm.push(Tick{timestamp: i as i64, bid: 1f64, ask: 1f64});
//     }
//     let mut i = 5000000;
//     b.iter(|| {
//         i = i + 1;
//         wm.push(Tick{timestamp: i as i64, bid: 1f64, ask: 1f64});
//     });
// }
<commit_msg>Removed all unnecessary Options from WindowManager<commit_after>//! Manages the sliding windows.  Each time a tick is pushed in, the max/min price of each
//! of the monitored time perdiods is updated.  When ticks become older than the period of
//! the greatest window-newest tick, they are dropped off the structure.
//!
//! NOTE: This algorithm could be more efficiently impelented by a joint linked-list/binary-heap.
//! Traversing a Vector is currently used instead due to the complexity of implementing the
//! alternative.  However, if the latency and inefficniecy caused ever becomes a problem,
//! there are options available.

use std::collections::{HashMap, VecDeque};
use test;

use algobot_util::tick::Tick;

/// Contains the computed information about the ticks in each time monitored time frame.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Window {
    pub min_price_t: Tick,
    pub max_price_t: Tick,
    pub oldest_t:    Tick
}

impl Window {
    pub fn new_empty() -> Window {
        Window {
            min_price_t: Tick::null(),
            max_price_t: Tick::null(),
            oldest_t:    Tick::null()
        }
    }
}

pub struct WindowManager {
    pub data: VecDeque<Tick>,
    pub windows: HashMap<i64, Window>,
    pub max_period: i64
}

/// Determines whether a tick is out of range of a window or not
fn out_of_range(period: i64, old_tick: Tick, newest_tick: Tick) -> bool {
    newest_tick.timestamp - old_tick.timestamp >= period
}

/// Checks if a tick is a max/min tick of a Window
fn is_max_min(t: Tick, window: Window) -> bool {
    if window.min_price_t.timestamp == 0 {
        // doesn't matter since we already have a recalc queued
        return false
    }
    t == window.min_price_t || t == window.max_price_t
}

impl WindowManager {
    pub fn new() -> WindowManager {
        WindowManager {
            data: VecDeque::new(),
            windows: HashMap::new(),
            max_period: 0
        }
    }

    pub fn add_period(&mut self, period: i64) {
        self.windows.insert(period, Window::new_empty());
        // update max period
        if period > self.max_period {
            self.max_period = period;
        }
    }

    pub fn remove_period(&mut self, period: i64) {
        let mut o = 0;
        for (k, _) in self.windows.iter() {
            if *k == period {
                o = *k;
                break;
            }
        }
        if o != 0 {
            self.windows.remove(&o);
            // assume that max_period is already set since we're removing an element
            if self.max_period == period {
                // calculate new max period
                let mut max = 0;
                for (k, _) in self.windows.iter() {
                    if *k > max{
                        max = *k;
                    }
                }
                self.max_period = max;
            }
        }
    }

    // Processes a new tick and returns a Vec containing periods whose mins/maxes have changed.
    pub fn push(&mut self, t: Tick) -> HashMap<i64, Window> {
        assert!(self.windows.len() > 0);
        if self.data.len() > 0 {
            assert!(t.timestamp > self.data.back().unwrap().timestamp);
        }
        // data is pushed on the back and popped off the front
        self.data.push_back(t);

        let mut ret = HashMap::new();
        for (period, window) in self.trim_overflow(t) {
            ret.insert(period, window);
        }

        ret
    }

    /// Removes ticks from the front of the queue until all timestamps are within
    /// the maximum period of the WindowManager.  For each tick that is removed,
    /// check to see if it was the maximum/minimum of any windows.  If it was,
    /// update that window.
    fn trim_overflow(&mut self, newest_tick: Tick) -> Vec<(i64, Window)> {
        let mut altered_periods = Vec::new();

        // iterate over all windows and check if the tick is out of their range
        //
        // NOTE: Currently windows are iterated over in an arbitrary order making it impossible to
        // do optimizations like use the max of smaller windows to avoid having to iterate over
        // those parts of larger windows.
        for (&period, &window) in self.windows.iter() {
            let mut window = window;
            let mut altered = false;
            // if it's the first tick
            if window.oldest_t.timestamp == 0 {
                window.oldest_t = newest_tick;
                window.min_price_t = newest_tick;
                window.max_price_t = newest_tick;
                altered = true;
            } else {
                // if our current oldest tick is no longer in range of the window
                if out_of_range(period, window.oldest_t, newest_tick) {
                    // have to re-scan the entire array starting at the oldest
                    let mut i = 0;

                    // loop through ticks until we find one that's inside the window
                    while let Some(newer_tick) = self.data.get(i as usize) {
                        i += 1;
                        if !out_of_range(period, *newer_tick, newest_tick) {
                            // found the first in-range tick
                            window.oldest_t = *newer_tick;
                            if is_max_min(*newer_tick, window) {
                                window.min_price_t.timestamp = 0;
                                window.max_price_t.timestamp = 0;
                            }
                            break;
                        }

                        // If the tick that went out of range max/min needs updating
                        if is_max_min(*newer_tick, window) {
                            window.min_price_t.timestamp = 0;
                            window.max_price_t.timestamp = 0;
                        }
                    }
                    // at this point the oldest tick for the window is either 0 or accurate
                    // (not accounting for the possibility of the newest tick)
                }
            }

            if window.min_price_t.timestamp == 0 || window.max_price_t.timestamp == 0 {
                let extremes = self.get_extreme_ticks(period);
                window.min_price_t = extremes.0;
                window.max_price_t = extremes.1;
                altered = true;
            } else {
                // check if newest_tick is a new max/min tick for the period
                if newest_tick.mid() < window.min_price_t.mid() {
                    window.min_price_t = newest_tick;
                    altered = true;
                }
                if newest_tick.mid() > window.max_price_t.mid() {
                    window.max_price_t = newest_tick;
                    altered = true;
                }
            }

            if altered {
                // Add the mutated window to the alteration list
                altered_periods.push((period, window));
            }
        }

        // make the alterations queued in the loop
        for &(period, window) in altered_periods.iter() {
            self.windows.insert(period, window);
        }

        // drop ticks that are outside of the range of the largest window
        while out_of_range(self.max_period, *self.data.front().unwrap(), newest_tick) {
            self.data.pop_front();
        }

        altered_periods
    }

    /// Gets the max and min tick in a window by iterating over every tick it contains.
    ///
    /// Returns (min_tick, max_tick)
    fn get_extreme_ticks(&self, period: i64) -> (Tick, Tick) {
        let newest_timestamp = self.data.back().unwrap().timestamp;
        let mut max_tick = Tick::null();
        let mut min_tick = Tick::null();
        let mut max_price = 0f64;
        let mut min_price = 0f64;

        // loop over all ticks, newest to oldest
        for t in self.data.iter().rev() {
            if newest_timestamp - t.timestamp >= period {
                break;
            }

            let price = t.mid();
            if price > max_price {
                max_tick = *t;
                max_price = price;
            }

            if price < min_price || min_price == 0f64 {
                min_tick = *t;
                min_price = price;
            }
        }

        (min_tick, max_tick)
    }
}

#[test]
fn period_addition_removal() {
    let mut wm = WindowManager::new();
    wm.add_period(2);
    wm.add_period(4);
    assert_eq!(wm.windows.len(), 2);
    wm.remove_period(2);
    wm.remove_period(4);
}

#[test]
fn min_max_accuracy() {
    let mut wm = WindowManager::new();
    wm.add_period(2);
    wm.add_period(4);

    let t1 = Tick{timestamp: 1i64, bid: 0.5f64, ask: 0.5f64};
    let wl = wm.push(t1);
    assert_eq!(*wl.get(&2).unwrap(), Window{min_price_t: t1, max_price_t: t1, oldest_t: t1});
    assert_eq!(*wl.get(&4).unwrap(), Window{min_price_t: t1, max_price_t: t1, oldest_t: t1});

    let t2 = Tick{timestamp: 2i64, bid: 2f64, ask: 2f64};
    let w2 = wm.push(t2);
    assert_eq!(*w2.get(&2).unwrap(), Window{min_price_t: t1, max_price_t: t2, oldest_t: t1});
    assert_eq!(*w2.get(&4).unwrap(), Window{min_price_t: t1, max_price_t: t2, oldest_t: t1});

    let t3 = Tick{timestamp: 3i64, bid: 4f64, ask: 4f64};
    let w3 = wm.push(t3);
    assert_eq!(*w3.get(&2).unwrap(), Window{min_price_t: t2, max_price_t: t3, oldest_t: t2});
    assert_eq!(*w3.get(&4).unwrap(), Window{min_price_t: t1, max_price_t: t3, oldest_t: t1});

    let t4 = Tick{timestamp: 6i64, bid: 5f64, ask: 5f64};
    let w4 = wm.push(t4);
    assert_eq!(*w4.get(&2).unwrap(), Window{min_price_t: t4, max_price_t: t4, oldest_t: t4});
    assert_eq!(*w4.get(&4).unwrap(), Window{min_price_t: t3, max_price_t: t4, oldest_t: t3});
}

#[bench]
fn small_wm_processing_speed(b: &mut test::Bencher) {
    let mut wm = WindowManager::new();
    wm.add_period(500);
    // preload with 500,000 ticks
    for i in 0..500 {
        wm.push(Tick{timestamp: i as i64, bid: 1f64, ask: 1f64});
    }
    let mut i = 500;
    b.iter(|| {
        i = i + 1;
        wm.push(Tick{timestamp: i as i64, bid: 1f64, ask: 1f64});
    });
}

// Commented because it takes a while to run
// #[bench]
// fn large_wm_processing_speed(b: &mut test::Bencher) {
//     let mut wm = WindowManager::new();
//     wm.add_period(5000000);
//     // preload with 500,000 ticks
//     for i in 0..5000000 {
//         wm.push(Tick{timestamp: i as i64, bid: 1f64, ask: 1f64});
//     }
//     let mut i = 5000000;
//     b.iter(|| {
//         i = i + 1;
//         wm.push(Tick{timestamp: i as i64, bid: 1f64, ask: 1f64});
//     });
// }
<|endoftext|>


<commit_before>// primitive_types4.rs
// Get a slice out of Array a where the ??? is so that the `if` statement
// returns true. Execute `rustlings hint primitive_types4` for hints!!

// I AM NOT DONE

#[test]
fn main() {
    let a = [1, 2, 3, 4, 5];

    let nice_slice = ???

    assert_eq!([2, 3, 4], nice_slice)
}
<commit_msg>fix(primitive_types4): update outdated comment<commit_after>// primitive_types4.rs
// Get a slice out of Array a where the ??? is so that the test passes.
// Execute `rustlings hint primitive_types4` for hints!!

// I AM NOT DONE

#[test]
fn slice_out_of_array() {
    let a = [1, 2, 3, 4, 5];

    let nice_slice = ???

    assert_eq!([2, 3, 4], nice_slice)
}
<|endoftext|>


<commit_before>
import option::none;
import option::some;

// A very naive implementation of union-find with unsigned integer nodes.
// Maintains the invariant that the root of a node is always equal to or less
// than the node itself.
type node = option::t[uint];

type ufind = rec(mutable vec[mutable node] nodes);

fn make() -> ufind {
    let vec[mutable node] v = [mutable none[uint]];
    vec::pop(v); // FIXME: botch

    ret rec(mutable nodes=v);
}

fn make_set(&ufind ufnd) -> uint {
    auto idx = vec::len(ufnd.nodes);
    ufnd.nodes += [mutable none[uint]];
    ret idx;
}

/// Creates sets as necessary to ensure that least `n` sets are present in the
/// data structure.
fn grow(&ufind ufnd, uint n) {
    while (set_count(ufnd) < n) { make_set(ufnd); }
}

fn find(&ufind ufnd, uint n) -> uint {
    alt (ufnd.nodes.(n)) {
        case (none) { ret n; }
        case (some(?m)) { auto m_ = m; be find(ufnd, m_); }
    }
}

fn union(&ufind ufnd, uint m, uint n) {
    auto m_root = find(ufnd, m);
    auto n_root = find(ufnd, n);
    if (m_root < n_root) {
        ufnd.nodes.(n_root) = some[uint](m_root);
    } else if (m_root > n_root) { ufnd.nodes.(m_root) = some[uint](n_root); }
}

fn set_count(&ufind ufnd) -> uint { ret vec::len[node](ufnd.nodes); }

// Removes all sets with IDs greater than or equal to the given value.
fn prune(&ufind ufnd, uint n) {
    // TODO: Use "slice" once we get rid of "mutable?"

    auto len = vec::len[node](ufnd.nodes);
    while (len != n) { vec::pop[node](ufnd.nodes); len -= 1u; }
}<commit_msg>stdlib: Remove old botch from ufind<commit_after>
import option::none;
import option::some;

// A very naive implementation of union-find with unsigned integer nodes.
// Maintains the invariant that the root of a node is always equal to or less
// than the node itself.
type node = option::t[uint];

type ufind = rec(mutable vec[mutable node] nodes);

fn make() -> ufind {
    ret rec(mutable nodes=[mutable]);
}

fn make_set(&ufind ufnd) -> uint {
    auto idx = vec::len(ufnd.nodes);
    ufnd.nodes += [mutable none[uint]];
    ret idx;
}

/// Creates sets as necessary to ensure that least `n` sets are present in the
/// data structure.
fn grow(&ufind ufnd, uint n) {
    while (set_count(ufnd) < n) { make_set(ufnd); }
}

fn find(&ufind ufnd, uint n) -> uint {
    alt (ufnd.nodes.(n)) {
        case (none) { ret n; }
        case (some(?m)) { auto m_ = m; be find(ufnd, m_); }
    }
}

fn union(&ufind ufnd, uint m, uint n) {
    auto m_root = find(ufnd, m);
    auto n_root = find(ufnd, n);
    if (m_root < n_root) {
        ufnd.nodes.(n_root) = some[uint](m_root);
    } else if (m_root > n_root) { ufnd.nodes.(m_root) = some[uint](n_root); }
}

fn set_count(&ufind ufnd) -> uint { ret vec::len[node](ufnd.nodes); }

// Removes all sets with IDs greater than or equal to the given value.
fn prune(&ufind ufnd, uint n) {
    // TODO: Use "slice" once we get rid of "mutable?"

    auto len = vec::len[node](ufnd.nodes);
    while (len != n) { vec::pop[node](ufnd.nodes); len -= 1u; }
}
<|endoftext|>


<commit_before>
use std::collections::HashMap;
use std::sync::{Arc,Mutex};
use std::sync::mpsc::Sender;
use snowflake::ProcessUniqueId;

#[derive(Debug,Clone,Eq,PartialEq,Hash)]
pub struct Subscription(ProcessUniqueId);

impl Subscription {
    fn new() -> Subscription {
        Subscription(ProcessUniqueId::new())
    }
}

#[derive(Clone)]
pub struct ListenerSet<T> where T: Send {
    listeners: Arc<Mutex<HashMap<Subscription, Sender<T>>>>,
}

impl<T> ListenerSet<T> where T: Send + Clone {
    pub fn new() -> Self {
        ListenerSet{
            listeners: Arc::new(Mutex::new(HashMap::new())),
        }
    }

    pub fn subscribe(&self, listener: Sender<T>) -> Subscription {
        let mut acquired_listeners = self.listeners.lock().unwrap();

        let subscription = Subscription::new();
        acquired_listeners.insert(subscription.clone(), listener);

        subscription
    }

    pub fn unsubscribe(&self, sub: Subscription) {
        let mut acquired_listeners = self.listeners.lock().unwrap();

        // channel will be close here automatically
        acquired_listeners.remove(&sub);
    }

    pub fn notify(&self, payload: &T) {
        let acquired_listeners = self.listeners.lock().unwrap();

        for listener in acquired_listeners.iter() {
            Self::notify_listener(listener.1, payload);
        }
    }

    fn notify_listener(chan: &Sender<T>, payload: &T) {
        chan.send(payload.clone());
    }
}

#[cfg(test)]
mod tests {
    use super::{ListenerSet,Subscription};
    use std::sync::mpsc;

    #[test]
    fn test_new_listener_set() {
        let ls = ListenerSet::<()>::new();
    }

    #[test]
    fn test_new_listener_for_chan() {
        let (tx, _rx) = mpsc::channel();
        let ls = ListenerSet::<bool>::new();

        ls.subscribe(tx);
    }

    #[test]
    fn test_add_listener_to_set() {
        let (tx, rx) = mpsc::channel();
        let ls = ListenerSet::<bool>::new();

        ls.subscribe(tx);
        ls.notify(&true);

        assert_eq!(rx.recv().is_ok(), true);
    }

    #[test]
    fn test_remove_listener_from_set() {
        let (tx, rx) = mpsc::channel();
        let ls = ListenerSet::<bool>::new();

        let sub = ls.subscribe(tx);
        ls.unsubscribe(sub);

        ls.notify(&true);

        assert_eq!(rx.recv().is_err(), true);
    }
}
<commit_msg>silently unsubscribe close channels and cleanup some warnings<commit_after>
use std::collections::HashMap;
use std::sync::{Arc,Mutex};
use std::sync::mpsc::Sender;
use snowflake::ProcessUniqueId;

#[derive(Debug,Clone,Copy,Eq,PartialEq,Hash)]
pub struct Subscription(ProcessUniqueId);

impl Subscription {
    fn new() -> Subscription {
        Subscription(ProcessUniqueId::new())
    }
}

type ListenerMap<T> = HashMap<Subscription, Sender<T>>;

#[derive(Clone)]
pub struct ListenerSet<T> where T: Send {
    listeners: Arc<Mutex<ListenerMap<T>>>,
}

impl<T> ListenerSet<T> where T: Send + Clone {
    pub fn new() -> Self {
        ListenerSet{
            listeners: Arc::new(Mutex::new(ListenerMap::new())),
        }
    }

    pub fn subscribe(&self, listener: Sender<T>) -> Subscription {
        let mut acquired_listeners = self.listeners.lock().unwrap();

        let subscription = Subscription::new();
        acquired_listeners.insert(subscription, listener);

        subscription
    }

    pub fn unsubscribe(&self, sub: Subscription) {
        let mut acquired_listeners = self.listeners.lock().unwrap();

        // channel will be close here automatically
        acquired_listeners.remove(&sub);
    }

    pub fn notify(&self, payload: &T) {
        let mut acquired_listeners = self.listeners.lock().unwrap();

        let failures = self.notify_listeners(&*acquired_listeners, payload);

        for failure in failures {
            acquired_listeners.remove(&failure);
        }
    }

    fn notify_listeners(&self, listeners: &ListenerMap<T>, payload: &T) -> Vec<Subscription> {
        let mut failures = vec![];
        for listener in listeners.iter() {
            if !self.notify_listener(&listener.1, payload) {
                failures.push(*listener.0);
            }
        }
        failures
    }

    fn notify_listener(&self, chan: &Sender<T>, payload: &T) -> bool {
        match chan.send(payload.clone()) {
            Ok(_) => true,
            _ => false
        }
    }

    pub fn len(&self) -> usize {
        self.listeners.lock().unwrap().len()
    }
}

#[cfg(test)]
mod tests {
    use super::{ListenerSet};
    use std::sync::mpsc;

    #[test]
    fn test_new_listener_set() {
        let ls = ListenerSet::<()>::new();
        assert_eq!(ls.len(), 0);
    }

    #[test]
    fn test_new_listener_for_chan() {
        let (tx, _rx) = mpsc::channel();
        let ls = ListenerSet::<bool>::new();

        ls.subscribe(tx);
        assert_eq!(ls.len(), 1);
    }

    #[test]
    fn test_add_listener_to_set() {
        let (tx, rx) = mpsc::channel();
        let ls = ListenerSet::<bool>::new();

        ls.subscribe(tx);
        assert_eq!(ls.len(), 1);

        ls.notify(&true);
        assert_eq!(rx.recv().is_ok(), true);
    }

    #[test]
    fn test_remove_listener_from_set() {
        let (tx, rx) = mpsc::channel();
        let ls = ListenerSet::<bool>::new();

        let sub = ls.subscribe(tx);
        ls.unsubscribe(sub);
        assert_eq!(ls.len(), 0);

        ls.notify(&true);
        assert_eq!(rx.recv().is_err(), true);
    }

    #[test]
    fn test_scoped_unsubscribe() {
        let ls = ListenerSet::<bool>::new();

        {
            let (tx, _rx) = mpsc::channel();
            let _sub = ls.subscribe(tx);
            assert_eq!(ls.len(), 1);
        }

        assert_eq!(ls.len(), 1);

        ls.notify(&true);
        assert_eq!(ls.len(), 0);
    }
}
<|endoftext|>


<commit_before>#![allow(unused)]

macro_rules! log {
    (target: $target:expr, $lvl:expr, $($arg:tt)+) => {
        let _ = $target;
        let _ = log!($lvl, $($arg)+);
    }
    ($lvl:expr, $($arg:tt)+) => {
        let _ = $lvl;
        let _ = format_args!($($arg)+);
    }
}
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! warn {
    (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! debug {
    (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! trace {
    (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
<commit_msg>Fix repetetion<commit_after>#![allow(unused)]

macro_rules! log {
    (target: $target:expr, $lvl:expr, $($arg:tt)+) => {
        let _ = $target;
        let _ = log!($lvl, $($arg)+);
    }
    ($lvl:expr, $($arg:tt)+) => {
        let _ = $lvl;
        let _ = format_args!($($arg)+);
    }
}
macro_rules! error {
    (target: $target:expr, $($arg:tt)+) => { log!(target: $target, "", $($arg)+); }
    ($($arg:tt)+) => { log!("", $($arg)+); }
}
macro_rules! warn {
    (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! info {
    (target: $target:expr, $($arg:tt)+) => { log!(target: $target, "", $($arg)+); }
    ($($arg:tt)+) => { log!("", $($arg)+); }
}
macro_rules! debug {
    (target: $target:expr, $($arg:tt)+) => { log!(target: $target, "", $($arg)+); }
    ($($arg:tt)+) => { log!("", $($arg)+); }
}
macro_rules! trace {
    (target: $target:expr, $($arg:tt)+) => { log!(target: $target, "", $($arg)+); }
    ($($arg:tt)+) => { log!("", $($arg)+); }
}
<|endoftext|>


<commit_before>/*!

Experimental BWT-DC compression model

*/

use std::{cmp, io};
use compress::entropy::ari;

/// Coding model for BWT-DC output
pub struct Model {
	bin_zero	: ari::bin::Model,
	table_log	: ari::table::Model,
	bin_rest	: [ari::bin::Model, ..4],
}

impl Model {
	/// Create a new model with a given max probability threshold
	pub fn new(threshold: ari::Border) -> Model {
		let num_logs = 24;
		Model {
			bin_zero	: ari::bin::Model::new_flat(threshold, 5),
			table_log	: ari::table::Model::new_custom(num_logs, threshold, |i| {
				1<<(10 - cmp::min(10,i))
			}),
			bin_rest	: [ari::bin::Model::new_flat(threshold, 5), ..4],
		}
	}
}

impl super::DistanceModel for Model {
	fn new_default() -> Model {
		Model::new(ari::RANGE_DEFAULT_THRESHOLD >> 2)
	}

	fn reset(&mut self) {
		self.bin_zero.reset_flat();
		self.table_log.reset_flat();
		for bm in self.bin_rest.mut_iter() {
			bm.reset_flat();
		}
	}

	fn encode<W: io::Writer>(&mut self, dist: super::Distance, _ctx: &super::Context, eh: &mut ari::Encoder<W>) {
		let bone = dist != 0;
		eh.encode(bone, &self.bin_zero).unwrap();
		self.bin_zero.update(bone);
		if !bone {
			return
		}
		fn int_log(d: super::Distance) -> uint {
			let mut log = 0;
			while d>>log !=0 {log += 1;}
			log
		}
		let log = int_log(dist);
		// write exponent
		eh.encode(log-1, &self.table_log).unwrap();
		self.table_log.update(log-1, 10, 1);
		// write mantissa
		for i in range(1,log) {
			let bit = (dist>>(log-i-1)) as uint & 1 != 0;
			if i >= self.bin_rest.len() {
				// just send bits past the model, equally distributed
				eh.encode(bit, self.bin_rest.last().unwrap()).unwrap();
			}else {
				let bc = &mut self.bin_rest[i-1];
				eh.encode(bit, bc).unwrap();
				bc.update(bit);
			};
		}
	}

	fn decode<R: io::Reader>(&mut self, _ctx: &super::Context, dh: &mut ari::Decoder<R>) -> super::Distance {
		let bone = dh.decode(&self.bin_zero).unwrap();
		self.bin_zero.update(bone);
		if !bone {
			return 0
		}
		let log = dh.decode(&self.table_log).unwrap() + 1;
		self.table_log.update(log-1, 10, 1);
		let mut dist = 1 as super::Distance;
		for i in range(1,log) {
			let bit = if i >= self.bin_rest.len() {
				dh.decode( self.bin_rest.last().unwrap() ).unwrap()
			}else {
				let bc = &mut self.bin_rest[i-1];
				let bit = dh.decode(bc).unwrap();
				bc.update(bit);
				bit
			};
			dist = (dist<<1) + (bit as super::Distance);
		}
		dist
	}
}
<commit_msg>Exp model is reimplemented to a simple bit model, using apm::Bit<commit_after>/*!

Experimental BWT-DC compression model

*/

use std::io;
use compress::entropy::ari;

/// Coding model for BWT-DC output
pub struct Model {
	bits	: [ari::apm::Bit, ..24],
}

impl Model {
	/// Create a new model
	pub fn new() -> Model {
		Model {
			bits	: [ari::apm::Bit::new_equal(), ..24],
		}
	}
}

impl super::DistanceModel for Model {
	fn new_default() -> Model {
		Model::new()
	}

	fn reset(&mut self) {
		for bit in self.bits.mut_iter() {
			*bit = ari::apm::Bit::new_equal();
		}
	}

	fn encode<W: io::Writer>(&mut self, dist: super::Distance, _ctx: &super::Context, eh: &mut ari::Encoder<W>) {
		for (i,bit) in self.bits.mut_iter().enumerate().rev() {
			let value = dist & (1<<i) != 0;
			eh.encode(value, bit).unwrap();
			bit.update(value, 5, 0);
		}
	}

	fn decode<R: io::Reader>(&mut self, _ctx: &super::Context, dh: &mut ari::Decoder<R>) -> super::Distance {
		self.bits.mut_iter().rev().fold(0 as super::Distance, |u,bit| {
			let value = dh.decode(bit).unwrap();
			bit.update(value, 5, 0);
			(u<<1) + if value {1} else {0}
		})
	}
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_types::vm_status::StatusCode;
use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
use std::fmt::Formatter;

/// This is the generic struct we use for all API errors, it contains a string
/// message and an Aptos API specific error code.
#[derive(Debug, Clone, Serialize, Deserialize, Object)]
pub struct AptosError {
    /// A message describing the error
    pub message: String,
    /// A code providing more granular error information beyond the HTTP status code
    pub error_code: AptosErrorCode,
    /// A code providing VM error details when submitting transactions to the VM
    #[serde(skip_serializing_if = "Option::is_none")]
    pub vm_error_code: Option<u64>,
}

impl std::fmt::Display for AptosError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "Error({:?}): {}", self.error_code, self.message)
    }
}

impl std::error::Error for AptosError {}

impl AptosError {
    pub fn new_with_error_code<ErrorType: std::fmt::Display>(
        error: ErrorType,
        error_code: AptosErrorCode,
    ) -> AptosError {
        Self {
            message: error.to_string(),
            error_code,
            vm_error_code: None,
        }
    }

    pub fn new_with_vm_status<ErrorType: std::fmt::Display>(
        error: ErrorType,
        error_code: AptosErrorCode,
        vm_error_code: StatusCode,
    ) -> AptosError {
        Self {
            message: error.to_string(),
            error_code,
            vm_error_code: Some(vm_error_code as u64),
        }
    }
}

/// These codes provide more granular error information beyond just the HTTP
/// status code of the response.
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Enum)]
#[oai(rename_all = "snake_case")]
#[serde(rename_all = "snake_case")]
#[repr(u32)]
pub enum AptosErrorCode {
    /// Account not found at the requested version
    AccountNotFound = 101,
    /// Resource not found at the requested version
    ResourceNotFound = 102,
    /// Module not found at the requested version
    ModuleNotFound = 103,
    /// Struct field not found at the requested version
    StructFieldNotFound = 104,
    /// Ledger version not found at the requested version
    ///
    /// Usually means that the version is ahead of the latest version
    VersionNotFound = 105,
    /// Transaction not found at the requested version or with the requested hash
    TransactionNotFound = 106,
    /// Table item not found at the requested version
    TableItemNotFound = 107,
    /// Block not found at the requested version or height
    ///
    /// Usually means the block is fully or partially pruned or the height / version is ahead
    /// of the latest version
    BlockNotFound = 108,

    /// Ledger version is pruned
    VersionPruned = 200,
    /// Block is fully or partially pruned
    BlockPruned = 201,

    /// The API's inputs were invalid
    InvalidInput = 300,

    /// The transaction was an invalid update to an already submitted transaction.
    InvalidTransactionUpdate = 401,
    /// The sequence number for the transaction is behind the latest sequence number.
    SequenceNumberTooOld = 402,
    /// The submitted transaction failed VM checks.
    VmError = 403,

    /// Health check failed.
    HealthCheckFailed = 500,
    /// The mempool is full, no new transactions can be submitted.
    MempoolIsFull = 501,

    /// Internal server error
    InternalError = 600,
    /// Error from the web framework
    WebFrameworkError = 601,
    /// BCS format is not supported on this API.
    BcsNotSupported = 602,
    /// API Disabled
    ApiDisabled = 603,
}

impl AptosErrorCode {
    pub fn as_u32(&self) -> u32 {
        *self as u32
    }
}
<commit_msg>[api] Fix response for submit_batch transactions (#3950)<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_types::vm_status::StatusCode;
use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
use std::fmt::Formatter;

/// This is the generic struct we use for all API errors, it contains a string
/// message and an Aptos API specific error code.
#[derive(Debug, Clone, Serialize, Deserialize, Object)]
pub struct AptosError {
    /// A message describing the error
    pub message: String,
    /// A code providing more granular error information beyond the HTTP status code
    pub error_code: AptosErrorCode,
    /// A code providing VM error details when submitting transactions to the VM
    pub vm_error_code: Option<u64>,
}

impl std::fmt::Display for AptosError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "Error({:?}): {}", self.error_code, self.message)
    }
}

impl std::error::Error for AptosError {}

impl AptosError {
    pub fn new_with_error_code<ErrorType: std::fmt::Display>(
        error: ErrorType,
        error_code: AptosErrorCode,
    ) -> AptosError {
        Self {
            message: error.to_string(),
            error_code,
            vm_error_code: None,
        }
    }

    pub fn new_with_vm_status<ErrorType: std::fmt::Display>(
        error: ErrorType,
        error_code: AptosErrorCode,
        vm_error_code: StatusCode,
    ) -> AptosError {
        Self {
            message: error.to_string(),
            error_code,
            vm_error_code: Some(vm_error_code as u64),
        }
    }
}

/// These codes provide more granular error information beyond just the HTTP
/// status code of the response.
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Enum)]
#[oai(rename_all = "snake_case")]
#[serde(rename_all = "snake_case")]
#[repr(u32)]
pub enum AptosErrorCode {
    /// Account not found at the requested version
    AccountNotFound = 101,
    /// Resource not found at the requested version
    ResourceNotFound = 102,
    /// Module not found at the requested version
    ModuleNotFound = 103,
    /// Struct field not found at the requested version
    StructFieldNotFound = 104,
    /// Ledger version not found at the requested version
    ///
    /// Usually means that the version is ahead of the latest version
    VersionNotFound = 105,
    /// Transaction not found at the requested version or with the requested hash
    TransactionNotFound = 106,
    /// Table item not found at the requested version
    TableItemNotFound = 107,
    /// Block not found at the requested version or height
    ///
    /// Usually means the block is fully or partially pruned or the height / version is ahead
    /// of the latest version
    BlockNotFound = 108,

    /// Ledger version is pruned
    VersionPruned = 200,
    /// Block is fully or partially pruned
    BlockPruned = 201,

    /// The API's inputs were invalid
    InvalidInput = 300,

    /// The transaction was an invalid update to an already submitted transaction.
    InvalidTransactionUpdate = 401,
    /// The sequence number for the transaction is behind the latest sequence number.
    SequenceNumberTooOld = 402,
    /// The submitted transaction failed VM checks.
    VmError = 403,

    /// Health check failed.
    HealthCheckFailed = 500,
    /// The mempool is full, no new transactions can be submitted.
    MempoolIsFull = 501,

    /// Internal server error
    InternalError = 600,
    /// Error from the web framework
    WebFrameworkError = 601,
    /// BCS format is not supported on this API.
    BcsNotSupported = 602,
    /// API Disabled
    ApiDisabled = 603,
}

impl AptosErrorCode {
    pub fn as_u32(&self) -> u32 {
        *self as u32
    }
}

#[test]
fn test_serialize_deserialize() {
    let with_code = AptosError::new_with_vm_status(
        "Invalid transaction",
        AptosErrorCode::VmError,
        aptos_types::vm_status::StatusCode::UNKNOWN_MODULE,
    );
    let _: AptosError = bcs::from_bytes(&bcs::to_bytes(&with_code).unwrap()).unwrap();
    let _: AptosError = serde_json::from_str(&serde_json::to_string(&with_code).unwrap()).unwrap();

    let without_code =
        AptosError::new_with_error_code("some message", AptosErrorCode::MempoolIsFull);
    let _: AptosError = bcs::from_bytes(&bcs::to_bytes(&without_code).unwrap()).unwrap();
    let _: AptosError =
        serde_json::from_str(&serde_json::to_string(&without_code).unwrap()).unwrap();
}
<|endoftext|>


<commit_before>use std::fmt;
use std::hash::{ Hash, Hasher };

#[cfg(feature = "generation")] use generation;
#[cfg(feature = "validation")] use validation;

use MultiHash::*;

#[allow(non_camel_case_types)]
pub enum MultiHash {
    Sha1([u8; 20], usize),
    Sha2_256([u8; 32], usize),
    Sha2_512([u8; 64], usize),
    Sha3_512([u8; 64], usize),
    Sha3_384([u8; 48], usize),
    Sha3_256([u8; 32], usize),
    Sha3_224([u8; 28], usize),
    Shake128(Vec<u8>),
    Shake256(Vec<u8>),
    Blake2B([u8; 64], usize),
    Blake2S([u8; 32], usize),
    ApplicationSpecific {
        code: usize,
        bytes: Vec<u8>,
    },
}

impl MultiHash {
    pub fn from_bytes<B: AsRef<[u8]>>(bytes: B) -> Result<MultiHash, &'static str> {
        let bytes = bytes.as_ref();
        let code = bytes[0] as usize;
        if code > 0x7f {
            panic!("TODO: support varints");
        }
        let length = bytes[1] as usize;
        if length > 0x7f {
            panic!("TODO: support varints");
        }
        let mut hash = try!(MultiHash::from_code_and_length(code, length));
        hash.digest_mut()[..length].copy_from_slice(&bytes[2..length+2]);
        Ok(hash)
    }

    // TODO: Real error type
    /// Returns an empty multihash of the specified type, validates code and length
    pub fn from_code_and_length(code: usize, length: usize) -> Result<MultiHash, &'static str> {
        Ok(match code {
            0x11 if length <= 20 => Sha1([0; 20], length),
            0x12 if length <= 32 => Sha2_256([0; 32], length),
            0x13 if length <= 64 => Sha2_512([0; 64], length),
            0x14 if length <= 64 => Sha3_512([0; 64], length),
            0x15 if length <= 48 => Sha3_384([0; 48], length),
            0x16 if length <= 32 => Sha3_256([0; 32], length),
            0x17 if length <= 28 => Sha3_224([0; 28], length),
            0x18 => Shake128(vec![0; length]),
            0x19 => Shake256(vec![0; length]),

            0x40 if length <= 64 => Blake2B([0; 64], length),
            0x41 if length <= 32 => Blake2S([0; 32], length),

            _ if code > 0x0400 && code < 0x040f =>
                ApplicationSpecific { code: code, bytes: vec![0; length] },
            _ => {
                return Err("MultiHash length exceeds allowed length for specified type")
            }
        })
    }

    #[cfg(all(feature = "generation"))]
    pub fn generate<D: AsRef<[u8]>>(data: D) -> MultiHash {
        generation::generate_default(data.as_ref())
    }

    #[cfg(all(feature = "generation", feature = "sha2"))]
    pub fn generate_sha256<D: AsRef<[u8]>>(data: D) -> MultiHash {
        generation::generate_sha256(data.as_ref())
    }

    #[cfg(all(feature = "generation", feature = "sha2"))]
    pub fn generate_sha512<D: AsRef<[u8]>>(data: D) -> MultiHash {
        generation::generate_sha512(data.as_ref())
    }

    pub fn len(&self) -> usize {
        match *self {
            Sha1(_, length) => length,
            Sha2_256(_, length) => length,
            Sha2_512(_, length) => length,
            Sha3_224(_, length) => length,
            Sha3_256(_, length) => length,
            Sha3_384(_, length) => length,
            Sha3_512(_, length) => length,
            Shake128(ref bytes) => bytes.len(),
            Shake256(ref bytes) => bytes.len(),
            Blake2B(_, length) => length,
            Blake2S(_, length) => length,
            ApplicationSpecific { ref bytes, .. } => bytes.len(),
        }
    }

    pub fn code(&self) -> u8 {
        match *self {
            Sha1(..) => 0x11,
            Sha2_256(..) => 0x12,
            Sha2_512(..) => 0x13,
            Sha3_512(..) => 0x14,
            Sha3_384(..) => 0x15,
            Sha3_256(..) => 0x16,
            Sha3_224(..) => 0x17,
            Shake128(..) => 0x18,
            Shake256(..) => 0x19,
            Blake2B(..) => 0x40,
            Blake2S(..) => 0x41,

            ApplicationSpecific { code, .. } if code > 0x0400 && code < 0x040f => {
                panic!("TODO: support varints");
            }

            // TODO: could just ignore them being invalid or return Error...
            ApplicationSpecific { code, .. } =>
                panic!("application specific code {:#04x} outside allowed range 0x0400-0x040f", code),
        }
    }

    pub fn name(&self) -> &'static str {
        match *self {
            Sha1(..) => "sha1",
            Sha2_256(..) => "sha2-256",
            Sha2_512(..) => "sha2-512",
            Sha3_224(..) => "sha3-224",
            Sha3_256(..) => "sha3-256",
            Sha3_384(..) => "sha3-384",
            Sha3_512(..) => "sha3-512",
            Shake128(..) => "shake-128",
            Shake256(..) => "shake-256",
            Blake2B(..) => "blake2b",
            Blake2S(..) => "blake2s",

            ApplicationSpecific { code, .. } if code > 0x0400 && code < 0x040f => "app-specific",
            _ => panic!("TODO: not panic"),
        }
    }

    /// Returns None if there is no validator for this digest type, otherwise
    /// the result of the validator
    #[cfg(feature = "validation")]
    pub fn validate<D: AsRef<[u8]>>(&self, data: D) -> Option<validation::Result> {
        validation::validate(self, data.as_ref())
    }

    pub fn digest(&self) -> &[u8] {
        match *self {
            Sha1(ref bytes, length) => &bytes[..length],
            Sha2_256(ref bytes, length) => &bytes[..length],
            Sha2_512(ref bytes, length) => &bytes[..length],
            Sha3_224(ref bytes, length) => &bytes[..length],
            Sha3_256(ref bytes, length) => &bytes[..length],
            Sha3_384(ref bytes, length) => &bytes[..length],
            Sha3_512(ref bytes, length) => &bytes[..length],
            Shake128(ref bytes) => bytes,
            Shake256(ref bytes) => bytes,
            Blake2B(ref bytes, length) => &bytes[..length],
            Blake2S(ref bytes, length) => &bytes[..length],
            ApplicationSpecific { ref bytes, .. } => bytes,
        }
    }

    pub fn digest_mut(&mut self) -> &mut [u8] {
        match *self {
            Sha1(ref mut bytes, length) => &mut bytes[..length],
            Sha2_256(ref mut bytes, length) => &mut bytes[..length],
            Sha2_512(ref mut bytes, length) => &mut bytes[..length],
            Sha3_224(ref mut bytes, length) => &mut bytes[..length],
            Sha3_256(ref mut bytes, length) => &mut bytes[..length],
            Sha3_384(ref mut bytes, length) => &mut bytes[..length],
            Sha3_512(ref mut bytes, length) => &mut bytes[..length],
            Shake128(ref mut bytes) => bytes,
            Shake256(ref mut bytes) => bytes,
            Blake2B(ref mut bytes, length) => &mut bytes[..length],
            Blake2S(ref mut bytes, length) => &mut bytes[..length],
            ApplicationSpecific { ref mut bytes, .. } => bytes,
        }
    }

    pub fn into_bytes(self) -> Vec<u8> {
        if let ApplicationSpecific { .. } = self {
            panic!("TODO: support varints");
        } else {
            self.to_bytes()
        }
    }

    pub fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::with_capacity(self.output_len());
        bytes.push(self.code());
        bytes.push(self.len() as u8);
        bytes.extend_from_slice(self.digest());
        bytes
    }

    /// The length of this multihash when serialized to a byte array/stream
    pub fn output_len(&self) -> usize {
        self.len() + 2
    }
}

impl fmt::Debug for MultiHash {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(f.write_str(self.name()));
        try!(f.write_str("(\""));
        for byte in self.digest() {
            try!(write!(f, "{:x}", byte));
        }
        try!(f.write_str("\")"));
        Ok(())
    }
}

impl Clone for MultiHash {
    fn clone(&self) -> MultiHash {
        match *self {
            Sha1(ref bytes, length) => Sha1(*bytes, length),
            Sha2_256(ref bytes, length) => Sha2_256(*bytes, length),
            Sha2_512(ref bytes, length) => Sha2_512(*bytes, length),
            Sha3_224(ref bytes, length) => Sha3_224(*bytes, length),
            Sha3_256(ref bytes, length) => Sha3_256(*bytes, length),
            Sha3_384(ref bytes, length) => Sha3_384(*bytes, length),
            Sha3_512(ref bytes, length) => Sha3_512(*bytes, length),
            Shake128(ref bytes) => Shake128(bytes.clone()),
            Shake256(ref bytes) => Shake256(bytes.clone()),
            Blake2B(ref bytes, length) => Blake2B(*bytes, length),
            Blake2S(ref bytes, length) => Blake2S(*bytes, length),
            ApplicationSpecific { code, ref bytes } => ApplicationSpecific {
                code: code,
                bytes: bytes.clone(),
            },
        }
    }
}

impl Eq for MultiHash {}
impl PartialEq for MultiHash {
    fn eq(&self, other: &MultiHash) -> bool {
        match (self, other) {
            (&Sha1(ref left, l1), &Sha1(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Sha2_256(ref left, l1), &Sha2_256(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Sha2_512(ref left, l1), &Sha2_512(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Sha3_224(ref left, l1), &Sha3_224(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Sha3_256(ref left, l1), &Sha3_256(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Sha3_384(ref left, l1), &Sha3_384(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Sha3_512(ref left, l1), &Sha3_512(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Shake128(ref left), &Shake128(ref right)) => left == right,
            (&Shake256(ref left), &Shake256(ref right)) => left == right,
            (&Blake2B(ref left, l1), &Blake2B(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Blake2S(ref left, l1), &Blake2S(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (
                &ApplicationSpecific { code: left_code, bytes: ref left },
                &ApplicationSpecific { code: right_code, bytes: ref right }
            ) => left_code == right_code && left == right,
            _ => false,
        }
    }
}

impl Hash for MultiHash {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        state.write_u8(self.code());
        state.write_usize(self.len());
        state.write(self.digest());
    }
}

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

    #[test]
    fn to_bytes() {
        let multihash = MultiHash::Sha1([
            0xde, 0xad, 0xbe, 0xef,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
        ], 4);
        assert_eq!(
            multihash.to_bytes(),
            vec![0x11, 0x04, 0xde, 0xad, 0xbe, 0xef]);
    }

    #[test]
    fn from_bytes() {
        let multihash = MultiHash::Sha1([
            0xde, 0xad, 0xbe, 0xef,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
        ], 4);
        assert_eq!(
            Ok(multihash),
            MultiHash::from_bytes([0x11, 0x04, 0xde, 0xad, 0xbe, 0xef]));
    }
}
<commit_msg>Add identity type<commit_after>use std::fmt;
use std::hash::{ Hash, Hasher };

#[cfg(feature = "generation")] use generation;
#[cfg(feature = "validation")] use validation;

use MultiHash::*;

#[allow(non_camel_case_types)]
pub enum MultiHash {
    Identity(Vec<u8>),
    Sha1([u8; 20], usize),
    Sha2_256([u8; 32], usize),
    Sha2_512([u8; 64], usize),
    Sha3_512([u8; 64], usize),
    Sha3_384([u8; 48], usize),
    Sha3_256([u8; 32], usize),
    Sha3_224([u8; 28], usize),
    Shake128(Vec<u8>),
    Shake256(Vec<u8>),
    Blake2B([u8; 64], usize),
    Blake2S([u8; 32], usize),
    ApplicationSpecific {
        code: usize,
        bytes: Vec<u8>,
    },
}

impl MultiHash {
    pub fn from_bytes<B: AsRef<[u8]>>(bytes: B) -> Result<MultiHash, &'static str> {
        let bytes = bytes.as_ref();
        let code = bytes[0] as usize;
        if code > 0x7f {
            panic!("TODO: support varints");
        }
        let length = bytes[1] as usize;
        if length > 0x7f {
            panic!("TODO: support varints");
        }
        let mut hash = try!(MultiHash::from_code_and_length(code, length));
        hash.digest_mut()[..length].copy_from_slice(&bytes[2..length+2]);
        Ok(hash)
    }

    // TODO: Real error type
    /// Returns an empty multihash of the specified type, validates code and length
    pub fn from_code_and_length(code: usize, length: usize) -> Result<MultiHash, &'static str> {
        Ok(match code {
            0x00 => Identity(vec![0; length]),
            0x11 if length <= 20 => Sha1([0; 20], length),
            0x12 if length <= 32 => Sha2_256([0; 32], length),
            0x13 if length <= 64 => Sha2_512([0; 64], length),
            0x14 if length <= 64 => Sha3_512([0; 64], length),
            0x15 if length <= 48 => Sha3_384([0; 48], length),
            0x16 if length <= 32 => Sha3_256([0; 32], length),
            0x17 if length <= 28 => Sha3_224([0; 28], length),
            0x18 => Shake128(vec![0; length]),
            0x19 => Shake256(vec![0; length]),

            0x40 if length <= 64 => Blake2B([0; 64], length),
            0x41 if length <= 32 => Blake2S([0; 32], length),

            _ if code > 0x0400 && code < 0x040f =>
                ApplicationSpecific { code: code, bytes: vec![0; length] },
            _ => {
                return Err("MultiHash length exceeds allowed length for specified type")
            }
        })
    }

    #[cfg(all(feature = "generation"))]
    pub fn generate<D: AsRef<[u8]>>(data: D) -> MultiHash {
        generation::generate_default(data.as_ref())
    }

    #[cfg(all(feature = "generation", feature = "sha2"))]
    pub fn generate_sha256<D: AsRef<[u8]>>(data: D) -> MultiHash {
        generation::generate_sha256(data.as_ref())
    }

    #[cfg(all(feature = "generation", feature = "sha2"))]
    pub fn generate_sha512<D: AsRef<[u8]>>(data: D) -> MultiHash {
        generation::generate_sha512(data.as_ref())
    }

    pub fn len(&self) -> usize {
        match *self {
            Identity(ref bytes) => bytes.len(),
            Sha1(_, length) => length,
            Sha2_256(_, length) => length,
            Sha2_512(_, length) => length,
            Sha3_224(_, length) => length,
            Sha3_256(_, length) => length,
            Sha3_384(_, length) => length,
            Sha3_512(_, length) => length,
            Shake128(ref bytes) => bytes.len(),
            Shake256(ref bytes) => bytes.len(),
            Blake2B(_, length) => length,
            Blake2S(_, length) => length,
            ApplicationSpecific { ref bytes, .. } => bytes.len(),
        }
    }

    pub fn code(&self) -> u8 {
        match *self {
            Identity(..) => 0x00,
            Sha1(..) => 0x11,
            Sha2_256(..) => 0x12,
            Sha2_512(..) => 0x13,
            Sha3_512(..) => 0x14,
            Sha3_384(..) => 0x15,
            Sha3_256(..) => 0x16,
            Sha3_224(..) => 0x17,
            Shake128(..) => 0x18,
            Shake256(..) => 0x19,
            Blake2B(..) => 0x40,
            Blake2S(..) => 0x41,

            ApplicationSpecific { code, .. } if code > 0x0400 && code < 0x040f => {
                panic!("TODO: support varints");
            }

            // TODO: could just ignore them being invalid or return Error...
            ApplicationSpecific { code, .. } =>
                panic!("application specific code {:#04x} outside allowed range 0x0400-0x040f", code),
        }
    }

    pub fn name(&self) -> &'static str {
        match *self {
            Identity(..) => "identity",
            Sha1(..) => "sha1",
            Sha2_256(..) => "sha2-256",
            Sha2_512(..) => "sha2-512",
            Sha3_224(..) => "sha3-224",
            Sha3_256(..) => "sha3-256",
            Sha3_384(..) => "sha3-384",
            Sha3_512(..) => "sha3-512",
            Shake128(..) => "shake-128",
            Shake256(..) => "shake-256",
            Blake2B(..) => "blake2b",
            Blake2S(..) => "blake2s",

            ApplicationSpecific { code, .. } if code > 0x0400 && code < 0x040f => "app-specific",
            _ => panic!("TODO: not panic"),
        }
    }

    /// Returns None if there is no validator for this digest type, otherwise
    /// the result of the validator
    #[cfg(feature = "validation")]
    pub fn validate<D: AsRef<[u8]>>(&self, data: D) -> Option<validation::Result> {
        validation::validate(self, data.as_ref())
    }

    pub fn digest(&self) -> &[u8] {
        match *self {
            Identity(ref bytes) => bytes,
            Sha1(ref bytes, length) => &bytes[..length],
            Sha2_256(ref bytes, length) => &bytes[..length],
            Sha2_512(ref bytes, length) => &bytes[..length],
            Sha3_224(ref bytes, length) => &bytes[..length],
            Sha3_256(ref bytes, length) => &bytes[..length],
            Sha3_384(ref bytes, length) => &bytes[..length],
            Sha3_512(ref bytes, length) => &bytes[..length],
            Shake128(ref bytes) => bytes,
            Shake256(ref bytes) => bytes,
            Blake2B(ref bytes, length) => &bytes[..length],
            Blake2S(ref bytes, length) => &bytes[..length],
            ApplicationSpecific { ref bytes, .. } => bytes,
        }
    }

    pub fn digest_mut(&mut self) -> &mut [u8] {
        match *self {
            Identity(ref mut bytes) => bytes,
            Sha1(ref mut bytes, length) => &mut bytes[..length],
            Sha2_256(ref mut bytes, length) => &mut bytes[..length],
            Sha2_512(ref mut bytes, length) => &mut bytes[..length],
            Sha3_224(ref mut bytes, length) => &mut bytes[..length],
            Sha3_256(ref mut bytes, length) => &mut bytes[..length],
            Sha3_384(ref mut bytes, length) => &mut bytes[..length],
            Sha3_512(ref mut bytes, length) => &mut bytes[..length],
            Shake128(ref mut bytes) => bytes,
            Shake256(ref mut bytes) => bytes,
            Blake2B(ref mut bytes, length) => &mut bytes[..length],
            Blake2S(ref mut bytes, length) => &mut bytes[..length],
            ApplicationSpecific { ref mut bytes, .. } => bytes,
        }
    }

    pub fn into_bytes(self) -> Vec<u8> {
        if let ApplicationSpecific { .. } = self {
            panic!("TODO: support varints");
        } else {
            self.to_bytes()
        }
    }

    pub fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::with_capacity(self.output_len());
        bytes.push(self.code());
        bytes.push(self.len() as u8);
        bytes.extend_from_slice(self.digest());
        bytes
    }

    /// The length of this multihash when serialized to a byte array/stream
    pub fn output_len(&self) -> usize {
        self.len() + 2
    }
}

impl fmt::Debug for MultiHash {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(f.write_str(self.name()));
        try!(f.write_str("(\""));
        for byte in self.digest() {
            try!(write!(f, "{:x}", byte));
        }
        try!(f.write_str("\")"));
        Ok(())
    }
}

impl Clone for MultiHash {
    fn clone(&self) -> MultiHash {
        match *self {
            Identity(ref bytes) => Identity(bytes.clone()),
            Sha1(ref bytes, length) => Sha1(*bytes, length),
            Sha2_256(ref bytes, length) => Sha2_256(*bytes, length),
            Sha2_512(ref bytes, length) => Sha2_512(*bytes, length),
            Sha3_224(ref bytes, length) => Sha3_224(*bytes, length),
            Sha3_256(ref bytes, length) => Sha3_256(*bytes, length),
            Sha3_384(ref bytes, length) => Sha3_384(*bytes, length),
            Sha3_512(ref bytes, length) => Sha3_512(*bytes, length),
            Shake128(ref bytes) => Shake128(bytes.clone()),
            Shake256(ref bytes) => Shake256(bytes.clone()),
            Blake2B(ref bytes, length) => Blake2B(*bytes, length),
            Blake2S(ref bytes, length) => Blake2S(*bytes, length),
            ApplicationSpecific { code, ref bytes } => ApplicationSpecific {
                code: code,
                bytes: bytes.clone(),
            },
        }
    }
}

impl Eq for MultiHash {}
impl PartialEq for MultiHash {
    fn eq(&self, other: &MultiHash) -> bool {
        match (self, other) {
            (&Identity(ref left), &Identity(ref right)) => left == right,
            (&Sha1(ref left, l1), &Sha1(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Sha2_256(ref left, l1), &Sha2_256(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Sha2_512(ref left, l1), &Sha2_512(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Sha3_224(ref left, l1), &Sha3_224(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Sha3_256(ref left, l1), &Sha3_256(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Sha3_384(ref left, l1), &Sha3_384(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Sha3_512(ref left, l1), &Sha3_512(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Shake128(ref left), &Shake128(ref right)) => left == right,
            (&Shake256(ref left), &Shake256(ref right)) => left == right,
            (&Blake2B(ref left, l1), &Blake2B(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (&Blake2S(ref left, l1), &Blake2S(ref right, l2)) => l1 == l2 && left[..l1] == right[..l2],
            (
                &ApplicationSpecific { code: left_code, bytes: ref left },
                &ApplicationSpecific { code: right_code, bytes: ref right }
            ) => left_code == right_code && left == right,
            _ => false,
        }
    }
}

impl Hash for MultiHash {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        state.write_u8(self.code());
        state.write_usize(self.len());
        state.write(self.digest());
    }
}

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

    #[test]
    fn to_bytes() {
        let multihash = MultiHash::Sha1([
            0xde, 0xad, 0xbe, 0xef,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
        ], 4);
        assert_eq!(
            multihash.to_bytes(),
            vec![0x11, 0x04, 0xde, 0xad, 0xbe, 0xef]);
    }

    #[test]
    fn from_bytes() {
        let multihash = MultiHash::Sha1([
            0xde, 0xad, 0xbe, 0xef,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
        ], 4);
        assert_eq!(
            Ok(multihash),
            MultiHash::from_bytes([0x11, 0x04, 0xde, 0xad, 0xbe, 0xef]));
    }
}
<|endoftext|>