<commit_before>#![allow(non_camel_case_types, non_snake_case)]

#[macro_use]
extern crate bitflags;

use std::os::raw::{c_int, c_uint};

/// Monochrome screen, pixel witdh
pub const MONO_WIDTH:  usize = 160;

/// Monochrome screen, pixel hight
pub const MONO_HEIGHT: usize = 43;

/// Color screen, pixel witdh
pub const COLOR_WIDTH:  usize = 320;

/// Color screen, pixel hight
pub const COLOR_HEIGHT: usize = 240;

bitflags! {
    /// Targeted lcd type.
    ///
    /// This library allows you to target either Mono or Color devices
    pub struct LcdType: u32 {
        /// Mono color.
        const MONO =  0x00000001;
        /// 32bit RGBA color.
        const COLOR = 0b00000010;
        /// Either mono or color.
        const EITHER = Self::MONO.bits | Self::COLOR.bits;
    }
}

bitflags! {
    /// Lcd Button bitmap.
    pub struct LcdButton: u32 {
        const MONO_BUTTON_0 = 0x00000001;
        const MONO_BUTTON_1 = 0x00000002;
        const MONO_BUTTON_2 = 0x00000004;
        const MONO_BUTTON_3 = 0x00000008;
        const MONO_BUTTON = Self::MONO_BUTTON_0.bits |
                            Self::MONO_BUTTON_1.bits |
                            Self::MONO_BUTTON_2.bits |
                            Self::MONO_BUTTON_3.bits;

        const COLOR_BUTTON_LEFT   = 0x00000100;
        const COLOR_BUTTON_RIGHT  = 0x00000200;
        const COLOR_BUTTON_OK     = 0x00000400;
        const COLOR_BUTTON_CANCEL = 0x00000800;
        const COLOR_BUTTON_UP     = 0x00001000;
        const COLOR_BUTTON_DOWN   = 0x00002000;
        const COLOR_BUTTON_MENU   = 0x00004000;
        const COLOR_BUTTON = Self::COLOR_BUTTON_LEFT.bits |
                             Self::COLOR_BUTTON_RIGHT.bits |
                             Self::COLOR_BUTTON_OK.bits |
                             Self::COLOR_BUTTON_CANCEL.bits |
                             Self::COLOR_BUTTON_UP.bits |
                             Self::COLOR_BUTTON_DOWN.bits |
                             Self::COLOR_BUTTON_MENU.bits;
    }
}

/// LogitechLcd library.
///
/// Contains library symbols/functions as fields. Will unload library when dropped.
pub struct LogitechLcd {
    // Main functions
    pub LogiLcdInit: unsafe extern "C" fn(friendlyName: *const u16, lcdType: c_uint) -> bool,
    pub LogiLcdIsConnected: unsafe extern "C" fn(lcdType: c_uint) -> bool,
    pub LogiLcdIsButtonPressed: unsafe extern "C" fn(button: c_uint) -> bool,
    pub LogiLcdUpdate: unsafe extern "C" fn(),
    pub LogiLcdShutdown: unsafe extern "C" fn(),

    // Monochrome LCD functions
    pub LogiLcdMonoSetBackground: unsafe extern "C" fn(monoBitmap: *const u8) -> bool,
    pub LogiLcdMonoSetText: unsafe extern "C" fn(lineNumber: c_int, text: *const u16) -> bool,

    // Color LCD functions
    pub LogiLcdColorSetBackground: unsafe extern "C" fn(colorBitmap: *const u8) -> bool,
    pub LogiLcdColorSetTitle: unsafe extern "C" fn(text: *const u16, red: c_int, green: c_int,
        blue: c_int) -> bool,
    pub LogiLcdColorSetText: unsafe extern "C" fn(lineNumber: c_int, text: *const u16, red: c_int,
        green: c_int, blue: c_int) -> bool,

    // UDK functions, use this only if working with UDK
    pub LogiLcdColorSetBackgroundUDK: unsafe extern "C" fn(partialBitmap: *const u8,
        arraySize: c_int) -> c_int,
    pub LogiLcdColorResetBackgroundUDK: unsafe extern "C" fn() -> c_int,
    pub LogiLcdMonoSetBackgroundUDK: unsafe extern "C" fn(partialBitmap: *const u8,
        arraySize: c_int) -> c_int,
    pub LogiLcdMonoResetBackgroundUDK: unsafe extern "C" fn() -> c_int,

    /// Library handle, will be freed on drop
    _library: platform::Library,
}

unsafe impl std::marker::Send for LogitechLcd {}

#[cfg(not(target_os = "windows"))]
mod platform {
    use super::LogitechLcd;
    use std::io::Error;

    pub struct Library;

    impl LogitechLcd {
        pub fn load() -> Result<LogitechLcd, Error> {
            unimplemented!();
        }
    }
}

#[cfg(target_os = "windows")]
mod platform {
    extern crate winapi;
    extern crate kernel32;
    extern crate winreg;

    use super::LogitechLcd;

    use self::winreg::RegKey;
    use self::winreg::enums::{HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT, KEY_READ};
    use self::winapi::minwindef::{HMODULE, FARPROC};

    use std::os::windows::ffi::OsStrExt;
    use std::ffi::OsStr;
    use std::io::Error;

    pub struct Library(HMODULE);

    const ERROR_MOD_NOT_FOUND: i32 = winapi::winerror::ERROR_MOD_NOT_FOUND as i32;

    /// Find `LogitechLcd.dll` in Windows registry using its CLSID
    fn dll_path_clsid() -> Result<Vec<u16>, Error> {
        let hkcl = RegKey::predef(HKEY_CLASSES_ROOT);
        let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);

        let mut dll_path = None;

        #[cfg(target_arch = "x86_64")]
        {
            match hkcl.open_subkey_with_flags(
                "CLSID\\{d0e790a5-01a7-49ae-ae0b-e986bdd0c21b}\\ServerBinary", KEY_READ)
            {
                Ok(key) => dll_path = key.get_value::<String, &str>("").ok(),
                Err(_) => {},
            }

            match hklm.open_subkey_with_flags(
                "SOFTWARE\\Classes\\CLSID\\{d0e790a5-01a7-49ae-ae0b-e986bdd0c21b}\\ServerBinary",
                KEY_READ)
            {
                Ok(key) => dll_path = key.get_value::<String, &str>("").ok(),
                Err(_) => {},
            }
        }

        #[cfg(target_arch = "x86")]
        {
            match hkcl.open_subkey_with_flags(
                "Wow6432Node\\CLSID\\{d0e790a5-01a7-49ae-ae0b-e986bdd0c21b}\\ServerBinary", KEY_READ)
            {
                Ok(key) => dll_path = key.get_value::<String, &str>("").ok(),
                Err(_) => {},
            }

            match hklm.open_subkey_with_flags(
                "SOFTWARE\\Classes\\Wow6432Node\\CLSID\\{d0e790a5-01a7-49ae-ae0b-e986bdd0c21b}\\ServerBinary",
                KEY_READ)
            {
                Ok(key) => dll_path = key.get_value::<String, &str>("").ok(),
                Err(_) => {},
            }

            match hklm.open_subkey_with_flags(
                "SOFTWARE\\Wow6432Node\\Classes\\CLSID\\{d0e790a5-01a7-49ae-ae0b-e986bdd0c21b}\\ServerBinary",
                KEY_READ)
            {
                Ok(key) => dll_path = key.get_value::<String, &str>("").ok(),
                Err(_) => {},
            }
        }

        match dll_path {
            // Convert to widestring and terminate with \0\0.
            Some(p) => Ok(OsStr::new(&p[..]).encode_wide().chain(Some(0)).collect::<Vec<u16>>()),
            None => Err(Error::from_raw_os_error(ERROR_MOD_NOT_FOUND)),
        }
    }

    unsafe fn load_lib() -> Result<HMODULE, Error> {
        match dll_path_clsid() {
            Ok(wide_path) => {
                let handle = kernel32::LoadLibraryW(wide_path.as_ptr());
                if handle.is_null() {
                    let error = Error::last_os_error();
                    let ecode = error.raw_os_error().unwrap();
                    // Fallthrough on ERROR_MOD_NOT_FOUND
                    if ecode != ERROR_MOD_NOT_FOUND {
                        return Err(error);
                    }
                } else {
                    return Ok(handle);
                }
            },
            Err(e) => {
                match e.raw_os_error() {
                    Some(ERROR_MOD_NOT_FOUND) => {},
                    _ => return Err(e),
                }
            },
        }

        // Convert to widestring and terminate with \0\0.
        let wide_name = OsStr::new("LogitechLcd.dll").encode_wide().chain(Some(0)).collect::<Vec<u16>>();
        let handle = kernel32::LoadLibraryW(wide_name.as_ptr());
        if handle.is_null() {
            Err(Error::last_os_error())
        } else {
            Ok(handle)
        }
    }

    impl LogitechLcd {
        /// Try to locate and load 'LogitechLcd.dll'.
        pub fn load() -> Result<LogitechLcd, Error> {
            use std::mem;

            unsafe {
                let handle = load_lib()?;

                let mut symbols = [
                    ("LogiLcdInit\0",                    0 as FARPROC),
                    ("LogiLcdIsConnected\0",             0 as FARPROC),
                    ("LogiLcdIsButtonPressed\0",         0 as FARPROC),
                    ("LogiLcdUpdate\0",                  0 as FARPROC),
                    ("LogiLcdShutdown\0",                0 as FARPROC),
                    ("LogiLcdMonoSetBackground\0",       0 as FARPROC),
                    ("LogiLcdMonoSetText\0",             0 as FARPROC),
                    ("LogiLcdColorSetBackground\0",      0 as FARPROC),
                    ("LogiLcdColorSetTitle\0",           0 as FARPROC),
                    ("LogiLcdColorSetText\0",            0 as FARPROC),
                    ("LogiLcdColorSetBackgroundUDK\0",   0 as FARPROC),
                    ("LogiLcdColorResetBackgroundUDK\0", 0 as FARPROC),
                    ("LogiLcdMonoSetBackgroundUDK\0",    0 as FARPROC),
                    ("LogiLcdMonoResetBackgroundUDK\0",  0 as FARPROC),
                ];

                for i in symbols.iter_mut() {
                    i.1 = kernel32::GetProcAddress(handle, i.0.as_ptr() as *const i8);
                    if i.1.is_null() {
                        let error = Error::last_os_error();
                        kernel32::FreeLibrary(handle);
                        return Err(error);
                    }
                }

                Ok(LogitechLcd {
                    LogiLcdInit:                    mem::transmute(symbols[0].1),
                    LogiLcdIsConnected:             mem::transmute(symbols[1].1),
                    LogiLcdIsButtonPressed:         mem::transmute(symbols[2].1),
                    LogiLcdUpdate:                  mem::transmute(symbols[3].1),
                    LogiLcdShutdown:                mem::transmute(symbols[4].1),
                    LogiLcdMonoSetBackground:       mem::transmute(symbols[5].1),
                    LogiLcdMonoSetText:             mem::transmute(symbols[6].1),
                    LogiLcdColorSetBackground:      mem::transmute(symbols[7].1),
                    LogiLcdColorSetTitle:           mem::transmute(symbols[8].1),
                    LogiLcdColorSetText:            mem::transmute(symbols[9].1),
                    LogiLcdColorSetBackgroundUDK:   mem::transmute(symbols[10].1),
                    LogiLcdColorResetBackgroundUDK: mem::transmute(symbols[11].1),
                    LogiLcdMonoSetBackgroundUDK:    mem::transmute(symbols[12].1),
                    LogiLcdMonoResetBackgroundUDK:  mem::transmute(symbols[13].1),
                    _library: Library(handle),
                })
            }
        }
    }

    impl Drop for Library {
        fn drop(&mut self) {
            unsafe {
                kernel32::FreeLibrary(self.0);
            }
        }
    }
}<commit_msg>More doc changes<commit_after>#![allow(non_camel_case_types, non_snake_case)]

//! FFI bindings and loader for the Logitech LCD SDK
//!
//! [LogitechLcd](struct.LogitechLcd.html) will try to locate and load
//! `LogitechLcd.dll` at Runtime for dynamic linking.
//!

#[macro_use]
extern crate bitflags;

use std::os::raw::{c_int, c_uint};

/// Monochrome screen width in pixels.
pub const MONO_WIDTH:  usize = 160;

/// Monochrome screen hight in pixels.
pub const MONO_HEIGHT: usize = 43;

/// Color screen witdh in pixels.
pub const COLOR_WIDTH:  usize = 320;

/// Color screen hight in pixels.
pub const COLOR_HEIGHT: usize = 240;

bitflags! {
    /// Targeted lcd type.
    ///
    /// This library allows you to target either Mono or Color devices
    pub struct LcdType: u32 {
        /// Mono color.
        const MONO =  0x00000001;
        /// 32bit RGBA color.
        const COLOR = 0b00000010;
        /// Either mono or color.
        const EITHER = Self::MONO.bits | Self::COLOR.bits;
    }
}

bitflags! {
    /// Lcd Button bitmap.
    pub struct LcdButton: u32 {
        const MONO_BUTTON_0 = 0x00000001;
        const MONO_BUTTON_1 = 0x00000002;
        const MONO_BUTTON_2 = 0x00000004;
        const MONO_BUTTON_3 = 0x00000008;
        const MONO_BUTTON = Self::MONO_BUTTON_0.bits |
                            Self::MONO_BUTTON_1.bits |
                            Self::MONO_BUTTON_2.bits |
                            Self::MONO_BUTTON_3.bits;

        const COLOR_BUTTON_LEFT   = 0x00000100;
        const COLOR_BUTTON_RIGHT  = 0x00000200;
        const COLOR_BUTTON_OK     = 0x00000400;
        const COLOR_BUTTON_CANCEL = 0x00000800;
        const COLOR_BUTTON_UP     = 0x00001000;
        const COLOR_BUTTON_DOWN   = 0x00002000;
        const COLOR_BUTTON_MENU   = 0x00004000;
        const COLOR_BUTTON = Self::COLOR_BUTTON_LEFT.bits |
                             Self::COLOR_BUTTON_RIGHT.bits |
                             Self::COLOR_BUTTON_OK.bits |
                             Self::COLOR_BUTTON_CANCEL.bits |
                             Self::COLOR_BUTTON_UP.bits |
                             Self::COLOR_BUTTON_DOWN.bits |
                             Self::COLOR_BUTTON_MENU.bits;
    }
}

/// LogitechLcd library.
///
/// Contains library symbols/functions as fields. Will unload library when dropped.
pub struct LogitechLcd {
    // Main functions
    pub LogiLcdInit: unsafe extern "C" fn(friendlyName: *const u16, lcdType: c_uint) -> bool,
    pub LogiLcdIsConnected: unsafe extern "C" fn(lcdType: c_uint) -> bool,
    pub LogiLcdIsButtonPressed: unsafe extern "C" fn(button: c_uint) -> bool,
    pub LogiLcdUpdate: unsafe extern "C" fn(),
    pub LogiLcdShutdown: unsafe extern "C" fn(),

    // Monochrome LCD functions
    pub LogiLcdMonoSetBackground: unsafe extern "C" fn(monoBitmap: *const u8) -> bool,
    pub LogiLcdMonoSetText: unsafe extern "C" fn(lineNumber: c_int, text: *const u16) -> bool,

    // Color LCD functions
    pub LogiLcdColorSetBackground: unsafe extern "C" fn(colorBitmap: *const u8) -> bool,
    pub LogiLcdColorSetTitle: unsafe extern "C" fn(text: *const u16, red: c_int, green: c_int,
        blue: c_int) -> bool,
    pub LogiLcdColorSetText: unsafe extern "C" fn(lineNumber: c_int, text: *const u16, red: c_int,
        green: c_int, blue: c_int) -> bool,

    // UDK functions, use this only if working with UDK
    pub LogiLcdColorSetBackgroundUDK: unsafe extern "C" fn(partialBitmap: *const u8,
        arraySize: c_int) -> c_int,
    pub LogiLcdColorResetBackgroundUDK: unsafe extern "C" fn() -> c_int,
    pub LogiLcdMonoSetBackgroundUDK: unsafe extern "C" fn(partialBitmap: *const u8,
        arraySize: c_int) -> c_int,
    pub LogiLcdMonoResetBackgroundUDK: unsafe extern "C" fn() -> c_int,

    /// Library handle, will be freed on drop
    _library: platform::Library,
}

unsafe impl std::marker::Send for LogitechLcd {}

#[cfg(not(target_os = "windows"))]
mod platform {
    use super::LogitechLcd;
    use std::io::Error;

    pub struct Library;

    impl LogitechLcd {
        pub fn load() -> Result<LogitechLcd, Error> {
            unimplemented!();
        }
    }
}

#[cfg(target_os = "windows")]
mod platform {
    extern crate winapi;
    extern crate kernel32;
    extern crate winreg;

    use super::LogitechLcd;

    use self::winreg::RegKey;
    use self::winreg::enums::{HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT, KEY_READ};
    use self::winapi::minwindef::{HMODULE, FARPROC};

    use std::os::windows::ffi::OsStrExt;
    use std::ffi::OsStr;
    use std::io::Error;

    pub struct Library(HMODULE);

    const ERROR_MOD_NOT_FOUND: i32 = winapi::winerror::ERROR_MOD_NOT_FOUND as i32;

    /// Find `LogitechLcd.dll` in Windows registry using its CLSID
    fn dll_path_clsid() -> Result<Vec<u16>, Error> {
        let hkcl = RegKey::predef(HKEY_CLASSES_ROOT);
        let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);

        let mut dll_path = None;

        #[cfg(target_arch = "x86_64")]
        {
            match hkcl.open_subkey_with_flags(
                "CLSID\\{d0e790a5-01a7-49ae-ae0b-e986bdd0c21b}\\ServerBinary", KEY_READ)
            {
                Ok(key) => dll_path = key.get_value::<String, &str>("").ok(),
                Err(_) => {},
            }

            match hklm.open_subkey_with_flags(
                "SOFTWARE\\Classes\\CLSID\\{d0e790a5-01a7-49ae-ae0b-e986bdd0c21b}\\ServerBinary",
                KEY_READ)
            {
                Ok(key) => dll_path = key.get_value::<String, &str>("").ok(),
                Err(_) => {},
            }
        }

        #[cfg(target_arch = "x86")]
        {
            match hkcl.open_subkey_with_flags(
                "Wow6432Node\\CLSID\\{d0e790a5-01a7-49ae-ae0b-e986bdd0c21b}\\ServerBinary", KEY_READ)
            {
                Ok(key) => dll_path = key.get_value::<String, &str>("").ok(),
                Err(_) => {},
            }

            match hklm.open_subkey_with_flags(
                "SOFTWARE\\Classes\\Wow6432Node\\CLSID\\{d0e790a5-01a7-49ae-ae0b-e986bdd0c21b}\\ServerBinary",
                KEY_READ)
            {
                Ok(key) => dll_path = key.get_value::<String, &str>("").ok(),
                Err(_) => {},
            }

            match hklm.open_subkey_with_flags(
                "SOFTWARE\\Wow6432Node\\Classes\\CLSID\\{d0e790a5-01a7-49ae-ae0b-e986bdd0c21b}\\ServerBinary",
                KEY_READ)
            {
                Ok(key) => dll_path = key.get_value::<String, &str>("").ok(),
                Err(_) => {},
            }
        }

        match dll_path {
            // Convert to widestring and terminate with \0\0.
            Some(p) => Ok(OsStr::new(&p[..]).encode_wide().chain(Some(0)).collect::<Vec<u16>>()),
            None => Err(Error::from_raw_os_error(ERROR_MOD_NOT_FOUND)),
        }
    }

    unsafe fn load_lib() -> Result<HMODULE, Error> {
        match dll_path_clsid() {
            Ok(wide_path) => {
                let handle = kernel32::LoadLibraryW(wide_path.as_ptr());
                if handle.is_null() {
                    let error = Error::last_os_error();
                    let ecode = error.raw_os_error().unwrap();
                    // Fallthrough on ERROR_MOD_NOT_FOUND
                    if ecode != ERROR_MOD_NOT_FOUND {
                        return Err(error);
                    }
                } else {
                    return Ok(handle);
                }
            },
            Err(e) => {
                match e.raw_os_error() {
                    Some(ERROR_MOD_NOT_FOUND) => {},
                    _ => return Err(e),
                }
            },
        }

        // Convert to widestring and terminate with \0\0.
        let wide_name = OsStr::new("LogitechLcd.dll").encode_wide().chain(Some(0)).collect::<Vec<u16>>();
        let handle = kernel32::LoadLibraryW(wide_name.as_ptr());
        if handle.is_null() {
            Err(Error::last_os_error())
        } else {
            Ok(handle)
        }
    }

    impl LogitechLcd {
        /// Try to locate and load 'LogitechLcd.dll'.
        pub fn load() -> Result<LogitechLcd, Error> {
            use std::mem;

            unsafe {
                let handle = load_lib()?;

                let mut symbols = [
                    ("LogiLcdInit\0",                    0 as FARPROC),
                    ("LogiLcdIsConnected\0",             0 as FARPROC),
                    ("LogiLcdIsButtonPressed\0",         0 as FARPROC),
                    ("LogiLcdUpdate\0",                  0 as FARPROC),
                    ("LogiLcdShutdown\0",                0 as FARPROC),
                    ("LogiLcdMonoSetBackground\0",       0 as FARPROC),
                    ("LogiLcdMonoSetText\0",             0 as FARPROC),
                    ("LogiLcdColorSetBackground\0",      0 as FARPROC),
                    ("LogiLcdColorSetTitle\0",           0 as FARPROC),
                    ("LogiLcdColorSetText\0",            0 as FARPROC),
                    ("LogiLcdColorSetBackgroundUDK\0",   0 as FARPROC),
                    ("LogiLcdColorResetBackgroundUDK\0", 0 as FARPROC),
                    ("LogiLcdMonoSetBackgroundUDK\0",    0 as FARPROC),
                    ("LogiLcdMonoResetBackgroundUDK\0",  0 as FARPROC),
                ];

                for i in symbols.iter_mut() {
                    i.1 = kernel32::GetProcAddress(handle, i.0.as_ptr() as *const i8);
                    if i.1.is_null() {
                        let error = Error::last_os_error();
                        kernel32::FreeLibrary(handle);
                        return Err(error);
                    }
                }

                Ok(LogitechLcd {
                    LogiLcdInit:                    mem::transmute(symbols[0].1),
                    LogiLcdIsConnected:             mem::transmute(symbols[1].1),
                    LogiLcdIsButtonPressed:         mem::transmute(symbols[2].1),
                    LogiLcdUpdate:                  mem::transmute(symbols[3].1),
                    LogiLcdShutdown:                mem::transmute(symbols[4].1),
                    LogiLcdMonoSetBackground:       mem::transmute(symbols[5].1),
                    LogiLcdMonoSetText:             mem::transmute(symbols[6].1),
                    LogiLcdColorSetBackground:      mem::transmute(symbols[7].1),
                    LogiLcdColorSetTitle:           mem::transmute(symbols[8].1),
                    LogiLcdColorSetText:            mem::transmute(symbols[9].1),
                    LogiLcdColorSetBackgroundUDK:   mem::transmute(symbols[10].1),
                    LogiLcdColorResetBackgroundUDK: mem::transmute(symbols[11].1),
                    LogiLcdMonoSetBackgroundUDK:    mem::transmute(symbols[12].1),
                    LogiLcdMonoResetBackgroundUDK:  mem::transmute(symbols[13].1),
                    _library: Library(handle),
                })
            }
        }
    }

    impl Drop for Library {
        fn drop(&mut self) {
            unsafe {
                kernel32::FreeLibrary(self.0);
            }
        }
    }
}<|endoftext|>


<commit_before>use crate::file_read::read_file_all;

use std::io::Result;
use std::io::prelude::*;
use std::fmt::Debug;
use std::process::Command;

use serde_json;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
pub enum BuildConfiguration {
    Debug,
    Release,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct App {
    name : String,
    debug_path : String,
    release_path : String,
    opt_arg : String
}

impl App {
    pub fn name(&self) -> &str {
        &self.name
    }

    #[cfg(windows)]
    pub fn executable_name(&self) -> String {
        format!("{}.exe", self.name)
    }

    #[cfg(not(windows))]
    pub fn executable_name(&self) -> String {
        self.name.clone()
    }

    pub fn run(&self, config : &BuildConfiguration) -> std::io::Result<()> {
        let directory = match config {
            BuildConfiguration::Debug => &self.debug_path,
            BuildConfiguration::Release => &self.release_path
        };
        let file_name = format!("{}.exe", self.name());

        let mut start_server = Command::new("cmd.exe");
        start_server.arg("/c").arg("start").arg("/d").arg(directory).arg(file_name);
        if !self.opt_arg.is_empty() {
            start_server.arg(&self.opt_arg);
        }

        start_server.spawn()?;

        Ok(())
    }

    pub fn kill(&self) -> std::io::Result<()> {
        let file_name = format!("{}.exe", self.name());

        let mut kill_server = Command::new("cmd.exe");
        kill_server.arg("/c").arg("taskkill").arg("/im").arg(file_name);

        kill_server.spawn()?;

        Ok(())
    }
}

#[derive(Serialize, Deserialize)]
pub struct Apps {
    apps : Vec<App>
}

impl Apps {
    pub fn new_from_file(file_name : &str) -> Apps {
        let file_data = match read_file_all(file_name) {
            Err(e) => panic!(e),
            Ok(s) => s
        };

        match serde_json::from_str(file_data.as_str()) {
            Err(e) => panic!(e),
            Ok(val) => val
        }
    }

    pub fn app_list(&self) -> &Vec<App> {
        &self.apps
    }
}<commit_msg>run-rs: fix namings<commit_after>use crate::file_read::read_file_all;

use std::io::Result;
use std::io::prelude::*;
use std::fmt::Debug;
use std::process::Command;

use serde_json;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
pub enum BuildConfiguration {
    Debug,
    Release,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct App {
    name : String,
    debug_path : String,
    release_path : String,
    opt_arg : String
}

impl App {
    pub fn name(&self) -> &str {
        &self.name
    }

    #[cfg(windows)]
    pub fn executable_name(&self) -> String {
        format!("{}.exe", self.name)
    }

    #[cfg(not(windows))]
    pub fn executable_name(&self) -> String {
        self.name.clone()
    }

    pub fn run(&self, config : &BuildConfiguration) -> std::io::Result<()> {
        let directory = match config {
            BuildConfiguration::Debug => &self.debug_path,
            BuildConfiguration::Release => &self.release_path
        };
        let file_name = format!("{}.exe", self.name());

        let mut start_app = Command::new("cmd.exe");
        start_app.arg("/c").arg("start").arg("/d").arg(directory).arg(file_name);
        if !self.opt_arg.is_empty() {
            start_app.arg(&self.opt_arg);
        }

        start_app.spawn()?;

        Ok(())
    }

    pub fn kill(&self) -> std::io::Result<()> {
        let file_name = format!("{}.exe", self.name());

        let mut kill_app = Command::new("cmd.exe");
        kill_app.arg("/c").arg("taskkill").arg("/im").arg(file_name);

        kill_app.spawn()?;

        Ok(())
    }
}

#[derive(Serialize, Deserialize)]
pub struct Apps {
    apps : Vec<App>
}

impl Apps {
    pub fn new_from_file(file_name : &str) -> Apps {
        let file_data = match read_file_all(file_name) {
            Err(e) => panic!(e),
            Ok(s) => s
        };

        match serde_json::from_str(file_data.as_str()) {
            Err(e) => panic!(e),
            Ok(val) => val
        }
    }

    pub fn app_list(&self) -> &Vec<App> {
        &self.apps
    }
}<|endoftext|>


<commit_before>// Not in interpret to make sure we do not use private implementation details

use std::convert::TryFrom;

use rustc_hir::Mutability;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::{
    mir::{self, interpret::ConstAlloc},
    ty::ScalarInt,
};
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};

use crate::interpret::{
    intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, MPlaceTy, MemPlaceMeta, Scalar,
};

mod error;
mod eval_queries;
mod fn_queries;
mod machine;

pub use error::*;
pub use eval_queries::*;
pub use fn_queries::*;
pub use machine::*;

pub(crate) fn const_caller_location(
    tcx: TyCtxt<'tcx>,
    (file, line, col): (Symbol, u32, u32),
) -> ConstValue<'tcx> {
    trace!("const_caller_location: {}:{}:{}", file, line, col);
    let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);

    let loc_place = ecx.alloc_caller_location(file, line, col);
    if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
        bug!("intern_const_alloc_recursive should not error in this case")
    }
    ConstValue::Scalar(loc_place.ptr)
}

/// Convert an evaluated constant to a type level constant
pub(crate) fn const_to_valtree<'tcx>(
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    raw: ConstAlloc<'tcx>,
) -> Option<ty::ValTree<'tcx>> {
    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
    let place = ecx.raw_const_to_mplace(raw).unwrap();
    const_to_valtree_inner(&ecx, &place)
}

fn const_to_valtree_inner<'tcx>(
    ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
    place: &MPlaceTy<'tcx>,
) -> Option<ty::ValTree<'tcx>> {
    let branches = |n, variant| {
        let place = match variant {
            Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
            None => *place,
        };
        let variant =
            variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32()))));
        let fields = (0..n).map(|i| {
            let field = ecx.mplace_field(&place, i).unwrap();
            const_to_valtree_inner(ecx, &field)
        });
        Some(ty::ValTree::Branch(
            ecx.tcx
                .arena
                .alloc_from_iter(variant.into_iter().chain(fields).collect::<Option<Vec<_>>>()?),
        ))
    };
    match place.layout.ty.kind() {
        ty::FnDef(..) => Some(ty::ValTree::zst()),
        ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
            let val = ecx.read_immediate(&place.into()).unwrap();
            let val = val.to_scalar().unwrap();
            Some(ty::ValTree::Leaf(val.assert_int()))
        }

        // Raw pointers are not allowed in type level constants, as raw pointers cannot be treated
        // like references. If we looked behind the raw pointer, we may be breaking the meaning of
        // the raw pointer. Equality on raw pointers is performed on the pointer and not on the pointee,
        // and we cannot guarantee any kind of pointer stability in the type system.
        // Technically we could allow function pointers, but they are not guaranteed to be the
        // same as the function pointers at runtime.
        ty::FnPtr(_) | ty::RawPtr(_) => None,
        ty::Ref(..) => unimplemented!("need to use deref_const"),

        ty::Dynamic(..) => unimplemented!(
            "for trait objects we must look at the vtable and figure out the real type"
        ),

        ty::Slice(_) | ty::Str => {
            unimplemented!("need to find the backing data of the slice/str and recurse on that")
        }
        ty::Tuple(substs) => branches(substs.len(), None),
        ty::Array(_, len) => branches(usize::try_from(len.eval_usize(ecx.tcx.tcx, ecx.param_env)).unwrap(), None),

        ty::Adt(def, _) => {
            if def.variants.is_empty() {
                // Uninhabited
                return None;
            }

            let variant = ecx.read_discriminant(&place.into()).unwrap().1;

            branches(def.variants[variant].fields.len(), Some(variant))
        }

        ty::Never
        | ty::Error(_)
        | ty::Foreign(..)
        | ty::Infer(ty::FreshIntTy(_))
        | ty::Infer(ty::FreshFloatTy(_))
        | ty::Projection(..)
        | ty::Param(_)
        | ty::Bound(..)
        | ty::Placeholder(..)
        // FIXME(oli-obk): we could look behind opaque types
        | ty::Opaque(..)
        | ty::Infer(_)
        // FIXME(oli-obk): we can probably encode closures just like structs
        | ty::Closure(..)
        | ty::Generator(..)
        | ty::GeneratorWitness(..) => None,
    }
}

/// This function uses `unwrap` copiously, because an already validated constant
/// must have valid fields and can thus never fail outside of compiler bugs. However, it is
/// invoked from the pretty printer, where it can receive enums with no variants and e.g.
/// `read_discriminant` needs to be able to handle that.
pub(crate) fn destructure_const<'tcx>(
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    val: &'tcx ty::Const<'tcx>,
) -> mir::DestructuredConst<'tcx> {
    trace!("destructure_const: {:?}", val);
    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
    let op = ecx.const_to_op(val, None).unwrap();

    // We go to `usize` as we cannot allocate anything bigger anyway.
    let (field_count, variant, down) = match val.ty.kind() {
        ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op),
        ty::Adt(def, _) if def.variants.is_empty() => {
            return mir::DestructuredConst { variant: None, fields: &[] };
        }
        ty::Adt(def, _) => {
            let variant = ecx.read_discriminant(&op).unwrap().1;
            let down = ecx.operand_downcast(&op, variant).unwrap();
            (def.variants[variant].fields.len(), Some(variant), down)
        }
        ty::Tuple(substs) => (substs.len(), None, op),
        _ => bug!("cannot destructure constant {:?}", val),
    };

    let fields_iter = (0..field_count).map(|i| {
        let field_op = ecx.operand_field(&down, i).unwrap();
        let val = op_to_const(&ecx, &field_op);
        ty::Const::from_value(tcx, val, field_op.layout.ty)
    });
    let fields = tcx.arena.alloc_from_iter(fields_iter);

    mir::DestructuredConst { variant, fields }
}

pub(crate) fn deref_const<'tcx>(
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    val: &'tcx ty::Const<'tcx>,
) -> &'tcx ty::Const<'tcx> {
    trace!("deref_const: {:?}", val);
    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
    let op = ecx.const_to_op(val, None).unwrap();
    let mplace = ecx.deref_operand(&op).unwrap();
    if let Scalar::Ptr(ptr) = mplace.ptr {
        assert_eq!(
            ecx.memory.get_raw(ptr.alloc_id).unwrap().mutability,
            Mutability::Not,
            "deref_const cannot be used with mutable allocations as \
            that could allow pattern matching to observe mutable statics",
        );
    }

    let ty = match mplace.meta {
        MemPlaceMeta::None => mplace.layout.ty,
        MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
        // In case of unsized types, figure out the real type behind.
        MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
            ty::Str => bug!("there's no sized equivalent of a `str`"),
            ty::Slice(elem_ty) => tcx.mk_array(elem_ty, scalar.to_machine_usize(&tcx).unwrap()),
            _ => bug!(
                "type {} should not have metadata, but had {:?}",
                mplace.layout.ty,
                mplace.meta
            ),
        },
    };

    tcx.mk_const(ty::Const { val: ty::ConstKind::Value(op_to_const(&ecx, &mplace.into())), ty })
}
<commit_msg>We won't support trait object constants in type level constants for the forseeable future<commit_after>// Not in interpret to make sure we do not use private implementation details

use std::convert::TryFrom;

use rustc_hir::Mutability;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::{
    mir::{self, interpret::ConstAlloc},
    ty::ScalarInt,
};
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};

use crate::interpret::{
    intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, MPlaceTy, MemPlaceMeta, Scalar,
};

mod error;
mod eval_queries;
mod fn_queries;
mod machine;

pub use error::*;
pub use eval_queries::*;
pub use fn_queries::*;
pub use machine::*;

pub(crate) fn const_caller_location(
    tcx: TyCtxt<'tcx>,
    (file, line, col): (Symbol, u32, u32),
) -> ConstValue<'tcx> {
    trace!("const_caller_location: {}:{}:{}", file, line, col);
    let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);

    let loc_place = ecx.alloc_caller_location(file, line, col);
    if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
        bug!("intern_const_alloc_recursive should not error in this case")
    }
    ConstValue::Scalar(loc_place.ptr)
}

/// Convert an evaluated constant to a type level constant
pub(crate) fn const_to_valtree<'tcx>(
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    raw: ConstAlloc<'tcx>,
) -> Option<ty::ValTree<'tcx>> {
    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
    let place = ecx.raw_const_to_mplace(raw).unwrap();
    const_to_valtree_inner(&ecx, &place)
}

fn const_to_valtree_inner<'tcx>(
    ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
    place: &MPlaceTy<'tcx>,
) -> Option<ty::ValTree<'tcx>> {
    let branches = |n, variant| {
        let place = match variant {
            Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
            None => *place,
        };
        let variant =
            variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32()))));
        let fields = (0..n).map(|i| {
            let field = ecx.mplace_field(&place, i).unwrap();
            const_to_valtree_inner(ecx, &field)
        });
        Some(ty::ValTree::Branch(
            ecx.tcx
                .arena
                .alloc_from_iter(variant.into_iter().chain(fields).collect::<Option<Vec<_>>>()?),
        ))
    };
    match place.layout.ty.kind() {
        ty::FnDef(..) => Some(ty::ValTree::zst()),
        ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
            let val = ecx.read_immediate(&place.into()).unwrap();
            let val = val.to_scalar().unwrap();
            Some(ty::ValTree::Leaf(val.assert_int()))
        }

        // Raw pointers are not allowed in type level constants, as raw pointers cannot be treated
        // like references. If we looked behind the raw pointer, we may be breaking the meaning of
        // the raw pointer. Equality on raw pointers is performed on the pointer and not on the pointee,
        // and we cannot guarantee any kind of pointer stability in the type system.
        // Technically we could allow function pointers, but they are not guaranteed to be the
        // same as the function pointers at runtime.
        ty::FnPtr(_) | ty::RawPtr(_) => None,
        ty::Ref(..) => unimplemented!("need to use deref_const"),

        // Trait objects are not allowed in type level constants, as we have no concept for
        // resolving their backing type, even if we can do that at const eval time. We may want to consider
        // adding a `ValTree::DownCast(Ty<'tcx>, Box<ValTree>)` in the future, but I don't even know the
        // questions such a concept would open up, so an RFC would probably be good for this.
        ty::Dynamic(..) => None,

        ty::Slice(_) | ty::Str => {
            unimplemented!("need to find the backing data of the slice/str and recurse on that")
        }
        ty::Tuple(substs) => branches(substs.len(), None),
        ty::Array(_, len) => branches(usize::try_from(len.eval_usize(ecx.tcx.tcx, ecx.param_env)).unwrap(), None),

        ty::Adt(def, _) => {
            if def.variants.is_empty() {
                // Uninhabited
                return None;
            }

            let variant = ecx.read_discriminant(&place.into()).unwrap().1;

            branches(def.variants[variant].fields.len(), Some(variant))
        }

        ty::Never
        | ty::Error(_)
        | ty::Foreign(..)
        | ty::Infer(ty::FreshIntTy(_))
        | ty::Infer(ty::FreshFloatTy(_))
        | ty::Projection(..)
        | ty::Param(_)
        | ty::Bound(..)
        | ty::Placeholder(..)
        // FIXME(oli-obk): we could look behind opaque types
        | ty::Opaque(..)
        | ty::Infer(_)
        // FIXME(oli-obk): we can probably encode closures just like structs
        | ty::Closure(..)
        | ty::Generator(..)
        | ty::GeneratorWitness(..) => None,
    }
}

/// This function uses `unwrap` copiously, because an already validated constant
/// must have valid fields and can thus never fail outside of compiler bugs. However, it is
/// invoked from the pretty printer, where it can receive enums with no variants and e.g.
/// `read_discriminant` needs to be able to handle that.
pub(crate) fn destructure_const<'tcx>(
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    val: &'tcx ty::Const<'tcx>,
) -> mir::DestructuredConst<'tcx> {
    trace!("destructure_const: {:?}", val);
    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
    let op = ecx.const_to_op(val, None).unwrap();

    // We go to `usize` as we cannot allocate anything bigger anyway.
    let (field_count, variant, down) = match val.ty.kind() {
        ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op),
        ty::Adt(def, _) if def.variants.is_empty() => {
            return mir::DestructuredConst { variant: None, fields: &[] };
        }
        ty::Adt(def, _) => {
            let variant = ecx.read_discriminant(&op).unwrap().1;
            let down = ecx.operand_downcast(&op, variant).unwrap();
            (def.variants[variant].fields.len(), Some(variant), down)
        }
        ty::Tuple(substs) => (substs.len(), None, op),
        _ => bug!("cannot destructure constant {:?}", val),
    };

    let fields_iter = (0..field_count).map(|i| {
        let field_op = ecx.operand_field(&down, i).unwrap();
        let val = op_to_const(&ecx, &field_op);
        ty::Const::from_value(tcx, val, field_op.layout.ty)
    });
    let fields = tcx.arena.alloc_from_iter(fields_iter);

    mir::DestructuredConst { variant, fields }
}

pub(crate) fn deref_const<'tcx>(
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    val: &'tcx ty::Const<'tcx>,
) -> &'tcx ty::Const<'tcx> {
    trace!("deref_const: {:?}", val);
    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
    let op = ecx.const_to_op(val, None).unwrap();
    let mplace = ecx.deref_operand(&op).unwrap();
    if let Scalar::Ptr(ptr) = mplace.ptr {
        assert_eq!(
            ecx.memory.get_raw(ptr.alloc_id).unwrap().mutability,
            Mutability::Not,
            "deref_const cannot be used with mutable allocations as \
            that could allow pattern matching to observe mutable statics",
        );
    }

    let ty = match mplace.meta {
        MemPlaceMeta::None => mplace.layout.ty,
        MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
        // In case of unsized types, figure out the real type behind.
        MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
            ty::Str => bug!("there's no sized equivalent of a `str`"),
            ty::Slice(elem_ty) => tcx.mk_array(elem_ty, scalar.to_machine_usize(&tcx).unwrap()),
            _ => bug!(
                "type {} should not have metadata, but had {:?}",
                mplace.layout.ty,
                mplace.meta
            ),
        },
    };

    tcx.mk_const(ty::Const { val: ty::ConstKind::Value(op_to_const(&ecx, &mplace.into())), ty })
}
<|endoftext|>


<commit_before>// A unit struct without resources
#[derive(Debug, Clone, Copy)]
struct Nil;

// A tuple struct with resources that implements the `Clone` trait
#[derive(Clone, Debug)]
struct Pair(Box<i32>, Box<i32>);

fn main() {
    // Instantiate `Nil`
    let nil = Nil;
    // Copy `Nil`, there are no resources to move
    let copied_nil = nil;

    // Both `Nil`s can be used independently
    println!("original: {:?}", nil);
    println!("copy: {:?}", copied_nil);

    // Instantiate `Pair`
    let pair = Pair(Box::new(1), Box::new(2));
    println!("original: {:?}", pair);

    // Copy `pair` into `moved_pair`, moves resources
    let moved_pair = pair;
    println!("copy: {:?}", moved_pair);

    // Error! `pair` has lost it resources
    //println!("original: {:?}", pair);
    // TODO ^ Try uncommenting this line

    // Clone `moved_pair` into `cloned_pair` (resources are included)
    let cloned_pair = moved_pair.clone();
    // Drop the original pair using std::mem::drop
    drop(moved_pair);

    // Error! `moved_pair` has been dropped
    //println!("copy: {:?}", moved_pair);
    // TODO ^ Try uncommenting this line

    // The result from .clone() can still be used!
    println!("clone: {:?}", cloned_pair);
}
<commit_msg>trait/clone: fix typo in comment<commit_after>// A unit struct without resources
#[derive(Debug, Clone, Copy)]
struct Nil;

// A tuple struct with resources that implements the `Clone` trait
#[derive(Clone, Debug)]
struct Pair(Box<i32>, Box<i32>);

fn main() {
    // Instantiate `Nil`
    let nil = Nil;
    // Copy `Nil`, there are no resources to move
    let copied_nil = nil;

    // Both `Nil`s can be used independently
    println!("original: {:?}", nil);
    println!("copy: {:?}", copied_nil);

    // Instantiate `Pair`
    let pair = Pair(Box::new(1), Box::new(2));
    println!("original: {:?}", pair);

    // Copy `pair` into `moved_pair`, moves resources
    let moved_pair = pair;
    println!("copy: {:?}", moved_pair);

    // Error! `pair` has lost its resources
    //println!("original: {:?}", pair);
    // TODO ^ Try uncommenting this line

    // Clone `moved_pair` into `cloned_pair` (resources are included)
    let cloned_pair = moved_pair.clone();
    // Drop the original pair using std::mem::drop
    drop(moved_pair);

    // Error! `moved_pair` has been dropped
    //println!("copy: {:?}", moved_pair);
    // TODO ^ Try uncommenting this line

    // The result from .clone() can still be used!
    println!("clone: {:?}", cloned_pair);
}
<|endoftext|>


<commit_before>//! The CXX code generator for constructing and compiling C++ code.
//!
//! This is intended to be used from Cargo build scripts to execute CXX's
//! C++ code generator, set up any additional compiler flags depending on
//! the use case, and make the C++ compiler invocation.
//!
//!

//!
//! # Example
//!
//! Example of a canonical Cargo build script that builds a CXX bridge:
//!
//! ```no_run
//! // build.rs
//!
//! fn main() {
//!     cxx_build::bridge("src/main.rs")
//!         .file("../demo-cxx/demo.cc")
//!         .flag_if_supported("-std=c++11")
//!         .compile("cxxbridge-demo");
//!
//!     println!("cargo:rerun-if-changed=src/main.rs");
//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
//! }
//! ```
//!
//! A runnable working setup with this build script is shown in the
//! *demo-rs* and *demo-cxx* directories of [https://github.com/dtolnay/cxx].
//!
//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
//!
//!

//!
//! # Alternatives
//!
//! For use in non-Cargo builds like Bazel or Buck, CXX provides an
//! alternate way of invoking the C++ code generator as a standalone command
//! line tool. The tool is packaged as the `cxxbridge-cmd` crate.
//!
//! ```bash
//! $ cargo install cxxbridge-cmd  # or build it from the repo
//!
//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
//! $ cxxbridge src/main.rs > path/to/mybridge.cc
//! ```

#![allow(
    clippy::inherent_to_string,
    clippy::needless_doctest_main,
    clippy::new_without_default,
    clippy::toplevel_ref_arg
)]

mod error;
mod gen;
mod paths;
mod syntax;

use crate::error::Result;
use crate::gen::error::report;
use crate::gen::{fs, Opt};
use cc::Build;
use std::io::{self, Write};
use std::iter;
use std::path::Path;
use std::process;

/// This returns a [`cc::Build`] on which you should continue to set up any
/// additional source files or compiler flags, and lastly call its [`compile`]
/// method to execute the C++ build.
///
/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
#[must_use]
pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
    bridges(iter::once(rust_source_file))
}

/// `cxx_build::bridge` but for when more than one file contains a
/// #\[cxx::bridge\] module.
///
/// ```no_run
/// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
/// cxx_build::bridges(source_files)
///     .file("../demo-cxx/demo.cc")
///     .flag_if_supported("-std=c++11")
///     .compile("cxxbridge-demo");
/// ```
pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
    let ref mut rust_source_files = rust_source_files.into_iter();
    build(rust_source_files).unwrap_or_else(|err| {
        let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
        process::exit(1);
    })
}

fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
    let mut build = paths::cc_build();
    build.cpp(true);
    build.cpp_link_stdlib(None); // linked via link-cplusplus crate
    write_header()?;

    for path in rust_source_files {
        generate_bridge(&mut build, path.as_ref())?;
    }

    Ok(build)
}

fn write_header() -> Result<()> {
    let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
    let _ = fs::create_dir_all(cxx_h.parent().unwrap());
    let _ = fs::remove_file(cxx_h);
    let _ = fs::write(cxx_h, gen::include::HEADER);
    Ok(())
}

fn generate_bridge(build: &mut Build, rust_source_file: &Path) -> Result<()> {
    let opt = Opt::default();
    let generated = gen::generate_from_path(rust_source_file, &opt);

    let header_path = paths::out_with_extension(rust_source_file, ".h")?;
    fs::create_dir_all(header_path.parent().unwrap())?;
    fs::write(&header_path, generated.header)?;
    paths::symlink_header(&header_path, rust_source_file);

    let implementation_path = paths::out_with_extension(rust_source_file, ".cc")?;
    fs::write(&implementation_path, generated.implementation)?;
    build.file(&implementation_path);
    Ok(())
}
<commit_msg>Avoid bumping modified time of existing up to date files<commit_after>//! The CXX code generator for constructing and compiling C++ code.
//!
//! This is intended to be used from Cargo build scripts to execute CXX's
//! C++ code generator, set up any additional compiler flags depending on
//! the use case, and make the C++ compiler invocation.
//!
//!

//!
//! # Example
//!
//! Example of a canonical Cargo build script that builds a CXX bridge:
//!
//! ```no_run
//! // build.rs
//!
//! fn main() {
//!     cxx_build::bridge("src/main.rs")
//!         .file("../demo-cxx/demo.cc")
//!         .flag_if_supported("-std=c++11")
//!         .compile("cxxbridge-demo");
//!
//!     println!("cargo:rerun-if-changed=src/main.rs");
//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
//! }
//! ```
//!
//! A runnable working setup with this build script is shown in the
//! *demo-rs* and *demo-cxx* directories of [https://github.com/dtolnay/cxx].
//!
//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
//!
//!

//!
//! # Alternatives
//!
//! For use in non-Cargo builds like Bazel or Buck, CXX provides an
//! alternate way of invoking the C++ code generator as a standalone command
//! line tool. The tool is packaged as the `cxxbridge-cmd` crate.
//!
//! ```bash
//! $ cargo install cxxbridge-cmd  # or build it from the repo
//!
//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
//! $ cxxbridge src/main.rs > path/to/mybridge.cc
//! ```

#![allow(
    clippy::inherent_to_string,
    clippy::needless_doctest_main,
    clippy::new_without_default,
    clippy::toplevel_ref_arg
)]

mod error;
mod gen;
mod paths;
mod syntax;

use crate::error::Result;
use crate::gen::error::report;
use crate::gen::{fs, Opt};
use cc::Build;
use std::io::{self, Write};
use std::iter;
use std::path::Path;
use std::process;

/// This returns a [`cc::Build`] on which you should continue to set up any
/// additional source files or compiler flags, and lastly call its [`compile`]
/// method to execute the C++ build.
///
/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
#[must_use]
pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
    bridges(iter::once(rust_source_file))
}

/// `cxx_build::bridge` but for when more than one file contains a
/// #\[cxx::bridge\] module.
///
/// ```no_run
/// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
/// cxx_build::bridges(source_files)
///     .file("../demo-cxx/demo.cc")
///     .flag_if_supported("-std=c++11")
///     .compile("cxxbridge-demo");
/// ```
pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
    let ref mut rust_source_files = rust_source_files.into_iter();
    build(rust_source_files).unwrap_or_else(|err| {
        let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
        process::exit(1);
    })
}

fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
    let mut build = paths::cc_build();
    build.cpp(true);
    build.cpp_link_stdlib(None); // linked via link-cplusplus crate
    write_header()?;

    for path in rust_source_files {
        generate_bridge(&mut build, path.as_ref())?;
    }

    Ok(build)
}

fn write_header() -> Result<()> {
    let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
    let _ = write(cxx_h, gen::include::HEADER.as_bytes());
    Ok(())
}

fn generate_bridge(build: &mut Build, rust_source_file: &Path) -> Result<()> {
    let opt = Opt::default();
    let generated = gen::generate_from_path(rust_source_file, &opt);

    let header_path = paths::out_with_extension(rust_source_file, ".h")?;
    fs::create_dir_all(header_path.parent().unwrap())?;
    write(&header_path, &generated.header)?;
    paths::symlink_header(&header_path, rust_source_file);

    let implementation_path = paths::out_with_extension(rust_source_file, ".cc")?;
    write(&implementation_path, &generated.implementation)?;
    build.file(&implementation_path);
    Ok(())
}

fn write(path: &Path, content: &[u8]) -> Result<()> {
    if path.exists() {
        if let Ok(existing) = fs::read(path) {
            if existing == content {
                // Avoid bumping modified time with unchanged contents.
                return Ok(());
            }
        }
        let _ = fs::remove_file(path);
    } else {
        let _ = fs::create_dir_all(path.parent().unwrap());
    }
    fs::write(path, content)?;
    Ok(())
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use browser_host::{ServoCefBrowserHost, ServoCefBrowserHostExtensions};
use eutil::Downcast;
use frame::{ServoCefFrame, ServoCefFrameExtensions};
use interfaces::{CefBrowser, CefBrowserHost, CefClient, CefFrame, CefRequestContext};
use interfaces::{cef_browser_t, cef_browser_host_t, cef_client_t, cef_frame_t};
use interfaces::{cef_request_context_t};
use servo::Browser;
use types::{cef_browser_settings_t, cef_string_t, cef_window_info_t, cef_window_handle_t};
use util::thread::spawn_named;
use window;
use wrappers::CefWrap;

use compositing::windowing::{WindowNavigateMsg, WindowEvent};
use glutin_app;
use libc::c_int;
use std::cell::{Cell, RefCell, BorrowState};
use std::ptr;
use std::rc::Rc;
use std::sync::atomic::{AtomicIsize, Ordering};

thread_local!(pub static ID_COUNTER: AtomicIsize = AtomicIsize::new(0));
thread_local!(pub static BROWSERS: RefCell<Vec<CefBrowser>> = RefCell::new(vec!()));

pub enum ServoBrowser {
    Invalid,
    OnScreen(Browser),
    OffScreen(Browser),
}

impl ServoBrowser {
    fn handle_event(&mut self, event: WindowEvent) {
        match *self {
            ServoBrowser::OnScreen(ref mut browser) => { browser.handle_events(vec![event]); }
            ServoBrowser::OffScreen(ref mut browser) => { browser.handle_events(vec![event]); }
            ServoBrowser::Invalid => {}
        }
    }

    pub fn request_title_for_main_frame(&self) {
        match *self {
            ServoBrowser::OnScreen(ref browser) => browser.request_title_for_main_frame(),
            ServoBrowser::OffScreen(ref browser) => browser.request_title_for_main_frame(),
            ServoBrowser::Invalid => {}
        }
    }

    pub fn pinch_zoom_level(&self) -> f32 {
        match *self {
            ServoBrowser::OnScreen(ref browser) => browser.pinch_zoom_level(),
            ServoBrowser::OffScreen(ref browser) => browser.pinch_zoom_level(),
            ServoBrowser::Invalid => 1.0,
        }
    }
}

cef_class_impl! {
    ServoCefBrowser : CefBrowser, cef_browser_t {
        fn get_host(&this,) -> *mut cef_browser_host_t {{
            this.downcast().host.clone()
        }}

        fn can_go_back(&this,) -> c_int {{
            this.downcast().back.get() as c_int
        }}

        fn can_go_forward(&this,) -> c_int {{
            this.downcast().forward.get() as c_int
        }}

        fn is_loading(&this,) -> c_int {{
            this.downcast().loading.get() as c_int
        }}

        fn go_back(&this,) -> () {{
            this.send_window_event(WindowEvent::Navigation(WindowNavigateMsg::Back));
        }}

        fn go_forward(&this,) -> () {{
            this.send_window_event(WindowEvent::Navigation(WindowNavigateMsg::Forward));
        }}

        // Returns the main (top-level) frame for the browser window.
        fn get_main_frame(&this,) -> *mut cef_frame_t {{
            this.downcast().frame.clone()
        }}

        fn get_identifier(&this,) -> c_int {{
            this.downcast().id as c_int
        }}
    }
}

pub struct ServoCefBrowser {
    /// A reference to the browser's primary frame.
    pub frame: CefFrame,
    /// A reference to the browser's host.
    pub host: CefBrowserHost,
    /// A reference to the browser client.
    pub client: CefClient,
    /// the glutin window when using windowed rendering
    pub window: Option<Rc<glutin_app::window::Window>>,
    /// Whether the on-created callback has fired yet.
    pub callback_executed: Cell<bool>,
    /// whether the browser can navigate back
    pub back: Cell<bool>,
    /// whether the browser can navigate forward
    pub forward: Cell<bool>,
    /// whether the browser is loading
    pub loading: Cell<bool>,
    /// a vec of favicon urls for the current page
    pub favicons: RefCell<Vec<String>>,
    /// the display system window handle: only to be used with host.get_window_handle()
    window_handle: cef_window_handle_t,

    id: isize,
    servo_browser: RefCell<ServoBrowser>,
    message_queue: RefCell<Vec<WindowEvent>>,
}

impl ServoCefBrowser {
    pub fn new(window_info: &cef_window_info_t, client: CefClient) -> ServoCefBrowser {
        let frame = ServoCefFrame::new().as_cef_interface();
        let host = ServoCefBrowserHost::new(client.clone()).as_cef_interface();
        let mut window_handle: cef_window_handle_t = get_null_window_handle();

        let (glutin_window, servo_browser) = if window_info.windowless_rendering_enabled == 0 {
            let parent_window = glutin_app::WindowID::new(window_info.parent_window as *mut _);
            let glutin_window = glutin_app::create_window(Some(parent_window));
            let servo_browser = Browser::new(glutin_window.clone());
            window_handle = glutin_window.platform_window().window as cef_window_handle_t;
            (Some(glutin_window), ServoBrowser::OnScreen(servo_browser))
        } else {
            (None, ServoBrowser::Invalid)
        };

        let id = ID_COUNTER.with(|counter| {
            counter.fetch_add(1, Ordering::SeqCst)
        });

        ServoCefBrowser {
            frame: frame,
            host: host,
            client: client,
            window: glutin_window,
            callback_executed: Cell::new(false),
            servo_browser: RefCell::new(servo_browser),
            message_queue: RefCell::new(vec!()),
            id: id,
            back: Cell::new(false),
            forward: Cell::new(false),
            loading: Cell::new(false),
            favicons: RefCell::new(vec!()),
            window_handle: window_handle,
        }
    }
}

pub trait ServoCefBrowserExtensions {
    fn init(&self, window_info: &cef_window_info_t);
    fn send_window_event(&self, event: WindowEvent);
    fn request_title_for_main_frame(&self);
    fn pinch_zoom_level(&self) -> f32;
}

impl ServoCefBrowserExtensions for CefBrowser {
    fn init(&self, window_info: &cef_window_info_t) {
        if window_info.windowless_rendering_enabled != 0 {
            let window = window::Window::new(window_info.width, window_info.height);
            window.set_browser(self.clone());
            let servo_browser = Browser::new(window.clone());
            *self.downcast().servo_browser.borrow_mut() = ServoBrowser::OffScreen(servo_browser);
        }

        self.downcast().host.set_browser((*self).clone());
        self.downcast().frame.set_browser((*self).clone());
        if window_info.windowless_rendering_enabled == 0 {
            self.downcast().host.initialize_compositing();
        }
    }

    fn send_window_event(&self, event: WindowEvent) {
        self.downcast().message_queue.borrow_mut().push(event);

        loop {
            match self.downcast().servo_browser.borrow_state() {
                BorrowState::Unused => {
                    let event = match self.downcast().message_queue.borrow_mut().pop() {
                        None => return,
                        Some(event) => event,
                    };
                    self.downcast().servo_browser.borrow_mut().handle_event(event);
                }
                _ => {
                    // We're trying to send an event while processing another one. This will
                    // cause general badness, so queue up that event instead of immediately
                    // processing it.
                    break
                }
            }
        }
    }

    fn request_title_for_main_frame(&self) {
        self.downcast().servo_browser.borrow().request_title_for_main_frame()
    }

    fn pinch_zoom_level(&self) -> f32 {
        self.downcast().servo_browser.borrow().pinch_zoom_level()
    }
}

#[cfg(target_os="macos")]
pub fn get_null_window_handle() -> cef_window_handle_t {
    ptr::null_mut()
}
#[cfg(target_os="linux")]
pub fn get_null_window_handle() -> cef_window_handle_t {
    0
}

pub fn update() {
    BROWSERS.with(|browsers| {
        for browser in &*browsers.borrow() {
            if browser.downcast().callback_executed.get() == false {
                browser_callback_after_created(browser.clone());
            }
            let mut events = match browser.downcast().window {
                Some(ref win) => win.wait_events(),
                None => vec![WindowEvent::Idle]
            };
            loop {
               match events.pop() {
                   Some(event) => browser.send_window_event(event),
                   None => break
               }
            }
        }
    });
}

pub fn close(browser: CefBrowser) {
    BROWSERS.with(|browsers| {
        let mut browsers = browsers.borrow_mut();
        browsers.iter()
                .position(|&ref n| n.downcast().id == browser.downcast().id)
                .map(|e| browsers.remove(e));
    });
}

pub fn get_window(browser: &CefBrowser) -> cef_window_handle_t {
    browser.downcast().window_handle
}

pub fn browser_callback_after_created(browser: CefBrowser) {
    if browser.downcast().client.is_null_cef_object() {
        return
    }
    let client = browser.downcast().client.clone();
    let life_span_handler = client.get_life_span_handler();
    if life_span_handler.is_not_null_cef_object() {
        life_span_handler.on_after_created(browser.clone());
    }
    browser.downcast().callback_executed.set(true);
    browser.downcast().frame.load();
    browser.downcast().host.was_resized();
}

fn browser_host_create(window_info: &cef_window_info_t,
                       client: CefClient,
                       url: *const cef_string_t,
                       callback_executed: bool)
                       -> CefBrowser {
    let browser = ServoCefBrowser::new(window_info, client).as_cef_interface();
    browser.init(window_info);
    if url != ptr::null() {
       unsafe { browser.downcast().frame.set_url(CefWrap::to_rust(url)); }
    }
    if callback_executed {
        browser_callback_after_created(browser.clone());
    }
    BROWSERS.with(|browsers| {
        browsers.borrow_mut().push(browser.clone());
    });
    browser
}

cef_static_method_impls! {
    fn cef_browser_host_create_browser(window_info: *const cef_window_info_t,
                                       client: *mut cef_client_t,
                                       url: *const cef_string_t,
                                       _browser_settings: *const cef_browser_settings_t,
                                       _request_context: *mut cef_request_context_t)
                                       -> c_int {{
        let client: CefClient = client;
        let _browser_settings: &cef_browser_settings_t = _browser_settings;
        let _request_context: CefRequestContext = _request_context;
        browser_host_create(window_info, client, url, false);
        spawn_named("async_browser_creation".to_owned(), move || {
            window::app_wakeup();
        });
        1i32
    }}
    fn cef_browser_host_create_browser_sync(window_info: *const cef_window_info_t,
                                            client: *mut cef_client_t,
                                            url: *const cef_string_t,
                                            _browser_settings: *const cef_browser_settings_t,
                                            _request_context: *mut cef_request_context_t)
                                            -> *mut cef_browser_t {{
        let client: CefClient = client;
        let _browser_settings: &cef_browser_settings_t = _browser_settings;
        let _request_context: CefRequestContext = _request_context;
        browser_host_create(window_info, client, url, true)
    }}
}<commit_msg>update cef build with proper Window params<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use browser_host::{ServoCefBrowserHost, ServoCefBrowserHostExtensions};
use eutil::Downcast;
use frame::{ServoCefFrame, ServoCefFrameExtensions};
use interfaces::{CefBrowser, CefBrowserHost, CefClient, CefFrame, CefRequestContext};
use interfaces::{cef_browser_t, cef_browser_host_t, cef_client_t, cef_frame_t};
use interfaces::{cef_request_context_t};
use servo::Browser;
use types::{cef_browser_settings_t, cef_string_t, cef_window_info_t, cef_window_handle_t};
use util::thread::spawn_named;
use window;
use wrappers::CefWrap;

use compositing::windowing::{WindowNavigateMsg, WindowEvent};
use glutin_app;
use libc::c_int;
use std::cell::{Cell, RefCell, BorrowState};
use std::ptr;
use std::rc::Rc;
use std::sync::atomic::{AtomicIsize, Ordering};

thread_local!(pub static ID_COUNTER: AtomicIsize = AtomicIsize::new(0));
thread_local!(pub static BROWSERS: RefCell<Vec<CefBrowser>> = RefCell::new(vec!()));

pub enum ServoBrowser {
    Invalid,
    OnScreen(Browser<glutin_app::window::Window>),
    OffScreen(Browser<window::Window>),
}

impl ServoBrowser {
    fn handle_event(&mut self, event: WindowEvent) {
        match *self {
            ServoBrowser::OnScreen(ref mut browser) => { browser.handle_events(vec![event]); }
            ServoBrowser::OffScreen(ref mut browser) => { browser.handle_events(vec![event]); }
            ServoBrowser::Invalid => {}
        }
    }

    pub fn request_title_for_main_frame(&self) {
        match *self {
            ServoBrowser::OnScreen(ref browser) => browser.request_title_for_main_frame(),
            ServoBrowser::OffScreen(ref browser) => browser.request_title_for_main_frame(),
            ServoBrowser::Invalid => {}
        }
    }

    pub fn pinch_zoom_level(&self) -> f32 {
        match *self {
            ServoBrowser::OnScreen(ref browser) => browser.pinch_zoom_level(),
            ServoBrowser::OffScreen(ref browser) => browser.pinch_zoom_level(),
            ServoBrowser::Invalid => 1.0,
        }
    }
}

cef_class_impl! {
    ServoCefBrowser : CefBrowser, cef_browser_t {
        fn get_host(&this,) -> *mut cef_browser_host_t {{
            this.downcast().host.clone()
        }}

        fn can_go_back(&this,) -> c_int {{
            this.downcast().back.get() as c_int
        }}

        fn can_go_forward(&this,) -> c_int {{
            this.downcast().forward.get() as c_int
        }}

        fn is_loading(&this,) -> c_int {{
            this.downcast().loading.get() as c_int
        }}

        fn go_back(&this,) -> () {{
            this.send_window_event(WindowEvent::Navigation(WindowNavigateMsg::Back));
        }}

        fn go_forward(&this,) -> () {{
            this.send_window_event(WindowEvent::Navigation(WindowNavigateMsg::Forward));
        }}

        // Returns the main (top-level) frame for the browser window.
        fn get_main_frame(&this,) -> *mut cef_frame_t {{
            this.downcast().frame.clone()
        }}

        fn get_identifier(&this,) -> c_int {{
            this.downcast().id as c_int
        }}
    }
}

pub struct ServoCefBrowser {
    /// A reference to the browser's primary frame.
    pub frame: CefFrame,
    /// A reference to the browser's host.
    pub host: CefBrowserHost,
    /// A reference to the browser client.
    pub client: CefClient,
    /// the glutin window when using windowed rendering
    pub window: Option<Rc<glutin_app::window::Window>>,
    /// Whether the on-created callback has fired yet.
    pub callback_executed: Cell<bool>,
    /// whether the browser can navigate back
    pub back: Cell<bool>,
    /// whether the browser can navigate forward
    pub forward: Cell<bool>,
    /// whether the browser is loading
    pub loading: Cell<bool>,
    /// a vec of favicon urls for the current page
    pub favicons: RefCell<Vec<String>>,
    /// the display system window handle: only to be used with host.get_window_handle()
    window_handle: cef_window_handle_t,

    id: isize,
    servo_browser: RefCell<ServoBrowser>,
    message_queue: RefCell<Vec<WindowEvent>>,
}

impl ServoCefBrowser {
    pub fn new(window_info: &cef_window_info_t, client: CefClient) -> ServoCefBrowser {
        let frame = ServoCefFrame::new().as_cef_interface();
        let host = ServoCefBrowserHost::new(client.clone()).as_cef_interface();
        let mut window_handle: cef_window_handle_t = get_null_window_handle();

        let (glutin_window, servo_browser) = if window_info.windowless_rendering_enabled == 0 {
            let parent_window = glutin_app::WindowID::new(window_info.parent_window as *mut _);
            let glutin_window = glutin_app::create_window(Some(parent_window));
            let servo_browser = Browser::new(glutin_window.clone());
            window_handle = glutin_window.platform_window().window as cef_window_handle_t;
            (Some(glutin_window), ServoBrowser::OnScreen(servo_browser))
        } else {
            (None, ServoBrowser::Invalid)
        };

        let id = ID_COUNTER.with(|counter| {
            counter.fetch_add(1, Ordering::SeqCst)
        });

        ServoCefBrowser {
            frame: frame,
            host: host,
            client: client,
            window: glutin_window,
            callback_executed: Cell::new(false),
            servo_browser: RefCell::new(servo_browser),
            message_queue: RefCell::new(vec!()),
            id: id,
            back: Cell::new(false),
            forward: Cell::new(false),
            loading: Cell::new(false),
            favicons: RefCell::new(vec!()),
            window_handle: window_handle,
        }
    }
}

pub trait ServoCefBrowserExtensions {
    fn init(&self, window_info: &cef_window_info_t);
    fn send_window_event(&self, event: WindowEvent);
    fn request_title_for_main_frame(&self);
    fn pinch_zoom_level(&self) -> f32;
}

impl ServoCefBrowserExtensions for CefBrowser {
    fn init(&self, window_info: &cef_window_info_t) {
        if window_info.windowless_rendering_enabled != 0 {
            let window = window::Window::new(window_info.width, window_info.height);
            window.set_browser(self.clone());
            let servo_browser = Browser::new(window.clone());
            *self.downcast().servo_browser.borrow_mut() = ServoBrowser::OffScreen(servo_browser);
        }

        self.downcast().host.set_browser((*self).clone());
        self.downcast().frame.set_browser((*self).clone());
        if window_info.windowless_rendering_enabled == 0 {
            self.downcast().host.initialize_compositing();
        }
    }

    fn send_window_event(&self, event: WindowEvent) {
        self.downcast().message_queue.borrow_mut().push(event);

        loop {
            match self.downcast().servo_browser.borrow_state() {
                BorrowState::Unused => {
                    let event = match self.downcast().message_queue.borrow_mut().pop() {
                        None => return,
                        Some(event) => event,
                    };
                    self.downcast().servo_browser.borrow_mut().handle_event(event);
                }
                _ => {
                    // We're trying to send an event while processing another one. This will
                    // cause general badness, so queue up that event instead of immediately
                    // processing it.
                    break
                }
            }
        }
    }

    fn request_title_for_main_frame(&self) {
        self.downcast().servo_browser.borrow().request_title_for_main_frame()
    }

    fn pinch_zoom_level(&self) -> f32 {
        self.downcast().servo_browser.borrow().pinch_zoom_level()
    }
}

#[cfg(target_os="macos")]
pub fn get_null_window_handle() -> cef_window_handle_t {
    ptr::null_mut()
}
#[cfg(target_os="linux")]
pub fn get_null_window_handle() -> cef_window_handle_t {
    0
}

pub fn update() {
    BROWSERS.with(|browsers| {
        for browser in &*browsers.borrow() {
            if browser.downcast().callback_executed.get() == false {
                browser_callback_after_created(browser.clone());
            }
            let mut events = match browser.downcast().window {
                Some(ref win) => win.wait_events(),
                None => vec![WindowEvent::Idle]
            };
            loop {
               match events.pop() {
                   Some(event) => browser.send_window_event(event),
                   None => break
               }
            }
        }
    });
}

pub fn close(browser: CefBrowser) {
    BROWSERS.with(|browsers| {
        let mut browsers = browsers.borrow_mut();
        browsers.iter()
                .position(|&ref n| n.downcast().id == browser.downcast().id)
                .map(|e| browsers.remove(e));
    });
}

pub fn get_window(browser: &CefBrowser) -> cef_window_handle_t {
    browser.downcast().window_handle
}

pub fn browser_callback_after_created(browser: CefBrowser) {
    if browser.downcast().client.is_null_cef_object() {
        return
    }
    let client = browser.downcast().client.clone();
    let life_span_handler = client.get_life_span_handler();
    if life_span_handler.is_not_null_cef_object() {
        life_span_handler.on_after_created(browser.clone());
    }
    browser.downcast().callback_executed.set(true);
    browser.downcast().frame.load();
    browser.downcast().host.was_resized();
}

fn browser_host_create(window_info: &cef_window_info_t,
                       client: CefClient,
                       url: *const cef_string_t,
                       callback_executed: bool)
                       -> CefBrowser {
    let browser = ServoCefBrowser::new(window_info, client).as_cef_interface();
    browser.init(window_info);
    if url != ptr::null() {
       unsafe { browser.downcast().frame.set_url(CefWrap::to_rust(url)); }
    }
    if callback_executed {
        browser_callback_after_created(browser.clone());
    }
    BROWSERS.with(|browsers| {
        browsers.borrow_mut().push(browser.clone());
    });
    browser
}

cef_static_method_impls! {
    fn cef_browser_host_create_browser(window_info: *const cef_window_info_t,
                                       client: *mut cef_client_t,
                                       url: *const cef_string_t,
                                       _browser_settings: *const cef_browser_settings_t,
                                       _request_context: *mut cef_request_context_t)
                                       -> c_int {{
        let client: CefClient = client;
        let _browser_settings: &cef_browser_settings_t = _browser_settings;
        let _request_context: CefRequestContext = _request_context;
        browser_host_create(window_info, client, url, false);
        spawn_named("async_browser_creation".to_owned(), move || {
            window::app_wakeup();
        });
        1i32
    }}
    fn cef_browser_host_create_browser_sync(window_info: *const cef_window_info_t,
                                            client: *mut cef_client_t,
                                            url: *const cef_string_t,
                                            _browser_settings: *const cef_browser_settings_t,
                                            _request_context: *mut cef_request_context_t)
                                            -> *mut cef_browser_t {{
        let client: CefClient = client;
        let _browser_settings: &cef_browser_settings_t = _browser_settings;
        let _request_context: CefRequestContext = _request_context;
        browser_host_create(window_info, client, url, true)
    }}
}<|endoftext|>


<commit_before>extern crate rosc;

use rosc::{encoder, decoder, errors};
use rosc::errors::OscError;
use rosc::types::{Result, OscMessage, OscPacket};

#[test]
fn test_encode_message_wo_args() {
    let msg = OscMessage {
        addr: "/some/addr".to_string(),
        args: None,
    };

    let enc_msg = encoder::encode_message(&msg).unwrap();
    match decoder::decode(&enc_msg).unwrap() {
        OscPacket::Message(dec_msg) => assert_eq!(msg.addr, dec_msg.addr),
        _ => panic!("Expected OSC message!"),
    }
}
<commit_msg>Add test for message encoding with arguments<commit_after>extern crate rosc;

use rosc::{encoder, decoder};
use rosc::types::{OscMessage, OscMidiMessage, OscPacket, OscType};

#[test]
fn test_encode_message_wo_args() {
    let msg = OscMessage {
        addr: "/some/addr".to_string(),
        args: None,
    };

    let enc_msg = encoder::encode_message(&msg).unwrap();
    match decoder::decode(&enc_msg).unwrap() {
        OscPacket::Message(dec_msg) => assert_eq!(msg.addr, dec_msg.addr),
        _ => panic!("Expected OSC message!"),
    }
}

#[test]
fn test_encode_message_with_args() {
    let addr = "/another/address/1";
    let string_arg = "This is a string";
    let blob_arg = vec![1u8, 2u8, 3u8];
    let time_arg = (123, 456);
    let int_arg = 4;
    let float_arg = 3.14;
    let long_arg = 42;
    let double_arg = 3.1415;
    let char_arg = 'c';
    let midi_arg = OscMidiMessage {
        port: 12,
        status: 14,
        data1: 120,
        data2: 53,
    };
    let args = vec![OscType::Int(int_arg),
                    OscType::Float(float_arg),
                    OscType::String(string_arg.to_string()),
                    OscType::Blob(blob_arg.iter().cloned().collect()),
                    OscType::Time(time_arg.0, time_arg.1),
                    OscType::Long(long_arg),
                    OscType::Double(double_arg),
                    OscType::Char(char_arg),
                    OscType::Bool(false),
                    OscType::Bool(true),
                    OscType::Nil,
                    OscType::Inf,
                    OscType::Midi(OscMidiMessage {
                        port: midi_arg.port,
                        status: midi_arg.status,
                        data1: midi_arg.data1,
                        data2: midi_arg.data2,
                    })];
    let arg_cnt = args.len();

    let msg = OscMessage {
        addr: addr.to_string(),
        args: Some(args),
    };

    let enc_msg = encoder::encode_message(&msg).unwrap();
    let dec_msg: OscMessage = match decoder::decode(&enc_msg).unwrap() {
        OscPacket::Message(m) => m,
        _ => panic!("Expected OscMessage!"),
    };

    // check if osc address is equal
    assert_eq!(addr, dec_msg.addr);
    // check if there are arguments
    assert!(dec_msg.args.is_some());
    let dec_args = dec_msg.args.unwrap();

    // check if argument count is equal
    assert_eq!(arg_cnt, dec_args.len());

    for arg in dec_args {
        match arg {
            OscType::Int(x) => assert_eq!(int_arg, x),
            OscType::Long(x) => assert_eq!(long_arg, x),
            OscType::Float(x) => assert_eq!(float_arg, x),
            OscType::Double(x) => assert_eq!(double_arg, x),
            OscType::String(x) => assert_eq!(string_arg, x),
            OscType::Blob(x) => assert_eq!(blob_arg, x),
            OscType::Time(x, y) => assert_eq!(time_arg, (x, y)),
            OscType::Char(x) => assert_eq!(char_arg, x),
            OscType::Bool(_) => (),
            OscType::Inf => (),
            OscType::Nil => (),
            OscType::Midi(x) => {
                assert_eq!(midi_arg.port, x.port);
                assert_eq!(midi_arg.status, x.status);
                assert_eq!(midi_arg.data1, x.data1);
                assert_eq!(midi_arg.data2, x.data2);
            }
            _ => panic!("Unexpected OSC argument!"),
        }
    }
}
<|endoftext|>


<commit_before>
#[derive(Clone,PartialEq,Eq,Debug)]
pub enum Token {
  And,
  Break,
  Do,
  Else,
  Elseif,
  End,
  False,
  For,
  Function,
  If,
  In,
  Local,
  Nil,
  Not,
  Or,
  Repeat,
  Return,
  Then,
  True,
  Until,
  While,

  Plus,
  Minus,
  Times,
  Divide,
  Mod,
  Exp,
  Len,
  Eq,
  Neq,
  Leq,
  Geq,
  Lt,
  Gt,
  Assign,
  LParen,
  RParen,
  LBrace,
  RBrace,
  LSquare,
  RSquare,
  Semi,
  Colon,
  Comma,
  Dot,
  Dotdot,
  Dotdotdot,

  String(String),
  Number(String),
  Name(String),

  EOF
}

<commit_msg>Revert "Revert "Add impl Display for Token""<commit_after>use std::fmt::{Display, Formatter, Error};

#[derive(Clone,PartialEq,Eq,Debug)]
pub enum Token {
  And,
  Break,
  Do,
  Else,
  Elseif,
  End,
  False,
  For,
  Function,
  If,
  In,
  Local,
  Nil,
  Not,
  Or,
  Repeat,
  Return,
  Then,
  True,
  Until,
  While,

  Plus,
  Minus,
  Times,
  Divide,
  Mod,
  Exp,
  Len,
  Eq,
  Neq,
  Leq,
  Geq,
  Lt,
  Gt,
  Assign,
  LParen,
  RParen,
  LBrace,
  RBrace,
  LSquare,
  RSquare,
  Semi,
  Colon,
  Comma,
  Dot,
  Dotdot,
  Dotdotdot,

  String(String),
  Number(String),
  Name(String),

  EOF
}

impl Display for Token {
  fn fmt(&self, f : &mut Formatter) -> Result<(), Error> {
    let repr = match *self {
      Token::And => "'and'",
      Token::Break => "'break'",
      Token::Do => "'do'",
      Token::Else => "'else'",
      Token::Elseif => "'elseif'",
      Token::End => "'end'",
      Token::False => "'false'",
      Token::For => "'for'",
      Token::Function => "'function'",
      Token::If => "'if'",
      Token::In => "'in'",
      Token::Local => "'local'",
      Token::Nil => "'nil'",
      Token::Not => "'not'",
      Token::Or => "'or'",
      Token::Repeat => "'repeat'",
      Token::Return => "'return'",
      Token::Then => "'then'",
      Token::True => "'true'",
      Token::Until => "'until'",
      Token::While => "'while'",

      Token::Plus => "'+'",
      Token::Minus => "'-'",
      Token::Times => "'*'",
      Token::Divide => "'/'",
      Token::Mod => "'%'",
      Token::Exp => "'^'",
      Token::Len => "'#'",
      Token::Eq => "'=='",
      Token::Neq => "'~='",
      Token::Leq => "'<='",
      Token::Geq => "'>='",
      Token::Lt => "'<'",
      Token::Gt => "'>'",
      Token::Assign => "'='",
      Token::LParen => "'('",
      Token::RParen => "')'",
      Token::LBrace => "'{'",
      Token::RBrace => "'}'",
      Token::LSquare => "'['",
      Token::RSquare => "']'",
      Token::Semi => "';'",
      Token::Colon => "':'",
      Token::Comma => "','",
      Token::Dot => "'.'",
      Token::Dotdot => "'..'",
      Token::Dotdotdot => "'...'",

      Token::String(_) => "string literal",
      Token::Number(_) => "number literal",
      Token::Name(_)   => "name",

      Token::EOF => "<eof>"
    };

    try!(f.write_str(repr));

    Ok(())
  }
}
<|endoftext|>