<commit_before>use address::{LENGTH, Address, Addressable};
use node::Node;
use num::bigint::{BigUint, ToBigUint};
use std::collections::HashMap;
use num;

#[derive(Debug)]
pub struct NodeBucket {
    k: usize,
    min: BigUint,
    max: BigUint,
    addresses: Vec<Address>,
    nodes: HashMap<Address, Box<Node>>
}

impl NodeBucket {
    pub fn new(k: usize) -> NodeBucket {
        let min = 0.to_biguint().unwrap();
        let max = num::pow(2.to_biguint().unwrap(), LENGTH);
        NodeBucket {
            k: k,
            min: min,
            max: max,
            addresses: Vec::with_capacity(k),
            nodes: HashMap::with_capacity(k)
        }
    }

    pub fn contains(&self, address: &Address) -> bool {
        self.addresses.contains(address)
    }

    pub fn covers(&self, address: &Address) -> bool {
        let numeric = address.as_numeric();
        self.min <= numeric && numeric < self.max
    }

    pub fn get_nodes(&self) -> Vec<&Box<Node>> {
        self.nodes.iter().map(|(_, node)| node).collect()
    }

    pub fn insert(&mut self, node: Box<Node>) {
        let address = node.get_address();
        if let Some(pos) = self.addresses.iter().position(|&a| a == address) {
            self.addresses.remove(pos);
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        } else if !self.is_full() {
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        }
    }

    pub fn is_full(&self) -> bool {
        self.addresses.len() >= self.k
    }

    pub fn split(&mut self) -> (Self, Self) {
        let partition = self.max.clone() / 2.to_biguint().unwrap();
        let addresses = self.addresses.clone();
        let (a_addresses, b_addresses): (Vec<Address>, Vec<Address>) = addresses
            .into_iter()
            .partition(|&a| a.as_numeric() < partition);
        let mut a_nodes = HashMap::new();
        let mut b_nodes = HashMap::new();
        for (address, node) in self.nodes.drain() {
            if address.as_numeric() < partition {
                a_nodes.insert(address, node);
            } else {
                b_nodes.insert(address, node);
            }
        }

        let a = NodeBucket {
            k: self.k,
            min: self.min.clone(),
            max: partition.clone(),
            addresses: a_addresses,
            nodes: a_nodes
        };
        let b = NodeBucket {
            k: self.k,
            min: partition.clone(),
            max: self.max.clone(),
            addresses: b_addresses,
            nodes: b_nodes
        };
        (a, b)
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use node::{Node, Serialize};
    use messages;
    use super::NodeBucket;

    #[derive(Debug)]
    struct TestNode {
        pub address: Address
    }

    impl TestNode {
        fn new(address: Address) -> TestNode {
            TestNode { address: address }
        }
    }

    impl Addressable for TestNode {
        fn get_address(&self) -> Address {
            self.address
        }
    }

    impl Node for TestNode {
        fn update(&mut self) { }
        fn send(&self, _: Vec<u8>) { }
    }

    impl Serialize for TestNode {
        fn serialize(&self) -> messages::protobufs::Node {
            messages::protobufs::Node::new()
        }
    }

    #[test]
    fn test_insert() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let node = Box::new(TestNode::new(Address::for_content("some string")));
        bucket.insert(node);
        assert_eq!(bucket.addresses.len(), 1);
    }

    #[test]
    fn test_insert_duplicate() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let addr_1 = Address::for_content("node 1");
        let addr_2 = Address::for_content("node 2");
        let addr_3 = Address::for_content("node 1");
        let a = Box::new(TestNode::new(addr_1));
        let b = Box::new(TestNode::new(addr_2));
        let c = Box::new(TestNode::new(addr_3));

        bucket.insert(a);
        bucket.insert(b);
        bucket.insert(c);

        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes[&Address::for_content("node 1")].get_address(), addr_1);
    }

    #[test]
    fn test_insert_full() {
        let mut bucket: NodeBucket = NodeBucket::new(2);
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1"))));
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 2"))));
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 3"))));
        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes.get(&Address::for_content("node 3")), None);
    }

    #[test]
    fn test_is_full() {
        let mut bucket: NodeBucket = NodeBucket::new(2);
        assert!(!bucket.is_full());

        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1"))));
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 2"))));
        assert!(bucket.is_full());
    }

    #[test]
    fn test_contains() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1"))));
        assert!(bucket.contains(&Address::for_content("node 1")));
    }

    #[test]
    fn test_covers() {
        let bucket: NodeBucket = NodeBucket::new(8);
        let address_1 = Address::from_str("0000000000000000000000000000000000000000");
        let address_2 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        assert!(bucket.covers(&address_1));
        assert!(bucket.covers(&address_2));
    }

    #[test]
    fn test_split() {
        let mut bucket: NodeBucket = NodeBucket::new(4);
        let addr_1 = Address::from_str("0000000000000000000000000000000000000000");
        let addr_2 = Address::from_str("7fffffffffffffffffffffffffffffffffffffff");
        let addr_3 = Address::from_str("8000000000000000000000000000000000000000");
        let addr_4 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        let node_1 = Box::new(TestNode::new(addr_1));
        let node_2 = Box::new(TestNode::new(addr_2));
        let node_3 = Box::new(TestNode::new(addr_3));
        let node_4 = Box::new(TestNode::new(addr_4));

        bucket.insert(node_1);
        bucket.insert(node_2);
        bucket.insert(node_3);
        bucket.insert(node_4);

        let (a, b) = bucket.split();

        // Splits up known address
        assert_eq!(a.addresses.len(), 2);
        assert_eq!(b.addresses.len(), 2);

        // Splits up known nodes
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")].get_address(), addr_1);
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")].get_address(), addr_1);
        assert_eq!(a.nodes[&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")].get_address(), addr_2);
        assert_eq!(b.nodes[&Address::from_str("8000000000000000000000000000000000000000")].get_address(), addr_3);
        assert_eq!(b.nodes[&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")].get_address(), addr_4);

        // Equitably covers address space
        assert!(a.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(!b.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(a.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!b.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!a.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(b.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(!a.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
        assert!(b.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
    }
}
<commit_msg>Fix bucket splitting partition<commit_after>use address::{LENGTH, Address, Addressable};
use node::Node;
use num::bigint::{BigUint, ToBigUint};
use std::collections::HashMap;
use num;

#[derive(Debug)]
pub struct NodeBucket {
    k: usize,
    min: BigUint,
    max: BigUint,
    addresses: Vec<Address>,
    nodes: HashMap<Address, Box<Node>>
}

impl NodeBucket {
    pub fn new(k: usize) -> NodeBucket {
        let min = 0.to_biguint().unwrap();
        let max = num::pow(2.to_biguint().unwrap(), LENGTH);
        NodeBucket {
            k: k,
            min: min,
            max: max,
            addresses: Vec::with_capacity(k),
            nodes: HashMap::with_capacity(k)
        }
    }

    pub fn contains(&self, address: &Address) -> bool {
        self.addresses.contains(address)
    }

    pub fn covers(&self, address: &Address) -> bool {
        let numeric = address.as_numeric();
        self.min <= numeric && numeric < self.max
    }

    pub fn get_nodes(&self) -> Vec<&Box<Node>> {
        self.nodes.iter().map(|(_, node)| node).collect()
    }

    pub fn insert(&mut self, node: Box<Node>) {
        let address = node.get_address();
        if let Some(pos) = self.addresses.iter().position(|&a| a == address) {
            self.addresses.remove(pos);
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        } else if !self.is_full() {
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        }
    }

    pub fn is_full(&self) -> bool {
        self.addresses.len() >= self.k
    }

    pub fn split(&mut self) -> (Self, Self) {
        let difference = self.max.clone() - self.min.clone();
        let partition = difference / 2.to_biguint().unwrap() + self.min.clone();
        let addresses = self.addresses.clone();
        let (a_addresses, b_addresses): (Vec<Address>, Vec<Address>) = addresses
            .into_iter()
            .partition(|&a| a.as_numeric() < partition);
        let mut a_nodes = HashMap::new();
        let mut b_nodes = HashMap::new();
        for (address, node) in self.nodes.drain() {
            if address.as_numeric() < partition {
                a_nodes.insert(address, node);
            } else {
                b_nodes.insert(address, node);
            }
        }

        let a = NodeBucket {
            k: self.k,
            min: self.min.clone(),
            max: partition.clone(),
            addresses: a_addresses,
            nodes: a_nodes
        };
        let b = NodeBucket {
            k: self.k,
            min: partition.clone(),
            max: self.max.clone(),
            addresses: b_addresses,
            nodes: b_nodes
        };
        (a, b)
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use node::{Node, Serialize};
    use messages;
    use super::NodeBucket;

    #[derive(Debug)]
    struct TestNode {
        pub address: Address
    }

    impl TestNode {
        fn new(address: Address) -> TestNode {
            TestNode { address: address }
        }
    }

    impl Addressable for TestNode {
        fn get_address(&self) -> Address {
            self.address
        }
    }

    impl Node for TestNode {
        fn update(&mut self) { }
        fn send(&self, _: Vec<u8>) { }
    }

    impl Serialize for TestNode {
        fn serialize(&self) -> messages::protobufs::Node {
            messages::protobufs::Node::new()
        }
    }

    #[test]
    fn test_insert() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let node = Box::new(TestNode::new(Address::for_content("some string")));
        bucket.insert(node);
        assert_eq!(bucket.addresses.len(), 1);
    }

    #[test]
    fn test_insert_duplicate() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let addr_1 = Address::for_content("node 1");
        let addr_2 = Address::for_content("node 2");
        let addr_3 = Address::for_content("node 1");
        let a = Box::new(TestNode::new(addr_1));
        let b = Box::new(TestNode::new(addr_2));
        let c = Box::new(TestNode::new(addr_3));

        bucket.insert(a);
        bucket.insert(b);
        bucket.insert(c);

        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes[&Address::for_content("node 1")].get_address(), addr_1);
    }

    #[test]
    fn test_insert_full() {
        let mut bucket: NodeBucket = NodeBucket::new(2);
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1"))));
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 2"))));
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 3"))));
        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes.get(&Address::for_content("node 3")), None);
    }

    #[test]
    fn test_is_full() {
        let mut bucket: NodeBucket = NodeBucket::new(2);
        assert!(!bucket.is_full());

        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1"))));
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 2"))));
        assert!(bucket.is_full());
    }

    #[test]
    fn test_contains() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1"))));
        assert!(bucket.contains(&Address::for_content("node 1")));
    }

    #[test]
    fn test_covers() {
        let bucket: NodeBucket = NodeBucket::new(8);
        let address_1 = Address::from_str("0000000000000000000000000000000000000000");
        let address_2 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        assert!(bucket.covers(&address_1));
        assert!(bucket.covers(&address_2));
    }

    #[test]
    fn test_split() {
        let mut bucket: NodeBucket = NodeBucket::new(4);
        let addr_1 = Address::from_str("0000000000000000000000000000000000000000");
        let addr_2 = Address::from_str("7fffffffffffffffffffffffffffffffffffffff");
        let addr_3 = Address::from_str("8000000000000000000000000000000000000000");
        let addr_4 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        let node_1 = Box::new(TestNode::new(addr_1));
        let node_2 = Box::new(TestNode::new(addr_2));
        let node_3 = Box::new(TestNode::new(addr_3));
        let node_4 = Box::new(TestNode::new(addr_4));

        bucket.insert(node_1);
        bucket.insert(node_2);
        bucket.insert(node_3);
        bucket.insert(node_4);

        let (a, b) = bucket.split();

        // Splits up known address
        assert_eq!(a.addresses.len(), 2);
        assert_eq!(b.addresses.len(), 2);

        // Splits up known nodes
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")].get_address(), addr_1);
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")].get_address(), addr_1);
        assert_eq!(a.nodes[&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")].get_address(), addr_2);
        assert_eq!(b.nodes[&Address::from_str("8000000000000000000000000000000000000000")].get_address(), addr_3);
        assert_eq!(b.nodes[&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")].get_address(), addr_4);

        // Equitably covers address space
        assert!(a.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(!b.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(a.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!b.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!a.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(b.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(!a.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
        assert!(b.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
    }
}
<|endoftext|>


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

use crate::{
    backup_types::{
        epoch_ending::restore::{EpochEndingRestoreController, EpochEndingRestoreOpt},
        state_snapshot::restore::{StateSnapshotRestoreController, StateSnapshotRestoreOpt},
        transaction::restore::{TransactionRestoreController, TransactionRestoreOpt},
    },
    metadata,
    metadata::cache::MetadataCacheOpt,
    storage::BackupStorage,
    utils::GlobalRestoreOpt,
};
use anyhow::Result;
use libra_types::transaction::Version;
use libradb::backup::restore_handler::RestoreHandler;
use std::sync::Arc;
use structopt::StructOpt;

#[derive(StructOpt)]
pub struct RestoreCoordinatorOpt {
    #[structopt(flatten)]
    pub metadata_cache_opt: MetadataCacheOpt,
}

pub struct RestoreCoordinator {
    storage: Arc<dyn BackupStorage>,
    restore_handler: Arc<RestoreHandler>,
    global_opt: GlobalRestoreOpt,
    metadata_cache_opt: MetadataCacheOpt,
}

impl RestoreCoordinator {
    pub fn new(
        opt: RestoreCoordinatorOpt,
        global_opt: GlobalRestoreOpt,
        storage: Arc<dyn BackupStorage>,
        restore_handler: Arc<RestoreHandler>,
    ) -> Self {
        Self {
            storage,
            restore_handler,
            global_opt,
            metadata_cache_opt: opt.metadata_cache_opt,
        }
    }

    pub async fn run(self) -> Result<()> {
        let metadata_view =
            metadata::cache::sync_and_load(&self.metadata_cache_opt, Arc::clone(&self.storage))
                .await?;

        let epoch_endings = metadata_view.select_epoch_ending_backups(self.target_version())?;
        let state_snapshot = metadata_view.select_state_snapshot(self.target_version())?;
        let transactions = metadata_view.select_transaction_backups(self.target_version())?;

        if transactions
            .last()
            .map_or(true, |b| b.last_version < self.target_version())
        {
            println!(
                "Warning: Can't find transaction backup that contains the target version, \
            will restore as much as possible"
            );
        }
        let replay_transactions_from_version = match &state_snapshot {
            Some(b) => b.version + 1,
            None => {
                println!(
                    "Warning: Can't find usable state snapshot, \
                will replay transactions from the beginning."
                );
                0
            }
        };

        for backup in epoch_endings {
            EpochEndingRestoreController::new(
                EpochEndingRestoreOpt {
                    manifest_handle: backup.manifest,
                },
                self.global_opt.clone(),
                Arc::clone(&self.storage),
                Arc::clone(&self.restore_handler),
            )
            .run()
            .await?;
        }

        if let Some(backup) = state_snapshot {
            StateSnapshotRestoreController::new(
                StateSnapshotRestoreOpt {
                    manifest_handle: backup.manifest,
                    version: backup.version,
                },
                self.global_opt.clone(),
                Arc::clone(&self.storage),
                Arc::clone(&self.restore_handler),
            )
            .run()
            .await?;
        }

        for backup in transactions {
            TransactionRestoreController::new(
                TransactionRestoreOpt {
                    manifest_handle: backup.manifest,
                    replay_from_version: Some(replay_transactions_from_version),
                },
                self.global_opt.clone(),
                Arc::clone(&self.storage),
                Arc::clone(&self.restore_handler),
            )
            .run()
            .await?;
        }

        println!("Restore finished.");
        Ok(())
    }
}

impl RestoreCoordinator {
    fn target_version(&self) -> Version {
        self.global_opt.target_version()
    }
}
<commit_msg>[backup] RestoreCoordiantor: not to select state snapshot newer than the newest transaction<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    backup_types::{
        epoch_ending::restore::{EpochEndingRestoreController, EpochEndingRestoreOpt},
        state_snapshot::restore::{StateSnapshotRestoreController, StateSnapshotRestoreOpt},
        transaction::restore::{TransactionRestoreController, TransactionRestoreOpt},
    },
    metadata,
    metadata::{cache::MetadataCacheOpt, TransactionBackupMeta},
    storage::BackupStorage,
    utils::GlobalRestoreOpt,
};
use anyhow::{bail, Result};
use libra_types::transaction::Version;
use libradb::backup::restore_handler::RestoreHandler;
use std::sync::Arc;
use structopt::StructOpt;

#[derive(StructOpt)]
pub struct RestoreCoordinatorOpt {
    #[structopt(flatten)]
    pub metadata_cache_opt: MetadataCacheOpt,
}

pub struct RestoreCoordinator {
    storage: Arc<dyn BackupStorage>,
    restore_handler: Arc<RestoreHandler>,
    global_opt: GlobalRestoreOpt,
    metadata_cache_opt: MetadataCacheOpt,
}

impl RestoreCoordinator {
    pub fn new(
        opt: RestoreCoordinatorOpt,
        global_opt: GlobalRestoreOpt,
        storage: Arc<dyn BackupStorage>,
        restore_handler: Arc<RestoreHandler>,
    ) -> Self {
        Self {
            storage,
            restore_handler,
            global_opt,
            metadata_cache_opt: opt.metadata_cache_opt,
        }
    }

    pub async fn run(self) -> Result<()> {
        let metadata_view =
            metadata::cache::sync_and_load(&self.metadata_cache_opt, Arc::clone(&self.storage))
                .await?;

        let transactions = metadata_view.select_transaction_backups(self.target_version())?;
        let actual_target_version = self.get_actual_target_version(&transactions)?;
        let epoch_endings = metadata_view.select_epoch_ending_backups(actual_target_version)?;
        let state_snapshot = metadata_view.select_state_snapshot(actual_target_version)?;
        let replay_transactions_from_version = match &state_snapshot {
            Some(b) => b.version + 1,
            None => 0,
        };
        println!("Planned to restore to version {}.", actual_target_version);

        for backup in epoch_endings {
            EpochEndingRestoreController::new(
                EpochEndingRestoreOpt {
                    manifest_handle: backup.manifest,
                },
                self.global_opt.clone(),
                Arc::clone(&self.storage),
                Arc::clone(&self.restore_handler),
            )
            .run()
            .await?;
        }

        if let Some(backup) = state_snapshot {
            StateSnapshotRestoreController::new(
                StateSnapshotRestoreOpt {
                    manifest_handle: backup.manifest,
                    version: backup.version,
                },
                self.global_opt.clone(),
                Arc::clone(&self.storage),
                Arc::clone(&self.restore_handler),
            )
            .run()
            .await?;
        }

        for backup in transactions {
            TransactionRestoreController::new(
                TransactionRestoreOpt {
                    manifest_handle: backup.manifest,
                    replay_from_version: Some(replay_transactions_from_version),
                },
                self.global_opt.clone(),
                Arc::clone(&self.storage),
                Arc::clone(&self.restore_handler),
            )
            .run()
            .await?;
        }

        println!("Restore finished.");
        Ok(())
    }
}

impl RestoreCoordinator {
    fn target_version(&self) -> Version {
        self.global_opt.target_version()
    }

    fn get_actual_target_version(
        &self,
        transaction_backups: &[TransactionBackupMeta],
    ) -> Result<Version> {
        if let Some(b) = transaction_backups.last() {
            if b.last_version > self.target_version() {
                Ok(self.target_version())
            } else {
                println!(
                    "Warning: Can't find transaction backup containing the target version, \
                    will restore as much as possible"
                );
                Ok(b.last_version)
            }
        } else {
            bail!("No transaction backup found.")
        }
    }
}
<|endoftext|>


<commit_before>#![allow(unknown_lints)]

use std::fmt;
use std::path::PathBuf;
use std::process::{ExitStatus, Output};
use std::str;

use clap;
use failure::{Context, Error, Fail};
use log::trace;

use crate::core::{TargetKind, Workspace};

pub type CargoResult<T> = failure::Fallible<T>; // Alex's body isn't quite ready to give up "Result"

pub trait CargoResultExt<T, E> {
    fn chain_err<F, D>(self, f: F) -> Result<T, Context<D>>
    where
        F: FnOnce() -> D,
        D: fmt::Display + Send + Sync + 'static;
}

impl<T, E> CargoResultExt<T, E> for Result<T, E>
where
    E: Into<Error>,
{
    fn chain_err<F, D>(self, f: F) -> Result<T, Context<D>>
    where
        F: FnOnce() -> D,
        D: fmt::Display + Send + Sync + 'static,
    {
        self.map_err(|failure| {
            let err = failure.into();
            let context = f();
            trace!("error: {}", err);
            trace!("\tcontext: {}", context);
            err.context(context)
        })
    }
}

#[derive(Debug, Fail)]
#[fail(display = "failed to get 200 response from `{}`, got {}", url, code)]
pub struct HttpNot200 {
    pub code: u32,
    pub url: String,
}

pub struct Internal {
    inner: Error,
}

impl Internal {
    pub fn new(inner: Error) -> Internal {
        Internal { inner }
    }
}

impl Fail for Internal {
    fn cause(&self) -> Option<&dyn Fail> {
        self.inner.as_fail().cause()
    }
}

impl fmt::Debug for Internal {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.inner.fmt(f)
    }
}

impl fmt::Display for Internal {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.inner.fmt(f)
    }
}

/// Error wrapper related to a particular manifest and providing it's path.
///
/// This error adds no displayable info of it's own.
pub struct ManifestError {
    cause: Error,
    manifest: PathBuf,
}

impl ManifestError {
    pub fn new<E: Into<Error>>(cause: E, manifest: PathBuf) -> Self {
        Self {
            cause: cause.into(),
            manifest,
        }
    }

    pub fn manifest_path(&self) -> &PathBuf {
        &self.manifest
    }

    /// Returns an iterator over the `ManifestError` chain of causes.
    ///
    /// So if this error was not caused by another `ManifestError` this will be empty.
    pub fn manifest_causes(&self) -> ManifestCauses<'_> {
        ManifestCauses { current: self }
    }
}

impl Fail for ManifestError {
    fn cause(&self) -> Option<&dyn Fail> {
        self.cause.as_fail().cause()
    }
}

impl fmt::Debug for ManifestError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.cause.fmt(f)
    }
}

impl fmt::Display for ManifestError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.cause.fmt(f)
    }
}

/// An iterator over the `ManifestError` chain of causes.
pub struct ManifestCauses<'a> {
    current: &'a ManifestError,
}

impl<'a> Iterator for ManifestCauses<'a> {
    type Item = &'a ManifestError;

    fn next(&mut self) -> Option<Self::Item> {
        self.current = self.current.cause.downcast_ref()?;
        Some(self.current)
    }
}

impl<'a> ::std::iter::FusedIterator for ManifestCauses<'a> {}

// =============================================================================
// Process errors
#[derive(Debug, Fail)]
#[fail(display = "{}", desc)]
pub struct ProcessError {
    pub desc: String,
    pub exit: Option<ExitStatus>,
    pub output: Option<Output>,
}

// =============================================================================
// Cargo test errors.

/// Error when testcases fail
#[derive(Debug, Fail)]
#[fail(display = "{}", desc)]
pub struct CargoTestError {
    pub test: Test,
    pub desc: String,
    pub exit: Option<ExitStatus>,
    pub causes: Vec<ProcessError>,
}

#[derive(Debug)]
pub enum Test {
    Multiple,
    Doc,
    UnitTest {
        kind: TargetKind,
        name: String,
        pkg_name: String,
    },
}

impl CargoTestError {
    pub fn new(test: Test, errors: Vec<ProcessError>) -> Self {
        if errors.is_empty() {
            panic!("Cannot create CargoTestError from empty Vec")
        }
        let desc = errors
            .iter()
            .map(|error| error.desc.clone())
            .collect::<Vec<String>>()
            .join("\n");
        CargoTestError {
            test,
            desc,
            exit: errors[0].exit,
            causes: errors,
        }
    }

    pub fn hint(&self, ws: &Workspace<'_>) -> String {
        match self.test {
            Test::UnitTest {
                ref kind,
                ref name,
                ref pkg_name,
            } => {
                let pkg_info = if ws.members().count() > 1 && ws.is_virtual() {
                    format!("-p {} ", pkg_name)
                } else {
                    String::new()
                };

                match *kind {
                    TargetKind::Bench => {
                        format!("test failed, to rerun pass '{}--bench {}'", pkg_info, name)
                    }
                    TargetKind::Bin => {
                        format!("test failed, to rerun pass '{}--bin {}'", pkg_info, name)
                    }
                    TargetKind::Lib(_) => format!("test failed, to rerun pass '{}--lib'", pkg_info),
                    TargetKind::Test => {
                        format!("test failed, to rerun pass '{}--test {}'", pkg_info, name)
                    }
                    TargetKind::ExampleBin | TargetKind::ExampleLib(_) => {
                        format!("test failed, to rerun pass '{}--example {}", pkg_info, name)
                    }
                    _ => "test failed.".into(),
                }
            }
            Test::Doc => "test failed, to rerun pass '--doc'".into(),
            _ => "test failed.".into(),
        }
    }
}

// =============================================================================
// CLI errors

pub type CliResult = Result<(), CliError>;

#[derive(Debug)]
pub struct CliError {
    pub error: Option<failure::Error>,
    pub unknown: bool,
    pub exit_code: i32,
}

impl CliError {
    pub fn new(error: failure::Error, code: i32) -> CliError {
        let unknown = error.downcast_ref::<Internal>().is_some();
        CliError {
            error: Some(error),
            exit_code: code,
            unknown,
        }
    }

    pub fn code(code: i32) -> CliError {
        CliError {
            error: None,
            exit_code: code,
            unknown: false,
        }
    }
}

impl From<failure::Error> for CliError {
    fn from(err: failure::Error) -> CliError {
        CliError::new(err, 101)
    }
}

impl From<clap::Error> for CliError {
    fn from(err: clap::Error) -> CliError {
        let code = if err.use_stderr() { 1 } else { 0 };
        CliError::new(err.into(), code)
    }
}

// =============================================================================
// Construction helpers

pub fn process_error(
    msg: &str,
    status: Option<ExitStatus>,
    output: Option<&Output>,
) -> ProcessError {
    let exit = match status {
        Some(s) => status_to_string(s),
        None => "never executed".to_string(),
    };
    let mut desc = format!("{} ({})", &msg, exit);

    if let Some(out) = output {
        match str::from_utf8(&out.stdout) {
            Ok(s) if !s.trim().is_empty() => {
                desc.push_str("\n--- stdout\n");
                desc.push_str(s);
            }
            Ok(..) | Err(..) => {}
        }
        match str::from_utf8(&out.stderr) {
            Ok(s) if !s.trim().is_empty() => {
                desc.push_str("\n--- stderr\n");
                desc.push_str(s);
            }
            Ok(..) | Err(..) => {}
        }
    }

    return ProcessError {
        desc,
        exit: status,
        output: output.cloned(),
    };

    #[cfg(unix)]
    fn status_to_string(status: ExitStatus) -> String {
        use libc;
        use std::os::unix::process::*;

        if let Some(signal) = status.signal() {
            let name = match signal as libc::c_int {
                libc::SIGABRT => ", SIGABRT: process abort signal",
                libc::SIGALRM => ", SIGALRM: alarm clock",
                libc::SIGFPE => ", SIGFPE: erroneous arithmetic operation",
                libc::SIGHUP => ", SIGHUP: hangup",
                libc::SIGILL => ", SIGILL: illegal instruction",
                libc::SIGINT => ", SIGINT: terminal interrupt signal",
                libc::SIGKILL => ", SIGKILL: kill",
                libc::SIGPIPE => ", SIGPIPE: write on a pipe with no one to read",
                libc::SIGQUIT => ", SIGQUIT: terminal quite signal",
                libc::SIGSEGV => ", SIGSEGV: invalid memory reference",
                libc::SIGTERM => ", SIGTERM: termination signal",
                libc::SIGBUS => ", SIGBUS: access to undefined memory",
                #[cfg(not(target_os = "haiku"))]
                libc::SIGSYS => ", SIGSYS: bad system call",
                libc::SIGTRAP => ", SIGTRAP: trace/breakpoint trap",
                _ => "",
            };
            format!("signal: {}{}", signal, name)
        } else {
            status.to_string()
        }
    }

    #[cfg(windows)]
    fn status_to_string(status: ExitStatus) -> String {
        status.to_string()
    }
}

pub fn internal<S: fmt::Display>(error: S) -> failure::Error {
    _internal(&error)
}

fn _internal(error: &dyn fmt::Display) -> failure::Error {
    Internal::new(failure::format_err!("{}", error)).into()
}
<commit_msg>Add helpful text for Windows exceptions like Unix<commit_after>#![allow(unknown_lints)]

use std::fmt;
use std::path::PathBuf;
use std::process::{ExitStatus, Output};
use std::str;

use clap;
use failure::{Context, Error, Fail};
use log::trace;

use crate::core::{TargetKind, Workspace};

pub type CargoResult<T> = failure::Fallible<T>; // Alex's body isn't quite ready to give up "Result"

pub trait CargoResultExt<T, E> {
    fn chain_err<F, D>(self, f: F) -> Result<T, Context<D>>
    where
        F: FnOnce() -> D,
        D: fmt::Display + Send + Sync + 'static;
}

impl<T, E> CargoResultExt<T, E> for Result<T, E>
where
    E: Into<Error>,
{
    fn chain_err<F, D>(self, f: F) -> Result<T, Context<D>>
    where
        F: FnOnce() -> D,
        D: fmt::Display + Send + Sync + 'static,
    {
        self.map_err(|failure| {
            let err = failure.into();
            let context = f();
            trace!("error: {}", err);
            trace!("\tcontext: {}", context);
            err.context(context)
        })
    }
}

#[derive(Debug, Fail)]
#[fail(display = "failed to get 200 response from `{}`, got {}", url, code)]
pub struct HttpNot200 {
    pub code: u32,
    pub url: String,
}

pub struct Internal {
    inner: Error,
}

impl Internal {
    pub fn new(inner: Error) -> Internal {
        Internal { inner }
    }
}

impl Fail for Internal {
    fn cause(&self) -> Option<&dyn Fail> {
        self.inner.as_fail().cause()
    }
}

impl fmt::Debug for Internal {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.inner.fmt(f)
    }
}

impl fmt::Display for Internal {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.inner.fmt(f)
    }
}

/// Error wrapper related to a particular manifest and providing it's path.
///
/// This error adds no displayable info of it's own.
pub struct ManifestError {
    cause: Error,
    manifest: PathBuf,
}

impl ManifestError {
    pub fn new<E: Into<Error>>(cause: E, manifest: PathBuf) -> Self {
        Self {
            cause: cause.into(),
            manifest,
        }
    }

    pub fn manifest_path(&self) -> &PathBuf {
        &self.manifest
    }

    /// Returns an iterator over the `ManifestError` chain of causes.
    ///
    /// So if this error was not caused by another `ManifestError` this will be empty.
    pub fn manifest_causes(&self) -> ManifestCauses<'_> {
        ManifestCauses { current: self }
    }
}

impl Fail for ManifestError {
    fn cause(&self) -> Option<&dyn Fail> {
        self.cause.as_fail().cause()
    }
}

impl fmt::Debug for ManifestError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.cause.fmt(f)
    }
}

impl fmt::Display for ManifestError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.cause.fmt(f)
    }
}

/// An iterator over the `ManifestError` chain of causes.
pub struct ManifestCauses<'a> {
    current: &'a ManifestError,
}

impl<'a> Iterator for ManifestCauses<'a> {
    type Item = &'a ManifestError;

    fn next(&mut self) -> Option<Self::Item> {
        self.current = self.current.cause.downcast_ref()?;
        Some(self.current)
    }
}

impl<'a> ::std::iter::FusedIterator for ManifestCauses<'a> {}

// =============================================================================
// Process errors
#[derive(Debug, Fail)]
#[fail(display = "{}", desc)]
pub struct ProcessError {
    pub desc: String,
    pub exit: Option<ExitStatus>,
    pub output: Option<Output>,
}

// =============================================================================
// Cargo test errors.

/// Error when testcases fail
#[derive(Debug, Fail)]
#[fail(display = "{}", desc)]
pub struct CargoTestError {
    pub test: Test,
    pub desc: String,
    pub exit: Option<ExitStatus>,
    pub causes: Vec<ProcessError>,
}

#[derive(Debug)]
pub enum Test {
    Multiple,
    Doc,
    UnitTest {
        kind: TargetKind,
        name: String,
        pkg_name: String,
    },
}

impl CargoTestError {
    pub fn new(test: Test, errors: Vec<ProcessError>) -> Self {
        if errors.is_empty() {
            panic!("Cannot create CargoTestError from empty Vec")
        }
        let desc = errors
            .iter()
            .map(|error| error.desc.clone())
            .collect::<Vec<String>>()
            .join("\n");
        CargoTestError {
            test,
            desc,
            exit: errors[0].exit,
            causes: errors,
        }
    }

    pub fn hint(&self, ws: &Workspace<'_>) -> String {
        match self.test {
            Test::UnitTest {
                ref kind,
                ref name,
                ref pkg_name,
            } => {
                let pkg_info = if ws.members().count() > 1 && ws.is_virtual() {
                    format!("-p {} ", pkg_name)
                } else {
                    String::new()
                };

                match *kind {
                    TargetKind::Bench => {
                        format!("test failed, to rerun pass '{}--bench {}'", pkg_info, name)
                    }
                    TargetKind::Bin => {
                        format!("test failed, to rerun pass '{}--bin {}'", pkg_info, name)
                    }
                    TargetKind::Lib(_) => format!("test failed, to rerun pass '{}--lib'", pkg_info),
                    TargetKind::Test => {
                        format!("test failed, to rerun pass '{}--test {}'", pkg_info, name)
                    }
                    TargetKind::ExampleBin | TargetKind::ExampleLib(_) => {
                        format!("test failed, to rerun pass '{}--example {}", pkg_info, name)
                    }
                    _ => "test failed.".into(),
                }
            }
            Test::Doc => "test failed, to rerun pass '--doc'".into(),
            _ => "test failed.".into(),
        }
    }
}

// =============================================================================
// CLI errors

pub type CliResult = Result<(), CliError>;

#[derive(Debug)]
pub struct CliError {
    pub error: Option<failure::Error>,
    pub unknown: bool,
    pub exit_code: i32,
}

impl CliError {
    pub fn new(error: failure::Error, code: i32) -> CliError {
        let unknown = error.downcast_ref::<Internal>().is_some();
        CliError {
            error: Some(error),
            exit_code: code,
            unknown,
        }
    }

    pub fn code(code: i32) -> CliError {
        CliError {
            error: None,
            exit_code: code,
            unknown: false,
        }
    }
}

impl From<failure::Error> for CliError {
    fn from(err: failure::Error) -> CliError {
        CliError::new(err, 101)
    }
}

impl From<clap::Error> for CliError {
    fn from(err: clap::Error) -> CliError {
        let code = if err.use_stderr() { 1 } else { 0 };
        CliError::new(err.into(), code)
    }
}

// =============================================================================
// Construction helpers

pub fn process_error(
    msg: &str,
    status: Option<ExitStatus>,
    output: Option<&Output>,
) -> ProcessError {
    let exit = match status {
        Some(s) => status_to_string(s),
        None => "never executed".to_string(),
    };
    let mut desc = format!("{} ({})", &msg, exit);

    if let Some(out) = output {
        match str::from_utf8(&out.stdout) {
            Ok(s) if !s.trim().is_empty() => {
                desc.push_str("\n--- stdout\n");
                desc.push_str(s);
            }
            Ok(..) | Err(..) => {}
        }
        match str::from_utf8(&out.stderr) {
            Ok(s) if !s.trim().is_empty() => {
                desc.push_str("\n--- stderr\n");
                desc.push_str(s);
            }
            Ok(..) | Err(..) => {}
        }
    }

    return ProcessError {
        desc,
        exit: status,
        output: output.cloned(),
    };

    #[cfg(unix)]
    fn status_to_string(status: ExitStatus) -> String {
        use libc;
        use std::os::unix::process::*;

        if let Some(signal) = status.signal() {
            let name = match signal as libc::c_int {
                libc::SIGABRT => ", SIGABRT: process abort signal",
                libc::SIGALRM => ", SIGALRM: alarm clock",
                libc::SIGFPE => ", SIGFPE: erroneous arithmetic operation",
                libc::SIGHUP => ", SIGHUP: hangup",
                libc::SIGILL => ", SIGILL: illegal instruction",
                libc::SIGINT => ", SIGINT: terminal interrupt signal",
                libc::SIGKILL => ", SIGKILL: kill",
                libc::SIGPIPE => ", SIGPIPE: write on a pipe with no one to read",
                libc::SIGQUIT => ", SIGQUIT: terminal quite signal",
                libc::SIGSEGV => ", SIGSEGV: invalid memory reference",
                libc::SIGTERM => ", SIGTERM: termination signal",
                libc::SIGBUS => ", SIGBUS: access to undefined memory",
                #[cfg(not(target_os = "haiku"))]
                libc::SIGSYS => ", SIGSYS: bad system call",
                libc::SIGTRAP => ", SIGTRAP: trace/breakpoint trap",
                _ => "",
            };
            format!("signal: {}{}", signal, name)
        } else {
            status.to_string()
        }
    }

    #[cfg(windows)]
    fn status_to_string(status: ExitStatus) -> String {
        use winapi::um::winnt::*;
        use winapi::shared::minwindef::DWORD;

        let mut base = status.to_string();
        let extra = match status.code().unwrap() as DWORD {
            STATUS_ACCESS_VIOLATION => "STATUS_ACCESS_VIOLATION",
            STATUS_IN_PAGE_ERROR => "STATUS_IN_PAGE_ERROR",
            STATUS_INVALID_HANDLE => "STATUS_INVALID_HANDLE",
            STATUS_INVALID_PARAMETER => "STATUS_INVALID_PARAMETER",
            STATUS_NO_MEMORY => "STATUS_NO_MEMORY",
            STATUS_ILLEGAL_INSTRUCTION => "STATUS_ILLEGAL_INSTRUCTION",
            STATUS_NONCONTINUABLE_EXCEPTION => "STATUS_NONCONTINUABLE_EXCEPTION",
            STATUS_INVALID_DISPOSITION => "STATUS_INVALID_DISPOSITION",
            STATUS_ARRAY_BOUNDS_EXCEEDED => "STATUS_ARRAY_BOUNDS_EXCEEDED",
            STATUS_FLOAT_DENORMAL_OPERAND => "STATUS_FLOAT_DENORMAL_OPERAND",
            STATUS_FLOAT_DIVIDE_BY_ZERO => "STATUS_FLOAT_DIVIDE_BY_ZERO",
            STATUS_FLOAT_INEXACT_RESULT => "STATUS_FLOAT_INEXACT_RESULT",
            STATUS_FLOAT_INVALID_OPERATION => "STATUS_FLOAT_INVALID_OPERATION",
            STATUS_FLOAT_OVERFLOW => "STATUS_FLOAT_OVERFLOW",
            STATUS_FLOAT_STACK_CHECK => "STATUS_FLOAT_STACK_CHECK",
            STATUS_FLOAT_UNDERFLOW => "STATUS_FLOAT_UNDERFLOW",
            STATUS_INTEGER_DIVIDE_BY_ZERO => "STATUS_INTEGER_DIVIDE_BY_ZERO",
            STATUS_INTEGER_OVERFLOW => "STATUS_INTEGER_OVERFLOW",
            STATUS_PRIVILEGED_INSTRUCTION => "STATUS_PRIVILEGED_INSTRUCTION",
            STATUS_STACK_OVERFLOW => "STATUS_STACK_OVERFLOW",
            STATUS_DLL_NOT_FOUND => "STATUS_DLL_NOT_FOUND",
            STATUS_ORDINAL_NOT_FOUND => "STATUS_ORDINAL_NOT_FOUND",
            STATUS_ENTRYPOINT_NOT_FOUND => "STATUS_ENTRYPOINT_NOT_FOUND",
            STATUS_CONTROL_C_EXIT => "STATUS_CONTROL_C_EXIT",
            STATUS_DLL_INIT_FAILED => "STATUS_DLL_INIT_FAILED",
            STATUS_FLOAT_MULTIPLE_FAULTS => "STATUS_FLOAT_MULTIPLE_FAULTS",
            STATUS_FLOAT_MULTIPLE_TRAPS => "STATUS_FLOAT_MULTIPLE_TRAPS",
            STATUS_REG_NAT_CONSUMPTION => "STATUS_REG_NAT_CONSUMPTION",
            STATUS_HEAP_CORRUPTION => "STATUS_HEAP_CORRUPTION",
            STATUS_STACK_BUFFER_OVERRUN => "STATUS_STACK_BUFFER_OVERRUN",
            STATUS_ASSERTION_FAILURE => "STATUS_ASSERTION_FAILURE",
            _ => return base,
        };
        base.push_str(", ");
        base.push_str(extra);
        base
    }
}

pub fn internal<S: fmt::Display>(error: S) -> failure::Error {
    _internal(&error)
}

fn _internal(error: &dyn fmt::Display) -> failure::Error {
    Internal::new(failure::format_err!("{}", error)).into()
}
<|endoftext|>


<commit_before>use proc_macro2::{Span, TokenStream};
use syn::spanned::Spanned;
use syn::{Field as SynField, Ident, Index, Type};

use attrs::{parse_attributes, AttributeSpanWrapper, FieldAttr, SqlIdentifier};

pub struct Field {
    pub ty: Type,
    pub span: Span,
    pub name: FieldName,
    column_name: Option<AttributeSpanWrapper<SqlIdentifier>>,
    pub sql_type: Option<AttributeSpanWrapper<Type>>,
    pub serialize_as: Option<AttributeSpanWrapper<Type>>,
    pub deserialize_as: Option<AttributeSpanWrapper<Type>>,
    pub select_expression: Option<AttributeSpanWrapper<SelectExpr>>,
    pub select_expression_type: Option<AttributeSpanWrapper<Type>>,
    pub embed: Option<AttributeSpanWrapper<bool>>,
}

impl Field {
    pub fn from_struct_field(field: &SynField, index: usize) -> Self {
        let SynField {
            ident, attrs, ty, ..
        } = field;

        let mut column_name = None;
        let mut sql_type = None;
        let mut serialize_as = None;
        let mut deserialize_as = None;
        let mut embed = None;
        let mut select_expression = None;
        let mut select_expression_type = None;

        for attr in parse_attributes(attrs) {
            let attribute_span = attr.attribute_span;
            let ident_span = attr.ident_span;
            match attr.item {
                FieldAttr::ColumnName(_, value) => {
                    column_name = Some(AttributeSpanWrapper {
                        item: value,
                        attribute_span,
                        ident_span,
                    })
                }
                FieldAttr::SqlType(_, value) => {
                    sql_type = Some(AttributeSpanWrapper {
                        item: Type::Path(value),
                        attribute_span,
                        ident_span,
                    })
                }
                FieldAttr::SerializeAs(_, value) => {
                    serialize_as = Some(AttributeSpanWrapper {
                        item: Type::Path(value),
                        attribute_span,
                        ident_span,
                    })
                }
                FieldAttr::DeserializeAs(_, value) => {
                    deserialize_as = Some(AttributeSpanWrapper {
                        item: Type::Path(value),
                        attribute_span,
                        ident_span,
                    })
                }
                FieldAttr::SelectExpression(_, value) => {
                    select_expression = Some(AttributeSpanWrapper {
                        item: value,
                        attribute_span,
                        ident_span,
                    })
                }
                FieldAttr::SelectExpressionType(_, value) => {
                    select_expression_type = Some(AttributeSpanWrapper {
                        item: value,
                        attribute_span,
                        ident_span,
                    })
                }
                FieldAttr::Embed(_) => {
                    embed = Some(AttributeSpanWrapper {
                        item: true,
                        attribute_span,
                        ident_span,
                    })
                }
            }
        }

        let name = match ident.clone() {
            Some(x) => FieldName::Named(x),
            None => FieldName::Unnamed(index.into()),
        };

        let span = match name {
            FieldName::Named(ref ident) => ident.span(),
            FieldName::Unnamed(_) => ty.span(),
        };

        Self {
            ty: ty.clone(),
            span,
            name,
            column_name,
            sql_type,
            serialize_as,
            deserialize_as,
            select_expression,
            select_expression_type,
            embed,
        }
    }

    pub fn column_name(&self) -> SqlIdentifier {
        self.column_name
            .as_ref()
            .map(|a| a.item.clone())
            .unwrap_or_else(|| match self.name {
                FieldName::Named(ref x) => x.into(),
                FieldName::Unnamed(ref x) => {
                    abort!(
                    x,
                    "All fields of tuple structs must be annotated with `#[diesel(column_name)]`"
                );
                }
            })
    }

    pub fn ty_for_deserialize(&self) -> &Type {
        if let Some(AttributeSpanWrapper { item: value, .. }) = &self.deserialize_as {
            value
        } else {
            &self.ty
        }
    }

    pub(crate) fn embed(&self) -> bool {
        self.embed.as_ref().map(|a| a.item).unwrap_or(false)
    }
}

pub enum FieldName {
    Named(Ident),
    Unnamed(Index),
}

impl quote::ToTokens for FieldName {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match *self {
            FieldName::Named(ref x) => x.to_tokens(tokens),
            FieldName::Unnamed(ref x) => x.to_tokens(tokens),
        }
    }
}

/// We use this instead of directly `syn::Expr` to reduce compilation time
///
/// `syn::Expr` does not properly support tuples when `syn/full` feature is
/// not enabled, and that feature slightly increases compilation time
pub enum SelectExpr {
    Expr(syn::Expr),
    Tuple {
        paren_token: syn::token::Paren,
        content: proc_macro2::TokenStream,
    },
}

impl quote::ToTokens for SelectExpr {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match self {
            SelectExpr::Expr(ref e) => e.to_tokens(tokens),
            SelectExpr::Tuple {
                ref paren_token,
                ref content,
            } => paren_token.surround(tokens, |tokens| content.to_tokens(tokens)),
        }
    }
}

impl syn::parse::Parse for SelectExpr {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        let lookahead = input.lookahead1();

        if lookahead.peek(syn::token::Paren) {
            let content;
            let paren_token = syn::parenthesized!(content in input);
            Ok(Self::Tuple {
                paren_token,
                content: content.parse()?,
            })
        } else {
            input.parse::<syn::Expr>().map(Self::Expr)
        }
    }
}
<commit_msg>Clippy fix<commit_after>use proc_macro2::{Span, TokenStream};
use syn::spanned::Spanned;
use syn::{Field as SynField, Ident, Index, Type};

use attrs::{parse_attributes, AttributeSpanWrapper, FieldAttr, SqlIdentifier};

pub struct Field {
    pub ty: Type,
    pub span: Span,
    pub name: FieldName,
    column_name: Option<AttributeSpanWrapper<SqlIdentifier>>,
    pub sql_type: Option<AttributeSpanWrapper<Type>>,
    pub serialize_as: Option<AttributeSpanWrapper<Type>>,
    pub deserialize_as: Option<AttributeSpanWrapper<Type>>,
    pub select_expression: Option<AttributeSpanWrapper<SelectExpr>>,
    pub select_expression_type: Option<AttributeSpanWrapper<Type>>,
    pub embed: Option<AttributeSpanWrapper<bool>>,
}

impl Field {
    pub fn from_struct_field(field: &SynField, index: usize) -> Self {
        let SynField {
            ident, attrs, ty, ..
        } = field;

        let mut column_name = None;
        let mut sql_type = None;
        let mut serialize_as = None;
        let mut deserialize_as = None;
        let mut embed = None;
        let mut select_expression = None;
        let mut select_expression_type = None;

        for attr in parse_attributes(attrs) {
            let attribute_span = attr.attribute_span;
            let ident_span = attr.ident_span;
            match attr.item {
                FieldAttr::ColumnName(_, value) => {
                    column_name = Some(AttributeSpanWrapper {
                        item: value,
                        attribute_span,
                        ident_span,
                    })
                }
                FieldAttr::SqlType(_, value) => {
                    sql_type = Some(AttributeSpanWrapper {
                        item: Type::Path(value),
                        attribute_span,
                        ident_span,
                    })
                }
                FieldAttr::SerializeAs(_, value) => {
                    serialize_as = Some(AttributeSpanWrapper {
                        item: Type::Path(value),
                        attribute_span,
                        ident_span,
                    })
                }
                FieldAttr::DeserializeAs(_, value) => {
                    deserialize_as = Some(AttributeSpanWrapper {
                        item: Type::Path(value),
                        attribute_span,
                        ident_span,
                    })
                }
                FieldAttr::SelectExpression(_, value) => {
                    select_expression = Some(AttributeSpanWrapper {
                        item: value,
                        attribute_span,
                        ident_span,
                    })
                }
                FieldAttr::SelectExpressionType(_, value) => {
                    select_expression_type = Some(AttributeSpanWrapper {
                        item: value,
                        attribute_span,
                        ident_span,
                    })
                }
                FieldAttr::Embed(_) => {
                    embed = Some(AttributeSpanWrapper {
                        item: true,
                        attribute_span,
                        ident_span,
                    })
                }
            }
        }

        let name = match ident.clone() {
            Some(x) => FieldName::Named(x),
            None => FieldName::Unnamed(index.into()),
        };

        let span = match name {
            FieldName::Named(ref ident) => ident.span(),
            FieldName::Unnamed(_) => ty.span(),
        };

        Self {
            ty: ty.clone(),
            span,
            name,
            column_name,
            sql_type,
            serialize_as,
            deserialize_as,
            select_expression,
            select_expression_type,
            embed,
        }
    }

    pub fn column_name(&self) -> SqlIdentifier {
        self.column_name
            .as_ref()
            .map(|a| a.item.clone())
            .unwrap_or_else(|| match self.name {
                FieldName::Named(ref x) => x.into(),
                FieldName::Unnamed(ref x) => {
                    abort!(
                    x,
                    "All fields of tuple structs must be annotated with `#[diesel(column_name)]`"
                );
                }
            })
    }

    pub fn ty_for_deserialize(&self) -> &Type {
        if let Some(AttributeSpanWrapper { item: value, .. }) = &self.deserialize_as {
            value
        } else {
            &self.ty
        }
    }

    pub(crate) fn embed(&self) -> bool {
        self.embed.as_ref().map(|a| a.item).unwrap_or(false)
    }
}

pub enum FieldName {
    Named(Ident),
    Unnamed(Index),
}

impl quote::ToTokens for FieldName {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match *self {
            FieldName::Named(ref x) => x.to_tokens(tokens),
            FieldName::Unnamed(ref x) => x.to_tokens(tokens),
        }
    }
}

/// We use this instead of directly `syn::Expr` to reduce compilation time
///
/// `syn::Expr` does not properly support tuples when `syn/full` feature is
/// not enabled, and that feature slightly increases compilation time
#[allow(clippy::large_enum_variant)]
pub enum SelectExpr {
    Expr(syn::Expr),
    Tuple {
        paren_token: syn::token::Paren,
        content: proc_macro2::TokenStream,
    },
}

impl quote::ToTokens for SelectExpr {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match self {
            SelectExpr::Expr(ref e) => e.to_tokens(tokens),
            SelectExpr::Tuple {
                ref paren_token,
                ref content,
            } => paren_token.surround(tokens, |tokens| content.to_tokens(tokens)),
        }
    }
}

impl syn::parse::Parse for SelectExpr {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        let lookahead = input.lookahead1();

        if lookahead.peek(syn::token::Paren) {
            let content;
            let paren_token = syn::parenthesized!(content in input);
            Ok(Self::Tuple {
                paren_token,
                content: content.parse()?,
            })
        } else {
            input.parse::<syn::Expr>().map(Self::Expr)
        }
    }
}
<|endoftext|>


<commit_before>use vm::{Memory, Storage, Instruction};
use vm::errors::EvalError;

use vm::eval::{State, ControlCheck};
use super::utils::check_range;

#[allow(unused_variables)]
pub fn check_opcode<M: Memory + Default, S: Storage + Default + Clone>(instruction: Instruction, state: &State<M, S>) -> Result<Option<ControlCheck>, EvalError> {
    match instruction {
        Instruction::STOP => Ok(None),
        Instruction::ADD => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::MUL => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::SUB => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::DIV => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::SDIV => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::MOD => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::SMOD => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::ADDMOD => { state.stack.check_pop_push(3, 1)?; Ok(None) },
        Instruction::MULMOD => { state.stack.check_pop_push(3, 1)?; Ok(None) },
        Instruction::EXP => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::SIGNEXTEND => { state.stack.check_pop_push(2, 1)?; Ok(None) },

        Instruction::LT => unimplemented!(),
        Instruction::GT => unimplemented!(),
        Instruction::SLT => unimplemented!(),
        Instruction::SGT => unimplemented!(),
        Instruction::EQ => unimplemented!(),
        Instruction::ISZERO => unimplemented!(),
        Instruction::AND => unimplemented!(),
        Instruction::OR => unimplemented!(),
        Instruction::XOR => unimplemented!(),
        Instruction::NOT => unimplemented!(),
        Instruction::BYTE => unimplemented!(),

        Instruction::SHA3 => unimplemented!(),

        Instruction::ADDRESS => unimplemented!(),
        Instruction::BALANCE => unimplemented!(),
        Instruction::ORIGIN => unimplemented!(),
        Instruction::CALLER => unimplemented!(),
        Instruction::CALLVALUE => unimplemented!(),
        Instruction::CALLDATALOAD => unimplemented!(),
        Instruction::CALLDATASIZE => unimplemented!(),
        Instruction::CALLDATACOPY => unimplemented!(),
        Instruction::CODESIZE => unimplemented!(),
        Instruction::CODECOPY => unimplemented!(),
        Instruction::GASPRICE => unimplemented!(),
        Instruction::EXTCODESIZE => unimplemented!(),
        Instruction::EXTCODECOPY => unimplemented!(),

        Instruction::BLOCKHASH => unimplemented!(),
        Instruction::COINBASE => unimplemented!(),
        Instruction::TIMESTAMP => unimplemented!(),
        Instruction::NUMBER => unimplemented!(),
        Instruction::DIFFICULTY => unimplemented!(),
        Instruction::GASLIMIT => unimplemented!(),

        Instruction::POP => unimplemented!(),
        Instruction::MLOAD => unimplemented!(),
        Instruction::MSTORE => unimplemented!(),
        Instruction::MSTORE8 => unimplemented!(),
        Instruction::SLOAD => {
            state.stack.check_pop_push(1, 1)?;
            state.account_state.require(state.context.address)?;
            Ok(None)
        },
        Instruction::SSTORE => {
            state.stack.check_pop_push(2, 0)?;
            state.account_state.storage(state.context.address)?.
                check_write(state.stack.peek(0).unwrap())?;
            Ok(None)
        },
        Instruction::JUMP => unimplemented!(),
        Instruction::JUMPI => unimplemented!(),
        Instruction::PC => unimplemented!(),
        Instruction::MSIZE => unimplemented!(),
        Instruction::GAS => unimplemented!(),
        Instruction::JUMPDEST => unimplemented!(),

        Instruction::PUSH(v) => { state.stack.check_pop_push(0, 1)?; Ok(None) }

        Instruction::DUP(v) => unimplemented!(),
        Instruction::SWAP(v) => unimplemented!(),
        Instruction::LOG(v) => unimplemented!(),

        Instruction::CREATE => unimplemented!(),
        Instruction::CALL => unimplemented!(),
        Instruction::CALLCODE => unimplemented!(),
        Instruction::RETURN => {
            state.stack.check_pop_push(2, 0)?;
            check_range(state.stack.peek(0).unwrap(), state.stack.peek(1).unwrap())?;
            Ok(None)
        }
        Instruction::DELEGATECALL => unimplemented!(),
        Instruction::SUICIDE => unimplemented!(),
    }
}
<commit_msg>Problem: bytes opcode check is not implemented Solution: implement it<commit_after>use vm::{Memory, Storage, Instruction};
use vm::errors::EvalError;

use vm::eval::{State, ControlCheck};
use super::utils::check_range;

#[allow(unused_variables)]
pub fn check_opcode<M: Memory + Default, S: Storage + Default + Clone>(instruction: Instruction, state: &State<M, S>) -> Result<Option<ControlCheck>, EvalError> {
    match instruction {
        Instruction::STOP => Ok(None),
        Instruction::ADD => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::MUL => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::SUB => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::DIV => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::SDIV => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::MOD => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::SMOD => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::ADDMOD => { state.stack.check_pop_push(3, 1)?; Ok(None) },
        Instruction::MULMOD => { state.stack.check_pop_push(3, 1)?; Ok(None) },
        Instruction::EXP => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::SIGNEXTEND => { state.stack.check_pop_push(2, 1)?; Ok(None) },

        Instruction::LT => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::GT => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::SLT => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::SGT => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::EQ => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::ISZERO => { state.stack.check_pop_push(1, 1)?; Ok(None) },
        Instruction::AND => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::OR => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::XOR => { state.stack.check_pop_push(2, 1)?; Ok(None) },
        Instruction::NOT => { state.stack.check_pop_push(1, 1)?; Ok(None) },
        Instruction::BYTE => { state.stack.check_pop_push(2, 1)?; Ok(None) },

        Instruction::SHA3 => unimplemented!(),

        Instruction::ADDRESS => unimplemented!(),
        Instruction::BALANCE => unimplemented!(),
        Instruction::ORIGIN => unimplemented!(),
        Instruction::CALLER => unimplemented!(),
        Instruction::CALLVALUE => unimplemented!(),
        Instruction::CALLDATALOAD => unimplemented!(),
        Instruction::CALLDATASIZE => unimplemented!(),
        Instruction::CALLDATACOPY => unimplemented!(),
        Instruction::CODESIZE => unimplemented!(),
        Instruction::CODECOPY => unimplemented!(),
        Instruction::GASPRICE => unimplemented!(),
        Instruction::EXTCODESIZE => unimplemented!(),
        Instruction::EXTCODECOPY => unimplemented!(),

        Instruction::BLOCKHASH => unimplemented!(),
        Instruction::COINBASE => unimplemented!(),
        Instruction::TIMESTAMP => unimplemented!(),
        Instruction::NUMBER => unimplemented!(),
        Instruction::DIFFICULTY => unimplemented!(),
        Instruction::GASLIMIT => unimplemented!(),

        Instruction::POP => unimplemented!(),
        Instruction::MLOAD => unimplemented!(),
        Instruction::MSTORE => unimplemented!(),
        Instruction::MSTORE8 => unimplemented!(),
        Instruction::SLOAD => {
            state.stack.check_pop_push(1, 1)?;
            state.account_state.require(state.context.address)?;
            Ok(None)
        },
        Instruction::SSTORE => {
            state.stack.check_pop_push(2, 0)?;
            state.account_state.storage(state.context.address)?.
                check_write(state.stack.peek(0).unwrap())?;
            Ok(None)
        },
        Instruction::JUMP => unimplemented!(),
        Instruction::JUMPI => unimplemented!(),
        Instruction::PC => unimplemented!(),
        Instruction::MSIZE => unimplemented!(),
        Instruction::GAS => unimplemented!(),
        Instruction::JUMPDEST => unimplemented!(),

        Instruction::PUSH(v) => { state.stack.check_pop_push(0, 1)?; Ok(None) }

        Instruction::DUP(v) => unimplemented!(),
        Instruction::SWAP(v) => unimplemented!(),
        Instruction::LOG(v) => unimplemented!(),

        Instruction::CREATE => unimplemented!(),
        Instruction::CALL => unimplemented!(),
        Instruction::CALLCODE => unimplemented!(),
        Instruction::RETURN => {
            state.stack.check_pop_push(2, 0)?;
            check_range(state.stack.peek(0).unwrap(), state.stack.peek(1).unwrap())?;
            Ok(None)
        }
        Instruction::DELEGATECALL => unimplemented!(),
        Instruction::SUICIDE => unimplemented!(),
    }
}
<|endoftext|>


<commit_before>macro_rules! fail {
    ($err:expr) => (
        return Err(From::from($err));
    );
    ($fmt:expr, $($arg:tt)*) => (
        return Err(From::from(format!($fmt, $($arg)*)));
    );
}

macro_rules! ensure {
    ($expr:expr, $err:expr) => (
        if !($expr) {
            fail!($err);
        }
    )
}

macro_rules! assert_err {
    ($expr:expr, $err:expr) => {
        match &($expr) {
            &Ok(_) => {
                panic!("assertion failed: not an error in `{}`", stringify!($expr));
            }
            &Err(ref value) => {
                use regex::Regex;
                use std::error::Error as BaseError;
                let re = Regex::new($err).unwrap();
                let desc = value.description().to_string();
                if !re.is_match(desc.as_ref()) {
                    panic!("assertion failed: error message \"{}\" doesn't match \"{}\" in `{}`",
                           desc, re, stringify!($expr));
                }
            }
        }
    }
}

macro_rules! h5lock_s {
    ($expr:expr) => ({
        use ::sync::sync;
        sync(|| { $expr })
    })
}

macro_rules! h5lock {
    ($expr:expr) => (h5lock_s!(unsafe { $expr }))
}

macro_rules! h5call_s {
    ($expr:expr) => ({
        use error::h5check;
        h5lock_s!(h5check($expr))
    })
}

macro_rules! h5call {
    ($expr:expr) => (h5call_s!(unsafe { $expr }))
}

macro_rules! h5try_s {
    ($expr:expr) => (match h5call_s!($expr) {
        Ok(value) => value,
        Err(err)  => {
            return Err(From::from(err))
        },
    })
}

macro_rules! h5try {
    ($expr:expr) => (h5try_s!(unsafe { $expr }))
}
<commit_msg>Add debug!() and debug_id!() macros<commit_after>macro_rules! fail {
    ($err:expr) => (
        return Err(From::from($err));
    );
    ($fmt:expr, $($arg:tt)*) => (
        return Err(From::from(format!($fmt, $($arg)*)));
    );
}

macro_rules! ensure {
    ($expr:expr, $err:expr) => (
        if !($expr) {
            fail!($err);
        }
    )
}

macro_rules! assert_err {
    ($expr:expr, $err:expr) => {
        match &($expr) {
            &Ok(_) => {
                panic!("assertion failed: not an error in `{}`", stringify!($expr));
            }
            &Err(ref value) => {
                use regex::Regex;
                use std::error::Error as BaseError;
                let re = Regex::new($err).unwrap();
                let desc = value.description().to_string();
                if !re.is_match(desc.as_ref()) {
                    panic!("assertion failed: error message \"{}\" doesn't match \"{}\" in `{}`",
                           desc, re, stringify!($expr));
                }
            }
        }
    }
}

macro_rules! h5lock_s {
    ($expr:expr) => ({
        use ::sync::sync;
        sync(|| { $expr })
    })
}

macro_rules! h5lock {
    ($expr:expr) => (h5lock_s!(unsafe { $expr }))
}

macro_rules! h5call_s {
    ($expr:expr) => ({
        use error::h5check;
        h5lock_s!(h5check($expr))
    })
}

macro_rules! h5call {
    ($expr:expr) => (h5call_s!(unsafe { $expr }))
}

macro_rules! h5try_s {
    ($expr:expr) => (match h5call_s!($expr) {
        Ok(value) => value,
        Err(err)  => {
            return Err(From::from(err))
        },
    })
}

macro_rules! h5try {
    ($expr:expr) => (h5try_s!(unsafe { $expr }))
}

thread_local!(static THREAD_ID: () = ());

pub fn thread_id() -> usize {
    THREAD_ID.with(|x| x as *const _ as usize)
}

macro_rules! debug {
    ($arg:expr) => {
        {
            use macros::thread_id;
            println!("{:x}: {}:{}: {}", thread_id(), file!(), line!(), $arg);
        }
    };
    ($fmt:expr, $($arg:tt)*) => {
        {
            use macros::thread_id;
            println!("{:x}: {}:{}: {}", thread_id(), file!(), line!(), format!($fmt, $($arg)*));
        }
    };
}

macro_rules! debug_id {
    ($id:expr) => {
        {
            use object::Object;
            debug!("{} / {} / {}", ($id).id(), ($id).refcount(), ($id).is_valid());
        }
    };
    ($id:expr, $msg:expr) => {
        {
            use object::Object;
            debug!("{}: {} / {} / {}", $msg, ($id).id(), ($id).refcount(), ($id).is_valid());
        }
    };
}
<|endoftext|>


<commit_before>//! This module provides two utility macros for testing custom derives. They can
//! be used together to eliminate some of the boilerplate required in order to
//! declare and test custom derive implementations.

// Re-exports used by the decl_derive! and test_derive!
pub use proc_macro::TokenStream;
pub use proc_macro2::TokenStream as TokenStream2;
pub use syn::{parse, parse_str, DeriveInput};

/// The `decl_derive!` macro declares a custom derive wrapper. It will parse the
/// incoming `TokenStream` into a `synstructure::Structure` object, and pass it
/// into the inner function.
///
/// Your inner function should take a `synstructure::Structure` by value, and
/// return a type implementing `synstructure::MacroResult`, for example:
///
/// ```
/// fn derive_simple(input: synstructure::Structure) -> proc_macro2::TokenStream {
///     unimplemented!()
/// }
///
/// fn derive_result(input: synstructure::Structure)
///     -> syn::Result<proc_macro2::TokenStream>
/// {
///     unimplemented!()
/// }
/// ```
///
/// # Usage
///
/// ### Without Attributes
/// ```
/// fn derive_interesting(_input: synstructure::Structure) -> proc_macro2::TokenStream {
///     quote::quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_derive!([Interesting] => derive_interesting);
/// # };
/// ```
///
/// ### With Attributes
/// ```
/// # fn main() {}
/// fn derive_interesting(_input: synstructure::Structure) -> proc_macro2::TokenStream {
///     quote::quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_derive!([Interesting, attributes(interesting_ignore)] => derive_interesting);
/// # };
/// ```
#[macro_export]
macro_rules! decl_derive {
    // XXX: Switch to using this variant everywhere?
    ([$derives:ident $($derive_t:tt)*] => $(#[$attrs:meta])* $inner:path) => {
        #[proc_macro_derive($derives $($derive_t)*)]
        #[allow(non_snake_case)]
        $(#[$attrs])*
        pub fn $derives(
            i: $crate::macros::TokenStream
        ) -> $crate::macros::TokenStream {
            match $crate::macros::parse::<$crate::macros::DeriveInput>(i) {
                Ok(p) => {
                    match $crate::Structure::try_new(&p) {
                        Ok(s) => $crate::MacroResult::into_stream($inner(s)),
                        Err(e) => e.to_compile_error().into(),
                    }
                }
                Err(e) => e.to_compile_error().into(),
            }
        }
    };
}

/// The `decl_attribute!` macro declares a custom attribute wrapper. It will
/// parse the incoming `TokenStream` into a `synstructure::Structure` object,
/// and pass it into the inner function.
///
/// Your inner function should have the following type:
///
/// ```
/// fn attribute(
///     attr: proc_macro2::TokenStream,
///     structure: synstructure::Structure,
/// ) -> proc_macro2::TokenStream {
///     unimplemented!()
/// }
/// ```
///
/// # Usage
///
/// ```
/// fn attribute_interesting(
///     _attr: proc_macro2::TokenStream,
///     _structure: synstructure::Structure,
/// ) -> proc_macro2::TokenStream {
///     quote::quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_attribute!([interesting] => attribute_interesting);
/// # };
/// ```
/// ```
#[macro_export]
macro_rules! decl_attribute {
    ([$attribute:ident] => $(#[$attrs:meta])* $inner:path) => {
        #[proc_macro_attribute]
        $(#[$attrs])*
        pub fn $attribute(
            attr: $crate::macros::TokenStream,
            i: $crate::macros::TokenStream,
        ) -> $crate::macros::TokenStream {
            match $crate::macros::parse::<$crate::macros::DeriveInput>(i) {
                Ok(p) => match $crate::Structure::try_new(&p) {
                    Ok(s) => $crate::MacroResult::into_stream($inner(attr.into(), s)),
                    Err(e) => e.to_compile_error().into(),
                },
                Err(e) => e.to_compile_error().into(),
            }
        }
    };
}

/// Run a test on a custom derive. This macro expands both the original struct
/// and the expansion to ensure that they compile correctly, and confirms that
/// feeding the original struct into the named derive will produce the written
/// output.
///
/// You can add `no_build` to the end of the macro invocation to disable
/// checking that the written code compiles. This is useful in contexts where
/// the procedural macro cannot depend on the crate where it is used during
/// tests.
///
/// # Usage
///
/// ```
/// fn test_derive_example(_s: synstructure::Structure)
///     -> Result<proc_macro2::TokenStream, syn::Error>
/// {
///     Ok(quote::quote! { const YOUR_OUTPUT: &'static str = "here"; })
/// }
///
/// fn main() {
///     synstructure::test_derive!{
///         test_derive_example {
///             struct A;
///         }
///         expands to {
///             const YOUR_OUTPUT: &'static str = "here";
///         }
///     }
/// }
/// ```
#[macro_export]
macro_rules! test_derive {
    ($name:path { $($i:tt)* } expands to { $($o:tt)* }) => {
        {
            #[allow(dead_code)]
            fn ensure_compiles() {
                $($i)*
                $($o)*
            }

            $crate::test_derive!($name { $($i)* } expands to { $($o)* } no_build);
        }
    };

    ($name:path { $($i:tt)* } expands to { $($o:tt)* } no_build) => {
        {
            let i = stringify!( $($i)* );
            let parsed = $crate::macros::parse_str::<$crate::macros::DeriveInput>(i)
                .expect(concat!(
                    "Failed to parse input to `#[derive(",
                    stringify!($name),
                    ")]`",
                ));

            let raw_res = $name($crate::Structure::new(&parsed));
            let res = $crate::MacroResult::into_result(raw_res)
                .expect(concat!(
                    "Procedural macro failed for `#[derive(",
                    stringify!($name),
                    ")]`",
                ));

            let expected = stringify!( $($o)* )
                .parse::<$crate::macros::TokenStream2>()
                .expect("output should be a valid TokenStream");
            let mut expected_toks = $crate::macros::TokenStream2::from(expected);
            if res.to_string() != expected_toks.to_string() {
                panic!("\
test_derive failed:
expected:
```
{}
```

got:
```
{}
```\n",
                    $crate::unpretty_print(&expected_toks),
                    $crate::unpretty_print(&res),
                );
            }
        }
    };
}
<commit_msg>Add documentation and make matchers more flexible<commit_after>//! This module provides two utility macros for testing custom derives. They can
//! be used together to eliminate some of the boilerplate required in order to
//! declare and test custom derive implementations.

// Re-exports used by the decl_derive! and test_derive!
pub use proc_macro::TokenStream;
pub use proc_macro2::TokenStream as TokenStream2;
pub use syn::{parse, parse_str, DeriveInput};

/// The `decl_derive!` macro declares a custom derive wrapper. It will parse the
/// incoming `TokenStream` into a `synstructure::Structure` object, and pass it
/// into the inner function.
///
/// Your inner function should take a `synstructure::Structure` by value, and
/// return a type implementing `synstructure::MacroResult`, for example:
///
/// ```
/// fn derive_simple(input: synstructure::Structure) -> proc_macro2::TokenStream {
///     unimplemented!()
/// }
///
/// fn derive_result(input: synstructure::Structure)
///     -> syn::Result<proc_macro2::TokenStream>
/// {
///     unimplemented!()
/// }
/// ```
///
/// # Usage
///
/// ### Without Attributes
/// ```
/// fn derive_interesting(_input: synstructure::Structure) -> proc_macro2::TokenStream {
///     quote::quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_derive!([Interesting] => derive_interesting);
/// # };
/// ```
///
/// ### With Attributes
/// ```
/// # fn main() {}
/// fn derive_interesting(_input: synstructure::Structure) -> proc_macro2::TokenStream {
///     quote::quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_derive!([Interesting, attributes(interesting_ignore)] => derive_interesting);
/// # };
/// ```
///
/// ### Decl Attributes & Doc Comments
/// ```
/// # fn main() {}
/// fn derive_interesting(_input: synstructure::Structure) -> proc_macro2::TokenStream {
///     quote::quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_derive! {
///     [Interesting] =>
///     #[allow(some_lint)]
///     /// Documentation Comments
///     derive_interesting
/// }
/// # };
/// ```
#[macro_export]
macro_rules! decl_derive {
    // XXX: Switch to using this variant everywhere?
    ([$derives:ident $($derive_t:tt)*] => $(#[$($attrs:tt)*])* $inner:path) => {
        #[proc_macro_derive($derives $($derive_t)*)]
        #[allow(non_snake_case)]
        $(#[$($attrs)*])*
        pub fn $derives(
            i: $crate::macros::TokenStream
        ) -> $crate::macros::TokenStream {
            match $crate::macros::parse::<$crate::macros::DeriveInput>(i) {
                Ok(p) => {
                    match $crate::Structure::try_new(&p) {
                        Ok(s) => $crate::MacroResult::into_stream($inner(s)),
                        Err(e) => e.to_compile_error().into(),
                    }
                }
                Err(e) => e.to_compile_error().into(),
            }
        }
    };
}

/// The `decl_attribute!` macro declares a custom attribute wrapper. It will
/// parse the incoming `TokenStream` into a `synstructure::Structure` object,
/// and pass it into the inner function.
///
/// Your inner function should have the following type:
///
/// ```
/// fn attribute(
///     attr: proc_macro2::TokenStream,
///     structure: synstructure::Structure,
/// ) -> proc_macro2::TokenStream {
///     unimplemented!()
/// }
/// ```
///
/// # Usage
///
/// ```
/// fn attribute_interesting(
///     _attr: proc_macro2::TokenStream,
///     _structure: synstructure::Structure,
/// ) -> proc_macro2::TokenStream {
///     quote::quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_attribute!([interesting] => attribute_interesting);
/// # };
/// ```
#[macro_export]
macro_rules! decl_attribute {
    ([$attribute:ident] => $(#[$($attrs:tt)*])* $inner:path) => {
        #[proc_macro_attribute]
        $(#[$($attrs)*])*
        pub fn $attribute(
            attr: $crate::macros::TokenStream,
            i: $crate::macros::TokenStream,
        ) -> $crate::macros::TokenStream {
            match $crate::macros::parse::<$crate::macros::DeriveInput>(i) {
                Ok(p) => match $crate::Structure::try_new(&p) {
                    Ok(s) => $crate::MacroResult::into_stream($inner(attr.into(), s)),
                    Err(e) => e.to_compile_error().into(),
                },
                Err(e) => e.to_compile_error().into(),
            }
        }
    };
}

/// Run a test on a custom derive. This macro expands both the original struct
/// and the expansion to ensure that they compile correctly, and confirms that
/// feeding the original struct into the named derive will produce the written
/// output.
///
/// You can add `no_build` to the end of the macro invocation to disable
/// checking that the written code compiles. This is useful in contexts where
/// the procedural macro cannot depend on the crate where it is used during
/// tests.
///
/// # Usage
///
/// ```
/// fn test_derive_example(_s: synstructure::Structure)
///     -> Result<proc_macro2::TokenStream, syn::Error>
/// {
///     Ok(quote::quote! { const YOUR_OUTPUT: &'static str = "here"; })
/// }
///
/// fn main() {
///     synstructure::test_derive!{
///         test_derive_example {
///             struct A;
///         }
///         expands to {
///             const YOUR_OUTPUT: &'static str = "here";
///         }
///     }
/// }
/// ```
#[macro_export]
macro_rules! test_derive {
    ($name:path { $($i:tt)* } expands to { $($o:tt)* }) => {
        {
            #[allow(dead_code)]
            fn ensure_compiles() {
                $($i)*
                $($o)*
            }

            $crate::test_derive!($name { $($i)* } expands to { $($o)* } no_build);
        }
    };

    ($name:path { $($i:tt)* } expands to { $($o:tt)* } no_build) => {
        {
            let i = stringify!( $($i)* );
            let parsed = $crate::macros::parse_str::<$crate::macros::DeriveInput>(i)
                .expect(concat!(
                    "Failed to parse input to `#[derive(",
                    stringify!($name),
                    ")]`",
                ));

            let raw_res = $name($crate::Structure::new(&parsed));
            let res = $crate::MacroResult::into_result(raw_res)
                .expect(concat!(
                    "Procedural macro failed for `#[derive(",
                    stringify!($name),
                    ")]`",
                ));

            let expected = stringify!( $($o)* )
                .parse::<$crate::macros::TokenStream2>()
                .expect("output should be a valid TokenStream");
            let mut expected_toks = $crate::macros::TokenStream2::from(expected);
            if res.to_string() != expected_toks.to_string() {
                panic!("\
test_derive failed:
expected:
```
{}
```

got:
```
{}
```\n",
                    $crate::unpretty_print(&expected_toks),
                    $crate::unpretty_print(&res),
                );
            }
        }
    };
}
<|endoftext|>


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

#[macro_export]
macro_rules! syscall(
    ($nr:ident)
        => ( ::syscall::syscall0(
                ::syscall::nr::$nr) );

    ($nr:ident, $a1:expr)
        => ( ::syscall::syscall1(
                ::syscall::nr::$nr,
                $a1 as uint) );

    ($nr:ident, $a1:expr, $a2:expr)
        => ( ::syscall::syscall2(
                ::syscall::nr::$nr,
                $a1 as uint, $a2 as uint) );

    ($nr:ident, $a1:expr, $a2:expr, $a3:expr)
        => ( ::syscall::syscall3(
                ::syscall::nr::$nr,
                $a1 as uint, $a2 as uint, $a3 as uint) );

    ($nr:ident, $a1:expr, $a2:expr, $a3:expr, $a4:expr)
        => ( ::syscall::syscall4(
                ::syscall::nr::$nr,
                $a1 as uint, $a2 as uint, $a3 as uint,
                $a4 as uint) );

    ($nr:ident, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr)
        => ( ::syscall::syscall5(
                ::syscall::nr::$nr,
                $a1 as uint, $a2 as uint, $a3 as uint,
                $a4 as uint, $a5 as uint) );

    ($nr:ident, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr)
        => ( ::syscall::syscall6(
                ::syscall::nr::$nr,
                $a1 as uint, $a2 as uint, $a3 as uint,
                $a4 as uint, $a5 as uint, $a6 as uint) );
)
<commit_msg>Fix build with rust master<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[macro_export]
macro_rules! syscall {
    ($nr:ident)
        => ( ::syscall::syscall0(
                ::syscall::nr::$nr) );

    ($nr:ident, $a1:expr)
        => ( ::syscall::syscall1(
                ::syscall::nr::$nr,
                $a1 as uint) );

    ($nr:ident, $a1:expr, $a2:expr)
        => ( ::syscall::syscall2(
                ::syscall::nr::$nr,
                $a1 as uint, $a2 as uint) );

    ($nr:ident, $a1:expr, $a2:expr, $a3:expr)
        => ( ::syscall::syscall3(
                ::syscall::nr::$nr,
                $a1 as uint, $a2 as uint, $a3 as uint) );

    ($nr:ident, $a1:expr, $a2:expr, $a3:expr, $a4:expr)
        => ( ::syscall::syscall4(
                ::syscall::nr::$nr,
                $a1 as uint, $a2 as uint, $a3 as uint,
                $a4 as uint) );

    ($nr:ident, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr)
        => ( ::syscall::syscall5(
                ::syscall::nr::$nr,
                $a1 as uint, $a2 as uint, $a3 as uint,
                $a4 as uint, $a5 as uint) );

    ($nr:ident, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr)
        => ( ::syscall::syscall6(
                ::syscall::nr::$nr,
                $a1 as uint, $a2 as uint, $a3 as uint,
                $a4 as uint, $a5 as uint, $a6 as uint) );
}
<|endoftext|>