<commit_before>extern crate glium;

use std::collections::HashMap;
use glium::program::Program;
use glium::backend::Facade;

pub struct ShaderManager {
	shaders:HashMap<String,Program>
}

/*
 The shader manager should load and cache files and compile the shaders.
 By doing this, display objects will be able to retrieve their shaders from
 the manager. Every scene object should have a shader assigned to it as well
 as other basic properties such as position
*/

impl ShaderManager {
	pub fn new<F>(display: &F) -> ShaderManager where F: Facade + Clone {
		ShaderManager {
			shaders:HashMap::new()
		}
	}

	pub fn load(&self, vertex: &str, fragment: &str) -> Result<&Program, &str> {

		Err("Test")
	}
}

struct ShaderSource {
	vertex:String,
	fragment:String,
	geometry:Option<String>,
}<commit_msg>Start file reading<commit_after>extern crate glium;

use std::collections::HashMap;
use glium::program::Program;
use glium::backend::Facade;

use std::io::prelude::*;
use std::fs::File;

/*
 The shader manager loads and caches shaders
*/

pub struct ShaderManager {
	shaders:HashMap<String,Program>
}

impl ShaderManager {
	pub fn new<F>(display: &F) -> ShaderManager where F: Facade + Clone {
		ShaderManager {
			shaders:HashMap::new()
		}
	}

	pub fn load(&self, vertex: &str, fragment: &str) -> Result<&Program, &str> {
		// open and read the vertex file
		let mut vertex_file = match File::open(vertex){
			Ok(vertex_file) => vertex_file,
			Err(..) => return Err("Unable to open file."),
		};
		let mut vertex_data = String::new();
		match vertex_file.read_to_string(&mut vertex_data){
			Err(..) => return Err("Failed to read file."),
			_ => {}
		};
		/*let vertex_file = try!(File::open(vertex));

		let mut vertex_data = String::new();
		try!(vertex_file.read_to_string(&mut vertex_data));*/
		// open and read the fragment file
		/*let fragment_file = try!(File::open(fragment));
		let mut fragment_data = String::new();
		try!(fragment_file.read_to_string(&mut fragment_data));*/

		// try and open
		Err("Test")
	}
}

struct ShaderSource {
	vertex:String,
	fragment:String,
	geometry:Option<String>,
}<|endoftext|>


<commit_before><commit_msg>Strip newline from jwt secrets (#3132)<commit_after><|endoftext|>


<commit_before>use std::sync::Arc;
use std::sync::Mutex;

use either::Either;
use pinyin::{Pinyin, ToPinyin};
use tbot::{
    contexts::{Command, Text},
    types::{input_file, parameters},
    Bot,
};

use crate::client::pull_feed;
use crate::data::Database;
use crate::messages::{format_large_msg, Escape};

mod opml;

pub async fn check_command(opt: &crate::Opt, cmd: Arc<Command<Text>>) -> bool {
    use tbot::contexts::fields::Message;
    use tbot::types::chat::Kind::*;
    let target = &mut MsgTarget::new(cmd.chat.id, cmd.message_id);
    let from = cmd
        .from()
        .map(|user| user.id.0)
        .unwrap_or_else(|| cmd.chat.id.0);

    // Single user mode
    if matches!(opt.single_user, Some(owner) if owner != from) {
        eprintln!(
            "Unauthenticated request from user/channel: {}, command: {}, args: {}",
            from, cmd.command, cmd.text.value
        );
        return false;
    }

    match cmd.chat.kind {
        Channel { .. } => {
            let msg = tr!("commands_in_private_channel");
            let _ignore_result =
                update_response(&cmd.bot, target, parameters::Text::with_plain(&msg)).await;
            return false;
        }
        // Restrict mode: bot commands are only accessible to admins.
        Group { .. } | Supergroup { .. } if opt.restricted => {
            let user_id = cmd.from.as_ref().unwrap().id;
            let admins = match cmd.bot.get_chat_administrators(cmd.chat.id).call().await {
                Ok(r) => r,
                _ => return false,
            };
            let user_is_admin = admins.iter().any(|member| member.user.id == user_id);
            if !user_is_admin {
                let _ignore_result = update_response(
                    &cmd.bot,
                    target,
                    parameters::Text::with_plain(tr!("group_admin_only_command")),
                )
                .await;
            }
            return user_is_admin;
        }
        _ => (),
    }

    true
}

#[derive(Debug, Copy, Clone)]
struct MsgTarget {
    chat_id: tbot::types::chat::Id,
    message_id: tbot::types::message::Id,
    first_time: bool,
}

impl MsgTarget {
    fn new(chat_id: tbot::types::chat::Id, message_id: tbot::types::message::Id) -> Self {
        MsgTarget {
            chat_id,
            message_id,
            first_time: true,
        }
    }
    fn update(&mut self, message_id: tbot::types::message::Id) {
        self.message_id = message_id;
        self.first_time = false;
    }
}

pub async fn start(
    _db: Arc<Mutex<Database>>,
    cmd: Arc<Command<Text>>,
) -> Result<(), tbot::errors::MethodCall> {
    let target = &mut MsgTarget::new(cmd.chat.id, cmd.message_id);
    let msg = tr!("start_message");
    update_response(&cmd.bot, target, parameters::Text::with_markdown(&msg)).await?;
    Ok(())
}

pub async fn rss(
    db: Arc<Mutex<Database>>,
    cmd: Arc<Command<Text>>,
) -> Result<(), tbot::errors::MethodCall> {
    let chat_id = cmd.chat.id;
    let channel = &cmd.text.value;
    let mut target_id = chat_id;
    let target = &mut MsgTarget::new(chat_id, cmd.message_id);

    if !channel.is_empty() {
        let user_id = cmd.from.as_ref().unwrap().id;
        let channel_id = check_channel_permission(&cmd.bot, channel, target, user_id).await?;
        if channel_id.is_none() {
            return Ok(());
        }
        target_id = channel_id.unwrap();
    }

    let feeds = db.lock().unwrap().subscribed_feeds(target_id.0);
    let msgs = if let Some(mut feeds) = feeds {
        feeds.sort_by_cached_key(|feed| {
            feed.title
                .chars()
                .map(|c| {
                    c.to_pinyin()
                        .map(Pinyin::plain)
                        .map(Either::Right)
                        .unwrap_or_else(|| Either::Left(c))
                })
                .collect::<Vec<Either<char, &str>>>()
        });
        format_large_msg(tr!("subscription_list").to_string(), &feeds, |feed| {
            format!(
                "{}",
                Escape(&feed.link),
                Escape(&feed.title)
            )
        })
    } else {
        vec![tr!("subscription_list_empty").to_string()]
    };

    let mut prev_msg = cmd.message_id;
    for msg in msgs {
        let text = parameters::Text::with_html(&msg);
        let msg = cmd
            .bot
            .send_message(chat_id, text)
            .in_reply_to(prev_msg)
            .is_web_page_preview_disabled(true)
            .call()
            .await?;
        prev_msg = msg.id;
    }
    Ok(())
}

pub async fn sub(
    db: Arc<Mutex<Database>>,
    cmd: Arc<Command<Text>>,
) -> Result<(), tbot::errors::MethodCall> {
    let chat_id = cmd.chat.id;
    let text = &cmd.text.value;
    let args = text.split_whitespace().collect::<Vec<_>>();
    let mut target_id = chat_id;
    let target = &mut MsgTarget::new(chat_id, cmd.message_id);
    let feed_url;

    match &*args {
        [url] => feed_url = url,
        [channel, url] => {
            let user_id = cmd.from.as_ref().unwrap().id;
            let channel_id = check_channel_permission(&cmd.bot, channel, target, user_id).await?;
            if channel_id.is_none() {
                return Ok(());
            }
            target_id = channel_id.unwrap();
            feed_url = url;
        }
        [..] => {
            let msg = tr!("sub_how_to_use");
            update_response(&cmd.bot, target, parameters::Text::with_plain(&msg)).await?;
            return Ok(());
        }
    };
    if db.lock().unwrap().is_subscribed(target_id.0, feed_url) {
        update_response(
            &cmd.bot,
            target,
            parameters::Text::with_plain(tr!("subscribed_to_rss")),
        )
        .await?;
        return Ok(());
    }

    if cfg!(feature = "hosted-by-iovxw") && db.lock().unwrap().all_feeds().len() >= 1500 {
        let msg = tr!("subscription_rate_limit");
        update_response(&cmd.bot, target, parameters::Text::with_markdown(msg)).await?;
        return Ok(());
    }
    update_response(
        &cmd.bot,
        target,
        parameters::Text::with_plain(tr!("processing_please_wait")),
    )
    .await?;
    let msg = match pull_feed(feed_url).await {
        Ok(feed) => {
            if db.lock().unwrap().subscribe(target_id.0, feed_url, &feed) {
                tr!(
                    "subscription_succeeded",
                    link = Escape(&feed.link),
                    title = Escape(&feed.title)
                )
            } else {
                tr!("subscribed_to_rss").into()
            }
        }
        Err(e) => tr!("subscription_failed", error = Escape(&e.to_user_friendly())),
    };
    update_response(&cmd.bot, target, parameters::Text::with_html(&msg)).await?;
    Ok(())
}

pub async fn unsub(
    db: Arc<Mutex<Database>>,
    cmd: Arc<Command<Text>>,
) -> Result<(), tbot::errors::MethodCall> {
    let chat_id = cmd.chat.id;
    let text = &cmd.text.value;
    let args = text.split_whitespace().collect::<Vec<_>>();
    let mut target_id = chat_id;
    let target = &mut MsgTarget::new(chat_id, cmd.message_id);
    let feed_url;

    match &*args {
        [url] => feed_url = url,
        [channel, url] => {
            let user_id = cmd.from.as_ref().unwrap().id;
            let channel_id = check_channel_permission(&cmd.bot, channel, target, user_id).await?;
            if channel_id.is_none() {
                return Ok(());
            }
            target_id = channel_id.unwrap();
            feed_url = url;
        }
        [..] => {
            let msg = tr!("unsub_how_to_use");
            update_response(&cmd.bot, target, parameters::Text::with_plain(&msg)).await?;
            return Ok(());
        }
    };
    let msg = if let Some(feed) = db.lock().unwrap().unsubscribe(target_id.0, feed_url) {
        tr!(
            "unsubscription_succeeded",
            link = Escape(&feed.link),
            title = Escape(&feed.title)
        )
    } else {
        tr!("unsubscribed_from_rss").into()
    };
    update_response(&cmd.bot, target, parameters::Text::with_html(&msg)).await?;
    Ok(())
}

pub async fn export(
    db: Arc<Mutex<Database>>,
    cmd: Arc<Command<Text>>,
) -> Result<(), tbot::errors::MethodCall> {
    let chat_id = cmd.chat.id;
    let channel = &cmd.text.value;
    let mut target_id = chat_id;
    let target = &mut MsgTarget::new(chat_id, cmd.message_id);

    if !channel.is_empty() {
        let user_id = cmd.from.as_ref().unwrap().id;
        let channel_id = check_channel_permission(&cmd.bot, channel, target, user_id).await?;
        if channel_id.is_none() {
            return Ok(());
        }
        target_id = channel_id.unwrap();
    }

    let feeds = db.lock().unwrap().subscribed_feeds(target_id.0);
    if feeds.is_none() {
        update_response(
            &cmd.bot,
            target,
            parameters::Text::with_plain(tr!("subscription_list_empty")),
        )
        .await?;
        return Ok(());
    }
    let opml = opml::into_opml(feeds.unwrap());

    cmd.bot
        .send_document(
            chat_id,
            input_file::Document::with_bytes("feeds.opml", opml.as_bytes()),
        )
        .in_reply_to(cmd.message_id)
        .call()
        .await?;
    Ok(())
}

async fn update_response(
    bot: &Bot,
    target: &mut MsgTarget,
    message: parameters::Text<'_>,
) -> Result<(), tbot::errors::MethodCall> {
    let msg = if target.first_time {
        bot.send_message(target.chat_id, message)
            .in_reply_to(target.message_id)
            .is_web_page_preview_disabled(true)
            .call()
            .await?
    } else {
        bot.edit_message_text(target.chat_id, target.message_id, message)
            .is_web_page_preview_disabled(true)
            .call()
            .await?
    };
    target.update(msg.id);
    Ok(())
}

async fn check_channel_permission(
    bot: &Bot,
    channel: &str,
    target: &mut MsgTarget,
    user_id: tbot::types::user::Id,
) -> Result<Option<tbot::types::chat::Id>, tbot::errors::MethodCall> {
    use tbot::errors::MethodCall;
    let channel_id = channel
        .parse::<i64>()
        .map(|id| parameters::ChatId::Id(id.into()))
        .unwrap_or_else(|_| parameters::ChatId::Username(channel));
    update_response(
        bot,
        target,
        parameters::Text::with_plain(tr!("verifying_channel")),
    )
    .await?;

    let chat = match bot.get_chat(channel_id).call().await {
        Err(MethodCall::RequestError {
            description,
            error_code: 400,
            ..
        }) => {
            let msg = tr!("unable_to_find_target_channel", desc = description);
            update_response(bot, target, parameters::Text::with_plain(&msg)).await?;
            return Ok(None);
        }
        other => other?,
    };
    if !chat.kind.is_channel() {
        update_response(
            bot,
            target,
            parameters::Text::with_plain(tr!("target_must_be_a_channel")),
        )
        .await?;
        return Ok(None);
    }
    let admins = match bot.get_chat_administrators(channel_id).call().await {
        Err(MethodCall::RequestError {
            description,
            error_code: 400,
            ..
        }) => {
            let msg = tr!("unable_to_get_channel_info", desc = description);
            update_response(bot, target, parameters::Text::with_plain(&msg)).await?;
            return Ok(None);
        }
        other => other?,
    };
    let user_is_admin = admins.iter().any(|member| member.user.id == user_id);
    if !user_is_admin {
        update_response(
            bot,
            target,
            parameters::Text::with_plain(tr!("channel_admin_only_command")),
        )
        .await?;
        return Ok(None);
    }
    let bot_is_admin = admins
        .iter()
        .find(|member| member.user.id == *crate::BOT_ID.get().unwrap())
        .is_some();
    if !bot_is_admin {
        update_response(
            bot,
            target,
            parameters::Text::with_plain(tr!("make_bot_admin")),
        )
        .await?;
        return Ok(None);
    }
    Ok(Some(chat.id))
}
<commit_msg>Fix the channel checking message in /rss command<commit_after>use std::sync::Arc;
use std::sync::Mutex;

use either::Either;
use pinyin::{Pinyin, ToPinyin};
use tbot::{
    contexts::{Command, Text},
    types::{input_file, parameters},
    Bot,
};

use crate::client::pull_feed;
use crate::data::Database;
use crate::messages::{format_large_msg, Escape};

mod opml;

pub async fn check_command(opt: &crate::Opt, cmd: Arc<Command<Text>>) -> bool {
    use tbot::contexts::fields::Message;
    use tbot::types::chat::Kind::*;
    let target = &mut MsgTarget::new(cmd.chat.id, cmd.message_id);
    let from = cmd
        .from()
        .map(|user| user.id.0)
        .unwrap_or_else(|| cmd.chat.id.0);

    // Single user mode
    if matches!(opt.single_user, Some(owner) if owner != from) {
        eprintln!(
            "Unauthenticated request from user/channel: {}, command: {}, args: {}",
            from, cmd.command, cmd.text.value
        );
        return false;
    }

    match cmd.chat.kind {
        Channel { .. } => {
            let msg = tr!("commands_in_private_channel");
            let _ignore_result =
                update_response(&cmd.bot, target, parameters::Text::with_plain(&msg)).await;
            return false;
        }
        // Restrict mode: bot commands are only accessible to admins.
        Group { .. } | Supergroup { .. } if opt.restricted => {
            let user_id = cmd.from.as_ref().unwrap().id;
            let admins = match cmd.bot.get_chat_administrators(cmd.chat.id).call().await {
                Ok(r) => r,
                _ => return false,
            };
            let user_is_admin = admins.iter().any(|member| member.user.id == user_id);
            if !user_is_admin {
                let _ignore_result = update_response(
                    &cmd.bot,
                    target,
                    parameters::Text::with_plain(tr!("group_admin_only_command")),
                )
                .await;
            }
            return user_is_admin;
        }
        _ => (),
    }

    true
}

#[derive(Debug, Copy, Clone)]
struct MsgTarget {
    chat_id: tbot::types::chat::Id,
    message_id: tbot::types::message::Id,
    first_time: bool,
}

impl MsgTarget {
    fn new(chat_id: tbot::types::chat::Id, message_id: tbot::types::message::Id) -> Self {
        MsgTarget {
            chat_id,
            message_id,
            first_time: true,
        }
    }
    fn update(&mut self, message_id: tbot::types::message::Id) {
        self.message_id = message_id;
        self.first_time = false;
    }
}

pub async fn start(
    _db: Arc<Mutex<Database>>,
    cmd: Arc<Command<Text>>,
) -> Result<(), tbot::errors::MethodCall> {
    let target = &mut MsgTarget::new(cmd.chat.id, cmd.message_id);
    let msg = tr!("start_message");
    update_response(&cmd.bot, target, parameters::Text::with_markdown(&msg)).await?;
    Ok(())
}

pub async fn rss(
    db: Arc<Mutex<Database>>,
    cmd: Arc<Command<Text>>,
) -> Result<(), tbot::errors::MethodCall> {
    let chat_id = cmd.chat.id;
    let channel = &cmd.text.value;
    let mut target_id = chat_id;
    let target = &mut MsgTarget::new(chat_id, cmd.message_id);

    if !channel.is_empty() {
        let user_id = cmd.from.as_ref().unwrap().id;
        let channel_id = check_channel_permission(&cmd.bot, channel, target, user_id).await?;
        if channel_id.is_none() {
            return Ok(());
        }
        target_id = channel_id.unwrap();
    }

    let feeds = db.lock().unwrap().subscribed_feeds(target_id.0);
    let mut msgs = if let Some(mut feeds) = feeds {
        feeds.sort_by_cached_key(|feed| {
            feed.title
                .chars()
                .map(|c| {
                    c.to_pinyin()
                        .map(Pinyin::plain)
                        .map(Either::Right)
                        .unwrap_or_else(|| Either::Left(c))
                })
                .collect::<Vec<Either<char, &str>>>()
        });
        format_large_msg(tr!("subscription_list").to_string(), &feeds, |feed| {
            format!(
                "{}",
                Escape(&feed.link),
                Escape(&feed.title)
            )
        })
    } else {
        vec![tr!("subscription_list_empty").to_string()]
    };

    let first_msg = msgs.remove(0);
    update_response(&cmd.bot, target, parameters::Text::with_html(&first_msg)).await?;

    let mut prev_msg = target.message_id;
    for msg in msgs {
        let text = parameters::Text::with_html(&msg);
        let msg = cmd
            .bot
            .send_message(chat_id, text)
            .in_reply_to(prev_msg)
            .is_web_page_preview_disabled(true)
            .call()
            .await?;
        prev_msg = msg.id;
    }
    Ok(())
}

pub async fn sub(
    db: Arc<Mutex<Database>>,
    cmd: Arc<Command<Text>>,
) -> Result<(), tbot::errors::MethodCall> {
    let chat_id = cmd.chat.id;
    let text = &cmd.text.value;
    let args = text.split_whitespace().collect::<Vec<_>>();
    let mut target_id = chat_id;
    let target = &mut MsgTarget::new(chat_id, cmd.message_id);
    let feed_url;

    match &*args {
        [url] => feed_url = url,
        [channel, url] => {
            let user_id = cmd.from.as_ref().unwrap().id;
            let channel_id = check_channel_permission(&cmd.bot, channel, target, user_id).await?;
            if channel_id.is_none() {
                return Ok(());
            }
            target_id = channel_id.unwrap();
            feed_url = url;
        }
        [..] => {
            let msg = tr!("sub_how_to_use");
            update_response(&cmd.bot, target, parameters::Text::with_plain(&msg)).await?;
            return Ok(());
        }
    };
    if db.lock().unwrap().is_subscribed(target_id.0, feed_url) {
        update_response(
            &cmd.bot,
            target,
            parameters::Text::with_plain(tr!("subscribed_to_rss")),
        )
        .await?;
        return Ok(());
    }

    if cfg!(feature = "hosted-by-iovxw") && db.lock().unwrap().all_feeds().len() >= 1500 {
        let msg = tr!("subscription_rate_limit");
        update_response(&cmd.bot, target, parameters::Text::with_markdown(msg)).await?;
        return Ok(());
    }
    update_response(
        &cmd.bot,
        target,
        parameters::Text::with_plain(tr!("processing_please_wait")),
    )
    .await?;
    let msg = match pull_feed(feed_url).await {
        Ok(feed) => {
            if db.lock().unwrap().subscribe(target_id.0, feed_url, &feed) {
                tr!(
                    "subscription_succeeded",
                    link = Escape(&feed.link),
                    title = Escape(&feed.title)
                )
            } else {
                tr!("subscribed_to_rss").into()
            }
        }
        Err(e) => tr!("subscription_failed", error = Escape(&e.to_user_friendly())),
    };
    update_response(&cmd.bot, target, parameters::Text::with_html(&msg)).await?;
    Ok(())
}

pub async fn unsub(
    db: Arc<Mutex<Database>>,
    cmd: Arc<Command<Text>>,
) -> Result<(), tbot::errors::MethodCall> {
    let chat_id = cmd.chat.id;
    let text = &cmd.text.value;
    let args = text.split_whitespace().collect::<Vec<_>>();
    let mut target_id = chat_id;
    let target = &mut MsgTarget::new(chat_id, cmd.message_id);
    let feed_url;

    match &*args {
        [url] => feed_url = url,
        [channel, url] => {
            let user_id = cmd.from.as_ref().unwrap().id;
            let channel_id = check_channel_permission(&cmd.bot, channel, target, user_id).await?;
            if channel_id.is_none() {
                return Ok(());
            }
            target_id = channel_id.unwrap();
            feed_url = url;
        }
        [..] => {
            let msg = tr!("unsub_how_to_use");
            update_response(&cmd.bot, target, parameters::Text::with_plain(&msg)).await?;
            return Ok(());
        }
    };
    let msg = if let Some(feed) = db.lock().unwrap().unsubscribe(target_id.0, feed_url) {
        tr!(
            "unsubscription_succeeded",
            link = Escape(&feed.link),
            title = Escape(&feed.title)
        )
    } else {
        tr!("unsubscribed_from_rss").into()
    };
    update_response(&cmd.bot, target, parameters::Text::with_html(&msg)).await?;
    Ok(())
}

pub async fn export(
    db: Arc<Mutex<Database>>,
    cmd: Arc<Command<Text>>,
) -> Result<(), tbot::errors::MethodCall> {
    let chat_id = cmd.chat.id;
    let channel = &cmd.text.value;
    let mut target_id = chat_id;
    let target = &mut MsgTarget::new(chat_id, cmd.message_id);

    if !channel.is_empty() {
        let user_id = cmd.from.as_ref().unwrap().id;
        let channel_id = check_channel_permission(&cmd.bot, channel, target, user_id).await?;
        if channel_id.is_none() {
            return Ok(());
        }
        target_id = channel_id.unwrap();
    }

    let feeds = db.lock().unwrap().subscribed_feeds(target_id.0);
    if feeds.is_none() {
        update_response(
            &cmd.bot,
            target,
            parameters::Text::with_plain(tr!("subscription_list_empty")),
        )
        .await?;
        return Ok(());
    }
    let opml = opml::into_opml(feeds.unwrap());

    cmd.bot
        .send_document(
            chat_id,
            input_file::Document::with_bytes("feeds.opml", opml.as_bytes()),
        )
        .in_reply_to(cmd.message_id)
        .call()
        .await?;
    Ok(())
}

async fn update_response(
    bot: &Bot,
    target: &mut MsgTarget,
    message: parameters::Text<'_>,
) -> Result<(), tbot::errors::MethodCall> {
    let msg = if target.first_time {
        bot.send_message(target.chat_id, message)
            .in_reply_to(target.message_id)
            .is_web_page_preview_disabled(true)
            .call()
            .await?
    } else {
        bot.edit_message_text(target.chat_id, target.message_id, message)
            .is_web_page_preview_disabled(true)
            .call()
            .await?
    };
    target.update(msg.id);
    Ok(())
}

async fn check_channel_permission(
    bot: &Bot,
    channel: &str,
    target: &mut MsgTarget,
    user_id: tbot::types::user::Id,
) -> Result<Option<tbot::types::chat::Id>, tbot::errors::MethodCall> {
    use tbot::errors::MethodCall;
    let channel_id = channel
        .parse::<i64>()
        .map(|id| parameters::ChatId::Id(id.into()))
        .unwrap_or_else(|_| parameters::ChatId::Username(channel));
    update_response(
        bot,
        target,
        parameters::Text::with_plain(tr!("verifying_channel")),
    )
    .await?;

    let chat = match bot.get_chat(channel_id).call().await {
        Err(MethodCall::RequestError {
            description,
            error_code: 400,
            ..
        }) => {
            let msg = tr!("unable_to_find_target_channel", desc = description);
            update_response(bot, target, parameters::Text::with_plain(&msg)).await?;
            return Ok(None);
        }
        other => other?,
    };
    if !chat.kind.is_channel() {
        update_response(
            bot,
            target,
            parameters::Text::with_plain(tr!("target_must_be_a_channel")),
        )
        .await?;
        return Ok(None);
    }
    let admins = match bot.get_chat_administrators(channel_id).call().await {
        Err(MethodCall::RequestError {
            description,
            error_code: 400,
            ..
        }) => {
            let msg = tr!("unable_to_get_channel_info", desc = description);
            update_response(bot, target, parameters::Text::with_plain(&msg)).await?;
            return Ok(None);
        }
        other => other?,
    };
    let user_is_admin = admins.iter().any(|member| member.user.id == user_id);
    if !user_is_admin {
        update_response(
            bot,
            target,
            parameters::Text::with_plain(tr!("channel_admin_only_command")),
        )
        .await?;
        return Ok(None);
    }
    let bot_is_admin = admins
        .iter()
        .find(|member| member.user.id == *crate::BOT_ID.get().unwrap())
        .is_some();
    if !bot_is_admin {
        update_response(
            bot,
            target,
            parameters::Text::with_plain(tr!("make_bot_admin")),
        )
        .await?;
        return Ok(None);
    }
    Ok(Some(chat.id))
}
<|endoftext|>


<commit_before>//! # Evicted Queue

#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;

/// This queue maintains an ordered list of elements, and a count of
/// dropped elements. Elements are removed from the queue in a first
/// in first out fashion.
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct EvictedQueue<T> {
    queue: VecDeque<T>,
    capacity: u32,
    dropped_count: u32,
}

impl<T> EvictedQueue<T> {
    /// Create a new `EvictedQueue` with a given capacity.
    pub(crate) fn new(capacity: u32) -> Self {
        EvictedQueue {
            queue: Default::default(),
            capacity,
            dropped_count: 0,
        }
    }

    /// Push a new element to the back of the queue, dropping and
    /// recording dropped count if over capacity.
    pub(crate) fn push_back(&mut self, value: T) {
        if self.queue.len() as u32 == self.capacity {
            self.queue.pop_front();
            self.dropped_count += 1;
        }
        self.queue.push_back(value);
    }

    /// Moves all the elements of other into self, leaving other empty.
    pub fn append_vec(&mut self, other: &mut Vec<T>) {
        self.extend(other.drain(..));
    }

    /// Returns `true` if the `EvictedQueue` is empty.
    pub fn is_empty(&self) -> bool {
        self.queue.is_empty()
    }

    /// Returns a front-to-back iterator.
    pub fn iter(&self) -> std::collections::vec_deque::Iter<T> {
        self.queue.iter()
    }

    /// Returns the number of elements in the `EvictedQueue`.
    pub fn len(&self) -> usize {
        self.queue.len()
    }
}

impl<T> IntoIterator for EvictedQueue<T> {
    type Item = T;
    type IntoIter = std::collections::vec_deque::IntoIter<T>;

    /// Consumes the `EvictedQueue` into a front-to-back iterator yielding elements by
    /// value.
    fn into_iter(self) -> Self::IntoIter {
        self.queue.into_iter()
    }
}

impl<'a, T> IntoIterator for &'a EvictedQueue<T> {
    type Item = &'a T;
    type IntoIter = std::collections::vec_deque::Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.queue.iter()
    }
}

impl<'a, T> IntoIterator for &'a mut EvictedQueue<T> {
    type Item = &'a mut T;
    type IntoIter = std::collections::vec_deque::IterMut<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.queue.iter_mut()
    }
}

impl<T> Extend<T> for EvictedQueue<T> {
    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
        iter.into_iter().for_each(move |elt| self.push_back(elt));
    }
}

#[cfg(test)]
mod tests {
    use super::EvictedQueue;
    use std::collections::VecDeque;

    #[test]
    fn insert_over_capacity_test() {
        let capacity = 10;
        let mut queue = EvictedQueue::new(capacity);

        for i in 0..=capacity {
            queue.push_back(i)
        }

        assert_eq!(queue.dropped_count, 1);
        assert_eq!(queue.len(), capacity as usize);
        assert_eq!(queue.queue, (1..=capacity).collect::<VecDeque<_>>());
    }
}
<commit_msg>export EvictedQueue::new (#108)<commit_after>//! # Evicted Queue

#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;

/// This queue maintains an ordered list of elements, and a count of
/// dropped elements. Elements are removed from the queue in a first
/// in first out fashion.
#[cfg_attr(feature = "serialize", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct EvictedQueue<T> {
    queue: VecDeque<T>,
    capacity: u32,
    dropped_count: u32,
}

impl<T> EvictedQueue<T> {
    /// Create a new `EvictedQueue` with a given capacity.
    pub fn new(capacity: u32) -> Self {
        EvictedQueue {
            queue: Default::default(),
            capacity,
            dropped_count: 0,
        }
    }

    /// Push a new element to the back of the queue, dropping and
    /// recording dropped count if over capacity.
    pub(crate) fn push_back(&mut self, value: T) {
        if self.queue.len() as u32 == self.capacity {
            self.queue.pop_front();
            self.dropped_count += 1;
        }
        self.queue.push_back(value);
    }

    /// Moves all the elements of other into self, leaving other empty.
    pub fn append_vec(&mut self, other: &mut Vec<T>) {
        self.extend(other.drain(..));
    }

    /// Returns `true` if the `EvictedQueue` is empty.
    pub fn is_empty(&self) -> bool {
        self.queue.is_empty()
    }

    /// Returns a front-to-back iterator.
    pub fn iter(&self) -> std::collections::vec_deque::Iter<T> {
        self.queue.iter()
    }

    /// Returns the number of elements in the `EvictedQueue`.
    pub fn len(&self) -> usize {
        self.queue.len()
    }
}

impl<T> IntoIterator for EvictedQueue<T> {
    type Item = T;
    type IntoIter = std::collections::vec_deque::IntoIter<T>;

    /// Consumes the `EvictedQueue` into a front-to-back iterator yielding elements by
    /// value.
    fn into_iter(self) -> Self::IntoIter {
        self.queue.into_iter()
    }
}

impl<'a, T> IntoIterator for &'a EvictedQueue<T> {
    type Item = &'a T;
    type IntoIter = std::collections::vec_deque::Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.queue.iter()
    }
}

impl<'a, T> IntoIterator for &'a mut EvictedQueue<T> {
    type Item = &'a mut T;
    type IntoIter = std::collections::vec_deque::IterMut<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.queue.iter_mut()
    }
}

impl<T> Extend<T> for EvictedQueue<T> {
    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
        iter.into_iter().for_each(move |elt| self.push_back(elt));
    }
}

#[cfg(test)]
mod tests {
    use super::EvictedQueue;
    use std::collections::VecDeque;

    #[test]
    fn insert_over_capacity_test() {
        let capacity = 10;
        let mut queue = EvictedQueue::new(capacity);

        for i in 0..=capacity {
            queue.push_back(i)
        }

        assert_eq!(queue.dropped_count, 1);
        assert_eq!(queue.len(), capacity as usize);
        assert_eq!(queue.queue, (1..=capacity).collect::<VecDeque<_>>());
    }
}
<|endoftext|>


<commit_before>use std::env;

use dotenv::dotenv;
use diesel;
use diesel::result::Error as DieselErr;
use diesel::prelude::*;
use diesel::pg::PgConnection;

use super::models::*;

pub struct Backend {
    connection: PgConnection
}

impl Backend {
    pub fn new() -> Self {
        dotenv().ok();

        let database_url = env::var("DATABASE_URL")
            .expect("DATABASE_URL must be set");
        let connection = PgConnection::establish(&database_url)
            .expect(&format!("Error connecting to {}", database_url));

        Self {
            connection
        }
    }

    pub fn vote(&self, user: &str, entity: &str, up: i32, down: i32) {
        use super::schema::{users, voteables, votes};

        use super::schema::users::dsl as us;
        let user: User = match us::users.filter(us::user_id.eq(user)).load(&self.connection) {
            Ok(mut u) => u.pop().unwrap(),
            Err(_) => {
                let new_user = NewUser { user_id: user };
                diesel::insert(&new_user).into(users::table)
                    .get_result(&self.connection)
                    .expect("Error creating new user")
            }
        };

        println!("User id: {}", user.id);

        use super::schema::voteables::dsl::*;
        let mut voteable: Voteable = match voteables.filter(value.eq(entity)).load(&self.connection) {
            Ok(mut v) => v.pop().unwrap(),
            Err(_) => {
                let new_voteable = NewVoteable {
                    value: entity,
                    total_up: 0,
                    total_down: 0,
                };

                diesel::insert(&new_voteable).into(voteables::table)
                    .get_result(&self.connection)
                    .expect("Error creating new voteable")
            }
        };

        voteable.total_up += up;
        voteable.total_down += down;
        voteable.save_changes::<Voteable>(&self.connection);

        use super::schema::votes::dsl as vts;
        let mut vote: Vote = match vts::votes.filter(vts::user_id.eq(user.id))
                                         .filter(vts::voteable_id.eq(voteable.id))
                                         .load(&self.connection) {
            Ok(mut v) => v.pop().unwrap(),
            Err(_) => {
                let new_vote = NewVote{
                    user_id: user.id,
                    voteable_id: voteable.id,
                    up: 0,
                    down: 0,
                };

                diesel::insert(&new_vote).into(votes::table)
                    .get_result(&self.connection)
                    .expect("Error creating new vote")
            }
        };

        vote.up += up;
        vote.down += down;
        vote.save_changes::<Vote>(&self.connection);
    }

    pub fn get_upvotes(&self, entity: &str) -> Result<Voteable, DieselErr> {
        use super::schema::voteables::dsl::*;

        match voteables.filter(value.eq(entity)).load(&self.connection) {
            Ok(mut v) => Ok(v.pop().unwrap()),
            Err(e) => Err(e),
        }
    }
}
<commit_msg>Karma/voting now works<commit_after>use std::env;

use dotenv::dotenv;
use diesel;
use diesel::result::Error as DieselErr;
use diesel::prelude::*;
use diesel::pg::PgConnection;

use super::models::*;

pub struct Backend {
    connection: PgConnection
}

impl Backend {
    pub fn new() -> Self {
        dotenv().ok();

        let database_url = env::var("DATABASE_URL")
            .expect("DATABASE_URL must be set");
        let connection = PgConnection::establish(&database_url)
            .expect(&format!("Error connecting to {}", database_url));

        Self {
            connection
        }
    }

    pub fn vote(&self, user: &str, entity: &str, up: i32, down: i32) {
        use super::schema::{users, voteables, votes};

        use super::schema::users::dsl as us;
        let mut res: Vec<User> = us::users.filter(us::user_id.eq(user)).load(&self.connection).unwrap();
        let user = match res.len() {
            0 => {
                let new_user = NewUser { user_id: user };
                diesel::insert(&new_user).into(users::table)
                    .get_result(&self.connection)
                    .expect("Error creating new user")
            },
            _ => res.pop().unwrap(),
        };

        use super::schema::voteables::dsl::*;
        let mut res: Vec<Voteable> = voteables.filter(value.eq(entity)).load(&self.connection).unwrap();
        let mut voteable= match res.len() {
            0 => {
                let new_voteable = NewVoteable {
                    value: entity,
                    total_up: 0,
                    total_down: 0,
                };

                diesel::insert(&new_voteable).into(voteables::table)
                    .get_result(&self.connection)
                    .expect("Error creating new voteable")
            },

            _ => res.pop().unwrap(),
        };

        voteable.total_up += up;
        voteable.total_down += down;
        voteable.save_changes::<Voteable>(&self.connection);

        use super::schema::votes::dsl as vts;
        let mut res: Vec<Vote> = vts::votes.filter(vts::user_id.eq(user.id))
                                           .filter(vts::voteable_id.eq(voteable.id))
                                           .load(&self.connection).unwrap();
        let mut vote = match res.len() {
            0 => {
                let new_vote = NewVote{
                    user_id: user.id,
                    voteable_id: voteable.id,
                    up: 0,
                    down: 0,
                };

                diesel::insert(&new_vote).into(votes::table)
                    .get_result(&self.connection)
                    .expect("Error creating new vote")
            },
            _ => res.pop().unwrap(),
        };

        vote.up += up;
        vote.down += down;
        vote.save_changes::<Vote>(&self.connection);
    }

    pub fn get_upvotes(&self, entity: &str) -> Result<Voteable, DieselErr> {
        use super::schema::voteables::dsl::*;

        match voteables.filter(value.eq(entity)).load(&self.connection) {
            Ok(mut v) => Ok(v.pop().unwrap()),
            Err(e) => Err(e),
        }
    }
}
<|endoftext|>


<commit_before>//! This module has various option flags and configs we can pass to ISPC,
//! located here for convience and clutter reduction.

/// Different math libraries that ISPC can use for computations.
pub enum MathLib {
    /// Use ispc's built-in math functions (the default).
    ISPCDefault,
    /// Use high-performance but lower-accuracy math functions.
    Fast,
    /// Use the Intel(r) SVML math libraries.
    SVML,
    /// Use the system's math library (**may be quite slow**).
    System,
}

impl ToString for MathLib {
    fn to_string(&self) -> String {
        match *self {
            MathLib::ISPCDefault => String::from("--math-lib=default"),
            MathLib::Fast => String::from("--math-lib=fast"),
            MathLib::SVML => String::from("--math-lib=svml"),
            MathLib::System => String::from("--math-lib=system"),
        }
    }
}

/// Select the target CPU architecture
pub enum Architecture {
    Arm,
    Aarch64,
    X86,
    X64
}

impl ToString for Architecture {
    fn to_string(&self) -> String {
        match *self {
            Architecture::Arm => String::from("--arch=arm"),
            Architecture::Aarch64 => String::from("--arch=aarch64"),
            Architecture::X86 => String::from("--arch=x86"),
            Architecture::X64 => String::from("--arch=x86_64"),
        }
    }
}

/// Select 32 or 64 bit addressing to be used by ISPC. Note: 32-bit
/// addressing calculations are done by default, even on 64 bit target
/// architectures.
pub enum Addressing {
    /// Select 32 bit addressing calculations.
    A32,
    /// Select 64 bit addressing calculations.
    A64,
}

impl ToString for Addressing {
    fn to_string(&self) -> String {
        match *self {
            Addressing::A32 => String::from("--addressing=32"),
            Addressing::A64 => String::from("--addressing=64"),
        }
    }
}

/// ISPC target CPU ISA options, if none is set ISPC will
/// target the machine being compile on.
#[derive(Eq, PartialEq)]
pub enum CPU {
    Generic,
    /// Synonym for Atom target
    Bonnell,
    Core2,
    Penryn,
    /// Synonym for corei7 target
    Nehalem,
    /// Synonym for btver2
    Ps4,
    /// Synonym for corei7-avx
    SandyBridge,
    /// Synonym for core-avx-i target
    IvyBridge,
    /// Synonym for core-avx2 target
    Haswell,
    Broadwell,
    Knl,
    Skx,
    Icl,
    /// Synonym for slm target
    Silvermont,
    CoretexA15,
    CoretexA9,
    CoretexA35,
    CoretexA53,
    CoretexA57,
}

impl ToString for CPU {
    fn to_string(&self) -> String {
        match *self {
            CPU::Generic => String::from("--cpu=generic"),
            CPU::Bonnell => String::from("--cpu=bonnell"),
            CPU::Core2 => String::from("--cpu=core2"),
            CPU::Penryn => String::from("--cpu=penryn"),
            CPU::Nehalem => String::from("--cpu=nehalem"),
            CPU::Ps4 => String::from("--cpu=ps4"),
            CPU::SandyBridge => String::from("--cpu=sandybridge"),
            CPU::IvyBridge => String::from("--cpu=ivybridge"),
            CPU::Haswell => String::from("--cpu=haswell"),
            CPU::Broadwell => String::from("--cpu=broadwell"),
            CPU::Knl => String::from("--cpu=knl"),
            CPU::Skx => String::from("--cpu=skx"),
            CPU::Icl => String::from("--cpu=icl"),
            CPU::Silvermont => String::from("--cpu=silvermont"),
            CPU::CoretexA15 => String::from("--cpu=cortex-a15"),
            CPU::CoretexA9 => String::from("--cpu=cortex-a9"),
            CPU::CoretexA35 => String::from("--cpu=cortex-a35"),
            CPU::CoretexA53 => String::from("--cpu=cortex-a53"),
            CPU::CoretexA57 => String::from("--cpu=cortex-a57"),
        }
    }
}

/// ISPC optimization options.
#[derive(Ord, PartialOrd, Eq, PartialEq)]
pub enum OptimizationOpt {
    /// Remove assertion statements from final code.
    DisableAssertions,
    /// Disable 'fused multiply-add' instructions (on targets that support them).
    DisableFMA,
    /// Disable loop unrolling.
    DisableLoopUnroll,
    /// Faster masked vector loads on SSE (may go past end of array).
    FastMaskedVload,
    /// Perform non-IEEE-compliant optimizations of numeric expressions.
    FastMath,
    /// Always issue aligned vector load and store instructions.
    ForceAlignedMemory,
}

impl ToString for OptimizationOpt {
    fn to_string(&self) -> String {
        match *self {
            OptimizationOpt::DisableAssertions => String::from("--opt=disable-assertions"),
            OptimizationOpt::DisableFMA => String::from("--opt=disable-fma"),
            OptimizationOpt::DisableLoopUnroll => String::from("--opt=disable-loop-unroll"),
            OptimizationOpt::FastMaskedVload => String::from("--opt=fast-masked-vload"),
            OptimizationOpt::FastMath => String::from("--opt=fast-math"),
            OptimizationOpt::ForceAlignedMemory => String::from("--opt=force-aligned-memory"),
        }
    }
}

/// Target instruction sets and vector widths available to specialize for. The
/// default if none is set will be the host CPU's ISA and vector width.
pub enum TargetISA {
    Host,
    SSE2i32x4,
    SSE2i32x8,
    SSE4i32x4,
    SSE4i32x8,
    SSE4i16x8,
    SSE4i8x16,
    AVX1i32x4,
    AVX1i32x8,
    AVX1i32x16,
    AVX1i64x4,
    AVX2i32x8,
    AVX2i32x16,
    AVX2i64x4,
    AVX512KNLi32x16,
    AVX512SKXi32x16,
    AVX512SKXi32x8,
    Neoni8x16,
    Neoni16x8,
    Neoni32x4,
    Neoni32x8,
}

impl TargetISA {
    pub fn lib_suffix(&self) -> String {
        match *self {
            TargetISA::Host => String::from("host"),
            TargetISA::SSE2i32x4 => String::from("sse2"),
            TargetISA::SSE2i32x8 => String::from("sse2"),
            TargetISA::SSE4i32x4 => String::from("sse4"),
            TargetISA::SSE4i32x8 => String::from("sse4"),
            TargetISA::SSE4i16x8 => String::from("sse4"),
            TargetISA::SSE4i8x16 => String::from("sse4"),
            TargetISA::AVX1i32x4 => String::from("avx"),
            TargetISA::AVX1i32x8 => String::from("avx"),
            TargetISA::AVX1i32x16 => String::from("avx"),
            TargetISA::AVX1i64x4 => String::from("avx"),
            TargetISA::AVX2i32x8 => String::from("avx2"),
            TargetISA::AVX2i32x16 => String::from("avx2"),
            TargetISA::AVX2i64x4 => String::from("avx2"),
            TargetISA::AVX512KNLi32x16 => String::from("avx512knl"),
            TargetISA::AVX512SKXi32x16 => String::from("avx512skx"),
            TargetISA::AVX512SKXi32x8 => String::from("avx512skx"),
            TargetISA::Neoni8x16 => String::from("neon"),
            TargetISA::Neoni16x8 => String::from("neon"),
            TargetISA::Neoni32x4 => String::from("neon"),
            TargetISA::Neoni32x8 => String::from("neon"),
        }
    }
}

impl ToString for TargetISA {
    fn to_string(&self) -> String {
        match *self {
            TargetISA::Host => String::from("host"),
            TargetISA::SSE2i32x4 => String::from("sse2-i32x4"),
            TargetISA::SSE2i32x8 => String::from("sse2-i32x8"),
            TargetISA::SSE4i32x4 => String::from("sse4-i32x4"),
            TargetISA::SSE4i32x8 => String::from("sse4-i32x8"),
            TargetISA::SSE4i16x8 => String::from("sse4-i16x8"),
            TargetISA::SSE4i8x16 => String::from("sse4-i8x16"),
            TargetISA::AVX1i32x4 => String::from("avx1-i32x4"),
            TargetISA::AVX1i32x8 => String::from("avx1-i32x8"),
            TargetISA::AVX1i32x16 => String::from("avx1-i32x16"),
            TargetISA::AVX1i64x4 => String::from("avx1-i64x4"),
            TargetISA::AVX2i32x8 => String::from("avx2-i32x8"),
            TargetISA::AVX2i32x16 => String::from("avx2-i32x16"),
            TargetISA::AVX2i64x4 => String::from("avx2-i64x4"),
            TargetISA::AVX512KNLi32x16 => String::from("avx512knl-i32x16"),
            TargetISA::AVX512SKXi32x16 => String::from("avx512skx-i32x16"),
            TargetISA::AVX512SKXi32x8 => String::from("avx512skx-i32x8"),
            TargetISA::Neoni8x16 => String::from("neon-i8x16"),
            TargetISA::Neoni16x8 => String::from("neon-i16x8"),
            TargetISA::Neoni32x4 => String::from("neon-i32x4"),
            TargetISA::Neoni32x8 => String::from("neon-i32x8"),
        }
    }
}

/// Target instruction sets and vector widths available to specialize for. The
/// default if none is set will be the host CPU's ISA and vector width.
pub enum TargetOS {
    Windows,
    Ps4,
    Linux,
    Macos,
    Android,
}

impl TargetOS {
    pub fn lib_suffix(&self) -> String {
        match *self {
            TargetOS::Windows => String::from("windows"),
            TargetOS::Ps4 => String::from("ps4"),
            TargetOS::Linux => String::from("linux"),
            TargetOS::Macos => String::from("macos"),
            TargetOS::Android => String::from("android"),
        }
    }
}

impl ToString for TargetOS {
    fn to_string(&self) -> String {
        match *self {
            TargetOS::Windows => String::from("--target-os=windows"),
            TargetOS::Ps4 => String::from("--target-os=ps4"),
            TargetOS::Linux => String::from("--target-os=linux"),
            TargetOS::Macos => String::from("--target-os=macos"),
            TargetOS::Android => String::from("--target-os=android"),
        }
    }
}

<commit_msg>add new disable-zmm opt for 1.13<commit_after>//! This module has various option flags and configs we can pass to ISPC,
//! located here for convience and clutter reduction.

/// Different math libraries that ISPC can use for computations.
pub enum MathLib {
    /// Use ispc's built-in math functions (the default).
    ISPCDefault,
    /// Use high-performance but lower-accuracy math functions.
    Fast,
    /// Use the Intel(r) SVML math libraries.
    SVML,
    /// Use the system's math library (**may be quite slow**).
    System,
}

impl ToString for MathLib {
    fn to_string(&self) -> String {
        match *self {
            MathLib::ISPCDefault => String::from("--math-lib=default"),
            MathLib::Fast => String::from("--math-lib=fast"),
            MathLib::SVML => String::from("--math-lib=svml"),
            MathLib::System => String::from("--math-lib=system"),
        }
    }
}

/// Select the target CPU architecture
pub enum Architecture {
    Arm,
    Aarch64,
    X86,
    X64
}

impl ToString for Architecture {
    fn to_string(&self) -> String {
        match *self {
            Architecture::Arm => String::from("--arch=arm"),
            Architecture::Aarch64 => String::from("--arch=aarch64"),
            Architecture::X86 => String::from("--arch=x86"),
            Architecture::X64 => String::from("--arch=x86_64"),
        }
    }
}

/// Select 32 or 64 bit addressing to be used by ISPC. Note: 32-bit
/// addressing calculations are done by default, even on 64 bit target
/// architectures.
pub enum Addressing {
    /// Select 32 bit addressing calculations.
    A32,
    /// Select 64 bit addressing calculations.
    A64,
}

impl ToString for Addressing {
    fn to_string(&self) -> String {
        match *self {
            Addressing::A32 => String::from("--addressing=32"),
            Addressing::A64 => String::from("--addressing=64"),
        }
    }
}

/// ISPC target CPU ISA options, if none is set ISPC will
/// target the machine being compile on.
#[derive(Eq, PartialEq)]
pub enum CPU {
    Generic,
    /// Synonym for Atom target
    Bonnell,
    Core2,
    Penryn,
    /// Synonym for corei7 target
    Nehalem,
    /// Synonym for btver2
    Ps4,
    /// Synonym for corei7-avx
    SandyBridge,
    /// Synonym for core-avx-i target
    IvyBridge,
    /// Synonym for core-avx2 target
    Haswell,
    Broadwell,
    Knl,
    Skx,
    Icl,
    /// Synonym for slm target
    Silvermont,
    CoretexA15,
    CoretexA9,
    CoretexA35,
    CoretexA53,
    CoretexA57,
}

impl ToString for CPU {
    fn to_string(&self) -> String {
        match *self {
            CPU::Generic => String::from("--cpu=generic"),
            CPU::Bonnell => String::from("--cpu=bonnell"),
            CPU::Core2 => String::from("--cpu=core2"),
            CPU::Penryn => String::from("--cpu=penryn"),
            CPU::Nehalem => String::from("--cpu=nehalem"),
            CPU::Ps4 => String::from("--cpu=ps4"),
            CPU::SandyBridge => String::from("--cpu=sandybridge"),
            CPU::IvyBridge => String::from("--cpu=ivybridge"),
            CPU::Haswell => String::from("--cpu=haswell"),
            CPU::Broadwell => String::from("--cpu=broadwell"),
            CPU::Knl => String::from("--cpu=knl"),
            CPU::Skx => String::from("--cpu=skx"),
            CPU::Icl => String::from("--cpu=icl"),
            CPU::Silvermont => String::from("--cpu=silvermont"),
            CPU::CoretexA15 => String::from("--cpu=cortex-a15"),
            CPU::CoretexA9 => String::from("--cpu=cortex-a9"),
            CPU::CoretexA35 => String::from("--cpu=cortex-a35"),
            CPU::CoretexA53 => String::from("--cpu=cortex-a53"),
            CPU::CoretexA57 => String::from("--cpu=cortex-a57"),
        }
    }
}

/// ISPC optimization options.
#[derive(Ord, PartialOrd, Eq, PartialEq)]
pub enum OptimizationOpt {
    /// Remove assertion statements from final code.
    DisableAssertions,
    /// Disable 'fused multiply-add' instructions (on targets that support them).
    DisableFMA,
    /// Disable loop unrolling.
    DisableLoopUnroll,
    /// Faster masked vector loads on SSE (may go past end of array).
    FastMaskedVload,
    /// Perform non-IEEE-compliant optimizations of numeric expressions.
    FastMath,
    /// Always issue aligned vector load and store instructions.
    ForceAlignedMemory,
    /// Disable using zmm registers in favor of ymm on avx512skx-i32x16 (ISPC 1.13+)
    DisableZmm,
}

impl ToString for OptimizationOpt {
    fn to_string(&self) -> String {
        match *self {
            OptimizationOpt::DisableAssertions => String::from("--opt=disable-assertions"),
            OptimizationOpt::DisableFMA => String::from("--opt=disable-fma"),
            OptimizationOpt::DisableLoopUnroll => String::from("--opt=disable-loop-unroll"),
            OptimizationOpt::FastMaskedVload => String::from("--opt=fast-masked-vload"),
            OptimizationOpt::FastMath => String::from("--opt=fast-math"),
            OptimizationOpt::ForceAlignedMemory => String::from("--opt=force-aligned-memory"),
            OptimizationOpt::DisableZmm => String::from("--opt=disable-zmm"),
        }
    }
}

/// Target instruction sets and vector widths available to specialize for. The
/// default if none is set will be the host CPU's ISA and vector width.
pub enum TargetISA {
    Host,
    SSE2i32x4,
    SSE2i32x8,
    SSE4i32x4,
    SSE4i32x8,
    SSE4i16x8,
    SSE4i8x16,
    AVX1i32x4,
    AVX1i32x8,
    AVX1i32x16,
    AVX1i64x4,
    AVX2i32x8,
    AVX2i32x16,
    AVX2i64x4,
    AVX512KNLi32x16,
    AVX512SKXi32x16,
    AVX512SKXi32x8,
    Neoni8x16,
    Neoni16x8,
    Neoni32x4,
    Neoni32x8,
}

impl TargetISA {
    pub fn lib_suffix(&self) -> String {
        match *self {
            TargetISA::Host => String::from("host"),
            TargetISA::SSE2i32x4 => String::from("sse2"),
            TargetISA::SSE2i32x8 => String::from("sse2"),
            TargetISA::SSE4i32x4 => String::from("sse4"),
            TargetISA::SSE4i32x8 => String::from("sse4"),
            TargetISA::SSE4i16x8 => String::from("sse4"),
            TargetISA::SSE4i8x16 => String::from("sse4"),
            TargetISA::AVX1i32x4 => String::from("avx"),
            TargetISA::AVX1i32x8 => String::from("avx"),
            TargetISA::AVX1i32x16 => String::from("avx"),
            TargetISA::AVX1i64x4 => String::from("avx"),
            TargetISA::AVX2i32x8 => String::from("avx2"),
            TargetISA::AVX2i32x16 => String::from("avx2"),
            TargetISA::AVX2i64x4 => String::from("avx2"),
            TargetISA::AVX512KNLi32x16 => String::from("avx512knl"),
            TargetISA::AVX512SKXi32x16 => String::from("avx512skx"),
            TargetISA::AVX512SKXi32x8 => String::from("avx512skx"),
            TargetISA::Neoni8x16 => String::from("neon"),
            TargetISA::Neoni16x8 => String::from("neon"),
            TargetISA::Neoni32x4 => String::from("neon"),
            TargetISA::Neoni32x8 => String::from("neon"),
        }
    }
}

impl ToString for TargetISA {
    fn to_string(&self) -> String {
        match *self {
            TargetISA::Host => String::from("host"),
            TargetISA::SSE2i32x4 => String::from("sse2-i32x4"),
            TargetISA::SSE2i32x8 => String::from("sse2-i32x8"),
            TargetISA::SSE4i32x4 => String::from("sse4-i32x4"),
            TargetISA::SSE4i32x8 => String::from("sse4-i32x8"),
            TargetISA::SSE4i16x8 => String::from("sse4-i16x8"),
            TargetISA::SSE4i8x16 => String::from("sse4-i8x16"),
            TargetISA::AVX1i32x4 => String::from("avx1-i32x4"),
            TargetISA::AVX1i32x8 => String::from("avx1-i32x8"),
            TargetISA::AVX1i32x16 => String::from("avx1-i32x16"),
            TargetISA::AVX1i64x4 => String::from("avx1-i64x4"),
            TargetISA::AVX2i32x8 => String::from("avx2-i32x8"),
            TargetISA::AVX2i32x16 => String::from("avx2-i32x16"),
            TargetISA::AVX2i64x4 => String::from("avx2-i64x4"),
            TargetISA::AVX512KNLi32x16 => String::from("avx512knl-i32x16"),
            TargetISA::AVX512SKXi32x16 => String::from("avx512skx-i32x16"),
            TargetISA::AVX512SKXi32x8 => String::from("avx512skx-i32x8"),
            TargetISA::Neoni8x16 => String::from("neon-i8x16"),
            TargetISA::Neoni16x8 => String::from("neon-i16x8"),
            TargetISA::Neoni32x4 => String::from("neon-i32x4"),
            TargetISA::Neoni32x8 => String::from("neon-i32x8"),
        }
    }
}

/// Target instruction sets and vector widths available to specialize for. The
/// default if none is set will be the host CPU's ISA and vector width.
pub enum TargetOS {
    Windows,
    Ps4,
    Linux,
    Macos,
    Android,
}

impl TargetOS {
    pub fn lib_suffix(&self) -> String {
        match *self {
            TargetOS::Windows => String::from("windows"),
            TargetOS::Ps4 => String::from("ps4"),
            TargetOS::Linux => String::from("linux"),
            TargetOS::Macos => String::from("macos"),
            TargetOS::Android => String::from("android"),
        }
    }
}

impl ToString for TargetOS {
    fn to_string(&self) -> String {
        match *self {
            TargetOS::Windows => String::from("--target-os=windows"),
            TargetOS::Ps4 => String::from("--target-os=ps4"),
            TargetOS::Linux => String::from("--target-os=linux"),
            TargetOS::Macos => String::from("--target-os=macos"),
            TargetOS::Android => String::from("--target-os=android"),
        }
    }
}

<|endoftext|>


<commit_before>use netsurfcss::stylesheet::CssStylesheet;
use netsurfcss::select::{CssSelectCtx, css_select_ctx_create, CssSelectResults, CssSelectHandler};
use netsurfcss::types::CssQName;
use netsurfcss::properties::CssProperty;
use netsurfcss::ll::types::{CSS_ORIGIN_AUTHOR, CSS_MEDIA_SCREEN};
use netsurfcss::hint::CssHint;
use util::DataStream;
use std::net::url::Url;

pub struct Stylesheet {
    inner: CssStylesheet
}

impl Stylesheet {
    static fn new(url: Url, input: DataStream) -> Stylesheet {
        Stylesheet {
            inner: parser::parse_stylesheet(move url, input)
        }
    }
}

pub struct SelectCtx {
    inner: CssSelectCtx
}

impl SelectCtx {
    static fn new() -> SelectCtx {
        SelectCtx {
            inner: css_select_ctx_create()
        }
    }

    fn append_sheet(&mut self, sheet: Stylesheet) {
        let sheet = match move sheet {
            Stylesheet { inner: move inner } => move inner
        };

        self.inner.append_sheet(move sheet, CSS_ORIGIN_AUTHOR, CSS_MEDIA_SCREEN)
    }

    fn select_style<N, H: SelectHandler<N>>(&self, node: &N, handler: &H) -> SelectResults {
        let inner_handler = InnerHandler {
            inner: ptr::to_unsafe_ptr(handler)
        };
        SelectResults {
            inner: self.inner.select_style::<N, InnerHandler<N, H>>(node, CSS_MEDIA_SCREEN, None, &inner_handler)
        }
    }
}

pub struct SelectResults {
    inner: CssSelectResults
}

pub trait SelectHandler<N> {
}

struct InnerHandler<N, H: SelectHandler<N>> {
    // FIXME: Can't encode region variables
    inner: *H
}

impl<N, H: SelectHandler<N>> InnerHandler<N, H>: CssSelectHandler<N> {
    fn node_name(_node: &N) -> CssQName {
        fail ~"implement node_name"
    }
    fn ua_default_for_property(_property: CssProperty) -> CssHint {
        fail ~"implement ua_default_for_property"
    }
}<commit_msg>Expose the node_name callback<commit_after>use netsurfcss::stylesheet::CssStylesheet;
use netsurfcss::select::{CssSelectCtx, css_select_ctx_create, CssSelectResults, CssSelectHandler};
use netsurfcss::types::CssQName;
use netsurfcss::properties::CssProperty;
use netsurfcss::ll::types::{CSS_ORIGIN_AUTHOR, CSS_MEDIA_SCREEN};
use netsurfcss::hint::{CssHint, CssHintDefault};
use wapcaplet::from_rust_string;
use util::DataStream;
use std::net::url::Url;

pub struct Stylesheet {
    inner: CssStylesheet
}

impl Stylesheet {
    static fn new(url: Url, input: DataStream) -> Stylesheet {
        Stylesheet {
            inner: parser::parse_stylesheet(move url, input)
        }
    }
}

pub struct SelectCtx {
    inner: CssSelectCtx
}

impl SelectCtx {
    static fn new() -> SelectCtx {
        SelectCtx {
            inner: css_select_ctx_create()
        }
    }

    fn append_sheet(&mut self, sheet: Stylesheet) {
        let sheet = match move sheet {
            Stylesheet { inner: move inner } => move inner
        };

        self.inner.append_sheet(move sheet, CSS_ORIGIN_AUTHOR, CSS_MEDIA_SCREEN)
    }

    fn select_style<N, H: SelectHandler<N>>(&self, node: &N, handler: &H) -> SelectResults {
        let inner_handler = InnerHandler {
            inner: ptr::to_unsafe_ptr(handler)
        };
        SelectResults {
            inner: self.inner.select_style::<N, InnerHandler<N, H>>(node, CSS_MEDIA_SCREEN, None, &inner_handler)
        }
    }
}

pub struct SelectResults {
    inner: CssSelectResults
}

pub trait SelectHandler<N> {
    fn node_name(node: &N) -> ~str;
}

struct InnerHandler<N, H: SelectHandler<N>> {
    // FIXME: Can't encode region variables
    inner: *H
}

priv impl<N, H: SelectHandler<N>> InnerHandler<N, H> {
    priv fn inner_ref() -> &self/H {
        unsafe { &*self.inner }
    }
}

impl<N, H: SelectHandler<N>> InnerHandler<N, H>: CssSelectHandler<N> {
    fn node_name(node: &N) -> CssQName {
        CssQName {
            ns: None,
            name: from_rust_string(self.inner_ref().node_name(node))
        }
    }
    fn ua_default_for_property(property: CssProperty) -> CssHint {
        error!("not specifiying ua default for property %?", property);
        CssHintDefault
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

extern crate chrono;
extern crate futures;
extern crate log;
extern crate tokio_core;
extern crate trust_dns;
extern crate trust_dns_proto;
extern crate trust_dns_server;

#[cfg(feature = "tls")]
extern crate trust_dns_openssl;

mod server_harness;

use std::net::*;
use std::str::FromStr;

use tokio_core::reactor::Core;

use trust_dns::client::*;
use trust_dns::op::ResponseCode;
use trust_dns::rr::*;
use trust_dns::tcp::TcpClientStream;
use trust_dns::udp::UdpClientStream;

// TODO: Needed for when TLS tests are added back
// #[cfg(feature = "tls")]
// use trust_dns_openssl::TlsClientStreamBuilder;

use server_harness::{named_test_harness, query_a};

#[test]
fn test_example_toml_startup() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        query_a(&mut io_loop, &mut client);

        // just tests that multiple queries work
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        query_a(&mut io_loop, &mut client);
    })
}

#[test]
fn test_ipv4_only_toml_startup() {
    named_test_harness("ipv4_only.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv4 should succeed
        query_a(&mut io_loop, &mut client);

        let addr: SocketAddr = SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv6 should fail
        let message = io_loop.run(client.query(
            Name::from_str("www.example.com").unwrap(),
            DNSClass::IN,
            RecordType::AAAA,
        ));
        assert!(message.is_err());
    })
}

// TODO: this is commented out b/c at least on macOS, ipv4 will route properly to ipv6 only
//  listeners over the [::ffff:127.0.0.1] interface
//
// #[ignore]
// #[test]
// fn test_ipv6_only_toml_startup() {
//   named_test_harness("ipv6_only.toml", |port, _| {
//     let mut io_loop = Core::new().unwrap();
//     let addr: SocketAddr = ("127.0.0.1", port).to_socket_addrs().unwrap().next().unwrap();
//     let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
//     let client = ClientFuture::new(stream, sender, &io_loop.handle(), None);
//
//     // ipv4 should fail
//     assert!(!query(&mut io_loop, client));
//
//     let addr: SocketAddr = ("::1", port).to_socket_addrs().unwrap().next().unwrap();
//     let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
//     let client = ClientFuture::new(stream, sender, &io_loop.handle(), None);
//
//     // ipv6 should succeed
//     assert!(query(&mut io_loop, client));
//
//     assert!(true);
//   })
// }

#[ignore]
#[test]
fn test_ipv4_and_ipv6_toml_startup() {
    named_test_harness("ipv4_and_ipv6.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv4 should succeed
        query_a(&mut io_loop, &mut client);

        let addr: SocketAddr = SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv6 should succeed
        query_a(&mut io_loop, &mut client);

        assert!(true);
    })
}

#[test]
fn test_nodata_where_name_exists() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        let msg = io_loop
            .run(client.query(
                Name::from_str("www.example.com.").unwrap(),
                DNSClass::IN,
                RecordType::SRV,
            ))
            .unwrap();
        assert_eq!(msg.response_code(), ResponseCode::NoError);
        assert!(msg.answers().is_empty());
        assert!(true);
    })
}

#[test]
fn test_nxdomain_where_no_name_exists() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        let msg = io_loop
            .run(client.query(
                Name::from_str("nxdomain.example.com.").unwrap(),
                DNSClass::IN,
                RecordType::SRV,
            ))
            .unwrap();
        assert_eq!(msg.response_code(), ResponseCode::NXDomain);
        assert!(msg.answers().is_empty());
        assert!(true);
    })
}

#[cfg(feature = "tls")]
#[test]
fn test_example_tls_toml_startup() {
    use std::env;
    use std::fs::File;
    use std::io::*;
    use trust_dns_openssl::TlsClientStreamBuilder;

    named_test_harness("dns_over_tls.toml", move |_, tls_port| {
        let mut cert_der = vec![];
        let server_path = env::var("TDNS_SERVER_SRC_ROOT").unwrap_or_else(|_| ".".to_owned());
        println!("using server src path: {}", server_path);

        File::open(&format!(
            "{}/tests/named_test_configs/sec/example.cert",
            server_path
        )).expect("failed to open cert")
            .read_to_end(&mut cert_der)
            .expect("failed to read cert");

        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), tls_port);
        let mut tls_conn_builder = TlsClientStreamBuilder::new();
        tls_conn_builder.add_ca_der(&cert_der).unwrap();
        let (stream, sender) =
            tls_conn_builder.build(addr, "ns.example.com".to_string(), &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv4 should succeed
        query_a(&mut io_loop, &mut client);

        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), tls_port);
        let mut tls_conn_builder = TlsClientStreamBuilder::new();
        tls_conn_builder.add_ca_der(&cert_der).unwrap();
        let (stream, sender) =
            tls_conn_builder.build(addr, "ns.example.com".to_string(), &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv6 should succeed
        query_a(&mut io_loop, &mut client);

        assert!(true);
    })
}

// #[test]
// fn test_server_continues_on_bad_data() {
//     named_test_harness("example.toml", |port, _| {
//         let mut io_loop = Core::new().unwrap();
//         let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
//         let (stream, sender) = UdpClientStream::new(addr, &io_loop.handle());
//         let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

//         query_a(&mut io_loop, &mut client);

//         // Send a bad packet, this should get rejected by the server
//         let raw_socket = UdpSocket::bind(SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 0))
//             .expect("couldn't bind raw");

//         raw_socket
//             .send_to(b"0xDEADBEEF", addr)
//             .expect("raw send failed");

//         // just tests that multiple queries work
//         let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
//         let (stream, sender) = UdpClientStream::new(addr, &io_loop.handle());
//         let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

//         query_a(&mut io_loop, &mut client);
//     })
// }
<commit_msg>fix hanging server<commit_after>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

extern crate chrono;
extern crate futures;
extern crate log;
extern crate tokio_core;
extern crate trust_dns;
extern crate trust_dns_proto;
extern crate trust_dns_server;

#[cfg(feature = "tls")]
extern crate trust_dns_openssl;

mod server_harness;

use std::net::*;
use std::str::FromStr;

use tokio_core::reactor::Core;

use trust_dns::client::*;
use trust_dns::op::ResponseCode;
use trust_dns::rr::*;
use trust_dns::tcp::TcpClientStream;
use trust_dns::udp::UdpClientStream;

// TODO: Needed for when TLS tests are added back
// #[cfg(feature = "tls")]
// use trust_dns_openssl::TlsClientStreamBuilder;

use server_harness::{named_test_harness, query_a};

#[test]
fn test_example_toml_startup() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        query_a(&mut io_loop, &mut client);

        // just tests that multiple queries work
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        query_a(&mut io_loop, &mut client);
    })
}

#[test]
fn test_ipv4_only_toml_startup() {
    named_test_harness("ipv4_only.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv4 should succeed
        query_a(&mut io_loop, &mut client);

        let addr: SocketAddr = SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv6 should fail
        let message = io_loop.run(client.query(
            Name::from_str("www.example.com").unwrap(),
            DNSClass::IN,
            RecordType::AAAA,
        ));
        assert!(message.is_err());
    })
}

// TODO: this is commented out b/c at least on macOS, ipv4 will route properly to ipv6 only
//  listeners over the [::ffff:127.0.0.1] interface
//
// #[ignore]
// #[test]
// fn test_ipv6_only_toml_startup() {
//   named_test_harness("ipv6_only.toml", |port, _| {
//     let mut io_loop = Core::new().unwrap();
//     let addr: SocketAddr = ("127.0.0.1", port).to_socket_addrs().unwrap().next().unwrap();
//     let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
//     let client = ClientFuture::new(stream, sender, &io_loop.handle(), None);
//
//     // ipv4 should fail
//     assert!(!query(&mut io_loop, client));
//
//     let addr: SocketAddr = ("::1", port).to_socket_addrs().unwrap().next().unwrap();
//     let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
//     let client = ClientFuture::new(stream, sender, &io_loop.handle(), None);
//
//     // ipv6 should succeed
//     assert!(query(&mut io_loop, client));
//
//     assert!(true);
//   })
// }

#[ignore]
#[test]
fn test_ipv4_and_ipv6_toml_startup() {
    named_test_harness("ipv4_and_ipv6.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv4 should succeed
        query_a(&mut io_loop, &mut client);

        let addr: SocketAddr = SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv6 should succeed
        query_a(&mut io_loop, &mut client);

        assert!(true);
    })
}

#[test]
fn test_nodata_where_name_exists() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        let msg = io_loop
            .run(client.query(
                Name::from_str("www.example.com.").unwrap(),
                DNSClass::IN,
                RecordType::SRV,
            ))
            .unwrap();
        assert_eq!(msg.response_code(), ResponseCode::NoError);
        assert!(msg.answers().is_empty());
        assert!(true);
    })
}

#[test]
fn test_nxdomain_where_no_name_exists() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        let msg = io_loop
            .run(client.query(
                Name::from_str("nxdomain.example.com.").unwrap(),
                DNSClass::IN,
                RecordType::SRV,
            ))
            .unwrap();
        assert_eq!(msg.response_code(), ResponseCode::NXDomain);
        assert!(msg.answers().is_empty());
        assert!(true);
    })
}

#[cfg(feature = "tls")]
#[test]
fn test_example_tls_toml_startup() {
    use std::env;
    use std::fs::File;
    use std::io::*;
    use trust_dns_openssl::TlsClientStreamBuilder;

    named_test_harness("dns_over_tls.toml", move |_, tls_port| {
        let mut cert_der = vec![];
        let server_path = env::var("TDNS_SERVER_SRC_ROOT").unwrap_or_else(|_| ".".to_owned());
        println!("using server src path: {}", server_path);

        File::open(&format!(
            "{}/tests/named_test_configs/sec/example.cert",
            server_path
        )).expect("failed to open cert")
            .read_to_end(&mut cert_der)
            .expect("failed to read cert");

        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), tls_port);
        let mut tls_conn_builder = TlsClientStreamBuilder::new();
        tls_conn_builder.add_ca_der(&cert_der).unwrap();
        let (stream, sender) =
            tls_conn_builder.build(addr, "ns.example.com".to_string(), &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv4 should succeed
        query_a(&mut io_loop, &mut client);

        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), tls_port);
        let mut tls_conn_builder = TlsClientStreamBuilder::new();
        tls_conn_builder.add_ca_der(&cert_der).unwrap();
        let (stream, sender) =
            tls_conn_builder.build(addr, "ns.example.com".to_string(), &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv6 should succeed
        query_a(&mut io_loop, &mut client);

        assert!(true);
    })
}

#[test]
fn test_server_continues_on_bad_data() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = UdpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        query_a(&mut io_loop, &mut client);

        // Send a bad packet, this should get rejected by the server
        let raw_socket = UdpSocket::bind(SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 0))
            .expect("couldn't bind raw");

        raw_socket
            .send_to(b"0xDEADBEEF", addr)
            .expect("raw send failed");

        // just tests that multiple queries work
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = UdpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        query_a(&mut io_loop, &mut client);
    })
}
<|endoftext|>


<commit_before>//
// sprocketnes/gfx.rs
//
// Author: Patrick Walton
//

use core::cast::transmute;
use core::uint::range;
use sdl::sdl::{InitAudio, InitTimer, InitVideo};
use sdl::sdl;
use sdl::video::{AsyncBlit, SWSurface, Surface};
use sdl::video;

const SCREEN_WIDTH: uint = 256;
const SCREEN_HEIGHT: uint = 240;

pub enum Scale {
    Scale1x,
    Scale2x,
    Scale3x,
}

impl Scale {
    fn factor(self) -> uint { match self { Scale1x => 1, Scale2x => 2, Scale3x => 3 } }
}

pub struct Gfx {
    screen: ~Surface,
    scale: Scale,
}

macro_rules! scaler(
    ($count:expr, $pixels:ident, $ppu_screen:ident) => (
        // Type safety goes out the window when we're in a performance critical loop
        // like this!

        unsafe {
            let mut dest: *mut u32 = transmute(&$pixels[0]);
            let mut src_start: *u8 = transmute(&$ppu_screen[0]);

            let mut src_y = 0;
            while src_y < SCREEN_HEIGHT {
                let src_scanline_start = src_start.offset(src_y * SCREEN_WIDTH * 3);
                let src_scanline_end = src_scanline_start.offset(SCREEN_WIDTH * 3);

                // Ugh, LLVM isn't inlining properly.
                //
                // FIXME: Mark for loop bodies as always inline in rustc.
                let mut repeat_y = 0;
                while repeat_y < $count {
                    let mut src = src_scanline_start;
                    while src < src_scanline_end {
                        let r = *src as u32; src = src.offset(1);
                        let g = *src as u32; src = src.offset(1);
                        let b = *src as u32; src = src.offset(1);
                        let pixel = (r << 24) | (g << 16) | (b << 8);

                        let mut repeat_x = 0;
                        while repeat_x < $count {
                            *dest = pixel; dest = dest.offset(1);
                            repeat_x += 1;
                        }
                    }
                    repeat_y += 1;
                }
                src_y += 1;
            }
        }
    )
)

impl Gfx {
    static pub fn new(scale: Scale) -> Gfx {
        sdl::init([ InitVideo, InitAudio, InitTimer ]);
        let screen = video::set_video_mode(SCREEN_WIDTH * scale.factor() as int,
                                           SCREEN_HEIGHT * scale.factor()  as int,
                                           32,
                                           [ SWSurface ],
                                           []);

        Gfx { screen: screen.unwrap(), scale: scale }
    }

    pub fn blit(&self, ppu_screen: &([u8 * 184320])) {
        do self.screen.with_lock |pixels| {
            match self.scale {
                Scale1x => scaler!(1, pixels, ppu_screen),
                Scale2x => scaler!(2, pixels, ppu_screen),
                Scale3x => scaler!(3, pixels, ppu_screen),
            }
        }
    }
}

<commit_msg>Compile in the PT Ronda Seven font from http://pinvoke.com/<commit_after>//
// sprocketnes/gfx.rs
//
// Author: Patrick Walton
//

use core::cast::transmute;
use core::uint::range;
use sdl::sdl::{InitAudio, InitTimer, InitVideo};
use sdl::sdl;
use sdl::video::{AsyncBlit, SWSurface, Surface};
use sdl::video;

const SCREEN_WIDTH: uint = 256;
const SCREEN_HEIGHT: uint = 240;

//
// PT Ronda Seven
//
// (c) Yusuke Kamiyamane, http://pinvoke.com/
//

const FONT_GLYPHS: [u8 * 950] = [
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // ' '
      0,  64,  64,  64,  64,  64,   0,  64,   0,   0,  // '!'
      0, 160, 160,   0,   0,   0,   0,   0,   0,   0,  // '"'
      0,  80,  80, 248,  80, 248,  80,  80,   0,   0,  // '#'
     32, 112, 168, 160, 112,  40, 168, 112,  32,   0,  // '$'
      0,  66, 164,  72,  16,  36,  74, 132,   0,   0,  // '%'
      0,  96, 144, 160,  72, 168, 144, 104,   0,   0,  // '&'
      0, 128, 128,   0,   0,   0,   0,   0,   0,   0,  // '''
     32,  64, 128, 128, 128, 128, 128,  64,  32,   0,  // '('
    128,  64,  32,  32,  32,  32,  32,  64, 128,   0,  // ')'
      0,  32, 168, 112, 168,  32,   0,   0,   0,   0,  // '*'
      0,   0,  32,  32, 248,  32,  32,   0,   0,   0,  // '+'
      0,   0,   0,   0,   0,   0,   0,  64,  64, 128,  // ','
      0,   0,   0,   0,   0, 224,   0,   0,   0,   0,  // '-'
      0,   0,   0,   0,   0,   0,   0,  64,   0,   0,  // '.'
      8,   8,  16,  16,  32,  64,  64, 128, 128,   0,  // '/'
      0, 112, 136, 136, 136, 136, 136, 112,   0,   0,  // '0'
      0, 192,  64,  64,  64,  64,  64,  64,   0,   0,  // '1'
      0, 112, 136,   8,  16,  32,  64, 248,   0,   0,  // '2'
      0, 112, 136,   8,  48,   8, 136, 112,   0,   0,  // '3'
      0,  48,  80,  80, 144, 248,  16,  16,   0,   0,  // '4'
      0, 248, 128, 128, 240,   8, 136, 112,   0,   0,  // '5'
      0, 112, 136, 128, 240, 136, 136, 112,   0,   0,  // '6'
      0, 248,   8,  16,  16,  32,  32,  64,   0,   0,  // '7'
      0, 112, 136, 136, 112, 136, 136, 112,   0,   0,  // '8'
      0, 112, 136, 136, 120,   8, 136, 112,   0,   0,  // '9'
      0,   0,   0,  64,   0,   0,   0,  64,   0,   0,  // ':'
      0,   0,   0,  64,   0,   0,   0,  64,  64, 128,  // ';'
      0,   0,  32,  64, 128,  64,  32,   0,   0,   0,  // '<'
      0,   0,   0, 224,   0, 224,   0,   0,   0,   0,  // '='
      0,   0, 128,  64,  32,  64, 128,   0,   0,   0,  // '>'
      0, 112, 136,   8,  16,  32,   0,  32,   0,   0,  // '?'
     60,  66, 157, 165, 165, 173, 149,  66,  56,   0,  // '@'
      0, 112, 136, 136, 248, 136, 136, 136,   0,   0,  // 'A'
      0, 240, 136, 136, 240, 136, 136, 240,   0,   0,  // 'B'
      0, 112, 136, 128, 128, 128, 136, 112,   0,   0,  // 'C'
      0, 240, 136, 136, 136, 136, 136, 240,   0,   0,  // 'D'
      0, 248, 128, 128, 240, 128, 128, 248,   0,   0,  // 'E'
      0, 248, 128, 128, 240, 128, 128, 128,   0,   0,  // 'F'
      0, 112, 136, 128, 184, 136, 152, 104,   0,   0,  // 'G'
      0, 136, 136, 136, 248, 136, 136, 136,   0,   0,  // 'H'
      0, 128, 128, 128, 128, 128, 128, 128,   0,   0,  // 'I'
      0,  16,  16,  16,  16,  16, 144,  96,   0,   0,  // 'J'
      0, 136, 144, 160, 192, 160, 144, 136,   0,   0,  // 'K'
      0, 128, 128, 128, 128, 128, 128, 240,   0,   0,  // 'L'
      0, 130, 198, 170, 146, 130, 130, 130,   0,   0,  // 'M'
      0, 136, 200, 168, 168, 168, 152, 136,   0,   0,  // 'N'
      0, 112, 136, 136, 136, 136, 136, 112,   0,   0,  // 'O'
      0, 240, 136, 136, 240, 128, 128, 128,   0,   0,  // 'P'
      0, 112, 136, 136, 136, 136, 136, 112,   8,   0,  // 'Q'
      0, 240, 136, 136, 240, 160, 144, 136,   0,   0,  // 'R'
      0, 112, 136, 128, 112,   8, 136, 112,   0,   0,  // 'S'
      0, 248,  32,  32,  32,  32,  32,  32,   0,   0,  // 'T'
      0, 136, 136, 136, 136, 136, 136, 112,   0,   0,  // 'U'
      0, 136, 136,  80,  80,  80,  32,  32,   0,   0,  // 'V'
      0, 146, 146, 146, 146, 146, 146, 108,   0,   0,  // 'W'
      0, 136, 136,  80,  32,  80, 136, 136,   0,   0,  // 'X'
      0, 136, 136,  80,  32,  32,  32,  32,   0,   0,  // 'Y'
      0, 248,   8,  16,  32,  64, 128, 248,   0,   0,  // 'Z'
    224, 128, 128, 128, 128, 128, 128, 128, 224,   0,  // '['
    128, 128,  64,  64,  32,  16,  16,   8,   8,   0,  // '\'
    224,  32,  32,  32,  32,  32,  32,  32, 224,   0,  // ']'
      0,  64, 160,   0,   0,   0,   0,   0,   0,   0,  // '^'
      0,   0,   0,   0,   0,   0,   0, 224,   0,   0,  // '_'
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // '`'
      0,   0,   0, 112, 144, 144, 176,  80,   0,   0,  // 'a'
      0, 128, 128, 160, 208, 144, 144, 224,   0,   0,  // 'b'
      0,   0,   0,  96, 144, 128, 144,  96,   0,   0,  // 'c'
      0,  16,  16, 112, 144, 144, 176,  80,   0,   0,  // 'd'
      0,   0,   0,  96, 144, 240, 128,  96,   0,   0,  // 'e'
      0,  96, 128, 192, 128, 128, 128, 128,   0,   0,  // 'f'
      0,   0,   0, 112, 144, 144, 176,  80,  16,  96,  // 'g'
      0, 128, 128, 160, 208, 144, 144, 144,   0,   0,  // 'h'
      0, 128,   0, 128, 128, 128, 128, 128,   0,   0,  // 'i'
      0, 128,   0, 128, 128, 128, 128, 128, 128,   0,  // 'j'
      0, 128, 128, 144, 160, 192, 160, 144,   0,   0,  // 'k'
      0, 128, 128, 128, 128, 128, 128, 128,   0,   0,  // 'l'
      0,   0,   0, 164, 218, 146, 146, 146,   0,   0,  // 'm'
      0,   0,   0, 160, 208, 144, 144, 144,   0,   0,  // 'n'
      0,   0,   0,  96, 144, 144, 144,  96,   0,   0,  // 'o'
      0,   0,   0, 160, 208, 144, 144, 224, 128, 128,  // 'p'
      0,   0,   0, 112, 144, 144, 176,  80,  16,  16,  // 'q'
      0,   0,   0, 160, 192, 128, 128, 128,   0,   0,  // 'r'
      0,   0,   0,  96, 128,  64,  32, 192,   0,   0,  // 's'
      0,  64,  64, 224,  64,  64,  64,  64,   0,   0,  // 't'
      0,   0,   0, 144, 144, 144, 176,  80,   0,   0,  // 'u'
      0,   0,   0, 144, 144, 144, 144,  96,   0,   0,  // 'v'
      0,   0,   0, 146, 146, 146, 146, 108,   0,   0,  // 'w'
      0,   0,   0, 144, 144,  96, 144, 144,   0,   0,  // 'x'
      0,   0,   0, 144, 144, 144, 176,  80,  16,  96,  // 'y'
      0,   0,   0, 224,  32,  64, 128, 224,   0,   0,  // 'z'
     32,  64,  64,  64, 128,  64,  64,  64,  32,   0,  // '{'
    128, 128, 128, 128, 128, 128, 128, 128, 128,   0,  // '|'
    128,  64,  64,  64,  32,  64,  64,  64, 128,   0,  // '}'
      0,  80, 160,   0,   0,   0,   0,   0,   0,   0,  // '~'
];

const FONT_ADVANCES: [u8 * 95] = [
    3 /*   */, 3 /* ! */, 4 /* " */, 6 /* # */, 6 /* $ */, 8 /* % */, 6 /* & */, 2 /* ' */,
    4 /* ( */, 4 /* ) */, 6 /* * */, 6 /* + */, 3 /* , */, 4 /* - */, 3 /* . */, 5 /* / */,
    6 /* 0 */, 3 /* 1 */, 6 /* 2 */, 6 /* 3 */, 6 /* 4 */, 6 /* 5 */, 6 /* 6 */, 6 /* 7 */,
    6 /* 8 */, 6 /* 9 */, 3 /* : */, 3 /* ; */, 4 /* < */, 4 /* = */, 4 /* > */, 6 /* ? */,
    8 /* @ */, 6 /* A */, 6 /* B */, 6 /* C */, 6 /* D */, 6 /* E */, 6 /* F */, 6 /* G */,
    6 /* H */, 2 /* I */, 5 /* J */, 6 /* K */, 5 /* L */, 8 /* M */, 6 /* N */, 6 /* O */,
    6 /* P */, 6 /* Q */, 6 /* R */, 6 /* S */, 6 /* T */, 6 /* U */, 6 /* V */, 8 /* W */,
    6 /* X */, 6 /* Y */, 6 /* Z */, 4 /* [ */, 6 /* \ */, 4 /* ] */, 4 /* ^ */, 4 /* _ */,
    3 /* ` */, 5 /* a */, 5 /* b */, 5 /* c */, 5 /* d */, 5 /* e */, 3 /* f */, 5 /* g */,
    5 /* h */, 2 /* i */, 2 /* j */, 5 /* k */, 2 /* l */, 8 /* m */, 5 /* n */, 5 /* o */,
    5 /* p */, 5 /* q */, 4 /* r */, 4 /* s */, 4 /* t */, 5 /* u */, 5 /* v */, 8 /* w */,
    5 /* x */, 5 /* y */, 4 /* z */, 4 /* { */, 2 /* | */, 4 /* } */, 5 /* ~ */,
];

//
// Screen scaling
//

pub enum Scale {
    Scale1x,
    Scale2x,
    Scale3x,
}

impl Scale {
    fn factor(self) -> uint { match self { Scale1x => 1, Scale2x => 2, Scale3x => 3 } }
}

pub struct Gfx {
    screen: ~Surface,
    scale: Scale,
}

macro_rules! scaler(
    ($count:expr, $pixels:ident, $ppu_screen:ident) => (
        // Type safety goes out the window when we're in a performance critical loop
        // like this!

        unsafe {
            let mut dest: *mut u32 = transmute(&$pixels[0]);
            let mut src_start: *u8 = transmute(&$ppu_screen[0]);

            let mut src_y = 0;
            while src_y < SCREEN_HEIGHT {
                let src_scanline_start = src_start.offset(src_y * SCREEN_WIDTH * 3);
                let src_scanline_end = src_scanline_start.offset(SCREEN_WIDTH * 3);

                // Ugh, LLVM isn't inlining properly.
                //
                // FIXME: Mark for loop bodies as always inline in rustc.
                let mut repeat_y = 0;
                while repeat_y < $count {
                    let mut src = src_scanline_start;
                    while src < src_scanline_end {
                        let r = *src as u32; src = src.offset(1);
                        let g = *src as u32; src = src.offset(1);
                        let b = *src as u32; src = src.offset(1);
                        let pixel = (r << 24) | (g << 16) | (b << 8);

                        let mut repeat_x = 0;
                        while repeat_x < $count {
                            *dest = pixel; dest = dest.offset(1);
                            repeat_x += 1;
                        }
                    }
                    repeat_y += 1;
                }
                src_y += 1;
            }
        }
    )
)

//
// Main graphics routine
//

impl Gfx {
    static pub fn new(scale: Scale) -> Gfx {
        sdl::init([ InitVideo, InitAudio, InitTimer ]);
        let screen = video::set_video_mode(SCREEN_WIDTH * scale.factor() as int,
                                           SCREEN_HEIGHT * scale.factor()  as int,
                                           32,
                                           [ SWSurface ],
                                           []);

        Gfx { screen: screen.unwrap(), scale: scale }
    }

    pub fn blit(&self, ppu_screen: &([u8 * 184320])) {
        do self.screen.with_lock |pixels| {
            match self.scale {
                Scale1x => scaler!(1, pixels, ppu_screen),
                Scale2x => scaler!(2, pixels, ppu_screen),
                Scale3x => scaler!(3, pixels, ppu_screen),
            }
        }
    }
}

<|endoftext|>