<commit_before>use redox::ops::DerefMut;
use redox::string::*;
use redox::vec::Vec;
use redox::boxed::Box;
use redox::fs::*;
use redox::io::*;
use redox::env::*;
use redox::time::Duration;
use redox::to_num::*;

/* Magic Macros { */
static mut application: *mut Application<'static> = 0 as *mut Application;

/// Execute a command
macro_rules! exec {
    ($cmd:expr) => ({
        unsafe {
            (*application).on_command(&$cmd.to_string());
        }
    })
}
/* } Magic Macros */

/// A command
pub struct Command<'a> {
    pub name: &'a str,
    pub main: Box<Fn(&Vec<String>)>,
}

impl<'a> Command<'a> {
    /// Return the vector of the commands
    // TODO: Use a more efficient collection instead
    pub fn vec() -> Vec<Self> {
        let mut commands: Vec<Self> = Vec::new();

        commands.push(Command {
            name: "cat",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read: {}", path),
                    }
                } else {
                    println!("Failed to open file: {}", path);
                }
            },
        });

        commands.push(Command {
            name: "cd",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(path) => {
                        if !change_cwd(&path) {
                            println!("Bad path: {}", path);
                        }
                    }
                    None => println!("No path given")
                }
            },
        });

        commands.push(Command {
            name: "echo",
            main: box |args: &Vec<String>| {
                let echo = args.iter()
                    .skip(1)
                    .fold(String::new(), |string, arg| string + " " + arg);
                println!("{}", echo.trim());
            },
        });

        commands.push(Command {
            name: "exec",
            main: box |args: &Vec<String>| {
                if let Some(arg) = args.get(1) {
                    File::exec(arg);
                }
            },
        });

        commands.push(Command {
            name: "exit",
            main: box |_: &Vec<String>| {
            },
        });

        commands.push(Command {
            name: "ls",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(dir) = read_dir(&path) {
                    for entry in dir {
                        println!("{}", entry.path());
                    }
                } else {
                    println!("Failed to open directory: {}", path);
                }
            }
        });

        commands.push(Command {
            name: "run",
            main: box |args: &Vec<String>| {
                if let Some(path) = args.get(1) {

                    let mut commands = String::new();
                    if let Some(mut file) = File::open(path) {
                        println!("URL: {:?}", file.path());

                        file.read_to_string(&mut commands);
                    }

                    for command in commands.split('\n') {
                        exec!(command);
                    }
                }
            },
        });

        commands.push(Command {
            name: "pwd",
            main: box |_: &Vec<String>| {
                let mut err = false;
                if let Some(file) = File::open("") {
                    if let Some(path) = file.path() {
                        println!("{}", path);
                    } else {
                        err = true;
                    }
                } else {
                    err = true;
                }
                if err {
                    println!("Could not get the path");
                }
            },
        });

        commands.push(Command {
            name: "sleep",
            main: box |args: &Vec<String>| {
                let secs = {
                    match args.get(1) {
                        Some(arg) => arg.to_num() as i64,
                        None => 0,
                    }
                };

                let nanos = {
                    match args.get(2) {
                        Some(arg) => arg.to_num() as i32,
                        None => 0,
                    }
                };

                println!("Sleep: {} {}", secs, nanos);
                let remaining = Duration::new(secs, nanos).sleep();
                println!("Remaining: {} {}", remaining.secs, remaining.nanos);
            },
        });

        commands.push(Command {
            name: "send",
            main: box |args: &Vec<String>| {
                if args.len() < 3 {
                    println!("Error: incorrect arguments");
                    println!("Usage: send [url] [data]");
                    return;
                }

                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let string: String = args.iter()
                        .skip(2)
                        .fold(String::new(), |s, arg| s + " " + arg)
                        + "\r\n\r\n";

                    match file.write(string.trim_left().as_bytes()) {
                        Some(size) => println!("Wrote {} bytes", size),
                        None => println!("Failed to write"),
                    }

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "test_ht",
            main: box |_: &Vec<String>| {
                ::redox::hashmap::test();
            },
        });

        commands.push(Command {
            name: "url_hex",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut vec: Vec<u8> = Vec::new();
                    match file.read_to_end(&mut vec) {
                        Some(_) => {
                            let mut line = "HEX:".to_string();
                            for byte in vec.iter() {
                                line = line + " " + &format!("{:X}", *byte);
                            }
                            println!("{}", line);
                        }
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "wget",
            main: box |args: &Vec<String>| {
                if let Some(host) = args.get(1) {
                    if let Some(req) = args.get(2) {
                        if let Some(mut con) = File::open(&("tcp://".to_string() + host)) {
                            con.write(("GET ".to_string() + req + " HTTP/1.1").as_bytes());

                            let mut res = Vec::new();
                            con.read_to_end(&mut res);

                            if let Some(mut file) = File::open(&req) {
                                file.write(&res);
                            }
                        }
                    } else {
                        println!("No request given");
                    }
                } else {
                    println!("No url given");
                }
            },
        });

        let command_list = commands.iter().fold(String::new(), |l , c| l + " " + c.name);

        commands.push(Command {
            name: "help",
            main: box move |_: &Vec<String>| {
                println!("Commands:{}", command_list);
            },
         });

        commands
    }
}

/// A (env) variable
pub struct Variable {
    pub name: String,
    pub value: String,
}

pub struct Mode {
    value: bool,
}

/// An application
pub struct Application<'a> {
    commands: Vec<Command<'a>>,
    variables: Vec<Variable>,
    modes: Vec<Mode>,
}

impl<'a> Application<'a> {
    /// Create a new empty application
    pub fn new() -> Self {
        return Application {
            commands: Command::vec(),
            variables: Vec::new(),
            modes: Vec::new(),
        };
    }

    fn on_command(&mut self, command_string: &str) {
        //Comment
        if command_string.starts_with('#') {
            return;
        }

        //Show variables
        if command_string == "$" {
            let variables = self.variables.iter()
                .fold(String::new(),
                      |string, variable| string + "\n" + &variable.name + "=" + &variable.value);
            println!("{}", variables);
            return;
        }

        //Explode into arguments, replace variables
        let mut args: Vec<String> = Vec::<String>::new();
        for arg in command_string.split(' ') {
            if !arg.is_empty() {
                if arg.starts_with('$') {
                    let name = arg[1 .. arg.len()].to_string();
                    for variable in self.variables.iter() {
                        if variable.name == name {
                            args.push(variable.value.clone());
                            break;
                        }
                    }
                } else {
                    args.push(arg.to_string());
                }
            }
        }

        //Execute commands
        if let Some(cmd) = args.get(0) {
            if cmd == "if" {
                let mut value = false;

                if let Some(left) = args.get(1) {
                    if let Some(cmp) = args.get(2) {
                        if let Some(right) = args.get(3) {
                            if cmp == "==" {
                                value = *left == *right;
                            } else if cmp == "!=" {
                                value = *left != *right;
                            } else if cmp == ">" {
                                value = left.to_num_signed() > right.to_num_signed();
                            } else if cmp == ">=" {
                                value = left.to_num_signed() >= right.to_num_signed();
                            } else if cmp == "<" {
                                value = left.to_num_signed() < right.to_num_signed();
                            } else if cmp == "<=" {
                                value = left.to_num_signed() <= right.to_num_signed();
                            } else {
                                println!("Unknown comparison: {}", cmp);
                            }
                        }
                    }
                }

                self.modes.insert(0, Mode { value: value });
                return;
            }

            if cmd == "else" {
                let mut syntax_error = false;
                match self.modes.get_mut(0) {
                    Some(mode) => mode.value = !mode.value,
                    None => syntax_error = true,
                }
                if syntax_error {
                    println!("Syntax error: else found with no previous if");
                }
                return;
            }

            if cmd == "fi" {
                let mut syntax_error = false;
                if !self.modes.is_empty() {
                    self.modes.remove(0);
                } else {
                    syntax_error = true;
                }
                if syntax_error {
                    println!("Syntax error: fi found with no previous if");
                }
                return;
            }

            for mode in self.modes.iter() {
                if !mode.value {
                    return;
                }
            }

            //Set variables
            if let Some(i) = cmd.find('=') {
                let name = cmd[0 .. i].to_string();
                let mut value = cmd[i + 1 .. cmd.len()].to_string();

                if name.is_empty() {
                    return;
                }

                for i in 1..args.len() {
                    if let Some(arg) = args.get(i) {
                        value = value + " " + &arg;
                    }
                }

                if value.is_empty() {
                    let mut remove = -1;
                    for i in 0..self.variables.len() {
                        match self.variables.get(i) {
                            Some(variable) => if variable.name == name {
                                remove = i as isize;
                                break;
                            },
                            None => break,
                        }
                    }

                    if remove >= 0 {
                        self.variables.remove(remove as usize);
                    }
                } else {
                    for variable in self.variables.iter_mut() {
                        if variable.name == name {
                            variable.value = value;
                            return;
                        }
                    }

                    self.variables.push(Variable {
                        name: name,
                        value: value,
                    });
                }
                return;
            }

            //Commands
            for command in self.commands.iter() {
                if &command.name == cmd {
                    (*command.main)(&args);
                    return;
                }
            }

            println!("Unknown command: '{}'", cmd);
        }
    }

    /// Run the application
    pub fn main(&mut self) {
        println!("Type help for a command list");
        if let Some(arg) = args().get(1) {
            let command = "run ".to_string() + arg;
            println!("# {}", command);
            self.on_command(&command);
        }

        loop {
            print!("# ");
            if let Some(command_original) = readln!() {
                let command = command_original.trim();
                if command == "exit" {
                    println!("Exit temporarily blocked (due to using terminal as init)")
                    //break;
                } else if !command.is_empty() {
                    self.on_command(&command);
                }
            } else {
                println!("Failed to read from stdin");
            }
        }
    }
}

pub fn main() {
    unsafe {
        let mut app = box Application::new();
        application = app.deref_mut();
        app.main();
    }
}
<commit_msg>Show current mode<commit_after>use redox::ops::DerefMut;
use redox::string::*;
use redox::vec::Vec;
use redox::boxed::Box;
use redox::fs::*;
use redox::io::*;
use redox::env::*;
use redox::time::Duration;
use redox::to_num::*;

/* Magic Macros { */
static mut application: *mut Application<'static> = 0 as *mut Application;

/// Execute a command
macro_rules! exec {
    ($cmd:expr) => ({
        unsafe {
            (*application).on_command(&$cmd.to_string());
        }
    })
}
/* } Magic Macros */

/// A command
pub struct Command<'a> {
    pub name: &'a str,
    pub main: Box<Fn(&Vec<String>)>,
}

impl<'a> Command<'a> {
    /// Return the vector of the commands
    // TODO: Use a more efficient collection instead
    pub fn vec() -> Vec<Self> {
        let mut commands: Vec<Self> = Vec::new();

        commands.push(Command {
            name: "cat",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read: {}", path),
                    }
                } else {
                    println!("Failed to open file: {}", path);
                }
            },
        });

        commands.push(Command {
            name: "cd",
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(path) => {
                        if !change_cwd(&path) {
                            println!("Bad path: {}", path);
                        }
                    }
                    None => println!("No path given")
                }
            },
        });

        commands.push(Command {
            name: "echo",
            main: box |args: &Vec<String>| {
                let echo = args.iter()
                    .skip(1)
                    .fold(String::new(), |string, arg| string + " " + arg);
                println!("{}", echo.trim());
            },
        });

        commands.push(Command {
            name: "exec",
            main: box |args: &Vec<String>| {
                if let Some(arg) = args.get(1) {
                    File::exec(arg);
                }
            },
        });

        commands.push(Command {
            name: "exit",
            main: box |_: &Vec<String>| {
            },
        });

        commands.push(Command {
            name: "ls",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(dir) = read_dir(&path) {
                    for entry in dir {
                        println!("{}", entry.path());
                    }
                } else {
                    println!("Failed to open directory: {}", path);
                }
            }
        });

        commands.push(Command {
            name: "run",
            main: box |args: &Vec<String>| {
                if let Some(path) = args.get(1) {

                    let mut commands = String::new();
                    if let Some(mut file) = File::open(path) {
                        file.read_to_string(&mut commands);
                    }

                    for command in commands.split('\n') {
                        exec!(command);
                    }
                }
            },
        });

        commands.push(Command {
            name: "pwd",
            main: box |_: &Vec<String>| {
                let mut err = false;
                if let Some(file) = File::open("") {
                    if let Some(path) = file.path() {
                        println!("{}", path);
                    } else {
                        err = true;
                    }
                } else {
                    err = true;
                }
                if err {
                    println!("Could not get the path");
                }
            },
        });

        commands.push(Command {
            name: "sleep",
            main: box |args: &Vec<String>| {
                let secs = {
                    match args.get(1) {
                        Some(arg) => arg.to_num() as i64,
                        None => 0,
                    }
                };

                let nanos = {
                    match args.get(2) {
                        Some(arg) => arg.to_num() as i32,
                        None => 0,
                    }
                };

                println!("Sleep: {} {}", secs, nanos);
                let remaining = Duration::new(secs, nanos).sleep();
                println!("Remaining: {} {}", remaining.secs, remaining.nanos);
            },
        });

        commands.push(Command {
            name: "send",
            main: box |args: &Vec<String>| {
                if args.len() < 3 {
                    println!("Error: incorrect arguments");
                    println!("Usage: send [url] [data]");
                    return;
                }

                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let string: String = args.iter()
                        .skip(2)
                        .fold(String::new(), |s, arg| s + " " + arg)
                        + "\r\n\r\n";

                    match file.write(string.trim_left().as_bytes()) {
                        Some(size) => println!("Wrote {} bytes", size),
                        None => println!("Failed to write"),
                    }

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "test_ht",
            main: box |_: &Vec<String>| {
                ::redox::hashmap::test();
            },
        });

        commands.push(Command {
            name: "url_hex",
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    let mut vec: Vec<u8> = Vec::new();
                    match file.read_to_end(&mut vec) {
                        Some(_) => {
                            let mut line = "HEX:".to_string();
                            for byte in vec.iter() {
                                line = line + " " + &format!("{:X}", *byte);
                            }
                            println!("{}", line);
                        }
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "wget",
            main: box |args: &Vec<String>| {
                if let Some(host) = args.get(1) {
                    if let Some(req) = args.get(2) {
                        if let Some(mut con) = File::open(&("tcp://".to_string() + host)) {
                            con.write(("GET ".to_string() + req + " HTTP/1.1").as_bytes());

                            let mut res = Vec::new();
                            con.read_to_end(&mut res);

                            if let Some(mut file) = File::open(&req) {
                                file.write(&res);
                            }
                        }
                    } else {
                        println!("No request given");
                    }
                } else {
                    println!("No url given");
                }
            },
        });

        let command_list = commands.iter().fold(String::new(), |l , c| l + " " + c.name);

        commands.push(Command {
            name: "help",
            main: box move |_: &Vec<String>| {
                println!("Commands:{}", command_list);
            },
         });

        commands
    }
}

/// A (env) variable
pub struct Variable {
    pub name: String,
    pub value: String,
}

pub struct Mode {
    value: bool,
}

/// An application
pub struct Application<'a> {
    commands: Vec<Command<'a>>,
    variables: Vec<Variable>,
    modes: Vec<Mode>,
}

impl<'a> Application<'a> {
    /// Create a new empty application
    pub fn new() -> Self {
        return Application {
            commands: Command::vec(),
            variables: Vec::new(),
            modes: Vec::new(),
        };
    }

    fn on_command(&mut self, command_string: &str) {
        //Comment
        if command_string.starts_with('#') {
            return;
        }

        //Show variables
        if command_string == "$" {
            let variables = self.variables.iter()
                .fold(String::new(),
                      |string, variable| string + "\n" + &variable.name + "=" + &variable.value);
            println!("{}", variables);
            return;
        }

        //Explode into arguments, replace variables
        let mut args: Vec<String> = Vec::<String>::new();
        for arg in command_string.split(' ') {
            if !arg.is_empty() {
                if arg.starts_with('$') {
                    let name = arg[1 .. arg.len()].to_string();
                    for variable in self.variables.iter() {
                        if variable.name == name {
                            args.push(variable.value.clone());
                            break;
                        }
                    }
                } else {
                    args.push(arg.to_string());
                }
            }
        }

        //Execute commands
        if let Some(cmd) = args.get(0) {
            if cmd == "if" {
                let mut value = false;

                if let Some(left) = args.get(1) {
                    if let Some(cmp) = args.get(2) {
                        if let Some(right) = args.get(3) {
                            if cmp == "==" {
                                value = *left == *right;
                            } else if cmp == "!=" {
                                value = *left != *right;
                            } else if cmp == ">" {
                                value = left.to_num_signed() > right.to_num_signed();
                            } else if cmp == ">=" {
                                value = left.to_num_signed() >= right.to_num_signed();
                            } else if cmp == "<" {
                                value = left.to_num_signed() < right.to_num_signed();
                            } else if cmp == "<=" {
                                value = left.to_num_signed() <= right.to_num_signed();
                            } else {
                                println!("Unknown comparison: {}", cmp);
                            }
                        }
                    }
                }

                self.modes.insert(0, Mode { value: value });
                return;
            }

            if cmd == "else" {
                let mut syntax_error = false;
                match self.modes.get_mut(0) {
                    Some(mode) => mode.value = !mode.value,
                    None => syntax_error = true,
                }
                if syntax_error {
                    println!("Syntax error: else found with no previous if");
                }
                return;
            }

            if cmd == "fi" {
                let mut syntax_error = false;
                if !self.modes.is_empty() {
                    self.modes.remove(0);
                } else {
                    syntax_error = true;
                }
                if syntax_error {
                    println!("Syntax error: fi found with no previous if");
                }
                return;
            }

            for mode in self.modes.iter() {
                if !mode.value {
                    return;
                }
            }

            //Set variables
            if let Some(i) = cmd.find('=') {
                let name = cmd[0 .. i].to_string();
                let mut value = cmd[i + 1 .. cmd.len()].to_string();

                if name.is_empty() {
                    return;
                }

                for i in 1..args.len() {
                    if let Some(arg) = args.get(i) {
                        value = value + " " + &arg;
                    }
                }

                if value.is_empty() {
                    let mut remove = -1;
                    for i in 0..self.variables.len() {
                        match self.variables.get(i) {
                            Some(variable) => if variable.name == name {
                                remove = i as isize;
                                break;
                            },
                            None => break,
                        }
                    }

                    if remove >= 0 {
                        self.variables.remove(remove as usize);
                    }
                } else {
                    for variable in self.variables.iter_mut() {
                        if variable.name == name {
                            variable.value = value;
                            return;
                        }
                    }

                    self.variables.push(Variable {
                        name: name,
                        value: value,
                    });
                }
                return;
            }

            //Commands
            for command in self.commands.iter() {
                if &command.name == cmd {
                    (*command.main)(&args);
                    return;
                }
            }

            println!("Unknown command: '{}'", cmd);
        }
    }

    /// Run the application
    pub fn main(&mut self) {
        println!("Type help for a command list");
        if let Some(arg) = args().get(1) {
            let command = "run ".to_string() + arg;
            println!("# {}", command);
            self.on_command(&command);
        }

        loop {
            for mode in self.modes.iter().rev() {
                if mode.value {
                    print!("+");
                } else {
                    print!("-");
                }
            }
            print!("# ");
            if let Some(command_original) = readln!() {
                let command = command_original.trim();
                if command == "exit" {
                    println!("Exit temporarily blocked (due to using terminal as init)")
                    //break;
                } else if !command.is_empty() {
                    self.on_command(&command);
                }
            } else {
                println!("Failed to read from stdin");
            }
        }
    }
}

pub fn main() {
    unsafe {
        let mut app = box Application::new();
        application = app.deref_mut();
        app.main();
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use data_encoding::BASE64;
use reqwest::header::{self, HeaderMap, HeaderValue};
use reqwest::Client;
use serde_json;

pub use reqwest::Response;

use errors::SendgridResult;

const V3_API_URL: &str = "https://api.sendgrid.com/v3/mail/send";

/// Just a redefinition of a map to store string keys and values.
pub type SGMap = HashMap<String, String>;

/// Used to send a V3 message body.
pub struct V3Sender {
    api_key: String,
}

/// The main structure for a V3 API mail send call. This is composed of many other smaller
/// structures used to add lots of customization to your message.
#[derive(Default, Serialize)]
pub struct SGMailV3 {
    from: Email,
    subject: String,
    personalizations: Vec<Personalization>,

    #[serde(skip_serializing_if = "Option::is_none")]
    content: Option<Vec<Content>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    attachments: Option<Vec<Attachment>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    template_id: Option<String>,
}

/// An email with a required address and an optional name field.
#[derive(Clone, Default, Serialize)]
pub struct Email {
    email: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    name: Option<String>,
}

/// The body of an email with the content type and the message.
#[derive(Clone, Default, Serialize)]
pub struct Content {
    #[serde(rename = "type")]
    content_type: String,
    value: String,
}

/// A personalization block for a V3 message. It has to at least contain one email as a to
/// address. All other fields are optional.
#[derive(Default, Serialize)]
pub struct Personalization {
    to: Vec<Email>,

    #[serde(skip_serializing_if = "Option::is_none")]
    cc: Option<Vec<Email>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    bcc: Option<Vec<Email>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    subject: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    headers: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    substitutions: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    custom_args: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    dynamic_template_data: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    send_at: Option<u64>,
}

/// An attachment block for a V3 message. Content and filename are required. If the
/// mime_type is unspecified, the email will use Sendgrid's default for attachments
/// which is 'application/octet-stream'.
#[derive(Default, Serialize)]
pub struct Attachment {
    content: String,

    filename: String,

    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
    mime_type: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    disposition: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    content_id: Option<String>,
}

impl V3Sender {
    /// Construct a new V3 message sender.
    pub fn new(api_key: String) -> V3Sender {
        V3Sender { api_key }
    }

    /// Send a V3 message and return the status code or an error from the request.
    pub fn send(&self, mail: &SGMailV3) -> SendgridResult<Response> {
        let client = Client::new();
        let mut headers = HeaderMap::new();
        headers.insert(
            header::AUTHORIZATION,
            HeaderValue::from_str(&format!("Bearer {}", self.api_key.clone()))?,
        );
        headers.insert(
            header::CONTENT_TYPE,
            HeaderValue::from_static("application/json"),
        );
        headers.insert(header::USER_AGENT, HeaderValue::from_static("sendgrid-rs"));

        let body = mail.gen_json();
        let res = client.post(V3_API_URL).headers(headers).body(body).send()?;
        Ok(res)
    }
}

impl SGMailV3 {
    /// Construct a new V3 message.
    pub fn new() -> SGMailV3 {
        SGMailV3::default()
    }

    /// Set the from address.
    pub fn set_from(&mut self, from: Email) {
        self.from = from;
    }

    /// Set the subject.
    pub fn set_subject(&mut self, subject: &str) {
        self.subject = String::from(subject);
    }

    /// Set the template id.
    pub fn set_template_id(&mut self, template_id: &str) {
        self.template_id = Some(String::from(template_id));
    }

    /// Add content to the message.
    pub fn add_content(&mut self, c: Content) {
        match self.content {
            None => {
                let mut content = Vec::new();
                content.push(c);
                self.content = Some(content);
            }
            Some(ref mut content) => content.push(c),
        };
    }

    /// Add a personalization to the message.
    pub fn add_personalization(&mut self, p: Personalization) {
        self.personalizations.push(p);
    }

    /// Add an attachment to the message.
    pub fn add_attachment(&mut self, a: Attachment) {
        match self.attachments {
            None => {
                let mut attachments = Vec::new();
                attachments.push(a);
                self.attachments = Some(attachments);
            }
            Some(ref mut attachments) => attachments.push(a),
        };
    }

    fn gen_json(&self) -> String {
        serde_json::to_string(self).unwrap()
    }
}

impl Email {
    /// Construct a new email type.
    pub fn new() -> Email {
        Email::default()
    }

    /// Set the address for this email.
    pub fn set_email(&mut self, email: &str) {
        self.email = String::from(email);
    }

    /// Set an optional name.
    pub fn set_name(&mut self, name: &str) {
        self.name = Some(String::from(name));
    }
}

impl Content {
    /// Construct a new content type.
    pub fn new() -> Content {
        Content::default()
    }

    /// Set the type of this content.
    pub fn set_content_type(&mut self, content_type: &str) {
        self.content_type = String::from(content_type);
    }

    /// Set the corresponding message for this content.
    pub fn set_value(&mut self, value: &str) {
        self.value = String::from(value);
    }
}

impl Personalization {
    /// Construct a new personalization block for this message.
    pub fn new() -> Personalization {
        Personalization::default()
    }

    /// Add a to field.
    pub fn add_to(&mut self, to: Email) {
        self.to.push(to);
    }

    /// Add a CC field.
    pub fn add_cc(&mut self, cc: Email) {
        match self.cc {
            None => {
                let mut ccs = Vec::new();
                ccs.push(cc);
                self.cc = Some(ccs);
            }
            Some(ref mut c) => {
                c.push(cc);
            }
        }
    }

    /// Add a BCC field.
    pub fn add_bcc(&mut self, bcc: Email) {
        match self.bcc {
            None => {
                let mut bccs = Vec::new();
                bccs.push(bcc);
                self.bcc = Some(bccs);
            }
            Some(ref mut b) => {
                b.push(bcc);
            }
        }
    }

    /// Add a headers field.
    pub fn add_headers(&mut self, headers: SGMap) {
        match self.headers {
            None => {
                let mut h = HashMap::new();
                for (name, value) in headers {
                    h.insert(name, value);
                }
                self.headers = Some(h);
            }
            Some(ref mut h) => {
                h.extend(headers);
            }
        }
    }

    /// Add a dynamic template data field.
    pub fn add_dynamic_template_data(&mut self, headers: SGMap) {
        match self.dynamic_template_data {
            None => {
                let mut h = HashMap::new();
                for (name, value) in headers {
                    h.insert(name, value);
                }
                self.headers = Some(h);
            }
            Some(ref mut h) => {
                h.extend(headers);
            }
        }
    }
}

impl Attachment {
    /// Construct a new attachment for this message.
    pub fn new() -> Attachment {
        Attachment::default()
    }

    /// The raw body of the attachment.
    pub fn set_content(&mut self, c: &[u8]) {
        self.content = BASE64.encode(c);
    }

    /// The base64 body of the attachment.
    pub fn set_base64_content(&mut self, c: &str) {
        self.content = String::from(c);
    }

    /// Sets the filename for the attachment.
    pub fn set_filename(&mut self, filename: &str) {
        self.filename = filename.into();
    }

    /// Set an optional mime type. Sendgrid will default to 'application/octet-stream'
    /// if unspecified.
    pub fn set_mime_type(&mut self, mime: &str) {
        self.mime_type = Some(String::from(mime));
    }
}
<commit_msg>v3: Fix dynamic template data assignment (#41)<commit_after>use std::collections::HashMap;

use data_encoding::BASE64;
use reqwest::header::{self, HeaderMap, HeaderValue};
use reqwest::Client;
use serde_json;

pub use reqwest::Response;

use errors::SendgridResult;

const V3_API_URL: &str = "https://api.sendgrid.com/v3/mail/send";

/// Just a redefinition of a map to store string keys and values.
pub type SGMap = HashMap<String, String>;

/// Used to send a V3 message body.
pub struct V3Sender {
    api_key: String,
}

/// The main structure for a V3 API mail send call. This is composed of many other smaller
/// structures used to add lots of customization to your message.
#[derive(Default, Serialize)]
pub struct SGMailV3 {
    from: Email,
    subject: String,
    personalizations: Vec<Personalization>,

    #[serde(skip_serializing_if = "Option::is_none")]
    content: Option<Vec<Content>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    attachments: Option<Vec<Attachment>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    template_id: Option<String>,
}

/// An email with a required address and an optional name field.
#[derive(Clone, Default, Serialize)]
pub struct Email {
    email: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    name: Option<String>,
}

/// The body of an email with the content type and the message.
#[derive(Clone, Default, Serialize)]
pub struct Content {
    #[serde(rename = "type")]
    content_type: String,
    value: String,
}

/// A personalization block for a V3 message. It has to at least contain one email as a to
/// address. All other fields are optional.
#[derive(Default, Serialize)]
pub struct Personalization {
    to: Vec<Email>,

    #[serde(skip_serializing_if = "Option::is_none")]
    cc: Option<Vec<Email>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    bcc: Option<Vec<Email>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    subject: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    headers: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    substitutions: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    custom_args: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    dynamic_template_data: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    send_at: Option<u64>,
}

/// An attachment block for a V3 message. Content and filename are required. If the
/// mime_type is unspecified, the email will use Sendgrid's default for attachments
/// which is 'application/octet-stream'.
#[derive(Default, Serialize)]
pub struct Attachment {
    content: String,

    filename: String,

    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
    mime_type: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    disposition: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    content_id: Option<String>,
}

impl V3Sender {
    /// Construct a new V3 message sender.
    pub fn new(api_key: String) -> V3Sender {
        V3Sender { api_key }
    }

    /// Send a V3 message and return the status code or an error from the request.
    pub fn send(&self, mail: &SGMailV3) -> SendgridResult<Response> {
        let client = Client::new();
        let mut headers = HeaderMap::new();
        headers.insert(
            header::AUTHORIZATION,
            HeaderValue::from_str(&format!("Bearer {}", self.api_key.clone()))?,
        );
        headers.insert(
            header::CONTENT_TYPE,
            HeaderValue::from_static("application/json"),
        );
        headers.insert(header::USER_AGENT, HeaderValue::from_static("sendgrid-rs"));

        let body = mail.gen_json();
        let res = client.post(V3_API_URL).headers(headers).body(body).send()?;
        Ok(res)
    }
}

impl SGMailV3 {
    /// Construct a new V3 message.
    pub fn new() -> SGMailV3 {
        SGMailV3::default()
    }

    /// Set the from address.
    pub fn set_from(&mut self, from: Email) {
        self.from = from;
    }

    /// Set the subject.
    pub fn set_subject(&mut self, subject: &str) {
        self.subject = String::from(subject);
    }

    /// Set the template id.
    pub fn set_template_id(&mut self, template_id: &str) {
        self.template_id = Some(String::from(template_id));
    }

    /// Add content to the message.
    pub fn add_content(&mut self, c: Content) {
        match self.content {
            None => {
                let mut content = Vec::new();
                content.push(c);
                self.content = Some(content);
            }
            Some(ref mut content) => content.push(c),
        };
    }

    /// Add a personalization to the message.
    pub fn add_personalization(&mut self, p: Personalization) {
        self.personalizations.push(p);
    }

    /// Add an attachment to the message.
    pub fn add_attachment(&mut self, a: Attachment) {
        match self.attachments {
            None => {
                let mut attachments = Vec::new();
                attachments.push(a);
                self.attachments = Some(attachments);
            }
            Some(ref mut attachments) => attachments.push(a),
        };
    }

    fn gen_json(&self) -> String {
        serde_json::to_string(self).unwrap()
    }
}

impl Email {
    /// Construct a new email type.
    pub fn new() -> Email {
        Email::default()
    }

    /// Set the address for this email.
    pub fn set_email(&mut self, email: &str) {
        self.email = String::from(email);
    }

    /// Set an optional name.
    pub fn set_name(&mut self, name: &str) {
        self.name = Some(String::from(name));
    }
}

impl Content {
    /// Construct a new content type.
    pub fn new() -> Content {
        Content::default()
    }

    /// Set the type of this content.
    pub fn set_content_type(&mut self, content_type: &str) {
        self.content_type = String::from(content_type);
    }

    /// Set the corresponding message for this content.
    pub fn set_value(&mut self, value: &str) {
        self.value = String::from(value);
    }
}

impl Personalization {
    /// Construct a new personalization block for this message.
    pub fn new() -> Personalization {
        Personalization::default()
    }

    /// Add a to field.
    pub fn add_to(&mut self, to: Email) {
        self.to.push(to);
    }

    /// Add a CC field.
    pub fn add_cc(&mut self, cc: Email) {
        match self.cc {
            None => {
                let mut ccs = Vec::new();
                ccs.push(cc);
                self.cc = Some(ccs);
            }
            Some(ref mut c) => {
                c.push(cc);
            }
        }
    }

    /// Add a BCC field.
    pub fn add_bcc(&mut self, bcc: Email) {
        match self.bcc {
            None => {
                let mut bccs = Vec::new();
                bccs.push(bcc);
                self.bcc = Some(bccs);
            }
            Some(ref mut b) => {
                b.push(bcc);
            }
        }
    }

    /// Add a headers field.
    pub fn add_headers(&mut self, headers: SGMap) {
        match self.headers {
            None => {
                let mut h = HashMap::new();
                for (name, value) in headers {
                    h.insert(name, value);
                }
                self.headers = Some(h);
            }
            Some(ref mut h) => {
                h.extend(headers);
            }
        }
    }

    /// Add a dynamic template data field.
    pub fn add_dynamic_template_data(&mut self, dynamic_template_data: SGMap) {
        match self.dynamic_template_data {
            None => {
                let mut h = HashMap::new();
                for (name, value) in dynamic_template_data {
                    h.insert(name, value);
                }
                self.dynamic_template_data = Some(h);
            }
            Some(ref mut h) => {
                h.extend(dynamic_template_data);
            }
        }
    }
}

impl Attachment {
    /// Construct a new attachment for this message.
    pub fn new() -> Attachment {
        Attachment::default()
    }

    /// The raw body of the attachment.
    pub fn set_content(&mut self, c: &[u8]) {
        self.content = BASE64.encode(c);
    }

    /// The base64 body of the attachment.
    pub fn set_base64_content(&mut self, c: &str) {
        self.content = String::from(c);
    }

    /// Sets the filename for the attachment.
    pub fn set_filename(&mut self, filename: &str) {
        self.filename = filename.into();
    }

    /// Set an optional mime type. Sendgrid will default to 'application/octet-stream'
    /// if unspecified.
    pub fn set_mime_type(&mut self, mime: &str) {
        self.mime_type = Some(String::from(mime));
    }
}
<|endoftext|>


<commit_before>use crate::graphics::prelude::*;
use itertools::Itertools;

//noinspection RsBorrowChecker,RsBorrowChecker
pub fn apply_matte(b: &mut BitmapWindowMut<u8>, matte_color: imageflow_types::Color) -> Result<(), FlowError>{
    // There's nothing to do unless it's BGRA
    if b.info().channels() != 4 || !b.info().alpha_meaningful() {
        return Ok(())
    }

    let colorcontext = ColorContext::new(WorkingFloatspace::LinearRGB,0f32);

    let matte = matte_color.to_color_32().map_err(|e| FlowError::from(e).at(here!()))?.to_bgra8();

    let alpha_to_float = (1.0f32) / 255.0f32;

    let matte_a = matte.a as f32 * alpha_to_float;
    let matte_b = colorcontext.srgb_to_floatspace(matte.b);
    let matte_g = colorcontext.srgb_to_floatspace(matte.g);
    let matte_r = colorcontext.srgb_to_floatspace(matte.r);

    for y in 0..b.h(){
        let mut row = b.row_window(y).unwrap();

        for mut pixel in row.slice_of_pixels().unwrap().iter_mut(){
            let pixel_a = (*pixel).a;
            let pixel_a_f32 = pixel_a as i32 as f32 * alpha_to_float;
            // if pixel_a == 0{
            //     *pixel = matte;
            // }else if pixel_a != 255{
                let matte_a = (1.0f32 - pixel_a_f32) * matte_a;
                let final_a: f32 = matte_a + pixel_a_f32;
                (*pixel).b = colorcontext.floatspace_to_srgb(
                    (colorcontext.srgb_to_floatspace(pixel.b) * pixel_a_f32 + matte_b * matte_a) / final_a);
                (*pixel).g = colorcontext.floatspace_to_srgb(
                    (colorcontext.srgb_to_floatspace(pixel.g) * pixel_a_f32 + matte_g * matte_a) / final_a);
                (*pixel).r = colorcontext.floatspace_to_srgb(
                    (colorcontext.srgb_to_floatspace(pixel.r) * pixel_a_f32 + matte_r * matte_a) / final_a);
                (*pixel).a =    uchar_clamp_ff(255f32 * final_a);
            //}
        }
    }

    Ok(())
}<commit_msg>Fixes #576 - terrible matte color performance including when converting from 32-bit png to jpeg<commit_after>use crate::graphics::prelude::*;
use itertools::Itertools;

//noinspection RsBorrowChecker,RsBorrowChecker
pub fn apply_matte(b: &mut BitmapWindowMut<u8>, matte_color: imageflow_types::Color) -> Result<(), FlowError>{
    // There's nothing to do unless it's BGRA
    if b.info().channels() != 4 || !b.info().alpha_meaningful() {
        return Ok(())
    }

    let colorcontext = ColorContext::new(WorkingFloatspace::LinearRGB,0f32);

    let matte = matte_color.to_color_32().map_err(|e| FlowError::from(e).at(here!()))?.to_bgra8();

    let alpha_to_float = (1.0f32) / 255.0f32;

    let matte_a = matte.a as f32 * alpha_to_float;
    let matte_b = colorcontext.srgb_to_floatspace(matte.b);
    let matte_g = colorcontext.srgb_to_floatspace(matte.g);
    let matte_r = colorcontext.srgb_to_floatspace(matte.r);

    for y in 0..b.h(){
        let mut row = b.row_window(y).unwrap();

        for mut pixel in row.slice_of_pixels().unwrap().iter_mut(){
            let pixel_a = (*pixel).a;
            let pixel_a_f32 = pixel_a as i32 as f32 * alpha_to_float;
            if pixel_a == 0{
                 *pixel = matte;
            }else if pixel_a != 255{
                let matte_a = (1.0f32 - pixel_a_f32) * matte_a;
                let final_a: f32 = matte_a + pixel_a_f32;
                (*pixel).b = colorcontext.floatspace_to_srgb(
                    (colorcontext.srgb_to_floatspace(pixel.b) * pixel_a_f32 + matte_b * matte_a) / final_a);
                (*pixel).g = colorcontext.floatspace_to_srgb(
                    (colorcontext.srgb_to_floatspace(pixel.g) * pixel_a_f32 + matte_g * matte_a) / final_a);
                (*pixel).r = colorcontext.floatspace_to_srgb(
                    (colorcontext.srgb_to_floatspace(pixel.r) * pixel_a_f32 + matte_r * matte_a) / final_a);
                (*pixel).a =    uchar_clamp_ff(255f32 * final_a);
            }
        }
    }

    Ok(())
}<|endoftext|>


<commit_before>//! Render to an SDL window

use frontend_api::FrontendAction;
use frontend_api::input::joypad::{JoypadImpl, JoypadState, JoypadButton};
use frontend_api::ppu::{SCREEN_WIDTH, SCREEN_HEIGHT};

use sdl2::{EventPump, Sdl};
use sdl2::event::WindowEventId;
use sdl2::keyboard::Scancode;
use sdl2::pixels::PixelFormatEnum;
use sdl2::render::{Renderer, Texture, TextureAccess};
use sdl2::rect::Rect;

use std::cell::RefCell;
use std::ops::Deref;

/// Takes care of SDL (mainly used for event management). Owns an `EventPump`, which makes it
/// unavailable for other code. Initialized when the emulator uses an SDL frontend.
struct SdlManager {
    sdl: Sdl,
    event_pump: EventPump,
    resized_to: Option<(u32, u32)>,
}

impl SdlManager {
    /// Updates all SDL-related state. Polls events and may terminate the process via
    /// `process::exit`. Should be called at least once per frame.
    fn update(&mut self) -> Option<FrontendAction> {
        use sdl2::event::Event::*;

        for event in self.event_pump.poll_iter() {
            match event {
                Quit { .. } => {
                    info!("quit event -> exiting");
                    return Some(FrontendAction::Exit);
                }
                Window { win_event_id: WindowEventId::Resized, data1: w, data2: h, .. } => {
                    info!("window resized to {}x{}", w, h);
                    self.resized_to = Some((w as u32, h as u32));
                }
                KeyDown { scancode: Some(Scancode::F5), .. } => {
                    return Some(FrontendAction::SaveState);
                }
                KeyDown { scancode: Some(Scancode::F9), .. } => {
                    return Some(FrontendAction::LoadState);
                }
                _ => {}
            }
        }

        if self.event_pump.keyboard_state().is_scancode_pressed(Scancode::LCtrl) {
            info!("<waiting>");
            for event in self.event_pump.wait_iter() {
                match event {
                    KeyUp { scancode: Some(Scancode::LCtrl), .. } => { break }
                    _ => {}
                }
            }
            info!("<running>");
        }

        None
    }

    fn resized(&mut self) -> Option<(u32, u32)> { self.resized_to.take() }
}

impl Deref for SdlManager {
    type Target = Sdl;
    fn deref(&self) -> &Sdl { &self.sdl }
}

thread_local! {
    static SDL: RefCell<SdlManager> = {
        let sdl = ::sdl2::init().unwrap();
        let pump = sdl.event_pump().unwrap();

        RefCell::new(SdlManager {
            sdl: sdl,
            event_pump: pump,
            resized_to: None,
        })
    }
}

pub struct SdlRenderer {
    renderer: Renderer<'static>,
    texture: Texture,
}

impl Default for SdlRenderer {
    fn default() -> Self {
        // FIXME: Support linear filtering and nearest neighbor

        SDL.with(|sdl_cell| {
            let sdl = sdl_cell.borrow_mut();
            let video = sdl.video().unwrap();
            let window = video.window("breeze", SCREEN_WIDTH * 3, SCREEN_HEIGHT * 3)
                .resizable()
                .build().unwrap();
            let renderer = window.renderer().accelerated().build().unwrap();
            let texture = renderer.create_texture(
                PixelFormatEnum::RGB24,
                TextureAccess::Static,
                (SCREEN_WIDTH, SCREEN_HEIGHT)).unwrap();

            let mut this = SdlRenderer {
                renderer: renderer,
                texture: texture,
            };
            this.resize_to(SCREEN_WIDTH * 3, SCREEN_HEIGHT * 3);

            this
        })
    }
}

impl ::frontend_api::Renderer for SdlRenderer {
    fn render(&mut self, frame_data: &[u8]) -> Option<FrontendAction> {
        if let Some((w, h)) = SDL.with(|sdl| sdl.borrow_mut().resized()) {
            self.resize_to(w, h)
        }

        // FIXME Can this be done with fewer copies?
        self.texture.update(None, frame_data, SCREEN_WIDTH as usize * 3).unwrap();
        self.renderer.clear();
        self.renderer.copy(&self.texture, None, None);
        self.renderer.present();

        SDL.with(|sdl| sdl.borrow_mut().update())
    }

    fn set_rom_title(&mut self, title: &str) {
        match self.renderer.window_mut() {
            Some(win) => win.set_title(title),
            None => {},
        }
    }
}

impl SdlRenderer {
    /// Handle a window resize to `w, h`
    fn resize_to(&mut self, w: u32, h: u32) {
        let w = w as f32;
        let h = h as f32;

        const NATIVE_RATIO: f32 = SCREEN_WIDTH as f32 / SCREEN_HEIGHT as f32;
        let ratio = w / h;

        let view_w;
        let view_h;

        if ratio > NATIVE_RATIO {
            // Too wide
            view_h = h;
            view_w = h * NATIVE_RATIO;
        } else {
            // Too high
            view_w = w;
            view_h = w / NATIVE_RATIO;
        }

        let border_x = (w - view_w).round() as u32 / 2;
        let border_y = (h - view_h).round() as u32 / 2;
        let view_w = view_w.round() as u32;
        let view_h = view_h.round() as u32;

        let viewport = Rect::new(border_x as i32, border_y as i32, view_w, view_h).unwrap();
        self.renderer.set_viewport(viewport);

        info!("window ratio is {:.2} (native: {:.2}), viewport {}x{}, border ({},{})",
            ratio, NATIVE_RATIO, view_w, view_h, border_x, border_y);
    }
}

#[allow(dead_code)]
pub struct KeyboardInput;

macro_rules! impl_fn {
    ( $btn:ident = $key:ident ) => {
        fn $btn(&mut self) -> bool {
            SDL.with(|sdl_cell| {
                let sdl = sdl_cell.borrow();
                let state = sdl.event_pump.keyboard_state();
                state.is_scancode_pressed(::sdl2::keyboard::Scancode::$key)
            })
        }
    };
}

impl JoypadImpl for KeyboardInput {
    fn update_state(&mut self) -> JoypadState {
        use sdl2::keyboard::Scancode::*;

        SDL.with(|sdl_cell| {
            let mut joypad = JoypadState::new();
            {
                // Fetch input state
                let sdl = sdl_cell.borrow();
                let state = sdl.event_pump.keyboard_state();

                // These bindings somewhat resemble an actual SNES controller:
                // Q W           I O P
                // A S D   G H   K L
                // -------------------
                // L ↑           Y X R
                // < ↓ > Sel Sta B A

                if state.is_scancode_pressed(W) { joypad.set(JoypadButton::Up, true); }
                if state.is_scancode_pressed(A) { joypad.set(JoypadButton::Left, true); }
                if state.is_scancode_pressed(S) { joypad.set(JoypadButton::Down, true); }
                if state.is_scancode_pressed(D) { joypad.set(JoypadButton::Right, true); }

                if state.is_scancode_pressed(G) { joypad.set(JoypadButton::Select, true); }
                if state.is_scancode_pressed(H) { joypad.set(JoypadButton::Start, true); }

                if state.is_scancode_pressed(L) { joypad.set(JoypadButton::A, true); }
                if state.is_scancode_pressed(K) { joypad.set(JoypadButton::B, true); }
                if state.is_scancode_pressed(O) { joypad.set(JoypadButton::X, true); }
                if state.is_scancode_pressed(I) { joypad.set(JoypadButton::Y, true); }

                if state.is_scancode_pressed(P) { joypad.set(JoypadButton::R, true); }
                if state.is_scancode_pressed(Q) { joypad.set(JoypadButton::L, true); }
            }

            joypad
        })
    }
}
<commit_msg>Enable V-Sync<commit_after>//! Render to an SDL window

use frontend_api::FrontendAction;
use frontend_api::input::joypad::{JoypadImpl, JoypadState, JoypadButton};
use frontend_api::ppu::{SCREEN_WIDTH, SCREEN_HEIGHT};

use sdl2::{EventPump, Sdl};
use sdl2::event::WindowEventId;
use sdl2::keyboard::Scancode;
use sdl2::pixels::PixelFormatEnum;
use sdl2::render::{Renderer, Texture, TextureAccess};
use sdl2::rect::Rect;

use std::cell::RefCell;
use std::ops::Deref;

/// Takes care of SDL (mainly used for event management). Owns an `EventPump`, which makes it
/// unavailable for other code. Initialized when the emulator uses an SDL frontend.
struct SdlManager {
    sdl: Sdl,
    event_pump: EventPump,
    resized_to: Option<(u32, u32)>,
}

impl SdlManager {
    /// Updates all SDL-related state. Polls events and may terminate the process via
    /// `process::exit`. Should be called at least once per frame.
    fn update(&mut self) -> Option<FrontendAction> {
        use sdl2::event::Event::*;

        for event in self.event_pump.poll_iter() {
            match event {
                Quit { .. } => {
                    info!("quit event -> exiting");
                    return Some(FrontendAction::Exit);
                }
                Window { win_event_id: WindowEventId::Resized, data1: w, data2: h, .. } => {
                    info!("window resized to {}x{}", w, h);
                    self.resized_to = Some((w as u32, h as u32));
                }
                KeyDown { scancode: Some(Scancode::F5), .. } => {
                    return Some(FrontendAction::SaveState);
                }
                KeyDown { scancode: Some(Scancode::F9), .. } => {
                    return Some(FrontendAction::LoadState);
                }
                _ => {}
            }
        }

        if self.event_pump.keyboard_state().is_scancode_pressed(Scancode::LCtrl) {
            info!("<waiting>");
            for event in self.event_pump.wait_iter() {
                match event {
                    KeyUp { scancode: Some(Scancode::LCtrl), .. } => { break }
                    _ => {}
                }
            }
            info!("<running>");
        }

        None
    }

    fn resized(&mut self) -> Option<(u32, u32)> { self.resized_to.take() }
}

impl Deref for SdlManager {
    type Target = Sdl;
    fn deref(&self) -> &Sdl { &self.sdl }
}

thread_local! {
    static SDL: RefCell<SdlManager> = {
        let sdl = ::sdl2::init().unwrap();
        let pump = sdl.event_pump().unwrap();

        RefCell::new(SdlManager {
            sdl: sdl,
            event_pump: pump,
            resized_to: None,
        })
    }
}

pub struct SdlRenderer {
    renderer: Renderer<'static>,
    texture: Texture,
}

impl Default for SdlRenderer {
    fn default() -> Self {
        // FIXME: Support linear filtering and nearest neighbor

        SDL.with(|sdl_cell| {
            let sdl = sdl_cell.borrow_mut();
            let video = sdl.video().unwrap();
            let window = video.window("breeze", SCREEN_WIDTH * 3, SCREEN_HEIGHT * 3)
                .resizable()
                .build().unwrap();
            let renderer = window.renderer()
                .accelerated()
                .present_vsync()
                .build().unwrap();
            let texture = renderer.create_texture(
                PixelFormatEnum::RGB24,
                TextureAccess::Static,
                (SCREEN_WIDTH, SCREEN_HEIGHT)).unwrap();

            let mut this = SdlRenderer {
                renderer: renderer,
                texture: texture,
            };
            this.resize_to(SCREEN_WIDTH * 3, SCREEN_HEIGHT * 3);

            this
        })
    }
}

impl ::frontend_api::Renderer for SdlRenderer {
    fn render(&mut self, frame_data: &[u8]) -> Option<FrontendAction> {
        if let Some((w, h)) = SDL.with(|sdl| sdl.borrow_mut().resized()) {
            self.resize_to(w, h)
        }

        // FIXME Can this be done with fewer copies?
        self.texture.update(None, frame_data, SCREEN_WIDTH as usize * 3).unwrap();
        self.renderer.clear();
        self.renderer.copy(&self.texture, None, None);
        self.renderer.present();

        SDL.with(|sdl| sdl.borrow_mut().update())
    }

    fn set_rom_title(&mut self, title: &str) {
        match self.renderer.window_mut() {
            Some(win) => win.set_title(title),
            None => {},
        }
    }
}

impl SdlRenderer {
    /// Handle a window resize to `w, h`
    fn resize_to(&mut self, w: u32, h: u32) {
        let w = w as f32;
        let h = h as f32;

        const NATIVE_RATIO: f32 = SCREEN_WIDTH as f32 / SCREEN_HEIGHT as f32;
        let ratio = w / h;

        let view_w;
        let view_h;

        if ratio > NATIVE_RATIO {
            // Too wide
            view_h = h;
            view_w = h * NATIVE_RATIO;
        } else {
            // Too high
            view_w = w;
            view_h = w / NATIVE_RATIO;
        }

        let border_x = (w - view_w).round() as u32 / 2;
        let border_y = (h - view_h).round() as u32 / 2;
        let view_w = view_w.round() as u32;
        let view_h = view_h.round() as u32;

        let viewport = Rect::new(border_x as i32, border_y as i32, view_w, view_h).unwrap();
        self.renderer.set_viewport(viewport);

        info!("window ratio is {:.2} (native: {:.2}), viewport {}x{}, border ({},{})",
            ratio, NATIVE_RATIO, view_w, view_h, border_x, border_y);
    }
}

#[allow(dead_code)]
pub struct KeyboardInput;

macro_rules! impl_fn {
    ( $btn:ident = $key:ident ) => {
        fn $btn(&mut self) -> bool {
            SDL.with(|sdl_cell| {
                let sdl = sdl_cell.borrow();
                let state = sdl.event_pump.keyboard_state();
                state.is_scancode_pressed(::sdl2::keyboard::Scancode::$key)
            })
        }
    };
}

impl JoypadImpl for KeyboardInput {
    fn update_state(&mut self) -> JoypadState {
        use sdl2::keyboard::Scancode::*;

        SDL.with(|sdl_cell| {
            let mut joypad = JoypadState::new();
            {
                // Fetch input state
                let sdl = sdl_cell.borrow();
                let state = sdl.event_pump.keyboard_state();

                // These bindings somewhat resemble an actual SNES controller:
                // Q W           I O P
                // A S D   G H   K L
                // -------------------
                // L ↑           Y X R
                // < ↓ > Sel Sta B A

                if state.is_scancode_pressed(W) { joypad.set(JoypadButton::Up, true); }
                if state.is_scancode_pressed(A) { joypad.set(JoypadButton::Left, true); }
                if state.is_scancode_pressed(S) { joypad.set(JoypadButton::Down, true); }
                if state.is_scancode_pressed(D) { joypad.set(JoypadButton::Right, true); }

                if state.is_scancode_pressed(G) { joypad.set(JoypadButton::Select, true); }
                if state.is_scancode_pressed(H) { joypad.set(JoypadButton::Start, true); }

                if state.is_scancode_pressed(L) { joypad.set(JoypadButton::A, true); }
                if state.is_scancode_pressed(K) { joypad.set(JoypadButton::B, true); }
                if state.is_scancode_pressed(O) { joypad.set(JoypadButton::X, true); }
                if state.is_scancode_pressed(I) { joypad.set(JoypadButton::Y, true); }

                if state.is_scancode_pressed(P) { joypad.set(JoypadButton::R, true); }
                if state.is_scancode_pressed(Q) { joypad.set(JoypadButton::L, true); }
            }

            joypad
        })
    }
}
<|endoftext|>


<commit_before>// Copyright:: Copyright (c) 2015-2016 Chef Software, Inc.
//
// The terms of the Evaluation Agreement (Bldr) between Chef Software Inc. and the party accessing
// this file ("Licensee") apply to Licensee's use of the Software until such time that the Software
// is made available under an open source license such as the Apache 2.0 License.

use rustc_serialize::{Decodable, Encodable};

use data_store::{DataRecord, InstaId, Table};

pub type Fields = Vec<(&'static str, String)>;

pub trait Model: Encodable + Decodable + From<DataRecord> {
    type Table: Table;

    fn fields(&self) -> Fields;
    fn id(&self) -> &InstaId;
    fn set_id(&mut self, InstaId) -> ();
}

#[cfg(test)]
mod test {
    use config::Config;
    use super::*;
    use super::super::DataStore;

    fn data_store() -> DataStore {
        let cfg = Config::new();
        let mut ds = DataStore::new();
        ds.open(&cfg).unwrap();
        ds
    }

    #[test]
    fn store_and_retrieve_model() {
        let ds = data_store();
        let mut account = Account::new("reset".to_string(), "reset@chef.io".to_string());
        account.save(&ds).unwrap();
        let record: Account = ds.find(&account.id).unwrap();
        assert_eq!(record.id, account.id);
        assert_eq!(record.email, account.email);
        assert_eq!(record.name, account.name);
    }
}
<commit_msg>remove old test from dbcache model module<commit_after>// Copyright:: Copyright (c) 2015-2016 Chef Software, Inc.
//
// The terms of the Evaluation Agreement (Bldr) between Chef Software Inc. and the party accessing
// this file ("Licensee") apply to Licensee's use of the Software until such time that the Software
// is made available under an open source license such as the Apache 2.0 License.

use rustc_serialize::{Decodable, Encodable};

use data_store::{DataRecord, InstaId, Table};

pub type Fields = Vec<(&'static str, String)>;

pub trait Model: Encodable + Decodable + From<DataRecord> {
    type Table: Table;

    fn fields(&self) -> Fields;
    fn id(&self) -> &InstaId;
    fn set_id(&mut self, InstaId) -> ();
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use diem_management::{config::ConfigPath, constants, error::Error, secure_backend::SharedBackend};
use serde::{Deserialize, Serialize};
use std::{
    fs::File,
    io::Read,
    path::{Path, PathBuf},
};
use structopt::StructOpt;

/// Layout defines the set of roles to identities within genesis. In practice, these identities
/// will map to distinct namespaces where the expected data should be stored in the deterministic
/// location as defined within this tool.
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct Layout {
    pub operators: Vec<String>,
    pub owners: Vec<String>,
    pub diem_root: String,
    pub treasury_compliance: String,
}

impl Layout {
    pub fn from_disk<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
        let mut file = File::open(&path).map_err(|e| Error::UnexpectedError(e.to_string()))?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)
            .map_err(|e| Error::UnexpectedError(e.to_string()))?;
        Self::parse(&contents)
    }

    pub fn parse(contents: &str) -> Result<Self, Error> {
        toml::from_str(&contents).map_err(|e| Error::UnexpectedError(e.to_string()))
    }

    pub fn to_toml(&self) -> Result<String, Error> {
        toml::to_string(&self).map_err(|e| Error::UnexpectedError(e.to_string()))
    }
}

impl std::fmt::Display for Layout {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", toml::to_string(self).unwrap())
    }
}

#[derive(Debug, StructOpt)]
pub struct SetLayout {
    #[structopt(flatten)]
    config: ConfigPath,
    #[structopt(long)]
    path: PathBuf,
    #[structopt(flatten)]
    backend: SharedBackend,
}

impl SetLayout {
    pub fn execute(self) -> Result<Layout, Error> {
        let layout = Layout::from_disk(&self.path)?;
        let data = layout.to_toml()?;

        let config = self
            .config
            .load()?
            .override_shared_backend(&self.backend.shared_backend)?;
        let mut storage = config.shared_backend_with_namespace(constants::COMMON_NS.to_string());
        storage.set(constants::LAYOUT, data)?;

        Ok(layout)
    }
}

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

    #[test]
    fn test_layout() {
        let contents = "\
            operators = [\"alice\", \"bob\"]\n\
            owners = [\"carol\"]\n\
            diem_root = \"dave\"\n\
            treasury_compliance = \"other_dave\"\n\
        ";

        let layout = Layout::parse(contents).unwrap();
        assert_eq!(
            layout.operators,
            vec!["alice".to_string(), "bob".to_string()]
        );
        assert_eq!(layout.owners, vec!["carol".to_string()]);
        assert_eq!(layout.diem_root, "dave");
        assert_eq!(layout.treasury_compliance, "other_dave");
    }
}
<commit_msg>genesis: convert the layout command to use the GenesisBuilder<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::builder::GenesisBuilder;
use diem_management::{config::ConfigPath, error::Error, secure_backend::SharedBackend};
use diem_secure_storage::Storage;
use serde::{Deserialize, Serialize};
use std::{
    fs::File,
    io::Read,
    path::{Path, PathBuf},
};
use structopt::StructOpt;

/// Layout defines the set of roles to identities within genesis. In practice, these identities
/// will map to distinct namespaces where the expected data should be stored in the deterministic
/// location as defined within this tool.
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct Layout {
    pub operators: Vec<String>,
    pub owners: Vec<String>,
    pub diem_root: String,
    pub treasury_compliance: String,
}

impl Layout {
    pub fn from_disk<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
        let mut file = File::open(&path).map_err(|e| Error::UnexpectedError(e.to_string()))?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)
            .map_err(|e| Error::UnexpectedError(e.to_string()))?;
        Self::parse(&contents)
    }

    pub fn parse(contents: &str) -> Result<Self, Error> {
        toml::from_str(&contents).map_err(|e| Error::UnexpectedError(e.to_string()))
    }

    pub fn to_toml(&self) -> Result<String, Error> {
        toml::to_string(&self).map_err(|e| Error::UnexpectedError(e.to_string()))
    }
}

impl std::fmt::Display for Layout {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", toml::to_string(self).unwrap())
    }
}

#[derive(Debug, StructOpt)]
pub struct SetLayout {
    #[structopt(flatten)]
    config: ConfigPath,
    #[structopt(long)]
    path: PathBuf,
    #[structopt(flatten)]
    backend: SharedBackend,
}

impl SetLayout {
    pub fn execute(self) -> Result<Layout, Error> {
        let layout = Layout::from_disk(&self.path)?;

        let config = self
            .config
            .load()?
            .override_shared_backend(&self.backend.shared_backend)?;

        // In order to not break cli compatibility we need to clear the namespace set via cli since
        // it was previously ignored.
        let mut shared_backend = config.shared_backend;
        shared_backend.clear_namespace();

        let storage = Storage::from(&shared_backend);
        GenesisBuilder::new(storage)
            .set_layout(&layout)
            .map_err(|e| Error::StorageWriteError("shared", "layout", e.to_string()))?;

        Ok(layout)
    }
}

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

    #[test]
    fn test_layout() {
        let contents = "\
            operators = [\"alice\", \"bob\"]\n\
            owners = [\"carol\"]\n\
            diem_root = \"dave\"\n\
            treasury_compliance = \"other_dave\"\n\
        ";

        let layout = Layout::parse(contents).unwrap();
        assert_eq!(
            layout.operators,
            vec!["alice".to_string(), "bob".to_string()]
        );
        assert_eq!(layout.owners, vec!["carol".to_string()]);
        assert_eq!(layout.diem_root, "dave");
        assert_eq!(layout.treasury_compliance, "other_dave");
    }
}
<|endoftext|>


<commit_before>// Copyright 2021 Vector 35 Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{borrow::Borrow, collections::HashMap, os::raw, path::Path, ptr, slice};

use binaryninjacore_sys::*;

use crate::{
    architecture::{Architecture, CoreArchitecture},
    callingconvention::CallingConvention,
    rc::*,
    string::*,
    types::{QualifiedName, QualifiedNameAndType, Type},
};

#[derive(PartialEq, Eq, Hash)]
pub struct Platform {
    pub(crate) handle: *mut BNPlatform,
}

unsafe impl Send for Platform {}
unsafe impl Sync for Platform {}

macro_rules! cc_func {
    ($get_name:ident, $get_api:ident, $set_name:ident, $set_api:ident) => {
        pub fn $get_name(&self) -> Option<Ref<CallingConvention<CoreArchitecture>>> {
            let arch = self.arch();

            unsafe {
                let cc = $get_api(self.handle);

                if cc.is_null() {
                    None
                } else {
                    Some(CallingConvention::ref_from_raw(cc, arch))
                }
            }
        }

        pub fn $set_name<A: Architecture>(&self, cc: &CallingConvention<A>) {
            let arch = self.arch();

            assert!(
                cc.arch_handle.borrow().as_ref().0 == arch.0,
                "use of calling convention with non-matching Platform architecture!"
            );

            unsafe {
                $set_api(self.handle, cc.handle);
            }
        }
    };
}

impl Platform {
    pub(crate) unsafe fn from_raw(handle: *mut BNPlatform) -> Self {
        debug_assert!(!handle.is_null());

        Self { handle }
    }

    pub fn by_name<S: BnStrCompatible>(name: S) -> Option<Ref<Self>> {
        let raw_name = name.as_bytes_with_nul();
        unsafe {
            let res = BNGetPlatformByName(raw_name.as_ref().as_ptr() as *mut _);

            if res.is_null() {
                None
            } else {
                Some(Ref::new(Self { handle: res }))
            }
        }
    }

    pub fn list_all() -> Array<Platform> {
        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformList(&mut count);

            Array::new(handles, count, ())
        }
    }

    pub fn list_by_arch(arch: &CoreArchitecture) -> Array<Platform> {
        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformListByArchitecture(arch.0, &mut count);

            Array::new(handles, count, ())
        }
    }

    pub fn list_by_os<S: BnStrCompatible>(name: S) -> Array<Platform> {
        let raw_name = name.as_bytes_with_nul();

        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformListByOS(raw_name.as_ref().as_ptr() as *mut _, &mut count);

            Array::new(handles, count, ())
        }
    }

    pub fn list_by_os_and_arch<S: BnStrCompatible>(
        name: S,
        arch: &CoreArchitecture,
    ) -> Array<Platform> {
        let raw_name = name.as_bytes_with_nul();

        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformListByOSAndArchitecture(
                raw_name.as_ref().as_ptr() as *mut _,
                arch.0,
                &mut count,
            );

            Array::new(handles, count, ())
        }
    }

    pub fn list_available_os() -> Array<BnString> {
        unsafe {
            let mut count = 0;
            let list = BNGetPlatformOSList(&mut count);

            Array::new(list, count, ())
        }
    }

    pub fn new<A: Architecture, S: BnStrCompatible>(arch: &A, name: S) -> Ref<Self> {
        let name = name.as_bytes_with_nul();
        unsafe {
            let handle = BNCreatePlatform(arch.as_ref().0, name.as_ref().as_ptr() as *mut _);

            assert!(!handle.is_null());

            Ref::new(Self { handle })
        }
    }

    pub fn name(&self) -> BnString {
        unsafe {
            let raw_name = BNGetPlatformName(self.handle);
            BnString::from_raw(raw_name)
        }
    }

    pub fn arch(&self) -> CoreArchitecture {
        unsafe { CoreArchitecture::from_raw(BNGetPlatformArchitecture(self.handle)) }
    }

    pub fn register_os<S: BnStrCompatible>(&self, os: S) {
        let os = os.as_bytes_with_nul();

        unsafe {
            BNRegisterPlatform(os.as_ref().as_ptr() as *mut _, self.handle);
        }
    }

    cc_func!(
        get_default_calling_convention,
        BNGetPlatformDefaultCallingConvention,
        set_default_calling_convention,
        BNRegisterPlatformDefaultCallingConvention
    );

    cc_func!(
        get_cdecl_calling_convention,
        BNGetPlatformCdeclCallingConvention,
        set_cdecl_calling_convention,
        BNRegisterPlatformCdeclCallingConvention
    );

    cc_func!(
        get_stdcall_calling_convention,
        BNGetPlatformStdcallCallingConvention,
        set_stdcall_calling_convention,
        BNRegisterPlatformStdcallCallingConvention
    );

    cc_func!(
        get_fastcall_calling_convention,
        BNGetPlatformFastcallCallingConvention,
        set_fastcall_calling_convention,
        BNRegisterPlatformFastcallCallingConvention
    );

    cc_func!(
        get_syscall_convention,
        BNGetPlatformSystemCallConvention,
        set_syscall_convention,
        BNSetPlatformSystemCallConvention
    );

    pub fn types(&self) -> Array<QualifiedNameAndType> {
        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformTypes(self.handle, &mut count);

            Array::new(handles, count, ())
        }
    }

    pub fn variables(&self) -> Array<QualifiedNameAndType> {
        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformVariables(self.handle, &mut count);

            Array::new(handles, count, ())
        }
    }

    pub fn functions(&self) -> Array<QualifiedNameAndType> {
        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformFunctions(self.handle, &mut count);

            Array::new(handles, count, ())
        }
    }
}

pub trait TypeParser {
    fn parse_types_from_source<S: BnStrCompatible, P: AsRef<Path>>(
        &self,
        _source: S,
        _filename: S,
        _include_directories: &[P],
        _auto_type_source: S,
    ) -> Result<TypeParserResult, String> {
        Err(String::new())
    }
}

#[derive(Clone, Default)]
pub struct TypeParserResult {
    pub types: HashMap<String, Ref<Type>>,
    pub variables: HashMap<String, Ref<Type>>,
    pub functions: HashMap<String, Ref<Type>>,
}

impl TypeParser for Platform {
    fn parse_types_from_source<S: BnStrCompatible, P: AsRef<Path>>(
        &self,
        source: S,
        filename: S,
        include_directories: &[P],
        auto_type_source: S,
    ) -> Result<TypeParserResult, String> {
        let mut result = BNTypeParserResult {
            functionCount: 0,
            typeCount: 0,
            variableCount: 0,
            functions: ptr::null_mut(),
            types: ptr::null_mut(),
            variables: ptr::null_mut(),
        };

        let mut type_parser_result = TypeParserResult::default();

        let mut error_string: *mut raw::c_char = ptr::null_mut();

        let src = source.as_bytes_with_nul();
        let filename = filename.as_bytes_with_nul();
        let auto_type_source = auto_type_source.as_bytes_with_nul();

        let mut include_dirs = vec![];

        for dir in include_directories.iter() {
            let d = dir.as_ref().to_string_lossy().as_bytes_with_nul();
            include_dirs.push(d.as_ptr() as _);
        }

        unsafe {
            let success = BNParseTypesFromSource(
                self.handle,
                src.as_ref().as_ptr() as _,
                filename.as_ref().as_ptr() as _,
                &mut result,
                &mut error_string,
                include_dirs.as_mut_ptr(),
                include_dirs.len(),
                auto_type_source.as_ref().as_ptr() as _,
            );

            let error_msg = BnString::from_raw(error_string);
            BNFreeString(error_string);

            if !success {
                return Err(error_msg.to_string());
            }

            for i in slice::from_raw_parts(result.types, result.typeCount) {
                let name = QualifiedName(i.name);
                type_parser_result
                    .types
                    .insert(name.string(), Type::ref_from_raw(i.type_));
            }

            for i in slice::from_raw_parts(result.functions, result.functionCount) {
                let name = QualifiedName(i.name);
                type_parser_result
                    .functions
                    .insert(name.string(), Type::ref_from_raw(i.type_));
            }

            for i in slice::from_raw_parts(result.variables, result.variableCount) {
                let name = QualifiedName(i.name);
                type_parser_result
                    .variables
                    .insert(name.string(), Type::ref_from_raw(i.type_));
            }
        }

        Ok(type_parser_result)
    }
}

impl ToOwned for Platform {
    type Owned = Ref<Self>;

    fn to_owned(&self) -> Self::Owned {
        unsafe { RefCountable::inc_ref(self) }
    }
}

unsafe impl RefCountable for Platform {
    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
        Ref::new(Self {
            handle: BNNewPlatformReference(handle.handle),
        })
    }

    unsafe fn dec_ref(handle: &Self) {
        BNFreePlatform(handle.handle);
    }
}

unsafe impl CoreOwnedArrayProvider for Platform {
    type Raw = *mut BNPlatform;
    type Context = ();

    unsafe fn free(raw: *mut *mut BNPlatform, count: usize, _context: &()) {
        BNFreePlatformList(raw, count);
    }
}

unsafe impl<'a> CoreOwnedArrayWrapper<'a> for Platform {
    type Wrapped = Guard<'a, Platform>;

    unsafe fn wrap_raw(raw: &'a *mut BNPlatform, context: &'a ()) -> Guard<'a, Platform> {
        Guard::new(Platform::from_raw(*raw), context)
    }
}
<commit_msg>Remove BNFreeString call<commit_after>// Copyright 2021 Vector 35 Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{borrow::Borrow, collections::HashMap, os::raw, path::Path, ptr, slice};

use binaryninjacore_sys::*;

use crate::{
    architecture::{Architecture, CoreArchitecture},
    callingconvention::CallingConvention,
    rc::*,
    string::*,
    types::{QualifiedName, QualifiedNameAndType, Type},
};

#[derive(PartialEq, Eq, Hash)]
pub struct Platform {
    pub(crate) handle: *mut BNPlatform,
}

unsafe impl Send for Platform {}
unsafe impl Sync for Platform {}

macro_rules! cc_func {
    ($get_name:ident, $get_api:ident, $set_name:ident, $set_api:ident) => {
        pub fn $get_name(&self) -> Option<Ref<CallingConvention<CoreArchitecture>>> {
            let arch = self.arch();

            unsafe {
                let cc = $get_api(self.handle);

                if cc.is_null() {
                    None
                } else {
                    Some(CallingConvention::ref_from_raw(cc, arch))
                }
            }
        }

        pub fn $set_name<A: Architecture>(&self, cc: &CallingConvention<A>) {
            let arch = self.arch();

            assert!(
                cc.arch_handle.borrow().as_ref().0 == arch.0,
                "use of calling convention with non-matching Platform architecture!"
            );

            unsafe {
                $set_api(self.handle, cc.handle);
            }
        }
    };
}

impl Platform {
    pub(crate) unsafe fn from_raw(handle: *mut BNPlatform) -> Self {
        debug_assert!(!handle.is_null());

        Self { handle }
    }

    pub fn by_name<S: BnStrCompatible>(name: S) -> Option<Ref<Self>> {
        let raw_name = name.as_bytes_with_nul();
        unsafe {
            let res = BNGetPlatformByName(raw_name.as_ref().as_ptr() as *mut _);

            if res.is_null() {
                None
            } else {
                Some(Ref::new(Self { handle: res }))
            }
        }
    }

    pub fn list_all() -> Array<Platform> {
        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformList(&mut count);

            Array::new(handles, count, ())
        }
    }

    pub fn list_by_arch(arch: &CoreArchitecture) -> Array<Platform> {
        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformListByArchitecture(arch.0, &mut count);

            Array::new(handles, count, ())
        }
    }

    pub fn list_by_os<S: BnStrCompatible>(name: S) -> Array<Platform> {
        let raw_name = name.as_bytes_with_nul();

        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformListByOS(raw_name.as_ref().as_ptr() as *mut _, &mut count);

            Array::new(handles, count, ())
        }
    }

    pub fn list_by_os_and_arch<S: BnStrCompatible>(
        name: S,
        arch: &CoreArchitecture,
    ) -> Array<Platform> {
        let raw_name = name.as_bytes_with_nul();

        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformListByOSAndArchitecture(
                raw_name.as_ref().as_ptr() as *mut _,
                arch.0,
                &mut count,
            );

            Array::new(handles, count, ())
        }
    }

    pub fn list_available_os() -> Array<BnString> {
        unsafe {
            let mut count = 0;
            let list = BNGetPlatformOSList(&mut count);

            Array::new(list, count, ())
        }
    }

    pub fn new<A: Architecture, S: BnStrCompatible>(arch: &A, name: S) -> Ref<Self> {
        let name = name.as_bytes_with_nul();
        unsafe {
            let handle = BNCreatePlatform(arch.as_ref().0, name.as_ref().as_ptr() as *mut _);

            assert!(!handle.is_null());

            Ref::new(Self { handle })
        }
    }

    pub fn name(&self) -> BnString {
        unsafe {
            let raw_name = BNGetPlatformName(self.handle);
            BnString::from_raw(raw_name)
        }
    }

    pub fn arch(&self) -> CoreArchitecture {
        unsafe { CoreArchitecture::from_raw(BNGetPlatformArchitecture(self.handle)) }
    }

    pub fn register_os<S: BnStrCompatible>(&self, os: S) {
        let os = os.as_bytes_with_nul();

        unsafe {
            BNRegisterPlatform(os.as_ref().as_ptr() as *mut _, self.handle);
        }
    }

    cc_func!(
        get_default_calling_convention,
        BNGetPlatformDefaultCallingConvention,
        set_default_calling_convention,
        BNRegisterPlatformDefaultCallingConvention
    );

    cc_func!(
        get_cdecl_calling_convention,
        BNGetPlatformCdeclCallingConvention,
        set_cdecl_calling_convention,
        BNRegisterPlatformCdeclCallingConvention
    );

    cc_func!(
        get_stdcall_calling_convention,
        BNGetPlatformStdcallCallingConvention,
        set_stdcall_calling_convention,
        BNRegisterPlatformStdcallCallingConvention
    );

    cc_func!(
        get_fastcall_calling_convention,
        BNGetPlatformFastcallCallingConvention,
        set_fastcall_calling_convention,
        BNRegisterPlatformFastcallCallingConvention
    );

    cc_func!(
        get_syscall_convention,
        BNGetPlatformSystemCallConvention,
        set_syscall_convention,
        BNSetPlatformSystemCallConvention
    );

    pub fn types(&self) -> Array<QualifiedNameAndType> {
        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformTypes(self.handle, &mut count);

            Array::new(handles, count, ())
        }
    }

    pub fn variables(&self) -> Array<QualifiedNameAndType> {
        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformVariables(self.handle, &mut count);

            Array::new(handles, count, ())
        }
    }

    pub fn functions(&self) -> Array<QualifiedNameAndType> {
        unsafe {
            let mut count = 0;
            let handles = BNGetPlatformFunctions(self.handle, &mut count);

            Array::new(handles, count, ())
        }
    }
}

pub trait TypeParser {
    fn parse_types_from_source<S: BnStrCompatible, P: AsRef<Path>>(
        &self,
        _source: S,
        _filename: S,
        _include_directories: &[P],
        _auto_type_source: S,
    ) -> Result<TypeParserResult, String> {
        Err(String::new())
    }
}

#[derive(Clone, Default)]
pub struct TypeParserResult {
    pub types: HashMap<String, Ref<Type>>,
    pub variables: HashMap<String, Ref<Type>>,
    pub functions: HashMap<String, Ref<Type>>,
}

impl TypeParser for Platform {
    fn parse_types_from_source<S: BnStrCompatible, P: AsRef<Path>>(
        &self,
        source: S,
        filename: S,
        include_directories: &[P],
        auto_type_source: S,
    ) -> Result<TypeParserResult, String> {
        let mut result = BNTypeParserResult {
            functionCount: 0,
            typeCount: 0,
            variableCount: 0,
            functions: ptr::null_mut(),
            types: ptr::null_mut(),
            variables: ptr::null_mut(),
        };

        let mut type_parser_result = TypeParserResult::default();

        let mut error_string: *mut raw::c_char = ptr::null_mut();

        let src = source.as_bytes_with_nul();
        let filename = filename.as_bytes_with_nul();
        let auto_type_source = auto_type_source.as_bytes_with_nul();

        let mut include_dirs = vec![];

        for dir in include_directories.iter() {
            let d = dir.as_ref().to_string_lossy().as_bytes_with_nul();
            include_dirs.push(d.as_ptr() as _);
        }

        unsafe {
            let success = BNParseTypesFromSource(
                self.handle,
                src.as_ref().as_ptr() as _,
                filename.as_ref().as_ptr() as _,
                &mut result,
                &mut error_string,
                include_dirs.as_mut_ptr(),
                include_dirs.len(),
                auto_type_source.as_ref().as_ptr() as _,
            );

            let error_msg = BnString::from_raw(error_string);

            if !success {
                return Err(error_msg.to_string());
            }

            for i in slice::from_raw_parts(result.types, result.typeCount) {
                let name = QualifiedName(i.name);
                type_parser_result
                    .types
                    .insert(name.string(), Type::ref_from_raw(i.type_));
            }

            for i in slice::from_raw_parts(result.functions, result.functionCount) {
                let name = QualifiedName(i.name);
                type_parser_result
                    .functions
                    .insert(name.string(), Type::ref_from_raw(i.type_));
            }

            for i in slice::from_raw_parts(result.variables, result.variableCount) {
                let name = QualifiedName(i.name);
                type_parser_result
                    .variables
                    .insert(name.string(), Type::ref_from_raw(i.type_));
            }
        }

        Ok(type_parser_result)
    }
}

impl ToOwned for Platform {
    type Owned = Ref<Self>;

    fn to_owned(&self) -> Self::Owned {
        unsafe { RefCountable::inc_ref(self) }
    }
}

unsafe impl RefCountable for Platform {
    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
        Ref::new(Self {
            handle: BNNewPlatformReference(handle.handle),
        })
    }

    unsafe fn dec_ref(handle: &Self) {
        BNFreePlatform(handle.handle);
    }
}

unsafe impl CoreOwnedArrayProvider for Platform {
    type Raw = *mut BNPlatform;
    type Context = ();

    unsafe fn free(raw: *mut *mut BNPlatform, count: usize, _context: &()) {
        BNFreePlatformList(raw, count);
    }
}

unsafe impl<'a> CoreOwnedArrayWrapper<'a> for Platform {
    type Wrapped = Guard<'a, Platform>;

    unsafe fn wrap_raw(raw: &'a *mut BNPlatform, context: &'a ()) -> Guard<'a, Platform> {
        Guard::new(Platform::from_raw(*raw), context)
    }
}
<|endoftext|>