<commit_before>#![macro_use]
use core::{Request, Response};
use futures::Future;
use proto::MiddleWare;
use std::sync::Arc;

/// This trait is automatically derived by the #[service] proc_macro.
pub trait ArcService: Send + Sync {
	fn call(&self, req: Request, res: Response) -> Box<Future<Item = Response, Error = Response>>;
}

pub type FutureResponse = Box<Future<Item = Response, Error = Response>>;

pub struct ArcHandler {
	pub before: Option<Arc<Box<MiddleWare<Request>>>>,
	pub handler: Arc<Box<ArcService>>,
	pub after: Option<Arc<Box<MiddleWare<Response>>>>,
}

impl ArcHandler {
	pub fn new<T: 'static + ArcService>(h: T) -> Self {
		Self {
			before: None,
			handler: Arc::new(box h),
			after: None,
		}
	}

	pub fn before<T: 'static + MiddleWare<Request>>(&mut self, before: T) {
		self.before = Some(Arc::new(box before));
	}

	pub fn after<T: 'static + MiddleWare<Response>>(&mut self, after: T) {
		self.after = Some(Arc::new(box after));
	}
}

impl ArcService for ArcHandler {
	fn call(&self, req: Request, res: Response) -> FutureResponse {
		if self.before.is_some() && self.after.is_none() {
			let before = self.before.clone().unwrap();
			let handler = self.handler.clone();
			return box before.call(req).and_then(move |req| handler.call(req, res));
		}

		if self.before.is_none() && self.after.is_some() {
			let after = self.after.clone().unwrap();
			let handler = self.handler.clone();
			return box handler.call(req, res).and_then(move |res| after.call(res));
		}

		if self.before.is_some() && self.after.is_some() {
			let before = self.before.clone().unwrap();
			let handler = self.handler.clone();
			let after = self.after.clone().unwrap();
			return box before
				.call(req)
				.and_then(move |req| handler.call(req, res))
				.and_then(move |res| after.call(res));
		}

		return box self.handler.call(req, res);
	}
}

/// This macro exists for composing a route handler with middlewares in order
/// to mount them on a router.
///
/// ```rust,ignore
/// fn rootRoutes() -> Router {
///   let RequestMiddlewares = mw![middleware1, middleware2];
///   let ResponseMiddlewares = mw![middleware3, middleware4];
///   Router::new()
///     .get("/", arc!(RequestMiddlewares, RouteHandler, ResponseMiddlewares)) // set both middlewares and Routehandler
///     .get("/test", arc!(RequestMiddleware, RouteHandler)) // set only the request middleware and route handler
///     .get("/test2", arc!(_, RouteHandler, ResponseMiddlewares)) // set only the response middleware and routehandler
/// }
/// ```
#[macro_export]
macro_rules! arc {
	($handler:expr) => {{
		use std::sync::Arc;
		use $crate::ArcHandler;
		ArcHandler::new(box $handler)
		}};
	($before:expr, $handler:expr) => {{
		use std::sync::Arc;
		use $crate::ArcHandler;
		let handler = ArcHandler::new(box $handler);
		handler.before($before);
		handler
		}};
	($before:expr, $handler:expr, $after:expr) => {{
		use std::sync::Arc;
		use $crate::ArcHandler;
		let handler = ArcHandler::new(box $handler);
		handler.before($before);
		handler.after($after);
		handler
		}};
	(_, $handler:expr, $after:expr) => {{
		use std::sync::Arc;
		use $crate::ArcHandler;
		handler.after($before);
		handler
		}};
}
<commit_msg>refactored ArcHandler and arc macro<commit_after>#![macro_use]
use core::{Request, Response};
use futures::Future;
use proto::MiddleWare;
use std::sync::Arc;

/// This trait is automatically derived by the #[service] proc_macro.
pub trait ArcService: Send + Sync {
	fn call(&self, req: Request, res: Response) -> Box<Future<Item = Response, Error = Response>>;
}

pub type FutureResponse = Box<Future<Item = Response, Error = Response>>;

pub struct ArcHandler {
	pub before: Option<Arc<Box<MiddleWare<Request>>>>,
	pub handler: Arc<Box<ArcService>>,
	pub after: Option<Arc<Box<MiddleWare<Response>>>>,
}

impl ArcHandler {
	pub fn new<T: 'static + ArcService>(h: T) -> Self {
		Self {
			before: None,
			handler: Arc::new(box h),
			after: None,
		}
	}

	pub fn before<T: 'static + MiddleWare<Request>>(&mut self, before: T) {
		self.before = Some(Arc::new(box before));
	}

	pub fn after<T: 'static + MiddleWare<Response>>(&mut self, after: T) {
		self.after = Some(Arc::new(box after));
	}
}

impl ArcService for ArcHandler {
	fn call(&self, req: Request, res: Response) -> FutureResponse {
		if self.before.is_some() && self.after.is_none() {
			let before = self.before.clone().unwrap();
			let handler = self.handler.clone();
			return box before.call(req).and_then(move |req| handler.call(req, res));
		}

		if self.before.is_none() && self.after.is_some() {
			let after = self.after.clone().unwrap();
			let handler = self.handler.clone();
			return box handler.call(req, res).and_then(move |res| after.call(res));
		}

		if self.before.is_some() && self.after.is_some() {
			let before = self.before.clone().unwrap();
			let handler = self.handler.clone();
			let after = self.after.clone().unwrap();
			return box before
				.call(req)
				.and_then(move |req| handler.call(req, res))
				.and_then(move |res| after.call(res));
		}

		return box self.handler.call(req, res);
	}
}

/// This macro exists for composing a route handler with middlewares in order
/// to mount them on a router.
///
/// ```rust,ignore
/// fn rootRoutes() -> Router {
///   let RequestMiddlewares = mw![middleware1, middleware2];
///   let ResponseMiddlewares = mw![middleware3, middleware4];
///   Router::new()
///     .get("/", arc!(RequestMiddlewares, RouteHandler, ResponseMiddlewares)) // set both middlewares and Routehandler
///     .get("/test", arc!(RequestMiddleware, RouteHandler)) // set only the request middleware and route handler
///     .get("/test2", arc!(_, RouteHandler, ResponseMiddlewares)) // set only the response middleware and routehandler
/// }
/// ```
#[macro_export]
macro_rules! arc {
	($handler:expr) => {{
		use $crate::ArcHandler;
		ArcHandler::new($handler)
		}};
	($before:expr, $handler:expr) => {{
		use $crate::ArcHandler;
		let mut handler = ArcHandler::new($handler);
		handler.before($before);
		handler
		}};
	($before:expr, $handler:expr, $after:expr) => {{
		use $crate::ArcHandler;
		let mut handler = ArcHandler::new($handler);
		handler.before($before);
		handler.after($after);
		handler
		}};
	(_, $handler:expr, $after:expr) => {{
		use $crate::ArcHandler;
		let mut handler = ArcHandler::new($handler);
		handler.after($before);
		handler
		}};
}
<|endoftext|>


<commit_before>use super::*;

use bifrost::raft::state_machine::StateMachineCtl;
use bifrost::raft::state_machine::callback::server::{SMCallback, NotifyError};
use bifrost::raft::RaftService;
use bifrost::utils::bincode;
use bifrost_hasher::hash_str;

use std::sync::Arc;

pub static SM_ID_PREFIX: &'static str = "NEB_SCHEMAS_SM";

pub fn generate_sm_id<'a>(group: &'a str) -> u64 {
    hash_str(&format!("{}-{}", SM_ID_PREFIX, group))
}

pub struct SchemasSM {
    callback: SMCallback,
    map: Arc<RwLock<SchemasMap>>,
    sm_id: u64
}

raft_state_machine! {
    def qry get_all() -> Vec<Schema>;
    def qry get(id: u32) -> Option<Schema>;
    def cmd new_schema(schema: Schema) | NotifyError;
    def cmd del_schema(name: String) | NotifyError;
    def cmd next_id() -> u32;
    def sub on_schema_added() -> Schema;
    def sub on_schema_deleted() -> String;
}

impl StateMachineCmds for SchemasSM {
    fn get_all(&self) -> Result<Vec<Schema>, ()> {
        let m = self.map.read();
        Ok(m.get_all())
    }
    fn get(&self, id: u32) -> Result<Option<Schema>, ()> {
        let m = self.map.read();
        Ok(m.get(&id).map(
            |r: Arc<Schema>| -> Schema {
                let borrow: &Schema = r.borrow();
                borrow.clone()
            }
        ))
    }
    fn new_schema(&mut self, schema: Schema) -> Result<(), NotifyError> {
        {
            let mut map = self.map.write();
            map.new_schema(schema.clone());
        }
        self.callback.notify(&commands::on_schema_added::new(), Ok(schema))?;
        Ok(())
    }
    fn del_schema(&mut self, name: String) -> Result<(), NotifyError> {
        {
            let mut map = self.map.write();
            map.del_schema(&name);
        }
        self.callback.notify(&commands::on_schema_deleted::new(), Ok(name))?;
        Ok(())
    }
    fn next_id(&mut self) -> Result<u32, ()> {
        let mut map = self.map.write();
        Ok(map.next_id())
    }
}

impl StateMachineCtl for SchemasSM {
    raft_sm_complete!();
    fn snapshot(&self) -> Option<Vec<u8>> {
        let map = self.map.read();
        Some(bincode::serialize(&map.get_all()))
    }
    fn recover(&mut self, data: Vec<u8>) {
        let schemas: Vec<Schema> = bincode::deserialize(&data);
        let mut map = self.map.write();
        map.load_from_list(&schemas);
    }
    fn id(&self) -> u64 {self.sm_id }
}

impl SchemasSM {
    pub fn new<'a>(group: &'a str, raft_service: &Arc<RaftService>) -> SchemasSM {
        let sm_id = generate_sm_id(group);
        SchemasSM {
            callback: SMCallback::new(sm_id, raft_service.clone()),
            map: Arc::new(RwLock::new(SchemasMap::new())),
            sm_id: sm_id
        }
    }
}<commit_msg>get rid of lock in state machine<commit_after>use super::*;

use bifrost::raft::state_machine::StateMachineCtl;
use bifrost::raft::state_machine::callback::server::{SMCallback, NotifyError};
use bifrost::raft::RaftService;
use bifrost::utils::bincode;
use bifrost_hasher::hash_str;

use std::sync::Arc;

pub static SM_ID_PREFIX: &'static str = "NEB_SCHEMAS_SM";

pub fn generate_sm_id<'a>(group: &'a str) -> u64 {
    hash_str(&format!("{}-{}", SM_ID_PREFIX, group))
}

pub struct SchemasSM {
    callback: SMCallback,
    map: SchemasMap,
    sm_id: u64
}

raft_state_machine! {
    def qry get_all() -> Vec<Schema>;
    def qry get(id: u32) -> Option<Schema>;
    def cmd new_schema(schema: Schema) | NotifyError;
    def cmd del_schema(name: String) | NotifyError;
    def cmd next_id() -> u32;
    def sub on_schema_added() -> Schema;
    def sub on_schema_deleted() -> String;
}

impl StateMachineCmds for SchemasSM {
    fn get_all(&self) -> Result<Vec<Schema>, ()> {
        Ok(self.map.get_all())
    }
    fn get(&self, id: u32) -> Result<Option<Schema>, ()> {
        Ok(self.map.get(&id).map(
            |r| -> Schema {
                let borrow: &Schema = r.borrow();
                borrow.clone()
            }
        ))
    }
    fn new_schema(&mut self, schema: Schema) -> Result<(), NotifyError> {
        self.map.new_schema(schema.clone());
        self.callback.notify(&commands::on_schema_added::new(), Ok(schema))?;
        Ok(())
    }
    fn del_schema(&mut self, name: String) -> Result<(), NotifyError> {
        self.map.del_schema(&name);
        self.callback.notify(&commands::on_schema_deleted::new(), Ok(name))?;
        Ok(())
    }
    fn next_id(&mut self) -> Result<u32, ()> {
        Ok(self.map.next_id())
    }
}

impl StateMachineCtl for SchemasSM {
    raft_sm_complete!();
    fn snapshot(&self) -> Option<Vec<u8>> {
        Some(bincode::serialize(&self.map.get_all()))
    }
    fn recover(&mut self, data: Vec<u8>) {
        let schemas: Vec<Schema> = bincode::deserialize(&data);
        self.map.load_from_list(&schemas);
    }
    fn id(&self) -> u64 {self.sm_id }
}

impl SchemasSM {
    pub fn new<'a>(group: &'a str, raft_service: &Arc<RaftService>) -> SchemasSM {
        let sm_id = generate_sm_id(group);
        SchemasSM {
            callback: SMCallback::new(sm_id, raft_service.clone()),
            map: SchemasMap::new(),
            sm_id
        }
    }
}<|endoftext|>


<commit_before>//! Contains `XmlEvent` datatype, instances of which are emitted by the parser.

use std::fmt;

use common;
use common::{Name, Error, HasPosition, Attribute, XmlVersion};
use namespace::Namespace;

/// An element of an XML input stream.
///
/// Items of this enum are emitted by `reader::EventReader`. They correspond to different
/// elements of an XML document.
#[deriving(PartialEq, Clone)]
pub enum XmlEvent {
    /// Corresponds to XML document declaration.
    ///
    /// This event is always emitted before any other event (except `Error`). It is emitted
    /// even if the actual declaration is not present in the document.
    StartDocument {
        /// XML version.
        ///
        /// If XML declaration is not present, defaults to `Version10`.
        pub version: XmlVersion,

        /// XML document encoding.
        ///
        /// If XML declaration is not present or does not contain `encoding` attribute,
        /// defaults to `"UTF-8"`. This field is currently used for no other purpose than
        /// informational.
        pub encoding: String,

        /// XML standalone declaration.
        ///
        /// If XML document is not present or does not contain `standalone` attribute,
        /// defaults to `None`. This field is currently used for no other purpose than
        /// informational.
        pub standalone: Option<bool>
    },

    /// Denotes to the end of the document stream.
    ///
    /// This event is always emitted after any other event (except `Error`). After it
    /// is emitted for the first time, it will always be emitted on next event pull attempts.
    EndDocument,

    /// Denotes an XML processing instruction.
    ///
    /// This event contains a processing instruction target (`name`) and opaque `data`. It
    /// is up to the application to process them.
    ProcessingInstruction {
        /// Processing instruction target.
        pub name: String,

        /// Processing instruction content.
        pub data: Option<String>
    },

    /// Denotes a beginning of an XML element.
    ///
    /// This event is emitted after parsing opening tags or after parsing bodiless tags. In the
    /// latter case `EndElement` event immediately follows.
    StartElement {
        /// Qualified name of the element.
        pub name: Name,

        /// A list of attributes associated with the element.
        ///
        /// Currently attributes are not checked for duplicates (TODO)
        pub attributes: Vec<Attribute>,

        /// Contents of the namespace mapping at this point of the document.
        pub namespace: Namespace,
    },

    /// Denotes an end of an XML document.
    ///
    /// This event is emitted after parsing closing tags or after parsing bodiless tags. In the
    /// latter case it is emitted immediately after corresponding `StartElement` event.
    EndElement {
        /// Qualified name of the element.
        pub name: Name
    },

    /// Denotes CDATA content.
    ///
    /// This event contains unparsed data. No unescaping will be performed.
    ///
    /// It is possible to configure a parser to emit `Characters` event instead of `CData`. See
    /// `pull::ParserConfiguration` structure for more information.
    CData(String),

    /// Denotes a comment.
    ///
    /// It is possible to configure a parser to ignore comments, so this event will never be emitted.
    /// See `pull::ParserConfiguration` structure for more information.
    Comment(String),

    /// Denotes character data outside of tags.
    ///
    /// Contents of this event will always be unescaped, so no entities like `<` or `&` or `{`
    /// will appear in it.
    ///
    /// It is possible to configure a parser to trim leading and trailing whitespace for this event.
    /// See `pull::ParserConfiguration` structure for more information.
    Characters(String),

    /// Denotes a chunk of whitespace outside of tags.
    ///
    /// It is possible to configure a parser to emit `Characters` event instead of `Whitespace`.
    /// See `pull::ParserConfiguration` structure for more information. When combined with whitespace
    /// trimming, it will eliminate standalone whitespace from the event stream completely.
    Whitespace(String),

    /// Denotes parsing error.
    ///
    /// This event will always be the last event in the stream; no further XML processing will be done
    /// as is required by XML specification, [section 1.2][1].
    ///
    /// [1]: http://www.w3.org/TR/2006/REC-xml11-20060816/#sec-terminology
    Error(common::Error)
}

impl fmt::Show for XmlEvent {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StartDocument { ref version, ref encoding, ref standalone } =>
                write!(f, "StartDocument({}, {}, {})", version, *encoding, *standalone),
            EndDocument =>
                write!(f, "EndDocument"),
            ProcessingInstruction { ref name, ref data } =>
                write!(f, "ProcessingInstruction({}{})", *name, match *data {
                    Some(ref data) => format!(", {}", data),
                    None       => String::new()
                }),
            StartElement { ref name, ref attributes, namespace: Namespace(ref namespace) } =>
                write!(f, "StartElement({}, {}{})", name, namespace, if attributes.is_empty() {
                    String::new()
                } else {
                    let attributes: Vec<String> = attributes.iter().map(
                        |a| format!("{} -> {}", a.name, a.value)
                    ).collect();
                    format!(", [{}]", attributes.connect(", "))
                }),
            EndElement { ref name } =>
                write!(f, "EndElement({})", name),
            Comment(ref data) =>
                write!(f, "Comment({})", data),
            CData(ref data) =>
                write!(f, "CData({})", data),
            Characters(ref data) =>
                write!(f, "Characters({})", data),
            Whitespace(ref data) =>
                write!(f, "Whitespace({})", data),
            Error(ref e) =>
                write!(f, "Error(row: {}, col: {}, message: {})", e.row()+1, e.col()+1, e.msg())
        }
    }
}

impl XmlEvent {
    pub fn as_writer_event<'a>(&'a self) -> Option<::writer::events::XmlEvent<'a>> {
        match *self {
            StartDocument { version, ref encoding, standalone } =>
                Some(::writer::events::StartDocument {
                    version: version,
                    encoding: Some(encoding.as_slice()),
                    standalone: standalone
                }),
            ProcessingInstruction { ref name, ref data } =>
                Some(::writer::events::ProcessingInstruction {
                    name: name.as_slice(),
                    data: data.as_ref().map(|s| s.as_slice())
                }),
            StartElement { ref name, ref attributes, ref namespace } =>
                Some(::writer::events::StartElement {
                    name: name,
                    attributes: attributes.as_slice(),
                    namespace: namespace
                }),
            EndElement { ref name } =>
                Some(::writer::events::EndElement { name: name }),
            Comment(ref data) => Some(::writer::events::Comment(data.as_slice())),
            CData(ref data) => Some(::writer::events::CData(data.as_slice())),
            Characters(ref data) => Some(::writer::events::Characters(data.as_slice())),
            Whitespace(ref data) => Some(::writer::events::Characters(data.as_slice())),
            _ => None
        }
    }
}
<commit_msg>Update to rustc d7e1bb5ff 2014-09-21 01:00:29 +0000<commit_after>//! Contains `XmlEvent` datatype, instances of which are emitted by the parser.

use std::fmt;

use common;
use common::{Name, HasPosition, Attribute, XmlVersion};
use common::Error as CommonError;
use namespace::Namespace;

/// An element of an XML input stream.
///
/// Items of this enum are emitted by `reader::EventReader`. They correspond to different
/// elements of an XML document.
#[deriving(PartialEq, Clone)]
pub enum XmlEvent {
    /// Corresponds to XML document declaration.
    ///
    /// This event is always emitted before any other event (except `Error`). It is emitted
    /// even if the actual declaration is not present in the document.
    StartDocument {
        /// XML version.
        ///
        /// If XML declaration is not present, defaults to `Version10`.
        pub version: XmlVersion,

        /// XML document encoding.
        ///
        /// If XML declaration is not present or does not contain `encoding` attribute,
        /// defaults to `"UTF-8"`. This field is currently used for no other purpose than
        /// informational.
        pub encoding: String,

        /// XML standalone declaration.
        ///
        /// If XML document is not present or does not contain `standalone` attribute,
        /// defaults to `None`. This field is currently used for no other purpose than
        /// informational.
        pub standalone: Option<bool>
    },

    /// Denotes to the end of the document stream.
    ///
    /// This event is always emitted after any other event (except `Error`). After it
    /// is emitted for the first time, it will always be emitted on next event pull attempts.
    EndDocument,

    /// Denotes an XML processing instruction.
    ///
    /// This event contains a processing instruction target (`name`) and opaque `data`. It
    /// is up to the application to process them.
    ProcessingInstruction {
        /// Processing instruction target.
        pub name: String,

        /// Processing instruction content.
        pub data: Option<String>
    },

    /// Denotes a beginning of an XML element.
    ///
    /// This event is emitted after parsing opening tags or after parsing bodiless tags. In the
    /// latter case `EndElement` event immediately follows.
    StartElement {
        /// Qualified name of the element.
        pub name: Name,

        /// A list of attributes associated with the element.
        ///
        /// Currently attributes are not checked for duplicates (TODO)
        pub attributes: Vec<Attribute>,

        /// Contents of the namespace mapping at this point of the document.
        pub namespace: Namespace,
    },

    /// Denotes an end of an XML document.
    ///
    /// This event is emitted after parsing closing tags or after parsing bodiless tags. In the
    /// latter case it is emitted immediately after corresponding `StartElement` event.
    EndElement {
        /// Qualified name of the element.
        pub name: Name
    },

    /// Denotes CDATA content.
    ///
    /// This event contains unparsed data. No unescaping will be performed.
    ///
    /// It is possible to configure a parser to emit `Characters` event instead of `CData`. See
    /// `pull::ParserConfiguration` structure for more information.
    CData(String),

    /// Denotes a comment.
    ///
    /// It is possible to configure a parser to ignore comments, so this event will never be emitted.
    /// See `pull::ParserConfiguration` structure for more information.
    Comment(String),

    /// Denotes character data outside of tags.
    ///
    /// Contents of this event will always be unescaped, so no entities like `<` or `&` or `{`
    /// will appear in it.
    ///
    /// It is possible to configure a parser to trim leading and trailing whitespace for this event.
    /// See `pull::ParserConfiguration` structure for more information.
    Characters(String),

    /// Denotes a chunk of whitespace outside of tags.
    ///
    /// It is possible to configure a parser to emit `Characters` event instead of `Whitespace`.
    /// See `pull::ParserConfiguration` structure for more information. When combined with whitespace
    /// trimming, it will eliminate standalone whitespace from the event stream completely.
    Whitespace(String),

    /// Denotes parsing error.
    ///
    /// This event will always be the last event in the stream; no further XML processing will be done
    /// as is required by XML specification, [section 1.2][1].
    ///
    /// [1]: http://www.w3.org/TR/2006/REC-xml11-20060816/#sec-terminology
    Error(CommonError)
}

impl fmt::Show for XmlEvent {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StartDocument { ref version, ref encoding, ref standalone } =>
                write!(f, "StartDocument({}, {}, {})", version, *encoding, *standalone),
            EndDocument =>
                write!(f, "EndDocument"),
            ProcessingInstruction { ref name, ref data } =>
                write!(f, "ProcessingInstruction({}{})", *name, match *data {
                    Some(ref data) => format!(", {}", data),
                    None       => String::new()
                }),
            StartElement { ref name, ref attributes, namespace: Namespace(ref namespace) } =>
                write!(f, "StartElement({}, {}{})", name, namespace, if attributes.is_empty() {
                    String::new()
                } else {
                    let attributes: Vec<String> = attributes.iter().map(
                        |a| format!("{} -> {}", a.name, a.value)
                    ).collect();
                    format!(", [{}]", attributes.connect(", "))
                }),
            EndElement { ref name } =>
                write!(f, "EndElement({})", name),
            Comment(ref data) =>
                write!(f, "Comment({})", data),
            CData(ref data) =>
                write!(f, "CData({})", data),
            Characters(ref data) =>
                write!(f, "Characters({})", data),
            Whitespace(ref data) =>
                write!(f, "Whitespace({})", data),
            Error(ref e) =>
                write!(f, "Error(row: {}, col: {}, message: {})", e.row()+1, e.col()+1, e.msg())
        }
    }
}

impl XmlEvent {
    pub fn as_writer_event<'a>(&'a self) -> Option<::writer::events::XmlEvent<'a>> {
        match *self {
            StartDocument { version, ref encoding, standalone } =>
                Some(::writer::events::StartDocument {
                    version: version,
                    encoding: Some(encoding.as_slice()),
                    standalone: standalone
                }),
            ProcessingInstruction { ref name, ref data } =>
                Some(::writer::events::ProcessingInstruction {
                    name: name.as_slice(),
                    data: data.as_ref().map(|s| s.as_slice())
                }),
            StartElement { ref name, ref attributes, ref namespace } =>
                Some(::writer::events::StartElement {
                    name: name,
                    attributes: attributes.as_slice(),
                    namespace: namespace
                }),
            EndElement { ref name } =>
                Some(::writer::events::EndElement { name: name }),
            Comment(ref data) => Some(::writer::events::Comment(data.as_slice())),
            CData(ref data) => Some(::writer::events::CData(data.as_slice())),
            Characters(ref data) => Some(::writer::events::Characters(data.as_slice())),
            Whitespace(ref data) => Some(::writer::events::Characters(data.as_slice())),
            _ => None
        }
    }
}
<|endoftext|>


<commit_before>// I think borrowed boxing is necessary for objekt::clone_box to work
#![allow(clippy::borrowed_box)]

//! UI event handling

use crate::cmd::{parse_cmd, CmdArgs, ParseCmdResult};
use crate::config;
use futures::stream::StreamExt;
use libtiny_client::Client;
use libtiny_common::{ChanNameRef, MsgSource, MsgTarget, TabStyle};
use libtiny_logger::Logger;
use libtiny_tui::TUI;
use std::path::{Path, PathBuf};
use time::Tm;
use tokio::sync::mpsc;

macro_rules! delegate {
    ( $name:ident ( $( $x:ident: $t:ty, )* )) => {
        pub(crate) fn $name(&self, $($x: $t,)*) {
            self.ui.$name( $( $x, )* );
            if let Some(logger) = &self.logger {
                logger.$name( $( $x, )* );
            }
        }
    }
}

macro_rules! delegate_ui {
    ( $name:ident ( $( $x:ident: $t:ty, )* ) $(->$ret:ty )? ) => {
        pub(crate) fn $name(&self, $($x: $t,)*) $(-> $ret)? {
            self.ui.$name( $( $x, )* )
        }
    }
}

#[derive(Clone)]
pub(crate) struct UI {
    ui: TUI,
    logger: Option<Logger>,
}

impl UI {
    pub(crate) fn new(ui: TUI, logger: Option<Logger>) -> UI {
        UI { ui, logger }
    }

    pub(crate) fn new_server_tab(&self, serv_name: &str, alias: Option<String>) {
        self.ui.new_server_tab(serv_name, alias);
        if let Some(logger) = &self.logger {
            logger.new_server_tab(serv_name);
        }
    }

    delegate!(close_server_tab(serv: &str,));
    delegate!(new_chan_tab(serv: &str, chan: &ChanNameRef,));
    delegate!(close_chan_tab(serv: &str, chan: &ChanNameRef,));
    delegate!(close_user_tab(serv: &str, nick: &str,));
    delegate!(add_client_msg(msg: &str, target: &MsgTarget,));
    delegate!(add_msg(msg: &str, ts: Tm, target: &MsgTarget,));
    delegate!(add_privmsg(
        sender: &str,
        msg: &str,
        ts: Tm,
        target: &MsgTarget,
        highlight: bool,
        is_action: bool,
    ));
    delegate!(add_nick(nick: &str, ts: Option<Tm>, target: &MsgTarget,));
    delegate!(remove_nick(nick: &str, ts: Option<Tm>, target: &MsgTarget,));
    delegate!(rename_nick(
        old_nick: &str,
        new_nick: &str,
        ts: Tm,
        target: &MsgTarget,
    ));
    delegate!(set_topic(
        topic: &str,
        ts: Tm,
        serv: &str,
        chan: &ChanNameRef,
    ));

    delegate_ui!(draw());
    delegate_ui!(add_err_msg(msg: &str, ts: Tm, target: &MsgTarget,));
    delegate_ui!(add_client_err_msg(msg: &str, target: &MsgTarget,));
    delegate_ui!(clear_nicks(serv: &str,));
    delegate_ui!(set_nick(serv: &str, nick: &str,));
    delegate_ui!(set_tab_style(style: TabStyle, target: &MsgTarget,));
    delegate_ui!(user_tab_exists(serv_name: &str, nick: &str,) -> bool);
}

pub(crate) async fn task(
    config_path: PathBuf,
    defaults: config::Defaults,
    ui: UI,
    mut clients: Vec<Client>,
    mut rcv_ev: mpsc::Receiver<libtiny_common::Event>,
) {
    while let Some(ev) = rcv_ev.next().await {
        handle_input_ev(&config_path, &defaults, &ui, &mut clients, ev);
        ui.draw();
    }
}

fn handle_input_ev(
    config_path: &Path,
    defaults: &config::Defaults,
    ui: &UI,
    clients: &mut Vec<Client>,
    ev: libtiny_common::Event,
) {
    use libtiny_common::Event::*;
    match ev {
        Abort => {
            for client in clients {
                client.quit(None);
            }
        }
        Msg { msg, source } => {
            send_msg(ui, clients, &source, msg, false);
        }
        Lines { lines, source } => {
            for line in lines.into_iter() {
                send_msg(ui, clients, &source, line, false)
            }
        }
        Cmd { cmd, source } => handle_cmd(config_path, defaults, ui, clients, source, &cmd),
    }
}

fn handle_cmd(
    config_path: &Path,
    defaults: &config::Defaults,
    ui: &UI,
    clients: &mut Vec<Client>,
    src: MsgSource,
    cmd: &str,
) {
    match parse_cmd(cmd) {
        ParseCmdResult::Ok { cmd, rest } => {
            let cmd_args = CmdArgs {
                args: rest,
                config_path,
                defaults,
                ui,
                clients,
                src,
            };
            (cmd.cmd_fn)(cmd_args);
        }
        // ParseCmdResult::Ambiguous(vec) => {
        //     self.ui.add_client_err_msg(
        //         &format!("Unsupported command: \"/{}\"", msg),
        //         &MsgTarget::CurrentTab,
        //     );
        //     self.ui.add_client_err_msg(
        //         &format!("Did you mean one of {:?} ?", vec),
        //         &MsgTarget::CurrentTab,
        //     );
        // },
        ParseCmdResult::Unknown => ui.add_client_err_msg(
            &format!("Unsupported command: \"/{}\"", cmd),
            &MsgTarget::CurrentTab,
        ),
    }
}

// TODO: move this somewhere else
pub(crate) fn send_msg(
    ui: &UI,
    clients: &mut Vec<Client>,
    src: &MsgSource,
    msg: String,
    is_action: bool,
) {
    if src.serv_name() == "mentions" {
        ui.add_client_err_msg(
            "Use `/connect <server>` to connect to a server",
            &MsgTarget::CurrentTab,
        );
        return;
    }

    let client = clients
        .iter_mut()
        .find(|client| client.get_serv_name() == src.serv_name())
        .unwrap();

    // TODO: For errors:
    //
    // ui.add_client_err_msg(
    //     &format!("Can't find server: {}", serv),
    //     &MsgTarget::CurrentTab,
    // );

    // `ui_target`: Where to show the message on ui
    // `msg_target`: Actual PRIVMSG target to send to the server
    let (ui_target, msg_target): (MsgTarget, &str) = {
        match src {
            MsgSource::Serv { .. } => {
                // we don't split raw messages to 512-bytes long chunks
                client.raw_msg(&msg);
                return;
            }

            MsgSource::Chan { ref serv, ref chan } => {
                (MsgTarget::Chan { serv, chan }, chan.display())
            }

            MsgSource::User { ref serv, ref nick } => {
                let msg_target = if nick.eq_ignore_ascii_case("nickserv")
                    || nick.eq_ignore_ascii_case("chanserv")
                {
                    MsgTarget::Server { serv }
                } else {
                    MsgTarget::User { serv, nick }
                };
                (msg_target, nick)
            }
        }
    };

    let ts = time::now();
    let extra_len = msg_target.len()
        + if is_action {
            9 // "\0x1ACTION \0x1".len()
        } else {
            0
        };
    for msg in client.split_privmsg(extra_len, &msg) {
        client.privmsg(msg_target, msg, is_action);
        ui.add_privmsg(&client.get_nick(), msg, ts, &ui_target, false, is_action);
    }
}
<commit_msg>chore: more friendly error message (#329)<commit_after>// I think borrowed boxing is necessary for objekt::clone_box to work
#![allow(clippy::borrowed_box)]

//! UI event handling

use crate::cmd::{parse_cmd, CmdArgs, ParseCmdResult};
use crate::config;
use futures::stream::StreamExt;
use libtiny_client::Client;
use libtiny_common::{ChanNameRef, MsgSource, MsgTarget, TabStyle};
use libtiny_logger::Logger;
use libtiny_tui::TUI;
use std::path::{Path, PathBuf};
use time::Tm;
use tokio::sync::mpsc;

macro_rules! delegate {
    ( $name:ident ( $( $x:ident: $t:ty, )* )) => {
        pub(crate) fn $name(&self, $($x: $t,)*) {
            self.ui.$name( $( $x, )* );
            if let Some(logger) = &self.logger {
                logger.$name( $( $x, )* );
            }
        }
    }
}

macro_rules! delegate_ui {
    ( $name:ident ( $( $x:ident: $t:ty, )* ) $(->$ret:ty )? ) => {
        pub(crate) fn $name(&self, $($x: $t,)*) $(-> $ret)? {
            self.ui.$name( $( $x, )* )
        }
    }
}

#[derive(Clone)]
pub(crate) struct UI {
    ui: TUI,
    logger: Option<Logger>,
}

impl UI {
    pub(crate) fn new(ui: TUI, logger: Option<Logger>) -> UI {
        UI { ui, logger }
    }

    pub(crate) fn new_server_tab(&self, serv_name: &str, alias: Option<String>) {
        self.ui.new_server_tab(serv_name, alias);
        if let Some(logger) = &self.logger {
            logger.new_server_tab(serv_name);
        }
    }

    delegate!(close_server_tab(serv: &str,));
    delegate!(new_chan_tab(serv: &str, chan: &ChanNameRef,));
    delegate!(close_chan_tab(serv: &str, chan: &ChanNameRef,));
    delegate!(close_user_tab(serv: &str, nick: &str,));
    delegate!(add_client_msg(msg: &str, target: &MsgTarget,));
    delegate!(add_msg(msg: &str, ts: Tm, target: &MsgTarget,));
    delegate!(add_privmsg(
        sender: &str,
        msg: &str,
        ts: Tm,
        target: &MsgTarget,
        highlight: bool,
        is_action: bool,
    ));
    delegate!(add_nick(nick: &str, ts: Option<Tm>, target: &MsgTarget,));
    delegate!(remove_nick(nick: &str, ts: Option<Tm>, target: &MsgTarget,));
    delegate!(rename_nick(
        old_nick: &str,
        new_nick: &str,
        ts: Tm,
        target: &MsgTarget,
    ));
    delegate!(set_topic(
        topic: &str,
        ts: Tm,
        serv: &str,
        chan: &ChanNameRef,
    ));

    delegate_ui!(draw());
    delegate_ui!(add_err_msg(msg: &str, ts: Tm, target: &MsgTarget,));
    delegate_ui!(add_client_err_msg(msg: &str, target: &MsgTarget,));
    delegate_ui!(clear_nicks(serv: &str,));
    delegate_ui!(set_nick(serv: &str, nick: &str,));
    delegate_ui!(set_tab_style(style: TabStyle, target: &MsgTarget,));
    delegate_ui!(user_tab_exists(serv_name: &str, nick: &str,) -> bool);
}

pub(crate) async fn task(
    config_path: PathBuf,
    defaults: config::Defaults,
    ui: UI,
    mut clients: Vec<Client>,
    mut rcv_ev: mpsc::Receiver<libtiny_common::Event>,
) {
    while let Some(ev) = rcv_ev.next().await {
        handle_input_ev(&config_path, &defaults, &ui, &mut clients, ev);
        ui.draw();
    }
}

fn handle_input_ev(
    config_path: &Path,
    defaults: &config::Defaults,
    ui: &UI,
    clients: &mut Vec<Client>,
    ev: libtiny_common::Event,
) {
    use libtiny_common::Event::*;
    match ev {
        Abort => {
            for client in clients {
                client.quit(None);
            }
        }
        Msg { msg, source } => {
            send_msg(ui, clients, &source, msg, false);
        }
        Lines { lines, source } => {
            for line in lines.into_iter() {
                send_msg(ui, clients, &source, line, false)
            }
        }
        Cmd { cmd, source } => handle_cmd(config_path, defaults, ui, clients, source, &cmd),
    }
}

fn handle_cmd(
    config_path: &Path,
    defaults: &config::Defaults,
    ui: &UI,
    clients: &mut Vec<Client>,
    src: MsgSource,
    cmd: &str,
) {
    match parse_cmd(cmd) {
        ParseCmdResult::Ok { cmd, rest } => {
            let cmd_args = CmdArgs {
                args: rest,
                config_path,
                defaults,
                ui,
                clients,
                src,
            };
            (cmd.cmd_fn)(cmd_args);
        }
        // ParseCmdResult::Ambiguous(vec) => {
        //     self.ui.add_client_err_msg(
        //         &format!("Unsupported command: \"/{}\"", msg),
        //         &MsgTarget::CurrentTab,
        //     );
        //     self.ui.add_client_err_msg(
        //         &format!("Did you mean one of {:?} ?", vec),
        //         &MsgTarget::CurrentTab,
        //     );
        // },
        ParseCmdResult::Unknown => ui.add_client_err_msg(
            &format!("Unsupported command: \"/{}\"", cmd),
            &MsgTarget::CurrentTab,
        ),
    }
}

// TODO: move this somewhere else
pub(crate) fn send_msg(
    ui: &UI,
    clients: &mut Vec<Client>,
    src: &MsgSource,
    msg: String,
    is_action: bool,
) {
    if src.serv_name() == "mentions" {
        if clients.len() == 0 {
            ui.add_client_err_msg(
                "No connected server found, please use `/connect <server>` to connect to a server",
                &MsgTarget::CurrentTab,
            );
        } else {
            ui.add_client_err_msg(
                "You are on the mentions tab, please use `/switch <tab name>` to switch to a tab",
                &MsgTarget::CurrentTab,
            );
        }
        return;
    }

    let client = clients
        .iter_mut()
        .find(|client| client.get_serv_name() == src.serv_name())
        .unwrap();

    // TODO: For errors:
    //
    // ui.add_client_err_msg(
    //     &format!("Can't find server: {}", serv),
    //     &MsgTarget::CurrentTab,
    // );

    // `ui_target`: Where to show the message on ui
    // `msg_target`: Actual PRIVMSG target to send to the server
    let (ui_target, msg_target): (MsgTarget, &str) = {
        match src {
            MsgSource::Serv { .. } => {
                // we don't split raw messages to 512-bytes long chunks
                client.raw_msg(&msg);
                return;
            }

            MsgSource::Chan { ref serv, ref chan } => {
                (MsgTarget::Chan { serv, chan }, chan.display())
            }

            MsgSource::User { ref serv, ref nick } => {
                let msg_target = if nick.eq_ignore_ascii_case("nickserv")
                    || nick.eq_ignore_ascii_case("chanserv")
                {
                    MsgTarget::Server { serv }
                } else {
                    MsgTarget::User { serv, nick }
                };
                (msg_target, nick)
            }
        }
    };

    let ts = time::now();
    let extra_len = msg_target.len()
        + if is_action {
            9 // "\0x1ACTION \0x1".len()
        } else {
            0
        };
    for msg in client.split_privmsg(extra_len, &msg) {
        client.privmsg(msg_target, msg, is_action);
        ui.add_privmsg(&client.get_nick(), msg, ts, &ui_target, false, is_action);
    }
}
<|endoftext|>


<commit_before>use serde_json::Value;
use std::fmt;

/// `S`ring/`I`nteger
/// a temporary type for strings that are integers
/// if a field with an integer as string is used, just use `.into()`

/// `S`ring/`I`nteger
/// a temporary type for strings that are integers
/// if a field with an integer as string is used, just use `.into()`
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum SI {
	I(i64),
	S(String),
}

impl From<SI> for i64 {
	fn from(si: SI) -> Self
	{
		match si
		{
			SI::I(i) => i,
			SI::S(s) => s.parse::<i64>().unwrap(),
		}
	}
}

impl fmt::Display for SI {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
	{
		write!(f, "{}", i64::from(self.to_owned()))
	}
}

#[derive(Debug, Clone, Deserialize)]
pub struct Fullentry {
	//#[serde(deserialize_with = "string_as_i64")]
	pub id: SI,
	pub names: Vec<Name>,
	pub genre: String,
	pub fsk: String,
	pub description: String,
	pub medium: String,
	pub count: String,
	pub state: String,
	pub rate_sum: String,
	pub rate_count: String,
	pub clicks: String,
	pub kat: String,
	pub license: String,
	pub tags: Vec<Tag>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct GetEntry {
	pub id: String,
	pub name: String,
	pub genre: String,
	pub fsk: String,
	pub description: String,
	pub medium: String,
	pub count: String,
	pub state: String,
	pub rate_sum: String,
	pub rate_count: String,
	pub clicks: String,
	pub kat: Value,
	pub license: Value,
}

#[derive(Debug, Clone, Deserialize)]
pub struct UserList {
	pub id: i64,
	pub name: String,
	pub description: String,
	pub genre: Vec<String>,
	pub fsk: Vec<String>,
	pub medium: String,
	pub count: i64,
	pub state: i64,
	pub rate_sum: i64,
	pub rate_count: i64,
	pub clicks: i64,
	pub kat: Kat,
	pub license: License,
}

#[derive(Debug, Clone, Deserialize)]
pub enum SpoilerFlag {
	#[serde(rename = "0")]
	NoSpoiler,
	#[serde(rename = "1")]
	Spoiler,
}

#[derive(Debug, Clone, Deserialize)]
pub enum RateFlag {
	#[serde(rename = "0")]
	NoMatch,
	#[serde(rename = "1")]
	Match,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Tag {
	pub info_id: Option<i64>,
	pub id: SI,
	#[serde(rename = "tid")]
	pub tag_id: SI,
	pub timestamp: String,
	pub rate_flag: RateFlag,
	pub spoiler_flag: SpoilerFlag,
	pub tag: String,
	pub description: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Name {
	id: String,
	eid: String,
	#[serde(rename = "type")]
	type_: String,
	name: String,
}

#[derive(Debug, Clone, Deserialize)]
pub enum WatchState {
	#[serde(rename = "0")]
	Watched,
	#[serde(rename = "1")]
	Watching,
	#[serde(rename = "2")]
	WillWatch,
	#[serde(rename = "3")]
	Cancelled,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Comment {
	pub id: SI,
	#[serde(rename = "tid")]
	pub info_id: SI,
	#[serde(rename = "type")]
	pub comment_type: String, // i have no idea what this is
	pub state: WatchState,
	pub data: String,
	pub comment: String,
	pub rating: SI,
	pub episode: SI,
	pub positive: SI,
	pub timestamp: SI, //Todo: use chrono here
	pub username: String,
	pub uid: String,
	pub avatar: String,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Userinfo {
	pub uid: i64,
	pub username: String,
	pub avatar: String, // use some sort of uri type here
	pub status: String,
	// status_time is sometimes a negative number. using i64
	pub status_time: i64,
	pub points_upload: i64,
	pub points_anime: i64,
	pub points_manga: i64,
	pub points_info: i64,
	pub points_forum: i64,
	pub points_misc: i64,
}

#[derive(Debug, Clone, Deserialize)]
pub enum Kat {
	Anime,
	Manga,
}

#[derive(Debug, Clone, Deserialize)]
pub enum License {
	Unknown,
	Unlicensed,
	Licensed,
}
<commit_msg>make fields `pub`lic fix types<commit_after>use serde_json::Value;
use std::fmt;

/// `S`ring/`I`nteger
/// a temporary type for strings that are integers
/// if a field with an integer as string is used, just use `.into()`

/// `S`ring/`I`nteger
/// a temporary type for strings that are integers
/// if a field with an integer as string is used, just use `.into()`
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum SI {
	I(i64),
	S(String),
}

impl From<SI> for i64 {
	fn from(si: SI) -> Self
	{
		match si
		{
			SI::I(i) => i,
			SI::S(s) => s.parse::<i64>().unwrap(),
		}
	}
}

impl fmt::Display for SI {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
	{
		write!(f, "{}", i64::from(self.to_owned()))
	}
}

#[derive(Debug, Clone, Deserialize)]
pub struct Fullentry {
	//#[serde(deserialize_with = "string_as_i64")]
	pub id: SI,
	pub names: Vec<Name>,
	pub genre: String,
	pub fsk: String,
	pub description: String,
	pub medium: String,
	pub count: String,
	pub state: String,
	pub rate_sum: String,
	pub rate_count: String,
	pub clicks: String,
	pub kat: String,
	pub license: String,
	pub tags: Vec<Tag>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct GetEntry {
	pub id: String,
	pub name: String,
	pub genre: String,
	pub fsk: String,
	pub description: String,
	pub medium: String,
	pub count: String,
	pub state: String,
	pub rate_sum: String,
	pub rate_count: String,
	pub clicks: String,
	pub kat: Value,
	pub license: Value,
}

#[derive(Debug, Clone, Deserialize)]
pub struct UserList {
	pub id: i64,
	pub name: String,
	pub description: String,
	pub genre: Vec<String>,
	pub fsk: Vec<String>,
	pub medium: String,
	pub count: i64,
	pub state: i64,
	pub rate_sum: i64,
	pub rate_count: i64,
	pub clicks: i64,
	pub kat: Kat,
	pub license: License,
}

#[derive(Debug, Clone, Deserialize)]
pub enum SpoilerFlag {
	#[serde(rename = "0")]
	NoSpoiler,
	#[serde(rename = "1")]
	Spoiler,
}

#[derive(Debug, Clone, Deserialize)]
pub enum RateFlag {
	#[serde(rename = "0")]
	NoMatch,
	#[serde(rename = "1")]
	Match,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Tag {
	pub info_id: Option<i64>,
	pub id: SI,
	#[serde(rename = "tid")]
	pub tag_id: SI,
	pub timestamp: String,
	pub rate_flag: RateFlag,
	pub spoiler_flag: SpoilerFlag,
	pub tag: String,
	pub description: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Name {
	pub id: String,
	pub eid: String,
	#[serde(rename = "type")]
	pub type_: String,
	pub name: String,
}

#[derive(Debug, Clone, Deserialize)]
pub enum WatchState {
	#[serde(rename = "0")]
	Watched,
	#[serde(rename = "1")]
	Watching,
	#[serde(rename = "2")]
	WillWatch,
	#[serde(rename = "3")]
	Cancelled,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Comment {
	pub id: SI,
	#[serde(rename = "tid")]
	pub info_id: SI,
	#[serde(rename = "type")]
	pub comment_type: String, // i have no idea what this is
	pub state: WatchState,
	pub data: String,
	pub comment: String,
	pub rating: SI,
	pub episode: SI,
	pub positive: SI,
	pub timestamp: SI, //Todo: use chrono here
	pub username: String,
	pub uid: SI,
	pub avatar: String,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Userinfo {
	pub uid: i64,
	pub username: String,
	pub avatar: String, // use some sort of uri type here
	pub status: String,
	// status_time is sometimes a negative number. using i64
	pub status_time: i64,
	pub points_upload: i64,
	pub points_anime: i64,
	pub points_manga: i64,
	pub points_info: i64,
	pub points_forum: i64,
	pub points_misc: i64,
}

#[derive(Debug, Clone, Deserialize)]
pub enum Kat {
	Anime,
	Manga,
}

#[derive(Debug, Clone, Deserialize)]
pub enum License {
	Unknown,
	Unlicensed,
	Licensed,
}
<|endoftext|>


<commit_before>extern crate byteorder;

use std;
use std::io::Write;
use self::byteorder::NativeEndian;
use self::byteorder::WriteBytesExt;

/// Represents a value in the scalar set.
/// The values must be able to store booking information
/// for managing the contents of the set. These requirements
/// are captured in this trait.
pub trait Value
{
    /// Gets the index of the bucket for this value.
    fn get_bucket_index(
        &self,
        buckets: &Self,
    ) -> usize;

    /// Gets a zero.
    fn zero() -> Self;

    /// Gets the integer value as a size.
    fn as_index( &self ) -> usize;

    /// Converts the number of buckets into the value type.i
    fn from_bucket_count( bucket_count: &usize ) -> Self;

    /// Converts the number of set members into the value type.
    fn from_member_count( member_count: usize ) -> Self;

    /// Converts the given index into the value type.
    fn from_index( index: usize ) -> Self;

    /// Decrements the value by one.
    fn decrement( &self ) -> Self;

    /// Provides total ordering for elements.
    fn cmp(
        &self,
        other: &Self,
    ) -> std::cmp::Ordering;

    /// Serializes the value.
    fn serialize(
        &self,
        &mut Write,
    ) -> Result<(), std::io::Error>;
}

/// Implements Value trait for i32
impl Value for i32
{
    /// Gets the index of the bucket for this value.
    fn get_bucket_index(
        &self,
        buckets: &i32,
    ) -> usize
    {
        return ( self.clone() as usize ) % ( buckets.clone() as usize );
    }

    /// Gets a zero.
    fn zero() -> i32
    {
        return 0;
    }

    /// Gets the integer value as a size.
    fn as_index( &self ) -> usize
    {
        return self.clone() as usize;
    }

    /// Converts the specified value to a value that can be stored in the container.
    fn from_bucket_count( bucket_count: &usize ) -> i32
    {
        return bucket_count.clone() as i32;
    }

    /// Converts the number of set members into the value type.
    fn from_member_count( member_count: usize ) -> i32
    {
        return member_count as i32;
    }

    /// Converts the given value to index.
    fn from_index( index: usize ) -> i32
    {
        return index as i32;
    }

    /// Decrements the value by one.
    fn decrement( &self ) -> i32
    {
        return self - 1;
    }

    /// Provides total ordering for elements.
    fn cmp(
        &self,
        other: &i32,
    ) -> std::cmp::Ordering
    {
        std::cmp::Ord::cmp( self, other )
    }

    /// Serializes the value.
    fn serialize(
        &self,
        writer: &mut Write,
    ) -> Result<(), std::io::Error>
    {
        writer.write_i32::<NativeEndian>( *self )?;
        Ok( () )
    }
}

/// Implements Value trait for f32
/// * The largest permissible value is 2^24.
/// * Mainly implemented to provide an easy to use interface for sending the structure to GPU.
#[cfg(any(feature = "floats", test))]
impl Value for f32
{
    /// Gets the index of the bucket for this value.
    fn get_bucket_index(
        &self,
        buckets: &f32,
    ) -> usize
    {
        return ( self.clone() as usize ) % ( buckets.clone() as usize );
    }

    /// Gets a zero.
    fn zero() -> f32
    {
        return 0.0;
    }

    /// Gets the integer value as a size.
    fn as_index( &self ) -> usize
    {
        return self.clone() as usize;
    }

    /// Converts the specified value to a value that can be stored in the container.
    fn from_bucket_count( bucket_count: &usize ) -> f32
    {
        return bucket_count.clone() as f32;
    }

    /// Converts the number of set members into the value type.
    fn from_member_count( member_count: usize ) -> f32
    {
        return member_count as f32;
    }

    /// Converts the given value to index.
    fn from_index( index: usize ) -> f32
    {
        return index as f32;
    }

    /// Decrements the value by one.
    fn decrement( &self ) -> f32
    {
        return self - 1.0;
    }

    /// Provides total ordering for elements.
    fn cmp(
        &self,
        other: &f32,
    ) -> std::cmp::Ordering
    {
        let me = self.clone() as i32;
        let other = other.clone() as i32;
        std::cmp::Ord::cmp( &me, &other )
    }

    /// Serializes the value.
    fn serialize(
        &self,
        writer: &mut Write,
    ) -> Result<(), std::io::Error>
    {
        writer.write_f32::<NativeEndian>( *self )?;
        Ok( () )
    }
}

/// The index of the number of members in the set.
const SIZE_INDEX: usize = 1;

/// The index of the first bucket.
const FIRST_BUCKET_INDEX: usize = 2;

/// Defines how the data is stored in the scalar set.
enum Storage<'a, TA, TB>
where
    TB: 'a,
{
    /// The data is stored as a vector.
    Vector
    { data: Vec<TA> },

    /// The data is stored as a slice.
    Slice
    { data: &'a [TB] },
}

/// Scalar set cabable of storing values with Value trait.
pub struct RoScalarSet<'a, T>
where
    T: std::clone::Clone + Value + 'a,
{
    _storage: Storage<'a, T, T>,
}

impl<'a, T> RoScalarSet<'a, T>
where
    T: std::clone::Clone + Value + 'a,
{
    /// Returns a new integer hash set holding the specified values.
    ///
    /// # ArgumentRoScalarSets
    ///
    /// * 'values' Holds the values stored in the hash set.
    pub fn new<'b, 'c>( values: &'c [T] ) -> RoScalarSet<'b, T>
    {
        // Determine the number of buckets. We introduce a 5% overhead.
        let bucket_count: usize = ( values.len() as f64 * 0.05 ).ceil() as usize;
        let mut storage: Vec<T> = vec![T::zero(); ( FIRST_BUCKET_INDEX + bucket_count + 1 + values.len() )];

        // Store the number of buckets.
        let buckets = T::from_bucket_count( &bucket_count );
        storage[0] = buckets.clone();

        // Store the number of members.
        storage[SIZE_INDEX] = T::from_member_count( values.len() );

        // Count the values required for each bucket.
        let mut values_in_buckets: Vec<i32> = vec![0; bucket_count];
        for v in values
        {
            let bucket = v.get_bucket_index( &buckets );
            values_in_buckets[bucket] += 1;
        }

        // Set bucket pointers to point the end of each bucket.
        // They will be decrements one-by-one when the buckets are filled.
        let first_bucket: usize = FIRST_BUCKET_INDEX;
        let data_start: usize = FIRST_BUCKET_INDEX + bucket_count + 1;
        let mut previous_bucket_end = data_start;
        for b in 0..bucket_count
        {
            // The end of the previous bucket is the start of the previous bucket.
            let index = previous_bucket_end + values_in_buckets[b].as_index();
            storage[b + first_bucket] = T::from_index( index );
            previous_bucket_end = index;
        }

        // Fix the end of the last bucket.
        storage[first_bucket + bucket_count] = T::from_index( storage.len() );

        // Put values into buckets.
        for v in values
        {
            // Determine bucket for the value.
            let bucket_id = v.get_bucket_index( &buckets );

            // Make room for the new value.
            storage[bucket_id + first_bucket] = storage[bucket_id + first_bucket].decrement();
            let value_index: usize = storage[bucket_id + first_bucket].as_index();
            storage[value_index] = v.clone();
        }

        // Sort each bucket to enable binary search.
        for b in 0..bucket_count
        {
            // Determine the location of the bucket.
            let begin: usize = storage[b + first_bucket].as_index();
            let end: usize = storage[b + first_bucket + 1].as_index();
            if end < begin
            {
                panic!( "Invalid bucket: {}", b );
            }

            // Get a splice for sorting.
            let ( _, remainder ) = storage.split_at_mut( begin );
            let ( bucket, _ ) = remainder.split_at_mut( end - begin );
            bucket.sort_by( |a, b| a.cmp( b ) );
        }

        let storage: Storage<'b, T, T> = Storage::Vector { data: storage };
        return RoScalarSet { _storage: storage };
    }

    /// Attaches an integer hash set to a slice holding the values.
    ///
    /// # ArgumentRoScalarSets
    ///
    /// * 'values' Holds the values stored in the hash set.
    pub fn attach<'b>( buffer: &'b [T] ) -> Result<( RoScalarSet<'b, T>, &'b [T] ), &str>
    {
        // Determine the length of this scalar set.
        if buffer.len() < 4
        {
            return Err( "The buffer is to small" );
        }
        let buckets = buffer[0].as_index();
        let values = buffer[SIZE_INDEX].as_index();
        let total_size = FIRST_BUCKET_INDEX + ( buckets + 1 ) + values;

        // Attach.
        let ( set, remainder ) = buffer.split_at( total_size );
        let storage: Storage<T, T> = Storage::Slice { data: set };
        return Ok( ( RoScalarSet { _storage: storage }, remainder ) );
    }

    /// Checks if any the sets have anything in common.
    pub fn any(
        &self,
        other: &RoScalarSet<T>,
    ) -> bool
    {
        // Determine the smaller set.
        let small;
        let large;
        if other.size() < self.size()
        {
            small = other;
            large = self;
        }
        else
        {
            small = self;
            large = other;
        }

        // For better performance we iterate the smaller set.
        for s in small.borrow_values()
        {
            if large.contains( s )
            {
                return true;
            }
        }

        // Values was not found.
        return false;
    }

    /// Checks whether the given value exists in the set or not.
    pub fn contains(
        &self,
        value: &T,
    ) -> bool
    {
        // Get the bucket associated with the value.
        let bucket = self.get_bucket( &value );

        // Locate the value.
        match bucket.binary_search_by( |probe| probe.cmp( &value ) )
        {
            Ok( _ ) => return true,
            Err( _ ) => return false,
        }
    }

    /// Gets the number of members in the set.
    pub fn size( &self ) -> usize
    {
        let storage = self.borrow_storage();
        return storage[SIZE_INDEX].as_index();
    }

    /// Gets the number of buckets.
    pub fn bucket_count( &self ) -> usize
    {
        let storage = self.borrow_storage();
        return storage[0].as_index();
    }

    /// Serializes the scalar set into the given writer.
    pub fn serialize<W>(
        &self,
        writer: &mut W,
    ) -> Result<(), std::io::Error>
    where
        W: Write,
    {
        // Write our intern
        let storage = self.borrow_storage();
        for v in storage
        {
            v.serialize( writer )?;
        }
        Ok( () )
    }

    /// Gets a read-only slice containing the values of a bucket.
    fn get_bucket(
        &self,
        value: &T,
    ) -> &[T]
    {
        // Determine the bucket.
        let storage = self.borrow_storage();
        let bucket_id: usize = value.get_bucket_index( &storage[0] );
        let bucket_index = bucket_id + FIRST_BUCKET_INDEX;
        let begin: usize = storage[bucket_index].as_index();
        let end: usize = storage[( bucket_index + 1 )].as_index();
        let ( _, remainder ) = storage.split_at( begin );
        let ( bucket, _ ) = remainder.split_at( end - begin );
        return bucket;
    }

    /// Borrows the values of the set.
    fn borrow_values( &'a self ) -> &'a [T]
    {
        // Split the value part from the storage.
        let start = FIRST_BUCKET_INDEX + self.bucket_count() + 1;
        let ( _, values ) = self.borrow_storage().split_at( start );
        return values;
    }

    /// Borrows the storage for accessing the values.
    fn borrow_storage( &'a self ) -> &'a [T]
    {
        let s: &'a [T] = match &self._storage
        {
            &Storage::Vector { ref data } => data.as_slice(),
            &Storage::Slice { ref data } => data,
        };
        return s;
    }
}
<commit_msg>Implemented Clone trait for the set<commit_after>extern crate byteorder;

use std;
use std::io::Write;
use self::byteorder::NativeEndian;
use self::byteorder::WriteBytesExt;

/// Represents a value in the scalar set.
/// The values must be able to store booking information
/// for managing the contents of the set. These requirements
/// are captured in this trait.
pub trait Value
{
    /// Gets the index of the bucket for this value.
    fn get_bucket_index(
        &self,
        buckets: &Self,
    ) -> usize;

    /// Gets a zero.
    fn zero() -> Self;

    /// Gets the integer value as a size.
    fn as_index( &self ) -> usize;

    /// Converts the number of buckets into the value type.i
    fn from_bucket_count( bucket_count: &usize ) -> Self;

    /// Converts the number of set members into the value type.
    fn from_member_count( member_count: usize ) -> Self;

    /// Converts the given index into the value type.
    fn from_index( index: usize ) -> Self;

    /// Decrements the value by one.
    fn decrement( &self ) -> Self;

    /// Provides total ordering for elements.
    fn cmp(
        &self,
        other: &Self,
    ) -> std::cmp::Ordering;

    /// Serializes the value.
    fn serialize(
        &self,
        &mut Write,
    ) -> Result<(), std::io::Error>;
}

/// Implements Value trait for i32
impl Value for i32
{
    /// Gets the index of the bucket for this value.
    fn get_bucket_index(
        &self,
        buckets: &i32,
    ) -> usize
    {
        return ( self.clone() as usize ) % ( buckets.clone() as usize );
    }

    /// Gets a zero.
    fn zero() -> i32
    {
        return 0;
    }

    /// Gets the integer value as a size.
    fn as_index( &self ) -> usize
    {
        return self.clone() as usize;
    }

    /// Converts the specified value to a value that can be stored in the container.
    fn from_bucket_count( bucket_count: &usize ) -> i32
    {
        return bucket_count.clone() as i32;
    }

    /// Converts the number of set members into the value type.
    fn from_member_count( member_count: usize ) -> i32
    {
        return member_count as i32;
    }

    /// Converts the given value to index.
    fn from_index( index: usize ) -> i32
    {
        return index as i32;
    }

    /// Decrements the value by one.
    fn decrement( &self ) -> i32
    {
        return self - 1;
    }

    /// Provides total ordering for elements.
    fn cmp(
        &self,
        other: &i32,
    ) -> std::cmp::Ordering
    {
        std::cmp::Ord::cmp( self, other )
    }

    /// Serializes the value.
    fn serialize(
        &self,
        writer: &mut Write,
    ) -> Result<(), std::io::Error>
    {
        writer.write_i32::<NativeEndian>( *self )?;
        Ok( () )
    }
}

/// Implements Value trait for f32
/// * The largest permissible value is 2^24.
/// * Mainly implemented to provide an easy to use interface for sending the structure to GPU.
#[cfg(any(feature = "floats", test))]
impl Value for f32
{
    /// Gets the index of the bucket for this value.
    fn get_bucket_index(
        &self,
        buckets: &f32,
    ) -> usize
    {
        return ( self.clone() as usize ) % ( buckets.clone() as usize );
    }

    /// Gets a zero.
    fn zero() -> f32
    {
        return 0.0;
    }

    /// Gets the integer value as a size.
    fn as_index( &self ) -> usize
    {
        return self.clone() as usize;
    }

    /// Converts the specified value to a value that can be stored in the container.
    fn from_bucket_count( bucket_count: &usize ) -> f32
    {
        return bucket_count.clone() as f32;
    }

    /// Converts the number of set members into the value type.
    fn from_member_count( member_count: usize ) -> f32
    {
        return member_count as f32;
    }

    /// Converts the given value to index.
    fn from_index( index: usize ) -> f32
    {
        return index as f32;
    }

    /// Decrements the value by one.
    fn decrement( &self ) -> f32
    {
        return self - 1.0;
    }

    /// Provides total ordering for elements.
    fn cmp(
        &self,
        other: &f32,
    ) -> std::cmp::Ordering
    {
        let me = self.clone() as i32;
        let other = other.clone() as i32;
        std::cmp::Ord::cmp( &me, &other )
    }

    /// Serializes the value.
    fn serialize(
        &self,
        writer: &mut Write,
    ) -> Result<(), std::io::Error>
    {
        writer.write_f32::<NativeEndian>( *self )?;
        Ok( () )
    }
}

/// The index of the number of members in the set.
const SIZE_INDEX: usize = 1;

/// The index of the first bucket.
const FIRST_BUCKET_INDEX: usize = 2;

/// Defines how the data is stored in the scalar set.
enum Storage<'a, TA, TB>
where
    TB: 'a,
{
    /// The data is stored as a vector.
    Vector
    { data: Vec<TA> },

    /// The data is stored as a slice.
    Slice
    { data: &'a [TB] },
}

/// Scalar set cabable of storing values with Value trait.
pub struct RoScalarSet<'a, T>
where
    T: std::clone::Clone + Value + 'a,
{
    _storage: Storage<'a, T, T>,
}

impl<'a, T> Clone for RoScalarSet<'a, T>
where
    T: std::clone::Clone + Value + 'a,
{
    /// Returns a copy of the value.
    fn clone( &self ) -> Self
    {
        RoScalarSet::new( self.borrow_values() )
    }

    /// Performs copy-assignment from source.
    fn clone_from(
        &mut self,
        source: &Self,
    )
    {
        let storage = RoScalarSet::create_storage( source.borrow_values() );
        self._storage = storage;
    }
}

impl<'a, T> RoScalarSet<'a, T>
where
    T: std::clone::Clone + Value + 'a,
{
    /// Returns a new integer hash set holding the specified values.
    ///
    /// # ArgumentRoScalarSets
    ///
    /// * 'values' Holds the values stored in the hash set.
    pub fn new<'b, 'c>( values: &'c [T] ) -> RoScalarSet<'b, T>
    {
        let storage = RoScalarSet::create_storage( values );
        return RoScalarSet { _storage: storage };
    }

    /// Attaches an integer hash set to a slice holding the values.
    ///
    /// # ArgumentRoScalarSets
    ///
    /// * 'values' Holds the values stored in the hash set.
    pub fn attach<'b>( buffer: &'b [T] ) -> Result<( RoScalarSet<'b, T>, &'b [T] ), &str>
    {
        // Determine the length of this scalar set.
        if buffer.len() < 4
        {
            return Err( "The buffer is to small" );
        }
        let buckets = buffer[0].as_index();
        let values = buffer[SIZE_INDEX].as_index();
        let total_size = FIRST_BUCKET_INDEX + ( buckets + 1 ) + values;

        // Attach.
        let ( set, remainder ) = buffer.split_at( total_size );
        let storage: Storage<T, T> = Storage::Slice { data: set };
        return Ok( ( RoScalarSet { _storage: storage }, remainder ) );
    }

    /// Checks if any the sets have anything in common.
    pub fn any(
        &self,
        other: &RoScalarSet<T>,
    ) -> bool
    {
        // Determine the smaller set.
        let small;
        let large;
        if other.size() < self.size()
        {
            small = other;
            large = self;
        }
        else
        {
            small = self;
            large = other;
        }

        // For better performance we iterate the smaller set.
        for s in small.borrow_values()
        {
            if large.contains( s )
            {
                return true;
            }
        }

        // Values was not found.
        return false;
    }

    /// Checks whether the given value exists in the set or not.
    pub fn contains(
        &self,
        value: &T,
    ) -> bool
    {
        // Get the bucket associated with the value.
        let bucket = self.get_bucket( &value );

        // Locate the value.
        match bucket.binary_search_by( |probe| probe.cmp( &value ) )
        {
            Ok( _ ) => return true,
            Err( _ ) => return false,
        }
    }

    /// Gets the number of members in the set.
    pub fn size( &self ) -> usize
    {
        let storage = self.borrow_storage();
        return storage[SIZE_INDEX].as_index();
    }

    /// Gets the number of buckets.
    pub fn bucket_count( &self ) -> usize
    {
        let storage = self.borrow_storage();
        return storage[0].as_index();
    }

    /// Serializes the scalar set into the given writer.
    pub fn serialize<W>(
        &self,
        writer: &mut W,
    ) -> Result<(), std::io::Error>
    where
        W: Write,
    {
        // Write our intern
        let storage = self.borrow_storage();
        for v in storage
        {
            v.serialize( writer )?;
        }
        Ok( () )
    }

    /// Gets a read-only slice containing the values of a bucket.
    fn get_bucket(
        &self,
        value: &T,
    ) -> &[T]
    {
        // Determine the bucket.
        let storage = self.borrow_storage();
        let bucket_id: usize = value.get_bucket_index( &storage[0] );
        let bucket_index = bucket_id + FIRST_BUCKET_INDEX;
        let begin: usize = storage[bucket_index].as_index();
        let end: usize = storage[( bucket_index + 1 )].as_index();
        let ( _, remainder ) = storage.split_at( begin );
        let ( bucket, _ ) = remainder.split_at( end - begin );
        return bucket;
    }

    /// Borrows the values of the set.
    fn borrow_values( &'a self ) -> &'a [T]
    {
        // Split the value part from the storage.
        let start = FIRST_BUCKET_INDEX + self.bucket_count() + 1;
        let ( _, values ) = self.borrow_storage().split_at( start );
        return values;
    }

    /// Borrows the storage for accessing the values.
    fn borrow_storage( &'a self ) -> &'a [T]
    {
        let s: &'a [T] = match &self._storage
        {
            &Storage::Vector { ref data } => data.as_slice(),
            &Storage::Slice { ref data } => data,
        };
        return s;
    }

    /// Creates a new storage buffer from the given values.
    fn create_storage( values: &[T] ) -> Storage<'a, T, T>
    {
        // Determine the number of buckets. We introduce a 5% overhead.
        let bucket_count: usize = ( values.len() as f64 * 0.05 ).ceil() as usize;
        let mut storage: Vec<T> = vec![T::zero(); ( FIRST_BUCKET_INDEX + bucket_count + 1 + values.len() )];

        // Store the number of buckets.
        let buckets = T::from_bucket_count( &bucket_count );
        storage[0] = buckets.clone();

        // Store the number of members.
        storage[SIZE_INDEX] = T::from_member_count( values.len() );

        // Count the values required for each bucket.
        let mut values_in_buckets: Vec<i32> = vec![0; bucket_count];
        for v in values
        {
            let bucket = v.get_bucket_index( &buckets );
            values_in_buckets[bucket] += 1;
        }

        // Set bucket pointers to point the end of each bucket.
        // They will be decrements one-by-one when the buckets are filled.
        let first_bucket: usize = FIRST_BUCKET_INDEX;
        let data_start: usize = FIRST_BUCKET_INDEX + bucket_count + 1;
        let mut previous_bucket_end = data_start;
        for b in 0..bucket_count
        {
            // The end of the previous bucket is the start of the previous bucket.
            let index = previous_bucket_end + values_in_buckets[b].as_index();
            storage[b + first_bucket] = T::from_index( index );
            previous_bucket_end = index;
        }

        // Fix the end of the last bucket.
        storage[first_bucket + bucket_count] = T::from_index( storage.len() );

        // Put values into buckets.
        for v in values
        {
            // Determine bucket for the value.
            let bucket_id = v.get_bucket_index( &buckets );

            // Make room for the new value.
            storage[bucket_id + first_bucket] = storage[bucket_id + first_bucket].decrement();
            let value_index: usize = storage[bucket_id + first_bucket].as_index();
            storage[value_index] = v.clone();
        }

        // Sort each bucket to enable binary search.
        for b in 0..bucket_count
        {
            // Determine the location of the bucket.
            let begin: usize = storage[b + first_bucket].as_index();
            let end: usize = storage[b + first_bucket + 1].as_index();
            if end < begin
            {
                panic!( "Invalid bucket: {}", b );
            }

            // Get a splice for sorting.
            let ( _, remainder ) = storage.split_at_mut( begin );
            let ( bucket, _ ) = remainder.split_at_mut( end - begin );
            bucket.sort_by( |a, b| a.cmp( b ) );
        }

        let storage: Storage<'a, T, T> = Storage::Vector { data: storage };
        storage
    }
}
<|endoftext|>


<commit_before>// Module for reading sprides and saving them in a HashMap

use std::collections::HashMap;
use piston_window::*;
use io::sprite::Sprite;

/// HashMap for all given sprites
pub struct SpriteMap {
    pub map: HashMap<&'static str, Sprite>,
}

impl SpriteMap {
    /// Initialize the SpriteMap with given window, fills Map with all Sprites
    pub fn init(mut w: &mut PistonWindow) -> Self {
        let mut map2: HashMap<&'static str, Sprite> = HashMap::new();
        for i in SPRITES {
            map2.insert(i.image,
                        Sprite::fill_sprite(i.image, i.size_x as u32, i.size_y as u32,i.dur as u64, i.once, w));
        }

        SpriteMap { map: map2 }

    }

    /// creates empty SpriteMap
    pub fn new() -> Self {
        SpriteMap { map: HashMap::new() }
    }
    pub fn get_sprite(&self, file: String) -> Option<&Sprite> {
        self.map.get(file.as_str())
    }
}

/// Struct for representing Necessary information about sprites
struct SpriteModel {
    image: &'static str,
    size_x: usize,
    size_y: usize,
    dur: usize,
    once: bool,
}

/// const with all Sprites
const SPRITES: &'static [SpriteModel] = &[SpriteModel {
                                              image: "bowman.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken_brown.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken_pink.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken_white.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "explosion.png",
                                              size_x: 59,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "knight.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "paladin.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "swipe_broadsword.png",
                                              size_x: 64,
                                              size_y: 192,
                                              dur: 100,
                                              once: true,
                                          },
                                          SpriteModel {
                                              image: "swipe_dagger.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 100,
                                              once: true,
                                          },
                                          SpriteModel {
                                              image: "swipe_longsword.png",
                                              size_x: 128,
                                              size_y: 64,
                                              dur: 100,
                                              once: true,
                                          },
                                          SpriteModel {
                                              image: "weapon_broadsword.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_dagger.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_spear.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "wizard.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_empty.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_full.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_half.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_broadsword_small.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_dagger_small.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_spear_small.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_10.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_20.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "swipe_enemy.png",
                                              size_x: 60,
                                              size_y: 64,
                                              dur: 100,
                                              once: false,
                                          }];
<commit_msg>bugfix for attack animation<commit_after>// Module for reading sprides and saving them in a HashMap

use std::collections::HashMap;
use piston_window::*;
use io::sprite::Sprite;

/// HashMap for all given sprites
pub struct SpriteMap {
    pub map: HashMap<&'static str, Sprite>,
}

impl SpriteMap {
    /// Initialize the SpriteMap with given window, fills Map with all Sprites
    pub fn init(mut w: &mut PistonWindow) -> Self {
        let mut map2: HashMap<&'static str, Sprite> = HashMap::new();
        for i in SPRITES {
            map2.insert(i.image,
                        Sprite::fill_sprite(i.image, i.size_x as u32, i.size_y as u32,i.dur as u64, i.once, w));
        }

        SpriteMap { map: map2 }

    }

    /// creates empty SpriteMap
    pub fn new() -> Self {
        SpriteMap { map: HashMap::new() }
    }
    pub fn get_sprite(&self, file: String) -> Option<&Sprite> {
        self.map.get(file.as_str())
    }
}

/// Struct for representing Necessary information about sprites
struct SpriteModel {
    image: &'static str,
    size_x: usize,
    size_y: usize,
    dur: usize,
    once: bool,
}

/// const with all Sprites
const SPRITES: &'static [SpriteModel] = &[SpriteModel {
                                              image: "bowman.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken_brown.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken_pink.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken_white.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "explosion.png",
                                              size_x: 59,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "knight.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "paladin.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "swipe_broadsword.png",
                                              size_x: 64,
                                              size_y: 192,
                                              dur: 100,
                                              once: true,
                                          },
                                          SpriteModel {
                                              image: "swipe_dagger.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 100,
                                              once: true,
                                          },
                                          SpriteModel {
                                              image: "swipe_longsword.png",
                                              size_x: 128,
                                              size_y: 64,
                                              dur: 100,
                                              once: true,
                                          },
                                          SpriteModel {
                                              image: "weapon_broadsword.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_dagger.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_spear.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "wizard.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_empty.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_full.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_half.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_broadsword_small.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_dagger_small.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_spear_small.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_10.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_20.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "swipe_enemy.png",
                                              size_x: 60,
                                              size_y: 64,
                                              dur: 100,
                                              once: true,
                                          }];
<|endoftext|>