<commit_before>use alloc::boxed::Box;
use collections::string::String;
use collections::string::ToString;
use collections::vec::Vec;

use core::fmt::{Debug, Formatter, Error};

use super::termlist::parse_term_list;
use super::namedobj::{ RegionSpace, FieldFlags };
use super::parser::{AmlExecutionContext, ExecutionState};
use super::AmlError;

#[derive(Clone)]
pub enum FieldSelector {
    Region(String),
    Bank {
        region: String,
        bank_selector: Box<AmlValue>
    },
    Index {
        index_selector: String,
        data_selector: String
    }
}

#[derive(Clone)]
pub enum ObjectReference {
    ArgObj(u8),
    LocalObj(u8),
    NamedObj(String),
    Object(Box<AmlValue>),
    Index(Box<AmlValue>, Box<AmlValue>)
}

#[derive(Clone)]
pub struct Method {
    pub arg_count: u8,
    pub serialized: bool,
    pub sync_level: u8,
    pub term_list: Vec<u8>
}

pub struct Accessor {
    pub read: fn(usize) -> u64,
    pub write: fn(usize, u64)
}

impl Clone for Accessor {
    fn clone(&self) -> Accessor {
        Accessor {
            read: (*self).read,
            write: (*self).write
        }
    }
}

#[derive(Clone)]
pub enum AmlValue {
    None,
    Uninitialized,
    Buffer(Vec<u8>),
    BufferField {
        source_buf: Box<AmlValue>,
        index: Box<AmlValue>,
        length: Box<AmlValue>
    },
    DDBHandle(Vec<String>),
    DebugObject,
    Device(Vec<String>),
    Event(u64),
    FieldUnit {
        selector: FieldSelector,
        connection: Box<AmlValue>,
        flags: FieldFlags,
        offset: usize,
        length: usize
    },
    Integer(u64),
    IntegerConstant(u64),
    Method(Method),
    Mutex((u8, Option<u64>)),
    ObjectReference(ObjectReference),
    OperationRegion {
        region: RegionSpace,
        offset: Box<AmlValue>,
        len: Box<AmlValue>,
        accessor: Accessor,
        accessed_by: Option<u64>
    },
    Package(Vec<AmlValue>),
    String(String),
    PowerResource {
        system_level: u8,
        resource_order: u16,
        obj_list: Vec<String>
    },
    Processor {
        proc_id: u8,
        p_blk: Option<u32>,
        obj_list: Vec<String>
    },
    RawDataBuffer(Vec<u8>),
    ThermalZone(Vec<String>)
}

impl Debug for AmlValue {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { Ok(()) }
}

impl AmlValue {
    pub fn get_as_event(&self) -> Result<u64, AmlError> {
        match *self {
            AmlValue::Event(ref e) => Ok(e.clone()),
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_as_ddb_handle(&self) -> Result<Vec<String>, AmlError> {
        match *self {
            AmlValue::DDBHandle(ref v) => Ok(v.clone()),
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_as_string(&self) -> Result<String, AmlError> {
        match *self {
            AmlValue::String(ref s) => Ok(s.clone()),
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_as_buffer(&self) -> Result<Vec<u8>, AmlError> {
        match *self {
            AmlValue::Buffer(ref b) => Ok(b.clone()),
            AmlValue::Integer(ref i) => {
                let mut v: Vec<u8> = vec!();
                let mut i = i.clone();

                while i != 0 {
                    v.push((i & 0xFF) as u8);
                    i >>= 8;
                }

                while v.len() < 8 {
                    v.push(0);
                }

                Ok(v)
            },
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_as_package(&self) -> Result<Vec<AmlValue>, AmlError> {
        match *self {
            AmlValue::Package(ref p) => Ok(p.clone()),
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_as_integer(&self) -> Result<u64, AmlError> {
        match *self {
            AmlValue::IntegerConstant(ref i) => Ok(i.clone()),
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_as_method(&self) -> Result<Method, AmlError> {
        match *self {
            AmlValue::Method(ref m) => Ok(m.clone()),
            _ => Err(AmlError::AmlValueError)
        }
    }
}

impl Method {
    pub fn execute(&self, scope: String, parameters: Vec<AmlValue>) -> AmlValue {
        let mut ctx = AmlExecutionContext::new(scope);
        ctx.init_arg_vars(parameters);

        parse_term_list(&self.term_list[..], &mut ctx);
        ctx.clean_namespace();

        match ctx.state {
            ExecutionState::RETURN(v) => v,
            _ => AmlValue::IntegerConstant(0)
        }
    }
}

pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> Result<String, AmlError> {
    let mut modifier = modifier_v.get_as_string()?;

    if current.len() == 0 {
        return Ok(modifier);
    }

    if modifier.len() == 0 {
        return Ok(current);
    }

    if modifier.starts_with("\\") {
        return Ok(modifier);
    }

    let mut namespace = current.clone();

    if modifier.starts_with("^") {
        while modifier.starts_with("^") {
            modifier = modifier[1..].to_string();

            if namespace.ends_with("\\") {
                return Err(AmlError::AmlValueError);
            }

            loop {
                if namespace.ends_with(".") {
                    namespace.pop();
                    break;
                }

                if namespace.pop() == None {
                    return Err(AmlError::AmlValueError);
                }
            }
        }
    }

    if !namespace.ends_with("\\") {
        namespace.push('.');
    }

    Ok(namespace + &modifier)
}
<commit_msg>Converted string to buffer<commit_after>use alloc::boxed::Box;
use collections::string::String;
use collections::string::ToString;
use collections::vec::Vec;

use core::fmt::{Debug, Formatter, Error};

use super::termlist::parse_term_list;
use super::namedobj::{ RegionSpace, FieldFlags };
use super::parser::{AmlExecutionContext, ExecutionState};
use super::AmlError;

#[derive(Clone)]
pub enum FieldSelector {
    Region(String),
    Bank {
        region: String,
        bank_selector: Box<AmlValue>
    },
    Index {
        index_selector: String,
        data_selector: String
    }
}

#[derive(Clone)]
pub enum ObjectReference {
    ArgObj(u8),
    LocalObj(u8),
    NamedObj(String),
    Object(Box<AmlValue>),
    Index(Box<AmlValue>, Box<AmlValue>)
}

#[derive(Clone)]
pub struct Method {
    pub arg_count: u8,
    pub serialized: bool,
    pub sync_level: u8,
    pub term_list: Vec<u8>
}

pub struct Accessor {
    pub read: fn(usize) -> u64,
    pub write: fn(usize, u64)
}

impl Clone for Accessor {
    fn clone(&self) -> Accessor {
        Accessor {
            read: (*self).read,
            write: (*self).write
        }
    }
}

#[derive(Clone)]
pub enum AmlValue {
    None,
    Uninitialized,
    Buffer(Vec<u8>),
    BufferField {
        source_buf: Box<AmlValue>,
        index: Box<AmlValue>,
        length: Box<AmlValue>
    },
    DDBHandle(Vec<String>),
    DebugObject,
    Device(Vec<String>),
    Event(u64),
    FieldUnit {
        selector: FieldSelector,
        connection: Box<AmlValue>,
        flags: FieldFlags,
        offset: usize,
        length: usize
    },
    Integer(u64),
    IntegerConstant(u64),
    Method(Method),
    Mutex((u8, Option<u64>)),
    ObjectReference(ObjectReference),
    OperationRegion {
        region: RegionSpace,
        offset: Box<AmlValue>,
        len: Box<AmlValue>,
        accessor: Accessor,
        accessed_by: Option<u64>
    },
    Package(Vec<AmlValue>),
    String(String),
    PowerResource {
        system_level: u8,
        resource_order: u16,
        obj_list: Vec<String>
    },
    Processor {
        proc_id: u8,
        p_blk: Option<u32>,
        obj_list: Vec<String>
    },
    RawDataBuffer(Vec<u8>),
    ThermalZone(Vec<String>)
}

impl Debug for AmlValue {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { Ok(()) }
}

impl AmlValue {
    pub fn get_as_event(&self) -> Result<u64, AmlError> {
        match *self {
            AmlValue::Event(ref e) => Ok(e.clone()),
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_as_ddb_handle(&self) -> Result<Vec<String>, AmlError> {
        match *self {
            AmlValue::DDBHandle(ref v) => Ok(v.clone()),
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_as_string(&self) -> Result<String, AmlError> {
        match *self {
            AmlValue::String(ref s) => Ok(s.clone()),
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_as_buffer(&self) -> Result<Vec<u8>, AmlError> {
        match *self {
            AmlValue::Buffer(ref b) => Ok(b.clone()),
            AmlValue::Integer(ref i) => {
                let mut v: Vec<u8> = vec!();
                let mut i = i.clone();

                while i != 0 {
                    v.push((i & 0xFF) as u8);
                    i >>= 8;
                }

                while v.len() < 8 {
                    v.push(0);
                }

                Ok(v)
            },
            AmlValue::String(ref s) => {
                Ok(s.clone().into_bytes())
            },
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_as_package(&self) -> Result<Vec<AmlValue>, AmlError> {
        match *self {
            AmlValue::Package(ref p) => Ok(p.clone()),
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_as_integer(&self) -> Result<u64, AmlError> {
        match *self {
            AmlValue::IntegerConstant(ref i) => Ok(i.clone()),
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_as_method(&self) -> Result<Method, AmlError> {
        match *self {
            AmlValue::Method(ref m) => Ok(m.clone()),
            _ => Err(AmlError::AmlValueError)
        }
    }
}

impl Method {
    pub fn execute(&self, scope: String, parameters: Vec<AmlValue>) -> AmlValue {
        let mut ctx = AmlExecutionContext::new(scope);
        ctx.init_arg_vars(parameters);

        parse_term_list(&self.term_list[..], &mut ctx);
        ctx.clean_namespace();

        match ctx.state {
            ExecutionState::RETURN(v) => v,
            _ => AmlValue::IntegerConstant(0)
        }
    }
}

pub fn get_namespace_string(current: String, modifier_v: AmlValue) -> Result<String, AmlError> {
    let mut modifier = modifier_v.get_as_string()?;

    if current.len() == 0 {
        return Ok(modifier);
    }

    if modifier.len() == 0 {
        return Ok(current);
    }

    if modifier.starts_with("\\") {
        return Ok(modifier);
    }

    let mut namespace = current.clone();

    if modifier.starts_with("^") {
        while modifier.starts_with("^") {
            modifier = modifier[1..].to_string();

            if namespace.ends_with("\\") {
                return Err(AmlError::AmlValueError);
            }

            loop {
                if namespace.ends_with(".") {
                    namespace.pop();
                    break;
                }

                if namespace.pop() == None {
                    return Err(AmlError::AmlValueError);
                }
            }
        }
    }

    if !namespace.ends_with("\\") {
        namespace.push('.');
    }

    Ok(namespace + &modifier)
}
<|endoftext|>


<commit_before>

use rustful::{Server, Handler, Context, Response, TreeRouter};

fn list_root(context: Context, mut response: Response) {
    response.send("Hello World!");
}

pub fn start_command() {
    let my_router = insert_routes!{
        TreeRouter::new() => {
            // //Receive GET requests to /hello and /hello/:name
            // "hello" => {
            //     Get: Greeting("hello"),
            //     ":name" => Get: Greeting("hello")
            // },
            // //Receive GET requests to /good_bye and /good_bye/:name
            // "good_bye" => {
            //     Get: Greeting("good bye"),
            //     ":name" => Get: Greeting("good bye")
            // }

            Get: list_root
        }
    };

    let server_result = Server {
        handlers: my_router,
        host: 8080.into(),
        ..Server::default()
    }.run();

    match server_result {
        Ok(server) => info!("Server started on port {}", server.socket.port()),
        Err(e) => panic!("could not start server: {}", e)
    }
}
<commit_msg>implemented main server that creates a child server on a post request<commit_after>

use rustful::{Server, Handler, Context, Response, TreeRouter};
use std::thread;
use std::sync::mpsc::channel;
use rustful::StatusCode;

fn list_root(context: Context, mut response: Response) {
    response.send("Hello World!");
}

fn start_provider(context: Context, mut response: Response) {
    let my_router = insert_routes!{
        TreeRouter::new() => {
            Get: list_root
        }
    };

    let (tx, rx) = channel();
    let child = thread::spawn(move || {
        let server_result = Server {
            handlers: my_router,
            host: 8081.into(),
            ..Server::default()
        }.run();

        match server_result {
            Ok(server) => {
                info!("Provider Server started on port {}", server.socket.port());
                tx.send("OK".to_string()).unwrap();
                tx.send(format!("Provider Server started on port {}", server.socket.port())).unwrap();
            },
            Err(e) => {
                error!("could not start server: {}", e);
                tx.send("ERROR".to_string()).unwrap();
                tx.send(format!("could not start server: {}", e));
            }
        }
    });
    match &*rx.recv().unwrap() {
        "OK" => response.set_status(StatusCode::Ok),
        _ => response.set_status(StatusCode::BadRequest)
    }
    response.send(rx.recv().unwrap());
}

pub fn start_command() {
    let my_router = insert_routes!{
        TreeRouter::new() => {
            // Get: list_root,
            Post: start_provider
        }
    };

    let server_result = Server {
        handlers: my_router,
        host: 8080.into(),
        ..Server::default()
    }.run();

    match server_result {
        Ok(server) => info!("Server started on port {}", server.socket.port()),
        Err(e) => panic!("could not start server: {}", e)
    }
}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::collections::HashSet;

use crate::assertions::iterator::IteratorAssertion;
use crate::base::{AssertionApi, AssertionResult, Fact, ReturnStrategy, Subject};
use crate::testing::CheckThatResult;

pub trait AssertionResultAssertion<'a, R> {
    fn facts_are<B: Borrow<Vec<Fact>>>(&self, facts: B) -> R;
    fn facts_are_at_least<B: Borrow<Vec<Fact>>>(&self, facts: B) -> R;
    // Returns subject of fact value for the first matched key.
    fn fact_value_for_key<I: Into<String>>(&self, key: I) -> Subject<String, (), R>;
    fn fact_keys(&self) -> Subject<'a, HashSet<&String>, (), R>;
}

fn get_assertion_result<'a, 'o, R>(
    subject: &'o Subject<'a, CheckThatResult, (), R>,
) -> &'o AssertionResult {
    subject
        .actual()
        .as_ref()
        .expect_err("Because this is assertion for error message.")
}

impl<'a, R> AssertionResultAssertion<'a, R> for Subject<'a, CheckThatResult, (), R>
where
    AssertionResult: ReturnStrategy<R>,
{
    fn facts_are<B: Borrow<Vec<Fact>>>(&self, expected: B) -> R {
        self.new_owned_subject(
            get_assertion_result(&self).facts().iter(),
            Some(format!("{}.facts()", self.description_or_expr())),
            (),
        )
        .contains_exactly_in_order(expected.borrow().iter())
    }

    fn facts_are_at_least<B: Borrow<Vec<Fact>>>(&self, facts: B) -> R {
        self.new_owned_subject(
            get_assertion_result(&self).facts().iter(),
            Some(format!("{}.facts()", self.description_or_expr())),
            (),
        )
        .contains_at_least_in_order(facts.borrow().iter())
    }

    fn fact_value_for_key<I: Into<String>>(&self, key: I) -> Subject<String, (), R> {
        let key_str = key.into();
        let assertion_result = get_assertion_result(&self);
        let value = assertion_result
            .facts()
            .iter()
            .flat_map(|fact| match fact {
                Fact::KeyValue { key: k, value } if k.eq(&key_str) => Some(value),
                _ => None,
            })
            .next()
            .expect(&format!(
                "key `{}` not found in assertion result.\n{:?}",
                key_str,
                assertion_result.generate_message()
            ))
            .clone();
        self.new_owned_subject(
            value,
            Some(format!("{}.[key={}]", self.description_or_expr(), key_str)),
            (),
        )
    }

    fn fact_keys(&self) -> Subject<HashSet<&String>, (), R> {
        let assertion_result = get_assertion_result(self);
        let keys: HashSet<&String> = assertion_result
            .facts()
            .iter()
            .flat_map(|fact| match fact {
                Fact::KeyValue { key, .. } => Some(key),
                Fact::Value { .. } => None,
                Fact::Splitter => None,
            })
            .collect();
        self.new_owned_subject(
            keys,
            Some(format!("{}.keys()", self.description_or_expr())),
            (),
        )
    }
}

#[cfg(test)]
mod tests {
    use std::fmt::Debug;

    use crate::{assert_that, check_that, Fact};

    use super::*;

    trait TestAssertion<'a, S, R> {
        fn is_same_to<B>(&self, expected: B) -> R
        where
            B: Borrow<S>,
            S: PartialEq + Debug;
    }

    impl<'a, S, R> TestAssertion<'a, S, R> for Subject<'a, S, (), R>
    where
        AssertionResult: ReturnStrategy<R>,
    {
        fn is_same_to<B>(&self, expected: B) -> R
        where
            B: Borrow<S>,
            S: PartialEq + Debug,
        {
            match expected.borrow().eq(self.actual().borrow()) {
                true => self.new_result().add_simple_fact("same").do_ok(),
                false => self.new_result().add_simple_fact("not same").do_fail(),
            }
        }
    }

    #[test]
    fn test_assertion() {
        assert_that!("same").is_same_to("same");
        assert_that!(check_that!("actual").is_same_to("expected"))
            .facts_are(vec![Fact::new_simple_fact("not same")]);
    }

    #[test]
    fn facts_are() {
        let failed: CheckThatResult = check_that!("actual").is_same_to("expected");
        assert_that!(check_that!(failed).facts_are(vec![])).facts_are(vec![
            Fact::new("value of", "failed.facts()"),
            Fact::new("unexpected (1)", r#"[Value { value: "not same" }]"#),
            Fact::new_splitter(),
            Fact::new("expected", "[]"),
            Fact::new("actual", r#"[Value { value: "not same" }]"#),
        ]);
    }
}
<commit_msg>Improve error message<commit_after>use std::borrow::Borrow;
use std::collections::HashSet;

use crate::assertions::iterator::IteratorAssertion;
use crate::base::{AssertionApi, AssertionResult, Fact, ReturnStrategy, Subject};
use crate::testing::CheckThatResult;

pub trait AssertionResultAssertion<'a, R> {
    fn facts_are<B: Borrow<Vec<Fact>>>(&self, facts: B) -> R;
    fn facts_are_at_least<B: Borrow<Vec<Fact>>>(&self, facts: B) -> R;
    // Returns subject of fact value for the first matched key.
    fn fact_value_for_key<I: Into<String>>(&self, key: I) -> Subject<String, (), R>;
    fn fact_keys(&self) -> Subject<'a, HashSet<&String>, (), R>;
}

fn get_assertion_result<'a, 'o, R>(
    subject: &'o Subject<'a, CheckThatResult, (), R>,
) -> &'o AssertionResult {
    subject
        .actual()
        .as_ref()
        // TODO: Improve error message; should have line-no.
        .expect_err("Expected Err but got Ok because this is assertion for error message.")
}

impl<'a, R> AssertionResultAssertion<'a, R> for Subject<'a, CheckThatResult, (), R>
where
    AssertionResult: ReturnStrategy<R>,
{
    fn facts_are<B: Borrow<Vec<Fact>>>(&self, expected: B) -> R {
        self.new_owned_subject(
            get_assertion_result(&self).facts().iter(),
            Some(format!("{}.facts()", self.description_or_expr())),
            (),
        )
        .contains_exactly_in_order(expected.borrow().iter())
    }

    fn facts_are_at_least<B: Borrow<Vec<Fact>>>(&self, facts: B) -> R {
        self.new_owned_subject(
            get_assertion_result(&self).facts().iter(),
            Some(format!("{}.facts()", self.description_or_expr())),
            (),
        )
        .contains_at_least_in_order(facts.borrow().iter())
    }

    fn fact_value_for_key<I: Into<String>>(&self, key: I) -> Subject<String, (), R> {
        let key_str = key.into();
        let assertion_result = get_assertion_result(&self);
        let value = assertion_result
            .facts()
            .iter()
            .flat_map(|fact| match fact {
                Fact::KeyValue { key: k, value } if k.eq(&key_str) => Some(value),
                _ => None,
            })
            .next()
            .expect(&format!(
                "key `{}` not found in assertion result.\n{:?}",
                key_str,
                assertion_result.generate_message()
            ))
            .clone();
        self.new_owned_subject(
            value,
            Some(format!("{}.[key={}]", self.description_or_expr(), key_str)),
            (),
        )
    }

    fn fact_keys(&self) -> Subject<HashSet<&String>, (), R> {
        let assertion_result = get_assertion_result(self);
        let keys: HashSet<&String> = assertion_result
            .facts()
            .iter()
            .flat_map(|fact| match fact {
                Fact::KeyValue { key, .. } => Some(key),
                Fact::Value { .. } => None,
                Fact::Splitter => None,
            })
            .collect();
        self.new_owned_subject(
            keys,
            Some(format!("{}.keys()", self.description_or_expr())),
            (),
        )
    }
}

#[cfg(test)]
mod tests {
    use std::fmt::Debug;

    use crate::{assert_that, check_that, Fact};

    use super::*;

    trait TestAssertion<'a, S, R> {
        fn is_same_to<B>(&self, expected: B) -> R
        where
            B: Borrow<S>,
            S: PartialEq + Debug;
    }

    impl<'a, S, R> TestAssertion<'a, S, R> for Subject<'a, S, (), R>
    where
        AssertionResult: ReturnStrategy<R>,
    {
        fn is_same_to<B>(&self, expected: B) -> R
        where
            B: Borrow<S>,
            S: PartialEq + Debug,
        {
            match expected.borrow().eq(self.actual().borrow()) {
                true => self.new_result().add_simple_fact("same").do_ok(),
                false => self.new_result().add_simple_fact("not same").do_fail(),
            }
        }
    }

    #[test]
    fn test_assertion() {
        assert_that!("same").is_same_to("same");
        assert_that!(check_that!("actual").is_same_to("expected"))
            .facts_are(vec![Fact::new_simple_fact("not same")]);
    }

    #[test]
    fn facts_are() {
        let failed: CheckThatResult = check_that!("actual").is_same_to("expected");
        assert_that!(check_that!(failed).facts_are(vec![])).facts_are(vec![
            Fact::new("value of", "failed.facts()"),
            Fact::new("unexpected (1)", r#"[Value { value: "not same" }]"#),
            Fact::new_splitter(),
            Fact::new("expected", "[]"),
            Fact::new("actual", r#"[Value { value: "not same" }]"#),
        ]);
    }
}
<|endoftext|>


<commit_before>use crate::syntax::Api;
use proc_macro2::Ident;
use std::collections::BTreeMap;
use std::iter::FromIterator;

pub struct NamespaceEntries<'a> {
    direct: Vec<&'a Api>,
    nested: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
}

impl<'a> NamespaceEntries<'a> {
    pub fn new(apis: &'a [Api]) -> Self {
        let api_refs = Vec::from_iter(apis);
        Self::sort_by_inner_namespace(api_refs, 0)
    }

    pub fn direct_content(&self) -> &[&'a Api] {
        &self.direct
    }

    pub fn nested_content(&self) -> impl Iterator<Item = (&Ident, &NamespaceEntries)> {
        self.nested.iter().map(|(k, entries)| (*k, entries))
    }

    fn sort_by_inner_namespace(apis: Vec<&'a Api>, depth: usize) -> Self {
        let mut root = NamespaceEntries {
            direct: Vec::new(),
            nested: BTreeMap::new(),
        };

        let mut kids_by_child_ns = BTreeMap::new();
        for api in apis {
            if let Some(ns) = api.namespace() {
                let first_ns_elem = ns.iter().nth(depth);
                if let Some(first_ns_elem) = first_ns_elem {
                    let list = kids_by_child_ns.entry(first_ns_elem).or_insert(Vec::new());
                    list.push(api);
                    continue;
                }
            }
            root.direct.push(api);
        }

        for (k, v) in kids_by_child_ns.into_iter() {
            root.nested
                .insert(k, Self::sort_by_inner_namespace(v, depth + 1));
        }

        root
    }
}

#[cfg(test)]
mod tests {
    use super::NamespaceEntries;
    use crate::syntax::namespace::Namespace;
    use crate::syntax::{Api, Doc, ExternType, Pair};
    use proc_macro2::{Ident, Span};
    use syn::Token;

    #[test]
    fn test_ns_entries_sort() {
        let entries = vec![
            make_api(None, "C"),
            make_api(None, "A"),
            make_api(Some("G"), "E"),
            make_api(Some("D"), "F"),
            make_api(Some("G"), "H"),
            make_api(Some("D::K"), "L"),
            make_api(Some("D::K"), "M"),
            make_api(None, "B"),
            make_api(Some("D"), "I"),
            make_api(Some("D"), "J"),
        ];
        let ns = NamespaceEntries::new(&entries);
        let root_entries = ns.direct_content();
        assert_eq!(root_entries.len(), 3);
        assert_ident(root_entries[0], "C");
        assert_ident(root_entries[1], "A");
        assert_ident(root_entries[2], "B");
        let mut kids = ns.nested_content();
        let (d_id, d_nse) = kids.next().unwrap();
        assert_eq!(d_id.to_string(), "D");
        let (g_id, g_nse) = kids.next().unwrap();
        assert_eq!(g_id.to_string(), "G");
        assert!(kids.next().is_none());
        let d_nse_entries = d_nse.direct_content();
        assert_eq!(d_nse_entries.len(), 3);
        assert_ident(d_nse_entries[0], "F");
        assert_ident(d_nse_entries[1], "I");
        assert_ident(d_nse_entries[2], "J");
        let g_nse_entries = g_nse.direct_content();
        assert_eq!(g_nse_entries.len(), 2);
        assert_ident(g_nse_entries[0], "E");
        assert_ident(g_nse_entries[1], "H");
        let mut g_kids = g_nse.nested_content();
        assert!(g_kids.next().is_none());
        let mut d_kids = d_nse.nested_content();
        let (k_id, k_nse) = d_kids.next().unwrap();
        assert_eq!(k_id.to_string(), "K");
        let k_nse_entries = k_nse.direct_content();
        assert_eq!(k_nse_entries.len(), 2);
        assert_ident(k_nse_entries[0], "L");
        assert_ident(k_nse_entries[1], "M");
    }

    fn assert_ident(api: &Api, expected: &str) {
        if let Api::CxxType(cxx_type) = api {
            assert_eq!(cxx_type.ident.cxx.ident.to_string(), expected);
        } else {
            unreachable!()
        }
    }

    fn make_api(ns: Option<&str>, ident: &str) -> Api {
        let ns = match ns {
            Some(st) => Namespace::from_str(st),
            None => Namespace::none(),
        };
        let ident = Pair::new(ns, Ident::new(ident, Span::call_site()));
        Api::CxxType(ExternType {
            doc: Doc::new(),
            type_token: Token![type](Span::call_site()),
            ident,
            semi_token: Token![;](Span::call_site()),
            trusted: true,
        })
    }
}
<commit_msg>Remove 'kids' naming<commit_after>use crate::syntax::Api;
use proc_macro2::Ident;
use std::collections::BTreeMap;
use std::iter::FromIterator;

pub struct NamespaceEntries<'a> {
    direct: Vec<&'a Api>,
    nested: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
}

impl<'a> NamespaceEntries<'a> {
    pub fn new(apis: &'a [Api]) -> Self {
        let api_refs = Vec::from_iter(apis);
        Self::sort_by_inner_namespace(api_refs, 0)
    }

    pub fn direct_content(&self) -> &[&'a Api] {
        &self.direct
    }

    pub fn nested_content(&self) -> impl Iterator<Item = (&Ident, &NamespaceEntries)> {
        self.nested.iter().map(|(k, entries)| (*k, entries))
    }

    fn sort_by_inner_namespace(apis: Vec<&'a Api>, depth: usize) -> Self {
        let mut root = NamespaceEntries {
            direct: Vec::new(),
            nested: BTreeMap::new(),
        };

        let mut nested_namespaces = BTreeMap::new();
        for api in apis {
            if let Some(ns) = api.namespace() {
                let first_ns_elem = ns.iter().nth(depth);
                if let Some(first_ns_elem) = first_ns_elem {
                    let list = nested_namespaces.entry(first_ns_elem).or_insert(Vec::new());
                    list.push(api);
                    continue;
                }
            }
            root.direct.push(api);
        }

        for (k, v) in nested_namespaces.into_iter() {
            root.nested
                .insert(k, Self::sort_by_inner_namespace(v, depth + 1));
        }

        root
    }
}

#[cfg(test)]
mod tests {
    use super::NamespaceEntries;
    use crate::syntax::namespace::Namespace;
    use crate::syntax::{Api, Doc, ExternType, Pair};
    use proc_macro2::{Ident, Span};
    use syn::Token;

    #[test]
    fn test_ns_entries_sort() {
        let entries = vec![
            make_api(None, "C"),
            make_api(None, "A"),
            make_api(Some("G"), "E"),
            make_api(Some("D"), "F"),
            make_api(Some("G"), "H"),
            make_api(Some("D::K"), "L"),
            make_api(Some("D::K"), "M"),
            make_api(None, "B"),
            make_api(Some("D"), "I"),
            make_api(Some("D"), "J"),
        ];
        let ns = NamespaceEntries::new(&entries);
        let root_entries = ns.direct_content();
        assert_eq!(root_entries.len(), 3);
        assert_ident(root_entries[0], "C");
        assert_ident(root_entries[1], "A");
        assert_ident(root_entries[2], "B");
        let mut kids = ns.nested_content();
        let (d_id, d_nse) = kids.next().unwrap();
        assert_eq!(d_id.to_string(), "D");
        let (g_id, g_nse) = kids.next().unwrap();
        assert_eq!(g_id.to_string(), "G");
        assert!(kids.next().is_none());
        let d_nse_entries = d_nse.direct_content();
        assert_eq!(d_nse_entries.len(), 3);
        assert_ident(d_nse_entries[0], "F");
        assert_ident(d_nse_entries[1], "I");
        assert_ident(d_nse_entries[2], "J");
        let g_nse_entries = g_nse.direct_content();
        assert_eq!(g_nse_entries.len(), 2);
        assert_ident(g_nse_entries[0], "E");
        assert_ident(g_nse_entries[1], "H");
        let mut g_kids = g_nse.nested_content();
        assert!(g_kids.next().is_none());
        let mut d_kids = d_nse.nested_content();
        let (k_id, k_nse) = d_kids.next().unwrap();
        assert_eq!(k_id.to_string(), "K");
        let k_nse_entries = k_nse.direct_content();
        assert_eq!(k_nse_entries.len(), 2);
        assert_ident(k_nse_entries[0], "L");
        assert_ident(k_nse_entries[1], "M");
    }

    fn assert_ident(api: &Api, expected: &str) {
        if let Api::CxxType(cxx_type) = api {
            assert_eq!(cxx_type.ident.cxx.ident.to_string(), expected);
        } else {
            unreachable!()
        }
    }

    fn make_api(ns: Option<&str>, ident: &str) -> Api {
        let ns = match ns {
            Some(st) => Namespace::from_str(st),
            None => Namespace::none(),
        };
        let ident = Pair::new(ns, Ident::new(ident, Span::call_site()));
        Api::CxxType(ExternType {
            doc: Doc::new(),
            type_token: Token![type](Span::call_site()),
            ident,
            semi_token: Token![;](Span::call_site()),
            trusted: true,
        })
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017  Sebastian Wiesner <swiesner@lunaryorn.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

extern crate reqwest;
extern crate sha2;

use sha2::{Sha256, Digest};
use std::env;
use std::fs::File;
use std::io::BufWriter;
use std::io::prelude::*;
use std::path::Path;

// We use the large diceware list of the EFF, which contains 7776 common English words between
// three and nine characters.  I'm unsure about the licensing situation concerning this list so I'm
// not shipping it with the sources but instead download it during the build and use its hash to
// verify its authenticity.
static URL: &'static str = "https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt";
static WORDLIST_SHA256: &'static [u8] = &[0xad, 0xdd, 0x35, 0x53, 0x65, 0x11, 0x59, 0x7a, 0x02,
                                          0xfa, 0x0a, 0x9f, 0xf1, 0xe5, 0x28, 0x46, 0x77, 0xb8,
                                          0x88, 0x3b, 0x83, 0xe9, 0x86, 0xe4, 0x3f, 0x15, 0xa3,
                                          0xdb, 0x99, 0x6b, 0x90, 0x3e];

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();

    let client = reqwest::Client::new().unwrap();
    let mut response = client.get(URL)
        .header(reqwest::header::Connection::close())
        .send()
        .unwrap();
    let mut response_buffer = Vec::with_capacity(40000);
    response.read_to_end(&mut response_buffer).unwrap();

    let mut hasher = Sha256::new();
    hasher.input(&response_buffer);
    let hash = hasher.result();
    if *hash != *WORDLIST_SHA256 {
        panic!("SHA256 mismatch for EFF wordlist! Report issue to \
                https://github.com/lunaryorn/xkpwgen.rs");
    }

    let wordlist = std::str::from_utf8(&response_buffer).unwrap();
    // A diceware list as one word entry per line. A word entry consists of a number followed by
    // whitespace followed by the actual word.  The number consists of digits between 1 and 6,
    // where each digit is the result of rolling a six-side die.  In other words, the number is the
    // sequence of results from repeatedly rolling a six-side die.  These numbers are intended to
    // support "manual" generation of a passphrase; for our random sampling we don't need those and
    // thus strip them from the final wordlist.
    let words = wordlist.lines().map(|l| l.split_whitespace().last().unwrap());

    let eff_wordlist = Path::new(&out_dir).join("eff_wordlist.txt");
    let mut sink = BufWriter::new(File::create(&eff_wordlist).unwrap());
    for word in words {
        sink.write_all(word.as_bytes()).unwrap();
        sink.write("\n".as_bytes()).unwrap();
    }
    println!("Wrote EFF wordlist to {}", eff_wordlist.to_string_lossy());
}
<commit_msg>Improve error messages in build script<commit_after>/*
 * Copyright (C) 2017  Sebastian Wiesner <swiesner@lunaryorn.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

extern crate reqwest;
extern crate sha2;

use sha2::{Sha256, Digest};
use std::env;
use std::fs::File;
use std::io::BufWriter;
use std::io::prelude::*;
use std::path::Path;

// We use the large diceware list of the EFF, which contains 7776 common English words between
// three and nine characters.  I'm unsure about the licensing situation concerning this list so I'm
// not shipping it with the sources but instead download it during the build and use its hash to
// verify its authenticity.
static URL: &'static str = "https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt";
static WORDLIST_SHA256: &'static [u8] = &[0xad, 0xdd, 0x35, 0x53, 0x65, 0x11, 0x59, 0x7a, 0x02,
                                          0xfa, 0x0a, 0x9f, 0xf1, 0xe5, 0x28, 0x46, 0x77, 0xb8,
                                          0x88, 0x3b, 0x83, 0xe9, 0x86, 0xe4, 0x3f, 0x15, 0xa3,
                                          0xdb, 0x99, 0x6b, 0x90, 0x3e];

fn main() {
    let out_dir = env::var("OUT_DIR").expect("Output directory $OUT_DIR missing!");

    let client = reqwest::Client::new().unwrap();
    let mut response = client.get(URL)
        .header(reqwest::header::Connection::close())
        .send()
        .expect("Failed to connect to EFF servers");
    let mut response_buffer = Vec::with_capacity(40000);
    response.read_to_end(&mut response_buffer).expect("Failed to download EFF wordlist");

    let mut hasher = Sha256::new();
    hasher.input(&response_buffer);
    let hash = hasher.result();
    if *hash != *WORDLIST_SHA256 {
        panic!("SHA256 mismatch for EFF wordlist! Report issue to \
                https://github.com/lunaryorn/xkpwgen.rs");
    }

    let wordlist = std::str::from_utf8(&response_buffer).unwrap();
    // A diceware list as one word entry per line. A word entry consists of a number followed by
    // whitespace followed by the actual word.  The number consists of digits between 1 and 6,
    // where each digit is the result of rolling a six-side die.  In other words, the number is the
    // sequence of results from repeatedly rolling a six-side die.  These numbers are intended to
    // support "manual" generation of a passphrase; for our random sampling we don't need those and
    // thus strip them from the final wordlist.
    let words = wordlist.lines().map(|l| l.split_whitespace().last().unwrap());

    let eff_wordlist = Path::new(&out_dir).join("eff_wordlist.txt");
    let mut sink = File::create(&eff_wordlist)
        .map(BufWriter::new)
        .expect("Failed to create wordlist file in output directory");
    for word in words {
        sink.write_all(word.as_bytes()).unwrap();
        sink.write("\n".as_bytes()).unwrap();
    }
    println!("Wrote EFF wordlist to {}", eff_wordlist.to_string_lossy());
}
<|endoftext|>


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

use std::collections::HashSet;
use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

const MIN_VERSION: &'static str = "7.0";
const MAX_VERSION: &'static str = "7.1";

static HEADER: &'static str = "#include <MagickWand/MagickWand.h>\n";

fn main() {
    if cfg!(target_os = "freebsd") {
        // pkg_config does not seem to work properly on FreeBSD, so
        // hard-code the builder settings for the time being.
        env_var_set_default(
            "IMAGE_MAGICK_INCLUDE_DIRS",
            "/usr/local/include/ImageMagick-7",
        );
        // Need to hack the linker flags as well.
        env_var_set_default("IMAGE_MAGICK_LIB_DIRS", "/usr/local/lib");
        env_var_set_default("IMAGE_MAGICK_LIBS", "MagickWand-7");
    }

    let cppflags = Command::new("MagickCore-config")
        .arg("--cppflags")
        .output()
        .unwrap()
        .stdout;
    let cppflags = String::from_utf8(cppflags).unwrap();

    env_var_set_default("BINDGEN_EXTRA_CLANG_ARGS", &cppflags);

    let lib_dirs = find_image_magick_lib_dirs();
    for d in &lib_dirs {
        if !d.exists() {
            panic!(
                "ImageMagick library directory does not exist: {}",
                d.to_string_lossy()
            );
        }
        println!("cargo:rustc-link-search=native={}", d.to_string_lossy());
    }
    let include_dirs = find_image_magick_include_dirs();
    for d in &include_dirs {
        if !d.exists() {
            panic!(
                "ImageMagick include directory does not exist: {}",
                d.to_string_lossy()
            );
        }
        println!("cargo:include={}", d.to_string_lossy());
    }
    println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_LIBS");

    let target = env::var("TARGET").unwrap();
    let libs_env = env::var("IMAGE_MAGICK_LIBS").ok();
    let libs = match libs_env {
        Some(ref v) => v.split(":").map(|x| x.to_owned()).collect(),
        None => {
            if target.contains("windows") {
                vec!["CORE_RL_MagickWand_".to_string()]
            } else if target.contains("freebsd") {
                vec!["MagickWand-7".to_string()]
            } else {
                run_pkg_config().libs
            }
        }
    };

    let kind = determine_mode(&lib_dirs, libs.as_slice());
    for lib in libs.into_iter() {
        println!("cargo:rustc-link-lib={}={}", kind, lib);
    }

    // If the generated bindings are missing, generate them now.
    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
    let bindings_path_str = out_dir.join("bindings.rs");

    #[derive(Debug)]
    struct IgnoreMacros(HashSet<String>);

    impl bindgen::callbacks::ParseCallbacks for IgnoreMacros {
        fn will_parse_macro(&self, name: &str) -> bindgen::callbacks::MacroParsingBehavior {
            if self.0.contains(name) {
                bindgen::callbacks::MacroParsingBehavior::Ignore
            } else {
                bindgen::callbacks::MacroParsingBehavior::Default
            }
        }
    }

    let ignored_macros = IgnoreMacros(
        vec![
            "FP_INFINITE".into(),
            "FP_NAN".into(),
            "FP_NORMAL".into(),
            "FP_SUBNORMAL".into(),
            "FP_ZERO".into(),
            "IPPORT_RESERVED".into(),
            "FP_INT_UPWARD".into(),
            "FP_INT_DOWNWARD".into(),
            "FP_INT_TOWARDZERO".into(),
            "FP_INT_TONEARESTFROMZERO".into(),
            "FP_INT_TONEAREST".into(),
        ]
        .into_iter()
        .collect(),
    );

    if !Path::new(&bindings_path_str).exists() {
        // Create the header file that rust-bindgen needs as input.
        let gen_h_path = out_dir.join("gen.h");
        let mut gen_h = File::create(&gen_h_path).expect("could not create file");
        gen_h
            .write_all(HEADER.as_bytes())
            .expect("could not write header file");

        // Geneate the bindings.
        let mut builder = bindgen::Builder::default()
            .emit_builtins()
            .ctypes_prefix("libc")
            .raw_line("extern crate libc;")
            .header(gen_h_path.to_str().unwrap())
            .size_t_is_usize(true)
            .parse_callbacks(Box::new(ignored_macros))
            .blacklist_type("timex")
            .blacklist_function("clock_adjtime");

        for d in include_dirs {
            builder = builder.clang_arg(format!("-I{}", d.to_string_lossy()));
        }

        let bindings = builder.generate().unwrap();
        let mut file = File::create(&bindings_path_str).expect("could not create bindings file");
        // Work around the include! issue in rustc (as described in the
        // rust-bindgen README file) by wrapping the generated code in a
        // `pub mod` declaration; see issue #359 in (old) rust-bindgen.
        file.write(b"pub mod bindings {\n").unwrap();
        file.write(bindings.to_string().as_bytes()).unwrap();
        file.write(b"\n}").unwrap();

        std::fs::remove_file(&gen_h_path).expect("could not remove header file");
    }
}

fn env_var_set_default(name: &str, value: &str) {
    if env::var(name).is_err() {
        env::set_var(name, value);
    }
}

fn find_image_magick_lib_dirs() -> Vec<PathBuf> {
    println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_LIB_DIRS");
    env::var("IMAGE_MAGICK_LIB_DIRS")
        .map(|x| x.split(":").map(PathBuf::from).collect::<Vec<PathBuf>>())
        .or_else(|_| Ok(vec![find_image_magick_dir()?.join("lib")]))
        .or_else(|_: env::VarError| -> Result<_, env::VarError> { Ok(run_pkg_config().link_paths) })
        .expect("Couldn't find ImageMagick library directory")
}

fn find_image_magick_include_dirs() -> Vec<PathBuf> {
    println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_INCLUDE_DIRS");
    env::var("IMAGE_MAGICK_INCLUDE_DIRS")
        .map(|x| x.split(":").map(PathBuf::from).collect::<Vec<PathBuf>>())
        .or_else(|_| Ok(vec![find_image_magick_dir()?.join("include")]))
        .or_else(|_: env::VarError| -> Result<_, env::VarError> {
            Ok(run_pkg_config().include_paths)
        })
        .expect("Couldn't find ImageMagick include directory")
}

fn find_image_magick_dir() -> Result<PathBuf, env::VarError> {
    println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_DIR");
    env::var("IMAGE_MAGICK_DIR").map(PathBuf::from)
}

fn determine_mode<T: AsRef<str>>(libdirs: &Vec<PathBuf>, libs: &[T]) -> &'static str {
    println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_STATIC");
    let kind = env::var("IMAGE_MAGICK_STATIC").ok();
    match kind.as_ref().map(|s| &s[..]) {
        Some("0") => return "dylib",
        Some(_) => return "static",
        None => {}
    }

    // See what files we actually have to link against, and see what our
    // possibilities even are.
    let files = libdirs
        .into_iter()
        .flat_map(|d| d.read_dir().unwrap())
        .map(|e| e.unwrap())
        .map(|e| e.file_name())
        .filter_map(|e| e.into_string().ok())
        .collect::<HashSet<_>>();
    let can_static = libs.iter().all(|l| {
        files.contains(&format!("lib{}.a", l.as_ref()))
            || files.contains(&format!("{}.lib", l.as_ref()))
    });
    let can_dylib = libs.iter().all(|l| {
        files.contains(&format!("lib{}.so", l.as_ref()))
            || files.contains(&format!("{}.dll", l.as_ref()))
            || files.contains(&format!("lib{}.dylib", l.as_ref()))
    });

    match (can_static, can_dylib) {
        (true, false) => return "static",
        (false, true) => return "dylib",
        (false, false) => {
            panic!(
                "ImageMagick libdirs at `{:?}` do not contain the required files \
                 to either statically or dynamically link ImageMagick",
                libdirs
            );
        }
        (true, true) => {}
    }

    // default
    "dylib"
}

fn run_pkg_config() -> pkg_config::Library {
    // Assert that the appropriate version of MagickWand is installed,
    // since we are very dependent on the particulars of MagickWand.
    pkg_config::Config::new()
        .cargo_metadata(false)
        .atleast_version(MIN_VERSION)
        .probe("MagickWand")
        .unwrap();
    // Check the maximum version separately as pkg-config will ignore that
    // option when combined with (certain) other options. And since the
    // pkg-config crate always adds those other flags, we must run the
    // command directly.
    if !Command::new("pkg-config")
        .arg(format!("--max-version={}", MAX_VERSION))
        .arg("MagickWand")
        .status()
        .unwrap()
        .success()
    {
        panic!(format!(
            "MagickWand version must be no higher than {}",
            MAX_VERSION
        ));
    }
    // We have to split the version check and the cflags/libs check because
    // you can't do both at the same time on RHEL (apparently).
    pkg_config::Config::new()
        .cargo_metadata(false)
        .probe("MagickWand")
        .unwrap()
}
<commit_msg>fix path_separator on windows can not build<commit_after>/*
 * Copyright 2016-2018 Nathan Fiedler
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
extern crate bindgen;
extern crate pkg_config;

use std::collections::HashSet;
use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

const MIN_VERSION: &'static str = "7.0";
const MAX_VERSION: &'static str = "7.1";

static HEADER: &'static str = "#include <MagickWand/MagickWand.h>\n";

//on windows path env always contain : like c:
pub const PATH_SEPARATOR: &str = match cfg!(target_os = "windows") {
    true => ";",
    _ => ":",
};

fn main() {
    if cfg!(target_os = "freebsd") {
        // pkg_config does not seem to work properly on FreeBSD, so
        // hard-code the builder settings for the time being.
        env_var_set_default(
            "IMAGE_MAGICK_INCLUDE_DIRS",
            "/usr/local/include/ImageMagick-7",
        );
        // Need to hack the linker flags as well.
        env_var_set_default("IMAGE_MAGICK_LIB_DIRS", "/usr/local/lib");
        env_var_set_default("IMAGE_MAGICK_LIBS", "MagickWand-7");
    }

    let check_cppflags = Command::new("MagickCore-config").arg("--cppflags").output();
    //on windows can not exec
    if check_cppflags.is_ok() {
        let cppflags = check_cppflags.unwrap().stdout;
        let cppflags = String::from_utf8(cppflags).unwrap();

        env_var_set_default("BINDGEN_EXTRA_CLANG_ARGS", &cppflags);
    }

    let lib_dirs = find_image_magick_lib_dirs();
    for d in &lib_dirs {
        if !d.exists() {
            panic!(
                "ImageMagick library directory does not exist: {}",
                d.to_string_lossy()
            );
        }
        println!("cargo:rustc-link-search=native={}", d.to_string_lossy());
    }
    let include_dirs = find_image_magick_include_dirs();
    for d in &include_dirs {
        if !d.exists() {
            panic!(
                "ImageMagick include directory does not exist: {}",
                d.to_string_lossy()
            );
        }
        println!("cargo:include={}", d.to_string_lossy());
    }
    println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_LIBS");

    let target = env::var("TARGET").unwrap();
    let libs_env = env::var("IMAGE_MAGICK_LIBS").ok();
    let libs = match libs_env {
        Some(ref v) => v.split(PATH_SEPARATOR).map(|x| x.to_owned()).collect(),
        None => {
            if target.contains("windows") {
                vec!["CORE_RL_MagickWand_".to_string()]
            } else if target.contains("freebsd") {
                vec!["MagickWand-7".to_string()]
            } else {
                run_pkg_config().libs
            }
        }
    };

    let kind = determine_mode(&lib_dirs, libs.as_slice());
    for lib in libs.into_iter() {
        println!("cargo:rustc-link-lib={}={}", kind, lib);
    }

    // If the generated bindings are missing, generate them now.
    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
    let bindings_path_str = out_dir.join("bindings.rs");

    #[derive(Debug)]
    struct IgnoreMacros(HashSet<String>);

    impl bindgen::callbacks::ParseCallbacks for IgnoreMacros {
        fn will_parse_macro(&self, name: &str) -> bindgen::callbacks::MacroParsingBehavior {
            if self.0.contains(name) {
                bindgen::callbacks::MacroParsingBehavior::Ignore
            } else {
                bindgen::callbacks::MacroParsingBehavior::Default
            }
        }
    }

    let ignored_macros = IgnoreMacros(
        vec![
            "FP_INFINITE".into(),
            "FP_NAN".into(),
            "FP_NORMAL".into(),
            "FP_SUBNORMAL".into(),
            "FP_ZERO".into(),
            "IPPORT_RESERVED".into(),
            "FP_INT_UPWARD".into(),
            "FP_INT_DOWNWARD".into(),
            "FP_INT_TOWARDZERO".into(),
            "FP_INT_TONEARESTFROMZERO".into(),
            "FP_INT_TONEAREST".into(),
        ]
        .into_iter()
        .collect(),
    );

    if !Path::new(&bindings_path_str).exists() {
        // Create the header file that rust-bindgen needs as input.
        let gen_h_path = out_dir.join("gen.h");
        let mut gen_h = File::create(&gen_h_path).expect("could not create file");
        gen_h
            .write_all(HEADER.as_bytes())
            .expect("could not write header file");

        // Geneate the bindings.
        let mut builder = bindgen::Builder::default()
            .emit_builtins()
            .ctypes_prefix("libc")
            .raw_line("extern crate libc;")
            .header(gen_h_path.to_str().unwrap())
            .size_t_is_usize(true)
            .parse_callbacks(Box::new(ignored_macros))
            .blacklist_type("timex")
            .blacklist_function("clock_adjtime");

        for d in include_dirs {
            builder = builder.clang_arg(format!("-I{}", d.to_string_lossy()));
        }

        let bindings = builder.generate().unwrap();
        let mut file = File::create(&bindings_path_str).expect("could not create bindings file");
        // Work around the include! issue in rustc (as described in the
        // rust-bindgen README file) by wrapping the generated code in a
        // `pub mod` declaration; see issue #359 in (old) rust-bindgen.
        file.write(b"pub mod bindings {\n").unwrap();
        file.write(bindings.to_string().as_bytes()).unwrap();
        file.write(b"\n}").unwrap();

        std::fs::remove_file(&gen_h_path).expect("could not remove header file");
    }
}

fn env_var_set_default(name: &str, value: &str) {
    if env::var(name).is_err() {
        env::set_var(name, value);
    }
}

fn find_image_magick_lib_dirs() -> Vec<PathBuf> {
    println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_LIB_DIRS");
    env::var("IMAGE_MAGICK_LIB_DIRS")
        .map(|x| {
            x.split(PATH_SEPARATOR)
                .map(PathBuf::from)
                .collect::<Vec<PathBuf>>()
        })
        .or_else(|_| Ok(vec![find_image_magick_dir()?.join("lib")]))
        .or_else(|_: env::VarError| -> Result<_, env::VarError> { Ok(run_pkg_config().link_paths) })
        .expect("Couldn't find ImageMagick library directory")
}

fn find_image_magick_include_dirs() -> Vec<PathBuf> {
    println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_INCLUDE_DIRS");
    env::var("IMAGE_MAGICK_INCLUDE_DIRS")
        .map(|x| {
            x.split(PATH_SEPARATOR)
                .map(PathBuf::from)
                .collect::<Vec<PathBuf>>()
        })
        .or_else(|_| Ok(vec![find_image_magick_dir()?.join("include")]))
        .or_else(|_: env::VarError| -> Result<_, env::VarError> {
            Ok(run_pkg_config().include_paths)
        })
        .expect("Couldn't find ImageMagick include directory")
}

fn find_image_magick_dir() -> Result<PathBuf, env::VarError> {
    println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_DIR");
    env::var("IMAGE_MAGICK_DIR").map(PathBuf::from)
}

fn determine_mode<T: AsRef<str>>(libdirs: &Vec<PathBuf>, libs: &[T]) -> &'static str {
    println!("cargo:rerun-if-env-changed=IMAGE_MAGICK_STATIC");
    let kind = env::var("IMAGE_MAGICK_STATIC").ok();
    match kind.as_ref().map(|s| &s[..]) {
        Some("0") => return "dylib",
        Some(_) => return "static",
        None => {}
    }

    // See what files we actually have to link against, and see what our
    // possibilities even are.
    let files = libdirs
        .into_iter()
        .flat_map(|d| d.read_dir().unwrap())
        .map(|e| e.unwrap())
        .map(|e| e.file_name())
        .filter_map(|e| e.into_string().ok())
        .collect::<HashSet<_>>();
    let can_static = libs.iter().all(|l| {
        files.contains(&format!("lib{}.a", l.as_ref()))
            || files.contains(&format!("{}.lib", l.as_ref()))
    });
    let can_dylib = libs.iter().all(|l| {
        files.contains(&format!("lib{}.so", l.as_ref()))
            || files.contains(&format!("{}.dll", l.as_ref()))
            || files.contains(&format!("lib{}.dylib", l.as_ref()))
    });

    match (can_static, can_dylib) {
        (true, false) => return "static",
        (false, true) => return "dylib",
        (false, false) => {
            panic!(
                "ImageMagick libdirs at `{:?}` do not contain the required files \
                 to either statically or dynamically link ImageMagick",
                libdirs
            );
        }
        (true, true) => {}
    }

    // default
    "dylib"
}

fn run_pkg_config() -> pkg_config::Library {
    // Assert that the appropriate version of MagickWand is installed,
    // since we are very dependent on the particulars of MagickWand.
    pkg_config::Config::new()
        .cargo_metadata(false)
        .atleast_version(MIN_VERSION)
        .probe("MagickWand")
        .unwrap();
    // Check the maximum version separately as pkg-config will ignore that
    // option when combined with (certain) other options. And since the
    // pkg-config crate always adds those other flags, we must run the
    // command directly.
    if !Command::new("pkg-config")
        .arg(format!("--max-version={}", MAX_VERSION))
        .arg("MagickWand")
        .status()
        .unwrap()
        .success()
    {
        panic!(format!(
            "MagickWand version must be no higher than {}",
            MAX_VERSION
        ));
    }
    // We have to split the version check and the cflags/libs check because
    // you can't do both at the same time on RHEL (apparently).
    pkg_config::Config::new()
        .cargo_metadata(false)
        .probe("MagickWand")
        .unwrap()
}
<|endoftext|>


<commit_before>extern crate cc;

fn main() {
    cc::Build::new()
        .file("libmikktspace/mikktspace.h")
        .file("libmikktspace/mikktspace.c")
        .compile("mikktspace");
}
<commit_msg>Fix build.rs to work on Linux<commit_after>extern crate cc;

fn main() {
    cc::Build::new()
        .file("libmikktspace/mikktspace.c")
        .include("libmikktspace")
        .compile("mikktspace");
}
<|endoftext|>


<commit_before>// build.rs

#[cfg(feature = "aom")]
extern crate cmake;
#[cfg(unix)]
extern crate pkg_config;
#[cfg(unix)]
#[cfg(feature = "decode_test")]
extern crate bindgen;
#[cfg(all(target_arch = "x86_64", feature = "nasm"))]
extern crate nasm_rs;

#[allow(unused_imports)]
use std::env;
use std::fs;
use std::path::Path;

#[allow(dead_code)]
fn rerun_dir<P: AsRef<Path>>(dir: P) {
    for entry in fs::read_dir(dir).unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();
        println!("cargo:rerun-if-changed={}", path.to_string_lossy());

        if path.is_dir() {
            rerun_dir(path);
        }
    }
}

fn main() {
    #[cfg(all(target_arch = "x86_64", not(windows), feature = "nasm"))] {
        use std::fs::File;
        use std::io::Write;
        let out_dir = env::var("OUT_DIR").unwrap();
        {
            let dest_path = Path::new(&out_dir).join("config.asm");
            let mut config_file = File::create(dest_path).unwrap();
            config_file.write(b"	%define private_prefix rav1e\n").unwrap();
            config_file.write(b"	%define ARCH_X86_32 0\n").unwrap();
            config_file.write(b" %define ARCH_X86_64 1\n").unwrap();
            config_file.write(b"	%define PIC 1\n").unwrap();
            config_file.write(b" %define STACK_ALIGNMENT 32\n").unwrap();
            if cfg!(target_os="macos") {
              config_file.write(b" %define PREFIX 1\n").unwrap();
            }
        }
        let mut config_include_arg = String::from("-I");
        config_include_arg.push_str(&out_dir);
        config_include_arg.push('/');
        nasm_rs::compile_library_args(
            "rav1easm",
            &[
                "src/x86/data.asm",
                "src/x86/ipred.asm",
                "src/x86/itx.asm",
                "src/x86/mc.asm",
                "src/x86/me.asm"
            ],
            &[&config_include_arg, "-Isrc/"]
        );
        println!("cargo:rustc-link-lib=static=rav1easm");
        rerun_dir("src/x86");
        rerun_dir("src/ext/x86");
    }

    if cfg!(windows) && cfg!(feature = "decode_test") {
        panic!("Unsupported feature on this platform!");
    }
    #[cfg(feature = "aom")] {
    let cargo_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let build_path = Path::new(&cargo_dir).join("aom_build/aom");
    let debug = if let Some(v) = env::var("PROFILE").ok() {
        match v.as_str() {
            "bench" | "release" => false,
            _ => true,
        }
    } else {
        false
    };

    let dst = cmake::Config::new(build_path)
        .define("CONFIG_DEBUG", (debug as u8).to_string())
        .define("CONFIG_ANALYZER", "0")
        .define("ENABLE_DOCS", "0")
        .define("ENABLE_NASM", "1")
        .define("ENABLE_TESTS", "0")
        .no_build_target(cfg!(windows))
        .build();

    // Dirty hack to force a rebuild whenever the defaults are changed upstream
    let _ = fs::remove_file(dst.join("build/CMakeCache.txt"));

    #[cfg(windows)] {
        println!("cargo:rustc-link-search=native={}", dst.join("build").to_str().unwrap());
        println!("cargo:rustc-link-search=native={}", dst.join("build/Debug").to_str().unwrap());
        println!("cargo:rustc-link-search=native={}", dst.join("build/Release").to_str().unwrap());
        println!("cargo:rustc-link-lib=static=aom");
    }

    #[cfg(unix)] {
        env::set_var("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));
        let _libs = pkg_config::Config::new().statik(true).probe("aom").unwrap();

        #[cfg(feature = "decode_test")] {
            use std::io::Write;

            let out_dir = env::var("OUT_DIR").unwrap();

            let headers = _libs.include_paths.clone();

            let mut builder = bindgen::builder()
                .blacklist_type("max_align_t")
                .rustfmt_bindings(false)
                .header("data/aom.h");

            for header in headers {
                builder = builder.clang_arg("-I").clang_arg(header.to_str().unwrap());
            }

            // Manually fix the comment so rustdoc won't try to pick them
            let s = builder
                .generate()
                .unwrap()
                .to_string()
                .replace("/**", "/*")
                .replace("/*!", "/*");

            let dest_path = Path::new(&out_dir).join("aom.rs");

            let mut file = fs::File::create(dest_path).unwrap();

            let _ = file.write(s.as_bytes());
        }
    }
    rerun_dir("aom_build");
    }
}
<commit_msg>Do not build aom examples and tools<commit_after>// build.rs

#[cfg(feature = "aom")]
extern crate cmake;
#[cfg(unix)]
extern crate pkg_config;
#[cfg(unix)]
#[cfg(feature = "decode_test")]
extern crate bindgen;
#[cfg(all(target_arch = "x86_64", feature = "nasm"))]
extern crate nasm_rs;

#[allow(unused_imports)]
use std::env;
use std::fs;
use std::path::Path;

#[allow(dead_code)]
fn rerun_dir<P: AsRef<Path>>(dir: P) {
    for entry in fs::read_dir(dir).unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();
        println!("cargo:rerun-if-changed={}", path.to_string_lossy());

        if path.is_dir() {
            rerun_dir(path);
        }
    }
}

fn main() {
    #[cfg(all(target_arch = "x86_64", not(windows), feature = "nasm"))] {
        use std::fs::File;
        use std::io::Write;
        let out_dir = env::var("OUT_DIR").unwrap();
        {
            let dest_path = Path::new(&out_dir).join("config.asm");
            let mut config_file = File::create(dest_path).unwrap();
            config_file.write(b"	%define private_prefix rav1e\n").unwrap();
            config_file.write(b"	%define ARCH_X86_32 0\n").unwrap();
            config_file.write(b" %define ARCH_X86_64 1\n").unwrap();
            config_file.write(b"	%define PIC 1\n").unwrap();
            config_file.write(b" %define STACK_ALIGNMENT 32\n").unwrap();
            if cfg!(target_os="macos") {
              config_file.write(b" %define PREFIX 1\n").unwrap();
            }
        }
        let mut config_include_arg = String::from("-I");
        config_include_arg.push_str(&out_dir);
        config_include_arg.push('/');
        nasm_rs::compile_library_args(
            "rav1easm",
            &[
                "src/x86/data.asm",
                "src/x86/ipred.asm",
                "src/x86/itx.asm",
                "src/x86/mc.asm",
                "src/x86/me.asm"
            ],
            &[&config_include_arg, "-Isrc/"]
        );
        println!("cargo:rustc-link-lib=static=rav1easm");
        rerun_dir("src/x86");
        rerun_dir("src/ext/x86");
    }

    if cfg!(windows) && cfg!(feature = "decode_test") {
        panic!("Unsupported feature on this platform!");
    }
    #[cfg(feature = "aom")] {
    let cargo_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let build_path = Path::new(&cargo_dir).join("aom_build/aom");
    let debug = if let Some(v) = env::var("PROFILE").ok() {
        match v.as_str() {
            "bench" | "release" => false,
            _ => true,
        }
    } else {
        false
    };

    let dst = cmake::Config::new(build_path)
        .define("CONFIG_DEBUG", (debug as u8).to_string())
        .define("CONFIG_ANALYZER", "0")
        .define("ENABLE_DOCS", "0")
        .define("ENABLE_NASM", "1")
        .define("ENABLE_TESTS", "0")
        .define("ENABLE_TOOLS", "0")
        .define("ENABLE_EXAMPLES", "0")
        .no_build_target(cfg!(windows))
        .build();

    // Dirty hack to force a rebuild whenever the defaults are changed upstream
    let _ = fs::remove_file(dst.join("build/CMakeCache.txt"));

    #[cfg(windows)] {
        println!("cargo:rustc-link-search=native={}", dst.join("build").to_str().unwrap());
        println!("cargo:rustc-link-search=native={}", dst.join("build/Debug").to_str().unwrap());
        println!("cargo:rustc-link-search=native={}", dst.join("build/Release").to_str().unwrap());
        println!("cargo:rustc-link-lib=static=aom");
    }

    #[cfg(unix)] {
        env::set_var("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));
        let _libs = pkg_config::Config::new().statik(true).probe("aom").unwrap();

        #[cfg(feature = "decode_test")] {
            use std::io::Write;

            let out_dir = env::var("OUT_DIR").unwrap();

            let headers = _libs.include_paths.clone();

            let mut builder = bindgen::builder()
                .blacklist_type("max_align_t")
                .rustfmt_bindings(false)
                .header("data/aom.h");

            for header in headers {
                builder = builder.clang_arg("-I").clang_arg(header.to_str().unwrap());
            }

            // Manually fix the comment so rustdoc won't try to pick them
            let s = builder
                .generate()
                .unwrap()
                .to_string()
                .replace("/**", "/*")
                .replace("/*!", "/*");

            let dest_path = Path::new(&out_dir).join("aom.rs");

            let mut file = fs::File::create(dest_path).unwrap();

            let _ = file.write(s.as_bytes());
        }
    }
    rerun_dir("aom_build");
    }
}
<|endoftext|>


<commit_before>//! This build script detects target platforms that lack proper support for
//! atomics and sets `cfg` flags accordingly.

use std::env;
use std::process::Command;
use std::str::{self, FromStr};

#[cfg(feature = "kv_unstable")]
#[path = "src/kv/value/internal/cast/primitive.rs"]
mod primitive;

fn main() {
    let minor = match rustc_minor_version() {
        Some(minor) => minor,
        None => return,
    };

    let target = match rustc_target() {
        Some(target) => target,
        None => return,
    };

    // If the target isn't thumbv6 then we can use atomic CAS
    if !target.starts_with("thumbv6") {
        println!("cargo:rustc-cfg=atomic_cas");
    }

    // If the Rust version is at least 1.46.0 then we can use type ids at compile time
    if minor >= 47 {
        println!("cargo:rustc-cfg=const_type_id");
    }

    // Generate sorted type id lookup
    #[cfg(feature = "kv_unstable")]
    primitive::generate();

    println!("cargo:rustc-cfg=srcbuild");
    println!("cargo:rerun-if-changed=build.rs");
}

fn rustc_target() -> Option<String> {
    env::var("TARGET").ok()
}

// From the `serde` build script
fn rustc_minor_version() -> Option<u32> {
    let rustc = match env::var_os("RUSTC") {
        Some(rustc) => rustc,
        None => return None,
    };

    let output = match Command::new(rustc).arg("--version").output() {
        Ok(output) => output,
        Err(_) => return None,
    };

    let version = match str::from_utf8(&output.stdout) {
        Ok(version) => version,
        Err(_) => return None,
    };

    let mut pieces = version.split('.');
    if pieces.next() != Some("rustc 1") {
        return None;
    }

    let next = match pieces.next() {
        Some(next) => next,
        None => return None,
    };

    u32::from_str(next).ok()
}
<commit_msg>build.rs: Update the list of non CAS targets<commit_after>//! This build script detects target platforms that lack proper support for
//! atomics and sets `cfg` flags accordingly.

use std::env;
use std::process::Command;
use std::str::{self, FromStr};

#[cfg(feature = "kv_unstable")]
#[path = "src/kv/value/internal/cast/primitive.rs"]
mod primitive;

fn main() {
    let minor = match rustc_minor_version() {
        Some(minor) => minor,
        None => return,
    };

    let target = match rustc_target() {
        Some(target) => target,
        None => return,
    };

    match &target[..] {
        "thumbv6m-none-eabi"
        | "msp430-none-elf"
        | "riscv32i-unknown-none-elf"
        | "riscv32imc-unknown-none-elf" => {}

        _ => {
            println!("cargo:rustc-cfg=atomic_cas");
        }
    };

    // If the Rust version is at least 1.46.0 then we can use type ids at compile time
    if minor >= 47 {
        println!("cargo:rustc-cfg=const_type_id");
    }

    // Generate sorted type id lookup
    #[cfg(feature = "kv_unstable")]
    primitive::generate();

    println!("cargo:rustc-cfg=srcbuild");
    println!("cargo:rerun-if-changed=build.rs");
}

fn rustc_target() -> Option<String> {
    env::var("TARGET").ok()
}

// From the `serde` build script
fn rustc_minor_version() -> Option<u32> {
    let rustc = match env::var_os("RUSTC") {
        Some(rustc) => rustc,
        None => return None,
    };

    let output = match Command::new(rustc).arg("--version").output() {
        Ok(output) => output,
        Err(_) => return None,
    };

    let version = match str::from_utf8(&output.stdout) {
        Ok(version) => version,
        Err(_) => return None,
    };

    let mut pieces = version.split('.');
    if pieces.next() != Some("rustc 1") {
        return None;
    }

    let next = match pieces.next() {
        Some(next) => next,
        None => return None,
    };

    u32::from_str(next).ok()
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Adam Perry <adam.n.perry@gmail.com>
//
// This software may be modified and distributed under the terms of the MIT license.  See the
// LICENSE file for details.

use std::env;
use std::fs::copy;
use std::path::Path;
use std::process::Command;

fn main() {
    let out_dir = env!("OUT_DIR");
    let num_jobs = env::var("NUM_JOBS").unwrap_or("1".to_string());

    // configure the build
    Command::new("./configure")
        .arg("--enable-shared")
        .arg("--with-pic")
        .current_dir(Path::new("parasail_c"))
        .output()
        .expect("Failed to configure parasail.");

    // build the library
    Command::new("make")
        .arg(format!("-j{}", num_jobs))
        .current_dir(Path::new("parasail_c"))
        .output()
        .expect("Failed to build parasail.");

    // put the static library in the right directory so we can clean up
    let target_file = format!("{}/libparasail.a", out_dir);
    copy("parasail_c/.libs/libparasail.a", target_file)
        .expect("Problem copying library to target directoy.");

    // clean up the temporary build files
    Command::new("make")
        .current_dir(Path::new("parasail_c"))
        .arg("clean")
        .output()
        .expect("Failed to clean up build files.");

    // clean up the configuration files
    Command::new("make")
        .arg("distclean")
        .current_dir(Path::new("parasail_c"))
        .output()
        .expect("Failed to clean up configuration files.");

    // let cargo know that it can find the file in the out directory
    println!("cargo:rustc-link-search=native={}", out_dir);
    println!("cargo:rustc-link-lib=static=parasail");
}
<commit_msg>Using correct OUT_DIR retrieval. Extracted a variable for a repeated Path::new().<commit_after>// Copyright (c) 2016 Adam Perry <adam.n.perry@gmail.com>
//
// This software may be modified and distributed under the terms of the MIT license.  See the
// LICENSE file for details.

use std::env;
use std::fs::copy;
use std::path::Path;
use std::process::Command;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let num_jobs = env::var("NUM_JOBS").unwrap();
    let c_src_path = Path::new("parasail_c");

    // configure the build
    Command::new("./configure")
        .arg("--enable-shared")
        .arg("--with-pic")
        .current_dir(&c_src_path)
        .output()
        .expect("Failed to configure parasail.");

    // build the library
    Command::new("make")
        .arg(format!("-j{}", num_jobs))
        .current_dir(&c_src_path)
        .output()
        .expect("Failed to build parasail.");

    // put the static library in the right directory so we can clean up
    let target_file = format!("{}/libparasail.a", out_dir);
    copy("parasail_c/.libs/libparasail.a", target_file)
        .expect("Problem copying library to target directoy.");

    // clean up the temporary build files
    Command::new("make")
        .current_dir(&c_src_path)
        .arg("clean")
        .output()
        .expect("Failed to clean up build files.");

    // clean up the configuration files
    Command::new("make")
        .arg("distclean")
        .current_dir(&c_src_path)
        .output()
        .expect("Failed to clean up configuration files.");

    // let cargo know that it can find the file in the out directory
    println!("cargo:rustc-link-search=native={}", out_dir);
    println!("cargo:rustc-link-lib=static=parasail");
}
<|endoftext|>