<commit_before>use std::alloc::alloc;
use std::alloc::dealloc;
use std::alloc::Layout;
use std::mem::size_of;
use std::ptr::eq;
use std::ptr::null;
use std::ptr::null_mut;

const _PAGE_SIZE: usize = 0x1000;

pub struct _Page<'a> {
    current_page: *mut _Page<'a>,
    next_object_offset: i32,
    exclusive_pages: i32
}

impl<'a> _Page<'a> {

    pub fn reset(&mut self) {
        unsafe {
            *(self.get_extension_page_location() as *mut *const _Page) = null();
        }
        self.next_object_offset = 0;
        self.exclusive_pages = 0;
        self.current_page = &mut *self;
    }

    pub fn clear(&mut self) {
        self.deallocate_extensions();
        self.reset();
    }

    pub fn is_oversized(&self) -> bool {
        self.current_page.is_null()
    }

    fn get_extension_page_location(&self) -> usize {

        // Convert self to page location
        let self_location = self as *const _Page as usize;

        // Advance one page size so we are past the end of our page
        let location_behind_page = self_location + _PAGE_SIZE;

        // Go back one pointer size
        location_behind_page - size_of::<*const _Page>()
    }

    fn get_next_location(&self) -> usize {
        self as *const _Page as usize + self.next_object_offset as usize
    }

    fn set_next_location(&mut self, location: usize) {
        let self_location = self as *const _Page as usize;
        self.next_object_offset = (location - self_location as usize) as i32;
    }

    fn get_next_exclusive_page_location(&self) -> usize  {
        self.get_extension_page_location() - (self.exclusive_pages as usize + 1) * size_of::<*const _Page>()
    }

    pub fn allocate_raw(&mut self, size: usize, align: usize) -> *mut u8 {
        if !eq(self, self.current_page) {
            unsafe {
                // We're already known to be full, so we delegate to the current page
                let new_object = (*self.current_page).allocate_raw(size, align);

                // Possibly our current page was also full so we propagate back the new current page
                let allocating_page = _Page::get_page(new_object);
                if !eq(allocating_page, self.current_page) && (!allocating_page.is_oversized()) {
                    self.current_page = allocating_page;
                }
                return new_object;
            }
        }

        // Try to allocate from ourselves
        let location = self.get_next_location();
        let next_location = (location + align - 1) & !(align - 1);
        if next_location <= self.get_next_exclusive_page_location() as usize {
            self.set_next_location(next_location);
            return location as *mut u8
        }

        // So the space did not fit.

        // Calculate gross size to decide whether we're oversized
        if size_of::<_Page>() + size + size_of::<*const _Page>() > _PAGE_SIZE {
            if self.get_next_location() >= self.get_extension_page_location() {

                // Allocate an extension page with default size
                let extension_page = self.allocate_extension_page();

                // Try again with the new extension page
                return extension_page.allocate_raw(size, align);
            }

            unsafe {
                // We allocate oversized objects directly.
                let memory = alloc(Layout::from_size_align_unchecked(size + size_of::<_Page>(), _PAGE_SIZE) );

                // Initialize a _Page object at the page start
                let page = memory as *mut _Page<'a>;

                // Oversized pages have no current_page
                (*page).current_page = null_mut();

                // Set the size since we will need it when deallocating
                (*page).next_object_offset = (size % 0x100000000) as i32;
                (*page).exclusive_pages =    (size / 0x100000000) as i32;

                *(self.get_next_exclusive_page_location() as *mut *const _Page) = page;
                self.exclusive_pages += 1;
                return page.offset(1) as *mut u8;
            }
        }

        // So we're not oversized. Create extension page and let it allocate.
        self.allocate_extension_page().allocate_raw(size, align)
    }

    fn allocate_extension_page(&mut self) -> &'a mut _Page<'a> {
        unsafe {
            let page = _Page::allocate_page();
            *(self.get_extension_page_location() as *mut *const _Page) = page;
            self.current_page = page;
            &mut *page
        }
    }

    fn allocate_page() -> *mut _Page<'a> {
        unsafe {
            let memory = alloc(Layout::from_size_align_unchecked(_PAGE_SIZE, _PAGE_SIZE));
            let page = memory as *mut _Page<'a>;
            (*page).reset();
            page
        }
    }

    pub fn allocate_exclusive_page(&mut self) -> &'a mut _Page<'a> {

        if !eq(self, self.current_page) {
            unsafe {
                // We're already known to be full, so we delegate to the current page
                return (*self.current_page).allocate_exclusive_page();
            }
        }

        // Check first whether we need an ordinary extension
        if self.get_next_location() >= self.get_next_exclusive_page_location() {

            // Allocate an extension page with default size
            return self.allocate_extension_page().allocate_exclusive_page();
        }

        let page = _Page::allocate_page();
        unsafe {
            *(self.get_next_exclusive_page_location() as *mut *const _Page) = page;
            self.exclusive_pages += 1;
            &mut *page
        }
    }

    pub fn extend(&mut self, top: usize, size: usize) -> bool {
        if top != self.get_next_location() {
            return false;
        }

        let new_top = top + size;
        if new_top > self.get_next_exclusive_page_location() {
            return false;
        }
        self.set_next_location(new_top);

        true
    }

    pub fn deallocate_extensions(&mut self) {
        let mut page: *mut _Page<'a> = self;
        unsafe {
            while !page.is_null() {
                let extension_location = (*page).get_extension_page_location();
                for i in 1..(*page).exclusive_pages {
                    let mut exclusive_page = &mut *((extension_location - (i as usize * size_of::<*const _Page> as usize)) as *mut _Page<'a>);
                    if !exclusive_page.is_oversized() {
                        exclusive_page.deallocate_extensions();
                    }
                    exclusive_page.forget();
                }

                if !eq(page, self) {
                    (*page).forget();
                }

                page = extension_location as *mut _Page<'a>;
            }
        }
    }

    pub fn forget(&self) {
        let size = if self.current_page == null_mut() {
            self.next_object_offset as usize + self.exclusive_pages as usize * 0x100000000
        } else {
            _PAGE_SIZE
        };
        unsafe {
            dealloc(self as *const _Page as *mut u8, Layout::from_size_align_unchecked(size, _PAGE_SIZE))
        }
    }

    pub fn reclaim_array(&mut self, address: usize) -> bool {
        unsafe {
            let mut page: *mut _Page<'a> = self;
            while !page.is_null() {
                if (*page).deallocate_exclusive_page(&mut *(address as *mut _Page<'a>)) {
                    return true;
                }
                page = (*page).get_extension_page_location() as *mut _Page<'a>;
            }
        }

        // If we arrive here, we have a memory leak.
        false
    }

    pub fn get_page(address: *mut u8) -> &'a mut _Page<'a> {
        unsafe {
            &mut *((address as usize & !_PAGE_SIZE - 1) as *mut _Page)
        }
    }

    fn deallocate_exclusive_page(&mut self, page: &'a mut _Page<'a>) -> bool {
        // Find the extension Page pointer
        let mut extension_location = self.get_extension_page_location() - size_of::<*const _Page>();
        let next_extension_page_location = self.get_next_exclusive_page_location();
        while extension_location > next_extension_page_location {
            if eq(extension_location as *const _Page, page) {
                break; }
            extension_location -= size_of::<*const _Page>();
        }

        // Report if we could not find it
        if extension_location == next_extension_page_location {
            return false;
        }

        // Shift the remaining array one position up
        while extension_location > next_extension_page_location {
            let pp_page = extension_location as *mut *const _Page;
            unsafe {
                *pp_page = *(pp_page.offset(- 1));
            }
            extension_location -= size_of::<*const _Page>();
        }

        // Make room for one more extension
        self.exclusive_pages -= 1;
        page.forget();

        true
    }
}

#[test]
fn test_page() {

    unsafe {

        // Allocate a page
        let memory = alloc(Layout::from_size_align_unchecked(_PAGE_SIZE, _PAGE_SIZE) );
        assert_ne!(memory, null_mut());

        // Write some numbers to the page memory
        for i in 0.._PAGE_SIZE {
            let ptr = memory.offset(i as isize);
            *ptr = i as u8
        }

        // Initialize a _Page object at the page start
        let page = &mut *(memory as *mut _Page);

        assert_ne!(page.next_object_offset, 0);
        assert_ne!(page.exclusive_pages, 0);

        page.reset();

        assert_eq!(page.next_object_offset, 0);
        assert_eq!(page.exclusive_pages, 0);
        assert_eq!((*(page.current_page)).next_object_offset, 0);
        assert_eq!((*(page.current_page)).exclusive_pages, 0);
        assert_eq!(page.is_oversized(), false);

    }
}<commit_msg>Format<commit_after>use std::alloc::alloc;
use std::alloc::dealloc;
use std::alloc::Layout;
use std::mem::size_of;
use std::ptr::eq;
use std::ptr::null;
use std::ptr::null_mut;

const _PAGE_SIZE: usize = 0x1000;

pub struct _Page<'a> {
    current_page: *mut _Page<'a>,
    next_object_offset: i32,
    exclusive_pages: i32,
}

impl<'a> _Page<'a> {
    pub fn reset(&mut self) {
        unsafe {
            *(self.get_extension_page_location() as *mut *const _Page) = null();
        }
        self.next_object_offset = 0;
        self.exclusive_pages = 0;
        self.current_page = &mut *self;
    }

    pub fn clear(&mut self) {
        self.deallocate_extensions();
        self.reset();
    }

    pub fn is_oversized(&self) -> bool {
        self.current_page.is_null()
    }

    fn get_extension_page_location(&self) -> usize {
        // Convert self to page location
        let self_location = self as *const _Page as usize;

        // Advance one page size so we are past the end of our page
        let location_behind_page = self_location + _PAGE_SIZE;

        // Go back one pointer size
        location_behind_page - size_of::<*const _Page>()
    }

    fn get_next_location(&self) -> usize {
        self as *const _Page as usize + self.next_object_offset as usize
    }

    fn set_next_location(&mut self, location: usize) {
        let self_location = self as *const _Page as usize;
        self.next_object_offset = (location - self_location as usize) as i32;
    }

    fn get_next_exclusive_page_location(&self) -> usize {
        self.get_extension_page_location()
            - (self.exclusive_pages as usize + 1) * size_of::<*const _Page>()
    }

    pub fn allocate_raw(&mut self, size: usize, align: usize) -> *mut u8 {
        if !eq(self, self.current_page) {
            unsafe {
                // We're already known to be full, so we delegate to the current page
                let new_object = (*self.current_page).allocate_raw(size, align);

                // Possibly our current page was also full so we propagate back the new current page
                let allocating_page = _Page::get_page(new_object);
                if !eq(allocating_page, self.current_page) && (!allocating_page.is_oversized()) {
                    self.current_page = allocating_page;
                }
                return new_object;
            }
        }

        // Try to allocate from ourselves
        let location = self.get_next_location();
        let next_location = (location + align - 1) & !(align - 1);
        if next_location <= self.get_next_exclusive_page_location() as usize {
            self.set_next_location(next_location);
            return location as *mut u8;
        }

        // So the space did not fit.

        // Calculate gross size to decide whether we're oversized
        if size_of::<_Page>() + size + size_of::<*const _Page>() > _PAGE_SIZE {
            if self.get_next_location() >= self.get_extension_page_location() {
                // Allocate an extension page with default size
                let extension_page = self.allocate_extension_page();

                // Try again with the new extension page
                return extension_page.allocate_raw(size, align);
            }

            unsafe {
                // We allocate oversized objects directly.
                let memory = alloc(Layout::from_size_align_unchecked(
                    size + size_of::<_Page>(),
                    _PAGE_SIZE,
                ));

                // Initialize a _Page object at the page start
                let page = memory as *mut _Page<'a>;

                // Oversized pages have no current_page
                (*page).current_page = null_mut();

                // Set the size since we will need it when deallocating
                (*page).next_object_offset = (size % 0x100000000) as i32;
                (*page).exclusive_pages = (size / 0x100000000) as i32;

                *(self.get_next_exclusive_page_location() as *mut *const _Page) = page;
                self.exclusive_pages += 1;
                return page.offset(1) as *mut u8;
            }
        }

        // So we're not oversized. Create extension page and let it allocate.
        self.allocate_extension_page().allocate_raw(size, align)
    }

    fn allocate_extension_page(&mut self) -> &'a mut _Page<'a> {
        unsafe {
            let page = _Page::allocate_page();
            *(self.get_extension_page_location() as *mut *const _Page) = page;
            self.current_page = page;
            &mut *page
        }
    }

    fn allocate_page() -> *mut _Page<'a> {
        unsafe {
            let memory = alloc(Layout::from_size_align_unchecked(_PAGE_SIZE, _PAGE_SIZE));
            let page = memory as *mut _Page<'a>;
            (*page).reset();
            page
        }
    }

    pub fn allocate_exclusive_page(&mut self) -> &'a mut _Page<'a> {
        if !eq(self, self.current_page) {
            unsafe {
                // We're already known to be full, so we delegate to the current page
                return (*self.current_page).allocate_exclusive_page();
            }
        }

        // Check first whether we need an ordinary extension
        if self.get_next_location() >= self.get_next_exclusive_page_location() {
            // Allocate an extension page with default size
            return self.allocate_extension_page().allocate_exclusive_page();
        }

        let page = _Page::allocate_page();
        unsafe {
            *(self.get_next_exclusive_page_location() as *mut *const _Page) = page;
            self.exclusive_pages += 1;
            &mut *page
        }
    }

    pub fn extend(&mut self, top: usize, size: usize) -> bool {
        if top != self.get_next_location() {
            return false;
        }

        let new_top = top + size;
        if new_top > self.get_next_exclusive_page_location() {
            return false;
        }
        self.set_next_location(new_top);

        true
    }

    pub fn deallocate_extensions(&mut self) {
        let mut page: *mut _Page<'a> = self;
        unsafe {
            while !page.is_null() {
                let extension_location = (*page).get_extension_page_location();
                for i in 1..(*page).exclusive_pages {
                    let mut exclusive_page = &mut *((extension_location
                        - (i as usize * size_of::<*const _Page> as usize))
                        as *mut _Page<'a>);
                    if !exclusive_page.is_oversized() {
                        exclusive_page.deallocate_extensions();
                    }
                    exclusive_page.forget();
                }

                if !eq(page, self) {
                    (*page).forget();
                }

                page = extension_location as *mut _Page<'a>;
            }
        }
    }

    pub fn forget(&self) {
        let size = if self.current_page == null_mut() {
            self.next_object_offset as usize + self.exclusive_pages as usize * 0x100000000
        } else {
            _PAGE_SIZE
        };
        unsafe {
            dealloc(
                self as *const _Page as *mut u8,
                Layout::from_size_align_unchecked(size, _PAGE_SIZE),
            )
        }
    }

    pub fn reclaim_array(&mut self, address: usize) -> bool {
        unsafe {
            let mut page: *mut _Page<'a> = self;
            while !page.is_null() {
                if (*page).deallocate_exclusive_page(&mut *(address as *mut _Page<'a>)) {
                    return true;
                }
                page = (*page).get_extension_page_location() as *mut _Page<'a>;
            }
        }

        // If we arrive here, we have a memory leak.
        false
    }

    pub fn get_page(address: *mut u8) -> &'a mut _Page<'a> {
        unsafe { &mut *((address as usize & !_PAGE_SIZE - 1) as *mut _Page) }
    }

    fn deallocate_exclusive_page(&mut self, page: &'a mut _Page<'a>) -> bool {
        // Find the extension Page pointer
        let mut extension_location = self.get_extension_page_location() - size_of::<*const _Page>();
        let next_extension_page_location = self.get_next_exclusive_page_location();
        while extension_location > next_extension_page_location {
            if eq(extension_location as *const _Page, page) {
                break;
            }
            extension_location -= size_of::<*const _Page>();
        }

        // Report if we could not find it
        if extension_location == next_extension_page_location {
            return false;
        }

        // Shift the remaining array one position up
        while extension_location > next_extension_page_location {
            let pp_page = extension_location as *mut *const _Page;
            unsafe {
                *pp_page = *(pp_page.offset(-1));
            }
            extension_location -= size_of::<*const _Page>();
        }

        // Make room for one more extension
        self.exclusive_pages -= 1;
        page.forget();

        true
    }
}

#[test]
fn test_page() {
    unsafe {
        // Allocate a page
        let memory = alloc(Layout::from_size_align_unchecked(_PAGE_SIZE, _PAGE_SIZE));
        assert_ne!(memory, null_mut());

        // Write some numbers to the page memory
        for i in 0.._PAGE_SIZE {
            let ptr = memory.offset(i as isize);
            *ptr = i as u8
        }

        // Initialize a _Page object at the page start
        let page = &mut *(memory as *mut _Page);

        assert_ne!(page.next_object_offset, 0);
        assert_ne!(page.exclusive_pages, 0);

        page.reset();

        assert_eq!(page.next_object_offset, 0);
        assert_eq!(page.exclusive_pages, 0);
        assert_eq!((*(page.current_page)).next_object_offset, 0);
        assert_eq!((*(page.current_page)).exclusive_pages, 0);
        assert_eq!(page.is_oversized(), false);
    }
}
<|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.

// Check that we can use `-C lto` when linking against libraries that were
// separately compiled.

// aux-build:sepcomp_lib.rs
// compile-flags: -C lto
// no-prefer-dynamic

extern crate sepcomp_lib;
use sepcomp_lib::a::one;
use sepcomp_lib::b::two;
use sepcomp_lib::c::three;

fn main() {
    assert_eq!(one(), 1);
    assert_eq!(two(), 2);
    assert_eq!(three(), 3);
}
<commit_msg>Disable run-pass/sepcomp-lib-lto.rs on Android until #18800 is fixed<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.

// Check that we can use `-C lto` when linking against libraries that were
// separately compiled.

// aux-build:sepcomp_lib.rs
// compile-flags: -C lto
// no-prefer-dynamic
// ignore-android FIXME #18800

extern crate sepcomp_lib;
use sepcomp_lib::a::one;
use sepcomp_lib::b::two;
use sepcomp_lib::c::three;

fn main() {
    assert_eq!(one(), 1);
    assert_eq!(two(), 2);
    assert_eq!(three(), 3);
}
<|endoftext|>


<commit_before>use error::Result;
use postgres::Connection;
use std::collections::BTreeMap;
use std::time::Duration;

pub(crate) struct Limits {
    memory: usize,
    targets: usize,
    timeout: Duration,
    networking: bool,
    max_log_size: usize,
}

impl Default for Limits {
    fn default() -> Self {
        Self {
            memory: 3 * 1024 * 1024 * 1024,  // 3 GB
            timeout: Duration::from_secs(15 * 60),  // 15 minutes
            targets: 10,
            networking: false,
            max_log_size: 100 * 1024, // 100 KB
        }
    }
}

impl Limits {
    pub(crate) fn for_crate(conn: &Connection, name: &str) -> Result<Self> {
        let mut limits = Self::default();

        let res = conn.query(
            "SELECT * FROM sandbox_overrides WHERE crate_name = $1;",
            &[&name],
        )?;
        if !res.is_empty() {
            let row = res.get(0);
            if let Some(memory) = row.get::<_, Option<i64>>("max_memory_bytes") {
                limits.memory = memory as usize;
            }
            if let Some(timeout) = row.get::<_, Option<i32>>("timeout_seconds") {
                limits.timeout = Duration::from_secs(timeout as u64);
            }
            if let Some(targets) = row.get::<_, Option<u32>>("max_targets") {
                limits.targets = targets as usize;
            }
        }

        Ok(limits)
    }

    pub(crate) fn memory(&self) -> usize {
        self.memory
    }

    pub(crate) fn timeout(&self) -> Duration {
        self.timeout
    }

    pub(crate) fn networking(&self) -> bool {
        self.networking
    }

    pub(crate) fn max_log_size(&self) -> usize {
        self.max_log_size
    }

    pub(crate) fn targets(&self) -> usize {
        self.targets
    }

    pub(crate) fn for_website(&self) -> BTreeMap<String, String> {
        let time_scale = |v| scale(v, 60, &["seconds", "minutes", "hours"]);
        let size_scale = |v| scale(v, 1024, &["bytes", "KB", "MB", "GB"]);

        let mut res = BTreeMap::new();
        res.insert("Available RAM".into(), size_scale(self.memory));
        res.insert(
            "Maximum rustdoc execution time".into(),
            time_scale(self.timeout.as_secs() as usize),
        );
        res.insert("Maximum size of a build log".into(), size_scale(self.max_log_size));
        if self.networking {
            res.insert("Network access".into(), "allowed".into());
        } else {
            res.insert("Network access".into(), "blocked".into());
        }
        res.insert("Maximum number of build targets".into(), self.targets.to_string());
        res
    }
}

fn scale(mut value: usize, interval: usize, labels: &[&str]) -> String {
    let mut chosen_label = &labels[0];
    for label in &labels[1..] {
        if (value as f64) / (interval as f64) >= 1.0 {
            chosen_label = label;
            value = value / interval;
        } else {
            break;
        }
    }
    format!("{} {}", value, chosen_label)
}
<commit_msg>Fix crash when retrieving targets<commit_after>use error::Result;
use postgres::Connection;
use std::collections::BTreeMap;
use std::time::Duration;

pub(crate) struct Limits {
    memory: usize,
    targets: usize,
    timeout: Duration,
    networking: bool,
    max_log_size: usize,
}

impl Default for Limits {
    fn default() -> Self {
        Self {
            memory: 3 * 1024 * 1024 * 1024,  // 3 GB
            timeout: Duration::from_secs(15 * 60),  // 15 minutes
            targets: 10,
            networking: false,
            max_log_size: 100 * 1024, // 100 KB
        }
    }
}

impl Limits {
    pub(crate) fn for_crate(conn: &Connection, name: &str) -> Result<Self> {
        let mut limits = Self::default();

        let res = conn.query(
            "SELECT * FROM sandbox_overrides WHERE crate_name = $1;",
            &[&name],
        )?;
        if !res.is_empty() {
            let row = res.get(0);
            if let Some(memory) = row.get::<_, Option<i64>>("max_memory_bytes") {
                limits.memory = memory as usize;
            }
            if let Some(timeout) = row.get::<_, Option<i32>>("timeout_seconds") {
                limits.timeout = Duration::from_secs(timeout as u64);
            }
            if let Some(targets) = row.get::<_, Option<i32>>("max_targets") {
                limits.targets = targets as usize;
            }
        }

        Ok(limits)
    }

    pub(crate) fn memory(&self) -> usize {
        self.memory
    }

    pub(crate) fn timeout(&self) -> Duration {
        self.timeout
    }

    pub(crate) fn networking(&self) -> bool {
        self.networking
    }

    pub(crate) fn max_log_size(&self) -> usize {
        self.max_log_size
    }

    pub(crate) fn targets(&self) -> usize {
        self.targets
    }

    pub(crate) fn for_website(&self) -> BTreeMap<String, String> {
        let time_scale = |v| scale(v, 60, &["seconds", "minutes", "hours"]);
        let size_scale = |v| scale(v, 1024, &["bytes", "KB", "MB", "GB"]);

        let mut res = BTreeMap::new();
        res.insert("Available RAM".into(), size_scale(self.memory));
        res.insert(
            "Maximum rustdoc execution time".into(),
            time_scale(self.timeout.as_secs() as usize),
        );
        res.insert("Maximum size of a build log".into(), size_scale(self.max_log_size));
        if self.networking {
            res.insert("Network access".into(), "allowed".into());
        } else {
            res.insert("Network access".into(), "blocked".into());
        }
        res.insert("Maximum number of build targets".into(), self.targets.to_string());
        res
    }
}

fn scale(mut value: usize, interval: usize, labels: &[&str]) -> String {
    let mut chosen_label = &labels[0];
    for label in &labels[1..] {
        if (value as f64) / (interval as f64) >= 1.0 {
            chosen_label = label;
            value = value / interval;
        } else {
            break;
        }
    }
    format!("{} {}", value, chosen_label)
}
<|endoftext|>


<commit_before>//! Character inclusion in binary or General_Category value Unicode sets.
//!
//! We rely on dead code elimination to remove the tables that aren't needed.

#![allow(bad_style)]

macro_rules! char_property_functions {
    {$(
        mod $module:ident;
        [$(
            $prop:ident,
        )*];
    )*} => {$(
        #[allow(unused)]
        mod $module;
        $(pub fn $prop(c: char) -> bool {
            self::$module::$prop.contains_char(c)
        })*
    )*};
}

char_property_functions! {
    mod binary;
    [
        // ASCII_HEX_DIGIT, // let this one be stripped out -- the full trie is wasteful for ASCII
        ALPHABETIC, BIDI_CONTROL, CASE_IGNORABLE, CASED, CHANGES_WHEN_CASEFOLDED,
        CHANGES_WHEN_CASEMAPPED, CHANGES_WHEN_LOWERCASED, CHANGES_WHEN_TITLECASED,
        CHANGES_WHEN_UPPERCASED, DASH, DEFAULT_IGNORABLE_CODE_POINT, DEPRECATED, DIACRITIC,
        EXTENDER, GRAPHEME_BASE, GRAPHEME_EXTEND, GRAPHEME_LINK, HEX_DIGIT, HYPHEN,
        IDS_BINARY_OPERATOR, IDS_TRINARY_OPERATOR, ID_CONTINUE, ID_START, IDEOGRAPHIC, JOIN_CONTROL,
        LOGICAL_ORDER_EXCEPTION, LOWERCASE, MATH, NONCHARACTER_CODE_POINT, OTHER_ALPHABETIC,
        OTHER_DEFAULT_IGNORABLE_CODE_POINT, OTHER_GRAPHEME_EXTEND, OTHER_ID_CONTINUE,
        OTHER_ID_START, OTHER_LOWERCASE, OTHER_MATH, OTHER_UPPERCASE, PATTERN_SYNTAX,
        PATTERN_WHITE_SPACE, PREPENDED_CONCATENATION_MARK, QUOTATION_MARK, RADICAL,
        REGIONAL_INDICATOR, SENTENCE_TERMINAL, SOFT_DOTTED, TERMINAL_PUNCTUATION, UNIFIED_IDEOGRAPH,
        UPPERCASE, VARIATION_SELECTOR, WHITE_SPACE, XID_CONTINUE, XID_START,
    ];

    mod category;
    [
        CASED_LETTER, CLOSE_PUNCTUATION, CONNECTOR_PUNCTUATION, CONTROL, CURRENCY_SYMBOL,
        DASH_PUNCTUATION, DECIMAL_NUMBER, ENCLOSING_MARK, FINAL_PUNCTUATION, FORMAT,
        INITIAL_PUNCTUATION, LETTER, LETTER_NUMBER, LINE_SEPARATOR, LOWERCASE_LETTER, MARK,
        MATH_SYMBOL, MODIFIER_LETTER, MODIFIER_SYMBOL, NONSPACING_MARK, NUMBER, OPEN_PUNCTUATION,
        OTHER, OTHER_LETTER, OTHER_NUMBER, OTHER_PUNCTUATION, OTHER_SYMBOL, PARAGRAPH_SEPARATOR,
        PRIVATE_USE, PUNCTUATION, SEPARATOR, SPACE_SEPARATOR, SPACING_MARK, SURROGATE, SYMBOL,
        TITLECASE_LETTER, UNASSIGNED, UPPERCASE_LETTER,
    ];
}
<commit_msg>Added by-name unicode selection.<commit_after>//! Character inclusion in binary or General_Category value Unicode sets.
//!
//! We rely on dead code elimination to remove the tables that aren't needed.

#![allow(bad_style)]

macro_rules! char_property_functions {
    {$(
        mod $module:ident;
        [$(
            $prop:ident,
        )*];
    )*} => {$(
        #[allow(unused)]
        mod $module;
        $(pub fn $prop(c: char) -> bool {
            self::$module::$prop.contains_char(c)
        })*
    )*};
}

char_property_functions! {
    mod binary;
    [
        // ASCII_HEX_DIGIT, // let this one be stripped out -- the full trie is wasteful for ASCII
        ALPHABETIC, BIDI_CONTROL, CASE_IGNORABLE, CASED, CHANGES_WHEN_CASEFOLDED,
        CHANGES_WHEN_CASEMAPPED, CHANGES_WHEN_LOWERCASED, CHANGES_WHEN_TITLECASED,
        CHANGES_WHEN_UPPERCASED, DASH, DEFAULT_IGNORABLE_CODE_POINT, DEPRECATED, DIACRITIC,
        EXTENDER, GRAPHEME_BASE, GRAPHEME_EXTEND, GRAPHEME_LINK, HEX_DIGIT, HYPHEN,
        IDS_BINARY_OPERATOR, IDS_TRINARY_OPERATOR, ID_CONTINUE, ID_START, IDEOGRAPHIC, JOIN_CONTROL,
        LOGICAL_ORDER_EXCEPTION, LOWERCASE, MATH, NONCHARACTER_CODE_POINT, OTHER_ALPHABETIC,
        OTHER_DEFAULT_IGNORABLE_CODE_POINT, OTHER_GRAPHEME_EXTEND, OTHER_ID_CONTINUE,
        OTHER_ID_START, OTHER_LOWERCASE, OTHER_MATH, OTHER_UPPERCASE, PATTERN_SYNTAX,
        PATTERN_WHITE_SPACE, PREPENDED_CONCATENATION_MARK, QUOTATION_MARK, RADICAL,
        REGIONAL_INDICATOR, SENTENCE_TERMINAL, SOFT_DOTTED, TERMINAL_PUNCTUATION, UNIFIED_IDEOGRAPH,
        UPPERCASE, VARIATION_SELECTOR, WHITE_SPACE, XID_CONTINUE, XID_START,
    ];

    mod category;
    [
        CASED_LETTER, CLOSE_PUNCTUATION, CONNECTOR_PUNCTUATION, CONTROL, CURRENCY_SYMBOL,
        DASH_PUNCTUATION, DECIMAL_NUMBER, ENCLOSING_MARK, FINAL_PUNCTUATION, FORMAT,
        INITIAL_PUNCTUATION, LETTER, LETTER_NUMBER, LINE_SEPARATOR, LOWERCASE_LETTER, MARK,
        MATH_SYMBOL, MODIFIER_LETTER, MODIFIER_SYMBOL, NONSPACING_MARK, NUMBER, OPEN_PUNCTUATION,
        OTHER, OTHER_LETTER, OTHER_NUMBER, OTHER_PUNCTUATION, OTHER_SYMBOL, PARAGRAPH_SEPARATOR,
        PRIVATE_USE, PUNCTUATION, SEPARATOR, SPACE_SEPARATOR, SPACING_MARK, SURROGATE, SYMBOL,
        TITLECASE_LETTER, UNASSIGNED, UPPERCASE_LETTER,
    ];
}

pub fn by_name(name: &str) -> Option<Box<Fn(char) -> bool>> {println!("{:?}", name);
    for property in binary::BY_NAME {
        if name == property.0.to_uppercase() {
            return Some(Box::new(move |c| property.1.contains_char(c)));
        }
    }

    for property in category::BY_NAME {
        if name == property.0.to_uppercase() {
            return Some(Box::new(move |c| property.1.contains_char(c)));
        }
    }

    None
}
<|endoftext|>


<commit_before>//! A generic event loop for games and interactive applications

#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

extern crate window;
extern crate input;
extern crate viewport;
extern crate time;

use std::cell::RefCell;
use std::rc::Rc;
use std::thread::sleep;
use std::time::Duration;
use std::cmp;
use std::marker::PhantomData;
use window::Window;
use input::{ AfterRenderArgs, Event, IdleArgs, RenderArgs, UpdateArgs };

/// A trait for create event iterator from window.
pub trait Events<W> where W: Window {
    /// Creates event iterator from window.
    fn events(self) -> WindowEvents<W, Event<W::Event>>;
}

impl<W> Events<W> for Rc<RefCell<W>> where W: Window {
    fn events(self) -> WindowEvents<W, Event<W::Event>> {
        WindowEvents::new(self)
    }
}

impl<W> Events<W> for W where W: Window {
    fn events(self) -> WindowEvents<W, Event<W::Event>> {
        Rc::new(RefCell::new(self)).events()
    }
}

impl<'a, W> Events<W> for &'a Rc<RefCell<W>> where W: Window {
    fn events(self) -> WindowEvents<W, Event<W::Event>> {
        self.clone().events()
    }
}

/// Tells whether last emitted event was idle or not.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Idle {
    No,
    Yes
}

#[derive(Copy, Clone, Debug)]
enum State {
    Render,
    SwapBuffers,
    UpdateLoop(Idle),
    HandleEvents,
    Update,
}

/// Methods implements for event loop settings.
pub trait EventLoop: Sized {
    /// The number of updates per second
    ///
    /// This is the fixed update rate on average over time.
    /// If the event loop lags, it will try to catch up.
    fn set_ups(&mut self, frames: u64);

    /// The number of updates per second
    ///
    /// This is the fixed update rate on average over time.
    /// If the event loop lags, it will try to catch up.
    fn ups(mut self, frames: u64) -> Self {
        self.set_ups(frames);
        self
    }

    /// The maximum number of frames per second
    ///
    /// The frame rate can be lower because the
    /// next frame is always scheduled from the previous frame.
    /// This causes the frames to "slip" over time.
    fn set_max_fps(&mut self, frames: u64);

    /// The maximum number of frames per second
    ///
    /// The frame rate can be lower because the
    /// next frame is always scheduled from the previous frame.
    /// This causes the frames to "slip" over time.
    fn max_fps(mut self, frames: u64) -> Self {
        self.set_max_fps(frames);
        self
    }

    /// Enable or disable automatic swapping of buffers.
    fn set_swap_buffers(&mut self, enable: bool);

    /// Enable or disable automatic swapping of buffers.
    fn swap_buffers(mut self, enable: bool) -> Self {
        self.set_swap_buffers(enable);
        self
    }

    /// Enable or disable benchmark mode.
    /// When enabled, it will render and update without sleep and ignore input.
    /// Used to test performance by playing through as fast as possible.
    fn set_bench_mode(&mut self, enable: bool);

    /// Enable or disable benchmark mode.
    /// When enabled, it will render and update without sleep and ignore input.
    /// Used to test performance by playing through as fast as possible.
    fn bench_mode(mut self, enable: bool) -> Self {
        self.set_bench_mode(enable);
        self
    }
}

/// An event loop iterator
///
/// *Warning: Because the iterator polls events from the window back-end,
/// it must be used on the same thread as the window back-end (usually main thread),
/// unless the window back-end supports multi-thread event polling.*
pub struct WindowEvents<W, E>
    where W: Window
{
    window: Rc<RefCell<W>>,
    state: State,
    last_update: u64,
    last_frame: u64,
    dt_update_in_ns: u64,
    dt_frame_in_ns: u64,
    dt: f64,
    swap_buffers: bool,
    bench_mode: bool,
    _marker_e: PhantomData<E>,
}

static BILLION: u64 = 1_000_000_000;

fn ns_to_duration(ns: u64) -> Duration {
    let secs = ns / BILLION;
    let nanos = (ns % BILLION) as u32;
    Duration::new(secs, nanos)
}

/// The default updates per second.
pub const DEFAULT_UPS: u64 = 120;
/// The default maximum frames per second.
pub const DEFAULT_MAX_FPS: u64 = 60;

impl<W> WindowEvents<W, Event<<W as Window>::Event>>
    where W: Window
{
    /// Creates a new event iterator with default UPS and FPS settings.
    pub fn new(window: Rc<RefCell<W>>) -> WindowEvents<W, Event<<W as Window>::Event>> {
        let start = time::precise_time_ns();
        let updates_per_second = DEFAULT_UPS;
        let max_frames_per_second = DEFAULT_MAX_FPS;
        WindowEvents {
            window: window,
            state: State::Render,
            last_update: start,
            last_frame: start,
            dt_update_in_ns: BILLION / updates_per_second,
            dt_frame_in_ns: BILLION / max_frames_per_second,
            dt: 1.0 / updates_per_second as f64,
            swap_buffers: true,
            bench_mode: false,
            _marker_e: PhantomData,
        }
    }
}

impl<W> EventLoop for WindowEvents<W, Event<<W as Window>::Event>>
    where W: Window
{
    fn set_ups(&mut self, frames: u64) {
        self.dt_update_in_ns = BILLION / frames;
        self.dt = 1.0 / frames as f64;
    }

    fn set_max_fps(&mut self, frames: u64) {
        self.dt_frame_in_ns = BILLION / frames;
    }

    fn set_swap_buffers(&mut self, enable: bool) {
        self.swap_buffers = enable;
    }

    fn set_bench_mode(&mut self, enable: bool) {
        self.bench_mode = enable;
    }
}

impl<W> Iterator for WindowEvents<W, Event<<W as Window>::Event>>
    where W: Window
{
    type Item = Event<<W as Window>::Event>;

    /// Returns the next game event.
    fn next(&mut self) -> Option<Event<<W as Window>::Event>> {
        loop {
            self.state = match self.state {
                State::Render => {
                    let window = self.window.borrow();
                    if window.should_close() { return None; }

                    if self.bench_mode {
                        // In benchmark mode, pretend FPS is perfect.
                        self.last_frame += self.dt_frame_in_ns;
                    } else {
                        // In normal mode, let the FPS slip if late.
                        self.last_frame = time::precise_time_ns();
                    }

                    let size = window.size();
                    let draw_size = window.draw_size();
                    if size.width != 0 && size.height != 0 {
                        // Swap buffers next time.
                        self.state = State::SwapBuffers;
                        return Some(Event::Render(RenderArgs {
                            // Extrapolate time forward to allow smooth motion.
                            ext_dt: (self.last_frame - self.last_update) as f64
                                    / BILLION as f64,
                            width: size.width,
                            height: size.height,
                            draw_width: draw_size.width,
                            draw_height: draw_size.height,
                        }));
                    }

                    State::UpdateLoop(Idle::No)
                }
                State::SwapBuffers => {
                    if self.swap_buffers {
                        self.window.borrow_mut().swap_buffers();
                        self.state = State::UpdateLoop(Idle::No);
                        return Some(Event::AfterRender(AfterRenderArgs));
                    } else {
                        State::UpdateLoop(Idle::No)
                    }
                }
                State::UpdateLoop(ref mut idle) => {
                    if self.bench_mode {
                        // In benchmark mode, pick the next event without sleep.
                        // Idle and input events are ignored.
                        let next_frame = self.last_frame + self.dt_frame_in_ns;
                        let next_update = self.last_update + self.dt_update_in_ns;
                        let next_event = cmp::min(next_frame, next_update);
                        if next_event == next_frame {
                            State::Render
                        } else {
                            State::HandleEvents
                        }
                    } else {
                        let current_time = time::precise_time_ns();
                        let next_frame = self.last_frame + self.dt_frame_in_ns;
                        let next_update = self.last_update + self.dt_update_in_ns;
                        let next_event = cmp::min(next_frame, next_update);
                        if next_event > current_time {
                            if let Some(x) = self.window.borrow_mut().poll_event() {
                                *idle = Idle::No;
                                return Some(Event::Input(x));
                            } else if *idle == Idle::No {
                                *idle = Idle::Yes;
                                let seconds = ((next_event - current_time) as f64) / (BILLION as f64);
                                return Some(Event::Idle(IdleArgs { dt: seconds }))
                            }
                            sleep(ns_to_duration(next_event - current_time));
                            State::UpdateLoop(Idle::No)
                        } else if next_event == next_frame {
                            State::Render
                        } else {
                            State::HandleEvents
                        }
                    }
                }
                State::HandleEvents => {
                    if self.bench_mode {
                        // Ignore input to prevent it affecting the benchmark.
                        match self.window.borrow_mut().poll_event() {
                            None => State::Update,
                            Some(_) => State::HandleEvents,
                        }
                    } else {
                        // Handle all events before updating.
                        match self.window.borrow_mut().poll_event() {
                            None => State::Update,
                            Some(x) => { return Some(Event::Input(x)); },
                        }
                    }
                }
                State::Update => {
                    self.state = State::UpdateLoop(Idle::No);
                    self.last_update += self.dt_update_in_ns;
                    return Some(Event::Update(UpdateArgs{ dt: self.dt }));
                }
            };
        }
    }
}
<commit_msg>Pass window as parameter to `WindowEvents::next`<commit_after>//! A generic event loop for games and interactive applications

#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

extern crate window;
extern crate input;
extern crate viewport;
extern crate time;

use std::thread::sleep;
use std::time::Duration;
use std::cmp;
use window::Window;
use input::{ AfterRenderArgs, Event, IdleArgs, RenderArgs, UpdateArgs };

/// A trait for create event iterator from window.
pub trait Events {
    /// Creates event iterator from window.
    fn events(&self) -> WindowEvents;
}

impl<W> Events for W where W: Window {
    fn events(&self) -> WindowEvents {
        WindowEvents::new()
    }
}

/// Tells whether last emitted event was idle or not.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Idle {
    No,
    Yes
}

#[derive(Copy, Clone, Debug)]
enum State {
    Render,
    SwapBuffers,
    UpdateLoop(Idle),
    HandleEvents,
    Update,
}

/// Methods implements for event loop settings.
pub trait EventLoop: Sized {
    /// The number of updates per second
    ///
    /// This is the fixed update rate on average over time.
    /// If the event loop lags, it will try to catch up.
    fn set_ups(&mut self, frames: u64);

    /// The number of updates per second
    ///
    /// This is the fixed update rate on average over time.
    /// If the event loop lags, it will try to catch up.
    fn ups(mut self, frames: u64) -> Self {
        self.set_ups(frames);
        self
    }

    /// The maximum number of frames per second
    ///
    /// The frame rate can be lower because the
    /// next frame is always scheduled from the previous frame.
    /// This causes the frames to "slip" over time.
    fn set_max_fps(&mut self, frames: u64);

    /// The maximum number of frames per second
    ///
    /// The frame rate can be lower because the
    /// next frame is always scheduled from the previous frame.
    /// This causes the frames to "slip" over time.
    fn max_fps(mut self, frames: u64) -> Self {
        self.set_max_fps(frames);
        self
    }

    /// Enable or disable automatic swapping of buffers.
    fn set_swap_buffers(&mut self, enable: bool);

    /// Enable or disable automatic swapping of buffers.
    fn swap_buffers(mut self, enable: bool) -> Self {
        self.set_swap_buffers(enable);
        self
    }

    /// Enable or disable benchmark mode.
    /// When enabled, it will render and update without sleep and ignore input.
    /// Used to test performance by playing through as fast as possible.
    fn set_bench_mode(&mut self, enable: bool);

    /// Enable or disable benchmark mode.
    /// When enabled, it will render and update without sleep and ignore input.
    /// Used to test performance by playing through as fast as possible.
    fn bench_mode(mut self, enable: bool) -> Self {
        self.set_bench_mode(enable);
        self
    }
}

/// An event loop iterator
///
/// *Warning: Because the iterator polls events from the window back-end,
/// it must be used on the same thread as the window back-end (usually main thread),
/// unless the window back-end supports multi-thread event polling.*
#[derive(Copy, Clone)]
pub struct WindowEvents {
    state: State,
    last_update: u64,
    last_frame: u64,
    dt_update_in_ns: u64,
    dt_frame_in_ns: u64,
    dt: f64,
    swap_buffers: bool,
    bench_mode: bool,
}

static BILLION: u64 = 1_000_000_000;

fn ns_to_duration(ns: u64) -> Duration {
    let secs = ns / BILLION;
    let nanos = (ns % BILLION) as u32;
    Duration::new(secs, nanos)
}

/// The default updates per second.
pub const DEFAULT_UPS: u64 = 120;
/// The default maximum frames per second.
pub const DEFAULT_MAX_FPS: u64 = 60;

impl WindowEvents
{
    /// Creates a new event iterator with default UPS and FPS settings.
    pub fn new() -> WindowEvents {
        let start = time::precise_time_ns();
        let updates_per_second = DEFAULT_UPS;
        let max_frames_per_second = DEFAULT_MAX_FPS;
        WindowEvents {
            state: State::Render,
            last_update: start,
            last_frame: start,
            dt_update_in_ns: BILLION / updates_per_second,
            dt_frame_in_ns: BILLION / max_frames_per_second,
            dt: 1.0 / updates_per_second as f64,
            swap_buffers: true,
            bench_mode: false,
        }
    }

    /// Returns the next game event.
    pub fn next<W>(&mut self, window: &mut W) -> Option<Event<W::Event>>
        where W: Window
    {
        loop {
            self.state = match self.state {
                State::Render => {
                    if window.should_close() { return None; }

                    if self.bench_mode {
                        // In benchmark mode, pretend FPS is perfect.
                        self.last_frame += self.dt_frame_in_ns;
                    } else {
                        // In normal mode, let the FPS slip if late.
                        self.last_frame = time::precise_time_ns();
                    }

                    let size = window.size();
                    let draw_size = window.draw_size();
                    if size.width != 0 && size.height != 0 {
                        // Swap buffers next time.
                        self.state = State::SwapBuffers;
                        return Some(Event::Render(RenderArgs {
                            // Extrapolate time forward to allow smooth motion.
                            ext_dt: (self.last_frame - self.last_update) as f64
                                    / BILLION as f64,
                            width: size.width,
                            height: size.height,
                            draw_width: draw_size.width,
                            draw_height: draw_size.height,
                        }));
                    }

                    State::UpdateLoop(Idle::No)
                }
                State::SwapBuffers => {
                    if self.swap_buffers {
                        window.swap_buffers();
                        self.state = State::UpdateLoop(Idle::No);
                        return Some(Event::AfterRender(AfterRenderArgs));
                    } else {
                        State::UpdateLoop(Idle::No)
                    }
                }
                State::UpdateLoop(ref mut idle) => {
                    if self.bench_mode {
                        // In benchmark mode, pick the next event without sleep.
                        // Idle and input events are ignored.
                        let next_frame = self.last_frame + self.dt_frame_in_ns;
                        let next_update = self.last_update + self.dt_update_in_ns;
                        let next_event = cmp::min(next_frame, next_update);
                        if next_event == next_frame {
                            State::Render
                        } else {
                            State::HandleEvents
                        }
                    } else {
                        let current_time = time::precise_time_ns();
                        let next_frame = self.last_frame + self.dt_frame_in_ns;
                        let next_update = self.last_update + self.dt_update_in_ns;
                        let next_event = cmp::min(next_frame, next_update);
                        if next_event > current_time {
                            if let Some(x) = window.poll_event() {
                                *idle = Idle::No;
                                return Some(Event::Input(x));
                            } else if *idle == Idle::No {
                                *idle = Idle::Yes;
                                let seconds = ((next_event - current_time) as f64) / (BILLION as f64);
                                return Some(Event::Idle(IdleArgs { dt: seconds }))
                            }
                            sleep(ns_to_duration(next_event - current_time));
                            State::UpdateLoop(Idle::No)
                        } else if next_event == next_frame {
                            State::Render
                        } else {
                            State::HandleEvents
                        }
                    }
                }
                State::HandleEvents => {
                    if self.bench_mode {
                        // Ignore input to prevent it affecting the benchmark.
                        match window.poll_event() {
                            None => State::Update,
                            Some(_) => State::HandleEvents,
                        }
                    } else {
                        // Handle all events before updating.
                        match window.poll_event() {
                            None => State::Update,
                            Some(x) => { return Some(Event::Input(x)); },
                        }
                    }
                }
                State::Update => {
                    self.state = State::UpdateLoop(Idle::No);
                    self.last_update += self.dt_update_in_ns;
                    return Some(Event::Update(UpdateArgs{ dt: self.dt }));
                }
            };
        }
    }
}

impl EventLoop for WindowEvents {
    fn set_ups(&mut self, frames: u64) {
        self.dt_update_in_ns = BILLION / frames;
        self.dt = 1.0 / frames as f64;
    }

    fn set_max_fps(&mut self, frames: u64) {
        self.dt_frame_in_ns = BILLION / frames;
    }

    fn set_swap_buffers(&mut self, enable: bool) {
        self.swap_buffers = enable;
    }

    fn set_bench_mode(&mut self, enable: bool) {
        self.bench_mode = enable;
    }
}
<|endoftext|>


<commit_before>//! Provides the parser for the SourceLiveTimer splits files.

use std::io::Read;
use std::result::Result as StdResult;
use serde_json::de::from_reader;
use serde_json::Error as JsonError;
use {GameTime, Run, Segment, Time, TimeSpan};

quick_error! {
    /// The Error type for splits files that couldn't be parsed by the
    /// SourceLiveTimer Parser.
    #[derive(Debug)]
    pub enum Error {
        /// Failed to parse JSON.
        Json(err: JsonError) {
            from()
        }
    }
}

/// The Result type for the SourceLiveTimer parser.
pub type Result<T> = StdResult<T, Error>;

#[allow(non_snake_case)]
#[derive(Deserialize)]
struct Splits {
    Category: String,
    RunName: Option<String>,
    Splits: Option<Vec<Split>>,
}

#[allow(non_snake_case)]
#[derive(Deserialize)]
struct Split {
    Map: String,
    Name: Option<String>,
    Segment: Option<u64>,
    BestSegment: Option<u64>,
}

fn time_span_from_ticks(category_name: &str, ticks: u64) -> TimeSpan {
    let seconds = if category_name.starts_with("Portal 2") {
        ticks as f64 / 30.0
    } else {
        // Game is either Portal or Half Life 2
        ticks as f64 / 66.6666666666667
    };

    TimeSpan::from_seconds(seconds)
}

/// Attempts to parse a SourceLiveTimer splits file.
pub fn parse<R: Read>(source: R) -> Result<Run> {
    let mut run = Run::new();
    let splits: Splits = from_reader(source)?;

    if splits.Category.starts_with("Portal 2") {
        run.set_game_name("Portal 2");
    } else if splits.Category.starts_with("Portal") {
        run.set_game_name("Portal");
    } else if splits.Category.starts_with("Half Life 2") {
        run.set_game_name("Half Life 2");
    }

    if let Some(run_name) = splits.RunName {
        if run_name != splits.Category {
            run.set_category_name(run_name);
        } else {
            run.set_category_name(splits.Category);
        }
    } else {
        run.set_category_name(splits.Category);
    }

    if let Some(segments) = splits.Splits {
        for split in segments {
            let name = if let Some(name) = split.Name {
                name.to_owned()
            } else {
                split.Map.to_owned()
            };

            let mut segment = Segment::new(name);

            let pb_split_time = if let Some(segment) = split.Segment {
                time_span_from_ticks(run.category_name(), segment)
            } else {
                TimeSpan::zero()
            };

            let best_split_time = if let Some(best) = split.BestSegment {
                time_span_from_ticks(run.category_name(), best)
            } else {
                pb_split_time
            };

            segment.set_personal_best_split_time(Time::from(GameTime(Some(pb_split_time))));
            segment.set_best_segment_time(Time::from(GameTime(Some(best_split_time))));
            run.push_segment(segment);
        }
    }

    Ok(run)
}
<commit_msg>Correct SourceLiveTimer Parsing<commit_after>//! Provides the parser for the SourceLiveTimer splits files.

use std::io::Read;
use std::result::Result as StdResult;
use serde_json::de::from_reader;
use serde_json::Error as JsonError;
use {GameTime, Run, Segment, TimeSpan};

quick_error! {
    /// The Error type for splits files that couldn't be parsed by the
    /// SourceLiveTimer Parser.
    #[derive(Debug)]
    pub enum Error {
        /// Failed to parse JSON.
        Json(err: JsonError) {
            from()
        }
    }
}

/// The Result type for the SourceLiveTimer parser.
pub type Result<T> = StdResult<T, Error>;

#[allow(non_snake_case)]
#[derive(Deserialize)]
struct Splits {
    Category: String,
    RunName: Option<String>,
    Splits: Option<Vec<Split>>,
}

#[allow(non_snake_case)]
#[derive(Deserialize)]
struct Split {
    Map: String,
    Name: Option<String>,
    Ticks: Option<u64>,
    BestSegment: Option<u64>,
}

fn time_span_from_ticks(category_name: &str, ticks: u64) -> TimeSpan {
    let seconds = if category_name.starts_with("Portal 2") {
        ticks as f64 / 30.0
    } else {
        // Game is either Portal or Half Life 2
        ticks as f64 / 66.6666666666667
    };

    TimeSpan::from_seconds(seconds)
}

/// Attempts to parse a SourceLiveTimer splits file.
pub fn parse<R: Read>(source: R) -> Result<Run> {
    let mut run = Run::new();
    let splits: Splits = from_reader(source)?;

    if splits.Category.starts_with("Portal 2") {
        run.set_game_name("Portal 2");
    } else if splits.Category.starts_with("Portal") {
        run.set_game_name("Portal");
    } else if splits.Category.starts_with("Half Life 2") {
        run.set_game_name("Half Life 2");
    }

    if let Some(run_name) = splits.RunName {
        if run_name != splits.Category {
            run.set_category_name(run_name);
        } else {
            run.set_category_name(splits.Category);
        }
    } else {
        run.set_category_name(splits.Category);
    }

    if let Some(segments) = splits.Splits {
        for split in segments {
            let name = if let Some(name) = split.Name {
                name.to_owned()
            } else {
                split.Map.to_owned()
            };

            let mut segment = Segment::new(name);

            if let Some(ticks) = split.Ticks {
                let pb_split_time = Some(time_span_from_ticks(run.category_name(), ticks));
                segment.set_personal_best_split_time(GameTime(pb_split_time).into());
            }

            if let Some(best) = split.BestSegment {
                let best_segment_time = Some(time_span_from_ticks(run.category_name(), best));
                segment.set_best_segment_time(GameTime(best_segment_time).into());
            }

            run.push_segment(segment);
        }
    }

    Ok(run)
}
<|endoftext|>


<commit_before>use gc::Address;

pub struct CrossingMap {
    // boundaries for crossing map
    start: Address,
    end: Address,
}

impl CrossingMap {
    pub fn new(start: Address, end: Address) -> CrossingMap {
        CrossingMap {
            start: start,
            end: end,
        }
    }
}<commit_msg>add functions for setting crossing map-entries<commit_after>use gc::Address;

// see GC Handbook 11.8: Crossing Maps
// meaning of byte value
//
// 0 = no references (set_no_refernces)
// 0 < v <= 64:   first object starts v words before end of card (set_first_object)
// 64 < v <= 128: the first v - 128 words of this card are a sequence of references at
//                end of object (set_references_at_start)
// v > 128:       consult the card v - 128 before (set_previous_card)

pub struct CrossingMap {
    // boundaries for crossing map
    start: Address,
    end: Address,
}

impl CrossingMap {
    pub fn new(start: Address, end: Address) -> CrossingMap {
        CrossingMap {
            start: start,
            end: end,
        }
    }

    pub fn set_no_references(&self, card: usize) {
        self.set(card, 0);
    }

    pub fn set_first_object(&self, card: usize, words: usize) {
        assert!(words > 0 && words <= 64);
        self.set(card, words as u8);
    }

    pub fn set_references_at_start(&self, card: usize, refs: usize) {
        assert!(refs > 0 && refs <= 64);
        self.set(card, 64 + (refs as u8));
    }

    pub fn set_previous_card(&self, card: usize, prev: usize) {
        assert!(prev > 0);

        let val = prev + 128;
        let val = if val >= 255 { 255 } else { val };

        self.set(card, val as u8);
    }

    fn set(&self, card: usize, val: u8) {
        unsafe {
            *self.start.offset(card).to_mut_ptr::<u8>() = val;
        }
    }
}<|endoftext|>


<commit_before>import std::option;
import std::getopts;
import std::test;
import std::fs;
import std::str;
import std::vec;
import std::ivec;
import std::task;

import common::cx;
import common::config;
import common::mode_run_pass;
import common::mode_run_fail;
import common::mode_compile_fail;
import common::mode_pretty;
import common::mode;
import util::logv;

fn main(args: vec[str]) {

    let ivec_args = ivec::from_vec(args);

    let config = parse_config(ivec_args);
    log_config(config);
    run_tests(config);
}

fn parse_config(args: &str[]) -> config {
    let opts =
        ~[getopts::reqopt("compile-lib-path"),
          getopts::reqopt("run-lib-path"), getopts::reqopt("rustc-path"),
          getopts::reqopt("src-base"), getopts::reqopt("build-base"),
          getopts::reqopt("stage-id"), getopts::reqopt("mode"),
          getopts::optflag("ignored"), getopts::optopt("runtool"),
          getopts::optopt("rustcflags"), getopts::optflag("verbose")];

    check (ivec::is_not_empty(args));
    let args_ = ivec::tail(args);
    let match =
        alt getopts::getopts_ivec(args_, opts) {
          getopts::success(m) { m }
          getopts::failure(f) { fail getopts::fail_str(f) }
        };

    ret {compile_lib_path: getopts::opt_str(match, "compile-lib-path"),
         run_lib_path: getopts::opt_str(match, "run-lib-path"),
         rustc_path: getopts::opt_str(match, "rustc-path"),
         src_base: getopts::opt_str(match, "src-base"),
         build_base: getopts::opt_str(match, "build-base"),
         stage_id: getopts::opt_str(match, "stage-id"),
         mode: str_mode(getopts::opt_str(match, "mode")),
         run_ignored: getopts::opt_present(match, "ignored"),
         filter:
             if vec::len(match.free) > 0u {
                 option::some(match.free.(0))
             } else { option::none },
         runtool: getopts::opt_maybe_str(match, "runtool"),
         rustcflags: getopts::opt_maybe_str(match, "rustcflags"),
         verbose: getopts::opt_present(match, "verbose")};
}

fn log_config(config: &config) {
    let c = config;
    logv(c, #fmt("configuration:"));
    logv(c, #fmt("compile_lib_path: %s", config.compile_lib_path));
    logv(c, #fmt("run_lib_path: %s", config.run_lib_path));
    logv(c, #fmt("rustc_path: %s", config.rustc_path));
    logv(c, #fmt("src_base: %s", config.src_base));
    logv(c, #fmt("build_base: %s", config.build_base));
    logv(c, #fmt("stage_id: %s", config.stage_id));
    logv(c, #fmt("mode: %s", mode_str(config.mode)));
    logv(c, #fmt("run_ignored: %b", config.run_ignored));
    logv(c, #fmt("filter: %s", opt_str(config.filter)));
    logv(c, #fmt("runtool: %s", opt_str(config.runtool)));
    logv(c, #fmt("rustcflags: %s", opt_str(config.rustcflags)));
    logv(c, #fmt("verbose: %b", config.verbose));
    logv(c, #fmt("\n"));
}

fn opt_str(maybestr: option::t[str]) -> str {
    alt maybestr { option::some(s) { s } option::none. { "(none)" } }
}

fn str_opt(maybestr: str) -> option::t[str] {
    if maybestr != "(none)" { option::some(maybestr) } else { option::none }
}

fn str_mode(s: str) -> mode {
    alt s {
      "compile-fail" { mode_compile_fail }
      "run-fail" { mode_run_fail }
      "run-pass" { mode_run_pass }
      "pretty" { mode_pretty }
      _ { fail "invalid mode" }
    }
}

fn mode_str(mode: mode) -> str {
    alt mode {
      mode_compile_fail. { "compile-fail" }
      mode_run_fail. { "run-fail" }
      mode_run_pass. { "run-pass" }
      mode_pretty. { "pretty" }
    }
}

fn run_tests(config: &config) {
    let opts = test_opts(config);
    let cx = {config: config, procsrv: procsrv::mk()};
    let tests = make_tests(cx);
    test::run_tests_console_(opts, tests.tests, tests.to_task);
    procsrv::close(cx.procsrv);
}

fn test_opts(config: &config) -> test::test_opts {
    {filter: config.filter, run_ignored: config.run_ignored}
}

type tests_and_conv_fn =
    {tests: test::test_desc[], to_task: fn(&fn() ) -> task };

fn make_tests(cx: &cx) -> tests_and_conv_fn {
    log #fmt("making tests from %s", cx.config.src_base);
    let configport = port[str]();
    let tests = ~[];
    for file: str  in fs::list_dir(cx.config.src_base) {
        log #fmt("inspecting file %s", file);
        if is_test(file) { tests += ~[make_test(cx, file, configport)]; }
    }
    ret {tests: tests, to_task: bind closure_to_task(cx, configport, _)};
}

fn is_test(testfile: &str) -> bool {
    let name = fs::basename(testfile);
    (str::ends_with(name, ".rs") || str::ends_with(name, ".rc")) &&
        !(str::starts_with(name, ".") || str::starts_with(name, "#") ||
              str::starts_with(name, "~"))
}

fn make_test(cx: &cx, testfile: &str, configport: &port[str]) ->
   test::test_desc {
    {name: make_test_name(cx.config, testfile),
     fn: make_test_closure(testfile, chan(configport)),
            ignore: header::is_test_ignored(cx.config.stage_id, testfile)}
}

fn make_test_name(config: &config, testfile: &str) -> str {
    #fmt("[%s] %s", mode_str(config.mode), testfile)
}

/*
So this is kind of crappy:

A test is just defined as a function, as you might expect, but tests have to
run their own tasks. Unfortunately, if your test needs dynamic data then it
needs to be a closure, and transferring closures across tasks without
committing a host of memory management transgressions is just impossible.

To get around this, the standard test runner allows you the opportunity do
your own conversion from a test function to a task. It gives you your function
and you give it back a task.

So that's what we're going to do. Here's where it gets stupid. To get the
the data out of the test function we are going to run the test function,
which will do nothing but send the data for that test to a port we've set
up. Then we'll spawn that data into another task and return the task.
Really convoluted. Need to think up of a better definition for tests.
*/

fn make_test_closure(testfile: &str, configchan: chan[str]) -> test::test_fn {
    bind send_config(testfile, configchan)
}

fn send_config(testfile: str, configchan: chan[str]) {
    task::send(configchan, testfile);
}

/*
FIXME: Good god forgive me.

So actually shuttling structural data across tasks isn't possible at this
time, but we can send strings! Sadly, I need the whole config record, in the
test task so, instead of fixing the mechanism in the compiler I'm going to
break up the config record and pass everything individually to the spawned
function.
*/

fn closure_to_task(cx: cx, configport: port[str], testfn: &fn() ) -> task {
    testfn();
    let testfile = task::recv(configport);
    ret spawn run_test_task(cx.config.compile_lib_path,
                            cx.config.run_lib_path, cx.config.rustc_path,
                            cx.config.src_base, cx.config.build_base,
                            cx.config.stage_id, mode_str(cx.config.mode),
                            cx.config.run_ignored, opt_str(cx.config.filter),
                            opt_str(cx.config.runtool),
                            opt_str(cx.config.rustcflags), cx.config.verbose,
                            task::clone_chan(cx.procsrv.chan), testfile);
}

fn run_test_task(compile_lib_path: str, run_lib_path: str, rustc_path: str,
                 src_base: str, build_base: str, stage_id: str, mode: str,
                 run_ignored: bool, opt_filter: str, opt_runtool: str,
                 opt_rustcflags: str, verbose: bool,
                 procsrv_chan: procsrv::reqchan, testfile: str) {

    let config =
        {compile_lib_path: compile_lib_path,
         run_lib_path: run_lib_path,
         rustc_path: rustc_path,
         src_base: src_base,
         build_base: build_base,
         stage_id: stage_id,
         mode: str_mode(mode),
         run_ignored: run_ignored,
         filter: str_opt(opt_filter),
         runtool: str_opt(opt_runtool),
         rustcflags: str_opt(opt_rustcflags),
         verbose: verbose};

    let procsrv = procsrv::from_chan(procsrv_chan);

    let cx = {config: config, procsrv: procsrv};

    runtest::run(cx, testfile);
}

// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Pretty-print tests only run on .rs files. Issue #789<commit_after>import std::option;
import std::getopts;
import std::test;
import std::fs;
import std::str;
import std::vec;
import std::ivec;
import std::task;

import common::cx;
import common::config;
import common::mode_run_pass;
import common::mode_run_fail;
import common::mode_compile_fail;
import common::mode_pretty;
import common::mode;
import util::logv;

fn main(args: vec[str]) {

    let ivec_args = ivec::from_vec(args);

    let config = parse_config(ivec_args);
    log_config(config);
    run_tests(config);
}

fn parse_config(args: &str[]) -> config {
    let opts =
        ~[getopts::reqopt("compile-lib-path"),
          getopts::reqopt("run-lib-path"), getopts::reqopt("rustc-path"),
          getopts::reqopt("src-base"), getopts::reqopt("build-base"),
          getopts::reqopt("stage-id"), getopts::reqopt("mode"),
          getopts::optflag("ignored"), getopts::optopt("runtool"),
          getopts::optopt("rustcflags"), getopts::optflag("verbose")];

    check (ivec::is_not_empty(args));
    let args_ = ivec::tail(args);
    let match =
        alt getopts::getopts_ivec(args_, opts) {
          getopts::success(m) { m }
          getopts::failure(f) { fail getopts::fail_str(f) }
        };

    ret {compile_lib_path: getopts::opt_str(match, "compile-lib-path"),
         run_lib_path: getopts::opt_str(match, "run-lib-path"),
         rustc_path: getopts::opt_str(match, "rustc-path"),
         src_base: getopts::opt_str(match, "src-base"),
         build_base: getopts::opt_str(match, "build-base"),
         stage_id: getopts::opt_str(match, "stage-id"),
         mode: str_mode(getopts::opt_str(match, "mode")),
         run_ignored: getopts::opt_present(match, "ignored"),
         filter:
             if vec::len(match.free) > 0u {
                 option::some(match.free.(0))
             } else { option::none },
         runtool: getopts::opt_maybe_str(match, "runtool"),
         rustcflags: getopts::opt_maybe_str(match, "rustcflags"),
         verbose: getopts::opt_present(match, "verbose")};
}

fn log_config(config: &config) {
    let c = config;
    logv(c, #fmt("configuration:"));
    logv(c, #fmt("compile_lib_path: %s", config.compile_lib_path));
    logv(c, #fmt("run_lib_path: %s", config.run_lib_path));
    logv(c, #fmt("rustc_path: %s", config.rustc_path));
    logv(c, #fmt("src_base: %s", config.src_base));
    logv(c, #fmt("build_base: %s", config.build_base));
    logv(c, #fmt("stage_id: %s", config.stage_id));
    logv(c, #fmt("mode: %s", mode_str(config.mode)));
    logv(c, #fmt("run_ignored: %b", config.run_ignored));
    logv(c, #fmt("filter: %s", opt_str(config.filter)));
    logv(c, #fmt("runtool: %s", opt_str(config.runtool)));
    logv(c, #fmt("rustcflags: %s", opt_str(config.rustcflags)));
    logv(c, #fmt("verbose: %b", config.verbose));
    logv(c, #fmt("\n"));
}

fn opt_str(maybestr: option::t[str]) -> str {
    alt maybestr { option::some(s) { s } option::none. { "(none)" } }
}

fn str_opt(maybestr: str) -> option::t[str] {
    if maybestr != "(none)" { option::some(maybestr) } else { option::none }
}

fn str_mode(s: str) -> mode {
    alt s {
      "compile-fail" { mode_compile_fail }
      "run-fail" { mode_run_fail }
      "run-pass" { mode_run_pass }
      "pretty" { mode_pretty }
      _ { fail "invalid mode" }
    }
}

fn mode_str(mode: mode) -> str {
    alt mode {
      mode_compile_fail. { "compile-fail" }
      mode_run_fail. { "run-fail" }
      mode_run_pass. { "run-pass" }
      mode_pretty. { "pretty" }
    }
}

fn run_tests(config: &config) {
    let opts = test_opts(config);
    let cx = {config: config, procsrv: procsrv::mk()};
    let tests = make_tests(cx);
    test::run_tests_console_(opts, tests.tests, tests.to_task);
    procsrv::close(cx.procsrv);
}

fn test_opts(config: &config) -> test::test_opts {
    {filter: config.filter, run_ignored: config.run_ignored}
}

type tests_and_conv_fn =
    {tests: test::test_desc[], to_task: fn(&fn() ) -> task };

fn make_tests(cx: &cx) -> tests_and_conv_fn {
    log #fmt("making tests from %s", cx.config.src_base);
    let configport = port[str]();
    let tests = ~[];
    for file: str  in fs::list_dir(cx.config.src_base) {
        log #fmt("inspecting file %s", file);
        if is_test(cx.config, file) {
            tests += ~[make_test(cx, file, configport)];
        }
    }
    ret {tests: tests, to_task: bind closure_to_task(cx, configport, _)};
}

fn is_test(config: &config, testfile: &str) -> bool {
    // Pretty-printer does not work with .rc files yet
    let valid_extensions = alt config.mode {
      mode_pretty. { ~[".rs"] }
      _ { ~[".rc", ".rs"] }
    };
    let invalid_prefixes = ~[".", "#", "~"];
    let name = fs::basename(testfile);

    let valid = false;

    for ext in valid_extensions {
        if str::ends_with(name, ext) { valid = true }
    }

    for pre in invalid_prefixes {
        if str::starts_with(name, pre) { valid = false }
    }

    ret valid;
}

fn make_test(cx: &cx, testfile: &str, configport: &port[str]) ->
   test::test_desc {
    {name: make_test_name(cx.config, testfile),
     fn: make_test_closure(testfile, chan(configport)),
            ignore: header::is_test_ignored(cx.config.stage_id, testfile)}
}

fn make_test_name(config: &config, testfile: &str) -> str {
    #fmt("[%s] %s", mode_str(config.mode), testfile)
}

/*
So this is kind of crappy:

A test is just defined as a function, as you might expect, but tests have to
run their own tasks. Unfortunately, if your test needs dynamic data then it
needs to be a closure, and transferring closures across tasks without
committing a host of memory management transgressions is just impossible.

To get around this, the standard test runner allows you the opportunity do
your own conversion from a test function to a task. It gives you your function
and you give it back a task.

So that's what we're going to do. Here's where it gets stupid. To get the
the data out of the test function we are going to run the test function,
which will do nothing but send the data for that test to a port we've set
up. Then we'll spawn that data into another task and return the task.
Really convoluted. Need to think up of a better definition for tests.
*/

fn make_test_closure(testfile: &str, configchan: chan[str]) -> test::test_fn {
    bind send_config(testfile, configchan)
}

fn send_config(testfile: str, configchan: chan[str]) {
    task::send(configchan, testfile);
}

/*
FIXME: Good god forgive me.

So actually shuttling structural data across tasks isn't possible at this
time, but we can send strings! Sadly, I need the whole config record, in the
test task so, instead of fixing the mechanism in the compiler I'm going to
break up the config record and pass everything individually to the spawned
function.
*/

fn closure_to_task(cx: cx, configport: port[str], testfn: &fn() ) -> task {
    testfn();
    let testfile = task::recv(configport);
    ret spawn run_test_task(cx.config.compile_lib_path,
                            cx.config.run_lib_path, cx.config.rustc_path,
                            cx.config.src_base, cx.config.build_base,
                            cx.config.stage_id, mode_str(cx.config.mode),
                            cx.config.run_ignored, opt_str(cx.config.filter),
                            opt_str(cx.config.runtool),
                            opt_str(cx.config.rustcflags), cx.config.verbose,
                            task::clone_chan(cx.procsrv.chan), testfile);
}

fn run_test_task(compile_lib_path: str, run_lib_path: str, rustc_path: str,
                 src_base: str, build_base: str, stage_id: str, mode: str,
                 run_ignored: bool, opt_filter: str, opt_runtool: str,
                 opt_rustcflags: str, verbose: bool,
                 procsrv_chan: procsrv::reqchan, testfile: str) {

    let config =
        {compile_lib_path: compile_lib_path,
         run_lib_path: run_lib_path,
         rustc_path: rustc_path,
         src_base: src_base,
         build_base: build_base,
         stage_id: stage_id,
         mode: str_mode(mode),
         run_ignored: run_ignored,
         filter: str_opt(opt_filter),
         runtool: str_opt(opt_runtool),
         rustcflags: str_opt(opt_rustcflags),
         verbose: verbose};

    let procsrv = procsrv::from_chan(procsrv_chan);

    let cx = {config: config, procsrv: procsrv};

    runtest::run(cx, testfile);
}

// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|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.

// compile-flags: --test
// xfail-fast

// In the current state of affairs, libuv registers a SIGCHLD handler when a
// process is spawned through it. This is not done with a SA_RESTART flag,
// meaning that all of our syscalls run the risk of returning EINTR. This error
// is not correctly handled in the majority of std::io, so these can't run with
// the main body of tests there.
//
// That being said, libuv correctly handles EINTR completely, so these tests
// themselves are safe against that. Currently the test runner may run into this
// problem, but it's less likely than a whole suite of tests...
//
// See #9341

use std::rt::io::process::*;
use std::rt::io::{Reader, Writer};
use std::rt::io::pipe::*;
use std::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 => { 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>Ignore tests on Android correctly<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.

// compile-flags: --test
// xfail-fast

// In the current state of affairs, libuv registers a SIGCHLD handler when a
// process is spawned through it. This is not done with a SA_RESTART flag,
// meaning that all of our syscalls run the risk of returning EINTR. This error
// is not correctly handled in the majority of std::io, so these can't run with
// the main body of tests there.
//
// That being said, libuv correctly handles EINTR completely, so these tests
// themselves are safe against that. Currently the test runner may run into this
// problem, but it's less likely than a whole suite of tests...
//
// See #9341

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

#[test]
#[cfg(unix, not(target_os="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(target_os="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(target_os="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 => { 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(target_os="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(target_os="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(target_os="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");
}
<|endoftext|>


<commit_before>use super::*;

derive_display!(TestErr);
#[derive(Debug, Error)]
enum TestErr {
    Unit,
    NamedImplicitNoSource {
        field: i32,
    },
    NamedImplicitSource {
        source: SimpleErr,
        field: i32,
    },
    NamedExplicitNoSource {
        #[error(not(source))]
        source: SimpleErr,
        field: i32,
    },
    NamedExplicitSource {
        #[error(source)]
        explicit_source: SimpleErr,
        field: i32,
    },
    NamedExplicitNoSourceRedundant {
        #[error(not(source))]
        field: i32,
    },
    NamedExplicitSourceRedundant {
        #[error(source)]
        source: SimpleErr,
        field: i32,
    },
    NamedExplicitSuppressesImplicit {
        source: i32,
        #[error(source)]
        field: SimpleErr,
    },
    UnnamedImplicitNoSource(i32, i32),
    UnnamedImplicitSource(SimpleErr),
    UnnamedExplicitNoSource(#[error(not(source))] SimpleErr),
    UnnamedExplicitSource(#[error(source)] SimpleErr, i32),
    UnnamedExplicitNoSourceRedundant(
        #[error(not(source))] i32,
        #[error(not(source))] i32,
    ),
    UnnamedExplicitSourceRedundant(#[error(source)] SimpleErr),
    NamedIgnore {
        #[error(ignore)]
        source: SimpleErr,
        field: i32,
    },
    UnnamedIgnore(#[error(ignore)] SimpleErr),
    NamedIgnoreRedundant {
        #[error(ignore)]
        field: i32,
    },
    UnnamedIgnoreRedundant(#[error(ignore)] i32, #[error(ignore)] i32),
    #[error(ignore)]
    NamedVariantIgnore {
        source: SimpleErr,
        field: i32,
    },
    #[error(ignore)]
    UnnamedVariantIgnore(SimpleErr),
    #[error(ignore)]
    NamedVariantIgnoreRedundant {
        field: i32,
    },
    #[error(ignore)]
    UnnamedVariantIgnoreRedundant(i32, i32),
}

#[test]
fn unit() {
    assert!(TestErr::Unit.source().is_none());
}

#[test]
fn named_implicit_no_source() {
    let err = TestErr::NamedImplicitNoSource { field: 0 };

    assert!(err.source().is_none());
}

#[test]
fn named_implicit_source() {
    let err = TestErr::NamedImplicitSource {
        source: SimpleErr,
        field: 0,
    };

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn named_explicit_no_source() {
    let err = TestErr::NamedExplicitNoSource {
        source: SimpleErr,
        field: 0,
    };

    assert!(err.source().is_none());
}

#[test]
fn named_explicit_source() {
    let err = TestErr::NamedExplicitSource {
        explicit_source: SimpleErr,
        field: 0,
    };

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn named_explicit_no_source_redundant() {
    let err = TestErr::NamedExplicitNoSourceRedundant { field: 0 };

    assert!(err.source().is_none());
}

#[test]
fn named_explicit_source_redundant() {
    let err = TestErr::NamedExplicitSourceRedundant {
        source: SimpleErr,
        field: 0,
    };

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn named_explicit_suppresses_implicit() {
    let err = TestErr::NamedExplicitSuppressesImplicit {
        source: 0,
        field: SimpleErr,
    };

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn unnamed_implicit_no_source() {
    assert!(TestErr::UnnamedImplicitNoSource(0, 0).source().is_none());
}

#[test]
fn unnamed_implicit_source() {
    let err = TestErr::UnnamedImplicitSource(SimpleErr);

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn unnamed_explicit_no_source() {
    let err = TestErr::UnnamedExplicitNoSource(SimpleErr);

    assert!(err.source().is_none());
}

#[test]
fn unnamed_explicit_source() {
    let err = TestErr::UnnamedExplicitSource(SimpleErr, 0);

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn unnamed_explicit_no_source_redundant() {
    let err = TestErr::UnnamedExplicitNoSourceRedundant(0, 0);

    assert!(err.source().is_none());
}

#[test]
fn unnamed_explicit_source_redundant() {
    let err = TestErr::UnnamedExplicitSourceRedundant(SimpleErr);

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn named_ignore() {
    let err = TestErr::NamedIgnore {
        source: SimpleErr,
        field: 0,
    };

    assert!(err.source().is_none());
}

#[test]
fn unnamed_ignore() {
    let err = TestErr::UnnamedIgnore(SimpleErr);

    assert!(err.source().is_none());
}

#[test]
fn named_ignore_redundant() {
    let err = TestErr::NamedIgnoreRedundant { field: 0 };

    assert!(err.source().is_none());
}

#[test]
fn unnamed_ignore_redundant() {
    let err = TestErr::UnnamedIgnoreRedundant(0, 0);

    assert!(err.source().is_none());
}

#[test]
fn named_variant_ignore() {
    let err = TestErr::NamedVariantIgnore {
        source: SimpleErr,
        field: 0,
    };

    assert!(err.source().is_none());
}

#[test]
fn unnamed_variant_ignore() {
    let err = TestErr::UnnamedVariantIgnore(SimpleErr);

    assert!(err.source().is_none())
}

#[test]
fn named_variant_ignore_redundant() {
    let err = TestErr::NamedVariantIgnoreRedundant { field: 0 };

    assert!(err.source().is_none());
}

#[test]
fn unnamed_variant_ignore_redundant() {
    let err = TestErr::UnnamedVariantIgnoreRedundant(0, 0);

    assert!(err.source().is_none())
}
<commit_msg>Allow dead code in test that complained about it<commit_after>#![allow(dead_code)]
use super::*;

derive_display!(TestErr);
#[derive(Debug, Error)]
enum TestErr {
    Unit,
    NamedImplicitNoSource {
        field: i32,
    },
    NamedImplicitSource {
        source: SimpleErr,
        field: i32,
    },
    NamedExplicitNoSource {
        #[error(not(source))]
        source: SimpleErr,
        field: i32,
    },
    NamedExplicitSource {
        #[error(source)]
        explicit_source: SimpleErr,
        field: i32,
    },
    NamedExplicitNoSourceRedundant {
        #[error(not(source))]
        field: i32,
    },
    NamedExplicitSourceRedundant {
        #[error(source)]
        source: SimpleErr,
        field: i32,
    },
    NamedExplicitSuppressesImplicit {
        source: i32,
        #[error(source)]
        field: SimpleErr,
    },
    UnnamedImplicitNoSource(i32, i32),
    UnnamedImplicitSource(SimpleErr),
    UnnamedExplicitNoSource(#[error(not(source))] SimpleErr),
    UnnamedExplicitSource(#[error(source)] SimpleErr, i32),
    UnnamedExplicitNoSourceRedundant(
        #[error(not(source))] i32,
        #[error(not(source))] i32,
    ),
    UnnamedExplicitSourceRedundant(#[error(source)] SimpleErr),
    NamedIgnore {
        #[error(ignore)]
        source: SimpleErr,
        field: i32,
    },
    UnnamedIgnore(#[error(ignore)] SimpleErr),
    NamedIgnoreRedundant {
        #[error(ignore)]
        field: i32,
    },
    UnnamedIgnoreRedundant(#[error(ignore)] i32, #[error(ignore)] i32),
    #[error(ignore)]
    NamedVariantIgnore {
        source: SimpleErr,
        field: i32,
    },
    #[error(ignore)]
    UnnamedVariantIgnore(SimpleErr),
    #[error(ignore)]
    NamedVariantIgnoreRedundant {
        field: i32,
    },
    #[error(ignore)]
    UnnamedVariantIgnoreRedundant(i32, i32),
}

#[test]
fn unit() {
    assert!(TestErr::Unit.source().is_none());
}

#[test]
fn named_implicit_no_source() {
    let err = TestErr::NamedImplicitNoSource { field: 0 };

    assert!(err.source().is_none());
}

#[test]
fn named_implicit_source() {
    let err = TestErr::NamedImplicitSource {
        source: SimpleErr,
        field: 0,
    };

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn named_explicit_no_source() {
    let err = TestErr::NamedExplicitNoSource {
        source: SimpleErr,
        field: 0,
    };

    assert!(err.source().is_none());
}

#[test]
fn named_explicit_source() {
    let err = TestErr::NamedExplicitSource {
        explicit_source: SimpleErr,
        field: 0,
    };

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn named_explicit_no_source_redundant() {
    let err = TestErr::NamedExplicitNoSourceRedundant { field: 0 };

    assert!(err.source().is_none());
}

#[test]
fn named_explicit_source_redundant() {
    let err = TestErr::NamedExplicitSourceRedundant {
        source: SimpleErr,
        field: 0,
    };

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn named_explicit_suppresses_implicit() {
    let err = TestErr::NamedExplicitSuppressesImplicit {
        source: 0,
        field: SimpleErr,
    };

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn unnamed_implicit_no_source() {
    assert!(TestErr::UnnamedImplicitNoSource(0, 0).source().is_none());
}

#[test]
fn unnamed_implicit_source() {
    let err = TestErr::UnnamedImplicitSource(SimpleErr);

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn unnamed_explicit_no_source() {
    let err = TestErr::UnnamedExplicitNoSource(SimpleErr);

    assert!(err.source().is_none());
}

#[test]
fn unnamed_explicit_source() {
    let err = TestErr::UnnamedExplicitSource(SimpleErr, 0);

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn unnamed_explicit_no_source_redundant() {
    let err = TestErr::UnnamedExplicitNoSourceRedundant(0, 0);

    assert!(err.source().is_none());
}

#[test]
fn unnamed_explicit_source_redundant() {
    let err = TestErr::UnnamedExplicitSourceRedundant(SimpleErr);

    assert!(err.source().is_some());
    assert!(err.source().unwrap().is::<SimpleErr>());
}

#[test]
fn named_ignore() {
    let err = TestErr::NamedIgnore {
        source: SimpleErr,
        field: 0,
    };

    assert!(err.source().is_none());
}

#[test]
fn unnamed_ignore() {
    let err = TestErr::UnnamedIgnore(SimpleErr);

    assert!(err.source().is_none());
}

#[test]
fn named_ignore_redundant() {
    let err = TestErr::NamedIgnoreRedundant { field: 0 };

    assert!(err.source().is_none());
}

#[test]
fn unnamed_ignore_redundant() {
    let err = TestErr::UnnamedIgnoreRedundant(0, 0);

    assert!(err.source().is_none());
}

#[test]
fn named_variant_ignore() {
    let err = TestErr::NamedVariantIgnore {
        source: SimpleErr,
        field: 0,
    };

    assert!(err.source().is_none());
}

#[test]
fn unnamed_variant_ignore() {
    let err = TestErr::UnnamedVariantIgnore(SimpleErr);

    assert!(err.source().is_none())
}

#[test]
fn named_variant_ignore_redundant() {
    let err = TestErr::NamedVariantIgnoreRedundant { field: 0 };

    assert!(err.source().is_none());
}

#[test]
fn unnamed_variant_ignore_redundant() {
    let err = TestErr::UnnamedVariantIgnoreRedundant(0, 0);

    assert!(err.source().is_none())
}
<|endoftext|>