<commit_before>use std::collections::{HashMap, HashSet};
use std::ops::{Deref, DerefMut};

use ndarray::Array2;
use jagged_array::Jagged2;

use render::Renderer;
use resman::AudioBuffer;
use routing::{Edge, GraphWatcher, NodeData, NodeHandle};
use routing::effect::{PrimitiveEffect, EffectData};
use streaming_iterator::StreamingIterator;
use util::unpack_f32;

#[derive(Debug)]
struct NodeMap {
    nodes: HashMap<NodeHandle, Node>,
}

#[derive(Default, Debug)]
pub struct RefRenderer {
    nodes: NodeMap,
    /// inputs[slot][sample] represents the value of the external input at
    /// the given slot and time. On OOB, it is assumed to be 0.
    inputs: Vec<Vec<f32>>,
    /// Next expected sample to be queried.
    /// This is tracked because if we do a seek, the inputs need to be zero'd.
    head: u64,
}

#[derive(Default, Debug)]
struct Node {
    data: Option<MyNodeData>,
    inbound: HashSet<Edge>
}

#[derive(Debug)]
enum MyNodeData {
    /// This node is a non-primitive effect.
    UserNode(NodeMap),
    /// Primitive effect (delay, constant, etc).
    Primitive(PrimitiveEffect),
    /// External audio.
    Buffer(AudioBuffer),
}

impl Renderer for RefRenderer {
    fn fill_buffer(&mut self, buff: &mut Array2<f32>, idx: u64, inputs: Jagged2<f32>) {
        let (n_slots, n_times) = buff.dim().into();
        // Store inputs for future use
        {
            // If this is a seek operation, forget historical input values.
            if idx != self.head {
                for slot in &mut self.inputs {
                    *slot = Vec::new();
                    // NB: Improper indexing on 32-bit OS, but will OOM first.
                    slot.resize(idx as usize, 0f32);
                }
            }
            // Make sure we have storage space for all inputs.
            while self.inputs.len() < buff.len() {
                // NB: Improper indexing on 32-bit OS, but will OOM first.
                let mut v = Vec::with_capacity(idx as usize);
                v.resize(idx as usize, 0f32);
                self.inputs.push(v);
            }
            let mut stream = inputs.stream();
            let mut self_it = self.inputs.iter_mut();
            while let (Some(row), Some(vec_dest)) = (stream.next(), self_it.next()) {
                assert_eq!(vec_dest.len(), idx as usize);
                vec_dest.extend(row);
                assert!(vec_dest.len() <= idx as usize + n_times); // cannot send inputs ahead of outputs.
                let pad_val = vec_dest.last().cloned().unwrap_or(0f32);
                vec_dest.resize(idx as usize +n_times, pad_val);
            }
        }

        // Calculate outputs
        for slot in 0..n_slots as u32 {
            for time in idx..idx+n_times as u64 {
                buff[[slot as usize, (time - idx) as usize]] = self.get_sample(time, slot);
            }
        }
        // Keep track of the playhead
        self.head = idx + n_times as u64;
    }
}
impl RefRenderer {
    fn get_sample(&mut self, time: u64, slot: u32) -> f32 {
        let node = &self.nodes[&NodeHandle::toplevel()];
        self.sum_input_to_slot(&self.nodes, &node, time, slot, &Vec::new()) as f32
    }
    /// Get the value on an edge at a particular time
    /// When backtracking from the output, we push each Node onto the context if we enter inside of
    ///   it (i.e. if it's a nested DAG) & pop when exiting.
    fn get_value(&self, nodes: &NodeMap, edge: &Edge, time: u64, context: &Vec<(&NodeMap, NodeHandle)>) -> f64 {
        let from = edge.from_full();
        if *from.node_handle() == None {
            if context.is_empty() {
                // toplevel input (i.e. external input)
                let slot = edge.from_slot() as usize;
                *self.inputs.get(slot).and_then(|v| v.get(time as usize)).unwrap_or(&0f32) as f64
            } else {
                // Reading from one of the inputs to the top of `context`
                // TODO: we can avoid cloning by reversing the pop after recursing.
                let mut new_context = context.clone();
                let (new_nodes, head) = new_context.pop().unwrap();
                // Sum the inputs to the matching slot
                self.sum_input_to_slot(new_nodes, &new_nodes[&head], time, edge.from_slot(), &new_context)
            }
        } else {
            // Reading from another node within the DAG
            let node = &nodes[&from];
            match *node.data.as_ref().expect("Expected node to have associated data") {
                MyNodeData::UserNode(ref new_nodes) => {
                    let mut new_context = context.clone();
                    new_context.push((nodes, from));
                    // Now find the *output* of the sub dag (or 0 if the sub dag has no outputs)
                    new_nodes.get(&NodeHandle::toplevel()).map_or(0f64, |root_node| {
                        self.sum_input_to_slot(new_nodes, root_node, time, edge.from_slot(), &new_context)
                    })
                },
                MyNodeData::Primitive(prim) => match prim {
                    // Output = sum of all inputs to slot 0.
                    PrimitiveEffect::Delay => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Delay slot != 0");
                            0f64
                        } else {
                            let delay_frames = self.sum_input_to_slot(nodes, node, time, 1, context);
                            // Clamp delay value to [0, u64::max]
                            let delay_int = if delay_frames < 0f64 {
                                0u64
                            } else if delay_frames > u64::max_value() as f64 {
                                // TODO: u64::max isn't precisely representable in f64;
                                // will this cause issues?
                                u64::max_value()
                            } else {
                                // Note: this conversion is flooring.
                                delay_frames as u64
                            };
                            // t<0 -> value is 0.
                            time.checked_sub(delay_int).map_or(0f64, |origin_time| {
                                self.sum_input_to_slot(nodes, node, origin_time, 0, context)
                            })
                        }
                    },
                    PrimitiveEffect::F32Constant => {
                        // Float value is encoded via the slot.
                        let value = edge.from_slot();
                        unpack_f32(value) as f64
                    },
                    PrimitiveEffect::Multiply => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Multiply slot != 0");
                            0f64
                        } else {
                            // Sum all inputs from slot=0 and slot=2 into two separate
                            // variables, then multiply them.
                            let val_a = self.sum_input_to_slot(nodes, node, time, 0, context);
                            let val_b = self.sum_input_to_slot(nodes, node, time, 1, context);
                            val_a * val_b
                        }
                    },
                    PrimitiveEffect::Divide => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from MultInv slot != 0");
                            0f64
                        } else {
                            // Sum all inputs
                            let dividend = self.sum_input_to_slot(nodes, node, time, 0, context);
                            let divisor = self.sum_input_to_slot(nodes, node, time, 1, context);
                            dividend / divisor
                        }
                    },
                    PrimitiveEffect::Minimum => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Modulo slot != 0");
                            0f64
                        } else {
                            let input_a = self.sum_input_to_slot(nodes, node, time, 0, context);
                            let input_b = self.sum_input_to_slot(nodes, node, time, 1, context);
                            input_a.min(input_b)
                        }
                    }
                    PrimitiveEffect::Modulo => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Modulo slot != 0");
                            0f64
                        } else {
                            // Sum all dividends
                            let dividend = self.sum_input_to_slot(nodes, node, time, 0, context);
                            // Sum all divisors
                            let divisor = self.sum_input_to_slot(nodes, node, time, 1, context);
                            let rem = dividend % divisor;
                            if rem < 0f64 {
                                // TODO: We may be losing precision here, if rem is small.
                                // We should find a way to do true modulus.
                                rem + divisor
                            } else {
                                rem
                            }
                        }
                    },
                },
                MyNodeData::Buffer(ref buf) => buf.get(time, edge.from_slot()) as f64,
            }
        }
    }
    /// Return the sum of all inputs into a specific slot of the given
    /// node at the given time.
    fn sum_input_to_slot(&self, nodes: &NodeMap, node: &Node, time: u64, slot: u32, context: &Vec<(&NodeMap, NodeHandle)>) -> f64 {
        let edges_in = node.inbound.iter().filter(|in_edge| {
            in_edge.to_slot() == slot
        });
        edges_in.map(|edge| self.get_value(nodes, edge, time, context)).sum()
    }

    fn make_node(&self, effect: &NodeData) -> MyNodeData {
        match *effect.data() {
            EffectData::Primitive(e) => MyNodeData::Primitive(e),
            EffectData::Buffer(ref buff) => MyNodeData::Buffer(buff.clone()),
            EffectData::RouteGraph(ref graph) => {
                let mut nodes: NodeMap = Default::default();

                for (node, data) in graph.iter_nodes() {
                    nodes.insert(*node, Node::new(Some(self.make_node(data))));
                }
                for edge in graph.iter_edges() {
                    nodes.get_mut(&edge.to_full()).unwrap().inbound.insert(edge.clone());
                }
                MyNodeData::UserNode(nodes)
            }
        }
    }
}

impl GraphWatcher for RefRenderer {
    fn on_add_node(&mut self, handle: &NodeHandle, data: &NodeData) {
        let my_node_data = self.make_node(data);
        self.nodes.insert(*handle, Node::new(Some(my_node_data)));
    }
    fn on_del_node(&mut self, handle: &NodeHandle) {
        self.nodes.remove(handle);
    }
    fn on_add_edge(&mut self, edge: &Edge) {
        self.nodes.get_mut(&edge.to_full()).unwrap().inbound.insert(edge.clone());
    }
    fn on_del_edge(&mut self, edge: &Edge) {
        self.nodes.get_mut(&edge.to_full()).unwrap().inbound.remove(edge);
    }
}

impl Node {
    fn new(data: Option<MyNodeData>) -> Self {
        Node {
            data: data,
            inbound: HashSet::new(),
        }
    }
}

impl Default for NodeMap {
    fn default() -> Self {
        // Create a NodeMap that already has an entry for the toplevel so that it can receive
        // edges.
        let nodes = Some((NodeHandle::toplevel(), Default::default())).into_iter().collect();
        Self { nodes }
    }
}

impl Deref for NodeMap {
    type Target = HashMap<NodeHandle, Node>;
    fn deref(&self) -> &Self::Target {
        &self.nodes
    }
}

impl DerefMut for NodeMap {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.nodes
    }
}
<commit_msg>More debug info<commit_after>use std::collections::{HashMap, HashSet};
use std::ops::{Deref, DerefMut};

use ndarray::Array2;
use jagged_array::Jagged2;

use render::Renderer;
use resman::AudioBuffer;
use routing::{Edge, GraphWatcher, NodeData, NodeHandle};
use routing::effect::{PrimitiveEffect, EffectData};
use streaming_iterator::StreamingIterator;
use util::unpack_f32;

#[derive(Debug)]
struct NodeMap {
    nodes: HashMap<NodeHandle, Node>,
}

#[derive(Default, Debug)]
pub struct RefRenderer {
    nodes: NodeMap,
    /// inputs[slot][sample] represents the value of the external input at
    /// the given slot and time. On OOB, it is assumed to be 0.
    inputs: Vec<Vec<f32>>,
    /// Next expected sample to be queried.
    /// This is tracked because if we do a seek, the inputs need to be zero'd.
    head: u64,
}

#[derive(Default, Debug)]
struct Node {
    data: Option<MyNodeData>,
    inbound: HashSet<Edge>
}

#[derive(Debug)]
enum MyNodeData {
    /// This node is a non-primitive effect.
    UserNode(NodeMap),
    /// Primitive effect (delay, constant, etc).
    Primitive(PrimitiveEffect),
    /// External audio.
    Buffer(AudioBuffer),
}

impl Renderer for RefRenderer {
    fn fill_buffer(&mut self, buff: &mut Array2<f32>, idx: u64, inputs: Jagged2<f32>) {
        let (n_slots, n_times) = buff.dim().into();
        // Store inputs for future use
        {
            // If this is a seek operation, forget historical input values.
            if idx != self.head {
                for slot in &mut self.inputs {
                    *slot = Vec::new();
                    // NB: Improper indexing on 32-bit OS, but will OOM first.
                    slot.resize(idx as usize, 0f32);
                }
            }
            // Make sure we have storage space for all inputs.
            while self.inputs.len() < buff.len() {
                // NB: Improper indexing on 32-bit OS, but will OOM first.
                let mut v = Vec::with_capacity(idx as usize);
                v.resize(idx as usize, 0f32);
                self.inputs.push(v);
            }
            let mut stream = inputs.stream();
            let mut self_it = self.inputs.iter_mut();
            while let (Some(row), Some(vec_dest)) = (stream.next(), self_it.next()) {
                assert_eq!(vec_dest.len(), idx as usize);
                vec_dest.extend(row);
                assert!(vec_dest.len() <= idx as usize + n_times); // cannot send inputs ahead of outputs.
                let pad_val = vec_dest.last().cloned().unwrap_or(0f32);
                vec_dest.resize(idx as usize +n_times, pad_val);
            }
        }

        // Calculate outputs
        for slot in 0..n_slots as u32 {
            for time in idx..idx+n_times as u64 {
                buff[[slot as usize, (time - idx) as usize]] = self.get_sample(time, slot);
            }
        }
        // Keep track of the playhead
        self.head = idx + n_times as u64;
    }
}
impl RefRenderer {
    fn get_sample(&mut self, time: u64, slot: u32) -> f32 {
        let node = &self.nodes[&NodeHandle::toplevel()];
        self.sum_input_to_slot(&self.nodes, &node, time, slot, &Vec::new()) as f32
    }
    /// Get the value on an edge at a particular time
    /// When backtracking from the output, we push each Node onto the context if we enter inside of
    ///   it (i.e. if it's a nested DAG) & pop when exiting.
    fn get_value(&self, nodes: &NodeMap, edge: &Edge, time: u64, context: &Vec<(&NodeMap, NodeHandle)>) -> f64 {
        let from = edge.from_full();
        if *from.node_handle() == None {
            if context.is_empty() {
                // toplevel input (i.e. external input)
                let slot = edge.from_slot() as usize;
                let value = *self.inputs.get(slot).and_then(|v| v.get(time as usize)).unwrap_or(&0f32) as f64;
                trace!("Renderer reading from ext input [t={}] [slot={}]: {}", time, slot, value);
                value
            } else {
                // Reading from one of the inputs to the top of `context`
                // TODO: we can avoid cloning by reversing the pop after recursing.
                let mut new_context = context.clone();
                let (new_nodes, head) = new_context.pop().unwrap();
                // Sum the inputs to the matching slot
                self.sum_input_to_slot(new_nodes, &new_nodes[&head], time, edge.from_slot(), &new_context)
            }
        } else {
            // Reading from another node within the DAG
            let node = &nodes[&from];
            match *node.data.as_ref().expect("Expected node to have associated data") {
                MyNodeData::UserNode(ref new_nodes) => {
                    let mut new_context = context.clone();
                    new_context.push((nodes, from));
                    // Now find the *output* of the sub dag (or 0 if the sub dag has no outputs)
                    new_nodes.get(&NodeHandle::toplevel()).map_or(0f64, |root_node| {
                        self.sum_input_to_slot(new_nodes, root_node, time, edge.from_slot(), &new_context)
                    })
                },
                MyNodeData::Primitive(prim) => match prim {
                    // Output = sum of all inputs to slot 0.
                    PrimitiveEffect::Delay => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Delay slot != 0");
                            0f64
                        } else {
                            let delay_frames = self.sum_input_to_slot(nodes, node, time, 1, context);
                            // Clamp delay value to [0, u64::max]
                            let delay_int = if delay_frames < 0f64 {
                                0u64
                            } else if delay_frames > u64::max_value() as f64 {
                                // TODO: u64::max isn't precisely representable in f64;
                                // will this cause issues?
                                u64::max_value()
                            } else {
                                // Note: this conversion is flooring.
                                delay_frames as u64
                            };
                            // t<0 -> value is 0.
                            time.checked_sub(delay_int).map_or(0f64, |origin_time| {
                                self.sum_input_to_slot(nodes, node, origin_time, 0, context)
                            })
                        }
                    },
                    PrimitiveEffect::F32Constant => {
                        // Float value is encoded via the slot.
                        let value = edge.from_slot();
                        unpack_f32(value) as f64
                    },
                    PrimitiveEffect::Multiply => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Multiply slot != 0");
                            0f64
                        } else {
                            // Sum all inputs from slot=0 and slot=2 into two separate
                            // variables, then multiply them.
                            let val_a = self.sum_input_to_slot(nodes, node, time, 0, context);
                            let val_b = self.sum_input_to_slot(nodes, node, time, 1, context);
                            val_a * val_b
                        }
                    },
                    PrimitiveEffect::Divide => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from MultInv slot != 0");
                            0f64
                        } else {
                            // Sum all inputs
                            let dividend = self.sum_input_to_slot(nodes, node, time, 0, context);
                            let divisor = self.sum_input_to_slot(nodes, node, time, 1, context);
                            dividend / divisor
                        }
                    },
                    PrimitiveEffect::Minimum => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Modulo slot != 0");
                            0f64
                        } else {
                            let input_a = self.sum_input_to_slot(nodes, node, time, 0, context);
                            let input_b = self.sum_input_to_slot(nodes, node, time, 1, context);
                            input_a.min(input_b)
                        }
                    }
                    PrimitiveEffect::Modulo => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Modulo slot != 0");
                            0f64
                        } else {
                            // Sum all dividends
                            let dividend = self.sum_input_to_slot(nodes, node, time, 0, context);
                            // Sum all divisors
                            let divisor = self.sum_input_to_slot(nodes, node, time, 1, context);
                            let rem = dividend % divisor;
                            if rem < 0f64 {
                                // TODO: We may be losing precision here, if rem is small.
                                // We should find a way to do true modulus.
                                rem + divisor
                            } else {
                                rem
                            }
                        }
                    },
                },
                MyNodeData::Buffer(ref buf) => buf.get(time, edge.from_slot()) as f64,
            }
        }
    }
    /// Return the sum of all inputs into a specific slot of the given
    /// node at the given time.
    fn sum_input_to_slot(&self, nodes: &NodeMap, node: &Node, time: u64, slot: u32, context: &Vec<(&NodeMap, NodeHandle)>) -> f64 {
        let edges_in = node.inbound.iter().filter(|in_edge| {
            in_edge.to_slot() == slot
        });
        edges_in.map(|edge| self.get_value(nodes, edge, time, context)).sum()
    }

    fn make_node(&self, effect: &NodeData) -> MyNodeData {
        match *effect.data() {
            EffectData::Primitive(e) => MyNodeData::Primitive(e),
            EffectData::Buffer(ref buff) => MyNodeData::Buffer(buff.clone()),
            EffectData::RouteGraph(ref graph) => {
                let mut nodes: NodeMap = Default::default();

                for (node, data) in graph.iter_nodes() {
                    nodes.insert(*node, Node::new(Some(self.make_node(data))));
                }
                for edge in graph.iter_edges() {
                    nodes.get_mut(&edge.to_full()).unwrap().inbound.insert(edge.clone());
                }
                MyNodeData::UserNode(nodes)
            }
        }
    }
}

impl GraphWatcher for RefRenderer {
    fn on_add_node(&mut self, handle: &NodeHandle, data: &NodeData) {
        let my_node_data = self.make_node(data);
        self.nodes.insert(*handle, Node::new(Some(my_node_data)));
    }
    fn on_del_node(&mut self, handle: &NodeHandle) {
        self.nodes.remove(handle);
    }
    fn on_add_edge(&mut self, edge: &Edge) {
        self.nodes.get_mut(&edge.to_full()).unwrap().inbound.insert(edge.clone());
    }
    fn on_del_edge(&mut self, edge: &Edge) {
        self.nodes.get_mut(&edge.to_full()).unwrap().inbound.remove(edge);
    }
}

impl Node {
    fn new(data: Option<MyNodeData>) -> Self {
        Node {
            data: data,
            inbound: HashSet::new(),
        }
    }
}

impl Default for NodeMap {
    fn default() -> Self {
        // Create a NodeMap that already has an entry for the toplevel so that it can receive
        // edges.
        let nodes = Some((NodeHandle::toplevel(), Default::default())).into_iter().collect();
        Self { nodes }
    }
}

impl Deref for NodeMap {
    type Target = HashMap<NodeHandle, Node>;
    fn deref(&self) -> &Self::Target {
        &self.nodes
    }
}

impl DerefMut for NodeMap {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.nodes
    }
}
<|endoftext|>


<commit_before>//! The `pact_mock_server` crate provides the CLI for the pact mock server for mocking HTTP requests
//! and generating responses based on a pact file. It implements the V1 Pact specification
//! (https://github.com/pact-foundation/pact-specification/tree/version-1).

#![warn(missing_docs)]

#[macro_use] extern crate clap;
#[macro_use] extern crate pact_matching;
extern crate pact_mock_server;
#[macro_use] extern crate rustful;
#[macro_use] extern crate p_macro;
#[macro_use] extern crate log;
#[macro_use] extern crate maplit;
extern crate simplelog;
extern crate uuid;
extern crate rustc_serialize;
#[macro_use] extern crate hyper;
extern crate rand;

#[cfg(test)]
extern crate quickcheck;

#[cfg(test)]
#[macro_use(expect)]
extern crate expectest;

use clap::{Arg, App, SubCommand, AppSettings, ErrorKind, ArgMatches};
use std::env;
use std::str::FromStr;
use std::fs;
use std::io;
use log::{LogLevelFilter};
use simplelog::{CombinedLogger, TermLogger, FileLogger};
use std::path::PathBuf;
use std::fs::OpenOptions;
use uuid::Uuid;
use pact_matching::models::PactSpecification;

fn display_error(error: String, matches: &ArgMatches) -> ! {
    println!("ERROR: {}", error);
    println!("");
    println!("{}", matches.usage());
    panic!("{}", error)
}

mod server;
mod create_mock;
mod list;
mod verify;

fn print_version() {
    println!("\npact mock server version  : v{}", crate_version!());
    println!("pact specification version: v{}", PactSpecification::V1.version_str());
}

fn setup_loggers(level: &str, command: &str, output: Option<&str>) -> Result<(), io::Error> {
    let log_level = match level {
        "none" => LogLevelFilter::Off,
        _ => LogLevelFilter::from_str(level).unwrap()
    };
    if command == "start" {
        let log_file = match output {
            Some(p) => {
                try!(fs::create_dir_all(p));
                let mut path = PathBuf::from(p);
                path.push("pact_v1_mock_server.log");
                path
            },
            None => PathBuf::from("pact_v1_mock_server.log")
        };
        let file = try!(OpenOptions::new()
            .read(false)
            .write(true)
            .append(true)
            .create(true)
            .open(log_file));
        CombinedLogger::init(
            vec![
                TermLogger::new(log_level),
                FileLogger::new(log_level, file)
            ]
        ).unwrap();
    } else {
        TermLogger::init(log_level).unwrap();
    }
    Ok(())
}

fn lookup_global_option<'a>(option: &str, matches: &'a ArgMatches<'a>) -> Option<&'a str> {
    let global_value = matches.value_of(option);
    let command_value = matches.subcommand().1.unwrap().value_of(option);
    match (global_value, command_value) {
        (Some(v), None) => Some(v),
        (None, Some(v)) => Some(v),
        (Some(_), Some(v)) => {
            println!("WARNING: The value for '{}' has been provided twice, defaulting to the second value '{}'",
                option, v);
            Some(v)
        },
        (None, None) => None
    }
}

fn integer_value(v: String) -> Result<(), String> {
    v.parse::<u16>().map(|_| ()).map_err(|e| format!("'{}' is not a valid port value: {}", v, e) )
}

fn uuid_value(v: String) -> Result<(), String> {
    Uuid::parse_str(v.as_str()).map(|_| ()).map_err(|e| format!("'{}' is not a valid UUID value: {}", v, e) )
}

fn main() {
    match handle_command_args() {
        Ok(_) => (),
        Err(err) => std::process::exit(err)
    }
}

fn handle_command_args() -> Result<(), i32> {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let version = format!("v{}", crate_version!());
    let app = App::new(program)
        .version(version.as_str())
        .about("Standalone Pact mock server")
        .version_short("v")
        .setting(AppSettings::ArgRequiredElseHelp)
        .setting(AppSettings::SubcommandRequired)
        .setting(AppSettings::GlobalVersion)
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::ColoredHelp)
        .arg(Arg::with_name("port")
            .short("p")
            .long("port")
            .takes_value(true)
            .use_delimiter(false)
            .global(true)
            .help("port the master mock server runs on (defaults to 8080)"))
        .arg(Arg::with_name("host")
            .short("h")
            .long("host")
            .takes_value(true)
            .use_delimiter(false)
            .global(true)
            .help("hostname the master mock server runs on (defaults to localhost)"))
        .arg(Arg::with_name("loglevel")
            .short("l")
            .long("loglevel")
            .takes_value(true)
            .use_delimiter(false)
            .global(true)
            .possible_values(&["error", "warn", "info", "debug", "trace", "none"])
            .help("Log level for mock servers to write to the log file (defaults to info)"))
        .subcommand(SubCommand::with_name("start")
                .about("Starts the master mock server")
                .setting(AppSettings::ColoredHelp)
                .arg(Arg::with_name("output")
                      .short("o")
                      .long("output")
                      .takes_value(true)
                      .use_delimiter(false)
                      .help("the directory where to write files to (defaults to current directory)")))
        .subcommand(SubCommand::with_name("list")
                .about("Lists all the running mock servers")
                .setting(AppSettings::ColoredHelp))
        .subcommand(SubCommand::with_name("create")
                .about("Creates a new mock server from a pact file")
                .arg(Arg::with_name("file")
                    .short("f")
                    .long("file")
                    .takes_value(true)
                    .use_delimiter(false)
                    .required(true)
                    .help("the pact file to define the mock server"))
                .setting(AppSettings::ColoredHelp))
        .subcommand(SubCommand::with_name("verify")
                .about("Verify the mock server by id or port number, and generate a pact file if all ok")
                .arg(Arg::with_name("mock-server-id")
                    .short("i")
                    .long("mock-server-id")
                    .takes_value(true)
                    .use_delimiter(false)
                    .required_unless("mock-server-port")
                    .conflicts_with("mock-server-port")
                    .help("the ID of the mock server")
                    .validator(uuid_value))
                .arg(Arg::with_name("mock-server-port")
                    .short("m")
                    .long("mock-server-port")
                    .takes_value(true)
                    .use_delimiter(false)
                    .required_unless("mock-server-host")
                    .help("the port number of the mock server")
                    .validator(integer_value))
                .setting(AppSettings::ColoredHelp));

    let matches = app.get_matches_safe();
    match matches {
        Ok(ref matches) => {
            let log_level = lookup_global_option("loglevel", matches);
            if let Err(err) = setup_loggers(log_level.unwrap_or("info"),
                matches.subcommand_name().unwrap(),
                matches.subcommand().1.unwrap().value_of("output")) {
                display_error(format!("Could not setup loggers: {}", err), matches);
            }
            let port = lookup_global_option("port", matches).unwrap_or("8080");
            let host = lookup_global_option("host", matches).unwrap_or("localhost");
            match port.parse::<u16>() {
                Ok(p) => {
                    match matches.subcommand() {
                        ("start", Some(sub_matches)) => server::start_server(p, sub_matches),
                        ("list", Some(sub_matches)) => list::list_mock_servers(host, p, sub_matches),
                        ("create", Some(sub_matches)) => create_mock::create_mock_server(host, p, sub_matches),
                        ("verify", Some(sub_matches)) => verify::verify_mock_server(host, p, sub_matches),
                        _ => Err(3)
                    }
                },
                Err(_) => display_error(format!("{} is not a valid port number", port), matches)
            }
        },
        Err(ref err) => {
            match err.kind {
                ErrorKind::HelpDisplayed => Ok(()),
                ErrorKind::VersionDisplayed => {
                    print_version();
                    Ok(())
                },
                _ => err.exit()
            }
        }
    }
}

#[cfg(test)]
mod test {

    use quickcheck::{TestResult, quickcheck};
    use rand::Rng;
    use super::{integer_value, uuid_value};
    use expectest::prelude::*;

    #[test]
    fn validates_integer_value() {
        fn prop(s: String) -> TestResult {
            let mut rng = ::rand::thread_rng();
            if rng.gen() && s.chars().any(|ch| !ch.is_numeric()) {
                TestResult::discard()
            } else {
                let validation = integer_value(s.clone());
                match validation {
                    Ok(_) => TestResult::from_bool(!s.is_empty() && s.chars().all(|ch| ch.is_numeric() )),
                    Err(_) => TestResult::from_bool(s.is_empty() || s.chars().find(|ch| !ch.is_numeric() ).is_some())
                }
            }
        }
        quickcheck(prop as fn(_) -> _);

        expect!(integer_value(s!("1234"))).to(be_ok());
        expect!(integer_value(s!("1234x"))).to(be_err());
    }

    #[test]
    fn validates_uuid_value() {
        fn prop(s: String) -> TestResult {
            let mut rng = ::rand::thread_rng();
            if rng.gen() && s.chars().any(|ch| !ch.is_digit(16)) {
                TestResult::discard()
            } else {
                let validation = uuid_value(s.clone());
                match validation {
                    Ok(_) => TestResult::from_bool(!s.is_empty() && s.len() == 32 && s.chars().all(|ch| ch.is_digit(16) )),
                    Err(_) => TestResult::from_bool(s.is_empty() || s.len() != 32 || s.chars().find(|ch| !ch.is_digit(16) ).is_some())
                }
            }
        }
        quickcheck(prop as fn(_) -> _);

        expect!(uuid_value(s!("5159135ceb064af8a6baa447d81e4fbd"))).to(be_ok());
        expect!(uuid_value(s!("1234x"))).to(be_err());
    }

}
<commit_msg>add a newline at the end of the help for people with crazy terminal settings<commit_after>//! The `pact_mock_server` crate provides the CLI for the pact mock server for mocking HTTP requests
//! and generating responses based on a pact file. It implements the V1 Pact specification
//! (https://github.com/pact-foundation/pact-specification/tree/version-1).

#![warn(missing_docs)]

#[macro_use] extern crate clap;
#[macro_use] extern crate pact_matching;
extern crate pact_mock_server;
#[macro_use] extern crate rustful;
#[macro_use] extern crate p_macro;
#[macro_use] extern crate log;
#[macro_use] extern crate maplit;
extern crate simplelog;
extern crate uuid;
extern crate rustc_serialize;
#[macro_use] extern crate hyper;
extern crate rand;

#[cfg(test)]
extern crate quickcheck;

#[cfg(test)]
#[macro_use(expect)]
extern crate expectest;

use clap::{Arg, App, SubCommand, AppSettings, ErrorKind, ArgMatches};
use std::env;
use std::str::FromStr;
use std::fs;
use std::io;
use log::{LogLevelFilter};
use simplelog::{CombinedLogger, TermLogger, FileLogger};
use std::path::PathBuf;
use std::fs::OpenOptions;
use uuid::Uuid;
use pact_matching::models::PactSpecification;

fn display_error(error: String, matches: &ArgMatches) -> ! {
    println!("ERROR: {}", error);
    println!("");
    println!("{}", matches.usage());
    panic!("{}", error)
}

mod server;
mod create_mock;
mod list;
mod verify;

fn print_version() {
    println!("\npact mock server version  : v{}", crate_version!());
    println!("pact specification version: v{}", PactSpecification::V1.version_str());
}

fn setup_loggers(level: &str, command: &str, output: Option<&str>) -> Result<(), io::Error> {
    let log_level = match level {
        "none" => LogLevelFilter::Off,
        _ => LogLevelFilter::from_str(level).unwrap()
    };
    if command == "start" {
        let log_file = match output {
            Some(p) => {
                try!(fs::create_dir_all(p));
                let mut path = PathBuf::from(p);
                path.push("pact_v1_mock_server.log");
                path
            },
            None => PathBuf::from("pact_v1_mock_server.log")
        };
        let file = try!(OpenOptions::new()
            .read(false)
            .write(true)
            .append(true)
            .create(true)
            .open(log_file));
        CombinedLogger::init(
            vec![
                TermLogger::new(log_level),
                FileLogger::new(log_level, file)
            ]
        ).unwrap();
    } else {
        TermLogger::init(log_level).unwrap();
    }
    Ok(())
}

fn lookup_global_option<'a>(option: &str, matches: &'a ArgMatches<'a>) -> Option<&'a str> {
    let global_value = matches.value_of(option);
    let command_value = matches.subcommand().1.unwrap().value_of(option);
    match (global_value, command_value) {
        (Some(v), None) => Some(v),
        (None, Some(v)) => Some(v),
        (Some(_), Some(v)) => {
            println!("WARNING: The value for '{}' has been provided twice, defaulting to the second value '{}'",
                option, v);
            Some(v)
        },
        (None, None) => None
    }
}

fn integer_value(v: String) -> Result<(), String> {
    v.parse::<u16>().map(|_| ()).map_err(|e| format!("'{}' is not a valid port value: {}", v, e) )
}

fn uuid_value(v: String) -> Result<(), String> {
    Uuid::parse_str(v.as_str()).map(|_| ()).map_err(|e| format!("'{}' is not a valid UUID value: {}", v, e) )
}

fn main() {
    match handle_command_args() {
        Ok(_) => (),
        Err(err) => std::process::exit(err)
    }
}

fn handle_command_args() -> Result<(), i32> {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let version = format!("v{}", crate_version!());
    let app = App::new(program)
        .version(version.as_str())
        .about("Standalone Pact mock server")
        .version_short("v")
        .setting(AppSettings::ArgRequiredElseHelp)
        .setting(AppSettings::SubcommandRequired)
        .setting(AppSettings::GlobalVersion)
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::ColoredHelp)
        .arg(Arg::with_name("port")
            .short("p")
            .long("port")
            .takes_value(true)
            .use_delimiter(false)
            .global(true)
            .help("port the master mock server runs on (defaults to 8080)"))
        .arg(Arg::with_name("host")
            .short("h")
            .long("host")
            .takes_value(true)
            .use_delimiter(false)
            .global(true)
            .help("hostname the master mock server runs on (defaults to localhost)"))
        .arg(Arg::with_name("loglevel")
            .short("l")
            .long("loglevel")
            .takes_value(true)
            .use_delimiter(false)
            .global(true)
            .possible_values(&["error", "warn", "info", "debug", "trace", "none"])
            .help("Log level for mock servers to write to the log file (defaults to info)"))
        .subcommand(SubCommand::with_name("start")
                .about("Starts the master mock server")
                .setting(AppSettings::ColoredHelp)
                .arg(Arg::with_name("output")
                      .short("o")
                      .long("output")
                      .takes_value(true)
                      .use_delimiter(false)
                      .help("the directory where to write files to (defaults to current directory)")))
        .subcommand(SubCommand::with_name("list")
                .about("Lists all the running mock servers")
                .setting(AppSettings::ColoredHelp))
        .subcommand(SubCommand::with_name("create")
                .about("Creates a new mock server from a pact file")
                .arg(Arg::with_name("file")
                    .short("f")
                    .long("file")
                    .takes_value(true)
                    .use_delimiter(false)
                    .required(true)
                    .help("the pact file to define the mock server"))
                .setting(AppSettings::ColoredHelp))
        .subcommand(SubCommand::with_name("verify")
                .about("Verify the mock server by id or port number, and generate a pact file if all ok")
                .arg(Arg::with_name("mock-server-id")
                    .short("i")
                    .long("mock-server-id")
                    .takes_value(true)
                    .use_delimiter(false)
                    .required_unless("mock-server-port")
                    .conflicts_with("mock-server-port")
                    .help("the ID of the mock server")
                    .validator(uuid_value))
                .arg(Arg::with_name("mock-server-port")
                    .short("m")
                    .long("mock-server-port")
                    .takes_value(true)
                    .use_delimiter(false)
                    .required_unless("mock-server-host")
                    .help("the port number of the mock server")
                    .validator(integer_value))
                .setting(AppSettings::ColoredHelp));

    let matches = app.get_matches_safe();
    match matches {
        Ok(ref matches) => {
            let log_level = lookup_global_option("loglevel", matches);
            if let Err(err) = setup_loggers(log_level.unwrap_or("info"),
                matches.subcommand_name().unwrap(),
                matches.subcommand().1.unwrap().value_of("output")) {
                display_error(format!("Could not setup loggers: {}", err), matches);
            }
            let port = lookup_global_option("port", matches).unwrap_or("8080");
            let host = lookup_global_option("host", matches).unwrap_or("localhost");
            match port.parse::<u16>() {
                Ok(p) => {
                    match matches.subcommand() {
                        ("start", Some(sub_matches)) => server::start_server(p, sub_matches),
                        ("list", Some(sub_matches)) => list::list_mock_servers(host, p, sub_matches),
                        ("create", Some(sub_matches)) => create_mock::create_mock_server(host, p, sub_matches),
                        ("verify", Some(sub_matches)) => verify::verify_mock_server(host, p, sub_matches),
                        _ => Err(3)
                    }
                },
                Err(_) => display_error(format!("{} is not a valid port number", port), matches)
            }
        },
        Err(ref err) => {
            match err.kind {
                ErrorKind::HelpDisplayed => {
                    println!("");
                    Ok(())
                },
                ErrorKind::VersionDisplayed => {
                    print_version();
                    println!("");
                    Ok(())
                },
                _ => {
                    println!("");
                    err.exit()
                }
            }
        }
    }
}

#[cfg(test)]
mod test {

    use quickcheck::{TestResult, quickcheck};
    use rand::Rng;
    use super::{integer_value, uuid_value};
    use expectest::prelude::*;

    #[test]
    fn validates_integer_value() {
        fn prop(s: String) -> TestResult {
            let mut rng = ::rand::thread_rng();
            if rng.gen() && s.chars().any(|ch| !ch.is_numeric()) {
                TestResult::discard()
            } else {
                let validation = integer_value(s.clone());
                match validation {
                    Ok(_) => TestResult::from_bool(!s.is_empty() && s.chars().all(|ch| ch.is_numeric() )),
                    Err(_) => TestResult::from_bool(s.is_empty() || s.chars().find(|ch| !ch.is_numeric() ).is_some())
                }
            }
        }
        quickcheck(prop as fn(_) -> _);

        expect!(integer_value(s!("1234"))).to(be_ok());
        expect!(integer_value(s!("1234x"))).to(be_err());
    }

    #[test]
    fn validates_uuid_value() {
        fn prop(s: String) -> TestResult {
            let mut rng = ::rand::thread_rng();
            if rng.gen() && s.chars().any(|ch| !ch.is_digit(16)) {
                TestResult::discard()
            } else {
                let validation = uuid_value(s.clone());
                match validation {
                    Ok(_) => TestResult::from_bool(!s.is_empty() && s.len() == 32 && s.chars().all(|ch| ch.is_digit(16) )),
                    Err(_) => TestResult::from_bool(s.is_empty() || s.len() != 32 || s.chars().find(|ch| !ch.is_digit(16) ).is_some())
                }
            }
        }
        quickcheck(prop as fn(_) -> _);

        expect!(uuid_value(s!("5159135ceb064af8a6baa447d81e4fbd"))).to(be_ok());
        expect!(uuid_value(s!("1234x"))).to(be_err());
    }

}
<|endoftext|>


<commit_before>extern crate rand;
extern crate image;

// internal crates
extern crate darwin_rs;
extern crate imageproc;
extern crate freetype;

use rand::Rng;
use std::fs::File;
use std::path::Path;
use image::{GenericImage, ImageBuffer, Rgb};
use imageproc::stats::root_mean_squared_error;
use freetype::RenderMode;

#[derive(Debug, Clone)]
struct OCRItem {
    text: String
}

impl Individual for OCRItem {
    fn new() -> OCRItem {
        OCRItem{ text: "abc test".to_string() }
    }

    fn mutate(&mut self) {
    }

    fn calculate_fittness(&self) -> f64 {
        0.0
    }
}

// internal modules
use darwin_rs::{Individual, SimulationBuilder, BuilderResult};

fn main() {
    println!("Darwin test: optical character recognition");

    let tsp_builder = SimulationBuilder::<OCRItem>::new()
        .factor(0.34)
        .threads(2)
        .individuals(100)
        .sorting_fittest()
        .increasing_exp_mutation_rate(1.03)
        .finalize();

        match tsp_builder {
            BuilderResult::TooLowEndIterration => { println!("more than 10 iteratons needed") },
            BuilderResult::TooLowIndividuals => { println!("more than 2 individuals needed") },
            BuilderResult::InvalidFittestCount => { println!("number of random fittest count > number of individuals") },
            BuilderResult::Ok(mut tsp_simulation) => {
                /*
                tsp_simulation.run();

                println!("total run time: {} ms", tsp_simulation.total_time_in_ms);
                println!("improvement factor: {}", tsp_simulation.improvement_factor);
                println!("number of iterations: {}", tsp_simulation.iteration_counter);

                tsp_simulation.print_fittness();
                */
            }
        }

        let img1 = image::open(&Path::new("ocr1.png")).unwrap();
        let img2 = image::open(&Path::new("ocr2.png")).unwrap();
        let mut img3: ImageBuffer<Rgb<u8>, Vec<u8>> = ImageBuffer::new(640, 480);

        println!("dimensions1 {:?}", img1.dimensions());
        println!("dimensions2 {:?}", img2.dimensions());
        println!("dimensions3 {:?}", img3.dimensions());

        println!("color1: {:?}", img1.color());
        println!("color2: {:?}", img2.color());
        // println!("color3: {:?}", img3.color());

        let error = root_mean_squared_error(&img1, &img2);

        println!("error1: {}", error);

        let ft_library = freetype::Library::init().unwrap();
        let face = ft_library.new_face("/usr/share/fonts/truetype/freefont/FreeMono.ttf", 0).unwrap();
        face.set_char_size(40 * 64, 0, 50, 0).unwrap();
        face.load_char(65, freetype::face::RENDER | freetype::face::TARGET_LCD).unwrap();
        let glyph = face.glyph();
        // glyph.render_glyph(RenderMode::Lcd);
        let x = glyph.bitmap_left() as usize;
        let y = glyph.bitmap_top() as usize;
        let bm = glyph.bitmap();
        let bm_slice = bm.buffer().to_vec();

        println!("x: {}, y: {}, width: {}, rows: {}, len: {}, pitch: {}", x, y, bm.width(), bm.rows(), bm_slice.len(), bm.pitch());
        println!("pixel mode: {:?}", bm.pixel_mode());

        let img4: ImageBuffer<Rgb<u8>, Vec<u8>> = ImageBuffer::from_vec(128, 128, bm_slice ).unwrap();
}
<commit_msg>use correct image buffer size, save rendered glyph to disk<commit_after>extern crate rand;
extern crate image;
extern crate imageproc;
extern crate freetype;

// internal crates
extern crate darwin_rs;

use rand::Rng;
use std::fs::File;
use std::path::Path;
use image::{GenericImage, ImageBuffer, Rgb};
use imageproc::stats::root_mean_squared_error;
use freetype::RenderMode;

#[derive(Debug, Clone)]
struct OCRItem {
    text: String
}

impl Individual for OCRItem {
    fn new() -> OCRItem {
        OCRItem{ text: "abc test".to_string() }
    }

    fn mutate(&mut self) {
    }

    fn calculate_fittness(&self) -> f64 {
        0.0
    }
}

// internal modules
use darwin_rs::{Individual, SimulationBuilder, BuilderResult};

fn main() {
    println!("Darwin test: optical character recognition");

    let tsp_builder = SimulationBuilder::<OCRItem>::new()
        .factor(0.34)
        .threads(2)
        .individuals(100)
        .sorting_fittest()
        .increasing_exp_mutation_rate(1.03)
        .finalize();

        match tsp_builder {
            BuilderResult::TooLowEndIterration => { println!("more than 10 iteratons needed") },
            BuilderResult::TooLowIndividuals => { println!("more than 2 individuals needed") },
            BuilderResult::InvalidFittestCount => { println!("number of random fittest count > number of individuals") },
            BuilderResult::Ok(mut tsp_simulation) => {
                /*
                tsp_simulation.run();

                println!("total run time: {} ms", tsp_simulation.total_time_in_ms);
                println!("improvement factor: {}", tsp_simulation.improvement_factor);
                println!("number of iterations: {}", tsp_simulation.iteration_counter);

                tsp_simulation.print_fittness();
                */
            }
        }

//        let img1 = image::open(&Path::new("ocr1.png")).unwrap();
//        let img2 = image::open(&Path::new("ocr2.png")).unwrap();
        let mut img3: ImageBuffer<Rgb<u8>, Vec<u8>> = ImageBuffer::new(640, 480);

//        println!("dimensions1 {:?}", img1.dimensions());
//        println!("dimensions2 {:?}", img2.dimensions());
        println!("dimensions3 {:?}", img3.dimensions());

//        println!("color1: {:?}", img1.color());
//        println!("color2: {:?}", img2.color());
        // println!("color3: {:?}", img3.color());

//        let error = root_mean_squared_error(&img1, &img2);

//        println!("error1: {}", error);

        let ft_library = freetype::Library::init().unwrap();
        let face = ft_library.new_face("/usr/share/fonts/truetype/freefont/FreeMono.ttf", 0).unwrap();
        face.set_char_size(40 * 64, 0, 50, 0).unwrap();
        face.load_char(65, freetype::face::RENDER | freetype::face::TARGET_LCD).unwrap();
        let glyph = face.glyph();
        // glyph.render_glyph(RenderMode::Lcd);
        let x = glyph.bitmap_left() as usize;
        let y = glyph.bitmap_top() as usize;
        let bm = glyph.bitmap();
        let bm_slice = bm.buffer().to_vec();

        println!("x: {}, y: {}, width: {}, rows: {}, len: {}, pitch: {}", x, y, bm.width(), bm.rows(), bm_slice.len(), bm.pitch());
        println!("pixel mode: {:?}", bm.pixel_mode());

        let img4: ImageBuffer<Rgb<u8>, Vec<u8>> = ImageBuffer::from_vec(17, 16, bm_slice ).unwrap();
        let fout = Path::new("char1.png");
        let _ = img4.save(&fout);
}
<|endoftext|>


<commit_before>//! Traps and notifies UNIX signals.

use crate::os::process::SignalCode;
use std::{io,
          mem,
          ptr,
          sync::{atomic::{AtomicBool,
                          Ordering},
                 Once},
          thread};

static INIT: Once = Once::new();
static PENDING_HUP: AtomicBool = AtomicBool::new(false);
static PENDING_CHLD: AtomicBool = AtomicBool::new(false);

pub fn init() {
    INIT.call_once(|| {
            // TODO(ssd) 2019-10-16: We could bubble this error up
            // further if we want, but in either case this should be a
            // hard failure.
            self::start_signal_handler().expect("starting signal handler failed");
        });
}

pub fn pending_sighup() -> bool { PENDING_HUP.compare_and_swap(true, false, Ordering::SeqCst) }
pub fn pending_sigchld() -> bool { PENDING_CHLD.compare_and_swap(true, false, Ordering::SeqCst) }

fn start_signal_handler() -> io::Result<()> {
    let mut handled_signals = Sigset::empty()?;
    handled_signals.addsig(libc::SIGINT)?;
    handled_signals.addsig(libc::SIGTERM)?;
    handled_signals.addsig(libc::SIGHUP)?;
    handled_signals.addsig(libc::SIGCHLD)?;

    // The following signals have no defined behavior. They are left
    // "handled" to preserve past behavior since handling them we
    // don't get their default behavior.
    handled_signals.addsig(libc::SIGQUIT)?;
    handled_signals.addsig(libc::SIGALRM)?;
    handled_signals.addsig(libc::SIGUSR1)?;
    handled_signals.addsig(libc::SIGUSR2)?;

    handled_signals.setsigmask()?;
    thread::Builder::new().name("signal-handler".to_string())
                          .spawn(move || process_signals(&handled_signals))?;
    Ok(())
}

fn process_signals(handled_signals: &Sigset) {
    loop {
        // Using expect here seems reasonable because our
        // understanding of wait() is that it only returns an error if
        // we called it with a bad signal.
        let signal = handled_signals.wait().expect("sigwait failed");
        debug!("signal-handler thread received signal #{}", signal);
        match signal {
            libc::SIGINT | libc::SIGTERM => {
                super::SHUTDOWN.store(true, Ordering::SeqCst);
            }
            libc::SIGHUP => {
                PENDING_HUP.store(true, Ordering::SeqCst);
            }
            libc::SIGCHLD => {
                PENDING_CHLD.store(true, Ordering::SeqCst);
            }
            _ => {
                debug!("signal #{} handled but ignored", signal);
            }
        };
    }
}

/// Sigset is a wrapper for the underlying libc type.
struct Sigset {
    inner: libc::sigset_t,
}

impl Sigset {
    /// empty returns an empty Sigset.
    ///
    /// For more information on the relevant libc function see:
    ///
    /// http://man7.org/linux/man-pages/man3/sigsetops.3.html
    fn empty() -> io::Result<Sigset> {
        let mut set: libc::sigset_t = unsafe { mem::zeroed() };
        let ret = unsafe { libc::sigemptyset(&mut set) };
        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(Sigset { inner: set })
        }
    }

    /// addsig adds the given signal to the Sigset.
    ///
    /// For more information on the relevant libc function see:
    ///
    /// http://man7.org/linux/man-pages/man3/sigsetops.3.html
    fn addsig(&mut self, signal: SignalCode) -> io::Result<()> {
        let ret = unsafe { libc::sigaddset(&mut self.inner, signal) };
        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(())
        }
    }

    /// setsigmask sets the calling thread's signal mask to the current
    /// sigmask, blocking delivery of all signals in the sigmask.
    ///
    /// This should be called before wait() to avoid race conditions.
    ///
    /// For more information on the relevant libc function see:
    ///
    /// http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html
    fn setsigmask(&self) -> io::Result<()> {
        let ret = unsafe { libc::pthread_sigmask(libc::SIG_SETMASK, &self.inner, ptr::null_mut()) };
        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(())
        }
    }

    /// wait blocks until a signal in the current sigset has been
    /// delivered to the thread.
    ///
    /// Callers should call setsigmask() before this function to avoid
    /// race conditions.
    ///
    /// For information on the relevant libc function see:
    ///
    /// http://man7.org/linux/man-pages/man3/sigwait.3.html
    ///
    /// The manual page on linux only lists a single failure case:
    ///
    /// > EINVAL set contains an invalid signal number.
    ///
    /// thus most callers should be able to expect success.
    fn wait(&self) -> io::Result<SignalCode> {
        let mut signal: libc::c_int = 0;
        let ret = unsafe { libc::sigwait(&self.inner, &mut signal) };
        if ret != 0 {
            Err(io::Error::from_raw_os_error(ret))
        } else {
            Ok(signal)
        }
    }
}
<commit_msg>fix linux clippy errors<commit_after>//! Traps and notifies UNIX signals.

use crate::os::process::SignalCode;
use std::{io,
          mem,
          ptr,
          sync::{atomic::{AtomicBool,
                          Ordering},
                 Once},
          thread};

static INIT: Once = Once::new();
static PENDING_HUP: AtomicBool = AtomicBool::new(false);
static PENDING_CHLD: AtomicBool = AtomicBool::new(false);

pub fn init() {
    INIT.call_once(|| {
            // TODO(ssd) 2019-10-16: We could bubble this error up
            // further if we want, but in either case this should be a
            // hard failure.
            self::start_signal_handler().expect("starting signal handler failed");
        });
}

pub fn pending_sighup() -> bool {
    PENDING_HUP.compare_exchange(true, false, Ordering::SeqCst, Ordering::SeqCst)
               .unwrap_or_else(core::convert::identity)
}
pub fn pending_sigchld() -> bool {
    PENDING_CHLD.compare_exchange(true, false, Ordering::SeqCst, Ordering::SeqCst)
                .unwrap_or_else(core::convert::identity)
}

fn start_signal_handler() -> io::Result<()> {
    let mut handled_signals = Sigset::empty()?;
    handled_signals.addsig(libc::SIGINT)?;
    handled_signals.addsig(libc::SIGTERM)?;
    handled_signals.addsig(libc::SIGHUP)?;
    handled_signals.addsig(libc::SIGCHLD)?;

    // The following signals have no defined behavior. They are left
    // "handled" to preserve past behavior since handling them we
    // don't get their default behavior.
    handled_signals.addsig(libc::SIGQUIT)?;
    handled_signals.addsig(libc::SIGALRM)?;
    handled_signals.addsig(libc::SIGUSR1)?;
    handled_signals.addsig(libc::SIGUSR2)?;

    handled_signals.setsigmask()?;
    thread::Builder::new().name("signal-handler".to_string())
                          .spawn(move || process_signals(&handled_signals))?;
    Ok(())
}

fn process_signals(handled_signals: &Sigset) {
    loop {
        // Using expect here seems reasonable because our
        // understanding of wait() is that it only returns an error if
        // we called it with a bad signal.
        let signal = handled_signals.wait().expect("sigwait failed");
        debug!("signal-handler thread received signal #{}", signal);
        match signal {
            libc::SIGINT | libc::SIGTERM => {
                super::SHUTDOWN.store(true, Ordering::SeqCst);
            }
            libc::SIGHUP => {
                PENDING_HUP.store(true, Ordering::SeqCst);
            }
            libc::SIGCHLD => {
                PENDING_CHLD.store(true, Ordering::SeqCst);
            }
            _ => {
                debug!("signal #{} handled but ignored", signal);
            }
        };
    }
}

/// Sigset is a wrapper for the underlying libc type.
struct Sigset {
    inner: libc::sigset_t,
}

impl Sigset {
    /// empty returns an empty Sigset.
    ///
    /// For more information on the relevant libc function see:
    ///
    /// http://man7.org/linux/man-pages/man3/sigsetops.3.html
    fn empty() -> io::Result<Sigset> {
        let mut set: libc::sigset_t = unsafe { mem::zeroed() };
        let ret = unsafe { libc::sigemptyset(&mut set) };
        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(Sigset { inner: set })
        }
    }

    /// addsig adds the given signal to the Sigset.
    ///
    /// For more information on the relevant libc function see:
    ///
    /// http://man7.org/linux/man-pages/man3/sigsetops.3.html
    fn addsig(&mut self, signal: SignalCode) -> io::Result<()> {
        let ret = unsafe { libc::sigaddset(&mut self.inner, signal) };
        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(())
        }
    }

    /// setsigmask sets the calling thread's signal mask to the current
    /// sigmask, blocking delivery of all signals in the sigmask.
    ///
    /// This should be called before wait() to avoid race conditions.
    ///
    /// For more information on the relevant libc function see:
    ///
    /// http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html
    fn setsigmask(&self) -> io::Result<()> {
        let ret = unsafe { libc::pthread_sigmask(libc::SIG_SETMASK, &self.inner, ptr::null_mut()) };
        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(())
        }
    }

    /// wait blocks until a signal in the current sigset has been
    /// delivered to the thread.
    ///
    /// Callers should call setsigmask() before this function to avoid
    /// race conditions.
    ///
    /// For information on the relevant libc function see:
    ///
    /// http://man7.org/linux/man-pages/man3/sigwait.3.html
    ///
    /// The manual page on linux only lists a single failure case:
    ///
    /// > EINVAL set contains an invalid signal number.
    ///
    /// thus most callers should be able to expect success.
    fn wait(&self) -> io::Result<SignalCode> {
        let mut signal: libc::c_int = 0;
        let ret = unsafe { libc::sigwait(&self.inner, &mut signal) };
        if ret != 0 {
            Err(io::Error::from_raw_os_error(ret))
        } else {
            Ok(signal)
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! DOM bindings for `CharacterData`.

use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
use dom::bindings::codegen::InheritTypes::{CharacterDataDerived, NodeCast};
use dom::bindings::error::{Fallible, ErrorResult, IndexSize};
use dom::bindings::js::JSRef;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::node::{CommentNodeTypeId, Node, NodeTypeId, TextNodeTypeId, ProcessingInstructionNodeTypeId, NodeHelpers};
use servo_util::str::DOMString;

use std::cell::{Ref, RefCell};
use std::mem;

#[jstraceable]
#[must_root]
#[privatize]
pub struct CharacterData {
    node: Node,
    data: RefCell<DOMString>,
}

impl CharacterDataDerived for EventTarget {
    fn is_characterdata(&self) -> bool {
        match *self.type_id() {
            NodeTargetTypeId(TextNodeTypeId) |
            NodeTargetTypeId(CommentNodeTypeId) |
            NodeTargetTypeId(ProcessingInstructionNodeTypeId) => true,
            _ => false
        }
    }
}

impl CharacterData {
    pub fn new_inherited(id: NodeTypeId, data: DOMString, document: JSRef<Document>) -> CharacterData {
        CharacterData {
            node: Node::new_inherited(id, document),
            data: RefCell::new(data),
        }
    }

    #[inline]
    pub fn node<'a>(&'a self) -> &'a Node {
        &self.node
    }

    #[inline]
    pub fn data(&self) -> Ref<DOMString> {
        self.data.borrow()
    }

    #[inline]
    pub fn set_data(&self, data: DOMString) {
        *self.data.borrow_mut() = data;
    }

    #[inline]
    pub unsafe fn data_for_layout<'a>(&'a self) -> &'a str {
        mem::transmute::<&RefCell<DOMString>, &DOMString>(&self.data).as_slice()
    }

}

impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> {
    fn Data(self) -> DOMString {
        self.data.borrow().clone()
    }

    fn SetData(self, arg: DOMString) -> ErrorResult {
        *self.data.borrow_mut() = arg;
        Ok(())
    }

    fn Length(self) -> u32 {
        self.data.borrow().len() as u32
    }

    fn SubstringData(self, offset: u32, count: u32) -> Fallible<DOMString> {
        Ok(self.data.borrow().as_slice().slice(offset as uint, count as uint).to_string())
    }

    fn AppendData(self, arg: DOMString) -> ErrorResult {
        self.data.borrow_mut().push_str(arg.as_slice());
        Ok(())
    }

    fn InsertData(self, offset: u32, arg: DOMString) -> ErrorResult {
        self.ReplaceData(offset, 0, arg)
    }

    fn DeleteData(self, offset: u32, count: u32) -> ErrorResult {
        self.ReplaceData(offset, count, "".to_string())
    }

    fn ReplaceData(self, offset: u32, count: u32, arg: DOMString) -> ErrorResult {
        let length = self.data.borrow().len() as u32;
        if offset > length {
            return Err(IndexSize);
        }
        let count = if offset + count > length {
            length - offset
        } else {
            count
        };
        let mut data = self.data.borrow().as_slice().slice(0, offset as uint).to_string();
        data.push_str(arg.as_slice());
        data.push_str(self.data.borrow().as_slice().slice((offset + count) as uint, length as uint));
        *self.data.borrow_mut() = data;
        // FIXME: Once we have `Range`, we should implement step7 to step11
        Ok(())
    }

    // http://dom.spec.whatwg.org/#dom-childnode-remove
    fn Remove(self) {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        node.remove_self();
    }
}

impl Reflectable for CharacterData {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.node.reflector()
    }
}
<commit_msg>Use DOMRefCell<T> in CharacterData.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! DOM bindings for `CharacterData`.

use dom::bindings::cell::{DOMRefCell, Ref};
use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
use dom::bindings::codegen::InheritTypes::{CharacterDataDerived, NodeCast};
use dom::bindings::error::{Fallible, ErrorResult, IndexSize};
use dom::bindings::js::JSRef;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::node::{CommentNodeTypeId, Node, NodeTypeId, TextNodeTypeId, ProcessingInstructionNodeTypeId, NodeHelpers};
use servo_util::str::DOMString;

#[jstraceable]
#[must_root]
#[privatize]
pub struct CharacterData {
    node: Node,
    data: DOMRefCell<DOMString>,
}

impl CharacterDataDerived for EventTarget {
    fn is_characterdata(&self) -> bool {
        match *self.type_id() {
            NodeTargetTypeId(TextNodeTypeId) |
            NodeTargetTypeId(CommentNodeTypeId) |
            NodeTargetTypeId(ProcessingInstructionNodeTypeId) => true,
            _ => false
        }
    }
}

impl CharacterData {
    pub fn new_inherited(id: NodeTypeId, data: DOMString, document: JSRef<Document>) -> CharacterData {
        CharacterData {
            node: Node::new_inherited(id, document),
            data: DOMRefCell::new(data),
        }
    }

    #[inline]
    pub fn node<'a>(&'a self) -> &'a Node {
        &self.node
    }

    #[inline]
    pub fn data(&self) -> Ref<DOMString> {
        self.data.borrow()
    }

    #[inline]
    pub fn set_data(&self, data: DOMString) {
        *self.data.borrow_mut() = data;
    }

    #[inline]
    pub unsafe fn data_for_layout<'a>(&'a self) -> &'a str {
        self.data.borrow_for_layout().as_slice()
    }

}

impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> {
    fn Data(self) -> DOMString {
        self.data.borrow().clone()
    }

    fn SetData(self, arg: DOMString) -> ErrorResult {
        *self.data.borrow_mut() = arg;
        Ok(())
    }

    fn Length(self) -> u32 {
        self.data.borrow().len() as u32
    }

    fn SubstringData(self, offset: u32, count: u32) -> Fallible<DOMString> {
        Ok(self.data.borrow().as_slice().slice(offset as uint, count as uint).to_string())
    }

    fn AppendData(self, arg: DOMString) -> ErrorResult {
        self.data.borrow_mut().push_str(arg.as_slice());
        Ok(())
    }

    fn InsertData(self, offset: u32, arg: DOMString) -> ErrorResult {
        self.ReplaceData(offset, 0, arg)
    }

    fn DeleteData(self, offset: u32, count: u32) -> ErrorResult {
        self.ReplaceData(offset, count, "".to_string())
    }

    fn ReplaceData(self, offset: u32, count: u32, arg: DOMString) -> ErrorResult {
        let length = self.data.borrow().len() as u32;
        if offset > length {
            return Err(IndexSize);
        }
        let count = if offset + count > length {
            length - offset
        } else {
            count
        };
        let mut data = self.data.borrow().as_slice().slice(0, offset as uint).to_string();
        data.push_str(arg.as_slice());
        data.push_str(self.data.borrow().as_slice().slice((offset + count) as uint, length as uint));
        *self.data.borrow_mut() = data;
        // FIXME: Once we have `Range`, we should implement step7 to step11
        Ok(())
    }

    // http://dom.spec.whatwg.org/#dom-childnode-remove
    fn Remove(self) {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        node.remove_self();
    }
}

impl Reflectable for CharacterData {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.node.reflector()
    }
}
<|endoftext|>