<commit_before>extern crate gtk;

mod glade;
mod handlers;
mod ui_state;

use std::cell::{RefCell};
use gtk::prelude::*;
use gtk::{Window, WindowType};
use gtk::{Button, FileChooserDialog, Entry};
use std::sync::mpsc::{Sender, Receiver};
use std::sync::{Arc,Mutex};
use std::rc::Rc;
use std::clone::Clone;
use std::thread;

use castnow::{KeyCommand, Command};
use state::State;
use self::glade::GladeObjectFactory;
use self::ui_state::{UiState, Channel};

lazy_static! {
    static ref UI_STATE: Mutex<UiState> = Mutex::new(UiState::new());
}

pub struct AppModel {
    status: String,
    playing: bool
}

pub struct AppState {
    channels: RefCell<AppChannels>,
    widgets: RefCell<AppWidgets>,
    model: RefCell<AppModel>
}

impl AppModel {
    fn new() -> AppModel {
        AppModel {
            status: "Ready".to_string(),
            playing: false
        }
    }
}

impl AppState {
    pub fn new_rc() -> Rc<AppState> {
        Rc::new(AppState{
            channels: RefCell::new(AppChannels::new()),
            widgets: RefCell::new(AppWidgets::new()),
            model: RefCell::new(AppModel::new())
        })
    }

    pub fn init(&self, self_rc: Rc<Self>, rx: Receiver<State>, tx: Sender<Command>) {

        let mut channels = self.channels.borrow_mut();
        channels.rx = Some(rx);
        channels.tx = Some(tx);

        self.build_widgets();
        self.attach_handlers(&self_rc);
        self.start_rendering_timer(&self_rc);
    }

    fn attach_handlers(&self, self_rc: &Rc<Self>) {
        let widgets = self.widgets.borrow_mut();
        if let Some(ref load_button) = widgets.load_button {
            let self_clone = self_rc.clone();
            load_button.connect_clicked(move |_| handlers::load_clicked(&self_clone));
        }
        if let Some(ref stop_button) = widgets.stop_button {
            let self_clone = self_rc.clone();
            stop_button.connect_clicked(move |_| handlers::load_clicked(&self_clone));
        }
    }

    fn build_widgets(&self) {
        let mut widgets = self.widgets.borrow_mut();
        let factory = GladeObjectFactory::new();

        widgets.file_path_entry = Some(factory.get("filePathEntry1"));
        widgets.load_button = Some(factory.get("playButton"));
        widgets.state_label = Some(factory.get("stateLabel"));
    }

    fn render_dirty(&self) {
        let widgets = self.widgets.borrow_mut();
        let model = self.model.borrow();
        //if flag is dirty
        if let Some(ref state_label) = widgets.state_label {
            state_label.set_text(model.status.as_str());
        }
    }

    fn start_rendering_timer(&self, self_rc: &Rc<Self>) {
        let self_clone = self_rc.clone();
        gtk::timeout_add(100, move || {
            //Render anything in the render queue
            if let Some(ref rx) = self_clone.channels.borrow().rx {
                while let Ok(state) = rx.try_recv() {
                    println!("Received state in ui updater thread {:?}", state);
                    //let's assume we also got some name/value pairs with enough info to locate our widget and render it

                    self_clone.render_dirty();
                }
            }
            //So this will get invoked on every timeout interval, but the main thread does that anyway by
            //invoking idle
            Continue(true)
        });
    }
}

pub struct AppChannels {
    pub rx: Option<Receiver<State>>,
    pub tx: Option<Sender<Command>>
}

impl AppChannels {
    fn new() -> AppChannels {
        AppChannels {
            rx: None,
            tx: None
        }
    }
}

#[derive(Clone)]
pub struct AppWidgets {
    app:                    Option<gtk::Application>,
    win:                    Option<gtk::ApplicationWindow>,
    file_path_entry:        Option<gtk::Entry>,
    load_button:            Option<gtk::Button>,
    stop_button:            Option<gtk::Button>,
    //load_button_dirty:    bool,
    state_label:            Option<gtk::Entry>
}

impl AppWidgets {
    pub fn new() -> AppWidgets {
        AppWidgets {
            app: None,
            win: None,
            file_path_entry: None,
            load_button: None,
            stop_button: None,
            state_label: None
        }
    }
}

// fn current_state() -> State {
//     match UI_STATE.lock() {
//         Ok(inner) => inner.state,
//         Err(e) => {
//             println!("Couldn't acquire UI_STATE lock {:?}", e);
//             State::Error
//         }
//     }
// }

// fn start_rendering_timer(rx: Rc<Receiver<State>>) {
//     gtk::timeout_add(100, move || {
//         //Render anything in the render queue
//         while let Ok(state) = rx.try_recv() {
//             println!("Received state in ui updater thread {:?}", state);
//             //let's assume we also got some name/value pairs with enough info to locate our widget and render it
//             UI_STATE.lock().unwrap().state = state;
//             render_dirty();
//         }
//         //So this will get invoked on every timeout interval, but the main thread does that anyway by
//         //invoking idle
//         Continue(true)
//     });
// }

// fn render_dirty(/* all the widgets */) {
//     let ui_state = UI_STATE.lock().unwrap();
//     //widget.txt = ui_state.status

//     let factory = GladeObjectFactory::new();
//     let state_label = factory.get::<gtk::Label>("stateLabel");
//     println!("setting text on state_label={:?}", " some new text");
//     state_label.set_text(" some new text");
// }

// fn render(state_label: &gtk::Label, state_arg: State) {
//     state_label.set_text(format!("{}", state_arg).as_str());
// }

// pub fn build(tx: Sender<Command>, rx: Receiver<State>) {

//     let factory = GladeObjectFactory::new();

//     let file_path_entry: Entry = factory.get("filePathEntry1");
//     let state_label = factory.get::<gtk::Label>("stateLabel");
//     //let state_labelx = Arc::new(state_label.clone());

//     //alternative is a thred blockign on recv(), then calling
//     //handle - gtk::idle_add (if possible in that thread)
//     //then idle_remove_by_data(handle) so there is no polling at all

//     let shared_tx = Rc::new(tx);
//     let shared_rx = Rc::new(rx);

//     start_rendering_timer(shared_rx.clone());

//     // Create Window
//     let window : gtk::Window = factory.get("applicationwindow1");
//     window.set_title("castnow desktop-rs");
//     window.connect_delete_event(|_, _| {
//         gtk::main_quit();
//         Inhibit(false)
//     });

//     let file_chooser_button: Button = factory.get("popupFileChooserButton");
//     let file_path_entry: Entry = factory.get("filePathEntry1");
//     let (load_button, load_button_tx) = get_obj::<Button>(&factory, "playButton", shared_tx.clone());
//     let (mute_button, mute_button_tx) = get_obj::<Button>(&factory, "muteButton", shared_tx.clone());
//     let (stop_button, stop_button_tx) = get_obj::<Button>(&factory, "stopButton", shared_tx.clone());

//     let open_menu_item = factory.get::<gtk::MenuItem>("openMenuItem");

//     let state_label = factory.get::<gtk::Label>("stateLabel");
//     render(&state_label, current_state());

//     let file_path_entry1 = file_path_entry.clone();
//     open_menu_item.connect_activate(move |_| popup_file_chooser(&file_path_entry1));

//     //aboutdialog1

//     let file_path_entry2 = file_path_entry.clone();
//     file_chooser_button.connect_clicked(move |_| popup_file_chooser(&file_path_entry2));

//     let state_label2 = state_label.clone();
//     load_button.connect_clicked(move |_| {
//         let path = file_path_entry.get_text();
//         send(&load_button_tx, KeyCommand::Load, path);
//         let new_state = UI_STATE.lock().unwrap().transition_to(KeyCommand::Load);
//         render(&state_label2, new_state);
//     });

//     mute_button.connect_clicked(move |_| send(&mute_button_tx, KeyCommand::Mute, None));
//     let state_label1 = state_label.clone();
//     stop_button.connect_clicked(move |_| {
//         send(&stop_button_tx, KeyCommand::Stop, None);
//         UI_STATE.lock().unwrap().transition_to(KeyCommand::Stop);
//         render(&state_label1, current_state());
//     });

//     window.show_all();
// }

// fn popup_file_chooser(file_path_entry: &Entry) {
//     let dialog = build_file_chooser();
//     if dialog.run() == gtk::ResponseType::Ok.into() {
//         dialog.get_filename().map(|path| path.to_str().map(|text| file_path_entry.set_text(text)));
//     }
//     dialog.destroy();
// }

// fn build_file_chooser() -> gtk::FileChooserDialog {
//     let dialog = FileChooserDialog::new (
//                 Some("Choose DireFilectory"),
//                 Some(&Window::new(WindowType::Popup)),
//                 gtk::FileChooserAction::Open,
//     );
//     dialog.add_button("Cancel", gtk::ResponseType::Cancel.into());
//     dialog.add_button("Select", gtk::ResponseType::Ok.into());
//     dialog
// }

// fn send(tx: &Sender<Command>, key: KeyCommand, state_arg: Option<String>) {
//     let cmd = Command::new_with_state(key, state_arg.unwrap_or_default());
//     tx.send(cmd).map_err(|e| println!("Failed to send {:?}", e)).ok();
// }

// fn get_obj<T: gtk::IsA<gtk::Object>>(factory: &GladeObjectFactory, name: &'static str, tx: Rc<Sender<Command>>) -> (T, Rc<Sender<Command>>) {
//     return (factory.get(name), tx);
// }
<commit_msg>borrow_mut panic fixes. Showing windows.<commit_after>extern crate gtk;

mod glade;
mod handlers;
mod ui_state;

use std::cell::{RefCell};
use gtk::prelude::*;
use gtk::{Window, WindowType};
use gtk::{Button, FileChooserDialog, Entry};
use std::sync::mpsc::{Sender, Receiver};
use std::sync::{Arc,Mutex};
use std::rc::Rc;
use std::clone::Clone;
use std::thread;

use castnow::{KeyCommand, Command};
use state::State;
use self::glade::GladeObjectFactory;
use self::ui_state::{UiState, Channel};

lazy_static! {
    static ref UI_STATE: Mutex<UiState> = Mutex::new(UiState::new());
}

pub struct AppModel {
    status: String,
    playing: bool
}

pub struct AppState {
    channels: RefCell<AppChannels>,
    widgets: RefCell<AppWidgets>,
    model: RefCell<AppModel>
}

impl AppModel {
    fn new() -> AppModel {
        AppModel {
            status: "Ready".to_string(),
            playing: false
        }
    }
}

impl AppState {
    pub fn new_rc() -> Rc<AppState> {
        Rc::new(AppState{
            channels: RefCell::new(AppChannels::new()),
            widgets: RefCell::new(AppWidgets::new()),
            model: RefCell::new(AppModel::new())
        })
    }

    pub fn init(&self, self_rc: Rc<Self>, rx: Receiver<State>, tx: Sender<Command>) {
        let mut channels = self_rc.channels.borrow_mut();
        channels.rx = Some(rx);
        channels.tx = Some(tx);

        self.build_widgets();
        self.attach_handlers(&self_rc);
        self.start_rendering_timer(&self_rc);
    }

    fn attach_handlers(&self, self_rc: &Rc<Self>) {
        let widgets = self.widgets.borrow();
        if let Some(ref load_button) = widgets.load_button {
            let self_clone = self_rc.clone();
            load_button.connect_clicked(move |_| handlers::load_clicked(&self_clone));
        }
        if let Some(ref stop_button) = widgets.stop_button {
            let self_clone = self_rc.clone();
            stop_button.connect_clicked(move |_| handlers::load_clicked(&self_clone));
        }

        if let Some(ref window) = widgets.win {
            window.connect_delete_event(|_, _| {
                gtk::main_quit();
                Inhibit(false)
            });
            window.show_all();
        }
    }

    fn build_widgets(&self) {
        let mut widgets = self.widgets.borrow_mut();
        let factory = GladeObjectFactory::new();

        widgets.win = Some(factory.get("applicationwindow1"));
        //window.set_title("castnow desktop-rs");
        widgets.file_path_entry = Some(factory.get("filePathEntry1"));
        widgets.load_button = Some(factory.get("playButton"));
        widgets.state_label = Some(factory.get("stateLabel"));
    }

    fn render_dirty(&self) {
        let widgets = self.widgets.borrow();
        let model = self.model.borrow();
        //if flag is dirty
        if let Some(ref state_label) = widgets.state_label {
            state_label.set_text(model.status.as_str());
        }
    }

    fn start_rendering_timer(&self, self_rc: &Rc<Self>) {
        let self_clone = self_rc.clone();
        gtk::timeout_add(100, move || {
            //Render anything in the render queue
            if let Some(ref rx) = self_clone.channels.borrow().rx {
                while let Ok(state) = rx.try_recv() {
                    println!("Received state in ui updater thread {:?}", state);
                    //let's assume we also got some name/value pairs with enough info to locate our widget and render it

                    //Modifying the model and updating it must be separate scopes
                    {
                        let mut model = self_clone.model.borrow_mut();
                        model.status = format!("{}", state);
                    }

                    self_clone.render_dirty();
                }
            }
            //So this will get invoked on every timeout interval, but the main thread does that anyway by
            //invoking idle
            Continue(true)
        });
    }
}

pub struct AppChannels {
    pub rx: Option<Receiver<State>>,
    pub tx: Option<Sender<Command>>
}

impl AppChannels {
    fn new() -> AppChannels {
        AppChannels {
            rx: None,
            tx: None
        }
    }
}

#[derive(Clone)]
pub struct AppWidgets {
    app:                    Option<gtk::Application>,
    win:                    Option<gtk::Window>,
    file_path_entry:        Option<gtk::Entry>,
    load_button:            Option<gtk::Button>,
    stop_button:            Option<gtk::Button>,
    //load_button_dirty:    bool,
    state_label:            Option<gtk::Label>
}

impl AppWidgets {
    pub fn new() -> AppWidgets {
        AppWidgets {
            app: None,
            win: None,
            file_path_entry: None,
            load_button: None,
            stop_button: None,
            state_label: None
        }
    }
}

// fn current_state() -> State {
//     match UI_STATE.lock() {
//         Ok(inner) => inner.state,
//         Err(e) => {
//             println!("Couldn't acquire UI_STATE lock {:?}", e);
//             State::Error
//         }
//     }
// }

// fn start_rendering_timer(rx: Rc<Receiver<State>>) {
//     gtk::timeout_add(100, move || {
//         //Render anything in the render queue
//         while let Ok(state) = rx.try_recv() {
//             println!("Received state in ui updater thread {:?}", state);
//             //let's assume we also got some name/value pairs with enough info to locate our widget and render it
//             UI_STATE.lock().unwrap().state = state;
//             render_dirty();
//         }
//         //So this will get invoked on every timeout interval, but the main thread does that anyway by
//         //invoking idle
//         Continue(true)
//     });
// }

// fn render_dirty(/* all the widgets */) {
//     let ui_state = UI_STATE.lock().unwrap();
//     //widget.txt = ui_state.status

//     let factory = GladeObjectFactory::new();
//     let state_label = factory.get::<gtk::Label>("stateLabel");
//     println!("setting text on state_label={:?}", " some new text");
//     state_label.set_text(" some new text");
// }

// fn render(state_label: &gtk::Label, state_arg: State) {
//     state_label.set_text(format!("{}", state_arg).as_str());
// }

// pub fn build(tx: Sender<Command>, rx: Receiver<State>) {

//     let factory = GladeObjectFactory::new();

//     let file_path_entry: Entry = factory.get("filePathEntry1");
//     let state_label = factory.get::<gtk::Label>("stateLabel");
//     //let state_labelx = Arc::new(state_label.clone());

//     //alternative is a thred blockign on recv(), then calling
//     //handle - gtk::idle_add (if possible in that thread)
//     //then idle_remove_by_data(handle) so there is no polling at all

//     let shared_tx = Rc::new(tx);
//     let shared_rx = Rc::new(rx);

//     start_rendering_timer(shared_rx.clone());

//     // Create Window
//     let window : gtk::Window = factory.get("applicationwindow1");
//     window.set_title("castnow desktop-rs");
//     window.connect_delete_event(|_, _| {
//         gtk::main_quit();
//         Inhibit(false)
//     });

//     let file_chooser_button: Button = factory.get("popupFileChooserButton");
//     let file_path_entry: Entry = factory.get("filePathEntry1");
//     let (load_button, load_button_tx) = get_obj::<Button>(&factory, "playButton", shared_tx.clone());
//     let (mute_button, mute_button_tx) = get_obj::<Button>(&factory, "muteButton", shared_tx.clone());
//     let (stop_button, stop_button_tx) = get_obj::<Button>(&factory, "stopButton", shared_tx.clone());

//     let open_menu_item = factory.get::<gtk::MenuItem>("openMenuItem");

//     let state_label = factory.get::<gtk::Label>("stateLabel");
//     render(&state_label, current_state());

//     let file_path_entry1 = file_path_entry.clone();
//     open_menu_item.connect_activate(move |_| popup_file_chooser(&file_path_entry1));

//     //aboutdialog1

//     let file_path_entry2 = file_path_entry.clone();
//     file_chooser_button.connect_clicked(move |_| popup_file_chooser(&file_path_entry2));

//     let state_label2 = state_label.clone();
//     load_button.connect_clicked(move |_| {
//         let path = file_path_entry.get_text();
//         send(&load_button_tx, KeyCommand::Load, path);
//         let new_state = UI_STATE.lock().unwrap().transition_to(KeyCommand::Load);
//         render(&state_label2, new_state);
//     });

//     mute_button.connect_clicked(move |_| send(&mute_button_tx, KeyCommand::Mute, None));
//     let state_label1 = state_label.clone();
//     stop_button.connect_clicked(move |_| {
//         send(&stop_button_tx, KeyCommand::Stop, None);
//         UI_STATE.lock().unwrap().transition_to(KeyCommand::Stop);
//         render(&state_label1, current_state());
//     });

//     window.show_all();
// }

// fn popup_file_chooser(file_path_entry: &Entry) {
//     let dialog = build_file_chooser();
//     if dialog.run() == gtk::ResponseType::Ok.into() {
//         dialog.get_filename().map(|path| path.to_str().map(|text| file_path_entry.set_text(text)));
//     }
//     dialog.destroy();
// }

// fn build_file_chooser() -> gtk::FileChooserDialog {
//     let dialog = FileChooserDialog::new (
//                 Some("Choose DireFilectory"),
//                 Some(&Window::new(WindowType::Popup)),
//                 gtk::FileChooserAction::Open,
//     );
//     dialog.add_button("Cancel", gtk::ResponseType::Cancel.into());
//     dialog.add_button("Select", gtk::ResponseType::Ok.into());
//     dialog
// }

// fn send(tx: &Sender<Command>, key: KeyCommand, state_arg: Option<String>) {
//     let cmd = Command::new_with_state(key, state_arg.unwrap_or_default());
//     tx.send(cmd).map_err(|e| println!("Failed to send {:?}", e)).ok();
// }

// fn get_obj<T: gtk::IsA<gtk::Object>>(factory: &GladeObjectFactory, name: &'static str, tx: Rc<Sender<Command>>) -> (T, Rc<Sender<Command>>) {
//     return (factory.get(name), tx);
// }
<|endoftext|>


<commit_before>//! Generate update information from dependency information.
<commit_msg>Added `Bump, Dependency, Package` to `dependencies`<commit_after>//! Generate update information from dependency information.

use std::rc::Rc;

use semver::Version;

/// Stores old and new version.
pub struct Bump {
    /// The old version.
    pub old: Version,
    /// The new version.
    pub new: Version,
}

/// Stores update info for dependency.
pub struct Dependency {
    /// The library name.
    pub name: Rc<String>,
    /// Bump info.
    pub bump: Bump,
}

/// Stores information about a package.
pub struct Package {
    /// The package name.
    pub name: Rc<String>,
    /// The order to update library.
    pub order: u32,
    /// Update information.
    pub bump: Bump,
    /// The dependencies.
    pub dependencies: Vec<Dependency>,
}
<|endoftext|>


<commit_before>use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Index};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl MulAssign for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

impl Index<i32> for Vec3 {
  type Output = f64;
  fn index(&self, idx: i32) -> &f64 {
    match idx {
      0 => &self.i,
      1 => &self.j,
      2 => &self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
  #[test]
  fn multiply_elementwise() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let product = v1 * v2;
    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_assign_elementwise() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 *= v2;
    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
  #[test]
  fn allow_index_access() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[0], 2.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
  #[test]
  #[should_panic(expected = "index out of range: 9")]
  fn panic_on_bad_index() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[9], 2.0);
  }
}<commit_msg>Add indexMut impl and test<commit_after>use std::ops::{
  Add, AddAssign,
  Sub, SubAssign,
  Mul, MulAssign,
  Index, IndexMut,
};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl MulAssign for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

impl Index<i32> for Vec3 {
  type Output = f64;
  fn index(&self, idx: i32) -> &f64 {
    match idx {
      0 => &self.i,
      1 => &self.j,
      2 => &self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

impl IndexMut<i32> for Vec3 {
  fn index_mut<'a>(&'a mut self, idx: i32) -> &'a mut f64 {
    match idx {
      0 => &mut self.i,
      1 => &mut self.j,
      2 => &mut self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
  #[test]
  fn multiply_elementwise() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let product = v1 * v2;
    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_assign_elementwise() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 *= v2;
    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
  #[test]
  fn allow_index_access() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[0], 2.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
  #[test]
  #[should_panic(expected = "index out of range: 9")]
  fn panic_on_bad_index() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[9], 2.0);
  }
  #[test]
  fn allow_index_mut_access() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1[0] = 9.0;

    assert_eq!(v1[0], 9.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
}<|endoftext|>


<commit_before>/// User facing module of this library.
///
/// Fetching message from multiple (topic, partition) pair or producing messages to multiple
/// topics is not yet supported.
/// It should be added very soon.

use error::{Result, Error};
use utils;
use protocol;
use connection::KafkaConnection;
use codecs::{ToByte, FromByte};
use std::collections::HashMap;
use std::io::Cursor;
use std::io::Read;

const CLIENTID: &'static str = "kafka-rust";
const DEFAULT_TIMEOUT: i32 = 120; // seconds

/// Client struct. It keeps track of brokers and topic metadata
///
/// # Examples
///
/// ```
/// let mut client = KafkaClient::new(&vec!("localhost:9092".to_string()));
/// let res = client.load_metadata_all();
/// ```
///
/// You will have to load metadata before making any other request.
#[derive(Default, Debug)]
pub struct KafkaClient {
    clientid: String,
    timeout: i32,
    hosts: Vec<String>,
    correlation: i32,
    conns: HashMap<String, KafkaConnection>,
    pub topic_partitions: HashMap<String, Vec<i32>>,
    topic_brokers: HashMap<String, String>
}

impl KafkaClient {
    /// Create a new instance of KafkaClient
    ///
    /// # Examples
    ///
    /// ```
    /// let mut client = KafkaClient::new(&vec!("localhost:9092".to_string()));
    /// ```
    pub fn new(hosts: &Vec<String>) -> KafkaClient {
        KafkaClient { hosts: hosts.to_vec(), clientid: CLIENTID.to_string(),
                      timeout: DEFAULT_TIMEOUT, ..KafkaClient::default()}
    }

    fn get_conn(& mut self, host: &str) -> Result<KafkaConnection> {
        match self.conns.get(host) {
            Some (conn) => return conn.clone(),
            None => {}
        }
        // TODO
        // Keeping this out here since get is causing ownership issues
        // Will refactor once I know better
        self.conns.insert(host.to_string(),
                          try!(KafkaConnection::new(host, self.timeout)));
        self.get_conn(host)
    }

    fn next_id(&mut self) -> i32{
        self.correlation = (self.correlation + 1) % (1i32 << 30);
        self.correlation
    }

    /// Resets and loads metadata for all topics.
    pub fn load_metadata_all(&mut self) -> Result<()>{
        self.reset_metadata();
        self.load_metadata(&vec!())
    }

    /// Reloads metadata for a list of supplied topics
    ///
    /// returns Result<(), error::Error>
    pub fn load_metadata (&mut self, topics: &Vec<String>) -> Result<()>{
        let resp = try!(self.get_metadata(topics));

        let mut brokers: HashMap<i32, String> = HashMap::new();
        for broker in resp.brokers {
            brokers.insert(broker.nodeid, format!("{}:{}", broker.host, broker.port));
        }

        self.topic_brokers.clear();
        for topic in resp.topics {
            self.topic_partitions.insert(topic.topic.clone(), vec!());

            for partition in topic.partitions {
                match brokers.get(&partition.leader) {
                    Some(broker) => {
                        self.topic_partitions.get_mut(&topic.topic).unwrap().push(partition.id);
                        self.topic_brokers.insert(
                            format!("{}-{}", topic.topic, partition.id),
                            broker.clone());
                    },
                    None => {}
                }
            }
        }
        Ok(())
    }

    /// Clears metadata stored in the client. You must load metadata after this call if you want
    /// to use the client
    pub fn reset_metadata(&mut self) {
        self.topic_partitions.clear();
        self.topic_brokers.clear();
    }

    fn get_metadata(&mut self, topics: &Vec<String>) -> Result<protocol::MetadataResponse> {
        let correlation = self.next_id();
        for host in self.hosts.to_vec() {
            let req = protocol::MetadataRequest::new(correlation, &self.clientid, topics);
            match self.get_conn(&host) {
                Ok(mut conn) => if self.send_request(&mut conn, req).is_ok() {
                    return self.get_response::<protocol::MetadataResponse>(&mut conn);
                },
                Err(_) => {}
            }
        }

        Err(Error::NoHostReachable)
    }

    /// Fetch offsets for a list of topics
    /// Not implemented as yet.
    pub fn fetch_offsets(&mut self, _topics: &Vec<String>) {
        // TODO - Implement method to fetch offsets for more than 1 topic

    }

    /// Fetch offset for a topic.
    /// It gets the latest offset only. Support for getting earliest will be added soon
    ///
    /// # Examples
    ///
    /// ```
    /// let mut client = KafkaClient::new(&vec!("localhost:9092".to_string()));
    /// let res = client.load_metadata_all();
    /// let offsets = client.fetch_topic_offset(&"my-topic".to_string());
    /// ```
    /// Returns a vector of (topic, partition offset data).
    /// PartitionOffset will contain parition and offset info Or Error code as returned by Kafka.
    pub fn fetch_topic_offset(&mut self, topic: &String) -> Result<Vec<(String, Vec<utils::PartitionOffset>)>> {
        // Doing it like this because HashMap will not return borrow of self otherwise
        let partitions = self.topic_partitions
                             .get(topic)
                             .unwrap_or(&vec!())
                             .clone();

        // Maybe TODO: Can this be simplified without complexifying?
        let mut brokers: HashMap<String, Vec<i32>> = HashMap:: new();
        for p in partitions {
            let key = format!("{}-{}", topic, p);
            match self.topic_brokers.get(&key) {
                Some(broker) => {
                    if !brokers.contains_key(broker) {brokers.insert(broker.clone(), Vec::new());}
                    brokers.get_mut(broker).unwrap().push(p);
                },
                None => {}
            }
        }

        let mut res: Vec<utils::PartitionOffset> = vec!();
        for (host, partitions) in brokers.iter() {
            let v = vec!(utils::TopicPartitions{
                topic: topic.clone(),
                partitions: partitions.to_vec()
                });
            for tpo in try!(self.fetch_offset(&v, host)) {
                res.push(utils::PartitionOffset{partition: tpo.partition, offset: tpo.offset});
            }
        }
        Ok(vec!((topic.clone(), res)))
    }

    fn fetch_offset(&mut self, topic_partitions: &Vec<utils::TopicPartitions>, host: &String)
                            -> Result<Vec<utils::TopicPartitionOffset>> {
        let correlation = self.next_id();
        let req = protocol::OffsetRequest::new_latest(topic_partitions, correlation, &self.clientid);

        let resp = try!(self.send_receive::<protocol::OffsetRequest, protocol::OffsetResponse>(&host, req));

        Ok(resp.get_offsets())

    }

    fn get_broker(&mut self, topic: &String, partition: i32) -> Option<String> {
        let key = format!("{}-{}", topic, partition);
        match self.topic_brokers.get(&key) {
            Some(broker) => {
                Some(broker.clone())
            },
            None => None
        }
    }

    /// Fetch messages from Kafka
    ///
    /// It takes a single topic, parition and offset and return a vector of messages
    /// or error::Error
    /// You can figure out the appropriate partition and offset using client's
    /// client.topic_partitions and client.fetch_topic_offset(topic)
    ///
    /// # Examples
    ///
    /// ```
    /// let mut client = KafkaClient::new(&vec!("localhost:9092".to_string()));
    /// let res = client.load_metadata_all();
    /// let msgs = client.fetch_messages(&"my-topic".to_string(), 0, 0);
    /// ```
    pub fn fetch_messages(&mut self, topic: &String, partition: i32, offset: i64) -> Result<Vec<utils::OffsetMessage>>{

        let host = self.get_broker(topic, partition).unwrap();

        let correlation = self.next_id();
        let req = protocol::FetchRequest::new_single(topic, partition, offset, correlation, &self.clientid);

        let resp = try!(self.send_receive::<protocol::FetchRequest, protocol::FetchResponse>(&host, req));
        Ok(resp.get_messages())
    }

    /// Send a message to Kafka
    ///
    /// You can figure out the appropriate partition and offset using client's
    /// client.topic_partitions and client.fetch_topic_offset(topic)
    ///
    /// `required_acks` - indicates how many acknowledgements the servers should receive before
    /// responding to the request. If it is 0 the server will not send any response
    /// (this is the only case where the server will not reply to a request).
    /// If it is 1, the server will wait the data is written to the local log before sending
    /// a response. If it is -1 the server will block until the message is committed by all
    /// in sync replicas before sending a response. For any number > 1 the server will block
    /// waiting for this number of acknowledgements to occur (but the server will never wait
    /// for more acknowledgements than there are in-sync replicas).
    ///
    /// `timeout` - This provides a maximum time in milliseconds the server can await the
    /// receipt of the number of acknowledgements in `required_acks`
    /// `message` - A single message as a vector of u8s
    ///
    /// # Example
    ///
    /// ```
    /// let mut client = KafkaClient::new(&vec!("localhost:9092".to_string()));
    /// let res = client.load_metadata_all();
    /// let msgs = client.send_message(&"my-topic".to_string(), 0, 1,
    ///                  100, &"b".to_string().into_bytes());
    /// ```
    /// The return value will contain topic, partition, offset and error if any
    /// OR error:Error
    pub fn send_message(&mut self, topic: &String, partition: i32, required_acks: i16,
                      timeout: i32, message: &Vec<u8>) -> Result<Vec<utils::TopicPartitionOffset>> {

        let host = self.get_broker(topic, partition).unwrap();

        let correlation = self.next_id();
        let req = protocol::ProduceRequest::new_single(topic, partition, required_acks,
            timeout, message, correlation, &self.clientid);

        let resp = try!(self.send_receive
            ::<protocol::ProduceRequest, protocol::ProduceResponse>(&host, req));
        Ok(resp.get_response())

    }

    fn send_receive<T: ToByte, V: FromByte>(&mut self, host: &str, req: T) -> Result<V::R> {
        let mut conn = try!(self.get_conn(&host));
        try!(self.send_request(&mut conn, req));
        self.get_response::<V>(&mut conn)
    }

    fn send_request<T: ToByte>(&self, conn: &mut KafkaConnection, request: T) -> Result<usize>{
        let mut buffer = vec!();
        request.encode(&mut buffer);

        let mut s = vec!();
        (buffer.len() as i32).encode(&mut s);
        for byte in buffer.iter() { s.push(*byte); }

        conn.send(&s)
    }

    fn get_response<T: FromByte>(&self, conn:&mut KafkaConnection) -> Result<T::R>{
        let mut v: Vec<u8> = vec!();
        let _ = conn.read(4, &mut v);
        let size = i32::decode_new(&mut Cursor::new(v)).unwrap();

        let mut resp: Vec<u8> = vec!();
        let _ = try!(conn.read(size as u64, &mut resp));

        T::decode_new(&mut Cursor::new(resp))
    }

}
<commit_msg>Pass doc tests<commit_after>/// User facing module of this library.
///
/// Fetching message from multiple (topic, partition) pair or producing messages to multiple
/// topics is not yet supported.
/// It should be added very soon.

use error::{Result, Error};
use utils;
use protocol;
use connection::KafkaConnection;
use codecs::{ToByte, FromByte};
use std::collections::HashMap;
use std::io::Cursor;
use std::io::Read;

const CLIENTID: &'static str = "kafka-rust";
const DEFAULT_TIMEOUT: i32 = 120; // seconds

/// Client struct. It keeps track of brokers and topic metadata
///
/// # Examples
///
/// ```no_run
/// let mut client = kafka::client::KafkaClient::new(&vec!("localhost:9092".to_string()));
/// let res = client.load_metadata_all();
/// ```
///
/// You will have to load metadata before making any other request.
#[derive(Default, Debug)]
pub struct KafkaClient {
    clientid: String,
    timeout: i32,
    hosts: Vec<String>,
    correlation: i32,
    conns: HashMap<String, KafkaConnection>,
    pub topic_partitions: HashMap<String, Vec<i32>>,
    topic_brokers: HashMap<String, String>
}

impl KafkaClient {
    /// Create a new instance of KafkaClient
    ///
    /// # Examples
    ///
    /// ```no_run
    /// let mut client = kafka::client::KafkaClient::new(&vec!("localhost:9092".to_string()));
    /// ```
    pub fn new(hosts: &Vec<String>) -> KafkaClient {
        KafkaClient { hosts: hosts.to_vec(), clientid: CLIENTID.to_string(),
                      timeout: DEFAULT_TIMEOUT, ..KafkaClient::default()}
    }

    fn get_conn(& mut self, host: &str) -> Result<KafkaConnection> {
        match self.conns.get(host) {
            Some (conn) => return conn.clone(),
            None => {}
        }
        // TODO
        // Keeping this out here since get is causing ownership issues
        // Will refactor once I know better
        self.conns.insert(host.to_string(),
                          try!(KafkaConnection::new(host, self.timeout)));
        self.get_conn(host)
    }

    fn next_id(&mut self) -> i32{
        self.correlation = (self.correlation + 1) % (1i32 << 30);
        self.correlation
    }

    /// Resets and loads metadata for all topics.
    pub fn load_metadata_all(&mut self) -> Result<()>{
        self.reset_metadata();
        self.load_metadata(&vec!())
    }

    /// Reloads metadata for a list of supplied topics
    ///
    /// returns Result<(), error::Error>
    pub fn load_metadata (&mut self, topics: &Vec<String>) -> Result<()>{
        let resp = try!(self.get_metadata(topics));

        let mut brokers: HashMap<i32, String> = HashMap::new();
        for broker in resp.brokers {
            brokers.insert(broker.nodeid, format!("{}:{}", broker.host, broker.port));
        }

        self.topic_brokers.clear();
        for topic in resp.topics {
            self.topic_partitions.insert(topic.topic.clone(), vec!());

            for partition in topic.partitions {
                match brokers.get(&partition.leader) {
                    Some(broker) => {
                        self.topic_partitions.get_mut(&topic.topic).unwrap().push(partition.id);
                        self.topic_brokers.insert(
                            format!("{}-{}", topic.topic, partition.id),
                            broker.clone());
                    },
                    None => {}
                }
            }
        }
        Ok(())
    }

    /// Clears metadata stored in the client. You must load metadata after this call if you want
    /// to use the client
    pub fn reset_metadata(&mut self) {
        self.topic_partitions.clear();
        self.topic_brokers.clear();
    }

    fn get_metadata(&mut self, topics: &Vec<String>) -> Result<protocol::MetadataResponse> {
        let correlation = self.next_id();
        for host in self.hosts.to_vec() {
            let req = protocol::MetadataRequest::new(correlation, &self.clientid, topics);
            match self.get_conn(&host) {
                Ok(mut conn) => if self.send_request(&mut conn, req).is_ok() {
                    return self.get_response::<protocol::MetadataResponse>(&mut conn);
                },
                Err(_) => {}
            }
        }

        Err(Error::NoHostReachable)
    }

    /// Fetch offsets for a list of topics
    /// Not implemented as yet.
    pub fn fetch_offsets(&mut self, _topics: &Vec<String>) {
        // TODO - Implement method to fetch offsets for more than 1 topic

    }

    /// Fetch offset for a topic.
    /// It gets the latest offset only. Support for getting earliest will be added soon
    ///
    /// # Examples
    ///
    /// ```no_run
    /// let mut client = kafka::client::KafkaClient::new(&vec!("localhost:9092".to_string()));
    /// let res = client.load_metadata_all();
    /// let offsets = client.fetch_topic_offset(&"my-topic".to_string());
    /// ```
    /// Returns a vector of (topic, partition offset data).
    /// PartitionOffset will contain parition and offset info Or Error code as returned by Kafka.
    pub fn fetch_topic_offset(&mut self, topic: &String) -> Result<Vec<(String, Vec<utils::PartitionOffset>)>> {
        // Doing it like this because HashMap will not return borrow of self otherwise
        let partitions = self.topic_partitions
                             .get(topic)
                             .unwrap_or(&vec!())
                             .clone();

        // Maybe TODO: Can this be simplified without complexifying?
        let mut brokers: HashMap<String, Vec<i32>> = HashMap:: new();
        for p in partitions {
            let key = format!("{}-{}", topic, p);
            match self.topic_brokers.get(&key) {
                Some(broker) => {
                    if !brokers.contains_key(broker) {brokers.insert(broker.clone(), Vec::new());}
                    brokers.get_mut(broker).unwrap().push(p);
                },
                None => {}
            }
        }

        let mut res: Vec<utils::PartitionOffset> = vec!();
        for (host, partitions) in brokers.iter() {
            let v = vec!(utils::TopicPartitions{
                topic: topic.clone(),
                partitions: partitions.to_vec()
                });
            for tpo in try!(self.fetch_offset(&v, host)) {
                res.push(utils::PartitionOffset{partition: tpo.partition, offset: tpo.offset});
            }
        }
        Ok(vec!((topic.clone(), res)))
    }

    fn fetch_offset(&mut self, topic_partitions: &Vec<utils::TopicPartitions>, host: &String)
                            -> Result<Vec<utils::TopicPartitionOffset>> {
        let correlation = self.next_id();
        let req = protocol::OffsetRequest::new_latest(topic_partitions, correlation, &self.clientid);

        let resp = try!(self.send_receive::<protocol::OffsetRequest, protocol::OffsetResponse>(&host, req));

        Ok(resp.get_offsets())

    }

    fn get_broker(&mut self, topic: &String, partition: i32) -> Option<String> {
        let key = format!("{}-{}", topic, partition);
        match self.topic_brokers.get(&key) {
            Some(broker) => {
                Some(broker.clone())
            },
            None => None
        }
    }

    /// Fetch messages from Kafka
    ///
    /// It takes a single topic, parition and offset and return a vector of messages
    /// or error::Error
    /// You can figure out the appropriate partition and offset using client's
    /// client.topic_partitions and client.fetch_topic_offset(topic)
    ///
    /// # Examples
    ///
    /// ```no_run
    /// let mut client = kafka::client::KafkaClient::new(&vec!("localhost:9092".to_string()));
    /// let res = client.load_metadata_all();
    /// let msgs = client.fetch_messages(&"my-topic".to_string(), 0, 0);
    /// ```
    pub fn fetch_messages(&mut self, topic: &String, partition: i32, offset: i64) -> Result<Vec<utils::OffsetMessage>>{

        let host = self.get_broker(topic, partition).unwrap();

        let correlation = self.next_id();
        let req = protocol::FetchRequest::new_single(topic, partition, offset, correlation, &self.clientid);

        let resp = try!(self.send_receive::<protocol::FetchRequest, protocol::FetchResponse>(&host, req));
        Ok(resp.get_messages())
    }

    /// Send a message to Kafka
    ///
    /// You can figure out the appropriate partition and offset using client's
    /// client.topic_partitions and client.fetch_topic_offset(topic)
    ///
    /// `required_acks` - indicates how many acknowledgements the servers should receive before
    /// responding to the request. If it is 0 the server will not send any response
    /// (this is the only case where the server will not reply to a request).
    /// If it is 1, the server will wait the data is written to the local log before sending
    /// a response. If it is -1 the server will block until the message is committed by all
    /// in sync replicas before sending a response. For any number > 1 the server will block
    /// waiting for this number of acknowledgements to occur (but the server will never wait
    /// for more acknowledgements than there are in-sync replicas).
    ///
    /// `timeout` - This provides a maximum time in milliseconds the server can await the
    /// receipt of the number of acknowledgements in `required_acks`
    /// `message` - A single message as a vector of u8s
    ///
    /// # Example
    ///
    /// ```no_run
    /// let mut client = kafka::client::KafkaClient::new(&vec!("localhost:9092".to_string()));
    /// let res = client.load_metadata_all();
    /// let msgs = client.send_message(&"my-topic".to_string(), 0, 1,
    ///                  100, &"b".to_string().into_bytes());
    /// ```
    /// The return value will contain topic, partition, offset and error if any
    /// OR error:Error
    pub fn send_message(&mut self, topic: &String, partition: i32, required_acks: i16,
                      timeout: i32, message: &Vec<u8>) -> Result<Vec<utils::TopicPartitionOffset>> {

        let host = self.get_broker(topic, partition).unwrap();

        let correlation = self.next_id();
        let req = protocol::ProduceRequest::new_single(topic, partition, required_acks,
            timeout, message, correlation, &self.clientid);

        let resp = try!(self.send_receive
            ::<protocol::ProduceRequest, protocol::ProduceResponse>(&host, req));
        Ok(resp.get_response())

    }

    fn send_receive<T: ToByte, V: FromByte>(&mut self, host: &str, req: T) -> Result<V::R> {
        let mut conn = try!(self.get_conn(&host));
        try!(self.send_request(&mut conn, req));
        self.get_response::<V>(&mut conn)
    }

    fn send_request<T: ToByte>(&self, conn: &mut KafkaConnection, request: T) -> Result<usize>{
        let mut buffer = vec!();
        request.encode(&mut buffer);

        let mut s = vec!();
        (buffer.len() as i32).encode(&mut s);
        for byte in buffer.iter() { s.push(*byte); }

        conn.send(&s)
    }

    fn get_response<T: FromByte>(&self, conn:&mut KafkaConnection) -> Result<T::R>{
        let mut v: Vec<u8> = vec!();
        let _ = conn.read(4, &mut v);
        let size = i32::decode_new(&mut Cursor::new(v)).unwrap();

        let mut resp: Vec<u8> = vec!();
        let _ = try!(conn.read(size as u64, &mut resp));

        T::decode_new(&mut Cursor::new(resp))
    }

}
<|endoftext|>


<commit_before>use std::thread;
use std::net::SocketAddr;
use std::net::ToSocketAddrs;
use std::sync::mpsc;
use std::sync::Arc;

use futures;
use futures::Future;
use futures::stream::Stream;
use futures::oneshot;
use futures::Complete;

use futures_io;
use futures_io::TaskIo;
use futures_io::TaskIoRead;
use futures_io::TaskIoWrite;

use futures_mio;
use futures_mio::Loop;
use futures_mio::TcpStream;

use solicit::http::client::ClientConnection;
use solicit::http::client::RequestStream;
use solicit::http::session::Client;
use solicit::http::session::SessionState;
use solicit::http::session::DefaultSessionState;
use solicit::http::session::DefaultStream;
use solicit::http::session::StreamState;
use solicit::http::session::StreamDataChunk;
use solicit::http::session::StreamDataError;
use solicit::http::session::Stream as solicit_Stream;
use solicit::http::connection::HttpConnection;
use solicit::http::connection::SendStatus;
use solicit::http::frame::RawFrame;
use solicit::http::HttpScheme;
use solicit::http::Header;

use method::MethodDescriptor;

use error::*;
use result::*;

use futures_misc::*;
use futures_grpc::*;

use grpc::*;
use solicit_async::*;
use solicit_misc::*;

// Data sent from event loop to GrpcClient
struct LoopToClient {
    call_tx: futures_mio::Sender<Box<CallRequest>>,
    shutdown_tx: futures_mio::Sender<()>,
}

pub struct GrpcClient {
    loop_to_client: LoopToClient,
    thread_join_handle: Option<thread::JoinHandle<()>>,
}

trait CallRequest : Send {
    fn write_req(&self) -> GrpcResult<Vec<u8>>;
    fn method_name(&self) -> &str;
    fn complete(&mut self, message: &[u8]);
}

struct CallRequestTyped<Req, Resp> {
    method: Arc<MethodDescriptor<Req, Resp>>,
    req: Req,
    complete: Option<Complete<GrpcResult<Resp>>>,
}

impl<Req : Send, Resp : Send> CallRequest for CallRequestTyped<Req, Resp> {
    fn write_req(&self) -> GrpcResult<Vec<u8>> {
        self.method.req_marshaller.write(&self.req)
    }

    fn method_name(&self) -> &str {
        &self.method.name
    }

    fn complete(&mut self, message: &[u8]) {
        self.complete.take().unwrap().complete(self.method.resp_marshaller.read(message));
    }
}

impl GrpcClient {
    pub fn new(host: &str, port: u16) -> GrpcClient {

        // TODO: sync
        let socket_addr = (host, port).to_socket_addrs().unwrap().next().unwrap();

        let (get_from_loop_tx, get_from_loop_rx) = mpsc::channel();

        let host = host.to_owned();

        let join_handle = thread::spawn(move || {
            run_client_event_loop(host, socket_addr, get_from_loop_tx);
        });

        let loop_to_client = get_from_loop_rx.recv().unwrap();

        let r = GrpcClient {
            loop_to_client: loop_to_client,
            thread_join_handle: Some(join_handle),
        };

        r
    }

    pub fn call<Req : Send + 'static, Resp : Send + 'static>(&self, req: Req, method: Arc<MethodDescriptor<Req, Resp>>) -> GrpcFuture<Resp> {
        let (complete, oneshot) = oneshot();

        self.loop_to_client.call_tx.send(Box::new(CallRequestTyped {
            method: method,
            req: req,
            complete: Some(complete),
        })).unwrap();

        oneshot.then(|result| {
            match result {
                Ok(grpc_result) => grpc_result,
                Err(err) => Err(GrpcError::from(err)),
            }
        }).boxed()
    }
}

impl Drop for GrpcClient {
    fn drop(&mut self) {
        // ignore error because even loop may be already dead
        self.loop_to_client.shutdown_tx.send(()).ok();

        // do not ignore errors because we own event loop thread
        self.thread_join_handle.take().unwrap().join().unwrap();
    }
}

struct GrpcHttp2ClientStream {
    stream: DefaultStream,
    call: Option<Box<CallRequest>>,
}

impl GrpcHttp2ClientStream {
    fn new() -> GrpcHttp2ClientStream {
        GrpcHttp2ClientStream {
            stream: DefaultStream::new(),
            call: None,
        }
    }
}

impl solicit_Stream for GrpcHttp2ClientStream {
    fn new_data_chunk(&mut self, data: &[u8]) {
        self.stream.new_data_chunk(data)
    }

    fn set_headers<'n, 'v>(&mut self, headers: Vec<Header<'n, 'v>>) {
        self.stream.set_headers(headers)
    }

    fn set_state(&mut self, state: StreamState) {
        //println!("set_state: {:?}", state);
        if state == StreamState::Closed {
            //println!("response body: {:?}", BsDebug(&self.stream.body));
            let message_serialized = parse_grpc_frame_completely(&self.stream.body).unwrap();
            self.call.as_mut().unwrap().complete(message_serialized);
        }
        self.stream.set_state(state)
    }

    fn get_data_chunk(&mut self, buf: &mut [u8]) -> Result<StreamDataChunk, StreamDataError> {
        self.stream.get_data_chunk(buf)
    }

    fn state(&self) -> StreamState {
        self.stream.state()
    }
}

struct ClientSharedState {
    host: String,
    conn: ClientConnection<DefaultSessionState<Client, GrpcHttp2ClientStream>>,
}

unsafe impl Sync for ClientSharedState {}

impl ClientSharedState {
    fn new_stream<'n, 'v>(
        &self,
        method: &'v [u8],
        path: &'v [u8],
        extras: &[Header<'n, 'v>],
        body: Option<Vec<u8>>)
            -> RequestStream<'n, 'v, GrpcHttp2ClientStream>
    {
        let mut stream = GrpcHttp2ClientStream::new();
        match body {
            Some(body) => stream.stream.set_full_data(body),
            None => stream.close_local(),
        };

        let mut headers: Vec<Header> = vec![
            Header::new(b":method", method),
            Header::new(b":path", path),
            Header::new(b":authority", self.host.clone().into_bytes()),
            Header::new(b":scheme", self.conn.scheme().as_bytes().to_vec()),
        ];

        headers.extend(extras.iter().cloned());

        RequestStream {
            headers: headers,
            stream: stream,
        }
    }
}

fn run_read(
    read: TaskIoRead<TcpStream>,
    shared: TaskDataMutex<ClientSharedState>)
        -> GrpcFuture<()>
{
    let stream = stream_repeat(());

    let future = stream.fold((read, shared), |(read, shared), _| {
        recv_raw_frame(read).map(|(read, raw_frame)| {

            shared.with(|shared: &mut ClientSharedState| {
                // https://github.com/mlalic/solicit/pull/32
                let raw_frame = RawFrame::from(raw_frame.serialize());

                let mut send = VecSendFrame(Vec::new());

                // TODO: do not unwrap
                shared.conn.handle_next_frame(
                    &mut OnceReceiveFrame::new(raw_frame),
                    &mut send).unwrap();

                // TODO: process send

                shared.conn.state.get_closed();
            });

            (read, shared)
        })
    });

    future.map(|_| ()).boxed()
}

fn run_write(
    write: TaskIoWrite<TcpStream>,
    shared: TaskDataMutex<ClientSharedState>,
    call_rx: futures_mio::Receiver<Box<CallRequest>>)
    -> GrpcFuture<()>
{
    let future = call_rx.fold((write, shared), |(write, shared), req| {
        let send_buf = shared.with(|shared: &mut ClientSharedState| {
            let mut body = Vec::new();
            write_grpc_frame(&mut body, &try!(req.write_req()));
            let path = req.method_name().as_bytes().to_vec();
            let mut stream = shared.new_stream(
                b"POST",
                &path,
                &[],
                Some(body));

            stream.stream.call = Some(req);

            let mut send_buf = VecSendFrame(Vec::new());

            // TODO: do not unwrap
            let _stream_id = shared.conn.start_request(stream, &mut send_buf).unwrap();
            while let SendStatus::Sent = shared.conn.send_next_data(&mut send_buf).unwrap() {
            }

            Ok(send_buf.0)
        });

        futures::done(send_buf)
            .and_then(|send_buf| {
                futures_io::write_all(write, send_buf)
                    .map(|(write, _)| (write, shared))
            })
    });
    future
        .map(|_| ())
        .map_err(|e| e.into())
        .boxed()
}

fn run_client_event_loop(
    host: String,
    socket_addr: SocketAddr,
    send_to_client: mpsc::Sender<LoopToClient>)
{
    let mut lp = Loop::new().unwrap();

    let (call_tx, call_rx) = lp.handle().channel();
    let (shutdown_tx, shutdown_rx) = lp.handle().channel();

    send_to_client.send(LoopToClient { call_tx: call_tx, shutdown_tx: shutdown_tx }).unwrap();

    let call_rx = call_rx.map_err(GrpcError::from);
    let shutdown_rx = shutdown_rx.map_err(GrpcError::from);

    let h = lp.handle();
    let connect = call_rx.and_then(|call_rx| {
        h.tcp_connect(&socket_addr)
            .map(|conn| (conn, call_rx))
            .map_err(GrpcError::from)
    });

    let handshake = connect.and_then(|(conn, call_rx)| {
        client_handshake(conn)
            .map(|conn| (conn, call_rx))
            .map_err(GrpcError::from)
    });

    let run_read_write = handshake.and_then(|(conn, call_rx)| {
        let (read, write) = TaskIo::new(conn).split();

        let conn = HttpConnection::new(HttpScheme::Http);
        let state = DefaultSessionState::<Client, _>::new();

        let conn = ClientConnection::with_connection(conn, state);

        let shared_for_read = TaskDataMutex::new(ClientSharedState {
            host: host,
            conn: conn,
        });
        let shared_for_write = shared_for_read.clone();
        run_read(read, shared_for_read)
            .join(run_write(write, shared_for_write, call_rx))
                .map_err(GrpcError::from)
    });

    let shutdown = shutdown_rx.and_then(|shutdown_rx| {
        shutdown_rx.into_future()
            .map_err(|_| GrpcError::Other("error in shutdown channel"))
            .and_then(|_| {
                let result: Result<(), _> = Err(GrpcError::Other("shutdown"));
                result
            })
    });

    let done = run_read_write.join(shutdown);

    lp.run(done).ok();
}
<commit_msg>unneeded unsafe<commit_after>use std::thread;
use std::net::SocketAddr;
use std::net::ToSocketAddrs;
use std::sync::mpsc;
use std::sync::Arc;

use futures;
use futures::Future;
use futures::stream::Stream;
use futures::oneshot;
use futures::Complete;

use futures_io;
use futures_io::TaskIo;
use futures_io::TaskIoRead;
use futures_io::TaskIoWrite;

use futures_mio;
use futures_mio::Loop;
use futures_mio::TcpStream;

use solicit::http::client::ClientConnection;
use solicit::http::client::RequestStream;
use solicit::http::session::Client;
use solicit::http::session::SessionState;
use solicit::http::session::DefaultSessionState;
use solicit::http::session::DefaultStream;
use solicit::http::session::StreamState;
use solicit::http::session::StreamDataChunk;
use solicit::http::session::StreamDataError;
use solicit::http::session::Stream as solicit_Stream;
use solicit::http::connection::HttpConnection;
use solicit::http::connection::SendStatus;
use solicit::http::frame::RawFrame;
use solicit::http::HttpScheme;
use solicit::http::Header;

use method::MethodDescriptor;

use error::*;
use result::*;

use futures_misc::*;
use futures_grpc::*;

use grpc::*;
use solicit_async::*;
use solicit_misc::*;

// Data sent from event loop to GrpcClient
struct LoopToClient {
    call_tx: futures_mio::Sender<Box<CallRequest>>,
    shutdown_tx: futures_mio::Sender<()>,
}

pub struct GrpcClient {
    loop_to_client: LoopToClient,
    thread_join_handle: Option<thread::JoinHandle<()>>,
}

trait CallRequest : Send {
    fn write_req(&self) -> GrpcResult<Vec<u8>>;
    fn method_name(&self) -> &str;
    fn complete(&mut self, message: &[u8]);
}

struct CallRequestTyped<Req, Resp> {
    method: Arc<MethodDescriptor<Req, Resp>>,
    req: Req,
    complete: Option<Complete<GrpcResult<Resp>>>,
}

impl<Req : Send, Resp : Send> CallRequest for CallRequestTyped<Req, Resp> {
    fn write_req(&self) -> GrpcResult<Vec<u8>> {
        self.method.req_marshaller.write(&self.req)
    }

    fn method_name(&self) -> &str {
        &self.method.name
    }

    fn complete(&mut self, message: &[u8]) {
        self.complete.take().unwrap().complete(self.method.resp_marshaller.read(message));
    }
}

impl GrpcClient {
    pub fn new(host: &str, port: u16) -> GrpcClient {

        // TODO: sync
        let socket_addr = (host, port).to_socket_addrs().unwrap().next().unwrap();

        let (get_from_loop_tx, get_from_loop_rx) = mpsc::channel();

        let host = host.to_owned();

        let join_handle = thread::spawn(move || {
            run_client_event_loop(host, socket_addr, get_from_loop_tx);
        });

        let loop_to_client = get_from_loop_rx.recv().unwrap();

        let r = GrpcClient {
            loop_to_client: loop_to_client,
            thread_join_handle: Some(join_handle),
        };

        r
    }

    pub fn call<Req : Send + 'static, Resp : Send + 'static>(&self, req: Req, method: Arc<MethodDescriptor<Req, Resp>>) -> GrpcFuture<Resp> {
        let (complete, oneshot) = oneshot();

        self.loop_to_client.call_tx.send(Box::new(CallRequestTyped {
            method: method,
            req: req,
            complete: Some(complete),
        })).unwrap();

        oneshot.then(|result| {
            match result {
                Ok(grpc_result) => grpc_result,
                Err(err) => Err(GrpcError::from(err)),
            }
        }).boxed()
    }
}

impl Drop for GrpcClient {
    fn drop(&mut self) {
        // ignore error because even loop may be already dead
        self.loop_to_client.shutdown_tx.send(()).ok();

        // do not ignore errors because we own event loop thread
        self.thread_join_handle.take().unwrap().join().unwrap();
    }
}

struct GrpcHttp2ClientStream {
    stream: DefaultStream,
    call: Option<Box<CallRequest>>,
}

impl GrpcHttp2ClientStream {
    fn new() -> GrpcHttp2ClientStream {
        GrpcHttp2ClientStream {
            stream: DefaultStream::new(),
            call: None,
        }
    }
}

impl solicit_Stream for GrpcHttp2ClientStream {
    fn new_data_chunk(&mut self, data: &[u8]) {
        self.stream.new_data_chunk(data)
    }

    fn set_headers<'n, 'v>(&mut self, headers: Vec<Header<'n, 'v>>) {
        self.stream.set_headers(headers)
    }

    fn set_state(&mut self, state: StreamState) {
        //println!("set_state: {:?}", state);
        if state == StreamState::Closed {
            //println!("response body: {:?}", BsDebug(&self.stream.body));
            let message_serialized = parse_grpc_frame_completely(&self.stream.body).unwrap();
            self.call.as_mut().unwrap().complete(message_serialized);
        }
        self.stream.set_state(state)
    }

    fn get_data_chunk(&mut self, buf: &mut [u8]) -> Result<StreamDataChunk, StreamDataError> {
        self.stream.get_data_chunk(buf)
    }

    fn state(&self) -> StreamState {
        self.stream.state()
    }
}

struct ClientSharedState {
    host: String,
    conn: ClientConnection<DefaultSessionState<Client, GrpcHttp2ClientStream>>,
}

impl ClientSharedState {
    fn new_stream<'n, 'v>(
        &self,
        method: &'v [u8],
        path: &'v [u8],
        extras: &[Header<'n, 'v>],
        body: Option<Vec<u8>>)
            -> RequestStream<'n, 'v, GrpcHttp2ClientStream>
    {
        let mut stream = GrpcHttp2ClientStream::new();
        match body {
            Some(body) => stream.stream.set_full_data(body),
            None => stream.close_local(),
        };

        let mut headers: Vec<Header> = vec![
            Header::new(b":method", method),
            Header::new(b":path", path),
            Header::new(b":authority", self.host.clone().into_bytes()),
            Header::new(b":scheme", self.conn.scheme().as_bytes().to_vec()),
        ];

        headers.extend(extras.iter().cloned());

        RequestStream {
            headers: headers,
            stream: stream,
        }
    }
}

fn run_read(
    read: TaskIoRead<TcpStream>,
    shared: TaskDataMutex<ClientSharedState>)
        -> GrpcFuture<()>
{
    let stream = stream_repeat(());

    let future = stream.fold((read, shared), |(read, shared), _| {
        recv_raw_frame(read).map(|(read, raw_frame)| {

            shared.with(|shared: &mut ClientSharedState| {
                // https://github.com/mlalic/solicit/pull/32
                let raw_frame = RawFrame::from(raw_frame.serialize());

                let mut send = VecSendFrame(Vec::new());

                // TODO: do not unwrap
                shared.conn.handle_next_frame(
                    &mut OnceReceiveFrame::new(raw_frame),
                    &mut send).unwrap();

                // TODO: process send

                shared.conn.state.get_closed();
            });

            (read, shared)
        })
    });

    future.map(|_| ()).boxed()
}

fn run_write(
    write: TaskIoWrite<TcpStream>,
    shared: TaskDataMutex<ClientSharedState>,
    call_rx: futures_mio::Receiver<Box<CallRequest>>)
    -> GrpcFuture<()>
{
    let future = call_rx.fold((write, shared), |(write, shared), req| {
        let send_buf = shared.with(|shared: &mut ClientSharedState| {
            let mut body = Vec::new();
            write_grpc_frame(&mut body, &try!(req.write_req()));
            let path = req.method_name().as_bytes().to_vec();
            let mut stream = shared.new_stream(
                b"POST",
                &path,
                &[],
                Some(body));

            stream.stream.call = Some(req);

            let mut send_buf = VecSendFrame(Vec::new());

            // TODO: do not unwrap
            let _stream_id = shared.conn.start_request(stream, &mut send_buf).unwrap();
            while let SendStatus::Sent = shared.conn.send_next_data(&mut send_buf).unwrap() {
            }

            Ok(send_buf.0)
        });

        futures::done(send_buf)
            .and_then(|send_buf| {
                futures_io::write_all(write, send_buf)
                    .map(|(write, _)| (write, shared))
            })
    });
    future
        .map(|_| ())
        .map_err(|e| e.into())
        .boxed()
}

fn run_client_event_loop(
    host: String,
    socket_addr: SocketAddr,
    send_to_client: mpsc::Sender<LoopToClient>)
{
    let mut lp = Loop::new().unwrap();

    let (call_tx, call_rx) = lp.handle().channel();
    let (shutdown_tx, shutdown_rx) = lp.handle().channel();

    send_to_client.send(LoopToClient { call_tx: call_tx, shutdown_tx: shutdown_tx }).unwrap();

    let call_rx = call_rx.map_err(GrpcError::from);
    let shutdown_rx = shutdown_rx.map_err(GrpcError::from);

    let h = lp.handle();
    let connect = call_rx.and_then(|call_rx| {
        h.tcp_connect(&socket_addr)
            .map(|conn| (conn, call_rx))
            .map_err(GrpcError::from)
    });

    let handshake = connect.and_then(|(conn, call_rx)| {
        client_handshake(conn)
            .map(|conn| (conn, call_rx))
            .map_err(GrpcError::from)
    });

    let run_read_write = handshake.and_then(|(conn, call_rx)| {
        let (read, write) = TaskIo::new(conn).split();

        let conn = HttpConnection::new(HttpScheme::Http);
        let state = DefaultSessionState::<Client, _>::new();

        let conn = ClientConnection::with_connection(conn, state);

        let shared_for_read = TaskDataMutex::new(ClientSharedState {
            host: host,
            conn: conn,
        });
        let shared_for_write = shared_for_read.clone();
        run_read(read, shared_for_read)
            .join(run_write(write, shared_for_write, call_rx))
                .map_err(GrpcError::from)
    });

    let shutdown = shutdown_rx.and_then(|shutdown_rx| {
        shutdown_rx.into_future()
            .map_err(|_| GrpcError::Other("error in shutdown channel"))
            .and_then(|_| {
                let result: Result<(), _> = Err(GrpcError::Other("shutdown"));
                result
            })
    });

    let done = run_read_write.join(shutdown);

    lp.run(done).ok();
}
<|endoftext|>


<commit_before>
#[derive(Copy, Clone)]
pub struct Color {
    pub r: u8,
    pub g: u8,
    pub b: u8,
    pub a: u8,
}

impl Color {
    pub fn RGB(r: u8, g: u8, b: u8) -> Color {
        Color {
            r: r,
            g: g,
            b: b,
            a: 255,
        }
    }

    pub fn RGBA(r: u8, g: u8, b: u8, a: u8) -> Color {
        Color {
            r: r,
            g: g,
            b: b,
            a: a,
        }
    }
}

impl PartialEq for Color {
    fn eq(&self, other: &Color) -> bool {
        (self.r == other.r && self.g == other.g && self.b == other.b && self.a == other.a)
    }
}

// Color constant definitions

#[allow(dead_code)]
pub const BLACK: Color = Color {
    r: 0,
    g: 0,
    b: 0,
    a: 255,
};

#[allow(dead_code)]
pub const WHITE: Color = Color {
    r: 255,
    g: 255,
    b: 255,
    a: 255,
};

#[allow(dead_code)]
pub const RED: Color = Color {
    r: 255,
    g: 0,
    b: 0,
    a: 255,
};

#[allow(dead_code)]
pub const GREEN: Color = Color {
    r: 0,
    g: 255,
    b: 0,
    a: 255,
};

#[allow(dead_code)]
pub const BLUE: Color = Color {
    r: 0,
    g: 0,
    b: 255,
    a: 255,
};

#[allow(dead_code)]
pub const YELLOW: Color = Color {
    r: 255,
    g: 255,
    b: 0,
    a: 255,
};
<commit_msg>renamed color functions to silence compiler warnings<commit_after>
#[derive(Copy, Clone)]
pub struct Color {
    pub r: u8,
    pub g: u8,
    pub b: u8,
    pub a: u8,
}

impl Color {
    pub fn rgb(r: u8, g: u8, b: u8) -> Color {
        Color {
            r: r,
            g: g,
            b: b,
            a: 255,
        }
    }

    pub fn rgba(r: u8, g: u8, b: u8, a: u8) -> Color {
        Color {
            r: r,
            g: g,
            b: b,
            a: a,
        }
    }
}

impl PartialEq for Color {
    fn eq(&self, other: &Color) -> bool {
        (self.r == other.r && self.g == other.g && self.b == other.b && self.a == other.a)
    }
}

// Color constant definitions

#[allow(dead_code)]
pub const BLACK: Color = Color {
    r: 0,
    g: 0,
    b: 0,
    a: 255,
};

#[allow(dead_code)]
pub const WHITE: Color = Color {
    r: 255,
    g: 255,
    b: 255,
    a: 255,
};

#[allow(dead_code)]
pub const RED: Color = Color {
    r: 255,
    g: 0,
    b: 0,
    a: 255,
};

#[allow(dead_code)]
pub const GREEN: Color = Color {
    r: 0,
    g: 255,
    b: 0,
    a: 255,
};

#[allow(dead_code)]
pub const BLUE: Color = Color {
    r: 0,
    g: 0,
    b: 255,
    a: 255,
};

#[allow(dead_code)]
pub const YELLOW: Color = Color {
    r: 255,
    g: 255,
    b: 0,
    a: 255,
};
<|endoftext|>


<commit_before>// Copyright 2015 Adrien Champion. See the COPYRIGHT file at the top-level
// directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Basic types used by the library.
*/

use std::io ;
use std::sync::Arc ;

use nom::IResult ;

/** Alias for `io` results of unit. */
pub type IoResUnit = io::Result<()> ;
/** Alias for `io` results of `bool`. */
pub type IoResBool = io::Result<bool> ;
/** Alias for generic `io` results. */
pub type IoRes<T> = io::Result<T> ;

/** Unexpected result for an SMT Lib 2 command. */
#[derive(Debug)]
pub enum UnexSmtRes {
  /** An unsupported command was issued. */
  Unsupported,
  /** A command produced an error. */
  Error(String),
  /** An input/output error occured. */
  IOError(io::Error),
}

/** Result of an SMT query. */
pub type SmtRes<T> = Result<T, UnexSmtRes> ;

/** Result of an SMT statement. */
pub type UnitSmtRes = SmtRes<()> ;

/** A symbol printable in the SMT Lib 2 standard. */
pub trait Sym2Smt {
  /** Prints a symbol to a writer. */
  fn sym_to_smt2(& self, writer: & mut io::Write) -> IoResUnit ;
}
impl<T: Sym2Smt> Sym2Smt for Arc<T> {
  fn sym_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    (* * self).sym_to_smt2(writer)
  }
}
/** An expression printable in the SMT Lib 2 standard. */
pub trait Expr2Smt {
  /** Prints an expression to a writer. */
  fn expr_to_smt2(& self, writer: & mut io::Write) -> IoResUnit ;
}
impl<T: Expr2Smt> Expr2Smt for Arc<T> {
  fn expr_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    (* * self).expr_to_smt2(writer)
  }
}
/** A sort printable in the SMT Lib 2 standard. */
pub trait Sort2Smt {
  /** Prints a sort to a writer. */
  fn sort_to_smt2(& self, writer: & mut io::Write) -> IoResUnit ;
}
impl<T: Sort2Smt> Sort2Smt for Arc<T> {
  fn sort_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    (* * self).sort_to_smt2(writer)
  }
}

impl<'a> Sym2Smt  for & 'a str {
  fn sym_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    write!(writer, "{}", self)
  }
}
impl<'a> Expr2Smt for & 'a str {
  fn expr_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    self.sym_to_smt2(writer)
  }
}
impl<'a> Sort2Smt for & 'a str {
  fn sort_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    self.sym_to_smt2(writer)
  }
}

/** Generic type for the parsing of an SMT Lib 2 answer.

Either a value of the expected type or an unexpected error. */
pub type SmtParseResult<T> = Result<T, UnexSmtRes> ;

/** Parsers on the user's structure.

Not all of them are necessary depending on the queries wanted. See each method
for details.*/
pub trait ParseSmt2 {
  /** Type of identifiers in the user's structure. */
  type Ident : ::std::fmt::Debug ;
  /** Type of values in the user's structure. */
  type Value : ::std::fmt::Debug ;
  /** Type of expressions in the user's structure. */
  type Expr :  ::std::fmt::Debug ;
  /** Type of proofs in the user's structure. */
  type Proof : ::std::fmt::Debug ;

  /** Parses an ident from self, viewed as a reader.

  Required by

  * `get-assignment`
  * `get-model`
  * `get-unsat-assumptions`
  * `get-unsat-core` */
  #[inline(always)]
  fn parse_ident<'a>(
    & self, & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Ident> ;

  /** Parses a value from self, viewed as a reader.

  Required by

  * `get-value`
  * `get-assignment`
  * `get-model` */
  #[inline(always)]
  fn parse_value<'a>(
    & self, & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Value> ;

  /** Parses an expression from self, viewed as a reader.

  Required by

  * `get_assertions` */
  #[inline(always)]
  fn parse_expr<'a>(
    & self, & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Expr> ;

  /** Parses a proof from self, viewed as a reader.

  Required by

  * `get_proof` */
  #[inline(always)]
  fn parse_proof<'a>(
    & self, & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Proof> ;
}

impl ParseSmt2 for () {
  type Ident = () ;
  type Value = () ;
  type Expr = () ;
  type Proof = () ;
  fn parse_ident<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Ident> {
    panic!("parser on () called")
  }
  fn parse_value<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Value> {
    panic!("parser on () called")
  }
  fn parse_expr<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Expr> {
    panic!("parser on () called")
  }
  fn parse_proof<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Proof> {
    panic!("parser on () called")
  }
}

/** SMT Lib 2 logics. */
#[allow(non_camel_case_types)]
pub enum Logic {
  /** Quantifier-free uninterpreted functions. */
  QF_UF,
  /** Quantifier-free linear integer arithmetic. */
  QF_LIA,
  /** Quantifier-free non-linear integer arithmetic. */
  QF_NIA,
  /** Quantifier-free linear real arithmetic. */
  QF_LRA,
  /** Quantifier-free arrays, uninterpreted functions, linear integer
  arithmetic. */
  QF_AUFLIA,
  /** Quantifier-free arrays, uninterpreted functions, linear integer
  arithmetic. */
  AUFLIA,
  /** Arrays, uninterpreted functions, linear integer/real arithmetic. */
  AUFLIRA,
  /** arrays, uninterpreted functions, non-linear integer/real arithmetic. */
  AUFNIRA,
  /** Linear real arithmetic. */
  LRA,
}

impl Logic {
  /** Prints the logic in a writer in SMT Lib 2 format. */
  pub fn to_smt2(& self, writer: & mut io::Write, _: ()) -> IoResUnit {
    use self::Logic::* ;
    match * self {
      QF_UF => write!(writer, "QF_UF"),
      QF_LIA => write!(writer, "QF_LIA"),
      QF_NIA => write!(writer, "QF_NIA"),
      QF_LRA => write!(writer, "QF_LRA"),
      QF_AUFLIA => write!(writer, "QF_AUFLIA"),
      AUFLIA => write!(writer, "AUFLIA"),
      AUFLIRA => write!(writer, "AUFLIRA"),
      AUFNIRA => write!(writer, "AUFNIRA"),
      LRA => write!(writer, "LRA"),
    }
  }
}<commit_msg>Info smt2 printing<commit_after>// Copyright 2015 Adrien Champion. See the COPYRIGHT file at the top-level
// directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Basic types used by the library.
*/

use std::io ;
use std::sync::Arc ;

use nom::IResult ;

/** Alias for `io` results of unit. */
pub type IoResUnit = io::Result<()> ;
/** Alias for `io` results of `bool`. */
pub type IoResBool = io::Result<bool> ;
/** Alias for generic `io` results. */
pub type IoRes<T> = io::Result<T> ;

/** Unexpected result for an SMT Lib 2 command. */
#[derive(Debug)]
pub enum UnexSmtRes {
  /** An unsupported command was issued. */
  Unsupported,
  /** A command produced an error. */
  Error(String),
  /** An input/output error occured. */
  IOError(io::Error),
}

/** Result of an SMT query. */
pub type SmtRes<T> = Result<T, UnexSmtRes> ;

/** Result of an SMT statement. */
pub type UnitSmtRes = SmtRes<()> ;

/** A symbol printable in the SMT Lib 2 standard. */
pub trait Sym2Smt {
  /** Prints a symbol to a writer. */
  fn sym_to_smt2(& self, writer: & mut io::Write) -> IoResUnit ;
}
impl<T: Sym2Smt> Sym2Smt for Arc<T> {
  fn sym_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    (* * self).sym_to_smt2(writer)
  }
}
/** A symbol printable in the SMT Lib 2 standard given some info. */
pub trait SymInfo2Smt<Info> {
  /** Prints a symbol to a writer given some info. */
  fn sym_info_to_smt2(
    & self, info: & Info, writer: & mut io::Write
  ) -> IoResUnit ;
}
impl<'a, 'b, Info, T: SymInfo2Smt<Info>> Sym2Smt for (& 'a T, & 'b Info) {
  fn sym_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    self.0.sym_info_to_smt2(self.1, writer)
  }
}

/** An expression printable in the SMT Lib 2 standard. */
pub trait Expr2Smt {
  /** Prints an expression to a writer. */
  fn expr_to_smt2(& self, writer: & mut io::Write) -> IoResUnit ;
}
impl<T: Expr2Smt> Expr2Smt for Arc<T> {
  fn expr_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    (* * self).expr_to_smt2(writer)
  }
}
/** An expression printable in the SMT Lib 2 standard given some info. */
pub trait ExprInfo2Smt<Info> {
  /** Prints an expression to a writer given some info. */
  fn expr_info_to_smt2(
    & self, info: & Info, writer: & mut io::Write
  ) -> IoResUnit ;
}
impl<'a, 'b, Info, T: ExprInfo2Smt<Info>> Expr2Smt for (& 'a T, & 'b Info) {
  fn expr_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    self.0.expr_info_to_smt2(self.1, writer)
  }
}

/** A sort printable in the SMT Lib 2 standard. */
pub trait Sort2Smt {
  /** Prints a sort to a writer. */
  fn sort_to_smt2(& self, writer: & mut io::Write) -> IoResUnit ;
}
impl<T: Sort2Smt> Sort2Smt for Arc<T> {
  fn sort_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    (* * self).sort_to_smt2(writer)
  }
}
/** A sort printable in the SMT Lib 2 standard given some info. */
pub trait SortInfo2Smt<Info> {
  /** Prints a sort to a writer given some info. */
  fn sort_info_to_smt2(
    & self, info: & Info, writer: & mut io::Write
  ) -> IoResUnit ;
}
impl<'a, 'b, Info, T: SortInfo2Smt<Info>> Sort2Smt for (& 'a T, & 'b Info) {
  fn sort_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    self.0.sort_info_to_smt2(self.1, writer)
  }
}

impl<'a> Sym2Smt  for & 'a str {
  fn sym_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    write!(writer, "{}", self)
  }
}
impl<'a> Expr2Smt for & 'a str {
  fn expr_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    self.sym_to_smt2(writer)
  }
}
impl<'a> Sort2Smt for & 'a str {
  fn sort_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    self.sym_to_smt2(writer)
  }
}

/** Generic type for the parsing of an SMT Lib 2 answer.

Either a value of the expected type or an unexpected error. */
pub type SmtParseResult<T> = Result<T, UnexSmtRes> ;

/** Parsers on the user's structure.

Not all of them are necessary depending on the queries wanted. See each method
for details.*/
pub trait ParseSmt2 {
  /** Type of identifiers in the user's structure. */
  type Ident : ::std::fmt::Debug ;
  /** Type of values in the user's structure. */
  type Value : ::std::fmt::Debug ;
  /** Type of expressions in the user's structure. */
  type Expr :  ::std::fmt::Debug ;
  /** Type of proofs in the user's structure. */
  type Proof : ::std::fmt::Debug ;

  /** Parses an ident from self, viewed as a reader.

  Required by

  * `get-assignment`
  * `get-model`
  * `get-unsat-assumptions`
  * `get-unsat-core` */
  #[inline(always)]
  fn parse_ident<'a>(
    & self, & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Ident> ;

  /** Parses a value from self, viewed as a reader.

  Required by

  * `get-value`
  * `get-assignment`
  * `get-model` */
  #[inline(always)]
  fn parse_value<'a>(
    & self, & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Value> ;

  /** Parses an expression from self, viewed as a reader.

  Required by

  * `get_assertions` */
  #[inline(always)]
  fn parse_expr<'a>(
    & self, & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Expr> ;

  /** Parses a proof from self, viewed as a reader.

  Required by

  * `get_proof` */
  #[inline(always)]
  fn parse_proof<'a>(
    & self, & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Proof> ;
}

impl ParseSmt2 for () {
  type Ident = () ;
  type Value = () ;
  type Expr = () ;
  type Proof = () ;
  fn parse_ident<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Ident> {
    panic!("parser on () called")
  }
  fn parse_value<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Value> {
    panic!("parser on () called")
  }
  fn parse_expr<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Expr> {
    panic!("parser on () called")
  }
  fn parse_proof<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<'a, & 'a [u8], Self::Proof> {
    panic!("parser on () called")
  }
}

/** SMT Lib 2 logics. */
#[allow(non_camel_case_types)]
pub enum Logic {
  /** Quantifier-free uninterpreted functions. */
  QF_UF,
  /** Quantifier-free linear integer arithmetic. */
  QF_LIA,
  /** Quantifier-free non-linear integer arithmetic. */
  QF_NIA,
  /** Quantifier-free linear real arithmetic. */
  QF_LRA,
  /** Quantifier-free arrays, uninterpreted functions, linear integer
  arithmetic. */
  QF_AUFLIA,
  /** Quantifier-free arrays, uninterpreted functions, linear integer
  arithmetic. */
  AUFLIA,
  /** Arrays, uninterpreted functions, linear integer/real arithmetic. */
  AUFLIRA,
  /** arrays, uninterpreted functions, non-linear integer/real arithmetic. */
  AUFNIRA,
  /** Linear real arithmetic. */
  LRA,
}

impl Logic {
  /** Prints the logic in a writer in SMT Lib 2 format. */
  pub fn to_smt2(& self, writer: & mut io::Write, _: ()) -> IoResUnit {
    use self::Logic::* ;
    match * self {
      QF_UF => write!(writer, "QF_UF"),
      QF_LIA => write!(writer, "QF_LIA"),
      QF_NIA => write!(writer, "QF_NIA"),
      QF_LRA => write!(writer, "QF_LRA"),
      QF_AUFLIA => write!(writer, "QF_AUFLIA"),
      AUFLIA => write!(writer, "AUFLIA"),
      AUFLIRA => write!(writer, "AUFLIRA"),
      AUFNIRA => write!(writer, "AUFNIRA"),
      LRA => write!(writer, "LRA"),
    }
  }
}<|endoftext|>