<commit_before>use crate::patches::Move;

use super::prelude::*;
use itertools::Itertools;
use similar::{ChangeTag, TextDiff};
use std::any::{type_name, Any};
use std::collections::hash_map::Entry;
use std::collections::{HashMap, VecDeque};
use std::iter::FromIterator;
use std::ops::Deref;

impl Diffable for String {
    diffable_is_same!(String);

    fn is_equal(&self, other: &Self) -> Result<()> {
        if self == other {
            Ok(())
        } else {
            bail!(Error::NotEqual)
        }
    }

    diffable_diff!(String);

    fn diff_same(&self, differ: &mut Differ, other: &Self) {
        if self == other {
            return;
        }

        let diff = TextDiff::from_chars(self, other);
        let mut ops: Vec<Operation> = Vec::new();
        let mut last: char = 'e';
        let mut curr: char = 'e';
        let mut next: char = 'e';
        let mut position = 0;
        let mut key: usize = 0;
        let mut items: usize = 0;
        let mut value: String = String::new();
        let mut adds: HashMap<String, usize> = HashMap::new();
        let mut removes: HashMap<String, usize> = HashMap::new();

        let changes = diff.iter_all_changes().collect_vec();
        for (index, change) in changes.iter().enumerate() {
            match change.tag() {
                ChangeTag::Equal => {
                    position += 1;
                    next = 'e';
                }
                ChangeTag::Delete => match curr {
                    'd' => {
                        items += 1;
                        value.push_str(change.value());
                    }
                    _ => {
                        next = 'd';
                        key = position;
                        items = 1;
                        value = change.value().into();
                    }
                },
                ChangeTag::Insert => {
                    match curr {
                        'i' => {
                            value.push_str(change.value());
                        }
                        _ => {
                            next = 'i';
                            if last != 'd' {
                                key = position;
                            }
                            value = change.value().into();
                        }
                    }
                    position += 1;
                }
            }

            let end = index == changes.len() - 1;
            if next != curr || end {
                // Generate a keys for a string position index
                fn keys(index: usize) -> VecDeque<Key> {
                    VecDeque::from_iter(vec![Key::Index(index)])
                }

                match if end { next } else { curr } {
                    'd' => {
                        if next != 'i' {
                            if let Entry::Occupied(entry) = adds.entry(value.clone()) {
                                let index = *entry.get();
                                let move_ = if let Some(Operation::Add(add)) = ops.get(index) {
                                    Operation::Move(Move {
                                        from: keys(position - value.len()),
                                        items,
                                        to: add.keys.clone(),
                                    })
                                } else {
                                    unreachable!()
                                };
                                ops.remove(index);
                                ops.push(move_);
                                entry.remove_entry();
                            } else {
                                ops.push(Operation::Remove(Remove {
                                    keys: keys(key),
                                    items,
                                }));
                                removes.insert(value.clone(), ops.len() - 1);
                            }
                        }
                    }
                    'i' => {
                        if last == 'd' || end && curr == 'd' {
                            ops.push(Operation::Replace(Replace {
                                keys: keys(key),
                                items,
                                value: Box::new(value.clone()),
                            }));
                        }
                        if let Entry::Occupied(entry) = removes.entry(value.clone()) {
                            let index = *entry.get();
                            let move_ = if let Some(Operation::Remove(remove)) = ops.get(index) {
                                Operation::Move(Move {
                                    from: remove.keys.clone(),
                                    items: remove.items,
                                    to: keys(position - value.len()),
                                })
                            } else {
                                unreachable!()
                            };
                            ops.remove(index);
                            ops.push(move_);
                            entry.remove_entry();
                        } else {
                            ops.push(Operation::Add(Add {
                                keys: keys(key),
                                value: Box::new(value.clone()),
                            }));
                            adds.insert(value.clone(), ops.len() - 1);
                        }
                    }
                    _ => {}
                };

                last = curr;
            }

            curr = next;
        }

        differ.append(ops)
    }

    fn apply_add(&mut self, keys: &mut Keys, value: &Box<dyn Any>) {
        let value = if let Some(value) = value.deref().downcast_ref::<Self>() {
            value
        } else {
            unreachable!("Invalid replacement value for {}", type_name::<Self>())
        };

        if let Some(Key::Index(index)) = keys.pop_front() {
            self.insert_str(index, value)
        } else {
            invalid_keys!(keys)
        }
    }

    fn apply_remove(&mut self, keys: &mut Keys, items: usize) {
        if let Some(Key::Index(index)) = keys.pop_front() {
            self.replace_range(index..(index + items), "")
        } else {
            invalid_keys!(keys)
        }
    }

    fn apply_move(&mut self, from: &mut Keys, items: usize, to: &mut Keys) {
        if let (Some(Key::Index(from)), Some(Key::Index(to))) = (from.pop_front(), to.pop_front()) {
            let chars: Vec<char> = self.chars().collect();
            let chars = if from < to {
                [
                    &chars[..from],
                    &chars[(from + items)..(to + items)],
                    &chars[from..(from + items)],
                    &chars[(to + items)..],
                ]
                .concat()
            } else {
                [
                    &chars[..to],
                    &chars[from..(from + items)],
                    &chars[to..from],
                    &chars[(from + items)..],
                ]
                .concat()
            };
            *self = chars.into_iter().collect();
        } else {
            invalid_keys!(from)
        }
    }

    fn apply_replace(&mut self, keys: &mut Keys, items: usize, value: &Box<dyn Any>) {
        let value = if let Some(value) = value.deref().downcast_ref::<Self>() {
            value
        } else {
            unreachable!("Invalid replacement value for {}", type_name::<Self>())
        };

        if keys.is_empty() {
            *self = value.clone();
        } else if let Some(Key::Index(index)) = keys.pop_front() {
            self.replace_range(index..(index + items), value);
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::{
        assert_json,
        patches::{apply_new, diff, equal},
    };
    use pretty_assertions::assert_eq;

    #[test]
    fn test_string() {
        let empty = "".to_string();
        let a = "1".to_string();
        let b = "123".to_string();
        let c = "a2b3".to_string();
        let d = "abcdef".to_string();
        let e = "adefbc".to_string();
        let f = "adbcfe".to_string();

        assert!(equal(&empty, &empty));
        assert!(equal(&a, &a));
        assert!(equal(&b, &b));
        assert!(equal(&c, &c));
        assert!(equal(&d, &d));

        // No diff

        assert_json!(diff(&empty, &empty), []);
        assert_json!(diff(&a, &a), []);
        assert_json!(diff(&d, &d), []);

        // Add

        let patch = diff(&empty, &a);
        assert_json!(
            patch,
            [{ "op": "add", "keys": [0], "value": "1" }]
        );
        assert_eq!(apply_new(&empty, &patch), a);

        let patch = diff(&empty, &d);
        assert_json!(
            patch,
            [{ "op": "add", "keys": [0], "value": "abcdef" }]
        );
        assert_eq!(apply_new(&empty, &patch), d);

        let patch = diff(&a, &b);
        assert_json!(
            patch,
            [{ "op": "add", "keys": [1], "value": "23" }]
        );
        assert_eq!(apply_new(&a, &patch), b);

        // Remove

        let patch = diff(&a, &empty);
        assert_json!(
            patch,
            [{ "op": "remove", "keys": [0], "items": 1 }]
        );

        let patch = diff(&d, &empty);
        assert_json!(
            patch,
            [{ "op": "remove", "keys": [0], "items": 6 }]
        );

        let patch = diff(&b, &a);
        assert_json!(
            patch,
            [{ "op": "remove", "keys": [1], "items": 2 }]
        );

        // Replace

        let patch = diff(&a, &c);
        assert_json!(
            patch,
            [{ "op": "replace", "keys": [0], "items": 1, "value": "a2b3" }]
        );
        assert_eq!(apply_new(&a, &patch), c);

        let patch = diff(&b, &d);
        assert_json!(
            patch,
            [{ "op": "replace", "keys": [0], "items": 3, "value": "abcdef" }]
        );
        assert_eq!(apply_new(&b, &patch), d);

        // Move

        let patch = diff(&d, &e);
        assert_json!(
            patch,
            [
                { "op": "move", "from": [1], "items": 2, "to": [4] },
            ]
        );
        assert_eq!(apply_new(&d, &patch), e);

        let patch = diff(&e, &d);
        assert_json!(
            patch,
            [
                { "op": "move", "from": [4], "items": 2, "to": [1] },
            ]
        );
        assert_eq!(apply_new(&e, &patch), d);

        // Mixed

        let patch = diff(&c, &d);
        assert_json!(
            patch,
            [
                { "op": "remove", "keys": [1], "items": 1 },
                { "op": "replace", "keys": [2], "items": 1, "value": "cdef" }
            ]
        );
        assert_eq!(apply_new(&c, &patch), d);

        let patch = diff(&d, &c);
        assert_json!(
            patch,
            [
                { "op": "add", "keys": [1], "value": "2" },
                { "op": "replace", "keys": [3], "items": 4, "value": "3" }
            ]
        );
        assert_eq!(apply_new(&d, &patch), c);

        let patch = diff(&d, &f);
        assert_json!(
            patch,
            [
                { "op": "add", "keys": [1], "value": "d" },
                { "op": "replace", "keys": [4], "items": 1, "value": "f" },
                { "op": "remove", "keys": [6], "items": 1 }
            ]
        );
        assert_eq!(apply_new(&d, &patch), f);
    }
}
<commit_msg>fix(String patches): Ignore linter warning which broke tests<commit_after>use crate::patches::Move;

use super::prelude::*;
use itertools::Itertools;
use similar::{ChangeTag, TextDiff};
use std::any::{type_name, Any};
use std::collections::hash_map::Entry;
use std::collections::{HashMap, VecDeque};
use std::iter::FromIterator;
use std::ops::Deref;

impl Diffable for String {
    diffable_is_same!(String);

    fn is_equal(&self, other: &Self) -> Result<()> {
        if self == other {
            Ok(())
        } else {
            bail!(Error::NotEqual)
        }
    }

    diffable_diff!(String);

    fn diff_same(&self, differ: &mut Differ, other: &Self) {
        if self == other {
            return;
        }

        let diff = TextDiff::from_chars(self, other);
        let mut ops: Vec<Operation> = Vec::new();
        let mut last: char = 'e';
        let mut curr: char = 'e';
        let mut next: char = 'e';
        let mut position = 0;
        let mut key: usize = 0;
        let mut items: usize = 0;
        let mut value: String = String::new();
        let mut adds: HashMap<String, usize> = HashMap::new();
        let mut removes: HashMap<String, usize> = HashMap::new();

        let changes = diff.iter_all_changes().collect_vec();
        for (index, change) in changes.iter().enumerate() {
            match change.tag() {
                ChangeTag::Equal => {
                    position += 1;
                    next = 'e';
                }
                ChangeTag::Delete => match curr {
                    'd' => {
                        items += 1;
                        value.push_str(change.value());
                    }
                    _ => {
                        next = 'd';
                        key = position;
                        items = 1;
                        value = change.value().into();
                    }
                },
                ChangeTag::Insert => {
                    match curr {
                        'i' => {
                            value.push_str(change.value());
                        }
                        _ => {
                            next = 'i';
                            if last != 'd' {
                                key = position;
                            }
                            value = change.value().into();
                        }
                    }
                    position += 1;
                }
            }

            let end = index == changes.len() - 1;
            if next != curr || end {
                // Generate a keys for a string position index
                fn keys(index: usize) -> VecDeque<Key> {
                    VecDeque::from_iter(vec![Key::Index(index)])
                }

                match if end { next } else { curr } {
                    'd' => {
                        if next != 'i' {
                            if let Entry::Occupied(entry) = adds.entry(value.clone()) {
                                let index = *entry.get();
                                let move_ = if let Some(Operation::Add(add)) = ops.get(index) {
                                    Operation::Move(Move {
                                        from: keys(position - value.len()),
                                        items,
                                        to: add.keys.clone(),
                                    })
                                } else {
                                    unreachable!()
                                };
                                ops.remove(index);
                                ops.push(move_);
                                entry.remove_entry();
                            } else {
                                ops.push(Operation::Remove(Remove {
                                    keys: keys(key),
                                    items,
                                }));
                                removes.insert(value.clone(), ops.len() - 1);
                            }
                        }
                    }
                    'i' => {
                        if last == 'd' || end && curr == 'd' {
                            ops.push(Operation::Replace(Replace {
                                keys: keys(key),
                                items,
                                value: Box::new(value.clone()),
                            }));
                        } else {
                            // Clippy seems to think this is collapsible with the above. It's not, tests break.
                            #[allow(clippy::collapsible_else_if)]
                            if let Entry::Occupied(entry) = removes.entry(value.clone()) {
                                let index = *entry.get();
                                let move_ = if let Some(Operation::Remove(remove)) = ops.get(index)
                                {
                                    Operation::Move(Move {
                                        from: remove.keys.clone(),
                                        items: remove.items,
                                        to: keys(position - value.len()),
                                    })
                                } else {
                                    unreachable!()
                                };
                                ops.remove(index);
                                ops.push(move_);
                                entry.remove_entry();
                            } else {
                                ops.push(Operation::Add(Add {
                                    keys: keys(key),
                                    value: Box::new(value.clone()),
                                }));
                                adds.insert(value.clone(), ops.len() - 1);
                            }
                        }
                    }
                    _ => {}
                };

                last = curr;
            }

            curr = next;
        }

        differ.append(ops)
    }

    fn apply_add(&mut self, keys: &mut Keys, value: &Box<dyn Any>) {
        let value = if let Some(value) = value.deref().downcast_ref::<Self>() {
            value
        } else {
            unreachable!("Invalid replacement value for {}", type_name::<Self>())
        };

        if let Some(Key::Index(index)) = keys.pop_front() {
            self.insert_str(index, value)
        } else {
            invalid_keys!(keys)
        }
    }

    fn apply_remove(&mut self, keys: &mut Keys, items: usize) {
        if let Some(Key::Index(index)) = keys.pop_front() {
            self.replace_range(index..(index + items), "")
        } else {
            invalid_keys!(keys)
        }
    }

    fn apply_move(&mut self, from: &mut Keys, items: usize, to: &mut Keys) {
        if let (Some(Key::Index(from)), Some(Key::Index(to))) = (from.pop_front(), to.pop_front()) {
            let chars: Vec<char> = self.chars().collect();
            let chars = if from < to {
                [
                    &chars[..from],
                    &chars[(from + items)..(to + items)],
                    &chars[from..(from + items)],
                    &chars[(to + items)..],
                ]
                .concat()
            } else {
                [
                    &chars[..to],
                    &chars[from..(from + items)],
                    &chars[to..from],
                    &chars[(from + items)..],
                ]
                .concat()
            };
            *self = chars.into_iter().collect();
        } else {
            invalid_keys!(from)
        }
    }

    fn apply_replace(&mut self, keys: &mut Keys, items: usize, value: &Box<dyn Any>) {
        let value = if let Some(value) = value.deref().downcast_ref::<Self>() {
            value
        } else {
            unreachable!("Invalid replacement value for {}", type_name::<Self>())
        };

        if keys.is_empty() {
            *self = value.clone();
        } else if let Some(Key::Index(index)) = keys.pop_front() {
            self.replace_range(index..(index + items), value);
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::{
        assert_json,
        patches::{apply_new, diff, equal},
    };
    use pretty_assertions::assert_eq;

    #[test]
    fn test_string() {
        let empty = "".to_string();
        let a = "1".to_string();
        let b = "123".to_string();
        let c = "a2b3".to_string();
        let d = "abcdef".to_string();
        let e = "adefbc".to_string();
        let f = "adbcfe".to_string();

        assert!(equal(&empty, &empty));
        assert!(equal(&a, &a));
        assert!(equal(&b, &b));
        assert!(equal(&c, &c));
        assert!(equal(&d, &d));

        // No diff

        assert_json!(diff(&empty, &empty), []);
        assert_json!(diff(&a, &a), []);
        assert_json!(diff(&d, &d), []);

        // Add

        let patch = diff(&empty, &a);
        assert_json!(
            patch,
            [{ "op": "add", "keys": [0], "value": "1" }]
        );
        assert_eq!(apply_new(&empty, &patch), a);

        let patch = diff(&empty, &d);
        assert_json!(
            patch,
            [{ "op": "add", "keys": [0], "value": "abcdef" }]
        );
        assert_eq!(apply_new(&empty, &patch), d);

        let patch = diff(&a, &b);
        assert_json!(
            patch,
            [{ "op": "add", "keys": [1], "value": "23" }]
        );
        assert_eq!(apply_new(&a, &patch), b);

        // Remove

        let patch = diff(&a, &empty);
        assert_json!(
            patch,
            [{ "op": "remove", "keys": [0], "items": 1 }]
        );

        let patch = diff(&d, &empty);
        assert_json!(
            patch,
            [{ "op": "remove", "keys": [0], "items": 6 }]
        );

        let patch = diff(&b, &a);
        assert_json!(
            patch,
            [{ "op": "remove", "keys": [1], "items": 2 }]
        );

        // Replace

        let patch = diff(&a, &c);
        assert_json!(
            patch,
            [{ "op": "replace", "keys": [0], "items": 1, "value": "a2b3" }]
        );
        assert_eq!(apply_new(&a, &patch), c);

        let patch = diff(&b, &d);
        assert_json!(
            patch,
            [{ "op": "replace", "keys": [0], "items": 3, "value": "abcdef" }]
        );
        assert_eq!(apply_new(&b, &patch), d);

        // Move

        let patch = diff(&d, &e);
        assert_json!(
            patch,
            [
                { "op": "move", "from": [1], "items": 2, "to": [4] },
            ]
        );
        assert_eq!(apply_new(&d, &patch), e);

        let patch = diff(&e, &d);
        assert_json!(
            patch,
            [
                { "op": "move", "from": [4], "items": 2, "to": [1] },
            ]
        );
        assert_eq!(apply_new(&e, &patch), d);

        // Mixed

        let patch = diff(&c, &d);
        assert_json!(
            patch,
            [
                { "op": "remove", "keys": [1], "items": 1 },
                { "op": "replace", "keys": [2], "items": 1, "value": "cdef" }
            ]
        );
        assert_eq!(apply_new(&c, &patch), d);

        let patch = diff(&d, &c);
        assert_json!(
            patch,
            [
                { "op": "add", "keys": [1], "value": "2" },
                { "op": "replace", "keys": [3], "items": 4, "value": "3" }
            ]
        );
        assert_eq!(apply_new(&d, &patch), c);

        let patch = diff(&d, &f);
        assert_json!(
            patch,
            [
                { "op": "add", "keys": [1], "value": "d" },
                { "op": "replace", "keys": [4], "items": 1, "value": "f" },
                { "op": "remove", "keys": [6], "items": 1 }
            ]
        );
        assert_eq!(apply_new(&d, &patch), f);
    }
}
<|endoftext|>


<commit_before>use primal_estimate;
use primal_bit::{BitVec};
use std::{cmp};
use hamming;

use wheel;

pub mod primes;
mod presieve;

/// A heavily optimised prime sieve.
///
/// This is a streaming segmented sieve, meaning it sieves numbers in
/// intervals, extracting whatever it needs and discarding it. See
/// `Sieve` for a wrapper that caches the information to allow for
/// repeated queries, at the cost of *O(limit)* memory use.
///
/// This uses *O(sqrt(limit))* memory, and is designed to be as
/// cache-friendly as possible. `StreamingSieve` should be used for
/// one-off calls, or simple linear iteration.
///
/// The design is *heavily* inspired/adopted from Kim Walisch's
/// [primesieve](http://primesieve.org/), and has similar speed
/// (around 5-20% slower).
///
/// # Examples
///
/// ```rust
/// # extern crate primal;
/// let count = primal::StreamingSieve::prime_pi(123456);
/// println!("𝜋(123456) = {}", count);
/// ```
#[derive(Debug)]
pub struct StreamingSieve {
    small: Option<::Sieve>,
    sieve: BitVec,
    primes: Vec<wheel::State<wheel::Wheel210>>,
    small_primes: Vec<wheel::State<wheel::Wheel30>>,
    large_primes: Vec<wheel::State<wheel::Wheel210>>,
    presieve: presieve::Presieve,

    low: usize,
    current: usize,
    limit: usize,
}

const CACHE: usize = 32 << 10;
const SEG_ELEMS: usize = 8 * CACHE;
const SEG_LEN: usize = SEG_ELEMS * wheel::BYTE_MODULO / wheel::BYTE_SIZE;

fn isqrt(x: usize) -> usize {
    (x as f64).sqrt() as usize
}

impl StreamingSieve {
    /// Create a new instance of the streaming sieve that will
    /// correctly progressively filter primes up to `limit`.
    fn new(limit: usize) -> StreamingSieve {
        let low = 0;

        let elems = cmp::min(wheel::bits_for(limit), SEG_ELEMS);
        let presieve = presieve::Presieve::new(elems);
        let current = presieve.smallest_unincluded_prime();

        let small = if limit < current * current {
            None
        } else {
            Some(::Sieve::new(isqrt(limit) + 1))
        };

        StreamingSieve {
            small: small,
            sieve: BitVec::from_elem(elems, true),
            primes: vec![],
            small_primes: vec![],
            large_primes: vec![],
            presieve: presieve,

            low: low,
            current: current,
            limit: limit
        }
    }
    fn split_index(&self, idx: usize) -> (usize, usize) {
        let len = SEG_ELEMS;
        (idx / len,idx % len)
    }
    fn index_for(&self, n: usize) -> (bool, usize, usize) {
        let (b, idx) = wheel::bit_index(n);
        let (base, tweak) = self.split_index(idx);
        (b, base, tweak)
    }

    /// Count the number of primes upto and including `n`, that is, 𝜋,
    /// the [prime counting
    /// function](https://en.wikipedia.org/wiki/Prime-counting_function).
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate primal;
    /// assert_eq!(primal::StreamingSieve::prime_pi(10), 4);
    /// // the endpoint is included
    /// assert_eq!(primal::StreamingSieve::prime_pi(11), 5);
    ///
    /// assert_eq!(primal::StreamingSieve::prime_pi(100), 25);
    /// assert_eq!(primal::StreamingSieve::prime_pi(1000), 168);
    /// ```
    pub fn prime_pi(n: usize) -> usize {
        match n {
            0...1 => 0,
            2 => 1,
            3...4 => 2,
            5...6 => 3,
            7...10 => 4,
            _ => {
                let mut sieve = StreamingSieve::new(n);
                let (includes, base, tweak) = sieve.index_for(n);
                let mut count = match wheel::BYTE_MODULO {
                    30 => 3,
                    _ => unimplemented!()
                };

                for _ in 0..base {
                    let (_, bitv) = sieve.next().unwrap();
                    let bytes = bitv.as_bytes();
                    count += hamming::weight(bytes) as usize;
                }

                let (_, last) = sieve.next().unwrap();
                count += last.count_ones_before(tweak + includes as usize);
                count
            }
        }
    }

    /// Compute *pn*, the `n` prime number, 1-indexed
    /// (i.e. *p1* = 2, *p2* = 3).
    ///
    /// # Panics
    ///
    /// `n` must be larger than 0 and less than the total number of
    /// primes in this sieve (that is,
    /// `self.prime_pi(self.upper_bound())`).
    ///
    /// # Example
    ///
    /// ```rust
    /// # extern crate primal;
    /// assert_eq!(primal::StreamingSieve::nth_prime(1_000), 7919);
    /// ```
    pub fn nth_prime(n: usize) -> usize {
        assert!(n > 0);
        match n {
            1 => 2,
            2 => 3,
            3 => 5,
            _ => {
                let mut bit_n = n - 3;
                let (_, hi) = primal_estimate::nth_prime(n as u64);
                let mut sieve = StreamingSieve::new(hi as usize);
                while let Some((low, bits)) = sieve.next() {
                    let count = hamming::weight(bits.as_bytes()) as usize;
                    if count >= bit_n {
                        let bit_idx = bits.find_nth_bit(bit_n - 1).unwrap();
                        return low + wheel::from_bit_index(bit_idx)
                    }

                    bit_n -= count
                }
                unreachable!()
            }
        }
    }

    fn add_sieving_prime(&mut self, p: usize, low: usize) {
        if p <= CACHE / 2 {
            self.small_primes.push(wheel::State::new(wheel::Wheel30, p, low));
        } else {
            let elem = wheel::State::new(wheel::Wheel210, p, low);
            if p < CACHE * 5 / 2 {
                self.primes.push(elem)
            } else {
                self.large_primes.push(elem)
            }
        }
    }

    fn find_new_sieving_primes(&mut self, low: usize, high: usize) {
        if let Some(small) = self.small.take() {
            for p in small.primes_from(self.current) {
                if p * p >= high {
                    self.current = p;
                    break
                }
                self.add_sieving_prime(p, low);
            }
            self.small = Some(small);
        }
    }

    fn small_primes_sieve<W: wheel::Wheel>(sieve: &mut BitVec,
                                           small_primes: &mut [wheel::State<W>]) {
        let bytes = sieve.as_bytes_mut();
        for wi in small_primes {
            wi.sieve_hardcoded(bytes);
        }
    }

    fn direct_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();

        let mut iter = self.primes.iter_mut();

        while iter.size_hint().0 >= 3 {
            match (iter.next(), iter.next(), iter.next()) {
                (Some(wi1), Some(wi2), Some(wi3)) => {
                    wi1.sieve_triple(wi2, wi3, bytes);
                }
                _ => unreachable!()
            }
        }
        for wi in iter {
            wi.sieve(bytes)
        }
    }

    fn large_primes_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();

        let mut iter = self.large_primes.iter_mut();

        while iter.size_hint().0 >= 2 {
            match (iter.next(), iter.next()) {
                (Some(wi1), Some(wi2)) => {
                    wi1.sieve_pair(wi2, bytes);
                }
                _ => unreachable!()
            }
        }
        for wi in iter {
            wi.sieve(bytes)
        }
    }

    /// Extract the next chunk of filtered primes, the return value is
    /// `Some((low, v))` or `None` if the sieve has reached the limit.
    ///
    /// The vector stores bits for each odd number starting at `low`.
    /// Bit `n` of `v` is set if and only if `low + 2 * n + 1` is
    /// prime.
    ///
    /// NB. the prime 2 is not included in any of these sieves and so
    /// needs special handling.
    fn next(&mut self) -> Option<(usize, &BitVec)> {
        if self.low >= self.limit {
            return None
        }

        let low = self.low;
        self.low = self.low.saturating_add(SEG_LEN);
        let high = cmp::min(low.saturating_add(SEG_LEN - 1), self.limit);

        self.find_new_sieving_primes(low, high);

        self.presieve.apply(&mut self.sieve, low);
        StreamingSieve::small_primes_sieve(&mut self.sieve, &mut self.small_primes);
        self.direct_sieve();
        self.large_primes_sieve();

        if low == 0 {
            // 1 is not prime.
            self.sieve.set(0, false);
            self.presieve.mark_small_primes(&mut self.sieve);
        }

        Some((low, &self.sieve))
    }
}

// module-public but crate-private wrappers, to allow `Sieve` to call these functions.
pub fn new(limit: usize) -> StreamingSieve {
    StreamingSieve::new(limit)
}
pub fn next(sieve: &mut StreamingSieve) -> Option<(usize, &BitVec)> {
    sieve.next()
}

#[cfg(test)]
mod tests {
    use Sieve;
    use primal_slowsieve::Primes;
    use wheel;
    use super::StreamingSieve;
    fn gcd(x: usize, y: usize) -> usize {
        if y == 0 { x }
        else { gcd(y, x % y) }
    }
    fn coprime_to(x: usize) -> Vec<usize> {
        (1..x).filter(|&n| gcd(n, x) == 1).collect()
    }
    #[test]
    fn test() {
        let coprime = coprime_to(wheel::BYTE_MODULO);
        const LIMIT: usize = 2_000_000;
        let mut sieve = StreamingSieve::new(LIMIT);
        let primes = ::primal_slowsieve::Primes::sieve(LIMIT);

        let mut base = 0;
        let mut index = 0;

        while let Some((_low, next)) = sieve.next() {
            for val in next {
                let i = wheel::BYTE_MODULO * base + coprime[index];
                if i >= LIMIT { break }
                assert!(primes.is_prime(i) == val,
                        "failed for {} (is prime = {})", i, primes.is_prime(i));

                index += 1;
                if index == wheel::BYTE_SIZE {
                    index = 0;
                    base += 1
                }
            }
        }
    }
    #[test]
    fn prime_pi() {
        let (limit, mult) = if cfg!(feature = "slow_tests") {
            (2_000_000, 19_998)
        } else {
            (200_000, 1_998)
        };
        let real = Primes::sieve(limit);

        for i in (0..20).chain((0..100).map(|n| n * mult + 1)) {
            let val = StreamingSieve::prime_pi(i);
            let true_ = real.primes().take_while(|p| *p <= i).count();
            assert!(val == true_, "failed for {}, true {}, computed {}",
                    i, true_, val)
        }
    }

    #[test]
    fn nth_prime() {
        let primes = Sieve::new(2_000_000);

        for (i, p) in primes.primes_from(0).enumerate() {
            let n = i + 1;
            if n < 2000 || n % 1000 == 0 {
                assert_eq!(StreamingSieve::nth_prime(n), p);
            }
        }
    }
}
<commit_msg>tests: add test hopefully covering larger prime sieving.<commit_after>use primal_estimate;
use primal_bit::{BitVec};
use std::{cmp};
use hamming;

use wheel;

pub mod primes;
mod presieve;

/// A heavily optimised prime sieve.
///
/// This is a streaming segmented sieve, meaning it sieves numbers in
/// intervals, extracting whatever it needs and discarding it. See
/// `Sieve` for a wrapper that caches the information to allow for
/// repeated queries, at the cost of *O(limit)* memory use.
///
/// This uses *O(sqrt(limit))* memory, and is designed to be as
/// cache-friendly as possible. `StreamingSieve` should be used for
/// one-off calls, or simple linear iteration.
///
/// The design is *heavily* inspired/adopted from Kim Walisch's
/// [primesieve](http://primesieve.org/), and has similar speed
/// (around 5-20% slower).
///
/// # Examples
///
/// ```rust
/// # extern crate primal;
/// let count = primal::StreamingSieve::prime_pi(123456);
/// println!("𝜋(123456) = {}", count);
/// ```
#[derive(Debug)]
pub struct StreamingSieve {
    small: Option<::Sieve>,
    sieve: BitVec,
    primes: Vec<wheel::State<wheel::Wheel210>>,
    small_primes: Vec<wheel::State<wheel::Wheel30>>,
    large_primes: Vec<wheel::State<wheel::Wheel210>>,
    presieve: presieve::Presieve,

    low: usize,
    current: usize,
    limit: usize,
}

const CACHE: usize = 32 << 10;
const SEG_ELEMS: usize = 8 * CACHE;
const SEG_LEN: usize = SEG_ELEMS * wheel::BYTE_MODULO / wheel::BYTE_SIZE;

fn isqrt(x: usize) -> usize {
    (x as f64).sqrt() as usize
}

impl StreamingSieve {
    /// Create a new instance of the streaming sieve that will
    /// correctly progressively filter primes up to `limit`.
    fn new(limit: usize) -> StreamingSieve {
        let low = 0;

        let elems = cmp::min(wheel::bits_for(limit), SEG_ELEMS);
        let presieve = presieve::Presieve::new(elems);
        let current = presieve.smallest_unincluded_prime();

        let small = if limit < current * current {
            None
        } else {
            Some(::Sieve::new(isqrt(limit) + 1))
        };

        StreamingSieve {
            small: small,
            sieve: BitVec::from_elem(elems, true),
            primes: vec![],
            small_primes: vec![],
            large_primes: vec![],
            presieve: presieve,

            low: low,
            current: current,
            limit: limit
        }
    }
    fn split_index(&self, idx: usize) -> (usize, usize) {
        let len = SEG_ELEMS;
        (idx / len,idx % len)
    }
    fn index_for(&self, n: usize) -> (bool, usize, usize) {
        let (b, idx) = wheel::bit_index(n);
        let (base, tweak) = self.split_index(idx);
        (b, base, tweak)
    }

    /// Count the number of primes upto and including `n`, that is, 𝜋,
    /// the [prime counting
    /// function](https://en.wikipedia.org/wiki/Prime-counting_function).
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate primal;
    /// assert_eq!(primal::StreamingSieve::prime_pi(10), 4);
    /// // the endpoint is included
    /// assert_eq!(primal::StreamingSieve::prime_pi(11), 5);
    ///
    /// assert_eq!(primal::StreamingSieve::prime_pi(100), 25);
    /// assert_eq!(primal::StreamingSieve::prime_pi(1000), 168);
    /// ```
    pub fn prime_pi(n: usize) -> usize {
        match n {
            0...1 => 0,
            2 => 1,
            3...4 => 2,
            5...6 => 3,
            7...10 => 4,
            _ => {
                let mut sieve = StreamingSieve::new(n);
                let (includes, base, tweak) = sieve.index_for(n);
                let mut count = match wheel::BYTE_MODULO {
                    30 => 3,
                    _ => unimplemented!()
                };

                for _ in 0..base {
                    let (_, bitv) = sieve.next().unwrap();
                    let bytes = bitv.as_bytes();
                    count += hamming::weight(bytes) as usize;
                }

                let (_, last) = sieve.next().unwrap();
                count += last.count_ones_before(tweak + includes as usize);
                count
            }
        }
    }

    /// Compute *pn*, the `n` prime number, 1-indexed
    /// (i.e. *p1* = 2, *p2* = 3).
    ///
    /// # Panics
    ///
    /// `n` must be larger than 0 and less than the total number of
    /// primes in this sieve (that is,
    /// `self.prime_pi(self.upper_bound())`).
    ///
    /// # Example
    ///
    /// ```rust
    /// # extern crate primal;
    /// assert_eq!(primal::StreamingSieve::nth_prime(1_000), 7919);
    /// ```
    pub fn nth_prime(n: usize) -> usize {
        assert!(n > 0);
        match n {
            1 => 2,
            2 => 3,
            3 => 5,
            _ => {
                let mut bit_n = n - 3;
                let (_, hi) = primal_estimate::nth_prime(n as u64);
                let mut sieve = StreamingSieve::new(hi as usize);
                while let Some((low, bits)) = sieve.next() {
                    let count = hamming::weight(bits.as_bytes()) as usize;
                    if count >= bit_n {
                        let bit_idx = bits.find_nth_bit(bit_n - 1).unwrap();
                        return low + wheel::from_bit_index(bit_idx)
                    }

                    bit_n -= count
                }
                unreachable!()
            }
        }
    }

    fn add_sieving_prime(&mut self, p: usize, low: usize) {
        if p <= CACHE / 2 {
            self.small_primes.push(wheel::State::new(wheel::Wheel30, p, low));
        } else {
            let elem = wheel::State::new(wheel::Wheel210, p, low);
            if p < CACHE * 5 / 2 {
                self.primes.push(elem)
            } else {
                self.large_primes.push(elem)
            }
        }
    }

    fn find_new_sieving_primes(&mut self, low: usize, high: usize) {
        if let Some(small) = self.small.take() {
            for p in small.primes_from(self.current) {
                if p * p >= high {
                    self.current = p;
                    break
                }
                self.add_sieving_prime(p, low);
            }
            self.small = Some(small);
        }
    }

    fn small_primes_sieve<W: wheel::Wheel>(sieve: &mut BitVec,
                                           small_primes: &mut [wheel::State<W>]) {
        let bytes = sieve.as_bytes_mut();
        for wi in small_primes {
            wi.sieve_hardcoded(bytes);
        }
    }

    fn direct_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();

        let mut iter = self.primes.iter_mut();

        while iter.size_hint().0 >= 3 {
            match (iter.next(), iter.next(), iter.next()) {
                (Some(wi1), Some(wi2), Some(wi3)) => {
                    wi1.sieve_triple(wi2, wi3, bytes);
                }
                _ => unreachable!()
            }
        }
        for wi in iter {
            wi.sieve(bytes)
        }
    }

    fn large_primes_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();

        let mut iter = self.large_primes.iter_mut();

        while iter.size_hint().0 >= 2 {
            match (iter.next(), iter.next()) {
                (Some(wi1), Some(wi2)) => {
                    wi1.sieve_pair(wi2, bytes);
                }
                _ => unreachable!()
            }
        }
        for wi in iter {
            wi.sieve(bytes)
        }
    }

    /// Extract the next chunk of filtered primes, the return value is
    /// `Some((low, v))` or `None` if the sieve has reached the limit.
    ///
    /// The vector stores bits for each odd number starting at `low`.
    /// Bit `n` of `v` is set if and only if `low + 2 * n + 1` is
    /// prime.
    ///
    /// NB. the prime 2 is not included in any of these sieves and so
    /// needs special handling.
    fn next(&mut self) -> Option<(usize, &BitVec)> {
        if self.low >= self.limit {
            return None
        }

        let low = self.low;
        self.low = self.low.saturating_add(SEG_LEN);
        let high = cmp::min(low.saturating_add(SEG_LEN - 1), self.limit);

        self.find_new_sieving_primes(low, high);

        self.presieve.apply(&mut self.sieve, low);
        StreamingSieve::small_primes_sieve(&mut self.sieve, &mut self.small_primes);
        self.direct_sieve();
        self.large_primes_sieve();

        if low == 0 {
            // 1 is not prime.
            self.sieve.set(0, false);
            self.presieve.mark_small_primes(&mut self.sieve);
        }

        Some((low, &self.sieve))
    }
}

// module-public but crate-private wrappers, to allow `Sieve` to call these functions.
pub fn new(limit: usize) -> StreamingSieve {
    StreamingSieve::new(limit)
}
pub fn next(sieve: &mut StreamingSieve) -> Option<(usize, &BitVec)> {
    sieve.next()
}

#[cfg(test)]
mod tests {
    use Sieve;
    use primal_slowsieve::Primes;
    use wheel;
    use super::StreamingSieve;
    fn gcd(x: usize, y: usize) -> usize {
        if y == 0 { x }
        else { gcd(y, x % y) }
    }
    fn coprime_to(x: usize) -> Vec<usize> {
        (1..x).filter(|&n| gcd(n, x) == 1).collect()
    }
    #[test]
    fn test() {
        let coprime = coprime_to(wheel::BYTE_MODULO);
        const LIMIT: usize = 2_000_000;
        let mut sieve = StreamingSieve::new(LIMIT);
        let primes = ::primal_slowsieve::Primes::sieve(LIMIT);

        let mut base = 0;
        let mut index = 0;

        while let Some((_low, next)) = sieve.next() {
            for val in next {
                let i = wheel::BYTE_MODULO * base + coprime[index];
                if i >= LIMIT { break }
                assert!(primes.is_prime(i) == val,
                        "failed for {} (is prime = {})", i, primes.is_prime(i));

                index += 1;
                if index == wheel::BYTE_SIZE {
                    index = 0;
                    base += 1
                }
            }
        }
    }
    #[test]
    fn prime_pi() {
        let (limit, mult) = if cfg!(feature = "slow_tests") {
            (2_000_000, 19_998)
        } else {
            (200_000, 1_998)
        };
        let real = Primes::sieve(limit);

        for i in (0..20).chain((0..100).map(|n| n * mult + 1)) {
            let val = StreamingSieve::prime_pi(i);
            let true_ = real.primes().take_while(|p| *p <= i).count();
            assert!(val == true_, "failed for {}, true {}, computed {}",
                    i, true_, val)
        }
    }

    #[test]
    fn nth_prime() {
        let primes = Sieve::new(2_000_000);

        for (i, p) in primes.primes_from(0).enumerate() {
            let n = i + 1;
            if n < 2000 || n % 1000 == 0 {
                assert_eq!(StreamingSieve::nth_prime(n), p);
            }
        }
    }

    // These are designed to specifically test the medium sized and
    // large prime sieving.
    #[test]
    fn prime_pi_huge() {
        #[cfg(all(feature = "slow_tests", target_pointer_width = "64"))]
        const LIMIT_RESULT: (usize, usize) = (10_000_000_000, 455_052_511);
        #[cfg(all(feature = "slow_tests", target_pointer_width = "32"))]
        const LIMIT_RESULT: (usize, usize) = (4_294_000_000, 203_236_859);
        #[cfg(not(feature = "slow_tests"))]
        const LIMIT_RESULT: (usize, usize) = (500_000_000, 26_355_867);

        assert_eq!(StreamingSieve::prime_pi(LIMIT_RESULT.0), LIMIT_RESULT.1);
    }

    #[test]
    fn nth_prime_huge() {
        #[cfg(all(feature = "slow_tests", target_pointer_width = "64"))]
        const LIMIT_RESULT: (usize, usize) = (455_052_512, 10_000_000_019);
        #[cfg(all(feature = "slow_tests", target_pointer_width = "32"))]
        const LIMIT_RESULT: (usize, usize) = (203_236_860, 4_294_000_079);
        #[cfg(not(feature = "slow_tests"))]
        const LIMIT_RESULT: (usize, usize) = (26_355_868, 500_000_003);

        assert_eq!(StreamingSieve::nth_prime(LIMIT_RESULT.0), LIMIT_RESULT.1);
    }
}
<|endoftext|>


<commit_before>#![feature(proc_macro, proc_macro_lib)]

#[macro_use] extern crate quote;

extern crate syn;
extern crate regex;
extern crate proc_macro;
extern crate serde;
extern crate serde_json;

use proc_macro::TokenStream;

use syn::{Body, Ident, Variant, VariantData, Visibility};
use quote::Tokens;

#[proc_macro_derive(Node)]
pub fn my_macro(input: TokenStream) -> TokenStream {
    let input = input.to_string();
    let ast = syn::parse_macro_input(&input).unwrap();
    let name = &ast.ident;

    let quote_tokens = match ast.body {
        Body::Enum(ref data)   => gen_enum(name, data),
        Body::Struct(ref data) => gen_struct(name, data)
    }.to_string();

    //println!("{}", quote_tokens.to_string());
    format!("{} {}", input, quote_tokens.to_string()).parse().unwrap()
}

fn gen_get(name: &str) -> Tokens {
    quote! {
        use serde_json;
        match serde_json::to_string(self) {
            Ok(result) => {
                result
            }
            Err(err) => {
                format!("{} get Error: {}", #name, err)
            }
        }
    }
}

fn gen_set(name: &str) -> Tokens {
    quote! {
        use serde_json;
        match serde_json::from_str(value.as_str()) {
            Ok(result) => {
                *self = result;
                String::from("")
            }
            Err(err) => {
                format!("{} set Error: {}", #name, err)
            }
        }
    }
}

fn gen_enum(name: &Ident, data: &Vec<Variant>) -> Tokens {
    let name_string = name.to_string();
    let get_arm = gen_get(&name_string);
    let set_arm = gen_set(&name_string);
    quote! {
        impl Node for #name {
            fn node_step(&mut self, mut runner: NodeRunner) -> String {
                match runner.step() {
                    NodeToken::Get => {
                        #get_arm
                    }
                    NodeToken::Set (value) => {
                        #set_arm
                    }
                    action => { format!("{} cannot '{:?}'", #name_string, action) }
                }
            }
        }
    }
}

fn gen_struct(name: &Ident, data: &VariantData) -> Tokens {
    let name_string = name.to_string();
    let get_arm = gen_get(&name_string);
    let set_arm = gen_set(&name_string);
    let match_property = gen_struct_chain_property(&name_string, data);

    quote! {
        impl Node for #name {
            fn node_step(&mut self, mut runner: NodeRunner) -> String {
                match runner.step() {
                    NodeToken::ChainProperty (property) => {
                        #match_property
                    },
                    NodeToken::Get => {
                        #get_arm
                    },
                    NodeToken::Set (value) => {
                        #set_arm
                    },
                    action => { format!("{} cannot '{:?}'", #name_string, action) }
                }
            }
        }
    }
}

fn gen_struct_chain_property(name: &str, data: &VariantData) -> Tokens {
    let mut arms: Vec<Tokens> = vec!();
    for field in data.fields() {
        let field_name = &field.ident.as_ref().unwrap();
        let field_name_string = field_name.to_string();
        if let Visibility::Public = field.vis {
            arms.push(quote!{
                #field_name_string => { self.#field_name.node_step(runner) },
            });
        }
    }

    quote! {
        match property.as_str() {
            #( #arms )*
            prop  => format!("{} does not have a property '{}'", #name, prop)
        }
    }
}
<commit_msg>Fix to work on latest rustc<commit_after>#![feature(proc_macro, proc_macro_lib)]

#[macro_use] extern crate quote;

extern crate syn;
extern crate regex;
extern crate proc_macro;
extern crate serde;
extern crate serde_json;

use proc_macro::TokenStream;

use syn::{Body, Ident, Variant, VariantData, Visibility};
use quote::Tokens;

#[proc_macro_derive(Node)]
pub fn my_macro(input: TokenStream) -> TokenStream {
    let input = input.to_string();
    let ast = syn::parse_macro_input(&input).unwrap();
    let name = &ast.ident;

    let quote_tokens = match ast.body {
        Body::Enum(ref data)   => gen_enum(name, data),
        Body::Struct(ref data) => gen_struct(name, data)
    }.to_string();

    quote_tokens.to_string().parse().unwrap()
}

fn gen_get(name: &str) -> Tokens {
    quote! {
        use serde_json;
        match serde_json::to_string(self) {
            Ok(result) => {
                result
            }
            Err(err) => {
                format!("{} get Error: {}", #name, err)
            }
        }
    }
}

fn gen_set(name: &str) -> Tokens {
    quote! {
        use serde_json;
        match serde_json::from_str(value.as_str()) {
            Ok(result) => {
                *self = result;
                String::from("")
            }
            Err(err) => {
                format!("{} set Error: {}", #name, err)
            }
        }
    }
}

fn gen_enum(name: &Ident, data: &Vec<Variant>) -> Tokens {
    let name_string = name.to_string();
    let get_arm = gen_get(&name_string);
    let set_arm = gen_set(&name_string);
    quote! {
        impl Node for #name {
            fn node_step(&mut self, mut runner: NodeRunner) -> String {
                match runner.step() {
                    NodeToken::Get => {
                        #get_arm
                    }
                    NodeToken::Set (value) => {
                        #set_arm
                    }
                    action => { format!("{} cannot '{:?}'", #name_string, action) }
                }
            }
        }
    }
}

fn gen_struct(name: &Ident, data: &VariantData) -> Tokens {
    let name_string = name.to_string();
    let get_arm = gen_get(&name_string);
    let set_arm = gen_set(&name_string);
    let match_property = gen_struct_chain_property(&name_string, data);

    quote! {
        impl Node for #name {
            fn node_step(&mut self, mut runner: NodeRunner) -> String {
                match runner.step() {
                    NodeToken::ChainProperty (property) => {
                        #match_property
                    },
                    NodeToken::Get => {
                        #get_arm
                    },
                    NodeToken::Set (value) => {
                        #set_arm
                    },
                    action => { format!("{} cannot '{:?}'", #name_string, action) }
                }
            }
        }
    }
}

fn gen_struct_chain_property(name: &str, data: &VariantData) -> Tokens {
    let mut arms: Vec<Tokens> = vec!();
    for field in data.fields() {
        let field_name = &field.ident.as_ref().unwrap();
        let field_name_string = field_name.to_string();
        if let Visibility::Public = field.vis {
            arms.push(quote!{
                #field_name_string => { self.#field_name.node_step(runner) },
            });
        }
    }

    quote! {
        match property.as_str() {
            #( #arms )*
            prop  => format!("{} does not have a property '{}'", #name, prop)
        }
    }
}
<|endoftext|>


<commit_before>//! # Diesel
//!
//! Diesel is an ORM and query builder designed to reduce the boilerplate for database interactions.
//! If this is your first time reading this documentation,
//! we recommend you start with the [getting started guide].
//! We also have [many other long form guides].
//!
//! [getting started guide]: https://diesel.rs/guides/getting-started/
//! [many other long form guides]: https://diesel.rs/guides
//!
//! # Where to find things
//!
//! ## Declaring your schema
//!
//! For Diesel to validate your queries at compile time
//! it requires you to specify your schema in your code,
//! which you can do with [the `table!` macro][`table!`].
//! `diesel print-schema` or `infer_schema!` can be used
//! to automatically generate these macro calls
//! (by connecting to your database and querying its schema).
//!
//! [`table!`]: macro.table.html
//!
//! ## Getting started
//!
//! Queries usually start from either a table, or a function like [`update`].
//! Those functions can be found [here](#functions).
//!
//! Diesel provides a [`prelude` module](prelude),
//! which exports most of the typically used traits and types.
//! We are conservative about what goes in this module,
//! and avoid anything which has a generic name.
//! Files which use Diesel are expected to have `use diesel::prelude::*;`.
//!
//! [`update`]: fn.update.html
//!
//! ## Constructing a query
//!
//! The tools the query builder gives you can be put into these three categories:
//!
//! - "Query builder methods" are things that map to portions of a whole query
//!   (such as `ORDER` and `WHERE`). These methods usually have the same name
//!   as the SQL they map to, except for `WHERE` which is called `filter` in Diesel
//!   (To not conflict with the Rust keyword).
//!   These methods live in [the `query_dsl` module](query_dsl).
//! - "Expression methods" are things you would call on columns
//!   or other individual values.
//!   These methods live in [the `expression_methods` module](expression_methods)
//!   You can often find these by thinking "what would this be called"
//!   if it were a method
//!   and typing that into the search bar
//!   (e.g. `LIKE` is called `like` in Diesel).
//!   Most operators are named based on the Rust function which maps to that
//!   operator in [`std::ops`][]
//!   (For example `==` is called `.eq`, and `!=` is called `.ne`).
//! - "Bare functions" are normal SQL functions
//!   such as `sum`.
//!   They live in [the `dsl` module](dsl).
//!   Diesel only supports a very small number of these functions.
//!   You can declare additional functions you want to use
//!   with [the `sql_function!` macro][`sql_function!`].
//!
//! [`std::ops`]: //doc.rust-lang.org/stable/std/ops/index.html
//! [`sql_function!`]: macro.sql_function.html
//!
//! ## Serializing and Deserializing
//!
//! Types which represent the result of a SQL query implement
//! a trait called [`Queryable`].
//!
//! Diesel maps "Rust types" (e.g. `i32`) to and from "SQL types"
//! (e.g. [`diesel::sql_types::Integer`]).
//! You can find all the types supported by Diesel in [the `sql_types` module](sql_types).
//! These types are only used to represent a SQL type.
//! You should never put them on your `Queryable` structs.
//!
//! To find all the Rust types which can be used with a given SQL type,
//! see the documentation for that SQL type.
//!
//! To find all the SQL types which can be used with a Rust type,
//! go to the docs for either [`ToSql`] or [`FromSql`],
//! go to the "Implementors" section,
//! and find the Rust type you want to use.
//!
//! [`Queryable`]: deserialize/trait.Queryable.html
//! [`diesel::sql_types::Integer`]: sql_types/struct.Integer.html
//! [`ToSql`]: serialize/trait.ToSql.html
//! [`FromSql`]: deserialize/trait.FromSql.html
//!
//! ## Getting help
//!
//! If you run into problems, Diesel has a very active Gitter room.
//! You can come ask for help at
//! [gitter.im/diesel-rs/diesel](https://gitter.im/diesel-rs/diesel)

#![cfg_attr(feature = "unstable", feature(specialization, try_from))]
// Built-in Lints
#![deny(
    warnings,
    missing_debug_implementations,
    missing_copy_implementations,
    missing_docs
)]
// Clippy lints
#![allow(
    clippy::option_map_unwrap_or_else,
    clippy::option_map_unwrap_or,
    clippy::match_same_arms,
    clippy::type_complexity,
    clippy::redundant_field_names
)]
#![cfg_attr(test, allow(clippy::option_map_unwrap_or, clippy::result_unwrap_used))]
#![warn(
    clippy::option_unwrap_used,
    clippy::result_unwrap_used,
    clippy::print_stdout,
    clippy::wrong_pub_self_convention,
    clippy::mut_mut,
    clippy::non_ascii_literal,
    clippy::similar_names,
    clippy::unicode_not_nfc,
    clippy::enum_glob_use,
    clippy::if_not_else,
    clippy::items_after_statements,
    clippy::used_underscore_binding
)]

#[cfg(feature = "postgres")]
#[macro_use]
extern crate bitflags;
extern crate byteorder;
#[macro_use]
extern crate diesel_derives;
#[doc(hidden)]
pub use diesel_derives::*;

#[macro_use]
mod macros;

#[cfg(test)]
#[macro_use]
extern crate cfg_if;

#[cfg(test)]
pub mod test_helpers;

pub mod associations;
pub mod backend;
pub mod connection;
pub mod data_types;
pub mod deserialize;
#[macro_use]
pub mod expression;
pub mod expression_methods;
#[doc(hidden)]
pub mod insertable;
pub mod query_builder;
pub mod query_dsl;
pub mod query_source;
#[cfg(feature = "r2d2")]
pub mod r2d2;
pub mod result;
pub mod serialize;
#[macro_use]
pub mod sql_types;
pub mod migration;
pub mod row;

#[cfg(feature = "mysql")]
pub mod mysql;
#[cfg(feature = "postgres")]
pub mod pg;
#[cfg(feature = "sqlite")]
pub mod sqlite;

mod type_impls;
mod util;

pub mod dsl {
    //! Includes various helper types and bare functions which are named too
    //! generically to be included in prelude, but are often used when using Diesel.

    #[doc(inline)]
    pub use helper_types::*;

    #[doc(inline)]
    pub use expression::dsl::*;

    #[doc(inline)]
    pub use query_builder::functions::{
        delete, insert_into, insert_or_ignore_into, replace_into, select, sql_query, update,
    };
}

pub mod helper_types {
    //! Provide helper types for concisely writing the return type of functions.
    //! As with iterators, it is unfortunately difficult to return a partially
    //! constructed query without exposing the exact implementation of the
    //! function. Without higher kinded types, these various DSLs can't be
    //! combined into a single trait for boxing purposes.
    //!
    //! All types here are in the form `<FirstType as
    //! DslName<OtherTypes>>::Output`. So the return type of
    //! `users.filter(first_name.eq("John")).order(last_name.asc()).limit(10)` would
    //! be `Limit<Order<FindBy<users, first_name, &str>, Asc<last_name>>>`
    use super::query_builder::locking_clause as lock;
    use super::query_dsl::methods::*;
    use super::query_dsl::*;
    use super::query_source::joins;

    #[doc(inline)]
    pub use expression::helper_types::*;

    /// Represents the return type of `.select(selection)`
    pub type Select<Source, Selection> = <Source as SelectDsl<Selection>>::Output;

    /// Represents the return type of `.filter(predicate)`
    pub type Filter<Source, Predicate> = <Source as FilterDsl<Predicate>>::Output;

    /// Represents the return type of `.filter(lhs.eq(rhs))`
    pub type FindBy<Source, Column, Value> = Filter<Source, Eq<Column, Value>>;

    /// Represents the return type of `.for_update()`
    pub type ForUpdate<Source> = <Source as LockingDsl<lock::ForUpdate>>::Output;

    /// Represents the return type of `.for_no_key_update()`
    pub type ForNoKeyUpdate<Source> = <Source as LockingDsl<lock::ForNoKeyUpdate>>::Output;

    /// Represents the return type of `.for_share()`
    pub type ForShare<Source> = <Source as LockingDsl<lock::ForShare>>::Output;

    /// Represents the return type of `.for_key_share()`
    pub type ForKeyShare<Source> = <Source as LockingDsl<lock::ForKeyShare>>::Output;

    /// Represents the return type of `.skip_locked()`
    pub type SkipLocked<Source> = <Source as ModifyLockDsl<lock::SkipLocked>>::Output;

    /// Represents the return type of `.no_wait()`
    pub type NoWait<Source> = <Source as ModifyLockDsl<lock::NoWait>>::Output;

    /// Represents the return type of `.find(pk)`
    pub type Find<Source, PK> = <Source as FindDsl<PK>>::Output;

    /// Represents the return type of `.or_filter(predicate)`
    pub type OrFilter<Source, Predicate> = <Source as OrFilterDsl<Predicate>>::Output;

    /// Represents the return type of `.order(ordering)`
    pub type Order<Source, Ordering> = <Source as OrderDsl<Ordering>>::Output;

    /// Represents the return type of `.then_order_by(ordering)`
    pub type ThenOrderBy<Source, Ordering> = <Source as ThenOrderDsl<Ordering>>::Output;

    /// Represents the return type of `.limit()`
    pub type Limit<Source> = <Source as LimitDsl>::Output;

    /// Represents the return type of `.offset()`
    pub type Offset<Source> = <Source as OffsetDsl>::Output;

    /// Represents the return type of `.inner_join(rhs)`
    pub type InnerJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::Inner>>::Output;

    /// Represents the return type of `.left_join(rhs)`
    pub type LeftJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::LeftOuter>>::Output;

    use super::associations::HasTable;
    use super::query_builder::{AsChangeset, IntoUpdateTarget, UpdateStatement};
    /// Represents the return type of `update(lhs).set(rhs)`
    pub type Update<Target, Changes> = UpdateStatement<
        <Target as HasTable>::Table,
        <Target as IntoUpdateTarget>::WhereClause,
        <Changes as AsChangeset>::Changeset,
    >;

    /// Represents the return type of `.into_boxed::<'a, DB>()`
    pub type IntoBoxed<'a, Source, DB> = <Source as BoxedDsl<'a, DB>>::Output;

    /// Represents the return type of `.distinct()`
    pub type Distinct<Source> = <Source as DistinctDsl>::Output;

    /// Represents the return type of `.distinct_on(expr)`
    #[cfg(feature = "postgres")]
    pub type DistinctOn<Source, Expr> = <Source as DistinctOnDsl<Expr>>::Output;

    /// Represents the return type of `.single_value()`
    pub type SingleValue<Source> = <Source as SingleValueDsl>::Output;

    /// Represents the return type of `.nullable()`
    pub type NullableSelect<Source> = <Source as SelectNullableDsl>::Output;
}

pub mod prelude {
    //! Re-exports important traits and types. Meant to be glob imported when using Diesel.
    pub use associations::{GroupedBy, Identifiable};
    pub use connection::Connection;
    #[deprecated(
        since = "1.1.0",
        note = "Explicitly `use diesel::deserialize::Queryable"
    )]
    pub use deserialize::Queryable;
    pub use expression::{
        AppearsOnTable, BoxableExpression, Expression, IntoSql, SelectableExpression,
    };
    pub use expression_methods::*;
    #[doc(inline)]
    pub use insertable::Insertable;
    #[doc(hidden)]
    pub use query_dsl::GroupByDsl;
    pub use query_dsl::{BelongingToDsl, JoinOnDsl, QueryDsl, RunQueryDsl, SaveChangesDsl};

    pub use query_source::{Column, JoinTo, QuerySource, Table};
    pub use result::{ConnectionError, ConnectionResult, OptionalExtension, QueryResult};

    #[cfg(feature = "mysql")]
    pub use mysql::MysqlConnection;
    #[cfg(feature = "postgres")]
    pub use pg::PgConnection;
    #[cfg(feature = "sqlite")]
    pub use sqlite::SqliteConnection;
}

pub use prelude::*;
#[doc(inline)]
pub use query_builder::debug_query;
#[doc(inline)]
pub use query_builder::functions::{
    delete, insert_into, insert_or_ignore_into, replace_into, select, sql_query, update,
};
pub use result::Error::NotFound;

pub(crate) mod diesel {
    pub use super::*;
}
<commit_msg>ungate try_from because it has been stabilized<commit_after>//! # Diesel
//!
//! Diesel is an ORM and query builder designed to reduce the boilerplate for database interactions.
//! If this is your first time reading this documentation,
//! we recommend you start with the [getting started guide].
//! We also have [many other long form guides].
//!
//! [getting started guide]: https://diesel.rs/guides/getting-started/
//! [many other long form guides]: https://diesel.rs/guides
//!
//! # Where to find things
//!
//! ## Declaring your schema
//!
//! For Diesel to validate your queries at compile time
//! it requires you to specify your schema in your code,
//! which you can do with [the `table!` macro][`table!`].
//! `diesel print-schema` or `infer_schema!` can be used
//! to automatically generate these macro calls
//! (by connecting to your database and querying its schema).
//!
//! [`table!`]: macro.table.html
//!
//! ## Getting started
//!
//! Queries usually start from either a table, or a function like [`update`].
//! Those functions can be found [here](#functions).
//!
//! Diesel provides a [`prelude` module](prelude),
//! which exports most of the typically used traits and types.
//! We are conservative about what goes in this module,
//! and avoid anything which has a generic name.
//! Files which use Diesel are expected to have `use diesel::prelude::*;`.
//!
//! [`update`]: fn.update.html
//!
//! ## Constructing a query
//!
//! The tools the query builder gives you can be put into these three categories:
//!
//! - "Query builder methods" are things that map to portions of a whole query
//!   (such as `ORDER` and `WHERE`). These methods usually have the same name
//!   as the SQL they map to, except for `WHERE` which is called `filter` in Diesel
//!   (To not conflict with the Rust keyword).
//!   These methods live in [the `query_dsl` module](query_dsl).
//! - "Expression methods" are things you would call on columns
//!   or other individual values.
//!   These methods live in [the `expression_methods` module](expression_methods)
//!   You can often find these by thinking "what would this be called"
//!   if it were a method
//!   and typing that into the search bar
//!   (e.g. `LIKE` is called `like` in Diesel).
//!   Most operators are named based on the Rust function which maps to that
//!   operator in [`std::ops`][]
//!   (For example `==` is called `.eq`, and `!=` is called `.ne`).
//! - "Bare functions" are normal SQL functions
//!   such as `sum`.
//!   They live in [the `dsl` module](dsl).
//!   Diesel only supports a very small number of these functions.
//!   You can declare additional functions you want to use
//!   with [the `sql_function!` macro][`sql_function!`].
//!
//! [`std::ops`]: //doc.rust-lang.org/stable/std/ops/index.html
//! [`sql_function!`]: macro.sql_function.html
//!
//! ## Serializing and Deserializing
//!
//! Types which represent the result of a SQL query implement
//! a trait called [`Queryable`].
//!
//! Diesel maps "Rust types" (e.g. `i32`) to and from "SQL types"
//! (e.g. [`diesel::sql_types::Integer`]).
//! You can find all the types supported by Diesel in [the `sql_types` module](sql_types).
//! These types are only used to represent a SQL type.
//! You should never put them on your `Queryable` structs.
//!
//! To find all the Rust types which can be used with a given SQL type,
//! see the documentation for that SQL type.
//!
//! To find all the SQL types which can be used with a Rust type,
//! go to the docs for either [`ToSql`] or [`FromSql`],
//! go to the "Implementors" section,
//! and find the Rust type you want to use.
//!
//! [`Queryable`]: deserialize/trait.Queryable.html
//! [`diesel::sql_types::Integer`]: sql_types/struct.Integer.html
//! [`ToSql`]: serialize/trait.ToSql.html
//! [`FromSql`]: deserialize/trait.FromSql.html
//!
//! ## Getting help
//!
//! If you run into problems, Diesel has a very active Gitter room.
//! You can come ask for help at
//! [gitter.im/diesel-rs/diesel](https://gitter.im/diesel-rs/diesel)

#![cfg_attr(feature = "unstable", feature(specialization))]
// Built-in Lints
#![deny(
    warnings,
    missing_debug_implementations,
    missing_copy_implementations,
    missing_docs
)]
// Clippy lints
#![allow(
    clippy::option_map_unwrap_or_else,
    clippy::option_map_unwrap_or,
    clippy::match_same_arms,
    clippy::type_complexity,
    clippy::redundant_field_names
)]
#![cfg_attr(test, allow(clippy::option_map_unwrap_or, clippy::result_unwrap_used))]
#![warn(
    clippy::option_unwrap_used,
    clippy::result_unwrap_used,
    clippy::print_stdout,
    clippy::wrong_pub_self_convention,
    clippy::mut_mut,
    clippy::non_ascii_literal,
    clippy::similar_names,
    clippy::unicode_not_nfc,
    clippy::enum_glob_use,
    clippy::if_not_else,
    clippy::items_after_statements,
    clippy::used_underscore_binding
)]

#[cfg(feature = "postgres")]
#[macro_use]
extern crate bitflags;
extern crate byteorder;
#[macro_use]
extern crate diesel_derives;
#[doc(hidden)]
pub use diesel_derives::*;

#[macro_use]
mod macros;

#[cfg(test)]
#[macro_use]
extern crate cfg_if;

#[cfg(test)]
pub mod test_helpers;

pub mod associations;
pub mod backend;
pub mod connection;
pub mod data_types;
pub mod deserialize;
#[macro_use]
pub mod expression;
pub mod expression_methods;
#[doc(hidden)]
pub mod insertable;
pub mod query_builder;
pub mod query_dsl;
pub mod query_source;
#[cfg(feature = "r2d2")]
pub mod r2d2;
pub mod result;
pub mod serialize;
#[macro_use]
pub mod sql_types;
pub mod migration;
pub mod row;

#[cfg(feature = "mysql")]
pub mod mysql;
#[cfg(feature = "postgres")]
pub mod pg;
#[cfg(feature = "sqlite")]
pub mod sqlite;

mod type_impls;
mod util;

pub mod dsl {
    //! Includes various helper types and bare functions which are named too
    //! generically to be included in prelude, but are often used when using Diesel.

    #[doc(inline)]
    pub use helper_types::*;

    #[doc(inline)]
    pub use expression::dsl::*;

    #[doc(inline)]
    pub use query_builder::functions::{
        delete, insert_into, insert_or_ignore_into, replace_into, select, sql_query, update,
    };
}

pub mod helper_types {
    //! Provide helper types for concisely writing the return type of functions.
    //! As with iterators, it is unfortunately difficult to return a partially
    //! constructed query without exposing the exact implementation of the
    //! function. Without higher kinded types, these various DSLs can't be
    //! combined into a single trait for boxing purposes.
    //!
    //! All types here are in the form `<FirstType as
    //! DslName<OtherTypes>>::Output`. So the return type of
    //! `users.filter(first_name.eq("John")).order(last_name.asc()).limit(10)` would
    //! be `Limit<Order<FindBy<users, first_name, &str>, Asc<last_name>>>`
    use super::query_builder::locking_clause as lock;
    use super::query_dsl::methods::*;
    use super::query_dsl::*;
    use super::query_source::joins;

    #[doc(inline)]
    pub use expression::helper_types::*;

    /// Represents the return type of `.select(selection)`
    pub type Select<Source, Selection> = <Source as SelectDsl<Selection>>::Output;

    /// Represents the return type of `.filter(predicate)`
    pub type Filter<Source, Predicate> = <Source as FilterDsl<Predicate>>::Output;

    /// Represents the return type of `.filter(lhs.eq(rhs))`
    pub type FindBy<Source, Column, Value> = Filter<Source, Eq<Column, Value>>;

    /// Represents the return type of `.for_update()`
    pub type ForUpdate<Source> = <Source as LockingDsl<lock::ForUpdate>>::Output;

    /// Represents the return type of `.for_no_key_update()`
    pub type ForNoKeyUpdate<Source> = <Source as LockingDsl<lock::ForNoKeyUpdate>>::Output;

    /// Represents the return type of `.for_share()`
    pub type ForShare<Source> = <Source as LockingDsl<lock::ForShare>>::Output;

    /// Represents the return type of `.for_key_share()`
    pub type ForKeyShare<Source> = <Source as LockingDsl<lock::ForKeyShare>>::Output;

    /// Represents the return type of `.skip_locked()`
    pub type SkipLocked<Source> = <Source as ModifyLockDsl<lock::SkipLocked>>::Output;

    /// Represents the return type of `.no_wait()`
    pub type NoWait<Source> = <Source as ModifyLockDsl<lock::NoWait>>::Output;

    /// Represents the return type of `.find(pk)`
    pub type Find<Source, PK> = <Source as FindDsl<PK>>::Output;

    /// Represents the return type of `.or_filter(predicate)`
    pub type OrFilter<Source, Predicate> = <Source as OrFilterDsl<Predicate>>::Output;

    /// Represents the return type of `.order(ordering)`
    pub type Order<Source, Ordering> = <Source as OrderDsl<Ordering>>::Output;

    /// Represents the return type of `.then_order_by(ordering)`
    pub type ThenOrderBy<Source, Ordering> = <Source as ThenOrderDsl<Ordering>>::Output;

    /// Represents the return type of `.limit()`
    pub type Limit<Source> = <Source as LimitDsl>::Output;

    /// Represents the return type of `.offset()`
    pub type Offset<Source> = <Source as OffsetDsl>::Output;

    /// Represents the return type of `.inner_join(rhs)`
    pub type InnerJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::Inner>>::Output;

    /// Represents the return type of `.left_join(rhs)`
    pub type LeftJoin<Source, Rhs> =
        <Source as JoinWithImplicitOnClause<Rhs, joins::LeftOuter>>::Output;

    use super::associations::HasTable;
    use super::query_builder::{AsChangeset, IntoUpdateTarget, UpdateStatement};
    /// Represents the return type of `update(lhs).set(rhs)`
    pub type Update<Target, Changes> = UpdateStatement<
        <Target as HasTable>::Table,
        <Target as IntoUpdateTarget>::WhereClause,
        <Changes as AsChangeset>::Changeset,
    >;

    /// Represents the return type of `.into_boxed::<'a, DB>()`
    pub type IntoBoxed<'a, Source, DB> = <Source as BoxedDsl<'a, DB>>::Output;

    /// Represents the return type of `.distinct()`
    pub type Distinct<Source> = <Source as DistinctDsl>::Output;

    /// Represents the return type of `.distinct_on(expr)`
    #[cfg(feature = "postgres")]
    pub type DistinctOn<Source, Expr> = <Source as DistinctOnDsl<Expr>>::Output;

    /// Represents the return type of `.single_value()`
    pub type SingleValue<Source> = <Source as SingleValueDsl>::Output;

    /// Represents the return type of `.nullable()`
    pub type NullableSelect<Source> = <Source as SelectNullableDsl>::Output;
}

pub mod prelude {
    //! Re-exports important traits and types. Meant to be glob imported when using Diesel.
    pub use associations::{GroupedBy, Identifiable};
    pub use connection::Connection;
    #[deprecated(
        since = "1.1.0",
        note = "Explicitly `use diesel::deserialize::Queryable"
    )]
    pub use deserialize::Queryable;
    pub use expression::{
        AppearsOnTable, BoxableExpression, Expression, IntoSql, SelectableExpression,
    };
    pub use expression_methods::*;
    #[doc(inline)]
    pub use insertable::Insertable;
    #[doc(hidden)]
    pub use query_dsl::GroupByDsl;
    pub use query_dsl::{BelongingToDsl, JoinOnDsl, QueryDsl, RunQueryDsl, SaveChangesDsl};

    pub use query_source::{Column, JoinTo, QuerySource, Table};
    pub use result::{ConnectionError, ConnectionResult, OptionalExtension, QueryResult};

    #[cfg(feature = "mysql")]
    pub use mysql::MysqlConnection;
    #[cfg(feature = "postgres")]
    pub use pg::PgConnection;
    #[cfg(feature = "sqlite")]
    pub use sqlite::SqliteConnection;
}

pub use prelude::*;
#[doc(inline)]
pub use query_builder::debug_query;
#[doc(inline)]
pub use query_builder::functions::{
    delete, insert_into, insert_or_ignore_into, replace_into, select, sql_query, update,
};
pub use result::Error::NotFound;

pub(crate) mod diesel {
    pub use super::*;
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::chained_bft::common::Round;
use canonical_serialization::{CanonicalSerialize, CanonicalSerializer, SimpleSerializer};
use crypto::{
    hash::{CryptoHash, CryptoHasher, VoteDataHasher},
    HashValue,
};
use failure::Result as ProtoResult;
use network::proto::VoteData as ProtoVoteData;
use proto_conv::{FromProto, IntoProto};
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};

// Internal use only. Contains all the fields in VoteDataSerializer that contributes to the
// computation of its hash.
struct VoteDataSerializer {
    block_id: HashValue,
    executed_state_id: HashValue,
    round: Round,
    parent_block_id: HashValue,
    parent_block_round: Round,
    grandparent_block_id: HashValue,
    grandparent_block_round: Round,
}

impl CanonicalSerialize for VoteDataSerializer {
    fn serialize(&self, serializer: &mut impl CanonicalSerializer) -> failure::Result<()> {
        serializer
            .encode_bytes(self.block_id.as_ref())?
            .encode_bytes(self.executed_state_id.as_ref())?
            .encode_u64(self.round)?
            .encode_bytes(self.parent_block_id.as_ref())?
            .encode_u64(self.parent_block_round)?
            .encode_bytes(self.grandparent_block_id.as_ref())?
            .encode_u64(self.grandparent_block_round)?;
        Ok(())
    }
}

impl CryptoHash for VoteDataSerializer {
    type Hasher = VoteDataHasher;

    fn hash(&self) -> HashValue {
        let mut state = Self::Hasher::default();
        state.write(
            SimpleSerializer::<Vec<u8>>::serialize(self)
                .expect("Should serialize.")
                .as_ref(),
        );
        state.finish()
    }
}

/// VoteData keeps the information about the block, its parent and grandparent.
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)]
pub struct VoteData {
    /// The id of the proposed block.
    block_id: HashValue,
    /// The id of the state generated by the StateExecutor after executing the proposed block.
    executed_state_id: HashValue,
    /// The round of the block.
    round: Round,
    /// The id of the parent block of the proposal
    parent_block_id: HashValue,
    /// The round of the parent block of the proposal
    parent_block_round: Round,
    /// The id of the grandparent block of the proposal
    grandparent_block_id: HashValue,
    /// The round of the grandparent block of the proposal
    grandparent_block_round: Round,
}

impl Display for VoteData {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(
            f,
            "VoteData: [block id: {}, round: {:02}, parent_block_id: {}, \
             parent_block_round: {:02}, grandparent_block_id: {}, grandparent_block_round: {:02}]",
            self.block_id,
            self.round,
            self.parent_block_id,
            self.parent_block_round,
            self.grandparent_block_id,
            self.grandparent_block_round,
        )
    }
}

impl VoteData {
    pub fn new(
        block_id: HashValue,
        executed_state_id: HashValue,
        round: Round,
        parent_block_id: HashValue,
        parent_block_round: Round,
        grandparent_block_id: HashValue,
        grandparent_block_round: Round,
    ) -> Self {
        Self {
            block_id,
            executed_state_id,
            round,
            parent_block_id,
            parent_block_round,
            grandparent_block_id,
            grandparent_block_round,
        }
    }

    /// Return the id of a block that is being voted.
    pub fn block_id(&self) -> HashValue {
        self.block_id
    }

    /// Return the executed state of the proposed block
    pub fn executed_state_id(&self) -> HashValue {
        self.executed_state_id
    }

    /// Return the round of the block
    pub fn block_round(&self) -> Round {
        self.round
    }

    /// Return the id of the parent of the proposed block
    pub fn parent_block_id(&self) -> HashValue {
        self.parent_block_id
    }

    /// Return the round of the parent block of the proposed block
    pub fn parent_block_round(&self) -> Round {
        self.parent_block_round
    }

    /// Return the id of the grandparent block of the proposed block
    pub fn grandparent_block_id(&self) -> HashValue {
        self.grandparent_block_id
    }

    /// Return the round of the grandparent block of the proposed block
    pub fn grandparent_block_round(&self) -> Round {
        self.grandparent_block_round
    }

    /// Return the hash of this struct
    pub fn hash(&self) -> HashValue {
        Self::vote_digest(
            self.block_id,
            self.executed_state_id,
            self.round,
            self.parent_block_id,
            self.parent_block_round,
            self.grandparent_block_id,
            self.grandparent_block_round,
        )
    }

    /// Return a digest of the vote
    pub fn vote_digest(
        block_id: HashValue,
        executed_state_id: HashValue,
        round: Round,
        parent_block_id: HashValue,
        parent_block_round: Round,
        grandparent_block_id: HashValue,
        grandparent_block_round: Round,
    ) -> HashValue {
        VoteDataSerializer {
            block_id,
            executed_state_id,
            round,
            parent_block_id,
            parent_block_round,
            grandparent_block_id,
            grandparent_block_round,
        }
        .hash()
    }
}

impl IntoProto for VoteData {
    type ProtoType = ProtoVoteData;

    fn into_proto(self) -> Self::ProtoType {
        let mut proto = Self::ProtoType::new();
        proto.set_block_id(self.block_id().into());
        proto.set_executed_state_id(self.executed_state_id().into());
        proto.set_round(self.round);
        proto.set_parent_block_id(self.parent_block_id.into());
        proto.set_parent_block_round(self.parent_block_round);
        proto.set_grandparent_block_id(self.grandparent_block_id.into());
        proto.set_grandparent_block_round(self.grandparent_block_round);
        proto
    }
}

impl FromProto for VoteData {
    type ProtoType = ProtoVoteData;

    fn from_proto(object: Self::ProtoType) -> ProtoResult<Self> {
        let block_id = HashValue::from_slice(object.get_block_id())?;
        let round = object.get_round();
        let executed_state_id = HashValue::from_slice(object.get_executed_state_id())?;
        let parent_block_id = HashValue::from_slice(object.get_parent_block_id())?;
        let parent_block_round = object.get_parent_block_round();
        let grandparent_block_id = HashValue::from_slice(object.get_grandparent_block_id())?;
        let grandparent_block_round = object.get_grandparent_block_round();
        Ok(VoteData {
            block_id,
            executed_state_id,
            round,
            parent_block_id,
            parent_block_round,
            grandparent_block_id,
            grandparent_block_round,
        })
    }
}
<commit_msg>[consensus] impl conversions from/to prost proto and VoteData<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::chained_bft::common::Round;
use canonical_serialization::{CanonicalSerialize, CanonicalSerializer, SimpleSerializer};
use crypto::{
    hash::{CryptoHash, CryptoHasher, VoteDataHasher},
    HashValue,
};
use failure::Result as ProtoResult;
use network::proto::VoteData as ProtoVoteData;
use proto_conv::{FromProto, IntoProto};
use serde::{Deserialize, Serialize};
use std::{
    convert::TryFrom,
    fmt::{Display, Formatter},
};

// Internal use only. Contains all the fields in VoteDataSerializer that contributes to the
// computation of its hash.
struct VoteDataSerializer {
    block_id: HashValue,
    executed_state_id: HashValue,
    round: Round,
    parent_block_id: HashValue,
    parent_block_round: Round,
    grandparent_block_id: HashValue,
    grandparent_block_round: Round,
}

impl CanonicalSerialize for VoteDataSerializer {
    fn serialize(&self, serializer: &mut impl CanonicalSerializer) -> failure::Result<()> {
        serializer
            .encode_bytes(self.block_id.as_ref())?
            .encode_bytes(self.executed_state_id.as_ref())?
            .encode_u64(self.round)?
            .encode_bytes(self.parent_block_id.as_ref())?
            .encode_u64(self.parent_block_round)?
            .encode_bytes(self.grandparent_block_id.as_ref())?
            .encode_u64(self.grandparent_block_round)?;
        Ok(())
    }
}

impl CryptoHash for VoteDataSerializer {
    type Hasher = VoteDataHasher;

    fn hash(&self) -> HashValue {
        let mut state = Self::Hasher::default();
        state.write(
            SimpleSerializer::<Vec<u8>>::serialize(self)
                .expect("Should serialize.")
                .as_ref(),
        );
        state.finish()
    }
}

/// VoteData keeps the information about the block, its parent and grandparent.
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)]
pub struct VoteData {
    /// The id of the proposed block.
    block_id: HashValue,
    /// The id of the state generated by the StateExecutor after executing the proposed block.
    executed_state_id: HashValue,
    /// The round of the block.
    round: Round,
    /// The id of the parent block of the proposal
    parent_block_id: HashValue,
    /// The round of the parent block of the proposal
    parent_block_round: Round,
    /// The id of the grandparent block of the proposal
    grandparent_block_id: HashValue,
    /// The round of the grandparent block of the proposal
    grandparent_block_round: Round,
}

impl Display for VoteData {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(
            f,
            "VoteData: [block id: {}, round: {:02}, parent_block_id: {}, \
             parent_block_round: {:02}, grandparent_block_id: {}, grandparent_block_round: {:02}]",
            self.block_id,
            self.round,
            self.parent_block_id,
            self.parent_block_round,
            self.grandparent_block_id,
            self.grandparent_block_round,
        )
    }
}

impl VoteData {
    pub fn new(
        block_id: HashValue,
        executed_state_id: HashValue,
        round: Round,
        parent_block_id: HashValue,
        parent_block_round: Round,
        grandparent_block_id: HashValue,
        grandparent_block_round: Round,
    ) -> Self {
        Self {
            block_id,
            executed_state_id,
            round,
            parent_block_id,
            parent_block_round,
            grandparent_block_id,
            grandparent_block_round,
        }
    }

    /// Return the id of a block that is being voted.
    pub fn block_id(&self) -> HashValue {
        self.block_id
    }

    /// Return the executed state of the proposed block
    pub fn executed_state_id(&self) -> HashValue {
        self.executed_state_id
    }

    /// Return the round of the block
    pub fn block_round(&self) -> Round {
        self.round
    }

    /// Return the id of the parent of the proposed block
    pub fn parent_block_id(&self) -> HashValue {
        self.parent_block_id
    }

    /// Return the round of the parent block of the proposed block
    pub fn parent_block_round(&self) -> Round {
        self.parent_block_round
    }

    /// Return the id of the grandparent block of the proposed block
    pub fn grandparent_block_id(&self) -> HashValue {
        self.grandparent_block_id
    }

    /// Return the round of the grandparent block of the proposed block
    pub fn grandparent_block_round(&self) -> Round {
        self.grandparent_block_round
    }

    /// Return the hash of this struct
    pub fn hash(&self) -> HashValue {
        Self::vote_digest(
            self.block_id,
            self.executed_state_id,
            self.round,
            self.parent_block_id,
            self.parent_block_round,
            self.grandparent_block_id,
            self.grandparent_block_round,
        )
    }

    /// Return a digest of the vote
    pub fn vote_digest(
        block_id: HashValue,
        executed_state_id: HashValue,
        round: Round,
        parent_block_id: HashValue,
        parent_block_round: Round,
        grandparent_block_id: HashValue,
        grandparent_block_round: Round,
    ) -> HashValue {
        VoteDataSerializer {
            block_id,
            executed_state_id,
            round,
            parent_block_id,
            parent_block_round,
            grandparent_block_id,
            grandparent_block_round,
        }
        .hash()
    }
}

impl IntoProto for VoteData {
    type ProtoType = ProtoVoteData;

    fn into_proto(self) -> Self::ProtoType {
        let mut proto = Self::ProtoType::new();
        proto.set_block_id(self.block_id().into());
        proto.set_executed_state_id(self.executed_state_id().into());
        proto.set_round(self.round);
        proto.set_parent_block_id(self.parent_block_id.into());
        proto.set_parent_block_round(self.parent_block_round);
        proto.set_grandparent_block_id(self.grandparent_block_id.into());
        proto.set_grandparent_block_round(self.grandparent_block_round);
        proto
    }
}

impl FromProto for VoteData {
    type ProtoType = ProtoVoteData;

    fn from_proto(object: Self::ProtoType) -> ProtoResult<Self> {
        let block_id = HashValue::from_slice(object.get_block_id())?;
        let round = object.get_round();
        let executed_state_id = HashValue::from_slice(object.get_executed_state_id())?;
        let parent_block_id = HashValue::from_slice(object.get_parent_block_id())?;
        let parent_block_round = object.get_parent_block_round();
        let grandparent_block_id = HashValue::from_slice(object.get_grandparent_block_id())?;
        let grandparent_block_round = object.get_grandparent_block_round();
        Ok(VoteData {
            block_id,
            executed_state_id,
            round,
            parent_block_id,
            parent_block_round,
            grandparent_block_id,
            grandparent_block_round,
        })
    }
}

impl TryFrom<network::proto::consensus_prost::VoteData> for VoteData {
    type Error = failure::Error;

    fn try_from(proto: network::proto::consensus_prost::VoteData) -> failure::Result<Self> {
        let block_id = HashValue::from_slice(proto.block_id.as_ref())?;
        let round = proto.round;
        let executed_state_id = HashValue::from_slice(proto.executed_state_id.as_ref())?;
        let parent_block_id = HashValue::from_slice(proto.parent_block_id.as_ref())?;
        let parent_block_round = proto.parent_block_round;
        let grandparent_block_id = HashValue::from_slice(proto.grandparent_block_id.as_ref())?;
        let grandparent_block_round = proto.grandparent_block_round;
        Ok(VoteData {
            block_id,
            executed_state_id,
            round,
            parent_block_id,
            parent_block_round,
            grandparent_block_id,
            grandparent_block_round,
        })
    }
}

impl From<VoteData> for network::proto::consensus_prost::VoteData {
    fn from(vote: VoteData) -> Self {
        Self {
            block_id: vote.block_id.to_vec(),
            executed_state_id: vote.executed_state_id.to_vec(),
            round: vote.round,
            parent_block_id: vote.parent_block_id.to_vec(),
            parent_block_round: vote.parent_block_round,
            grandparent_block_id: vote.grandparent_block_id.to_vec(),
            grandparent_block_round: vote.grandparent_block_round,
        }
    }
}
<|endoftext|>