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

//! The `servo` test application.
//!
//! Creates a `Browser` instance with a simple implementation of
//! the compositor's `WindowMethods` to create a working web browser.
//!
//! This browser's implementation of `WindowMethods` is built on top
//! of [glutin], the cross-platform OpenGL utility and windowing
//! library.
//!
//! For the engine itself look next door in lib.rs.
//!
//! [glutin]: https://github.com/tomaka/glutin

#![feature(start, core_intrinsics)]

#[cfg(target_os = "android")]
#[macro_use]
extern crate android_glue;
#[cfg(not(target_os = "android"))]
extern crate backtrace;
// The window backed by glutin
extern crate glutin_app as app;
#[cfg(target_os = "android")]
extern crate libc;
#[macro_use]
extern crate log;
// The Servo engine
extern crate servo;
#[cfg(not(target_os = "android"))]
#[macro_use]
extern crate sig;

use servo::Browser;
use servo::compositing::windowing::WindowEvent;
use servo::util::opts::{self, ArgumentParsingResult};
use servo::util::servo_version;
use std::panic;
use std::process;
use std::rc::Rc;

pub mod platform {
    #[cfg(target_os = "macos")]
    pub use platform::macos::deinit;

    #[cfg(target_os = "macos")]
    pub mod macos;

    #[cfg(not(target_os = "macos"))]
    pub fn deinit() {}
}

#[cfg(not(target_os = "android"))]
fn install_crash_handler() {
    use backtrace::Backtrace;
    use sig::ffi::Sig;
    use std::intrinsics::abort;
    use std::thread;

    fn handler(_sig: i32) {
        let name = thread::current().name()
                                    .map(|n| format!(" for thread \"{}\"", n))
                                    .unwrap_or("".to_owned());
        println!("Stack trace{}\n{:?}", name, Backtrace::new());
        unsafe {
            abort();
        }
    }

    signal!(Sig::SEGV, handler); // handle segfaults
    signal!(Sig::ILL, handler); // handle stack overflow and unsupported CPUs
    signal!(Sig::IOT, handler); // handle double panics
    signal!(Sig::BUS, handler); // handle invalid memory access
}

#[cfg(target_os = "android")]
fn install_crash_handler() {
}

fn main() {
    install_crash_handler();

    // Parse the command line options and store them globally
    let opts_result = opts::from_cmdline_args(&*args());

    let content_process_token = if let ArgumentParsingResult::ContentProcess(token) = opts_result {
        Some(token)
    } else {
        if opts::get().is_running_problem_test && ::std::env::var("RUST_LOG").is_err() {
            ::std::env::set_var("RUST_LOG", "compositing::constellation");
        }

        None
    };

    // TODO: once log-panics is released, this can be replaced by
    // log_panics::init();
    panic::set_hook(Box::new(|info| {
        warn!("Panic hook called.");
        let msg = match info.payload().downcast_ref::<&'static str>() {
            Some(s) => *s,
            None => match info.payload().downcast_ref::<String>() {
                Some(s) => &**s,
                None => "Box<Any>",
            },
        };
        error!("{}", msg);
    }));

    setup_logging();

    if let Some(token) = content_process_token {
        return servo::run_content_process(token)
    }

    if opts::get().is_printing_version {
        println!("{}", servo_version());
        process::exit(0);
    }

    let window = app::create_window(None);

    // Our wrapper around `Browser` that also implements some
    // callbacks required by the glutin window implementation.
    let mut browser = BrowserWrapper {
        browser: Browser::new(window.clone()),
    };

    browser.browser.setup_logging();

    register_glutin_resize_handler(&window, &mut browser);

    browser.browser.handle_events(vec![WindowEvent::InitializeCompositing]);

    // Feed events from the window to the browser until the browser
    // says to stop.
    loop {
        let should_continue = browser.browser.handle_events(window.wait_events());
        if !should_continue {
            break
        }
    };

    unregister_glutin_resize_handler(&window);

    platform::deinit()
}

fn register_glutin_resize_handler(window: &Rc<app::window::Window>,
                                        browser: &mut BrowserWrapper) {
    unsafe {
        window.set_nested_event_loop_listener(browser);
    }
}

fn unregister_glutin_resize_handler(window: &Rc<app::window::Window>) {
    unsafe {
        window.remove_nested_event_loop_listener();
    }
}

struct BrowserWrapper {
    browser: Browser<app::window::Window>,
}

impl app::NestedEventLoopListener for BrowserWrapper {
    fn handle_event_from_nested_event_loop(&mut self, event: WindowEvent) -> bool {
        let is_resize = match event {
            WindowEvent::Resize(..) => true,
            _ => false,
        };
        if !self.browser.handle_events(vec![event]) {
            return false
        }
        if is_resize {
            self.browser.repaint_synchronously()
        }
        true
    }
}

#[cfg(target_os = "android")]
fn setup_logging() {
    android::setup_logging();
}

#[cfg(not(target_os = "android"))]
fn setup_logging() {
}

#[cfg(target_os = "android")]
/// Attempt to read parameters from a file since they are not passed to us in Android environments.
/// The first line should be the "servo" argument and the last should be the URL to load.
/// Blank lines and those beginning with a '#' are ignored.
/// Each line should be a separate parameter as would be parsed by the shell.
/// For example, "servo -p 10 http://en.wikipedia.org/wiki/Rust" would take 4 lines.
fn args() -> Vec<String> {
    use std::error::Error;
    use std::fs::File;
    use std::io::{BufRead, BufReader};

    const PARAMS_FILE: &'static str = "/sdcard/servo/android_params";
    match File::open(PARAMS_FILE) {
        Ok(f) => {
            let mut vec = Vec::new();
            let file = BufReader::new(&f);
            for line in file.lines() {
                let l = line.unwrap().trim().to_owned();
                // ignore blank lines and those that start with a '#'
                match l.is_empty() || l.as_bytes()[0] == b'#' {
                    true => (),
                    false => vec.push(l),
                }
            }
            vec
        },
        Err(e) => {
            debug!("Failed to open params file '{}': {}", PARAMS_FILE, Error::description(&e));
            vec![
                "servo".to_owned(),
                "http://en.wikipedia.org/wiki/Rust".to_owned()
            ]
        },
    }
}

#[cfg(not(target_os = "android"))]
fn args() -> Vec<String> {
    use std::env;
    env::args().collect()
}

// This extern definition ensures that the linker will not discard
// the static native lib bits, which are brought in from the NDK libraries
// we link in from build.rs.
#[cfg(target_os = "android")]
extern {
    fn app_dummy() -> libc::c_void;
}

// This macro must be used at toplevel because it defines a nested
// module, but macros can only accept identifiers - not paths -
// preventing the expansion of this macro within the android module
// without use of an additionl stub method or other hackery.
#[cfg(target_os = "android")]
android_start!(main);

#[cfg(target_os = "android")]
mod android {
    extern crate android_glue;
    extern crate libc;

    use self::libc::c_int;
    use std::borrow::ToOwned;

    pub fn setup_logging() {
        use self::libc::{STDERR_FILENO, STDOUT_FILENO};
        //use std::env;

        //env::set_var("RUST_LOG", "servo,gfx,msg,util,layers,js,std,rt,extra");
        redirect_output(STDERR_FILENO);
        redirect_output(STDOUT_FILENO);

        unsafe { super::app_dummy(); }
    }

    struct FilePtr(*mut self::libc::FILE);

    unsafe impl Send for FilePtr {}

    fn redirect_output(file_no: c_int) {
        use self::libc::fdopen;
        use self::libc::fgets;
        use self::libc::{pipe, dup2};
        use servo::util::thread::spawn_named;
        use std::ffi::CStr;
        use std::ffi::CString;
        use std::str::from_utf8;

        unsafe {
            let mut pipes: [c_int; 2] = [ 0, 0 ];
            pipe(pipes.as_mut_ptr());
            dup2(pipes[1], file_no);
            let mode = CString::new("r").unwrap();
            let input_file = FilePtr(fdopen(pipes[0], mode.as_ptr()));
            spawn_named("android-logger".to_owned(), move || {
                static READ_SIZE: usize = 1024;
                let mut read_buffer = vec![0; READ_SIZE];
                let FilePtr(input_file) = input_file;
                loop {
                    fgets(read_buffer.as_mut_ptr(), (read_buffer.len() as i32)-1, input_file);
                    let c_str = CStr::from_ptr(read_buffer.as_ptr());
                    let slice = from_utf8(c_str.to_bytes()).unwrap();
                    android_glue::write_log(slice);
                }
            });
        }
    }

}
<commit_msg>Auto merge of #12733 - nox:panic-location, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The `servo` test application.
//!
//! Creates a `Browser` instance with a simple implementation of
//! the compositor's `WindowMethods` to create a working web browser.
//!
//! This browser's implementation of `WindowMethods` is built on top
//! of [glutin], the cross-platform OpenGL utility and windowing
//! library.
//!
//! For the engine itself look next door in lib.rs.
//!
//! [glutin]: https://github.com/tomaka/glutin

#![feature(start, core_intrinsics)]

#[cfg(target_os = "android")]
#[macro_use]
extern crate android_glue;
#[cfg(not(target_os = "android"))]
extern crate backtrace;
// The window backed by glutin
extern crate glutin_app as app;
#[cfg(target_os = "android")]
extern crate libc;
#[macro_use]
extern crate log;
// The Servo engine
extern crate servo;
#[cfg(not(target_os = "android"))]
#[macro_use]
extern crate sig;

use servo::Browser;
use servo::compositing::windowing::WindowEvent;
use servo::util::opts::{self, ArgumentParsingResult};
use servo::util::servo_version;
use std::panic;
use std::process;
use std::rc::Rc;
use std::thread;

pub mod platform {
    #[cfg(target_os = "macos")]
    pub use platform::macos::deinit;

    #[cfg(target_os = "macos")]
    pub mod macos;

    #[cfg(not(target_os = "macos"))]
    pub fn deinit() {}
}

#[cfg(not(target_os = "android"))]
fn install_crash_handler() {
    use backtrace::Backtrace;
    use sig::ffi::Sig;
    use std::intrinsics::abort;
    use std::thread;

    fn handler(_sig: i32) {
        let name = thread::current().name()
                                    .map(|n| format!(" for thread \"{}\"", n))
                                    .unwrap_or("".to_owned());
        println!("Stack trace{}\n{:?}", name, Backtrace::new());
        unsafe {
            abort();
        }
    }

    signal!(Sig::SEGV, handler); // handle segfaults
    signal!(Sig::ILL, handler); // handle stack overflow and unsupported CPUs
    signal!(Sig::IOT, handler); // handle double panics
    signal!(Sig::BUS, handler); // handle invalid memory access
}

#[cfg(target_os = "android")]
fn install_crash_handler() {
}

fn main() {
    install_crash_handler();

    // Parse the command line options and store them globally
    let opts_result = opts::from_cmdline_args(&*args());

    let content_process_token = if let ArgumentParsingResult::ContentProcess(token) = opts_result {
        Some(token)
    } else {
        if opts::get().is_running_problem_test && ::std::env::var("RUST_LOG").is_err() {
            ::std::env::set_var("RUST_LOG", "compositing::constellation");
        }

        None
    };

    // TODO: once log-panics is released, this can be replaced by
    // log_panics::init();
    panic::set_hook(Box::new(|info| {
        warn!("Panic hook called.");
        let msg = match info.payload().downcast_ref::<&'static str>() {
            Some(s) => *s,
            None => match info.payload().downcast_ref::<String>() {
                Some(s) => &**s,
                None => "Box<Any>",
            },
        };
        let current_thread = thread::current();
        let name = current_thread.name().unwrap_or("<unnamed>");
        if let Some(location) = info.location() {
            error!("{} (thread {}, at {}:{})", msg, name, location.file(), location.line());
        } else {
            error!("{} (thread {})", msg, name);
        }
    }));

    setup_logging();

    if let Some(token) = content_process_token {
        return servo::run_content_process(token)
    }

    if opts::get().is_printing_version {
        println!("{}", servo_version());
        process::exit(0);
    }

    let window = app::create_window(None);

    // Our wrapper around `Browser` that also implements some
    // callbacks required by the glutin window implementation.
    let mut browser = BrowserWrapper {
        browser: Browser::new(window.clone()),
    };

    browser.browser.setup_logging();

    register_glutin_resize_handler(&window, &mut browser);

    browser.browser.handle_events(vec![WindowEvent::InitializeCompositing]);

    // Feed events from the window to the browser until the browser
    // says to stop.
    loop {
        let should_continue = browser.browser.handle_events(window.wait_events());
        if !should_continue {
            break
        }
    };

    unregister_glutin_resize_handler(&window);

    platform::deinit()
}

fn register_glutin_resize_handler(window: &Rc<app::window::Window>,
                                        browser: &mut BrowserWrapper) {
    unsafe {
        window.set_nested_event_loop_listener(browser);
    }
}

fn unregister_glutin_resize_handler(window: &Rc<app::window::Window>) {
    unsafe {
        window.remove_nested_event_loop_listener();
    }
}

struct BrowserWrapper {
    browser: Browser<app::window::Window>,
}

impl app::NestedEventLoopListener for BrowserWrapper {
    fn handle_event_from_nested_event_loop(&mut self, event: WindowEvent) -> bool {
        let is_resize = match event {
            WindowEvent::Resize(..) => true,
            _ => false,
        };
        if !self.browser.handle_events(vec![event]) {
            return false
        }
        if is_resize {
            self.browser.repaint_synchronously()
        }
        true
    }
}

#[cfg(target_os = "android")]
fn setup_logging() {
    android::setup_logging();
}

#[cfg(not(target_os = "android"))]
fn setup_logging() {
}

#[cfg(target_os = "android")]
/// Attempt to read parameters from a file since they are not passed to us in Android environments.
/// The first line should be the "servo" argument and the last should be the URL to load.
/// Blank lines and those beginning with a '#' are ignored.
/// Each line should be a separate parameter as would be parsed by the shell.
/// For example, "servo -p 10 http://en.wikipedia.org/wiki/Rust" would take 4 lines.
fn args() -> Vec<String> {
    use std::error::Error;
    use std::fs::File;
    use std::io::{BufRead, BufReader};

    const PARAMS_FILE: &'static str = "/sdcard/servo/android_params";
    match File::open(PARAMS_FILE) {
        Ok(f) => {
            let mut vec = Vec::new();
            let file = BufReader::new(&f);
            for line in file.lines() {
                let l = line.unwrap().trim().to_owned();
                // ignore blank lines and those that start with a '#'
                match l.is_empty() || l.as_bytes()[0] == b'#' {
                    true => (),
                    false => vec.push(l),
                }
            }
            vec
        },
        Err(e) => {
            debug!("Failed to open params file '{}': {}", PARAMS_FILE, Error::description(&e));
            vec![
                "servo".to_owned(),
                "http://en.wikipedia.org/wiki/Rust".to_owned()
            ]
        },
    }
}

#[cfg(not(target_os = "android"))]
fn args() -> Vec<String> {
    use std::env;
    env::args().collect()
}

// This extern definition ensures that the linker will not discard
// the static native lib bits, which are brought in from the NDK libraries
// we link in from build.rs.
#[cfg(target_os = "android")]
extern {
    fn app_dummy() -> libc::c_void;
}

// This macro must be used at toplevel because it defines a nested
// module, but macros can only accept identifiers - not paths -
// preventing the expansion of this macro within the android module
// without use of an additionl stub method or other hackery.
#[cfg(target_os = "android")]
android_start!(main);

#[cfg(target_os = "android")]
mod android {
    extern crate android_glue;
    extern crate libc;

    use self::libc::c_int;
    use std::borrow::ToOwned;

    pub fn setup_logging() {
        use self::libc::{STDERR_FILENO, STDOUT_FILENO};
        //use std::env;

        //env::set_var("RUST_LOG", "servo,gfx,msg,util,layers,js,std,rt,extra");
        redirect_output(STDERR_FILENO);
        redirect_output(STDOUT_FILENO);

        unsafe { super::app_dummy(); }
    }

    struct FilePtr(*mut self::libc::FILE);

    unsafe impl Send for FilePtr {}

    fn redirect_output(file_no: c_int) {
        use self::libc::fdopen;
        use self::libc::fgets;
        use self::libc::{pipe, dup2};
        use servo::util::thread::spawn_named;
        use std::ffi::CStr;
        use std::ffi::CString;
        use std::str::from_utf8;

        unsafe {
            let mut pipes: [c_int; 2] = [ 0, 0 ];
            pipe(pipes.as_mut_ptr());
            dup2(pipes[1], file_no);
            let mode = CString::new("r").unwrap();
            let input_file = FilePtr(fdopen(pipes[0], mode.as_ptr()));
            spawn_named("android-logger".to_owned(), move || {
                static READ_SIZE: usize = 1024;
                let mut read_buffer = vec![0; READ_SIZE];
                let FilePtr(input_file) = input_file;
                loop {
                    fgets(read_buffer.as_mut_ptr(), (read_buffer.len() as i32)-1, input_file);
                    let c_str = CStr::from_ptr(read_buffer.as_ptr());
                    let slice = from_utf8(c_str.to_bytes()).unwrap();
                    android_glue::write_log(slice);
                }
            });
        }
    }

}
<|endoftext|>


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

use num_lib;
use std::cmp::{self, max, min};
use std::fmt;
use std::iter;
use std::marker::PhantomData;
use std::num;
use std::ops;

pub trait Int:
    Copy
    + ops::Add<Self, Output=Self>
    + ops::Sub<Self, Output=Self>
    + cmp::Ord
{
    fn zero() -> Self;
    fn one() -> Self;
    fn max_value() -> Self;
    fn from_usize(n: usize) -> Option<Self>;
}
impl Int for isize {
    fn zero() -> isize { 0 }
    fn one() -> isize { 1 }
    fn max_value() -> isize { ::std::isize::MAX }
    fn from_usize(n: usize) -> Option<isize> { num_lib::NumCast::from(n) }
}
impl Int for usize {
    fn zero() -> usize { 0 }
    fn one() -> usize { 1 }
    fn max_value() -> usize { ::std::usize::MAX }
    fn from_usize(n: usize) -> Option<usize> { Some(n) }
}

/// An index type to be used by a `Range`
pub trait RangeIndex: Int + fmt::Debug {
    type Index;
    fn new(x: Self::Index) -> Self;
    fn get(self) -> Self::Index;
}

impl RangeIndex for isize {
    type Index = isize;
    #[inline]
    fn new(x: isize) -> isize { x }

    #[inline]
    fn get(self) -> isize { self }
}

impl RangeIndex for usize {
    type Index = usize;
    #[inline]
    fn new(x: usize) -> usize { x }

    #[inline]
    fn get(self) -> usize { self }
}

/// Implements a range index type with operator overloads
#[macro_export]
macro_rules! int_range_index {
    ($(#[$attr:meta])* struct $Self_:ident($T:ty)) => (
        #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Copy)]
        $(#[$attr])*
        pub struct $Self_(pub $T);

        impl $Self_ {
            #[inline]
            pub fn to_usize(self) -> usize {
                self.get() as usize
            }
        }

        impl RangeIndex for $Self_ {
            type Index = $T;
            #[inline]
            fn new(x: $T) -> $Self_ {
                $Self_(x)
            }

            #[inline]
            fn get(self) -> $T {
                match self { $Self_(x) => x }
            }
        }

        impl $crate::range::Int for $Self_ {
            fn zero() -> $Self_ { $Self_($crate::range::Int::zero()) }
            fn one() -> $Self_ { $Self_($crate::range::Int::one()) }
            fn max_value() -> $Self_ { $Self_($crate::range::Int::max_value()) }
            fn from_usize(n: usize) -> Option<$Self_> { $crate::range::Int::from_usize(n).map($Self_) }
        }

        impl ::std::ops::Add<$Self_> for $Self_ {
            type Output = $Self_;

            #[inline]
            fn add(self, other: $Self_) -> $Self_ {
                $Self_(self.get() + other.get())
            }
        }

        impl ::std::ops::Sub<$Self_> for $Self_ {
            type Output = $Self_;

            #[inline]
            fn sub(self, other: $Self_) -> $Self_ {
                $Self_(self.get() - other.get())
            }
        }

        impl ::std::ops::Neg for $Self_ {
            type Output = $Self_;

            #[inline]
            fn neg(self) -> $Self_ {
                $Self_(-self.get())
            }
        }
    )
}

/// A range of indices
#[derive(Clone, RustcEncodable, Copy, Deserialize, Serialize)]
pub struct Range<I> {
    begin: I,
    length: I,
}

impl<I: RangeIndex> fmt::Debug for Range<I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?} .. {:?})", self.begin(), self.end())
    }
}

/// An iterator over each index in a range
pub struct EachIndex<T, I> {
    it: ops::Range<T>,
    phantom: PhantomData<I>,
}

pub fn each_index<T: Int, I: RangeIndex<Index=T>>(start: I, stop: I) -> EachIndex<T, I> {
    EachIndex { it: start.get()..stop.get(), phantom: PhantomData }
}

impl<T: Int, I: RangeIndex<Index=T>> Iterator for EachIndex<T, I>
where T: Int + num::One + iter::Step, for<'a> &'a T: ops::Add<&'a T, Output = T> {
    type Item = I;

    #[inline]
    fn next(&mut self) -> Option<I> {
        self.it.next().map(RangeIndex::new)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.it.size_hint()
    }
}

impl<I: RangeIndex> Range<I> {
    /// Create a new range from beginning and length offsets. This could be
    /// denoted as `[begin, begin + length)`.
    ///
    /// ~~~ignore
    ///    |-- begin ->|-- length ->|
    ///    |           |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn new(begin: I, length: I) -> Range<I> {
        Range { begin: begin, length: length }
    }

    #[inline]
    pub fn empty() -> Range<I> {
        Range::new(Int::zero(), Int::zero())
    }

    /// The index offset to the beginning of the range.
    ///
    /// ~~~ignore
    ///    |-- begin ->|
    ///    |           |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn begin(&self) -> I { self.begin  }

    /// The index offset from the beginning to the end of the range.
    ///
    /// ~~~ignore
    ///                |-- length ->|
    ///                |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn length(&self) -> I { self.length }

    /// The index offset to the end of the range.
    ///
    /// ~~~ignore
    ///    |--------- end --------->|
    ///    |                        |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn end(&self) -> I { self.begin + self.length }

    /// `true` if the index is between the beginning and the end of the range.
    ///
    /// ~~~ignore
    ///        false        true      false
    ///          |           |          |
    /// <- o - - + - - +=====+======+ - + - ->
    /// ~~~
    #[inline]
    pub fn contains(&self, i: I) -> bool {
        i >= self.begin() && i < self.end()
    }

    /// `true` if the offset from the beginning to the end of the range is zero.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.length() == Int::zero()
    }

    /// Shift the entire range by the supplied index delta.
    ///
    /// ~~~ignore
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - +============+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn shift_by(&mut self, delta: I) {
        self.begin = self.begin + delta;
    }

    /// Extend the end of the range by the supplied index delta.
    ///
    /// ~~~ignore
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_by(&mut self, delta: I) {
        self.length = self.length + delta;
    }

    /// Move the end of the range to the target index.
    ///
    /// ~~~ignore
    ///                               target
    ///                                 |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_to(&mut self, target: I) {
        self.length = target - self.begin;
    }

    /// Adjust the beginning offset and the length by the supplied deltas.
    #[inline]
    pub fn adjust_by(&mut self, begin_delta: I, length_delta: I) {
        self.begin = self.begin + begin_delta;
        self.length = self.length + length_delta;
    }

    /// Set the begin and length values.
    #[inline]
    pub fn reset(&mut self, begin: I, length: I) {
        self.begin = begin;
        self.length = length;
    }

    #[inline]
    pub fn intersect(&self, other: &Range<I>) -> Range<I> {
        let begin = max(self.begin(), other.begin());
        let end = min(self.end(), other.end());

        if end < begin {
            Range::empty()
        } else {
            Range::new(begin, end - begin)
        }
    }
}

/// Methods for `Range`s with indices based on integer values
impl<T: Int, I: RangeIndex<Index=T>> Range<I> {
    /// Returns an iterater that increments over `[begin, end)`.
    #[inline]
    pub fn each_index(&self) -> EachIndex<T, I> {
        each_index(self.begin(), self.end())
    }

    #[inline]
    pub fn is_valid_for_string(&self, s: &str) -> bool {
        let s_len = s.len();
        match Int::from_usize(s_len) {
            Some(len) => {
                let len = RangeIndex::new(len);
                self.begin() < len
                && self.end() <= len
                && self.length() <= len
            },
            None => {
                debug!("Range<T>::is_valid_for_string: string length \
                        (len={:?}) is longer than the max value for the range \
                        index (max={:?})", s_len,
                        {
                            let max: T = Int::max_value();
                            let val: I = RangeIndex::new(max);
                            val
                        });
                false
            },
        }
    }
}
<commit_msg>Remove unused method from Range<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use num_lib;
use std::cmp::{self, max, min};
use std::fmt;
use std::iter;
use std::marker::PhantomData;
use std::num;
use std::ops;

pub trait Int:
    Copy
    + ops::Add<Self, Output=Self>
    + ops::Sub<Self, Output=Self>
    + cmp::Ord
{
    fn zero() -> Self;
    fn one() -> Self;
    fn max_value() -> Self;
    fn from_usize(n: usize) -> Option<Self>;
}
impl Int for isize {
    fn zero() -> isize { 0 }
    fn one() -> isize { 1 }
    fn max_value() -> isize { ::std::isize::MAX }
    fn from_usize(n: usize) -> Option<isize> { num_lib::NumCast::from(n) }
}
impl Int for usize {
    fn zero() -> usize { 0 }
    fn one() -> usize { 1 }
    fn max_value() -> usize { ::std::usize::MAX }
    fn from_usize(n: usize) -> Option<usize> { Some(n) }
}

/// An index type to be used by a `Range`
pub trait RangeIndex: Int + fmt::Debug {
    type Index;
    fn new(x: Self::Index) -> Self;
    fn get(self) -> Self::Index;
}

impl RangeIndex for isize {
    type Index = isize;
    #[inline]
    fn new(x: isize) -> isize { x }

    #[inline]
    fn get(self) -> isize { self }
}

impl RangeIndex for usize {
    type Index = usize;
    #[inline]
    fn new(x: usize) -> usize { x }

    #[inline]
    fn get(self) -> usize { self }
}

/// Implements a range index type with operator overloads
#[macro_export]
macro_rules! int_range_index {
    ($(#[$attr:meta])* struct $Self_:ident($T:ty)) => (
        #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Copy)]
        $(#[$attr])*
        pub struct $Self_(pub $T);

        impl $Self_ {
            #[inline]
            pub fn to_usize(self) -> usize {
                self.get() as usize
            }
        }

        impl RangeIndex for $Self_ {
            type Index = $T;
            #[inline]
            fn new(x: $T) -> $Self_ {
                $Self_(x)
            }

            #[inline]
            fn get(self) -> $T {
                match self { $Self_(x) => x }
            }
        }

        impl $crate::range::Int for $Self_ {
            fn zero() -> $Self_ { $Self_($crate::range::Int::zero()) }
            fn one() -> $Self_ { $Self_($crate::range::Int::one()) }
            fn max_value() -> $Self_ { $Self_($crate::range::Int::max_value()) }
            fn from_usize(n: usize) -> Option<$Self_> { $crate::range::Int::from_usize(n).map($Self_) }
        }

        impl ::std::ops::Add<$Self_> for $Self_ {
            type Output = $Self_;

            #[inline]
            fn add(self, other: $Self_) -> $Self_ {
                $Self_(self.get() + other.get())
            }
        }

        impl ::std::ops::Sub<$Self_> for $Self_ {
            type Output = $Self_;

            #[inline]
            fn sub(self, other: $Self_) -> $Self_ {
                $Self_(self.get() - other.get())
            }
        }

        impl ::std::ops::Neg for $Self_ {
            type Output = $Self_;

            #[inline]
            fn neg(self) -> $Self_ {
                $Self_(-self.get())
            }
        }
    )
}

/// A range of indices
#[derive(Clone, RustcEncodable, Copy, Deserialize, Serialize)]
pub struct Range<I> {
    begin: I,
    length: I,
}

impl<I: RangeIndex> fmt::Debug for Range<I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?} .. {:?})", self.begin(), self.end())
    }
}

/// An iterator over each index in a range
pub struct EachIndex<T, I> {
    it: ops::Range<T>,
    phantom: PhantomData<I>,
}

pub fn each_index<T: Int, I: RangeIndex<Index=T>>(start: I, stop: I) -> EachIndex<T, I> {
    EachIndex { it: start.get()..stop.get(), phantom: PhantomData }
}

impl<T: Int, I: RangeIndex<Index=T>> Iterator for EachIndex<T, I>
where T: Int + num::One + iter::Step, for<'a> &'a T: ops::Add<&'a T, Output = T> {
    type Item = I;

    #[inline]
    fn next(&mut self) -> Option<I> {
        self.it.next().map(RangeIndex::new)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.it.size_hint()
    }
}

impl<I: RangeIndex> Range<I> {
    /// Create a new range from beginning and length offsets. This could be
    /// denoted as `[begin, begin + length)`.
    ///
    /// ~~~ignore
    ///    |-- begin ->|-- length ->|
    ///    |           |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn new(begin: I, length: I) -> Range<I> {
        Range { begin: begin, length: length }
    }

    #[inline]
    pub fn empty() -> Range<I> {
        Range::new(Int::zero(), Int::zero())
    }

    /// The index offset to the beginning of the range.
    ///
    /// ~~~ignore
    ///    |-- begin ->|
    ///    |           |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn begin(&self) -> I { self.begin  }

    /// The index offset from the beginning to the end of the range.
    ///
    /// ~~~ignore
    ///                |-- length ->|
    ///                |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn length(&self) -> I { self.length }

    /// The index offset to the end of the range.
    ///
    /// ~~~ignore
    ///    |--------- end --------->|
    ///    |                        |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn end(&self) -> I { self.begin + self.length }

    /// `true` if the index is between the beginning and the end of the range.
    ///
    /// ~~~ignore
    ///        false        true      false
    ///          |           |          |
    /// <- o - - + - - +=====+======+ - + - ->
    /// ~~~
    #[inline]
    pub fn contains(&self, i: I) -> bool {
        i >= self.begin() && i < self.end()
    }

    /// `true` if the offset from the beginning to the end of the range is zero.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.length() == Int::zero()
    }

    /// Shift the entire range by the supplied index delta.
    ///
    /// ~~~ignore
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - +============+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn shift_by(&mut self, delta: I) {
        self.begin = self.begin + delta;
    }

    /// Extend the end of the range by the supplied index delta.
    ///
    /// ~~~ignore
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_by(&mut self, delta: I) {
        self.length = self.length + delta;
    }

    /// Move the end of the range to the target index.
    ///
    /// ~~~ignore
    ///                               target
    ///                                 |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_to(&mut self, target: I) {
        self.length = target - self.begin;
    }

    /// Adjust the beginning offset and the length by the supplied deltas.
    #[inline]
    pub fn adjust_by(&mut self, begin_delta: I, length_delta: I) {
        self.begin = self.begin + begin_delta;
        self.length = self.length + length_delta;
    }

    /// Set the begin and length values.
    #[inline]
    pub fn reset(&mut self, begin: I, length: I) {
        self.begin = begin;
        self.length = length;
    }

    #[inline]
    pub fn intersect(&self, other: &Range<I>) -> Range<I> {
        let begin = max(self.begin(), other.begin());
        let end = min(self.end(), other.end());

        if end < begin {
            Range::empty()
        } else {
            Range::new(begin, end - begin)
        }
    }
}

/// Methods for `Range`s with indices based on integer values
impl<T: Int, I: RangeIndex<Index=T>> Range<I> {
    /// Returns an iterater that increments over `[begin, end)`.
    #[inline]
    pub fn each_index(&self) -> EachIndex<T, I> {
        each_index(self.begin(), self.end())
    }
}
<|endoftext|>


<commit_before>#![feature(old_path)]

extern crate piston;
extern crate ai_behavior;
extern crate sprite;
extern crate graphics;
extern crate sdl2_window;
extern crate opengl_graphics;

use std::cell::RefCell;
use std::rc::Rc;

use sprite::*;
use ai_behavior::{
    Action,
    Sequence,
    Wait,
    WaitForever,
    While,
};

use sdl2_window::Sdl2Window;
use opengl_graphics::{
    GlGraphics,
    OpenGL,
    Texture,
};

fn main() {
    let (width, height) = (300, 300);
    let opengl = OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        piston::window::WindowSettings {
            title: "Sprite".to_string(),
            size: [width, height],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let mut scene = Scene::new();
    let tex = Path::new("./rust-logo.png");
    let tex = Rc::new(Texture::from_path(&tex).unwrap());
    let mut sprite = Sprite::from_texture(tex.clone());
    sprite.set_position(width as f64 / 2.0, height as f64 / 2.0);

    let id = scene.add_child(sprite);

    // Run a sequence or animations.
    let seq = Sequence(vec![
        Action(Ease(EaseFunction::CubicOut, Box::new(ScaleTo(2.0, 0.5, 0.5)))),
        Action(Ease(EaseFunction::BounceOut, Box::new(MoveBy(1.0, 0.0, 100.0)))),
        Action(Ease(EaseFunction::ElasticOut, Box::new(MoveBy(2.0, 0.0, -100.0)))),
        Action(Ease(EaseFunction::BackInOut, Box::new(MoveBy(1.0, 0.0, -100.0)))),
        Wait(0.5),
        Action(Ease(EaseFunction::ExponentialInOut, Box::new(MoveBy(1.0, 0.0, 100.0)))),
        Action(Blink(1.0, 5)),
        While(Box::new(WaitForever), vec![
            Action(Ease(EaseFunction::QuadraticIn, Box::new(FadeOut(1.0)))),
            Action(Ease(EaseFunction::QuadraticOut, Box::new(FadeIn(1.0)))),
        ]),
    ]);
    scene.run(id.clone(), &seq);

    // This animation and the one above can run in parallel.
    let rotate = Action(Ease(EaseFunction::ExponentialInOut,
        Box::new(RotateTo(2.0, 360.0))));
    scene.run(id.clone(), &rotate);

    println!("Press any key to pause/resume the animation!");

    let ref mut gl = GlGraphics::new(opengl);
    let window = RefCell::new(window);
    for e in piston::events(&window) {
        use piston::event::{ PressEvent, RenderEvent };

        scene.event(&e);

        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([1.0, 1.0, 1.0, 1.0], gl);
                scene.draw(&c, gl);
            });
        }
        if let Some(_) = e.press_args() {
            scene.toggle(id.clone(), &seq);
            scene.toggle(id.clone(), &rotate);
        }
    }
}
<commit_msg>Update sprite example to latest graphics<commit_after>#![feature(old_path)]

extern crate piston;
extern crate ai_behavior;
extern crate sprite;
extern crate graphics;
extern crate sdl2_window;
extern crate opengl_graphics;

use std::cell::RefCell;
use std::rc::Rc;

use sprite::*;
use ai_behavior::{
    Action,
    Sequence,
    Wait,
    WaitForever,
    While,
};

use sdl2_window::Sdl2Window;
use opengl_graphics::{
    GlGraphics,
    OpenGL,
    Texture,
};

fn main() {
    let (width, height) = (300, 300);
    let opengl = OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        piston::window::WindowSettings {
            title: "Sprite".to_string(),
            size: [width, height],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let mut scene = Scene::new();
    let tex = Path::new("./rust-logo.png");
    let tex = Rc::new(Texture::from_path(&tex).unwrap());
    let mut sprite = Sprite::from_texture(tex.clone());
    sprite.set_position(width as f64 / 2.0, height as f64 / 2.0);

    let id = scene.add_child(sprite);

    // Run a sequence or animations.
    let seq = Sequence(vec![
        Action(Ease(EaseFunction::CubicOut, Box::new(ScaleTo(2.0, 0.5, 0.5)))),
        Action(Ease(EaseFunction::BounceOut, Box::new(MoveBy(1.0, 0.0, 100.0)))),
        Action(Ease(EaseFunction::ElasticOut, Box::new(MoveBy(2.0, 0.0, -100.0)))),
        Action(Ease(EaseFunction::BackInOut, Box::new(MoveBy(1.0, 0.0, -100.0)))),
        Wait(0.5),
        Action(Ease(EaseFunction::ExponentialInOut, Box::new(MoveBy(1.0, 0.0, 100.0)))),
        Action(Blink(1.0, 5)),
        While(Box::new(WaitForever), vec![
            Action(Ease(EaseFunction::QuadraticIn, Box::new(FadeOut(1.0)))),
            Action(Ease(EaseFunction::QuadraticOut, Box::new(FadeIn(1.0)))),
        ]),
    ]);
    scene.run(id.clone(), &seq);

    // This animation and the one above can run in parallel.
    let rotate = Action(Ease(EaseFunction::ExponentialInOut,
        Box::new(RotateTo(2.0, 360.0))));
    scene.run(id.clone(), &rotate);

    println!("Press any key to pause/resume the animation!");

    let ref mut gl = GlGraphics::new(opengl);
    let window = RefCell::new(window);
    for e in piston::events(&window) {
        use piston::event::{ PressEvent, RenderEvent };

        scene.event(&e);

        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([1.0, 1.0, 1.0, 1.0], gl);
                scene.draw(c.transform, gl);
            });
        }
        if let Some(_) = e.press_args() {
            scene.toggle(id.clone(), &seq);
            scene.toggle(id.clone(), &rotate);
        }
    }
}
<|endoftext|>


<commit_before>///! Inline of `https://github.com/bltavares/atomic-shim`

#[cfg(not(any(
    target_arch = "mips",
    target_arch = "powerpc",
    feature = "mutex"
)))]
pub use std::sync::atomic::{AtomicI64, AtomicU64};
#[cfg(any(target_arch = "mips", target_arch = "powerpc", feature = "mutex"))]
mod shim {
    use parking_lot::{const_rwlock, RwLock};
    use std::sync::atomic::Ordering;

    #[derive(Debug, Default)]
    pub struct AtomicU64 {
        value: RwLock<u64>,
    }

    impl AtomicU64 {
        pub const fn new(v: u64) -> Self {
            Self { value: const_rwlock(v) }
        }

        #[allow(dead_code)]
        pub fn load(&self, _: Ordering) -> u64 {
            *self.value.read()
        }

        #[allow(dead_code)]
        pub fn store(&self, value: u64, _: Ordering) {
            let mut lock = self.value.write();
            *lock = value;
        }

        #[allow(dead_code)]
        pub fn swap(&self, value: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = value;
            prev
        }

        #[allow(dead_code)]
        pub fn compare_exchange(
            &self,
            current: u64,
            new: u64,
            _: Ordering,
            _: Ordering,
        ) -> Result<u64, u64> {
            let mut lock = self.value.write();
            let prev = *lock;
            if prev == current {
                *lock = new;
                Ok(current)
            } else {
                Err(prev)
            }
        }

        #[allow(dead_code)]
        pub fn compare_exchange_weak(
            &self,
            current: u64,
            new: u64,
            success: Ordering,
            failure: Ordering,
        ) -> Result<u64, u64> {
            self.compare_exchange(current, new, success, failure)
        }

        #[allow(dead_code)]
        pub fn fetch_add(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev.wrapping_add(val);
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_sub(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev.wrapping_sub(val);
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_and(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev & val;
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_nand(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = !(prev & val);
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_or(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev | val;
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_xor(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev ^ val;
            prev
        }
    }

    impl From<u64> for AtomicU64 {
        fn from(value: u64) -> Self {
            AtomicU64::new(value)
        }
    }

    #[derive(Debug, Default)]
    pub struct AtomicI64 {
        value: RwLock<i64>,
    }

    impl AtomicI64 {
        pub const fn new(v: i64) -> Self {
            Self { value: const_rwlock(v) }
        }

        #[allow(dead_code)]
        pub fn load(&self, _: Ordering) -> i64 {
            *self.value.read()
        }

        #[allow(dead_code)]
        pub fn store(&self, value: i64, _: Ordering) {
            let mut lock = self.value.write();
            *lock = value;
        }

        #[allow(dead_code)]
        pub fn swap(&self, value: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = value;
            prev
        }

        #[allow(dead_code)]
        pub fn compare_exchange(
            &self,
            current: i64,
            new: i64,
            _: Ordering,
            _: Ordering,
        ) -> Result<i64, i64> {
            let mut lock = self.value.write();
            let prev = *lock;
            if prev == current {
                *lock = new;
                Ok(current)
            } else {
                Err(prev)
            }
        }

        #[allow(dead_code)]
        pub fn compare_exchange_weak(
            &self,
            current: i64,
            new: i64,
            success: Ordering,
            failure: Ordering,
        ) -> Result<i64, i64> {
            self.compare_exchange(current, new, success, failure)
        }

        #[allow(dead_code)]
        pub fn fetch_add(&self, val: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev.wrapping_add(val);
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_sub(&self, val: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev.wrapping_sub(val);
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_and(&self, val: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev & val;
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_nand(&self, val: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = !(prev & val);
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_or(&self, val: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev | val;
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_xor(&self, val: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev ^ val;
            prev
        }
    }

    impl From<i64> for AtomicI64 {
        fn from(value: i64) -> Self {
            AtomicI64::new(value)
        }
    }
}

#[cfg(any(
    target_arch = "mips",
    target_arch = "powerpc",
    feature = "mutex"
))]
pub use shim::{AtomicI64, AtomicU64};
<commit_msg>Add atomic_shim impl for fetch_max<commit_after>///! Inline of `https://github.com/bltavares/atomic-shim`

#[cfg(not(any(
    target_arch = "mips",
    target_arch = "powerpc",
    feature = "mutex"
)))]
pub use std::sync::atomic::{AtomicI64, AtomicU64};
#[cfg(any(target_arch = "mips", target_arch = "powerpc", feature = "mutex"))]
mod shim {
    use parking_lot::{const_rwlock, RwLock};
    use std::sync::atomic::Ordering;

    #[derive(Debug, Default)]
    pub struct AtomicU64 {
        value: RwLock<u64>,
    }

    impl AtomicU64 {
        pub const fn new(v: u64) -> Self {
            Self { value: const_rwlock(v) }
        }

        #[allow(dead_code)]
        pub fn load(&self, _: Ordering) -> u64 {
            *self.value.read()
        }

        #[allow(dead_code)]
        pub fn store(&self, value: u64, _: Ordering) {
            let mut lock = self.value.write();
            *lock = value;
        }

        #[allow(dead_code)]
        pub fn swap(&self, value: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = value;
            prev
        }

        #[allow(dead_code)]
        pub fn compare_exchange(
            &self,
            current: u64,
            new: u64,
            _: Ordering,
            _: Ordering,
        ) -> Result<u64, u64> {
            let mut lock = self.value.write();
            let prev = *lock;
            if prev == current {
                *lock = new;
                Ok(current)
            } else {
                Err(prev)
            }
        }

        #[allow(dead_code)]
        pub fn compare_exchange_weak(
            &self,
            current: u64,
            new: u64,
            success: Ordering,
            failure: Ordering,
        ) -> Result<u64, u64> {
            self.compare_exchange(current, new, success, failure)
        }

        #[allow(dead_code)]
        pub fn fetch_add(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev.wrapping_add(val);
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_sub(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev.wrapping_sub(val);
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_and(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev & val;
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_nand(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = !(prev & val);
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_or(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev | val;
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_xor(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev ^ val;
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_max(&self, val: u64, _: Ordering) -> u64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev.max(val);
            prev
        }
    }

    impl From<u64> for AtomicU64 {
        fn from(value: u64) -> Self {
            AtomicU64::new(value)
        }
    }

    #[derive(Debug, Default)]
    pub struct AtomicI64 {
        value: RwLock<i64>,
    }

    impl AtomicI64 {
        pub const fn new(v: i64) -> Self {
            Self { value: const_rwlock(v) }
        }

        #[allow(dead_code)]
        pub fn load(&self, _: Ordering) -> i64 {
            *self.value.read()
        }

        #[allow(dead_code)]
        pub fn store(&self, value: i64, _: Ordering) {
            let mut lock = self.value.write();
            *lock = value;
        }

        #[allow(dead_code)]
        pub fn swap(&self, value: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = value;
            prev
        }

        #[allow(dead_code)]
        pub fn compare_exchange(
            &self,
            current: i64,
            new: i64,
            _: Ordering,
            _: Ordering,
        ) -> Result<i64, i64> {
            let mut lock = self.value.write();
            let prev = *lock;
            if prev == current {
                *lock = new;
                Ok(current)
            } else {
                Err(prev)
            }
        }

        #[allow(dead_code)]
        pub fn compare_exchange_weak(
            &self,
            current: i64,
            new: i64,
            success: Ordering,
            failure: Ordering,
        ) -> Result<i64, i64> {
            self.compare_exchange(current, new, success, failure)
        }

        #[allow(dead_code)]
        pub fn fetch_add(&self, val: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev.wrapping_add(val);
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_sub(&self, val: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev.wrapping_sub(val);
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_and(&self, val: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev & val;
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_nand(&self, val: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = !(prev & val);
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_or(&self, val: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev | val;
            prev
        }

        #[allow(dead_code)]
        pub fn fetch_xor(&self, val: i64, _: Ordering) -> i64 {
            let mut lock = self.value.write();
            let prev = *lock;
            *lock = prev ^ val;
            prev
        }
    }

    impl From<i64> for AtomicI64 {
        fn from(value: i64) -> Self {
            AtomicI64::new(value)
        }
    }
}

#[cfg(any(
    target_arch = "mips",
    target_arch = "powerpc",
    feature = "mutex"
))]
pub use shim::{AtomicI64, AtomicU64};
<|endoftext|>


<commit_before>#[derive(Debug, Clone, PartialEq)]
pub enum SimilarityModel {
    TfIdf,
    Bm25{k1: f64, b: f64},
}

/// tf(term_frequency) = log(term_frequency + 1.0) + 1.0
#[inline]
fn tf(term_frequency: u32) -> f64 {
    (term_frequency as f64 + 1.0f64).ln() + 1.0
}

/// idf(term_docs, total_docs) = log((total_docs + 1.0) / (term_docs + 1.0)) + 1.0
#[inline]
fn idf(term_docs: u64, total_docs: u64) -> f64 {
    ((total_docs as f64 + 1.0) / (term_docs as f64 + 1.0)).ln() + 1.0
}

impl SimilarityModel {
    pub fn score(&self, term_frequency: u32, length: f64, total_tokens: u64, total_docs: u64, total_docs_with_term: u64) -> f64 {
        match *self {
            SimilarityModel::TfIdf => {
                let tf = tf(term_frequency);
                let idf = idf(total_docs_with_term, total_docs);

                tf * idf
            }
            SimilarityModel::Bm25{k1, b} => {
                let tf = tf(term_frequency);
                let idf = idf(total_docs_with_term, total_docs);
                let average_length = (total_tokens as f64 + 1.0f64) / (total_docs as f64 + 1.0f64);

                idf * (k1 + 1.0) * (tf / (tf + (k1 * ((1.0 - b) + b * length.sqrt() / average_length.sqrt())) + 1.0f64))
            }
        }
    }
}

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

    #[test]
    fn test_tf_idf_higher_term_freq_increases_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(2, 40, 100, 10, 5) > similarity.score(1, 40, 100, 10, 5));
    }

    #[test]
    fn test_tf_idf_lower_term_docs_increases_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(1, 40, 100, 10, 5) > similarity.score(1, 40, 100, 10, 10));
    }

    #[test]
    fn test_tf_idf_field_length_doesnt_affect_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(1, 100, 100, 20, 5) == similarity.score(1, 40, 100, 20, 5));
    }

    #[test]
    fn test_tf_idf_total_tokens_doesnt_affect_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(1, 40, 1000, 20, 5) == similarity.score(1, 40, 100, 20, 5));
    }

    #[test]
    fn test_tf_idf_handles_zeros() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(0, 0, 0, 0, 0).is_finite());
    }

    #[test]
    fn test_bm25_higher_term_freq_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(2, 40, 100, 10, 5) > similarity.score(1, 40, 100, 10, 5));
    }

    #[test]
    fn test_bm25_lower_term_docs_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(1, 40, 100, 10, 5) > similarity.score(1, 40, 100, 10, 10));
    }

    #[test]
    fn test_bm25_lower_field_length_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(1, 40, 100, 20, 5) > similarity.score(1, 100, 100, 20, 5));
    }

    #[test]
    fn test_bm25_higher_total_tokens_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(1, 40, 1000, 20, 5) > similarity.score(1, 40, 100, 20, 5));
    }

    #[test]
    fn test_bm25_handles_zeros() {
        let similarity = SimilarityModel::Bm25 {
            k1: 0.0,
            b: 0.0,
        };

        assert!(similarity.score(0, 0, 0, 0, 0).is_finite());
    }
}
<commit_msg>Fixed similarity tests<commit_after>#[derive(Debug, Clone, PartialEq)]
pub enum SimilarityModel {
    TfIdf,
    Bm25{k1: f64, b: f64},
}

/// tf(term_frequency) = log(term_frequency + 1.0) + 1.0
#[inline]
fn tf(term_frequency: u32) -> f64 {
    (term_frequency as f64 + 1.0f64).ln() + 1.0
}

/// idf(term_docs, total_docs) = log((total_docs + 1.0) / (term_docs + 1.0)) + 1.0
#[inline]
fn idf(term_docs: u64, total_docs: u64) -> f64 {
    ((total_docs as f64 + 1.0) / (term_docs as f64 + 1.0)).ln() + 1.0
}

impl SimilarityModel {
    pub fn score(&self, term_frequency: u32, length: f64, total_tokens: u64, total_docs: u64, total_docs_with_term: u64) -> f64 {
        match *self {
            SimilarityModel::TfIdf => {
                let tf = tf(term_frequency);
                let idf = idf(total_docs_with_term, total_docs);

                tf * idf
            }
            SimilarityModel::Bm25{k1, b} => {
                let tf = tf(term_frequency);
                let idf = idf(total_docs_with_term, total_docs);
                let average_length = (total_tokens as f64 + 1.0f64) / (total_docs as f64 + 1.0f64);

                idf * (k1 + 1.0) * (tf / (tf + (k1 * ((1.0 - b) + b * length.sqrt() / average_length.sqrt())) + 1.0f64))
            }
        }
    }
}

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

    #[test]
    fn test_tf_idf_higher_term_freq_increases_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(2, 40.0, 100, 10, 5) > similarity.score(1, 40.0, 100, 10, 5));
    }

    #[test]
    fn test_tf_idf_lower_term_docs_increases_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(1, 40.0, 100, 10, 5) > similarity.score(1, 40.0, 100, 10, 10));
    }

    #[test]
    fn test_tf_idf_field_length_doesnt_affect_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(1, 100.0, 100, 20, 5) == similarity.score(1, 40.0, 100, 20, 5));
    }

    #[test]
    fn test_tf_idf_total_tokens_doesnt_affect_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(1, 40.0, 1000, 20, 5) == similarity.score(1, 40.0, 100, 20, 5));
    }

    #[test]
    fn test_tf_idf_handles_zeros() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(0, 0.0, 0, 0, 0).is_finite());
    }

    #[test]
    fn test_bm25_higher_term_freq_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(2, 40.0, 100, 10, 5) > similarity.score(1, 40.0, 100, 10, 5));
    }

    #[test]
    fn test_bm25_lower_term_docs_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(1, 40.0, 100, 10, 5) > similarity.score(1, 40.0, 100, 10, 10));
    }

    #[test]
    fn test_bm25_lower_field_length_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(1, 40.0, 100, 20, 5) > similarity.score(1, 100.0, 100, 20, 5));
    }

    #[test]
    fn test_bm25_higher_total_tokens_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(1, 40.0, 1000, 20, 5) > similarity.score(1, 40.0, 100, 20, 5));
    }

    #[test]
    fn test_bm25_handles_zeros() {
        let similarity = SimilarityModel::Bm25 {
            k1: 0.0,
            b: 0.0,
        };

        assert!(similarity.score(0, 0.0, 0, 0, 0).is_finite());
    }
}
<|endoftext|>


<commit_before>//! JIT Compiler to generate code fragments in runtime.

extern crate libc;
extern crate llvm_sys;

#[macro_use]
mod macros;
mod block;
mod buffer;
mod builder;
mod util;
mod types;
mod value;

use std::mem;
use std::ptr;

use llvm_sys::analysis;
use llvm_sys::core;
use llvm_sys::prelude::{
  LLVMContextRef,
  LLVMModuleRef
};
use llvm_sys::bit_reader::LLVMParseBitcodeInContext;
use llvm_sys::execution_engine::{
  LLVMExecutionEngineRef,
  LLVMLinkInMCJIT,
  LLVMMCJITCompilerOptions,
  LLVMCreateMCJITCompilerForModule
};
use llvm_sys::linker;
use llvm_sys::transforms::pass_manager_builder as pass;
use llvm_sys::target::{
  LLVM_InitializeNativeTarget,
  LLVM_InitializeNativeAsmPrinter
};
use llvm_sys::target_machine::LLVMCodeModel;

use libc::{c_char, c_uint};

use buffer::MemoryBuffer;
use builder::Builder;
use value::{GlobalValue, Value, ValueIter};
use types::Ty;
use util::chars;

pub const JIT_OPT_LVEL: usize = 2;

#[repr(C)]
#[derive(Copy, Clone)]
pub enum AddressSpace
{
  Generic = 0,
  Global = 1,
  Shared = 3,
  Const = 4,
  Local = 5,
}

fn new_module(ctx: LLVMContextRef, name: &str) -> LLVMModuleRef
{
  let c_name = util::chars::from_str(name);
  unsafe {
  	core::LLVMModuleCreateWithNameInContext(c_name, ctx)
  }
}
fn new_module_from_bc(ctx: LLVMContextRef, path: &str) -> Result<LLVMModuleRef, String>
{
  unsafe {
    let mut out: LLVMModuleRef = mem::uninitialized();
    let mut err: *mut c_char   = mem::uninitialized();
    let buf = try!(MemoryBuffer::from_file(path));

    let ret = LLVMParseBitcodeInContext(ctx,
                                        buf.as_ptr(),
    	                                  &mut out,
    	                                  &mut err);
    llvm_ret!(ret, out, err)
  }
}

fn new_jit_ee(m: LLVMModuleRef, opt_lv: usize) -> Result<LLVMExecutionEngineRef, String>
{
  unsafe {
    let mut ee : LLVMExecutionEngineRef = mem::uninitialized();
    let mut err: *mut c_char = mem::uninitialized();

    LLVMLinkInMCJIT();
    expect_noerr!(LLVM_InitializeNativeTarget(), "failed to initialize native target");
    expect_noerr!(LLVM_InitializeNativeAsmPrinter(), "failed to initialize native asm printer");

    let mut opts = new_mcjit_compiler_options(opt_lv);
    let opts_size = mem::size_of::<LLVMMCJITCompilerOptions>();

    let ret = LLVMCreateMCJITCompilerForModule(&mut ee,
      		                                     m,
      		                                     &mut opts,
      		                                     opts_size as u64,
      		                                     &mut err);
    llvm_ret!(ret, ee, err)
  }
}

fn new_mcjit_compiler_options(opt_lv: usize) -> LLVMMCJITCompilerOptions
{
  LLVMMCJITCompilerOptions {
    OptLevel: opt_lv as c_uint,
    CodeModel: LLVMCodeModel::LLVMCodeModelJITDefault,
    NoFramePointerElim: 0,
    EnableFastISel: 1,
    MCJMM: ptr::null_mut()
  }
}

pub struct JitCompiler
{
  ctx    : LLVMContextRef,
  module : LLVMModuleRef,
  ee     : LLVMExecutionEngineRef,
  //builder: Builder // internal use
}

impl JitCompiler {

  pub fn new(module_name: &str) -> Result<JitCompiler, String>
  {
    let ctx     = unsafe { core::LLVMContextCreate() };
    let module  = new_module(ctx, module_name);
    JitCompiler::new_internal(ctx, module)
  }

  pub fn new_from_bc(bitcode_path: &str) -> Result<JitCompiler, String>
  {
    let ctx     = unsafe { core::LLVMContextCreate() };
    let module  = try!(new_module_from_bc(ctx, bitcode_path));
    JitCompiler::new_internal(ctx, module)
  }

  fn new_internal(ctx: LLVMContextRef, module: LLVMModuleRef) -> Result<JitCompiler, String>
  {
    let ee      = try!(new_jit_ee(module, JIT_OPT_LVEL));
    //let builder = Builder(unsafe { core::LLVMCreateBuilderInContext(ctx) });

    Ok(JitCompiler {
      ctx    : ctx,
      module : module,
      ee     : ee,
      //builder: builder
    })
  }

  pub fn context(&self) -> LLVMContextRef { self.ctx }
  pub fn module(&self) -> LLVMModuleRef { self.module }
  pub fn engine(&self) -> LLVMExecutionEngineRef { self.ee }

  /// Returns the target data of the base module represented as a string
  pub fn get_target(&self) -> &str
  {
    unsafe {
      let target = core::LLVMGetTarget(self.module);
      chars::to_str(target)
    }
  }

  /// Get the data layout of the base module
  pub fn get_data_layout(&self) -> &str
  {
  	unsafe {
  		let layout = core::LLVMGetDataLayout(self.module);
  		chars::to_str(layout as *mut c_char)
  	}
  }

  /// Add an external global to the module with the given type and name.
  pub fn add_global(&self, name: &str, ty: &Ty) -> GlobalValue
  {
    let c_name = chars::from_str(name);
    GlobalValue(
      unsafe {
        core::LLVMAddGlobal(self.module, ty.0, c_name)
      }
    )
  }

  /// Add a global in the given address space to the module with the given type and name.
  pub fn add_global_in_addr_space(&self,
  	                              name: &str,
  	                              ty: &Ty,
  	                              sp: AddressSpace) -> GlobalValue
  {
    let c_name = chars::from_str(name);
    GlobalValue(
      unsafe {
        core::LLVMAddGlobalInAddressSpace(self.module, ty.0, c_name, sp as c_uint)
      }
    )
  }

  /// Add a constant global to the module with the given type, name and value.
  pub fn add_global_constant(&self, name: &str, val: &Value) -> GlobalValue
  {
    let c_name = chars::from_str(name);
    GlobalValue(
      unsafe {
        let global = core::LLVMAddGlobal(self.module, val.ty().0, c_name);
        core::LLVMSetInitializer (global, val.0);
        global
      }
    )
  }

  /// Get the global with the name given, or `None` if no global with that name exists.
  pub fn get_global(&self, name: &str) -> Option<GlobalValue>
  {
    let c_name = chars::from_str(name);
    unsafe {
      let ptr = core::LLVMGetNamedGlobal(self.module, c_name);
      if ptr.is_null() {
        None
      } else {
        Some(GlobalValue(ptr))
      }
    }
  }

  /// Get an iterator of global values
  pub fn global_values(&self) -> ValueIter<GlobalValue>
  {
  	ValueIter::new(
 			unsafe { core::LLVMGetFirstGlobal(self.module) },
 			core::LLVMGetNextGlobal
 		)
  }

  /// Link a module into this module, returning an error string if an error occurs.
  ///
  /// This *does not* destroy the source module.
  pub fn link(&self, module: LLVMModuleRef) -> Result<(), String>
  {
    unsafe {
      let mut error = mem::uninitialized();
      let ret = linker::LLVMLinkModules(self.module, module,
      	                                linker::LLVMLinkerMode::LLVMLinkerPreserveSource,
      	                                &mut error);
      llvm_ret!(ret, (), error)
    }
  }

  /// Link a module into this module, returning an error string if an error occurs.
  ///
  /// This *does* destroy the source module.
  pub fn link_destroy(&self, module: LLVMModuleRef) -> Result<(), String>
  {
    unsafe {
      let mut error = mem::uninitialized();
      let ret = linker::LLVMLinkModules(self.module, module,
      	                                linker::LLVMLinkerMode::LLVMLinkerDestroySource,
      	                                &mut error);
      llvm_ret!(ret, (), error)
    }
  }

  /// Optimize this module with the given optimization level and size level.
  ///
  /// This runs passes depending on the levels given.
  pub fn optimize(&self, opt_level: usize, size_level: usize) {
    unsafe {
      let builder = pass::LLVMPassManagerBuilderCreate();
      pass::LLVMPassManagerBuilderSetOptLevel(builder, opt_level as c_uint);
      pass::LLVMPassManagerBuilderSetSizeLevel(builder, size_level as c_uint);
      let pass_manager = core::LLVMCreatePassManager();
      pass::LLVMPassManagerBuilderPopulateModulePassManager(builder, pass_manager);
      pass::LLVMPassManagerBuilderDispose(builder);
      core::LLVMRunPassManager(pass_manager, self.module);
    }
  }

  pub fn new_builder(&self) -> Builder
  {
    Builder(unsafe { core::LLVMCreateBuilderInContext(self.ctx) })
  }
}

impl Drop for JitCompiler {
  fn drop(&mut self) {
    unsafe {
      core::LLVMDisposeModule(self.module);
      core::LLVMContextDispose(self.ctx);
    }
  }
}

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

  #[test]
  fn test_ctor() {
    let jit = JitCompiler::new("target/test-ir/test-module.bc").ok().unwrap();
  }
}<commit_msg>Add verify() to JitCompiler.<commit_after>//! JIT Compiler to generate code fragments in runtime.

extern crate libc;
extern crate llvm_sys;

#[macro_use]
mod macros;
mod block;
mod buffer;
mod builder;
mod util;
mod types;
mod value;

use std::mem;
use std::ptr;

use llvm_sys::analysis;
use llvm_sys::core;
use llvm_sys::prelude::{
  LLVMContextRef,
  LLVMModuleRef
};
use llvm_sys::bit_reader::LLVMParseBitcodeInContext;
use llvm_sys::execution_engine::{
  LLVMExecutionEngineRef,
  LLVMLinkInMCJIT,
  LLVMMCJITCompilerOptions,
  LLVMCreateMCJITCompilerForModule
};
use llvm_sys::linker;
use llvm_sys::transforms::pass_manager_builder as pass;
use llvm_sys::target::{
  LLVM_InitializeNativeTarget,
  LLVM_InitializeNativeAsmPrinter
};
use llvm_sys::target_machine::LLVMCodeModel;

use libc::{c_char, c_uint};

use buffer::MemoryBuffer;
use builder::Builder;
use value::{GlobalValue, Value, ValueIter};
use types::Ty;
use util::chars;

pub const JIT_OPT_LVEL: usize = 2;

#[repr(C)]
#[derive(Copy, Clone)]
pub enum AddressSpace
{
  Generic = 0,
  Global = 1,
  Shared = 3,
  Const = 4,
  Local = 5,
}

fn new_module(ctx: LLVMContextRef, name: &str) -> LLVMModuleRef
{
  let c_name = util::chars::from_str(name);
  unsafe {
  	core::LLVMModuleCreateWithNameInContext(c_name, ctx)
  }
}
fn new_module_from_bc(ctx: LLVMContextRef, path: &str) -> Result<LLVMModuleRef, String>
{
  unsafe {
    let mut out: LLVMModuleRef = mem::uninitialized();
    let mut err: *mut c_char   = mem::uninitialized();
    let buf = try!(MemoryBuffer::from_file(path));

    let ret = LLVMParseBitcodeInContext(ctx,
                                        buf.as_ptr(),
    	                                  &mut out,
    	                                  &mut err);
    llvm_ret!(ret, out, err)
  }
}

fn new_jit_ee(m: LLVMModuleRef, opt_lv: usize) -> Result<LLVMExecutionEngineRef, String>
{
  unsafe {
    let mut ee : LLVMExecutionEngineRef = mem::uninitialized();
    let mut err: *mut c_char = mem::uninitialized();

    LLVMLinkInMCJIT();
    expect_noerr!(LLVM_InitializeNativeTarget(), "failed to initialize native target");
    expect_noerr!(LLVM_InitializeNativeAsmPrinter(), "failed to initialize native asm printer");

    let mut opts = new_mcjit_compiler_options(opt_lv);
    let opts_size = mem::size_of::<LLVMMCJITCompilerOptions>();

    let ret = LLVMCreateMCJITCompilerForModule(&mut ee,
      		                                     m,
      		                                     &mut opts,
      		                                     opts_size as u64,
      		                                     &mut err);
    llvm_ret!(ret, ee, err)
  }
}

fn new_mcjit_compiler_options(opt_lv: usize) -> LLVMMCJITCompilerOptions
{
  LLVMMCJITCompilerOptions {
    OptLevel: opt_lv as c_uint,
    CodeModel: LLVMCodeModel::LLVMCodeModelJITDefault,
    NoFramePointerElim: 0,
    EnableFastISel: 1,
    MCJMM: ptr::null_mut()
  }
}

pub struct JitCompiler
{
  ctx    : LLVMContextRef,
  module : LLVMModuleRef,
  ee     : LLVMExecutionEngineRef,
  //builder: Builder // internal use
}

impl JitCompiler {

  pub fn new(module_name: &str) -> Result<JitCompiler, String>
  {
    let ctx     = unsafe { core::LLVMContextCreate() };
    let module  = new_module(ctx, module_name);
    JitCompiler::new_internal(ctx, module)
  }

  pub fn new_from_bc(bitcode_path: &str) -> Result<JitCompiler, String>
  {
    let ctx     = unsafe { core::LLVMContextCreate() };
    let module  = try!(new_module_from_bc(ctx, bitcode_path));
    JitCompiler::new_internal(ctx, module)
  }

  fn new_internal(ctx: LLVMContextRef, module: LLVMModuleRef) -> Result<JitCompiler, String>
  {
    let ee      = try!(new_jit_ee(module, JIT_OPT_LVEL));
    //let builder = Builder(unsafe { core::LLVMCreateBuilderInContext(ctx) });

    Ok(JitCompiler {
      ctx    : ctx,
      module : module,
      ee     : ee,
      //builder: builder
    })
  }

  pub fn context(&self) -> LLVMContextRef { self.ctx }
  pub fn module(&self) -> LLVMModuleRef { self.module }
  pub fn engine(&self) -> LLVMExecutionEngineRef { self.ee }

  /// Returns the target data of the base module represented as a string
  pub fn get_target(&self) -> &str
  {
    unsafe {
      let target = core::LLVMGetTarget(self.module);
      chars::to_str(target)
    }
  }

  /// Get the data layout of the base module
  pub fn get_data_layout(&self) -> &str
  {
  	unsafe {
  		let layout = core::LLVMGetDataLayout(self.module);
  		chars::to_str(layout as *mut c_char)
  	}
  }

  /// Add an external global to the module with the given type and name.
  pub fn add_global(&self, name: &str, ty: &Ty) -> GlobalValue
  {
    let c_name = chars::from_str(name);
    GlobalValue(
      unsafe {
        core::LLVMAddGlobal(self.module, ty.0, c_name)
      }
    )
  }

  /// Add a global in the given address space to the module with the given type and name.
  pub fn add_global_in_addr_space(&self,
  	                              name: &str,
  	                              ty: &Ty,
  	                              sp: AddressSpace) -> GlobalValue
  {
    let c_name = chars::from_str(name);
    GlobalValue(
      unsafe {
        core::LLVMAddGlobalInAddressSpace(self.module, ty.0, c_name, sp as c_uint)
      }
    )
  }

  /// Add a constant global to the module with the given type, name and value.
  pub fn add_global_constant(&self, name: &str, val: &Value) -> GlobalValue
  {
    let c_name = chars::from_str(name);
    GlobalValue(
      unsafe {
        let global = core::LLVMAddGlobal(self.module, val.ty().0, c_name);
        core::LLVMSetInitializer (global, val.0);
        global
      }
    )
  }

  /// Get the global with the name given, or `None` if no global with that name exists.
  pub fn get_global(&self, name: &str) -> Option<GlobalValue>
  {
    let c_name = chars::from_str(name);
    unsafe {
      let ptr = core::LLVMGetNamedGlobal(self.module, c_name);
      if ptr.is_null() {
        None
      } else {
        Some(GlobalValue(ptr))
      }
    }
  }

  /// Get an iterator of global values
  pub fn global_values(&self) -> ValueIter<GlobalValue>
  {
  	ValueIter::new(
 			unsafe { core::LLVMGetFirstGlobal(self.module) },
 			core::LLVMGetNextGlobal
 		)
  }

  /// Link a module into this module, returning an error string if an error occurs.
  ///
  /// This *does not* destroy the source module.
  pub fn link(&self, module: LLVMModuleRef) -> Result<(), String>
  {
    unsafe {
      let mut error = mem::uninitialized();
      let ret = linker::LLVMLinkModules(self.module, module,
      	                                linker::LLVMLinkerMode::LLVMLinkerPreserveSource,
      	                                &mut error);
      llvm_ret!(ret, (), error)
    }
  }

  /// Link a module into this module, returning an error string if an error occurs.
  ///
  /// This *does* destroy the source module.
  pub fn link_destroy(&self, module: LLVMModuleRef) -> Result<(), String>
  {
    unsafe {
      let mut error = mem::uninitialized();
      let ret = linker::LLVMLinkModules(self.module, module,
      	                                linker::LLVMLinkerMode::LLVMLinkerDestroySource,
      	                                &mut error);
      llvm_ret!(ret, (), error)
    }
  }

  /// Optimize this module with the given optimization level and size level.
  ///
  /// This runs passes depending on the levels given.
  pub fn optimize(&self, opt_level: usize, size_level: usize) {
    unsafe {
      let builder = pass::LLVMPassManagerBuilderCreate();
      pass::LLVMPassManagerBuilderSetOptLevel(builder, opt_level as c_uint);
      pass::LLVMPassManagerBuilderSetSizeLevel(builder, size_level as c_uint);
      let pass_manager = core::LLVMCreatePassManager();
      pass::LLVMPassManagerBuilderPopulateModulePassManager(builder, pass_manager);
      pass::LLVMPassManagerBuilderDispose(builder);
      core::LLVMRunPassManager(pass_manager, self.module);
    }
  }

  /// Verify that the module is safe to run, returning a string detailing the error
  /// when an error occurs.
  pub fn verify(&self) -> Result<(), String>
  {
    unsafe {
      let mut error = mem::uninitialized();
      let action = analysis::LLVMVerifierFailureAction::LLVMReturnStatusAction;
      let ret = analysis::LLVMVerifyModule(self.module, action, &mut error);

      llvm_ret!(ret, (), error)
    }
  }

  pub fn new_builder(&self) -> Builder
  {
    Builder(unsafe { core::LLVMCreateBuilderInContext(self.ctx) })
  }
}

impl Drop for JitCompiler {
  fn drop(&mut self) {
    unsafe {
      core::LLVMDisposeModule(self.module);
      core::LLVMContextDispose(self.ctx);
    }
  }
}

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

  #[test]
  fn test_ctor() {
    let jit = JitCompiler::new("target/test-ir/test-module.bc").ok().unwrap();
  }
}<|endoftext|>


<commit_before>#[macro_use]
extern crate human_panic;
#[macro_use]
extern crate clap;
extern crate failure;
extern crate xxd;

use cli::create_arg_parser;
use failure::*;
use xxd::dump::{dump_iterator, Config, Format};
use xxd::generate::{Render, Template};

use clap::ArgMatches;

use std::fmt::Display;
use std::io::{Read, Write};
use std::process::exit;

mod cli;

fn main() {
    setup_panic!();
    let matches = create_arg_parser().get_matches();
    match run(&matches) {
        Ok(_) => exit(0),
        Err(e) => {
            report_error(&e);
            exit(1)
        }
    }
}

fn run(args: &ArgMatches) -> Result<(), failure::Error> {
    match args.subcommand_name() {
        Some("dump") => dump(args.subcommand_matches("dump")),
        Some("generate") => generate(args.subcommand_matches("generate")),
        _ => bail!(format_err!("{}", args.usage())),
    }
}

pub fn create_reader(path: String) -> Result<Box<std::io::Read>, failure::Error> {
    match path.as_ref() {
        "stdin" => Ok(Box::new(std::io::stdin())),
        _ => {
            let file_reader = std::fs::File::open(path)?;
            Ok(Box::new(file_reader))
        }
    }
}

pub fn create_writer(path: String) -> Result<Box<std::io::Write>, failure::Error> {
    match path.as_ref() {
        "stdout" => Ok(Box::new(std::io::stdout())),
        _ => {
            let mut file_writer = std::fs::File::create(path)?;
            Ok(Box::new(file_writer))
        }
    }
}

fn dump<'a>(args: Option<&ArgMatches<'a>>) -> Result<(), failure::Error> {
    let args = args.ok_or_else(|| format_err!("No arguments available"))?;
    let output_file = args.value_of("outfile").unwrap_or("stdout");
    let input_file = args.value_of("file").unwrap_or("stdin");
    let seek = usize::from_str_radix(args.value_of("seek").unwrap_or("0"), 10)?;
    let length = args.value_of("length");
    let settings = create_dump_settings(args)?;
    let reader = create_reader(input_file.to_string())?;
    let mut writer = create_writer(output_file.to_string())?;
    match length {
        None => dump_iterator(
            reader.bytes().skip(seek).flat_map(|result| result),
            &mut *writer,
            settings,
        ),
        Some(n) => dump_iterator(
            reader
                .bytes()
                .skip(seek)
                .take(usize::from_str_radix(n, 10)?)
                .flat_map(|result| result),
            &mut *writer,
            settings,
        ),
    }
}

fn create_dump_settings<'a>(args: &ArgMatches<'a>) -> Result<Config, failure::Error> {
    let columns = usize::from_str_radix(args.value_of("columns").unwrap_or("8"), 10)?;
    let format = args.value_of("format").unwrap_or("hex");
    let group_size = usize::from_str_radix(args.value_of("group-size").unwrap_or("2"), 10)?;
    let settings = Config::new()
        .format(Format::from(format.to_string()))
        .group_size(group_size)
        .columns(columns);
    if args.is_present("plain_hexdump") {
        Ok(settings
            .separator(false)
            .show_address(false)
            .show_interpretation(false))
    } else {
        Ok(settings)
    }
}

fn generate<'a>(args: Option<&ArgMatches<'a>>) -> Result<(), failure::Error> {
    let args = args.ok_or_else(|| format_err!("No arguments available"))?;
    let output_file = args.value_of("outfile").unwrap_or("stdout");
    let input_file = args.value_of("file").unwrap_or("stdin");
    let seek = usize::from_str_radix(args.value_of("seek").unwrap_or("0"), 10)?;
    let length = args.value_of("length");
    let reader = create_reader(input_file.to_string())?;
    let mut writer = create_writer(output_file.to_string())?;
    let lang = xxd::generate::Language::from(args.value_of("template").unwrap_or("c"));
    let template = Template::new(lang);
    let data: Vec<u8> = match length {
        None => reader
            .bytes()
            .skip(seek)
            .flat_map(|result| result)
            .collect(),
        Some(n) => reader
            .bytes()
            .skip(seek)
            .take(usize::from_str_radix(n, 10)?)
            .flat_map(|result| result)
            .collect(),
    };
    writer
        .write_fmt(format_args!("{}\n", template.render(&data)))
        .unwrap();
    Ok(())
}

// fn command_not_supported() -> Result<(), failure::Error> {
//     bail!(format_err!("Command not supported yet!"))
// }

fn report_error<T: Display>(error: &T) {
    eprintln!("xxd-rs: {}", error);
}
<commit_msg>Removed unused command_not_supported<commit_after>#[macro_use]
extern crate human_panic;
#[macro_use]
extern crate clap;
extern crate failure;
extern crate xxd;

use cli::create_arg_parser;
use failure::*;
use xxd::dump::{dump_iterator, Config, Format};
use xxd::generate::{Render, Template};

use clap::ArgMatches;

use std::fmt::Display;
use std::io::{Read, Write};
use std::process::exit;

mod cli;

fn main() {
    setup_panic!();
    let matches = create_arg_parser().get_matches();
    match run(&matches) {
        Ok(_) => exit(0),
        Err(e) => {
            report_error(&e);
            exit(1)
        }
    }
}

fn run(args: &ArgMatches) -> Result<(), failure::Error> {
    match args.subcommand_name() {
        Some("dump") => dump(args.subcommand_matches("dump")),
        Some("generate") => generate(args.subcommand_matches("generate")),
        _ => bail!(format_err!("{}", args.usage())),
    }
}

pub fn create_reader(path: String) -> Result<Box<std::io::Read>, failure::Error> {
    match path.as_ref() {
        "stdin" => Ok(Box::new(std::io::stdin())),
        _ => {
            let file_reader = std::fs::File::open(path)?;
            Ok(Box::new(file_reader))
        }
    }
}

pub fn create_writer(path: String) -> Result<Box<std::io::Write>, failure::Error> {
    match path.as_ref() {
        "stdout" => Ok(Box::new(std::io::stdout())),
        _ => {
            let mut file_writer = std::fs::File::create(path)?;
            Ok(Box::new(file_writer))
        }
    }
}

fn dump<'a>(args: Option<&ArgMatches<'a>>) -> Result<(), failure::Error> {
    let args = args.ok_or_else(|| format_err!("No arguments available"))?;
    let output_file = args.value_of("outfile").unwrap_or("stdout");
    let input_file = args.value_of("file").unwrap_or("stdin");
    let seek = usize::from_str_radix(args.value_of("seek").unwrap_or("0"), 10)?;
    let length = args.value_of("length");
    let settings = create_dump_settings(args)?;
    let reader = create_reader(input_file.to_string())?;
    let mut writer = create_writer(output_file.to_string())?;
    match length {
        None => dump_iterator(
            reader.bytes().skip(seek).flat_map(|result| result),
            &mut *writer,
            settings,
        ),
        Some(n) => dump_iterator(
            reader
                .bytes()
                .skip(seek)
                .take(usize::from_str_radix(n, 10)?)
                .flat_map(|result| result),
            &mut *writer,
            settings,
        ),
    }
}

fn create_dump_settings<'a>(args: &ArgMatches<'a>) -> Result<Config, failure::Error> {
    let columns = usize::from_str_radix(args.value_of("columns").unwrap_or("8"), 10)?;
    let format = args.value_of("format").unwrap_or("hex");
    let group_size = usize::from_str_radix(args.value_of("group-size").unwrap_or("2"), 10)?;
    let settings = Config::new()
        .format(Format::from(format.to_string()))
        .group_size(group_size)
        .columns(columns);
    if args.is_present("plain_hexdump") {
        Ok(settings
            .separator(false)
            .show_address(false)
            .show_interpretation(false))
    } else {
        Ok(settings)
    }
}

fn generate<'a>(args: Option<&ArgMatches<'a>>) -> Result<(), failure::Error> {
    let args = args.ok_or_else(|| format_err!("No arguments available"))?;
    let output_file = args.value_of("outfile").unwrap_or("stdout");
    let input_file = args.value_of("file").unwrap_or("stdin");
    let seek = usize::from_str_radix(args.value_of("seek").unwrap_or("0"), 10)?;
    let length = args.value_of("length");
    let reader = create_reader(input_file.to_string())?;
    let mut writer = create_writer(output_file.to_string())?;
    let lang = xxd::generate::Language::from(args.value_of("template").unwrap_or("c"));
    let template = Template::new(lang);
    let data: Vec<u8> = match length {
        None => reader
            .bytes()
            .skip(seek)
            .flat_map(|result| result)
            .collect(),
        Some(n) => reader
            .bytes()
            .skip(seek)
            .take(usize::from_str_radix(n, 10)?)
            .flat_map(|result| result)
            .collect(),
    };
    writer
        .write_fmt(format_args!("{}\n", template.render(&data)))
        .unwrap();
    Ok(())
}

fn report_error<T: Display>(error: &T) {
    eprintln!("xxd-rs: {}", error);
}
<|endoftext|>