<commit_before>extern crate futures;
extern crate tokio_core;

use tokio_core::reactor::Interval;
use tokio_core::reactor::Handle;
use futures::stream::{Stream};

use std::time::{Instant, Duration};
use futures::Future;
use futures::IntoFuture;
use futures::Then;
use futures::Map;
use futures::Async;
use futures::future::Ok;
use futures::Poll;
use std::thread;
use std::cell::Cell;

use tokio_core::reactor::{Core, Timeout};

struct Error {
    code: i32
}

impl Error {
    fn new(c: i32) -> Error {
        Error { code: c }
    }
}

// A future as return type of getAsynch() method below.
//struct After {
//    d: Duration,
//    s: State
//}
//
//impl Future for After {
//    type Item = State;
//    type Error = Error;
//
//    fn poll(&mut self) -> Poll<State, Error> {
//        Ok(Async::Ready(self.s))
//    }
//}

enum Cmd<S: Clone> {
    Start(S),
    //    Immediately(Duration, S),
    After(Duration, S)
}

// A struct that holds some state and a handle on
// which to run its worker function.
struct Actor<S: Clone> {
    dur: Duration,
    state: S,
    //fu: fn(S) -> Future<Item = S, Error = Error>,
    fu: fn(S) -> Cmd<S>,
}

impl<S: 'static + Clone> Actor<S> {
    // Create a new S and schedule its worker function
    //    fn new(handle: Handle, start: S, f: fn(S) -> Future<Item = S, Error = Error>) -> Actor<S> {
    fn new(handle: Handle, start: S, f: fn(S) -> Cmd<S>) -> Actor<S> {
        let d = Duration::from_millis(5000);
        let a: Actor<S> = Actor { dur: d, state: start.clone(), fu: f };
        let cmd = Cmd::Start(start.clone());
        Actor::nextf2(handle, cmd, f);
        //handle.spawn(fut);
        a
    }

    fn nextf2(handle: Handle, cmd: Cmd<S>, f: fn(S) -> Cmd<S>) {
        let futu = match cmd {
            Cmd::Start(s) => {
                let timeout = Timeout::new(Duration::from_millis(5000), &handle).unwrap();
                let x = handle.clone();
                let s2 = s.clone();
                let f2 = f.clone();
                let futu = timeout.then(move |r| {
                    println!("Worker says start");
                    match r {
                        Ok(_) => {
                            let cmd2 = f2(s2);
                            Actor::nextf2(x, cmd2, f);
                            futures::future::ok::<(), ()>(())
                        },
                        Err(_) => futures::future::ok::<(), ()>(()),
                    }
                });
                handle.spawn(futu);
            },
            Cmd::After(d, s) => {
                let timeout = Timeout::new(d, &handle).unwrap();
                let x = handle.clone();
                let s2 = s.clone();
                let f2 = f.clone();
                let futu = timeout.then(move |r| {
                    println!("Worker says after");
                    match r {
                        Ok(_) => {
                            let cmd2 = f2(s2);
                            Actor::nextf2(x, cmd2, f);
                            futures::future::ok::<(), ()>(())
                        },
                        Err(_) => futures::future::ok::<(), ()>(()),
                    }
                });
                handle.spawn(futu);
            },
            //            Cmd::Run(rf) => {
            //                let timeout = Timeout::new(d, &handle).unwrap();
            //                let x = handle.clone();
            //
            //                let s2 = s.clone();
            //                let f2 = f.clone();
            //                let futu = rf.then(move |r| {
            //                    println!("Worker says run");
            //                    match r {
            //                        Ok(_) => {
            //                            let cmd2 = f2(s2);
            //                            Actor::nextf2(x, cmd2, f);
            //                            futures::future::ok::<(), ()>(())
            //                        },
            //                        Err(_) => futures::future::ok::<(), ()>(()),
            //                    }
            //                });
            //                handle.spawn(futu);
            //            }
        };
    }

    // Will later on be used to access state from other threads in a reactive way.
    //    fn getAsync(&self) -> MyFuture {
    //        MyFuture { v: self.state }
    //    }
}

#[derive(Copy, Clone)]
enum State {
    Start(i32),
    Foo,
    End
}

//fn testGetFromUpstream<R, F>(handle: &Handle, d: Duration, v: R) -> Map<Timeout, F>
//    where R: Clone, F: FnOnce(()) -> R,
//{
//    let timeout = Timeout::new(d, handle).unwrap();
//    let futu = timeout.map(|r| { v });
//    futu
//}

fn testSimulateRemoteGetValue<R, F>(handle: &Handle, d: Duration, f: F) -> Map<Timeout, F>
    where R: Clone, F: FnOnce(()) -> R,
{
    let timeout = Timeout::new(d, handle).unwrap();
    let fut: Map<Timeout, F> = timeout.map(f);
    fut
}

//fn map<F, U>( self , f: F) -> Map < Self, F>
//where F: FnOnce( Self::Item) -> U,
//Self: Sized,
//{
//assert_future::< U, Self::Error, _> (map::new( self, f))
//}

//type FOO = fn(()) -> i32;
//
//fn testGetFromUpstream(handle: &Handle, d: Duration, v: i32) -> Map<Timeout, fn(()) -> i32> {
//    let timeout = Timeout::new(d, handle).unwrap();
//    let c: fn(()) -> i32 = |r| { v };
//    timeout.map(c)
//}

fn main() {
    // A thread on which background workers will be run.
    let worker_thread = thread::spawn(move || {
        let mut core = Core::new().unwrap();

        //        fn add_10<F>(f: F) -> Map<F, fn(i32) -> i32>
        //            where F: Future<Item = i32>,
        //        {
        //            fn do_map(i: i32) -> i32 { i + 10 }
        //            f.map(do_map)
        //        }
        //
        //        fn doIt<S>(s:S) -> Map<F, fn(i32) -> i32>
        //            where F: Future<Item = S>,
        //        {
        //
        //        }

        //        fn update(state: State) -> Future<Item = State, Error = Error> {
        fn update(state: State) -> Cmd<State> {
            match state {
                State::Start(s) => {
                    println!("start");
                    Cmd::After(Duration::new(1, 0), State::Foo)
                },
                //                State::Foo => {
                //                    println!("foo");
                //                    Cmd::Run(|| {
                //
                //                    })
                //                },
                State::End => {
                    println!("end");
                    Cmd::After(Duration::new(1, 0), State::End)
                },
            }
        }

        // Create a background worker
        let a: Actor<State> = Actor::new(core.handle(), State::Start(10), update);

        // An interval stream to drive the background worker futures.
        let interval_stream = Interval::new(Duration::new(1, 0), &(core.handle())).unwrap();
        let stream_future = interval_stream.for_each(|_| {
            println!("Worker driver says hello");
            Ok(())
        });

        core.run(stream_future).unwrap();
    });

    // Request handler threads to be started here (e.g. HTTP server)
    // These threads will eventually use the state the workers work on.

    worker_thread.join().unwrap();
}
<commit_msg>First working version of reschedule (using boxes)<commit_after>extern crate futures;
extern crate tokio_core;

use tokio_core::reactor::Interval;
use tokio_core::reactor::Handle;
use futures::stream::{Stream};

use std::time::{Instant, Duration};
use futures::Future;
use futures::IntoFuture;
use futures::Then;
use futures::Map;
use std::result::Result;
use std::io;
use futures::Async;
use futures::future::Ok;
use futures::Poll;
use std::thread;
use std::cell::Cell;
use std::boxed::Box;
//use std::boxed::FnBox;

use tokio_core::reactor::{Core, Timeout};

#[derive(Debug)]
struct Error {
    code: i32
}

impl Error {
    fn new(c: i32) -> Error {
        Error { code: c }
    }
}

//struct MyFuture<S: Clone> {
//    v: S
//}
//
//impl<S: Clone> Future for MyFuture<S>
//{
//    type Item = S;
//    type Error = Error;
//
//    fn poll(&mut self) -> Poll<S, Error> {
//        //self.get().poll()
//        Ok(Async::Ready(self.v.clone()))
//    }
//}

//impl<S: Clone> IntoFuture for MyFuture<S> {
//    type Future = MyFuture<S>;
//    type Item = S;
//    type Error = Error;
//
//    fn into_future(self) -> MyFuture<S> {
//        self
//    }
//}

//impl<F, R> Future for Lazy<F, R>
//where F: FnOnce() -> R,
//R: IntoFuture,

enum Cmd<S: Clone> {
    Start(S),
    //    Run(Box<FnBox(Handle) -> MyFuture<S>>),
    //Run(Box<FnOnce(Handle) -> MyFuture<S>>),
    Run(fn(handle: Handle) -> Box<Future<Item = S, Error = ()>>),
    After(Duration, S)
}

// A struct that holds some state and a handle on
// which to run its worker function.
#[derive(Debug)]
struct Actor<S: Clone> {
    //dur: Duration,
    state: S,
    //fu: fn(S) -> Cmd<S>,
}

impl<S: 'static + Clone> Actor<S> {
    fn new(handle: Handle, start_state: S, guts: fn(S) -> Cmd<S>) -> Actor<S> {
        //        let d = Duration::from_millis(5000);
        //        let a: Actor<S> = Actor { dur: d, state: start.clone(), fu: f };
        let a: Actor<S> = Actor { state: start_state.clone() };
        let cmd = Cmd::Start(start_state.clone());
        Actor::run_guts(handle, cmd, guts);
        a
    }

    fn run_guts(handle: Handle, cmd: Cmd<S>, guts: fn(S) -> Cmd<S>) {
        let futu = match cmd {
            Cmd::Start(state) => {
                let timeout = Timeout::new(Duration::from_millis(5000), &handle).unwrap();
                let handle_copy = handle.clone();
                let state_copy = state.clone();
                let guts_copy = guts.clone();
                let fut = timeout.then(move |r| {
                    println!("******************************** START **********");
                    let next_cmd = guts_copy(state_copy);
                    Actor::run_guts(handle_copy, next_cmd, guts_copy);
                    // TODO match on r
                    futures::future::ok::<(), ()>(())
                });
                handle.spawn(fut);
            },
            Cmd::After(d, state) => {
                let timeout = Timeout::new(d, &handle).unwrap();
                let handle_copy = handle.clone();
                let state_copy = state.clone();
                let guts_copy = guts.clone();
                let fut = timeout.then(move |r| {
                    println!("******************************** AFTER **********");
                    let next_cmd = guts_copy(state_copy);
                    Actor::run_guts(handle_copy, next_cmd, guts_copy);
                    // TODO match on r
                    futures::future::ok::<(), ()>(())
                });
                handle.spawn(fut);
            },
            Cmd::Run(work_future) => {
                let handle_copy = handle.clone();
                let handle_copy2 = handle.clone();
                //                let state_copy = state.clone();
                let guts_copy = guts.clone();
                let fut0: Box<Future<Item = S, Error = ()>> = work_future(handle_copy);
                let fut = fut0.then(move |x: Result<S, ()>| {
                    let new_state = x.unwrap();
                    println!("******************************** RUN **********");
                    let next_cmd = guts_copy(new_state);
                    Actor::run_guts(handle_copy2, next_cmd, guts_copy);
                    // TODO match on r
                    futures::future::ok::<(), ()>(())
                });
                handle.spawn(fut);
            }
        };
    }

    // Will later on be used to access state from other threads in a reactive way.
    //    fn getAsync(&self) -> MyFuture {
    //        MyFuture { v: self.state }
    //    }
}

#[derive(Copy, Clone)]
enum State {
    Start(i32),
    Foo(i32),
    End
}

fn main() {
    // A thread on which background workers will be run.
    let worker_thread = thread::spawn(move || {
        let mut core = Core::new().unwrap();

        //        let z = testSimulateRemoteGetValue(&(core.handle()), |()| { State::End }).then(|_| {
        //            println!("XXXXXXXXXXXXX");
        //            futures::future::ok::<(), ()>(())
        //        });
        //        core.handle().spawn(z);

        fn doFoo(handle: Handle) -> Box<Future<Item = State, Error = ()>> {
            println!("Starting dofoo >>>> =======================================");
            let f = testSimulateRemoteGetValue(&handle, |()| { State::End });
            //Box::new(f.map(|x| { State::End }).map_err(|e| { () }))
            Box::new(f.map(|x| {
                println!("completed dofoo <<<< =======================================");
                State::End
            }).map_err(|e| { () }))
        }

        fn update(state: State) -> Cmd<State> {
            match state {
                State::Start(s) => {
                    println!("start - foo in 1 sec");
                    Cmd::After(Duration::new(1, 0), State::Foo(20))
                },
                State::Foo(s) => {
                    println!("foo - run doFoo now");
                    Cmd::Run(doFoo)
                },
                State::End => {
                    println!("end - end, run end egain in 1 sec");
                    Cmd::After(Duration::new(1, 0), State::End)
                },
            }
        }

        // Create a background worker
        let a: Actor<State> = Actor::new(core.handle(), State::Start(10), update);

        // An interval stream to drive the background worker futures.
        let interval_stream = Interval::new(Duration::new(1, 0), &(core.handle())).unwrap();
        let stream_future = interval_stream.for_each(|_| {
            println!("Worker driver says hello");
            Ok(())
        });

        core.run(stream_future).unwrap();
    });

    // Request handler threads to be started here (e.g. HTTP server)
    // These threads will eventually use the state the workers work on.

    worker_thread.join().unwrap();
}

fn testSimulateRemoteGetValue<R, F>(handle: &Handle, f: F) -> Map<Timeout, F>
    where R: Clone, F: FnOnce(()) -> R,
{
    let timeout = Timeout::new(Duration::from_millis(5000), handle).unwrap();
    let fut: Map<Timeout, F> = timeout.map(f);
    fut
}<|endoftext|>


<commit_before>extern crate uosql;

use uosql::storage::*;

fn main() {

    //let db = Database::create("storage_team").unwrap();
    let db = Database::load("storage_team").unwrap();

    let mut cols = Vec::new();
    cols.push(Column { name: "Heiner".into(), data_type: DataType::Integer });
    cols.push(Column { name: "Mathias".into(), data_type: DataType::Float });
    cols.push(Column { name: "Dennis".into(), data_type: DataType::Float });
    cols.push(Column { name: "Jana".into(), data_type: DataType::Integer });

    let _storage_team = db.create_table("storage_team", cols, 1).unwrap();

    let t = db.load_table("storage_team").unwrap();

    let mut engine = t.create_engine();
    let _e  = engine.create_table();
    let t = engine.get_table();
}
<commit_msg>Remove line with unimplemented function<commit_after>extern crate uosql;

use uosql::storage::*;

fn main() {

    //let db = Database::create("storage_team").unwrap();
    let db = Database::load("storage_team").unwrap();

    let mut cols = Vec::new();
    cols.push(Column { name: "Heiner".into(), data_type: DataType::Integer });
    cols.push(Column { name: "Mathias".into(), data_type: DataType::Float });
    cols.push(Column { name: "Dennis".into(), data_type: DataType::Float });
    cols.push(Column { name: "Jana".into(), data_type: DataType::Integer });

    let _storage_team = db.create_table("storage_team", cols, 1).unwrap();

    let t = db.load_table("storage_team").unwrap();

    let mut engine = t.create_engine();
    let _e  = engine.create_table();
}
<|endoftext|>


<commit_before>use std::io;

pub struct State(imp::State);

impl State {
    /// Captures the current state of all CPUs on the system.
    ///
    /// The `State` returned here isn't too meaningful in terms of
    /// interpretation across platforms, but it can be compared to previous
    /// states to get a meaningful cross-platform number.
    pub fn current() -> io::Result<State> {
        imp::current().map(State)
    }

    /// Returns the percentage of time CPUs were idle from the current state
    /// relative to the previous state, as a percentage from 0.0 to 100.0.
    ///
    /// This function will return, as a percentage, the amount of time that the
    /// entire system was idle between the `previous` state and this own state.
    /// This can be useful to compare two snapshots in time of CPU usage to see
    /// how the CPU usage compares between the two.
    pub fn idle_since(&self, previous: &State) -> f64 {
        imp::pct_idle(&previous.0, &self.0)
    }
}

#[cfg(target_os = "linux")]
mod imp {
    use std::fs::File;
    use std::io::{self, Read};

    pub struct State {
        user: u64,
        nice: u64,
        system: u64,
        idle: u64,
        iowait: u64,
        irq: u64,
        softirq: u64,
        steal: u64,
        guest: u64,
        guest_nice: u64,
    }

    pub fn current() -> io::Result<State> {
        let mut state = String::new();
        File::open("/proc/stat")?.read_to_string(&mut state)?;
        let mut parts = state.lines().next().unwrap().split_whitespace();
        if parts.next() != Some("cpu") {
            return Err(io::Error::new(
                io::ErrorKind::Other,
                "cannot parse /proc/stat",
            ));
        }

        Ok(State {
            user: parts.next().unwrap().parse::<u64>().unwrap(),
            nice: parts.next().unwrap().parse::<u64>().unwrap(),
            system: parts.next().unwrap().parse::<u64>().unwrap(),
            idle: parts.next().unwrap().parse::<u64>().unwrap(),
            iowait: parts.next().unwrap().parse::<u64>().unwrap(),
            irq: parts.next().unwrap().parse::<u64>().unwrap(),
            softirq: parts.next().unwrap().parse::<u64>().unwrap(),
            steal: parts.next().unwrap().parse::<u64>().unwrap(),
            guest: parts.next().unwrap().parse::<u64>().unwrap(),
            guest_nice: parts.next().unwrap().parse::<u64>().unwrap(),
        })
    }

    pub fn pct_idle(prev: &State, next: &State) -> f64 {
        let user = next.user - prev.user;
        let nice = next.nice - prev.nice;
        let system = next.system - prev.system;
        let idle = next.idle - prev.idle;
        let iowait = next.iowait - prev.iowait;
        let irq = next.irq - prev.irq;
        let softirq = next.softirq - prev.softirq;
        let steal = next.steal - prev.steal;
        let guest = next.guest - prev.guest;
        let guest_nice = next.guest_nice - prev.guest_nice;
        let total =
            user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice;

        (idle as f64) / (total as f64) * 100.0
    }
}

#[cfg(target_os = "macos")]
#[allow(bad_style)]
mod imp {
    use std::io;
    use std::ptr;

    type host_t = u32;
    type mach_port_t = u32;
    type vm_map_t = mach_port_t;
    type vm_offset_t = usize;
    type vm_size_t = usize;
    type vm_address_t = vm_offset_t;
    type processor_flavor_t = i32;
    type natural_t = u32;
    type processor_info_array_t = *mut i32;
    type mach_msg_type_number_t = i32;
    type kern_return_t = i32;

    const PROESSOR_CPU_LOAD_INFO: processor_flavor_t = 2;
    const CPU_STATE_USER: usize = 0;
    const CPU_STATE_SYSTEM: usize = 1;
    const CPU_STATE_IDLE: usize = 2;
    const CPU_STATE_NICE: usize = 3;
    const CPU_STATE_MAX: usize = 4;

    extern "C" {
        static mut mach_task_self_: mach_port_t;

        fn mach_host_self() -> mach_port_t;
        fn host_processor_info(
            host: host_t,
            flavor: processor_flavor_t,
            out_processor_count: *mut natural_t,
            out_processor_info: *mut processor_info_array_t,
            out_processor_infoCnt: *mut mach_msg_type_number_t,
        ) -> kern_return_t;
        fn vm_deallocate(
            target_task: vm_map_t,
            address: vm_address_t,
            size: vm_size_t,
        ) -> kern_return_t;
    }

    pub struct State {
        user: u64,
        system: u64,
        idle: u64,
        nice: u64,
    }

    #[repr(C)]
    struct processor_cpu_load_info_data_t {
        cpu_ticks: [u32; CPU_STATE_MAX],
    }

    pub fn current() -> io::Result<State> {
        // There's scant little documentation on `host_processor_info`
        // throughout the internet, so this is just modeled after what everyone
        // else is doing. For now this is modeled largely after libuv.

        unsafe {
            let mut num_cpus_u = 0;
            let mut cpu_info = ptr::null_mut();
            let mut msg_type = 0;
            let err = host_processor_info(
                mach_host_self(),
                PROESSOR_CPU_LOAD_INFO,
                &mut num_cpus_u,
                &mut cpu_info,
                &mut msg_type,
            );
            if err != 0 {
                return Err(io::Error::last_os_error());
            }
            let mut ret = State {
                user: 0,
                system: 0,
                idle: 0,
                nice: 0,
            };
            let mut current = cpu_info as *const processor_cpu_load_info_data_t;
            for _ in 0..num_cpus_u {
                ret.user += (*current).cpu_ticks[CPU_STATE_USER] as u64;
                ret.system += (*current).cpu_ticks[CPU_STATE_SYSTEM] as u64;
                ret.idle += (*current).cpu_ticks[CPU_STATE_IDLE] as u64;
                ret.nice += (*current).cpu_ticks[CPU_STATE_NICE] as u64;
                current = current.offset(1);
            }
            vm_deallocate(mach_task_self_, cpu_info as vm_address_t, msg_type as usize);
            Ok(ret)
        }
    }

    pub fn pct_idle(prev: &State, next: &State) -> f64 {
        let user = next.user - prev.user;
        let system = next.system - prev.system;
        let idle = next.idle - prev.idle;
        let nice = next.nice - prev.nice;
        let total = user + system + idle + nice;
        (idle as f64) / (total as f64) * 100.0
    }
}

#[cfg(windows)]
mod imp {
    use std::io;
    use std::mem;
    use winapi::shared::minwindef::*;
    use winapi::um::processthreadsapi::*;

    pub struct State {
        idle: FILETIME,
        kernel: FILETIME,
        user: FILETIME,
    }

    pub fn current() -> io::Result<State> {
        unsafe {
            let mut ret = mem::zeroed::<State>();
            let r = GetSystemTimes(&mut ret.idle, &mut ret.kernel, &mut ret.user);
            if r != 0 {
                Ok(ret)
            } else {
                Err(io::Error::last_os_error())
            }
        }
    }

    pub fn pct_idle(prev: &State, next: &State) -> f64 {
        fn to_u64(a: &FILETIME) -> u64 {
            ((a.dwHighDateTime as u64) << 32) | (a.dwLowDateTime as u64)
        }

        let idle = to_u64(&next.idle) - to_u64(&prev.idle);
        let kernel = to_u64(&next.kernel) - to_u64(&prev.kernel);
        let user = to_u64(&next.user) - to_u64(&prev.user);
        let total = user + kernel;
        (idle as f64) / (total as f64) * 100.0
    }
}

#[cfg(not(any(target_os = "linux", target_os = "macos", windows)))]
mod imp {
    use std::io;

    pub struct State;

    pub fn current() -> io::Result<State> {
        Err(io::Error::new(
            io::ErrorKind::Other,
            "unsupported platform to learn CPU state",
        ))
    }

    pub fn pct_idle(_prev: &State, _next: &State) -> f64 {
        unimplemented!()
    }
}
<commit_msg>Auto merge of #7580 - alexcrichton:less-unwrap, r=ehuss<commit_after>use std::io;

pub struct State(imp::State);

impl State {
    /// Captures the current state of all CPUs on the system.
    ///
    /// The `State` returned here isn't too meaningful in terms of
    /// interpretation across platforms, but it can be compared to previous
    /// states to get a meaningful cross-platform number.
    pub fn current() -> io::Result<State> {
        imp::current().map(State)
    }

    /// Returns the percentage of time CPUs were idle from the current state
    /// relative to the previous state, as a percentage from 0.0 to 100.0.
    ///
    /// This function will return, as a percentage, the amount of time that the
    /// entire system was idle between the `previous` state and this own state.
    /// This can be useful to compare two snapshots in time of CPU usage to see
    /// how the CPU usage compares between the two.
    pub fn idle_since(&self, previous: &State) -> f64 {
        imp::pct_idle(&previous.0, &self.0)
    }
}

#[cfg(target_os = "linux")]
mod imp {
    use std::fs::File;
    use std::io::{self, Read};

    pub struct State {
        user: u64,
        nice: u64,
        system: u64,
        idle: u64,
        iowait: u64,
        irq: u64,
        softirq: u64,
        steal: u64,
        guest: u64,
        guest_nice: u64,
    }

    pub fn current() -> io::Result<State> {
        let mut state = String::new();
        File::open("/proc/stat")?.read_to_string(&mut state)?;

        (|| {
            let mut parts = state.lines().next()?.split_whitespace();
            if parts.next()? != "cpu" {
                return None;
            }
            Some(State {
                user: parts.next()?.parse::<u64>().ok()?,
                nice: parts.next()?.parse::<u64>().ok()?,
                system: parts.next()?.parse::<u64>().ok()?,
                idle: parts.next()?.parse::<u64>().ok()?,
                iowait: parts.next()?.parse::<u64>().ok()?,
                irq: parts.next()?.parse::<u64>().ok()?,
                softirq: parts.next()?.parse::<u64>().ok()?,
                steal: parts.next()?.parse::<u64>().ok()?,
                guest: parts.next()?.parse::<u64>().ok()?,
                guest_nice: parts.next()?.parse::<u64>().ok()?,
            })
        })()
        .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "first line of /proc/stat malformed"))
    }

    pub fn pct_idle(prev: &State, next: &State) -> f64 {
        let user = next.user - prev.user;
        let nice = next.nice - prev.nice;
        let system = next.system - prev.system;
        let idle = next.idle - prev.idle;
        let iowait = next.iowait - prev.iowait;
        let irq = next.irq - prev.irq;
        let softirq = next.softirq - prev.softirq;
        let steal = next.steal - prev.steal;
        let guest = next.guest - prev.guest;
        let guest_nice = next.guest_nice - prev.guest_nice;
        let total =
            user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice;

        (idle as f64) / (total as f64) * 100.0
    }
}

#[cfg(target_os = "macos")]
#[allow(bad_style)]
mod imp {
    use std::io;
    use std::ptr;

    type host_t = u32;
    type mach_port_t = u32;
    type vm_map_t = mach_port_t;
    type vm_offset_t = usize;
    type vm_size_t = usize;
    type vm_address_t = vm_offset_t;
    type processor_flavor_t = i32;
    type natural_t = u32;
    type processor_info_array_t = *mut i32;
    type mach_msg_type_number_t = i32;
    type kern_return_t = i32;

    const PROESSOR_CPU_LOAD_INFO: processor_flavor_t = 2;
    const CPU_STATE_USER: usize = 0;
    const CPU_STATE_SYSTEM: usize = 1;
    const CPU_STATE_IDLE: usize = 2;
    const CPU_STATE_NICE: usize = 3;
    const CPU_STATE_MAX: usize = 4;

    extern "C" {
        static mut mach_task_self_: mach_port_t;

        fn mach_host_self() -> mach_port_t;
        fn host_processor_info(
            host: host_t,
            flavor: processor_flavor_t,
            out_processor_count: *mut natural_t,
            out_processor_info: *mut processor_info_array_t,
            out_processor_infoCnt: *mut mach_msg_type_number_t,
        ) -> kern_return_t;
        fn vm_deallocate(
            target_task: vm_map_t,
            address: vm_address_t,
            size: vm_size_t,
        ) -> kern_return_t;
    }

    pub struct State {
        user: u64,
        system: u64,
        idle: u64,
        nice: u64,
    }

    #[repr(C)]
    struct processor_cpu_load_info_data_t {
        cpu_ticks: [u32; CPU_STATE_MAX],
    }

    pub fn current() -> io::Result<State> {
        // There's scant little documentation on `host_processor_info`
        // throughout the internet, so this is just modeled after what everyone
        // else is doing. For now this is modeled largely after libuv.

        unsafe {
            let mut num_cpus_u = 0;
            let mut cpu_info = ptr::null_mut();
            let mut msg_type = 0;
            let err = host_processor_info(
                mach_host_self(),
                PROESSOR_CPU_LOAD_INFO,
                &mut num_cpus_u,
                &mut cpu_info,
                &mut msg_type,
            );
            if err != 0 {
                return Err(io::Error::last_os_error());
            }
            let mut ret = State {
                user: 0,
                system: 0,
                idle: 0,
                nice: 0,
            };
            let mut current = cpu_info as *const processor_cpu_load_info_data_t;
            for _ in 0..num_cpus_u {
                ret.user += (*current).cpu_ticks[CPU_STATE_USER] as u64;
                ret.system += (*current).cpu_ticks[CPU_STATE_SYSTEM] as u64;
                ret.idle += (*current).cpu_ticks[CPU_STATE_IDLE] as u64;
                ret.nice += (*current).cpu_ticks[CPU_STATE_NICE] as u64;
                current = current.offset(1);
            }
            vm_deallocate(mach_task_self_, cpu_info as vm_address_t, msg_type as usize);
            Ok(ret)
        }
    }

    pub fn pct_idle(prev: &State, next: &State) -> f64 {
        let user = next.user - prev.user;
        let system = next.system - prev.system;
        let idle = next.idle - prev.idle;
        let nice = next.nice - prev.nice;
        let total = user + system + idle + nice;
        (idle as f64) / (total as f64) * 100.0
    }
}

#[cfg(windows)]
mod imp {
    use std::io;
    use std::mem;
    use winapi::shared::minwindef::*;
    use winapi::um::processthreadsapi::*;

    pub struct State {
        idle: FILETIME,
        kernel: FILETIME,
        user: FILETIME,
    }

    pub fn current() -> io::Result<State> {
        unsafe {
            let mut ret = mem::zeroed::<State>();
            let r = GetSystemTimes(&mut ret.idle, &mut ret.kernel, &mut ret.user);
            if r != 0 {
                Ok(ret)
            } else {
                Err(io::Error::last_os_error())
            }
        }
    }

    pub fn pct_idle(prev: &State, next: &State) -> f64 {
        fn to_u64(a: &FILETIME) -> u64 {
            ((a.dwHighDateTime as u64) << 32) | (a.dwLowDateTime as u64)
        }

        let idle = to_u64(&next.idle) - to_u64(&prev.idle);
        let kernel = to_u64(&next.kernel) - to_u64(&prev.kernel);
        let user = to_u64(&next.user) - to_u64(&prev.user);
        let total = user + kernel;
        (idle as f64) / (total as f64) * 100.0
    }
}

#[cfg(not(any(target_os = "linux", target_os = "macos", windows)))]
mod imp {
    use std::io;

    pub struct State;

    pub fn current() -> io::Result<State> {
        Err(io::Error::new(
            io::ErrorKind::Other,
            "unsupported platform to learn CPU state",
        ))
    }

    pub fn pct_idle(_prev: &State, _next: &State) -> f64 {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>//! Name resolution algorithm. The end result of the algorithm is `ItemMap`: a
//! map with maps each module to it's scope: the set of items, visible in the
//! module. That is, we only resolve imports here, name resolution of item
//! bodies will be done in a separate step.
//!
//! Like Rustc, we use an interative per-crate algorithm: we start with scopes
//! containing only directly defined items, and then iteratively resolve
//! imports.
//!
//! To make this work nicely in the IDE scenarios, we place `InputModuleItems`
//! in between raw syntax and name resolution. `InputModuleItems` are computed
//! using only the module's syntax, and it is all directly defined items plus
//! imports. The plain is to make `InputModuleItems` independent of local
//! modifications (that is, typing inside a function shold not change IMIs),
//! such that the results of name resolution can be preserved unless the module
//! structure itself is modified.
use std::{
    sync::Arc,
};

use rustc_hash::FxHashMap;
use ra_syntax::{
    TextRange,
    SmolStr, SyntaxKind::{self, *},
    ast::{self, AstNode}
};
use ra_db::SourceRootId;

use crate::{
    Cancelable, FileId,
    DefId, DefLoc, DefKind,
    SourceItemId, SourceFileItemId, SourceFileItems,
    Path, PathKind,
    HirDatabase, Crate,
    module::{Module, ModuleId, ModuleTree},
};

/// Item map is the result of the name resolution. Item map contains, for each
/// module, the set of visible items.
#[derive(Default, Debug, PartialEq, Eq)]
pub struct ItemMap {
    pub per_module: FxHashMap<ModuleId, ModuleScope>,
}

#[derive(Debug, Default, PartialEq, Eq, Clone)]
pub struct ModuleScope {
    items: FxHashMap<SmolStr, Resolution>,
}

impl ModuleScope {
    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &Resolution)> + 'a {
        self.items.iter()
    }
    pub fn get(&self, name: &SmolStr) -> Option<&Resolution> {
        self.items.get(name)
    }
}

/// A set of items and imports declared inside a module, without relation to
/// other modules.
///
/// This stands in-between raw syntax and name resolution and alow us to avoid
/// recomputing name res: if `InputModuleItems` are the same, we can avoid
/// running name resolution.
#[derive(Debug, Default, PartialEq, Eq)]
pub struct InputModuleItems {
    items: Vec<ModuleItem>,
    imports: Vec<Import>,
}

#[derive(Debug, PartialEq, Eq)]
struct ModuleItem {
    id: SourceFileItemId,
    name: SmolStr,
    kind: SyntaxKind,
    vis: Vis,
}

#[derive(Debug, PartialEq, Eq)]
enum Vis {
    // Priv,
    Other,
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct Import {
    path: Path,
    kind: ImportKind,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NamedImport {
    pub file_item_id: SourceFileItemId,
    pub relative_range: TextRange,
}

impl NamedImport {
    pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange {
        let source_item_id = SourceItemId {
            file_id,
            item_id: Some(self.file_item_id),
        };
        let syntax = db.file_item(source_item_id);
        let offset = syntax.borrowed().range().start();
        self.relative_range + offset
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
enum ImportKind {
    Glob,
    Named(NamedImport),
}

/// Resolution is basically `DefId` atm, but it should account for stuff like
/// multiple namespaces, ambiguity and errors.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Resolution {
    /// None for unresolved
    pub def_id: Option<DefId>,
    /// ident by whitch this is imported into local scope.
    pub import: Option<NamedImport>,
}

// #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
// enum Namespace {
//     Types,
//     Values,
// }

// #[derive(Debug)]
// struct PerNs<T> {
//     types: Option<T>,
//     values: Option<T>,
// }

impl InputModuleItems {
    pub(crate) fn new<'a>(
        file_items: &SourceFileItems,
        items: impl Iterator<Item = ast::ModuleItem<'a>>,
    ) -> InputModuleItems {
        let mut res = InputModuleItems::default();
        for item in items {
            res.add_item(file_items, item);
        }
        res
    }

    fn add_item(&mut self, file_items: &SourceFileItems, item: ast::ModuleItem) -> Option<()> {
        match item {
            ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::ImplItem(_) => {
                // impls don't define items
            }
            ast::ModuleItem::UseItem(it) => self.add_use_item(file_items, it),
            ast::ModuleItem::ExternCrateItem(_) => {
                // TODO
            }
            ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(file_items, it)?),
        }
        Some(())
    }

    fn add_use_item(&mut self, file_items: &SourceFileItems, item: ast::UseItem) {
        let file_item_id = file_items.id_of_unchecked(item.syntax());
        let start_offset = item.syntax().range().start();
        Path::expand_use_item(item, |path, range| {
            let kind = match range {
                None => ImportKind::Glob,
                Some(range) => ImportKind::Named(NamedImport {
                    file_item_id,
                    relative_range: range - start_offset,
                }),
            };
            self.imports.push(Import { kind, path })
        })
    }
}

impl ModuleItem {
    fn new<'a>(file_items: &SourceFileItems, item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
        let name = item.name()?.text();
        let kind = item.syntax().kind();
        let vis = Vis::Other;
        let id = file_items.id_of_unchecked(item.syntax());
        let res = ModuleItem {
            id,
            name,
            kind,
            vis,
        };
        Some(res)
    }
}

pub(crate) struct Resolver<'a, DB> {
    db: &'a DB,
    input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>,
    source_root: SourceRootId,
    module_tree: Arc<ModuleTree>,
    result: ItemMap,
}

impl<'a, DB> Resolver<'a, DB>
where
    DB: HirDatabase,
{
    pub(crate) fn new(
        db: &'a DB,
        input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>,
        source_root: SourceRootId,
        module_tree: Arc<ModuleTree>,
    ) -> Resolver<'a, DB> {
        Resolver {
            db,
            input,
            source_root,
            module_tree,
            result: ItemMap::default(),
        }
    }

    pub(crate) fn resolve(mut self) -> Cancelable<ItemMap> {
        for (&module_id, items) in self.input.iter() {
            self.populate_module(module_id, items)?;
        }

        for &module_id in self.input.keys() {
            self.db.check_canceled()?;
            self.resolve_imports(module_id)?;
        }
        Ok(self.result)
    }

    fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) -> Cancelable<()> {
        let file_id = module_id.source(&self.module_tree).file_id();

        let mut module_items = ModuleScope::default();

        // Populate extern crates prelude
        {
            let root_id = module_id.crate_root(&self.module_tree);
            let file_id = root_id.source(&self.module_tree).file_id();
            let crate_graph = self.db.crate_graph();
            if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id) {
                let krate = Crate::new(crate_id);
                for dep in krate.dependencies(self.db) {
                    if let Some(module) = dep.krate.root_module(self.db)? {
                        let def_id = module.def_id(self.db);
                        self.add_module_item(&mut module_items, dep.name, def_id);
                    }
                }
            };
        }
        for import in input.imports.iter() {
            if let Some(name) = import.path.segments.iter().last() {
                if let ImportKind::Named(import) = import.kind {
                    module_items.items.insert(
                        name.clone(),
                        Resolution {
                            def_id: None,
                            import: Some(import),
                        },
                    );
                }
            }
        }
        // Populate explicitelly declared items, except modules
        for item in input.items.iter() {
            if item.kind == MODULE {
                continue;
            }
            let def_loc = DefLoc {
                kind: DefKind::Item,
                source_root_id: self.source_root,
                module_id,
                source_item_id: SourceItemId {
                    file_id,
                    item_id: Some(item.id),
                },
            };
            let def_id = def_loc.id(self.db);
            let resolution = Resolution {
                def_id: Some(def_id),
                import: None,
            };
            module_items.items.insert(item.name.clone(), resolution);
        }

        // Populate modules
        for (name, module_id) in module_id.children(&self.module_tree) {
            let def_loc = DefLoc {
                kind: DefKind::Module,
                source_root_id: self.source_root,
                module_id,
                source_item_id: module_id.source(&self.module_tree).0,
            };
            let def_id = def_loc.id(self.db);
            self.add_module_item(&mut module_items, name, def_id);
        }

        self.result.per_module.insert(module_id, module_items);
        Ok(())
    }

    fn add_module_item(&self, module_items: &mut ModuleScope, name: SmolStr, def_id: DefId) {
        let resolution = Resolution {
            def_id: Some(def_id),
            import: None,
        };
        module_items.items.insert(name, resolution);
    }

    fn resolve_imports(&mut self, module_id: ModuleId) -> Cancelable<()> {
        for import in self.input[&module_id].imports.iter() {
            self.resolve_import(module_id, import)?;
        }
        Ok(())
    }

    fn resolve_import(&mut self, module_id: ModuleId, import: &Import) -> Cancelable<()> {
        let ptr = match import.kind {
            ImportKind::Glob => return Ok(()),
            ImportKind::Named(ptr) => ptr,
        };

        let mut curr: ModuleId = match import.path.kind {
            PathKind::Plain | PathKind::Self_ => module_id,
            PathKind::Super => {
                match module_id.parent(&self.module_tree) {
                    Some(it) => it,
                    // TODO: error
                    None => return Ok(()),
                }
            }
            PathKind::Crate => module_id.crate_root(&self.module_tree),
        };

        for (i, name) in import.path.segments.iter().enumerate() {
            let is_last = i == import.path.segments.len() - 1;

            let def_id = match self.result.per_module[&curr].items.get(name) {
                None => return Ok(()),
                Some(res) => match res.def_id {
                    Some(it) => it,
                    None => return Ok(()),
                },
            };

            if !is_last {
                curr = match def_id.loc(self.db) {
                    DefLoc {
                        kind: DefKind::Module,
                        module_id: target_module_id,
                        source_root_id,
                        ..
                    } => {
                        if source_root_id == self.source_root {
                            target_module_id
                        } else {
                            let module = Module::new(self.db, source_root_id, target_module_id)?;
                            let path = Path {
                                segments: import.path.segments[i + 1..].iter().cloned().collect(),
                                kind: PathKind::Crate,
                            };
                            if let Some(def_id) = module.resolve_path(self.db, path)? {
                                self.update(module_id, |items| {
                                    let res = Resolution {
                                        def_id: Some(def_id),
                                        import: Some(ptr),
                                    };
                                    items.items.insert(name.clone(), res);
                                })
                            }
                            return Ok(());
                        }
                    }
                    _ => return Ok(()),
                }
            } else {
                self.update(module_id, |items| {
                    let res = Resolution {
                        def_id: Some(def_id),
                        import: Some(ptr),
                    };
                    items.items.insert(name.clone(), res);
                })
            }
        }
        Ok(())
    }

    fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleScope)) {
        let module_items = self.result.per_module.get_mut(&module_id).unwrap();
        f(module_items)
    }
}

#[cfg(test)]
mod tests;
<commit_msg>fixme comment<commit_after>//! Name resolution algorithm. The end result of the algorithm is `ItemMap`: a
//! map with maps each module to it's scope: the set of items, visible in the
//! module. That is, we only resolve imports here, name resolution of item
//! bodies will be done in a separate step.
//!
//! Like Rustc, we use an interative per-crate algorithm: we start with scopes
//! containing only directly defined items, and then iteratively resolve
//! imports.
//!
//! To make this work nicely in the IDE scenarios, we place `InputModuleItems`
//! in between raw syntax and name resolution. `InputModuleItems` are computed
//! using only the module's syntax, and it is all directly defined items plus
//! imports. The plain is to make `InputModuleItems` independent of local
//! modifications (that is, typing inside a function shold not change IMIs),
//! such that the results of name resolution can be preserved unless the module
//! structure itself is modified.
use std::{
    sync::Arc,
};

use rustc_hash::FxHashMap;
use ra_syntax::{
    TextRange,
    SmolStr, SyntaxKind::{self, *},
    ast::{self, AstNode}
};
use ra_db::SourceRootId;

use crate::{
    Cancelable, FileId,
    DefId, DefLoc, DefKind,
    SourceItemId, SourceFileItemId, SourceFileItems,
    Path, PathKind,
    HirDatabase, Crate,
    module::{Module, ModuleId, ModuleTree},
};

/// Item map is the result of the name resolution. Item map contains, for each
/// module, the set of visible items.
// FIXME: currenty we compute item map per source-root. We should do it per crate instead.
#[derive(Default, Debug, PartialEq, Eq)]
pub struct ItemMap {
    pub per_module: FxHashMap<ModuleId, ModuleScope>,
}

#[derive(Debug, Default, PartialEq, Eq, Clone)]
pub struct ModuleScope {
    items: FxHashMap<SmolStr, Resolution>,
}

impl ModuleScope {
    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &Resolution)> + 'a {
        self.items.iter()
    }
    pub fn get(&self, name: &SmolStr) -> Option<&Resolution> {
        self.items.get(name)
    }
}

/// A set of items and imports declared inside a module, without relation to
/// other modules.
///
/// This stands in-between raw syntax and name resolution and alow us to avoid
/// recomputing name res: if `InputModuleItems` are the same, we can avoid
/// running name resolution.
#[derive(Debug, Default, PartialEq, Eq)]
pub struct InputModuleItems {
    items: Vec<ModuleItem>,
    imports: Vec<Import>,
}

#[derive(Debug, PartialEq, Eq)]
struct ModuleItem {
    id: SourceFileItemId,
    name: SmolStr,
    kind: SyntaxKind,
    vis: Vis,
}

#[derive(Debug, PartialEq, Eq)]
enum Vis {
    // Priv,
    Other,
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct Import {
    path: Path,
    kind: ImportKind,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NamedImport {
    pub file_item_id: SourceFileItemId,
    pub relative_range: TextRange,
}

impl NamedImport {
    pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange {
        let source_item_id = SourceItemId {
            file_id,
            item_id: Some(self.file_item_id),
        };
        let syntax = db.file_item(source_item_id);
        let offset = syntax.borrowed().range().start();
        self.relative_range + offset
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
enum ImportKind {
    Glob,
    Named(NamedImport),
}

/// Resolution is basically `DefId` atm, but it should account for stuff like
/// multiple namespaces, ambiguity and errors.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Resolution {
    /// None for unresolved
    pub def_id: Option<DefId>,
    /// ident by whitch this is imported into local scope.
    pub import: Option<NamedImport>,
}

// #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
// enum Namespace {
//     Types,
//     Values,
// }

// #[derive(Debug)]
// struct PerNs<T> {
//     types: Option<T>,
//     values: Option<T>,
// }

impl InputModuleItems {
    pub(crate) fn new<'a>(
        file_items: &SourceFileItems,
        items: impl Iterator<Item = ast::ModuleItem<'a>>,
    ) -> InputModuleItems {
        let mut res = InputModuleItems::default();
        for item in items {
            res.add_item(file_items, item);
        }
        res
    }

    fn add_item(&mut self, file_items: &SourceFileItems, item: ast::ModuleItem) -> Option<()> {
        match item {
            ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::ImplItem(_) => {
                // impls don't define items
            }
            ast::ModuleItem::UseItem(it) => self.add_use_item(file_items, it),
            ast::ModuleItem::ExternCrateItem(_) => {
                // TODO
            }
            ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
            ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(file_items, it)?),
        }
        Some(())
    }

    fn add_use_item(&mut self, file_items: &SourceFileItems, item: ast::UseItem) {
        let file_item_id = file_items.id_of_unchecked(item.syntax());
        let start_offset = item.syntax().range().start();
        Path::expand_use_item(item, |path, range| {
            let kind = match range {
                None => ImportKind::Glob,
                Some(range) => ImportKind::Named(NamedImport {
                    file_item_id,
                    relative_range: range - start_offset,
                }),
            };
            self.imports.push(Import { kind, path })
        })
    }
}

impl ModuleItem {
    fn new<'a>(file_items: &SourceFileItems, item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
        let name = item.name()?.text();
        let kind = item.syntax().kind();
        let vis = Vis::Other;
        let id = file_items.id_of_unchecked(item.syntax());
        let res = ModuleItem {
            id,
            name,
            kind,
            vis,
        };
        Some(res)
    }
}

pub(crate) struct Resolver<'a, DB> {
    db: &'a DB,
    input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>,
    source_root: SourceRootId,
    module_tree: Arc<ModuleTree>,
    result: ItemMap,
}

impl<'a, DB> Resolver<'a, DB>
where
    DB: HirDatabase,
{
    pub(crate) fn new(
        db: &'a DB,
        input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>,
        source_root: SourceRootId,
        module_tree: Arc<ModuleTree>,
    ) -> Resolver<'a, DB> {
        Resolver {
            db,
            input,
            source_root,
            module_tree,
            result: ItemMap::default(),
        }
    }

    pub(crate) fn resolve(mut self) -> Cancelable<ItemMap> {
        for (&module_id, items) in self.input.iter() {
            self.populate_module(module_id, items)?;
        }

        for &module_id in self.input.keys() {
            self.db.check_canceled()?;
            self.resolve_imports(module_id)?;
        }
        Ok(self.result)
    }

    fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) -> Cancelable<()> {
        let file_id = module_id.source(&self.module_tree).file_id();

        let mut module_items = ModuleScope::default();

        // Populate extern crates prelude
        {
            let root_id = module_id.crate_root(&self.module_tree);
            let file_id = root_id.source(&self.module_tree).file_id();
            let crate_graph = self.db.crate_graph();
            if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id) {
                let krate = Crate::new(crate_id);
                for dep in krate.dependencies(self.db) {
                    if let Some(module) = dep.krate.root_module(self.db)? {
                        let def_id = module.def_id(self.db);
                        self.add_module_item(&mut module_items, dep.name, def_id);
                    }
                }
            };
        }
        for import in input.imports.iter() {
            if let Some(name) = import.path.segments.iter().last() {
                if let ImportKind::Named(import) = import.kind {
                    module_items.items.insert(
                        name.clone(),
                        Resolution {
                            def_id: None,
                            import: Some(import),
                        },
                    );
                }
            }
        }
        // Populate explicitelly declared items, except modules
        for item in input.items.iter() {
            if item.kind == MODULE {
                continue;
            }
            let def_loc = DefLoc {
                kind: DefKind::Item,
                source_root_id: self.source_root,
                module_id,
                source_item_id: SourceItemId {
                    file_id,
                    item_id: Some(item.id),
                },
            };
            let def_id = def_loc.id(self.db);
            let resolution = Resolution {
                def_id: Some(def_id),
                import: None,
            };
            module_items.items.insert(item.name.clone(), resolution);
        }

        // Populate modules
        for (name, module_id) in module_id.children(&self.module_tree) {
            let def_loc = DefLoc {
                kind: DefKind::Module,
                source_root_id: self.source_root,
                module_id,
                source_item_id: module_id.source(&self.module_tree).0,
            };
            let def_id = def_loc.id(self.db);
            self.add_module_item(&mut module_items, name, def_id);
        }

        self.result.per_module.insert(module_id, module_items);
        Ok(())
    }

    fn add_module_item(&self, module_items: &mut ModuleScope, name: SmolStr, def_id: DefId) {
        let resolution = Resolution {
            def_id: Some(def_id),
            import: None,
        };
        module_items.items.insert(name, resolution);
    }

    fn resolve_imports(&mut self, module_id: ModuleId) -> Cancelable<()> {
        for import in self.input[&module_id].imports.iter() {
            self.resolve_import(module_id, import)?;
        }
        Ok(())
    }

    fn resolve_import(&mut self, module_id: ModuleId, import: &Import) -> Cancelable<()> {
        let ptr = match import.kind {
            ImportKind::Glob => return Ok(()),
            ImportKind::Named(ptr) => ptr,
        };

        let mut curr: ModuleId = match import.path.kind {
            PathKind::Plain | PathKind::Self_ => module_id,
            PathKind::Super => {
                match module_id.parent(&self.module_tree) {
                    Some(it) => it,
                    // TODO: error
                    None => return Ok(()),
                }
            }
            PathKind::Crate => module_id.crate_root(&self.module_tree),
        };

        for (i, name) in import.path.segments.iter().enumerate() {
            let is_last = i == import.path.segments.len() - 1;

            let def_id = match self.result.per_module[&curr].items.get(name) {
                None => return Ok(()),
                Some(res) => match res.def_id {
                    Some(it) => it,
                    None => return Ok(()),
                },
            };

            if !is_last {
                curr = match def_id.loc(self.db) {
                    DefLoc {
                        kind: DefKind::Module,
                        module_id: target_module_id,
                        source_root_id,
                        ..
                    } => {
                        if source_root_id == self.source_root {
                            target_module_id
                        } else {
                            let module = Module::new(self.db, source_root_id, target_module_id)?;
                            let path = Path {
                                segments: import.path.segments[i + 1..].iter().cloned().collect(),
                                kind: PathKind::Crate,
                            };
                            if let Some(def_id) = module.resolve_path(self.db, path)? {
                                self.update(module_id, |items| {
                                    let res = Resolution {
                                        def_id: Some(def_id),
                                        import: Some(ptr),
                                    };
                                    items.items.insert(name.clone(), res);
                                })
                            }
                            return Ok(());
                        }
                    }
                    _ => return Ok(()),
                }
            } else {
                self.update(module_id, |items| {
                    let res = Resolution {
                        def_id: Some(def_id),
                        import: Some(ptr),
                    };
                    items.items.insert(name.clone(), res);
                })
            }
        }
        Ok(())
    }

    fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleScope)) {
        let module_items = self.result.per_module.get_mut(&module_id).unwrap();
        f(module_items)
    }
}

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>
use items::SystemdItem;
use nom::*;

fn c_always_true(_c: char) -> bool { true }
fn c_is_alphabetic(c: char) -> bool { c.is_alphabetic() }
fn c_is_value_element(c: char) -> bool {
    match c {
        ' '|'/'|'-'|'_'|'.'|'@'|'+'|':'|'"'|'|'|'\'' => true,
        c if c.is_alphanumeric() => true,
        _ => false
    }
}
fn c_is_key_element(c: char) -> bool {
    match c {
        '!'|'|'|'@' => true,
        c if c.is_alphabetic() => true,
        _ => false
    }
}

named!(pub take_whole_line<&str, &str>, take_while_s!(c_always_true));

named!(
    pub parse_comment<&str, SystemdItem>,
    do_parse!(
        eat_separator!(" \t")      >>
        tag_s!("#")                >>
        comment: take_whole_line   >>
        (SystemdItem::Comment(comment.trim()))
    )
);

named!(
    pub parse_category<&str, SystemdItem>,
    do_parse!(
        eat_separator!(" \t")   >>
        tag!("[")               >>
        eat_separator!(" ")     >>
        category: take_while1_s!(c_is_alphabetic) >>
        eat_separator!(" ")     >>
        tag!("]")               >>
        (SystemdItem::Category(category))
    )
);

named!(
    pub parse_directive<&str, SystemdItem>,
    do_parse!(
        eat_separator!(" \t")   >>
        key: take_while1_s!(c_is_key_element) >>
        eat_separator!(" ")     >>
        tag!("=")               >>
        eat_separator!(" ")     >>
        value: take_while1_s!(c_is_value_element) >>
        (SystemdItem::Directive(key, value))
    )
);

named!(
    pub parse_line<&str, SystemdItem>,
    alt!(parse_category | parse_comment | parse_directive)
);

pub fn parse_unit(input: &str) -> Result<Vec<SystemdItem>, Vec<(IError<&str>, u32)>> {
    let mut errors = vec!();
    let mut oks = vec!();
    let mut line_index = 0;
    let mixed_res = input.lines()
                         .map(|l| {
                             let res = (l, line_index);
                             line_index += 1;
                             res
                         })
                         .filter(|&(line, _)| !line.trim().is_empty()) // skip white lines
                         .map(|(line, idx)| (parse_line(line), idx));

    for (res, line_idx) in mixed_res {
        match res.to_full_result() {
            Ok(ok_res) => oks.push(ok_res),
            Err(err_res) => errors.push((err_res, line_idx))
        }
    }

    if errors.len() > 0 {
        Err(errors)
    } else {
        Ok(oks)
    }
}

<commit_msg> Parser: fix Needed(size) return on parse error<commit_after>
use items::SystemdItem;
use nom::*;

fn c_always_true(_c: char) -> bool { true }
fn c_is_alphabetic(c: char) -> bool { c.is_alphabetic() }
fn c_is_value_element(c: char) -> bool {
    match c {
        ' '|'/'|'-'|'_'|'.'|'@'|'+'|':'|'"'|'|'|'\'' => true,
        c if c.is_alphanumeric() => true,
        _ => false
    }
}
fn c_is_key_element(c: char) -> bool {
    match c {
        '!'|'|'|'@' => true,
        c if c.is_alphabetic() => true,
        _ => false
    }
}

named!(pub take_whole_line<&str, &str>, take_while_s!(c_always_true));

named!(
    pub parse_comment<&str, SystemdItem>,
    complete!(do_parse!(
        eat_separator!(" \t")      >>
        tag_s!("#")                >>
        comment: take_whole_line   >>
        (SystemdItem::Comment(comment.trim()))
    ))
);

named!(
    pub parse_category<&str, SystemdItem>,
    complete!(do_parse!(
        eat_separator!(" \t")   >>
        tag!("[")               >>
        eat_separator!(" ")     >>
        category: take_while1_s!(c_is_alphabetic) >>
        eat_separator!(" ")     >>
        tag!("]")               >>
        (SystemdItem::Category(category))
    ))
);

named!(
    pub parse_directive<&str, SystemdItem>,
    complete!(do_parse!(
        eat_separator!(" \t")   >>
        key: take_while1_s!(c_is_key_element) >>
        eat_separator!(" ")     >>
        tag!("=")               >>
        eat_separator!(" ")     >>
        value: take_while1_s!(c_is_value_element) >>
        (SystemdItem::Directive(key, value))
    ))
);

named!(
    pub parse_line<&str, SystemdItem>,
    alt_complete!(parse_category | parse_comment | parse_directive)
);

pub fn parse_unit(input: &str) -> Result<Vec<SystemdItem>, Vec<(IError<&str>, u32)>> {
    let mut errors = vec!();
    let mut oks = vec!();
    let mut line_index = 0;
    let mixed_res = input.lines()
                         .map(|l| {
                             let res = (l, line_index);
                             line_index += 1;
                             res
                         })
                         .filter(|&(line, _)| !line.trim().is_empty()) // skip white lines
                         .map(|(line, idx)| (parse_line(line), idx));

    for (res, line_idx) in mixed_res {
        match res.to_full_result() {
            Ok(ok_res) => oks.push(ok_res),
            Err(err_res) => errors.push((err_res, line_idx))
        }
    }

    if errors.len() > 0 {
        Err(errors)
    } else {
        Ok(oks)
    }
}

<|endoftext|>


<commit_before><commit_msg>Make structures order more logical in render.rs<commit_after><|endoftext|>


<commit_before><commit_msg>Build proc-macro-test-impl out-of-tree<commit_after><|endoftext|>


<commit_before>use chrono::{DateTime, TimeZone, Utc};
use failure::{Error, ResultExt};
use std::ffi::OsStr;
use std::fmt;
use std::fs::{self, File};
use std::io::{BufReader, Read};
use std::path::{Path, PathBuf};
use tar::Archive;
use xz2::bufread::XzDecoder;

#[derive(Debug, Clone)]
struct Commit {
    sha: String,
    date: DateTime<Utc>,
}

pub struct Sysroot {
    pub sha: String,
    pub rustc: PathBuf,
    pub rustdoc: PathBuf,
    pub cargo: PathBuf,
    pub triple: String,
}

impl Sysroot {
    pub fn install(sha: &str, date: DateTime<Utc>, triple: &str) -> Result<Self, Error> {
        let commit = Commit {
            sha: sha.to_owned(),
            date,
        };
        let unpack_into = "cache";
        // Versions of rustc older than Mar 20 have bugs in their cargo.
        let download_cargo = commit.date >= Utc.ymd(2017, 3, 20).and_hms(0, 0, 0);

        fs::create_dir_all(&unpack_into)?;

        let download = SysrootDownload {
            directory: unpack_into.into(),
            rust_sha: commit.sha.clone(),
            triple: triple.to_owned(),
        };

        download.get_and_extract(ModuleVariant::Rustc)?;
        download.get_and_extract(ModuleVariant::Std)?;
        if download_cargo {
            download.get_and_extract(ModuleVariant::Cargo)?;
        }

        download.into_sysroot(download_cargo)
    }
}

impl Drop for Sysroot {
    fn drop(&mut self) {
        fs::remove_dir_all(format!("cache/{}", self.sha)).unwrap_or_else(|err| {
            log::info!(
                "failed to remove {:?}, please do so manually: {:?}",
                format!("cache/{}", self.sha),
                err
            );
        });
    }
}

#[derive(Debug, Clone)]
struct SysrootDownload {
    directory: PathBuf,
    rust_sha: String,
    triple: String,
}

const MODULE_URLS: &[&str] = &[
    "https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rustc-builds/@SHA@/@MODULE@-nightly-@TRIPLE@.tar.xz",
    "https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rustc-builds-try/@SHA@/@MODULE@-nightly-@TRIPLE@.tar.xz",
];

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum ModuleVariant {
    Cargo,
    Rustc,
    Std,
}

impl fmt::Display for ModuleVariant {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            ModuleVariant::Cargo => write!(f, "cargo"),
            ModuleVariant::Rustc => write!(f, "rustc"),
            ModuleVariant::Std => write!(f, "rust-std"),
        }
    }
}

impl ModuleVariant {
    fn urls(&self, sysroot: &SysrootDownload, triple: &str) -> Vec<String> {
        MODULE_URLS
            .iter()
            .map(|url| {
                url.replace("@MODULE@", &self.to_string())
                    .replace("@SHA@", &sysroot.rust_sha)
                    .replace("@TRIPLE@", triple)
            })
            .collect()
    }
}

impl SysrootDownload {
    fn into_sysroot(self, used_fallback_cargo: bool) -> Result<Sysroot, Error> {
        Ok(Sysroot {
            rustc: self
                .directory
                .join(&self.rust_sha)
                .join("rustc/bin/rustc")
                .canonicalize()
                .with_context(|_| {
                    format!("failed to canonicalize rustc path for {}", self.rust_sha)
                })?,
            rustdoc: self
                .directory
                .join(&self.rust_sha)
                .join("rustc/bin/rustdoc")
                .canonicalize()
                .with_context(|_| {
                    format!("failed to canonicalize rustdoc path for {}", self.rust_sha)
                })?,
            cargo: if used_fallback_cargo {
                // go with cargo present in environment if we need to fallback
                PathBuf::from("cargo")
            } else {
                let path = self.directory.join(&self.rust_sha).join("cargo/bin/cargo");
                path.canonicalize().with_context(|_| {
                    format!(
                        "failed to canonicalize cargo path for {}: {:?}",
                        self.rust_sha, path
                    )
                })?
            },
            sha: self.rust_sha,
            triple: self.triple,
        })
    }

    fn get_and_extract(&self, variant: ModuleVariant) -> Result<(), Error> {
        let archive_path = self.directory.join(format!(
            "{}-{}-{}.tar.xz",
            self.rust_sha, self.triple, variant,
        ));
        if archive_path.exists() {
            let reader = BufReader::new(File::open(&archive_path)?);
            let decompress = XzDecoder::new(reader);
            let extract = self.extract(variant, decompress);
            match extract {
                Ok(()) => return Ok(()),
                Err(err) => {
                    log::warn!("extracting {} failed: {:?}", archive_path.display(), err);
                    fs::remove_file(&archive_path)?;
                }
            }
        }

        for url in variant.urls(self, &self.triple) {
            log::debug!("requesting: {}", url);
            let resp = reqwest::get(&url)?;
            log::debug!("{}", resp.status());
            let reader = if resp.status().is_success() {
                XzDecoder::new(BufReader::new(resp))
            } else {
                continue;
            };
            match self.extract(variant, reader) {
                Ok(()) => return Ok(()),
                Err(err) => {
                    log::warn!("extracting {} failed: {:?}", url, err);
                    continue;
                }
            }
        }

        failure::bail!(
            "unable to download sha {} triple {} module {}",
            self.rust_sha,
            self.triple,
            variant
        );
    }

    fn extract<T: Read>(&self, variant: ModuleVariant, reader: T) -> Result<(), Error> {
        let is_std = variant == ModuleVariant::Std;
        let mut archive = Archive::new(reader);
        let std_prefix = format!("rust-std-{}/lib/rustlib", self.triple);

        let mut to_link = Vec::new();

        let unpack_into = self.directory.join(&self.rust_sha);

        for entry in archive.entries()? {
            let mut entry = entry?;
            let path = entry.path()?.into_owned();
            let mut components = path.components();
            assert!(components.next().is_some(), "strip container directory");
            let path = components.as_path();

            let path = if is_std {
                if let Ok(path) = path.strip_prefix(&std_prefix) {
                    if path.extension() == Some(OsStr::new("dylib")) {
                        to_link.push(path.to_owned());
                        continue;
                    } else {
                        Path::new("rustc/lib/rustlib").join(path)
                    }
                } else {
                    continue;
                }
            } else {
                path.into()
            };
            let path = unpack_into.join(path);
            fs::create_dir_all(&path.parent().unwrap()).with_context(|_| {
                format!(
                    "could not create intermediate directories for {}",
                    path.display()
                )
            })?;
            entry.unpack(path)?;
        }

        let link_dst_prefix = unpack_into.join(format!("rustc/lib/rustlib/{}/lib", self.triple));
        let link_src_prefix = format!("{}/lib", self.triple);
        for path in to_link {
            let src = unpack_into.join("rustc/lib").join(
                path.strip_prefix(&link_src_prefix)
                    .with_context(|_| format!("stripping prefix from: {:?}", path))?,
            );
            let dst = link_dst_prefix.join(&path);
            fs::create_dir_all(&dst.parent().unwrap()).with_context(|_| {
                format!(
                    "could not create intermediate directories for {}",
                    dst.display()
                )
            })?;
            log::trace!("linking {} to {}", src.display(), dst.display());
            fs::hard_link(src, dst)?;
        }

        Ok(())
    }
}
<commit_msg>Fix condition for expecting Cargo in download<commit_after>use chrono::{DateTime, TimeZone, Utc};
use failure::{Error, ResultExt};
use std::ffi::OsStr;
use std::fmt;
use std::fs::{self, File};
use std::io::{BufReader, Read};
use std::path::{Path, PathBuf};
use tar::Archive;
use xz2::bufread::XzDecoder;

#[derive(Debug, Clone)]
struct Commit {
    sha: String,
    date: DateTime<Utc>,
}

pub struct Sysroot {
    pub sha: String,
    pub rustc: PathBuf,
    pub rustdoc: PathBuf,
    pub cargo: PathBuf,
    pub triple: String,
}

impl Sysroot {
    pub fn install(sha: &str, date: DateTime<Utc>, triple: &str) -> Result<Self, Error> {
        let commit = Commit {
            sha: sha.to_owned(),
            date,
        };
        let unpack_into = "cache";
        // Versions of rustc older than Mar 20 have bugs in their cargo.
        let download_cargo = commit.date >= Utc.ymd(2017, 3, 20).and_hms(0, 0, 0);

        fs::create_dir_all(&unpack_into)?;

        let download = SysrootDownload {
            directory: unpack_into.into(),
            rust_sha: commit.sha.clone(),
            triple: triple.to_owned(),
        };

        download.get_and_extract(ModuleVariant::Rustc)?;
        download.get_and_extract(ModuleVariant::Std)?;
        if download_cargo {
            download.get_and_extract(ModuleVariant::Cargo)?;
        }

        download.into_sysroot(download_cargo)
    }
}

impl Drop for Sysroot {
    fn drop(&mut self) {
        fs::remove_dir_all(format!("cache/{}", self.sha)).unwrap_or_else(|err| {
            log::info!(
                "failed to remove {:?}, please do so manually: {:?}",
                format!("cache/{}", self.sha),
                err
            );
        });
    }
}

#[derive(Debug, Clone)]
struct SysrootDownload {
    directory: PathBuf,
    rust_sha: String,
    triple: String,
}

const MODULE_URLS: &[&str] = &[
    "https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rustc-builds/@SHA@/@MODULE@-nightly-@TRIPLE@.tar.xz",
    "https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rustc-builds-try/@SHA@/@MODULE@-nightly-@TRIPLE@.tar.xz",
];

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum ModuleVariant {
    Cargo,
    Rustc,
    Std,
}

impl fmt::Display for ModuleVariant {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            ModuleVariant::Cargo => write!(f, "cargo"),
            ModuleVariant::Rustc => write!(f, "rustc"),
            ModuleVariant::Std => write!(f, "rust-std"),
        }
    }
}

impl ModuleVariant {
    fn urls(&self, sysroot: &SysrootDownload, triple: &str) -> Vec<String> {
        MODULE_URLS
            .iter()
            .map(|url| {
                url.replace("@MODULE@", &self.to_string())
                    .replace("@SHA@", &sysroot.rust_sha)
                    .replace("@TRIPLE@", triple)
            })
            .collect()
    }
}

impl SysrootDownload {
    fn into_sysroot(self, download_cargo: bool) -> Result<Sysroot, Error> {
        Ok(Sysroot {
            rustc: self
                .directory
                .join(&self.rust_sha)
                .join("rustc/bin/rustc")
                .canonicalize()
                .with_context(|_| {
                    format!("failed to canonicalize rustc path for {}", self.rust_sha)
                })?,
            rustdoc: self
                .directory
                .join(&self.rust_sha)
                .join("rustc/bin/rustdoc")
                .canonicalize()
                .with_context(|_| {
                    format!("failed to canonicalize rustdoc path for {}", self.rust_sha)
                })?,
            cargo: if !download_cargo {
                // go with cargo present in environment if we need to fallback
                PathBuf::from("cargo")
            } else {
                let path = self.directory.join(&self.rust_sha).join("cargo/bin/cargo");
                path.canonicalize().with_context(|_| {
                    format!(
                        "failed to canonicalize cargo path for {}: {:?}",
                        self.rust_sha, path
                    )
                })?
            },
            sha: self.rust_sha,
            triple: self.triple,
        })
    }

    fn get_and_extract(&self, variant: ModuleVariant) -> Result<(), Error> {
        let archive_path = self.directory.join(format!(
            "{}-{}-{}.tar.xz",
            self.rust_sha, self.triple, variant,
        ));
        if archive_path.exists() {
            let reader = BufReader::new(File::open(&archive_path)?);
            let decompress = XzDecoder::new(reader);
            let extract = self.extract(variant, decompress);
            match extract {
                Ok(()) => return Ok(()),
                Err(err) => {
                    log::warn!("extracting {} failed: {:?}", archive_path.display(), err);
                    fs::remove_file(&archive_path)?;
                }
            }
        }

        for url in variant.urls(self, &self.triple) {
            log::debug!("requesting: {}", url);
            let resp = reqwest::get(&url)?;
            log::debug!("{}", resp.status());
            let reader = if resp.status().is_success() {
                XzDecoder::new(BufReader::new(resp))
            } else {
                continue;
            };
            match self.extract(variant, reader) {
                Ok(()) => return Ok(()),
                Err(err) => {
                    log::warn!("extracting {} failed: {:?}", url, err);
                    continue;
                }
            }
        }

        failure::bail!(
            "unable to download sha {} triple {} module {}",
            self.rust_sha,
            self.triple,
            variant
        );
    }

    fn extract<T: Read>(&self, variant: ModuleVariant, reader: T) -> Result<(), Error> {
        let is_std = variant == ModuleVariant::Std;
        let mut archive = Archive::new(reader);
        let std_prefix = format!("rust-std-{}/lib/rustlib", self.triple);

        let mut to_link = Vec::new();

        let unpack_into = self.directory.join(&self.rust_sha);

        for entry in archive.entries()? {
            let mut entry = entry?;
            let path = entry.path()?.into_owned();
            let mut components = path.components();
            assert!(components.next().is_some(), "strip container directory");
            let path = components.as_path();

            let path = if is_std {
                if let Ok(path) = path.strip_prefix(&std_prefix) {
                    if path.extension() == Some(OsStr::new("dylib")) {
                        to_link.push(path.to_owned());
                        continue;
                    } else {
                        Path::new("rustc/lib/rustlib").join(path)
                    }
                } else {
                    continue;
                }
            } else {
                path.into()
            };
            let path = unpack_into.join(path);
            fs::create_dir_all(&path.parent().unwrap()).with_context(|_| {
                format!(
                    "could not create intermediate directories for {}",
                    path.display()
                )
            })?;
            entry.unpack(path)?;
        }

        let link_dst_prefix = unpack_into.join(format!("rustc/lib/rustlib/{}/lib", self.triple));
        let link_src_prefix = format!("{}/lib", self.triple);
        for path in to_link {
            let src = unpack_into.join("rustc/lib").join(
                path.strip_prefix(&link_src_prefix)
                    .with_context(|_| format!("stripping prefix from: {:?}", path))?,
            );
            let dst = link_dst_prefix.join(&path);
            fs::create_dir_all(&dst.parent().unwrap()).with_context(|_| {
                format!(
                    "could not create intermediate directories for {}",
                    dst.display()
                )
            })?;
            log::trace!("linking {} to {}", src.display(), dst.display());
            fs::hard_link(src, dst)?;
        }

        Ok(())
    }
}
<|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.

// issue 7327

// xfail-fast #7103
extern mod extra;
use extra::arc::*;

struct A { y: Arc<int>, x: Arc<int> }

impl Drop for A {
    fn drop(&mut self) { println(fmt!("x=%?", self.x.get())); }
}
fn main() {
    let a = A { y: Arc::new(1), x: Arc::new(2) };
    let _b = A { y: Arc::new(3), ..a };
    let _c = a; //~ ERROR use of moved value
}
<commit_msg>fixed another test.<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.

// issue 7327

// xfail-fast #7103
extern mod extra;
use extra::arc::*;

struct A { y: Arc<int>, x: Arc<int> }

impl Drop for A {
    fn drop(&mut self) { println(fmt!("x=%?", self.x.get())); }
}
fn main() {
    let a = A { y: Arc::new(1), x: Arc::new(2) };
    let _b = A { y: Arc::new(3), ..a }; //~ ERROR cannot move out of type `A`
    let _c = a;
}
<|endoftext|>


<commit_before>// rust - simulate occasional problematic (long blocking) requests for disk IO
// language version: 1.9.0
// NOTE: does not compile yet
// to build: rustc simulated-disk-io-server.rs

use std::io;
use std::io::Read;
use std::io::Write;
use std::net::SocketAddr;
use std::net::{TcpListener, TcpStream};
use std::process;
use std::thread;
use std::thread::spawn;
use std::time::Duration;

const READ_TIMEOUT_SECS: u32 = 4;
const STATUS_OK: i32 = 0;
const STATUS_QUEUE_TIMEOUT: i32 = 1;
const STATUS_BAD_INPUT: i32 = 2;

fn current_time_millis() -> u64 {
    //TODO: time::now()
    return 0;
}

fn simulated_file_read(disk_read_time_ms: u64) {
    thread::sleep(Duration::from_millis(disk_read_time_ms));
}

//TODO: review how stream should be accepted
fn handle_socket_request(stream: TcpStream,
                         receipt_timestamp: u64) {
    // read request from client
    let mut request_text = String::new();
    if stream.read_line(&mut request_text).unwrap() > 0 {
        // did we get anything from client?
        if request_text.trim().len() > 0 {
            // determine how long the request has waited in queue
            let start_processing_timestamp = current_time_millis();
            let server_queue_time_ms =
                start_processing_timestamp - receipt_timestamp;
            let x = server_queue_time_ms / 1000;
            let server_queue_time_secs = x as u32;

            let mut rc = STATUS_OK;
            let mut disk_read_time_ms: u64 = 0;
            let mut file_path = "";

            // has this request already timed out?
            if server_queue_time_secs >= READ_TIMEOUT_SECS {
                println!("timeout (queue)");
                rc = STATUS_QUEUE_TIMEOUT;
            } else {
                let tokens: Vec<&str> = request_text.split(',').collect();
                if tokens.len() == 3 {
                    let parse_rc_result = tokens[0].parse();
                    match parse_rc_result {
                        Ok(rc_input) => {
                            let parse_time_result = tokens[1].parse();
                            match parse_time_result {
                                Ok(req_response_time_ms) => {
                                    rc = rc_input;
                                    disk_read_time_ms = req_response_time_ms;
                                    file_path = tokens[2];
                                    simulated_file_read(disk_read_time_ms);
                                }
                            }
                        }
                    }
                }
            }

            // total request time is sum of time spent in queue and the
            // simulated disk read time
            let tot_request_time_ms =
                server_queue_time_ms + disk_read_time_ms;

            // create response text
            let response_text = format!("{0},{1},{2}",
                rc,
                tot_request_time_ms,
                file_path);

            // return response text to client
            stream.write_all(response_text.as_bytes()).unwrap();
        }
    }
}

fn main() {
    let server_port = 7000;
    let listener = TcpListener::bind("127.0.0.1:7000").unwrap();
    println!("server listening on port {0}", server_port);

    for stream in listener.incoming() {
        match stream {
            Ok(mut stream) => {
                let receipt_timestamp = current_time_millis();
                thread::spawn(move|| {
                    //TODO: review how stream should be passed
                    handle_socket_request(stream, receipt_timestamp);
                });
            }
        }
    }
}

<commit_msg>get rust implementation working<commit_after>// rust - simulate occasional problematic (long blocking) requests for disk IO
// language version: 1.9.0
// to build: rustc simulated-disk-io-server.rs
// NOTE: this is my first Rust program, so much of it is probably crappy

use std::io::Read;
use std::io::Write;
use std::net::Shutdown;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::thread;
use std::time::Duration;

const READ_TIMEOUT_SECS: u32 = 4;
const STATUS_OK: i32 = 0;
const STATUS_QUEUE_TIMEOUT: i32 = 1;
//const STATUS_BAD_INPUT: i32 = 2;

fn current_time_millis() -> u64 {
    //TODO: time::now()
    return 0;
}

fn simulated_file_read(disk_read_time_ms: u64) {
    thread::sleep(Duration::from_millis(disk_read_time_ms));
}

//TODO: review how stream should be accepted
fn handle_socket_request(stream: &mut TcpStream,
                         receipt_timestamp: u64) {
    // read request from client
    //let mut request_text = String::new();
    let mut request_buffer = [0; 512];
    if stream.read(&mut request_buffer).unwrap() > 0 {
        let request_text = str::from_utf8(&request_buffer).unwrap();
        // did we get anything from client?
        if request_text.trim().len() > 0 {
            // determine how long the request has waited in queue
            let start_processing_timestamp = current_time_millis();
            let server_queue_time_ms =
                start_processing_timestamp - receipt_timestamp;
            let x = server_queue_time_ms / 1000;
            let server_queue_time_secs = x as u32;

            let mut rc = STATUS_OK;
            let mut disk_read_time_ms: u64 = 0;
            let mut file_path = "";

            // has this request already timed out?
            if server_queue_time_secs >= READ_TIMEOUT_SECS {
                println!("timeout (queue)");
                rc = STATUS_QUEUE_TIMEOUT;
            } else {
                let tokens: Vec<&str> = request_text.split(',').collect();
                if tokens.len() == 3 {
                    let parse_rc_result = tokens[0].parse();
                    match parse_rc_result {
                        Err(_) => {},
                        Ok(rc_input) => {
                            let parse_time_result = tokens[1].parse();
                            match parse_time_result {
                                Err(_) => {},
                                Ok(req_response_time_ms) => {
                                    rc = rc_input;
                                    disk_read_time_ms = req_response_time_ms;
                                    file_path = tokens[2];
                                    simulated_file_read(disk_read_time_ms);
                                }
                            }
                        }
                    }
                }
            }

            // total request time is sum of time spent in queue and the
            // simulated disk read time
            let tot_request_time_ms =
                server_queue_time_ms + disk_read_time_ms;

            // create response text
            let response_text = format!("{0},{1},{2}",
                rc,
                tot_request_time_ms,
                file_path);

            // return response text to client
            stream.write_all(response_text.as_bytes()).unwrap();
        }
    }

    let _ = stream.shutdown(Shutdown::Both);
}

fn main() {
    let server_port = 7000;
    let listener = TcpListener::bind("127.0.0.1:7000").unwrap();
    println!("server listening on port {0}", server_port);

    for stream in listener.incoming() {
        match stream {
            Err(_) => {},
            Ok(mut stream) => {
                let receipt_timestamp = current_time_millis();
                thread::spawn(move|| {
                    //TODO: review how stream should be passed
                    handle_socket_request(&mut stream, receipt_timestamp);
                });
            }
        }
    }
}

<|endoftext|>