<commit_before>//! Gets the commandline input and packs it into an usable Stuct.
//! Data that can be included: genres, movies, rating.
use clap::{App, Arg};
use std::process;

/// Struct contains all the needed information to make suggestions of films
#[derive(Debug, Clone)]
pub struct SearchParams {
    genres: Vec<String>,
    movies: Vec<String>,
    rating: f32,
}

impl SearchParams {
    /// initialize a SearchParams type with empty fields
    fn init() -> Self {
        SearchParams {
            genres: Vec::new(),
            movies: Vec::new(),
            rating: 0.0,
        }
    }

    pub fn get_genres(&self) -> Vec<String> {
        self.genres.clone()
    }

    pub fn get_movies(&self) -> Vec<String> {
        self.movies.clone()
    }

    pub fn get_rating(&self) -> f32 {
        self.rating
    }
}

/// Creates struct SearchParams with all given parameters
pub fn get_search_params() -> SearchParams {
    // status of program
    println!("Getting Commandline Input ...");

    // search parameters
    let mut search_params = SearchParams::init();

    // matches, we can later use those to handle our commandline input
    let matches = App::new("Film-O-Mat")
        .arg(Arg::with_name("genre")
            .short("g")
            .help("Takes one or more genres")
            .takes_value(true)
            .multiple(true))
        .arg(Arg::with_name("movie")
            .short("m")
            .help("Takes one or more movies. e.g. \u{0022}Schindler's List\u{0022}")
            .takes_value(true)
            .multiple(true))
        .arg(Arg::with_name("rating")
            .short("r")
            .help("Takes a rating")
            .takes_value(true))
        .get_matches();

    // If a genre was given, save it in our SearchParams Type
    if matches.is_present("genre") {
        let genres: Vec<String> = match matches.values_of("genre") {
            Some(vals) => {
                vals.map(|x| x.to_string())
                    .collect()
            }
            None => {
                println!("Invalid Genre");
                process::exit(0);
            }
        };
        search_params.genres = genres;
    }

    // If a genre was given, save it in our SearchParams Type
    if matches.is_present("movie") {
        let movies: Vec<String> = match matches.values_of("movie") {
            Some(vals) => {
                vals.map(|x| x.to_string())
                    .collect()
            }
            None => {
                println!("Invalid Movie");
                process::exit(0);
            }
        };
        search_params.movies = movies;
    }

    // If a rating was given, save it in our SearchParams
    if matches.is_present("rating") {
        let val = match matches.value_of("rating") {
            Some(vals) => vals,
            None => {
                println!("Invalid Rating");
                process::exit(0);
            }
        };
        search_params.rating = match val.parse() {
            Ok(val) => val,
            Err(err) => {
                println!("{:?}", err);
                process::exit(0);
            }
        };
    }
    search_params
}
<commit_msg>added validators to clap<commit_after>//! Gets the commandline input and packs it into an usable Stuct.
//! Data that can be included: genres, movies, rating.
use clap::{App, Arg};
use std::process;

/// Struct contains all the needed information to make suggestions of films
#[derive(Debug, Clone)]
pub struct SearchParams {
    genres: Vec<String>,
    movies: Vec<String>,
    rating: f32,
}

impl SearchParams {
    /// initialize a SearchParams type with empty fields
    fn init() -> Self {
        SearchParams {
            genres: Vec::new(),
            movies: Vec::new(),
            rating: 0.0,
        }
    }

    pub fn get_genres(&self) -> Vec<String> {
        self.genres.clone()
    }

    pub fn get_movies(&self) -> Vec<String> {
        self.movies.clone()
    }

    pub fn get_rating(&self) -> f32 {
        self.rating
    }
}

/// Creates struct SearchParams with all given parameters
pub fn get_search_params() -> SearchParams {
    // status of program
    println!("Getting Commandline Input ...");

    // search parameters
    let mut search_params = SearchParams::init();

    // matches, we can later use those to handle our commandline input
    let matches = App::new("Film-O-Mat")
        .arg(Arg::with_name("genre")
            .short("g")
            .help("Takes one or more genres")
            .takes_value(true)
            .multiple(true)
            .validator(feasable_genre))
        .arg(Arg::with_name("movie")
            .short("m")
            .help("Takes one or more movies. e.g. \u{0022}Schindler's List\u{0022}")
            .takes_value(true)
            .multiple(true))
        .arg(Arg::with_name("rating")
            .short("r")
            .help("Takes a rating")
            .takes_value(true)
            .validator(is_rating))
        .get_matches();

    // If a genre was given, save it in our SearchParams Type
    if matches.is_present("genre") {
        let genres: Vec<String> = match matches.values_of("genre") {
            Some(vals) => {
                vals.map(|x| x.to_string())
                    .collect()
            }
            None => {
                println!("Invalid Genre");
                process::exit(0);
            }
        };
        search_params.genres = genres;
    }

    // If a genre was given, save it in our SearchParams Type
    if matches.is_present("movie") {
        let movies: Vec<String> = match matches.values_of("movie") {
            Some(vals) => {
                vals.map(|x| x.to_string())
                    .collect()
            }
            None => {
                println!("Invalid Movie");
                process::exit(0);
            }
        };
        search_params.movies = movies;
    }

    // If a rating was given, save it in our SearchParams
    if matches.is_present("rating") {
        let val = match matches.value_of("rating") {
            Some(vals) => vals,
            None => {
                println!("Invalid Rating");
                process::exit(0);
            }
        };
        search_params.rating = match val.parse() {
            Ok(val) => val,
            Err(err) => {
                println!("{:?}", err);
                process::exit(0);
            }
        };
    }
    search_params
}

fn feasable_genre(value: String) -> Result<(), String> {
    match value.as_str() {
        "Action" => Ok(()),
        "Adult" => Ok(()),
        "Adventure" => Ok(()),
        "Animation" => Ok(()),
        "Biography" => Ok(()),
        "Comedy" => Ok(()),
        "Crime" => Ok(()),
        "Documentary" => Ok(()),
        "Drama" => Ok(()),
        "Family" => Ok(()),
        "Fantasy" => Ok(()),
        "Film-Noir" => Ok(()),
        "History" => Ok(()),
        "Horror" => Ok(()),
        "Music" => Ok(()),
        "Musical" => Ok(()),
        "Mystery" => Ok(()),
        "Romance" => Ok(()),
        "Sci-Fi" => Ok(()),
        "Short" => Ok(()),
        "Sport" => Ok(()),
        "Thriller" => Ok(()),
        "War" => Ok(()),
        "Western" => Ok(()),
        _ => Err(String::from("Given Genre is not valid")),
    }
}

fn is_rating(value: String) -> Result<(), String> {
    match value.parse::<f32>() {
        Ok(_) => Ok(()),
        _ => Err(String::from("Given Rating is not a number")),
    }
}
<|endoftext|>


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

use toml::Value;

use libimagrt::runtime::Runtime;
use libimagrt::edit::{Edit, EditResult};
use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::StoreIdIterator;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagtag::tag::Tag;
use libimagtag::tagable::Tagable;
use libimagtag::result::Result as TagResult;

use module_path::ModuleEntryPath;
use result::Result;
use error::NoteError as NE;
use error::NoteErrorKind as NEK;

pub struct Note<'a> {
    entry: FileLockEntry<'a>,
}

impl<'a> Note<'a> {

    pub fn new(store: &Store, name: String, text: String) -> Result<Note> {
        use std::ops::DerefMut;

        debug!("Creating new Note: '{}'", name);
        let fle = {
            let lockentry = store.create(ModuleEntryPath::new(name.clone()).into_storeid());
            if lockentry.is_err() {
                return Err(NE::new(NEK::StoreWriteError, Some(Box::new(lockentry.err().unwrap()))));
            }
            let mut lockentry = lockentry.unwrap();

            {
                let mut entry  = lockentry.deref_mut();

                {
                    let mut header = entry.get_header_mut();
                    let setres = header.set("note", Value::Table(BTreeMap::new()));
                    if setres.is_err() {
                        let kind = NEK::StoreWriteError;
                        return Err(NE::new(kind, Some(Box::new(setres.err().unwrap()))));
                    }

                    let setres = header.set("note.name", Value::String(name));
                    if setres.is_err() {
                        let kind = NEK::StoreWriteError;
                        return Err(NE::new(kind, Some(Box::new(setres.err().unwrap()))));
                    }
                }

                *entry.get_content_mut() = text;
            }

            lockentry
        };

        Ok(Note { entry: fle })
    }

    pub fn set_name(&mut self, n: String) -> Result<()> {
        let mut header = self.entry.deref_mut().get_header_mut();
        header.set("note.name", Value::String(n))
            .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
            .map(|_| ())
    }

    pub fn get_name(&self) -> Result<String> {
        let header = self.entry.deref().get_header();
        match header.read("note.name") {
            Ok(Some(Value::String(s))) => Ok(String::from(s)),
            Ok(_)                => {
                let e = NE::new(NEK::HeaderTypeError, None);
                Err(NE::new(NEK::StoreReadError, Some(Box::new(e))))
            },
            Err(e) => Err(NE::new(NEK::StoreReadError, Some(Box::new(e))))
        }
    }

    pub fn set_text(&mut self, n: String) {
        *self.entry.deref_mut().get_content_mut() = n
    }

    pub fn get_text(&self) -> &String {
        self.entry.deref().get_content()
    }

    pub fn delete(store: &Store, name: String) -> Result<()> {
        store.delete(ModuleEntryPath::new(name).into_storeid())
            .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
    }

    pub fn retrieve(store: &Store, name: String) -> Result<Note> {
        store.retrieve(ModuleEntryPath::new(name).into_storeid())
            .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
            .map(|entry| Note { entry: entry })
    }

    pub fn all_notes(store: &Store) -> Result<NoteIterator> {
        store.retrieve_for_module("notes")
            .map(|iter| NoteIterator::new(store, iter))
            .map_err(|e| NE::new(NEK::StoreReadError, Some(Box::new(e))))
    }

}

impl<'a> Edit for Note<'a> {

    fn edit_content(&mut self, rt: &Runtime) -> EditResult<()> {
        self.entry.edit_content(rt)
    }

}

impl<'a> Tagable for Note<'a> {

    fn get_tags(&self) -> TagResult<Vec<Tag>> {
        self.entry.deref().get_tags()
    }

    fn set_tags(&mut self, ts: Vec<Tag>) -> TagResult<()> {
        self.entry.deref_mut().set_tags(ts)
    }

    fn add_tag(&mut self, t: Tag) -> TagResult<()> {
        self.entry.deref_mut().add_tag(t)
    }

    fn remove_tag(&mut self, t: Tag) -> TagResult<()> {
        self.entry.deref_mut().remove_tag(t)
    }

    fn has_tag(&self, t: &Tag) -> TagResult<bool> {
        self.entry.deref().has_tag(t)
    }

    fn has_tags(&self, ts: &Vec<Tag>) -> TagResult<bool> {
        self.entry.deref().has_tags(ts)
    }

}

trait FromStoreId {
    fn from_storeid<'a>(&'a Store, StoreId) -> Result<Note<'a>>;
}

impl<'a> FromStoreId for Note<'a> {

    fn from_storeid<'b>(store: &'b Store, id: StoreId) -> Result<Note<'b>> {
        debug!("Loading note from storeid: '{:?}'", id);
        match store.retrieve(id) {
            Err(e)    => Err(NE::new(NEK::StoreReadError, Some(Box::new(e)))),
            Ok(entry) => Ok(Note { entry: entry }),
        }
    }

}

pub struct NoteIterator<'a> {
    store: &'a Store,
    iditer: StoreIdIterator,
}

impl<'a> NoteIterator<'a> {

    pub fn new(store: &'a Store, iditer: StoreIdIterator) -> NoteIterator<'a> {
        NoteIterator {
            store: store,
            iditer: iditer,
        }
    }

}

impl<'a> Iterator for NoteIterator<'a> {
    type Item = Result<Note<'a>>;

    fn next(&mut self) -> Option<Result<Note<'a>>> {
        self.iditer
            .next()
            .map(|id| Note::from_storeid(self.store, id))
    }

}

<commit_msg>impl Deref for Note<commit_after>use std::collections::BTreeMap;
use std::ops::{DerefMut, Deref};

use toml::Value;

use libimagrt::runtime::Runtime;
use libimagrt::edit::{Edit, EditResult};
use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::StoreIdIterator;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagtag::tag::Tag;
use libimagtag::tagable::Tagable;
use libimagtag::result::Result as TagResult;

use module_path::ModuleEntryPath;
use result::Result;
use error::NoteError as NE;
use error::NoteErrorKind as NEK;

pub struct Note<'a> {
    entry: FileLockEntry<'a>,
}

impl<'a> Note<'a> {

    pub fn new(store: &Store, name: String, text: String) -> Result<Note> {
        use std::ops::DerefMut;

        debug!("Creating new Note: '{}'", name);
        let fle = {
            let lockentry = store.create(ModuleEntryPath::new(name.clone()).into_storeid());
            if lockentry.is_err() {
                return Err(NE::new(NEK::StoreWriteError, Some(Box::new(lockentry.err().unwrap()))));
            }
            let mut lockentry = lockentry.unwrap();

            {
                let mut entry  = lockentry.deref_mut();

                {
                    let mut header = entry.get_header_mut();
                    let setres = header.set("note", Value::Table(BTreeMap::new()));
                    if setres.is_err() {
                        let kind = NEK::StoreWriteError;
                        return Err(NE::new(kind, Some(Box::new(setres.err().unwrap()))));
                    }

                    let setres = header.set("note.name", Value::String(name));
                    if setres.is_err() {
                        let kind = NEK::StoreWriteError;
                        return Err(NE::new(kind, Some(Box::new(setres.err().unwrap()))));
                    }
                }

                *entry.get_content_mut() = text;
            }

            lockentry
        };

        Ok(Note { entry: fle })
    }

    pub fn set_name(&mut self, n: String) -> Result<()> {
        let mut header = self.entry.deref_mut().get_header_mut();
        header.set("note.name", Value::String(n))
            .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
            .map(|_| ())
    }

    pub fn get_name(&self) -> Result<String> {
        let header = self.entry.deref().get_header();
        match header.read("note.name") {
            Ok(Some(Value::String(s))) => Ok(String::from(s)),
            Ok(_)                => {
                let e = NE::new(NEK::HeaderTypeError, None);
                Err(NE::new(NEK::StoreReadError, Some(Box::new(e))))
            },
            Err(e) => Err(NE::new(NEK::StoreReadError, Some(Box::new(e))))
        }
    }

    pub fn set_text(&mut self, n: String) {
        *self.entry.deref_mut().get_content_mut() = n
    }

    pub fn get_text(&self) -> &String {
        self.entry.deref().get_content()
    }

    pub fn delete(store: &Store, name: String) -> Result<()> {
        store.delete(ModuleEntryPath::new(name).into_storeid())
            .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
    }

    pub fn retrieve(store: &Store, name: String) -> Result<Note> {
        store.retrieve(ModuleEntryPath::new(name).into_storeid())
            .map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
            .map(|entry| Note { entry: entry })
    }

    pub fn all_notes(store: &Store) -> Result<NoteIterator> {
        store.retrieve_for_module("notes")
            .map(|iter| NoteIterator::new(store, iter))
            .map_err(|e| NE::new(NEK::StoreReadError, Some(Box::new(e))))
    }

}

impl<'a> Edit for Note<'a> {

    fn edit_content(&mut self, rt: &Runtime) -> EditResult<()> {
        self.entry.edit_content(rt)
    }

}

impl<'a> Tagable for Note<'a> {

    fn get_tags(&self) -> TagResult<Vec<Tag>> {
        self.entry.deref().get_tags()
    }

    fn set_tags(&mut self, ts: Vec<Tag>) -> TagResult<()> {
        self.entry.deref_mut().set_tags(ts)
    }

    fn add_tag(&mut self, t: Tag) -> TagResult<()> {
        self.entry.deref_mut().add_tag(t)
    }

    fn remove_tag(&mut self, t: Tag) -> TagResult<()> {
        self.entry.deref_mut().remove_tag(t)
    }

    fn has_tag(&self, t: &Tag) -> TagResult<bool> {
        self.entry.deref().has_tag(t)
    }

    fn has_tags(&self, ts: &Vec<Tag>) -> TagResult<bool> {
        self.entry.deref().has_tags(ts)
    }

}

trait FromStoreId {
    fn from_storeid<'a>(&'a Store, StoreId) -> Result<Note<'a>>;
}

impl<'a> FromStoreId for Note<'a> {

    fn from_storeid<'b>(store: &'b Store, id: StoreId) -> Result<Note<'b>> {
        debug!("Loading note from storeid: '{:?}'", id);
        match store.retrieve(id) {
            Err(e)    => Err(NE::new(NEK::StoreReadError, Some(Box::new(e)))),
            Ok(entry) => Ok(Note { entry: entry }),
        }
    }

}

impl<'a> Deref for Note<'a> {

    type Target = FileLockEntry<'a>;

    fn deref(&self) -> &FileLockEntry<'a> {
        &self.entry
    }

}

pub struct NoteIterator<'a> {
    store: &'a Store,
    iditer: StoreIdIterator,
}

impl<'a> NoteIterator<'a> {

    pub fn new(store: &'a Store, iditer: StoreIdIterator) -> NoteIterator<'a> {
        NoteIterator {
            store: store,
            iditer: iditer,
        }
    }

}

impl<'a> Iterator for NoteIterator<'a> {
    type Item = Result<Note<'a>>;

    fn next(&mut self) -> Option<Result<Note<'a>>> {
        self.iditer
            .next()
            .map(|id| Note::from_storeid(self.store, id))
    }

}

<|endoftext|>


<commit_before>extern crate glfw;

use self::glfw::{Action, Key, WindowEvent};
use graphics::Graphics;
use std::sync::Arc;

const  KEY_CODE_MAX: i32 = 255;

enum Peripheral {
    HardwareKeyboard, OnscreenKeyboard, MultitouchScreen, Accelerometer, Compass, Vibrator, Gyroscope
}

pub struct Input;

impl Input {
        pub fn new() -> Self {
            Input {}
        }

        pub fn update(&self, graphics: &mut Graphics) {
                graphics.glfw.poll_events();
                for event in glfw::flush_messages(&graphics.events) {
                    Input::handle_window_event(&mut graphics.window, event);
                }
        }

        pub fn is_key_pressed(&self, key_code: i32) -> bool {
            false
        }

        fn handle_window_event(window: &mut glfw::Window, (time, event): (f64, glfw::WindowEvent)) {
            match event {
                glfw::WindowEvent::Pos(x, y)                      => window.set_title(&format!("Time: {:?}, Window pos: ({:?}, {:?})", time, x, y)),
                glfw::WindowEvent::Size(w, h)                     => window.set_title(&format!("Time: {:?}, Window size: ({:?}, {:?})", time, w, h)),
                glfw::WindowEvent::Close                          => println!("Time: {:?}, Window close requested.", time),
                glfw::WindowEvent::Refresh                        => println!("Time: {:?}, Window refresh callback triggered.", time),
                glfw::WindowEvent::Focus(true)                    => println!("Time: {:?}, Window focus gained.", time),
                glfw::WindowEvent::Focus(false)                   => println!("Time: {:?}, Window focus lost.", time),
                glfw::WindowEvent::Iconify(true)                  => println!("Time: {:?}, Window was minimised", time),
                glfw::WindowEvent::Iconify(false)                 => println!("Time: {:?}, Window was maximised.", time),
                glfw::WindowEvent::FramebufferSize(w, h)          => println!("Time: {:?}, Framebuffer size: ({:?}, {:?})", time, w, h),
                glfw::WindowEvent::Char(character)                => println!("Time: {:?}, Character: {:?}", time, character),
                glfw::WindowEvent::MouseButton(btn, action, mods) => println!("Time: {:?}, Button: {:?}, Action: {:?}, Modifiers: [{:?}]", time, glfw::DebugAliases(btn), action, mods),
                glfw::WindowEvent::CursorPos(xpos, ypos)          => window.set_title(&format!("Time: {:?}, Cursor position: ({:?}, {:?})", time, xpos, ypos)),
                glfw::WindowEvent::CursorEnter(true)              => println!("Time: {:?}, Cursor entered window.", time),
                glfw::WindowEvent::CursorEnter(false)             => println!("Time: {:?}, Cursor left window.", time),
                glfw::WindowEvent::Scroll(x, y)                   => window.set_title(&format!("Time: {:?}, Scroll offset: ({:?}, {:?})", time, x, y)),
                glfw::WindowEvent::Key(key, scancode, action, mods) => {
                    println!("Time: {:?}, Key: {:?}, ScanCode: {:?}, Action: {:?}, Modifiers: [{:?}]", time, key, scancode, action, mods);
                    match (key, action) {
                        (Key::Escape, Action::Press) => window.set_should_close(true),
                        (Key::R, Action::Press) => {
                            // Resize should cause the window to "refresh"
                            let (window_width, window_height) = window.get_size();
                            window.set_size(window_width + 1, window_height);
                            window.set_size(window_width, window_height);
                        }
                        _ => {}
                    }
                }
            }
        }
}

#[derive(Debug)]
pub struct KeyboardEvent {
    pub name: String,
    pub key_code: i32
}

impl KeyboardEvent {
    pub fn execute(&self)
    {
         println!("KeyboardEvent name: {}, key code: {}", &self.name, &self.key_code);
    }

}

pub trait InputProcessor {
    fn new() -> Self;
    fn key_down(&mut self, keycode: i32) -> bool;
	fn key_up(&mut self, keycode: i32) -> bool;
	/*fn key_typed(&self, character: char) -> bool;
	fn touch_down(&self, screenX: i32, screenY: i32, pointer: i32, button: i32) -> bool;
	fn touch_up(&self, screenX: i32, screenY: i32, pointer: i32, button: i32) -> bool;
	fn touch_dragged(&self, screenX: i32, screenY: i32, pointer: i32) -> bool;
	fn mouse_moved(&self, screenX: i32, screenY: i32) -> bool;
	fn scrolled(&self, amount: i32) -> bool;*/
}

#[allow(dead_code)]
enum Buttons {
 LEFT, RIGHT, MIDDLE, BACK, FORWARD
	}

#[allow(dead_code)]
enum Keys {
    ANY_KEY,NUM_0
,NUM_1
,NUM_2
,NUM_3,NUM_4,NUM_5,NUM_6,NUM_7,NUM_8,NUM_9,A,ALT_LEFT,ALT_RIGHT,APOSTROPHE,AT,B,BACK
,BACKSLASH,C,CALL
,CAMERA,CLEAR,COMMA,D,DEL,BACKSPACE,FORWARD_DEL,DPAD_CENTER,DPAD_DOWN,DPAD_LEFT,DPAD_RIGHT,DPAD_UP,CENTER,DOWN,LEFT,RIGHT,UP,E,ENDCALL
,ENTER,ENVELOPE,EQUALS,EXPLORER,F,FOCUS,G,GRAVE,H,HEADSETHOOK,HOME
,I,J,K,L,LEFT_BRACKET,M,MEDIA_FAST_FORWARD,MEDIA_NEXT,MEDIA_PLAY_PAUSE,MEDIA_PREVIOUS,MEDIA_REWIND,MEDIA_STOP,MENU,MINUS,MUTE,N,NOTIFICATION,NUM,O,P,PERIOD,PLUS,POUND,POWER,Q,R,RIGHT_BRACKET,S,SEARCH,SEMICOLON,SHIFT_LEFT,SHIFT_RIGHT,SLASH,SOFT_LEFT
,SOFT_RIGHT
,SPACE,STAR,SYM,T,TAB,U,UNKNOWN
,V,VOLUME_DOWN,VOLUME_UP,W,X,Y,Z,META_ALT_LEFT_ON,META_ALT_ON
,META_ALT_RIGHT_ON,META_SHIFT_LEFT_ON,META_SHIFT_ON
,META_SHIFT_RIGHT_ON,META_SYM_ON
,CONTROL_LEFT,CONTROL_RIGHT,ESCAPE,END,INSERT,PAGE_UP,PAGE_DOWN,PICTSYMBOLS,SWITCH_CHARSET,BUTTON_CIRCLE,BUTTON_A,BUTTON_B,BUTTON_C,BUTTON_X,BUTTON_Y,BUTTON_Z,BUTTON_L1,BUTTON_R1,BUTTON_L2,BUTTON_R2,BUTTON_THUMBL,BUTTON_THUMBR,BUTTON_START,BUTTON_SELECT,BUTTON_MODE
,NUMPAD_0,NUMPAD_1,NUMPAD_2,NUMPAD_3,NUMPAD_4,NUMPAD_5,NUMPAD_6,NUMPAD_7,NUMPAD_8,NUMPAD_9,
        COLON ,F1 ,F2 ,F3 ,F4 ,F5 ,F6 ,F7 ,F8 ,F9 ,F10 ,F11 ,F12
}
<commit_msg>Event processing through input_processors addedd<commit_after>extern crate glfw;

use graphics::Graphics;
use std::collections::BTreeMap;

#[allow(dead_code)]
enum Peripheral {
    HardwareKeyboard, OnscreenKeyboard, MultitouchScreen, Accelerometer, Compass, Vibrator, Gyroscope
}

pub struct Input {
    input_processors: Vec<Box<InputProcessor>>,
    keys_states: BTreeMap<glfw::Key, bool>
}

impl Input {
        pub fn new() -> Self {
            Input {
                input_processors: Vec::new(),
                keys_states:  BTreeMap::new()
            }
        }

        pub fn update(&mut self, graphics: &mut Graphics) {
                graphics.glfw.poll_events();
                for event in glfw::flush_messages(&graphics.events) {
                    Input::handle_window_event(self, &mut graphics.window, event);
                }
        }

        pub fn is_key_pressed(&self, key: glfw::Key) -> bool {
            match self.keys_states.get(&key) {
                Some(value) => *value,
                None => false
            }
        }

        fn handle_window_event(&mut self, window: &mut glfw::Window, (time, event): (f64, glfw::WindowEvent)) {
            match event {
                glfw::WindowEvent::Pos(x, y)                      => window.set_title(&format!("Time: {:?}, Window pos: ({:?}, {:?})", time, x, y)),
                glfw::WindowEvent::Size(w, h)                     => window.set_title(&format!("Time: {:?}, Window size: ({:?}, {:?})", time, w, h)),
                glfw::WindowEvent::Close                          => println!("Time: {:?}, Window close requested.", time),
                glfw::WindowEvent::Refresh                        => println!("Time: {:?}, Window refresh callback triggered.", time),
                glfw::WindowEvent::Focus(true)                    => println!("Time: {:?}, Window focus gained.", time),
                glfw::WindowEvent::Focus(false)                   => println!("Time: {:?}, Window focus lost.", time),
                glfw::WindowEvent::Iconify(true)                  => println!("Time: {:?}, Window was minimised", time),
                glfw::WindowEvent::Iconify(false)                 => println!("Time: {:?}, Window was maximised.", time),
                glfw::WindowEvent::FramebufferSize(w, h)          => println!("Time: {:?}, Framebuffer size: ({:?}, {:?})", time, w, h),
                glfw::WindowEvent::Char(character)                => println!("Time: {:?}, Character: {:?}", time, character),
                glfw::WindowEvent::MouseButton(btn, action, mods) => println!("Time: {:?}, Button: {:?}, Action: {:?}, Modifiers: [{:?}]", time, glfw::DebugAliases(btn), action, mods),
                glfw::WindowEvent::CursorPos(xpos, ypos)          => window.set_title(&format!("Time: {:?}, Cursor position: ({:?}, {:?})", time, xpos, ypos)),
                glfw::WindowEvent::CursorEnter(true)              => println!("Time: {:?}, Cursor entered window.", time),
                glfw::WindowEvent::CursorEnter(false)             => println!("Time: {:?}, Cursor left window.", time),
                glfw::WindowEvent::Scroll(x, y)                   => window.set_title(&format!("Time: {:?}, Scroll offset: ({:?}, {:?})", time, x, y)),
                glfw::WindowEvent::Key(key, scancode, action, mods) => {
                    println!("Time: {:?}, Key: {:?}, ScanCode: {:?}, Action: {:?}, Modifiers: [{:?}]", time, key, scancode, action, mods);
                    match (key, action) {
                        (glfw::Key::Escape, glfw::Action::Press) => window.set_should_close(true),
                        (glfw::Key::R, glfw::Action::Press) => {
                            // Resize should cause the window to "refresh"
                            let (window_width, window_height) = window.get_size();
                            window.set_size(window_width + 1, window_height);
                            window.set_size(window_width, window_height);
                        },
                        (_, glfw::Action::Press) => {
                            &self.keys_states.insert(key, true);
                            for processor in &self.input_processors {
                                processor.key_down(key);
                            }
                        },
                        _ => {}
                    }
                }
            }
        }
}

#[derive(Debug)]
pub struct KeyboardEvent {
    pub name: String,
    pub key_code: i32
}

impl KeyboardEvent {
    pub fn execute(&self)
    {
         println!("KeyboardEvent name: {}, key code: {}", &self.name, &self.key_code);
    }

}

pub trait InputProcessor {
    fn key_down(&self, keycode: glfw::Key) -> bool;
	fn key_up(&self, keycode: glfw::Key) -> bool;
	/*fn key_typed(&self, character: char) -> bool;
	fn touch_down(&self, screenX: i32, screenY: i32, pointer: i32, button: i32) -> bool;
	fn touch_up(&self, screenX: i32, screenY: i32, pointer: i32, button: i32) -> bool;
	fn touch_dragged(&self, screenX: i32, screenY: i32, pointer: i32) -> bool;
	fn mouse_moved(&self, screenX: i32, screenY: i32) -> bool;
	fn scrolled(&self, amount: i32) -> bool;*/
}

#[allow(dead_code)]
enum Buttons {
    LEFT, RIGHT, MIDDLE, BACK, FORWARD
}

#[allow(dead_code)]
enum Keys {
    AnyKey, Num0, Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, A,
    AltLEFT, AltRIGHT, APOSTROPHE, AT, B, BACK, BACKSLASH, C, CALL, CAMERA, CLEAR, COMMA, D, DEL,
    BACKSPACE, ForwardDEL, DpadCENTER, DpadDOWN,
    DpadLEFT,DpadRIGHT,DpadUP,CENTER,DOWN,LEFT,RIGHT,UP,E,ENDCALL
    ,ENTER,ENVELOPE,EQUALS,EXPLORER,F,FOCUS,G,GRAVE,H,HEADSETHOOK,HOME
    ,I,J,K,L,LeftBRACKET,M,MediaFastFORWARD,MediaNEXT,MediaPlayPAUSE,MediaPREVIOUS,MediaREWIND,
    MediaSTOP,MENU,MINUS,MUTE,N,NOTIFICATION,NUM,O,P,PERIOD,PLUS,POUND,POWER,Q,R,RightBRACKET,S,
    SEARCH,SEMICOLON,ShiftLEFT,ShiftRIGHT,SLASH,SoftLEFT
    ,SoftRIGHT ,SPACE,STAR,SYM,T,TAB,U,UNKNOWN
    ,V,VolumeDOWN,VolumeUP,W,X,Y,Z,MetaAltLeftON,MetaAltON
    ,MetaAltRightON,MetaShiftLeftON,MetaShiftON ,MetaShiftRightON,MetaSymON
    ,ControlLEFT,ControlRIGHT,ESCAPE,END,INSERT,PageUP,PageDOWN,PICTSYMBOLS,SwitchCHARSET,
    ButtonCIRCLE,ButtonA,ButtonB,ButtonC,ButtonX,ButtonY,ButtonZ,ButtonL1,ButtonR1,ButtonL2,ButtonR2,ButtonTHUMBL,ButtonTHUMBR,ButtonSTART,ButtonSELECT,ButtonMODE
    ,NUMpad0,NUMpad1,NUMpad2,NUMpad3,NUMpad4,NUMpad5,NUMpad6,NUMpad7,NUMpad8,NUMpad9, COLON
    ,F1 ,F2 ,F3 ,F4 ,F5 ,F6 ,F7 ,F8 ,F9 ,F10 ,F11 ,F12
}
<|endoftext|>


<commit_before>extern crate libc;

use api::ErrorCode;
use commands::{Command, CommandExecutor};
use commands::agent::AgentCommand;
use errors::ToErrorCode;
use utils::cstring::CStringUtils;

use self::libc::c_char;

/// Establishes agent to agent connection.
///
/// Information about sender Identity must be saved in the wallet with indy_create_and_store_my_did
/// call before establishing of connection.
///
/// Information about receiver Identity can be saved in the wallet with indy_store_their_did
/// call before establishing of connection. If there is no corresponded wallet record for receiver Identity
/// than this call will lookup Identity Ledger and cache this information in the wallet.
///
/// Note that messages encryption/decryption will be performed automatically.
///
/// #Params
/// command_handle: Command handle to map callback to caller context.
/// pool_handle: Pool handle (created by open_pool_ledger).
/// wallet_handle: Wallet handle (created by open_wallet).
/// sender_did: Id of sender Identity stored in secured Wallet.
/// receiver_did: Id of receiver Identity.
/// connection_cb: Callback that will be called after establishing of connection or on error.
///     Will be called exactly once with result of connect operation.
/// message_cb: Callback that will be called on receiving of an incoming message.
///     Can be called multiply times: once for each incoming message.
///
/// #Returns
/// Error code
/// connection_cb:
/// - xcommand_handle: command handle to map callback to caller context.
/// - err: Error code.
/// - connection_handle: Connection handle to use for messages sending and mapping of incomming messages to this connection.
/// message_cb:
/// - xconnection_handle: Connection handle. Indetnifies connection.
/// - err: Error code.
/// - message: Received message.
#[no_mangle]
pub extern fn indy_agent_connect(command_handle: i32,
                                 pool_handle: i32,
                                 wallet_handle: i32,
                                 sender_did: *const c_char,
                                 receiver_did: *const c_char,
                                 connection_cb: Option<extern fn(xcommand_handle: i32,
                                                                 err: ErrorCode,
                                                                 connection_handle: i32)>,
                                 message_cb: Option<extern fn(xconnection_handle: i32,
                                                              err: ErrorCode,
                                                              message: *const c_char)>) -> ErrorCode {
    check_useful_c_str!(sender_did, ErrorCode::CommonInvalidParam3);
    check_useful_c_str!(receiver_did, ErrorCode::CommonInvalidParam4);
    check_useful_c_callback!(connection_cb, ErrorCode::CommonInvalidParam5);
    check_useful_c_callback!(message_cb, ErrorCode::CommonInvalidParam6);

    let result = CommandExecutor::instance().send(
        Command::Agent(
            AgentCommand::Connect(
                pool_handle,
                wallet_handle,
                sender_did,
                receiver_did,
                Box::new(move |result| {
                    let (err, handle) = result_to_err_code_1!(result, 0);
                    connection_cb(command_handle, err, handle);
                }),
                Box::new(move |result| {
                    let (err, handle, msg) = result_to_err_code_2!(result, 0, String::new());
                    let msg = CStringUtils::string_to_cstring(msg);
                    message_cb(handle, err, msg.as_ptr());
                })
            )
        )
    );

    result_to_err_code!(result)
}

/// Starts listening of agent connections.
///
/// Listener will accept only connections to registered DIDs by indy_agent_add_identity call.
///
/// Information about sender Identity for incomming connection validation can be saved in the wallet
/// with indy_store_their_did call before establishing of connection. If there is no corresponded
/// wallet record for sender Identity than listener will lookup Identity Ledger and cache this
/// information in the wallet.
///
/// Note that messages encryption/decryption will be performed automatically.
///
/// #Params
/// command_handle: command handle to map callback to caller context.
/// endpoint: endpoint to use in starting listener.
/// listener_cb: Callback that will be called after listening started or on error.
///     Will be called exactly once with result of start listen operation.
/// connection_cb: Callback that will be called after establishing of incoming connection.
///     Can be called multiply times: once for each incoming connection.
/// message_cb: Callback that will be called on receiving of an incoming message.
///     Can be called multiply times: once for each incoming message.
///
/// #Returns
/// Error code
/// listener_cb:
/// - xcommand_handle: command handle to map callback to caller context.
/// - err: Error code
/// - listener_handle: Listener handle to use for mapping of incomming connections to this listener.
/// connection_cb:
/// - xlistener_handle: Listener handle. Identifies listener.
/// - err: Error code
/// - connection_handle: Connection handle to use for messages sending and mapping of incomming messages to to this connection.
/// - sender_did: Id of sender Identity stored in secured Wallet.
/// - receiver_did: Id of receiver Identity.
/// message_cb:
/// - xconnection_handle: Connection handle. Indetnifies connection.
/// - err: Error code.
/// - message: Received message.
#[no_mangle]
pub extern fn indy_agent_listen(command_handle: i32,
                                endpoint: *const c_char,
                                listener_cb: Option<extern fn(xcommand_handle: i32,
                                                              err: ErrorCode,
                                                              listener_handle: i32)>,
                                connection_cb: Option<extern fn(xlistener_handle: i32,
                                                                err: ErrorCode,
                                                                connection_handle: i32,
                                                                sender_did: *const c_char,
                                                                receiver_did: *const c_char)>,
                                message_cb: Option<extern fn(xconnection_handle: i32,
                                                             err: ErrorCode,
                                                             message: *const c_char)>) -> ErrorCode {
    check_useful_c_str!(endpoint, ErrorCode::CommonInvalidParam2);
    check_useful_c_callback!(listener_cb, ErrorCode::CommonInvalidParam3);
    check_useful_c_callback!(connection_cb, ErrorCode::CommonInvalidParam4);
    check_useful_c_callback!(message_cb, ErrorCode::CommonInvalidParam5);

    let cmd = Command::Agent(AgentCommand::Listen(
        endpoint,
        Box::new(move |result| {
            let (err, handle) = result_to_err_code_1!(result, 0);
            listener_cb(command_handle, err, handle);
        }),
        Box::new(move |result| {
            let (err, listener_handle, conn_handle, sender_did, receiver_did) =
                result_to_err_code_4!(result, 0, 0, String::new(), String::new());
            connection_cb(listener_handle, err, conn_handle,
                          CStringUtils::string_to_cstring(sender_did).as_ptr(),
                          CStringUtils::string_to_cstring(receiver_did).as_ptr());
        }),
        Box::new(move |result| {
            let (err, handle, msg) = result_to_err_code_2!(result, 0, String::new());
            let msg = CStringUtils::string_to_cstring(msg);
            message_cb(handle, err, msg.as_ptr());
        })
    ));

    let result = CommandExecutor::instance().send(cmd);

    result_to_err_code!(result)
}

/// Add identity to listener.
///
/// Performs wallet lookup to find corresponded receiver Identity information.
/// Information about receiver Identity must be saved in the wallet with
/// indy_create_and_store_my_did call before this call.
///
/// After successfully add_identity listener will start to accept incoming connection to added DID.
///
///
/// #Params
/// command_handle: command handle to map callback to caller context.
/// listener_handle: listener handle (created by indy_agent_listen).
/// pool_handle: pool handle (created by open_pool_ledger).
/// wallet_handle: wallet handle (created by open_wallet).
/// did: DID of identity.
///
/// add_identity_cb: Callback that will be called after identity added or on error.
///     Will be called exactly once with result of start listen operation.
///
/// #Returns
/// Error code
/// add_identity_cb:
/// - xcommand_handle: command handle to map callback to caller context.
/// - err: Error code
#[no_mangle]
pub extern fn indy_agent_add_identity(command_handle: i32,
                                      listener_handle: i32,
                                      pool_handle: i32,
                                      wallet_handle: i32,
                                      did: *const c_char,
                                      add_identity_cb: Option<extern fn(xcommand_handle: i32,
                                                                        err: ErrorCode)>) -> ErrorCode {
    check_useful_c_str!(did, ErrorCode::CommonInvalidParam5);
    check_useful_c_callback!(add_identity_cb, ErrorCode::CommonInvalidParam6);

    let cmd = Command::Agent(AgentCommand::ListenerAddIdentity(
        listener_handle,
        pool_handle,
        wallet_handle,
        did,
        Box::new(move |result| {
            let result = result_to_err_code!(result);
            add_identity_cb(command_handle, result);
        }),
    ));

    let result = CommandExecutor::instance().send(cmd);

    result_to_err_code!(result)
}

/// Remove identity from listener.
///
/// Performs wallet lookup to find corresponded receiver Identity information.
/// Information about receiver Identity must be saved in the wallet with
/// indy_create_and_store_my_did call before this call.
///
/// After successfully rm_identity listener will stop to accept incoming connection to removed DID.
///
///
/// #Params
/// command_handle: command handle to map callback to caller context.
/// listener_handle: listener handle (created by indy_agent_listen).
/// wallet_handle: wallet handle (created by open_wallet).
/// did: DID of identity.
///
/// rm_identity_cb: Callback that will be called after identity removed or on error.
///     Will be called exactly once with result of start listen operation.
///
/// #Returns
/// Error code
/// rm_identity_cb:
/// - xcommand_handle: command handle to map callback to caller context.
/// - err: Error code
#[no_mangle]
pub extern fn indy_agent_remove_identity(command_handle: i32,
                                         listener_handle: i32,
                                         wallet_handle: i32,
                                         did: *const c_char,
                                         rm_identity_cb: Option<extern fn(xcommand_handle: i32,
                                                                          err: ErrorCode)>) -> ErrorCode {
    check_useful_c_str!(did, ErrorCode::CommonInvalidParam4);
    check_useful_c_callback!(rm_identity_cb, ErrorCode::CommonInvalidParam5);

    let cmd = Command::Agent(AgentCommand::ListenerRmIdentity(
        listener_handle,
        wallet_handle,
        did,
        Box::new(move |result| {
            let result = result_to_err_code!(result);
            rm_identity_cb(command_handle, result);
        }),
    ));

    let result = CommandExecutor::instance().send(cmd);

    result_to_err_code!(result)
}

/// Sends message to connected agent.
///
/// Note that this call works for both incoming and outgoing connections.
/// Note that messages encryption/decryption will be performed automatically.
///
/// #Params
/// command_handle: command handle to map callback to caller context.
/// connection_handle: Connection handle returned by indy_agent_connect or indy_agent_listen calls.
/// message: Message to send.
/// cb: Callback that will be called after message sent or on error. Will be called exactly once.
///
/// #Returns
/// err: Error code
/// cb:
/// - xcommand_handle: Command handle to map callback to caller context.
/// - err: Error code
///
/// #Errors
#[no_mangle]
pub extern fn indy_agent_send(command_handle: i32,
                              connection_handle: i32,
                              message: *const c_char,
                              cb: Option<extern fn(xcommand_handle: i32,
                                                   err: ErrorCode)>) -> ErrorCode {
    check_useful_opt_c_str!(message, ErrorCode::CommonInvalidParam3);
    check_useful_c_callback!(cb, ErrorCode::CommonInvalidParam4);

    let cmd = Command::Agent(AgentCommand::Send(
        connection_handle,
        message,
        Box::new(move |result| {
            cb(command_handle, result_to_err_code!(result))
        })
    ));

    let res = CommandExecutor::instance().send(cmd);
    result_to_err_code!(res)
}

/// Closes agent connection.
///
/// Note that this call works for both incoming and outgoing connections.
///
/// #Params
/// command_handle: command handle to map callback to caller context.
/// connection_handle: Connection handle returned by indy_agent_connect or indy_agent_listen calls.
/// cb: Callback that will be called after connection closed or on error. Will be called exactly once.
///
/// #Returns
/// Error code
/// cb:
/// - xcommand_handle: command handle to map callback to caller context.
/// - err: Error code
///
/// #Errors
#[no_mangle]
pub extern fn indy_agent_close_connection(command_handle: i32,
                                          connection_handle: i32,
                                          cb: Option<extern fn(xcommand_handle: i32,
                                                               err: ErrorCode)>) -> ErrorCode {
    check_useful_c_callback!(cb, ErrorCode::CommonInvalidParam4);

    let cmd = Command::Agent(AgentCommand::CloseConnection(
        connection_handle,
        Box::new(move |result| {
            cb(command_handle, result_to_err_code!(result))
        })
    ));

    let res = CommandExecutor::instance().send(cmd);
    result_to_err_code!(res)
}

/// Closes listener and stops listening for agent connections.
///
/// Note that all opened incomming connections will be closed automatically.
///
/// #Params
/// command_handle: command handle to map callback to caller context.
/// listener_handle: Listener handle returned by indy_agent_listen call.
/// cb: Callback that will be called after listener closed or on error. Will be called exactly once.
///
/// #Returns
/// Error code
/// cb:
/// - xcommand_handle: command handle to map callback to caller context.
/// - err: Error code
///
/// #Errors
#[no_mangle]
pub extern fn indy_agent_close_listener(command_handle: i32,
                                        listener_handle: i32,
                                        cb: Option<extern fn(xcommand_handle: i32,
                                                             err: ErrorCode)>) -> ErrorCode {
    check_useful_c_callback!(cb, ErrorCode::CommonInvalidParam4);

    let cmd = Command::Agent(AgentCommand::CloseListener(
        listener_handle,
        Box::new(move |result| {
            cb(command_handle, result_to_err_code!(result))
        })
    ));

    let res = CommandExecutor::instance().send(cmd);
    result_to_err_code!(res)
}
<commit_msg>Add new Agent2Agent API for agent.rs.<commit_after>extern crate libc;

use api::ErrorCode;
use commands::{Command, CommandExecutor};
use commands::agent::AgentCommand;
use errors::ToErrorCode;
use utils::cstring::CStringUtils;

use self::libc::c_char;

#[no_mangle]
pub extern fn indy_prep_msg(command_handle: i32,
                            sender_vk: *const c_char,
                            recipient_vk: *const c_char,
                            msg_data: *const u8,
                            msg_len: u32,
                            cb: Option<extern fn(command_handle_: i32,
                                                 encrypted_msg: *const c_char,
                                                 encrypted_len: u32)>) -> ErrorCode {
    unimplemented!();
}

#[no_mangle]
pub extern fn indy_prep_anonymous_msg(command_handle: i32,
                                      recipient_vk: *const c_char,
                                      msg_data: *const u8,
                                      msg_len: u32,
                                      cb: Option<extern fn(command_handle_: i32,
                                                           encrypted_msg: *const c_char,
                                                           encrypted_len: u32)>) -> ErrorCode {
    unimplemented!();
}

#[no_mangle]
pub extern fn indy_parse_msg(command_handle: i32,
                             recipient_vk: *const c_char,
                             encrypted_msg: *const u8,
                             encrypted_len: u32,
                             cb: Option<extern fn(command_handle_: i32,
                                                  sender_vk: *const c_char,
                                                  msg_data: *const u8,
                                                  msg_len: u32)>) -> ErrorCode {
    unimplemented!();
}

/// Establishes agent to agent connection.
///
/// Information about sender Identity must be saved in the wallet with indy_create_and_store_my_did
/// call before establishing of connection.
///
/// Information about receiver Identity can be saved in the wallet with indy_store_their_did
/// call before establishing of connection. If there is no corresponded wallet record for receiver Identity
/// than this call will lookup Identity Ledger and cache this information in the wallet.
///
/// Note that messages encryption/decryption will be performed automatically.
///
/// #Params
/// command_handle: Command handle to map callback to caller context.
/// pool_handle: Pool handle (created by open_pool_ledger).
/// wallet_handle: Wallet handle (created by open_wallet).
/// sender_did: Id of sender Identity stored in secured Wallet.
/// receiver_did: Id of receiver Identity.
/// connection_cb: Callback that will be called after establishing of connection or on error.
///     Will be called exactly once with result of connect operation.
/// message_cb: Callback that will be called on receiving of an incoming message.
///     Can be called multiply times: once for each incoming message.
///
/// #Returns
/// Error code
/// connection_cb:
/// - xcommand_handle: command handle to map callback to caller context.
/// - err: Error code.
/// - connection_handle: Connection handle to use for messages sending and mapping of incomming messages to this connection.
/// message_cb:
/// - xconnection_handle: Connection handle. Indetnifies connection.
/// - err: Error code.
/// - message: Received message.
#[no_mangle]
pub extern fn indy_agent_connect(command_handle: i32,
                                 pool_handle: i32,
                                 wallet_handle: i32,
                                 sender_did: *const c_char,
                                 receiver_did: *const c_char,
                                 connection_cb: Option<extern fn(xcommand_handle: i32,
                                                                 err: ErrorCode,
                                                                 connection_handle: i32)>,
                                 message_cb: Option<extern fn(xconnection_handle: i32,
                                                              err: ErrorCode,
                                                              message: *const c_char)>) -> ErrorCode {
    check_useful_c_str!(sender_did, ErrorCode::CommonInvalidParam3);
    check_useful_c_str!(receiver_did, ErrorCode::CommonInvalidParam4);
    check_useful_c_callback!(connection_cb, ErrorCode::CommonInvalidParam5);
    check_useful_c_callback!(message_cb, ErrorCode::CommonInvalidParam6);

    let result = CommandExecutor::instance().send(
        Command::Agent(
            AgentCommand::Connect(
                pool_handle,
                wallet_handle,
                sender_did,
                receiver_did,
                Box::new(move |result| {
                    let (err, handle) = result_to_err_code_1!(result, 0);
                    connection_cb(command_handle, err, handle);
                }),
                Box::new(move |result| {
                    let (err, handle, msg) = result_to_err_code_2!(result, 0, String::new());
                    let msg = CStringUtils::string_to_cstring(msg);
                    message_cb(handle, err, msg.as_ptr());
                })
            )
        )
    );

    result_to_err_code!(result)
}

/// Starts listening of agent connections.
///
/// Listener will accept only connections to registered DIDs by indy_agent_add_identity call.
///
/// Information about sender Identity for incomming connection validation can be saved in the wallet
/// with indy_store_their_did call before establishing of connection. If there is no corresponded
/// wallet record for sender Identity than listener will lookup Identity Ledger and cache this
/// information in the wallet.
///
/// Note that messages encryption/decryption will be performed automatically.
///
/// #Params
/// command_handle: command handle to map callback to caller context.
/// endpoint: endpoint to use in starting listener.
/// listener_cb: Callback that will be called after listening started or on error.
///     Will be called exactly once with result of start listen operation.
/// connection_cb: Callback that will be called after establishing of incoming connection.
///     Can be called multiply times: once for each incoming connection.
/// message_cb: Callback that will be called on receiving of an incoming message.
///     Can be called multiply times: once for each incoming message.
///
/// #Returns
/// Error code
/// listener_cb:
/// - xcommand_handle: command handle to map callback to caller context.
/// - err: Error code
/// - listener_handle: Listener handle to use for mapping of incomming connections to this listener.
/// connection_cb:
/// - xlistener_handle: Listener handle. Identifies listener.
/// - err: Error code
/// - connection_handle: Connection handle to use for messages sending and mapping of incomming messages to to this connection.
/// - sender_did: Id of sender Identity stored in secured Wallet.
/// - receiver_did: Id of receiver Identity.
/// message_cb:
/// - xconnection_handle: Connection handle. Indetnifies connection.
/// - err: Error code.
/// - message: Received message.
#[no_mangle]
pub extern fn indy_agent_listen(command_handle: i32,
                                endpoint: *const c_char,
                                listener_cb: Option<extern fn(xcommand_handle: i32,
                                                              err: ErrorCode,
                                                              listener_handle: i32)>,
                                connection_cb: Option<extern fn(xlistener_handle: i32,
                                                                err: ErrorCode,
                                                                connection_handle: i32,
                                                                sender_did: *const c_char,
                                                                receiver_did: *const c_char)>,
                                message_cb: Option<extern fn(xconnection_handle: i32,
                                                             err: ErrorCode,
                                                             message: *const c_char)>) -> ErrorCode {
    check_useful_c_str!(endpoint, ErrorCode::CommonInvalidParam2);
    check_useful_c_callback!(listener_cb, ErrorCode::CommonInvalidParam3);
    check_useful_c_callback!(connection_cb, ErrorCode::CommonInvalidParam4);
    check_useful_c_callback!(message_cb, ErrorCode::CommonInvalidParam5);

    let cmd = Command::Agent(AgentCommand::Listen(
        endpoint,
        Box::new(move |result| {
            let (err, handle) = result_to_err_code_1!(result, 0);
            listener_cb(command_handle, err, handle);
        }),
        Box::new(move |result| {
            let (err, listener_handle, conn_handle, sender_did, receiver_did) =
                result_to_err_code_4!(result, 0, 0, String::new(), String::new());
            connection_cb(listener_handle, err, conn_handle,
                          CStringUtils::string_to_cstring(sender_did).as_ptr(),
                          CStringUtils::string_to_cstring(receiver_did).as_ptr());
        }),
        Box::new(move |result| {
            let (err, handle, msg) = result_to_err_code_2!(result, 0, String::new());
            let msg = CStringUtils::string_to_cstring(msg);
            message_cb(handle, err, msg.as_ptr());
        })
    ));

    let result = CommandExecutor::instance().send(cmd);

    result_to_err_code!(result)
}

/// Add identity to listener.
///
/// Performs wallet lookup to find corresponded receiver Identity information.
/// Information about receiver Identity must be saved in the wallet with
/// indy_create_and_store_my_did call before this call.
///
/// After successfully add_identity listener will start to accept incoming connection to added DID.
///
///
/// #Params
/// command_handle: command handle to map callback to caller context.
/// listener_handle: listener handle (created by indy_agent_listen).
/// pool_handle: pool handle (created by open_pool_ledger).
/// wallet_handle: wallet handle (created by open_wallet).
/// did: DID of identity.
///
/// add_identity_cb: Callback that will be called after identity added or on error.
///     Will be called exactly once with result of start listen operation.
///
/// #Returns
/// Error code
/// add_identity_cb:
/// - xcommand_handle: command handle to map callback to caller context.
/// - err: Error code
#[no_mangle]
pub extern fn indy_agent_add_identity(command_handle: i32,
                                      listener_handle: i32,
                                      pool_handle: i32,
                                      wallet_handle: i32,
                                      did: *const c_char,
                                      add_identity_cb: Option<extern fn(xcommand_handle: i32,
                                                                        err: ErrorCode)>) -> ErrorCode {
    check_useful_c_str!(did, ErrorCode::CommonInvalidParam5);
    check_useful_c_callback!(add_identity_cb, ErrorCode::CommonInvalidParam6);

    let cmd = Command::Agent(AgentCommand::ListenerAddIdentity(
        listener_handle,
        pool_handle,
        wallet_handle,
        did,
        Box::new(move |result| {
            let result = result_to_err_code!(result);
            add_identity_cb(command_handle, result);
        }),
    ));

    let result = CommandExecutor::instance().send(cmd);

    result_to_err_code!(result)
}

/// Remove identity from listener.
///
/// Performs wallet lookup to find corresponded receiver Identity information.
/// Information about receiver Identity must be saved in the wallet with
/// indy_create_and_store_my_did call before this call.
///
/// After successfully rm_identity listener will stop to accept incoming connection to removed DID.
///
///
/// #Params
/// command_handle: command handle to map callback to caller context.
/// listener_handle: listener handle (created by indy_agent_listen).
/// wallet_handle: wallet handle (created by open_wallet).
/// did: DID of identity.
///
/// rm_identity_cb: Callback that will be called after identity removed or on error.
///     Will be called exactly once with result of start listen operation.
///
/// #Returns
/// Error code
/// rm_identity_cb:
/// - xcommand_handle: command handle to map callback to caller context.
/// - err: Error code
#[no_mangle]
pub extern fn indy_agent_remove_identity(command_handle: i32,
                                         listener_handle: i32,
                                         wallet_handle: i32,
                                         did: *const c_char,
                                         rm_identity_cb: Option<extern fn(xcommand_handle: i32,
                                                                          err: ErrorCode)>) -> ErrorCode {
    check_useful_c_str!(did, ErrorCode::CommonInvalidParam4);
    check_useful_c_callback!(rm_identity_cb, ErrorCode::CommonInvalidParam5);

    let cmd = Command::Agent(AgentCommand::ListenerRmIdentity(
        listener_handle,
        wallet_handle,
        did,
        Box::new(move |result| {
            let result = result_to_err_code!(result);
            rm_identity_cb(command_handle, result);
        }),
    ));

    let result = CommandExecutor::instance().send(cmd);

    result_to_err_code!(result)
}

/// Sends message to connected agent.
///
/// Note that this call works for both incoming and outgoing connections.
/// Note that messages encryption/decryption will be performed automatically.
///
/// #Params
/// command_handle: command handle to map callback to caller context.
/// connection_handle: Connection handle returned by indy_agent_connect or indy_agent_listen calls.
/// message: Message to send.
/// cb: Callback that will be called after message sent or on error. Will be called exactly once.
///
/// #Returns
/// err: Error code
/// cb:
/// - xcommand_handle: Command handle to map callback to caller context.
/// - err: Error code
///
/// #Errors
#[no_mangle]
pub extern fn indy_agent_send(command_handle: i32,
                              connection_handle: i32,
                              message: *const c_char,
                              cb: Option<extern fn(xcommand_handle: i32,
                                                   err: ErrorCode)>) -> ErrorCode {
    check_useful_opt_c_str!(message, ErrorCode::CommonInvalidParam3);
    check_useful_c_callback!(cb, ErrorCode::CommonInvalidParam4);

    let cmd = Command::Agent(AgentCommand::Send(
        connection_handle,
        message,
        Box::new(move |result| {
            cb(command_handle, result_to_err_code!(result))
        })
    ));

    let res = CommandExecutor::instance().send(cmd);
    result_to_err_code!(res)
}

/// Closes agent connection.
///
/// Note that this call works for both incoming and outgoing connections.
///
/// #Params
/// command_handle: command handle to map callback to caller context.
/// connection_handle: Connection handle returned by indy_agent_connect or indy_agent_listen calls.
/// cb: Callback that will be called after connection closed or on error. Will be called exactly once.
///
/// #Returns
/// Error code
/// cb:
/// - xcommand_handle: command handle to map callback to caller context.
/// - err: Error code
///
/// #Errors
#[no_mangle]
pub extern fn indy_agent_close_connection(command_handle: i32,
                                          connection_handle: i32,
                                          cb: Option<extern fn(xcommand_handle: i32,
                                                               err: ErrorCode)>) -> ErrorCode {
    check_useful_c_callback!(cb, ErrorCode::CommonInvalidParam4);

    let cmd = Command::Agent(AgentCommand::CloseConnection(
        connection_handle,
        Box::new(move |result| {
            cb(command_handle, result_to_err_code!(result))
        })
    ));

    let res = CommandExecutor::instance().send(cmd);
    result_to_err_code!(res)
}

/// Closes listener and stops listening for agent connections.
///
/// Note that all opened incomming connections will be closed automatically.
///
/// #Params
/// command_handle: command handle to map callback to caller context.
/// listener_handle: Listener handle returned by indy_agent_listen call.
/// cb: Callback that will be called after listener closed or on error. Will be called exactly once.
///
/// #Returns
/// Error code
/// cb:
/// - xcommand_handle: command handle to map callback to caller context.
/// - err: Error code
///
/// #Errors
#[no_mangle]
pub extern fn indy_agent_close_listener(command_handle: i32,
                                        listener_handle: i32,
                                        cb: Option<extern fn(xcommand_handle: i32,
                                                             err: ErrorCode)>) -> ErrorCode {
    check_useful_c_callback!(cb, ErrorCode::CommonInvalidParam4);

    let cmd = Command::Agent(AgentCommand::CloseListener(
        listener_handle,
        Box::new(move |result| {
            cb(command_handle, result_to_err_code!(result))
        })
    ));

    let res = CommandExecutor::instance().send(cmd);
    result_to_err_code!(res)
}
<|endoftext|>


<commit_before>use std::io::{Read, Seek, SeekFrom};
use std::fs::File;
use std::io::ErrorKind::UnexpectedEof;

#[cfg(feature = "zstd")]
use zstd::block::decompress;

use super::*;

pub(super) trait LogReader {
    fn read_segment_header(
        &mut self,
        id: LogID,
    ) -> std::io::Result<SegmentHeader>;

    fn read_segment_trailer(
        &mut self,
        id: LogID,
    ) -> std::io::Result<SegmentTrailer>;

    fn read_message_header(
        &mut self,
        id: LogID,
    ) -> std::io::Result<MessageHeader>;

    fn read_message(
        &mut self,
        id: LogID,
        segment_len: usize,
        use_compression: bool,
    ) -> std::io::Result<LogRead>;
}

impl LogReader for File {
    fn read_segment_header(
        &mut self,
        id: LogID,
    ) -> std::io::Result<SegmentHeader> {
        trace!("reading segment header at {}", id);
        self.seek(SeekFrom::Start(id))?;

        let mut seg_header_buf = [0u8; SEG_HEADER_LEN];
        self.read_exact(&mut seg_header_buf)?;

        Ok(seg_header_buf.into())
    }

    fn read_segment_trailer(
        &mut self,
        id: LogID,
    ) -> std::io::Result<SegmentTrailer> {
        trace!("reading segment trailer at {}", id);
        self.seek(SeekFrom::Start(id))?;

        let mut seg_trailer_buf = [0u8; SEG_TRAILER_LEN];
        self.read_exact(&mut seg_trailer_buf)?;

        Ok(seg_trailer_buf.into())
    }

    fn read_message_header(
        &mut self,
        id: LogID,
    ) -> std::io::Result<MessageHeader> {
        self.seek(SeekFrom::Start(id))?;

        let mut msg_header_buf = [0u8; MSG_HEADER_LEN];
        self.read_exact(&mut msg_header_buf)?;

        Ok(msg_header_buf.into())
    }

    /// read a buffer from the disk
    fn read_message(
        &mut self,
        lid: LogID,
        segment_len: usize,
        _use_compression: bool,
    ) -> std::io::Result<LogRead> {
        let start = clock();
        let seg_start = lid / segment_len as LogID * segment_len as LogID;
        trace!("reading message from segment: {} at lid: {}", seg_start, lid);
        assert!(seg_start + MSG_HEADER_LEN as LogID <= lid);

        let ceiling = seg_start + segment_len as LogID -
            SEG_TRAILER_LEN as LogID;

        assert!(lid + MSG_HEADER_LEN as LogID <= ceiling);

        let header = self.read_message_header(lid)?;
        assert!(
            lid + MSG_HEADER_LEN as LogID + header.len as LogID <= ceiling,
            "while reading message at {}, read an invalid header: {:?}",
            lid,
            header
        );

        self.seek(SeekFrom::Start(lid + MSG_HEADER_LEN as LogID))?;

        let max = (ceiling - lid - MSG_HEADER_LEN as LogID) as usize;
        let mut len = header.len;
        if len > max {
            error!(
                "log read invalid message length, {} should be <= {}",
                len,
                max
            );
            M.read.measure(clock() - start);
            trace!("read a corrupted message of len {}", len);
            return Ok(LogRead::Corrupted(len));
        } else if len == 0 && !header.successful_flush {
            // skip to next record, which starts with 1
            while len <= max {
                let mut byte = [0u8; 1];
                if let Err(e) = self.read_exact(&mut byte) {
                    if e.kind() == UnexpectedEof {
                        // we've hit the end of the file
                        break;
                    }
                    panic!("{:?}", e);
                }
                if byte[0] != 1 {
                    len += 1;
                } else {
                    break;
                }
            }
        }

        if !header.successful_flush {
            M.read.measure(clock() - start);
            trace!("read zeroes of len {}", len + MSG_HEADER_LEN);
            return Ok(LogRead::Zeroed(len + MSG_HEADER_LEN));
        }

        let mut buf = Vec::with_capacity(len);
        unsafe {
            buf.set_len(len);
        }
        self.read_exact(&mut buf)?;

        let checksum = crc16_arr(&buf);
        if checksum != header.crc16 {
            M.read.measure(clock() - start);
            trace!("read a message with a bad checksum of len {}", len);
            return Ok(LogRead::Corrupted(len));
        }

        #[cfg(feature = "zstd")]
        let res = {
            if _use_compression {
                let start = clock();
                let res = Ok(LogRead::Flush(
                    header.lsn,
                    decompress(&*buf, segment_len).unwrap(),
                    len,
                ));
                M.decompress.measure(clock() - start);
                res
            } else {
                Ok(LogRead::Flush(header.lsn, buf, len))
            }
        };

        #[cfg(not(feature = "zstd"))]
        let res = Ok(LogRead::Flush(header.lsn, buf, len));

        M.read.measure(clock() - start);
        trace!("read a successful flushed message");
        res
    }
}
<commit_msg>small refactor of read_message<commit_after>use std::io::{Read, Seek, SeekFrom};
use std::fs::File;
use std::io::ErrorKind::UnexpectedEof;

#[cfg(feature = "zstd")]
use zstd::block::decompress;

use super::*;

pub(super) trait LogReader {
    fn read_segment_header(
        &mut self,
        id: LogID,
    ) -> std::io::Result<SegmentHeader>;

    fn read_segment_trailer(
        &mut self,
        id: LogID,
    ) -> std::io::Result<SegmentTrailer>;

    fn read_message_header(
        &mut self,
        id: LogID,
    ) -> std::io::Result<MessageHeader>;

    fn read_message(
        &mut self,
        id: LogID,
        segment_len: usize,
        use_compression: bool,
    ) -> std::io::Result<LogRead>;
}

impl LogReader for File {
    fn read_segment_header(
        &mut self,
        id: LogID,
    ) -> std::io::Result<SegmentHeader> {
        trace!("reading segment header at {}", id);
        self.seek(SeekFrom::Start(id))?;

        let mut seg_header_buf = [0u8; SEG_HEADER_LEN];
        self.read_exact(&mut seg_header_buf)?;

        Ok(seg_header_buf.into())
    }

    fn read_segment_trailer(
        &mut self,
        id: LogID,
    ) -> std::io::Result<SegmentTrailer> {
        trace!("reading segment trailer at {}", id);
        self.seek(SeekFrom::Start(id))?;

        let mut seg_trailer_buf = [0u8; SEG_TRAILER_LEN];
        self.read_exact(&mut seg_trailer_buf)?;

        Ok(seg_trailer_buf.into())
    }

    fn read_message_header(
        &mut self,
        id: LogID,
    ) -> std::io::Result<MessageHeader> {
        self.seek(SeekFrom::Start(id))?;

        let mut msg_header_buf = [0u8; MSG_HEADER_LEN];
        self.read_exact(&mut msg_header_buf)?;

        Ok(msg_header_buf.into())
    }

    /// read a buffer from the disk
    fn read_message(
        &mut self,
        lid: LogID,
        segment_len: usize,
        _use_compression: bool,
    ) -> std::io::Result<LogRead> {
        let start = clock();
        let seg_start = lid / segment_len as LogID * segment_len as LogID;
        trace!("reading message from segment: {} at lid: {}", seg_start, lid);
        assert!(seg_start + MSG_HEADER_LEN as LogID <= lid);

        let ceiling = seg_start + segment_len as LogID -
            SEG_TRAILER_LEN as LogID;

        assert!(lid + MSG_HEADER_LEN as LogID <= ceiling);

        let header = self.read_message_header(lid)?;

        let max_possible_len = (ceiling - lid - MSG_HEADER_LEN as LogID) as
            usize;
        if header.len > max_possible_len {
            error!(
                "log read invalid message length, {} should be <= {}",
                header.len,
                max_possible_len
            );
            M.read.measure(clock() - start);
            trace!("read a corrupted message of len {}", header.len);
            return Ok(LogRead::Corrupted(header.len));
        }

        self.seek(SeekFrom::Start(lid + MSG_HEADER_LEN as LogID))?;

        let mut len = header.len;
        if len == 0 && !header.successful_flush {
            // skip to next record, which starts with 1
            while len <= max_possible_len {
                let mut byte = [0u8; 1];
                if let Err(e) = self.read_exact(&mut byte) {
                    if e.kind() == UnexpectedEof {
                        // we've hit the end of the file
                        break;
                    }
                    panic!("{:?}", e);
                }
                if byte[0] != 1 {
                    len += 1;
                } else {
                    break;
                }
            }
        }

        if !header.successful_flush {
            M.read.measure(clock() - start);
            trace!("read zeroes of len {}", len + MSG_HEADER_LEN);
            return Ok(LogRead::Zeroed(len + MSG_HEADER_LEN));
        }

        let mut buf = Vec::with_capacity(len);
        unsafe {
            buf.set_len(len);
        }
        self.read_exact(&mut buf)?;

        let checksum = crc16_arr(&buf);
        if checksum != header.crc16 {
            M.read.measure(clock() - start);
            trace!("read a message with a bad checksum of len {}", len);
            return Ok(LogRead::Corrupted(len));
        }

        #[cfg(feature = "zstd")]
        let res = {
            if _use_compression {
                let start = clock();
                let res = Ok(LogRead::Flush(
                    header.lsn,
                    decompress(&*buf, segment_len).unwrap(),
                    len,
                ));
                M.decompress.measure(clock() - start);
                res
            } else {
                Ok(LogRead::Flush(header.lsn, buf, len))
            }
        };

        #[cfg(not(feature = "zstd"))]
        let res = Ok(LogRead::Flush(header.lsn, buf, len));

        M.read.measure(clock() - start);
        trace!("read a successful flushed message");
        res
    }
}
<|endoftext|>