<commit_before>//! Utilities for graph transformations.

use std::cell::{Ref, RefCell, RefMut};
use std::default::Default;
use super::interface::{Graph, ConcreteGraphMut, Id};
use util::splitvec::SplitVec;

// ----------------------------------------------------------------

/// Target-node specifier for use with `Builder::append_edge`.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Target<I> where I: Id {
    /// Use the specified target node, and ensure that it is in the outputs
    /// list
    Output(I),

    /// Use all current output nodes, creating one if none exist
    AllOutputs,

    /// Use the first available output node if one exists, or create one and
    /// add it to the outputs list
    AutoOutput,

    /// Unconditionally create a new node, and add it to the outputs list
    NewOutput,

    /// Use the specified target node, but do not add it to the outputs list
    Intermediate(I),

    /// Create a new target node, but do not add it to the outputs list
    AutoIntermediate,

    /// Use each input node as the output.
    InputOutput
}

impl<I> Target<I> where I: Id {
    /// Check if the target specifies a node that should be added to the
    /// Builder's outputs list.
    pub fn is_output(&self) -> bool {
        match self {
            &Target::Output(_) |
            &Target::AutoOutput |
            &Target::NewOutput |
            &Target::InputOutput |
            &Target::AllOutputs
                => true,
            &Target::Intermediate(_) |
            &Target::AutoIntermediate
                => false
        }
    }

    /// Resolve the target into a node id, potentially creating a new node
    ///
    /// `auto_output_candidate` is the calling Builder's first output (or None if
    /// no outputs currently exist).
    ///
    /// `f` is called when a new node should be created, and must return that
    /// node's ID.
    pub fn node_id<'a, F>(&self, auto_output_candidate: Option<I>, mut f: F) -> I
        where F: FnMut() -> I
    {
        match self {
            &Target::AutoOutput
                => auto_output_candidate.unwrap_or_else(|| f()),
            &Target::Output(id) |
            &Target::Intermediate(id)
                => id,
            &Target::NewOutput |
            &Target::AutoIntermediate
                => f(),
            &Target::AllOutputs
                => panic!("cannot handle `Target::AllOutputs` variant from `node_id`"),
            &Target::InputOutput
                => panic!("cannot handle `Target::InputOutput` variant from `node_id`")
        }
    }

    /// Fetch the ID contained in an `Output` or `Intermediate` variant.
    pub fn unwrap_id(&self) -> I {
        match self {
            &Target::Output(id) | &Target::Intermediate(id) => id,
            _ => panic!("Attempted to unwrap Target instance without a specific id")
        }
    }
}

// ----------------------------------------------------------------

/// Trait describing bounds on graph-construction functions and closures passed
/// to `Builder`'s methods.
pub trait BuildFn<G, I>: for<'a> Fn(&'a mut Builder<G>, Target<G::NodeId>, I) -> G::NodeId
    where G: Graph
{}

impl<G, I, F> BuildFn<G, I> for F
    where F: for<'a> Fn(&'a mut Builder<G>, Target<G::NodeId>, I) -> G::NodeId,
          G: Graph
{}

/// Closure type used when a new node must be created on a graph
pub trait NodeFn<G, E>: Fn(&mut G, &E) -> G::NodeId
    where G: Graph
{}

impl<G, E, F> NodeFn<G, E> for F
    where F: Fn(&mut G, &E) -> G::NodeId,
          G: Graph
{}

// ----------------------------------------------------------------

/// Handles node and edge addition for each stage of a graph
/// under construction.
#[derive(Clone, Debug)]
pub struct Builder<G>
    where G: ConcreteGraphMut
{
    graph: RefCell<G>,

    /// "out" nodes from the previous stage
    pub inputs: SplitVec<G::NodeId>,

    /// "out" nodes  for the stage under construction
    pub outputs: SplitVec<G::NodeId>,
}

impl<G> Builder<G> where G: ConcreteGraphMut
{
    /// Create an empty `Builder` instance for the given entry node
    pub fn new(g: G, entry: G::NodeId) -> Self {
        Builder{graph: RefCell::new(g),
                inputs: vec![entry].into(),
                outputs: SplitVec::new()}
    }

    /// Consume the Builder object, returning the built graph.
    pub fn finish(self) -> G {
        self.graph.into_inner()
    }

    /// Get a reference to the builder's graph
    pub fn graph(&self) -> Ref<G> {
        self.graph.borrow()
    }

    /// Get a reference to the builder's graph
    pub fn graph_mut(&mut self) -> &mut G {
        self.graph.get_mut()
    }

    /// Fetch a slice over the IDs of nodes that act as inputs for this stage
    pub fn stage_inputs(&self) -> &[G::NodeId] {
        &self.inputs[..]
    }

    /// Fetch a slice over the IDs of nodes that act as outputs for this stage
    pub fn stage_outputs(&self) -> &[G::NodeId] {
        &self.outputs[..]
    }

    /// Run the given function or closure, providing mutable access to the
    /// underlying graph.
    pub fn with_graph_mut<F>(&mut self, f: F)
        where F: FnOnce(&Self, RefMut<G>) {
        f(self, self.graph.borrow_mut());
    }

    /// Append an edge between all inputs for the stage and some target node.
    ///
    ///
    pub fn append_edge<E, F>(&mut self, tgt: Target<G::NodeId>, e: E, f: F) -> G::NodeId
        where F: NodeFn<G, E>,
              (G::NodeId, G::NodeId, E): Into<G::Edge>,
              E: Clone
    {
        match tgt {
            Target::InputOutput
                => {
                    for prev in self.inputs.iter() {
                        self.graph.get_mut().add_edge((*prev, *prev, e.clone()));
                    }
                    *self.inputs.first().unwrap()
                },
            Target::AllOutputs
                => {
                    // If the stage has no outputs, create one.
                    if self.outputs.is_empty() {
                        self.outputs.push(f(self.graph.get_mut(), &e));
                    }

                    for next in self.outputs.iter() {
                        for prev in self.inputs.iter() {
                            self.graph.get_mut().add_edge((*prev, *next, e.clone()));
                        }
                    }
                    *self.outputs.first().unwrap()
                },
            _ => {
                let next = tgt.node_id(self.outputs.first().cloned(), || f(self.graph.get_mut(), &e));
                if tgt.is_output() {
                    self.mark_output(next);
                }

                // For ALL inputs from the previous stage, add an edge from that input
                // to the specified output.
                for prev in self.inputs.iter() {
                    self.graph.get_mut().add_edge((*prev, next, e.clone()));
                }
                next
            }
        }
    }

    /// Add an edge from a *specific* source node to some target node
    pub fn append_edge_from<E, F>(&mut self,
                                  source: G::NodeId,
                                  target: Target<G::NodeId>,
                                  e: E,
                                  f: F) -> G::NodeId
        where F: NodeFn<G, E>,
              (G::NodeId, G::NodeId, E): Into<G::Edge>,
              E: Clone
    {
        let next = target.node_id(self.outputs.first().cloned(), || f(self.graph.get_mut(), &e));
        if target.is_output() {
            self.mark_output(next);
        }
        self.graph.get_mut().add_edge((source, next, e));
        next
    }

    /// Ensure that a particular node id is included in the current
    /// stage's outputs.
    pub fn mark_output(&mut self, id: G::NodeId) -> G::NodeId {
        if ! self.outputs.contains(&id) {
            self.outputs.push(id);
        }
        id
    }

    /// Mark all stage inputs as outputs.
    pub fn mark_inputs_as_outputs(&mut self) {
        for id in self.inputs.iter_mut() {
            self.outputs.push(*id)
        }
    }

    /// Build _within_ the current stage, preserving the list of stage inputs.
    pub fn recurse<F, I>(&mut self, next: Target<G::NodeId>, input: I, build: F) -> G::NodeId
        where F: for<'a> FnOnce(&'a mut Builder<G>, Target<G::NodeId>, I) -> G::NodeId
    {
        self.inputs.dedup();

        self.inputs.push_and_copy_state();

        let o = build(self, next, input);

        self.inputs.pop_state();

        o
    }

    /// Chain together the subgraphs built from the elements produced by
    /// an iterator.
    ///
    /// If the given target specifies a node, that node will be used as the
    /// terminal end of the subgraph chain in addition to being marked as
    /// a stage output.
    ///
    /// This method will **panic** if called with an empty iterator.
    pub fn chain<F, I, R>(&mut self, target: Target<G::NodeId>, input: R, build: F) -> G::NodeId
        where R: IntoIterator<Item=I>,
              F: for<'a> Fn(&'a mut Builder<G>, Target<G::NodeId>, I) -> G::NodeId
    {
        let mut o = None;
        let mut iter = input.into_iter().peekable();
        let build = &build;

        self.inputs.push_and_copy_state();
        self.outputs.push_state();
        while let Some(elt) = iter.next() {
            if iter.peek().is_some() {
                // If there's another element after this one, create a pristine
                // node to connect it to the one we're about to build
                o = Some(build(self, Target::NewOutput, elt));
                self.advance();
            } else {
                // Last element; connect to the specified target.
                match target {
                    Target::InputOutput
                        => {
                            // When `InputOutput` was specified, we need to
                            // copy the *chain* inputs -- i.e., the inputs to
                            // the _first_ stage in the chain -- to the current
                            // outputs list.
                            self.outputs.truncate(0);
                            self.outputs.extend_from_slice(self.inputs.prev_state().unwrap());
                            o = Some(build(self, Target::AllOutputs, elt));
                            self.outputs.pop_state();
                            self.outputs.extend_from_slice(self.inputs.prev_state().unwrap());
                        },
                    _ => {
                        self.outputs.pop_state();
                        o = Some(build(self, target, elt));
                    }
                }
            }
        }
        self.inputs.pop_state();
        o.unwrap()
    }

    /// Build subgraphs from the elements of an iterator between the current
    /// stage's inputs and some specified output.
    pub fn branch<F, I, R>(&mut self, target: Target<G::NodeId>, input: R, build: F) -> G::NodeId
        where R: IntoIterator<Item=I>,
              F: for<'a> Fn(&'a mut Builder<G>, Target<G::NodeId>, I) -> G::NodeId//BuildFn<G, I>
    {
        let build = &build;
        let mut target = target;
        for elt in input {
            target = Target::Output(self.recurse(target, elt.into(), build));
        }
        target.unwrap_id()
    }

    /// Finalize the current stage.
    ///
    /// This overwrites the current list of input nodes with the list of output
    /// nodes, and truncates the output-node list.
    pub fn advance(&mut self) {
        if self.outputs.len() > 0 {
            self.inputs.truncate(0);
            self.inputs.extend_from_slice(&self.outputs[..]);
            self.outputs.truncate(0);
        }
    }
}

// ----------------------------------------------------------------

/// Graph-building interface.
pub trait Build<G: ConcreteGraphMut> {
    /// Type from which the graph is built.
    type Input;

    /// Create the entry node for the given input, returning its ID.
    fn entry_node(g: &mut G, input: &Self::Input) -> G::NodeId;

    /// Create the target node for the given edge data, returning the ID of the
    /// new node.
    fn target_node<E>(g: &mut G, e: &E) -> G::NodeId
        where (G::NodeId, G::NodeId, E): Into<G::Edge>;

    /// Perform any finalization on the builder or the built graph.
    #[inline]
    fn finish(_: &mut Builder<G>) {
    }

    /// Recursively build the graph for the given input data.
    ///
    /// @param b Builder instance to use for building the graph
    ///
    /// @param next Output to which the stage built from this input data should
    /// connect
    ///
    /// @param input
    fn build_recursive(b: &mut Builder<G>,
                       next: Target<G::NodeId>,
                       input: Self::Input) -> G::NodeId;

    // /// Create a subgraph describing the given input, and return its
    // /// entry and exit node IDs.
    // ///
    // /// @return Tuple containing the stand-alone graph's entry- and
    // /// exit-node IDs.
    // fn build_subgraph<'g>(ep: &mut Builder<'g, G>,
    //                       input: Self::Input) -> (G::NodeId,
    //                                               G::NodeId) {
    //     Self::build_recursive(ep, input);
    // }

    /// Convert the given input into a graph.
    ///
    /// Returns the resulting graph and the entry node.
    fn build(input: Self::Input) -> (G, G::NodeId)
        where G: Default {
        let mut g = G::new();
        let entry = Self::entry_node(&mut g, &input);

        let mut builder = Builder::new(g, entry);
        Self::build_recursive(&mut builder, Target::AutoOutput, input);
        Self::finish(&mut builder);
        (builder.finish(), entry)
    }
}
<commit_msg>util/graph/transform: more `Graph` => `ConcreteGraphMut` bounds changes<commit_after>//! Utilities for graph transformations.

use std::cell::{Ref, RefCell, RefMut};
use std::default::Default;
use super::interface::{Graph, ConcreteGraphMut, Id};
use util::splitvec::SplitVec;

// ----------------------------------------------------------------

/// Target-node specifier for use with `Builder::append_edge`.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Target<I> where I: Id {
    /// Use the specified target node, and ensure that it is in the outputs
    /// list
    Output(I),

    /// Use all current output nodes, creating one if none exist
    AllOutputs,

    /// Use the first available output node if one exists, or create one and
    /// add it to the outputs list
    AutoOutput,

    /// Unconditionally create a new node, and add it to the outputs list
    NewOutput,

    /// Use the specified target node, but do not add it to the outputs list
    Intermediate(I),

    /// Create a new target node, but do not add it to the outputs list
    AutoIntermediate,

    /// Use each input node as the output.
    InputOutput
}

impl<I> Target<I> where I: Id {
    /// Check if the target specifies a node that should be added to the
    /// Builder's outputs list.
    pub fn is_output(&self) -> bool {
        match self {
            &Target::Output(_) |
            &Target::AutoOutput |
            &Target::NewOutput |
            &Target::InputOutput |
            &Target::AllOutputs
                => true,
            &Target::Intermediate(_) |
            &Target::AutoIntermediate
                => false
        }
    }

    /// Resolve the target into a node id, potentially creating a new node
    ///
    /// `auto_output_candidate` is the calling Builder's first output (or None if
    /// no outputs currently exist).
    ///
    /// `f` is called when a new node should be created, and must return that
    /// node's ID.
    pub fn node_id<'a, F>(&self, auto_output_candidate: Option<I>, mut f: F) -> I
        where F: FnMut() -> I
    {
        match self {
            &Target::AutoOutput
                => auto_output_candidate.unwrap_or_else(|| f()),
            &Target::Output(id) |
            &Target::Intermediate(id)
                => id,
            &Target::NewOutput |
            &Target::AutoIntermediate
                => f(),
            &Target::AllOutputs
                => panic!("cannot handle `Target::AllOutputs` variant from `node_id`"),
            &Target::InputOutput
                => panic!("cannot handle `Target::InputOutput` variant from `node_id`")
        }
    }

    /// Fetch the ID contained in an `Output` or `Intermediate` variant.
    pub fn unwrap_id(&self) -> I {
        match self {
            &Target::Output(id) | &Target::Intermediate(id) => id,
            _ => panic!("Attempted to unwrap Target instance without a specific id")
        }
    }
}

// ----------------------------------------------------------------

/// Trait describing bounds on graph-construction functions and closures passed
/// to `Builder`'s methods.
pub trait BuildFn<G, I>: for<'a> Fn(&'a mut Builder<G>, Target<G::NodeId>, I) -> G::NodeId
    where G: ConcreteGraphMut
{}

impl<G, I, F> BuildFn<G, I> for F
    where F: for<'a> Fn(&'a mut Builder<G>, Target<G::NodeId>, I) -> G::NodeId,
          G: ConcreteGraphMut
{}

/// Closure type used when a new node must be created on a graph
pub trait NodeFn<G, E>: Fn(&mut G, &E) -> G::NodeId
    where G: ConcreteGraphMut
{}

impl<G, E, F> NodeFn<G, E> for F
    where F: Fn(&mut G, &E) -> G::NodeId,
          G: ConcreteGraphMut
{}

// ----------------------------------------------------------------

/// Handles node and edge addition for each stage of a graph
/// under construction.
#[derive(Clone, Debug)]
pub struct Builder<G>
    where G: ConcreteGraphMut
{
    graph: RefCell<G>,

    /// "out" nodes from the previous stage
    pub inputs: SplitVec<G::NodeId>,

    /// "out" nodes  for the stage under construction
    pub outputs: SplitVec<G::NodeId>,
}

impl<G> Builder<G> where G: ConcreteGraphMut
{
    /// Create an empty `Builder` instance for the given entry node
    pub fn new(g: G, entry: G::NodeId) -> Self {
        Builder{graph: RefCell::new(g),
                inputs: vec![entry].into(),
                outputs: SplitVec::new()}
    }

    /// Consume the Builder object, returning the built graph.
    pub fn finish(self) -> G {
        self.graph.into_inner()
    }

    /// Get a reference to the builder's graph
    pub fn graph(&self) -> Ref<G> {
        self.graph.borrow()
    }

    /// Get a reference to the builder's graph
    pub fn graph_mut(&mut self) -> &mut G {
        self.graph.get_mut()
    }

    /// Fetch a slice over the IDs of nodes that act as inputs for this stage
    pub fn stage_inputs(&self) -> &[G::NodeId] {
        &self.inputs[..]
    }

    /// Fetch a slice over the IDs of nodes that act as outputs for this stage
    pub fn stage_outputs(&self) -> &[G::NodeId] {
        &self.outputs[..]
    }

    /// Run the given function or closure, providing mutable access to the
    /// underlying graph.
    pub fn with_graph_mut<F>(&mut self, f: F)
        where F: FnOnce(&Self, RefMut<G>) {
        f(self, self.graph.borrow_mut());
    }

    /// Append an edge between all inputs for the stage and some target node.
    ///
    ///
    pub fn append_edge<E, F>(&mut self, tgt: Target<G::NodeId>, e: E, f: F) -> G::NodeId
        where F: NodeFn<G, E>,
              (G::NodeId, G::NodeId, E): Into<G::Edge>,
              E: Clone
    {
        match tgt {
            Target::InputOutput
                => {
                    for prev in self.inputs.iter() {
                        self.graph.get_mut().add_edge((*prev, *prev, e.clone()));
                    }
                    *self.inputs.first().unwrap()
                },
            Target::AllOutputs
                => {
                    // If the stage has no outputs, create one.
                    if self.outputs.is_empty() {
                        self.outputs.push(f(self.graph.get_mut(), &e));
                    }

                    for next in self.outputs.iter() {
                        for prev in self.inputs.iter() {
                            self.graph.get_mut().add_edge((*prev, *next, e.clone()));
                        }
                    }
                    *self.outputs.first().unwrap()
                },
            _ => {
                let next = tgt.node_id(self.outputs.first().cloned(), || f(self.graph.get_mut(), &e));
                if tgt.is_output() {
                    self.mark_output(next);
                }

                // For ALL inputs from the previous stage, add an edge from that input
                // to the specified output.
                for prev in self.inputs.iter() {
                    self.graph.get_mut().add_edge((*prev, next, e.clone()));
                }
                next
            }
        }
    }

    /// Add an edge from a *specific* source node to some target node
    pub fn append_edge_from<E, F>(&mut self,
                                  source: G::NodeId,
                                  target: Target<G::NodeId>,
                                  e: E,
                                  f: F) -> G::NodeId
        where F: NodeFn<G, E>,
              (G::NodeId, G::NodeId, E): Into<G::Edge>,
              E: Clone
    {
        let next = target.node_id(self.outputs.first().cloned(), || f(self.graph.get_mut(), &e));
        if target.is_output() {
            self.mark_output(next);
        }
        self.graph.get_mut().add_edge((source, next, e));
        next
    }

    /// Ensure that a particular node id is included in the current
    /// stage's outputs.
    pub fn mark_output(&mut self, id: G::NodeId) -> G::NodeId {
        if ! self.outputs.contains(&id) {
            self.outputs.push(id);
        }
        id
    }

    /// Mark all stage inputs as outputs.
    pub fn mark_inputs_as_outputs(&mut self) {
        for id in self.inputs.iter_mut() {
            self.outputs.push(*id)
        }
    }

    /// Build _within_ the current stage, preserving the list of stage inputs.
    pub fn recurse<F, I>(&mut self, next: Target<G::NodeId>, input: I, build: F) -> G::NodeId
        where F: for<'a> FnOnce(&'a mut Builder<G>, Target<G::NodeId>, I) -> G::NodeId
    {
        self.inputs.dedup();

        self.inputs.push_and_copy_state();

        let o = build(self, next, input);

        self.inputs.pop_state();

        o
    }

    /// Chain together the subgraphs built from the elements produced by
    /// an iterator.
    ///
    /// If the given target specifies a node, that node will be used as the
    /// terminal end of the subgraph chain in addition to being marked as
    /// a stage output.
    ///
    /// This method will **panic** if called with an empty iterator.
    pub fn chain<F, I, R>(&mut self, target: Target<G::NodeId>, input: R, build: F) -> G::NodeId
        where R: IntoIterator<Item=I>,
              F: for<'a> Fn(&'a mut Builder<G>, Target<G::NodeId>, I) -> G::NodeId
    {
        let mut o = None;
        let mut iter = input.into_iter().peekable();
        let build = &build;

        self.inputs.push_and_copy_state();
        self.outputs.push_state();
        while let Some(elt) = iter.next() {
            if iter.peek().is_some() {
                // If there's another element after this one, create a pristine
                // node to connect it to the one we're about to build
                o = Some(build(self, Target::NewOutput, elt));
                self.advance();
            } else {
                // Last element; connect to the specified target.
                match target {
                    Target::InputOutput
                        => {
                            // When `InputOutput` was specified, we need to
                            // copy the *chain* inputs -- i.e., the inputs to
                            // the _first_ stage in the chain -- to the current
                            // outputs list.
                            self.outputs.truncate(0);
                            self.outputs.extend_from_slice(self.inputs.prev_state().unwrap());
                            o = Some(build(self, Target::AllOutputs, elt));
                            self.outputs.pop_state();
                            self.outputs.extend_from_slice(self.inputs.prev_state().unwrap());
                        },
                    _ => {
                        self.outputs.pop_state();
                        o = Some(build(self, target, elt));
                    }
                }
            }
        }
        self.inputs.pop_state();
        o.unwrap()
    }

    /// Build subgraphs from the elements of an iterator between the current
    /// stage's inputs and some specified output.
    pub fn branch<F, I, R>(&mut self, target: Target<G::NodeId>, input: R, build: F) -> G::NodeId
        where R: IntoIterator<Item=I>,
              F: for<'a> Fn(&'a mut Builder<G>, Target<G::NodeId>, I) -> G::NodeId//BuildFn<G, I>
    {
        let build = &build;
        let mut target = target;
        for elt in input {
            target = Target::Output(self.recurse(target, elt.into(), build));
        }
        target.unwrap_id()
    }

    /// Finalize the current stage.
    ///
    /// This overwrites the current list of input nodes with the list of output
    /// nodes, and truncates the output-node list.
    pub fn advance(&mut self) {
        if self.outputs.len() > 0 {
            self.inputs.truncate(0);
            self.inputs.extend_from_slice(&self.outputs[..]);
            self.outputs.truncate(0);
        }
    }
}

// ----------------------------------------------------------------

/// Graph-building interface.
pub trait Build<G: ConcreteGraphMut> {
    /// Type from which the graph is built.
    type Input;

    /// Create the entry node for the given input, returning its ID.
    fn entry_node(g: &mut G, input: &Self::Input) -> G::NodeId;

    /// Create the target node for the given edge data, returning the ID of the
    /// new node.
    fn target_node<E>(g: &mut G, e: &E) -> G::NodeId
        where (G::NodeId, G::NodeId, E): Into<G::Edge>;

    /// Perform any finalization on the builder or the built graph.
    #[inline]
    fn finish(_: &mut Builder<G>) {
    }

    /// Recursively build the graph for the given input data.
    ///
    /// @param b Builder instance to use for building the graph
    ///
    /// @param next Output to which the stage built from this input data should
    /// connect
    ///
    /// @param input
    fn build_recursive(b: &mut Builder<G>,
                       next: Target<G::NodeId>,
                       input: Self::Input) -> G::NodeId;

    // /// Create a subgraph describing the given input, and return its
    // /// entry and exit node IDs.
    // ///
    // /// @return Tuple containing the stand-alone graph's entry- and
    // /// exit-node IDs.
    // fn build_subgraph<'g>(ep: &mut Builder<'g, G>,
    //                       input: Self::Input) -> (G::NodeId,
    //                                               G::NodeId) {
    //     Self::build_recursive(ep, input);
    // }

    /// Convert the given input into a graph.
    ///
    /// Returns the resulting graph and the entry node.
    fn build(input: Self::Input) -> (G, G::NodeId)
        where G: Default {
        let mut g = G::new();
        let entry = Self::entry_node(&mut g, &input);

        let mut builder = Builder::new(g, entry);
        Self::build_recursive(&mut builder, Target::AutoOutput, input);
        Self::finish(&mut builder);
        (builder.finish(), entry)
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate httpbis;
extern crate futures;
extern crate bytes;

use httpbis::*;

use futures::stream;
use futures::stream::Stream;
use futures::future::Future;

use bytes::Bytes;

use test::Bencher;

struct Megabyte;

impl Service for Megabyte {
    fn start_request(&self, _headers: Headers, _req: HttpPartStream) -> Response {
        Response::headers_and_bytes_stream(
            Headers::ok_200(),
            stream::iter((0..1024).map(|i| Ok(Bytes::from(vec![(i % 0xff) as u8; 1024])))))
    }
}

#[bench]
fn bench(b: &mut Bencher) {
    b.iter(|| {
        let server = Server::new_plain_single_thread(
            "[::1]:0",
            Default::default(),
            Megabyte)
                .expect("server");

        let client = Client::new_plain(
            "::1",
            server.local_addr().port(),
            Default::default())
                .expect("client");

        let (header, body) = client.start_get("/any", "localhost").0.wait().expect("headers");
        assert_eq!(200, header.status());

        let mut s = 0;
        for p in body.check_only_data().wait() {
            s += p.expect("body").len();
        }

        assert_eq!(1024 * 1024, s);
    })
}
<commit_msg>Fix bench compilation<commit_after>#![feature(test)]

use std::sync::Arc;

extern crate test;
extern crate httpbis;
extern crate futures;
extern crate bytes;

use httpbis::*;

use futures::stream;
use futures::stream::Stream;
use futures::future::Future;

use bytes::Bytes;

use test::Bencher;

struct Megabyte;

impl Service for Megabyte {
    fn start_request(&self, _headers: Headers, _req: HttpPartStream) -> Response {
        Response::headers_and_bytes_stream(
            Headers::ok_200(),
            stream::iter((0..1024).map(|i| Ok(Bytes::from(vec![(i % 0xff) as u8; 1024])))))
    }
}

#[bench]
fn bench(b: &mut Bencher) {
    b.iter(|| {
        let mut server = ServerBuilder::new_plain();
        server.set_port(0);
        server.service.set_service("/", Arc::new(Megabyte));
        let server = server.build().expect("server");

        let client = Client::new_plain(
            "::1",
            server.local_addr().port(),
            Default::default())
                .expect("client");

        let (header, body) = client.start_get("/any", "localhost").0.wait().expect("headers");
        assert_eq!(200, header.status());

        let mut s = 0;
        for p in body.check_only_data().wait() {
            s += p.expect("body").len();
        }

        assert_eq!(1024 * 1024, s);
    })
}
<|endoftext|>


<commit_before>#[cfg(not(lib_build))]
#[macro_use]
extern crate log;

macro_rules! all_log_macros {
    ($($arg:tt)*) => ({
        trace!($($arg)*);
        debug!($($arg)*);
        info!($($arg)*);
        warn!($($arg)*);
        error!($($arg)*);
    });
}

#[test]
fn no_args() {
    for lvl in log::Level::iter() {
        log!(lvl, "hello");
        log!(lvl, "hello",);

        log!(target: "my_target", lvl, "hello");
        log!(target: "my_target", lvl, "hello",);

        log!(lvl; "hello");
        log!(lvl; "hello",);

        log!(target = "my_target", lvl; "hello");
        log!(target = "my_target", lvl; "hello",);
    }

    all_log_macros!("hello");
    all_log_macros!("hello",);

    all_log_macros!(target = "my_target"; "hello");
    all_log_macros!(target = "my_target"; "hello",);

    all_log_macros!(target: "my_target", "hello");
    all_log_macros!(target: "my_target", "hello",);
}

#[test]
fn anonymous_args() {
    for lvl in log::Level::iter() {
        log!(lvl, "hello {}", "world");
        log!(lvl, "hello {}", "world",);

        log!(target: "my_target", lvl, "hello {}", "world");
        log!(target: "my_target", lvl, "hello {}", "world",);

        log!(lvl; "hello {}", "world");
        log!(lvl; "hello {}", "world",);

        log!(target = "my_target", lvl; "hello {}", "world");
        log!(target = "my_target", lvl; "hello {}", "world",);
    }

    all_log_macros!("hello {}", "world");
    all_log_macros!("hello {}", "world",);

    all_log_macros!(target = "my_target"; "hello {}", "world");
    all_log_macros!(target = "my_target"; "hello {}", "world",);

    all_log_macros!(target: "my_target", "hello {}", "world");
    all_log_macros!(target: "my_target", "hello {}", "world",);
}

#[test]
fn named_args() {
    for lvl in log::Level::iter() {
        log!(lvl, "hello {world}", world = "world");
        log!(lvl, "hello {world}", world = "world",);

        log!(target: "my_target", lvl, "hello {world}", world = "world");
        log!(target: "my_target", lvl, "hello {world}", world = "world",);

        log!(lvl; "hello {world}", world = "world");
        log!(lvl; "hello {world}", world = "world",);

        log!(target = "my_target", lvl; "hello {world}", world = "world");
        log!(target = "my_target", lvl; "hello {world}", world = "world",);
    }

    all_log_macros!("hello {world}", world = "world");
    all_log_macros!("hello {world}", world = "world",);

    all_log_macros!(target = "my_target"; "hello {world}", world = "world");
    all_log_macros!(target = "my_target"; "hello {world}", world = "world",);

    all_log_macros!(target: "my_target", "hello {world}", world = "world");
    all_log_macros!(target: "my_target", "hello {world}", world = "world",);
}

#[test]
fn enabled() {
    for lvl in log::Level::iter() {
        let _enabled = if log_enabled!(target: "my_target", lvl) {
            true
        } else {
            false
        };

        let _enabled = if log_enabled!(target = "my_target", lvl) {
            true
        } else {
            false
        };
    }
}

#[test]
fn expr() {
    for lvl in log::Level::iter() {
        let _ = log!(lvl; "hello");
    }
}

#[test]
#[cfg(feature = "kv_unstable")]
fn kv_no_args() {
    for lvl in log::Level::iter() {
        log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello");

        log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello");
    }

    all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello");
    all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello");
}

#[test]
#[cfg(feature = "kv_unstable")]
fn kv_anonymous_args() {
    for lvl in log::Level::iter() {
        log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world");

        log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world");
    }

    all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world");
    all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world");
}

#[test]
#[cfg(feature = "kv_unstable")]
fn kv_named_args() {
    for lvl in log::Level::iter() {
        log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world");

        log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world");
    }

    all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world");
    all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world");
}

#[test]
#[cfg(feature = "kv_unstable")]
fn kv_expr_context() {
    match "chashu" {
        cat_1 => {
            info!(target = "target"; cat_1 = cat_1, cat_2 = "nori"; "hello {}", "cats")
        }
    };
}

#[test]
#[cfg(feature = "kv_unstable")]
fn kv_shadow_target() {
    all_log_macros!(target = "kv_target"; "hello {}", "world");
    all_log_macros!(target = "kv_target", cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world");
}

#[rustversion::since(1.58)]
mod implicit_args {
    use super::*;

    #[test]
    fn implicit_named_args() {
        let world = "world";

        for lvl in log::Level::iter() {
            log!(lvl, "hello {world}");
            log!(lvl, "hello {world}",);

            log!(target: "my_target", lvl, "hello {world}");
            log!(target: "my_target", lvl, "hello {world}",);

            log!(lvl; "hello {world}");
            log!(lvl; "hello {world}",);

            log!(target = "my_target", lvl; "hello {world}");
            log!(target = "my_target", lvl; "hello {world}",);
        }

        all_log_macros!("hello {world}");
        all_log_macros!("hello {world}",);

        all_log_macros!(target = "my_target"; "hello {world}");
        all_log_macros!(target = "my_target"; "hello {world}",);

        all_log_macros!(target: "my_target", "hello {world}");
        all_log_macros!(target: "my_target", "hello {world}",);
    }

    #[test]
    #[cfg(feature = "kv_unstable")]
    fn kv_implicit_named_args() {
        let world = "world";

        for lvl in log::Level::iter() {
            log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}");

            log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}");
        }

        all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello {world}");
        all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello {world}");
    }
}
<commit_msg>add a different prop type to macro tests<commit_after>#[cfg(not(lib_build))]
#[macro_use]
extern crate log;

macro_rules! all_log_macros {
    ($($arg:tt)*) => ({
        trace!($($arg)*);
        debug!($($arg)*);
        info!($($arg)*);
        warn!($($arg)*);
        error!($($arg)*);
    });
}

#[test]
fn no_args() {
    for lvl in log::Level::iter() {
        log!(lvl, "hello");
        log!(lvl, "hello",);

        log!(target: "my_target", lvl, "hello");
        log!(target: "my_target", lvl, "hello",);

        log!(lvl; "hello");
        log!(lvl; "hello",);

        log!(target = "my_target", lvl; "hello");
        log!(target = "my_target", lvl; "hello",);
    }

    all_log_macros!("hello");
    all_log_macros!("hello",);

    all_log_macros!(target = "my_target"; "hello");
    all_log_macros!(target = "my_target"; "hello",);

    all_log_macros!(target: "my_target", "hello");
    all_log_macros!(target: "my_target", "hello",);
}

#[test]
fn anonymous_args() {
    for lvl in log::Level::iter() {
        log!(lvl, "hello {}", "world");
        log!(lvl, "hello {}", "world",);

        log!(target: "my_target", lvl, "hello {}", "world");
        log!(target: "my_target", lvl, "hello {}", "world",);

        log!(lvl; "hello {}", "world");
        log!(lvl; "hello {}", "world",);

        log!(target = "my_target", lvl; "hello {}", "world");
        log!(target = "my_target", lvl; "hello {}", "world",);
    }

    all_log_macros!("hello {}", "world");
    all_log_macros!("hello {}", "world",);

    all_log_macros!(target = "my_target"; "hello {}", "world");
    all_log_macros!(target = "my_target"; "hello {}", "world",);

    all_log_macros!(target: "my_target", "hello {}", "world");
    all_log_macros!(target: "my_target", "hello {}", "world",);
}

#[test]
fn named_args() {
    for lvl in log::Level::iter() {
        log!(lvl, "hello {world}", world = "world");
        log!(lvl, "hello {world}", world = "world",);

        log!(target: "my_target", lvl, "hello {world}", world = "world");
        log!(target: "my_target", lvl, "hello {world}", world = "world",);

        log!(lvl; "hello {world}", world = "world");
        log!(lvl; "hello {world}", world = "world",);

        log!(target = "my_target", lvl; "hello {world}", world = "world");
        log!(target = "my_target", lvl; "hello {world}", world = "world",);
    }

    all_log_macros!("hello {world}", world = "world");
    all_log_macros!("hello {world}", world = "world",);

    all_log_macros!(target = "my_target"; "hello {world}", world = "world");
    all_log_macros!(target = "my_target"; "hello {world}", world = "world",);

    all_log_macros!(target: "my_target", "hello {world}", world = "world");
    all_log_macros!(target: "my_target", "hello {world}", world = "world",);
}

#[test]
fn enabled() {
    for lvl in log::Level::iter() {
        let _enabled = if log_enabled!(target: "my_target", lvl) {
            true
        } else {
            false
        };

        let _enabled = if log_enabled!(target = "my_target", lvl) {
            true
        } else {
            false
        };
    }
}

#[test]
fn expr() {
    for lvl in log::Level::iter() {
        let _ = log!(lvl; "hello");
    }
}

#[test]
#[cfg(feature = "kv_unstable")]
fn kv_no_args() {
    for lvl in log::Level::iter() {
        log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello");

        log!(lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello");
    }

    all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello");
    all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello");
}

#[test]
#[cfg(feature = "kv_unstable")]
fn kv_anonymous_args() {
    for lvl in log::Level::iter() {
        log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world");

        log!(lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world");
    }

    all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world");
    all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world");
}

#[test]
#[cfg(feature = "kv_unstable")]
fn kv_named_args() {
    for lvl in log::Level::iter() {
        log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world");

        log!(lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world");
    }

    all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world");
    all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world");
}

#[test]
#[cfg(feature = "kv_unstable")]
fn kv_expr_context() {
    match "chashu" {
        cat_1 => {
            info!(target = "target"; cat_1 = cat_1, cat_2 = "nori"; "hello {}", "cats")
        }
    };
}

#[test]
#[cfg(feature = "kv_unstable")]
fn kv_shadow_target() {
    all_log_macros!(target = "kv_target"; "hello {}", "world");
    all_log_macros!(target = "kv_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world");
}

#[rustversion::since(1.58)]
mod implicit_args {
    use super::*;

    #[test]
    fn implicit_named_args() {
        let world = "world";

        for lvl in log::Level::iter() {
            log!(lvl, "hello {world}");
            log!(lvl, "hello {world}",);

            log!(target: "my_target", lvl, "hello {world}");
            log!(target: "my_target", lvl, "hello {world}",);

            log!(lvl; "hello {world}");
            log!(lvl; "hello {world}",);

            log!(target = "my_target", lvl; "hello {world}");
            log!(target = "my_target", lvl; "hello {world}",);
        }

        all_log_macros!("hello {world}");
        all_log_macros!("hello {world}",);

        all_log_macros!(target = "my_target"; "hello {world}");
        all_log_macros!(target = "my_target"; "hello {world}",);

        all_log_macros!(target: "my_target", "hello {world}");
        all_log_macros!(target: "my_target", "hello {world}",);
    }

    #[test]
    #[cfg(feature = "kv_unstable")]
    fn kv_implicit_named_args() {
        let world = "world";

        for lvl in log::Level::iter() {
            log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}");

            log!(lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}");
        }

        all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}");
        all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}");
    }
}
<|endoftext|>


<commit_before>//! Utility macros.

#[allow(unused)]
macro_rules! constify_imm8 {
    ($imm8:expr, $expand:ident) => {
        #[allow(overflowing_literals)]
        match ($imm8) & 0b1111_1111 {
            0 => $expand!(0),
            1 => $expand!(1),
            2 => $expand!(2),
            3 => $expand!(3),
            4 => $expand!(4),
            5 => $expand!(5),
            6 => $expand!(6),
            7 => $expand!(7),
            8 => $expand!(8),
            9 => $expand!(9),
            10 => $expand!(10),
            11 => $expand!(11),
            12 => $expand!(12),
            13 => $expand!(13),
            14 => $expand!(14),
            15 => $expand!(15),
            16 => $expand!(16),
            17 => $expand!(17),
            18 => $expand!(18),
            19 => $expand!(19),
            20 => $expand!(20),
            21 => $expand!(21),
            22 => $expand!(22),
            23 => $expand!(23),
            24 => $expand!(24),
            25 => $expand!(25),
            26 => $expand!(26),
            27 => $expand!(27),
            28 => $expand!(28),
            29 => $expand!(29),
            30 => $expand!(30),
            31 => $expand!(31),
            32 => $expand!(32),
            33 => $expand!(33),
            34 => $expand!(34),
            35 => $expand!(35),
            36 => $expand!(36),
            37 => $expand!(37),
            38 => $expand!(38),
            39 => $expand!(39),
            40 => $expand!(40),
            41 => $expand!(41),
            42 => $expand!(42),
            43 => $expand!(43),
            44 => $expand!(44),
            45 => $expand!(45),
            46 => $expand!(46),
            47 => $expand!(47),
            48 => $expand!(48),
            49 => $expand!(49),
            50 => $expand!(50),
            51 => $expand!(51),
            52 => $expand!(52),
            53 => $expand!(53),
            54 => $expand!(54),
            55 => $expand!(55),
            56 => $expand!(56),
            57 => $expand!(57),
            58 => $expand!(58),
            59 => $expand!(59),
            60 => $expand!(60),
            61 => $expand!(61),
            62 => $expand!(62),
            63 => $expand!(63),
            64 => $expand!(64),
            65 => $expand!(65),
            66 => $expand!(66),
            67 => $expand!(67),
            68 => $expand!(68),
            69 => $expand!(69),
            70 => $expand!(70),
            71 => $expand!(71),
            72 => $expand!(72),
            73 => $expand!(73),
            74 => $expand!(74),
            75 => $expand!(75),
            76 => $expand!(76),
            77 => $expand!(77),
            78 => $expand!(78),
            79 => $expand!(79),
            80 => $expand!(80),
            81 => $expand!(81),
            82 => $expand!(82),
            83 => $expand!(83),
            84 => $expand!(84),
            85 => $expand!(85),
            86 => $expand!(86),
            87 => $expand!(87),
            88 => $expand!(88),
            89 => $expand!(89),
            90 => $expand!(90),
            91 => $expand!(91),
            92 => $expand!(92),
            93 => $expand!(93),
            94 => $expand!(94),
            95 => $expand!(95),
            96 => $expand!(96),
            97 => $expand!(97),
            98 => $expand!(98),
            99 => $expand!(99),
            100 => $expand!(100),
            101 => $expand!(101),
            102 => $expand!(102),
            103 => $expand!(103),
            104 => $expand!(104),
            105 => $expand!(105),
            106 => $expand!(106),
            107 => $expand!(107),
            108 => $expand!(108),
            109 => $expand!(109),
            110 => $expand!(110),
            111 => $expand!(111),
            112 => $expand!(112),
            113 => $expand!(113),
            114 => $expand!(114),
            115 => $expand!(115),
            116 => $expand!(116),
            117 => $expand!(117),
            118 => $expand!(118),
            119 => $expand!(119),
            120 => $expand!(120),
            121 => $expand!(121),
            122 => $expand!(122),
            123 => $expand!(123),
            124 => $expand!(124),
            125 => $expand!(125),
            126 => $expand!(126),
            127 => $expand!(127),
            128 => $expand!(128),
            129 => $expand!(129),
            130 => $expand!(130),
            131 => $expand!(131),
            132 => $expand!(132),
            133 => $expand!(133),
            134 => $expand!(134),
            135 => $expand!(135),
            136 => $expand!(136),
            137 => $expand!(137),
            138 => $expand!(138),
            139 => $expand!(139),
            140 => $expand!(140),
            141 => $expand!(141),
            142 => $expand!(142),
            143 => $expand!(143),
            144 => $expand!(144),
            145 => $expand!(145),
            146 => $expand!(146),
            147 => $expand!(147),
            148 => $expand!(148),
            149 => $expand!(149),
            150 => $expand!(150),
            151 => $expand!(151),
            152 => $expand!(152),
            153 => $expand!(153),
            154 => $expand!(154),
            155 => $expand!(155),
            156 => $expand!(156),
            157 => $expand!(157),
            158 => $expand!(158),
            159 => $expand!(159),
            160 => $expand!(160),
            161 => $expand!(161),
            162 => $expand!(162),
            163 => $expand!(163),
            164 => $expand!(164),
            165 => $expand!(165),
            166 => $expand!(166),
            167 => $expand!(167),
            168 => $expand!(168),
            169 => $expand!(169),
            170 => $expand!(170),
            171 => $expand!(171),
            172 => $expand!(172),
            173 => $expand!(173),
            174 => $expand!(174),
            175 => $expand!(175),
            176 => $expand!(176),
            177 => $expand!(177),
            178 => $expand!(178),
            179 => $expand!(179),
            180 => $expand!(180),
            181 => $expand!(181),
            182 => $expand!(182),
            183 => $expand!(183),
            184 => $expand!(184),
            185 => $expand!(185),
            186 => $expand!(186),
            187 => $expand!(187),
            188 => $expand!(188),
            189 => $expand!(189),
            190 => $expand!(190),
            191 => $expand!(191),
            192 => $expand!(192),
            193 => $expand!(193),
            194 => $expand!(194),
            195 => $expand!(195),
            196 => $expand!(196),
            197 => $expand!(197),
            198 => $expand!(198),
            199 => $expand!(199),
            200 => $expand!(200),
            201 => $expand!(201),
            202 => $expand!(202),
            203 => $expand!(203),
            204 => $expand!(204),
            205 => $expand!(205),
            206 => $expand!(206),
            207 => $expand!(207),
            208 => $expand!(208),
            209 => $expand!(209),
            210 => $expand!(210),
            211 => $expand!(211),
            212 => $expand!(212),
            213 => $expand!(213),
            214 => $expand!(214),
            215 => $expand!(215),
            216 => $expand!(216),
            217 => $expand!(217),
            218 => $expand!(218),
            219 => $expand!(219),
            220 => $expand!(220),
            221 => $expand!(221),
            222 => $expand!(222),
            223 => $expand!(223),
            224 => $expand!(224),
            225 => $expand!(225),
            226 => $expand!(226),
            227 => $expand!(227),
            228 => $expand!(228),
            229 => $expand!(229),
            230 => $expand!(230),
            231 => $expand!(231),
            232 => $expand!(232),
            233 => $expand!(233),
            234 => $expand!(234),
            235 => $expand!(235),
            236 => $expand!(236),
            237 => $expand!(237),
            238 => $expand!(238),
            239 => $expand!(239),
            240 => $expand!(240),
            241 => $expand!(241),
            242 => $expand!(242),
            243 => $expand!(243),
            244 => $expand!(244),
            245 => $expand!(245),
            246 => $expand!(246),
            247 => $expand!(247),
            248 => $expand!(248),
            249 => $expand!(249),
            250 => $expand!(250),
            251 => $expand!(251),
            252 => $expand!(252),
            253 => $expand!(253),
            254 => $expand!(254),
            _ => $expand!(255),
        }
    };
}

#[allow(unused)]
macro_rules! types {
    ($(
        $(#[$doc:meta])*
        pub struct $name:ident($($fields:tt)*);
    )*) => ($(
        $(#[$doc])*
        #[derive(Copy, Clone, Debug)]
        #[allow(non_camel_case_types)]
        #[repr(simd)]
        #[allow(clippy::missing_inline_in_public_items)]
        pub struct $name($($fields)*);
    )*)
}
<commit_msg>Add imm5 and imm_s5 to the common macros<commit_after>//! Utility macros.

#[allow(unused)]
macro_rules! constify_imm8 {
    ($imm8:expr, $expand:ident) => {
        #[allow(overflowing_literals)]
        match ($imm8) & 0b1111_1111 {
            0 => $expand!(0),
            1 => $expand!(1),
            2 => $expand!(2),
            3 => $expand!(3),
            4 => $expand!(4),
            5 => $expand!(5),
            6 => $expand!(6),
            7 => $expand!(7),
            8 => $expand!(8),
            9 => $expand!(9),
            10 => $expand!(10),
            11 => $expand!(11),
            12 => $expand!(12),
            13 => $expand!(13),
            14 => $expand!(14),
            15 => $expand!(15),
            16 => $expand!(16),
            17 => $expand!(17),
            18 => $expand!(18),
            19 => $expand!(19),
            20 => $expand!(20),
            21 => $expand!(21),
            22 => $expand!(22),
            23 => $expand!(23),
            24 => $expand!(24),
            25 => $expand!(25),
            26 => $expand!(26),
            27 => $expand!(27),
            28 => $expand!(28),
            29 => $expand!(29),
            30 => $expand!(30),
            31 => $expand!(31),
            32 => $expand!(32),
            33 => $expand!(33),
            34 => $expand!(34),
            35 => $expand!(35),
            36 => $expand!(36),
            37 => $expand!(37),
            38 => $expand!(38),
            39 => $expand!(39),
            40 => $expand!(40),
            41 => $expand!(41),
            42 => $expand!(42),
            43 => $expand!(43),
            44 => $expand!(44),
            45 => $expand!(45),
            46 => $expand!(46),
            47 => $expand!(47),
            48 => $expand!(48),
            49 => $expand!(49),
            50 => $expand!(50),
            51 => $expand!(51),
            52 => $expand!(52),
            53 => $expand!(53),
            54 => $expand!(54),
            55 => $expand!(55),
            56 => $expand!(56),
            57 => $expand!(57),
            58 => $expand!(58),
            59 => $expand!(59),
            60 => $expand!(60),
            61 => $expand!(61),
            62 => $expand!(62),
            63 => $expand!(63),
            64 => $expand!(64),
            65 => $expand!(65),
            66 => $expand!(66),
            67 => $expand!(67),
            68 => $expand!(68),
            69 => $expand!(69),
            70 => $expand!(70),
            71 => $expand!(71),
            72 => $expand!(72),
            73 => $expand!(73),
            74 => $expand!(74),
            75 => $expand!(75),
            76 => $expand!(76),
            77 => $expand!(77),
            78 => $expand!(78),
            79 => $expand!(79),
            80 => $expand!(80),
            81 => $expand!(81),
            82 => $expand!(82),
            83 => $expand!(83),
            84 => $expand!(84),
            85 => $expand!(85),
            86 => $expand!(86),
            87 => $expand!(87),
            88 => $expand!(88),
            89 => $expand!(89),
            90 => $expand!(90),
            91 => $expand!(91),
            92 => $expand!(92),
            93 => $expand!(93),
            94 => $expand!(94),
            95 => $expand!(95),
            96 => $expand!(96),
            97 => $expand!(97),
            98 => $expand!(98),
            99 => $expand!(99),
            100 => $expand!(100),
            101 => $expand!(101),
            102 => $expand!(102),
            103 => $expand!(103),
            104 => $expand!(104),
            105 => $expand!(105),
            106 => $expand!(106),
            107 => $expand!(107),
            108 => $expand!(108),
            109 => $expand!(109),
            110 => $expand!(110),
            111 => $expand!(111),
            112 => $expand!(112),
            113 => $expand!(113),
            114 => $expand!(114),
            115 => $expand!(115),
            116 => $expand!(116),
            117 => $expand!(117),
            118 => $expand!(118),
            119 => $expand!(119),
            120 => $expand!(120),
            121 => $expand!(121),
            122 => $expand!(122),
            123 => $expand!(123),
            124 => $expand!(124),
            125 => $expand!(125),
            126 => $expand!(126),
            127 => $expand!(127),
            128 => $expand!(128),
            129 => $expand!(129),
            130 => $expand!(130),
            131 => $expand!(131),
            132 => $expand!(132),
            133 => $expand!(133),
            134 => $expand!(134),
            135 => $expand!(135),
            136 => $expand!(136),
            137 => $expand!(137),
            138 => $expand!(138),
            139 => $expand!(139),
            140 => $expand!(140),
            141 => $expand!(141),
            142 => $expand!(142),
            143 => $expand!(143),
            144 => $expand!(144),
            145 => $expand!(145),
            146 => $expand!(146),
            147 => $expand!(147),
            148 => $expand!(148),
            149 => $expand!(149),
            150 => $expand!(150),
            151 => $expand!(151),
            152 => $expand!(152),
            153 => $expand!(153),
            154 => $expand!(154),
            155 => $expand!(155),
            156 => $expand!(156),
            157 => $expand!(157),
            158 => $expand!(158),
            159 => $expand!(159),
            160 => $expand!(160),
            161 => $expand!(161),
            162 => $expand!(162),
            163 => $expand!(163),
            164 => $expand!(164),
            165 => $expand!(165),
            166 => $expand!(166),
            167 => $expand!(167),
            168 => $expand!(168),
            169 => $expand!(169),
            170 => $expand!(170),
            171 => $expand!(171),
            172 => $expand!(172),
            173 => $expand!(173),
            174 => $expand!(174),
            175 => $expand!(175),
            176 => $expand!(176),
            177 => $expand!(177),
            178 => $expand!(178),
            179 => $expand!(179),
            180 => $expand!(180),
            181 => $expand!(181),
            182 => $expand!(182),
            183 => $expand!(183),
            184 => $expand!(184),
            185 => $expand!(185),
            186 => $expand!(186),
            187 => $expand!(187),
            188 => $expand!(188),
            189 => $expand!(189),
            190 => $expand!(190),
            191 => $expand!(191),
            192 => $expand!(192),
            193 => $expand!(193),
            194 => $expand!(194),
            195 => $expand!(195),
            196 => $expand!(196),
            197 => $expand!(197),
            198 => $expand!(198),
            199 => $expand!(199),
            200 => $expand!(200),
            201 => $expand!(201),
            202 => $expand!(202),
            203 => $expand!(203),
            204 => $expand!(204),
            205 => $expand!(205),
            206 => $expand!(206),
            207 => $expand!(207),
            208 => $expand!(208),
            209 => $expand!(209),
            210 => $expand!(210),
            211 => $expand!(211),
            212 => $expand!(212),
            213 => $expand!(213),
            214 => $expand!(214),
            215 => $expand!(215),
            216 => $expand!(216),
            217 => $expand!(217),
            218 => $expand!(218),
            219 => $expand!(219),
            220 => $expand!(220),
            221 => $expand!(221),
            222 => $expand!(222),
            223 => $expand!(223),
            224 => $expand!(224),
            225 => $expand!(225),
            226 => $expand!(226),
            227 => $expand!(227),
            228 => $expand!(228),
            229 => $expand!(229),
            230 => $expand!(230),
            231 => $expand!(231),
            232 => $expand!(232),
            233 => $expand!(233),
            234 => $expand!(234),
            235 => $expand!(235),
            236 => $expand!(236),
            237 => $expand!(237),
            238 => $expand!(238),
            239 => $expand!(239),
            240 => $expand!(240),
            241 => $expand!(241),
            242 => $expand!(242),
            243 => $expand!(243),
            244 => $expand!(244),
            245 => $expand!(245),
            246 => $expand!(246),
            247 => $expand!(247),
            248 => $expand!(248),
            249 => $expand!(249),
            250 => $expand!(250),
            251 => $expand!(251),
            252 => $expand!(252),
            253 => $expand!(253),
            254 => $expand!(254),
            _ => $expand!(255),
        }
    };
}

//immediate value: 0:31
#[allow(unused)]
macro_rules! constify_imm5 {
    ($imm8:expr, $expand:ident) => {
        #[allow(overflowing_literals)]
        match ($imm8) & 0b1_1111 {
            0 => $expand!(0),
            1 => $expand!(1),
            2 => $expand!(2),
            3 => $expand!(3),
            4 => $expand!(4),
            5 => $expand!(5),
            6 => $expand!(6),
            7 => $expand!(7),
            8 => $expand!(8),
            9 => $expand!(9),
            10 => $expand!(10),
            11 => $expand!(11),
            12 => $expand!(12),
            13 => $expand!(13),
            14 => $expand!(14),
            15 => $expand!(15),
            16 => $expand!(16),
            17 => $expand!(17),
            18 => $expand!(18),
            19 => $expand!(19),
            20 => $expand!(20),
            21 => $expand!(21),
            22 => $expand!(22),
            23 => $expand!(23),
            24 => $expand!(24),
            25 => $expand!(25),
            26 => $expand!(26),
            27 => $expand!(27),
            28 => $expand!(28),
            29 => $expand!(29),
            30 => $expand!(30),
            _ => $expand!(31),
        }
    };
}

//immediate value: -16:15
#[allow(unused)]
macro_rules! constify_imm5 {
    ($imm8:expr, $expand:ident) => {
        #[allow(overflowing_literals)]
        match ($imm8) & 0b1_1111 {
            0 => $expand!(0),
            1 => $expand!(1),
            2 => $expand!(2),
            3 => $expand!(3),
            4 => $expand!(4),
            5 => $expand!(5),
            6 => $expand!(6),
            7 => $expand!(7),
            8 => $expand!(8),
            9 => $expand!(9),
            10 => $expand!(10),
            11 => $expand!(11),
            12 => $expand!(12),
            13 => $expand!(13),
            14 => $expand!(14),
            15 => $expand!(15),
            16 => $expand!(16),
            17 => $expand!(17),
            18 => $expand!(18),
            19 => $expand!(19),
            20 => $expand!(20),
            21 => $expand!(21),
            22 => $expand!(22),
            23 => $expand!(23),
            24 => $expand!(24),
            25 => $expand!(25),
            26 => $expand!(26),
            27 => $expand!(27),
            28 => $expand!(28),
            29 => $expand!(29),
            30 => $expand!(30),
            _ => $expand!(31),
        }
    };
}

#[allow(unused)]
macro_rules! types {
    ($(
        $(#[$doc:meta])*
        pub struct $name:ident($($fields:tt)*);
    )*) => ($(
        $(#[$doc])*
        #[derive(Copy, Clone, Debug)]
        #[allow(non_camel_case_types)]
        #[repr(simd)]
        #[allow(clippy::missing_inline_in_public_items)]
        pub struct $name($($fields)*);
    )*)
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate godcoin;
extern crate tokio;
extern crate ctrlc;
extern crate dirs;
extern crate clap;

#[macro_use]
extern crate log;

use godcoin::{*, net::PeerPool, producer::Producer};
use clap::{Arg, App, AppSettings, SubCommand};
use std::sync::{Arc, mpsc};
use tokio::prelude::*;

struct StartNode<'a> {
    bind_address: Option<&'a str>,
    minter_key: Option<KeyPair>,
    peers: Option<Vec<&'a str>>
}

fn generate_keypair(shutdown_handle: &mpsc::Sender<()>) {
    let pair = KeyPair::gen_keypair();
    info!("~~ Keys have been generated ~~");
    info!("Private key WIF: {}", pair.1.to_wif());
    info!("Public key WIF: {}", pair.0.to_wif());
    info!("- Make sure the keys are securely stored");
    info!("- Coins cannot be recovered if you lose your private key");
    info!("- Never give private keys to anyone");
    shutdown_handle.send(()).unwrap();
}

fn start_node(node_opts: &StartNode) {
    use godcoin::blockchain::*;
    use std::{env, path::*};

    let home: PathBuf = {
        use dirs;
        let home = env::var("GODCOIN_HOME").map(|s| {
            PathBuf::from(s)
        }).unwrap_or_else(|_| {
            Path::join(&dirs::data_local_dir().unwrap(), "godcoin")
        });
        if !Path::is_dir(&home) {
            let res = std::fs::create_dir(&home);
            res.unwrap_or_else(|_| panic!("Failed to create dir at {:?}", &home));
            info!("Created GODcoin home at {:?}", &home);
        } else {
            info!("Found GODcoin home at {:?}", &home);
        }
        home
    };

    let blockchain = Blockchain::new(&home);
    info!("Using height in block log at {}", blockchain.get_chain_height());

    let blockchain = Arc::new(blockchain);
    let producer = match &node_opts.minter_key {
        Some(key) => {
            let bond = blockchain.get_bond(&key.0).expect("No bond found for minter key");
            let minter = key.clone();
            let staker = bond.staker;
            let producer = Producer::new(Arc::clone(&blockchain), minter, staker);
            Arc::new(Some(producer))
        },
        None => Arc::new(None)
    };

    if let Some(peers) = &node_opts.peers {
        let pool = PeerPool::new(peers);
        pool.start(&blockchain, &producer);

        // TODO synchronize blocks with peers
    }

    {
        let create_genesis = blockchain.get_block(0).is_none();
        if create_genesis && node_opts.minter_key.is_some() {
            if let Some(ref key) = node_opts.minter_key {
                blockchain.create_genesis_block(key);
            }
        }
    }

    if let Some(producer) = producer.as_ref() {
        producer.clone().start_timer();
    }

    if let Some(bind) = node_opts.bind_address {
        let addr = bind.parse()
                        .unwrap_or_else(|_| panic!("Failed to parse address: {:?}", bind));
        net::server::start(addr, blockchain, producer);
    }
}

fn main() {
    let env = env_logger::Env::new().filter_or(env_logger::DEFAULT_FILTER_ENV, "godcoin=info");
    env_logger::init_from_env(env);

    godcoin::init().unwrap();
    let app = App::new("godcoin")
                .about("GODcoin core CLI")
                .version(env!("CARGO_PKG_VERSION"))
                .setting(AppSettings::VersionlessSubcommands)
                .setting(AppSettings::SubcommandRequiredElseHelp)
                .subcommand(SubCommand::with_name("keygen")
                            .about("Generates a keypair"))
                .subcommand(SubCommand::with_name("node")
                            .about("Starts the blockchain node service")
                            .arg(Arg::with_name("bind_address")
                                .help("Bind address endpoint (i.e 0.0.0.0:7777)")
                                .env("GODCOIN_BIND_ADDRESS")
                                .long("bind")
                                .value_name("address"))
                            .arg(Arg::with_name("peers")
                                .help("Comma-separated list of peers")
                                .env("GODCOIN_PEERS")
                                .long("peers")
                                .value_delimiter(",")
                                .value_name("peers")
                                .use_delimiter(true))
                            .arg(Arg::with_name("minter_key")
                                .help("Private minting key required to mint")
                                .env("GODCOIN_MINTER_KEY")
                                .long("minter-key")
                                .value_name("key")));
    let matches = app.get_matches();

    let (tx, rx) = mpsc::channel::<()>();
    let mut rt = tokio::runtime::Runtime::new().unwrap();

    {
        let tx = tx.clone();
        rt.block_on(future::lazy(move || {
            use ::std::io::{Error, ErrorKind};

            if matches.subcommand_matches("keygen").is_some() {
                generate_keypair(&tx);
            } else if let Some(matches) = matches.subcommand_matches("node") {
                start_node(&StartNode {
                    bind_address: matches.value_of("bind_address"),
                    peers: matches.values_of("peers").map(|p| { p.collect() }),
                    minter_key: matches.value_of("minter_key").map(|s| {
                        godcoin::PrivateKey::from_wif(s)
                            .expect("Failed to parse minter key argument")
                    })
                });
            } else {
                return Err(Error::new(ErrorKind::Other, "Failed to match subcommand"))
            }

            Ok(())
        }).map_err(|err| {
            error!("Startup failure: {:?}", err);
        })).unwrap();
    }

    ctrlc::set_handler(move || {
        println!("Received ctrl-c signal, shutting down...");
        tx.send(()).unwrap();
    }).unwrap();

    rx.recv().unwrap();
    rt.shutdown_now().wait().ok().unwrap();
}
<commit_msg>Avoid cloning peers vector during startup<commit_after>extern crate env_logger;
extern crate godcoin;
extern crate tokio;
extern crate ctrlc;
extern crate dirs;
extern crate clap;

#[macro_use]
extern crate log;

use godcoin::{*, net::PeerPool, producer::Producer};
use clap::{Arg, App, AppSettings, SubCommand};
use std::sync::{Arc, mpsc};
use tokio::prelude::*;
use std::borrow::Cow;

struct StartNode<'a> {
    bind_address: Option<&'a str>,
    minter_key: Option<KeyPair>,
    peers: Option<Vec<&'a str>>
}

fn generate_keypair(shutdown_handle: &mpsc::Sender<()>) {
    let pair = KeyPair::gen_keypair();
    info!("~~ Keys have been generated ~~");
    info!("Private key WIF: {}", pair.1.to_wif());
    info!("Public key WIF: {}", pair.0.to_wif());
    info!("- Make sure the keys are securely stored");
    info!("- Coins cannot be recovered if you lose your private key");
    info!("- Never give private keys to anyone");
    shutdown_handle.send(()).unwrap();
}

fn start_node(node_opts: &StartNode) {
    use godcoin::blockchain::*;
    use std::{env, path::*};

    let home: PathBuf = {
        use dirs;
        let home = env::var("GODCOIN_HOME").map(|s| {
            PathBuf::from(s)
        }).unwrap_or_else(|_| {
            Path::join(&dirs::data_local_dir().unwrap(), "godcoin")
        });
        if !Path::is_dir(&home) {
            let res = std::fs::create_dir(&home);
            res.unwrap_or_else(|_| panic!("Failed to create dir at {:?}", &home));
            info!("Created GODcoin home at {:?}", &home);
        } else {
            info!("Found GODcoin home at {:?}", &home);
        }
        home
    };

    let blockchain = Blockchain::new(&home);
    info!("Using height in block log at {}", blockchain.get_chain_height());

    let blockchain = Arc::new(blockchain);
    let producer = match &node_opts.minter_key {
        Some(key) => {
            let bond = blockchain.get_bond(&key.0).expect("No bond found for minter key");
            let minter = key.clone();
            let staker = bond.staker;
            let producer = Producer::new(Arc::clone(&blockchain), minter, staker);
            Arc::new(Some(producer))
        },
        None => Arc::new(None)
    };

    {
        let peers = if let Some(peers) = &node_opts.peers {
            Cow::Borrowed(peers)
        } else {
            Cow::Owned(vec![])
        };
        let pool = PeerPool::new(&peers);
        pool.start(&blockchain, &producer);

        // TODO synchronize blocks with peers
    }

    {
        let create_genesis = blockchain.get_block(0).is_none();
        if create_genesis && node_opts.minter_key.is_some() {
            if let Some(ref key) = node_opts.minter_key {
                blockchain.create_genesis_block(key);
            }
        }
    }

    if let Some(producer) = producer.as_ref() {
        producer.clone().start_timer();
    }

    if let Some(bind) = node_opts.bind_address {
        let addr = bind.parse()
                        .unwrap_or_else(|_| panic!("Failed to parse address: {:?}", bind));
        net::server::start(addr, blockchain, producer);
    }
}

fn main() {
    let env = env_logger::Env::new().filter_or(env_logger::DEFAULT_FILTER_ENV, "godcoin=info");
    env_logger::init_from_env(env);

    godcoin::init().unwrap();
    let app = App::new("godcoin")
                .about("GODcoin core CLI")
                .version(env!("CARGO_PKG_VERSION"))
                .setting(AppSettings::VersionlessSubcommands)
                .setting(AppSettings::SubcommandRequiredElseHelp)
                .subcommand(SubCommand::with_name("keygen")
                            .about("Generates a keypair"))
                .subcommand(SubCommand::with_name("node")
                            .about("Starts the blockchain node service")
                            .arg(Arg::with_name("bind_address")
                                .help("Bind address endpoint (i.e 0.0.0.0:7777)")
                                .env("GODCOIN_BIND_ADDRESS")
                                .long("bind")
                                .value_name("address"))
                            .arg(Arg::with_name("peers")
                                .help("Comma-separated list of peers")
                                .env("GODCOIN_PEERS")
                                .long("peers")
                                .value_delimiter(",")
                                .value_name("peers")
                                .use_delimiter(true))
                            .arg(Arg::with_name("minter_key")
                                .help("Private minting key required to mint")
                                .env("GODCOIN_MINTER_KEY")
                                .long("minter-key")
                                .value_name("key")));
    let matches = app.get_matches();

    let (tx, rx) = mpsc::channel::<()>();
    let mut rt = tokio::runtime::Runtime::new().unwrap();

    {
        let tx = tx.clone();
        rt.block_on(future::lazy(move || {
            use ::std::io::{Error, ErrorKind};

            if matches.subcommand_matches("keygen").is_some() {
                generate_keypair(&tx);
            } else if let Some(matches) = matches.subcommand_matches("node") {
                start_node(&StartNode {
                    bind_address: matches.value_of("bind_address"),
                    peers: matches.values_of("peers").map(|p| { p.collect() }),
                    minter_key: matches.value_of("minter_key").map(|s| {
                        godcoin::PrivateKey::from_wif(s)
                            .expect("Failed to parse minter key argument")
                    })
                });
            } else {
                return Err(Error::new(ErrorKind::Other, "Failed to match subcommand"))
            }

            Ok(())
        }).map_err(|err| {
            error!("Startup failure: {:?}", err);
        })).unwrap();
    }

    ctrlc::set_handler(move || {
        println!("Received ctrl-c signal, shutting down...");
        tx.send(()).unwrap();
    }).unwrap();

    rx.recv().unwrap();
    rt.shutdown_now().wait().ok().unwrap();
}
<|endoftext|>


<commit_before>mod sealed {
    pub trait Sealed {}
}
use sealed::Sealed;

/// Supporting trait for vector `select` function
pub trait Select<Mask>: Sealed {
    #[doc(hidden)]
    fn select(mask: Mask, true_values: Self, false_values: Self) -> Self;
}

macro_rules! impl_select {
    {
        $mask:ident ($bits_ty:ident): $($type:ident),*
    } => {
        $(
        impl<const LANES: usize> Sealed for crate::$type<LANES> where Self: crate::LanesAtMost32 {}
        impl<const LANES: usize> Select<crate::$mask<LANES>> for crate::$type<LANES>
        where
            crate::$mask<LANES>: crate::Mask,
            crate::$bits_ty<LANES>: crate::LanesAtMost32,
            Self: crate::LanesAtMost32,
        {
            #[doc(hidden)]
            #[inline]
            fn select(mask: crate::$mask<LANES>, true_values: Self, false_values: Self) -> Self {
                unsafe { crate::intrinsics::simd_select(mask.to_int(), true_values, false_values) }
            }
        }
        )*

        impl<const LANES: usize> Sealed for crate::$mask<LANES>
        where
            Self: crate::Mask,
            crate::$bits_ty<LANES>: crate::LanesAtMost32,
        {}
        impl<const LANES: usize> Select<Self> for crate::$mask<LANES>
        where
            Self: crate::Mask,
            crate::$bits_ty<LANES>: crate::LanesAtMost32,
        {
            #[doc(hidden)]
            #[inline]
            fn select(mask: Self, true_values: Self, false_values: Self) -> Self {
                mask & true_values | !mask & false_values
            }
        }

        impl<const LANES: usize> crate::$mask<LANES>
        where
            Self: crate::Mask,
            crate::$bits_ty<LANES>: crate::LanesAtMost32,
        {
            /// Choose lanes from two vectors.
            ///
            /// For each lane in the mask, choose the corresponding lane from `true_values` if
            /// that lane mask is true, and `false_values` if that lane mask is false.
            ///
            /// ```
            /// # use core_simd::{Mask32, SimdI32};
            /// let a = SimdI32::from_array([0, 1, 2, 3]);
            /// let b = SimdI32::from_array([4, 5, 6, 7]);
            /// let mask = Mask32::from_array([true, false, false, true]);
            /// let c = mask.select(a, b);
            /// assert_eq!(c.to_array(), [0, 5, 6, 3]);
            /// ```
            ///
            /// `select` can also be used with masks:
            /// ```
            /// # use core_simd::{Mask32};
            /// let a = Mask32::from_array([true, true, false, false]);
            /// let b = Mask32::from_array([false, false, true, true]);
            /// let mask = Mask32::from_array([true, false, false, true]);
            /// let c = mask.select(a, b);
            /// assert_eq!(c.to_array(), [true, false, true, false]);
            /// ```
            #[inline]
            pub fn select<S: Select<Self>>(self, true_values: S, false_values: S) -> S {
                S::select(self, true_values, false_values)
            }
        }
    }
}

impl_select! { Mask8 (SimdI8): SimdU8, SimdI8 }
impl_select! { Mask16 (SimdI16): SimdU16, SimdI16 }
impl_select! { Mask32 (SimdI32): SimdU32, SimdI32, SimdF32}
impl_select! { Mask64 (SimdI64): SimdU64, SimdI64, SimdF64}
impl_select! { MaskSize (SimdIsize): SimdUsize, SimdIsize }
<commit_msg>Clarify documentation<commit_after>mod sealed {
    pub trait Sealed {}
}
use sealed::Sealed;

/// Supporting trait for vector `select` function
pub trait Select<Mask>: Sealed {
    #[doc(hidden)]
    fn select(mask: Mask, true_values: Self, false_values: Self) -> Self;
}

macro_rules! impl_select {
    {
        $mask:ident ($bits_ty:ident): $($type:ident),*
    } => {
        $(
        impl<const LANES: usize> Sealed for crate::$type<LANES> where Self: crate::LanesAtMost32 {}
        impl<const LANES: usize> Select<crate::$mask<LANES>> for crate::$type<LANES>
        where
            crate::$mask<LANES>: crate::Mask,
            crate::$bits_ty<LANES>: crate::LanesAtMost32,
            Self: crate::LanesAtMost32,
        {
            #[doc(hidden)]
            #[inline]
            fn select(mask: crate::$mask<LANES>, true_values: Self, false_values: Self) -> Self {
                unsafe { crate::intrinsics::simd_select(mask.to_int(), true_values, false_values) }
            }
        }
        )*

        impl<const LANES: usize> Sealed for crate::$mask<LANES>
        where
            Self: crate::Mask,
            crate::$bits_ty<LANES>: crate::LanesAtMost32,
        {}
        impl<const LANES: usize> Select<Self> for crate::$mask<LANES>
        where
            Self: crate::Mask,
            crate::$bits_ty<LANES>: crate::LanesAtMost32,
        {
            #[doc(hidden)]
            #[inline]
            fn select(mask: Self, true_values: Self, false_values: Self) -> Self {
                mask & true_values | !mask & false_values
            }
        }

        impl<const LANES: usize> crate::$mask<LANES>
        where
            Self: crate::Mask,
            crate::$bits_ty<LANES>: crate::LanesAtMost32,
        {
            /// Choose lanes from two vectors.
            ///
            /// For each lane in the mask, choose the corresponding lane from `true_values` if
            /// that lane mask is true, and `false_values` if that lane mask is false.
            ///
            /// ```
            /// # use core_simd::{Mask32, SimdI32};
            /// let a = SimdI32::from_array([0, 1, 2, 3]);
            /// let b = SimdI32::from_array([4, 5, 6, 7]);
            /// let mask = Mask32::from_array([true, false, false, true]);
            /// let c = mask.select(a, b);
            /// assert_eq!(c.to_array(), [0, 5, 6, 3]);
            /// ```
            ///
            /// `select` can also be used on masks:
            /// ```
            /// # use core_simd::Mask32;
            /// let a = Mask32::from_array([true, true, false, false]);
            /// let b = Mask32::from_array([false, false, true, true]);
            /// let mask = Mask32::from_array([true, false, false, true]);
            /// let c = mask.select(a, b);
            /// assert_eq!(c.to_array(), [true, false, true, false]);
            /// ```
            #[inline]
            pub fn select<S: Select<Self>>(self, true_values: S, false_values: S) -> S {
                S::select(self, true_values, false_values)
            }
        }
    }
}

impl_select! { Mask8 (SimdI8): SimdU8, SimdI8 }
impl_select! { Mask16 (SimdI16): SimdU16, SimdI16 }
impl_select! { Mask32 (SimdI32): SimdU32, SimdI32, SimdF32}
impl_select! { Mask64 (SimdI64): SimdU64, SimdI64, SimdF64}
impl_select! { MaskSize (SimdIsize): SimdUsize, SimdIsize }
<|endoftext|>