<commit_before>use std::net::*;
use std::vec::Vec;

extern crate linux_tuples_client;
use linux_tuples_client::*;

fn main() {
	if std::env::args().count() != 4
	{
		println!("ex_listener. USAGE: ex_listener <IP> <port> <node name>");
		return;
	}

	let ip: String = std::env::args().nth(1).unwrap();
	let port: String = std::env::args().nth(2).unwrap();
	let name: String = std::env::args().nth(3).unwrap();

	let conn: SocketAddr = (format!("{}:{}", ip, port)).parse().unwrap();
	let serv = LinuxTuplesConnection { connection: conn };

	let users_count_request_tuple: Vec<E> = vec![E::S("USERS_COUNT".to_string()), E::None];
	let users_list_request_tuple: Vec<E> = vec![E::S("USER_LIST".to_string()), E::None];

	let users_count_list = serv.read_nb_tuple(&users_count_request_tuple).unwrap();
	if users_count_list.len() > 0
	{
		let users_count = serv.get_tuple(&users_count_request_tuple).unwrap();
		if let E::I(count) = users_count[1] {
				let users_count_updated = vec![E::S("USERS_COUNT".to_string()), E::I(count + 1)];
				serv.put_tuple(&users_count_updated);
		}

		let mut users_tuple = serv.get_tuple(&users_list_request_tuple).unwrap();
		if let &mut E::T(ref mut v) = &mut users_tuple[1] {
				v.push(E::S(name.clone()));
				let users_list_confirm_tuple = vec![E::S("USER_LIST".to_string()), E::T(v.clone())];
				serv.put_tuple(&users_list_confirm_tuple);
		}
	} else {
		let users_count_init_tuple = vec![E::S("USERS_COUNT".to_string()), E::I(1)];
		serv.put_tuple(&users_count_init_tuple);
		let users_list_confirm_tuple = vec![E::S("USER_LIST".to_string()), E::T(vec![E::S(name.clone())])];
		serv.put_tuple(&users_list_confirm_tuple);
	}

	let serv_global = serv.clone();
	let name_global = name.clone();

	let th = std::thread::spawn(move || {
			let mut cmd_id: i32 = 0;

			'thread: loop {
				let command_received = serv_global.read_tuple(&vec![E::None, E::S("global".to_string()), E::None]).unwrap();

				let mut text:String = "".to_string();

				if let E::I(id) = command_received[0] {
					if cmd_id == id {
						continue 'thread;
					}
					cmd_id = id;
				}

				if let &E::S(ref txt) = &command_received[2] {
					text = txt.clone();
				}

				let mut sp = text.split(" ").collect::<Vec<&str>>();
				let mut process = std::process::Command::new(sp[0]);
				for i in 1..sp.len()
				{
					process.arg(sp[i]);
				}
				let output = String::from_utf8(process.output().unwrap().stdout).unwrap();

				serv_global.put_tuple(&vec![E::S(name_global.clone()), E::I(cmd_id), E::S(output)]);
			}
	});

	//name-based thread
	'main: loop {
		let command_received = serv.get_tuple(
			&vec![E::S(name.clone()), E::None, E::None, E::None]).unwrap();

		//LinuxTuplesConnection::print_tuple(&command_received);

		if let &E::S(ref s) = &command_received[2] {
				let mut sp = s.split(" ").collect::<Vec<&str>>();
				let mut process = std::process::Command::new(sp[0]);
				for i in 1..sp.len()
				{
					process.arg(sp[i]);
				}
				let output = process.output().unwrap().stdout;

				if let &E::I(ref command_id) = &command_received[3] {
						let output_tuple = vec![E::I(*command_id), E::S(String::from_utf8(output).unwrap())];
						serv.put_tuple(&output_tuple);
				}
				//println!("{}", String::from_utf8(output).unwrap());
		}

		println!("");
		if command_received[1] == E::S("shutdown".to_string())
		{
			let users_count = serv.get_tuple(&users_count_request_tuple).unwrap();
			if let E::I(count) = users_count[1] {
				if count > 1 {
					serv.put_tuple(&vec![E::S("USERS_COUNT".to_string()), E::I(count - 1)]);
				}
			}

			let mut users_list = serv.get_tuple(&users_list_request_tuple).unwrap();
			let mut shouldRemove: bool = false;

			if let &mut E::T(ref mut users) = &mut users_list[1] {
				let mut ind: usize = 0;
				for i in 0..users.len() {
					if users[i] == E::S(name.clone()) {
								ind = i;
					}
				}
				users.remove(ind);
				if users.len() == 0 {
					shouldRemove = true;
				}
			}

			if !shouldRemove {
				serv.put_tuple(&users_list);
			}

			break 'main;
		}
	}

}
<commit_msg>replace instead of get/put<commit_after>use std::net::*;
use std::vec::Vec;

extern crate linux_tuples_client;
use linux_tuples_client::*;

fn main() {
	if std::env::args().count() != 4
	{
		println!("ex_listener. USAGE: ex_listener <IP> <port> <node name>");
		return;
	}

	let ip: String = std::env::args().nth(1).unwrap();
	let port: String = std::env::args().nth(2).unwrap();
	let name: String = std::env::args().nth(3).unwrap();

	let conn: SocketAddr = (format!("{}:{}", ip, port)).parse().unwrap();
	let serv = LinuxTuplesConnection { connection: conn };

	let users_count_request_tuple: Vec<E> = vec![E::S("USERS_COUNT".to_string()), E::None];
	let users_list_request_tuple: Vec<E> = vec![E::S("USER_LIST".to_string()), E::None];

	let users_count_list = serv.read_nb_tuple(&users_count_request_tuple).unwrap();
	if users_count_list.len() > 0
	{
		if let E::I(count) = users_count_list[1] {
				serv.replace_tuple(&users_count_list, &vec![E::S("USERS_COUNT".to_string()), E::I(count + 1)]);
		}

		let mut users_tuple = serv.read_nb_tuple(&users_list_request_tuple).unwrap();
		if let &E::T(ref v) = &users_tuple[1] {
				let mut v_new = v.clone();
				v_new.push(E::S(name.clone()));
				let users_list_confirm_tuple = vec![E::S("USER_LIST".to_string()), E::T(v_new.clone())];
				serv.replace_tuple(&users_tuple, &users_list_confirm_tuple);
		}
	} else {
		let users_count_init_tuple = vec![E::S("USERS_COUNT".to_string()), E::I(1)];
		serv.put_tuple(&users_count_init_tuple);
		let users_list_confirm_tuple = vec![E::S("USER_LIST".to_string()), E::T(vec![E::S(name.clone())])];
		serv.put_tuple(&users_list_confirm_tuple);
	}

	let serv_global = serv.clone();
	let name_global = name.clone();

	let th = std::thread::spawn(move || {
			let mut cmd_id: i32 = 0;

			'thread: loop {
				let command_received = serv_global.read_tuple(&vec![E::None, E::S("global".to_string()), E::None]).unwrap();

				let mut text:String = "".to_string();

				if let E::I(id) = command_received[0] {
					if cmd_id == id {
						continue 'thread;
					}
					cmd_id = id;
				}

				if let &E::S(ref txt) = &command_received[2] {
					text = txt.clone();
				}

				let mut sp = text.split(" ").collect::<Vec<&str>>();
				let mut process = std::process::Command::new(sp[0]);
				for i in 1..sp.len()
				{
					process.arg(sp[i]);
				}
				let output = String::from_utf8(process.output().unwrap().stdout).unwrap();

				serv_global.put_tuple(&vec![E::S(name_global.clone()), E::I(cmd_id), E::S(output)]);
			}
	});

	//name-based thread
	'main: loop {
		let command_received = serv.get_tuple(
			&vec![E::S(name.clone()), E::None, E::None, E::None]).unwrap();

		//LinuxTuplesConnection::print_tuple(&command_received);

		if let &E::S(ref s) = &command_received[2] {
				let mut sp = s.split(" ").collect::<Vec<&str>>();
				let mut process = std::process::Command::new(sp[0]);
				for i in 1..sp.len()
				{
					process.arg(sp[i]);
				}
				let output = process.output().unwrap().stdout;

				if let &E::I(ref command_id) = &command_received[3] {
						let output_tuple = vec![E::I(*command_id), E::S(String::from_utf8(output).unwrap())];
						serv.put_tuple(&output_tuple);
				}
				//println!("{}", String::from_utf8(output).unwrap());
		}

		println!("");
		if command_received[1] == E::S("shutdown".to_string())
		{
			let users_count = serv.get_tuple(&users_count_request_tuple).unwrap();
			if let E::I(count) = users_count[1] {
				if count > 1 {
					serv.put_tuple(&vec![E::S("USERS_COUNT".to_string()), E::I(count - 1)]);
				}
			}

			let mut users_list = serv.get_tuple(&users_list_request_tuple).unwrap();
			let mut shouldRemove: bool = false;

			if let &mut E::T(ref mut users) = &mut users_list[1] {
				let mut ind: usize = 0;
				for i in 0..users.len() {
					if users[i] == E::S(name.clone()) {
								ind = i;
					}
				}
				users.remove(ind);
				if users.len() == 0 {
					shouldRemove = true;
				}
			}

			if !shouldRemove {
				serv.put_tuple(&users_list);
			}

			break 'main;
		}
	}

}
<|endoftext|>


<commit_before>use std::net::SocketAddr;
use std::str::FromStr;

use hyper::header;
use hyper::method::Method;

use url::Host;
use url::SchemeData;

use urlencoded;

use unicase::UniCase;

use iron;
use iron::prelude::*;

use models;

pub struct XForwardedMiddleware;

fn get_one_raw(r: &mut Request, key: &str) -> Option<String> {
    r.headers
        .get_raw(key)
        .and_then(|vals| if vals.len() > 0 { vals.to_owned().pop() } else { None })
        .and_then(|x| String::from_utf8(x).ok())
}

impl iron::middleware::BeforeMiddleware for XForwardedMiddleware {
    fn before(&self, r: &mut Request) -> IronResult<()> {
        get_one_raw(r, "X-Forwarded-Host")
            .and_then(|host| Host::parse(&host[..]).ok())
            .map(|x| r.url.host = x);

        get_one_raw(r, "X-Forwarded-Port")
            .and_then(|s| u16::from_str(&s[..]).ok())
            .map(|port| r.url.port = port);

        get_one_raw(r, "X-Forwarded-For")
            .and_then(parse_remote_addrs)
            .map(|ip| r.remote_addr = ip);

        get_one_raw(r, "X-Forwarded-Proto")
            .map(|scheme| r.url.scheme = scheme.to_lowercase());

        Ok(())
    }
}

fn parse_remote_addrs(s: String) -> Option<SocketAddr> {
    let split = s.split(',');
    let mut iter_ips = split.map(|x| x.trim()).filter(|x| x.len() > 0);
    iter_ips.next().and_then(|ip| SocketAddr::from_str(ip).ok())
}

pub struct SecurityHeaderMiddleware;

impl iron::middleware::AfterMiddleware for SecurityHeaderMiddleware {
    fn after(&self, request: &mut Request, mut response: Response) -> IronResult<Response> {
        Self::set_security_headers(&request, &mut response);
        Ok(response)
    }

    fn catch(&self, request: &mut Request, mut error: IronError) -> IronResult<Response> {
        Self::set_security_headers(&request, &mut error.response);
        Err(error)
    }
}

impl SecurityHeaderMiddleware {
    fn set_security_headers(rq: &Request, r: &mut Response) {
        Self::set_cors_headers(rq, r);
        r.headers.set_raw("X-Content-Type-Options", vec![b"nosniff".to_vec()]);

        let mut csp = vec!["default-src 'self'"];

        if &rq.url.path[0] != "storage" {
            // It's probably fine to embed user storage data into other documents

            // Prevent clickjacking attacks like described in OAuth RFC
            // https://tools.ietf.org/html/rfc6749#section-10.13
            r.headers.set_raw("X-Frame-Options", vec![b"DENY".to_vec()]);

            // This is a newer way to do what X-Frame-Options does
            // http://www.w3.org/TR/CSP11/#frame-ancestors-and-frame-options
            csp.push("frame-ancestors 'none'");
        };
        r.headers.set_raw("Content-Security-Policy", vec![csp.join(";").as_bytes().to_vec()]);
    }

    /// Required by remoteStorage spec
    fn set_cors_headers(rq: &Request, r: &mut Response) {
        match &rq.url.path[0][..] {
            ".well-known" | "storage" => (),
            _ => return
        };

        let origin = match rq.headers.get_raw("Origin") {
            Some(x) => if x.len() == 1 {
                match String::from_utf8(x.to_owned().into_iter().next().unwrap()) {
                    Ok(x) => x,
                    Err(_) => return
                }
            } else {
                return;
            },
            None => return
        };

        r.headers.set(header::AccessControlAllowOrigin::Value(origin));
        r.headers.set(header::AccessControlExposeHeaders(vec![
            UniCase("ETag".to_owned()),
            UniCase("Content-Length".to_owned())
        ]));
        r.headers.set(header::AccessControlAllowMethods(vec![Method::Get, Method::Put, Method::Delete]));
        r.headers.set(header::AccessControlAllowHeaders(vec![
            UniCase("Authorization".to_owned()),
            UniCase("Content-Type".to_owned()),
            UniCase("Origin".to_owned()),
            UniCase("If-Match".to_owned()),
            UniCase("If-None-Match".to_owned()),
        ]));
    }
}

pub trait EtagMatcher {
    fn matches_etag(&self, given: Option<&str>) -> bool;
}

impl EtagMatcher for header::IfNoneMatch {
    fn matches_etag(&self, given: Option<&str>) -> bool {
        match *self {
            header::IfNoneMatch::Any => given.is_some(),
            header::IfNoneMatch::Items(ref values) => {
                match given {
                    Some(given_value) => values.iter().any(|val| val.tag() == &given_value[..]),
                    None => false
                }
            }
        }
    }
}

impl EtagMatcher for header::IfMatch {
    fn matches_etag(&self, given: Option<&str>) -> bool {
        match *self {
            header::IfMatch::Any => given.is_some(),
            header::IfMatch::Items(ref values) => {
                match given {
                    Some(given_value) => values.iter().any(|val| val.tag() == &given_value[..]),
                    None => false
                }
            }
        }
    }
}

pub fn preconditions_ok(request: &Request, etag: Option<&str>) -> bool {
    match request.headers.get::<header::IfNoneMatch>() {
        Some(header) => if header.matches_etag(etag) { return false; },
        None => ()
    };

    match request.headers.get::<header::IfMatch>() {
        Some(header) => if !header.matches_etag(etag) { return false; },
        None => ()
    };
    true
}

pub trait FormDataHelper<K: ?Sized, V> {
    fn get_only<Q: AsRef<K>>(&self, k: Q) -> Option<&String>;
}

impl FormDataHelper<str, String> for urlencoded::QueryMap {
    fn get_only<Q: AsRef<str>>(&self, k: Q) -> Option<&String> {
        match self.get(&k.as_ref().to_owned()) {
            Some(x) if x.len() == 1 => Some(&x[0]),
            _ => None
        }
    }
}

pub fn get_account_id(user: &models::User, request: &Request) -> String {
    let url = request.url.clone().into_generic_url();
    let scheme_data = match url.scheme_data {
        SchemeData::Relative(ref x) => x,
        _ => panic!("Expected relative scheme data.")
    };

    let mut rv = format!("{}@{}", user.userid, scheme_data.host);
    if let Some(port) = scheme_data.port {
        if Some(port) != scheme_data.default_port {
            rv.push_str(&format!(":{}", port)[..]);
        }
    };

    rv
}
<commit_msg>Add X-XSS-Protection<commit_after>use std::net::SocketAddr;
use std::str::FromStr;

use hyper::header;
use hyper::method::Method;

use url::Host;
use url::SchemeData;

use urlencoded;

use unicase::UniCase;

use iron;
use iron::prelude::*;

use models;

pub struct XForwardedMiddleware;

fn get_one_raw(r: &mut Request, key: &str) -> Option<String> {
    r.headers
        .get_raw(key)
        .and_then(|vals| if vals.len() > 0 { vals.to_owned().pop() } else { None })
        .and_then(|x| String::from_utf8(x).ok())
}

impl iron::middleware::BeforeMiddleware for XForwardedMiddleware {
    fn before(&self, r: &mut Request) -> IronResult<()> {
        get_one_raw(r, "X-Forwarded-Host")
            .and_then(|host| Host::parse(&host[..]).ok())
            .map(|x| r.url.host = x);

        get_one_raw(r, "X-Forwarded-Port")
            .and_then(|s| u16::from_str(&s[..]).ok())
            .map(|port| r.url.port = port);

        get_one_raw(r, "X-Forwarded-For")
            .and_then(parse_remote_addrs)
            .map(|ip| r.remote_addr = ip);

        get_one_raw(r, "X-Forwarded-Proto")
            .map(|scheme| r.url.scheme = scheme.to_lowercase());

        Ok(())
    }
}

fn parse_remote_addrs(s: String) -> Option<SocketAddr> {
    let split = s.split(',');
    let mut iter_ips = split.map(|x| x.trim()).filter(|x| x.len() > 0);
    iter_ips.next().and_then(|ip| SocketAddr::from_str(ip).ok())
}

pub struct SecurityHeaderMiddleware;

impl iron::middleware::AfterMiddleware for SecurityHeaderMiddleware {
    fn after(&self, request: &mut Request, mut response: Response) -> IronResult<Response> {
        Self::set_security_headers(&request, &mut response);
        Ok(response)
    }

    fn catch(&self, request: &mut Request, mut error: IronError) -> IronResult<Response> {
        Self::set_security_headers(&request, &mut error.response);
        Err(error)
    }
}

impl SecurityHeaderMiddleware {
    fn set_security_headers(rq: &Request, r: &mut Response) {
        Self::set_cors_headers(rq, r);
        r.headers.set_raw("X-Content-Type-Options", vec![b"nosniff".to_vec()]);
        r.headers.set_raw("X-XSS-Protection", vec![b"1; mode=block".to_vec()]);

        let mut csp = vec!["default-src 'self'"];

        if &rq.url.path[0] != "storage" {
            // It's probably fine to embed user storage data into other documents

            // Prevent clickjacking attacks like described in OAuth RFC
            // https://tools.ietf.org/html/rfc6749#section-10.13
            r.headers.set_raw("X-Frame-Options", vec![b"DENY".to_vec()]);

            // This is a newer way to do what X-Frame-Options does
            // http://www.w3.org/TR/CSP11/#frame-ancestors-and-frame-options
            csp.push("frame-ancestors 'none'");
        };
        r.headers.set_raw("Content-Security-Policy", vec![csp.join(";").as_bytes().to_vec()]);
    }

    /// Required by remoteStorage spec
    fn set_cors_headers(rq: &Request, r: &mut Response) {
        match &rq.url.path[0][..] {
            ".well-known" | "storage" => (),
            _ => return
        };

        let origin = match rq.headers.get_raw("Origin") {
            Some(x) => if x.len() == 1 {
                match String::from_utf8(x.to_owned().into_iter().next().unwrap()) {
                    Ok(x) => x,
                    Err(_) => return
                }
            } else {
                return;
            },
            None => return
        };

        r.headers.set(header::AccessControlAllowOrigin::Value(origin));
        r.headers.set(header::AccessControlExposeHeaders(vec![
            UniCase("ETag".to_owned()),
            UniCase("Content-Length".to_owned())
        ]));
        r.headers.set(header::AccessControlAllowMethods(vec![Method::Get, Method::Put, Method::Delete]));
        r.headers.set(header::AccessControlAllowHeaders(vec![
            UniCase("Authorization".to_owned()),
            UniCase("Content-Type".to_owned()),
            UniCase("Origin".to_owned()),
            UniCase("If-Match".to_owned()),
            UniCase("If-None-Match".to_owned()),
        ]));
    }
}

pub trait EtagMatcher {
    fn matches_etag(&self, given: Option<&str>) -> bool;
}

impl EtagMatcher for header::IfNoneMatch {
    fn matches_etag(&self, given: Option<&str>) -> bool {
        match *self {
            header::IfNoneMatch::Any => given.is_some(),
            header::IfNoneMatch::Items(ref values) => {
                match given {
                    Some(given_value) => values.iter().any(|val| val.tag() == &given_value[..]),
                    None => false
                }
            }
        }
    }
}

impl EtagMatcher for header::IfMatch {
    fn matches_etag(&self, given: Option<&str>) -> bool {
        match *self {
            header::IfMatch::Any => given.is_some(),
            header::IfMatch::Items(ref values) => {
                match given {
                    Some(given_value) => values.iter().any(|val| val.tag() == &given_value[..]),
                    None => false
                }
            }
        }
    }
}

pub fn preconditions_ok(request: &Request, etag: Option<&str>) -> bool {
    match request.headers.get::<header::IfNoneMatch>() {
        Some(header) => if header.matches_etag(etag) { return false; },
        None => ()
    };

    match request.headers.get::<header::IfMatch>() {
        Some(header) => if !header.matches_etag(etag) { return false; },
        None => ()
    };
    true
}

pub trait FormDataHelper<K: ?Sized, V> {
    fn get_only<Q: AsRef<K>>(&self, k: Q) -> Option<&String>;
}

impl FormDataHelper<str, String> for urlencoded::QueryMap {
    fn get_only<Q: AsRef<str>>(&self, k: Q) -> Option<&String> {
        match self.get(&k.as_ref().to_owned()) {
            Some(x) if x.len() == 1 => Some(&x[0]),
            _ => None
        }
    }
}

pub fn get_account_id(user: &models::User, request: &Request) -> String {
    let url = request.url.clone().into_generic_url();
    let scheme_data = match url.scheme_data {
        SchemeData::Relative(ref x) => x,
        _ => panic!("Expected relative scheme data.")
    };

    let mut rv = format!("{}@{}", user.userid, scheme_data.host);
    if let Some(port) = scheme_data.port {
        if Some(port) != scheme_data.default_port {
            rv.push_str(&format!(":{}", port)[..]);
        }
    };

    rv
}
<|endoftext|>


<commit_before>use std::cmp::min;

use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::error::*;
use crate::node::{Node, NodeBorrow};
use crate::parsers::{NumberList, NumberListLength, Parse, ParseValue};
use crate::surface_utils::{
    iterators::Pixels, shared_surface::ExclusiveImageSurface, ImageSurfaceDataExt, Pixel,
};
use crate::util::clamp;
use crate::xml::Attributes;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, FilterRender, PrimitiveWithInput};

/// The `feComponentTransfer` filter primitive.
pub struct FeComponentTransfer {
    base: PrimitiveWithInput,
}

impl Default for FeComponentTransfer {
    /// Constructs a new `ComponentTransfer` with empty properties.
    #[inline]
    fn default() -> FeComponentTransfer {
        FeComponentTransfer {
            base: PrimitiveWithInput::new::<Self>(),
        }
    }
}

impl SetAttributes for FeComponentTransfer {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.base.set_attributes(attrs)
    }
}

/// Pixel components that can be influenced by `feComponentTransfer`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Channel {
    R,
    G,
    B,
    A,
}

/// Component transfer function types.
enum FunctionType {
    Identity,
    Table,
    Discrete,
    Linear,
    Gamma,
}

impl Parse for FunctionType {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "identity" => FunctionType::Identity,
            "table" => FunctionType::Table,
            "discrete" => FunctionType::Discrete,
            "linear" => FunctionType::Linear,
            "gamma" => FunctionType::Gamma,
        )?)
    }
}

/// The compute function parameters.
struct FunctionParameters {
    table_values: Vec<f64>,
    slope: f64,
    intercept: f64,
    amplitude: f64,
    exponent: f64,
    offset: f64,
}

/// The compute function type.
type Function = fn(&FunctionParameters, f64) -> f64;

/// The identity component transfer function.
fn identity(_: &FunctionParameters, value: f64) -> f64 {
    value
}

/// The table component transfer function.
fn table(params: &FunctionParameters, value: f64) -> f64 {
    let n = params.table_values.len() - 1;
    let k = (value * (n as f64)).floor() as usize;

    let k = min(k, n); // Just in case.

    if k == n {
        return params.table_values[k];
    }

    let vk = params.table_values[k];
    let vk1 = params.table_values[k + 1];
    let k = k as f64;
    let n = n as f64;

    vk + (value - k / n) * n * (vk1 - vk)
}

/// The discrete component transfer function.
fn discrete(params: &FunctionParameters, value: f64) -> f64 {
    let n = params.table_values.len();
    let k = (value * (n as f64)).floor() as usize;

    params.table_values[min(k, n - 1)]
}

/// The linear component transfer function.
fn linear(params: &FunctionParameters, value: f64) -> f64 {
    params.slope * value + params.intercept
}

/// The gamma component transfer function.
fn gamma(params: &FunctionParameters, value: f64) -> f64 {
    params.amplitude * value.powf(params.exponent) + params.offset
}

trait FeComponentTransferFunc {
    /// Returns the component transfer function.
    fn function(&self) -> Function;

    /// Returns the component transfer function parameters.
    fn function_parameters(&self) -> FunctionParameters;

    /// Returns the channel.
    fn channel(&self) -> Channel;
}

macro_rules! func_x {
    ($func_name:ident, $channel:expr) => {
        pub struct $func_name {
            channel: Channel,
            function_type: FunctionType,
            table_values: Vec<f64>,
            slope: f64,
            intercept: f64,
            amplitude: f64,
            exponent: f64,
            offset: f64,
        }

        impl Default for $func_name {
            #[inline]
            fn default() -> Self {
                Self {
                    channel: $channel,
                    function_type: FunctionType::Identity,
                    table_values: Vec::new(),
                    slope: 1.0,
                    intercept: 0.0,
                    amplitude: 1.0,
                    exponent: 1.0,
                    offset: 0.0,
                }
            }
        }

        impl FeComponentTransferFunc for $func_name {
            #[inline]
            fn function_parameters(&self) -> FunctionParameters {
                FunctionParameters {
                    table_values: self.table_values.clone(),
                    slope: self.slope,
                    intercept: self.intercept,
                    amplitude: self.amplitude,
                    exponent: self.exponent,
                    offset: self.offset,
                }
            }

            #[inline]
            fn function(&self) -> Function {
                match self.function_type {
                    FunctionType::Identity => identity,
                    FunctionType::Table => table,
                    FunctionType::Discrete => discrete,
                    FunctionType::Linear => linear,
                    FunctionType::Gamma => gamma,
                }
            }

            #[inline]
            fn channel(&self) -> Channel {
                self.channel
            }
        }

        impl SetAttributes for $func_name {
            #[inline]
            fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
                for (attr, value) in attrs.iter() {
                    match attr.expanded() {
                        expanded_name!("", "type") => self.function_type = attr.parse(value)?,
                        expanded_name!("", "tableValues") => {
                            let NumberList(v) =
                                NumberList::parse_str(value, NumberListLength::Unbounded)
                                    .attribute(attr)?;
                            self.table_values = v;
                        }
                        expanded_name!("", "slope") => self.slope = attr.parse(value)?,
                        expanded_name!("", "intercept") => self.intercept = attr.parse(value)?,
                        expanded_name!("", "amplitude") => self.amplitude = attr.parse(value)?,
                        expanded_name!("", "exponent") => self.exponent = attr.parse(value)?,
                        expanded_name!("", "offset") => self.offset = attr.parse(value)?,

                        _ => (),
                    }
                }

                // The table function type with empty table_values is considered
                // an identity function.
                match self.function_type {
                    FunctionType::Table | FunctionType::Discrete => {
                        if self.table_values.is_empty() {
                            self.function_type = FunctionType::Identity;
                        }
                    }
                    _ => (),
                }

                Ok(())
            }
        }

        impl Draw for $func_name {}
    };
}

// The `<feFuncR>` element
func_x!(FeFuncR, Channel::R);

// The `<feFuncG>` element
func_x!(FeFuncG, Channel::G);

// The `<feFuncB>` element
func_x!(FeFuncB, Channel::B);

// The `<feFuncA>` element
func_x!(FeFuncA, Channel::A);

macro_rules! func_or_default {
    ($func_node:ident, $func_type:ident, $func_data:ident, $func_default:ident) => {
        match $func_node {
            Some(ref f) => {
                $func_data = f.borrow_element();
                match *$func_data {
                    Element::$func_type(ref e) => &*e,
                    _ => unreachable!(),
                }
            }
            _ => &$func_default,
        };
    };
}

macro_rules! get_func_x_node {
    ($func_node:ident, $func_type:ident, $channel:expr) => {
        $func_node
            .children()
            .rev()
            .filter(|c| c.is_element())
            .find(|c| match *c.borrow_element() {
                Element::$func_type(ref f) => f.channel() == $channel,
                _ => false,
            })
    };
}

impl FilterRender for FeComponentTransfer {
    fn render(
        &self,
        node: &Node,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, acquired_nodes, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx)?
            .add_input(&input)
            .into_irect(ctx, draw_ctx);

        // Create the output surface.
        let mut surface = ExclusiveImageSurface::new(
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
            input.surface().surface_type(),
        )?;

        let func_r_node = get_func_x_node!(node, FeFuncR, Channel::R);
        let func_g_node = get_func_x_node!(node, FeFuncG, Channel::G);
        let func_b_node = get_func_x_node!(node, FeFuncB, Channel::B);
        let func_a_node = get_func_x_node!(node, FeFuncA, Channel::A);

        for node in [&func_r_node, &func_g_node, &func_b_node, &func_a_node]
            .iter()
            .filter_map(|x| x.as_ref())
        {
            if node.borrow_element().is_in_error() {
                return Err(FilterError::ChildNodeInError);
            }
        }

        // These are the default funcs that perform an identity transformation.
        let func_r_default = FeFuncR::default();
        let func_g_default = FeFuncG::default();
        let func_b_default = FeFuncB::default();
        let func_a_default = FeFuncA::default();

        // We need to tell the borrow checker that these live long enough
        let func_r_element;
        let func_g_element;
        let func_b_element;
        let func_a_element;

        let func_r = func_or_default!(func_r_node, FeFuncR, func_r_element, func_r_default);
        let func_g = func_or_default!(func_g_node, FeFuncG, func_g_element, func_g_default);
        let func_b = func_or_default!(func_b_node, FeFuncB, func_b_element, func_b_default);
        let func_a = func_or_default!(func_a_node, FeFuncA, func_a_element, func_a_default);

        #[inline]
        fn compute_func<F>(func: &F) -> impl Fn(u8, f64, f64) -> u8 + '_
        where
            F: FeComponentTransferFunc,
        {
            let compute = func.function();
            let params = func.function_parameters();

            move |value, alpha, new_alpha| {
                let value = f64::from(value) / 255f64;

                let unpremultiplied = if alpha == 0f64 { 0f64 } else { value / alpha };

                let new_value = compute(&params, unpremultiplied);
                let new_value = clamp(new_value, 0f64, 1f64);

                ((new_value * new_alpha * 255f64) + 0.5) as u8
            }
        }

        let compute_r = compute_func::<FeFuncR>(&func_r);
        let compute_g = compute_func::<FeFuncG>(&func_g);
        let compute_b = compute_func::<FeFuncB>(&func_b);

        // Alpha gets special handling since everything else depends on it.
        let compute_a = func_a.function();
        let params_a = func_a.function_parameters();
        let compute_a = |alpha| compute_a(&params_a, alpha);

        // Do the actual processing.
        surface.modify(&mut |data, stride| {
            for (x, y, pixel) in Pixels::within(input.surface(), bounds) {
                let alpha = f64::from(pixel.a) / 255f64;
                let new_alpha = compute_a(alpha);

                let output_pixel = Pixel {
                    r: compute_r(pixel.r, alpha, new_alpha),
                    g: compute_g(pixel.g, alpha, new_alpha),
                    b: compute_b(pixel.b, alpha, new_alpha),
                    a: ((new_alpha * 255f64) + 0.5) as u8,
                };

                data.set_pixel(stride, output_pixel, x, y);
            }
        });

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: surface.share()?,
                bounds,
            },
        })
    }
}

impl FilterEffect for FeComponentTransfer {
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}
<commit_msg>feComponentTransfer - extract the functions to use before doing the remapping<commit_after>use std::cmp::min;

use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::error::*;
use crate::node::{Node, NodeBorrow};
use crate::parsers::{NumberList, NumberListLength, Parse, ParseValue};
use crate::surface_utils::{
    iterators::Pixels, shared_surface::ExclusiveImageSurface, ImageSurfaceDataExt, Pixel,
};
use crate::util::clamp;
use crate::xml::Attributes;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, FilterRender, PrimitiveWithInput};

/// The `feComponentTransfer` filter primitive.
pub struct FeComponentTransfer {
    base: PrimitiveWithInput,
}

impl Default for FeComponentTransfer {
    /// Constructs a new `ComponentTransfer` with empty properties.
    #[inline]
    fn default() -> FeComponentTransfer {
        FeComponentTransfer {
            base: PrimitiveWithInput::new::<Self>(),
        }
    }
}

impl SetAttributes for FeComponentTransfer {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.base.set_attributes(attrs)
    }
}

/// Pixel components that can be influenced by `feComponentTransfer`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Channel {
    R,
    G,
    B,
    A,
}

/// Component transfer function types.
#[derive(Clone)]
enum FunctionType {
    Identity,
    Table,
    Discrete,
    Linear,
    Gamma,
}

impl Parse for FunctionType {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "identity" => FunctionType::Identity,
            "table" => FunctionType::Table,
            "discrete" => FunctionType::Discrete,
            "linear" => FunctionType::Linear,
            "gamma" => FunctionType::Gamma,
        )?)
    }
}

/// The compute function parameters.
struct FunctionParameters {
    table_values: Vec<f64>,
    slope: f64,
    intercept: f64,
    amplitude: f64,
    exponent: f64,
    offset: f64,
}

struct Functions {
    r: FeFuncR,
    g: FeFuncG,
    b: FeFuncB,
    a: FeFuncA,
}

/// The compute function type.
type Function = fn(&FunctionParameters, f64) -> f64;

/// The identity component transfer function.
fn identity(_: &FunctionParameters, value: f64) -> f64 {
    value
}

/// The table component transfer function.
fn table(params: &FunctionParameters, value: f64) -> f64 {
    let n = params.table_values.len() - 1;
    let k = (value * (n as f64)).floor() as usize;

    let k = min(k, n); // Just in case.

    if k == n {
        return params.table_values[k];
    }

    let vk = params.table_values[k];
    let vk1 = params.table_values[k + 1];
    let k = k as f64;
    let n = n as f64;

    vk + (value - k / n) * n * (vk1 - vk)
}

/// The discrete component transfer function.
fn discrete(params: &FunctionParameters, value: f64) -> f64 {
    let n = params.table_values.len();
    let k = (value * (n as f64)).floor() as usize;

    params.table_values[min(k, n - 1)]
}

/// The linear component transfer function.
fn linear(params: &FunctionParameters, value: f64) -> f64 {
    params.slope * value + params.intercept
}

/// The gamma component transfer function.
fn gamma(params: &FunctionParameters, value: f64) -> f64 {
    params.amplitude * value.powf(params.exponent) + params.offset
}

trait FeComponentTransferFunc {
    /// Returns the component transfer function.
    fn function(&self) -> Function;

    /// Returns the component transfer function parameters.
    fn function_parameters(&self) -> FunctionParameters;

    /// Returns the channel.
    fn channel(&self) -> Channel;
}

macro_rules! func_x {
    ($func_name:ident, $channel:expr) => {
        #[derive(Clone)]
        pub struct $func_name {
            channel: Channel,
            function_type: FunctionType,
            table_values: Vec<f64>,
            slope: f64,
            intercept: f64,
            amplitude: f64,
            exponent: f64,
            offset: f64,
        }

        impl Default for $func_name {
            #[inline]
            fn default() -> Self {
                Self {
                    channel: $channel,
                    function_type: FunctionType::Identity,
                    table_values: Vec::new(),
                    slope: 1.0,
                    intercept: 0.0,
                    amplitude: 1.0,
                    exponent: 1.0,
                    offset: 0.0,
                }
            }
        }

        impl FeComponentTransferFunc for $func_name {
            #[inline]
            fn function_parameters(&self) -> FunctionParameters {
                FunctionParameters {
                    table_values: self.table_values.clone(),
                    slope: self.slope,
                    intercept: self.intercept,
                    amplitude: self.amplitude,
                    exponent: self.exponent,
                    offset: self.offset,
                }
            }

            #[inline]
            fn function(&self) -> Function {
                match self.function_type {
                    FunctionType::Identity => identity,
                    FunctionType::Table => table,
                    FunctionType::Discrete => discrete,
                    FunctionType::Linear => linear,
                    FunctionType::Gamma => gamma,
                }
            }

            #[inline]
            fn channel(&self) -> Channel {
                self.channel
            }
        }

        impl SetAttributes for $func_name {
            #[inline]
            fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
                for (attr, value) in attrs.iter() {
                    match attr.expanded() {
                        expanded_name!("", "type") => self.function_type = attr.parse(value)?,
                        expanded_name!("", "tableValues") => {
                            let NumberList(v) =
                                NumberList::parse_str(value, NumberListLength::Unbounded)
                                    .attribute(attr)?;
                            self.table_values = v;
                        }
                        expanded_name!("", "slope") => self.slope = attr.parse(value)?,
                        expanded_name!("", "intercept") => self.intercept = attr.parse(value)?,
                        expanded_name!("", "amplitude") => self.amplitude = attr.parse(value)?,
                        expanded_name!("", "exponent") => self.exponent = attr.parse(value)?,
                        expanded_name!("", "offset") => self.offset = attr.parse(value)?,

                        _ => (),
                    }
                }

                // The table function type with empty table_values is considered
                // an identity function.
                match self.function_type {
                    FunctionType::Table | FunctionType::Discrete => {
                        if self.table_values.is_empty() {
                            self.function_type = FunctionType::Identity;
                        }
                    }
                    _ => (),
                }

                Ok(())
            }
        }

        impl Draw for $func_name {}
    };
}

// The `<feFuncR>` element
func_x!(FeFuncR, Channel::R);

// The `<feFuncG>` element
func_x!(FeFuncG, Channel::G);

// The `<feFuncB>` element
func_x!(FeFuncB, Channel::B);

// The `<feFuncA>` element
func_x!(FeFuncA, Channel::A);

macro_rules! func_or_default {
    ($func_node:ident, $func_type:ident, $func_data:ident, $func_default:ident) => {
        match $func_node {
            Some(ref f) => {
                $func_data = f.borrow_element();
                match *$func_data {
                    Element::$func_type(ref e) => e.element_impl.clone(),
                    _ => unreachable!(),
                }
            }
            _ => $func_default,
        };
    };
}

macro_rules! get_func_x_node {
    ($func_node:ident, $func_type:ident, $channel:expr) => {
        $func_node
            .children()
            .rev()
            .filter(|c| c.is_element())
            .find(|c| match *c.borrow_element() {
                Element::$func_type(ref f) => f.channel() == $channel,
                _ => false,
            })
    };
}

impl FilterRender for FeComponentTransfer {
    fn render(
        &self,
        node: &Node,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let functions = get_parameters(node)?;

        let input = self.base.get_input(ctx, acquired_nodes, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx)?
            .add_input(&input)
            .into_irect(ctx, draw_ctx);

        // Create the output surface.
        let mut surface = ExclusiveImageSurface::new(
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
            input.surface().surface_type(),
        )?;

        #[inline]
        fn compute_func<F>(func: &F) -> impl Fn(u8, f64, f64) -> u8 + '_
        where
            F: FeComponentTransferFunc,
        {
            let compute = func.function();
            let params = func.function_parameters();

            move |value, alpha, new_alpha| {
                let value = f64::from(value) / 255f64;

                let unpremultiplied = if alpha == 0f64 { 0f64 } else { value / alpha };

                let new_value = compute(&params, unpremultiplied);
                let new_value = clamp(new_value, 0f64, 1f64);

                ((new_value * new_alpha * 255f64) + 0.5) as u8
            }
        }

        let compute_r = compute_func::<FeFuncR>(&functions.r);
        let compute_g = compute_func::<FeFuncG>(&functions.g);
        let compute_b = compute_func::<FeFuncB>(&functions.b);

        // Alpha gets special handling since everything else depends on it.
        let compute_a = functions.a.function();
        let params_a = functions.a.function_parameters();
        let compute_a = |alpha| compute_a(&params_a, alpha);

        // Do the actual processing.
        surface.modify(&mut |data, stride| {
            for (x, y, pixel) in Pixels::within(input.surface(), bounds) {
                let alpha = f64::from(pixel.a) / 255f64;
                let new_alpha = compute_a(alpha);

                let output_pixel = Pixel {
                    r: compute_r(pixel.r, alpha, new_alpha),
                    g: compute_g(pixel.g, alpha, new_alpha),
                    b: compute_b(pixel.b, alpha, new_alpha),
                    a: ((new_alpha * 255f64) + 0.5) as u8,
                };

                data.set_pixel(stride, output_pixel, x, y);
            }
        });

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: surface.share()?,
                bounds,
            },
        })
    }
}

impl FilterEffect for FeComponentTransfer {
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}

/// Takes a feComponentTransfer and walks its children to produce the feFuncX arguments.
fn get_parameters(node: &Node) -> Result<Functions, FilterError> {
    let func_r_node = get_func_x_node!(node, FeFuncR, Channel::R);
    let func_g_node = get_func_x_node!(node, FeFuncG, Channel::G);
    let func_b_node = get_func_x_node!(node, FeFuncB, Channel::B);
    let func_a_node = get_func_x_node!(node, FeFuncA, Channel::A);

    for node in [&func_r_node, &func_g_node, &func_b_node, &func_a_node]
        .iter()
        .filter_map(|x| x.as_ref())
    {
        if node.borrow_element().is_in_error() {
            return Err(FilterError::ChildNodeInError);
        }
    }

    // These are the default funcs that perform an identity transformation.
    let func_r_default = FeFuncR::default();
    let func_g_default = FeFuncG::default();
    let func_b_default = FeFuncB::default();
    let func_a_default = FeFuncA::default();

    // We need to tell the borrow checker that these live long enough
    let func_r_element;
    let func_g_element;
    let func_b_element;
    let func_a_element;

    let r = func_or_default!(func_r_node, FeFuncR, func_r_element, func_r_default);
    let g = func_or_default!(func_g_node, FeFuncG, func_g_element, func_g_default);
    let b = func_or_default!(func_b_node, FeFuncB, func_b_element, func_b_default);
    let a = func_or_default!(func_a_node, FeFuncA, func_a_element, func_a_default);

    Ok(Functions { r, g, b, a })
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use super::{Args, Configuration};
use client::Context;
use model::{Message, Permissions};
use std::collections::HashMap;
use std::fmt;

pub type Check = Fn(&mut Context, &Message, &mut Args, &Arc<Command>) -> bool
                     + Send
                     + Sync
                     + 'static;
pub type Exec = Fn(&mut Context, &Message, Args) -> Result<(), Error> + Send + Sync + 'static;
pub type Help = Fn(&mut Context, &Message, HashMap<String, Arc<CommandGroup>>, Args)
                   -> Result<(), Error>
                    + Send
                    + Sync
                    + 'static;
pub type BeforeHook = Fn(&mut Context, &Message, &str) -> bool + Send + Sync + 'static;
pub type AfterHook = Fn(&mut Context, &Message, &str, Result<(), Error>) + Send + Sync + 'static;
pub(crate) type InternalCommand = Arc<Command>;
pub type PrefixCheck = Fn(&mut Context, &Message) -> Option<String> + Send + Sync + 'static;

pub enum CommandOrAlias {
    Alias(String),
    Command(InternalCommand),
}

/// An error from a command.
#[derive(Clone, Debug)]
pub struct Error(String);

impl<D: fmt::Display> From<D> for Error {
    fn from(d: D) -> Self {
        Error(format!("{}", d))
    }
}

/// Command function type. Allows to access internal framework things inside
/// your commands.
pub enum CommandType {
    StringResponse(String),
    Basic(Box<Exec>),
    WithCommands(Box<Help>),
}

pub struct CommandGroup {
    pub prefix: Option<String>,
    pub commands: HashMap<String, CommandOrAlias>,
    /// Some fields taken from Command
    pub bucket: Option<String>,
    pub required_permissions: Permissions,
    pub allowed_roles: Vec<String>,
    pub help_available: bool,
    pub dm_only: bool,
    pub guild_only: bool,
    pub owners_only: bool,
}

/// Command struct used to store commands internally.
pub struct Command {
    /// A set of checks to be called prior to executing the command. The checks
    /// will short-circuit on the first check that returns `false`.
    pub checks: Vec<Box<Check>>,
    /// Function called when the command is called.
    pub exec: CommandType,
    /// Ratelimit bucket.
    pub bucket: Option<String>,
    /// Command description, used by other commands.
    pub desc: Option<String>,
    /// Example arguments, used by other commands.
    pub example: Option<String>,
    /// Command usage schema, used by other commands.
    pub usage: Option<String>,
    /// Minumum amount of arguments that should be passed.
    pub min_args: Option<i32>,
    /// Maximum amount of arguments that can be passed.
    pub max_args: Option<i32>,
    /// Permissions required to use this command.
    pub required_permissions: Permissions,
    /// Roles allowed to use this command.
    pub allowed_roles: Vec<String>,
    /// Whether command should be displayed in help list or not, used by other commands.
    pub help_available: bool,
    /// Whether command can be used only privately or not.
    pub dm_only: bool,
    /// Whether command can be used only in guilds or not.
    pub guild_only: bool,
    /// Whether command can only be used by owners or not.
    pub owners_only: bool,
    pub(crate) aliases: Vec<String>,
}

impl Command {
    pub fn new<F>(f: F) -> Self
        where F: Fn(&mut Context, &Message, Args) -> Result<(), Error> + Send + Sync + 'static {
        Command {
            exec: CommandType::Basic(Box::new(f)),
            ..Command::default()
        }
    }
}

impl Default for Command {
    fn default() -> Command {
        Command {
            aliases: Vec::new(),
            checks: Vec::default(),
            exec: CommandType::Basic(Box::new(|_, _, _| Ok(()))),
            desc: None,
            usage: None,
            example: None,
            min_args: None,
            bucket: None,
            max_args: None,
            required_permissions: Permissions::empty(),
            dm_only: false,
            guild_only: false,
            help_available: true,
            owners_only: false,
            allowed_roles: Vec::new(),
        }
    }
}

pub fn positions(ctx: &mut Context, msg: &Message, conf: &Configuration) -> Option<Vec<usize>> {
    if !conf.prefixes.is_empty() || conf.dynamic_prefix.is_some() {
        // Find out if they were mentioned. If not, determine if the prefix
        // was used. If not, return None.
        let mut positions: Vec<usize> = vec![];

        if let Some(mention_end) = find_mention_end(&msg.content, conf) {
            positions.push(mention_end);
        } else if let Some(ref func) = conf.dynamic_prefix {
            if let Some(x) = func(ctx, msg) {
                if msg.content.starts_with(&x) {
                    positions.push(x.len());
                }
            } else {
                for n in &conf.prefixes {
                    if msg.content.starts_with(n) {
                        positions.push(n.len());
                    }
                }
            }
        } else {
            for n in &conf.prefixes {
                if msg.content.starts_with(n) {
                    positions.push(n.len());
                }
            }
        };

        if positions.is_empty() {
            return None;
        }

        if conf.allow_whitespace {
            let pos = *unsafe { positions.get_unchecked(0) };

            positions.insert(0, pos + 1);
        }

        Some(positions)
    } else if conf.on_mention.is_some() {
        find_mention_end(&msg.content, conf).map(|mention_end| {
            let mut positions = vec![mention_end];

            if conf.allow_whitespace {
                positions.insert(0, mention_end + 1);
            }

            positions
        })
    } else {
        None
    }
}

fn find_mention_end(content: &str, conf: &Configuration) -> Option<usize> {
    conf.on_mention.as_ref().and_then(|mentions| {
        mentions
            .iter()
            .find(|mention| content.starts_with(&mention[..]))
            .map(|m| m.len())
    })
}
<commit_msg>Make the internal string public<commit_after>use std::sync::Arc;
use super::{Args, Configuration};
use client::Context;
use model::{Message, Permissions};
use std::collections::HashMap;
use std::fmt;

pub type Check = Fn(&mut Context, &Message, &mut Args, &Arc<Command>) -> bool
                     + Send
                     + Sync
                     + 'static;
pub type Exec = Fn(&mut Context, &Message, Args) -> Result<(), Error> + Send + Sync + 'static;
pub type Help = Fn(&mut Context, &Message, HashMap<String, Arc<CommandGroup>>, Args)
                   -> Result<(), Error>
                    + Send
                    + Sync
                    + 'static;
pub type BeforeHook = Fn(&mut Context, &Message, &str) -> bool + Send + Sync + 'static;
pub type AfterHook = Fn(&mut Context, &Message, &str, Result<(), Error>) + Send + Sync + 'static;
pub(crate) type InternalCommand = Arc<Command>;
pub type PrefixCheck = Fn(&mut Context, &Message) -> Option<String> + Send + Sync + 'static;

pub enum CommandOrAlias {
    Alias(String),
    Command(InternalCommand),
}

/// An error from a command.
#[derive(Clone, Debug)]
pub struct Error(pub String);

impl<D: fmt::Display> From<D> for Error {
    fn from(d: D) -> Self {
        Error(format!("{}", d))
    }
}

/// Command function type. Allows to access internal framework things inside
/// your commands.
pub enum CommandType {
    StringResponse(String),
    Basic(Box<Exec>),
    WithCommands(Box<Help>),
}

pub struct CommandGroup {
    pub prefix: Option<String>,
    pub commands: HashMap<String, CommandOrAlias>,
    /// Some fields taken from Command
    pub bucket: Option<String>,
    pub required_permissions: Permissions,
    pub allowed_roles: Vec<String>,
    pub help_available: bool,
    pub dm_only: bool,
    pub guild_only: bool,
    pub owners_only: bool,
}

/// Command struct used to store commands internally.
pub struct Command {
    /// A set of checks to be called prior to executing the command. The checks
    /// will short-circuit on the first check that returns `false`.
    pub checks: Vec<Box<Check>>,
    /// Function called when the command is called.
    pub exec: CommandType,
    /// Ratelimit bucket.
    pub bucket: Option<String>,
    /// Command description, used by other commands.
    pub desc: Option<String>,
    /// Example arguments, used by other commands.
    pub example: Option<String>,
    /// Command usage schema, used by other commands.
    pub usage: Option<String>,
    /// Minumum amount of arguments that should be passed.
    pub min_args: Option<i32>,
    /// Maximum amount of arguments that can be passed.
    pub max_args: Option<i32>,
    /// Permissions required to use this command.
    pub required_permissions: Permissions,
    /// Roles allowed to use this command.
    pub allowed_roles: Vec<String>,
    /// Whether command should be displayed in help list or not, used by other commands.
    pub help_available: bool,
    /// Whether command can be used only privately or not.
    pub dm_only: bool,
    /// Whether command can be used only in guilds or not.
    pub guild_only: bool,
    /// Whether command can only be used by owners or not.
    pub owners_only: bool,
    pub(crate) aliases: Vec<String>,
}

impl Command {
    pub fn new<F>(f: F) -> Self
        where F: Fn(&mut Context, &Message, Args) -> Result<(), Error> + Send + Sync + 'static {
        Command {
            exec: CommandType::Basic(Box::new(f)),
            ..Command::default()
        }
    }
}

impl Default for Command {
    fn default() -> Command {
        Command {
            aliases: Vec::new(),
            checks: Vec::default(),
            exec: CommandType::Basic(Box::new(|_, _, _| Ok(()))),
            desc: None,
            usage: None,
            example: None,
            min_args: None,
            bucket: None,
            max_args: None,
            required_permissions: Permissions::empty(),
            dm_only: false,
            guild_only: false,
            help_available: true,
            owners_only: false,
            allowed_roles: Vec::new(),
        }
    }
}

pub fn positions(ctx: &mut Context, msg: &Message, conf: &Configuration) -> Option<Vec<usize>> {
    if !conf.prefixes.is_empty() || conf.dynamic_prefix.is_some() {
        // Find out if they were mentioned. If not, determine if the prefix
        // was used. If not, return None.
        let mut positions: Vec<usize> = vec![];

        if let Some(mention_end) = find_mention_end(&msg.content, conf) {
            positions.push(mention_end);
        } else if let Some(ref func) = conf.dynamic_prefix {
            if let Some(x) = func(ctx, msg) {
                if msg.content.starts_with(&x) {
                    positions.push(x.len());
                }
            } else {
                for n in &conf.prefixes {
                    if msg.content.starts_with(n) {
                        positions.push(n.len());
                    }
                }
            }
        } else {
            for n in &conf.prefixes {
                if msg.content.starts_with(n) {
                    positions.push(n.len());
                }
            }
        };

        if positions.is_empty() {
            return None;
        }

        if conf.allow_whitespace {
            let pos = *unsafe { positions.get_unchecked(0) };

            positions.insert(0, pos + 1);
        }

        Some(positions)
    } else if conf.on_mention.is_some() {
        find_mention_end(&msg.content, conf).map(|mention_end| {
            let mut positions = vec![mention_end];

            if conf.allow_whitespace {
                positions.insert(0, mention_end + 1);
            }

            positions
        })
    } else {
        None
    }
}

fn find_mention_end(content: &str, conf: &Configuration) -> Option<usize> {
    conf.on_mention.as_ref().and_then(|mentions| {
        mentions
            .iter()
            .find(|mention| content.starts_with(&mention[..]))
            .map(|m| m.len())
    })
}
<|endoftext|>


<commit_before>use subframe::{self, Subframe, MAX_FIXED_ORDER, MAX_LPC_ORDER};

use std::ptr;

// Restore the original signal from a fixed linear prediction.
//
// Signal restoration is accomplished by summing up the residual and the
// predictor. With the linear prediction being "fixed", the polynomials will
// remain the same depending on the order value. And the max order is
// `MAX_FIXED_ORDER`, which is 4.
//
// This function also assumes that `output` already has the warm up values
// from the `Fixed` subframe in it.
pub fn fixed_restore_signal(order: usize,
                            block_size: usize,
                            output: &mut [i32]) {
  debug_assert!(order <= MAX_FIXED_ORDER);

  let polynomial = [ &[][..]
                   , &[1][..]
                   , &[-1, 2][..]
                   , &[1, -3, 3][..]
                   , &[-1, 4, -6, 4][..]
                   ];

  let coefficients = polynomial[order];
  let length       = block_size - order;

  for i in 0..length {
    let offset     = i + order;
    let prediction = coefficients.iter()
                      .zip(&output[i..offset])
                      .fold(0, |result, (coefficient, signal)|
                            result + coefficient * signal);

    output[offset] += prediction;
  }
}

// Restore the original signal from a FIR linear prediction.
//
// Signal restoration is accomplished by summing up the residual and the
// predictor. Figuring out the linear prediction for finite impulse response
// is a bit more involved because you have more to deal with, but the
// concept is very similar to the fixed version. Coefficients are passed in
// and reversed within function and the result of these reverse order
// coefficients and warm up values are summed and the quantization level
// will determine how much the bits gets shifted in order to figure the
// current predictor for it's corresponding residual value.
//
// The order doesn't get passed in explicitly because the coefficients
// length is assumed to be the value of order. And the max order is
// `MAX_LPC_ORDER`, which is 32. This function also assumes that `output`
// already has the warm up values from the `LPC` subframe in it.
pub fn lpc_restore_signal(quantization_level: i8,
                          block_size: usize,
                          coefficients: &[i32],
                          output: &mut [i32]) {
  let order  = coefficients.len();
  let length = block_size - order;

  debug_assert!(order <= MAX_LPC_ORDER);

  for i in 0..length {
    let offset     = i + order;
    let prediction = coefficients.iter().rev()
                       .zip(&output[i..offset])
                       .fold(0, |result, (coefficient, signal)|
                             result + coefficient * signal);

    output[offset] += prediction >> quantization_level;
  }
}

/// Decodes the current subframe.
///
/// * `Constant` - fills the length of `output` with the constant value
///   within the subframe.
/// * `Verbatim` - copies the data within the verbatim subframe over to
///   `output`.
/// * `Fixed` - restore the signal of the fixed linear prediction and put
///   the result into `output`.
/// * `LPC` - restore the signal of the finite impulse response linear
///   prediction and put the result into `output`.
pub fn decode(subframe: &Subframe, block_size: usize, output: &mut [i32]) {
  match subframe.data {
    subframe::Data::Constant(constant)     => {
      for i in 0..output.len() {
        output[i] = constant
      }
    }
    subframe::Data::Verbatim(ref verbatim) => {
      let length = verbatim.len();

      unsafe {
        ptr::copy(verbatim.as_ptr(), output.as_mut_ptr(), length)
      }
    }
    subframe::Data::Fixed(ref fixed)       => {
      let order = fixed.order as usize;

      for i in 0..order {
        output[i] = fixed.warmup[i];
      }

      fixed_restore_signal(order, block_size, output);
    }
    subframe::Data::LPC(ref lpc)           => {
      let order        = lpc.order as usize;
      let coefficients = &lpc.qlp_coefficients[0..order];

      for i in 0..order {
        output[i] = lpc.warmup[i];
      }

      lpc_restore_signal(lpc.quantization_level, block_size, coefficients,
                         output);
    }
  }

  if subframe.wasted_bits > 0 {
    for value in output {
      *value <<= subframe.wasted_bits;
    }
  }
}

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

  use subframe;
  use subframe::{
    Subframe, Fixed, LPC,
    EntropyCodingMethod, CodingMethod, PartitionedRice,
    PartitionedRiceContents,
  };

  #[test]
  fn test_fixed_restore_signal() {
    let mut outputs = [ &mut [-729, -722, -667, -19, -16, 17, -23, -7, 16
                             , -16, -5, 3, -8, -13, -15, -1][..]
                      , &mut [21877, 27482, -6513][..]
                      ];

    fixed_restore_signal(3, 16, &mut outputs[0]);
    fixed_restore_signal(2, 3, &mut outputs[1]);

    assert_eq!(&outputs[0], &[-729, -722, -667, -583, -486, -359, -225, -91
                             , 59, 209, 354, 497, 630, 740, 812, 845]);
    assert_eq!(&outputs[1], &[21877, 27482, 26574]);
  }

  #[test]
  fn test_lpc_restore_signal() {
    let coefficients = [ &[1042, -399, -75, -269, 121, 166, -75][..]
                       , &[1757, -1199, 879, -836, 555, -255, 119][..]
                       ];
    let mut outputs = [ &mut [-796, -547, -285, -32, 199, 443, 670
                             , -2, -23, 14, 6, 3, -4, 12, -2, 10][..]
                      , &mut [-21363, -21951, -22649, -24364, -27297, -26870
                             ,-30017, 3157][..]
                      ];

    lpc_restore_signal(9, 16, &coefficients[0], &mut outputs[0]);
    lpc_restore_signal(10, 8, &coefficients[1], &mut outputs[1]);

    assert_eq!(&outputs[0], &[-796, -547, -285, -32, 199, 443, 670, 875
                             , 1046, 1208, 1343, 1454, 1541, 1616, 1663
                             , 1701]);
    assert_eq!(&outputs[1], &[-21363, -21951, -22649, -24364, -27297, -26870
                             , -30017, -29718]);
  }

  #[test]
  fn test_decode() {
    let mut output = [0; 16];

    let constant = Subframe {
      data: subframe::Data::Constant(4),
      wasted_bits: 0,
    };

    let verbatim = Subframe {
      data: subframe::Data::Verbatim(vec![16, -3, 55, 49, -32, 6, 40, -90, 1
                                         ,0, 77, -12, 84, 10, -112, 136]),
      wasted_bits: 0,
    };

    let fixed = Subframe {
      data: subframe::Data::Fixed(Fixed {
        entropy_coding_method: EntropyCodingMethod {
          method_type: CodingMethod::PartitionedRice,
          data: PartitionedRice {
            order: 0,
            contents: PartitionedRiceContents {
              parameters: vec![],
              raw_bits: vec![],
            },
          },
        },
        order: 3,
        warmup: [-729, -722, -667, 0],
        residual: vec![-19, -16, 17, -23, -7, 16, -16, -5, 3 , -8, -13, -15
                      ,-1],
      }),
      wasted_bits: 0,
    };

    let lpc = Subframe {
      data: subframe::Data::LPC(LPC {
        entropy_coding_method: EntropyCodingMethod {
          method_type: CodingMethod::PartitionedRice,
          data: PartitionedRice {
            order: 0,
            contents: PartitionedRiceContents {
              parameters: vec![],
              raw_bits: vec![],
            },
          },
        },
        order: 7,
        qlp_coeff_precision: 0,
        quantization_level: 9,
        qlp_coefficients: [1042, -399, -75, -269, 121, 166, -75, 0, 0, 0, 0
                          ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                          ,0, 0, 0, 0],
        warmup: [-796, -547, -285, -32, 199, 443, 670, 0, 0, 0, 0, 0, 0, 0, 0
                ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        residual: vec![-2, -23, 14, 6, 3, -4, 12, -2, 10],
      }),
      wasted_bits: 0,
    };

    decode(&constant, 16, &mut output);
    assert_eq!(&output, &[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]);

    decode(&verbatim, 16, &mut output);
    assert_eq!(&output, &[16, -3, 55, 49, -32, 6, 40 , -90, 1, 0, 77, -12, 84
                         ,10 , -112, 136]);

    {
      let residual = [-19, -16, 17, -23, -7, 16, -16, -5, 3 , -8, -13, -15
                     ,-1];

      for i in 0..residual.len() {
        output[i + 3] = residual[i];
      }

      decode(&fixed, 16, &mut output);
      assert_eq!(&output, &[-729, -722, -667, -583, -486, -359, -225, -91, 59
                           ,209, 354, 497, 630, 740, 812, 845]);
    }

    {
      let residual = [-2, -23, 14, 6, 3, -4, 12, -2, 10];

      for i in 0..residual.len() {
        output[i + 7] = residual[i];
      }

      decode(&lpc, 16, &mut output);
      assert_eq!(&output, &[-796, -547, -285, -32, 199, 443, 670, 875, 1046
                           ,1208, 1343, 1454, 1541, 1616, 1663, 1701]);
    }
  }

  #[test]
  fn test_wasted_bit_decode() {
    let mut output = [0; 4];

    let constant = Subframe {
      data: subframe::Data::Constant(1),
      wasted_bits: 10,
    };

    decode(&constant, 4, &mut output);
    assert_eq!(&output, &[1024, 1024, 1024, 1024]);
  }
}
<commit_msg>Fix decode tests for new `PartitionedRiceContents`<commit_after>use subframe::{self, Subframe, MAX_FIXED_ORDER, MAX_LPC_ORDER};

use std::ptr;

// Restore the original signal from a fixed linear prediction.
//
// Signal restoration is accomplished by summing up the residual and the
// predictor. With the linear prediction being "fixed", the polynomials will
// remain the same depending on the order value. And the max order is
// `MAX_FIXED_ORDER`, which is 4.
//
// This function also assumes that `output` already has the warm up values
// from the `Fixed` subframe in it.
pub fn fixed_restore_signal(order: usize,
                            block_size: usize,
                            output: &mut [i32]) {
  debug_assert!(order <= MAX_FIXED_ORDER);

  let polynomial = [ &[][..]
                   , &[1][..]
                   , &[-1, 2][..]
                   , &[1, -3, 3][..]
                   , &[-1, 4, -6, 4][..]
                   ];

  let coefficients = polynomial[order];
  let length       = block_size - order;

  for i in 0..length {
    let offset     = i + order;
    let prediction = coefficients.iter()
                      .zip(&output[i..offset])
                      .fold(0, |result, (coefficient, signal)|
                            result + coefficient * signal);

    output[offset] += prediction;
  }
}

// Restore the original signal from a FIR linear prediction.
//
// Signal restoration is accomplished by summing up the residual and the
// predictor. Figuring out the linear prediction for finite impulse response
// is a bit more involved because you have more to deal with, but the
// concept is very similar to the fixed version. Coefficients are passed in
// and reversed within function and the result of these reverse order
// coefficients and warm up values are summed and the quantization level
// will determine how much the bits gets shifted in order to figure the
// current predictor for it's corresponding residual value.
//
// The order doesn't get passed in explicitly because the coefficients
// length is assumed to be the value of order. And the max order is
// `MAX_LPC_ORDER`, which is 32. This function also assumes that `output`
// already has the warm up values from the `LPC` subframe in it.
pub fn lpc_restore_signal(quantization_level: i8,
                          block_size: usize,
                          coefficients: &[i32],
                          output: &mut [i32]) {
  let order  = coefficients.len();
  let length = block_size - order;

  debug_assert!(order <= MAX_LPC_ORDER);

  for i in 0..length {
    let offset     = i + order;
    let prediction = coefficients.iter().rev()
                       .zip(&output[i..offset])
                       .fold(0, |result, (coefficient, signal)|
                             result + coefficient * signal);

    output[offset] += prediction >> quantization_level;
  }
}

/// Decodes the current subframe.
///
/// * `Constant` - fills the length of `output` with the constant value
///   within the subframe.
/// * `Verbatim` - copies the data within the verbatim subframe over to
///   `output`.
/// * `Fixed` - restore the signal of the fixed linear prediction and put
///   the result into `output`.
/// * `LPC` - restore the signal of the finite impulse response linear
///   prediction and put the result into `output`.
pub fn decode(subframe: &Subframe, block_size: usize, output: &mut [i32]) {
  match subframe.data {
    subframe::Data::Constant(constant)     => {
      for i in 0..output.len() {
        output[i] = constant
      }
    }
    subframe::Data::Verbatim(ref verbatim) => {
      let length = verbatim.len();

      unsafe {
        ptr::copy(verbatim.as_ptr(), output.as_mut_ptr(), length)
      }
    }
    subframe::Data::Fixed(ref fixed)       => {
      let order = fixed.order as usize;

      for i in 0..order {
        output[i] = fixed.warmup[i];
      }

      fixed_restore_signal(order, block_size, output);
    }
    subframe::Data::LPC(ref lpc)           => {
      let order        = lpc.order as usize;
      let coefficients = &lpc.qlp_coefficients[0..order];

      for i in 0..order {
        output[i] = lpc.warmup[i];
      }

      lpc_restore_signal(lpc.quantization_level, block_size, coefficients,
                         output);
    }
  }

  if subframe.wasted_bits > 0 {
    for value in output {
      *value <<= subframe.wasted_bits;
    }
  }
}

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

  use subframe;
  use subframe::{
    Subframe, Fixed, LPC,
    EntropyCodingMethod, CodingMethod, PartitionedRice,
    PartitionedRiceContents,
  };

  #[test]
  fn test_fixed_restore_signal() {
    let mut outputs = [ &mut [-729, -722, -667, -19, -16, 17, -23, -7, 16
                             , -16, -5, 3, -8, -13, -15, -1][..]
                      , &mut [21877, 27482, -6513][..]
                      ];

    fixed_restore_signal(3, 16, &mut outputs[0]);
    fixed_restore_signal(2, 3, &mut outputs[1]);

    assert_eq!(&outputs[0], &[-729, -722, -667, -583, -486, -359, -225, -91
                             , 59, 209, 354, 497, 630, 740, 812, 845]);
    assert_eq!(&outputs[1], &[21877, 27482, 26574]);
  }

  #[test]
  fn test_lpc_restore_signal() {
    let coefficients = [ &[1042, -399, -75, -269, 121, 166, -75][..]
                       , &[1757, -1199, 879, -836, 555, -255, 119][..]
                       ];
    let mut outputs = [ &mut [-796, -547, -285, -32, 199, 443, 670
                             , -2, -23, 14, 6, 3, -4, 12, -2, 10][..]
                      , &mut [-21363, -21951, -22649, -24364, -27297, -26870
                             ,-30017, 3157][..]
                      ];

    lpc_restore_signal(9, 16, &coefficients[0], &mut outputs[0]);
    lpc_restore_signal(10, 8, &coefficients[1], &mut outputs[1]);

    assert_eq!(&outputs[0], &[-796, -547, -285, -32, 199, 443, 670, 875
                             , 1046, 1208, 1343, 1454, 1541, 1616, 1663
                             , 1701]);
    assert_eq!(&outputs[1], &[-21363, -21951, -22649, -24364, -27297, -26870
                             , -30017, -29718]);
  }

  #[test]
  fn test_decode() {
    let mut output = [0; 16];

    let constant = Subframe {
      data: subframe::Data::Constant(4),
      wasted_bits: 0,
    };

    let verbatim = Subframe {
      data: subframe::Data::Verbatim(vec![16, -3, 55, 49, -32, 6, 40, -90, 1
                                         ,0, 77, -12, 84, 10, -112, 136]),
      wasted_bits: 0,
    };

    let fixed = Subframe {
      data: subframe::Data::Fixed(Fixed {
        entropy_coding_method: EntropyCodingMethod {
          method_type: CodingMethod::PartitionedRice,
          data: PartitionedRice {
            order: 0,
            contents: PartitionedRiceContents {
              capacity: 0,
              data: Vec::new(),
            },
          },
        },
        order: 3,
        warmup: [-729, -722, -667, 0],
        residual: vec![-19, -16, 17, -23, -7, 16, -16, -5, 3 , -8, -13, -15
                      ,-1],
      }),
      wasted_bits: 0,
    };

    let lpc = Subframe {
      data: subframe::Data::LPC(LPC {
        entropy_coding_method: EntropyCodingMethod {
          method_type: CodingMethod::PartitionedRice,
          data: PartitionedRice {
            order: 0,
            contents: PartitionedRiceContents {
              capacity: 0,
              data: Vec::new(),
            },
          },
        },
        order: 7,
        qlp_coeff_precision: 0,
        quantization_level: 9,
        qlp_coefficients: [1042, -399, -75, -269, 121, 166, -75, 0, 0, 0, 0
                          ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                          ,0, 0, 0, 0],
        warmup: [-796, -547, -285, -32, 199, 443, 670, 0, 0, 0, 0, 0, 0, 0, 0
                ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        residual: vec![-2, -23, 14, 6, 3, -4, 12, -2, 10],
      }),
      wasted_bits: 0,
    };

    decode(&constant, 16, &mut output);
    assert_eq!(&output, &[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]);

    decode(&verbatim, 16, &mut output);
    assert_eq!(&output, &[16, -3, 55, 49, -32, 6, 40 , -90, 1, 0, 77, -12, 84
                         ,10 , -112, 136]);

    {
      let residual = [-19, -16, 17, -23, -7, 16, -16, -5, 3 , -8, -13, -15
                     ,-1];

      for i in 0..residual.len() {
        output[i + 3] = residual[i];
      }

      decode(&fixed, 16, &mut output);
      assert_eq!(&output, &[-729, -722, -667, -583, -486, -359, -225, -91, 59
                           ,209, 354, 497, 630, 740, 812, 845]);
    }

    {
      let residual = [-2, -23, 14, 6, 3, -4, 12, -2, 10];

      for i in 0..residual.len() {
        output[i + 7] = residual[i];
      }

      decode(&lpc, 16, &mut output);
      assert_eq!(&output, &[-796, -547, -285, -32, 199, 443, 670, 875, 1046
                           ,1208, 1343, 1454, 1541, 1616, 1663, 1701]);
    }
  }

  #[test]
  fn test_wasted_bit_decode() {
    let mut output = [0; 4];

    let constant = Subframe {
      data: subframe::Data::Constant(1),
      wasted_bits: 10,
    };

    decode(&constant, 4, &mut output);
    assert_eq!(&output, &[1024, 1024, 1024, 1024]);
  }
}
<|endoftext|>


<commit_before>/*!
The functionality in this module is only available on Linux platforms; NVML does
not support events on any other platform.
*/

use Device;
use EventSet;
use NVML;
use bitmasks::event::*;
use enums::event::XidError;
use error::*;
use struct_wrappers::event::EventData;

// TODO: Tests

/**
Represents the event types that an `EventLoop` can gather for you.

These are analagous to the constants in `bitmasks::event`.

Checking to see if the `Device` within an `Event` is the same physical device as
another `Device` that you have on hand can be accomplished via `Device.uuid()`.
*/
#[derive(Debug)]
pub enum Event<'nvml> {
    ClockChange(Device<'nvml>),
    CriticalXidError(Device<'nvml>, XidError),
    DoubleBitEccError(Device<'nvml>),
    PowerStateChange(Device<'nvml>),
    SingleBitEccError(Device<'nvml>),
    /// Returned if none of the above event types are contained in the
    /// `EventData` the `EventLoop` processes.
    Unknown
}

impl<'nvml> From<EventData<'nvml>> for Event<'nvml> {
    fn from(struct_: EventData<'nvml>) -> Self {
        if struct_.event_type.contains(CLOCK_CHANGE) {
            Event::ClockChange(struct_.device)
        } else if struct_.event_type.contains(CRITICAL_XID_ERROR) {
            // We can unwrap here because we know `event_data` will be `Some`
            // since the error is `CRITICAL_XID_ERROR`
            Event::CriticalXidError(struct_.device, struct_.event_data.unwrap())
        } else if struct_.event_type.contains(DOUBLE_BIT_ECC_ERROR) {
            Event::DoubleBitEccError(struct_.device)
        } else if struct_.event_type.contains(PSTATE_CHANGE) {
            Event::PowerStateChange(struct_.device)
        } else if struct_.event_type.contains(SINGLE_BIT_ECC_ERROR) {
            Event::SingleBitEccError(struct_.device)
        } else {
            Event::Unknown
        }
    }
}

/// Holds the `EventSet` utilized within an event loop.
///
/// A usage example can be found in the `examples` directory at the root.
// TODO: Example name ^
pub struct EventLoop<'nvml> {
    set: EventSet<'nvml>
}

impl<'nvml> EventLoop<'nvml> {
    /**
    Register another device that this `EventLoop` should receive events for.

    This method takes ownership of this struct and then hands it back to you if
    everything went well with the registration process.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `GpuLost`, if a GPU has fallen off the bus or is otherwise inaccessible
    * `Unknown`, on any unexpected error

    # Platform Support
    Only supports Linux.
    */
    #[inline]
    pub fn register_device(mut self, device: &'nvml Device<'nvml>) -> Result<Self> {
        self.set = device.register_events(device.supported_event_types()?, self.set)?;

        Ok(self)
    }

    /**
    Handle events with the given callback until the loop is manually interrupted.

    # Errors
    The function itself does not return anything. You will be given errors to
    handle within your closure if they occur; events are handed to you wrapped
    in a `Result`.

    The errors that you will need to handle are:

    * `Uninitialized`, if the library has not been successfully initialized
    * `GpuLost`, if a GPU has fallen off the bus or is otherwise inaccessible
    * `Unknown`, on any unexpected error

    # Examples
    See the `event_loop` example in the `examples` directory at the root.

    # Platform Support
    Only supports Linux.
    */
    // TODO: example name
    #[inline]
    pub fn run_forever<F>(&mut self, mut callback: F)
    where
        F: FnMut(Result<Event<'nvml>>, &mut EventLoopState),
    {
        let mut state = EventLoopState {
            interrupted: false
        };

        loop {
            if state.interrupted {
                break;
            };

            match self.set.wait(1) {
                Ok(data) => {
                    callback(Ok(data.into()), &mut state);
                },
                Err(Error(ErrorKind::Timeout, _)) => continue,
                value => callback(value.map(|d| d.into()), &mut state),
            };
        }
    }

    /// Obtain a reference to the `EventSet` contained within this struct.
    #[inline]
    pub fn as_inner(&'nvml self) -> &'nvml EventSet<'nvml> {
        &(self.set)
    }

    /// Obtain a mutable reference to the `EventSet` contained within this
    /// struct.
    #[inline]
    pub fn as_mut_inner(&'nvml mut self) -> &'nvml mut EventSet<'nvml> {
        &mut (self.set)
    }

    /// Consumes this `EventLoop` and yields the `EventSet` contained within.
    #[inline]
    pub fn into_inner(self) -> EventSet<'nvml> {
        self.set
    }
}

impl<'nvml> From<EventSet<'nvml>> for EventLoop<'nvml> {
    fn from(set: EventSet<'nvml>) -> Self {
        Self {
            set
        }
    }
}

/// Keeps track of whether an `EventLoop` is interrupted or not.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct EventLoopState {
    interrupted: bool
}

impl EventLoopState {
    /// Call this to mark the loop as interrupted.
    #[inline]
    pub fn interrupt(&mut self) {
        self.interrupted = true;
    }
}

/// Adds a method to obtain an `EventLoop` to the `NVML` struct.
///
/// `use` it at your leisure.
pub trait EventLoopProvider {
    // Thanks to Thinkofname for lifetime help, again :)
    fn create_event_loop<'nvml>(
        &'nvml self,
        devices: Vec<&'nvml Device<'nvml>>,
    ) -> Result<EventLoop>;
}

impl EventLoopProvider for NVML {
    /**
    Create an event loop that will register itself to recieve events for the given
    `Device`s.

    This function creates an event set and registers each devices' supported event
    types for it. The returned `EventLoop` struct then has methods that you can
    call to actually utilize it.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `GpuLost`, if any of the given `Device`s have fallen off the bus or are
    otherwise inaccessible
    * `Unknown`, on any unexpected error

    # Platform Support
    Only supports Linux.
    */
    #[inline]
    fn create_event_loop<'nvml>(
        &'nvml self,
        devices: Vec<&'nvml Device<'nvml>>,
    ) -> Result<EventLoop> {

        let mut set = self.create_event_set()?;

        for d in devices {
            set = d.register_events(d.supported_event_types()?, set)?;
        }

        Ok(EventLoop {
            set
        })
    }
}
<commit_msg>Improve the `event_loop` module documentation<commit_after>/*!
A convenient abstraction for working with events.

Simply register the devices you wish to receive events for and then compose
a handler for the events. Event handling looks like this (details removed):

```no_run
# extern crate nvml_wrapper as nvml;
#
# #[cfg(target_os = "linux")]
# fn main() {
#     example::actual_main().unwrap();
# }
#
# #[cfg(target_os = "windows")]
# fn main() {}
#
# #[cfg(target_os = "linux")]
# mod example {
# use nvml::NVML;
# use nvml::error::{Error, ErrorKind, Result};
# use nvml::high_level::EventLoopProvider;
# use nvml::high_level::Event::*;
#
# pub fn actual_main() -> Result<()> {
# let nvml = NVML::init()?;
# let device = nvml.device_by_index(0)?;
# let mut event_loop = nvml.create_event_loop(vec![&device])?;
#
event_loop.run_forever(|event, state| match event {
    // If there were no errors, extract the event
    Ok(event) => match event {
        ClockChange(device) => { /* ... */ },
        PowerStateChange(device) => { /* ... */ },
        _ => { /* ... */ }
    },

    // If there was an error, handle it
    Err(Error(error, _)) => match error {
        // If the error is `Unknown`, continue looping and hope for the best
        ErrorKind::Unknown => {},
        // The other errors that can occur are almost guaranteed to mean that
        // further looping will never be successful (`GpuLost` and
        // `Uninitialized`), so we stop looping
        _ => state.interrupt()
    }
});

# Ok(())
# }
# }
```

The full, fleshed-out example can be viewed in the examples directory
(`event_loop.rs`). Run it as follows:

```bash
cargo run --example event_loop
```

The functionality in this module is only available on Linux platforms; NVML does
not support events on any other platform.
*/

use Device;
use EventSet;
use NVML;
use bitmasks::event::*;
use enums::event::XidError;
use error::*;
use struct_wrappers::event::EventData;

// TODO: Tests

/**
Represents the event types that an `EventLoop` can gather for you.

These are analagous to the constants in `bitmasks::event`.

Checking to see if the `Device` within an `Event` is the same physical device as
another `Device` that you have on hand can be accomplished via `Device.uuid()`.
*/
#[derive(Debug)]
pub enum Event<'nvml> {
    ClockChange(Device<'nvml>),
    CriticalXidError(Device<'nvml>, XidError),
    DoubleBitEccError(Device<'nvml>),
    PowerStateChange(Device<'nvml>),
    SingleBitEccError(Device<'nvml>),
    /// Returned if none of the above event types are contained in the
    /// `EventData` the `EventLoop` processes.
    Unknown
}

impl<'nvml> From<EventData<'nvml>> for Event<'nvml> {
    fn from(struct_: EventData<'nvml>) -> Self {
        if struct_.event_type.contains(CLOCK_CHANGE) {
            Event::ClockChange(struct_.device)
        } else if struct_.event_type.contains(CRITICAL_XID_ERROR) {
            // We can unwrap here because we know `event_data` will be `Some`
            // since the error is `CRITICAL_XID_ERROR`
            Event::CriticalXidError(struct_.device, struct_.event_data.unwrap())
        } else if struct_.event_type.contains(DOUBLE_BIT_ECC_ERROR) {
            Event::DoubleBitEccError(struct_.device)
        } else if struct_.event_type.contains(PSTATE_CHANGE) {
            Event::PowerStateChange(struct_.device)
        } else if struct_.event_type.contains(SINGLE_BIT_ECC_ERROR) {
            Event::SingleBitEccError(struct_.device)
        } else {
            Event::Unknown
        }
    }
}

/**
Holds the `EventSet` utilized within an event loop.

A usage example is available (`examples/event_loop.rs`). It can be run as
follows:

```bash
cargo run --example event_loop
```
*/
// TODO: Example name ^
pub struct EventLoop<'nvml> {
    set: EventSet<'nvml>
}

impl<'nvml> EventLoop<'nvml> {
    /**
    Register another device that this `EventLoop` should receive events for.

    This method takes ownership of this struct and then hands it back to you if
    everything went well with the registration process.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `GpuLost`, if a GPU has fallen off the bus or is otherwise inaccessible
    * `Unknown`, on any unexpected error

    # Platform Support
    Only supports Linux.
    */
    #[inline]
    pub fn register_device(mut self, device: &'nvml Device<'nvml>) -> Result<Self> {
        self.set = device.register_events(device.supported_event_types()?, self.set)?;

        Ok(self)
    }

    /**
    Handle events with the given callback until the loop is manually interrupted.

    # Errors
    The function itself does not return anything. You will be given errors to
    handle within your closure if they occur; events are handed to you wrapped
    in a `Result`.

    The errors that you will need to handle are:

    * `Uninitialized`, if the library has not been successfully initialized
    * `GpuLost`, if a GPU has fallen off the bus or is otherwise inaccessible
    * `Unknown`, on any unexpected error

    # Examples
    See the `event_loop` example in the `examples` directory at the root.

    # Platform Support
    Only supports Linux.
    */
    // TODO: example name
    #[inline]
    pub fn run_forever<F>(&mut self, mut callback: F)
    where
        F: FnMut(Result<Event<'nvml>>, &mut EventLoopState),
    {
        let mut state = EventLoopState {
            interrupted: false
        };

        loop {
            if state.interrupted {
                break;
            };

            match self.set.wait(1) {
                Ok(data) => {
                    callback(Ok(data.into()), &mut state);
                },
                Err(Error(ErrorKind::Timeout, _)) => continue,
                value => callback(value.map(|d| d.into()), &mut state),
            };
        }
    }

    /// Obtain a reference to the `EventSet` contained within this struct.
    #[inline]
    pub fn as_inner(&'nvml self) -> &'nvml EventSet<'nvml> {
        &(self.set)
    }

    /// Obtain a mutable reference to the `EventSet` contained within this
    /// struct.
    #[inline]
    pub fn as_mut_inner(&'nvml mut self) -> &'nvml mut EventSet<'nvml> {
        &mut (self.set)
    }

    /// Consumes this `EventLoop` and yields the `EventSet` contained within.
    #[inline]
    pub fn into_inner(self) -> EventSet<'nvml> {
        self.set
    }
}

impl<'nvml> From<EventSet<'nvml>> for EventLoop<'nvml> {
    fn from(set: EventSet<'nvml>) -> Self {
        Self {
            set
        }
    }
}

/// Keeps track of whether an `EventLoop` is interrupted or not.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct EventLoopState {
    interrupted: bool
}

impl EventLoopState {
    /// Call this to mark the loop as interrupted.
    #[inline]
    pub fn interrupt(&mut self) {
        self.interrupted = true;
    }
}

/// Adds a method to obtain an `EventLoop` to the `NVML` struct.
///
/// `use` it at your leisure.
pub trait EventLoopProvider {
    // Thanks to Thinkofname for lifetime help, again :)
    fn create_event_loop<'nvml>(
        &'nvml self,
        devices: Vec<&'nvml Device<'nvml>>,
    ) -> Result<EventLoop>;
}

impl EventLoopProvider for NVML {
    /**
    Create an event loop that will register itself to recieve events for the given
    `Device`s.

    This function creates an event set and registers each devices' supported event
    types for it. The returned `EventLoop` struct then has methods that you can
    call to actually utilize it.

    # Errors
    * `Uninitialized`, if the library has not been successfully initialized
    * `GpuLost`, if any of the given `Device`s have fallen off the bus or are
    otherwise inaccessible
    * `Unknown`, on any unexpected error

    # Platform Support
    Only supports Linux.
    */
    #[inline]
    fn create_event_loop<'nvml>(
        &'nvml self,
        devices: Vec<&'nvml Device<'nvml>>,
    ) -> Result<EventLoop> {

        let mut set = self.create_event_set()?;

        for d in devices {
            set = d.register_events(d.supported_event_types()?, set)?;
        }

        Ok(EventLoop {
            set
        })
    }
}
<|endoftext|>


<commit_before>// Cymbalum, an extensible molecular simulation engine
// Copyright (C) 2015-2016 G. Fraux — BSD license
use toml::{Table, Value};

use input::error::{Error, Result};
use input::FromToml;
use super::read_restriction;

use system::System;
use potentials::{Wolf, Ewald, CoulombicPotential};

pub fn read_coulomb(system: &mut System, coulomb: &Table) -> Result<()> {
    let solvers = coulomb.keys().cloned()
                         .filter(|key| key != "restriction")
                         .collect::<Vec<_>>();

    if solvers.len() != 1 {
        return Err(Error::from(
            format!("Got more than one coulombic solver: {}", solvers.join(" - "))
        ));
    }

    let key = &*solvers[0];
    if let Value::Table(ref table) = coulomb[key] {
        let mut potential: Box<CoulombicPotential> = match key {
            "wolf" => Box::new(try!(Wolf::from_toml(table))),
            "ewald" => Box::new(try!(Ewald::from_toml(table))),
            other => {
                return Err(Error::from(format!("Unknown coulomb solver '{}'", other)))
            },
        };

        if let Some(restriction) = try!(read_restriction(coulomb)) {
            potential.set_restriction(restriction);
        }

        system.interactions_mut().set_coulomb(potential);
        Ok(())
    } else {
        Err(
            Error::from(format!("Coulombic solver '{}' must be a table", key))
        )
    }
}

pub fn set_charges(system: &mut System, charges: &Table) -> Result<()> {
    for (name, charge) in charges.iter() {
        let charge = match *charge {
            Value::Integer(val) => val as f64,
            Value::Float(val) => val,
            _ => {
                return Err(Error::from("Charges must be numbers"));
            }
        };

        let mut nchanged = 0;
        for particle in system.iter_mut() {
            if particle.name() == name {
                particle.charge = charge;
                nchanged += 1;
            }
        }

        if nchanged == 0 {
            warn!("No particle with name '{}' was found while setting the charges", name);
        } else {
            info!("Charge set to {} for {} {} particles", charge, nchanged, name);
        }
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use input::read_interactions;
    use input::testing::bad_inputs;
    use system::{Particle, System};
    use std::path::Path;

    #[test]
    fn ewald() {
        let data_root = Path::new(file!()).parent().unwrap().join("data");
        let mut system = System::new();
        system.add_particle(Particle::new("A"));
        system.add_particle(Particle::new("B"));

        read_interactions(&mut system, data_root.join("ewald.toml")).unwrap();
        assert!(system.interactions().coulomb().is_some());

        assert_eq!(system[0].charge, -8.0);
        assert_eq!(system[1].charge, 3.0);
    }

    #[test]
    fn wolf() {
        let data_root = Path::new(file!()).parent().unwrap().join("data");
        let mut system = System::new();
        system.add_particle(Particle::new("A"));
        system.add_particle(Particle::new("B"));

        read_interactions(&mut system, data_root.join("wolf.toml")).unwrap();
        assert!(system.interactions().coulomb().is_some());

        assert_eq!(system[0].charge, -2.0);
        assert_eq!(system[1].charge, 2.0);
    }

    #[test]
    fn bad_coulomb() {
        for path in bad_inputs("interactions", "coulomb") {
            let mut system = System::new();
            assert!(read_interactions(&mut system, path).is_err());
        }
    }
}
<commit_msg>Add a warning about non-neutral systems<commit_after>// Cymbalum, an extensible molecular simulation engine
// Copyright (C) 2015-2016 G. Fraux — BSD license
use toml::{Table, Value};

use input::error::{Error, Result};
use input::FromToml;
use super::read_restriction;

use system::System;
use potentials::{Wolf, Ewald, CoulombicPotential};

pub fn read_coulomb(system: &mut System, coulomb: &Table) -> Result<()> {
    let solvers = coulomb.keys().cloned()
                         .filter(|key| key != "restriction")
                         .collect::<Vec<_>>();

    if solvers.len() != 1 {
        return Err(Error::from(
            format!("Got more than one coulombic solver: {}", solvers.join(" - "))
        ));
    }

    let key = &*solvers[0];
    if let Value::Table(ref table) = coulomb[key] {
        let mut potential: Box<CoulombicPotential> = match key {
            "wolf" => Box::new(try!(Wolf::from_toml(table))),
            "ewald" => Box::new(try!(Ewald::from_toml(table))),
            other => {
                return Err(Error::from(format!("Unknown coulomb solver '{}'", other)))
            },
        };

        if let Some(restriction) = try!(read_restriction(coulomb)) {
            potential.set_restriction(restriction);
        }

        system.interactions_mut().set_coulomb(potential);
        Ok(())
    } else {
        Err(
            Error::from(format!("Coulombic solver '{}' must be a table", key))
        )
    }
}

pub fn set_charges(system: &mut System, charges: &Table) -> Result<()> {
    let mut total_charge = 0.0;
    for (name, charge) in charges.iter() {
        let charge = match *charge {
            Value::Integer(val) => val as f64,
            Value::Float(val) => val,
            _ => {
                return Err(Error::from("Charges must be numbers"));
            }
        };

        let mut nchanged = 0;
        for particle in system.iter_mut() {
            if particle.name() == name {
                particle.charge = charge;
                nchanged += 1;
                total_charge += charge;
            }
        }

        if nchanged == 0 {
            warn!("No particle with name '{}' was found while setting the charges", name);
        } else {
            info!("Charge set to {:+} for {} {} particles", charge, nchanged, name);
        }
    }

    if total_charge.abs() > 1e-6 {
        warn!("System is not neutral and have a net charge of {:+}", total_charge);
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use input::read_interactions;
    use input::testing::bad_inputs;
    use system::{Particle, System};
    use std::path::Path;

    #[test]
    fn ewald() {
        let data_root = Path::new(file!()).parent().unwrap().join("data");
        let mut system = System::new();
        system.add_particle(Particle::new("A"));
        system.add_particle(Particle::new("B"));

        read_interactions(&mut system, data_root.join("ewald.toml")).unwrap();
        assert!(system.interactions().coulomb().is_some());

        assert_eq!(system[0].charge, -8.0);
        assert_eq!(system[1].charge, 3.0);
    }

    #[test]
    fn wolf() {
        let data_root = Path::new(file!()).parent().unwrap().join("data");
        let mut system = System::new();
        system.add_particle(Particle::new("A"));
        system.add_particle(Particle::new("B"));

        read_interactions(&mut system, data_root.join("wolf.toml")).unwrap();
        assert!(system.interactions().coulomb().is_some());

        assert_eq!(system[0].charge, -2.0);
        assert_eq!(system[1].charge, 2.0);
    }

    #[test]
    fn bad_coulomb() {
        for path in bad_inputs("interactions", "coulomb") {
            let mut system = System::new();
            assert!(read_interactions(&mut system, path).is_err());
        }
    }
}
<|endoftext|>