<commit_before>#![feature(const_fn)]
#![allow(dead_code)]
#![deny(unsafe_code)]

extern crate js;
extern crate libc;
#[macro_use] extern crate linjs;
#[macro_use] extern crate linjs_derive;

use js::jsapi;
use js::jsapi::JSClass;
use js::jsapi::JSClassOps;
use js::jsapi::JSNativeWrapper;
use js::jsapi::JSPropertySpec;
use js::jsapi::Value;

use libc::c_char;
use libc::c_uint;

use linjs::CanAccess;
use linjs::CanAlloc;
use linjs::CanCreate;
use linjs::HasClass;
use linjs::HasInstance;
use linjs::HasGlobal;
use linjs::InCompartment;
use linjs::Initialized;
use linjs::JSContext;
use linjs::JSInitializer;
use linjs::JSManaged;
use linjs::JSRunnable;
use linjs::null_property;
use linjs::null_wrapper;

use std::ptr;

// -------------------------------------------------------------------

type Window<'a, C> = JSManaged<'a, C, WindowClass>;

#[derive(JSTraceable, JSRootable)]
struct NativeWindow<'a, C> {
    console: Console<'a, C>,
    document: Document<'a, C>,
}

fn init_window<'a, C, S>(cx: JSContext<S>) -> JSContext<Initialized<C>> where
    S: CanCreate<C>,
    C: HasGlobal<WindowClass>,
{
    let mut cx = cx.create_compartment();
    rooted!(in(cx) let console = new_console(&mut cx));
    rooted!(in(cx) let document = new_document(&mut cx));
    cx.global_manage(NativeWindow {
        console: console,
        document: document,
    })
}

struct WindowClass;

impl<'a, C> HasClass for NativeWindow<'a, C> {
    type Class = WindowClass;
    type Init = WindowInitializer;
}

impl<'a, C> HasInstance<'a, C> for WindowClass {
    type Instance = NativeWindow<'a, C>;
}

impl WindowMethods for WindowClass {
    fn Console<'a, C, S>(cx: &'a mut JSContext<S>, this: Window<'a, C>) -> Console<'a, C> where
        S: CanAccess + InCompartment<C>,
        C: 'a,
    {
        this.get(cx).console
    }

    fn Document<'a, C, S>(cx: &'a mut JSContext<S>, this: Window<'a, C>) -> Document<'a, C> where
        S: CanAccess + InCompartment<C>,
        C: 'a,
    {
        this.get(cx).document
    }
}

// -------------------------------------------------------------------

type Console<'a, C> = JSManaged<'a, C, NativeConsoleClass>;

#[derive(HasClass, JSTraceable, JSRootable)]
struct NativeConsole();

fn new_console<'a, C, S>(cx: &'a mut JSContext<S>) -> Console<'a, C> where
    C: 'a,
    S: CanAlloc + InCompartment<C>,
{
    cx.manage(NativeConsole())
}

// -------------------------------------------------------------------

type Document<'a, C> = JSManaged<'a, C, NativeDocumentClass>;

#[derive(HasClass, JSTraceable, JSRootable)]
struct NativeDocument<'a, C> {
    body: Element<'a, C>,
}

fn new_document<'a, C, S>(cx: &'a mut JSContext<S>) -> Document<'a, C> where
    C: 'a,
    S: CanAlloc + InCompartment<C>,
{
    rooted!(in(cx) let body = new_element(cx));
    cx.manage(NativeDocument {
        body: body,
    })
}

// -------------------------------------------------------------------

type Element<'a, C> = JSManaged<'a, C, NativeElementClass>;

#[derive(HasClass, JSTraceable, JSRootable)]
struct NativeElement<'a, C> {
    parent: Option<Element<'a, C>>,
    children: Vec<Element<'a, C>>,
}

fn new_element<'a, C, S>(cx: &'a mut JSContext<S>) -> Element<'a, C> where
    S: CanAlloc + InCompartment<C>,
    C: 'a,
{
    cx.manage(NativeElement {
        parent: None,
        children: Vec::new(),
    })
}

// -------------------------------------------------------------------

struct Main;

impl JSRunnable<WindowClass> for Main {
    fn run<C, S>(self, cx: JSContext<S>) where
        S: CanCreate<C>,
        C: HasGlobal<WindowClass>,
    {
        let ref mut _cx = init_window(cx);
    }
}

fn main() {
    Main.start();
}

// -------------------------------------------------------------------

// Stuff which is produced by codegen

#[allow(non_snake_case)]
trait WindowMethods {
    fn Console<'a, C, S>(cx: &'a mut JSContext<S>, this: Window<'a, C>) -> Console<'a, C> where
        S: 'a + CanAccess + CanAlloc + InCompartment<C>,
        C: 'a + HasGlobal<WindowClass>;

    fn Document<'a, C, S>(cx: &'a mut JSContext<S>, this: Window<'a,
        C>) -> Document<'a, C> where S: 'a + CanAccess + CanAlloc +
        InCompartment<C>, C: 'a + HasGlobal<WindowClass>; }

static WINDOW_CLASS: JSClass = JSClass {
    name: b"Window\0" as *const u8 as *const c_char,
    flags: js::JSCLASS_IS_GLOBAL,
    cOps: &JSClassOps {
        addProperty: None,
        call: None,
        construct: None,
        delProperty: None,
        enumerate: None,
        finalize: None,
        getProperty: None,
        hasInstance: None,
        mayResolve: None,
        resolve: None,
        setProperty: None,
        trace: None,
    },
    reserved: [0 as *mut _; 3],
};

const WINDOW_PROPERTIES: &[JSPropertySpec] = &[
    JSPropertySpec {
        name: b"document\0" as *const u8 as *const c_char,
        flags: 0,
        getter: JSNativeWrapper {
            op: Some(window_document_getter),
            info: ptr::null(),
        },
        setter: null_wrapper(),
    },
    null_property(),
];

#[allow(unsafe_code)]
unsafe extern "C" fn window_document_getter(_cx: *mut jsapi::JSContext, _argc: c_uint, _vp: *mut Value) -> bool {
    // let args = CallArgs::from_vp(vp, argc);
    // let window = args.thisv();
    // let ref mut cx = JSContext::from(cx);
    // let result = WindowClass::Console(cx, window);
    // args.rval().set(result);
    true
}

// Stuff which could be produced by codegen

struct WindowInitializer;

impl JSInitializer for WindowInitializer {
    #[allow(unsafe_code)]
    unsafe fn classp() -> *const JSClass {
        &WINDOW_CLASS
    }

    #[allow(unsafe_code)]
    unsafe fn properties() -> *const JSPropertySpec {
        &WINDOW_PROPERTIES[0]
    }
}
<commit_msg>Fixed linebreaks.<commit_after>#![feature(const_fn)]
#![allow(dead_code)]
#![deny(unsafe_code)]

extern crate js;
extern crate libc;
#[macro_use] extern crate linjs;
#[macro_use] extern crate linjs_derive;

use js::jsapi;
use js::jsapi::JSClass;
use js::jsapi::JSClassOps;
use js::jsapi::JSNativeWrapper;
use js::jsapi::JSPropertySpec;
use js::jsapi::Value;

use libc::c_char;
use libc::c_uint;

use linjs::CanAccess;
use linjs::CanAlloc;
use linjs::CanCreate;
use linjs::HasClass;
use linjs::HasInstance;
use linjs::HasGlobal;
use linjs::InCompartment;
use linjs::Initialized;
use linjs::JSContext;
use linjs::JSInitializer;
use linjs::JSManaged;
use linjs::JSRunnable;
use linjs::null_property;
use linjs::null_wrapper;

use std::ptr;

// -------------------------------------------------------------------

type Window<'a, C> = JSManaged<'a, C, WindowClass>;

#[derive(JSTraceable, JSRootable)]
struct NativeWindow<'a, C> {
    console: Console<'a, C>,
    document: Document<'a, C>,
}

fn init_window<'a, C, S>(cx: JSContext<S>) -> JSContext<Initialized<C>> where
    S: CanCreate<C>,
    C: HasGlobal<WindowClass>,
{
    let mut cx = cx.create_compartment();
    rooted!(in(cx) let console = new_console(&mut cx));
    rooted!(in(cx) let document = new_document(&mut cx));
    cx.global_manage(NativeWindow {
        console: console,
        document: document,
    })
}

struct WindowClass;

impl<'a, C> HasClass for NativeWindow<'a, C> {
    type Class = WindowClass;
    type Init = WindowInitializer;
}

impl<'a, C> HasInstance<'a, C> for WindowClass {
    type Instance = NativeWindow<'a, C>;
}

impl WindowMethods for WindowClass {
    fn Console<'a, C, S>(cx: &'a mut JSContext<S>, this: Window<'a, C>) -> Console<'a, C> where
        S: CanAccess + InCompartment<C>,
        C: 'a,
    {
        this.get(cx).console
    }

    fn Document<'a, C, S>(cx: &'a mut JSContext<S>, this: Window<'a, C>) -> Document<'a, C> where
        S: CanAccess + InCompartment<C>,
        C: 'a,
    {
        this.get(cx).document
    }
}

// -------------------------------------------------------------------

type Console<'a, C> = JSManaged<'a, C, NativeConsoleClass>;

#[derive(HasClass, JSTraceable, JSRootable)]
struct NativeConsole();

fn new_console<'a, C, S>(cx: &'a mut JSContext<S>) -> Console<'a, C> where
    C: 'a,
    S: CanAlloc + InCompartment<C>,
{
    cx.manage(NativeConsole())
}

// -------------------------------------------------------------------

type Document<'a, C> = JSManaged<'a, C, NativeDocumentClass>;

#[derive(HasClass, JSTraceable, JSRootable)]
struct NativeDocument<'a, C> {
    body: Element<'a, C>,
}

fn new_document<'a, C, S>(cx: &'a mut JSContext<S>) -> Document<'a, C> where
    C: 'a,
    S: CanAlloc + InCompartment<C>,
{
    rooted!(in(cx) let body = new_element(cx));
    cx.manage(NativeDocument {
        body: body,
    })
}

// -------------------------------------------------------------------

type Element<'a, C> = JSManaged<'a, C, NativeElementClass>;

#[derive(HasClass, JSTraceable, JSRootable)]
struct NativeElement<'a, C> {
    parent: Option<Element<'a, C>>,
    children: Vec<Element<'a, C>>,
}

fn new_element<'a, C, S>(cx: &'a mut JSContext<S>) -> Element<'a, C> where
    S: CanAlloc + InCompartment<C>,
    C: 'a,
{
    cx.manage(NativeElement {
        parent: None,
        children: Vec::new(),
    })
}

// -------------------------------------------------------------------

struct Main;

impl JSRunnable<WindowClass> for Main {
    fn run<C, S>(self, cx: JSContext<S>) where
        S: CanCreate<C>,
        C: HasGlobal<WindowClass>,
    {
        let ref mut _cx = init_window(cx);
    }
}

fn main() {
    Main.start();
}

// -------------------------------------------------------------------

// Stuff which is produced by codegen

#[allow(non_snake_case)]
trait WindowMethods {
    fn Console<'a, C, S>(cx: &'a mut JSContext<S>, this: Window<'a, C>) -> Console<'a, C> where
        S: 'a + CanAccess + CanAlloc + InCompartment<C>,
        C: 'a + HasGlobal<WindowClass>;

    fn Document<'a, C, S>(cx: &'a mut JSContext<S>, this: Window<'a, C>) -> Document<'a, C> where
        S: 'a + CanAccess + CanAlloc + InCompartment<C>,
        C: 'a + HasGlobal<WindowClass>;
}

static WINDOW_CLASS: JSClass = JSClass {
    name: b"Window\0" as *const u8 as *const c_char,
    flags: js::JSCLASS_IS_GLOBAL,
    cOps: &JSClassOps {
        addProperty: None,
        call: None,
        construct: None,
        delProperty: None,
        enumerate: None,
        finalize: None,
        getProperty: None,
        hasInstance: None,
        mayResolve: None,
        resolve: None,
        setProperty: None,
        trace: None,
    },
    reserved: [0 as *mut _; 3],
};

const WINDOW_PROPERTIES: &[JSPropertySpec] = &[
    JSPropertySpec {
        name: b"document\0" as *const u8 as *const c_char,
        flags: 0,
        getter: JSNativeWrapper {
            op: Some(window_document_getter),
            info: ptr::null(),
        },
        setter: null_wrapper(),
    },
    null_property(),
];

#[allow(unsafe_code)]
unsafe extern "C" fn window_document_getter(_cx: *mut jsapi::JSContext, _argc: c_uint, _vp: *mut Value) -> bool {
    // let args = CallArgs::from_vp(vp, argc);
    // let window = args.thisv();
    // let ref mut cx = JSContext::from(cx);
    // let result = WindowClass::Console(cx, window);
    // args.rval().set(result);
    true
}

// Stuff which could be produced by codegen

struct WindowInitializer;

impl JSInitializer for WindowInitializer {
    #[allow(unsafe_code)]
    unsafe fn classp() -> *const JSClass {
        &WINDOW_CLASS
    }

    #[allow(unsafe_code)]
    unsafe fn properties() -> *const JSPropertySpec {
        &WINDOW_PROPERTIES[0]
    }
}
<|endoftext|>


<commit_before>//! A simple example which prints out information about available Metal devices

extern crate mtl;

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
fn main() {
    println!("Metal is not supported on this platform");
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
fn main() {
    let devices = mtl::Device::enumerate_all_system_devices();

    let num_devices_message = format!("Number of system devices: {}", devices.len());
    let separator = std::iter::repeat('=')
                        .take(num_devices_message.len())
                        .collect::<String>();

    println!("{}", num_devices_message);
    println!("{}", separator);
    println!("");

    for (index, device) in devices.into_iter().enumerate() {
        println!("Device {} info:", index);
        let device = match device {
            Ok(device) => device,
            Err(e) => {
                use std::error::Error;
                println!("{}", e.description());
                break;
            }
        };

        println!("Name:\t\t\t\t\t\t{}", device.name());
        println!("Supports 24 bit stencil and 8 bit depth:\t{}",
                 device.is_depth24_stencil8_pixel_format_supported());
        {
            let max_tpg = device.max_threads_per_group();
            println!("Maximum threads per group:\t\t\t({}, {}, {})",
                     max_tpg.width,
                     max_tpg.height,
                     max_tpg.depth);
        }
        println!("Is low power:\t\t\t\t\t{}", device.is_low_power());
        println!("Is headless:\t\t\t\t\t{}", device.is_headless());
        println!("");
    }
}
<commit_msg>Don't break when encountering a bad device in mtlinfo; continue instead<commit_after>//! A simple example which prints out information about available Metal devices

extern crate mtl;

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
fn main() {
    println!("Metal is not supported on this platform");
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
fn main() {
    let devices = mtl::Device::enumerate_all_system_devices();

    let num_devices_message = format!("Number of system devices: {}", devices.len());
    let separator = std::iter::repeat('=')
                        .take(num_devices_message.len())
                        .collect::<String>();

    println!("{}", num_devices_message);
    println!("{}", separator);
    println!("");

    for (index, device) in devices.into_iter().enumerate() {
        println!("Device {} info:", index);
        let device = match device {
            Ok(device) => device,
            Err(e) => {
                use std::error::Error;
                println!("{}", e.description());
                continue
            }
        };

        println!("Name:\t\t\t\t\t\t{}", device.name());
        println!("Supports 24 bit stencil and 8 bit depth:\t{}",
                 device.is_depth24_stencil8_pixel_format_supported());
        {
            let max_tpg = device.max_threads_per_group();
            println!("Maximum threads per group:\t\t\t({}, {}, {})",
                     max_tpg.width,
                     max_tpg.height,
                     max_tpg.depth);
        }
        println!("Is low power:\t\t\t\t\t{}", device.is_low_power());
        println!("Is headless:\t\t\t\t\t{}", device.is_headless());
        println!("");
    }
}
<|endoftext|>


<commit_before>extern crate rsrl;
extern crate seahash;

use rsrl::{run, logging, Parameter, SerialExperiment, Evaluation};
use rsrl::agents::control::td::ExpectedSARSA;
use rsrl::domains::{Domain, Acrobat};
use rsrl::fa::{Linear, SparseLinear};
use rsrl::fa::projection::RBFNetwork;
use rsrl::geometry::Space;
use rsrl::policies::EpsilonGreedy;

use std::hash::BuildHasherDefault;

type SeahashBuildHasher = BuildHasherDefault<seahash::SeaHasher>;

fn main() {
    let logger = logging::root(logging::stdout());

    let domain = Acrobat::default();
    let mut agent = {
        let aspace = domain.action_space();
        let n_actions: usize = aspace.span().into();

        let pr = RBFNetwork::from_space(domain.state_space().partitioned(8));
        let q_func = Linear::new(pr, n_actions);
        let policy = EpsilonGreedy::new(Parameter::exponential(0.99, 0.05, 0.99));

        ExpectedSARSA::new(q_func, policy, 0.2, 0.99)
    };

    // Training:
    let _training_result = {
        let e = SerialExperiment::new(&mut agent, Box::new(Acrobat::default), 1000);

        run(e, 1000, Some(logger))
    };

    // println!("{:?}", agent.q_func.weights);

    // Testing:
    let testing_result =
        Evaluation::new(&mut agent, Box::new(Acrobat::default)).next().unwrap();

    println!("Solution \u{21D2} {} steps | reward {}",
             testing_result.steps,
             testing_result.reward);
}
<commit_msg>Remove commented line from sandbox.rs<commit_after>extern crate rsrl;
extern crate seahash;

use rsrl::{run, logging, Parameter, SerialExperiment, Evaluation};
use rsrl::agents::control::td::ExpectedSARSA;
use rsrl::domains::{Domain, Acrobat};
use rsrl::fa::{Linear, SparseLinear};
use rsrl::fa::projection::RBFNetwork;
use rsrl::geometry::Space;
use rsrl::policies::EpsilonGreedy;

use std::hash::BuildHasherDefault;

type SeahashBuildHasher = BuildHasherDefault<seahash::SeaHasher>;

fn main() {
    let logger = logging::root(logging::stdout());

    let domain = Acrobat::default();
    let mut agent = {
        let aspace = domain.action_space();
        let n_actions: usize = aspace.span().into();

        let pr = RBFNetwork::from_space(domain.state_space().partitioned(8));
        let q_func = Linear::new(pr, n_actions);
        let policy = EpsilonGreedy::new(Parameter::exponential(0.99, 0.05, 0.99));

        ExpectedSARSA::new(q_func, policy, 0.2, 0.99)
    };

    // Training:
    let _training_result = {
        let e = SerialExperiment::new(&mut agent, Box::new(Acrobat::default), 1000);

        run(e, 1000, Some(logger))
    };

    // Testing:
    let testing_result =
        Evaluation::new(&mut agent, Box::new(Acrobat::default)).next().unwrap();

    println!("Solution \u{21D2} {} steps | reward {}",
             testing_result.steps,
             testing_result.reward);
}
<|endoftext|>


<commit_before>use fallible_iterator::FallibleIterator;
use postgres_protocol::message::backend::DataRowBody;
use std::ascii::AsciiExt;
use std::io;
use std::ops::Range;

use stmt::Column;

/// A trait implemented by types that can index into columns of a row.
pub trait RowIndex {
    /// Returns the index of the appropriate column, or `None` if no such
    /// column exists.
    fn idx(&self, stmt: &[Column]) -> Option<usize>;
}

impl RowIndex for usize {
    #[inline]
    fn idx(&self, stmt: &[Column]) -> Option<usize> {
        if *self >= stmt.len() {
            None
        } else {
            Some(*self)
        }
    }
}

impl<'a> RowIndex for str {
    #[inline]
    fn idx(&self, stmt: &[Column]) -> Option<usize> {
        if let Some(idx) = stmt.iter().position(|d| d.name() == self) {
            return Some(idx);
        };

        // FIXME ASCII-only case insensitivity isn't really the right thing to
        // do. Postgres itself uses a dubious wrapper around tolower and JDBC
        // uses the US locale.
        stmt.iter().position(
            |d| d.name().eq_ignore_ascii_case(self),
        )
    }
}

impl<'a, T: ?Sized> RowIndex for &'a T
where
    T: RowIndex,
{
    #[inline]
    fn idx(&self, columns: &[Column]) -> Option<usize> {
        T::idx(*self, columns)
    }
}

#[doc(hidden)]
pub struct RowData {
    body: DataRowBody,
    ranges: Vec<Option<Range<usize>>>,
}

impl RowData {
    pub fn new(body: DataRowBody) -> io::Result<RowData> {
        let ranges = body.ranges().collect()?;
        Ok(RowData {
            body: body,
            ranges: ranges,
        })
    }

    pub fn len(&self) -> usize {
        self.ranges.len()
    }

    pub fn get(&self, index: usize) -> Option<&[u8]> {
        match &self.ranges[index] {
            &Some(ref range) => Some(&self.body.buffer()[range.clone()]),
            &None => None,
        }
    }
}
<commit_msg>Seal RowIndex<commit_after>use fallible_iterator::FallibleIterator;
use postgres_protocol::message::backend::DataRowBody;
use std::ascii::AsciiExt;
use std::io;
use std::ops::Range;

use stmt::Column;
use rows::sealed::Sealed;

mod sealed {
    use stmt::Column;

    pub trait Sealed {
        fn idx(&self, stmt: &[Column]) -> Option<usize>;
    }
}

/// A trait implemented by types that can index into columns of a row.
///
/// This cannot be implemented outside of this crate.
pub trait RowIndex: Sealed {}

impl Sealed for usize {
    #[inline]
    fn idx(&self, stmt: &[Column]) -> Option<usize> {
        if *self >= stmt.len() {
            None
        } else {
            Some(*self)
        }
    }
}

impl RowIndex for usize {}

impl Sealed for str {
    #[inline]
    fn idx(&self, stmt: &[Column]) -> Option<usize> {
        if let Some(idx) = stmt.iter().position(|d| d.name() == self) {
            return Some(idx);
        };

        // FIXME ASCII-only case insensitivity isn't really the right thing to
        // do. Postgres itself uses a dubious wrapper around tolower and JDBC
        // uses the US locale.
        stmt.iter().position(
            |d| d.name().eq_ignore_ascii_case(self),
        )
    }
}

impl RowIndex for str {}

impl<'a, T> Sealed for &'a T
where
    T: ?Sized + Sealed,
{
    #[inline]
    fn idx(&self, columns: &[Column]) -> Option<usize> {
        T::idx(*self, columns)
    }
}

impl<'a, T> RowIndex for &'a T
where
    T: ?Sized + Sealed,
{
}

#[doc(hidden)]
pub struct RowData {
    body: DataRowBody,
    ranges: Vec<Option<Range<usize>>>,
}

impl RowData {
    pub fn new(body: DataRowBody) -> io::Result<RowData> {
        let ranges = body.ranges().collect()?;
        Ok(RowData {
            body: body,
            ranges: ranges,
        })
    }

    pub fn len(&self) -> usize {
        self.ranges.len()
    }

    pub fn get(&self, index: usize) -> Option<&[u8]> {
        match &self.ranges[index] {
            &Some(ref range) => Some(&self.body.buffer()[range.clone()]),
            &None => None,
        }
    }
}
<|endoftext|>


<commit_before>/// This function is where the kernel sets up IRQ handlers
/// It is increcibly unsafe, and should be minimal in nature
/// It must create the IDT with the correct entries, those entries are
/// defined in other files inside of the `arch` module

use core::slice;
use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

use allocator;
#[cfg(feature = "acpi")]
use acpi;
#[cfg(feature = "graphical_debug")]
use arch::x86_64::graphical_debug;
use arch::x86_64::pti;
use device;
use gdt;
use idt;
use interrupt;
use memory;
use paging;

/// Test of zero values in BSS.
static BSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in data.
static DATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF;
/// Test of zero values in thread BSS
#[thread_local]
static mut TBSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in thread data.
#[thread_local]
static mut TDATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF;

pub static KERNEL_BASE: AtomicUsize = ATOMIC_USIZE_INIT;
pub static KERNEL_SIZE: AtomicUsize = ATOMIC_USIZE_INIT;
pub static CPU_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
pub static AP_READY: AtomicBool = ATOMIC_BOOL_INIT;
static BSP_READY: AtomicBool = ATOMIC_BOOL_INIT;

#[repr(packed)]
pub struct KernelArgs {
    kernel_base: u64,
    kernel_size: u64,
    stack_base: u64,
    stack_size: u64,
    env_base: u64,
    env_size: u64,
}

/// The entry to Rust, all things must be initialized
#[no_mangle]
pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
    let env = {
        let args = &*args_ptr;

        let kernel_base = args.kernel_base as usize;
        let kernel_size = args.kernel_size as usize;
        let stack_base = args.stack_base as usize;
        let stack_size = args.stack_size as usize;
        let env_base = args.env_base as usize;
        let env_size = args.env_size as usize;

        // BSS should already be zero
        {
            assert_eq!(BSS_TEST_ZERO, 0);
            assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
        }

        KERNEL_BASE.store(kernel_base, Ordering::SeqCst);
        KERNEL_SIZE.store(kernel_size, Ordering::SeqCst);

        println!("Kernel: {:X}:{:X}", kernel_base, kernel_base + kernel_size);
        println!("Stack: {:X}:{:X}", stack_base, stack_base + stack_size);
        println!("Env: {:X}:{:X}", env_base, env_base + env_size);

        // Set up GDT before paging
        gdt::init();

        // Set up IDT before paging
        idt::init();

        // Initialize memory management
        memory::init(0, kernel_base + ((kernel_size + 4095)/4096) * 4096);

        // Initialize paging
        let (mut active_table, tcb_offset) = paging::init(0, kernel_base, kernel_base + kernel_size, stack_base, stack_base + stack_size);

        // Set up GDT after paging with TLS
        gdt::init_paging(tcb_offset, stack_base + stack_size);

        // Set up IDT
        idt::init_paging();

        // Set up syscall instruction
        interrupt::syscall::init();

        // Test tdata and tbss
        {
            assert_eq!(TBSS_TEST_ZERO, 0);
            TBSS_TEST_ZERO += 1;
            assert_eq!(TBSS_TEST_ZERO, 1);
            assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
            TDATA_TEST_NONZERO -= 1;
            assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFE);
        }

        // Reset AP variables
        CPU_COUNT.store(1, Ordering::SeqCst);
        AP_READY.store(false, Ordering::SeqCst);
        BSP_READY.store(false, Ordering::SeqCst);

        // Setup kernel heap
        allocator::init(&mut active_table);

        // Use graphical debug
        #[cfg(feature="graphical_debug")]
        graphical_debug::init(&mut active_table);

        // Initialize devices
        device::init(&mut active_table);

        // Read ACPI tables, starts APs
        #[cfg(feature = "acpi")]
        acpi::init(&mut active_table);

        // Initialize all of the non-core devices not otherwise needed to complete initialization
        device::init_noncore();

        // Initialize memory functions after core has loaded
        memory::init_noncore();

        // Stop graphical debug
        #[cfg(feature="graphical_debug")]
        graphical_debug::fini(&mut active_table);

        BSP_READY.store(true, Ordering::SeqCst);

        slice::from_raw_parts(env_base as *const u8, env_size)
    };

    ::kmain(CPU_COUNT.load(Ordering::SeqCst), env);
}

#[repr(packed)]
pub struct KernelArgsAp {
    cpu_id: u64,
    page_table: u64,
    stack_start: u64,
    stack_end: u64,
}

/// Entry to rust for an AP
pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
    let cpu_id = {
        let args = &*args_ptr;
        let cpu_id = args.cpu_id as usize;
        let bsp_table = args.page_table as usize;
        let stack_start = args.stack_start as usize;
        let stack_end = args.stack_end as usize;

        assert_eq!(BSS_TEST_ZERO, 0);
        assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);

        // Set up GDT before paging
        gdt::init();

        // Set up IDT before paging
        idt::init();

        // Initialize paging
        let tcb_offset = paging::init_ap(cpu_id, bsp_table, stack_start, stack_end);

        // Set up GDT with TLS
        gdt::init_paging(tcb_offset, stack_end);

        // Set up IDT for AP
        idt::init_paging();

        // Test tdata and tbss
        {
            assert_eq!(TBSS_TEST_ZERO, 0);
            TBSS_TEST_ZERO += 1;
            assert_eq!(TBSS_TEST_ZERO, 1);
            assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
            TDATA_TEST_NONZERO -= 1;
            assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFE);
        }

        // Initialize devices (for AP)
        device::init_ap();

        AP_READY.store(true, Ordering::SeqCst);

        cpu_id
    };

    while ! BSP_READY.load(Ordering::SeqCst) {
        interrupt::pause();
    }

    ::kmain_ap(cpu_id);
}

#[naked]
pub unsafe fn usermode(ip: usize, sp: usize, arg: usize) -> ! {
    asm!("push r10
          push r11
          push r12
          push r13
          push r14
          push r15"
          : // No output
          :   "{r10}"(gdt::GDT_USER_DATA << 3 | 3), // Data segment
              "{r11}"(sp), // Stack pointer
              "{r12}"(1 << 9), // Flags - Set interrupt enable flag
              "{r13}"(gdt::GDT_USER_CODE << 3 | 3), // Code segment
              "{r14}"(ip), // IP
              "{r15}"(arg) // Argument
          : // No clobbers
          : "intel", "volatile");

    // Unmap kernel
    pti::unmap();

    // Go to usermode
    asm!("mov ds, r14d
         mov es, r14d
         mov fs, r15d
         mov gs, r14d
         xor rax, rax
         xor rbx, rbx
         xor rcx, rcx
         xor rdx, rdx
         xor rsi, rsi
         xor rdi, rdi
         xor rbp, rbp
         xor r8, r8
         xor r9, r9
         xor r10, r10
         xor r11, r11
         xor r12, r12
         xor r13, r13
         xor r14, r14
         xor r15, r15
         fninit
         pop rdi
         iretq"
         : // No output because it never returns
         :   "{r14}"(gdt::GDT_USER_DATA << 3 | 3), // Data segment
             "{r15}"(gdt::GDT_USER_TLS << 3 | 3) // TLS segment
         : // No clobbers because it never returns
         : "intel", "volatile");
    unreachable!();
}
<commit_msg>Add syscall setup to kstart_ap<commit_after>/// This function is where the kernel sets up IRQ handlers
/// It is increcibly unsafe, and should be minimal in nature
/// It must create the IDT with the correct entries, those entries are
/// defined in other files inside of the `arch` module

use core::slice;
use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

use allocator;
#[cfg(feature = "acpi")]
use acpi;
#[cfg(feature = "graphical_debug")]
use arch::x86_64::graphical_debug;
use arch::x86_64::pti;
use device;
use gdt;
use idt;
use interrupt;
use memory;
use paging;

/// Test of zero values in BSS.
static BSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in data.
static DATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF;
/// Test of zero values in thread BSS
#[thread_local]
static mut TBSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in thread data.
#[thread_local]
static mut TDATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF;

pub static KERNEL_BASE: AtomicUsize = ATOMIC_USIZE_INIT;
pub static KERNEL_SIZE: AtomicUsize = ATOMIC_USIZE_INIT;
pub static CPU_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
pub static AP_READY: AtomicBool = ATOMIC_BOOL_INIT;
static BSP_READY: AtomicBool = ATOMIC_BOOL_INIT;

#[repr(packed)]
pub struct KernelArgs {
    kernel_base: u64,
    kernel_size: u64,
    stack_base: u64,
    stack_size: u64,
    env_base: u64,
    env_size: u64,
}

/// The entry to Rust, all things must be initialized
#[no_mangle]
pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
    let env = {
        let args = &*args_ptr;

        let kernel_base = args.kernel_base as usize;
        let kernel_size = args.kernel_size as usize;
        let stack_base = args.stack_base as usize;
        let stack_size = args.stack_size as usize;
        let env_base = args.env_base as usize;
        let env_size = args.env_size as usize;

        // BSS should already be zero
        {
            assert_eq!(BSS_TEST_ZERO, 0);
            assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
        }

        KERNEL_BASE.store(kernel_base, Ordering::SeqCst);
        KERNEL_SIZE.store(kernel_size, Ordering::SeqCst);

        println!("Kernel: {:X}:{:X}", kernel_base, kernel_base + kernel_size);
        println!("Stack: {:X}:{:X}", stack_base, stack_base + stack_size);
        println!("Env: {:X}:{:X}", env_base, env_base + env_size);

        // Set up GDT before paging
        gdt::init();

        // Set up IDT before paging
        idt::init();

        // Initialize memory management
        memory::init(0, kernel_base + ((kernel_size + 4095)/4096) * 4096);

        // Initialize paging
        let (mut active_table, tcb_offset) = paging::init(0, kernel_base, kernel_base + kernel_size, stack_base, stack_base + stack_size);

        // Set up GDT after paging with TLS
        gdt::init_paging(tcb_offset, stack_base + stack_size);

        // Set up IDT
        idt::init_paging();

        // Set up syscall instruction
        interrupt::syscall::init();

        // Test tdata and tbss
        {
            assert_eq!(TBSS_TEST_ZERO, 0);
            TBSS_TEST_ZERO += 1;
            assert_eq!(TBSS_TEST_ZERO, 1);
            assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
            TDATA_TEST_NONZERO -= 1;
            assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFE);
        }

        // Reset AP variables
        CPU_COUNT.store(1, Ordering::SeqCst);
        AP_READY.store(false, Ordering::SeqCst);
        BSP_READY.store(false, Ordering::SeqCst);

        // Setup kernel heap
        allocator::init(&mut active_table);

        // Use graphical debug
        #[cfg(feature="graphical_debug")]
        graphical_debug::init(&mut active_table);

        // Initialize devices
        device::init(&mut active_table);

        // Read ACPI tables, starts APs
        #[cfg(feature = "acpi")]
        acpi::init(&mut active_table);

        // Initialize all of the non-core devices not otherwise needed to complete initialization
        device::init_noncore();

        // Initialize memory functions after core has loaded
        memory::init_noncore();

        // Stop graphical debug
        #[cfg(feature="graphical_debug")]
        graphical_debug::fini(&mut active_table);

        BSP_READY.store(true, Ordering::SeqCst);

        slice::from_raw_parts(env_base as *const u8, env_size)
    };

    ::kmain(CPU_COUNT.load(Ordering::SeqCst), env);
}

#[repr(packed)]
pub struct KernelArgsAp {
    cpu_id: u64,
    page_table: u64,
    stack_start: u64,
    stack_end: u64,
}

/// Entry to rust for an AP
pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
    let cpu_id = {
        let args = &*args_ptr;
        let cpu_id = args.cpu_id as usize;
        let bsp_table = args.page_table as usize;
        let stack_start = args.stack_start as usize;
        let stack_end = args.stack_end as usize;

        assert_eq!(BSS_TEST_ZERO, 0);
        assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);

        // Set up GDT before paging
        gdt::init();

        // Set up IDT before paging
        idt::init();

        // Initialize paging
        let tcb_offset = paging::init_ap(cpu_id, bsp_table, stack_start, stack_end);

        // Set up GDT with TLS
        gdt::init_paging(tcb_offset, stack_end);

        // Set up IDT for AP
        idt::init_paging();

        // Set up syscall instruction
        interrupt::syscall::init();

        // Test tdata and tbss
        {
            assert_eq!(TBSS_TEST_ZERO, 0);
            TBSS_TEST_ZERO += 1;
            assert_eq!(TBSS_TEST_ZERO, 1);
            assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
            TDATA_TEST_NONZERO -= 1;
            assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFE);
        }

        // Initialize devices (for AP)
        device::init_ap();

        AP_READY.store(true, Ordering::SeqCst);

        cpu_id
    };

    while ! BSP_READY.load(Ordering::SeqCst) {
        interrupt::pause();
    }

    ::kmain_ap(cpu_id);
}

#[naked]
pub unsafe fn usermode(ip: usize, sp: usize, arg: usize) -> ! {
    asm!("push r10
          push r11
          push r12
          push r13
          push r14
          push r15"
          : // No output
          :   "{r10}"(gdt::GDT_USER_DATA << 3 | 3), // Data segment
              "{r11}"(sp), // Stack pointer
              "{r12}"(1 << 9), // Flags - Set interrupt enable flag
              "{r13}"(gdt::GDT_USER_CODE << 3 | 3), // Code segment
              "{r14}"(ip), // IP
              "{r15}"(arg) // Argument
          : // No clobbers
          : "intel", "volatile");

    // Unmap kernel
    pti::unmap();

    // Go to usermode
    asm!("mov ds, r14d
         mov es, r14d
         mov fs, r15d
         mov gs, r14d
         xor rax, rax
         xor rbx, rbx
         xor rcx, rcx
         xor rdx, rdx
         xor rsi, rsi
         xor rdi, rdi
         xor rbp, rbp
         xor r8, r8
         xor r9, r9
         xor r10, r10
         xor r11, r11
         xor r12, r12
         xor r13, r13
         xor r14, r14
         xor r15, r15
         fninit
         pop rdi
         iretq"
         : // No output because it never returns
         :   "{r14}"(gdt::GDT_USER_DATA << 3 | 3), // Data segment
             "{r15}"(gdt::GDT_USER_TLS << 3 | 3) // TLS segment
         : // No clobbers because it never returns
         : "intel", "volatile");
    unreachable!();
}
<|endoftext|>


<commit_before>use super::OverlapError;

use crate::traits;
use rustc::ty::fast_reject::{self, SimplifiedType};
use rustc::ty::{self, TyCtxt, TypeFoldable};
use rustc_hir::def_id::DefId;

pub use rustc::traits::types::specialization_graph::*;

#[derive(Copy, Clone, Debug)]
pub enum FutureCompatOverlapErrorKind {
    Issue33140,
    LeakCheck,
}

#[derive(Debug)]
pub struct FutureCompatOverlapError {
    pub error: OverlapError,
    pub kind: FutureCompatOverlapErrorKind,
}

/// The result of attempting to insert an impl into a group of children.
enum Inserted {
    /// The impl was inserted as a new child in this group of children.
    BecameNewSibling(Option<FutureCompatOverlapError>),

    /// The impl should replace existing impls [X1, ..], because the impl specializes X1, X2, etc.
    ReplaceChildren(Vec<DefId>),

    /// The impl is a specialization of an existing child.
    ShouldRecurseOn(DefId),
}

impl<'tcx> Children {
    /// Insert an impl into this set of children without comparing to any existing impls.
    fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
            debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
            self.nonblanket_impls.entry(st).or_default().push(impl_def_id)
        } else {
            debug!("insert_blindly: impl_def_id={:?} st=None", impl_def_id);
            self.blanket_impls.push(impl_def_id)
        }
    }

    /// Removes an impl from this set of children. Used when replacing
    /// an impl with a parent. The impl must be present in the list of
    /// children already.
    fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
        let vec: &mut Vec<DefId>;
        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
            debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
            vec = self.nonblanket_impls.get_mut(&st).unwrap();
        } else {
            debug!("remove_existing: impl_def_id={:?} st=None", impl_def_id);
            vec = &mut self.blanket_impls;
        }

        let index = vec.iter().position(|d| *d == impl_def_id).unwrap();
        vec.remove(index);
    }

    /// Attempt to insert an impl into this set of children, while comparing for
    /// specialization relationships.
    fn insert(
        &mut self,
        tcx: TyCtxt<'tcx>,
        impl_def_id: DefId,
        simplified_self: Option<SimplifiedType>,
    ) -> Result<Inserted, OverlapError> {
        let mut last_lint = None;
        let mut replace_children = Vec::new();

        debug!("insert(impl_def_id={:?}, simplified_self={:?})", impl_def_id, simplified_self,);

        let possible_siblings = match simplified_self {
            Some(st) => PotentialSiblings::Filtered(self.filtered(st)),
            None => PotentialSiblings::Unfiltered(self.iter()),
        };

        for possible_sibling in possible_siblings {
            debug!(
                "insert: impl_def_id={:?}, simplified_self={:?}, possible_sibling={:?}",
                impl_def_id, simplified_self, possible_sibling,
            );

            let overlap_error = |overlap: traits::coherence::OverlapResult<'_>| {
                // Found overlap, but no specialization; error out.
                let trait_ref = overlap.impl_header.trait_ref.unwrap();
                let self_ty = trait_ref.self_ty();
                OverlapError {
                    with_impl: possible_sibling,
                    trait_desc: trait_ref.print_only_trait_path().to_string(),
                    // Only report the `Self` type if it has at least
                    // some outer concrete shell; otherwise, it's
                    // not adding much information.
                    self_desc: if self_ty.has_concrete_skeleton() {
                        Some(self_ty.to_string())
                    } else {
                        None
                    },
                    intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
                    involves_placeholder: overlap.involves_placeholder,
                }
            };

            let allowed_to_overlap =
                tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling);

            let (le, ge) = traits::overlapping_impls(
                tcx,
                possible_sibling,
                impl_def_id,
                traits::SkipLeakCheck::default(),
                |overlap| {
                    if let Some(overlap_kind) = &allowed_to_overlap {
                        match overlap_kind {
                            ty::ImplOverlapKind::Permitted { marker: _ } => {}
                            ty::ImplOverlapKind::Issue33140 => {
                                last_lint = Some(FutureCompatOverlapError {
                                    error: overlap_error(overlap),
                                    kind: FutureCompatOverlapErrorKind::Issue33140,
                                });
                            }
                        }

                        return Ok((false, false));
                    }

                    let le = tcx.specializes((impl_def_id, possible_sibling));
                    let ge = tcx.specializes((possible_sibling, impl_def_id));

                    if le == ge { Err(overlap_error(overlap)) } else { Ok((le, ge)) }
                },
                || Ok((false, false)),
            )?;

            if le && !ge {
                debug!(
                    "descending as child of TraitRef {:?}",
                    tcx.impl_trait_ref(possible_sibling).unwrap()
                );

                // The impl specializes `possible_sibling`.
                return Ok(Inserted::ShouldRecurseOn(possible_sibling));
            } else if ge && !le {
                debug!(
                    "placing as parent of TraitRef {:?}",
                    tcx.impl_trait_ref(possible_sibling).unwrap()
                );

                replace_children.push(possible_sibling);
            } else {
                if let None = allowed_to_overlap {
                    // Do future-compat checks for overlap.

                    if last_lint.is_none() {
                        traits::overlapping_impls(
                            tcx,
                            possible_sibling,
                            impl_def_id,
                            traits::SkipLeakCheck::Yes,
                            |overlap| {
                                last_lint = Some(FutureCompatOverlapError {
                                    error: overlap_error(overlap),
                                    kind: FutureCompatOverlapErrorKind::LeakCheck,
                                });
                            },
                            || (),
                        );
                    }
                }

                // no overlap (error bailed already via ?)
            }
        }

        if !replace_children.is_empty() {
            return Ok(Inserted::ReplaceChildren(replace_children));
        }

        // No overlap with any potential siblings, so add as a new sibling.
        debug!("placing as new sibling");
        self.insert_blindly(tcx, impl_def_id);
        Ok(Inserted::BecameNewSibling(last_lint))
    }

    fn iter(&mut self) -> impl Iterator<Item = DefId> + '_ {
        let nonblanket = self.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter());
        self.blanket_impls.iter().chain(nonblanket).cloned()
    }

    fn filtered(&mut self, st: SimplifiedType) -> impl Iterator<Item = DefId> + '_ {
        let nonblanket = self.nonblanket_impls.entry(st).or_default().iter();
        self.blanket_impls.iter().chain(nonblanket).cloned()
    }
}

// A custom iterator used by Children::insert
enum PotentialSiblings<I, J>
where
    I: Iterator<Item = DefId>,
    J: Iterator<Item = DefId>,
{
    Unfiltered(I),
    Filtered(J),
}

impl<I, J> Iterator for PotentialSiblings<I, J>
where
    I: Iterator<Item = DefId>,
    J: Iterator<Item = DefId>,
{
    type Item = DefId;

    fn next(&mut self) -> Option<Self::Item> {
        match *self {
            PotentialSiblings::Unfiltered(ref mut iter) => iter.next(),
            PotentialSiblings::Filtered(ref mut iter) => iter.next(),
        }
    }
}

impl<'tcx> Graph {
    /// Insert a local impl into the specialization graph. If an existing impl
    /// conflicts with it (has overlap, but neither specializes the other),
    /// information about the area of overlap is returned in the `Err`.
    pub fn insert(
        &mut self,
        tcx: TyCtxt<'tcx>,
        impl_def_id: DefId,
    ) -> Result<Option<FutureCompatOverlapError>, OverlapError> {
        assert!(impl_def_id.is_local());

        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
        let trait_def_id = trait_ref.def_id;

        debug!(
            "insert({:?}): inserting TraitRef {:?} into specialization graph",
            impl_def_id, trait_ref
        );

        // If the reference itself contains an earlier error (e.g., due to a
        // resolution failure), then we just insert the impl at the top level of
        // the graph and claim that there's no overlap (in order to suppress
        // bogus errors).
        if trait_ref.references_error() {
            debug!(
                "insert: inserting dummy node for erroneous TraitRef {:?}, \
                 impl_def_id={:?}, trait_def_id={:?}",
                trait_ref, impl_def_id, trait_def_id
            );

            self.parent.insert(impl_def_id, trait_def_id);
            self.children.entry(trait_def_id).or_default().insert_blindly(tcx, impl_def_id);
            return Ok(None);
        }

        let mut parent = trait_def_id;
        let mut last_lint = None;
        let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false);

        // Descend the specialization tree, where `parent` is the current parent node.
        loop {
            use self::Inserted::*;

            let insert_result =
                self.children.entry(parent).or_default().insert(tcx, impl_def_id, simplified)?;

            match insert_result {
                BecameNewSibling(opt_lint) => {
                    last_lint = opt_lint;
                    break;
                }
                ReplaceChildren(grand_children_to_be) => {
                    // We currently have
                    //
                    //     P
                    //     |
                    //     G
                    //
                    // and we are inserting the impl N. We want to make it:
                    //
                    //     P
                    //     |
                    //     N
                    //     |
                    //     G

                    // Adjust P's list of children: remove G and then add N.
                    {
                        let siblings = self.children.get_mut(&parent).unwrap();
                        for &grand_child_to_be in &grand_children_to_be {
                            siblings.remove_existing(tcx, grand_child_to_be);
                        }
                        siblings.insert_blindly(tcx, impl_def_id);
                    }

                    // Set G's parent to N and N's parent to P.
                    for &grand_child_to_be in &grand_children_to_be {
                        self.parent.insert(grand_child_to_be, impl_def_id);
                    }
                    self.parent.insert(impl_def_id, parent);

                    // Add G as N's child.
                    for &grand_child_to_be in &grand_children_to_be {
                        self.children
                            .entry(impl_def_id)
                            .or_default()
                            .insert_blindly(tcx, grand_child_to_be);
                    }
                    break;
                }
                ShouldRecurseOn(new_parent) => {
                    parent = new_parent;
                }
            }
        }

        self.parent.insert(impl_def_id, parent);
        Ok(last_lint)
    }

    /// Insert cached metadata mapping from a child impl back to its parent.
    pub fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId) {
        if self.parent.insert(child, parent).is_some() {
            bug!(
                "When recording an impl from the crate store, information about its parent \
                 was already present."
            );
        }

        self.children.entry(parent).or_default().insert_blindly(tcx, child);
    }
}
<commit_msg>Rollup merge of #69044 - jonas-schievink:dont-run-coherence-twice, r=davidtwco<commit_after>use super::OverlapError;

use crate::traits;
use rustc::ty::fast_reject::{self, SimplifiedType};
use rustc::ty::{self, TyCtxt, TypeFoldable};
use rustc_hir::def_id::DefId;

pub use rustc::traits::types::specialization_graph::*;

#[derive(Copy, Clone, Debug)]
pub enum FutureCompatOverlapErrorKind {
    Issue33140,
    LeakCheck,
}

#[derive(Debug)]
pub struct FutureCompatOverlapError {
    pub error: OverlapError,
    pub kind: FutureCompatOverlapErrorKind,
}

/// The result of attempting to insert an impl into a group of children.
enum Inserted {
    /// The impl was inserted as a new child in this group of children.
    BecameNewSibling(Option<FutureCompatOverlapError>),

    /// The impl should replace existing impls [X1, ..], because the impl specializes X1, X2, etc.
    ReplaceChildren(Vec<DefId>),

    /// The impl is a specialization of an existing child.
    ShouldRecurseOn(DefId),
}

impl<'tcx> Children {
    /// Insert an impl into this set of children without comparing to any existing impls.
    fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
            debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
            self.nonblanket_impls.entry(st).or_default().push(impl_def_id)
        } else {
            debug!("insert_blindly: impl_def_id={:?} st=None", impl_def_id);
            self.blanket_impls.push(impl_def_id)
        }
    }

    /// Removes an impl from this set of children. Used when replacing
    /// an impl with a parent. The impl must be present in the list of
    /// children already.
    fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
        let vec: &mut Vec<DefId>;
        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
            debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
            vec = self.nonblanket_impls.get_mut(&st).unwrap();
        } else {
            debug!("remove_existing: impl_def_id={:?} st=None", impl_def_id);
            vec = &mut self.blanket_impls;
        }

        let index = vec.iter().position(|d| *d == impl_def_id).unwrap();
        vec.remove(index);
    }

    /// Attempt to insert an impl into this set of children, while comparing for
    /// specialization relationships.
    fn insert(
        &mut self,
        tcx: TyCtxt<'tcx>,
        impl_def_id: DefId,
        simplified_self: Option<SimplifiedType>,
    ) -> Result<Inserted, OverlapError> {
        let mut last_lint = None;
        let mut replace_children = Vec::new();

        debug!("insert(impl_def_id={:?}, simplified_self={:?})", impl_def_id, simplified_self,);

        let possible_siblings = match simplified_self {
            Some(st) => PotentialSiblings::Filtered(self.filtered(st)),
            None => PotentialSiblings::Unfiltered(self.iter()),
        };

        for possible_sibling in possible_siblings {
            debug!(
                "insert: impl_def_id={:?}, simplified_self={:?}, possible_sibling={:?}",
                impl_def_id, simplified_self, possible_sibling,
            );

            let create_overlap_error = |overlap: traits::coherence::OverlapResult<'_>| {
                let trait_ref = overlap.impl_header.trait_ref.unwrap();
                let self_ty = trait_ref.self_ty();

                OverlapError {
                    with_impl: possible_sibling,
                    trait_desc: trait_ref.print_only_trait_path().to_string(),
                    // Only report the `Self` type if it has at least
                    // some outer concrete shell; otherwise, it's
                    // not adding much information.
                    self_desc: if self_ty.has_concrete_skeleton() {
                        Some(self_ty.to_string())
                    } else {
                        None
                    },
                    intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
                    involves_placeholder: overlap.involves_placeholder,
                }
            };

            let report_overlap_error = |overlap: traits::coherence::OverlapResult<'_>,
                                        last_lint: &mut _| {
                // Found overlap, but no specialization; error out or report future-compat warning.

                // Do we *still* get overlap if we disable the future-incompatible modes?
                let should_err = traits::overlapping_impls(
                    tcx,
                    possible_sibling,
                    impl_def_id,
                    traits::SkipLeakCheck::default(),
                    |_| true,
                    || false,
                );

                let error = create_overlap_error(overlap);

                if should_err {
                    Err(error)
                } else {
                    *last_lint = Some(FutureCompatOverlapError {
                        error,
                        kind: FutureCompatOverlapErrorKind::LeakCheck,
                    });

                    Ok((false, false))
                }
            };

            let last_lint_mut = &mut last_lint;
            let (le, ge) = traits::overlapping_impls(
                tcx,
                possible_sibling,
                impl_def_id,
                traits::SkipLeakCheck::Yes,
                |overlap| {
                    if let Some(overlap_kind) =
                        tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
                    {
                        match overlap_kind {
                            ty::ImplOverlapKind::Permitted { marker: _ } => {}
                            ty::ImplOverlapKind::Issue33140 => {
                                *last_lint_mut = Some(FutureCompatOverlapError {
                                    error: create_overlap_error(overlap),
                                    kind: FutureCompatOverlapErrorKind::Issue33140,
                                });
                            }
                        }

                        return Ok((false, false));
                    }

                    let le = tcx.specializes((impl_def_id, possible_sibling));
                    let ge = tcx.specializes((possible_sibling, impl_def_id));

                    if le == ge {
                        report_overlap_error(overlap, last_lint_mut)
                    } else {
                        Ok((le, ge))
                    }
                },
                || Ok((false, false)),
            )?;

            if le && !ge {
                debug!(
                    "descending as child of TraitRef {:?}",
                    tcx.impl_trait_ref(possible_sibling).unwrap()
                );

                // The impl specializes `possible_sibling`.
                return Ok(Inserted::ShouldRecurseOn(possible_sibling));
            } else if ge && !le {
                debug!(
                    "placing as parent of TraitRef {:?}",
                    tcx.impl_trait_ref(possible_sibling).unwrap()
                );

                replace_children.push(possible_sibling);
            } else {
                // Either there's no overlap, or the overlap was already reported by
                // `overlap_error`.
            }
        }

        if !replace_children.is_empty() {
            return Ok(Inserted::ReplaceChildren(replace_children));
        }

        // No overlap with any potential siblings, so add as a new sibling.
        debug!("placing as new sibling");
        self.insert_blindly(tcx, impl_def_id);
        Ok(Inserted::BecameNewSibling(last_lint))
    }

    fn iter(&mut self) -> impl Iterator<Item = DefId> + '_ {
        let nonblanket = self.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter());
        self.blanket_impls.iter().chain(nonblanket).cloned()
    }

    fn filtered(&mut self, st: SimplifiedType) -> impl Iterator<Item = DefId> + '_ {
        let nonblanket = self.nonblanket_impls.entry(st).or_default().iter();
        self.blanket_impls.iter().chain(nonblanket).cloned()
    }
}

// A custom iterator used by Children::insert
enum PotentialSiblings<I, J>
where
    I: Iterator<Item = DefId>,
    J: Iterator<Item = DefId>,
{
    Unfiltered(I),
    Filtered(J),
}

impl<I, J> Iterator for PotentialSiblings<I, J>
where
    I: Iterator<Item = DefId>,
    J: Iterator<Item = DefId>,
{
    type Item = DefId;

    fn next(&mut self) -> Option<Self::Item> {
        match *self {
            PotentialSiblings::Unfiltered(ref mut iter) => iter.next(),
            PotentialSiblings::Filtered(ref mut iter) => iter.next(),
        }
    }
}

impl<'tcx> Graph {
    /// Insert a local impl into the specialization graph. If an existing impl
    /// conflicts with it (has overlap, but neither specializes the other),
    /// information about the area of overlap is returned in the `Err`.
    pub fn insert(
        &mut self,
        tcx: TyCtxt<'tcx>,
        impl_def_id: DefId,
    ) -> Result<Option<FutureCompatOverlapError>, OverlapError> {
        assert!(impl_def_id.is_local());

        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
        let trait_def_id = trait_ref.def_id;

        debug!(
            "insert({:?}): inserting TraitRef {:?} into specialization graph",
            impl_def_id, trait_ref
        );

        // If the reference itself contains an earlier error (e.g., due to a
        // resolution failure), then we just insert the impl at the top level of
        // the graph and claim that there's no overlap (in order to suppress
        // bogus errors).
        if trait_ref.references_error() {
            debug!(
                "insert: inserting dummy node for erroneous TraitRef {:?}, \
                 impl_def_id={:?}, trait_def_id={:?}",
                trait_ref, impl_def_id, trait_def_id
            );

            self.parent.insert(impl_def_id, trait_def_id);
            self.children.entry(trait_def_id).or_default().insert_blindly(tcx, impl_def_id);
            return Ok(None);
        }

        let mut parent = trait_def_id;
        let mut last_lint = None;
        let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false);

        // Descend the specialization tree, where `parent` is the current parent node.
        loop {
            use self::Inserted::*;

            let insert_result =
                self.children.entry(parent).or_default().insert(tcx, impl_def_id, simplified)?;

            match insert_result {
                BecameNewSibling(opt_lint) => {
                    last_lint = opt_lint;
                    break;
                }
                ReplaceChildren(grand_children_to_be) => {
                    // We currently have
                    //
                    //     P
                    //     |
                    //     G
                    //
                    // and we are inserting the impl N. We want to make it:
                    //
                    //     P
                    //     |
                    //     N
                    //     |
                    //     G

                    // Adjust P's list of children: remove G and then add N.
                    {
                        let siblings = self.children.get_mut(&parent).unwrap();
                        for &grand_child_to_be in &grand_children_to_be {
                            siblings.remove_existing(tcx, grand_child_to_be);
                        }
                        siblings.insert_blindly(tcx, impl_def_id);
                    }

                    // Set G's parent to N and N's parent to P.
                    for &grand_child_to_be in &grand_children_to_be {
                        self.parent.insert(grand_child_to_be, impl_def_id);
                    }
                    self.parent.insert(impl_def_id, parent);

                    // Add G as N's child.
                    for &grand_child_to_be in &grand_children_to_be {
                        self.children
                            .entry(impl_def_id)
                            .or_default()
                            .insert_blindly(tcx, grand_child_to_be);
                    }
                    break;
                }
                ShouldRecurseOn(new_parent) => {
                    parent = new_parent;
                }
            }
        }

        self.parent.insert(impl_def_id, parent);
        Ok(last_lint)
    }

    /// Insert cached metadata mapping from a child impl back to its parent.
    pub fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId) {
        if self.parent.insert(child, parent).is_some() {
            bug!(
                "When recording an impl from the crate store, information about its parent \
                 was already present."
            );
        }

        self.children.entry(parent).or_default().insert_blindly(tcx, child);
    }
}
<|endoftext|>


<commit_before>use std::os::unix::io::RawFd;

use utils::mmap;
use utils::page;
use binary::elf::program_header;

fn load_size (phdrs: &[program_header::ProgramHeader]) -> (usize, u64, u64) {
    let mut max_vaddr = 0;
    let mut min_vaddr = 0;
    for phdr in phdrs {
        if phdr.p_type != program_header::PT_LOAD {
            continue;
        }

        if phdr.p_vaddr < min_vaddr {
            min_vaddr = phdr.p_vaddr;
        }

        if phdr.p_vaddr + phdr.p_memsz > max_vaddr {
            max_vaddr = phdr.p_vaddr + phdr.p_memsz;
        }
    }

    min_vaddr = page::page_start(min_vaddr);
    max_vaddr = page::page_end(max_vaddr);
    println!("size: {:x} min_vaddr: {:x} max_vaddr: {:x}", max_vaddr - min_vaddr, min_vaddr, max_vaddr);
    return ((max_vaddr - min_vaddr) as usize, min_vaddr, max_vaddr);
}

fn reserve_address_space (phdrs: &[program_header::ProgramHeader]) -> Result <(u64, u64), String> {

    let (size, min_vaddr, max_vaddr) = load_size(&phdrs);

    let mmap_flags = mmap::MAP_PRIVATE | mmap::MAP_ANONYMOUS;
    let start = unsafe { mmap::mmap(0 as *const u64,
                                    size,
                                    mmap::PROT_NONE,
                                    mmap_flags,
                                    -1,
                                    0) };
    if start == mmap::MAP_FAILED {
        Err(format!("<dryad> Failure: anonymous mmap failed for size {:x}", size))
    } else {

        let load_bias = start - min_vaddr;
        println!("Reserved {:x} bytes @ 0x{:x} with bias {:x}", size, start, load_bias);

        Ok((start, load_bias))
    }
}

#[inline(always)]
fn pflags_to_prot (x:u32) -> isize {
    use binary::elf::program_header::{PF_X, PF_R, PF_W};

    (if x & PF_X == PF_X { mmap::PROT_EXEC } else { 0 }) |
    (if x & PF_R == PF_R { mmap::PROT_READ } else { 0 }) |
    (if x & PF_W == PF_W { mmap::PROT_WRITE } else { 0 })
}

extern {
    /// musl #defines erro *(__errno_location()) ... so errno isn't a symbol in the final binary and accesses will segfault us. yay.
    fn __errno_location() -> *const i32;
}

pub fn load (fd: RawFd, phdrs: &[program_header::ProgramHeader]) -> Result <(), String> {
    let (start, load_bias) = try!(reserve_address_space(phdrs));

    for phdr in phdrs {

        if phdr.p_type != program_header::PT_LOAD {
            continue;
        }

        let seg_start:u64 = phdr.p_vaddr + load_bias;
        let seg_end:u64   = seg_start + phdr.p_memsz;

        let seg_page_start:u64 = page::page_start(seg_start);
        let seg_page_end:u64   = page::page_start(seg_end);

        let mut seg_file_end:u64   = seg_start + phdr.p_filesz;

        // File offsets.
        let file_start:u64 = phdr.p_offset;
        let file_end:u64   = file_start + phdr.p_filesz;

        let file_page_start:u64 = page::page_start(file_start);
        let file_length:u64 = file_end - file_page_start;

        // TODO: add error checking, if file size <= 0, if file_end greater than file_size, etc.

        println!("DATA:\n\tseg_start: {:x} seg_end: {:x} seg_page_start: {:x} seg_page_end: {:x} seg_file_end: {:x}\n\tfile_start: {:x} file_end: {:x} file_page_start: {:x} file_length: {:x}", seg_start, seg_end, seg_page_start, seg_page_end, seg_file_end, file_start, file_end, file_page_start, file_length);

        if file_length != 0 {
            let mmap_flags = mmap::MAP_FIXED | mmap::MAP_PRIVATE;
            let prot_flags = pflags_to_prot(phdr.p_flags);
            unsafe {
                let start = mmap::mmap(seg_page_start as *const u64,
                                       file_length as usize,
                                       prot_flags,
                                       mmap_flags,
                                       -1,
                                       0);
                // `start` used in load bias computation
                println!("MMAP start: {:x} map_failed: {}", start, start == mmap::MAP_FAILED);

                println!("errno: {:x}", *__errno_location());
            }
        }

        seg_file_end = page::page_end(seg_file_end);
    }

    Ok(())
}
<commit_msg>fixed map failing error; stupidly forgot to use fd and file_page_start; current code is so, so unsafe tho<commit_after>use std::os::unix::io::RawFd;

use utils::mmap;
use utils::page;
use binary::elf::program_header;

fn load_size (phdrs: &[program_header::ProgramHeader]) -> (usize, u64, u64) {
    let mut max_vaddr = 0;
    let mut min_vaddr = 0;
    for phdr in phdrs {
        if phdr.p_type != program_header::PT_LOAD {
            continue;
        }

        if phdr.p_vaddr < min_vaddr {
            min_vaddr = phdr.p_vaddr;
        }

        if phdr.p_vaddr + phdr.p_memsz > max_vaddr {
            max_vaddr = phdr.p_vaddr + phdr.p_memsz;
        }
    }

    min_vaddr = page::page_start(min_vaddr);
    max_vaddr = page::page_end(max_vaddr);
    println!("size: {:x} min_vaddr: {:x} max_vaddr: {:x}", max_vaddr - min_vaddr, min_vaddr, max_vaddr);
    return ((max_vaddr - min_vaddr) as usize, min_vaddr, max_vaddr);
}

fn reserve_address_space (phdrs: &[program_header::ProgramHeader]) -> Result <(u64, u64), String> {

    let (size, min_vaddr, max_vaddr) = load_size(&phdrs);

    let mmap_flags = mmap::MAP_PRIVATE | mmap::MAP_ANONYMOUS;
    let start = unsafe { mmap::mmap(0 as *const u64,
                                    size,
                                    mmap::PROT_NONE,
                                    mmap_flags,
                                    -1,
                                    0) };
    if start == mmap::MAP_FAILED {
        Err(format!("<dryad> Failure: anonymous mmap failed for size {:x}", size))
    } else {

        let load_bias = start - min_vaddr;
        println!("Reserved {:x} bytes @ 0x{:x} with bias {:x}", size, start, load_bias);

        Ok((start, load_bias))
    }
}

#[inline(always)]
fn pflags_to_prot (x:u32) -> isize {
    use binary::elf::program_header::{PF_X, PF_R, PF_W};

    (if x & PF_X == PF_X { mmap::PROT_EXEC } else { 0 }) |
    (if x & PF_R == PF_R { mmap::PROT_READ } else { 0 }) |
    (if x & PF_W == PF_W { mmap::PROT_WRITE } else { 0 })
}

extern {
    /// musl #defines erro *(__errno_location()) ... so errno isn't a symbol in the final binary and accesses will segfault us. yay.
    fn __errno_location() -> *const i32;
}

pub fn load (fd: RawFd, phdrs: &[program_header::ProgramHeader]) -> Result <(), String> {
    let (start, load_bias) = try!(reserve_address_space(phdrs));

    //TODO: figure out what the file offset, if any, should be
    let file_offset:usize = 0;

    for phdr in phdrs {

        if phdr.p_type != program_header::PT_LOAD {
            continue;
        }

        let seg_start:u64 = phdr.p_vaddr + load_bias;
        let seg_end:u64   = seg_start + phdr.p_memsz;

        let seg_page_start:u64 = page::page_start(seg_start);
        let seg_page_end:u64   = page::page_start(seg_end);

        let mut seg_file_end:u64   = seg_start + phdr.p_filesz;

        // File offsets.
        let file_start:u64 = phdr.p_offset;
        let file_end:u64   = file_start + phdr.p_filesz;

        let file_page_start = page::page_start(file_start);
        let file_length:u64 = file_end - file_page_start;

        // TODO: add error checking, if file size <= 0, if file_end greater than file_size, etc.

        println!("DATA:\n\tseg_start: {:x} seg_end: {:x} seg_page_start: {:x} seg_page_end: {:x} seg_file_end: {:x}\n\tfile_start: {:x} file_end: {:x} file_page_start: {:x} file_length: {:x}", seg_start, seg_end, seg_page_start, seg_page_end, seg_file_end, file_start, file_end, file_page_start, file_length);

        if file_length != 0 {
            let mmap_flags = mmap::MAP_FIXED | mmap::MAP_PRIVATE;
            let prot_flags = pflags_to_prot(phdr.p_flags);
            unsafe {
                let start = mmap::mmap(seg_page_start as *const u64,
                                       file_length as usize,
                                       prot_flags,
                                       mmap_flags,
                                       fd as isize,
                                       file_offset + file_page_start as usize);
                // `start` used in load bias computation
                println!("MMAP start: {:x} map_failed: {}", start, start == mmap::MAP_FAILED);

                println!("errno: {:x}", *__errno_location());
            }
        }

        seg_file_end = page::page_end(seg_file_end);
    }

    Ok(())
}
<|endoftext|>


<commit_before>pub trait BitRead {
    fn get_bit1(&mut self) -> bool;
/*
    fn peek_bit1(size : u8) -> bool;

    fn get_bits32(size : u8) -> u32;

    fn get_bits64(size : u8) -> u64;

    fn peek_bits32(size : u8) -> u32;

    fn peek_bits64(size : u8) -> u64;

    fn skip_bits(size : u8) -> ();
*/
}

pub struct LittleEndian <'a> {
    buffer : &'a[u8],
    index : usize,
    cache : u64,
    left : usize,
}

impl <'a> BitRead for LittleEndian<'a> {
    fn get_bit1(&mut self) -> bool {
        let val = (self.cache & 1) == 1;
        self.cache = self.cache >> 1;
        return val;
    }
}

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

#[test]
    fn get_bit1() {
        let mut reader = LittleEndian {
            buffer : &b""[..],
            index : 0,
            cache: 0b10,
            left: 2
        };

        assert!(!reader.get_bit1());
        assert!(reader.get_bit1());
    }

}
<commit_msg>bitread: Change the struct name<commit_after>pub trait BitRead {
    fn get_bit1(&mut self) -> bool;
/*
    fn peek_bit1(size : u8) -> bool;

    fn get_bits32(size : u8) -> u32;

    fn get_bits64(size : u8) -> u64;

    fn peek_bits32(size : u8) -> u32;

    fn peek_bits64(size : u8) -> u64;

    fn skip_bits(size : u8) -> ();
*/
}

pub struct BitReadLE <'a> {
    buffer : &'a[u8],
    index : usize,
    cache : u64,
    left : usize,
}

impl <'a> BitRead for BitReadLE<'a> {
    fn get_bit1(&mut self) -> bool {
        let val = (self.cache & 1) == 1;
        self.cache = self.cache >> 1;
        return val;
    }
}

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

#[test]
    fn get_bit1() {
        let mut reader = BitReadLE {
            buffer : &b""[..],
            index : 0,
            cache: 0b10,
            left: 2
        };

        assert!(!reader.get_bit1());
        assert!(reader.get_bit1());
    }

}
<|endoftext|>


<commit_before>//! `Ports` are the IO channels for a `Node`
//!
//! They can be used as a `Source` and `Destination` for certain `Instruction`s.

/// A `Port` can be read from and write to
#[derive(Debug,PartialEq,Eq)]
pub struct Port {
    input: Vec<i32>,
    output: Vec<i32>,
}

/// The result of reading from a `Port`
#[derive(Debug)]
pub enum PortReadResult {
    /// Success
    Success(Port, i32),
    /// Failure
    Failure
}

impl Port {
    /// Create a port with a number of readable values
    pub fn new(input: Vec<i32>) -> Port {
        Port { input: input, output: vec![] }
    }

    fn with(input: Vec<i32>, output: Vec<i32>) -> Port {
        Port { input: input, output: output }
    }

    /// Read from this `Port`. Will return a `PortReadResult::Success` when a
    /// value is available, otherwise a `PortReadResult::Failure`
    pub fn read(&self) -> PortReadResult {
        if self.input.len() > 0 {
            let mut result_input = vec![];
            for index in 1..self.input.len() {
                result_input.push(self.input[index]);
            }
            PortReadResult::Success(Port::with(result_input, vec![]), self.input[0])
        } else {
            PortReadResult::Failure
        }
    }
}

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

    #[test]
    fn read_from_a_port_should_work_correctly() {
        let port: Port = Port::new(vec![0, 1, 2]);

        match port.read() {
            PortReadResult::Success(next_port, value) => {
                assert_eq!(0, value);
                assert_eq!(Port::with(vec![1,2], vec![]), next_port);
            },
            PortReadResult::Failure => panic!(),

        }
    }
}
<commit_msg>Write to a Port<commit_after>//! `Ports` are the IO channels for a `Node`
//!
//! They can be used as a `Source` and `Destination` for certain `Instruction`s.

/// A `Port` can be read from and write to
#[derive(Debug,PartialEq,Eq)]
pub struct Port {
    input: Vec<i32>,
    output: Vec<i32>,
}

/// The result of reading from a `Port`
#[derive(Debug)]
pub enum PortReadResult {
    /// Success
    Success(Port, i32),
    /// Failure
    Failure
}

impl Port {
    /// Create a port with a number of readable values
    pub fn new(input: Vec<i32>) -> Port {
        Port { input: input, output: vec![] }
    }

    fn with(input: Vec<i32>, output: Vec<i32>) -> Port {
        Port { input: input, output: output }
    }

    /// Read from this `Port`. Will return a `PortReadResult::Success` when a
    /// value is available, otherwise a `PortReadResult::Failure`
    pub fn read(&self) -> PortReadResult {
        if self.input.len() > 0 {
            let mut result_input = vec![];
            for index in 1..self.input.len() {
                result_input.push(self.input[index]);
            }
            PortReadResult::Success(Port::with(result_input, vec![]), self.input[0])
        } else {
            PortReadResult::Failure
        }
    }

    /// Write to this `Port`. Will always succeed and return the Port as it is
    /// changed by the write
    pub fn write(&self, value: i32) -> Port {
        let mut result_input = vec![];
        for index in 0..self.input.len() {
            result_input.push(self.input[index]);
        }
        let mut result_output = vec![];
        for index in 0..self.output.len() {
            result_output.push(self.output[index]);
        }
        result_output.push(value);
        Port::with(result_input, result_output)
    }
}

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

    #[test]
    fn read_from_a_port_should_work_correctly() {
        let port: Port = Port::new(vec![0, 1, 2]);

        match port.read() {
            PortReadResult::Success(next_port, value) => {
                assert_eq!(0, value);
                assert_eq!(Port::with(vec![1,2], vec![]), next_port);
            },
            PortReadResult::Failure => panic!(),

        }
    }

    #[test]
    fn write_to_a_port_should_work_correctly() {
        let port: Port = Port::with(vec![1, 2], vec![3]);

        let next_port = port.write(4);

        assert_eq!(Port::with(vec![1, 2], vec![3, 4]), next_port);
    }
}
<|endoftext|>


<commit_before>extern mod std;
use std::rand;
use std::rand::{Rand,Rng};
use std::ops;
use std::num::{pow,sqrt};

#[deriving(Clone,Eq)]
pub struct Point {
    x : f64,
    y : f64,
    z : f64
}

impl Point {
    pub fn new() -> Point {
        Point{x: 0.0, y: 0.0, z: 0.0}
    }

    pub fn new_dir() -> Point {
        let mut pt : Point =rand::random();
        pt=pt-0.5f64;
        pt/pt.norm2()
    }

    pub fn norm2(&self) -> f64 {
        sqrt(pow(self.x,2.0)+pow(self.y,2.0)+pow(self.z,2.0))
    }

    pub fn dist(&self, other : &Point) -> f64 {
        (*self-*other).norm2()
    }

}

impl ToStr for Point {
    fn to_str(&self) -> ~str {
        format!("({:f}, {:f}, {:f})", self.x, self.y, self.z)
    }
}

//
// * Génération aléatoire
//
impl Rand for Point {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Point {
        Point { x: rng.gen::<f64>(), y: rng.gen::<f64>(), z: rng.gen::<f64>()}
    }
}

//
// * Opérateurs arithmétiques
//
// Addition
trait RhsOfAdd<Result> {
  fn add_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfAdd<Point> for Point {
  fn add_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (self.x+lhs.x), y:(self.y+lhs.y), z:(self.z+lhs.z)}
   }
}
impl RhsOfAdd<Point> for f64 {
  fn add_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (*self+lhs.x), y:(*self+lhs.y), z:(*self+lhs.z)}
   }
}
impl<Result, Rhs: RhsOfAdd<Result> > ops::Add<Rhs, Result> for Point {
  fn add(&self, rhs: &Rhs) -> Result {
    rhs.add_lhs_to(self)
  }
}
// Soustraction
trait RhsOfSub<Result> {
  fn sub_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfSub<Point> for Point {
  fn sub_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (-self.x+lhs.x), y:(-self.y+lhs.y), z:(-self.z+lhs.z)}
   }
}
impl RhsOfSub<Point> for f64 {
    fn sub_lhs_to(&self, lhs:&Point) -> Point {
        Point{x: lhs.x - *self, y: lhs.y-*self, z: lhs.z-*self}
    }
}
impl<Result, Rhs: RhsOfSub<Result> > ops::Sub<Rhs, Result> for Point {
  fn sub(&self, rhs: &Rhs) -> Result {
    rhs.sub_lhs_to(self)
  }
}
// Multiplication
trait RhsOfMul<Result> {
  fn mul_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfMul<Point> for Point {
  fn mul_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (self.x*lhs.x), y:(self.y*lhs.y), z:(self.z*lhs.z)}
   }
}
impl RhsOfMul<Point> for f64 {
  fn mul_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (self*lhs.x), y:(self*lhs.y), z:(self*lhs.z)}
   }
}

impl<Result, Rhs: RhsOfMul<Result> > ops::Mul<Rhs, Result> for Point {
  fn mul(&self, rhs: &Rhs) -> Result {
    rhs.mul_lhs_to(self)
  }
}
// Division
trait RhsOfDiv<Result> {
  fn div_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfDiv<Point> for Point {
  fn div_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (lhs.x/self.x), y:(lhs.y/self.y), z:(lhs.z/self.z)}
   }
}
impl RhsOfDiv<Point> for f64 {
  fn div_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (lhs.x/ *self), y:(lhs.y/ *self), z:(lhs.z/ *self)}
   }
}
impl<Result, Rhs: RhsOfDiv<Result> > ops::Div<Rhs, Result> for Point {
  fn div(&self, rhs: &Rhs) -> Result {
    rhs.div_lhs_to(self)
  }
}

//
// * Test
//
#[test]
fn test_norm2() {
    let pt1=Rc<Point>(Point{ x: 1.0, y: 2.0, z: 1.0});
    let norm=pt1.norm2();

    assert!(norm==sqrt(6.0));
}

#[test]
fn test_dist() {
    let pt1=Rc<Point>(Point{ x: 1.0, y: 2.0, z: 0.0});
    let pt2=Rc<Point>(Point{ x: 2.0, y: 3.0, z: 1.0});
    let distance=pt1.dist(pt2);

    assert!(distance==sqrt(3.0));
}

#[test]
fn test_add() {
    let pt1=Rc<Point>(Point{ x: 1.0, y: 2.0, z: 1.0});
    let pt2=Rc<Point>(Point{ x: -1.0, y: 3.0, z: 0.0});
    let pt3=*pt1+*pt2;

    assert!((pt3.x==0.0)&&(pt3.y==5.0)&&(pt3.z==1.0));
}

#[test]
fn test_add_float() {
    let pt1=Point{ x: 1.0, y: 2.0, z: -1.0};
    let pt3=pt1+1.0f64;

    assert!((pt3.x==2.0)&&(pt3.y==3.0)&&(pt3.z==0.0));
}

#[test]
fn test_sub() {
    let pt1=Rc<Point>(Point{ x: 1.0, y: 2.0, z: 0.0});
    let pt2=Rc<Point>(Point{ x: -1.0, y: 3.0, z: -1.0});
    let pt3=*pt1-*pt2;
    assert!((pt3.x==2.0)&&(pt3.y==-1.0)&&(pt3.z==1.0));
}
fn test_sub_float() {
    let pt1=Point{ x: 1.0, y: 2.0,z: 0.0};
    let pt3=pt1-0.5 as f64;
    assert!((pt3.x==0.5)&&(pt3.y==1.5)&&(pt3.z==-0.5));
}

#[test]
fn test_mult() {
    let pt1=Rc<Point>(Point{ x: 1.0, y: 2.0, z: 1.0});
    let pt2=Rc<Point>(Point{ x: -1.0, y: 3.0, z: 0.0});
    let pt3=(*pt1)*(*pt2);
    assert!((pt3.x==-1.0)&&(pt3.y==6.0)&&(pt3.z==0.0));
    let pt4=(*pt1)*(2.0 as f64);
    assert!((pt4.x==2.0)&&(pt4.y==4.0)&&(pt4.z==2.0));
}

#[test]
fn test_div() {
    let pt1=Rc<Point>(Point{ x: 1.0, y: 2.0, z: 2.0});
    let pt2=Rc<Point>(Point{ x: -1.0, y: 3.0, z: -2.0});
    let pt3=(*pt1)/(*pt2);
    assert!(pt3.dist(&Point{x:-1.0, y:2.0/3.0, z: -1.0})==0.0);
    let pt4=(*pt1)/(2.0 as f64);
    assert!((pt4.x==0.5)&&(pt4.y==1.0)&&(pt4.z==1.0));
}

#[test]
fn test_new_dir() {
    let pt = Point::new_dir();
    assert!((pt.norm2()-1.0).abs()<=1e-15f64);
}

#[test]
fn test_rand() {
    let pt1 : Point = rand::random();
    let pt2 : Point = rand::random();
    let pt3 : Point = rand::random();

    assert!(pt1 != pt2); assert!(pt1 != pt3); assert!(pt2 != pt3);
    assert!((pt1.x>=0.0)&&(pt1.y<=1.0)&&(pt1.z<=1.0));
}
<commit_msg>Update tests<commit_after>extern mod std;
use std::rand;
use std::rand::{Rand,Rng};
use std::ops;
use std::num::{pow,sqrt};
use std::gc::Gc;

#[deriving(Clone,Eq)]
pub struct Point {
    x : f64,
    y : f64,
    z : f64
}

impl Point {
    pub fn new() -> Point {
        Point{x: 0.0, y: 0.0, z: 0.0}
    }

    pub fn new_dir() -> Point {
        let mut pt : Point =rand::random();
        pt=pt-0.5f64;
        pt/pt.norm2()
    }

    pub fn norm2(&self) -> f64 {
        sqrt(pow(self.x,2.0)+pow(self.y,2.0)+pow(self.z,2.0))
    }

    pub fn dist(&self, other : &Point) -> f64 {
        (*self-*other).norm2()
    }

}

impl ToStr for Point {
    fn to_str(&self) -> ~str {
        format!("({:f}, {:f}, {:f})", self.x, self.y, self.z)
    }
}

//
// * Génération aléatoire
//
impl Rand for Point {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Point {
        Point { x: rng.gen::<f64>(), y: rng.gen::<f64>(), z: rng.gen::<f64>()}
    }
}

//
// * Opérateurs arithmétiques
//
// Addition
trait RhsOfAdd<Result> {
  fn add_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfAdd<Point> for Point {
  fn add_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (self.x+lhs.x), y:(self.y+lhs.y), z:(self.z+lhs.z)}
   }
}
impl RhsOfAdd<Point> for f64 {
  fn add_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (*self+lhs.x), y:(*self+lhs.y), z:(*self+lhs.z)}
   }
}
impl<Result, Rhs: RhsOfAdd<Result> > ops::Add<Rhs, Result> for Point {
  fn add(&self, rhs: &Rhs) -> Result {
    rhs.add_lhs_to(self)
  }
}
// Soustraction
trait RhsOfSub<Result> {
  fn sub_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfSub<Point> for Point {
  fn sub_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (-self.x+lhs.x), y:(-self.y+lhs.y), z:(-self.z+lhs.z)}
   }
}
impl RhsOfSub<Point> for f64 {
    fn sub_lhs_to(&self, lhs:&Point) -> Point {
        Point{x: lhs.x - *self, y: lhs.y-*self, z: lhs.z-*self}
    }
}
impl<Result, Rhs: RhsOfSub<Result> > ops::Sub<Rhs, Result> for Point {
  fn sub(&self, rhs: &Rhs) -> Result {
    rhs.sub_lhs_to(self)
  }
}
// Multiplication
trait RhsOfMul<Result> {
  fn mul_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfMul<Point> for Point {
  fn mul_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (self.x*lhs.x), y:(self.y*lhs.y), z:(self.z*lhs.z)}
   }
}
impl RhsOfMul<Point> for f64 {
  fn mul_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (self*lhs.x), y:(self*lhs.y), z:(self*lhs.z)}
   }
}

impl<Result, Rhs: RhsOfMul<Result> > ops::Mul<Rhs, Result> for Point {
  fn mul(&self, rhs: &Rhs) -> Result {
    rhs.mul_lhs_to(self)
  }
}
// Division
trait RhsOfDiv<Result> {
  fn div_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfDiv<Point> for Point {
  fn div_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (lhs.x/self.x), y:(lhs.y/self.y), z:(lhs.z/self.z)}
   }
}
impl RhsOfDiv<Point> for f64 {
  fn div_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (lhs.x/ *self), y:(lhs.y/ *self), z:(lhs.z/ *self)}
   }
}
impl<Result, Rhs: RhsOfDiv<Result> > ops::Div<Rhs, Result> for Point {
  fn div(&self, rhs: &Rhs) -> Result {
    rhs.div_lhs_to(self)
  }
}

//
// * Test
//
#[test]
fn test_norm2() {
    let pt1=Point{ x: 1.0, y: 2.0, z: 1.0};
    let norm=pt1.norm2();

    assert!(norm==sqrt(6.0));
}

#[test]
fn test_dist() {
    let pt1=Point{ x: 1.0, y: 2.0, z: 0.0};
    let pt2=Point{ x: 2.0, y: 3.0, z: 1.0};
    let distance=pt1.dist(&pt2);

    assert!(distance==sqrt(3.0));
}

#[test]
fn test_add() {
    let pt1=Point{ x: 1.0, y: 2.0, z: 1.0};
    let pt2=Point{ x: -1.0, y: 3.0, z: 0.0};
    let pt3=pt1+pt2;

    assert!((pt3.x==0.0)&&(pt3.y==5.0)&&(pt3.z==1.0));
}

#[test]
fn test_add_float() {
    let pt1=Point{ x: 1.0, y: 2.0, z: -1.0};
    let pt3=pt1+1.0f64;

    assert!((pt3.x==2.0)&&(pt3.y==3.0)&&(pt3.z==0.0));
}

#[test]
fn test_sub() {
    let pt1=Point{ x: 1.0, y: 2.0, z: 0.0};
    let pt2=Point{ x: -1.0, y: 3.0, z: -1.0};
    let pt3=pt1-pt2;
    assert!((pt3.x==2.0)&&(pt3.y==-1.0)&&(pt3.z==1.0));
}
fn test_sub_float() {
    let pt1=Point{ x: 1.0, y: 2.0,z: 0.0};
    let pt3=pt1-0.5 as f64;
    assert!((pt3.x==0.5)&&(pt3.y==1.5)&&(pt3.z==-0.5));
}

#[test]
fn test_mult() {
    let pt1=Point{ x: 1.0, y: 2.0, z: 1.0};
    let pt2=Point{ x: -1.0, y: 3.0, z: 0.0};
    let pt3=(pt1)*(pt2);
    assert!((pt3.x==-1.0)&&(pt3.y==6.0)&&(pt3.z==0.0));
    let pt4=(pt1)*2.0;
    assert!((pt4.x==2.0)&&(pt4.y==4.0)&&(pt4.z==2.0));
}

#[test]
fn test_div() {
    let pt1=Point{ x: 1.0, y: 2.0, z: 2.0};
    let pt2=Point{ x: -1.0, y: 3.0, z: -2.0};
    let pt3=pt1/pt2;
    assert!(pt3.dist(&Point{x:-1.0, y:2.0/3.0, z: -1.0})==0.0);
    let pt4=pt1/2.0;
    assert!((pt4.x==0.5)&&(pt4.y==1.0)&&(pt4.z==1.0));
}

#[test]
fn test_new_dir() {
    let pt = Point::new_dir();
    assert!((pt.norm2()-1.0).abs()<=1e-15f64);
}

#[test]
fn test_rand() {
    let pt1 : Point = rand::random();
    let pt2 : Point = rand::random();
    let pt3 : Point = rand::random();

    assert!(pt1 != pt2); assert!(pt1 != pt3); assert!(pt2 != pt3);
    assert!((pt1.x>=0.0)&&(pt1.y<=1.0)&&(pt1.z<=1.0));
}
<|endoftext|>