<commit_before>/*
   Copyright (c) 2016 Saurav Sachidanand

   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.
*/

mod ffi;
mod error;

use ffi::*;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use error::NFDError;

/// Result of opening a file dialog
pub enum Response {
    /// User pressed okay. `String` is the file path selected
    Okay(String),
    /// User pressed okay on mupliple selections. Result contains a Vec of all the files
    OkayMultiple(Vec<String>),
    /// User pressed cancel
    Cancel,
}

#[derive(Copy, Clone, PartialEq)]
pub enum DialogType {
    SingleFile,
    MultipleFiles,
    SaveFile,
}

pub struct DialogBuilder<'a> {
    filter: Option<&'a str>,
    default_path: Option<&'a str>,
    dialog_type: DialogType,
}

impl<'a> DialogBuilder<'a> {

    pub fn new(dialog_type: DialogType) -> Self {
        DialogBuilder {
            filter: None,
            default_path: None,
            dialog_type: dialog_type,
        }
    }

    pub fn filter(&'a mut self, filter: &'a str) -> &mut DialogBuilder {
        self.filter = Some(filter);
        self
    }

    pub fn default_path(&'a mut self, path: &'a str) -> &mut DialogBuilder {
        self.default_path = Some(path);
        self
    }

    pub fn dialog_type(&'a mut self, dialog_type: DialogType) -> &mut DialogBuilder {
        self.dialog_type = dialog_type;
        self
    }

    pub fn open(&self) -> Result<Response> {
        open_dialog(self.filter, self.default_path, self.dialog_type.clone())
    }
}

pub fn dialog<'a>() -> DialogBuilder<'a> {
    DialogBuilder::new(DialogType::SingleFile)
}

pub fn dialog_multiple<'a>() -> DialogBuilder<'a> {
    DialogBuilder::new(DialogType::MultipleFiles)
}

pub fn dialog_save<'a>() -> DialogBuilder<'a> {
    DialogBuilder::new(DialogType::SaveFile)
}

pub type Result<T> = std::result::Result<T, NFDError>;

/// Open single file dialog
pub fn open_file_dialog(filter_list: Option<&str>, default_path: Option<&str>) -> Result<Response> {
    open_dialog(filter_list, default_path, DialogType::SingleFile)
}

/// Open mulitple file dialog
pub fn open_file_multiple_dialog(filter_list: Option<&str>, default_path: Option<&str>) -> Result<Response> {
    open_dialog(filter_list, default_path, DialogType::MultipleFiles)
}

/// Open save dialog
pub fn open_save_dialog(filter_list: Option<&str>, default_path: Option<&str>) -> Result<Response> {
    open_dialog(filter_list, default_path, DialogType::SaveFile)
}

pub fn open_dialog(filter_list: Option<&str>, default_path: Option<&str>, dialog_type: DialogType) -> Result<Response> {
    let result;
    let filter_list_cstring;
    let default_path_cstring;

    let filter_list_ptr = match filter_list {
        Some(fl_str) => {
            filter_list_cstring = try!(CString::new(fl_str));
            filter_list_cstring.as_ptr()
        }
        None => std::ptr::null()
    };

    let default_path_ptr = match default_path {
        Some(dp_str) => {
            default_path_cstring = try!(CString::new(dp_str));
            default_path_cstring.as_ptr()
        }
        None => std::ptr::null()
    };

    let mut out_path: *mut c_char = std::ptr::null_mut();
    let ptr_out_path = &mut out_path as *mut *mut c_char;

    let mut out_multiple = nfdpathset_t::default();
    let ptr_out_multyple = &mut out_multiple as *mut nfdpathset_t;

    unsafe {
        result = match dialog_type {
            DialogType::SingleFile => {
                NFD_OpenDialog(filter_list_ptr, default_path_ptr, ptr_out_path)
            },

            DialogType::MultipleFiles => {
                NFD_OpenDialogMultiple(filter_list_ptr, default_path_ptr, ptr_out_multyple)
            },

            DialogType::SaveFile => {
                NFD_SaveDialog(filter_list_ptr, default_path_ptr, ptr_out_path)
            },
        };

        match result {
            nfdresult_t::NFD_OKAY =>{
                if dialog_type == DialogType::SingleFile {
                    Ok(Response::Okay(CStr::from_ptr(out_path).to_string_lossy().into_owned()))
                } else {
                    let count = NFD_PathSet_GetCount(&out_multiple);
                    let mut res = Vec::with_capacity(count);
                    for i in 0..count {
                        let path = CStr::from_ptr(NFD_PathSet_GetPath(&out_multiple, i)).to_string_lossy().into_owned();
                        res.push(path)

                    }

                    NFD_PathSet_Free(ptr_out_multyple);

                    Ok(Response::OkayMultiple(res))
                }
            },

            nfdresult_t::NFD_CANCEL => Ok(Response::Cancel),
            nfdresult_t::NFD_ERROR => Err(NFDError::Error(CStr::from_ptr(NFD_GetError()).to_string_lossy().into_owned())),
        }
    }
}
<commit_msg>Remove dialog_type method of builder<commit_after>/*
   Copyright (c) 2016 Saurav Sachidanand

   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.
*/

mod ffi;
mod error;

use ffi::*;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use error::NFDError;

/// Result of opening a file dialog
pub enum Response {
    /// User pressed okay. `String` is the file path selected
    Okay(String),
    /// User pressed okay on mupliple selections. Result contains a Vec of all the files
    OkayMultiple(Vec<String>),
    /// User pressed cancel
    Cancel,
}

#[derive(Copy, Clone, PartialEq)]
pub enum DialogType {
    SingleFile,
    MultipleFiles,
    SaveFile,
}

pub struct DialogBuilder<'a> {
    filter: Option<&'a str>,
    default_path: Option<&'a str>,
    dialog_type: DialogType,
}

impl<'a> DialogBuilder<'a> {

    pub fn new(dialog_type: DialogType) -> Self {
        DialogBuilder {
            filter: None,
            default_path: None,
            dialog_type: dialog_type,
        }
    }

    pub fn filter(&'a mut self, filter: &'a str) -> &mut DialogBuilder {
        self.filter = Some(filter);
        self
    }

    pub fn default_path(&'a mut self, path: &'a str) -> &mut DialogBuilder {
        self.default_path = Some(path);
        self
    }

    pub fn open(&self) -> Result<Response> {
        open_dialog(self.filter, self.default_path, self.dialog_type.clone())
    }
}

pub fn dialog<'a>() -> DialogBuilder<'a> {
    DialogBuilder::new(DialogType::SingleFile)
}

pub fn dialog_multiple<'a>() -> DialogBuilder<'a> {
    DialogBuilder::new(DialogType::MultipleFiles)
}

pub fn dialog_save<'a>() -> DialogBuilder<'a> {
    DialogBuilder::new(DialogType::SaveFile)
}

pub type Result<T> = std::result::Result<T, NFDError>;

/// Open single file dialog
pub fn open_file_dialog(filter_list: Option<&str>, default_path: Option<&str>) -> Result<Response> {
    open_dialog(filter_list, default_path, DialogType::SingleFile)
}

/// Open mulitple file dialog
pub fn open_file_multiple_dialog(filter_list: Option<&str>, default_path: Option<&str>) -> Result<Response> {
    open_dialog(filter_list, default_path, DialogType::MultipleFiles)
}

/// Open save dialog
pub fn open_save_dialog(filter_list: Option<&str>, default_path: Option<&str>) -> Result<Response> {
    open_dialog(filter_list, default_path, DialogType::SaveFile)
}

pub fn open_dialog(filter_list: Option<&str>, default_path: Option<&str>, dialog_type: DialogType) -> Result<Response> {
    let result;
    let filter_list_cstring;
    let default_path_cstring;

    let filter_list_ptr = match filter_list {
        Some(fl_str) => {
            filter_list_cstring = try!(CString::new(fl_str));
            filter_list_cstring.as_ptr()
        }
        None => std::ptr::null()
    };

    let default_path_ptr = match default_path {
        Some(dp_str) => {
            default_path_cstring = try!(CString::new(dp_str));
            default_path_cstring.as_ptr()
        }
        None => std::ptr::null()
    };

    let mut out_path: *mut c_char = std::ptr::null_mut();
    let ptr_out_path = &mut out_path as *mut *mut c_char;

    let mut out_multiple = nfdpathset_t::default();
    let ptr_out_multyple = &mut out_multiple as *mut nfdpathset_t;

    unsafe {
        result = match dialog_type {
            DialogType::SingleFile => {
                NFD_OpenDialog(filter_list_ptr, default_path_ptr, ptr_out_path)
            },

            DialogType::MultipleFiles => {
                NFD_OpenDialogMultiple(filter_list_ptr, default_path_ptr, ptr_out_multyple)
            },

            DialogType::SaveFile => {
                NFD_SaveDialog(filter_list_ptr, default_path_ptr, ptr_out_path)
            },
        };

        match result {
            nfdresult_t::NFD_OKAY =>{
                if dialog_type == DialogType::SingleFile {
                    Ok(Response::Okay(CStr::from_ptr(out_path).to_string_lossy().into_owned()))
                } else {
                    let count = NFD_PathSet_GetCount(&out_multiple);
                    let mut res = Vec::with_capacity(count);
                    for i in 0..count {
                        let path = CStr::from_ptr(NFD_PathSet_GetPath(&out_multiple, i)).to_string_lossy().into_owned();
                        res.push(path)

                    }

                    NFD_PathSet_Free(ptr_out_multyple);

                    Ok(Response::OkayMultiple(res))
                }
            },

            nfdresult_t::NFD_CANCEL => Ok(Response::Cancel),
            nfdresult_t::NFD_ERROR => Err(NFDError::Error(CStr::from_ptr(NFD_GetError()).to_string_lossy().into_owned())),
        }
    }
}
<|endoftext|>


<commit_before>// Rx -- Reactive programming for Rust
// Copyright 2016 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

#![feature(fn_traits, unboxed_closures)]

use observer::{NextObserver, CompletedObserver, ErrorObserver};
use std::fmt::Debug;
use std::iter::IntoIterator;

mod observer;

pub use observer::{Observer, PanickingObserver};

trait Observable {
    type Item;
    type Error;
    type Subscription: Drop;

    fn subscribe<O>(&mut self, observer: O) -> Self::Subscription
        where O: Observer<Self::Item, Self::Error>;

    fn subscribe_next<FnNext>(&mut self,
                              on_next: FnNext)
                              -> Self::Subscription
        where Self::Error: Debug,
              FnNext: FnMut(Self::Item) {
        let observer = NextObserver {
            fn_next: on_next,
        };
        self.subscribe(observer)
    }

    fn subscribe_completed<FnNext, FnCompleted>(&mut self,
                                                on_next: FnNext,
                                                on_completed: FnCompleted)
                                                -> Self::Subscription
        where Self::Error: Debug,
              FnNext: FnMut(Self::Item),
              FnCompleted: FnOnce() {
        let observer = CompletedObserver {
            fn_next: on_next,
            fn_completed: on_completed,
        };
        self.subscribe(observer)
    }

    fn subscribe_error<FnNext, FnCompleted, FnError>(&mut self,
                                                     on_next: FnNext,
                                                     on_completed: FnCompleted,
                                                     on_error: FnError)
                                                     -> Self::Subscription
        where FnNext: FnMut(Self::Item),
              FnCompleted: FnOnce(),
              FnError: FnOnce(Self::Error) {
        let observer = ErrorObserver {
            fn_next: on_next,
            fn_completed: on_completed,
            fn_error: on_error,
        };
        self.subscribe(observer)
    }
}

struct UncancellableSubscription;

impl Drop for UncancellableSubscription {
    fn drop(&mut self) { }
}

impl<'i, I> Observable for &'i I where &'i I: IntoIterator {
    type Item = <&'i I as IntoIterator>::Item;
    type Error = ();
    type Subscription = UncancellableSubscription;

    fn subscribe<O>(&mut self, mut observer: O) -> UncancellableSubscription
        where O: Observer<Self::Item, Self::Error> {
        for x in self.into_iter() {
            observer.on_next(x);
        }
        observer.on_completed();
        UncancellableSubscription
    }
}

#[test]
fn subscribe_to_slice() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    values.subscribe(|x| println!("{:?}", x));
}

#[test]
fn subscribe_next_slice() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let mut received = Vec::new();
    values.subscribe_next(|&x| received.push(x));
    assert_eq!(&values[..], &received[..]);
}
<commit_msg>Add more tests<commit_after>// Rx -- Reactive programming for Rust
// Copyright 2016 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

#![feature(fn_traits, unboxed_closures)]

use observer::{NextObserver, CompletedObserver, ErrorObserver};
use std::fmt::Debug;
use std::iter::IntoIterator;

mod observer;

pub use observer::{Observer, PanickingObserver};

trait Observable {
    type Item;
    type Error;
    type Subscription: Drop;

    fn subscribe<O>(&mut self, observer: O) -> Self::Subscription
        where O: Observer<Self::Item, Self::Error>;

    fn subscribe_next<FnNext>(&mut self,
                              on_next: FnNext)
                              -> Self::Subscription
        where Self::Error: Debug,
              FnNext: FnMut(Self::Item) {
        let observer = NextObserver {
            fn_next: on_next,
        };
        self.subscribe(observer)
    }

    fn subscribe_completed<FnNext, FnCompleted>(&mut self,
                                                on_next: FnNext,
                                                on_completed: FnCompleted)
                                                -> Self::Subscription
        where Self::Error: Debug,
              FnNext: FnMut(Self::Item),
              FnCompleted: FnOnce() {
        let observer = CompletedObserver {
            fn_next: on_next,
            fn_completed: on_completed,
        };
        self.subscribe(observer)
    }

    fn subscribe_error<FnNext, FnCompleted, FnError>(&mut self,
                                                     on_next: FnNext,
                                                     on_completed: FnCompleted,
                                                     on_error: FnError)
                                                     -> Self::Subscription
        where FnNext: FnMut(Self::Item),
              FnCompleted: FnOnce(),
              FnError: FnOnce(Self::Error) {
        let observer = ErrorObserver {
            fn_next: on_next,
            fn_completed: on_completed,
            fn_error: on_error,
        };
        self.subscribe(observer)
    }
}

struct UncancellableSubscription;

impl Drop for UncancellableSubscription {
    fn drop(&mut self) { }
}

impl<'i, I> Observable for &'i I where &'i I: IntoIterator {
    type Item = <&'i I as IntoIterator>::Item;
    type Error = ();
    type Subscription = UncancellableSubscription;

    fn subscribe<O>(&mut self, mut observer: O) -> UncancellableSubscription
        where O: Observer<Self::Item, Self::Error> {
        for x in self.into_iter() {
            observer.on_next(x);
        }
        observer.on_completed();
        UncancellableSubscription
    }
}

#[test]
fn subscribe_to_slice() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    values.subscribe(|x| println!("{:?}", x));
}

#[test]
fn subscribe_next_slice() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let mut received = Vec::new();
    values.subscribe_next(|&x| received.push(x));
    assert_eq!(&values[..], &received[..]);
}

#[test]
fn subscribe_completed_slice() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let mut received = Vec::new();
    let mut completed = false;
    values.subscribe_completed(|&x| received.push(x), || completed = true);
    assert_eq!(&values[..], &received[..]);
    assert!(completed);
}

#[test]
fn subscribe_error_slice() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let mut received = Vec::new();
    let mut completed = false;
    let mut failed = false;
    values.subscribe_error(|&x| received.push(x), || completed = true, |err| failed = true);
    assert_eq!(&values[..], &received[..]);
    assert!(completed);
    assert!(!failed);
}
<|endoftext|>


<commit_before>
pub fn puzzle(input: &str) -> u32 {
    let mut total = 0;
    for line in input.lines() {
        if supports_tls(line) {
            total += 1;
        }
    }
    total
}

pub fn supports_tls(candidate: &str) -> bool {
    println!("considering {}", candidate);
    let mut start_index = 0;
    let end_index = candidate.len();

    let mut abba_outside = false;

    for (i, c) in candidate.match_indices(|c| c == '[' || c == ']') {
        println!("looking at slice ending in {}, [{}..{}]", c, start_index, i);
        println!("slice is {}", &candidate[start_index..i]);
        println!("abba_outside = {}", abba_outside);
        if c == "[" {
            abba_outside = abba_outside || contains_abba(&candidate[start_index..i]);
            println!("after looking, abba_outside = {}", abba_outside);
        } else {
            if contains_abba(&candidate[start_index..i]) {
                println!("womp womp, found an abba inside");
                return false;
            }
        }
        start_index = i + 1;
        println!("start_index = {}", start_index);
    }
    println!("looking at final slice [{}..{}]: '{}", start_index, end_index, &candidate[start_index..end_index]);

    abba_outside = abba_outside || contains_abba(&candidate[start_index..end_index]);

    println!("final answer: {}", abba_outside);

    abba_outside
}

pub fn contains_abba(candidate: &str) -> bool {
    let by_chars: Vec<char> = candidate.chars().collect();

    for (i, &c) in by_chars.iter().enumerate() {
        if i + 3 < by_chars.len() &&
            c != by_chars[i + 1] &&
            by_chars[i + 1] == by_chars[i + 2] &&
            by_chars[i + 3] == c {
            return true
        }
    }
    false
}

pub fn supports_ssl(candidate: &str) -> bool {
    let mut start_index = 0;
    let end_index = candidate.len();

    let mut potential_abas: Vec<&str> = vec![];
    let mut potential_babs = vec![];

    for (i, c) in candidate.match_indices(|c| c == '[' || c == ']') {
        let mut f = find_abas(&candidate[start_index..i]);
        if c == "[" {
            potential_abas.append(&mut f);
        } else {
            potential_babs.append(&mut f);
        }
        start_index = i + 1;
    }
    let mut f = find_abas(&candidate[start_index..end_index]);
    potential_abas.append(&mut f);

    for aba in potential_abas {
        let mut by_chars = aba.chars();
        let first = by_chars.next().expect("no first char");
        let second = by_chars.next().expect("no second char");
        let bab = format!("{}{}{}", second, first, second);
        if potential_babs.contains(&&bab[..]) {
            return true;
        }
    }
    false
}

fn find_abas(s: &str) -> Vec<&str> {
   let mut abas: Vec<&str> = vec![];

   let by_chars: Vec<char> = s.chars().collect();

   for (i, &c) in by_chars.iter().enumerate() {
       if i + 2 < by_chars.len() &&
           c != by_chars[i + 1] &&
           by_chars[i + 2] == c {
           abas.push(&s[i..i+3]);
       }
   }

   abas
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn does_support_ssl() {
        assert!(supports_ssl("aba[bab]xyz"));
        assert!(supports_ssl("aaa[kek]eke"));
        assert!(supports_ssl("zazbz[bzb]cdb"));
        assert!(supports_ssl("zazaaabz[bzb]cdb[foo]zbz"));
    }

    #[test]
    fn does_not_support_ssl() {
        assert!( ! supports_ssl("xyx[xyx]xyx") );
    }

    #[test]
    fn does_support_tls() {
        assert!(supports_tls("abba[mnop]qrst"));
        assert!(supports_tls("ioxxoj[asdfgh]zxcvbn"));
        assert!(supports_tls("abcd[efgh]ijk[lmn]oppo"))
    }

    #[test]
    fn does_not_support_tls() {
        assert!( ! supports_tls("abcd[bddb]xyyx") );
        assert!( ! supports_tls("aaaa[qwer]tyui") );
        assert!( ! supports_tls("aaaa[qwer]tyui[foof]poop") );
    }

    #[test]
    fn does_contain_abba() {
        assert!(contains_abba("abba"));
        assert!(contains_abba("ioxxoj"));
    }

    #[test]
    fn does_not_contain_abba() {
        assert!( ! contains_abba("mnop") );
        assert!( ! contains_abba("aaaa") );
    }
}
<commit_msg>Ahaha i almost forgot to change the puzzle method<commit_after>
pub fn puzzle(input: &str) -> u32 {
    let mut total = 0;
    for line in input.lines() {
        if supports_ssl(line) {
            total += 1;
        }
    }
    total
}

pub fn supports_tls(candidate: &str) -> bool {
    println!("considering {}", candidate);
    let mut start_index = 0;
    let end_index = candidate.len();

    let mut abba_outside = false;

    for (i, c) in candidate.match_indices(|c| c == '[' || c == ']') {
        println!("looking at slice ending in {}, [{}..{}]", c, start_index, i);
        println!("slice is {}", &candidate[start_index..i]);
        println!("abba_outside = {}", abba_outside);
        if c == "[" {
            abba_outside = abba_outside || contains_abba(&candidate[start_index..i]);
            println!("after looking, abba_outside = {}", abba_outside);
        } else {
            if contains_abba(&candidate[start_index..i]) {
                println!("womp womp, found an abba inside");
                return false;
            }
        }
        start_index = i + 1;
        println!("start_index = {}", start_index);
    }
    println!("looking at final slice [{}..{}]: '{}", start_index, end_index, &candidate[start_index..end_index]);

    abba_outside = abba_outside || contains_abba(&candidate[start_index..end_index]);

    println!("final answer: {}", abba_outside);

    abba_outside
}

pub fn contains_abba(candidate: &str) -> bool {
    let by_chars: Vec<char> = candidate.chars().collect();

    for (i, &c) in by_chars.iter().enumerate() {
        if i + 3 < by_chars.len() &&
            c != by_chars[i + 1] &&
            by_chars[i + 1] == by_chars[i + 2] &&
            by_chars[i + 3] == c {
            return true
        }
    }
    false
}

pub fn supports_ssl(candidate: &str) -> bool {
    let mut start_index = 0;
    let end_index = candidate.len();

    let mut potential_abas: Vec<&str> = vec![];
    let mut potential_babs = vec![];

    for (i, c) in candidate.match_indices(|c| c == '[' || c == ']') {
        let mut f = find_abas(&candidate[start_index..i]);
        if c == "[" {
            potential_abas.append(&mut f);
        } else {
            potential_babs.append(&mut f);
        }
        start_index = i + 1;
    }
    let mut f = find_abas(&candidate[start_index..end_index]);
    potential_abas.append(&mut f);

    for aba in potential_abas {
        let mut by_chars = aba.chars();
        let first = by_chars.next().expect("no first char");
        let second = by_chars.next().expect("no second char");
        let bab = format!("{}{}{}", second, first, second);
        if potential_babs.contains(&&bab[..]) {
            return true;
        }
    }
    false
}

fn find_abas(s: &str) -> Vec<&str> {
   let mut abas: Vec<&str> = vec![];

   let by_chars: Vec<char> = s.chars().collect();

   for (i, &c) in by_chars.iter().enumerate() {
       if i + 2 < by_chars.len() &&
           c != by_chars[i + 1] &&
           by_chars[i + 2] == c {
           abas.push(&s[i..i+3]);
       }
   }

   abas
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn does_support_ssl() {
        assert!(supports_ssl("aba[bab]xyz"));
        assert!(supports_ssl("aaa[kek]eke"));
        assert!(supports_ssl("zazbz[bzb]cdb"));
        assert!(supports_ssl("zazaaabz[bzb]cdb[foo]zbz"));
    }

    #[test]
    fn does_not_support_ssl() {
        assert!( ! supports_ssl("xyx[xyx]xyx") );
    }

    #[test]
    fn does_support_tls() {
        assert!(supports_tls("abba[mnop]qrst"));
        assert!(supports_tls("ioxxoj[asdfgh]zxcvbn"));
        assert!(supports_tls("abcd[efgh]ijk[lmn]oppo"))
    }

    #[test]
    fn does_not_support_tls() {
        assert!( ! supports_tls("abcd[bddb]xyyx") );
        assert!( ! supports_tls("aaaa[qwer]tyui") );
        assert!( ! supports_tls("aaaa[qwer]tyui[foof]poop") );
    }

    #[test]
    fn does_contain_abba() {
        assert!(contains_abba("abba"));
        assert!(contains_abba("ioxxoj"));
    }

    #[test]
    fn does_not_contain_abba() {
        assert!( ! contains_abba("mnop") );
        assert!( ! contains_abba("aaaa") );
    }
}
<|endoftext|>


<commit_before>mod ffi;

pub struct SoundIo {
    context: *mut ffi::Struct_SoundIo,
}
impl SoundIo {
    pub fn new() -> Self {
        SoundIo { context: unsafe { ffi::soundio_create() } }
    }

    pub fn connect(&self) -> Option<ffi::Enum_SoundIoError> {
        match unsafe { ffi::soundio_connect(self.context) } {
            ffi::Enum_SoundIoError::SoundIoErrorNone => None,
            err @ _ => Some(err),
        }
    }

    pub fn connect_backend(&self,
                           backend: ffi::Enum_SoundIoBackend)
                           -> Option<ffi::Enum_SoundIoError> {
        match unsafe { ffi::soundio_connect_backend(self.context, backend) } {
            ffi::Enum_SoundIoError::SoundIoErrorNone => None,
            err @ _ => {
                println!("{:?}", err);
                Some(err)
            }
        }
    }

    pub fn backend_count(&self) -> i32 {
        let cnt: i32 = unsafe { ffi::soundio_backend_count(self.context) };
        if cnt < 0 {
            panic!("Negative backend count!");
        } else {
            cnt
        }
    }

    pub fn get_backend(&self, idx: i32) -> Option<ffi::Enum_SoundIoBackend> {
        match unsafe { ffi::soundio_get_backend(self.context, idx) } {
            ffi::Enum_SoundIoBackend::SoundIoBackendNone => None,
            backend @ _ => Some(backend),
        }
    }

    pub fn have_backend(&self, backend: ffi::Enum_SoundIoBackend) -> bool {
        unsafe { ffi::soundio_have_backend(backend) == 1u8 }
    }

    pub fn flush_events(&self) {
        unsafe { ffi::soundio_flush_events(self.context) }
    }

    pub fn wait_events(&self) {
        unsafe { ffi::soundio_wait_events(self.context) }
    }

    pub fn wakeup(&self) {
        unsafe { ffi::soundio_wakeup(self.context) }
    }

    pub fn force_device_scan(&self) {
        unsafe { ffi::soundio_force_device_scan(self.context) }
    }

    pub fn disconnect(&self) {
        unsafe { ffi::soundio_disconnect(self.context) }
    }
}
impl Drop for SoundIo {
    fn drop(&mut self) {
        unsafe {
            self.disconnect();
            ffi::soundio_destroy(self.context)
        }
    }
}

#[test]
fn test_soundio() {
    let sio = SoundIo::new();
    assert!(sio.backend_count() > 0);
    assert!(sio.get_backend(0).is_some());
    assert!(sio.get_backend(-1).is_none());
    assert!(sio.connect().is_none());
    sio.disconnect();
    if sio.have_backend(ffi::Enum_SoundIoBackend::SoundIoBackendAlsa) {
        assert!(sio.connect_backend(ffi::Enum_SoundIoBackend::SoundIoBackendAlsa).is_none());
        sio.disconnect();
    }
}

#[test]
fn test_enums() {
    assert_eq!("(no error)",
               format!("{}", ffi::Enum_SoundIoError::SoundIoErrorNone));
    assert_eq!("ALSA",
               format!("{}", ffi::Enum_SoundIoBackend::SoundIoBackendAlsa));
    assert_eq!("Front Left",
               format!("{}", ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft));
    assert_eq!(ffi::Enum_SoundIoChannelId::from("Front Left".to_string()),
               ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft);
    assert!(ffi::Enum_SoundIoChannelId::from("SomeInvalidBoredom".to_string()) !=
            ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft);
}
<commit_msg>Implement `channel_layout_builtin_count`<commit_after>mod ffi;

pub struct SoundIo {
    context: *mut ffi::Struct_SoundIo,
}
impl SoundIo {
    pub fn new() -> Self {
        SoundIo { context: unsafe { ffi::soundio_create() } }
    }

    pub fn channel_layout_builtin_count() -> i32 {
        let cnt = unsafe { ffi::soundio_channel_layout_builtin_count() };
        if cnt < 0 {
            panic!("Negative # of builtin channel layouts!")
        } else {
            cnt as i32
        }
    }

    pub fn connect(&self) -> Option<ffi::Enum_SoundIoError> {
        match unsafe { ffi::soundio_connect(self.context) } {
            ffi::Enum_SoundIoError::SoundIoErrorNone => None,
            err @ _ => Some(err),
        }
    }

    pub fn connect_backend(&self,
                           backend: ffi::Enum_SoundIoBackend)
                           -> Option<ffi::Enum_SoundIoError> {
        match unsafe { ffi::soundio_connect_backend(self.context, backend) } {
            ffi::Enum_SoundIoError::SoundIoErrorNone => None,
            err @ _ => {
                println!("{:?}", err);
                Some(err)
            }
        }
    }

    pub fn backend_count(&self) -> i32 {
        let cnt: i32 = unsafe { ffi::soundio_backend_count(self.context) };
        if cnt < 0 {
            panic!("Negative backend count!");
        } else {
            cnt
        }
    }

    pub fn get_backend(&self, idx: i32) -> Option<ffi::Enum_SoundIoBackend> {
        match unsafe { ffi::soundio_get_backend(self.context, idx) } {
            ffi::Enum_SoundIoBackend::SoundIoBackendNone => None,
            backend @ _ => Some(backend),
        }
    }

    pub fn have_backend(&self, backend: ffi::Enum_SoundIoBackend) -> bool {
        unsafe { ffi::soundio_have_backend(backend) == 1u8 }
    }

    pub fn flush_events(&self) {
        unsafe { ffi::soundio_flush_events(self.context) }
    }

    pub fn wait_events(&self) {
        unsafe { ffi::soundio_wait_events(self.context) }
    }

    pub fn wakeup(&self) {
        unsafe { ffi::soundio_wakeup(self.context) }
    }

    pub fn force_device_scan(&self) {
        unsafe { ffi::soundio_force_device_scan(self.context) }
    }

    pub fn disconnect(&self) {
        unsafe { ffi::soundio_disconnect(self.context) }
    }
}
impl Drop for SoundIo {
    fn drop(&mut self) {
        unsafe {
            self.disconnect();
            ffi::soundio_destroy(self.context)
        }
    }
}

#[test]
fn test_soundio() {
    let sio = SoundIo::new();
    assert!(sio.backend_count() > 0);
    assert!(sio.get_backend(0).is_some());
    assert!(sio.get_backend(-1).is_none());
    assert!(sio.connect().is_none());
    sio.disconnect();
    if sio.have_backend(ffi::Enum_SoundIoBackend::SoundIoBackendAlsa) {
        assert!(sio.connect_backend(ffi::Enum_SoundIoBackend::SoundIoBackendAlsa).is_none());
        sio.disconnect();
    }
    assert!(SoundIo::channel_layout_builtin_count() >= 0);
}

#[test]
fn test_enums() {
    assert_eq!("(no error)",
               format!("{}", ffi::Enum_SoundIoError::SoundIoErrorNone));
    assert_eq!("ALSA",
               format!("{}", ffi::Enum_SoundIoBackend::SoundIoBackendAlsa));
    assert_eq!("Front Left",
               format!("{}", ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft));
    assert_eq!(ffi::Enum_SoundIoChannelId::from("Front Left".to_string()),
               ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft);
    assert!(ffi::Enum_SoundIoChannelId::from("SomeInvalidBoredom".to_string()) !=
            ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft);
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// 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.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do [Cap'n Proto code generation]
//! (https://capnproto.org/otherlang.html#how-to-write-compiler-plugins)
//! within a Cargo build.
//!
//! In your Cargo.toml:
//!
//! ```ignore
//!   [package]
//!   build = "build.rs"
//!
//!   [build-dependencies]
//!   capnpc = "*"
//! ```
//!
//! In your build.rs:
//!
//! ```ignore
//! extern crate capnpc;
//!
//! fn main() {
//!     ::capnpc::CompilerCommand::new()
//!         .src_prefix("schema")
//!         .file("schema/foo.capnp")
//!         .file("schema/bar.capnp")
//!         .run().expect("schema compiler command");
//! }
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

extern crate capnp;

/// Code generated from [schema.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp).
pub mod schema_capnp;

pub mod codegen;
pub mod codegen_types;
pub mod schema;

use std::path::{Path, PathBuf};

fn run_command(mut command: ::std::process::Command) -> ::capnp::Result<()> {
    let mut p = try!(command.spawn());
    try!(::codegen::main(p.stdout.take().unwrap(),
                         ::std::path::Path::new(&::std::env::var("OUT_DIR").unwrap())));
    let exit_status = try!(p.wait());
    if !exit_status.success() {
        Err(::capnp::Error::failed(format!("Non-success exit status: {}", exit_status)))
    } else {
        Ok(())
    }
}

/// A builder object for schema compiler commands.
pub struct CompilerCommand {
    files: Vec<PathBuf>,
    src_prefixes: Vec<PathBuf>,
}

impl CompilerCommand {
    /// Creates a new, empty command.
    pub fn new() -> CompilerCommand {
        CompilerCommand {
            files: Vec::new(),
            src_prefixes: Vec::new(),
        }
    }

    /// Adds a file to be compiled.
    pub fn file<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.files.push(path.as_ref().to_path_buf());
        self
    }

    /// Adds a --src-prefix flag. For all files specified for compilation that start
    /// with `prefix`, removes the prefix when computing output filenames.
    pub fn src_prefix<'a, P>(&'a mut self, prefix: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.src_prefixes.push(prefix.as_ref().to_path_buf());
        self
    }

    /// Runs the command.
    pub fn run(&mut self) -> ::capnp::Result<()> {
        let mut command = ::std::process::Command::new("capnp");
        command.arg("compile").arg("-o").arg("-");
        for src_prefix in &self.src_prefixes {
            command.arg(&format!("--src-prefix={}", src_prefix.display()));
        }

        for file in &self.files {
            command.arg(&format!("{}", file.display()));
        }

        command.stdout(::std::process::Stdio::piped());
        command.stderr(::std::process::Stdio::inherit());

        run_command(command).map_err(|error| {
            ::capnp::Error::failed(format!(
                "Error while trying to execute `capnp compile`: {}.  \
                 Please verify that version 0.5.2 or higher of the capnp executable \
                 is installed on your system. See https://capnproto.org/install.html",
                error))})
    }
}
<commit_msg>add import_path() and no_std_import() options to CompilerCommand<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// 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.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do [Cap'n Proto code generation]
//! (https://capnproto.org/otherlang.html#how-to-write-compiler-plugins)
//! within a Cargo build.
//!
//! In your Cargo.toml:
//!
//! ```ignore
//!   [package]
//!   build = "build.rs"
//!
//!   [build-dependencies]
//!   capnpc = "*"
//! ```
//!
//! In your build.rs:
//!
//! ```ignore
//! extern crate capnpc;
//!
//! fn main() {
//!     ::capnpc::CompilerCommand::new()
//!         .src_prefix("schema")
//!         .file("schema/foo.capnp")
//!         .file("schema/bar.capnp")
//!         .run().expect("schema compiler command");
//! }
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

extern crate capnp;

/// Code generated from [schema.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp).
pub mod schema_capnp;

pub mod codegen;
pub mod codegen_types;
pub mod schema;

use std::path::{Path, PathBuf};

fn run_command(mut command: ::std::process::Command) -> ::capnp::Result<()> {
    let mut p = try!(command.spawn());
    try!(::codegen::main(p.stdout.take().unwrap(),
                         ::std::path::Path::new(&::std::env::var("OUT_DIR").unwrap())));
    let exit_status = try!(p.wait());
    if !exit_status.success() {
        Err(::capnp::Error::failed(format!("Non-success exit status: {}", exit_status)))
    } else {
        Ok(())
    }
}

/// A builder object for schema compiler commands.
pub struct CompilerCommand {
    files: Vec<PathBuf>,
    src_prefixes: Vec<PathBuf>,
    import_paths: Vec<PathBuf>,
    no_std_import: bool,
}

impl CompilerCommand {
    /// Creates a new, empty command.
    pub fn new() -> CompilerCommand {
        CompilerCommand {
            files: Vec::new(),
            src_prefixes: Vec::new(),
            import_paths: Vec::new(),
            no_std_import: false,
        }
    }

    /// Adds a file to be compiled.
    pub fn file<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.files.push(path.as_ref().to_path_buf());
        self
    }

    /// Adds a --src-prefix flag. For all files specified for compilation that start
    /// with `prefix`, removes the prefix when computing output filenames.
    pub fn src_prefix<'a, P>(&'a mut self, prefix: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.src_prefixes.push(prefix.as_ref().to_path_buf());
        self
    }

    /// Adds an --import_path flag. Adds `dir` to the list of directories searched
    /// for absolute imports.
    pub fn import_path<'a, P>(&'a mut self, dir: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.import_paths.push(dir.as_ref().to_path_buf());
        self
    }

    /// Adds the --no-std-import flag, indicating that the default import paths of
    /// /usr/include and /usr/local/include should not bet included.
    pub fn no_std_import<'a>(&'a mut self) -> &'a mut CompilerCommand {
        self.no_std_import = true;
        self
    }

    /// Runs the command.
    pub fn run(&mut self) -> ::capnp::Result<()> {
        let mut command = ::std::process::Command::new("capnp");
        command.arg("compile").arg("-o").arg("-");

        if self.no_std_import {
            command.arg("--no-std-import");
        }

        for import_path in &self.import_paths {
            command.arg(&format!("--import-path={}", import_path.display()));
        }

        for src_prefix in &self.src_prefixes {
            command.arg(&format!("--src-prefix={}", src_prefix.display()));
        }

        for file in &self.files {
            command.arg(&format!("{}", file.display()));
        }

        command.stdout(::std::process::Stdio::piped());
        command.stderr(::std::process::Stdio::inherit());

        run_command(command).map_err(|error| {
            ::capnp::Error::failed(format!(
                "Error while trying to execute `capnp compile`: {}.  \
                 Please verify that version 0.5.2 or higher of the capnp executable \
                 is installed on your system. See https://capnproto.org/install.html",
                error))})
    }
}
<|endoftext|>


<commit_before>extern crate libc;

pub mod groonga;

use libc::funcs::c95::string;
use std::ffi::CString;
use std::fs;
use std::mem;
use std::ptr;
use std::result::Result;
use std::result::Result::{Ok, Err};

#[derive(Debug)]
pub struct Error {
    code: i32
}

impl Error {
    pub fn new(code: i32) -> Error {
        Error {code: code}
    }
}

pub struct Groonga {
    closed: bool
}

impl Groonga {
    pub fn new() -> Result<Groonga, Error> {
        unsafe {
            let rc =  groonga::grn_init();
            if rc != groonga::GRN_SUCCESS {
                return Err(Error::new(rc))
            }
            Ok(Groonga{ closed: false })
        }
    }

    pub fn close(&mut self) -> Result<(), Error> {
        if self.closed {
            return Ok(())
        }
        unsafe {
            let rc = groonga::grn_fin();
            if rc != groonga::GRN_SUCCESS {
                return Err(Error::new(rc))
            }
            self.closed = true;
            Ok(())
        }
    }
}

impl Drop for Groonga {
    fn drop(&mut self) {
        self.close().unwrap()
    }
}

pub struct Context {
    ctx: *mut groonga::grn_ctx,
    db: *mut groonga::grn_obj,
}

pub struct Object {
    obj: *mut groonga::grn_obj,
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            if !self.db.is_null() {
                groonga::grn_obj_unlink(self.ctx, self.db);
            }

            let rc2 = groonga::grn_ctx_fin(self.ctx);
            if rc2 != groonga::GRN_SUCCESS {
                panic!("grn_ctx_fin(ctx) failed with rc2={}", rc2);
            }
        }
    }
}

impl Context {
    pub fn new() -> Result<Context, Error> {
        unsafe {
            let ctx = groonga::grn_ctx_open(0);
            if ctx.is_null() {
                return Err(Error::new(groonga::GRN_NO_MEMORY_AVAILABLE))
            }
            Ok(Context { ctx: ctx, db: mem::zeroed() })
        }
    }

    pub fn db_create(&mut self, path: &str) -> Result<(), Error> {
        let c_path = CString::new(path).unwrap();
        unsafe {
            self.db = groonga::grn_db_create(
                self.ctx, c_path.as_ptr(), mem::zeroed());
            if self.db.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(())
        }
    }

    pub fn db_open(&mut self, path: &str) -> Result<(), Error> {
        let c_path = CString::new(path).unwrap();
        unsafe {
            self.db = groonga::grn_db_open(self.ctx, c_path.as_ptr());
            if self.db.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(())
        }
    }

    pub fn db_open_or_create(&mut self, path: &str) -> Result<(), Error> {
        if file_exists(path) {
            self.db_open(path)
        } else {
            self.db_create(path)
        }
    }

    pub fn ctx_at(&mut self, id: u32) -> Result<Object, Error> {
        unsafe {
            let obj = groonga::grn_ctx_at(self.ctx, id);
            if obj.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(Object { obj: obj })
        }
    }

    pub fn ctx_get(&mut self, name: &str) -> Result<Object, Error> {
        let c_name = CString::new(name).unwrap().as_ptr();
        unsafe {
            let obj = groonga::grn_ctx_get(
                self.ctx, c_name, string::strlen(c_name) as i32);
            if obj.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(Object { obj: obj })
        }
    }

    pub fn table_create(&mut self, name: &str, path: &str, flags: u32,
        key_type: &Object, value_type: Option<&Object>) -> Result<Object, Error> {
        let c_name = CString::new(name).unwrap().as_ptr();
        let c_path = if path != "" {
            CString::new(path).unwrap().as_ptr()
        } else {
            ptr::null()
        };
        unsafe {
            let c_value_type =
                match value_type {
                    Some(value_type_obj) => value_type_obj.obj,
                    None => mem::zeroed(),
                };
            let table = groonga::grn_table_create(
                self.ctx, c_name, string::strlen(c_name) as u32, c_path,
                flags as u16, key_type.obj, c_value_type);
            if table.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(Object { obj: table })
        }
    }

    pub fn table_open_or_create(&mut self, name: &str, path: &str, flags: u32,
        key_type: &Object, value_type: Option<&Object>) -> Result<Object, Error> {
        if let Ok(table) = self.ctx_get(name) {
            Ok(table)
        } else {
            self.table_create(name, path, flags,
                key_type, value_type)
        }
    }

    pub fn obj_column(&mut self, table: &Object, name: &str)
        -> Result<Object, Error> {
        let c_name = CString::new(name).unwrap().as_ptr();
        unsafe {
            let obj = groonga::grn_obj_column(
                self.ctx, table.obj, c_name, string::strlen(c_name) as u32);
            if obj.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(Object { obj: obj })
        }
    }

    pub fn column_create(&mut self, table: &Object, name: &str, path: &str,
        flags: u32, _type: &Object) -> Result<Object, Error> {
        let c_name = CString::new(name).unwrap().as_ptr();
        let c_path = if path != "" {
            CString::new(path).unwrap().as_ptr()
        } else {
            ptr::null()
        };
        unsafe {
            let column = groonga::grn_column_create(
                self.ctx, table.obj, c_name, string::strlen(c_name) as u32,
                c_path, flags as u16, _type.obj);
            if column.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(Object { obj: column })
        }
    }

    pub fn column_open_or_create(&mut self, table: &Object, name: &str,
        path: &str, flags: u32, _type: &Object) -> Result<Object, Error> {
        if let Ok(column) = self.obj_column(&table, name) {
            Ok(column)
        } else {
            self.column_create(&table, name, path, flags, _type)
        }
    }
}

fn file_exists(path: &str) -> bool {
    match fs::File::open(path) {
        Ok(_) => true,
        Err(_) => false,
    }
}
<commit_msg>Remove db field from Context<commit_after>extern crate libc;

pub mod groonga;

use libc::funcs::c95::string;
use std::ffi::CString;
use std::fs;
use std::mem;
use std::ptr;
use std::result::Result;
use std::result::Result::{Ok, Err};

#[derive(Debug)]
pub struct Error {
    code: i32
}

impl Error {
    pub fn new(code: i32) -> Error {
        Error {code: code}
    }
}

pub struct Groonga {
    closed: bool
}

impl Groonga {
    pub fn new() -> Result<Groonga, Error> {
        unsafe {
            let rc =  groonga::grn_init();
            if rc != groonga::GRN_SUCCESS {
                return Err(Error::new(rc))
            }
            Ok(Groonga{ closed: false })
        }
    }

    pub fn close(&mut self) -> Result<(), Error> {
        if self.closed {
            return Ok(())
        }
        unsafe {
            let rc = groonga::grn_fin();
            if rc != groonga::GRN_SUCCESS {
                return Err(Error::new(rc))
            }
            self.closed = true;
            Ok(())
        }
    }
}

impl Drop for Groonga {
    fn drop(&mut self) {
        self.close().unwrap()
    }
}

pub struct Context {
    ctx: *mut groonga::grn_ctx,
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            let rc = groonga::grn_ctx_fin(self.ctx);
            if rc != groonga::GRN_SUCCESS {
                panic!("grn_ctx_fin(ctx) failed with rc={}", rc);
            }
        }
    }
}

impl Context {
    pub fn new() -> Result<Context, Error> {
        unsafe {
            let ctx = groonga::grn_ctx_open(0);
            if ctx.is_null() {
                return Err(Error::new(groonga::GRN_NO_MEMORY_AVAILABLE))
            }
            Ok(Context { ctx: ctx })
        }
    }

    pub fn db_create(&mut self, path: &str) -> Result<(), Error> {
        let c_path = CString::new(path).unwrap();
        unsafe {
            let db = groonga::grn_db_create(
                self.ctx, c_path.as_ptr(), mem::zeroed());
            if db.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(())
        }
    }

    pub fn db_open(&mut self, path: &str) -> Result<(), Error> {
        let c_path = CString::new(path).unwrap();
        unsafe {
            let db = groonga::grn_db_open(self.ctx, c_path.as_ptr());
            if db.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(())
        }
    }

    pub fn db_open_or_create(&mut self, path: &str) -> Result<(), Error> {
        if file_exists(path) {
            self.db_open(path)
        } else {
            self.db_create(path)
        }
    }

    pub fn ctx_at(&mut self, id: u32) -> Result<Object, Error> {
        unsafe {
            let obj = groonga::grn_ctx_at(self.ctx, id);
            if obj.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(Object { context: self, obj: obj })
        }
    }

    pub fn ctx_get(&mut self, name: &str) -> Result<Object, Error> {
        let c_name = CString::new(name).unwrap().as_ptr();
        unsafe {
            let obj = groonga::grn_ctx_get(
                self.ctx, c_name, string::strlen(c_name) as i32);
            if obj.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(Object { context: self, obj: obj })
        }
    }

    pub fn table_create(&mut self, name: &str, path: &str, flags: u32,
        key_type: &Object, value_type: Option<&Object>) -> Result<Object, Error> {
        let c_name = CString::new(name).unwrap().as_ptr();
        let c_path = if path != "" {
            CString::new(path).unwrap().as_ptr()
        } else {
            ptr::null()
        };
        unsafe {
            let c_value_type =
                match value_type {
                    Some(value_type_obj) => value_type_obj.obj,
                    None => mem::zeroed(),
                };
            let table = groonga::grn_table_create(
                self.ctx, c_name, string::strlen(c_name) as u32, c_path,
                flags as u16, key_type.obj, c_value_type);
            if table.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(Object { context: self, obj: table })
        }
    }

    pub fn table_open_or_create(&mut self, name: &str, path: &str, flags: u32,
        key_type: &Object, value_type: Option<&Object>) -> Result<Object, Error> {
        if let Ok(table) = self.ctx_get(name) {
            Ok(table)
        } else {
            self.table_create(name, path, flags,
                key_type, value_type)
        }
    }

    pub fn obj_column(&mut self, table: &Object, name: &str)
        -> Result<Object, Error> {
        let c_name = CString::new(name).unwrap().as_ptr();
        unsafe {
            let obj = groonga::grn_obj_column(
                self.ctx, table.obj, c_name, string::strlen(c_name) as u32);
            if obj.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(Object { context: self, obj: obj })
        }
    }

    pub fn column_create(&mut self, table: &Object, name: &str, path: &str,
        flags: u32, _type: &Object) -> Result<Object, Error> {
        let c_name = CString::new(name).unwrap().as_ptr();
        let c_path = if path != "" {
            CString::new(path).unwrap().as_ptr()
        } else {
            ptr::null()
        };
        unsafe {
            let column = groonga::grn_column_create(
                self.ctx, table.obj, c_name, string::strlen(c_name) as u32,
                c_path, flags as u16, _type.obj);
            if column.is_null() {
                return Err(Error::new((*self.ctx).rc))
            }
            Ok(Object { context: self, obj: column })
        }
    }

    pub fn column_open_or_create(&mut self, table: &Object, name: &str,
        path: &str, flags: u32, _type: &Object) -> Result<Object, Error> {
        if let Ok(column) = self.obj_column(&table, name) {
            Ok(column)
        } else {
            self.column_create(&table, name, path, flags, _type)
        }
    }
}

pub struct Object {
    context: *mut Context,
    obj: *mut groonga::grn_obj,
}

impl Object {
    pub fn close(&mut self) {
        unsafe {
            if self.obj.is_null() {
                return
            }
            groonga::grn_obj_unlink((*self.context).ctx, self.obj)
        }
    }
}

fn file_exists(path: &str) -> bool {
    match fs::File::open(path) {
        Ok(_) => true,
        Err(_) => false,
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate oven;
extern crate cookie;

use iron::prelude::*;
use iron::middleware;
use oven::prelude::*;

pub struct LoginManager {
    signing_key: Vec<u8>
}

impl LoginManager {
    pub fn new(signing_key: Vec<u8>) -> LoginManager {
        LoginManager { signing_key: signing_key }
    }
}

impl middleware::AroundMiddleware for LoginManager {
    fn around(self, handler: Box<middleware::Handler>) -> Box<middleware::Handler> {
        let mut ch = Chain::new(handler);
        let key = self.signing_key;

        ch.link(oven::new(key.clone()));

        Box::new(ch)
    }
}

pub trait User: Send + Sync + Sized {
    fn from_username(request: &mut Request, username: &str) -> Option<Self>;
    fn get_username(&self) -> &str;

    fn from_request(request: &mut Request) -> Option<Self> {
        let value = match request.get_cookie("logged_in_user") {
            Some(x) => x.value.clone(),
            None => return None
        };
        Self::from_username(request, &value[..])
    }

    fn log_in_on(&self, response: &mut Response) {
        response.set_cookie({
            let mut x = cookie::Cookie::new("logged_in_user".to_owned(), self.get_username().to_owned());
            x.path = Some("/".to_owned());
            x
        });
    }

    fn log_in(self) -> LoginModifier<Self> { LoginModifier { user: self } }
}

pub struct LoginModifier<U: User> { user: U }
impl<U: User> iron::modifier::Modifier<Response> for LoginModifier<U> {
    fn modify(self, response: &mut Response) { self.user.log_in_on(response) }
}

pub fn log_out_of(response: &mut Response) {
    response.get_mut::<oven::ResponseCookies>().unwrap().remove("logged_in_user");
}

pub fn log_out() -> LogoutModifier { LogoutModifier }

pub struct LogoutModifier;
impl iron::modifier::Modifier<Response> for LogoutModifier {
    fn modify(self, response: &mut Response) { log_out_of(response) }
}
<commit_msg>Another bugfix<commit_after>extern crate iron;
extern crate oven;
extern crate cookie;

use iron::prelude::*;
use iron::middleware;
use oven::prelude::*;

pub struct LoginManager {
    signing_key: Vec<u8>
}

impl LoginManager {
    pub fn new(signing_key: Vec<u8>) -> LoginManager {
        LoginManager { signing_key: signing_key }
    }
}

impl middleware::AroundMiddleware for LoginManager {
    fn around(self, handler: Box<middleware::Handler>) -> Box<middleware::Handler> {
        let mut ch = Chain::new(handler);
        let key = self.signing_key;

        ch.link(oven::new(key.clone()));

        Box::new(ch)
    }
}

pub trait User: Send + Sync + Sized {
    fn from_username(request: &mut Request, username: &str) -> Option<Self>;
    fn get_username(&self) -> &str;

    fn from_request(request: &mut Request) -> Option<Self> {
        let value = match request.get_cookie("logged_in_user") {
            Some(x) if x.value.len() > 0 => x.value.clone(),
            _ => return None
        };
        Self::from_username(request, &value[..])
    }

    fn log_in(self) -> LoginModifier<Self> { LoginModifier { user: self } }
}

pub struct LoginModifier<U: User> { user: U }
impl<U: User> iron::modifier::Modifier<Response> for LoginModifier<U> {
    fn modify(self, response: &mut Response) { log_in_on(response, self.user.get_username()) }
}

pub fn log_in_on(response: &mut Response, username: &str) {
    response.set_cookie({
        let mut x = cookie::Cookie::new("logged_in_user".to_owned(), username.to_owned());
        x.path = Some("/".to_owned());
        x
    });
}

pub struct LogoutModifier;
impl iron::modifier::Modifier<Response> for LogoutModifier {
    fn modify(self, response: &mut Response) { log_out_of(response) }
}

pub fn log_out_of(response: &mut Response) {
    log_in_on(response, "");
}

pub fn log_out() -> LogoutModifier { LogoutModifier }
<|endoftext|>


<commit_before>#[pkgid="allegro5#5.0.10.1"];
#[link(name = "allegro5")];

#[comment = "Allegro 5 core library Rust bindings"];
#[license = "zlib"];
#[crate_type = "lib"];
#[feature(globs)];
#[feature(macro_rules)];
#[feature(struct_variant)];

pub use internal::bitmap::external::*;
pub use internal::bitmap_like::*;
pub use internal::color::*;
pub use internal::core::*;
pub use internal::core_drawing::*;
pub use internal::display::external::*;
pub use internal::events::external::*;
pub use internal::keycodes::*;
pub use internal::run::*;
pub use internal::timer::external::*;

pub mod ffi;
#[macro_escape]
pub mod rust_util;

mod internal
{
	pub mod bitmap;
	pub mod bitmap_like;
	pub mod color;
	pub mod core;
	pub mod core_drawing;
	pub mod display;
	pub mod events;
	pub mod keycodes;
	pub mod run;
	pub mod timer;
}
<commit_msg>Update to newest Rust<commit_after>#[crate_id="allegro5#5.0.10.1"];

#[comment = "Allegro 5 core library Rust bindings"];
#[license = "zlib"];
#[crate_type = "lib"];
#[feature(globs)];
#[feature(macro_rules)];
#[feature(struct_variant)];

pub use internal::bitmap::external::*;
pub use internal::bitmap_like::*;
pub use internal::color::*;
pub use internal::core::*;
pub use internal::core_drawing::*;
pub use internal::display::external::*;
pub use internal::events::external::*;
pub use internal::keycodes::*;
pub use internal::run::*;
pub use internal::timer::external::*;

pub mod ffi;
#[macro_escape]
pub mod rust_util;

mod internal
{
	pub mod bitmap;
	pub mod bitmap_like;
	pub mod color;
	pub mod core;
	pub mod core_drawing;
	pub mod display;
	pub mod events;
	pub mod keycodes;
	pub mod run;
	pub mod timer;
}
<|endoftext|>


<commit_before>//! Board Support Crate for the [Blue Pill]
//!
//! [Blue Pill]: http://wiki.stm32duino.com/index.php?title=Blue_Pill
//!
//! # Usage
//!
//! Follow `cortex-m-quickstart` [instructions][i] but remove the `memory.x`
//! linker script and the `build.rs` build script file as part of the
//! configuration of the quickstart crate.
//!
//! [i]: https://docs.rs/cortex-m-quickstart/0.1.8/cortex_m_quickstart/

#![deny(missing_docs)]
#![deny(warnings)]
#![feature(get_type_id)]
#![no_std]

extern crate cast;
extern crate either;

pub extern crate stm32f103xx;

mod frequency;

pub mod capture;
pub mod gpio;
pub mod led;
pub mod pwm;
pub mod qei;
pub mod serial;
pub mod spi;
pub mod timer;
<commit_msg>re-export main interfaces from the root<commit_after>//! Board Support Crate for the [Blue Pill]
//!
//! [Blue Pill]: http://wiki.stm32duino.com/index.php?title=Blue_Pill
//!
//! # Usage
//!
//! Follow `cortex-m-quickstart` [instructions][i] but remove the `memory.x`
//! linker script and the `build.rs` build script file as part of the
//! configuration of the quickstart crate.
//!
//! [i]: https://docs.rs/cortex-m-quickstart/0.1.8/cortex_m_quickstart/

#![deny(missing_docs)]
#![deny(warnings)]
#![feature(get_type_id)]
#![no_std]

extern crate cast;
extern crate either;

pub extern crate stm32f103xx;

mod frequency;

pub mod capture;
pub mod gpio;
pub mod led;
pub mod pwm;
pub mod qei;
pub mod serial;
pub mod spi;
pub mod timer;

pub use capture::Capture;
pub use pwm::Pwm;
pub use qei::Qei;
pub use serial::Serial;
pub use spi::Spi;
pub use timer::Timer;
<|endoftext|>


<commit_before>//! Typed inter-thread, intra-process channels.

use std::rc::Rc;
use std::cell::RefCell;
use std::sync::{Arc, Mutex};
use std::any::Any;
use std::sync::mpsc::{Sender, Receiver, channel};
use std::collections::{HashMap, VecDeque};

use allocator::thread::{ThreadBuilder};
use allocator::{Allocate, AllocateBuilder, Event, Thread};
use {Push, Pull, Message};

/// An allocater for inter-thread, intra-process communication
pub struct ProcessBuilder {
    inner: ThreadBuilder,
    index: usize,
    peers: usize,
    // below: `Box<Any+Send>` is a `Box<Vec<Option<(Vec<Sender<T>>, Receiver<T>)>>>`
    channels: Arc<Mutex<HashMap<usize, Box<Any+Send>>>>,

    counters_send: Vec<Sender<(usize, Event)>>,
    counters_recv: Receiver<(usize, Event)>,
}

impl AllocateBuilder for ProcessBuilder {
    type Allocator = Process;
    fn build(self) -> Self::Allocator {
        Process {
            inner: self.inner.build(),
            index: self.index,
            peers: self.peers,
            channels: self.channels,
            counters_send: self.counters_send,
            counters_recv: self.counters_recv,
        }
    }
}

/// An allocater for inter-thread, intra-process communication
pub struct Process {
    inner: Thread,
    index: usize,
    peers: usize,
    // below: `Box<Any+Send>` is a `Box<Vec<Option<(Vec<Sender<T>>, Receiver<T>)>>>`
    channels: Arc<Mutex<HashMap</* channel id */ usize, Box<Any+Send>>>>,
    counters_send: Vec<Sender<(usize, Event)>>,
    counters_recv: Receiver<(usize, Event)>,
}

impl Process {
    /// Access the wrapped inner allocator.
    pub fn inner<'a>(&'a mut self) -> &'a mut Thread { &mut self.inner }
    /// Allocate a list of connected intra-process allocators.
    pub fn new_vector(peers: usize) -> Vec<ProcessBuilder> {

        let mut counters_send = Vec::new();
        let mut counters_recv = Vec::new();
        for _ in 0 .. peers {
            let (send, recv) = channel();
            counters_send.push(send);
            counters_recv.push(recv);
        }

        let channels = Arc::new(Mutex::new(HashMap::new()));

        counters_recv
            .into_iter()
            .enumerate()
            .map(|(index, recv)| {
                ProcessBuilder {
                    inner: ThreadBuilder,
                    index,
                    peers,
                    channels: channels.clone(),
                    counters_send: counters_send.clone(),
                    counters_recv: recv,
                }
            })
            .collect()
    }
}

impl Allocate for Process {
    fn index(&self) -> usize { self.index }
    fn peers(&self) -> usize { self.peers }
    fn allocate<T: Any+Send+Sync+'static>(&mut self, identifier: usize) -> (Vec<Box<Push<Message<T>>>>, Box<Pull<Message<T>>>) {

        // this is race-y global initialisation of all channels for all workers, performed by the
        // first worker that enters this critical section

        // ensure exclusive access to shared list of channels
        let mut channels = self.channels.lock().ok().expect("mutex error?");

        let (sends, recv, empty) = {

            // we may need to alloc a new channel ...
            let mut entry = channels.entry(identifier).or_insert_with(|| {

                let mut pushers = Vec::new();
                let mut pullers = Vec::new();
                for _ in 0..self.peers {

                    let (s, r): (Sender<Message<T>>, Receiver<Message<T>>) = channel();
                    pushers.push(Pusher { target: s });
                    pullers.push(Puller { source: r, current: None });
                }

                let mut to_box = Vec::new();
                for recv in pullers.into_iter() {
                    to_box.push(Some((pushers.clone(), recv)));
                }

                Box::new(to_box)
            });

            let vector =
            entry
                .downcast_mut::<(Vec<Option<(Vec<Pusher<Message<T>>>, Puller<Message<T>>)>>)>()
                .expect("failed to correctly cast channel");

            let (sends, recv) =
            vector[self.index]
                .take()
                .expect("channel already consumed");

            let empty = vector.iter().all(|x| x.is_none());

            (sends, recv, empty)
        };

        // send is a vec of all senders, recv is this worker's receiver

        if empty { channels.remove(&identifier); }

        use allocator::counters::ArcPusher as CountPusher;
        use allocator::counters::Puller as CountPuller;

        let sends =
        sends.into_iter()
             .enumerate()
             .map(|(i,s)| CountPusher::new(s, identifier, self.counters_send[i].clone()))
             .map(|s| Box::new(s) as Box<Push<super::Message<T>>>)
             .collect::<Vec<_>>();

        let recv = Box::new(CountPuller::new(recv, identifier, self.inner.events().clone())) as Box<Pull<super::Message<T>>>;

        (sends, recv)
    }

    fn events(&self) -> &Rc<RefCell<VecDeque<(usize, Event)>>> {
        self.inner.events()
    }

    fn receive(&mut self) {
        let mut events = self.inner.events().borrow_mut();
        while let Ok((index, event)) = self.counters_recv.try_recv() {
            events.push_back((index, event));
        }
    }
}

/// The push half of an intra-process channel.
struct Pusher<T> {
    target: Sender<T>,
}

impl<T> Clone for Pusher<T> {
    fn clone(&self) -> Self {
        Pusher { target: self.target.clone() }
    }
}

impl<T> Push<T> for Pusher<T> {
    #[inline] fn push(&mut self, element: &mut Option<T>) {
        if let Some(element) = element.take() {
            self.target.send(element).unwrap();
        }
    }
}

/// The pull half of an intra-process channel.
struct Puller<T> {
    current: Option<T>,
    source: Receiver<T>,
}

impl<T> Pull<T> for Puller<T> {
    #[inline]
    fn pull(&mut self) -> &mut Option<T> {
        self.current = self.source.try_recv().ok();
        &mut self.current
    }
}
<commit_msg>Fix typo in spelling of "allocator"<commit_after>//! Typed inter-thread, intra-process channels.

use std::rc::Rc;
use std::cell::RefCell;
use std::sync::{Arc, Mutex};
use std::any::Any;
use std::sync::mpsc::{Sender, Receiver, channel};
use std::collections::{HashMap, VecDeque};

use allocator::thread::{ThreadBuilder};
use allocator::{Allocate, AllocateBuilder, Event, Thread};
use {Push, Pull, Message};

/// An allocator for inter-thread, intra-process communication
pub struct ProcessBuilder {
    inner: ThreadBuilder,
    index: usize,
    peers: usize,
    // below: `Box<Any+Send>` is a `Box<Vec<Option<(Vec<Sender<T>>, Receiver<T>)>>>`
    channels: Arc<Mutex<HashMap<usize, Box<Any+Send>>>>,

    counters_send: Vec<Sender<(usize, Event)>>,
    counters_recv: Receiver<(usize, Event)>,
}

impl AllocateBuilder for ProcessBuilder {
    type Allocator = Process;
    fn build(self) -> Self::Allocator {
        Process {
            inner: self.inner.build(),
            index: self.index,
            peers: self.peers,
            channels: self.channels,
            counters_send: self.counters_send,
            counters_recv: self.counters_recv,
        }
    }
}

/// An allocator for inter-thread, intra-process communication
pub struct Process {
    inner: Thread,
    index: usize,
    peers: usize,
    // below: `Box<Any+Send>` is a `Box<Vec<Option<(Vec<Sender<T>>, Receiver<T>)>>>`
    channels: Arc<Mutex<HashMap</* channel id */ usize, Box<Any+Send>>>>,
    counters_send: Vec<Sender<(usize, Event)>>,
    counters_recv: Receiver<(usize, Event)>,
}

impl Process {
    /// Access the wrapped inner allocator.
    pub fn inner<'a>(&'a mut self) -> &'a mut Thread { &mut self.inner }
    /// Allocate a list of connected intra-process allocators.
    pub fn new_vector(peers: usize) -> Vec<ProcessBuilder> {

        let mut counters_send = Vec::new();
        let mut counters_recv = Vec::new();
        for _ in 0 .. peers {
            let (send, recv) = channel();
            counters_send.push(send);
            counters_recv.push(recv);
        }

        let channels = Arc::new(Mutex::new(HashMap::new()));

        counters_recv
            .into_iter()
            .enumerate()
            .map(|(index, recv)| {
                ProcessBuilder {
                    inner: ThreadBuilder,
                    index,
                    peers,
                    channels: channels.clone(),
                    counters_send: counters_send.clone(),
                    counters_recv: recv,
                }
            })
            .collect()
    }
}

impl Allocate for Process {
    fn index(&self) -> usize { self.index }
    fn peers(&self) -> usize { self.peers }
    fn allocate<T: Any+Send+Sync+'static>(&mut self, identifier: usize) -> (Vec<Box<Push<Message<T>>>>, Box<Pull<Message<T>>>) {

        // this is race-y global initialisation of all channels for all workers, performed by the
        // first worker that enters this critical section

        // ensure exclusive access to shared list of channels
        let mut channels = self.channels.lock().ok().expect("mutex error?");

        let (sends, recv, empty) = {

            // we may need to alloc a new channel ...
            let mut entry = channels.entry(identifier).or_insert_with(|| {

                let mut pushers = Vec::new();
                let mut pullers = Vec::new();
                for _ in 0..self.peers {

                    let (s, r): (Sender<Message<T>>, Receiver<Message<T>>) = channel();
                    pushers.push(Pusher { target: s });
                    pullers.push(Puller { source: r, current: None });
                }

                let mut to_box = Vec::new();
                for recv in pullers.into_iter() {
                    to_box.push(Some((pushers.clone(), recv)));
                }

                Box::new(to_box)
            });

            let vector =
            entry
                .downcast_mut::<(Vec<Option<(Vec<Pusher<Message<T>>>, Puller<Message<T>>)>>)>()
                .expect("failed to correctly cast channel");

            let (sends, recv) =
            vector[self.index]
                .take()
                .expect("channel already consumed");

            let empty = vector.iter().all(|x| x.is_none());

            (sends, recv, empty)
        };

        // send is a vec of all senders, recv is this worker's receiver

        if empty { channels.remove(&identifier); }

        use allocator::counters::ArcPusher as CountPusher;
        use allocator::counters::Puller as CountPuller;

        let sends =
        sends.into_iter()
             .enumerate()
             .map(|(i,s)| CountPusher::new(s, identifier, self.counters_send[i].clone()))
             .map(|s| Box::new(s) as Box<Push<super::Message<T>>>)
             .collect::<Vec<_>>();

        let recv = Box::new(CountPuller::new(recv, identifier, self.inner.events().clone())) as Box<Pull<super::Message<T>>>;

        (sends, recv)
    }

    fn events(&self) -> &Rc<RefCell<VecDeque<(usize, Event)>>> {
        self.inner.events()
    }

    fn receive(&mut self) {
        let mut events = self.inner.events().borrow_mut();
        while let Ok((index, event)) = self.counters_recv.try_recv() {
            events.push_back((index, event));
        }
    }
}

/// The push half of an intra-process channel.
struct Pusher<T> {
    target: Sender<T>,
}

impl<T> Clone for Pusher<T> {
    fn clone(&self) -> Self {
        Pusher { target: self.target.clone() }
    }
}

impl<T> Push<T> for Pusher<T> {
    #[inline] fn push(&mut self, element: &mut Option<T>) {
        if let Some(element) = element.take() {
            self.target.send(element).unwrap();
        }
    }
}

/// The pull half of an intra-process channel.
struct Puller<T> {
    current: Option<T>,
    source: Receiver<T>,
}

impl<T> Pull<T> for Puller<T> {
    #[inline]
    fn pull(&mut self) -> &mut Option<T> {
        self.current = self.source.try_recv().ok();
        &mut self.current
    }
}
<|endoftext|>


<commit_before>pub mod array_matrix;

/// A macro that takes a struct-like definition that takes an array type and (row, column)
/// size arguments and implements the required methods.
///
/// Usage:
/// #impl_matrix!{
/// #    struct MyMatrix([f32; (3, 3)]);
/// #};
///
/// #let mut matrix =  MyMatrix([0.0; 9]);
/// #matrix[(2,1)] = 8.1;
/// #println!("{:?}", matrix);
/// #println!("{}", m.row());
///
/// The matrix methods are based on the [`generic_matrix`] crate which uses an internal Vec<T> to
/// hold data.
///
/// [`generic_matrix`]: http://gifnksm.github.io/generic-matrix-rs/generic_matrix/index.html
#[macro_export]
macro_rules! impl_matrix {
    ($st:ident([$t:ty; ($row:expr, $col:expr)])) => {
        use array_matrix::ArrayMatrix;
        use std::ops::{Index, IndexMut};

        #[derive(Debug)]
        struct $st([$t; $row * $col]);

        impl ArrayMatrix for $st {
            fn row(&self) -> usize {
                $row
            }

            fn column(&self) -> usize {
                $col
            }

            fn size(&self) -> (usize, usize) {
                (self.row(), self.column())
            }
        }

        impl Index<(usize, usize)> for $st {
            type Output = $t;

            #[inline]
            fn index(&self, (i, j): (usize, usize)) -> &$t {
                assert!(i < $row && j < $col);
                &self.0[i * $col + j]
            }
        }

        impl IndexMut<(usize, usize)> for $st {

            #[inline]
            fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut $t {
                assert!(i < $row && j < $col);
                &mut self.0[i * $col + j]
            }
        }
    }
}

#[macro_use]
#[cfg(test)]
mod tests {

    #[test]
    fn test_impl_matrix() {
        const ROW: usize = 3;
        const COLUMN: usize = 3;

        impl_matrix!(TestMatrix([i32; (ROW, COLUMN)]));

        let mut m = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);

        println!("{:?}", m);

        assert_eq!(m[(1, 2)], 6);
        m[(1, 2)] = 30;
        assert_eq!(m[(1, 2)], 30);
        assert_eq!(m.row(), ROW);
        assert_eq!(m.column(), COLUMN);
    }
}
<commit_msg>Update module for crate usage.<commit_after>pub use array_matrix::ArrayMatrix;
pub mod array_matrix;

/// A macro that takes a struct-like definition that takes an array type and (row, column)
/// size arguments and implements the required methods.
///
/// Usage:
/// #impl_matrix!{
/// #    struct MyMatrix([f32; (3, 3)]);
/// #};
///
/// #let mut matrix =  MyMatrix([0.0; 9]);
/// #matrix[(2,1)] = 8.1;
/// #println!("{:?}", matrix);
/// #println!("{}", m.row());
///
/// The matrix methods are based on the [`generic_matrix`] crate which uses an internal Vec<T> to
/// hold data.
///
/// [`generic_matrix`]: http://gifnksm.github.io/generic-matrix-rs/generic_matrix/index.html
#[macro_export]
macro_rules! impl_matrix {
    ($st:ident([$t:ty; ($row:expr, $col:expr)])) => {
        use array_matrix::ArrayMatrix;
        use std::ops::{Index, IndexMut};

        #[derive(Debug)]
        struct $st([$t; $row * $col]);

        impl ArrayMatrix for $st {
            fn row(&self) -> usize {
                $row
            }

            fn column(&self) -> usize {
                $col
            }

            fn size(&self) -> (usize, usize) {
                (self.row(), self.column())
            }
        }

        impl Index<(usize, usize)> for $st {
            type Output = $t;

            #[inline]
            fn index(&self, (i, j): (usize, usize)) -> &$t {
                assert!(i < $row && j < $col);
                &self.0[i * $col + j]
            }
        }

        impl IndexMut<(usize, usize)> for $st {

            #[inline]
            fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut $t {
                assert!(i < $row && j < $col);
                &mut self.0[i * $col + j]
            }
        }
    }
}

#[macro_use]
#[cfg(test)]
mod tests {

    #[test]
    fn test_impl_matrix() {
        const ROW: usize = 3;
        const COLUMN: usize = 3;

        impl_matrix!(TestMatrix([i32; (ROW, COLUMN)]));

        let mut m = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);

        println!("{:?}", m);

        assert_eq!(m[(1, 2)], 6);
        m[(1, 2)] = 30;
        assert_eq!(m[(1, 2)], 30);
        assert_eq!(m.row(), ROW);
        assert_eq!(m.column(), COLUMN);
    }
}
<|endoftext|>