<commit_before>use log::{debug, error, info};
use std::cell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::env;
use std::fmt::Write;
use std::os::raw::{c_char, c_int, c_void};
use std::slice;
use std::str;

use cpython::*;
use lldb::*;

use crate::debug_protocol::{DisplayHtmlEventBody, EventBody};
use crate::error::Error;

#[derive(Debug)]
pub enum PythonValue {
    SBValue(SBValue),
    Int(i64),
    Bool(bool),
    String(String),
    Object(String),
}

pub struct PythonInterface {
    interpreter: SBCommandInterpreter,
    pymod_lldb: PyModule,
    pymod_codelldb: PyModule,
    pymod_traceback: PyModule,
    pyty_sbexec_context: PyType,
    pyty_sbmodule: PyType,
    pyty_sbvalue: PyType,
    pyfn_evaluate_in_frame: PyObject,
    pyfn_modules_loaded: PyObject,
}

impl PythonInterface {
    pub fn new(
        interpreter: SBCommandInterpreter, send_event: Box<Fn(EventBody) + Send>,
    ) -> Result<Box<PythonInterface>, Error> {
        let mut init_script = env::current_exe()?;
        init_script.set_file_name("codelldb.py");

        // Import codelldb.py
        let mut command_result = SBCommandReturnObject::new();
        let command = format!("command script import '{}'", init_script.to_str()?);
        interpreter.handle_command(&command, &mut command_result, false);
        info!("{:?}", command_result);

        // Import rust.py
        let mut rust_formatters = init_script.clone();
        rust_formatters.set_file_name("rust.py");
        let command = format!("command script import '{}'", rust_formatters.to_str()?);
        interpreter.handle_command(&command, &mut command_result, false);
        info!("{:?}", command_result);

        // Cache some objects
        let gil = Python::acquire_gil();
        let py = gil.python();

        let pymod_lldb = py.import("lldb").unwrap();
        let pyty_sbvalue = PyType::downcast_from(py, pymod_lldb.get(py, "SBValue").unwrap()).unwrap();
        let pyty_sbmodule = PyType::downcast_from(py, pymod_lldb.get(py, "SBModule").unwrap()).unwrap();
        let pyty_sbexec_context = PyType::downcast_from(py, pymod_lldb.get(py, "SBExecutionContext").unwrap()).unwrap();

        let pymod_codelldb = py.import("codelldb").unwrap();
        let pyfn_evaluate_in_frame = pymod_codelldb.get(py, "evaluate_in_frame").unwrap();
        let pyfn_modules_loaded = pymod_codelldb.get(py, "modules_loaded").unwrap();

        let pymod_traceback = py.import("traceback").unwrap();

        let callback = RustClosure::new(py, move |py: Python, args, kwargs| {
            py_argparse!(py, None, args, kwargs, (
                    html: String,
                    title: Option<String> = None,
                    position: Option<i32> = None,
                    reveal: bool = false
            ) {
                send_event(EventBody::displayHtml(DisplayHtmlEventBody {
                    html, title, position, reveal
                }));
                Ok(py.None())
            })
        });
        pymod_codelldb.as_object().setattr(py, "display_html", callback.unwrap());

        let mut py_interface = Box::new(PythonInterface {
            interpreter,
            pymod_lldb,
            pymod_codelldb,
            pymod_traceback,
            pyty_sbexec_context,
            pyty_sbmodule,
            pyty_sbvalue,
            pyfn_evaluate_in_frame,
            pyfn_modules_loaded,
        });
        Ok(py_interface)
    }

    pub fn evaluate(&self, expr: &str, is_simple_expr: bool, context: &SBExecutionContext) -> Result<SBValue, String> {
        let gil = Python::acquire_gil();
        let py = gil.python();
        let pysb_exec_context =
            unsafe { into_swig_wrapper::<SBExecutionContext>(py, context.clone(), &self.pyty_sbexec_context) };
        let result = self.pyfn_evaluate_in_frame.call(py, (expr, is_simple_expr, pysb_exec_context), None);
        let target = context.target().unwrap();
        let result = self.to_sbvalue(py, &target, result);
        debug!("evaluate {} -> {:?}", expr, result);
        result
    }

    pub fn evaluate_as_bool(
        &self, expr: &str, is_simple_expr: bool, context: &SBExecutionContext,
    ) -> Result<bool, String> {
        let gil = Python::acquire_gil();
        let py = gil.python();
        let pysb_exec_context =
            unsafe { into_swig_wrapper::<SBExecutionContext>(py, context.clone(), &self.pyty_sbexec_context) };
        let result = self.pyfn_evaluate_in_frame.call(py, (expr, is_simple_expr, pysb_exec_context), None);
        let result = match result {
            Ok(value) => Ok(value.is_true(py).unwrap()),
            Err(pyerr) => Err(self.format_exception(py, pyerr)),
        };
        debug!("evaluate_as_bool {} -> {:?}", expr, result);
        result
    }

    pub fn modules_loaded(&self, modules: &mut Iterator<Item = &SBModule>) {
        let gil = Python::acquire_gil();
        let py = gil.python();

        let list = PyList::new(py, &[]);
        for module in modules {
            let pysbmodule = unsafe { into_swig_wrapper::<SBModule>(py, module.clone(), &self.pyty_sbmodule) };
            list.insert_item(py, list.len(py), pysbmodule);
        }
        self.pyfn_modules_loaded.call(py, (list,), None).unwrap();
    }

    fn to_sbvalue(&self, py: Python, target: &SBTarget, result: PyResult<PyObject>) -> Result<SBValue, String> {
        match result {
            Ok(value) => {
                if self.pyty_sbvalue.is_instance(py, &value) {
                    let sbvalue = unsafe { from_swig_wrapper::<SBValue>(py, &value) };
                    Ok(sbvalue)
                } else if PyBool::type_object(py).is_instance(py, &value) {
                    let value = bool::extract(py, &value).unwrap();
                    Ok(sbvalue_from_bool(value, target))
                } else if PyInt::type_object(py).is_instance(py, &value) {
                    let value = i64::extract(py, &value).unwrap();
                    Ok(sbvalue_from_i64(value, target))
                } else if PyLong::type_object(py).is_instance(py, &value) {
                    let value = i64::extract(py, &value).unwrap();
                    Ok(sbvalue_from_i64(value, target))
                } else if PyString::type_object(py).is_instance(py, &value) {
                    let value = String::extract(py, &value).unwrap();
                    Ok(sbvalue_from_str(&value, target))
                } else {
                    let value = value.to_string();
                    Ok(sbvalue_from_str(&value, target))
                }
            }
            Err(pyerr) => Err(self.format_exception(py, pyerr)),
        }
    }

    fn format_exception(&self, py: Python, mut err: PyErr) -> String {
        err.normalize(py);
        match self.pymod_traceback.call(py, "format_exception", (&err.ptype, &err.pvalue, &err.ptraceback), None) {
            Ok(tb) => {
                let lines = Vec::<String>::extract(py, &tb).unwrap();
                lines.concat()
            }
            Err(_) => format!("Could not format exception: {:?}", err),
        }
    }
}

// Creates a SWIG wrapper containing native SB object.
// `pytype` is the Python type object of the wrapper.
// Obviously, `SBT` and `pytype` must match, hence `unsafe`.
unsafe fn into_swig_wrapper<SBT>(py: Python, obj: SBT, pytype: &PyType) -> PyObject {
    // SWIG does not provide an API for creating Python wrapper from a native object, so we have to employ a bit of trickery:
    // First, we call SB wrapper's constructor on the Python side, which creates an instance wrapping dummy native SB object,
    let pysb = pytype.call(py, NoArgs, None).unwrap();
    // then, we retrieve a pointer to the native object via wrapper's `this` attribute,
    let this = pysb.getattr(py, "this").unwrap().extract::<usize>(py).unwrap();
    // finally, we replace it with the actual SB object we wanted to wrap.
    std::ptr::replace(this as *mut SBT, obj);
    pysb
}

// Extracts native SB object from a SWIG wrapper.
unsafe fn from_swig_wrapper<SBT>(py: Python, pyobj: &PyObject) -> SBT
where
    SBT: Clone,
{
    let this = pyobj.getattr(py, "this").unwrap().extract::<usize>(py).unwrap();
    let mut sb = this as *const SBT;
    (*sb).clone()
}

fn sbvalue_from_bool(value: bool, target: &SBTarget) -> SBValue {
    let ty = target.get_basic_type(BasicType::Bool);
    let slice = [value as u8, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes ought to be enough to hold a bool on any platform
    let data = SBData::borrow_bytes(&slice, ByteOrder::Little, 8);
    target.create_value_from_data("result", &data, &ty)
}

fn sbvalue_from_i64(value: i64, target: &SBTarget) -> SBValue {
    let ty = target.get_basic_type(BasicType::LongLong);
    let bytes = value.to_le_bytes();
    let data = SBData::borrow_bytes(&bytes, ByteOrder::Little, 8);
    target.create_value_from_data("result", &data, &ty)
}

fn sbvalue_from_str(value: &str, target: &SBTarget) -> SBValue {
    let ty = target.get_basic_type(BasicType::Char).array_type(value.len() as u64);
    let bytes = value.as_bytes();
    let data = SBData::borrow_bytes(bytes, ByteOrder::Little, 8);
    target.create_value_from_data("result", &data, &ty)
}

// Python wrapper for Rust closures
py_class!(class RustClosure |py| {
    data closure: cell::RefCell<Box<FnMut(Python, &PyTuple, Option<&PyDict>) -> PyResult<PyObject> + Send>>;

    def __call__(&self, *args, **kwargs) -> PyResult<PyObject> {
        use std::ops::DerefMut;
        let mut mut_ref = self.closure(py).borrow_mut();
        mut_ref.deref_mut()(py, &args, kwargs)
    }
});

impl RustClosure {
    fn new<F>(py: Python, closure: F) -> PyResult<RustClosure>
    where
        F: FnMut(Python, &PyTuple, Option<&PyDict>) -> PyResult<PyObject> + Send + 'static,
    {
        let closure = cell::RefCell::new(Box::new(closure));
        RustClosure::create_instance(py, closure)
    }
}
<commit_msg>Auto-import the debugger module.<commit_after>use log::{debug, error, info};
use std::cell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::env;
use std::fmt::Write;
use std::os::raw::{c_char, c_int, c_void};
use std::slice;
use std::str;

use cpython::*;
use lldb::*;

use crate::debug_protocol::{DisplayHtmlEventBody, EventBody};
use crate::error::Error;

#[derive(Debug)]
pub enum PythonValue {
    SBValue(SBValue),
    Int(i64),
    Bool(bool),
    String(String),
    Object(String),
}

pub struct PythonInterface {
    interpreter: SBCommandInterpreter,
    pymod_lldb: PyModule,
    pymod_codelldb: PyModule,
    pymod_traceback: PyModule,
    pyty_sbexec_context: PyType,
    pyty_sbmodule: PyType,
    pyty_sbvalue: PyType,
    pyfn_evaluate_in_frame: PyObject,
    pyfn_modules_loaded: PyObject,
}

impl PythonInterface {
    pub fn new(
        interpreter: SBCommandInterpreter, send_event: Box<Fn(EventBody) + Send>,
    ) -> Result<Box<PythonInterface>, Error> {
        let current_exe = env::current_exe()?;
        let mut command_result = SBCommandReturnObject::new();

        // Import debugger.py into script interpreter's namespace.
        // This also adds our bin directory to sys.path, so we can import the rest of our modules below.
        let init_script = current_exe.with_file_name("debugger.py");
        let command = format!("command script import '{}'", init_script.to_str()?);
        interpreter.handle_command(&command, &mut command_result, false);
        info!("{:?}", command_result);

        let rust_formatters = current_exe.with_file_name("rust.py");
        let command = format!("command script import '{}'", rust_formatters.to_str()?);
        interpreter.handle_command(&command, &mut command_result, false);
        info!("{:?}", command_result);

        // Cache some objects
        let gil = Python::acquire_gil();
        let py = gil.python();

        let pymod_lldb = py.import("lldb").unwrap();
        let pyty_sbvalue = PyType::downcast_from(py, pymod_lldb.get(py, "SBValue").unwrap()).unwrap();
        let pyty_sbmodule = PyType::downcast_from(py, pymod_lldb.get(py, "SBModule").unwrap()).unwrap();
        let pyty_sbexec_context = PyType::downcast_from(py, pymod_lldb.get(py, "SBExecutionContext").unwrap()).unwrap();

        let pymod_codelldb = py.import("codelldb").unwrap();
        let pyfn_evaluate_in_frame = pymod_codelldb.get(py, "evaluate_in_frame").unwrap();
        let pyfn_modules_loaded = pymod_codelldb.get(py, "modules_loaded").unwrap();

        let pymod_traceback = py.import("traceback").unwrap();

        let callback = RustClosure::new(py, move |py: Python, args, kwargs| {
            py_argparse!(py, None, args, kwargs, (
                    html: String,
                    title: Option<String> = None,
                    position: Option<i32> = None,
                    reveal: bool = false
            ) {
                send_event(EventBody::displayHtml(DisplayHtmlEventBody {
                    html, title, position, reveal
                }));
                Ok(py.None())
            })
        });
        pymod_codelldb.as_object().setattr(py, "display_html", callback.unwrap());

        let mut py_interface = Box::new(PythonInterface {
            interpreter,
            pymod_lldb,
            pymod_codelldb,
            pymod_traceback,
            pyty_sbexec_context,
            pyty_sbmodule,
            pyty_sbvalue,
            pyfn_evaluate_in_frame,
            pyfn_modules_loaded,
        });
        Ok(py_interface)
    }

    pub fn evaluate(&self, expr: &str, is_simple_expr: bool, context: &SBExecutionContext) -> Result<SBValue, String> {
        let gil = Python::acquire_gil();
        let py = gil.python();
        let pysb_exec_context =
            unsafe { into_swig_wrapper::<SBExecutionContext>(py, context.clone(), &self.pyty_sbexec_context) };
        let result = self.pyfn_evaluate_in_frame.call(py, (expr, is_simple_expr, pysb_exec_context), None);
        let target = context.target().unwrap();
        let result = self.to_sbvalue(py, &target, result);
        debug!("evaluate {} -> {:?}", expr, result);
        result
    }

    pub fn evaluate_as_bool(
        &self, expr: &str, is_simple_expr: bool, context: &SBExecutionContext,
    ) -> Result<bool, String> {
        let gil = Python::acquire_gil();
        let py = gil.python();
        let pysb_exec_context =
            unsafe { into_swig_wrapper::<SBExecutionContext>(py, context.clone(), &self.pyty_sbexec_context) };
        let result = self.pyfn_evaluate_in_frame.call(py, (expr, is_simple_expr, pysb_exec_context), None);
        let result = match result {
            Ok(value) => Ok(value.is_true(py).unwrap()),
            Err(pyerr) => Err(self.format_exception(py, pyerr)),
        };
        debug!("evaluate_as_bool {} -> {:?}", expr, result);
        result
    }

    pub fn modules_loaded(&self, modules: &mut Iterator<Item = &SBModule>) {
        let gil = Python::acquire_gil();
        let py = gil.python();

        let list = PyList::new(py, &[]);
        for module in modules {
            let pysbmodule = unsafe { into_swig_wrapper::<SBModule>(py, module.clone(), &self.pyty_sbmodule) };
            list.insert_item(py, list.len(py), pysbmodule);
        }
        self.pyfn_modules_loaded.call(py, (list,), None).unwrap();
    }

    fn to_sbvalue(&self, py: Python, target: &SBTarget, result: PyResult<PyObject>) -> Result<SBValue, String> {
        match result {
            Ok(value) => {
                if self.pyty_sbvalue.is_instance(py, &value) {
                    let sbvalue = unsafe { from_swig_wrapper::<SBValue>(py, &value) };
                    Ok(sbvalue)
                } else if PyBool::type_object(py).is_instance(py, &value) {
                    let value = bool::extract(py, &value).unwrap();
                    Ok(sbvalue_from_bool(value, target))
                } else if PyInt::type_object(py).is_instance(py, &value) {
                    let value = i64::extract(py, &value).unwrap();
                    Ok(sbvalue_from_i64(value, target))
                } else if PyLong::type_object(py).is_instance(py, &value) {
                    let value = i64::extract(py, &value).unwrap();
                    Ok(sbvalue_from_i64(value, target))
                } else if PyString::type_object(py).is_instance(py, &value) {
                    let value = String::extract(py, &value).unwrap();
                    Ok(sbvalue_from_str(&value, target))
                } else {
                    let value = value.to_string();
                    Ok(sbvalue_from_str(&value, target))
                }
            }
            Err(pyerr) => Err(self.format_exception(py, pyerr)),
        }
    }

    fn format_exception(&self, py: Python, mut err: PyErr) -> String {
        err.normalize(py);
        match self.pymod_traceback.call(py, "format_exception", (&err.ptype, &err.pvalue, &err.ptraceback), None) {
            Ok(tb) => {
                let lines = Vec::<String>::extract(py, &tb).unwrap();
                lines.concat()
            }
            Err(_) => format!("Could not format exception: {:?}", err),
        }
    }
}

// Creates a SWIG wrapper containing native SB object.
// `pytype` is the Python type object of the wrapper.
// Obviously, `SBT` and `pytype` must match, hence `unsafe`.
unsafe fn into_swig_wrapper<SBT>(py: Python, obj: SBT, pytype: &PyType) -> PyObject {
    // SWIG does not provide an API for creating Python wrapper from a native object, so we have to employ a bit of trickery:
    // First, we call SB wrapper's constructor on the Python side, which creates an instance wrapping dummy native SB object,
    let pysb = pytype.call(py, NoArgs, None).unwrap();
    // then, we retrieve a pointer to the native object via wrapper's `this` attribute,
    let this = pysb.getattr(py, "this").unwrap().extract::<usize>(py).unwrap();
    // finally, we replace it with the actual SB object we wanted to wrap.
    std::ptr::replace(this as *mut SBT, obj);
    pysb
}

// Extracts native SB object from a SWIG wrapper.
unsafe fn from_swig_wrapper<SBT>(py: Python, pyobj: &PyObject) -> SBT
where
    SBT: Clone,
{
    let this = pyobj.getattr(py, "this").unwrap().extract::<usize>(py).unwrap();
    let mut sb = this as *const SBT;
    (*sb).clone()
}

fn sbvalue_from_bool(value: bool, target: &SBTarget) -> SBValue {
    let ty = target.get_basic_type(BasicType::Bool);
    let slice = [value as u8, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes ought to be enough to hold a bool on any platform
    let data = SBData::borrow_bytes(&slice, ByteOrder::Little, 8);
    target.create_value_from_data("result", &data, &ty)
}

fn sbvalue_from_i64(value: i64, target: &SBTarget) -> SBValue {
    let ty = target.get_basic_type(BasicType::LongLong);
    let bytes = value.to_le_bytes();
    let data = SBData::borrow_bytes(&bytes, ByteOrder::Little, 8);
    target.create_value_from_data("result", &data, &ty)
}

fn sbvalue_from_str(value: &str, target: &SBTarget) -> SBValue {
    let ty = target.get_basic_type(BasicType::Char).array_type(value.len() as u64);
    let bytes = value.as_bytes();
    let data = SBData::borrow_bytes(bytes, ByteOrder::Little, 8);
    target.create_value_from_data("result", &data, &ty)
}

// Python wrapper for Rust closures
py_class!(class RustClosure |py| {
    data closure: cell::RefCell<Box<FnMut(Python, &PyTuple, Option<&PyDict>) -> PyResult<PyObject> + Send>>;

    def __call__(&self, *args, **kwargs) -> PyResult<PyObject> {
        use std::ops::DerefMut;
        let mut mut_ref = self.closure(py).borrow_mut();
        mut_ref.deref_mut()(py, &args, kwargs)
    }
});

impl RustClosure {
    fn new<F>(py: Python, closure: F) -> PyResult<RustClosure>
    where
        F: FnMut(Python, &PyTuple, Option<&PyDict>) -> PyResult<PyObject> + Send + 'static,
    {
        let closure = cell::RefCell::new(Box::new(closure));
        RustClosure::create_instance(py, closure)
    }
}
<|endoftext|>


<commit_before>
struct median_filter_t<'a> {
    window: &'a mut Vec<u8>,
    input: &'a mut Vec<u8>,
    hole: i64,
    max: i64,
}

fn median_init(f: &mut median_filter_t, w_size: usize){
    f.max = 0;
    f.hole = 0;

    *f.window = Vec::with_capacity(w_size);
    *f.input = Vec::with_capacity(w_size/2);
}

fn median_close_hole(f: &mut median_filter_t) {
    while f.hole < f.max - 1 {
        let i: usize = f.hole as usize;
        f.window[i] = f.window[i + 1];
        f.hole += 1;
    }

    if f.hole == f.max - 1 {
        f.max = f.max - 1;
    }
}

fn media_remove(f: &mut median_filter_t, v: u8) {
    median_close_hole(f);

    let mut lo: i64 = 0;
    let mut hi: i64 = f.max - 1;

    f.hole = (hi / 2) as i64;

    while lo <= hi {
        let i: usize = f.hole as usize;
        if v > f.window[i] {
            lo = f.hole + 1;
        } else if v < f.window[i] {
            hi = f.hole - 1;
        } else {
            break;
        }
        f.hole = (lo + hi) / 2;
    }
}

fn median_add(f: &mut median_filter_t, v: u8) {
    if f.hole == f.max {
        f.max += 1;
    }

    let mut i: usize = f.hole as usize;
    while (f.hole > 0) && (f.window[i] > v) {
        f.window[i] = f.window[i-1];
        f.hole -= 1;
        i = f.hole as usize;
    }

    i = f.hole as usize;

    while (f.hole < f.max - 1) && (f.window[i+1] < v) {
        f.window[i] = f.window[i+1];
        f.hole += 1;
        i = f.hole as usize;
    }

    f.window[i] = v;
    f.hole = f.max;
}

fn median_get(f: &mut median_filter_t) -> u8 {
    median_close_hole(f);

    if f.max == 0 {
        return 0;
    }

    if (f.max & 1i64) == 1 {
        let i: usize = f.max as usize;
        return f.window[(i-1)/2];
    } else {
        let i: usize = f.max as usize;
        return (f.window[(i-1)/2] + f.window[i/2]) / 2;
    }
}

fn median_filter(input: &mut Vec<u8>, size: i64, w_size: i64) -> i32 {

    return 0;
}

fn main() {
    println!("Hello, world!");
}
<commit_msg>remove whitespace<commit_after>
struct median_filter_t<'a> {
    window: &'a mut Vec<u8>,
    input: &'a mut Vec<u8>,
    hole: i64,
    max: i64,
}

fn median_init(f: &mut median_filter_t, w_size: usize){
    f.max = 0;
    f.hole = 0;

    *f.window = Vec::with_capacity(w_size);
    *f.input = Vec::with_capacity(w_size/2);
}

fn median_close_hole(f: &mut median_filter_t) {
    while f.hole < f.max - 1 {
        let i: usize = f.hole as usize;
        f.window[i] = f.window[i + 1];
        f.hole += 1;
    }

    if f.hole == f.max - 1 {
        f.max = f.max - 1;
    }
}

fn media_remove(f: &mut median_filter_t, v: u8) {
    median_close_hole(f);

    let mut lo: i64 = 0;
    let mut hi: i64 = f.max - 1;

    f.hole = (hi / 2) as i64;

    while lo <= hi {
        let i: usize = f.hole as usize;
        if v > f.window[i] {
            lo = f.hole + 1;
        } else if v < f.window[i] {
            hi = f.hole - 1;
        } else {
            break;
        }
        f.hole = (lo + hi) / 2;
    }
}

fn median_add(f: &mut median_filter_t, v: u8) {
    if f.hole == f.max {
        f.max += 1;
    }

    let mut i: usize = f.hole as usize;
    while (f.hole > 0) && (f.window[i] > v) {
        f.window[i] = f.window[i-1];
        f.hole -= 1;
        i = f.hole as usize;
    }

    i = f.hole as usize;

    while (f.hole < f.max - 1) && (f.window[i+1] < v) {
        f.window[i] = f.window[i+1];
        f.hole += 1;
        i = f.hole as usize;
    }

    f.window[i] = v;
    f.hole = f.max;
}

fn median_get(f: &mut median_filter_t) -> u8 {
    median_close_hole(f);

    if f.max == 0 {
        return 0;
    }

    if (f.max & 1i64) == 1 {
        let i: usize = f.max as usize;
        return f.window[(i-1)/2];
    } else {
        let i: usize = f.max as usize;
        return (f.window[(i-1)/2] + f.window[i/2]) / 2;
    }
}

fn median_filter(input: &mut Vec<u8>, size: i64, w_size: i64) -> i32 {
    return 0;
}

fn main() {
    println!("Hello, world!");
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Richard Diamond & contributors.
//
// This file is part of the Rust PPApi project.
//
// 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 std::borrow::Cow;

use ffi;

use gles::{self, Context3d, TextureBuffer, TexFormat};
use ppb::{get_video_decoder_opt, VideoDecoderIf};

use super::{GenericResource, Resource, ResourceType, Callback, Code,
            CallbackArgs, StorageToArgsMapper};

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct VideoDecoder(GenericResource);
impl Resource for VideoDecoder {
    fn unwrap(&self) -> ffi::PP_Resource { self.0.unwrap() }
    fn type_of(&self) -> Option<ResourceType> { Some(ResourceType::VideoDecoder) }
}
#[doc(hidden)]
impl From<ffi::PP_Resource> for VideoDecoder {
    fn from(v: ffi::PP_Resource) -> VideoDecoder {
        debug_assert!(get_video_decoder().is(v));
        VideoDecoder(From::from(v))
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum H264Profile {
    BaseLine,
    Main,
    Extended,
    High,
    High10,
    High422,
    High444Predictive,
    ScalableBaseLine,
    ScalableHigh,
    StereoHigh,
    MultiViewHigh,
}
#[doc(hidden)]
impl Into<ffi::PP_VideoProfile> for H264Profile {
    fn into(self) -> ffi::PP_VideoProfile {
        use self::H264Profile::*;
        match self {
            BaseLine => ffi::PP_VIDEOPROFILE_H264BASELINE,
            Main => ffi::PP_VIDEOPROFILE_H264MAIN,
            Extended => ffi::PP_VIDEOPROFILE_H264EXTENDED,
            High => ffi::PP_VIDEOPROFILE_H264HIGH,
            High10 => ffi::PP_VIDEOPROFILE_H264HIGH10PROFILE,
            High422 => ffi::PP_VIDEOPROFILE_H264HIGH422PROFILE,
            High444Predictive => ffi::PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE,
            ScalableBaseLine => ffi::PP_VIDEOPROFILE_H264SCALABLEBASELINE,
            ScalableHigh => ffi::PP_VIDEOPROFILE_H264SCALABLEHIGH,
            StereoHigh => ffi::PP_VIDEOPROFILE_H264STEREOHIGH,
            MultiViewHigh => ffi::PP_VIDEOPROFILE_H264MULTIVIEWHIGH,
        }
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum Profile {
    VP9,
    VP8,
    H264(H264Profile),
}
#[doc(hidden)]
impl Into<ffi::PP_VideoProfile> for Profile {
    fn into(self) -> ffi::PP_VideoProfile {
        use self::Profile::*;
        match self {
            H264(v) => v.into(),
            VP9 => ffi::PP_VIDEOPROFILE_VP9_ANY,
            VP8 => ffi::PP_VIDEOPROFILE_VP8_ANY,
        }
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum Acceleration {
    Hardware { with_fallback: bool },
    Software,
}
#[doc(hidden)]
impl Into<ffi::PP_HardwareAcceleration> for Acceleration {
    fn into(self) -> ffi::PP_HardwareAcceleration {
        match self {
            Acceleration::Hardware { with_fallback: false, } =>
                ffi::PP_HARDWAREACCELERATION_ONLY,
            Acceleration::Hardware { with_fallback: true,  } =>
                ffi::PP_HARDWAREACCELERATION_WITHFALLBACK,
            Acceleration::Software =>
                ffi::PP_HARDWAREACCELERATION_NONE,
        }
    }
}
impl Default for Acceleration {
    fn default() -> Acceleration { Acceleration::Hardware { with_fallback: true } }
}

pub struct Frame {
    pub tag: u32,
    texture: TextureBuffer,
    texture_target: gles::types::Enum,
    texture_size: super::Size,
    visible_rect: super::Rect,
}
impl Frame {
    pub fn format(&self) -> TexFormat { TexFormat::Rgba }
}
impl From<ffi::Struct_PP_VideoPicture> for Frame {
    fn from(raw: ffi::Struct_PP_VideoPicture) -> Frame {
        Frame {
            tag: raw.decode_id,
            texture: From::from(raw.texture_id),
            texture_target: From::from(raw.texture_target),
            texture_size: From::from(raw.texture_size),
            visible_rect: From::from(raw.visible_rect),
        }
    }
}
impl Into<ffi::Struct_PP_VideoPicture> for Frame {
    fn into(self) -> ffi::Struct_PP_VideoPicture {
        use gles::traits::Buffer;
        ffi::Struct_PP_VideoPicture {
            decode_id: self.tag,
            texture_id: self.texture.unwrap(),
            texture_target: self.texture_target,
            texture_size: self.texture_size.into(),
            visible_rect: self.visible_rect.into(),
        }
    }
}
impl VideoDecoder {
    pub fn initialize<F>(&self, g3d: Context3d, profile: Profile,
                     accel: Acceleration, callback: F) -> Code
        where F: Callback,
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.initialize(self.unwrap(), g3d.unwrap(), profile.into(),
                                        accel.into(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    /// PPAPI allocates it's own copy of the data before returning.
    pub fn decode<'a, F>(&self, decode_tag: u32, data: Cow<'a, [u8]>, callback: F) -> Code
        where F: Callback
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.decode(self.unwrap(), decode_tag,
                                    data.as_ref().len(), data.as_ref().as_ptr(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn flush<F>(&self, callback: F) -> Code where F: Callback {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.flush(self.unwrap(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn reset<F>(&self, callback: F) -> Code where F: Callback {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.reset(self.unwrap(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn get_picture<F>(&self, callback: F) -> Code<Frame>
        where F: CallbackArgs<Frame>
    {
        impl super::InPlaceInit for ffi::Struct_PP_VideoPicture { }
        fn arg_map(raw: ffi::Struct_PP_VideoPicture, _status: Code) -> Frame {
            From::from(raw)
        }
        get_video_decoder_opt()
            .map(move |i| {
                let raw: ffi::Struct_PP_VideoPicture = Default::default();
                let mapper = StorageToArgsMapper(arg_map);
                let cc = callback.to_ffi_callback(raw, mapper);
                let code = i.get_picture(self.unwrap(), cc.raw_args(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn recycle(&self, frame: Frame) {
        get_video_decoder_opt()
            .map(move |i| {
                let ffi: ffi::Struct_PP_VideoPicture =
                    frame.into();
                i.recycle_picture(self.unwrap(), &ffi)
            });
    }
}
<commit_msg>Revert "Add a debug check."<commit_after>// Copyright (c) 2014 Richard Diamond & contributors.
//
// This file is part of the Rust PPApi project.
//
// 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 std::borrow::Cow;

use ffi;

use gles::{self, Context3d, TextureBuffer, TexFormat};
use ppb::{get_video_decoder_opt, VideoDecoderIf};

use super::{GenericResource, Resource, ResourceType, Callback, Code,
            CallbackArgs, StorageToArgsMapper};

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct VideoDecoder(GenericResource);
impl Resource for VideoDecoder {
    fn unwrap(&self) -> ffi::PP_Resource { self.0.unwrap() }
    fn type_of(&self) -> Option<ResourceType> { Some(ResourceType::VideoDecoder) }
}
#[doc(hidden)]
impl From<ffi::PP_Resource> for VideoDecoder {
    fn from(v: ffi::PP_Resource) -> VideoDecoder {
        VideoDecoder(From::from(v))
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum H264Profile {
    BaseLine,
    Main,
    Extended,
    High,
    High10,
    High422,
    High444Predictive,
    ScalableBaseLine,
    ScalableHigh,
    StereoHigh,
    MultiViewHigh,
}
#[doc(hidden)]
impl Into<ffi::PP_VideoProfile> for H264Profile {
    fn into(self) -> ffi::PP_VideoProfile {
        use self::H264Profile::*;
        match self {
            BaseLine => ffi::PP_VIDEOPROFILE_H264BASELINE,
            Main => ffi::PP_VIDEOPROFILE_H264MAIN,
            Extended => ffi::PP_VIDEOPROFILE_H264EXTENDED,
            High => ffi::PP_VIDEOPROFILE_H264HIGH,
            High10 => ffi::PP_VIDEOPROFILE_H264HIGH10PROFILE,
            High422 => ffi::PP_VIDEOPROFILE_H264HIGH422PROFILE,
            High444Predictive => ffi::PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE,
            ScalableBaseLine => ffi::PP_VIDEOPROFILE_H264SCALABLEBASELINE,
            ScalableHigh => ffi::PP_VIDEOPROFILE_H264SCALABLEHIGH,
            StereoHigh => ffi::PP_VIDEOPROFILE_H264STEREOHIGH,
            MultiViewHigh => ffi::PP_VIDEOPROFILE_H264MULTIVIEWHIGH,
        }
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum Profile {
    VP9,
    VP8,
    H264(H264Profile),
}
#[doc(hidden)]
impl Into<ffi::PP_VideoProfile> for Profile {
    fn into(self) -> ffi::PP_VideoProfile {
        use self::Profile::*;
        match self {
            H264(v) => v.into(),
            VP9 => ffi::PP_VIDEOPROFILE_VP9_ANY,
            VP8 => ffi::PP_VIDEOPROFILE_VP8_ANY,
        }
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum Acceleration {
    Hardware { with_fallback: bool },
    Software,
}
#[doc(hidden)]
impl Into<ffi::PP_HardwareAcceleration> for Acceleration {
    fn into(self) -> ffi::PP_HardwareAcceleration {
        match self {
            Acceleration::Hardware { with_fallback: false, } =>
                ffi::PP_HARDWAREACCELERATION_ONLY,
            Acceleration::Hardware { with_fallback: true,  } =>
                ffi::PP_HARDWAREACCELERATION_WITHFALLBACK,
            Acceleration::Software =>
                ffi::PP_HARDWAREACCELERATION_NONE,
        }
    }
}
impl Default for Acceleration {
    fn default() -> Acceleration { Acceleration::Hardware { with_fallback: true } }
}

pub struct Frame {
    pub tag: u32,
    texture: TextureBuffer,
    texture_target: gles::types::Enum,
    texture_size: super::Size,
    visible_rect: super::Rect,
}
impl Frame {
    pub fn format(&self) -> TexFormat { TexFormat::Rgba }
}
impl From<ffi::Struct_PP_VideoPicture> for Frame {
    fn from(raw: ffi::Struct_PP_VideoPicture) -> Frame {
        Frame {
            tag: raw.decode_id,
            texture: From::from(raw.texture_id),
            texture_target: From::from(raw.texture_target),
            texture_size: From::from(raw.texture_size),
            visible_rect: From::from(raw.visible_rect),
        }
    }
}
impl Into<ffi::Struct_PP_VideoPicture> for Frame {
    fn into(self) -> ffi::Struct_PP_VideoPicture {
        use gles::traits::Buffer;
        ffi::Struct_PP_VideoPicture {
            decode_id: self.tag,
            texture_id: self.texture.unwrap(),
            texture_target: self.texture_target,
            texture_size: self.texture_size.into(),
            visible_rect: self.visible_rect.into(),
        }
    }
}
impl VideoDecoder {
    pub fn initialize<F>(&self, g3d: Context3d, profile: Profile,
                     accel: Acceleration, callback: F) -> Code
        where F: Callback,
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.initialize(self.unwrap(), g3d.unwrap(), profile.into(),
                                        accel.into(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    /// PPAPI allocates it's own copy of the data before returning.
    pub fn decode<'a, F>(&self, decode_tag: u32, data: Cow<'a, [u8]>, callback: F) -> Code
        where F: Callback
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.decode(self.unwrap(), decode_tag,
                                    data.as_ref().len(), data.as_ref().as_ptr(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn flush<F>(&self, callback: F) -> Code where F: Callback {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.flush(self.unwrap(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn reset<F>(&self, callback: F) -> Code where F: Callback {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.reset(self.unwrap(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn get_picture<F>(&self, callback: F) -> Code<Frame>
        where F: CallbackArgs<Frame>
    {
        impl super::InPlaceInit for ffi::Struct_PP_VideoPicture { }
        fn arg_map(raw: ffi::Struct_PP_VideoPicture, _status: Code) -> Frame {
            From::from(raw)
        }
        get_video_decoder_opt()
            .map(move |i| {
                let raw: ffi::Struct_PP_VideoPicture = Default::default();
                let mapper = StorageToArgsMapper(arg_map);
                let cc = callback.to_ffi_callback(raw, mapper);
                let code = i.get_picture(self.unwrap(), cc.raw_args(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn recycle(&self, frame: Frame) {
        get_video_decoder_opt()
            .map(move |i| {
                let ffi: ffi::Struct_PP_VideoPicture =
                    frame.into();
                i.recycle_picture(self.unwrap(), &ffi)
            });
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/// The `Deref` trait is used to specify the functionality of dereferencing
/// operations, like `*v`.
///
/// `Deref` also enables ['`Deref` coercions'][coercions].
///
/// [coercions]: ../../book/first-edition/deref-coercions.html
///
/// # Examples
///
/// A struct with a single field which is accessible via dereferencing the
/// struct.
///
/// ```
/// use std::ops::Deref;
///
/// struct DerefExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &T {
///         &self.value
///     }
/// }
///
/// fn main() {
///     let x = DerefExample { value: 'a' };
///     assert_eq!('a', *x);
/// }
/// ```
#[lang = "deref"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Deref {
    /// The resulting type after dereferencing
    #[stable(feature = "rust1", since = "1.0.0")]
    type Target: ?Sized;

    /// The method called to dereference a value
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref(&self) -> &Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Deref for &'a T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Deref for &'a mut T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

/// The `DerefMut` trait is used to specify the functionality of dereferencing
/// mutably like `*v = 1;`
///
/// `DerefMut` also enables ['`Deref` coercions'][coercions].
///
/// [coercions]: ../../book/first-edition/deref-coercions.html
///
/// # Examples
///
/// A struct with a single field which is modifiable via dereferencing the
/// struct.
///
/// ```
/// use std::ops::{Deref, DerefMut};
///
/// struct DerefMutExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefMutExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &T {
///         &self.value
///     }
/// }
///
/// impl<T> DerefMut for DerefMutExample<T> {
///     fn deref_mut(&mut self) -> &mut T {
///         &mut self.value
///     }
/// }
///
/// fn main() {
///     let mut x = DerefMutExample { value: 'a' };
///     *x = 'b';
///     assert_eq!('b', *x);
/// }
/// ```
#[lang = "deref_mut"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DerefMut: Deref {
    /// The method called to mutably dereference a value
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref_mut(&mut self) -> &mut Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> DerefMut for &'a mut T {
    fn deref_mut(&mut self) -> &mut T { *self }
}
<commit_msg>Expand docs on `Deref` and `DerefMut`<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/// Used for immutable dereferencing operations, like `*v`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
///
/// Implementing `Deref` for smart pointers makes accessing the data behind them
/// convenient, which is why they implement `Deref`. On the other hand, the
/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
/// accomodate smart pointers. Because of this, **`Deref` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
/// * In immutable contexts, `*x` on non-pointer types is equivalent to
///   `*Deref::deref(&x)`.
/// * Values of type `&T` are coerced to values of type `&U`
/// * `T` implicitly implements all the (immutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [the `Deref` trait][ref-deref-trait], and [type coercions].
///
/// [book]: ../../book/second-edition/ch15-02-deref.html
/// [`DerefMut`]: trait.DerefMut.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions.html#the-dereference-operator
/// [ref-deref-trait]: ../../reference/the-deref-trait.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is accessible by dereferencing the
/// struct.
///
/// ```
/// use std::ops::Deref;
///
/// struct DerefExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &T {
///         &self.value
///     }
/// }
///
/// let x = DerefExample { value: 'a' };
/// assert_eq!('a', *x);
/// ```
#[lang = "deref"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Deref {
    /// The resulting type after dereferencing.
    #[stable(feature = "rust1", since = "1.0.0")]
    type Target: ?Sized;

    /// Dereferences the value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref(&self) -> &Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Deref for &'a T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Deref for &'a mut T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

/// Used for mutable dereferencing operations, like in `*v = 1;`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used.
///
/// Implementing `DerefMut` for smart pointers makes mutating the data behind
/// them convenient, which is why they implement `DerefMut`. On the other hand,
/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
/// accomodate smart pointers. Because of this, **`DerefMut` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `DerefMut` is invoked
/// implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `MutDeref<Target = U>`, and `x` is a value of type `T`,
/// then:
/// * In mutable contexts, `*x` on non-pointer types is equivalent to
///   `*Deref::deref(&x)`.
/// * Values of type `&mut T` are coerced to values of type `&mut U`
/// * `T` implicitly implements all the (mutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [the `Deref` trait][ref-deref-trait], and [type coercions].
///
/// [book]: ../../book/second-edition/ch15-02-deref.html
/// [`Deref`]: trait.Deref.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions.html#the-dereference-operator
/// [ref-deref-trait]: ../../reference/the-deref-trait.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is modifiable by dereferencing the
/// struct.
///
/// ```
/// use std::ops::{Deref, DerefMut};
///
/// struct DerefMutExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefMutExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &T {
///         &self.value
///     }
/// }
///
/// impl<T> DerefMut for DerefMutExample<T> {
///     fn deref_mut(&mut self) -> &mut T {
///         &mut self.value
///     }
/// }
///
/// let mut x = DerefMutExample { value: 'a' };
/// *x = 'b';
/// assert_eq!('b', *x);
/// ```
#[lang = "deref_mut"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DerefMut: Deref {
    /// Mutably dereferences the value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref_mut(&mut self) -> &mut Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> DerefMut for &'a mut T {
    fn deref_mut(&mut self) -> &mut T { *self }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Bindings for executing child processes

use prelude::*;

use libc;
use rt::io;
use rt::io::io_error;
use rt::local::Local;
use rt::rtio::{RtioProcess, RtioProcessObject, IoFactoryObject, IoFactory};

pub struct Process {
    priv handle: ~RtioProcessObject,
    io: ~[Option<io::PipeStream>],
}

/// This configuration describes how a new process should be spawned. This is
/// translated to libuv's own configuration
pub struct ProcessConfig<'self> {
    /// Path to the program to run
    program: &'self str,

    /// Arguments to pass to the program (doesn't include the program itself)
    args: &'self [~str],

    /// Optional environment to specify for the program. If this is None, then
    /// it will inherit the current process's environment.
    env: Option<&'self [(~str, ~str)]>,

    /// Optional working directory for the new process. If this is None, then
    /// the current directory of the running process is inherited.
    cwd: Option<&'self str>,

    /// Any number of streams/file descriptors/pipes may be attached to this
    /// process. This list enumerates the file descriptors and such for the
    /// process to be spawned, and the file descriptors inherited will start at
    /// 0 and go to the length of this array.
    ///
    /// Standard file descriptors are:
    ///
    ///     0 - stdin
    ///     1 - stdout
    ///     2 - stderr
    io: ~[StdioContainer]
}

/// Describes what to do with a standard io stream for a child process.
pub enum StdioContainer {
    /// This stream will be ignored. This is the equivalent of attaching the
    /// stream to `/dev/null`
    Ignored,

    /// The specified file descriptor is inherited for the stream which it is
    /// specified for.
    InheritFd(libc::c_int),

    // XXX: these two shouldn't have libuv-specific implementation details

    /// The specified libuv stream is inherited for the corresponding file
    /// descriptor it is assigned to.
    // XXX: this needs to be thought out more.
    //InheritStream(uv::net::StreamWatcher),

    /// Creates a pipe for the specified file descriptor which will be directed
    /// into the previously-initialized pipe passed in.
    ///
    /// The first boolean argument is whether the pipe is readable, and the
    /// second is whether it is writable. These properties are from the view of
    /// the *child* process, not the parent process.
    CreatePipe(io::UnboundPipeStream,
               bool /* readable */,
               bool /* writable */),
}

impl Process {
    /// Creates a new pipe initialized, but not bound to any particular
    /// source/destination
    pub fn new(config: ProcessConfig) -> Option<Process> {
        let process = unsafe {
            let io: *mut IoFactoryObject = Local::unsafe_borrow();
            (*io).spawn(config)
        };
        match process {
            Ok((p, io)) => Some(Process{
                handle: p,
                io: io.move_iter().map(|p|
                    p.map_move(|p| io::PipeStream::bind(p))
                ).collect()
            }),
            Err(ioerr) => {
                io_error::cond.raise(ioerr);
                None
            }
        }
    }

    /// Returns the process id of this child process
    pub fn id(&self) -> libc::pid_t { self.handle.id() }

    /// Sends the specified signal to the child process, returning whether the
    /// signal could be delivered or not.
    ///
    /// Note that this is purely a wrapper around libuv's `uv_process_kill`
    /// function.
    ///
    /// If the signal delivery fails, then the `io_error` condition is raised on
    pub fn signal(&mut self, signal: int) {
        match self.handle.kill(signal) {
            Ok(()) => {}
            Err(err) => {
                io_error::cond.raise(err)
            }
        }
    }

    /// Wait for the child to exit completely, returning the status that it
    /// exited with. This function will continue to have the same return value
    /// after it has been called at least once.
    pub fn wait(&mut self) -> int { self.handle.wait() }
}

impl Drop for Process {
    fn drop(&mut self) {
        // Close all I/O before exiting to ensure that the child doesn't wait
        // forever to print some text or something similar.
        for _ in range(0, self.io.len()) {
            self.io.pop();
        }

        self.wait();
    }
}

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

    use rt::io::{Reader, Writer};
    use rt::io::pipe::*;
    use str;

    #[test]
    #[cfg(unix, not(android))]
    fn smoke() {
        let io = ~[];
        let args = ProcessConfig {
            program: "/bin/sh",
            args: [~"-c", ~"true"],
            env: None,
            cwd: None,
            io: io,
        };
        let p = Process::new(args);
        assert!(p.is_some());
        let mut p = p.unwrap();
        assert_eq!(p.wait(), 0);
    }

    #[test]
    #[cfg(unix, not(android))]
    fn smoke_failure() {
        let io = ~[];
        let args = ProcessConfig {
            program: "if-this-is-a-binary-then-the-world-has-ended",
            args: [],
            env: None,
            cwd: None,
            io: io,
        };
        let p = Process::new(args);
        assert!(p.is_some());
        let mut p = p.unwrap();
        assert!(p.wait() != 0);
    }

    #[test]
    #[cfg(unix, not(android))]
    fn exit_reported_right() {
        let io = ~[];
        let args = ProcessConfig {
            program: "/bin/sh",
            args: [~"-c", ~"exit 1"],
            env: None,
            cwd: None,
            io: io,
        };
        let p = Process::new(args);
        assert!(p.is_some());
        let mut p = p.unwrap();
        assert_eq!(p.wait(), 1);
    }

    fn read_all(input: &mut Reader) -> ~str {
        let mut ret = ~"";
        let mut buf = [0, ..1024];
        loop {
            match input.read(buf) {
                None | Some(0) => { break }
                Some(n) => { ret = ret + str::from_utf8(buf.slice_to(n)); }
            }
        }
        return ret;
    }

    fn run_output(args: ProcessConfig) -> ~str {
        let p = Process::new(args);
        assert!(p.is_some());
        let mut p = p.unwrap();
        assert!(p.io[0].is_none());
        assert!(p.io[1].is_some());
        let ret = read_all(p.io[1].get_mut_ref() as &mut Reader);
        assert_eq!(p.wait(), 0);
        return ret;
    }

    #[test]
    #[cfg(unix, not(android))]
    fn stdout_works() {
        let pipe = PipeStream::new().unwrap();
        let io = ~[Ignored, CreatePipe(pipe, false, true)];
        let args = ProcessConfig {
            program: "/bin/sh",
            args: [~"-c", ~"echo foobar"],
            env: None,
            cwd: None,
            io: io,
        };
        assert_eq!(run_output(args), ~"foobar\n");
    }

    #[test]
    #[cfg(unix, not(android))]
    fn set_cwd_works() {
        let pipe = PipeStream::new().unwrap();
        let io = ~[Ignored, CreatePipe(pipe, false, true)];
        let cwd = Some("/");
        let args = ProcessConfig {
            program: "/bin/sh",
            args: [~"-c", ~"pwd"],
            env: None,
            cwd: cwd,
            io: io,
        };
        assert_eq!(run_output(args), ~"/\n");
    }

    #[test]
    #[cfg(unix, not(android))]
    fn stdin_works() {
        let input = PipeStream::new().unwrap();
        let output = PipeStream::new().unwrap();
        let io = ~[CreatePipe(input, true, false),
                   CreatePipe(output, false, true)];
        let args = ProcessConfig {
            program: "/bin/sh",
            args: [~"-c", ~"read line; echo $line"],
            env: None,
            cwd: None,
            io: io,
        };
        let mut p = Process::new(args).expect("didn't create a proces?!");
        p.io[0].get_mut_ref().write("foobar".as_bytes());
        p.io[0] = None; // close stdin;
        let out = read_all(p.io[1].get_mut_ref() as &mut Reader);
        assert_eq!(p.wait(), 0);
        assert_eq!(out, ~"foobar\n");
    }
}
<commit_msg>auto merge of #9342 : alexcrichton/rust/ignore-libuv-signal-tests, r=brson<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Bindings for executing child processes

use prelude::*;

use libc;
use rt::io;
use rt::io::io_error;
use rt::local::Local;
use rt::rtio::{RtioProcess, RtioProcessObject, IoFactoryObject, IoFactory};

pub struct Process {
    priv handle: ~RtioProcessObject,
    io: ~[Option<io::PipeStream>],
}

/// This configuration describes how a new process should be spawned. This is
/// translated to libuv's own configuration
pub struct ProcessConfig<'self> {
    /// Path to the program to run
    program: &'self str,

    /// Arguments to pass to the program (doesn't include the program itself)
    args: &'self [~str],

    /// Optional environment to specify for the program. If this is None, then
    /// it will inherit the current process's environment.
    env: Option<&'self [(~str, ~str)]>,

    /// Optional working directory for the new process. If this is None, then
    /// the current directory of the running process is inherited.
    cwd: Option<&'self str>,

    /// Any number of streams/file descriptors/pipes may be attached to this
    /// process. This list enumerates the file descriptors and such for the
    /// process to be spawned, and the file descriptors inherited will start at
    /// 0 and go to the length of this array.
    ///
    /// Standard file descriptors are:
    ///
    ///     0 - stdin
    ///     1 - stdout
    ///     2 - stderr
    io: ~[StdioContainer]
}

/// Describes what to do with a standard io stream for a child process.
pub enum StdioContainer {
    /// This stream will be ignored. This is the equivalent of attaching the
    /// stream to `/dev/null`
    Ignored,

    /// The specified file descriptor is inherited for the stream which it is
    /// specified for.
    InheritFd(libc::c_int),

    // XXX: these two shouldn't have libuv-specific implementation details

    /// The specified libuv stream is inherited for the corresponding file
    /// descriptor it is assigned to.
    // XXX: this needs to be thought out more.
    //InheritStream(uv::net::StreamWatcher),

    /// Creates a pipe for the specified file descriptor which will be directed
    /// into the previously-initialized pipe passed in.
    ///
    /// The first boolean argument is whether the pipe is readable, and the
    /// second is whether it is writable. These properties are from the view of
    /// the *child* process, not the parent process.
    CreatePipe(io::UnboundPipeStream,
               bool /* readable */,
               bool /* writable */),
}

impl Process {
    /// Creates a new pipe initialized, but not bound to any particular
    /// source/destination
    pub fn new(config: ProcessConfig) -> Option<Process> {
        let process = unsafe {
            let io: *mut IoFactoryObject = Local::unsafe_borrow();
            (*io).spawn(config)
        };
        match process {
            Ok((p, io)) => Some(Process{
                handle: p,
                io: io.move_iter().map(|p|
                    p.map_move(|p| io::PipeStream::bind(p))
                ).collect()
            }),
            Err(ioerr) => {
                io_error::cond.raise(ioerr);
                None
            }
        }
    }

    /// Returns the process id of this child process
    pub fn id(&self) -> libc::pid_t { self.handle.id() }

    /// Sends the specified signal to the child process, returning whether the
    /// signal could be delivered or not.
    ///
    /// Note that this is purely a wrapper around libuv's `uv_process_kill`
    /// function.
    ///
    /// If the signal delivery fails, then the `io_error` condition is raised on
    pub fn signal(&mut self, signal: int) {
        match self.handle.kill(signal) {
            Ok(()) => {}
            Err(err) => {
                io_error::cond.raise(err)
            }
        }
    }

    /// Wait for the child to exit completely, returning the status that it
    /// exited with. This function will continue to have the same return value
    /// after it has been called at least once.
    pub fn wait(&mut self) -> int { self.handle.wait() }
}

impl Drop for Process {
    fn drop(&mut self) {
        // Close all I/O before exiting to ensure that the child doesn't wait
        // forever to print some text or something similar.
        for _ in range(0, self.io.len()) {
            self.io.pop();
        }

        self.wait();
    }
}

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

    use rt::io::{Reader, Writer};
    use rt::io::pipe::*;
    use str;

    #[test]
    #[cfg(unix, not(android))]
    #[ignore] // FIXME(#9341)
    fn smoke() {
        let io = ~[];
        let args = ProcessConfig {
            program: "/bin/sh",
            args: [~"-c", ~"true"],
            env: None,
            cwd: None,
            io: io,
        };
        let p = Process::new(args);
        assert!(p.is_some());
        let mut p = p.unwrap();
        assert_eq!(p.wait(), 0);
    }

    #[test]
    #[cfg(unix, not(android))]
    #[ignore] // FIXME(#9341)
    fn smoke_failure() {
        let io = ~[];
        let args = ProcessConfig {
            program: "if-this-is-a-binary-then-the-world-has-ended",
            args: [],
            env: None,
            cwd: None,
            io: io,
        };
        let p = Process::new(args);
        assert!(p.is_some());
        let mut p = p.unwrap();
        assert!(p.wait() != 0);
    }

    #[test]
    #[cfg(unix, not(android))]
    #[ignore] // FIXME(#9341)
    fn exit_reported_right() {
        let io = ~[];
        let args = ProcessConfig {
            program: "/bin/sh",
            args: [~"-c", ~"exit 1"],
            env: None,
            cwd: None,
            io: io,
        };
        let p = Process::new(args);
        assert!(p.is_some());
        let mut p = p.unwrap();
        assert_eq!(p.wait(), 1);
    }

    fn read_all(input: &mut Reader) -> ~str {
        let mut ret = ~"";
        let mut buf = [0, ..1024];
        loop {
            match input.read(buf) {
                None | Some(0) => { break }
                Some(n) => { ret = ret + str::from_utf8(buf.slice_to(n)); }
            }
        }
        return ret;
    }

    fn run_output(args: ProcessConfig) -> ~str {
        let p = Process::new(args);
        assert!(p.is_some());
        let mut p = p.unwrap();
        assert!(p.io[0].is_none());
        assert!(p.io[1].is_some());
        let ret = read_all(p.io[1].get_mut_ref() as &mut Reader);
        assert_eq!(p.wait(), 0);
        return ret;
    }

    #[test]
    #[cfg(unix, not(android))]
    #[ignore] // FIXME(#9341)
    fn stdout_works() {
        let pipe = PipeStream::new().unwrap();
        let io = ~[Ignored, CreatePipe(pipe, false, true)];
        let args = ProcessConfig {
            program: "/bin/sh",
            args: [~"-c", ~"echo foobar"],
            env: None,
            cwd: None,
            io: io,
        };
        assert_eq!(run_output(args), ~"foobar\n");
    }

    #[test]
    #[cfg(unix, not(android))]
    #[ignore] // FIXME(#9341)
    fn set_cwd_works() {
        let pipe = PipeStream::new().unwrap();
        let io = ~[Ignored, CreatePipe(pipe, false, true)];
        let cwd = Some("/");
        let args = ProcessConfig {
            program: "/bin/sh",
            args: [~"-c", ~"pwd"],
            env: None,
            cwd: cwd,
            io: io,
        };
        assert_eq!(run_output(args), ~"/\n");
    }

    #[test]
    #[cfg(unix, not(android))]
    #[ignore] // FIXME(#9341)
    fn stdin_works() {
        let input = PipeStream::new().unwrap();
        let output = PipeStream::new().unwrap();
        let io = ~[CreatePipe(input, true, false),
                   CreatePipe(output, false, true)];
        let args = ProcessConfig {
            program: "/bin/sh",
            args: [~"-c", ~"read line; echo $line"],
            env: None,
            cwd: None,
            io: io,
        };
        let mut p = Process::new(args).expect("didn't create a proces?!");
        p.io[0].get_mut_ref().write("foobar".as_bytes());
        p.io[0] = None; // close stdin;
        let out = read_all(p.io[1].get_mut_ref() as &mut Reader);
        assert_eq!(p.wait(), 0);
        assert_eq!(out, ~"foobar\n");
    }
}
<|endoftext|>


<commit_before>use nix::unistd::*;
use nix::unistd::ForkResult::*;
use nix::sys::wait::*;
use std::ffi::CString;

use std::io::{Write, Read};
use tempfile::tempfile;
use libc::off_t;
use std::os::unix::prelude::*;

#[test]
fn test_fork_and_waitpid() {
    let pid = fork();
    match pid {
      Ok(Child) => {} // ignore child here
      Ok(Parent { child }) => {
          // assert that child was created and pid > 0
          assert!(child > 0);
          let wait_status = waitpid(child, None);
          match wait_status {
              // assert that waitpid returned correct status and the pid is the one of the child
              Ok(WaitStatus::Exited(pid_t, _)) =>  assert!(pid_t == child),

              // panic, must never happen
              Ok(_) => panic!("Child still alive, should never happen"),

              // panic, waitpid should never fail
              Err(_) => panic!("Error: waitpid Failed")
          }

      },
      // panic, fork should never fail unless there is a serious problem with the OS
      Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_wait() {
    let pid = fork();
    match pid {
      Ok(Child) => {} // ignore child here
      Ok(Parent { child }) => {
          let wait_status = wait();

          // just assert that (any) one child returns with WaitStatus::Exited
          assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0)));
      },
      // panic, fork should never fail unless there is a serious problem with the OS
      Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_getpid() {
    let pid = getpid();
    let ppid = getppid();
    assert!(pid > 0);
    assert!(ppid > 0);
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux_android {
    use nix::unistd::gettid;

    #[test]
    fn test_gettid() {
        let tid = gettid();
        assert!(tid > 0);
    }
}

macro_rules! execve_test_factory(
    ($test_name:ident, $syscall:ident, $unix_sh:expr, $android_sh:expr) => (
    #[test]
    fn $test_name() {
        // The `exec`d process will write to `writer`, and we'll read that
        // data from `reader`.
        let (reader, writer) = pipe().unwrap();

        match fork().unwrap() {
            Child => {
                #[cfg(not(target_os = "android"))]
                const SH_PATH: &'static [u8] = $unix_sh;

                #[cfg(target_os = "android")]
                const SH_PATH: &'static [u8] = $android_sh;

                // Close stdout.
                close(1).unwrap();
                // Make `writer` be the stdout of the new process.
                dup(writer).unwrap();
                // exec!
                $syscall(
                    &CString::new(SH_PATH).unwrap(),
                    &[CString::new(b"".as_ref()).unwrap(),
                      CString::new(b"-c".as_ref()).unwrap(),
                      CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
                                   .as_ref()).unwrap()],
                    &[CString::new(b"foo=bar".as_ref()).unwrap(),
                      CString::new(b"baz=quux".as_ref()).unwrap()]).unwrap();
            },
            Parent { child } => {
                // Wait for the child to exit.
                waitpid(child, None).unwrap();
                // Read 1024 bytes.
                let mut buf = [0u8; 1024];
                read(reader, &mut buf).unwrap();
                // It should contain the things we printed using `/bin/sh`.
                let string = String::from_utf8_lossy(&buf);
                assert!(string.contains("nix!!!"));
                assert!(string.contains("foo=bar"));
                assert!(string.contains("baz=quux"));
            }
        }
    }
    )
);

#[test]
fn test_getcwd() {
  println!("{}", getcwd().unwrap().display());
}

#[test]
fn test_lseek() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();

    let offset: off_t = 5;
    lseek(tmp.as_raw_fd(), offset, Whence::SeekSet).unwrap();

    let mut buf = String::new();
     tmp.read_to_string(&mut buf).unwrap();
     assert_eq!(b"f123456", buf.as_bytes());

     close(tmp.as_raw_fd()).unwrap();
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn test_lseek64() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();

    lseek64(tmp.as_raw_fd(), 5, Whence::SeekSet).unwrap();

    let mut buf = String::new();
    tmp.read_to_string(&mut buf).unwrap();
    assert_eq!(b"f123456", buf.as_bytes());

    close(tmp.as_raw_fd()).unwrap();
}

execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh");

#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(feature = "execvpe")]
execve_test_factory!(test_execvpe, execvpe, b"sh", b"sh");
<commit_msg>added test for getcwd, still not complete (needs to check also longer directory names, need to be created with mkdir first which doesn't exist yet)<commit_after>extern crate tempdir;

use nix::unistd::*;
use nix::unistd::ForkResult::*;
use nix::sys::wait::*;
use std::ffi::CString;

use std::io::{Write, Read};
use tempfile::tempfile;
use tempdir::TempDir;
use libc::off_t;
use std::os::unix::prelude::*;

#[test]
fn test_fork_and_waitpid() {
    let pid = fork();
    match pid {
      Ok(Child) => {} // ignore child here
      Ok(Parent { child }) => {
          // assert that child was created and pid > 0
          assert!(child > 0);
          let wait_status = waitpid(child, None);
          match wait_status {
              // assert that waitpid returned correct status and the pid is the one of the child
              Ok(WaitStatus::Exited(pid_t, _)) =>  assert!(pid_t == child),

              // panic, must never happen
              Ok(_) => panic!("Child still alive, should never happen"),

              // panic, waitpid should never fail
              Err(_) => panic!("Error: waitpid Failed")
          }

      },
      // panic, fork should never fail unless there is a serious problem with the OS
      Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_wait() {
    let pid = fork();
    match pid {
      Ok(Child) => {} // ignore child here
      Ok(Parent { child }) => {
          let wait_status = wait();

          // just assert that (any) one child returns with WaitStatus::Exited
          assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0)));
      },
      // panic, fork should never fail unless there is a serious problem with the OS
      Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_getpid() {
    let pid = getpid();
    let ppid = getppid();
    assert!(pid > 0);
    assert!(ppid > 0);
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux_android {
    use nix::unistd::gettid;

    #[test]
    fn test_gettid() {
        let tid = gettid();
        assert!(tid > 0);
    }
}

macro_rules! execve_test_factory(
    ($test_name:ident, $syscall:ident, $unix_sh:expr, $android_sh:expr) => (
    #[test]
    fn $test_name() {
        // The `exec`d process will write to `writer`, and we'll read that
        // data from `reader`.
        let (reader, writer) = pipe().unwrap();

        match fork().unwrap() {
            Child => {
                #[cfg(not(target_os = "android"))]
                const SH_PATH: &'static [u8] = $unix_sh;

                #[cfg(target_os = "android")]
                const SH_PATH: &'static [u8] = $android_sh;

                // Close stdout.
                close(1).unwrap();
                // Make `writer` be the stdout of the new process.
                dup(writer).unwrap();
                // exec!
                $syscall(
                    &CString::new(SH_PATH).unwrap(),
                    &[CString::new(b"".as_ref()).unwrap(),
                      CString::new(b"-c".as_ref()).unwrap(),
                      CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
                                   .as_ref()).unwrap()],
                    &[CString::new(b"foo=bar".as_ref()).unwrap(),
                      CString::new(b"baz=quux".as_ref()).unwrap()]).unwrap();
            },
            Parent { child } => {
                // Wait for the child to exit.
                waitpid(child, None).unwrap();
                // Read 1024 bytes.
                let mut buf = [0u8; 1024];
                read(reader, &mut buf).unwrap();
                // It should contain the things we printed using `/bin/sh`.
                let string = String::from_utf8_lossy(&buf);
                assert!(string.contains("nix!!!"));
                assert!(string.contains("foo=bar"));
                assert!(string.contains("baz=quux"));
            }
        }
    }
    )
);

#[test]
fn test_getcwd() {
  // workaround for the fact that on os x TmpDir::new returns /var/folders/... but upon
  // chdir into that directory getcwd returns /private/var/folders/...
  let base = if cfg!(target_os = "macos") {
    "/private/tmp/"
  } else {
    "/tmp/"
  };
  let tmp_dir = TempDir::new_in(base, "test_getcwd").expect("create temp dir").into_path();
  assert!(chdir(tmp_dir.as_path()).is_ok());
  assert_eq!(getcwd().unwrap(), tmp_dir);
}

#[test]
fn test_lseek() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();

    let offset: off_t = 5;
    lseek(tmp.as_raw_fd(), offset, Whence::SeekSet).unwrap();

    let mut buf = String::new();
     tmp.read_to_string(&mut buf).unwrap();
     assert_eq!(b"f123456", buf.as_bytes());

     close(tmp.as_raw_fd()).unwrap();
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn test_lseek64() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();

    lseek64(tmp.as_raw_fd(), 5, Whence::SeekSet).unwrap();

    let mut buf = String::new();
    tmp.read_to_string(&mut buf).unwrap();
    assert_eq!(b"f123456", buf.as_bytes());

    close(tmp.as_raw_fd()).unwrap();
}

execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh");

#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(feature = "execvpe")]
execve_test_factory!(test_execvpe, execvpe, b"sh", b"sh");
<|endoftext|>


<commit_before>use crate::error::Error;
use crate::instance::{InstanceHandle, InternalRunResult, RunResult, State, TerminationDetails};
use crate::module::FunctionHandle;
use crate::val::{UntypedRetVal, Val};
use crate::vmctx::{Vmctx, VmctxInternal};
use std::any::Any;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

/// This is the same type defined by the `futures` library, but we don't need the rest of the
/// library for this purpose.
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

/// A unique type that wraps a boxed future with a boxed return value.
///
/// Type and lifetime guarantees are maintained by `Vmctx::block_on` and `Instance::run_async`. The
/// user never sees this type.
struct YieldedFuture(BoxFuture<'static, ResumeVal>);

/// A unique type for a boxed return value. The user never sees this type.
pub struct ResumeVal(Box<dyn Any + Send + 'static>);

unsafe impl Send for ResumeVal {}

impl Vmctx {
    /// Block on the result of an `async` computation from an instance run by `Instance::run_async`.
    ///
    /// Lucet hostcalls are synchronous `extern "C" fn` functions called from WebAssembly. In that
    /// context, we cannot use `.await` directly because the hostcall is not `async`. While we could
    /// block on an executor using `futures::executor::block_on` or
    /// `tokio::runtime::Runtime::block_on`, that has two drawbacks:
    ///
    /// - If the Lucet instance was originally invoked from an async context, trying to block on the
    ///   same runtime will fail if the executor cannot be nested (all executors we know of have this
    ///   restriction).
    ///
    /// - The current OS thread would be blocked on the result of the computation, rather than being
    ///   able to run other async tasks while awaiting. This means an application will need more
    ///   threads than otherwise would be necessary.
    ///
    /// Instead, this block_on operator is designed to work only when called within an invocation
    /// of [`Instance::run_async`]. The `run_async` method executes instance code within a
    /// trampoline, itself running within an async context, making it possible to temporarily pause
    /// guest execution, jump back to the trampoline, and await there. The future given to block_on
    /// is in passed back to that trampoline, and runs on the same runtime that invoked
    /// `run_async`, avoiding problems of nesting, and allowing the current OS thread to continue
    /// performing other async work.
    ///
    /// Note that this method may only be used if `Instance::run_async` was used to run the VM,
    /// otherwise it will terminate the instance with `TerminationDetails::BlockOnNeedsAsync`.
    pub fn block_on<'a, R>(&'a self, f: impl Future<Output = R> + Send + 'a) -> R
    where
        R: Any + Send + 'static,
    {
        // Die if we aren't in Instance::run_async
        match self.instance().state {
            State::Running { async_context } => {
                if !async_context {
                    panic!(TerminationDetails::BlockOnNeedsAsync)
                }
            }
            _ => unreachable!("Access to vmctx implies instance is Running"),
        }
        // Wrap the Output of `f` as a boxed ResumeVal. Then, box the entire
        // async computation.
        let f = Box::pin(async move { ResumeVal(Box::new(f.await)) });
        // Change the lifetime of the async computation from `'a` to `'static.
        // We need to lie about this lifetime so that `YieldedFuture` may impl
        // `Any` and be passed through the yield. `Instance::run_async`
        // rehydrates this lifetime to be at most as long as the Vmctx's `'a`.
        // This is safe because the stack frame that `'a` is tied to gets
        // frozen in place as part of `self.yield_val_expecting_val`.
        let f = unsafe {
            std::mem::transmute::<BoxFuture<'a, ResumeVal>, BoxFuture<'static, ResumeVal>>(f)
        };
        // Wrap the computation in `YieldedFuture` so that
        // `Instance::run_async` can catch and run it.  We will get the
        // `ResumeVal` we applied to `f` above.
        self.yield_impl::<YieldedFuture, ResumeVal>(YieldedFuture(f), false, false);
        let ResumeVal(v) = self.take_resumed_val();
        // We may now downcast and unbox the returned Box<dyn Any> into an `R`
        // again.
        *v.downcast().expect("run_async broke invariant")
    }
}

/// A simple future that yields once. We use this to yield when a runtime bound is reached.
///
/// Inspired by Tokio's `yield_now()`.
struct YieldNow {
    yielded: bool,
}

impl YieldNow {
    fn new() -> Self {
        Self { yielded: false }
    }
}

impl Future for YieldNow {
    type Output = ();
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
        if self.yielded {
            Poll::Ready(())
        } else {
            self.yielded = true;
            cx.waker().wake_by_ref();
            Poll::Pending
        }
    }
}

impl InstanceHandle {
    /// Run a WebAssembly function with arguments in the guest context at the given entrypoint.
    ///
    /// This method is similar to `Instance::run()`, but allows the Wasm program to invoke hostcalls
    /// that use `Vmctx::block_on` and provides the trampoline that `.await`s those futures on
    /// behalf of the guest.
    ///
    /// If `runtime_bound` is provided, it will also pause the Wasm execution and yield a future
    /// that resumes it after (approximately) that many Wasm opcodes have executed.
    ///
    /// # `Vmctx` Restrictions
    ///
    /// This method permits the use of `Vmctx::block_on`, but disallows all other uses of `Vmctx::
    /// yield_val_expecting_val` and family (`Vmctx::yield_`, `Vmctx::yield_expecting_val`,
    /// `Vmctx::yield_val`).
    pub async fn run_async<'a>(
        &'a mut self,
        entrypoint: &'a str,
        args: &'a [Val],
        runtime_bound: Option<u64>,
    ) -> Result<UntypedRetVal, Error> {
        let func = self.module.get_export_func(entrypoint)?;
        self.run_async_internal(func, args, runtime_bound).await
    }

    /// Run the module's [start function][start], if one exists.
    ///
    /// If there is no start function in the module, this does nothing.
    ///
    /// All of the other restrictions on the start function, what it may do, and
    /// the requirement that it must be invoked first, are described in the
    /// documentation for `Instance::run_start()`. This async version of that
    /// function satisfies the requirement to run the start function first, as
    /// long as the async function fully returns (not just yields).
    ///
    /// This method is similar to `Instance::run_start()`, except that it bounds
    /// runtime between async future yields (invocations of `.poll()` on the
    /// underlying generated future) if `runtime_bound` is provided. This
    /// behaves the same way as `Instance::run_async()`.
    pub async fn run_async_start<'a>(
        &'a mut self,
        runtime_bound: Option<u64>,
    ) -> Result<(), Error> {
        if let Some(start) = self.module.get_start_func()? {
            if !self.is_not_started() {
                return Err(Error::StartAlreadyRun);
            }
            self.run_async_internal(start, &[], runtime_bound).await?;
        }
        Ok(())
    }

    /// Shared async run-loop implementation for both `run_async()` and
    /// `run_start_async()`.
    async fn run_async_internal<'a>(
        &'a mut self,
        func: FunctionHandle,
        args: &'a [Val],
        runtime_bound: Option<u64>,
    ) -> Result<UntypedRetVal, Error> {
        if self.is_yielded() {
            return Err(Error::Unsupported(
                "cannot run_async a yielded instance".to_owned(),
            ));
        }

        // Store the ResumeVal here when we get it.
        let mut resume_val: Option<ResumeVal> = None;
        loop {
            // Run the WebAssembly program
            let run_result = if self.is_yielded() {
                // A previous iteration of the loop stored the ResumeVal in
                // `resume_val`, send it back to the guest ctx and continue
                // running:
                self.resume_with_val_impl(
                    resume_val
                        .take()
                        .expect("is_yielded implies resume_value is some"),
                    true,
                    runtime_bound,
                )
            } else if self.is_bound_expired() {
                self.resume_bounded(
                    runtime_bound.expect("should have bound if guest had expired bound"),
                )
            } else {
                // This is the first iteration, call the entrypoint:
                self.run_func(func, args, true, runtime_bound)
            };
            match run_result? {
                InternalRunResult::Normal(RunResult::Returned(rval)) => {
                    // Finished running, return UntypedReturnValue
                    return Ok(rval);
                }
                InternalRunResult::Normal(RunResult::Yielded(yval)) => {
                    // Check if the yield came from Vmctx::block_on:
                    if yval.is::<YieldedFuture>() {
                        let YieldedFuture(future) = *yval.downcast::<YieldedFuture>().unwrap();
                        // Rehydrate the lifetime from `'static` to `'a`, which
                        // is morally the same lifetime as was passed into
                        // `Vmctx::block_on`.
                        let future = future as BoxFuture<'a, ResumeVal>;

                        // await on the computation. Store its result in
                        // `resume_val`.
                        resume_val = Some(future.await);
                    // Now we want to `Instance::resume_with_val` and start
                    // this cycle over.
                    } else {
                        // Any other yielded value is not supported - die with an error.
                        return Err(Error::Unsupported(
                            "cannot yield anything besides a future in Instance::run_async"
                                .to_owned(),
                        ));
                    }
                }
                InternalRunResult::BoundExpired => {
                    // Await on a simple future that yields once then is ready.
                    YieldNow::new().await
                }
            }
        }
    }
}
<commit_msg>Make `InstanceHandle::run_async_start()` future impl `Send`<commit_after>use crate::error::Error;
use crate::instance::{InstanceHandle, InternalRunResult, RunResult, State, TerminationDetails};
use crate::module::FunctionHandle;
use crate::val::{UntypedRetVal, Val};
use crate::vmctx::{Vmctx, VmctxInternal};
use std::any::Any;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

/// This is the same type defined by the `futures` library, but we don't need the rest of the
/// library for this purpose.
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

/// A unique type that wraps a boxed future with a boxed return value.
///
/// Type and lifetime guarantees are maintained by `Vmctx::block_on` and `Instance::run_async`. The
/// user never sees this type.
struct YieldedFuture(BoxFuture<'static, ResumeVal>);

/// A unique type for a boxed return value. The user never sees this type.
pub struct ResumeVal(Box<dyn Any + Send + 'static>);

unsafe impl Send for ResumeVal {}

impl Vmctx {
    /// Block on the result of an `async` computation from an instance run by `Instance::run_async`.
    ///
    /// Lucet hostcalls are synchronous `extern "C" fn` functions called from WebAssembly. In that
    /// context, we cannot use `.await` directly because the hostcall is not `async`. While we could
    /// block on an executor using `futures::executor::block_on` or
    /// `tokio::runtime::Runtime::block_on`, that has two drawbacks:
    ///
    /// - If the Lucet instance was originally invoked from an async context, trying to block on the
    ///   same runtime will fail if the executor cannot be nested (all executors we know of have this
    ///   restriction).
    ///
    /// - The current OS thread would be blocked on the result of the computation, rather than being
    ///   able to run other async tasks while awaiting. This means an application will need more
    ///   threads than otherwise would be necessary.
    ///
    /// Instead, this block_on operator is designed to work only when called within an invocation
    /// of [`Instance::run_async`]. The `run_async` method executes instance code within a
    /// trampoline, itself running within an async context, making it possible to temporarily pause
    /// guest execution, jump back to the trampoline, and await there. The future given to block_on
    /// is in passed back to that trampoline, and runs on the same runtime that invoked
    /// `run_async`, avoiding problems of nesting, and allowing the current OS thread to continue
    /// performing other async work.
    ///
    /// Note that this method may only be used if `Instance::run_async` was used to run the VM,
    /// otherwise it will terminate the instance with `TerminationDetails::BlockOnNeedsAsync`.
    pub fn block_on<'a, R>(&'a self, f: impl Future<Output = R> + Send + 'a) -> R
    where
        R: Any + Send + 'static,
    {
        // Die if we aren't in Instance::run_async
        match self.instance().state {
            State::Running { async_context } => {
                if !async_context {
                    panic!(TerminationDetails::BlockOnNeedsAsync)
                }
            }
            _ => unreachable!("Access to vmctx implies instance is Running"),
        }
        // Wrap the Output of `f` as a boxed ResumeVal. Then, box the entire
        // async computation.
        let f = Box::pin(async move { ResumeVal(Box::new(f.await)) });
        // Change the lifetime of the async computation from `'a` to `'static.
        // We need to lie about this lifetime so that `YieldedFuture` may impl
        // `Any` and be passed through the yield. `Instance::run_async`
        // rehydrates this lifetime to be at most as long as the Vmctx's `'a`.
        // This is safe because the stack frame that `'a` is tied to gets
        // frozen in place as part of `self.yield_val_expecting_val`.
        let f = unsafe {
            std::mem::transmute::<BoxFuture<'a, ResumeVal>, BoxFuture<'static, ResumeVal>>(f)
        };
        // Wrap the computation in `YieldedFuture` so that
        // `Instance::run_async` can catch and run it.  We will get the
        // `ResumeVal` we applied to `f` above.
        self.yield_impl::<YieldedFuture, ResumeVal>(YieldedFuture(f), false, false);
        let ResumeVal(v) = self.take_resumed_val();
        // We may now downcast and unbox the returned Box<dyn Any> into an `R`
        // again.
        *v.downcast().expect("run_async broke invariant")
    }
}

/// A simple future that yields once. We use this to yield when a runtime bound is reached.
///
/// Inspired by Tokio's `yield_now()`.
struct YieldNow {
    yielded: bool,
}

impl YieldNow {
    fn new() -> Self {
        Self { yielded: false }
    }
}

impl Future for YieldNow {
    type Output = ();
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
        if self.yielded {
            Poll::Ready(())
        } else {
            self.yielded = true;
            cx.waker().wake_by_ref();
            Poll::Pending
        }
    }
}

impl InstanceHandle {
    /// Run a WebAssembly function with arguments in the guest context at the given entrypoint.
    ///
    /// This method is similar to `Instance::run()`, but allows the Wasm program to invoke hostcalls
    /// that use `Vmctx::block_on` and provides the trampoline that `.await`s those futures on
    /// behalf of the guest.
    ///
    /// If `runtime_bound` is provided, it will also pause the Wasm execution and yield a future
    /// that resumes it after (approximately) that many Wasm opcodes have executed.
    ///
    /// # `Vmctx` Restrictions
    ///
    /// This method permits the use of `Vmctx::block_on`, but disallows all other uses of `Vmctx::
    /// yield_val_expecting_val` and family (`Vmctx::yield_`, `Vmctx::yield_expecting_val`,
    /// `Vmctx::yield_val`).
    pub async fn run_async<'a>(
        &'a mut self,
        entrypoint: &'a str,
        args: &'a [Val],
        runtime_bound: Option<u64>,
    ) -> Result<UntypedRetVal, Error> {
        let func = self.module.get_export_func(entrypoint)?;
        self.run_async_internal(func, args, runtime_bound).await
    }

    /// Run the module's [start function][start], if one exists.
    ///
    /// If there is no start function in the module, this does nothing.
    ///
    /// All of the other restrictions on the start function, what it may do, and
    /// the requirement that it must be invoked first, are described in the
    /// documentation for `Instance::run_start()`. This async version of that
    /// function satisfies the requirement to run the start function first, as
    /// long as the async function fully returns (not just yields).
    ///
    /// This method is similar to `Instance::run_start()`, except that it bounds
    /// runtime between async future yields (invocations of `.poll()` on the
    /// underlying generated future) if `runtime_bound` is provided. This
    /// behaves the same way as `Instance::run_async()`.
    pub async fn run_async_start<'a>(
        &'a mut self,
        runtime_bound: Option<u64>,
    ) -> Result<(), Error> {
        if !self.is_not_started() {
            return Err(Error::StartAlreadyRun);
        }
        let start = match self.module.get_start_func()? {
            Some(start) => start,
            None => return Ok(()),
        };
        self.run_async_internal(start, &[], runtime_bound).await?;
        Ok(())
    }

    /// Shared async run-loop implementation for both `run_async()` and
    /// `run_start_async()`.
    async fn run_async_internal<'a>(
        &'a mut self,
        func: FunctionHandle,
        args: &'a [Val],
        runtime_bound: Option<u64>,
    ) -> Result<UntypedRetVal, Error> {
        if self.is_yielded() {
            return Err(Error::Unsupported(
                "cannot run_async a yielded instance".to_owned(),
            ));
        }

        // Store the ResumeVal here when we get it.
        let mut resume_val: Option<ResumeVal> = None;
        loop {
            // Run the WebAssembly program
            let run_result = if self.is_yielded() {
                // A previous iteration of the loop stored the ResumeVal in
                // `resume_val`, send it back to the guest ctx and continue
                // running:
                self.resume_with_val_impl(
                    resume_val
                        .take()
                        .expect("is_yielded implies resume_value is some"),
                    true,
                    runtime_bound,
                )
            } else if self.is_bound_expired() {
                self.resume_bounded(
                    runtime_bound.expect("should have bound if guest had expired bound"),
                )
            } else {
                // This is the first iteration, call the entrypoint:
                self.run_func(func, args, true, runtime_bound)
            };
            match run_result? {
                InternalRunResult::Normal(RunResult::Returned(rval)) => {
                    // Finished running, return UntypedReturnValue
                    return Ok(rval);
                }
                InternalRunResult::Normal(RunResult::Yielded(yval)) => {
                    // Check if the yield came from Vmctx::block_on:
                    if yval.is::<YieldedFuture>() {
                        let YieldedFuture(future) = *yval.downcast::<YieldedFuture>().unwrap();
                        // Rehydrate the lifetime from `'static` to `'a`, which
                        // is morally the same lifetime as was passed into
                        // `Vmctx::block_on`.
                        let future = future as BoxFuture<'a, ResumeVal>;

                        // await on the computation. Store its result in
                        // `resume_val`.
                        resume_val = Some(future.await);
                    // Now we want to `Instance::resume_with_val` and start
                    // this cycle over.
                    } else {
                        // Any other yielded value is not supported - die with an error.
                        return Err(Error::Unsupported(
                            "cannot yield anything besides a future in Instance::run_async"
                                .to_owned(),
                        ));
                    }
                }
                InternalRunResult::BoundExpired => {
                    // Await on a simple future that yields once then is ready.
                    YieldNow::new().await
                }
            }
        }
    }
}

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

    /// Show that the futures returned by `InstanceHandle` methods are `Send`.
    ///
    /// This doesn't actually do anything at runtime, the fact that it compiles is what counts.
    #[test]
    fn async_futures_are_send() {
        fn _assert_send<T: Send>(_: &T) {}
        #[allow(unreachable_code)]
        fn _dont_run_me() {
            let mut _inst: InstanceHandle = unimplemented!();
            _assert_send(&_inst.run_async("", &[], None));
            _assert_send(&_inst.run_async_start(None));
        }
    }
}
<|endoftext|>