<commit_before>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

include!("../relm-state/src/macros.rs");
<commit_msg>Temporary fix to publish the crate<commit_after>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/// Connect events to sending a message.
///
/// ## Rules
/// 1. Send `$msg` to `$other_component` when the GTK+ `$event` is emitted on `$widget`.
///
/// 2. Optionally send `$msg.0` when the GTK+ `$event` is emitted on `$widget`.
/// Return `$msg.1` in the GTK+ callback.
/// This variant gives more control to the caller since it expects a `$msg` returning `(Option<MSG>,
/// ReturnValue)` where the `ReturnValue` is the value to return in the GTK+ callback.
/// Option<MSG> can be None if no message needs to be emitted.
///
/// 3. Send `$msg` when the GTK+ `$event` is emitted on `$widget`.
///
/// 4. Send `$msg` to `$widget` when the `$message` is received on `$stream`.
#[macro_export]
macro_rules! connect {
    // Connect to a GTK+ widget event, sending a message to another widget.
    ($widget:expr, $event:ident($($args:pat),*), $other_component:expr, $msg:expr) => {
        connect_stream!($widget, $event($($args),*), $other_component.stream(), $msg);
    };

    // Connect to a GTK+ widget event.
    // This variant gives more control to the caller since it expects a `$msg` returning (Option<MSG>,
    // ReturnValue) where the ReturnValue is the value to return in the GTK+ callback.
    // Option<MSG> can be None if no message needs to be emitted.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), return $msg:expr) => {{
        connect_stream!(return $relm.stream(), $widget, $event($($args),*), $msg);
    }};

    // Connect to a GTK+ widget event.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), $msg:expr) => {{
        let stream = $relm.stream().clone();
        let _ = $widget.$event(move |$($args),*| {
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    }};

    // Connect to a message reception.
    // TODO: create another macro rule accepting multiple patterns.
    ($src_component:ident @ $message:pat, $dst_component:expr, $msg:expr) => {
        let stream = $src_component.stream().clone();
        connect_stream!(stream@$message, $dst_component.stream(), $msg);
    };
}

/// Connect events to sending a message.
/// Similar to `connect!` but wants a stream instead of a component.
///
/// ## Rules
/// 1. Send `$msg` to `$other_stream` when the GTK+ `$event` is emitted on `$widget`.
///
/// 2. Send `$msg` to `$widget` when the `$message` is received on `$stream`.
#[macro_export]
macro_rules! connect_stream {
    // Connect to a GTK+ widget event.
    // This variant gives more control to the caller since it expects a `$msg` returning (Option<MSG>,
    // ReturnValue) where the ReturnValue is the value to return in the GTK+ callback.
    // Option<MSG> can be None if no message needs to be emitted.
    (return $stream:expr, $widget:expr, $event:ident($($args:pat),*), $msg:expr) => {{
        let stream = $stream.clone();
        let _ = $widget.$event(move |$($args),*| {
            let (msg, return_value) = $crate::IntoPair::into_pair($msg);
            let msg: Option<_> = $crate::IntoOption::into_option(msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
            return_value
        });
    }};

    // Connect to a GTK+ widget event, sending a message to another widget.
    ($widget:expr, $event:ident($($args:pat),*), $other_stream:expr, $msg:expr) => {
        let stream = $other_stream.clone();
        let _ = $widget.$event(move |$($args),*| {
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    };

    // Connect to a message reception.
    // TODO: create another macro rule accepting multiple patterns.
    ($src_stream:ident @ $message:pat, $dst_stream:expr, $msg:expr) => {
        let stream = $dst_stream.clone();
        $src_stream.observe(move |msg| {
            #[allow(unreachable_patterns)]
            match msg {
                &$message =>  {
                    let msg: Option<_> = $crate::IntoOption::into_option($msg);
                    if let Some(msg) = msg {
                        stream.emit(msg);
                    }
                },
                _ => (),
            }
        });
    };
}

/// Connect an asynchronous method call to send a message.
/// The variants with `$fail_msg` will send this message when there's an error.
/// Those without this argument will ignore the error.
#[macro_export]
macro_rules! connect_async {
    ($object:expr, $async_method:ident, $relm:expr, $msg:expr) => {
        connect_async!($object, $async_method(), $relm, $msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:expr) => {{
        let stream = $relm.stream().clone();
        $object.$async_method($($args,)* None, move |result| {
            if let Ok(result) = result {
                stream.emit($msg(result));
            }
        });
    }};
    ($object:expr, $async_method:ident, $relm:expr, $msg:expr, $fail_msg:expr) => {
        connect_async!($object, $async_method(), $relm, $msg, $fail_msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:expr, $fail_msg:expr) => {{
        let event_stream = $relm.stream().clone();
        let fail_event_stream = $relm.stream().clone();
        $object.$async_method($($args,)* None, move |result| {
            match result {
                Ok(value) => event_stream.emit($msg(value)),
                Err(error) => fail_event_stream.emit($fail_msg(error)),
            }
        });
    }};
}

/// Connect an asynchronous function call to send a message.
/// The variants with `$fail_msg` will send this message when there's an error.
/// Those without this argument will ignore the error.
#[macro_export]
macro_rules! connect_async_func {
    ($class:ident :: $async_function:ident, $relm:expr, $msg:expr) => {
        connect_async_func!($class::$async_func(), $relm, $msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:expr) => {{
        let stream = $relm.stream().clone();
        $class::$async_func($($args,)* None, move |result| {
            if let Ok(result) = result {
                stream.emit($msg(result));
            }
        });
    }};
    ($class:ident :: $async_func:ident, $relm:expr, $msg:expr, $fail_msg:expr) => {
        connect_async_func!($class::$async_func(), $relm, $msg, $fail_msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:expr, $fail_msg:expr) => {{
        let event_stream = $relm.stream().clone();
        let fail_event_stream = $relm.stream().clone();
        $class::$async_func($($args,)* None, move |result| {
            match result {
                Ok(value) => event_stream.emit($msg(value)),
                Err(error) => fail_event_stream.emit($fail_msg(error)),
            }
        });

    }};
}

/// Like `connect_async!`, but also return a `Cancellable` to control the asynchronous request.
#[macro_export]
macro_rules! connect_async_full {
    ($object:expr, $async_method:ident, $relm:expr, $msg:expr) => {
        connect_async_full!($object, $async_method(), $relm, $msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:expr) => {{
        let cancellable = ::gio::Cancellable::new();
        let stream = $relm.stream().clone();
        $object.$async_method($($args,)* Some(&cancellable), move |result| {
            if let Ok(result) = result {
                stream.emit($msg(result));
            }
        });
        cancellable
    }};
    ($object:expr, $async_method:ident, $relm:expr, $msg:expr, $fail_msg:expr) => {
        connect_async_full!($object, $async_method(), $relm, $msg, $fail_msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:expr, $fail_msg:expr) => {{
        let cancellable = ::gio::Cancellable::new();
        let event_stream = $relm.stream().clone();
        let fail_event_stream = $relm.stream().clone();
        $object.$async_method($($args,)* Some(&cancellable), move |result| {
            match result {
                Ok(value) => event_stream.emit($msg(value)),
                Err(error) => fail_event_stream.emit($fail_msg(error)),
            }
        });

        cancellable
    }};
}

/// Like `connect_async_func!`, but also return a `Cancellable` to control the asynchronous request.
#[macro_export]
macro_rules! connect_async_func_full {
    ($class:ident :: $async_function:ident, $relm:expr, $msg:expr) => {
        connect_async!($async_func(), $relm, $msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:expr) => {{
        let cancellable = ::gio::Cancellable::new();
        let stream = $relm.stream().clone();
        $class::$async_func($($args,)* Some(&cancellable), move |result| {
            if let Ok(result) = result {
                stream.emit($msg(result));
            }
        });
        cancellable
    }};
    ($class:ident :: $async_func:ident, $relm:expr, $msg:expr, $fail_msg:expr) => {
        connect_async!($async_func(), $relm, $msg, $fail_msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:expr, $fail_msg:expr) => {{
        let cancellable = ::gio::Cancellable::new();
        let event_stream = $relm.stream().clone();
        let fail_event_stream = $relm.stream().clone();
        $class::$async_func($($args,)* Some(&cancellable), move |result| {
            match result {
                Ok(value) => event_stream.emit($msg(value)),
                Err(error) => fail_event_stream.emit($fail_msg(error)),
            }
        });

        cancellable
    }};
}
<|endoftext|>


<commit_before>use quote::{Tokens, Ident};
use structs::Struct;

pub fn derive(input: &Struct) -> Tokens {
    let name = &input.name;
    let detail_mod = Ident::from(format!("__detail_{}", name));
    let vec_name = &input.vec_name();
    let slice_name = &input.slice_name();
    let slice_mut_name = &input.slice_mut_name();
    let ref_name = &input.ref_name();
    let ref_mut_name = &input.ref_mut_name();

    let fields_names = input.fields.iter()
                                   .map(|field| field.ident.clone().unwrap())
                                   .collect::<Vec<_>>();
    let fields_names_1 = &fields_names;
    let fields_names_2 = &fields_names;
    let first_field = &fields_names[0];

    let fields_types = &input.fields.iter()
                                    .map(|field| &field.ty)
                                    .collect::<Vec<_>>();

    quote! {
        #[allow(non_snake_case)]
        mod #detail_mod {
            use super::{#vec_name, #slice_name, #slice_mut_name, #ref_name, #ref_mut_name};
            use std::slice;

            pub struct Iter<'a> {
                #(#fields_names_1: slice::Iter<'a, #fields_types>,)*
            }

            impl<'a> Iterator for Iter<'a> {
                type Item = #ref_name<'a>;
                fn next(&mut self) -> Option<#ref_name<'a>> {
                    #(let #fields_names_1 = self.#fields_names_2.next();)*
                    if #first_field.is_none() {
                        None
                    } else {
                        Some(#ref_name {
                            #(#fields_names_1: #fields_names_2.unwrap(),)*
                        })
                    }
                }
            }

            impl #vec_name {
                pub fn iter(&self) -> Iter {
                    Iter {
                        #(#fields_names_1: self.#fields_names_2.iter(),)*
                    }
                }
            }

            impl<'a> #slice_name<'a> {
                pub fn iter(&self) -> Iter {
                    Iter {
                        #(#fields_names_1: self.#fields_names_2.iter(),)*
                    }
                }
            }

            pub struct IterMut<'a> {
                #(#fields_names_1: slice::IterMut<'a, #fields_types>,)*
            }

            impl<'a> Iterator for IterMut<'a> {
                type Item = #ref_mut_name<'a>;
                fn next(&mut self) -> Option<#ref_mut_name<'a>> {
                    #(let #fields_names_1 = self.#fields_names_2.next();)*
                    if #first_field.is_none() {
                        None
                    } else {
                        Some(#ref_mut_name {
                            #(#fields_names_1: #fields_names_2.unwrap(),)*
                        })
                    }
                }
            }

            impl #vec_name {
                pub fn iter_mut(&mut self) -> IterMut {
                    IterMut {
                        #(#fields_names_1: self.#fields_names_2.iter_mut(),)*
                    }
                }
            }

            impl<'a> #slice_mut_name<'a> {
                pub fn iter_mut(&mut self) -> IterMut {
                    IterMut {
                        #(#fields_names_1: self.#fields_names_2.iter_mut(),)*
                    }
                }
            }
        }
    }
}
<commit_msg>Allow to use types from outside of std<commit_after>use quote::{Tokens, Ident};
use structs::Struct;

pub fn derive(input: &Struct) -> Tokens {
    let name = &input.name;
    let detail_mod = Ident::from(format!("__detail_{}", name));
    let vec_name = &input.vec_name();
    let slice_name = &input.slice_name();
    let slice_mut_name = &input.slice_mut_name();
    let ref_name = &input.ref_name();
    let ref_mut_name = &input.ref_mut_name();

    let fields_names = input.fields.iter()
                                   .map(|field| field.ident.clone().unwrap())
                                   .collect::<Vec<_>>();
    let fields_names_1 = &fields_names;
    let fields_names_2 = &fields_names;
    let first_field = &fields_names[0];

    let fields_types = &input.fields.iter()
                                    .map(|field| &field.ty)
                                    .collect::<Vec<_>>();

    quote! {
        #[allow(non_snake_case)]
        mod #detail_mod {
            use super::*;
            use std::slice;

            pub struct Iter<'a> {
                #(#fields_names_1: slice::Iter<'a, #fields_types>,)*
            }

            impl<'a> Iterator for Iter<'a> {
                type Item = #ref_name<'a>;
                fn next(&mut self) -> Option<#ref_name<'a>> {
                    #(let #fields_names_1 = self.#fields_names_2.next();)*
                    if #first_field.is_none() {
                        None
                    } else {
                        Some(#ref_name {
                            #(#fields_names_1: #fields_names_2.unwrap(),)*
                        })
                    }
                }
            }

            impl #vec_name {
                pub fn iter(&self) -> Iter {
                    Iter {
                        #(#fields_names_1: self.#fields_names_2.iter(),)*
                    }
                }
            }

            impl<'a> #slice_name<'a> {
                pub fn iter(&self) -> Iter {
                    Iter {
                        #(#fields_names_1: self.#fields_names_2.iter(),)*
                    }
                }
            }

            pub struct IterMut<'a> {
                #(#fields_names_1: slice::IterMut<'a, #fields_types>,)*
            }

            impl<'a> Iterator for IterMut<'a> {
                type Item = #ref_mut_name<'a>;
                fn next(&mut self) -> Option<#ref_mut_name<'a>> {
                    #(let #fields_names_1 = self.#fields_names_2.next();)*
                    if #first_field.is_none() {
                        None
                    } else {
                        Some(#ref_mut_name {
                            #(#fields_names_1: #fields_names_2.unwrap(),)*
                        })
                    }
                }
            }

            impl #vec_name {
                pub fn iter_mut(&mut self) -> IterMut {
                    IterMut {
                        #(#fields_names_1: self.#fields_names_2.iter_mut(),)*
                    }
                }
            }

            impl<'a> #slice_mut_name<'a> {
                pub fn iter_mut(&mut self) -> IterMut {
                    IterMut {
                        #(#fields_names_1: self.#fields_names_2.iter_mut(),)*
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// An Iterator adapter that walks through all the elements in the Iterator,
// converts them to Strings and joins them to one big String, seperated by
// some seperator string slice.
pub trait StringJoiner {
  /// Converts all elements the Iterator yields to Strings,
  /// then combines them all into one String, seperated by sep.
  ///
  /// # Example
  ///
  /// ```
  /// use collect::iter::StringJoiner;
  ///
  /// let vec = vec![1u,2,3];
  /// assert_eq!(vec.iter().join(", ").as_slice(), "1, 2, 3");
  /// ```
  fn join(&mut self, sep: &str) -> String;
}

// Implement it for all Iterators with Elements convertable into a String
impl<A: ToString, T: Iterator<A>> StringJoiner for T {
  fn join(&mut self, sep: &str) -> String {
    match self.next() {
      Some(elem) => {
        let mut output = elem.to_string();
        for elem in *self {
          output.push_str(sep);
          output.push_str(elem.to_string().as_slice());
        }
        output
      }
      None => String::new()
    }
  }
}

#[test]
fn test_join() {
  let many = vec![1u,2,3];
  let one  = vec![1u];
  let none: Vec<uint> = vec![];

  assert_eq!(many.iter().join(", ").as_slice(), "1, 2, 3");
  assert_eq!( one.iter().join(", ").as_slice(), "1");
  assert_eq!(none.iter().join(", ").as_slice(), "");
}
<commit_msg>oops, more docs<commit_after>/// An Iterator adapter that walks through all the elements in the Iterator,
/// converts them to Strings and joins them to one big String, seperated by
/// some seperator string slice.
pub trait StringJoiner {
  /// Converts all elements the Iterator yields to Strings,
  /// then combines them all into one String, seperated by sep.
  ///
  /// # Example
  ///
  /// ```
  /// use collect::iter::StringJoiner;
  ///
  /// let vec = vec![1u,2,3];
  /// assert_eq!(vec.iter().join(", ").as_slice(), "1, 2, 3");
  /// ```
  fn join(&mut self, sep: &str) -> String;
}

// Implement it for all Iterators with Elements convertable into a String
impl<A: ToString, T: Iterator<A>> StringJoiner for T {
  fn join(&mut self, sep: &str) -> String {
    match self.next() {
      Some(elem) => {
        let mut output = elem.to_string();
        for elem in *self {
          output.push_str(sep);
          output.push_str(elem.to_string().as_slice());
        }
        output
      }
      None => String::new()
    }
  }
}

#[test]
fn test_join() {
  let many = vec![1u,2,3];
  let one  = vec![1u];
  let none: Vec<uint> = vec![];

  assert_eq!(many.iter().join(", ").as_slice(), "1, 2, 3");
  assert_eq!( one.iter().join(", ").as_slice(), "1");
  assert_eq!(none.iter().join(", ").as_slice(), "");
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cmp::Ordering;
use std::option::Option;

pub struct Node<T,C> {
    pub leaf: Option<Rc<C>>,
    pub func: Option<Rc<Fn(&T) -> bool>>,
    pub left: Option<Rc<Node<T,C>>>,
    pub right: Option<Rc<Node<T,C>>>
}

pub fn create_tree<C:Eq, T>(dataset:&Vec<(Rc<T>, Rc<C>)>,
                         rules:&Vec<Rc<Fn(&T)->bool>>,
                         gain:Rc<Fn(&Vec<(Rc<T>, Rc<C>)>, Rc<C>)->f64>)
                         ->  Option<Rc<Node<T,C>>> {

    if dataset.len() == 0 {
        return None;
    }

    let classes: Vec<Rc<C>> = dataset.iter().map(|x| {x.1.clone()}).collect();
    let mut score = Vec::new();

    if classes.len() == 1 {
        return Some(Rc::new(Node{leaf:Some(classes[0].clone()), func:None, left:None, right:None}));
    }
    for r in rules {
        let mut right = Rc::new(Vec::new());
        let mut left = Rc::new(Vec::new());
        for d in dataset {
            if r(&d.0) {
                Rc::get_mut(&mut left).unwrap().push(d.clone())
            }
            else {
                Rc::get_mut(&mut right).unwrap().push(d.clone());
            }
        }
        for c in &classes {
            score.push((r,
                        c.clone(),
                        gain(&left, c.clone()),
                        left.clone(),
                        gain(&right, c.clone()),
                        right.clone()));
        }
    }

    score.sort_by(|x, y| {
        if x.2 < y.2 && x.4 < y.4 {
            return Ordering::Less
        }
        if x.2 == y.2 && x.4 == y.4 {
            return Ordering::Equal
        }
        return Ordering::Greater
    });

    Some(Rc::new(Node{
        func: Some(score[0].0.clone()),
        leaf: None,
        left: create_tree(&score[0].3.as_ref(), rules, gain.clone()),
        right: create_tree(&score[0].5.as_ref(), rules, gain.clone())
    }))
}
<commit_msg>don't pass used already rule, and recursion stop is empty rule set<commit_after>use std::rc::Rc;
use std::cmp::Ordering;
use std::option::Option;

pub struct Node<T,C> {
    pub leaf: Option<Rc<C>>,
    pub func: Option<Rc<Fn(&T) -> bool>>,
    pub left: Option<Rc<Node<T,C>>>,
    pub right: Option<Rc<Node<T,C>>>
}

pub fn create_tree<C:Eq, T>(dataset:&Vec<(Rc<T>, Rc<C>)>,
                         rules:&Vec<Rc<Fn(&T)->bool>>,
                         gain:Rc<Fn(&Vec<(Rc<T>, Rc<C>)>, Rc<C>)->f64>)
                         ->  Option<Rc<Node<T,C>>> {

    if dataset.len() == 0 || rules.len() == 0 {
        return None;
    }

    let classes: Vec<Rc<C>> = dataset.iter().map(|x| {x.1.clone()}).collect();
    let mut score = Vec::new();

    if classes.len() == 1 {
        return Some(Rc::new(Node{leaf:Some(classes[0].clone()), func:None, left:None, right:None}));
    }
    for r in rules.iter().enumerate() {
        let mut right = Rc::new(Vec::new());
        let mut left = Rc::new(Vec::new());
        for d in dataset {
            if r.1(&d.0) {
                Rc::get_mut(&mut left).unwrap().push(d.clone())
            }
            else {
                Rc::get_mut(&mut right).unwrap().push(d.clone());
            }
        }
        for c in &classes {
            score.push((r,
                        c.clone(),
                        gain(&left, c.clone()),
                        left.clone(),
                        gain(&right, c.clone()),
                        right.clone()));
        }
    }

    let mut new_rules = rules.clone();
    new_rules.remove((score[0].0).0);
    score.sort_by(|x, y| {
        if x.2 < y.2 && x.4 < y.4 {
            return Ordering::Less
        }
        if x.2 == y.2 && x.4 == y.4 {
            return Ordering::Equal
        }
        return Ordering::Greater
    });

    Some(Rc::new(Node{
        func: Some((score[0].0).1.clone()),
        leaf: None,
        left: create_tree(&score[0].3.as_ref(), &new_rules, gain.clone()),
        right: create_tree(&score[0].5.as_ref(), &new_rules, gain.clone())
    }))
}
<|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/.

use std::{
    fmt::Debug,
    sync::{Once, ONCE_INIT},
};

use crate::engine::{
    types::{BlockDevState, FreeSpaceState, PoolExtendState, PoolState},
    MaybeDbusPath,
};

static INIT: Once = ONCE_INIT;
static mut ENGINE_LISTENER_LIST: Option<EngineListenerList> = None;

#[derive(Debug, Clone)]
pub enum EngineEvent<'a> {
    BlockdevStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: BlockDevState,
    },
    FilesystemRenamed {
        dbus_path: &'a MaybeDbusPath,
        from: &'a str,
        to: &'a str,
    },
    PoolExtendStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: PoolExtendState,
    },
    PoolRenamed {
        dbus_path: &'a MaybeDbusPath,
        from: &'a str,
        to: &'a str,
    },
    PoolSpaceStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: FreeSpaceState,
    },
    PoolStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: PoolState,
    },
}

pub trait EngineListener: Debug {
    fn notify(&self, event: &EngineEvent);
}

#[derive(Debug)]
pub struct EngineListenerList {
    listeners: Vec<Box<dyn EngineListener>>,
}

impl EngineListenerList {
    /// Create a new EngineListenerList.
    fn new() -> EngineListenerList {
        EngineListenerList {
            listeners: Vec::new(),
        }
    }

    /// Add a listener.
    pub fn register_listener(&mut self, listener: Box<dyn EngineListener>) {
        self.listeners.push(listener);
    }

    /// Notify a listener.
    pub fn notify(&self, event: &EngineEvent) {
        for listener in &self.listeners {
            listener.notify(&event);
        }
    }
}

pub fn get_engine_listener_list() -> &'static EngineListenerList {
    unsafe {
        INIT.call_once(|| ENGINE_LISTENER_LIST = Some(EngineListenerList::new()));
        match ENGINE_LISTENER_LIST {
            Some(ref mut ell) => ell,
            _ => panic!("ENGINE_LISTENER_LIST is None"),
        }
    }
}

pub fn get_engine_listener_list_mut() -> &'static mut EngineListenerList {
    unsafe {
        INIT.call_once(|| ENGINE_LISTENER_LIST = Some(EngineListenerList::new()));
        match ENGINE_LISTENER_LIST {
            Some(ref mut ell) => ell,
            _ => panic!("ENGINE_LISTENER_LIST is None"),
        }
    }
}
<commit_msg>Drop an unnecessary mut modifier<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/.

use std::{
    fmt::Debug,
    sync::{Once, ONCE_INIT},
};

use crate::engine::{
    types::{BlockDevState, FreeSpaceState, PoolExtendState, PoolState},
    MaybeDbusPath,
};

static INIT: Once = ONCE_INIT;
static mut ENGINE_LISTENER_LIST: Option<EngineListenerList> = None;

#[derive(Debug, Clone)]
pub enum EngineEvent<'a> {
    BlockdevStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: BlockDevState,
    },
    FilesystemRenamed {
        dbus_path: &'a MaybeDbusPath,
        from: &'a str,
        to: &'a str,
    },
    PoolExtendStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: PoolExtendState,
    },
    PoolRenamed {
        dbus_path: &'a MaybeDbusPath,
        from: &'a str,
        to: &'a str,
    },
    PoolSpaceStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: FreeSpaceState,
    },
    PoolStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: PoolState,
    },
}

pub trait EngineListener: Debug {
    fn notify(&self, event: &EngineEvent);
}

#[derive(Debug)]
pub struct EngineListenerList {
    listeners: Vec<Box<dyn EngineListener>>,
}

impl EngineListenerList {
    /// Create a new EngineListenerList.
    fn new() -> EngineListenerList {
        EngineListenerList {
            listeners: Vec::new(),
        }
    }

    /// Add a listener.
    pub fn register_listener(&mut self, listener: Box<dyn EngineListener>) {
        self.listeners.push(listener);
    }

    /// Notify a listener.
    pub fn notify(&self, event: &EngineEvent) {
        for listener in &self.listeners {
            listener.notify(&event);
        }
    }
}

pub fn get_engine_listener_list() -> &'static EngineListenerList {
    unsafe {
        INIT.call_once(|| ENGINE_LISTENER_LIST = Some(EngineListenerList::new()));
        match ENGINE_LISTENER_LIST {
            Some(ref ell) => ell,
            _ => panic!("ENGINE_LISTENER_LIST is None"),
        }
    }
}

pub fn get_engine_listener_list_mut() -> &'static mut EngineListenerList {
    unsafe {
        INIT.call_once(|| ENGINE_LISTENER_LIST = Some(EngineListenerList::new()));
        match ENGINE_LISTENER_LIST {
            Some(ref mut ell) => ell,
            _ => panic!("ENGINE_LISTENER_LIST is None"),
        }
    }
}
<|endoftext|>


<commit_before>//! This is a memory mock for the fact database interface.
//!
//! The primary purpose of this module is to allow for quick doctest-time
//! checks of the language. Any serious program should use a different backend,
//! as should the correctness tests.
//!
//! It is not built efficiently, and I do not intend to make it efficient - I'd
//! essentially be reimplementing many parts of a traditional database
//! (indexing, joins, etc).
use fact_db::{FactDB, FactId, CacheId};
use pg::dyn::{Value, Type};
use pg::dyn::types::default_types;
use engine::types::{Fact, Clause, Predicate, MatchExpr};
use std::collections::{HashMap, HashSet};

use std::error;
use std::fmt;
use std::result;

#[derive(Debug)]
/// Type for errors arising from MemDB interaction
pub enum Error {
    /// MemDB Type Error
    Type(String),
}

type Result<T> = result::Result<T, Error>;

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
        match *self {
            Error::Type(ref msg) => write!(fmt, "MemDB Type Error: {}", msg),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        return "MemDB Error";
    }
}

/// MemDB is an in-memory mock up of the fact database interface.
///
/// While it can be useful for quick tests, it should not be depended on for
/// anything serious, even if you want a standalone app. It is very slow and
/// persists nothing.
pub struct MemDB {
    facts: HashMap<FactId, Fact>,
    facts_set: HashSet<Fact>,
    next_id: FactId,
    rule_cache: Vec<HashSet<Vec<FactId>>>,
    types: HashMap<String, Type>,
    preds: HashMap<String, Predicate>,
}

impl MemDB {
    /// Creates a fresh empty `MemDB`.
    pub fn new() -> MemDB {
        MemDB {
            facts: HashMap::new(),
            next_id: 0,
            facts_set: HashSet::new(),
            rule_cache: Vec::new(),
            types: default_types()
                .iter()
                .map(|type_| (type_.name().unwrap().to_owned(), type_.clone()))
                .collect(),
            preds: HashMap::new(),
        }
    }
}

fn raw_option<T>(some: bool, val: T) -> Option<T> {
    if some { Some(val) } else { None }
}

impl FactDB for MemDB {
    type Error = Error;
    fn new_rule_cache(&mut self, _preds: Vec<String>) -> Result<CacheId> {
        self.rule_cache.push(HashSet::new());
        Ok((self.rule_cache.len() - 1) as CacheId)
    }
    fn cache_hit(&mut self, cache: CacheId, facts: Vec<FactId>) -> Result<()> {
        self.rule_cache[cache as usize].insert(facts);
        Ok(())
    }
    fn insert_fact(&mut self, fact: &Fact) -> Result<bool> {
        if self.facts_set.contains(fact) {
            return Ok(false);
        };
        let id = self.next_id;
        self.next_id += 1;
        self.facts.insert(id, fact.clone());
        self.facts_set.insert(fact.clone());
        Ok(true)
    }
    fn add_type(&mut self, type_: Type) -> Result<()> {
        self.types.insert(type_.name().unwrap().to_string(), type_);
        Ok(())
    }
    fn get_type(&self, type_str: &str) -> Option<Type> {
        self.types.get(type_str).map(|x| x.clone())
    }
    fn get_predicate(&self, pred_name: &str) -> Option<&Predicate> {
        self.preds.get(pred_name)
    }
    fn new_predicate(&mut self, pred: &Predicate) -> Result<()> {
        match self.preds.get(&pred.name) {
            Some(exist) => {
                if exist == pred {
                    return Ok(());
                } else {
                    return Err(Error::Type(format!("Predicate \
                                                     already registered \
                                                     with different \
                                                     type.\nExisting: \
                                                     {:?}\nNew: \
                                                     {:?}",
                                                   exist,
                                                   pred)));
                }
            }
            None => (),
        }
        self.preds.insert(pred.name.to_string(), pred.clone());
        Ok(())
    }
    fn search_facts(&self,
                    query: &Vec<Clause>,
                    cache: Option<CacheId>)
                    -> Result<Vec<(Vec<FactId>, Vec<Value>)>> {
        Ok(query.iter().fold(vec![(vec![], vec![])], |asgns, clause| {
            asgns.iter()
                .flat_map(|asgn| {
                    self.facts.iter().flat_map(move |(id, fact)| {
                        (if fact.pred_name == clause.pred_name {
                                fact.args
                                    .iter()
                                    .zip(clause.args.iter())
                                    .fold(Some({
                                              let mut nasgn = asgn.clone();
                                              nasgn.0.push(*id);
                                              nasgn
                                          }),
                                          |o_asgn, (val, arg)| {
                                        o_asgn.and_then(|asgn| {
                                            match *arg {
                                                MatchExpr::Unbound => Some(asgn),
                                                MatchExpr::Var(var) => {
                                                    if var >= asgn.1.len() {
                                                        let mut next = asgn.clone();
                                                        next.1.push(val.clone());
                                                        Some(next)
                                                    } else {
                                                        raw_option(&asgn.1[var] == val, asgn)
                                                    }
                                                }
                                                MatchExpr::SubStr(_, _, _) => {
                                                    panic!("Substring not implemented in memdb")
                                                }
                                                MatchExpr::Const(ref k) => {
                                                    raw_option(k == val, asgn)
                                                }
                                            }
                                        })
                                    })
                            } else {
                                None
                            })
                            .into_iter()
                    })
                })
                .filter(|&(ref facts, _)| {
                    match cache {
                        Some(c) => !self.rule_cache[c as usize].contains(facts),
                        None => true,
                    }
                })
                .collect()
        }))
    }
}
<commit_msg>Switched MemDB to error-chain<commit_after>//! This is a memory mock for the fact database interface.
//!
//! The primary purpose of this module is to allow for quick doctest-time
//! checks of the language. Any serious program should use a different backend,
//! as should the correctness tests.
//!
//! It is not built efficiently, and I do not intend to make it efficient - I'd
//! essentially be reimplementing many parts of a traditional database
//! (indexing, joins, etc).
use fact_db::{FactDB, FactId, CacheId};
use pg::dyn::{Value, Type};
use pg::dyn::types::default_types;
use engine::types::{Fact, Clause, Predicate, MatchExpr};
use std::collections::{HashMap, HashSet};

#[allow(missing_docs)]
mod errors {
    error_chain! {
        errors {
            Type(msg: String)
        }
    }
}

pub use self::errors::*;

/// MemDB is an in-memory mock up of the fact database interface.
///
/// While it can be useful for quick tests, it should not be depended on for
/// anything serious, even if you want a standalone app. It is very slow and
/// persists nothing.
pub struct MemDB {
    facts: HashMap<FactId, Fact>,
    facts_set: HashSet<Fact>,
    next_id: FactId,
    rule_cache: Vec<HashSet<Vec<FactId>>>,
    types: HashMap<String, Type>,
    preds: HashMap<String, Predicate>,
}

impl MemDB {
    /// Creates a fresh empty `MemDB`.
    pub fn new() -> MemDB {
        MemDB {
            facts: HashMap::new(),
            next_id: 0,
            facts_set: HashSet::new(),
            rule_cache: Vec::new(),
            types: default_types()
                .iter()
                .map(|type_| (type_.name().unwrap().to_owned(), type_.clone()))
                .collect(),
            preds: HashMap::new(),
        }
    }
}

fn raw_option<T>(some: bool, val: T) -> Option<T> {
    if some { Some(val) } else { None }
}

impl FactDB for MemDB {
    type Error = Error;
    fn new_rule_cache(&mut self, _preds: Vec<String>) -> Result<CacheId> {
        self.rule_cache.push(HashSet::new());
        Ok((self.rule_cache.len() - 1) as CacheId)
    }
    fn cache_hit(&mut self, cache: CacheId, facts: Vec<FactId>) -> Result<()> {
        self.rule_cache[cache as usize].insert(facts);
        Ok(())
    }
    fn insert_fact(&mut self, fact: &Fact) -> Result<bool> {
        if self.facts_set.contains(fact) {
            return Ok(false);
        };
        let id = self.next_id;
        self.next_id += 1;
        self.facts.insert(id, fact.clone());
        self.facts_set.insert(fact.clone());
        Ok(true)
    }
    fn add_type(&mut self, type_: Type) -> Result<()> {
        self.types.insert(type_.name().unwrap().to_string(), type_);
        Ok(())
    }
    fn get_type(&self, type_str: &str) -> Option<Type> {
        self.types.get(type_str).map(|x| x.clone())
    }
    fn get_predicate(&self, pred_name: &str) -> Option<&Predicate> {
        self.preds.get(pred_name)
    }
    fn new_predicate(&mut self, pred: &Predicate) -> Result<()> {
        match self.preds.get(&pred.name) {
            Some(exist) => {
                if exist == pred {
                    return Ok(());
                } else {
                    bail!(ErrorKind::Type(format!(
                                "Predicate already registered with different type.\nExisting: {:?}\nNew: {:?}",
                                exist,
                                pred)));
                }
            }
            None => (),
        }
        self.preds.insert(pred.name.to_string(), pred.clone());
        Ok(())
    }
    fn search_facts(&self,
                    query: &Vec<Clause>,
                    cache: Option<CacheId>)
                    -> Result<Vec<(Vec<FactId>, Vec<Value>)>> {
        Ok(query.iter().fold(vec![(vec![], vec![])], |asgns, clause| {
            asgns.iter()
                .flat_map(|asgn| {
                    self.facts.iter().flat_map(move |(id, fact)| {
                        (if fact.pred_name == clause.pred_name {
                                fact.args
                                    .iter()
                                    .zip(clause.args.iter())
                                    .fold(Some({
                                              let mut nasgn = asgn.clone();
                                              nasgn.0.push(*id);
                                              nasgn
                                          }),
                                          |o_asgn, (val, arg)| {
                                        o_asgn.and_then(|asgn| {
                                            match *arg {
                                                MatchExpr::Unbound => Some(asgn),
                                                MatchExpr::Var(var) => {
                                                    if var >= asgn.1.len() {
                                                        let mut next = asgn.clone();
                                                        next.1.push(val.clone());
                                                        Some(next)
                                                    } else {
                                                        raw_option(&asgn.1[var] == val, asgn)
                                                    }
                                                }
                                                MatchExpr::SubStr(_, _, _) => {
                                                    panic!("Substring not implemented in memdb")
                                                }
                                                MatchExpr::Const(ref k) => {
                                                    raw_option(k == val, asgn)
                                                }
                                            }
                                        })
                                    })
                            } else {
                                None
                            })
                            .into_iter()
                    })
                })
                .filter(|&(ref facts, _)| {
                    match cache {
                        Some(c) => !self.rule_cache[c as usize].contains(facts),
                        None => true,
                    }
                })
                .collect()
        }))
    }
}
<|endoftext|>


<commit_before>use super::mapper;

struct RAM {
    ram: [u8; 0x800]
}

impl RAM {
    fn read(&self, address: u16) -> u8 {
        self.ram[address as usize & 0x7FF]
    }
    fn write(&mut self, address: u16, value: u8) {
        self.ram[address as usize & 0x7FF] = value;
    }
}

pub struct MemMap {
    ram: RAM,
    //ppu: PPU,
    //apu: APU,
    //controllers: Controllers,
    mapper: mapper::Mapper,
}

impl MemMap {
    pub fn new(mapper: mapper::Mapper) -> MemMap {
        MemMap {
            ram: RAM { ram: [0; 0x800] },
            mapper: mapper,
        }
    }
    pub fn read(&self, address: u16) -> u8 {
        if address < 0x2000 {
            self.ram.read(address)
        }
        else if address >= 0x8000 {
            self.mapper.read(address)
        }
        else {
            0
        }
    }

    pub fn write(&mut self, address: u16, value: u8) {
        if address < 0x2000 {
            self.ram.write(address, value);
        }
    }

    pub fn readw(&self, address: u16) -> u16 {
         ((self.read(address + 1) as u16) << 8) | (self.read(address) as u16)
    }
}
<commit_msg>Include readw_zp method to the memory mapper that handles zero page wrap around when reading 2 bytes.<commit_after>use super::mapper;

struct RAM {
    ram: [u8; 0x800]
}

impl RAM {
    fn read(&self, address: u16) -> u8 {
        self.ram[address as usize & 0x7FF]
    }
    fn write(&mut self, address: u16, value: u8) {
        self.ram[address as usize & 0x7FF] = value;
    }
}

pub struct MemMap {
    ram: RAM,
    //ppu: PPU,
    //apu: APU,
    //controllers: Controllers,
    mapper: mapper::Mapper,
}

impl MemMap {
    pub fn new(mapper: mapper::Mapper) -> MemMap {
        MemMap {
            ram: RAM { ram: [0; 0x800] },
            mapper: mapper,
        }
    }
    pub fn read(&self, address: u16) -> u8 {
        if address < 0x2000 {
            self.ram.read(address)
        }
        else if address >= 0x8000 {
            self.mapper.read(address)
        }
        else {
            0
        }
    }

    pub fn write(&mut self, address: u16, value: u8) {
        if address < 0x2000 {
            self.ram.write(address, value);
        }
    }

    pub fn readw(&self, address: u16) -> u16 {
         ((self.read(address + 1) as u16) << 8) | (self.read(address) as u16)
    }
    pub fn readw_zp(&self, address: u16) -> u16 {
        if address > 0xFF {
            panic!("readw_zp address should be less than or equal to 0x00FF");
        }
        if address == 0xFF {
            ((self.read(0x0000) as u16) << 8) | (self.read(0x00FF) as u16)
        }
        else {
            ((self.read(address + 1) as u16) << 8) | (self.read(address) as u16)
        }
    }
}
<|endoftext|>


<commit_before>extern crate pkg_config;
extern crate gcc;

use std::env;
use std::path::PathBuf;

fn main() {
    // Find and link OpenEXR and IlmBase
    let include_paths = {
        let mut include_paths = Vec::new();

        let suffix = if let Ok(v) = env::var("OPENEXR_LIB_SUFFIX") {
            format!("-{}", v)
        } else {
            "".into()
        };

        if let Ok(path) = env::var("OPENEXR_DIR") {
            // There's an environment variable, so let's use that
            println!("cargo:rustc-link-search=native={}/lib", path);
            println!("cargo:rustc-link-lib=static=IlmImf{}", suffix);
            println!("cargo:rustc-link-lib=static=IlmImfUtil{}", suffix);
            include_paths.push(PathBuf::from(&format!("{}/include/OpenEXR", path)));
        } else {
            // There's no enviroment variable, so use pkgconfig to find
            // the libs
            let paths = pkg_config::Config::new()
                .atleast_version("2.0.0")
                .probe("OpenEXR")
                .map(|openexr_cfg| openexr_cfg.include_paths.clone())
                .map_err(|err| {
                    panic!("couldn't find OpenEXR: environment variable \
                            OPENEXR_DIR is unset and pkg-config failed: {}",
                           err)
                })
                .unwrap();

            include_paths.extend_from_slice(&paths);
        }

        if let Ok(path) = env::var("ILMBASE_DIR") {
            println!("cargo:rustc-link-search=native={}/lib", path);
            println!("cargo:rustc-link-lib=static=IexMath{}", suffix);
            println!("cargo:rustc-link-lib=static=Iex{}", suffix);
            println!("cargo:rustc-link-lib=static=Imath{}", suffix);
            println!("cargo:rustc-link-lib=static=IlmThread{}", suffix);
            println!("cargo:rustc-link-lib=static=Half");
            include_paths.push(PathBuf::from(&format!("{}/include/OpenEXR", path)));
        } else {
            let paths = pkg_config::Config::new()
                .atleast_version("2.0.0")
                .cargo_metadata(false) // OpenEXR already pulls in all the flags we need
                .probe("IlmBase")
                .map(|ilmbase_cfg| ilmbase_cfg.include_paths.clone())
                .map_err(|err| {
                    panic!("couldn't find IlmBase: environment variable \
                            OPENEXR_DIR is unset and pkg-config failed: {}",
                           err)
                })
                .unwrap();
            include_paths.extend_from_slice(&paths);
        }

        include_paths
    };

    // Find and link zlib, needed for OpenEXR
    // Use environment variable if it exists, and otherwise use pkgconfig.
    if let Ok(path) = env::var("ZLIB_DIR") {
        println!("cargo:rustc-link-search=native={}/lib", path);
        println!("cargo:rustc-link-lib=static=zlibstatic");
    } else if let Err(err) = pkg_config::probe_library("zlib") {
        panic!("couldn't find zlib: environment variable ZLIB_DIR is unset \
            and pkg-config failed: {}",
               err);
    }

    // Build C wrapper for OpenEXR
    let mut gcc = gcc::Config::new();
    gcc.cpp(true).include("c_wrapper");
    #[cfg(target_env = "msvc")]
    gcc.flag("/std:c++14");
    #[cfg(not(target_env = "msvc"))]
    gcc.flag("-std=c++14");
    for path in &include_paths {
        gcc.include(path);
    }
    gcc.file("c_wrapper/cexr.cpp")
        .file("c_wrapper/memory_istream.cpp")
        .compile("libcexr.a");
}
<commit_msg>Fix build error message typo.<commit_after>extern crate pkg_config;
extern crate gcc;

use std::env;
use std::path::PathBuf;

fn main() {
    // Find and link OpenEXR and IlmBase
    let include_paths = {
        let mut include_paths = Vec::new();

        let suffix = if let Ok(v) = env::var("OPENEXR_LIB_SUFFIX") {
            format!("-{}", v)
        } else {
            "".into()
        };

        if let Ok(path) = env::var("OPENEXR_DIR") {
            // There's an environment variable, so let's use that
            println!("cargo:rustc-link-search=native={}/lib", path);
            println!("cargo:rustc-link-lib=static=IlmImf{}", suffix);
            println!("cargo:rustc-link-lib=static=IlmImfUtil{}", suffix);
            include_paths.push(PathBuf::from(&format!("{}/include/OpenEXR", path)));
        } else {
            // There's no enviroment variable, so use pkgconfig to find
            // the libs
            let paths = pkg_config::Config::new()
                .atleast_version("2.0.0")
                .probe("OpenEXR")
                .map(|openexr_cfg| openexr_cfg.include_paths.clone())
                .map_err(|err| {
                    panic!("couldn't find OpenEXR: environment variable \
                            OPENEXR_DIR is unset and pkg-config failed: {}",
                           err)
                })
                .unwrap();

            include_paths.extend_from_slice(&paths);
        }

        if let Ok(path) = env::var("ILMBASE_DIR") {
            println!("cargo:rustc-link-search=native={}/lib", path);
            println!("cargo:rustc-link-lib=static=IexMath{}", suffix);
            println!("cargo:rustc-link-lib=static=Iex{}", suffix);
            println!("cargo:rustc-link-lib=static=Imath{}", suffix);
            println!("cargo:rustc-link-lib=static=IlmThread{}", suffix);
            println!("cargo:rustc-link-lib=static=Half");
            include_paths.push(PathBuf::from(&format!("{}/include/OpenEXR", path)));
        } else {
            let paths = pkg_config::Config::new()
                .atleast_version("2.0.0")
                .cargo_metadata(false) // OpenEXR already pulls in all the flags we need
                .probe("IlmBase")
                .map(|ilmbase_cfg| ilmbase_cfg.include_paths.clone())
                .map_err(|err| {
                    panic!("couldn't find IlmBase: environment variable \
                            ILMBASE_DIR is unset and pkg-config failed: {}",
                           err)
                })
                .unwrap();
            include_paths.extend_from_slice(&paths);
        }

        include_paths
    };

    // Find and link zlib, needed for OpenEXR
    // Use environment variable if it exists, and otherwise use pkgconfig.
    if let Ok(path) = env::var("ZLIB_DIR") {
        println!("cargo:rustc-link-search=native={}/lib", path);
        println!("cargo:rustc-link-lib=static=zlibstatic");
    } else if let Err(err) = pkg_config::probe_library("zlib") {
        panic!("couldn't find zlib: environment variable ZLIB_DIR is unset \
            and pkg-config failed: {}",
               err);
    }

    // Build C wrapper for OpenEXR
    let mut gcc = gcc::Config::new();
    gcc.cpp(true).include("c_wrapper");
    #[cfg(target_env = "msvc")]
    gcc.flag("/std:c++14");
    #[cfg(not(target_env = "msvc"))]
    gcc.flag("-std=c++14");
    for path in &include_paths {
        gcc.include(path);
    }
    gcc.file("c_wrapper/cexr.cpp")
        .file("c_wrapper/memory_istream.cpp")
        .compile("libcexr.a");
}
<|endoftext|>


<commit_before>use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::ptr;
use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
use std::time::Instant;

use coco::epoch::{self, Atomic, Owned};

use CaseId;
use actor;
use backoff::Backoff;
use err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError};
use monitor::Monitor;

const NODE_LEN: usize = 32;

struct Entry<T> {
    value: ManuallyDrop<T>,
    ready: AtomicBool,
}

struct Node<T> {
    start: usize,
    entries: [UnsafeCell<Entry<T>>; NODE_LEN],
    next: Atomic<Node<T>>,
}

impl<T> Node<T> {
    fn new(start: usize) -> Node<T> {
        Node {
            start,
            entries: unsafe { mem::zeroed() },
            next: Atomic::null(),
        }
    }
}

#[repr(C)]
pub(crate) struct Channel<T> {
    low: AtomicUsize,
    head: Atomic<Node<T>>,
    _pad0: [u8; 64],
    high: AtomicUsize,
    tail: Atomic<Node<T>>,
    _pad1: [u8; 64],
    closed: AtomicBool,
    receivers: Monitor,
    _marker: PhantomData<T>,
}

impl<T> Channel<T> {
    pub fn new() -> Self {
        let queue = Channel {
            head: Atomic::null(),
            tail: Atomic::null(),
            low: AtomicUsize::new(0),
            high: AtomicUsize::new(0),
            closed: AtomicBool::new(false),
            receivers: Monitor::new(),
            _pad0: [0; 64],
            _pad1: [0; 64],
            _marker: PhantomData,
        };

        unsafe {
            epoch::unprotected(|scope| {
                let node = Owned::new(Node::new(0)).into_ptr(scope);
                queue.head.store(node, Relaxed);
                queue.tail.store(node, Relaxed);
            })
        }

        queue
    }

    fn push(&self, value: T) {
        epoch::pin(|scope| {
            let mut backoff = Backoff::new();
            loop {
                let tail = unsafe { self.tail.load(SeqCst, scope).deref() };
                let high = self.high.load(SeqCst);
                let new_high = high.wrapping_add(1);
                let offset = high.wrapping_sub(tail.start);

                if offset >= NODE_LEN {
                    backoff.step();
                    continue;
                }

                if self.high.compare_and_swap(high, new_high, SeqCst) == high {
                    unsafe {
                        let entry = tail.entries.get_unchecked(offset).get();
                        ptr::write(&mut (*entry).value, ManuallyDrop::new(value));
                        (*entry).ready.store(true, SeqCst);
                    }

                    if offset + 1 == NODE_LEN {
                        let new = Owned::new(Node::new(new_high)).into_ptr(scope);
                        tail.next.store(new, SeqCst);
                        self.tail.store(new, SeqCst);
                    }

                    return;
                }
            }
        })
    }

    fn pop(&self) -> Option<T> {
        epoch::pin(|scope| {
            let mut backoff = Backoff::new();
            loop {
                let head = self.head.load(SeqCst, scope);
                let h = unsafe { head.deref() };
                let low = self.low.load(SeqCst);
                let new_low = low.wrapping_add(1);
                let offset = low.wrapping_sub(h.start);

                if offset >= NODE_LEN {
                    backoff.step();
                    continue;
                }

                let entry = unsafe { &*h.entries.get_unchecked(offset).get() };

                if !entry.ready.load(Relaxed) && self.high.load(SeqCst) == low {
                    return None;
                }

                if self.low.compare_and_swap(low, new_low, SeqCst) == low {
                    while !entry.ready.load(SeqCst) {
                        backoff.step();
                    }

                    if offset + 1 == NODE_LEN {
                        loop {
                            let next = h.next.load(SeqCst, scope);
                            if !next.is_null() {
                                self.head.store(next, SeqCst);
                                unsafe {
                                    scope.defer_free(head);
                                }
                                break;
                            }
                            backoff.step();
                        }
                    }

                    let v = unsafe { ptr::read(&(*entry).value) };
                    return Some(ManuallyDrop::into_inner(v));
                }
            }
        })
    }

    pub fn len(&self) -> usize {
        loop {
            let high = self.high.load(SeqCst);
            let low = self.low.load(SeqCst);

            if self.high.load(SeqCst) == high {
                return high.wrapping_sub(low);
            }
        }
    }

    pub fn try_send(&self, value: T) -> Result<(), TrySendError<T>> {
        if self.closed.load(SeqCst) {
            Err(TrySendError::Disconnected(value))
        } else {
            self.push(value);
            self.receivers.notify_one();
            Ok(())
        }
    }

    pub fn send(&self, value: T) -> Result<(), SendTimeoutError<T>> {
        if self.closed.load(SeqCst) {
            Err(SendTimeoutError::Disconnected(value))
        } else {
            self.push(value);
            self.receivers.notify_one();
            Ok(())
        }
    }

    pub fn try_recv(&self) -> Result<T, TryRecvError> {
        let closed = self.closed.load(SeqCst);
        match self.pop() {
            None => if closed {
                Err(TryRecvError::Disconnected)
            } else {
                Err(TryRecvError::Empty)
            },
            Some(v) => Ok(v),
        }
    }

    pub fn spin_try_recv(&self) -> Result<T, TryRecvError> {
        for _ in 0..20 {
            let closed = self.closed.load(SeqCst);
            if let Some(v) = self.pop() {
                return Ok(v);
            }
            if closed {
                return Err(TryRecvError::Disconnected);
            }
        }
        Err(TryRecvError::Empty)
    }

    pub fn recv_until(
        &self,
        deadline: Option<Instant>,
        case_id: CaseId,
    ) -> Result<T, RecvTimeoutError> {
        loop {
            match self.spin_try_recv() {
                Ok(v) => return Ok(v),
                Err(TryRecvError::Empty) => {}
                Err(TryRecvError::Disconnected) => return Err(RecvTimeoutError::Disconnected),
            }

            actor::current_reset();
            self.receivers.register(case_id);
            let is_closed = self.is_closed();
            let timed_out = !is_closed && self.is_empty() && !actor::current_wait_until(deadline);
            self.receivers.unregister(case_id);

            if is_closed {
                return Err(RecvTimeoutError::Disconnected);
            } else if timed_out {
                return Err(RecvTimeoutError::Timeout);
            }
        }
    }

    /// Closes the channel.
    pub fn close(&self) -> bool {
        if self.closed.swap(true, SeqCst) {
            false
        } else {
            self.receivers.abort_all();
            true
        }
    }

    /// Returns `true` if the channel is closed.
    pub fn is_closed(&self) -> bool {
        self.closed.load(SeqCst)
    }

    /// Returns `true` if the channel is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn receivers(&self) -> &Monitor {
        &self.receivers
    }
}

impl<T> Drop for Channel<T> {
    fn drop(&mut self) {
        unsafe {
            epoch::unprotected(|scope| {
                let high = self.high.load(Relaxed);
                let mut low = self.low.load(Relaxed);
                let mut node = self.head.load(Relaxed, scope);

                while low != high {
                    let n = node.deref();
                    let offset = low.wrapping_sub(n.start);
                    let entry = &mut *n.entries.get_unchecked(offset).get();

                    let v = ptr::read(&mut (*entry).value);
                    drop(ManuallyDrop::into_inner(v));

                    if offset + 1 == NODE_LEN {
                        let next = n.next.load(Relaxed, scope);
                        node.destroy();
                        node = next;
                    }

                    low = low.wrapping_add(1);
                }
            })
        }
    }
}
<commit_msg>Use CachePadded<commit_after>//! Linked list-based channel implementation.
//!
//! This flavor is unbounded.

use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::ptr;
use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
use std::time::Instant;

use coco::epoch::{self, Atomic, Owned};
use crossbeam_utils::cache_padded::CachePadded;

use CaseId;
use actor;
use backoff::Backoff;
use err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError};
use monitor::Monitor;

const NODE_LEN: usize = 32;

struct Entry<T> {
    value: ManuallyDrop<T>,
    ready: AtomicBool,
}

struct Node<T> {
    start: usize,
    entries: [UnsafeCell<Entry<T>>; NODE_LEN],
    next: Atomic<Node<T>>,
}

impl<T> Node<T> {
    fn new(start: usize) -> Node<T> {
        Node {
            start,
            entries: unsafe { mem::zeroed() },
            next: Atomic::null(),
        }
    }
}

struct Position<T> {
    index: AtomicUsize,
    node: Atomic<Node<T>>,
}

pub struct Channel<T> {
    head: CachePadded<Position<T>>,
    tail: CachePadded<Position<T>>,
    closed: AtomicBool,
    receivers: Monitor,
    _marker: PhantomData<T>,
}

impl<T> Channel<T> {
    pub fn new() -> Self {
        let queue = Channel {
            head: CachePadded::new(Position {
                index: AtomicUsize::new(0),
                node: Atomic::null(),
            }),
            tail: CachePadded::new(Position {
                index: AtomicUsize::new(0),
                node: Atomic::null(),
            }),
            closed: AtomicBool::new(false),
            receivers: Monitor::new(),
            _marker: PhantomData,
        };

        unsafe {
            epoch::unprotected(|scope| {
                let node = Owned::new(Node::new(0)).into_ptr(scope);
                queue.head.node.store(node, Relaxed);
                queue.tail.node.store(node, Relaxed);
            })
        }

        queue
    }

    fn push(&self, value: T) {
        epoch::pin(|scope| {
            let mut backoff = Backoff::new();
            loop {
                let tail = unsafe { self.tail.node.load(SeqCst, scope).deref() };
                let index = self.tail.index.load(SeqCst);
                let new_index = index.wrapping_add(1);
                let offset = index.wrapping_sub(tail.start);

                if offset >= NODE_LEN {
                    backoff.step();
                    continue;
                }

                if self.tail.index.compare_and_swap(index, new_index, SeqCst) == index {
                    unsafe {
                        let entry = tail.entries.get_unchecked(offset).get();
                        ptr::write(&mut (*entry).value, ManuallyDrop::new(value));
                        (*entry).ready.store(true, SeqCst);
                    }

                    if offset + 1 == NODE_LEN {
                        let new = Owned::new(Node::new(new_index)).into_ptr(scope);
                        tail.next.store(new, SeqCst);
                        self.tail.node.store(new, SeqCst);
                    }

                    return;
                }
            }
        })
    }

    fn pop(&self) -> Option<T> {
        epoch::pin(|scope| {
            let mut backoff = Backoff::new();
            loop {
                let head = self.head.node.load(SeqCst, scope);
                let h = unsafe { head.deref() };
                let index = self.head.index.load(SeqCst);
                let new_index = index.wrapping_add(1);
                let offset = index.wrapping_sub(h.start);

                if offset >= NODE_LEN {
                    backoff.step();
                    continue;
                }

                let entry = unsafe { &*h.entries.get_unchecked(offset).get() };

                if !entry.ready.load(Relaxed) && self.tail.index.load(SeqCst) == index {
                    return None;
                }

                if self.head.index.compare_and_swap(index, new_index, SeqCst) == index {
                    while !entry.ready.load(SeqCst) {
                        backoff.step();
                    }

                    if offset + 1 == NODE_LEN {
                        loop {
                            let next = h.next.load(SeqCst, scope);
                            if !next.is_null() {
                                self.head.node.store(next, SeqCst);
                                unsafe {
                                    scope.defer_free(head);
                                }
                                break;
                            }
                            backoff.step();
                        }
                    }

                    let v = unsafe { ptr::read(&(*entry).value) };
                    return Some(ManuallyDrop::into_inner(v));
                }
            }
        })
    }

    pub fn len(&self) -> usize {
        loop {
            let tail_index = self.tail.index.load(SeqCst);
            let head_index = self.head.index.load(SeqCst);

            if self.tail.index.load(SeqCst) == tail_index {
                return tail_index.wrapping_sub(head_index);
            }
        }
    }

    pub fn try_send(&self, value: T) -> Result<(), TrySendError<T>> {
        if self.closed.load(SeqCst) {
            Err(TrySendError::Disconnected(value))
        } else {
            self.push(value);
            self.receivers.notify_one();
            Ok(())
        }
    }

    pub fn send(&self, value: T) -> Result<(), SendTimeoutError<T>> {
        if self.closed.load(SeqCst) {
            Err(SendTimeoutError::Disconnected(value))
        } else {
            self.push(value);
            self.receivers.notify_one();
            Ok(())
        }
    }

    pub fn try_recv(&self) -> Result<T, TryRecvError> {
        let closed = self.closed.load(SeqCst);
        match self.pop() {
            None => if closed {
                Err(TryRecvError::Disconnected)
            } else {
                Err(TryRecvError::Empty)
            },
            Some(v) => Ok(v),
        }
    }

    pub fn spin_try_recv(&self) -> Result<T, TryRecvError> {
        for _ in 0..20 {
            let closed = self.closed.load(SeqCst);
            if let Some(v) = self.pop() {
                return Ok(v);
            }
            if closed {
                return Err(TryRecvError::Disconnected);
            }
        }
        Err(TryRecvError::Empty)
    }

    pub fn recv_until(
        &self,
        deadline: Option<Instant>,
        case_id: CaseId,
    ) -> Result<T, RecvTimeoutError> {
        loop {
            match self.spin_try_recv() {
                Ok(v) => return Ok(v),
                Err(TryRecvError::Empty) => {}
                Err(TryRecvError::Disconnected) => return Err(RecvTimeoutError::Disconnected),
            }

            actor::current_reset();
            self.receivers.register(case_id);
            let is_closed = self.is_closed();
            let timed_out = !is_closed && self.is_empty() && !actor::current_wait_until(deadline);
            self.receivers.unregister(case_id);

            if is_closed {
                return Err(RecvTimeoutError::Disconnected);
            } else if timed_out {
                return Err(RecvTimeoutError::Timeout);
            }
        }
    }

    /// Closes the channel.
    pub fn close(&self) -> bool {
        if self.closed.swap(true, SeqCst) {
            false
        } else {
            self.receivers.abort_all();
            true
        }
    }

    /// Returns `true` if the channel is closed.
    pub fn is_closed(&self) -> bool {
        self.closed.load(SeqCst)
    }

    /// Returns `true` if the channel is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn receivers(&self) -> &Monitor {
        &self.receivers
    }
}

impl<T> Drop for Channel<T> {
    fn drop(&mut self) {
        unsafe {
            epoch::unprotected(|scope| {
                let tail_index = self.tail.index.load(Relaxed);
                let mut head_index = self.head.index.load(Relaxed);
                let mut node = self.head.node.load(Relaxed, scope);

                while head_index != tail_index {
                    let n = node.deref();
                    let offset = head_index.wrapping_sub(n.start);
                    let entry = &mut *n.entries.get_unchecked(offset).get();

                    let v = ptr::read(&mut (*entry).value);
                    drop(ManuallyDrop::into_inner(v));

                    if offset + 1 == NODE_LEN {
                        let next = n.next.load(Relaxed, scope);
                        node.destroy();
                        node = next;
                    }

                    head_index = head_index.wrapping_add(1);
                }
            })
        }
    }
}
<|endoftext|>


<commit_before>use schema::tags;
use schema::raw_images;
use schema::images;
use schema::collections;
use schema::images_collections;
use schema::images_tags;
use diesel::pg::data_types::PgDate;

#[derive(Queryable)]
pub struct Tag {
    pub id: i32,
    pub label: String,
}

#[derive(Insertable)]
#[table_name="tags"]
pub struct NewTag<'a> {
    pub label: &'a str,
}

#[derive(Queryable)]
pub struct RawImage {
    pub id: i32,
    pub user_id: i32,
    pub camera: String,
    pub latitude: f64,
    pub longitude: f64,
    pub creation: PgDate,
}

#[derive(Insertable)]
#[table_name="raw_images"]
pub struct NewRawImage<'a> {
    pub user_id: i32,
    pub camera: &'a str,
    pub latitude: f64,
    pub longitude: f64,
    pub creation: PgDate,
}

#[derive(Queryable)]
pub struct Image {
    pub id: i32,
    pub titel: String,
    pub description: String,
    pub license: String,
    pub side_car_file: String,
    pub raw_image_id: i32,
}

#[derive(Insertable)]
#[table_name="images"]
pub struct NewImage<'a> {
    pub title: &'a str,
    pub description: &'a str,
    pub license: &'a str,
    pub side_car_file: &'a str,
    pub raw_image_id: i32,
}

#[derive(Queryable)]
pub struct Collection {
    pub id: i32,
    pub name: String,
    pub description: String,
}

#[derive(Insertable)]
#[table_name="collections"]
pub struct NewCollection<'a> {
    pub name: &'a str,
    pub description: &'a str,
}
<commit_msg>Add n:m table models<commit_after>use schema::{tags, images, raw_images, collections, images_tags, images_collections};
use diesel::pg::data_types::PgDate;

#[derive(Queryable)]
pub struct Tag {
    pub id: i32,
    pub label: String,
}

#[derive(Insertable)]
#[table_name="tags"]
pub struct NewTag<'a> {
    pub label: &'a str,
}

#[derive(Queryable)]
pub struct RawImage {
    pub id: i32,
    pub user_id: i32,
    pub camera: String,
    pub latitude: f64,
    pub longitude: f64,
    pub creation: PgDate,
}

#[derive(Insertable)]
#[table_name="raw_images"]
pub struct NewRawImage<'a> {
    pub user_id: i32,
    pub camera: &'a str,
    pub latitude: f64,
    pub longitude: f64,
    pub creation: PgDate,
}

#[derive(Queryable)]
pub struct Image {
    pub id: i32,
    pub titel: String,
    pub description: String,
    pub license: String,
    pub side_car_file: String,
    pub raw_image_id: i32,
}

#[derive(Insertable)]
#[table_name="images"]
pub struct NewImage<'a> {
    pub title: &'a str,
    pub description: &'a str,
    pub license: &'a str,
    pub side_car_file: &'a str,
    pub raw_image_id: i32,
}

#[derive(Queryable)]
pub struct Collection {
    pub id: i32,
    pub name: String,
    pub description: String,
}

#[derive(Insertable)]
#[table_name="collections"]
pub struct NewCollection<'a> {
    pub name: &'a str,
    pub description: &'a str,
}

#[derive(Queryable)]
pub struct ImageTag {
    pub image_id: i32,
    pub tag_id: i32,
}

#[derive(Insertable)]
#[table_name="images_tags"]
pub struct NewImageTag {
    pub image_id: i32,
    pub tag_id: i32,
}

#[derive(Queryable)]
pub struct ImageCollection {
    pub image_id: i32,
    pub collection_id: i32,
}

#[derive(Insertable)]
#[table_name="images_collections"]
pub struct NewImageCollection {
    pub image_id: i32,
    pub collection_id: i32,
}
<|endoftext|>


<commit_before>use super::{LzfResult,LzfError};
use std::ptr;
use std::mem;

pub fn decompress(data: &[u8], out_len_should: usize) -> LzfResult<Vec<u8>> {
    let mut current_offset = 0;

    // We have sanity checks to not exceed this capacity.
    let mut output = Vec::with_capacity(out_len_should);
    unsafe { output.set_len(out_len_should) };
    let mut out_len : usize = 0;

    let in_len = data.len();

    while current_offset < in_len {
        let mut ctrl = unsafe{*data.get_unchecked(current_offset)} as usize;
        current_offset += 1;

        if ctrl < (1<<5) {
            ctrl += 1;

            if out_len + ctrl > out_len_should {
                return Err(LzfError::BufferTooSmall);
            }

            if current_offset+ctrl > in_len {
                return Err(LzfError::DataCorrupted);
            }

            // We can simply memcpy everything from the input to the output
            unsafe {
                let (src, _) : (*const u8, usize) = mem::transmute(&data[..]);
                let src = src.offset(current_offset as isize);
                let (dst, _) : (*mut u8, usize) = mem::transmute(&output[..]);
                let dst = dst.offset((out_len) as isize);
                ptr::copy_nonoverlapping(src, dst, ctrl);

                current_offset += ctrl;
                out_len += ctrl;
            }
        } else {
            let mut len = ctrl >> 5;

            let mut ref_offset = (((ctrl & 0x1f) << 8) + 1) as i32;

            if len == 7 {
                len += unsafe{*data.get_unchecked(current_offset)} as usize;
                current_offset += 1;

                if current_offset >= in_len {
                    return Err(LzfError::DataCorrupted);
                }
            }

            ref_offset += unsafe{*data.get_unchecked(current_offset)} as i32;
            current_offset += 1;

            if current_offset + len + 2 > out_len_should {
                return Err(LzfError::BufferTooSmall);
            }

            let mut ref_pos = (out_len as i32) - ref_offset;
            if ref_pos < 0 {
                return Err(LzfError::DataCorrupted);
            }

            let c = unsafe{*output.get_unchecked(ref_pos as usize)};
            output[out_len] = c;
            out_len += 1;
            ref_pos += 1;

            let c = unsafe{*output.get_unchecked(ref_pos as usize)};
            output[out_len] = c;
            out_len += 1;
            ref_pos += 1;

            // We can safely use copy_nonoverlapping here,
            // as we know that we only copy data from before our current insertion point.
            unsafe {
                let (src, _) : (*const u8, usize) = mem::transmute(&output[..]);
                let src = src.offset(ref_pos as isize);
                let (dst, _) : (*mut u8, usize) = mem::transmute(&output[..]);
                let dst = dst.offset((out_len) as isize);

                ptr::copy_nonoverlapping(src, dst, len);
                out_len += len;
            }
        }
    }

    // Set the real length now, user might have passed a bigger buffer in the first place.
    unsafe { output.set_len(out_len) };

    Ok(output)
}

#[test]
fn test_decompress_lorem() {
    use super::compress;

    let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod \
                 tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At \
                 vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, \
                 no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit \
                 amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut \
                 labore et dolore magna aliquyam erat, sed diam voluptua.";

    let compressed = compress(lorem.as_bytes()).unwrap();

    let decompressed = decompress(&compressed[..], lorem.len()).unwrap();
    assert_eq!(lorem.as_bytes(), &decompressed[..]);

    let decompressed = decompress(&compressed[..], 1000).unwrap();
    assert_eq!(lorem.len(), decompressed.len());
}

#[test]
fn test_decompress_fails_with_short_buffer() {
    use super::compress;

    let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.";

    let compressed = match compress(lorem.as_bytes()) {
        Ok(c) => c,
        Err(err) => panic!("Compression failed with error {:?}", err)
    };

    match decompress(&compressed, 10) {
        Ok(_) => panic!("Decompression worked. That should not happen"),
        Err(err) => assert_eq!(LzfError::BufferTooSmall, err)
    }
}

#[test]
fn test_decompress_fails_for_corrupted_data() {
    let lorem = "Lorem ipsum dolor sit amet";

    match decompress(lorem.as_bytes(), lorem.len()) {
        Ok(_) => panic!("Decompression worked. That should not happen"),
        Err(err) => assert_eq!(LzfError::DataCorrupted, err)
    }
}
<commit_msg>Don't blindly copy the buffer<commit_after>use super::{LzfResult,LzfError};
use std::ptr;
use std::mem;

pub fn decompress(data: &[u8], out_len_should: usize) -> LzfResult<Vec<u8>> {
    let mut current_offset = 0;

    // We have sanity checks to not exceed this capacity.
    let mut output = Vec::with_capacity(out_len_should);
    unsafe { output.set_len(out_len_should) };
    let mut out_len : usize = 0;

    let in_len = data.len();

    while current_offset < in_len {
        let mut ctrl = unsafe{*data.get_unchecked(current_offset)} as usize;
        current_offset += 1;

        if ctrl < (1<<5) {
            ctrl += 1;

            if out_len + ctrl > out_len_should {
                return Err(LzfError::BufferTooSmall);
            }

            if current_offset+ctrl > in_len {
                return Err(LzfError::DataCorrupted);
            }

            // We can simply memcpy everything from the input to the output
            unsafe {
                let (src, _) : (*const u8, usize) = mem::transmute(&data[..]);
                let src = src.offset(current_offset as isize);
                let (dst, _) : (*mut u8, usize) = mem::transmute(&output[..]);
                let dst = dst.offset((out_len) as isize);
                ptr::copy_nonoverlapping(src, dst, ctrl);

                current_offset += ctrl;
                out_len += ctrl;
            }
        } else {
            let mut len = ctrl >> 5;

            let mut ref_offset = (((ctrl & 0x1f) << 8) + 1) as i32;

            if len == 7 {
                len += unsafe{*data.get_unchecked(current_offset)} as usize;
                current_offset += 1;

                if current_offset >= in_len {
                    return Err(LzfError::DataCorrupted);
                }
            }

            ref_offset += unsafe{*data.get_unchecked(current_offset)} as i32;
            current_offset += 1;

            if current_offset + len + 2 > out_len_should {
                return Err(LzfError::BufferTooSmall);
            }

            let mut ref_pos = (out_len as i32) - ref_offset;
            if ref_pos < 0 {
                return Err(LzfError::DataCorrupted);
            }

            let c = unsafe{*output.get_unchecked(ref_pos as usize)};
            output[out_len] = c;
            out_len += 1;
            ref_pos += 1;

            let c = unsafe{*output.get_unchecked(ref_pos as usize)};
            output[out_len] = c;
            out_len += 1;
            ref_pos += 1;

            while len > 0 {
                let c = unsafe{*output.get_unchecked(ref_pos as usize)};
                output[out_len] = c;
                out_len += 1;
                ref_pos += 1;
                len -= 1;
            }
        }
    }

    // Set the real length now, user might have passed a bigger buffer in the first place.
    unsafe { output.set_len(out_len) };

    Ok(output)
}

#[test]
fn test_decompress_lorem() {
    use super::compress;

    let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod \
                 tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At \
                 vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, \
                 no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit \
                 amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut \
                 labore et dolore magna aliquyam erat, sed diam voluptua.";

    let compressed = compress(lorem.as_bytes()).unwrap();

    let decompressed = decompress(&compressed[..], lorem.len()).unwrap();
    assert_eq!(lorem.as_bytes(), &decompressed[..]);

    let decompressed = decompress(&compressed[..], 1000).unwrap();
    assert_eq!(lorem.len(), decompressed.len());
}

#[test]
fn test_decompress_fails_with_short_buffer() {
    use super::compress;

    let lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.";

    let compressed = match compress(lorem.as_bytes()) {
        Ok(c) => c,
        Err(err) => panic!("Compression failed with error {:?}", err)
    };

    match decompress(&compressed, 10) {
        Ok(_) => panic!("Decompression worked. That should not happen"),
        Err(err) => assert_eq!(LzfError::BufferTooSmall, err)
    }
}

#[test]
fn test_decompress_fails_for_corrupted_data() {
    let lorem = "Lorem ipsum dolor sit amet";

    match decompress(lorem.as_bytes(), lorem.len()) {
        Ok(_) => panic!("Decompression worked. That should not happen"),
        Err(err) => assert_eq!(LzfError::DataCorrupted, err)
    }
}

#[test]
fn test_alice_wonderland() {
    let alice = "\r\n\r\n\r\n\r\n                ALICE'S ADVENTURES IN WONDERLAND\r\n";

    let compressed = match compress(alice.as_bytes()) {
        Ok(c) => c,
        Err(err) => panic!("Compression failed with error {:?}", err)
    };

    match decompress(&compressed, alice.len()) {
        Ok(decompressed) => {
            assert_eq!(alice.len(), decompressed.len());
            assert_eq!(alice.as_bytes(), &decompressed[..]);
        },
        Err(err) => panic!("Decompression failed with error {:?}", err)
    }
}
<|endoftext|>


<commit_before>/// Implement ncurses-compatible database discovery

use core::os::getenv;
use core::str;
use core::io::{file_reader, Reader};
use path = core::path::PosixPath;

/// Return path to database entry for `term`
pub fn get_dbpath_for_term(term: &str) -> Option<~path> {
    if term.len() == 0 {
        return None;
    }

    let mut dirs_to_search = ~[];
    let first_char = term.substr(0, 1);

    // Find search directory
    match getenv(~"TERMINFO") {
        Some(dir) => dirs_to_search.push(path(dir)),
        None => {
            match getenv(~"TERMINFO_DIRS") {
                Some(dirs) => for str::each_split_char(dirs, ':') |i| {
                    if i == ~"" {
                        dirs_to_search.push(path(~"/usr/share/terminfo"));
                    } else {
                        dirs_to_search.push(path(i.to_owned()));
                    }
                },
                // Found nothing, use the default path
                None => dirs_to_search.push(path(~"/usr/share/terminfo"))
            }
        }
    };

    // Look for the terminal in all of the search directories
    for dirs_to_search.each |p| {
        let newp = ~p.push_many(&[first_char.to_owned(), term.to_owned()]);
        if os::path_exists(p) && os::path_exists(newp) {
            return Some(newp);
        }
    }
    None
}

/// Return open file for `term`
fn open(term: &str) -> Result<@Reader, ~str> {
    match get_dbpath_for_term(term) {
        Some(x) => file_reader(x),
        None => Err(fmt!("could not find terminfo entry for %s", term))
    }
}

#[test]
fn test_get_dbpath_for_term() {
    // woefully inadequate test coverage
    use core::os::{setenv, unsetenv};
    fn x(t: &str) -> ~str { get_dbpath_for_term(t).expect("no terminfo entry found").to_str() };
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    assert!(get_dbpath_for_term("") == None);
    setenv("TERMINFO_DIRS", ":");
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    unsetenv("TERMINFO_DIRS");
}

#[test]
fn test_open() {
    open("screen");
    let t = open("nonexistent terminal that hopefully does not exist");
    assert!(t.is_err());
}
<commit_msg>search homedir for terminfo as ncurses expects<commit_after>/// Implement ncurses-compatible database discovery

use core::os;
use core::os::getenv;
use core::str;
use core::io::{file_reader, Reader};
use path = core::path::PosixPath;

/// Return path to database entry for `term`
pub fn get_dbpath_for_term(term: &str) -> Option<~path> {
    if term.len() == 0 {
        return None;
    }

    let homedir = os::homedir();

    let mut dirs_to_search = ~[];
    let first_char = term.substr(0, 1);

    // Find search directory
    match getenv(~"TERMINFO") {
        Some(dir) => dirs_to_search.push(path(dir)),
        None => {
            if homedir.is_some() {
                dirs_to_search.push(homedir.unwrap().push(".terminfo")); // ncurses compatability
            }
            match getenv(~"TERMINFO_DIRS") {
                Some(dirs) => for str::each_split_char(dirs, ':') |i| {
                    if i == ~"" {
                        dirs_to_search.push(path(~"/usr/share/terminfo"));
                    } else {
                        dirs_to_search.push(path(i.to_owned()));
                    }
                },
                // Found nothing, use the default path
                None => dirs_to_search.push(path(~"/usr/share/terminfo"))
            }
        }
    };

    // Look for the terminal in all of the search directories
    for dirs_to_search.each |p| {
        let newp = ~p.push_many(&[first_char.to_owned(), term.to_owned()]);
        if os::path_exists(p) && os::path_exists(newp) {
            return Some(newp);
        }
    }
    None
}

/// Return open file for `term`
fn open(term: &str) -> Result<@Reader, ~str> {
    match get_dbpath_for_term(term) {
        Some(x) => file_reader(x),
        None => Err(fmt!("could not find terminfo entry for %s", term))
    }
}

#[test]
fn test_get_dbpath_for_term() {
    // woefully inadequate test coverage
    use core::os::{setenv, unsetenv};
    fn x(t: &str) -> ~str { get_dbpath_for_term(t).expect("no terminfo entry found").to_str() };
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    assert!(get_dbpath_for_term("") == None);
    setenv("TERMINFO_DIRS", ":");
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    unsetenv("TERMINFO_DIRS");
}

#[test]
fn test_open() {
    open("screen");
    let t = open("nonexistent terminal that hopefully does not exist");
    assert!(t.is_err());
}
<|endoftext|>