<commit_before>use bytes::Buf;
use hashing::hash;
use int_to_bytes::{int_to_bytes1, int_to_bytes4};
use std::cmp::max;
use std::io::Cursor;

/// Return `p(index)` in a pseudorandom permutation `p` of `0...list_size-1` with ``seed`` as entropy.
///
/// Utilizes 'swap or not' shuffling found in
/// https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf
/// See the 'generalized domain' algorithm on page 3.
///
/// Note: this function is significantly slower than the `shuffle_list` function in this crate.
/// Using `get_permutated_list` to shuffle an entire list, index by index, has been observed to be
/// 250x slower than `shuffle_list`. Therefore, this function is only useful when shuffling a small
/// portion of a much larger list.
///
/// Returns `None` under any of the following conditions:
///  - `list_size == 0`
///  - `index >= list_size`
///  - `list_size > 2**24`
///  - `list_size > usize::max_value() / 2`
pub fn get_permutated_index(
    index: usize,
    list_size: usize,
    seed: &[u8],
    shuffle_round_count: u8,
) -> Option<usize> {
    if list_size == 0
        || index >= list_size
        || list_size > usize::max_value() / 2
        || list_size > 2_usize.pow(24)
    {
        return None;
    }

    let mut index = index;
    for round in 0..shuffle_round_count {
        let pivot = bytes_to_int64(&hash_with_round(seed, round)[..]) as usize % list_size;
        index = do_round(seed, index, pivot, round, list_size)?;
    }
    Some(index)
}

fn do_round(seed: &[u8], index: usize, pivot: usize, round: u8, list_size: usize) -> Option<usize> {
    let flip = (pivot + list_size - index) % list_size;
    let position = max(index, flip);
    let source = hash_with_round_and_position(seed, round, position)?;
    let byte = source[(position % 256) / 8];
    let bit = (byte >> (position % 8)) % 2;
    Some(if bit == 1 { flip } else { index })
}

fn hash_with_round_and_position(seed: &[u8], round: u8, position: usize) -> Option<Vec<u8>> {
    let mut seed = seed.to_vec();
    seed.append(&mut int_to_bytes1(round));
    /*
     * Note: the specification has an implicit assertion in `int_to_bytes4` that `position / 256 <
     * 2**24`. For efficiency, we do not check for that here as it is checked in `get_permutated_index`.
     */
    seed.append(&mut int_to_bytes4((position / 256) as u32));
    Some(hash(&seed[..]))
}

fn hash_with_round(seed: &[u8], round: u8) -> Vec<u8> {
    let mut seed = seed.to_vec();
    seed.append(&mut int_to_bytes1(round));
    hash(&seed[..])
}

fn bytes_to_int64(bytes: &[u8]) -> u64 {
    let mut cursor = Cursor::new(bytes);
    cursor.get_u64_le()
}

#[cfg(test)]
mod tests {
    use super::*;
    use ethereum_types::H256 as Hash256;
    use hex;
    use std::{fs::File, io::prelude::*, path::PathBuf};
    use yaml_rust::yaml;

    #[test]
    #[ignore]
    fn fuzz_test() {
        let max_list_size = 2_usize.pow(24);
        let test_runs = 1000;

        // Test at max list_size with the end index.
        for _ in 0..test_runs {
            let index = max_list_size - 1;
            let list_size = max_list_size;
            let seed = Hash256::random();
            let shuffle_rounds = 90;

            assert!(get_permutated_index(index, list_size, &seed[..], shuffle_rounds).is_some());
        }

        // Test at max list_size low indices.
        for i in 0..test_runs {
            let index = i;
            let list_size = max_list_size;
            let seed = Hash256::random();
            let shuffle_rounds = 90;

            assert!(get_permutated_index(index, list_size, &seed[..], shuffle_rounds).is_some());
        }

        // Test at max list_size high indices.
        for i in 0..test_runs {
            let index = max_list_size - 1 - i;
            let list_size = max_list_size;
            let seed = Hash256::random();
            let shuffle_rounds = 90;

            assert!(get_permutated_index(index, list_size, &seed[..], shuffle_rounds).is_some());
        }
    }

    #[test]
    fn returns_none_for_zero_length_list() {
        assert_eq!(None, get_permutated_index(100, 0, &[42, 42], 90));
    }

    #[test]
    fn returns_none_for_out_of_bounds_index() {
        assert_eq!(None, get_permutated_index(100, 100, &[42, 42], 90));
    }

    #[test]
    fn returns_none_for_too_large_list() {
        assert_eq!(
            None,
            get_permutated_index(100, usize::max_value() / 2, &[42, 42], 90)
        );
    }

    #[test]
    fn test_vectors() {
        /*
         * Test vectors are generated here:
         *
         * https://github.com/ethereum/eth2.0-test-generators
         */
        let mut file = {
            let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
            file_path_buf.push("src/specs/test_vector_permutated_index.yml");

            File::open(file_path_buf).unwrap()
        };

        let mut yaml_str = String::new();

        file.read_to_string(&mut yaml_str).unwrap();

        let docs = yaml::YamlLoader::load_from_str(&yaml_str).unwrap();
        let doc = &docs[0];
        let test_cases = doc["test_cases"].as_vec().unwrap();

        for (i, test_case) in test_cases.iter().enumerate() {
            let index = test_case["index"].as_i64().unwrap() as usize;
            let list_size = test_case["list_size"].as_i64().unwrap() as usize;
            let permutated_index = test_case["permutated_index"].as_i64().unwrap() as usize;
            let shuffle_round_count = test_case["shuffle_round_count"].as_i64().unwrap();
            let seed_string = test_case["seed"].clone().into_string().unwrap();
            let seed = hex::decode(seed_string.replace("0x", "")).unwrap();

            let shuffle_round_count = if shuffle_round_count < (u8::max_value() as i64) {
                shuffle_round_count as u8
            } else {
                panic!("shuffle_round_count must be a u8")
            };

            assert_eq!(
                Some(permutated_index),
                get_permutated_index(index, list_size, &seed[..], shuffle_round_count),
                "Failure on case #{} index: {}, list_size: {}, round_count: {}, seed: {}",
                i,
                index,
                list_size,
                shuffle_round_count,
                seed_string,
            );
        }
    }
}
<commit_msg>Update shuffling to use new(ish) to_le_bytes fn<commit_after>use hashing::hash;
use int_to_bytes::{int_to_bytes1, int_to_bytes4};
use std::cmp::max;

/// Return `p(index)` in a pseudorandom permutation `p` of `0...list_size-1` with ``seed`` as entropy.
///
/// Utilizes 'swap or not' shuffling found in
/// https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf
/// See the 'generalized domain' algorithm on page 3.
///
/// Note: this function is significantly slower than the `shuffle_list` function in this crate.
/// Using `get_permutated_list` to shuffle an entire list, index by index, has been observed to be
/// 250x slower than `shuffle_list`. Therefore, this function is only useful when shuffling a small
/// portion of a much larger list.
///
/// Returns `None` under any of the following conditions:
///  - `list_size == 0`
///  - `index >= list_size`
///  - `list_size > 2**24`
///  - `list_size > usize::max_value() / 2`
pub fn get_permutated_index(
    index: usize,
    list_size: usize,
    seed: &[u8],
    shuffle_round_count: u8,
) -> Option<usize> {
    if list_size == 0
        || index >= list_size
        || list_size > usize::max_value() / 2
        || list_size > 2_usize.pow(24)
    {
        return None;
    }

    let mut index = index;
    for round in 0..shuffle_round_count {
        let pivot = bytes_to_int64(&hash_with_round(seed, round)[..]) as usize % list_size;
        index = do_round(seed, index, pivot, round, list_size)?;
    }
    Some(index)
}

fn do_round(seed: &[u8], index: usize, pivot: usize, round: u8, list_size: usize) -> Option<usize> {
    let flip = (pivot + list_size - index) % list_size;
    let position = max(index, flip);
    let source = hash_with_round_and_position(seed, round, position)?;
    let byte = source[(position % 256) / 8];
    let bit = (byte >> (position % 8)) % 2;
    Some(if bit == 1 { flip } else { index })
}

fn hash_with_round_and_position(seed: &[u8], round: u8, position: usize) -> Option<Vec<u8>> {
    let mut seed = seed.to_vec();
    seed.append(&mut int_to_bytes1(round));
    /*
     * Note: the specification has an implicit assertion in `int_to_bytes4` that `position / 256 <
     * 2**24`. For efficiency, we do not check for that here as it is checked in `get_permutated_index`.
     */
    seed.append(&mut int_to_bytes4((position / 256) as u32));
    Some(hash(&seed[..]))
}

fn hash_with_round(seed: &[u8], round: u8) -> Vec<u8> {
    let mut seed = seed.to_vec();
    seed.append(&mut int_to_bytes1(round));
    hash(&seed[..])
}

fn bytes_to_int64(slice: &[u8]) -> u64 {
    let mut bytes = [0; 8];
    bytes.copy_from_slice(&slice[0..8]);
    u64::from_le_bytes(bytes)
}

#[cfg(test)]
mod tests {
    use super::*;
    use ethereum_types::H256 as Hash256;
    use hex;
    use std::{fs::File, io::prelude::*, path::PathBuf};
    use yaml_rust::yaml;

    #[test]
    #[ignore]
    fn fuzz_test() {
        let max_list_size = 2_usize.pow(24);
        let test_runs = 1000;

        // Test at max list_size with the end index.
        for _ in 0..test_runs {
            let index = max_list_size - 1;
            let list_size = max_list_size;
            let seed = Hash256::random();
            let shuffle_rounds = 90;

            assert!(get_permutated_index(index, list_size, &seed[..], shuffle_rounds).is_some());
        }

        // Test at max list_size low indices.
        for i in 0..test_runs {
            let index = i;
            let list_size = max_list_size;
            let seed = Hash256::random();
            let shuffle_rounds = 90;

            assert!(get_permutated_index(index, list_size, &seed[..], shuffle_rounds).is_some());
        }

        // Test at max list_size high indices.
        for i in 0..test_runs {
            let index = max_list_size - 1 - i;
            let list_size = max_list_size;
            let seed = Hash256::random();
            let shuffle_rounds = 90;

            assert!(get_permutated_index(index, list_size, &seed[..], shuffle_rounds).is_some());
        }
    }

    #[test]
    fn returns_none_for_zero_length_list() {
        assert_eq!(None, get_permutated_index(100, 0, &[42, 42], 90));
    }

    #[test]
    fn returns_none_for_out_of_bounds_index() {
        assert_eq!(None, get_permutated_index(100, 100, &[42, 42], 90));
    }

    #[test]
    fn returns_none_for_too_large_list() {
        assert_eq!(
            None,
            get_permutated_index(100, usize::max_value() / 2, &[42, 42], 90)
        );
    }

    #[test]
    fn test_vectors() {
        /*
         * Test vectors are generated here:
         *
         * https://github.com/ethereum/eth2.0-test-generators
         */
        let mut file = {
            let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
            file_path_buf.push("src/specs/test_vector_permutated_index.yml");

            File::open(file_path_buf).unwrap()
        };

        let mut yaml_str = String::new();

        file.read_to_string(&mut yaml_str).unwrap();

        let docs = yaml::YamlLoader::load_from_str(&yaml_str).unwrap();
        let doc = &docs[0];
        let test_cases = doc["test_cases"].as_vec().unwrap();

        for (i, test_case) in test_cases.iter().enumerate() {
            let index = test_case["index"].as_i64().unwrap() as usize;
            let list_size = test_case["list_size"].as_i64().unwrap() as usize;
            let permutated_index = test_case["permutated_index"].as_i64().unwrap() as usize;
            let shuffle_round_count = test_case["shuffle_round_count"].as_i64().unwrap();
            let seed_string = test_case["seed"].clone().into_string().unwrap();
            let seed = hex::decode(seed_string.replace("0x", "")).unwrap();

            let shuffle_round_count = if shuffle_round_count < (u8::max_value() as i64) {
                shuffle_round_count as u8
            } else {
                panic!("shuffle_round_count must be a u8")
            };

            assert_eq!(
                Some(permutated_index),
                get_permutated_index(index, list_size, &seed[..], shuffle_round_count),
                "Failure on case #{} index: {}, list_size: {}, round_count: {}, seed: {}",
                i,
                index,
                list_size,
                shuffle_round_count,
                seed_string,
            );
        }
    }
}
<|endoftext|>


<commit_before>use futures::stable::block_on_stable;
use futures::executor::{block_on, ThreadPool};
use futures::prelude::*;

#[async]
fn foo() -> Result<i32, i32> {
    Ok(1)
}

#[async]
fn bar(x: &i32) -> Result<i32, i32> {
    Ok(*x)
}

#[async]
fn baz(x: i32) -> Result<i32, i32> {
    await!(bar(&x))
}

#[async_move]
fn qux(x: i32) -> Result<i32, i32> {
    await!(baz(x).pin())
}

// This test is to check that the internal __await macro generated in each
// function does not leak across function boundaries. If it did then calling
// the #[async] version of __await in the #[async_move] function should cause
// a 'borrow may still be in use when generator yields' error, while calling
// the #[async_move] version in the #[async] function should fail because `bar`
// does not implement `Future`.
#[async_move]
fn qux2(x: i32) -> Result<i32, i32> {
    #[async]
    fn baz2(x: i32) -> Result<i32, i32> {
        await!(bar(&x))
    }
    await!(baz2(x).pin())
}

#[async(pinned)]
fn boxed(x: i32) -> Result<i32, i32> {
    Ok(x)
}

#[async(pinned)]
fn boxed_borrow(x: &i32) -> Result<i32, i32> {
    Ok(*x)
}

#[async(pinned_send)]
fn boxed_send(x: i32) -> Result<i32, i32> {
    Ok(x)
}

#[async(pinned_send)]
fn boxed_send_borrow(x: &i32) -> Result<i32, i32> {
    Ok(*x)
}

#[async(pinned_send)]
fn spawnable() -> Result<(), Never> {
    Ok(())
}

#[async_stream(item = u64)]
fn _stream1() -> Result<(), i32> {
    fn integer() -> u64 { 1 }
    let x = &integer();
    stream_yield!(0);
    stream_yield!(*x);
    Ok(())
}

#[async_stream(pinned, item = u64)]
fn _stream_boxed() -> Result<(), i32> {
    fn integer() -> u64 { 1 }
    let x = &integer();
    stream_yield!(0);
    stream_yield!(*x);
    Ok(())
}

#[async]
pub fn uses_async_for() -> Result<Vec<u64>, i32> {
    let mut v = vec![];
    #[async]
    for i in _stream1() {
        v.push(i);
    }
    Ok(v)
}

#[test]
fn main() {
    assert_eq!(block_on_stable(foo()), Ok(1));
    assert_eq!(block_on_stable(bar(&1)), Ok(1));
    assert_eq!(block_on_stable(baz(17)), Ok(17));
    assert_eq!(block_on_stable(qux(17)), Ok(17));
    assert_eq!(block_on_stable(qux2(17)), Ok(17));
    assert_eq!(block_on(boxed(17)), Ok(17));
    assert_eq!(block_on(boxed_send(17)), Ok(17));
    assert_eq!(block_on_stable(uses_async_for()), Ok(vec![0, 1]));
}

#[test]
fn run_pinned_future_in_thread_pool() {
    let mut pool = ThreadPool::new().unwrap();
    pool.spawn_pinned(spawnable()).unwrap();
}
<commit_msg>Test borrowing test functions by using them<commit_after>use futures::stable::block_on_stable;
use futures::executor::{block_on, ThreadPool};
use futures::prelude::*;

#[async]
fn foo() -> Result<i32, i32> {
    Ok(1)
}

#[async]
fn bar(x: &i32) -> Result<i32, i32> {
    Ok(*x)
}

#[async]
fn baz(x: i32) -> Result<i32, i32> {
    await!(bar(&x))
}

#[async_move]
fn qux(x: i32) -> Result<i32, i32> {
    await!(baz(x).pin())
}

// This test is to check that the internal __await macro generated in each
// function does not leak across function boundaries. If it did then calling
// the #[async] version of __await in the #[async_move] function should cause
// a 'borrow may still be in use when generator yields' error, while calling
// the #[async_move] version in the #[async] function should fail because `bar`
// does not implement `Future`.
#[async_move]
fn qux2(x: i32) -> Result<i32, i32> {
    #[async]
    fn baz2(x: i32) -> Result<i32, i32> {
        await!(bar(&x))
    }
    await!(baz2(x).pin())
}

#[async(pinned)]
fn boxed(x: i32) -> Result<i32, i32> {
    Ok(x)
}

#[async(pinned)]
fn boxed_borrow(x: &i32) -> Result<i32, i32> {
    Ok(*x)
}

#[async(pinned_send)]
fn boxed_send(x: i32) -> Result<i32, i32> {
    Ok(x)
}

#[async(pinned_send)]
fn boxed_send_borrow(x: &i32) -> Result<i32, i32> {
    Ok(*x)
}

#[async(pinned_send)]
fn spawnable() -> Result<(), Never> {
    Ok(())
}

#[async_stream(item = u64)]
fn _stream1() -> Result<(), i32> {
    fn integer() -> u64 { 1 }
    let x = &integer();
    stream_yield!(0);
    stream_yield!(*x);
    Ok(())
}

#[async_stream(pinned, item = u64)]
fn _stream_boxed() -> Result<(), i32> {
    fn integer() -> u64 { 1 }
    let x = &integer();
    stream_yield!(0);
    stream_yield!(*x);
    Ok(())
}

#[async]
pub fn uses_async_for() -> Result<Vec<u64>, i32> {
    let mut v = vec![];
    #[async]
    for i in _stream1() {
        v.push(i);
    }
    Ok(v)
}

#[test]
fn main() {
    assert_eq!(block_on_stable(foo()), Ok(1));
    assert_eq!(block_on_stable(bar(&1)), Ok(1));
    assert_eq!(block_on_stable(baz(17)), Ok(17));
    assert_eq!(block_on_stable(qux(17)), Ok(17));
    assert_eq!(block_on_stable(qux2(17)), Ok(17));
    assert_eq!(block_on(boxed(17)), Ok(17));
    assert_eq!(block_on(boxed_send(17)), Ok(17));
    assert_eq!(block_on(boxed_borrow(&17)), Ok(17));
    assert_eq!(block_on(boxed_send_borrow(&17)), Ok(17));
    assert_eq!(block_on_stable(uses_async_for()), Ok(vec![0, 1]));
}

#[test]
fn run_pinned_future_in_thread_pool() {
    let mut pool = ThreadPool::new().unwrap();
    pool.spawn_pinned(spawnable()).unwrap();
}
<|endoftext|>


<commit_before>//! Diagnostic data structures.

#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};
use std::ops::Range;
use std::fmt::Display;

/// A severity level for diagnostic messages.
///
/// These are ordered in the following way:
///
/// ```rust
/// use codespan_reporting::diagnostic::Severity;
///
/// assert!(Severity::Bug > Severity::Error);
/// assert!(Severity::Error > Severity::Warning);
/// assert!(Severity::Warning > Severity::Note);
/// assert!(Severity::Note > Severity::Help);
/// ```
#[derive(Copy, Clone, PartialEq, Hash, Debug)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub enum Severity {
    /// An unexpected bug.
    Bug,
    /// An error.
    Error,
    /// A warning.
    Warning,
    /// A note.
    Note,
    /// A help message.
    Help,
}

impl Severity {
    /// We want bugs to be the maximum severity, errors next, etc...
    fn to_cmp_int(self) -> u8 {
        match self {
            Severity::Bug => 5,
            Severity::Error => 4,
            Severity::Warning => 3,
            Severity::Note => 2,
            Severity::Help => 1,
        }
    }
}

impl PartialOrd for Severity {
    fn partial_cmp(&self, other: &Severity) -> Option<std::cmp::Ordering> {
        u8::partial_cmp(&self.to_cmp_int(), &other.to_cmp_int())
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub enum LabelStyle {
    /// Labels that describe the primary cause of a diagnostic.
    Primary,
    /// Labels that provide additional context for a diagnostic.
    Secondary,
}

/// A label describing an underlined region of code associated with a diagnostic.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Label<FileId> {
    /// The style of the label.
    pub style: LabelStyle,
    /// The file that we are labelling.
    pub file_id: FileId,
    /// The range we are going to include in the final snippet.
    pub range: Range<usize>,
    /// An optional message to provide some additional information for the
    /// underlined code. These should not include line breaks.
    pub message: String,
}

impl<FileId> Label<FileId> {
    /// Create a new label.
    pub fn new(
        style: LabelStyle,
        file_id: FileId,
        range: impl Into<Range<usize>>,
    ) -> Label<FileId> {
        Label {
            style,
            file_id,
            range: range.into(),
            message: String::new(),
        }
    }

    /// Create a new label with a style of [`LabelStyle::Primary`].
    ///
    /// [`LabelStyle::Primary`]: LabelStyle::Primary
    pub fn primary(file_id: FileId, range: impl Into<Range<usize>>) -> Label<FileId> {
        Label::new(LabelStyle::Primary, file_id, range)
    }

    /// Create a new label with a style of [`LabelStyle::Secondary`].
    ///
    /// [`LabelStyle::Secondary`]: LabelStyle::Secondary
    pub fn secondary(file_id: FileId, range: impl Into<Range<usize>>) -> Label<FileId> {
        Label::new(LabelStyle::Secondary, file_id, range)
    }

    /// Add a message to the diagnostic.
    pub fn with_message(mut self, message: impl Display) -> Label<FileId> {
        self.message = message.to_string();
        self
    }
}

/// Represents a diagnostic message that can provide information like errors and
/// warnings to the user.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Diagnostic<FileId> {
    /// The overall severity of the diagnostic
    pub severity: Severity,
    /// An optional code that identifies this diagnostic.
    pub code: Option<String>,
    /// The main message associated with this diagnostic.
    ///
    /// These should not include line breaks, and in order support the 'short'
    /// diagnostic display mod, the message should be specific enough to make
    /// sense on its own, without additional context provided by labels and notes.
    pub message: String,
    /// Source labels that describe the cause of the diagnostic.
    pub labels: Vec<Label<FileId>>,
    /// Notes that are associated with the primary cause of the diagnostic.
    /// These can include line breaks for improved formatting.
    pub notes: Vec<String>,
}

impl<FileId> Diagnostic<FileId> {
    /// Create a new diagnostic.
    pub fn new(severity: Severity) -> Diagnostic<FileId> {
        Diagnostic {
            severity,
            code: None,
            message: String::new(),
            labels: Vec::new(),
            notes: Vec::new(),
        }
    }

    /// Create a new diagnostic with a severity of [`Severity::Bug`].
    ///
    /// [`Severity::Bug`]: Severity::Bug
    pub fn bug() -> Diagnostic<FileId> {
        Diagnostic::new(Severity::Bug)
    }

    /// Create a new diagnostic with a severity of [`Severity::Error`].
    ///
    /// [`Severity::Error`]: Severity::Error
    pub fn error() -> Diagnostic<FileId> {
        Diagnostic::new(Severity::Error)
    }

    /// Create a new diagnostic with a severity of [`Severity::Warning`].
    ///
    /// [`Severity::Warning`]: Severity::Warning
    pub fn warning() -> Diagnostic<FileId> {
        Diagnostic::new(Severity::Warning)
    }

    /// Create a new diagnostic with a severity of [`Severity::Note`].
    ///
    /// [`Severity::Note`]: Severity::Note
    pub fn note() -> Diagnostic<FileId> {
        Diagnostic::new(Severity::Note)
    }

    /// Create a new diagnostic with a severity of [`Severity::Help`].
    ///
    /// [`Severity::Help`]: Severity::Help
    pub fn help() -> Diagnostic<FileId> {
        Diagnostic::new(Severity::Help)
    }

    /// Add an error code to the diagnostic.
    pub fn with_code(mut self, code: impl Into<String>) -> Diagnostic<FileId> {
        self.code = Some(code.into());
        self
    }

    /// Add a message to the diagnostic.
    pub fn with_message(mut self, message: impl Display) -> Diagnostic<FileId> {
        self.message = message.to_string();
        self
    }

    /// Add some labels to the diagnostic.
    pub fn with_labels(mut self, labels: Vec<Label<FileId>>) -> Diagnostic<FileId> {
        self.labels = labels;
        self
    }

    /// Add some notes to the diagnostic.
    pub fn with_notes(mut self, notes: Vec<String>) -> Diagnostic<FileId> {
        self.notes = notes;
        self
    }
}
<commit_msg>change to ToString trait<commit_after>//! Diagnostic data structures.

#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};
use std::string::ToString;
use std::ops::Range;

/// A severity level for diagnostic messages.
///
/// These are ordered in the following way:
///
/// ```rust
/// use codespan_reporting::diagnostic::Severity;
///
/// assert!(Severity::Bug > Severity::Error);
/// assert!(Severity::Error > Severity::Warning);
/// assert!(Severity::Warning > Severity::Note);
/// assert!(Severity::Note > Severity::Help);
/// ```
#[derive(Copy, Clone, PartialEq, Hash, Debug)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub enum Severity {
    /// An unexpected bug.
    Bug,
    /// An error.
    Error,
    /// A warning.
    Warning,
    /// A note.
    Note,
    /// A help message.
    Help,
}

impl Severity {
    /// We want bugs to be the maximum severity, errors next, etc...
    fn to_cmp_int(self) -> u8 {
        match self {
            Severity::Bug => 5,
            Severity::Error => 4,
            Severity::Warning => 3,
            Severity::Note => 2,
            Severity::Help => 1,
        }
    }
}

impl PartialOrd for Severity {
    fn partial_cmp(&self, other: &Severity) -> Option<std::cmp::Ordering> {
        u8::partial_cmp(&self.to_cmp_int(), &other.to_cmp_int())
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub enum LabelStyle {
    /// Labels that describe the primary cause of a diagnostic.
    Primary,
    /// Labels that provide additional context for a diagnostic.
    Secondary,
}

/// A label describing an underlined region of code associated with a diagnostic.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Label<FileId> {
    /// The style of the label.
    pub style: LabelStyle,
    /// The file that we are labelling.
    pub file_id: FileId,
    /// The range we are going to include in the final snippet.
    pub range: Range<usize>,
    /// An optional message to provide some additional information for the
    /// underlined code. These should not include line breaks.
    pub message: String,
}

impl<FileId> Label<FileId> {
    /// Create a new label.
    pub fn new(
        style: LabelStyle,
        file_id: FileId,
        range: impl Into<Range<usize>>,
    ) -> Label<FileId> {
        Label {
            style,
            file_id,
            range: range.into(),
            message: String::new(),
        }
    }

    /// Create a new label with a style of [`LabelStyle::Primary`].
    ///
    /// [`LabelStyle::Primary`]: LabelStyle::Primary
    pub fn primary(file_id: FileId, range: impl Into<Range<usize>>) -> Label<FileId> {
        Label::new(LabelStyle::Primary, file_id, range)
    }

    /// Create a new label with a style of [`LabelStyle::Secondary`].
    ///
    /// [`LabelStyle::Secondary`]: LabelStyle::Secondary
    pub fn secondary(file_id: FileId, range: impl Into<Range<usize>>) -> Label<FileId> {
        Label::new(LabelStyle::Secondary, file_id, range)
    }

    /// Add a message to the diagnostic.
    pub fn with_message(mut self, message: impl ToString) -> Label<FileId> {
        self.message = message.to_string();
        self
    }
}

/// Represents a diagnostic message that can provide information like errors and
/// warnings to the user.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Diagnostic<FileId> {
    /// The overall severity of the diagnostic
    pub severity: Severity,
    /// An optional code that identifies this diagnostic.
    pub code: Option<String>,
    /// The main message associated with this diagnostic.
    ///
    /// These should not include line breaks, and in order support the 'short'
    /// diagnostic display mod, the message should be specific enough to make
    /// sense on its own, without additional context provided by labels and notes.
    pub message: String,
    /// Source labels that describe the cause of the diagnostic.
    pub labels: Vec<Label<FileId>>,
    /// Notes that are associated with the primary cause of the diagnostic.
    /// These can include line breaks for improved formatting.
    pub notes: Vec<String>,
}

impl<FileId> Diagnostic<FileId> {
    /// Create a new diagnostic.
    pub fn new(severity: Severity) -> Diagnostic<FileId> {
        Diagnostic {
            severity,
            code: None,
            message: String::new(),
            labels: Vec::new(),
            notes: Vec::new(),
        }
    }

    /// Create a new diagnostic with a severity of [`Severity::Bug`].
    ///
    /// [`Severity::Bug`]: Severity::Bug
    pub fn bug() -> Diagnostic<FileId> {
        Diagnostic::new(Severity::Bug)
    }

    /// Create a new diagnostic with a severity of [`Severity::Error`].
    ///
    /// [`Severity::Error`]: Severity::Error
    pub fn error() -> Diagnostic<FileId> {
        Diagnostic::new(Severity::Error)
    }

    /// Create a new diagnostic with a severity of [`Severity::Warning`].
    ///
    /// [`Severity::Warning`]: Severity::Warning
    pub fn warning() -> Diagnostic<FileId> {
        Diagnostic::new(Severity::Warning)
    }

    /// Create a new diagnostic with a severity of [`Severity::Note`].
    ///
    /// [`Severity::Note`]: Severity::Note
    pub fn note() -> Diagnostic<FileId> {
        Diagnostic::new(Severity::Note)
    }

    /// Create a new diagnostic with a severity of [`Severity::Help`].
    ///
    /// [`Severity::Help`]: Severity::Help
    pub fn help() -> Diagnostic<FileId> {
        Diagnostic::new(Severity::Help)
    }

    /// Add an error code to the diagnostic.
    pub fn with_code(mut self, code: impl Into<String>) -> Diagnostic<FileId> {
        self.code = Some(code.into());
        self
    }

    /// Add a message to the diagnostic.
    pub fn with_message(mut self, message: impl ToString) -> Diagnostic<FileId> {
        self.message = message.to_string();
        self
    }

    /// Add some labels to the diagnostic.
    pub fn with_labels(mut self, labels: Vec<Label<FileId>>) -> Diagnostic<FileId> {
        self.labels = labels;
        self
    }

    /// Add some notes to the diagnostic.
    pub fn with_notes(mut self, notes: Vec<String>) -> Diagnostic<FileId> {
        self.notes = notes;
        self
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#![no_main]

use std::fs::File;
use std::io::{Cursor, Read, Seek, SeekFrom};
use std::mem::size_of;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::panic;
use std::process;
use std::slice;
use std::sync::atomic::AtomicUsize;
use std::sync::Arc;

use devices::virtio::{Block, Queue, VirtioDevice};
use sys_util::{EventFd, GuestAddress, GuestMemory, SharedMemory};

const MEM_SIZE: u64 = 256 * 1024 * 1024;
const DESC_SIZE: u64 = 16; // Bytes in one virtio descriptor.
const QUEUE_SIZE: u16 = 16; // Max entries in the queue.
const CMD_SIZE: usize = 16; // Bytes in the command.

// Take the first 64 bits of data as an address and the next 64 bits as data to
// store there. The rest of the data is used as a qcow image.
#[export_name = "LLVMFuzzerTestOneInput"]
pub fn test_one_input(data: *const u8, size: usize) -> i32 {
    // We cannot unwind past ffi boundaries.
    panic::catch_unwind(|| {
        // Safe because the libfuzzer runtime will guarantee that `data` is at least
        // `size` bytes long and that it will be valid for the lifetime of this
        // function.
        let bytes = unsafe { slice::from_raw_parts(data, size) };
        let size_u64 = size_of::<u64>();
        let mem = GuestMemory::new(&[(GuestAddress(0), MEM_SIZE)]).unwrap();

        // The fuzz data is interpreted as:
        // starting index 8 bytes
        // command location 8 bytes
        // command 16 bytes
        // descriptors circular buffer 16 bytes * 3
        if bytes.len() < 4 * size_u64 {
            // Need an index to start.
            return;
        }

        let mut data_image = Cursor::new(bytes);

        let first_index = read_u64(&mut data_image);
        if first_index > MEM_SIZE / DESC_SIZE {
            return;
        }
        let first_offset = first_index * DESC_SIZE;
        if first_offset as usize + size_u64 > bytes.len() {
            return;
        }

        let command_addr = read_u64(&mut data_image);
        if command_addr > MEM_SIZE - CMD_SIZE as u64 {
            return;
        }
        if mem
            .write_all_at_addr(
                &bytes[2 * size_u64..(2 * size_u64) + CMD_SIZE],
                GuestAddress(command_addr as u64),
            )
            .is_err()
        {
            return;
        }

        data_image.seek(SeekFrom::Start(first_offset)).unwrap();
        let desc_table = read_u64(&mut data_image);

        if mem
            .write_all_at_addr(&bytes[32..], GuestAddress(desc_table as u64))
            .is_err()
        {
            return;
        }

        let mut q = Queue::new(QUEUE_SIZE);
        q.ready = true;
        q.size = QUEUE_SIZE / 2;
        q.max_size = QUEUE_SIZE;

        let queue_evts: Vec<EventFd> = vec![EventFd::new().unwrap()];
        let queue_fd = queue_evts[0].as_raw_fd();
        let queue_evt = unsafe { EventFd::from_raw_fd(libc::dup(queue_fd)) };

        let shm = SharedMemory::anon().unwrap();
        let disk_file: File = shm.into();
        let mut block = Block::new(Box::new(disk_file), false, None).unwrap();

        block.activate(
            mem,
            EventFd::new().unwrap(),
            EventFd::new().unwrap(),
            Arc::new(AtomicUsize::new(0)),
            vec![q],
            queue_evts,
        );

        queue_evt.write(77).unwrap(); // Rings the doorbell, any byte will do.
    })
    .err()
    .map(|_| process::abort());

    0
}

fn read_u64<T: Read>(readable: &mut T) -> u64 {
    let mut buf = [0u8; size_of::<u64>()];
    readable.read_exact(&mut buf[..]).unwrap();
    u64::from_le_bytes(buf)
}
<commit_msg>fuzz: remove misleading block fuzzer comment<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#![no_main]

use std::fs::File;
use std::io::{Cursor, Read, Seek, SeekFrom};
use std::mem::size_of;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::panic;
use std::process;
use std::slice;
use std::sync::atomic::AtomicUsize;
use std::sync::Arc;

use devices::virtio::{Block, Queue, VirtioDevice};
use sys_util::{EventFd, GuestAddress, GuestMemory, SharedMemory};

const MEM_SIZE: u64 = 256 * 1024 * 1024;
const DESC_SIZE: u64 = 16; // Bytes in one virtio descriptor.
const QUEUE_SIZE: u16 = 16; // Max entries in the queue.
const CMD_SIZE: usize = 16; // Bytes in the command.

#[export_name = "LLVMFuzzerTestOneInput"]
pub fn test_one_input(data: *const u8, size: usize) -> i32 {
    // We cannot unwind past ffi boundaries.
    panic::catch_unwind(|| {
        // Safe because the libfuzzer runtime will guarantee that `data` is at least
        // `size` bytes long and that it will be valid for the lifetime of this
        // function.
        let bytes = unsafe { slice::from_raw_parts(data, size) };
        let size_u64 = size_of::<u64>();
        let mem = GuestMemory::new(&[(GuestAddress(0), MEM_SIZE)]).unwrap();

        // The fuzz data is interpreted as:
        // starting index 8 bytes
        // command location 8 bytes
        // command 16 bytes
        // descriptors circular buffer 16 bytes * 3
        if bytes.len() < 4 * size_u64 {
            // Need an index to start.
            return;
        }

        let mut data_image = Cursor::new(bytes);

        let first_index = read_u64(&mut data_image);
        if first_index > MEM_SIZE / DESC_SIZE {
            return;
        }
        let first_offset = first_index * DESC_SIZE;
        if first_offset as usize + size_u64 > bytes.len() {
            return;
        }

        let command_addr = read_u64(&mut data_image);
        if command_addr > MEM_SIZE - CMD_SIZE as u64 {
            return;
        }
        if mem
            .write_all_at_addr(
                &bytes[2 * size_u64..(2 * size_u64) + CMD_SIZE],
                GuestAddress(command_addr as u64),
            )
            .is_err()
        {
            return;
        }

        data_image.seek(SeekFrom::Start(first_offset)).unwrap();
        let desc_table = read_u64(&mut data_image);

        if mem
            .write_all_at_addr(&bytes[32..], GuestAddress(desc_table as u64))
            .is_err()
        {
            return;
        }

        let mut q = Queue::new(QUEUE_SIZE);
        q.ready = true;
        q.size = QUEUE_SIZE / 2;
        q.max_size = QUEUE_SIZE;

        let queue_evts: Vec<EventFd> = vec![EventFd::new().unwrap()];
        let queue_fd = queue_evts[0].as_raw_fd();
        let queue_evt = unsafe { EventFd::from_raw_fd(libc::dup(queue_fd)) };

        let shm = SharedMemory::anon().unwrap();
        let disk_file: File = shm.into();
        let mut block = Block::new(Box::new(disk_file), false, None).unwrap();

        block.activate(
            mem,
            EventFd::new().unwrap(),
            EventFd::new().unwrap(),
            Arc::new(AtomicUsize::new(0)),
            vec![q],
            queue_evts,
        );

        queue_evt.write(77).unwrap(); // Rings the doorbell, any byte will do.
    })
    .err()
    .map(|_| process::abort());

    0
}

fn read_u64<T: Read>(readable: &mut T) -> u64 {
    let mut buf = [0u8; size_of::<u64>()];
    readable.read_exact(&mut buf[..]).unwrap();
    u64::from_le_bytes(buf)
}
<|endoftext|>


<commit_before>use common::types::Ty;

#[derive(Clone)]
pub struct Expr
{
	out_ty: Ty,
	spec: ExprSpec
}

impl Expr
{
	pub fn spec(&self) -> &ExprSpec
	{
		&self.spec
	}
}

/// Expression Specific Element
#[derive(Clone)]
pub enum ExprSpec {
  // Unary Expressions
  Not(Box<Expr>),
  IsNull(Box<Expr>, bool), // bool - 'is null' if true. 'is not null' if false.
  Sign(Box<Expr>, bool), // true - Plus, false - Minus
  Cast(Box<Expr>, Box<Ty>, Box<Ty>),

  // Binary Arithmetic Expressions
  And(Box<Expr>,Box<Expr>),
  Or(Box<Expr>,Box<Expr>),
  Comp(CompOp, Box<Expr>, Box<Expr>),
  Arithm(ArithmOp, Box<Expr>, Box<Expr>),
  Concat(Box<Expr>,Box<Expr>),

  // Functions
  Fn(Box<FnDecl>, Vec<Box<Expr>>),

  // String operators or pattern matching predicates: lhs - pattern, rhs - value
  Like(Box<Expr>,Box<Expr>, bool),
  SimilarTo(Box<Expr>,Box<Expr>, bool),
  RegexMatch(Box<Expr>,Box<Expr>, bool),

  // Other predicates
  Between(Box<Expr>,Box<Expr>,Box<Expr>), // predicand, begin, end
  In(Box<Expr>, Vec<Box<Expr>>), // predicand, a set

  // condition
  Case(Vec<Box<Expr>>, Box<Expr>), // multiple conditions, else return value
  IfThen(Box<Expr>, Box<Expr>), // condition, return value

  // values
  Row(Vec<Box<Expr>>),
  Field(String),
  Const(Literal)
}

/// Comparison Operator Type
#[derive(Clone, Copy)]
pub enum CompOp {
  Eq,
  Ne,
  Lt,
  Le,
  Gt,
  Ge
}

/// Arithmetic Operator Type
#[derive(Clone, Copy)]
pub enum ArithmOp {
  Plus,
  Sub,
  Mul,
  Div,
  Rem,
}

/// Function Declaration
#[derive(Clone)]
pub struct FnDecl {
  signature: String
}

/// Representation for a single value
#[derive(Clone)]
pub enum Literal
{
  Bool(bool),
  Int1(i8),
  Int2(i16),
  Int4(i32),
  Int8(i64),
  Float4(f32),
  Float8(f64),
  Time(i64),
  Date(i32),
  Timestamp(i64),
  Interval(i64, i32),
  Char(String),
  Text(String),
  Varchar(String),
  Blob(Vec<u8>)
}

pub mod visitor {
	use common::types::Ty;
	use super::*;

	/// Visitor for Expr Tree
	pub trait Visitor<'v>: Sized {
	  fn visit_not(&mut self, child: &'v Expr) {
	    walk_expr(self, child);
	  }
	  fn visit_is_null(&mut self, child: &'v Expr, not: bool) {
	    walk_expr(self, child);
	  }
	  fn visit_sign(&mut self, child: &'v Expr, not: bool) {
	    walk_expr(self, child);
	  }
	  fn visit_cast(&mut self, expr: &'v Expr, from: &'v Ty, to: &'v Ty) {
	    walk_expr(self, expr);
	  }

	  fn visit_and(&mut self, lhs: &'v Expr, rhs: &'v Expr) {
	    walk_expr(self, lhs);
	    walk_expr(self, rhs);
	  }
	  fn visit_or(&mut self, lhs: &'v Expr, rhs: &'v Expr) {
	    walk_expr(self, lhs);
	    walk_expr(self, rhs);
	  }
	  fn visit_comp(&mut self, op: &CompOp, lhs: &'v Expr, rhs: &'v Expr) {
	    walk_expr(self, lhs);
	    walk_expr(self, rhs);
	  }
	  fn visit_arithm(&mut self, op: &ArithmOp, lhs: &'v Expr, rhs: &'v Expr) {
	    walk_expr(self, lhs);
	    walk_expr(self, rhs);
	  }
	  fn visit_concat(&mut self, lhs: &'v Expr, rhs: &'v Expr) {
	    walk_expr(self, lhs);
	    walk_expr(self, rhs);
	  }

	  fn visit_fn(&mut self, fd: &'v FnDecl, args: &'v Vec<Box<Expr>>) {
	    for ref arg in args {
	      walk_expr(self, arg);
	    }
	  }

	  fn visit_like(&mut self, pat: &'v Expr, pred: &'v Expr, not: bool) {
	    walk_expr(self, pat);
	    walk_expr(self, pred);
	  }
	  fn visit_similarto(&mut self, pat: &'v Expr, pred: &'v Expr, not: bool) {
	    walk_expr(self, pat);
	    walk_expr(self, pred);
	  }
	  fn visit_regexmatch(&mut self, pat: &'v Expr, pred: &'v Expr, not: bool) {
	    walk_expr(self, pat);
	    walk_expr(self, pred);
	  }

	  fn visit_between(&mut self, pred: &'v Expr, begin: &'v Expr, end: &'v Expr) {
	    walk_expr(self, pred);
	    walk_expr(self, begin);
	    walk_expr(self, end);
	  }
	  fn visit_in(&mut self, pred: &'v Expr, values: &'v Vec<Box<Expr>>) {
	    walk_expr(self, pred);
	    self.visit_row(values);
	  }

	  fn visit_case(&mut self, ifconds: &'v Vec<Box<Expr>>, else_result: &'v Expr) {
	    for ref each_if in ifconds {
	      walk_expr(self, each_if);
	    }
	    walk_expr(self, else_result);
	  }
	  fn visit_if_then(&mut self, ifcond: &'v Expr, result: &'v Expr) {
	    walk_expr(self, ifcond);
	    walk_expr(self, result);
	  }

	  fn visit_row(&mut self, values: &'v Vec<Box<Expr>>) {
	    for ref v in values {
	      walk_expr(self, v);
	    }
	  }
	  fn visit_field(&mut self, field: &'v String) {}
	  fn visit_const(&mut self, literal: &'v Literal) {}
	}

	/// Walker for Expr Tree
	pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v Expr) {

	  match *expr.spec() {

	    ExprSpec::Not(ref child) => {
	      visitor.visit_not(child);
	    }

	    ExprSpec::IsNull(ref child, positive) => {
	      visitor.visit_is_null(child, positive);
	    }

	    ExprSpec::Sign(ref child, positive) => {
	      visitor.visit_sign(child, positive);
	    }

	    ExprSpec::Cast(ref value, ref from, ref to) => {
	      visitor.visit_cast(value, from, to)
	    },

	    ExprSpec::And(ref lhs, ref rhs) => {
	      visitor.visit_and(lhs, rhs);
	    }

	    ExprSpec::Or(ref lhs, ref rhs) => {
	      visitor.visit_or(lhs, rhs);
	    }

	    ExprSpec::Comp(ref op, ref lhs, ref rhs) => {
	      visitor.visit_comp(op, lhs, rhs);
	    }

	    ExprSpec::Arithm(ref op, ref lhs, ref rhs) => {
	      visitor.visit_arithm(op, lhs, rhs);
	    }

	    ExprSpec::Concat(ref lhs, ref rhs) => {
	      visitor.visit_concat(lhs, rhs);
	    }

	    ExprSpec::Fn(ref fd, ref args) => {
	      visitor.visit_fn(fd, args);
	    },

	    ExprSpec::Like(ref pat, ref pred, not) => {
	      visitor.visit_like(pat, pred, not)
	    },

	    ExprSpec::SimilarTo(ref pat, ref pred, not) => {
	      visitor.visit_similarto(pat, pred, not)
	    },

	    ExprSpec::RegexMatch(ref pat, ref pred, not) => {
	      visitor.visit_regexmatch(pat, pred, not)
	    },

	    ExprSpec::Between(ref pred, ref begin, ref end) => {
	      visitor.visit_between(pred, begin, end)
	    }

	    ExprSpec::In(ref pred, ref values) => {
	      visitor.visit_in(pred, values)
	    }

	    ExprSpec::Case(ref ifconds, ref else_result) => {
	      visitor.visit_case(ifconds, else_result)
	    }

	    ExprSpec::IfThen(ref ifcond, ref result) => {
	      visitor.visit_if_then(ifcond, result)
	    },

	    ExprSpec::Row(ref values) => visitor.visit_row(values),

	    ExprSpec::Field(ref column) => visitor.visit_field(column),

	    ExprSpec::Const(ref datum) => visitor.visit_const(datum),
	  }
	}

	pub trait SimpleVisitor {
	  fn accept(&self, op: &Expr) {
	    self.accept_by_default(op);
	  }

	  fn accept_by_default(&self, e: &Expr) {
	    match *e.spec() {
	      ExprSpec::Const    (_)                   => {},
	      ExprSpec::And      (ref l, ref r)        => { self.accept(l); self.accept(r) },
	      _ => unimplemented!()
	    }
	  }
	}

}<commit_msg>Simplified ExprSpec and its visitors.<commit_after>use common::types::Ty;

#[derive(Clone)]
pub struct Expr
{
	out_ty: Ty,
	spec: ExprSpec
}

impl Expr
{
	pub fn spec(&self) -> &ExprSpec
	{
		&self.spec
	}
}

/// Expression Specific Element
#[derive(Clone)]
pub enum ExprSpec {
  // Unary Expressions
  Not(Box<Expr>),
  IsNull(Box<Expr>, bool), // bool - 'is null' if true. 'is not null' if false.
  Sign(Box<Expr>, bool), // true - Plus, false - Minus
  Cast(Box<Expr>, Box<Ty>, Box<Ty>),

  // Binary Arithmetic Expressions
  And(Box<Expr>,Box<Expr>),
  Or(Box<Expr>,Box<Expr>),
  Comp(CompOp, Box<Expr>, Box<Expr>),
  Arithm(ArithmOp, Box<Expr>, Box<Expr>),

  // Functions
  Fn(Box<FnDecl>, Vec<Box<Expr>>),

  // Other predicates
  Between(Box<Expr>,Box<Expr>,Box<Expr>), // predicand, begin, end

  // condition
  Switch(Vec<Box<Expr>>, Box<Expr>), // multiple conditions, else return value
  Case  (Box<Expr>, Box<Expr>),      // condition, return value

  // values
  Field(String),
  Const(Literal)
}

/// Comparison Operator Type
#[derive(Clone, Copy)]
pub enum CompOp {
  Eq,
  Ne,
  Lt,
  Le,
  Gt,
  Ge
}

/// Arithmetic Operator Type
#[derive(Clone, Copy)]
pub enum ArithmOp {
  Plus,
  Sub,
  Mul,
  Div,
  Rem,
}

/// Function Declaration
#[derive(Clone)]
pub struct FnDecl {
  signature: String
}

/// Representation for a single value
#[derive(Clone)]
pub enum Literal
{
  Bool(bool),
  Int1(i8),
  Int2(i16),
  Int4(i32),
  Int8(i64),
  Float4(f32),
  Float8(f64),
  Time(i64),
  Date(i32),
  Timestamp(i64),
  Interval(i64, i32),
  Char(String),
  Text(String),
  Varchar(String),
  Blob(Vec<u8>)
}

pub mod visitor {
	use common::types::Ty;
	use super::*;

	/// Visitor for Expr Tree
	pub trait Visitor<'v>: Sized {
	  fn visit_not(&mut self, child: &'v Expr) {
	    walk_expr(self, child);
	  }
	  fn visit_is_null(&mut self, child: &'v Expr, not: bool) {
	    walk_expr(self, child);
	  }
	  fn visit_sign(&mut self, child: &'v Expr, not: bool) {
	    walk_expr(self, child);
	  }
	  fn visit_cast(&mut self, expr: &'v Expr, from: &'v Ty, to: &'v Ty) {
	    walk_expr(self, expr);
	  }

	  fn visit_and(&mut self, lhs: &'v Expr, rhs: &'v Expr) {
	    walk_expr(self, lhs);
	    walk_expr(self, rhs);
	  }
	  fn visit_or(&mut self, lhs: &'v Expr, rhs: &'v Expr) {
	    walk_expr(self, lhs);
	    walk_expr(self, rhs);
	  }
	  fn visit_comp(&mut self, op: &CompOp, lhs: &'v Expr, rhs: &'v Expr) {
	    walk_expr(self, lhs);
	    walk_expr(self, rhs);
	  }
	  fn visit_arithm(&mut self, op: &ArithmOp, lhs: &'v Expr, rhs: &'v Expr) {
	    walk_expr(self, lhs);
	    walk_expr(self, rhs);
	  }
	  fn visit_concat(&mut self, lhs: &'v Expr, rhs: &'v Expr) {
	    walk_expr(self, lhs);
	    walk_expr(self, rhs);
	  }

	  fn visit_fn(&mut self, fd: &'v FnDecl, args: &'v Vec<Box<Expr>>) {
	    for ref arg in args {
	      walk_expr(self, arg);
	    }
	  }

	  fn visit_between(&mut self, predicand: &'v Expr, begin: &'v Expr, end: &'v Expr) {
	    walk_expr(self, predicand);
	    walk_expr(self, begin);
	    walk_expr(self, end);
	  }

	  fn visit_switch(&mut self, cases: &'v Vec<Box<Expr>>, default_value: &'v Expr) {
	    for ref each_case in cases {
	      walk_expr(self, each_case);
	    }
	    walk_expr(self, default_value);
	  }
	  fn visit_case(&mut self, condition: &'v Expr, result: &'v Expr) {
	    walk_expr(self, condition);
	    walk_expr(self, result);
	  }

	  fn visit_field(&mut self, field: &'v String) {}
	  fn visit_const(&mut self, literal: &'v Literal) {}
	}

	/// Walker for Expr Tree
	pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v Expr) {

	  match *expr.spec() {

	    ExprSpec::Not(ref child) => visitor.visit_not(child),

	    ExprSpec::IsNull(ref child, positive) => {
	      visitor.visit_is_null(child, positive)
	    }

	    ExprSpec::Sign(ref child, positive) => {
	      visitor.visit_sign(child, positive)
	    }

	    ExprSpec::Cast(ref value, ref from, ref to) => {
	      visitor.visit_cast(value, from, to)
	    }

	    ExprSpec::And(ref lhs, ref rhs) => visitor.visit_and(lhs, rhs),

	    ExprSpec::Or(ref lhs, ref rhs) => visitor.visit_or(lhs, rhs),

	    ExprSpec::Comp(ref op, ref lhs, ref rhs) => {
	      visitor.visit_comp(op, lhs, rhs);
	    }

	    ExprSpec::Arithm(ref op, ref lhs, ref rhs) => {
	      visitor.visit_arithm(op, lhs, rhs);
	    },

	    ExprSpec::Fn(ref fd, ref args) => visitor.visit_fn(fd, args),

	    ExprSpec::Between(ref predicand, ref begin, ref end) => {
	      visitor.visit_between(predicand, begin, end)
	    },

	    ExprSpec::Switch(ref cases, ref default_value) => {
	      visitor.visit_switch(cases, default_value)
	    }
	    ExprSpec::Case(ref condition, ref result) => {
	      visitor.visit_case(condition, result)
	    },

	    ExprSpec::Field(ref name) => visitor.visit_field(name),

	    ExprSpec::Const(ref datum) => visitor.visit_const(datum),
	  }
	}

	pub trait SimpleVisitor {
	  fn accept(&self, op: &Expr) {
	    self.accept_by_default(op);
	  }

	  fn accept_by_default(&self, e: &Expr) {
	    match *e.spec() {
	      ExprSpec::Not      (ref c)               => self.accept(c),
	      ExprSpec::IsNull   (ref c, _)            => self.accept(c),
	      ExprSpec::Sign     (ref c, _)            => self.accept(c),
	      ExprSpec::Cast     (ref c, _, _)         => self.accept(c),

	      ExprSpec::Const    (_)                   => {},
	      ExprSpec::And      (ref l, ref r)        => { self.accept(l); self.accept(r) },
	      _ => unimplemented!()
	    }
	  }
	}

}<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This crate provides Serde's two derive macros.
//!
//! ```rust
//! # #[macro_use]
//! # extern crate serde_derive;
//! #
//! #[derive(Serialize, Deserialize)]
//! # struct S;
//! #
//! # fn main() {}
//! ```
//!
//! Please refer to [https://serde.rs/derive.html] for how to set this up.
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html

#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.65")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding,
        cyclomatic_complexity
    )
)]
// Whitelisted clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        items_after_statements, doc_markdown, stutter, similar_names, use_self, single_match_else,
        enum_glob_use, match_same_arms, filter_map, cast_possible_truncation
    )
)]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "512"]

#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;

extern crate proc_macro;
extern crate proc_macro2;

mod internals;

use proc_macro::TokenStream;
use syn::DeriveInput;

#[macro_use]
mod bound;
#[macro_use]
mod fragment;

mod de;
mod pretend;
mod ser;
mod try;

#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();
    match ser::expand_derive_serialize(&input) {
        Ok(expanded) => expanded.into(),
        Err(msg) => quote! {compile_error!(#msg);}.into(),
    }
}

#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();
    match de::expand_derive_deserialize(&input) {
        Ok(expanded) => expanded.into(),
        Err(msg) => quote! {compile_error!(#msg);}.into(),
    }
}
<commit_msg>These match-expressions are implementing unwrap_or_else<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This crate provides Serde's two derive macros.
//!
//! ```rust
//! # #[macro_use]
//! # extern crate serde_derive;
//! #
//! #[derive(Serialize, Deserialize)]
//! # struct S;
//! #
//! # fn main() {}
//! ```
//!
//! Please refer to [https://serde.rs/derive.html] for how to set this up.
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html

#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.65")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding,
        cyclomatic_complexity, needless_pass_by_value
    )
)]
// Whitelisted clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        items_after_statements, doc_markdown, stutter, similar_names, use_self, single_match_else,
        enum_glob_use, match_same_arms, filter_map, cast_possible_truncation
    )
)]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "512"]

#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;

extern crate proc_macro;
extern crate proc_macro2;

mod internals;

use proc_macro::TokenStream;
use syn::DeriveInput;

#[macro_use]
mod bound;
#[macro_use]
mod fragment;

mod de;
mod pretend;
mod ser;
mod try;

#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();
    ser::expand_derive_serialize(&input)
        .unwrap_or_else(compile_error)
        .into()
}

#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();
    de::expand_derive_deserialize(&input)
        .unwrap_or_else(compile_error)
        .into()
}

fn compile_error(message: String) -> proc_macro2::TokenStream {
    quote! {
        compile_error!(#message);
    }
}
<|endoftext|>


<commit_before>extern crate timely;
extern crate graph_map;
extern crate differential_dataflow;

use std::hash::Hash;

use timely::dataflow::*;
use timely::dataflow::operators::*;

use differential_dataflow::{Collection, Data};
use differential_dataflow::lattice::Lattice;
use differential_dataflow::operators::*;

use graph_map::GraphMMap;

type Node = u32;
type Edge = (Node, Node);

type Nodes<G,V> = Collection<G, (Node, V)>;
type Edges<G> = Collection<G, Edge>;

fn main() {

    // snag a filename to use for the input graph.
    let filename = std::env::args().nth(1).unwrap();

    timely::execute_from_args(std::env::args().skip(1), move |worker| {

        let peers = worker.peers();
        let index = worker.index();

        // What you might do if you used GraphMMap:
        let graph = GraphMMap::new(&filename);
        // let nodes = graph.nodes();
        let nodes = std::env::args().nth(2).unwrap().parse::<usize>().unwrap();
        let edges = (0..nodes).filter(move |node| node % peers == index)
                              .flat_map(move |node| {
                                  let vec = graph.edges(node).to_vec();
                                  vec.into_iter().map(move |edge| ((node as u32, edge), Default::default(), 1))
                              });

        // let edges = vec![((0,1),1),((1,2),1),((0,2),1)].into_iter();

        worker.dataflow::<u64,_,_>(|scope| {
            let edges = Collection::new(edges.to_stream(scope));
            let edges = edges.map(|(x,y)| (y,x)).concat(&edges);

            // _color(&edges)
            _reach(&edges).map(|(_x,c)| c).consolidate().inspect(|x| println!("{:?}", x));
        });

    }).unwrap();
}

fn _color<G: Scope>(edges: &Edges<G>) -> Nodes<G,Option<u32>>
where G::Timestamp: Lattice+Hash+Ord {

    // need some bogus initial values.
    let start = edges.map(|(x,_y)| (x,u32::max_value()))
                     .consolidate();

    // repeatedly apply color-picking logic.
    sequence(&start, &edges, |_node, vals| {

        // look for the first absent positive integer.
        // start at 1 in case we ever use NonZero<u32>.

        let mut index = 0;
        while index < vals.len() && vals[index].0.unwrap() == (index as u32) + 1 {
          index += 1;
        }

        (index as u32) + 1
    })
}

fn _reach<G: Scope>(edges: &Edges<G>) -> Nodes<G,Option<bool>>
where G::Timestamp: Lattice+Hash+Ord {

    // need some bogus initial values.
    let start = edges.map(|(x,_y)| (x, x < 10))
                     .consolidate();

    // repeatedly apply color-picking logic.
    sequence(&start, &edges, |_node, vals| {

        let mut reached = false;
        let mut iter = vals.iter();
        while let Some(&(b, _)) = iter.next() {
            if let &Some(b) = b {
                if b { reached = true; }
            }
        }
        reached
    })
}

fn sequence<G: Scope, V: Data, F>(state: &Nodes<G, V>, edges: &Edges<G>, logic: F) -> Nodes<G, Option<V>>
where G::Timestamp: Lattice+Hash+Ord,
      F: Fn(&Node, &[(&Option<V>, isize)])->V+'static {

        // start iteration with None messages for all.
        state.map(|(node, _state)| (node, None))
             .iterate(|new_state| {

                let edges = edges.enter(&new_state.scope());
                let old_state = state.enter(&new_state.scope())
                                     .map(|x| (x.0, Some(x.1)));

                // break edges into forward and reverse directions.
                let forward = edges.filter(|edge| edge.0 < edge.1);
                let reverse = edges.filter(|edge| edge.0 > edge.1);

                // new state goes along forward edges, old state along reverse edges
                let new_messages = new_state.join_map(&forward, |_k,v,d| (*d,v.clone()));
                let old_messages = old_state.join_map(&reverse, |_k,v,d| (*d,v.clone()));

                // merge messages; apply logic if no None messages remain.
                let result = new_messages.concat(&old_messages)
                                         .group(move |k, vs, t| {
                                             if vs[0].0.is_some() {
                                                 t.push((Some(logic(k, vs)), 1));
                                             }
                                             else {
                                                 t.push((None, 1));
                                             }
                                         });

                result.inner.count().inspect_batch(|t,xs| println!("count[{:?}]:\t{:?}", t, xs));
                result
             })
}
<commit_msg>tidy sequential example<commit_after>extern crate timely;
extern crate graph_map;
extern crate differential_dataflow;

use std::hash::Hash;

use timely::dataflow::*;
use timely::dataflow::operators::*;

use differential_dataflow::{Collection, Data};
use differential_dataflow::lattice::Lattice;
use differential_dataflow::operators::*;

use graph_map::GraphMMap;

type Node = u32;
type Edge = (Node, Node);

type Nodes<G,V> = Collection<G, (Node, V)>;
type Edges<G> = Collection<G, Edge>;

fn main() {

    // snag a filename to use for the input graph.
    let filename = std::env::args().nth(1).unwrap();

    timely::execute_from_args(std::env::args().skip(1), move |worker| {

        let peers = worker.peers();
        let index = worker.index();

        // What you might do if you used GraphMMap:
        let graph = GraphMMap::new(&filename);
        // let nodes = graph.nodes();
        let nodes = std::env::args().nth(2).unwrap().parse::<usize>().unwrap();
        let edges = (0..nodes).filter(move |node| node % peers == index)
                              .flat_map(move |node| {
                                  let vec = graph.edges(node).to_vec();
                                  vec.into_iter().map(move |edge| ((node as u32, edge), Default::default(), 1))
                              });

        // let edges = vec![((0,1),1),((1,2),1),((0,2),1)].into_iter();

        worker.dataflow::<u64,_,_>(|scope| {
            let edges = Collection::new(edges.to_stream(scope));
            let edges = edges.map(|(x,y)| (y,x)).concat(&edges);

            // _color(&edges)
            _reach(&edges).map(|(_x,c)| c).consolidate().inspect(|x| println!("{:?}", x));
        });

    }).unwrap();
}

fn _color<G: Scope>(edges: &Edges<G>) -> Nodes<G,Option<u32>>
where G::Timestamp: Lattice+Hash+Ord {

    // need some bogus initial values.
    let start = edges.map(|(x,_y)| (x,u32::max_value()))
                     .consolidate();

    // repeatedly apply color-picking logic.
    sequence(&start, &edges, |_node, vals| {

        // look for the first absent positive integer.
        // start at 1 in case we ever use NonZero<u32>.

        (1u32 ..)
            .filter(|&i| vals.get(i as usize - 1).map(|x| x.0) != Some(&Some(i)))
            .next()
            .unwrap()
    })
}

fn _reach<G: Scope>(edges: &Edges<G>) -> Nodes<G,Option<bool>>
where G::Timestamp: Lattice+Hash+Ord {

    // need some bogus initial values.
    let start = edges.map(|(x,_y)| (x, x < 10))
                     .consolidate();

    // repeatedly apply color-picking logic.
    sequence(&start, &edges, |_node, vals| {

        let mut reached = false;
        let mut iter = vals.iter();
        while let Some(&(b, _)) = iter.next() {
            if let &Some(b) = b {
                if b { reached = true; }
            }
        }
        reached
    })
}

fn sequence<G: Scope, V: Data, F>(state: &Nodes<G, V>, edges: &Edges<G>, logic: F) -> Nodes<G, Option<V>>
where
    G::Timestamp: Lattice+Hash+Ord,
    F: Fn(&Node, &[(&Option<V>, isize)])->V+'static
{

    // start iteration with None messages for all.
    state
        .map(|(node, _state)| (node, None))
        .iterate(|new_state| {

            // immutable content: edges and initial state.
            let edges = edges.enter(&new_state.scope());
            let old_state = state.enter(&new_state.scope())
                                 .map(|x| (x.0, Some(x.1)));

            // break edges into forward and reverse directions.
            let forward = edges.filter(|edge| edge.0 < edge.1);
            let reverse = edges.filter(|edge| edge.0 > edge.1);

            // new state goes along forward edges, old state along reverse edges
            let new_messages = new_state.join_map(&forward, |_k,v,d| (*d,v.clone()));
            let old_messages = old_state.join_map(&reverse, |_k,v,d| (*d,v.clone()));

            // merge messages; suppress computation if not all inputs available yet.
            new_messages
                .concat(&old_messages)  // /-- possibly too clever: None if any inputs None.
                .group(move |k, vs, t| t.push((vs[0].0.as_ref().map(|_| logic(k, vs)), 1)))
        })
}
<|endoftext|>


<commit_before>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Mining plugin manager, using the cuckoo-miner crate to provide
//! a mining worker implementation
//!

use chrono::prelude::Utc;
use chrono::{Duration, MIN_DATE};
use rand::{thread_rng, Rng};
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{mpsc, Arc};
use std::{cmp, io, str, thread, time};

use p2p;
use p2p::ChainAdapter;
use pool::DandelionConfig;

// DNS Seeds with contact email associated
const DNS_SEEDS: &'static [&'static str] = &[
	"t4.seed.grin-tech.org", // igno.peverell@protonmail.com
];

pub fn connect_and_monitor(
	p2p_server: Arc<p2p::Server>,
	capabilities: p2p::Capabilities,
	dandelion_config: DandelionConfig,
	seed_list: Box<Fn() -> Vec<SocketAddr> + Send>,
	preferred_peers: Option<Vec<SocketAddr>>,
	stop: Arc<AtomicBool>,
) {
	let _ = thread::Builder::new()
		.name("seed".to_string())
		.spawn(move || {
			let peers = p2p_server.peers.clone();

			// open a channel with a listener that connects every peer address sent below
			// max peer count
			let (tx, rx) = mpsc::channel();

			// check seeds first
			connect_to_seeds_and_preferred_peers(
				peers.clone(),
				tx.clone(),
				seed_list,
				preferred_peers.clone(),
			);

			let mut prev = MIN_DATE.and_hms(0, 0, 0);
			let mut prev_expire_check = MIN_DATE.and_hms(0, 0, 0);
			let mut prev_ping = Utc::now();
			let mut start_attempt = 0;

			while !stop.load(Ordering::Relaxed) {
				// Check for and remove expired peers from the storage
				if Utc::now() - prev_expire_check > Duration::hours(1) {
					peers.remove_expired();

					prev_expire_check = Utc::now();
				}

				// make several attempts to get peers as quick as possible
				// with exponential backoff
				if Utc::now() - prev > Duration::seconds(cmp::min(20, 1 << start_attempt)) {
					// try to connect to any address sent to the channel
					listen_for_addrs(peers.clone(), p2p_server.clone(), capabilities, &rx);

					// monitor additional peers if we need to add more
					monitor_peers(
						peers.clone(),
						p2p_server.config.clone(),
						capabilities,
						tx.clone(),
						preferred_peers.clone(),
					);

					update_dandelion_relay(peers.clone(), dandelion_config.clone());

					prev = Utc::now();
					start_attempt = cmp::min(6, start_attempt + 1);
				}

				// Ping connected peers on every 10s to monitor peers.
				if Utc::now() - prev_ping > Duration::seconds(10) {
					let total_diff = peers.total_difficulty();
					let total_height = peers.total_height();
					peers.check_all(total_diff, total_height);
					prev_ping = Utc::now();
				}

				thread::sleep(time::Duration::from_secs(1));
			}
		});
}

fn monitor_peers(
	peers: Arc<p2p::Peers>,
	config: p2p::P2PConfig,
	capabilities: p2p::Capabilities,
	tx: mpsc::Sender<SocketAddr>,
	preferred_peers_list: Option<Vec<SocketAddr>>,
) {
	// regularly check if we need to acquire more peers  and if so, gets
	// them from db
	let total_count = peers.all_peers().len();
	let mut healthy_count = 0;
	let mut banned_count = 0;
	let mut defuncts = vec![];

	for x in peers.all_peers() {
		match x.flags {
			p2p::State::Banned => {
				let interval = Utc::now().timestamp() - x.last_banned;
				// Unban peer
				if interval >= config.ban_window() {
					peers.unban_peer(&x.addr);
					debug!(
						"monitor_peers: unbanned {} after {} seconds",
						x.addr, interval
					);
				} else {
					banned_count += 1;
				}
			}
			p2p::State::Healthy => healthy_count += 1,
			p2p::State::Defunct => defuncts.push(x),
		}
	}

	debug!(
		"monitor_peers: on {}:{}, {} connected ({} most_work). \
		 all {} = {} healthy + {} banned + {} defunct",
		config.host,
		config.port,
		peers.peer_count(),
		peers.most_work_peers().len(),
		total_count,
		healthy_count,
		banned_count,
		defuncts.len(),
	);

	// maintenance step first, clean up p2p server peers
	peers.clean_peers(config.peer_max_count() as usize);

	// not enough peers, getting more from db
	if peers.peer_count() >= config.peer_min_preferred_count() {
		return;
	}

	// loop over connected peers
	// ask them for their list of peers
	let mut connected_peers: Vec<SocketAddr> = vec![];
	for p in peers.connected_peers() {
		debug!(
			"monitor_peers: {}:{} ask {} for more peers",
			config.host, config.port, p.info.addr,
		);
		let _ = p.send_peer_request(capabilities);
		connected_peers.push(p.info.addr)
	}

	// Attempt to connect to preferred peers if there is some
	match preferred_peers_list {
		Some(preferred_peers) => {
			for mut p in preferred_peers {
				if !connected_peers.is_empty() {
					if !connected_peers.contains(&p) {
						tx.send(p).unwrap();
					}
				} else {
					tx.send(p).unwrap();
				}
			}
		}
		None => debug!("monitor_peers: no preferred peers"),
	}

	// take a random defunct peer and mark it healthy: over a long period any
	// peer will see another as defunct eventually, gives us a chance to retry
	if defuncts.len() > 0 {
		thread_rng().shuffle(&mut defuncts);
		let _ = peers.update_state(defuncts[0].addr, p2p::State::Healthy);
	}

	// find some peers from our db
	// and queue them up for a connection attempt
	let new_peers = peers.find_peers(
		p2p::State::Healthy,
		p2p::Capabilities::UNKNOWN,
		config.peer_max_count() as usize,
	);
	for p in new_peers.iter().filter(|p| !peers.is_known(&p.addr)) {
		debug!(
			"monitor_peers: on {}:{}, queue to soon try {}",
			config.host, config.port, p.addr,
		);
		tx.send(p.addr).unwrap();
	}
}

fn update_dandelion_relay(peers: Arc<p2p::Peers>, dandelion_config: DandelionConfig) {
	// Dandelion Relay Updater
	let dandelion_relay = peers.get_dandelion_relay();
	if dandelion_relay.is_empty() {
		debug!("monitor_peers: no dandelion relay updating");
		peers.update_dandelion_relay();
	} else {
		for last_added in dandelion_relay.keys() {
			let dandelion_interval = Utc::now().timestamp() - last_added;
			if dandelion_interval >= dandelion_config.relay_secs.unwrap() as i64 {
				debug!("monitor_peers: updating expired dandelion relay");
				peers.update_dandelion_relay();
			}
		}
	}
}

// Check if we have any pre-existing peer in db. If so, start with those,
// otherwise use the seeds provided.
fn connect_to_seeds_and_preferred_peers(
	peers: Arc<p2p::Peers>,
	tx: mpsc::Sender<SocketAddr>,
	seed_list: Box<Fn() -> Vec<SocketAddr>>,
	peers_preferred_list: Option<Vec<SocketAddr>>,
) {
	// check if we have some peers in db
	let peers = peers.find_peers(p2p::State::Healthy, p2p::Capabilities::FULL_HIST, 100);

	// if so, get their addresses, otherwise use our seeds
	let mut peer_addrs = if peers.len() > 3 {
		peers.iter().map(|p| p.addr).collect::<Vec<_>>()
	} else {
		seed_list()
	};

	// If we have preferred peers add them to the connection
	match peers_preferred_list {
		Some(mut peers_preferred) => peer_addrs.append(&mut peers_preferred),
		None => debug!("No preferred peers"),
	};

	if peer_addrs.len() == 0 {
		warn!("No seeds were retrieved.");
	}

	// connect to this first set of addresses
	for addr in peer_addrs {
		tx.send(addr).unwrap();
	}
}

/// Regularly poll a channel receiver for new addresses and initiate a
/// connection if the max peer count isn't exceeded. A request for more
/// peers is also automatically sent after connection.
fn listen_for_addrs(
	peers: Arc<p2p::Peers>,
	p2p: Arc<p2p::Server>,
	capab: p2p::Capabilities,
	rx: &mpsc::Receiver<SocketAddr>,
) {
	if peers.peer_count() >= p2p.config.peer_max_count() {
		// clean the rx messages to avoid accumulating
		for _ in rx.try_iter() {}
		return;
	}

	for addr in rx.try_iter() {
		let peers_c = peers.clone();
		let p2p_c = p2p.clone();
		let _ = thread::Builder::new()
			.name("peer_connect".to_string())
			.spawn(move || {
				// connect and retry on fail, but for 3 times at most
				for _ in 0..3 {
					match p2p_c.connect(&addr) {
						Ok(p) => {
							let _ = p.send_peer_request(capab);
							let _ = peers_c.update_state(addr, p2p::State::Healthy);
							break;
						}
						Err(e) => {
							let _ = peers_c.update_state(addr, p2p::State::Defunct);

							// don't retry if connection refused or PeerWithSelf
							match e {
								p2p::Error::Connection(io_err) => {
									if io::ErrorKind::ConnectionRefused == io_err.kind() {
										break;
									}
								}
								p2p::Error::PeerWithSelf => break,
								_ => (), // allow to retry on any other error
							}
						}
					}

					thread::sleep(time::Duration::from_secs(1));
				}
			});
	}
}

pub fn dns_seeds() -> Box<Fn() -> Vec<SocketAddr> + Send> {
	Box::new(|| {
		let mut addresses: Vec<SocketAddr> = vec![];
		for dns_seed in DNS_SEEDS {
			let temp_addresses = addresses.clone();
			debug!("Retrieving seed nodes from dns {}", dns_seed);
			match (dns_seed.to_owned(), 0).to_socket_addrs() {
				Ok(addrs) => addresses.append(
					&mut (addrs
						.map(|mut addr| {
							addr.set_port(13414);
							addr
						}).filter(|addr| !temp_addresses.contains(addr))
						.collect()),
				),
				Err(e) => debug!("Failed to resolve seed {:?} got error {:?}", dns_seed, e),
			}
		}
		debug!("Retrieved seed addresses: {:?}", addresses);
		addresses
	})
}

/// Convenience function when the seed list is immediately known. Mostly used
/// for tests.
pub fn predefined_seeds(addrs_str: Vec<String>) -> Box<Fn() -> Vec<SocketAddr> + Send> {
	Box::new(move || {
		addrs_str
			.iter()
			.map(|s| s.parse().unwrap())
			.collect::<Vec<_>>()
	})
}

/// Convenience function when the seed list is immediately known. Mostly used
/// for tests.
pub fn preferred_peers(addrs_str: Vec<String>) -> Option<Vec<SocketAddr>> {
	if addrs_str.is_empty() {
		None
	} else {
		Some(
			addrs_str
				.iter()
				.map(|s| s.parse().unwrap())
				.collect::<Vec<_>>(),
		)
	}
}
<commit_msg>Minor update to seed module documentation<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Seeds a server with initial peers on first start and keep monitoring
//! peer counts to connect to more if neeed. Seedin strategy is
//! configurable with either no peers, a user-defined list or a preset
//! list of DNS records (the default).

use chrono::prelude::Utc;
use chrono::{Duration, MIN_DATE};
use rand::{thread_rng, Rng};
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{mpsc, Arc};
use std::{cmp, io, str, thread, time};

use p2p;
use p2p::ChainAdapter;
use pool::DandelionConfig;

// DNS Seeds with contact email associated
const DNS_SEEDS: &'static [&'static str] = &[
	"t4.seed.grin-tech.org", // igno.peverell@protonmail.com
];

pub fn connect_and_monitor(
	p2p_server: Arc<p2p::Server>,
	capabilities: p2p::Capabilities,
	dandelion_config: DandelionConfig,
	seed_list: Box<Fn() -> Vec<SocketAddr> + Send>,
	preferred_peers: Option<Vec<SocketAddr>>,
	stop: Arc<AtomicBool>,
) {
	let _ = thread::Builder::new()
		.name("seed".to_string())
		.spawn(move || {
			let peers = p2p_server.peers.clone();

			// open a channel with a listener that connects every peer address sent below
			// max peer count
			let (tx, rx) = mpsc::channel();

			// check seeds first
			connect_to_seeds_and_preferred_peers(
				peers.clone(),
				tx.clone(),
				seed_list,
				preferred_peers.clone(),
			);

			let mut prev = MIN_DATE.and_hms(0, 0, 0);
			let mut prev_expire_check = MIN_DATE.and_hms(0, 0, 0);
			let mut prev_ping = Utc::now();
			let mut start_attempt = 0;

			while !stop.load(Ordering::Relaxed) {
				// Check for and remove expired peers from the storage
				if Utc::now() - prev_expire_check > Duration::hours(1) {
					peers.remove_expired();

					prev_expire_check = Utc::now();
				}

				// make several attempts to get peers as quick as possible
				// with exponential backoff
				if Utc::now() - prev > Duration::seconds(cmp::min(20, 1 << start_attempt)) {
					// try to connect to any address sent to the channel
					listen_for_addrs(peers.clone(), p2p_server.clone(), capabilities, &rx);

					// monitor additional peers if we need to add more
					monitor_peers(
						peers.clone(),
						p2p_server.config.clone(),
						capabilities,
						tx.clone(),
						preferred_peers.clone(),
					);

					update_dandelion_relay(peers.clone(), dandelion_config.clone());

					prev = Utc::now();
					start_attempt = cmp::min(6, start_attempt + 1);
				}

				// Ping connected peers on every 10s to monitor peers.
				if Utc::now() - prev_ping > Duration::seconds(10) {
					let total_diff = peers.total_difficulty();
					let total_height = peers.total_height();
					peers.check_all(total_diff, total_height);
					prev_ping = Utc::now();
				}

				thread::sleep(time::Duration::from_secs(1));
			}
		});
}

fn monitor_peers(
	peers: Arc<p2p::Peers>,
	config: p2p::P2PConfig,
	capabilities: p2p::Capabilities,
	tx: mpsc::Sender<SocketAddr>,
	preferred_peers_list: Option<Vec<SocketAddr>>,
) {
	// regularly check if we need to acquire more peers  and if so, gets
	// them from db
	let total_count = peers.all_peers().len();
	let mut healthy_count = 0;
	let mut banned_count = 0;
	let mut defuncts = vec![];

	for x in peers.all_peers() {
		match x.flags {
			p2p::State::Banned => {
				let interval = Utc::now().timestamp() - x.last_banned;
				// Unban peer
				if interval >= config.ban_window() {
					peers.unban_peer(&x.addr);
					debug!(
						"monitor_peers: unbanned {} after {} seconds",
						x.addr, interval
					);
				} else {
					banned_count += 1;
				}
			}
			p2p::State::Healthy => healthy_count += 1,
			p2p::State::Defunct => defuncts.push(x),
		}
	}

	debug!(
		"monitor_peers: on {}:{}, {} connected ({} most_work). \
		 all {} = {} healthy + {} banned + {} defunct",
		config.host,
		config.port,
		peers.peer_count(),
		peers.most_work_peers().len(),
		total_count,
		healthy_count,
		banned_count,
		defuncts.len(),
	);

	// maintenance step first, clean up p2p server peers
	peers.clean_peers(config.peer_max_count() as usize);

	// not enough peers, getting more from db
	if peers.peer_count() >= config.peer_min_preferred_count() {
		return;
	}

	// loop over connected peers
	// ask them for their list of peers
	let mut connected_peers: Vec<SocketAddr> = vec![];
	for p in peers.connected_peers() {
		debug!(
			"monitor_peers: {}:{} ask {} for more peers",
			config.host, config.port, p.info.addr,
		);
		let _ = p.send_peer_request(capabilities);
		connected_peers.push(p.info.addr)
	}

	// Attempt to connect to preferred peers if there is some
	match preferred_peers_list {
		Some(preferred_peers) => {
			for mut p in preferred_peers {
				if !connected_peers.is_empty() {
					if !connected_peers.contains(&p) {
						tx.send(p).unwrap();
					}
				} else {
					tx.send(p).unwrap();
				}
			}
		}
		None => debug!("monitor_peers: no preferred peers"),
	}

	// take a random defunct peer and mark it healthy: over a long period any
	// peer will see another as defunct eventually, gives us a chance to retry
	if defuncts.len() > 0 {
		thread_rng().shuffle(&mut defuncts);
		let _ = peers.update_state(defuncts[0].addr, p2p::State::Healthy);
	}

	// find some peers from our db
	// and queue them up for a connection attempt
	let new_peers = peers.find_peers(
		p2p::State::Healthy,
		p2p::Capabilities::UNKNOWN,
		config.peer_max_count() as usize,
	);
	for p in new_peers.iter().filter(|p| !peers.is_known(&p.addr)) {
		debug!(
			"monitor_peers: on {}:{}, queue to soon try {}",
			config.host, config.port, p.addr,
		);
		tx.send(p.addr).unwrap();
	}
}

fn update_dandelion_relay(peers: Arc<p2p::Peers>, dandelion_config: DandelionConfig) {
	// Dandelion Relay Updater
	let dandelion_relay = peers.get_dandelion_relay();
	if dandelion_relay.is_empty() {
		debug!("monitor_peers: no dandelion relay updating");
		peers.update_dandelion_relay();
	} else {
		for last_added in dandelion_relay.keys() {
			let dandelion_interval = Utc::now().timestamp() - last_added;
			if dandelion_interval >= dandelion_config.relay_secs.unwrap() as i64 {
				debug!("monitor_peers: updating expired dandelion relay");
				peers.update_dandelion_relay();
			}
		}
	}
}

// Check if we have any pre-existing peer in db. If so, start with those,
// otherwise use the seeds provided.
fn connect_to_seeds_and_preferred_peers(
	peers: Arc<p2p::Peers>,
	tx: mpsc::Sender<SocketAddr>,
	seed_list: Box<Fn() -> Vec<SocketAddr>>,
	peers_preferred_list: Option<Vec<SocketAddr>>,
) {
	// check if we have some peers in db
	let peers = peers.find_peers(p2p::State::Healthy, p2p::Capabilities::FULL_HIST, 100);

	// if so, get their addresses, otherwise use our seeds
	let mut peer_addrs = if peers.len() > 3 {
		peers.iter().map(|p| p.addr).collect::<Vec<_>>()
	} else {
		seed_list()
	};

	// If we have preferred peers add them to the connection
	match peers_preferred_list {
		Some(mut peers_preferred) => peer_addrs.append(&mut peers_preferred),
		None => debug!("No preferred peers"),
	};

	if peer_addrs.len() == 0 {
		warn!("No seeds were retrieved.");
	}

	// connect to this first set of addresses
	for addr in peer_addrs {
		tx.send(addr).unwrap();
	}
}

/// Regularly poll a channel receiver for new addresses and initiate a
/// connection if the max peer count isn't exceeded. A request for more
/// peers is also automatically sent after connection.
fn listen_for_addrs(
	peers: Arc<p2p::Peers>,
	p2p: Arc<p2p::Server>,
	capab: p2p::Capabilities,
	rx: &mpsc::Receiver<SocketAddr>,
) {
	if peers.peer_count() >= p2p.config.peer_max_count() {
		// clean the rx messages to avoid accumulating
		for _ in rx.try_iter() {}
		return;
	}

	for addr in rx.try_iter() {
		let peers_c = peers.clone();
		let p2p_c = p2p.clone();
		let _ = thread::Builder::new()
			.name("peer_connect".to_string())
			.spawn(move || {
				// connect and retry on fail, but for 3 times at most
				for _ in 0..3 {
					match p2p_c.connect(&addr) {
						Ok(p) => {
							let _ = p.send_peer_request(capab);
							let _ = peers_c.update_state(addr, p2p::State::Healthy);
							break;
						}
						Err(e) => {
							let _ = peers_c.update_state(addr, p2p::State::Defunct);

							// don't retry if connection refused or PeerWithSelf
							match e {
								p2p::Error::Connection(io_err) => {
									if io::ErrorKind::ConnectionRefused == io_err.kind() {
										break;
									}
								}
								p2p::Error::PeerWithSelf => break,
								_ => (), // allow to retry on any other error
							}
						}
					}

					thread::sleep(time::Duration::from_secs(1));
				}
			});
	}
}

pub fn dns_seeds() -> Box<Fn() -> Vec<SocketAddr> + Send> {
	Box::new(|| {
		let mut addresses: Vec<SocketAddr> = vec![];
		for dns_seed in DNS_SEEDS {
			let temp_addresses = addresses.clone();
			debug!("Retrieving seed nodes from dns {}", dns_seed);
			match (dns_seed.to_owned(), 0).to_socket_addrs() {
				Ok(addrs) => addresses.append(
					&mut (addrs
						.map(|mut addr| {
							addr.set_port(13414);
							addr
						}).filter(|addr| !temp_addresses.contains(addr))
						.collect()),
				),
				Err(e) => debug!("Failed to resolve seed {:?} got error {:?}", dns_seed, e),
			}
		}
		debug!("Retrieved seed addresses: {:?}", addresses);
		addresses
	})
}

/// Convenience function when the seed list is immediately known. Mostly used
/// for tests.
pub fn predefined_seeds(addrs_str: Vec<String>) -> Box<Fn() -> Vec<SocketAddr> + Send> {
	Box::new(move || {
		addrs_str
			.iter()
			.map(|s| s.parse().unwrap())
			.collect::<Vec<_>>()
	})
}

/// Convenience function when the seed list is immediately known. Mostly used
/// for tests.
pub fn preferred_peers(addrs_str: Vec<String>) -> Option<Vec<SocketAddr>> {
	if addrs_str.is_empty() {
		None
	} else {
		Some(
			addrs_str
				.iter()
				.map(|s| s.parse().unwrap())
				.collect::<Vec<_>>(),
		)
	}
}
<|endoftext|>


<commit_before>#[macro_use] extern crate macrolisp;
use macrolisp::prelude::*;
lisp! {

    (ns
        (extern [bytes futures
                 tokio_io
                 tokio_proto
                 tokio_service])
        (use [(std {io str})
              (bytes BytesMut)
              (futures {future Future BoxFuture})
              (tokio_io {AsyncRead AsyncWrite})
              (tokio_io codec {Encoder Decoder Framed})
              (tokio_proto TcpServer)
              (tokio_proto pipeline ServerProto)
              (tokio_service Service)]))

    (defstruct LineCodec)
    (defstruct LineProto)
    (defstruct Echo)

    (defimpl (Decoder) (for LineCodec)
        (deftype Item String)
        (deftype Error io::Error)

        (defn decode ([(self &mut Self) (buf &mut BytesMut)]
                      io::Result<Option<String>>)

            (match (.position (.iter buf)
                              (lambda [b]
                                  (== (* b)
                                      b'\n')))

                (Some(i))   (let [line (.split_to buf i)] // remove the serialized frame from the buffer.

                                (.split_to buf 1) // Also remove the '\n'

                                (match ((:: str::from_utf8) (& line))
                                    (Ok(s))    (Ok (Some (.to_string s)))
                                    (Err(_))   (Err ((:: io::Error::new) ((:: io::ErrorKind::Other) .) "invalid UTF-8"))))

                (None)      (Ok None))))

    (defimpl (Encoder) (for LineCodec)
        (deftype Item String)
        (deftype Error io::Error)

        (defn encode ([(self &mut Self) (msg String) (buf &mut BytesMut)]
                      io::Result<()>)

            (.extend buf (.as_bytes msg))
            (.extend buf b"\n")
            (Ok ())))

    (defimpl <T> (ServerProto<T>) (for LineProto)
        (where (T AsyncRead)
               (T AsyncWrite)
               (T 'static))

        // For this protocal style, `Request` matches the `Item` type of the codec's `Encoder`
        (deftype Request String)
        // `Response` matches the `Item` type of the codec's `Decoder`
        (deftype Response String)

        // boilerplate to hook in the codec
        (deftype Transport Framed<T, LineCodec>)
        (deftype BindTransport Result<Self::Transport, io::Error>)
        (defn bind_transport ([(self &Self) (io T)]
                              Self::BindTransport)
            (Ok (.framed io (LineCodec.)))))

    (defimpl (Service) (for Echo)
        // These types must match the corresponding protocol types;
        (deftype Request String)
        (deftype Response String)

        // For non-streaming protocols, service errors are always io::Error
        (deftype Error io::Error)

        // The future for computing the response; box it for simplicity.
        (deftype Future BoxFuture<Self::Response, Self::Error>)

        // Produce a future for computing a response from a request.
        (defn call ([(self &Self) (req Self::Request)]
                    Self::Future)
            // In this case, the response is immediate.
            (.boxed ((:: future::ok) req))))

    (defn main ([] ())
        (let [addr     (.unwrap (.parse "0.0.0.0:12345")) // Specify the localhost address
              server   ((:: TcpServer::new) (LineProto.) addr)] // The builder requires a protocol and an address
            // We provide a way to *instantiate* the service for each new
            // connection; here, we just immediately return a new instance.
            (.serve server (lambda []
                               (Ok (Echo.))))))

}
<commit_msg>remove deprecations from tokio example<commit_after>#[macro_use] extern crate macrolisp;
use macrolisp::prelude::*;
lisp! {

    (ns
        (extern [bytes futures
                 tokio_io
                 tokio_proto
                 tokio_service])
        (use [(std {io str})
              (bytes BytesMut)
              (futures {future Future})
              (tokio_io {AsyncRead AsyncWrite})
              (tokio_io codec {Encoder Decoder Framed})
              (tokio_proto TcpServer)
              (tokio_proto pipeline ServerProto)
              (tokio_service Service)]))

    (defstruct LineCodec)
    (defstruct LineProto)
    (defstruct Echo)

    (defimpl (Decoder) (for LineCodec)
        (deftype Item String)
        (deftype Error io::Error)

        (defn decode ([(self &mut Self) (buf &mut BytesMut)]
                      io::Result<Option<String>>)

            (match (.position (.iter buf)
                              (lambda [b]
                                  (== (* b)
                                      b'\n')))

                (Some(i))   (let [line (.split_to buf i)] // remove the serialized frame from the buffer.

                                (.split_to buf 1) // Also remove the '\n'

                                (match ((:: str::from_utf8) (& line))
                                    (Ok(s))    (Ok (Some (.to_string s)))
                                    (Err(_))   (Err ((:: io::Error::new) ((:: io::ErrorKind::Other) .) "invalid UTF-8"))))

                (None)      (Ok None))))

    (defimpl (Encoder) (for LineCodec)
        (deftype Item String)
        (deftype Error io::Error)

        (defn encode ([(self &mut Self) (msg String) (buf &mut BytesMut)]
                      io::Result<()>)

            (.extend buf (.as_bytes msg))
            (.extend buf b"\n")
            (Ok ())))

    (defimpl <T> (ServerProto<T>) (for LineProto)
        (where (T AsyncRead)
               (T AsyncWrite)
               (T 'static))

        // For this protocal style, `Request` matches the `Item` type of the codec's `Encoder`
        (deftype Request String)
        // `Response` matches the `Item` type of the codec's `Decoder`
        (deftype Response String)

        // boilerplate to hook in the codec
        (deftype Transport Framed<T, LineCodec>)
        (deftype BindTransport Result<Self::Transport, io::Error>)
        (defn bind_transport ([(self &Self) (io T)]
                              Self::BindTransport)
            (Ok (.framed io (LineCodec.)))))

    (defimpl (Service) (for Echo)
        // These types must match the corresponding protocol types;
        (deftype Request String)
        (deftype Response String)

        // For non-streaming protocols, service errors are always io::Error
        (deftype Error io::Error)

        // The future for computing the response; box it for simplicity.
        (deftype Future Box<Future<Item=Self::Response, Error=Self::Error>>)

        // Produce a future for computing a response from a request.
        (defn call ([(self &Self) (req Self::Request)]
                    Self::Future)
            // In this case, the response is immediate.
            ((:: Box::new) ((:: future::ok) req))))

    (defn main ([] ())
        (let [addr     (.unwrap (.parse "0.0.0.0:12345")) // Specify the localhost address
              server   ((:: TcpServer::new) (LineProto.) addr)] // The builder requires a protocol and an address
            // We provide a way to *instantiate* the service for each new
            // connection; here, we just immediately return a new instance.
            (.serve server (lambda []
                               (Ok (Echo.))))))

}
<|endoftext|>


<commit_before>// This example demonstrates use of the callback-based `Resolver`.  It uses
// a third-party DNS parser to handle the response, rather than `c-ares`'s own
// parser.
extern crate c_ares;
extern crate c_ares_resolver;
extern crate dns_parser;
extern crate tokio_core;

use std::error::Error;
use std::sync::mpsc;

use c_ares_resolver:: Resolver;
use dns_parser::Packet;

fn handle_result(result: Result<&[u8], c_ares::Error>) {
    match result {
        Err(e) => {
            println!("Query failed with error '{}'", e.description());
        },
        Ok(bytes) => {
            match Packet::parse(bytes) {
                Err(e) => {
                    println!(
                        "Parser failed with error '{}'",
                        e.description()
                    );
                },
                Ok(packet) => {
                    for answer in &packet.answers {
                        println!("{:?}", answer.data);
                    }
                },
            }
        },
    }
}

fn main() {
    // Create Resolver.
    let resolver = Resolver::new().expect("Failed to create resolver");

    // Make an A-query, but use a third-party DNS parser to handle the result.
    let (tx, rx) = mpsc::channel();
    resolver.query(
        "apple.com",
        1,  // internet
        1,  // Host address
        move |result| {
            handle_result(result);
            tx.send(()).expect("failed to send on channel!");
        }
    );

    // If we allowed the resolver to be dropped, we'd shut down c-ares and the
    // query would fail.  Wait for the handler to signal that it is done.
    rx.recv().expect("query did not complete!");
}
<commit_msg>unused import<commit_after>// This example demonstrates use of the callback-based `Resolver`.  It uses
// a third-party DNS parser to handle the response, rather than `c-ares`'s own
// parser.
extern crate c_ares;
extern crate c_ares_resolver;
extern crate dns_parser;

use std::error::Error;
use std::sync::mpsc;

use c_ares_resolver::Resolver;
use dns_parser::Packet;

fn handle_result(result: Result<&[u8], c_ares::Error>) {
    match result {
        Err(e) => {
            println!("Query failed with error '{}'", e.description());
        },
        Ok(bytes) => {
            match Packet::parse(bytes) {
                Err(e) => {
                    println!(
                        "Parser failed with error '{}'",
                        e.description()
                    );
                },
                Ok(packet) => {
                    for answer in &packet.answers {
                        println!("{:?}", answer.data);
                    }
                },
            }
        },
    }
}

fn main() {
    // Create Resolver.
    let resolver = Resolver::new().expect("Failed to create resolver");

    // Make an A-query, but use a third-party DNS parser to handle the result.
    let (tx, rx) = mpsc::channel();
    resolver.query(
        "apple.com",
        1,  // internet
        1,  // Host address
        move |result| {
            handle_result(result);
            tx.send(()).expect("failed to send on channel!");
        }
    );

    // If we allowed the resolver to be dropped, we'd shut down c-ares and the
    // query would fail.  Wait for the handler to signal that it is done.
    rx.recv().expect("query did not complete!");
}
<|endoftext|>