<commit_before>extern crate getopts;
use std::io::Write;

pub struct HelpText<'a> {
    pub name : &'a str,
    pub version : &'a str,
    pub syntax : &'a str,
    pub summary : &'a str,
    pub long_help : &'a str,
    pub display_usage : bool
}

pub struct CoreOptions<'a> {
    options : getopts::Options,
    help_text : HelpText<'a>
}

impl<'a> CoreOptions<'a> {
    pub fn new(help_text: HelpText<'a>) -> Self {
        let mut ret = CoreOptions {
            options : getopts::Options::new(),
            help_text : help_text
        };
        ret.options
            .optflag("", "help", "print usage information")
            .optflag("", "version", "print name and version number");
        ret
    }
    pub fn optopt(&mut self, short_name: &str, long_name: &str, desc: &str, hint: &str) -> &mut CoreOptions<'a> {
        self.options.optopt(short_name, long_name, desc, hint);
        self
    }
    pub fn optflag(&mut self, short_name: &str, long_name: &str, desc: &str) -> &mut CoreOptions<'a> {
        self.options.optflag(short_name, long_name, desc);
        self
    }
    pub fn usage(&self, summary : &str) -> String {
        self.options.usage(summary)
    }
    pub fn parse(&mut self, args : Vec<String>) -> getopts::Matches {
        let matches = match self.options.parse(&args[1..]) {
            Ok(m) => { Some(m) },
            Err(f) => {
                pipe_write!(&mut ::std::io::stderr(), "{}: error: ", self.help_text.name);
                pipe_writeln!(&mut ::std::io::stderr(), "{}", f);
                ::std::process::exit(1);
            }
        }.unwrap();
        if matches.opt_present("help") {
            let usage_str = if self.help_text.display_usage {
                    format!("\n {}\n\n Reference\n",
                        self.options.usage(self.help_text.summary)
                    ).replace("Options:", " Options:")
                } else { String::new() };
            print!("
 {0} {1}

 {0} {2}
{3}{4}
", self.help_text.name, self.help_text.version, self.help_text.syntax, usage_str, self.help_text.long_help);
            exit!(0);
        } else if matches.opt_present("version") {
            println!("{} {}", self.help_text.name, self.help_text.version);
            exit!(0);
        }
        matches
    }
}

#[macro_export]
macro_rules! new_coreopts {
    ($syntax: expr, $summary: expr, $long_help: expr) => (
        uucore::coreopts::CoreOptions::new(uucore::coreopts::HelpText {
            name: executable!(),
            version: env!("CARGO_PKG_VERSION"),
            syntax: $syntax,
            summary: $summary,
            long_help: $long_help,
            display_usage: true
        })
    );
    ($syntax: expr, $summary: expr, $long_help: expr, $display_usage: expr) => (
        uucore::coreopts::CoreOptions::new(uucore::coreopts::HelpText {
            name: executable!(),
            version: env!("CARGO_PKG_VERSION"),
            syntax: $syntax,
            summary: $summary,
            long_help: $long_help,
            display_usage: $display_usage
        })
    );
}
<commit_msg>uucore: add support for optflagopt to coreopts<commit_after>extern crate getopts;
use std::io::Write;

pub struct HelpText<'a> {
    pub name : &'a str,
    pub version : &'a str,
    pub syntax : &'a str,
    pub summary : &'a str,
    pub long_help : &'a str,
    pub display_usage : bool
}

pub struct CoreOptions<'a> {
    options : getopts::Options,
    help_text : HelpText<'a>
}

impl<'a> CoreOptions<'a> {
    pub fn new(help_text: HelpText<'a>) -> Self {
        let mut ret = CoreOptions {
            options : getopts::Options::new(),
            help_text : help_text
        };
        ret.options
            .optflag("", "help", "print usage information")
            .optflag("", "version", "print name and version number");
        ret
    }
    pub fn optflagopt(&mut self, short_name: &str, long_name: &str, desc: &str, hint: &str) -> &mut CoreOptions<'a> {
        self.options.optflagopt(short_name, long_name, desc, hint);
        self
    }
    pub fn optflag(&mut self, short_name: &str, long_name: &str, desc: &str) -> &mut CoreOptions<'a> {
        self.options.optflag(short_name, long_name, desc);
        self
    }
    pub fn optopt(&mut self, short_name: &str, long_name: &str, desc: &str, hint: &str) -> &mut CoreOptions<'a> {
        self.options.optopt(short_name, long_name, desc, hint);
        self
    }
    pub fn usage(&self, summary : &str) -> String {
        self.options.usage(summary)
    }
    pub fn parse(&mut self, args : Vec<String>) -> getopts::Matches {
        let matches = match self.options.parse(&args[1..]) {
            Ok(m) => { Some(m) },
            Err(f) => {
                pipe_write!(&mut ::std::io::stderr(), "{}: error: ", self.help_text.name);
                pipe_writeln!(&mut ::std::io::stderr(), "{}", f);
                ::std::process::exit(1);
            }
        }.unwrap();
        if matches.opt_present("help") {
            let usage_str = if self.help_text.display_usage {
                    format!("\n {}\n\n Reference\n",
                        self.options.usage(self.help_text.summary)
                    ).replace("Options:", " Options:")
                } else { String::new() };
            print!("
 {0} {1}

 {0} {2}
{3}{4}
", self.help_text.name, self.help_text.version, self.help_text.syntax, usage_str, self.help_text.long_help);
            exit!(0);
        } else if matches.opt_present("version") {
            println!("{} {}", self.help_text.name, self.help_text.version);
            exit!(0);
        }
        matches
    }
}

#[macro_export]
macro_rules! new_coreopts {
    ($syntax: expr, $summary: expr, $long_help: expr) => (
        uucore::coreopts::CoreOptions::new(uucore::coreopts::HelpText {
            name: executable!(),
            version: env!("CARGO_PKG_VERSION"),
            syntax: $syntax,
            summary: $summary,
            long_help: $long_help,
            display_usage: true
        })
    );
    ($syntax: expr, $summary: expr, $long_help: expr, $display_usage: expr) => (
        uucore::coreopts::CoreOptions::new(uucore::coreopts::HelpText {
            name: executable!(),
            version: env!("CARGO_PKG_VERSION"),
            syntax: $syntax,
            summary: $summary,
            long_help: $long_help,
            display_usage: $display_usage
        })
    );
}
<|endoftext|>


<commit_before>use std::ptr::null;
use libc::{c_char, c_int, c_double};
use std::ffi::CString;
use utils::_string;
use vector::{ogr, geom};
use GdalError;

pub struct Geometry {
    c_geometry: *const (),
    owned: bool,
}

impl Geometry {
    pub unsafe fn from_gdal_ptr(c_geometry: *const ()) -> Geometry {
        // c_geometry is owned by a Feature. The Feature must own this
        // Geometry and destroy it when the Feature is destroyed.
        return Geometry{c_geometry: c_geometry, owned: false};
    }

    pub fn empty(wkb_type: c_int) -> Geometry {
        let c_geom = unsafe { ogr::OGR_G_CreateGeometry(wkb_type) };
        assert!(c_geom != null());
        return Geometry{c_geometry: c_geom, owned: true};
    }

    pub fn from_wkt(wkt: &str) -> Geometry {
        let c_wkt = CString::new(wkt.as_bytes()).unwrap();
        let mut c_wkt_ptr: *const c_char = c_wkt.as_ptr();
        let mut c_geom: *const () = null();
        let rv = unsafe { ogr::OGR_G_CreateFromWkt(&mut c_wkt_ptr, null(), &mut c_geom) };
        assert_eq!(rv, ogr::OGRERR_NONE);
        return Geometry{c_geometry: c_geom, owned: true};
    }

    pub fn bbox(w: f64, s: f64, e: f64, n: f64) -> Geometry {
        Geometry::from_wkt(&format!(
            "POLYGON (({} {}, {} {}, {} {}, {} {}, {} {}))",
            w, n,
            e, n,
            e, s,
            w, s,
            w, n,
        ))
    }

    pub fn json(&self) -> String {
        let c_json = unsafe { ogr::OGR_G_ExportToJson(self.c_geometry) };
        let rv = _string(c_json);
        unsafe { ogr::VSIFree(c_json as *mut ()) };
        return rv;
    }

    pub fn wkt(&self) -> String {
        let mut c_wkt: *const c_char = null();
        let _err = unsafe { ogr::OGR_G_ExportToWkt(self.c_geometry, &mut c_wkt) };
        assert_eq!(_err, ogr::OGRERR_NONE);
        let wkt = _string(c_wkt);
        unsafe { ogr::OGRFree(c_wkt as *mut ()) };
        return wkt;
    }

    pub unsafe fn c_geometry(&self) -> *const () {
        return self.c_geometry;
    }

    pub fn set_point_2d(&mut self, i: i32, p: (f64, f64)) {
        let (x, y) = p;
        unsafe { ogr::OGR_G_SetPoint_2D(
            self.c_geometry,
            i as c_int,
            x as c_double,
            y as c_double,
        ) };
    }

    pub fn get_point(&self, i: i32) -> (f64, f64, f64) {
        let mut x: c_double = 0.;
        let mut y: c_double = 0.;
        let mut z: c_double = 0.;
        unsafe { ogr::OGR_G_GetPoint(self.c_geometry, i, &mut x, &mut y, &mut z) };
        return (x as f64, y as f64, z as f64);
    }

    pub fn to_geom(&self) -> Result<geom::Geom, GdalError> {
        let geometry_type = unsafe { ogr::OGR_G_GetGeometryType(self.c_geometry) };
        match geometry_type {
            1 => {
                let (x, y, _) = self.get_point(0);
                Ok(geom::Geom::Point(geom::Point{x: x, y: y}))
            },
            _ => Err(GdalError{desc: "Unknown geometry type"})
        }
    }
}

impl Drop for Geometry {
    fn drop(&mut self) {
        if self.owned {
            unsafe { ogr::OGR_G_DestroyGeometry(self.c_geometry as *mut ()) };
        }
    }
}

pub trait ToGdal {
    fn to_gdal(&self) -> Geometry;
}

impl ToGdal for geom::Point {
    fn to_gdal(&self) -> Geometry {
        let mut geom = Geometry::empty(ogr::WKB_POINT);
        geom.set_point_2d(0, (self.x, self.y));
        return geom;
    }
}

#[cfg(test)]
mod tests {
    use vector::{Geometry, ToGdal};
    use vector::geom::{Geom, Point};

    #[test]
    fn test_ogr_to_point() {
        let g = Geometry::from_wkt("POINT (10 20)");
        assert_eq!(g.to_geom(), Ok(Geom::Point(Point{x: 10., y: 20.})));
    }

    #[test]
    fn test_point_to_ogr() {
        let g = Point{x: 10., y: 20.}.to_gdal();
        assert_eq!(g.wkt(), "POINT (10 20)");
    }
}
<commit_msg>get c_geometry via method<commit_after>use std::ptr::null;
use libc::{c_char, c_int, c_double};
use std::ffi::CString;
use utils::_string;
use vector::{ogr, geom};
use GdalError;

pub struct Geometry {
    c_geometry: *const (),
    owned: bool,
}

impl Geometry {
    pub unsafe fn from_gdal_ptr(c_geometry: *const ()) -> Geometry {
        // c_geometry is owned by a Feature. The Feature must own this
        // Geometry and destroy it when the Feature is destroyed.
        return Geometry{c_geometry: c_geometry, owned: false};
    }

    pub fn empty(wkb_type: c_int) -> Geometry {
        let c_geom = unsafe { ogr::OGR_G_CreateGeometry(wkb_type) };
        assert!(c_geom != null());
        return Geometry{c_geometry: c_geom, owned: true};
    }

    pub fn from_wkt(wkt: &str) -> Geometry {
        let c_wkt = CString::new(wkt.as_bytes()).unwrap();
        let mut c_wkt_ptr: *const c_char = c_wkt.as_ptr();
        let mut c_geom: *const () = null();
        let rv = unsafe { ogr::OGR_G_CreateFromWkt(&mut c_wkt_ptr, null(), &mut c_geom) };
        assert_eq!(rv, ogr::OGRERR_NONE);
        return Geometry{c_geometry: c_geom, owned: true};
    }

    pub fn bbox(w: f64, s: f64, e: f64, n: f64) -> Geometry {
        Geometry::from_wkt(&format!(
            "POLYGON (({} {}, {} {}, {} {}, {} {}, {} {}))",
            w, n,
            e, n,
            e, s,
            w, s,
            w, n,
        ))
    }

    pub fn json(&self) -> String {
        let c_json = unsafe { ogr::OGR_G_ExportToJson(self.c_geometry()) };
        let rv = _string(c_json);
        unsafe { ogr::VSIFree(c_json as *mut ()) };
        return rv;
    }

    pub fn wkt(&self) -> String {
        let mut c_wkt: *const c_char = null();
        let _err = unsafe { ogr::OGR_G_ExportToWkt(self.c_geometry(), &mut c_wkt) };
        assert_eq!(_err, ogr::OGRERR_NONE);
        let wkt = _string(c_wkt);
        unsafe { ogr::OGRFree(c_wkt as *mut ()) };
        return wkt;
    }

    pub unsafe fn c_geometry(&self) -> *const () {
        return self.c_geometry;
    }

    pub fn set_point_2d(&mut self, i: i32, p: (f64, f64)) {
        let (x, y) = p;
        unsafe { ogr::OGR_G_SetPoint_2D(
            self.c_geometry(),
            i as c_int,
            x as c_double,
            y as c_double,
        ) };
    }

    pub fn get_point(&self, i: i32) -> (f64, f64, f64) {
        let mut x: c_double = 0.;
        let mut y: c_double = 0.;
        let mut z: c_double = 0.;
        unsafe { ogr::OGR_G_GetPoint(self.c_geometry(), i, &mut x, &mut y, &mut z) };
        return (x as f64, y as f64, z as f64);
    }

    pub fn to_geom(&self) -> Result<geom::Geom, GdalError> {
        let geometry_type = unsafe { ogr::OGR_G_GetGeometryType(self.c_geometry()) };
        match geometry_type {
            1 => {
                let (x, y, _) = self.get_point(0);
                Ok(geom::Geom::Point(geom::Point{x: x, y: y}))
            },
            _ => Err(GdalError{desc: "Unknown geometry type"})
        }
    }
}

impl Drop for Geometry {
    fn drop(&mut self) {
        if self.owned {
            unsafe { ogr::OGR_G_DestroyGeometry(self.c_geometry as *mut ()) };
        }
    }
}

pub trait ToGdal {
    fn to_gdal(&self) -> Geometry;
}

impl ToGdal for geom::Point {
    fn to_gdal(&self) -> Geometry {
        let mut geom = Geometry::empty(ogr::WKB_POINT);
        geom.set_point_2d(0, (self.x, self.y));
        return geom;
    }
}

#[cfg(test)]
mod tests {
    use vector::{Geometry, ToGdal};
    use vector::geom::{Geom, Point};

    #[test]
    fn test_ogr_to_point() {
        let g = Geometry::from_wkt("POINT (10 20)");
        assert_eq!(g.to_geom(), Ok(Geom::Point(Point{x: 10., y: 20.})));
    }

    #[test]
    fn test_point_to_ogr() {
        let g = Point{x: 10., y: 20.}.to_gdal();
        assert_eq!(g.wkt(), "POINT (10 20)");
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Grove Enterprises LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[cfg(target_family = "unix")]
use liner::Context;
use std::io;

const DEFAULT_PROMPT: &'static str = "datafusion> ";
const CONTINUE_PROMPT: &'static str = "> ";

#[cfg(target_family = "unix")]
pub enum LineResult {
    Break,
    Input(String),
}

#[cfg(target_family = "unix")]
pub struct LineReader<'a> {
    reader: Context,
    prompt: &'a str,
}

#[cfg(target_family = "unix")]
impl<'a> LineReader<'a> {
    pub fn new() -> Self {
        LineReader {
            reader: Context::new(),
            prompt: DEFAULT_PROMPT,
        }
    }

    pub fn set_prompt(&mut self, prompt: &'a str) {
        self.prompt = prompt;
    }

    pub fn read_lines(&mut self) -> Option<LineResult> {
        let mut result = String::new();
        loop {
            let line = self.reader.read_line(self.prompt, &mut |_| {});

            match line {
                Ok(i) => {
                    result.push_str(i.as_str());

                    match i.as_str() {
                        "quit" | "exit" => {
                            return Some(LineResult::Break);
                        }
                        _ => {
                            // Handle the two types of statements, Default and Continue.
                            // CONTINUE: are statements that don't end with a semicolon
                            // DEFAULT: are statements that end with a semicolon
                            // and can be returned to being executed.
                            if i.as_str().ends_with(';') {
                                self.set_prompt(DEFAULT_PROMPT);
                                break;
                            } else {
                                self.set_prompt(CONTINUE_PROMPT);
                                result.push_str(" ");
                                continue;
                            }
                        }
                    }
                }
                Err(e) => {
                    match e.kind() {
                        // ctrl-c pressed
                        io::ErrorKind::Interrupted => {}
                        // ctrl-d pressed
                        io::ErrorKind::UnexpectedEof => {
                            return Some(LineResult::Break);
                        }
                        _ => {
                            // Ensure that all writes to the history file
                            // are written before exiting.
                            self.reader.history.commit_history();
                            panic!("error: {:?}", e)
                        }
                    }
                }
            };
        }

        if !result.trim().is_empty() {
            self.reader.history.push(result.clone().into()).unwrap();
        }

        // Return the command without semicolon
        Some(LineResult::Input(result[..result.len() - 1].to_string()))
    }
}
<commit_msg>console: allow for "SELECT 1; " (trailing whitespace) (#164)<commit_after>// Copyright 2018 Grove Enterprises LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[cfg(target_family = "unix")]
use liner::Context;
use std::io;

const DEFAULT_PROMPT: &'static str = "datafusion> ";
const CONTINUE_PROMPT: &'static str = "> ";

#[cfg(target_family = "unix")]
pub enum LineResult {
    Break,
    Input(String),
}

#[cfg(target_family = "unix")]
pub struct LineReader<'a> {
    reader: Context,
    prompt: &'a str,
}

#[cfg(target_family = "unix")]
impl<'a> LineReader<'a> {
    pub fn new() -> Self {
        LineReader {
            reader: Context::new(),
            prompt: DEFAULT_PROMPT,
        }
    }

    pub fn set_prompt(&mut self, prompt: &'a str) {
        self.prompt = prompt;
    }

    pub fn read_lines(&mut self) -> Option<LineResult> {
        let mut result = String::new();
        loop {
            let line = self.reader.read_line(self.prompt, &mut |_| {});

            match line {
                Ok(i) => {
                    let j = i.as_str().trim_right();
                    result.push_str(j);

                    match j {
                        "quit" | "exit" => {
                            return Some(LineResult::Break);
                        }
                        _ => {
                            // Handle the two types of statements, Default and Continue.
                            // CONTINUE: are statements that don't end with a semicolon
                            // DEFAULT: are statements that end with a semicolon
                            // and can be returned to being executed.
                            if j.ends_with(';') {
                                self.set_prompt(DEFAULT_PROMPT);
                                break;
                            } else {
                                self.set_prompt(CONTINUE_PROMPT);
                                result.push_str(" ");
                                continue;
                            }
                        }
                    }
                }
                Err(e) => {
                    match e.kind() {
                        // ctrl-c pressed
                        io::ErrorKind::Interrupted => {}
                        // ctrl-d pressed
                        io::ErrorKind::UnexpectedEof => {
                            return Some(LineResult::Break);
                        }
                        _ => {
                            // Ensure that all writes to the history file
                            // are written before exiting.
                            self.reader.history.commit_history();
                            panic!("error: {:?}", e)
                        }
                    }
                }
            };
        }

        if !result.trim().is_empty() {
            self.reader.history.push(result.clone().into()).unwrap();
        }

        // Return the command without semicolon
        Some(LineResult::Input(result[..result.len() - 1].to_string()))
    }
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2018 Guillaume Gomez
//

use std::fmt::{self, Formatter, Debug};
use std::mem::{size_of, zeroed};
use std::path::{Path, PathBuf};
use std::str;

use libc::{c_uint, c_void, memcpy};

use Pid;
use ProcessExt;

use winapi::shared::minwindef::{DWORD, FALSE, FILETIME, MAX_PATH/*, TRUE, USHORT*/};
use winapi::um::handleapi::CloseHandle;
use winapi::um::winnt::{
    HANDLE, ULARGE_INTEGER, /*THREAD_GET_CONTEXT, THREAD_QUERY_INFORMATION, THREAD_SUSPEND_RESUME,*/
    /*, PWSTR*/ PROCESS_QUERY_INFORMATION, PROCESS_TERMINATE, PROCESS_VM_READ,
};
use winapi::um::processthreadsapi::{GetProcessTimes, OpenProcess, TerminateProcess};
use winapi::um::psapi::{
    GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS, PROCESS_MEMORY_COUNTERS_EX,
    EnumProcessModulesEx, GetModuleBaseNameW, GetModuleFileNameExW, LIST_MODULES_ALL,
};
use winapi::um::sysinfoapi::GetSystemTimeAsFileTime;
use winapi::um::tlhelp32::{
    CreateToolhelp32Snapshot, Process32First, Process32Next, PROCESSENTRY32, TH32CS_SNAPPROCESS,
};

/// Enum describing the different status of a process.
#[derive(Clone, Copy, Debug)]
pub enum ProcessStatus {
    /// Currently runnable.
    Run,
}

impl ProcessStatus {
    /// Used to display `ProcessStatus`.
    pub fn to_string(&self) -> &str {
        match *self {
            ProcessStatus::Run => "Runnable",
        }
    }
}

impl fmt::Display for ProcessStatus {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.to_string())
    }
}

fn get_process_handler(pid: Pid) -> Option<HANDLE> {
    if pid == 0 {
        return None;
    }
    let options = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE;
    let process_handler = unsafe { OpenProcess(options, FALSE, pid as DWORD) };
    if process_handler.is_null() {
        let options = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
        let process_handler = unsafe { OpenProcess(options, FALSE, pid as DWORD) };
        if process_handler.is_null() {
            None
        } else {
            Some(process_handler)
        }
    } else {
        Some(process_handler)
    }
}

/// Struct containing a process' information.
#[derive(Clone)]
pub struct Process {
    name: String,
    cmd: Vec<String>,
    exe: PathBuf,
    pid: Pid,
    environ: Vec<String>,
    cwd: PathBuf,
    root: PathBuf,
    memory: u64,
    parent: Option<Pid>,
    status: ProcessStatus,
    handle: HANDLE,
    old_cpu: u64,
    old_sys_cpu: u64,
    old_user_cpu: u64,
    start_time: u64,
    cpu_usage: f32,
}

// TODO: it's possible to get environment variables like it's done in
// https://github.com/processhacker/processhacker
//
// They have a very nice function called PhGetProcessEnvironment. Just very complicated as it
// seems...
impl ProcessExt for Process {
    fn new(pid: Pid, parent: Option<Pid>, _: u64) -> Process {
        if let Some(process_handler) = get_process_handler(pid) {
            let mut h_mod = ::std::ptr::null_mut();
            let mut process_name = [0u16; MAX_PATH + 1];
            let mut cb_needed = 0;

            unsafe {
                if EnumProcessModulesEx(process_handler,
                                        &mut h_mod,
                                        ::std::mem::size_of::<DWORD>() as DWORD,
                                        &mut cb_needed,
                                        LIST_MODULES_ALL) != 0 {
                    GetModuleBaseNameW(process_handler,
                                       h_mod,
                                       process_name.as_mut_ptr(),
                                       MAX_PATH as DWORD + 1);
                }
                let mut pos = 0;
                for x in process_name.iter() {
                    if *x == 0 {
                        break
                    }
                    pos += 1;
                }
                let name = String::from_utf16_lossy(&process_name[..pos]);
                let environ = get_proc_env(process_handler, pid as u32, &name);

                let mut root_buf = [0u16; MAX_PATH + 1];
                GetModuleFileNameExW(process_handler,
                                     h_mod,
                                     root_buf.as_mut_ptr(),
                                     MAX_PATH as DWORD + 1);

                pos = 0;
                for x in root_buf.iter() {
                    if *x == 0 {
                        break
                    }
                    pos += 1;
                }

                let root = String::from_utf16_lossy(&root_buf[..pos]);
                Process {
                    handle: process_handler,
                    name: name,
                    pid: pid,
                    parent: parent,
                    cmd: get_cmd_line(pid),
                    environ: environ,
                    exe: get_executable_path(pid),
                    cwd: PathBuf::new(),
                    root: PathBuf::from(root),
                    status: ProcessStatus::Run,
                    memory: 0,
                    cpu_usage: 0.,
                    old_cpu: 0,
                    old_sys_cpu: 0,
                    old_user_cpu: 0,
                    start_time: get_start_time(process_handler),
                }
            }
        } else {
            Process {
                handle: ::std::ptr::null_mut(),
                name: String::new(),
                pid: pid,
                parent: parent,
                cmd: get_cmd_line(pid),
                environ: Vec::new(),
                exe: get_executable_path(pid),
                cwd: PathBuf::new(),
                root: PathBuf::new(),
                status: ProcessStatus::Run,
                memory: 0,
                cpu_usage: 0.,
                old_cpu: 0,
                old_sys_cpu: 0,
                old_user_cpu: 0,
                start_time: 0,
            }
        }
    }

    fn kill(&self, signal: ::Signal) -> bool {
        let x = unsafe { TerminateProcess(self.handle, signal as c_uint) };
        x != 0
    }

    fn name(&self) -> &str {
        &self.name
    }

    fn cmd(&self) -> &[String] {
        &self.cmd
    }

    fn exe(&self) -> &Path {
        self.exe.as_path()
    }

    fn pid(&self) -> Pid {
        self.pid
    }

    fn environ(&self) -> &[String] {
        &self.environ
    }

    fn cwd(&self) -> &Path {
        self.cwd.as_path()
    }

    fn root(&self) -> &Path {
        self.root.as_path()
    }

    fn memory(&self) -> u64 {
        self.memory
    }

    fn parent(&self) -> Option<Pid> {
        self.parent
    }

    fn status(&self) -> ProcessStatus {
        self.status
    }

    fn start_time(&self) -> u64 {
        self.start_time
    }

    fn cpu_usage(&self) -> f32 {
        self.cpu_usage
    }
}

impl Drop for Process {
    fn drop(&mut self) {
        unsafe {
            if self.handle.is_null() {
                return
            }
            CloseHandle(self.handle);
        }
    }
}

#[allow(unused_must_use)]
impl Debug for Process {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        writeln!(f, "pid: {}", self.pid);
        writeln!(f, "name: {}", self.name);
        writeln!(f, "environment:");
        for var in self.environ.iter() {
        if var.len() > 0 {
                writeln!(f, "\t{}", var);
            }
        }
        writeln!(f, "command:");
        for arg in &self.cmd {
            writeln!(f, "\t{}", arg);
        }
        writeln!(f, "executable path: {:?}", self.exe);
        writeln!(f, "current working directory: {:?}", self.cwd);
        writeln!(f, "memory usage: {} kB", self.memory);
        writeln!(f, "cpu usage: {}", self.cpu_usage);
        writeln!(f, "root path: {:?}", self.root)
    }
}

unsafe fn get_start_time(handle: HANDLE) -> u64 {
    let mut fstart: FILETIME = zeroed();
    let mut x = zeroed();

    GetProcessTimes(handle,
                    &mut fstart as *mut FILETIME,
                    &mut x as *mut FILETIME,
                    &mut x as *mut FILETIME,
                    &mut x as *mut FILETIME);
    let tmp = (fstart.dwHighDateTime as u64) << 32 | (fstart.dwLowDateTime as u64);
    tmp / 10_000_000 - 11_644_473_600
}

pub unsafe fn get_parent_process_id(pid: Pid) -> Option<Pid> {
    let snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    let mut entry: PROCESSENTRY32 = zeroed();
    entry.dwSize = size_of::<PROCESSENTRY32>() as u32;
    let mut not_the_end = Process32First(snapshot, &mut entry);
    while not_the_end != 0 {
        if pid == entry.th32ProcessID as usize {
            // TODO: if some day I have the motivation to add threads:
            // ListProcessThreads(entry.th32ProcessID);
            CloseHandle(snapshot);
            return Some(entry.th32ParentProcessID as usize);
        }
        not_the_end = Process32Next(snapshot, &mut entry);
    }
    CloseHandle(snapshot);
    None
}

/*fn run_wmi(args: &[&str]) -> Option<String> {
    use std::process::Command;

    if let Ok(out) = Command::new("wmic")
                             .args(args)
                             .output() {
        if out.status.success() {
            return Some(String::from_utf8_lossy(&out.stdout).into_owned());
        }
    }
    None
}*/

fn get_cmd_line(_pid: Pid) -> Vec<String> {
    /*let where_req = format!("ProcessId={}", pid);

    if let Some(ret) = run_wmi(&["process", "where", &where_req, "get", "CommandLine"]) {
        for line in ret.lines() {
            if line.is_empty() || line == "CommandLine" {
                continue
            }
            return vec![line.to_owned()];
        }
    }*/
    Vec::new()
}

unsafe fn get_proc_env(_handle: HANDLE, _pid: u32, _name: &str) -> Vec<String> {
    let ret = Vec::new();
    /*
    println!("current pid: {}", kernel32::GetCurrentProcessId());
    if kernel32::GetCurrentProcessId() == pid {
        println!("current proc!");
        for (key, value) in env::vars() {
            ret.push(format!("{}={}", key, value));
        }
        return ret;
    }
    println!("1");
    let snapshot_handle = kernel32::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if !snapshot_handle.is_null() {
        println!("2");
        let mut target_thread: THREADENTRY32 = zeroed();
        target_thread.dwSize = size_of::<THREADENTRY32>() as DWORD;
        if kernel32::Thread32First(snapshot_handle, &mut target_thread) == TRUE {
            println!("3");
            loop {
                if target_thread.th32OwnerProcessID == pid {
                    println!("4");
                    let thread_handle = kernel32::OpenThread(THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION | THREAD_GET_CONTEXT,
                                                             FALSE,
                                                             target_thread.th32ThreadID);
                    if !thread_handle.is_null() {
                        println!("5 -> {}", pid);
                        if kernel32::SuspendThread(thread_handle) != DWORD::max_value() {
                            println!("6");
                            let mut context = zeroed();
                            if kernel32::GetThreadContext(thread_handle, &mut context) != 0 {
                                println!("7 --> {:?}", context);
                                let mut x = vec![0u8; 10];
                                if kernel32::ReadProcessMemory(handle,
                                                               context.MxCsr as usize as *mut winapi::c_void,
                                                               x.as_mut_ptr() as *mut winapi::c_void,
                                                               x.len() as u64,
                                                               ::std::ptr::null_mut()) != 0 {
                                    for y in x {
                                        print!("{}", y as char);
                                    }
                                    println!("");
                                } else {
                                    println!("failure... {:?}", kernel32::GetLastError());
                                }
                            } else {
                                println!("-> {:?}", kernel32::GetLastError());
                            }
                            kernel32::ResumeThread(thread_handle);
                        }
                        kernel32::CloseHandle(thread_handle);
                    }
                    break;
                }
                if kernel32::Thread32Next(snapshot_handle, &mut target_thread) != TRUE {
                    break;
                }
            }
        }
        kernel32::CloseHandle(snapshot_handle);
    }*/
    ret
}

pub fn get_executable_path(_pid: Pid) -> PathBuf {
    /*let where_req = format!("ProcessId={}", pid);

    if let Some(ret) = run_wmi(&["process", "where", &where_req, "get", "ExecutablePath"]) {
        for line in ret.lines() {
            if line.is_empty() || line == "ExecutablePath" {
                continue
            }
            return line.to_owned();
        }
    }*/
    PathBuf::new()
}

pub fn compute_cpu_usage(p: &mut Process, nb_processors: u64) {
    unsafe {
        let mut now: ULARGE_INTEGER = ::std::mem::zeroed();
        let mut sys: ULARGE_INTEGER = ::std::mem::zeroed();
        let mut user: ULARGE_INTEGER = ::std::mem::zeroed();
        let mut ftime: FILETIME = zeroed();
        let mut fsys: FILETIME = zeroed();
        let mut fuser: FILETIME = zeroed();

        GetSystemTimeAsFileTime(&mut ftime);
        memcpy(&mut now as *mut ULARGE_INTEGER as *mut c_void,
               &mut ftime as *mut FILETIME as *mut c_void,
               size_of::<FILETIME>());

        GetProcessTimes(p.handle,
                        &mut ftime as *mut FILETIME,
                        &mut ftime as *mut FILETIME,
                        &mut fsys as *mut FILETIME,
                        &mut fuser as *mut FILETIME);
        memcpy(&mut sys as *mut ULARGE_INTEGER as *mut c_void,
               &mut fsys as *mut FILETIME as *mut c_void,
               size_of::<FILETIME>());
        memcpy(&mut user as *mut ULARGE_INTEGER as *mut c_void,
               &mut fuser as *mut FILETIME as *mut c_void,
               size_of::<FILETIME>());
        p.cpu_usage = ((*sys.QuadPart() - p.old_sys_cpu) as f32 +
            (*user.QuadPart() - p.old_user_cpu) as f32)
            / (*now.QuadPart() - p.old_cpu) as f32
            / nb_processors as f32 * 100.;
        p.old_cpu = *now.QuadPart();
        p.old_user_cpu = *user.QuadPart();
        p.old_sys_cpu = *sys.QuadPart();
    }
}

pub fn get_handle(p: &Process) -> HANDLE {
    p.handle
}

pub fn update_proc_info(p: &mut Process) {
    update_memory(p);
}

pub fn update_memory(p: &mut Process) {
    unsafe {
        let mut pmc: PROCESS_MEMORY_COUNTERS_EX = zeroed();
        if GetProcessMemoryInfo(p.handle,
                                &mut pmc as *mut PROCESS_MEMORY_COUNTERS_EX as *mut c_void as *mut PROCESS_MEMORY_COUNTERS,
                                size_of::<PROCESS_MEMORY_COUNTERS_EX>() as DWORD) != 0 {
            p.memory = (pmc.PrivateUsage as u64) >> 10u64; // / 1024;
        }
    }
}
<commit_msg>Windows: get exe path and correct root<commit_after>//
// Sysinfo
//
// Copyright (c) 2018 Guillaume Gomez
//

use std::fmt::{self, Formatter, Debug};
use std::mem::{size_of, zeroed};
use std::path::{Path, PathBuf};
use std::str;

use libc::{c_uint, c_void, memcpy};

use Pid;
use ProcessExt;

use winapi::shared::minwindef::{DWORD, FALSE, FILETIME, MAX_PATH/*, TRUE, USHORT*/};
use winapi::um::handleapi::CloseHandle;
use winapi::um::winnt::{
    HANDLE, ULARGE_INTEGER, /*THREAD_GET_CONTEXT, THREAD_QUERY_INFORMATION, THREAD_SUSPEND_RESUME,*/
    /*, PWSTR*/ PROCESS_QUERY_INFORMATION, PROCESS_TERMINATE, PROCESS_VM_READ,
};
use winapi::um::processthreadsapi::{GetProcessTimes, OpenProcess, TerminateProcess};
use winapi::um::psapi::{
    GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS, PROCESS_MEMORY_COUNTERS_EX,
    EnumProcessModulesEx, GetModuleBaseNameW, GetModuleFileNameExW, LIST_MODULES_ALL,
};
use winapi::um::sysinfoapi::GetSystemTimeAsFileTime;
use winapi::um::tlhelp32::{
    CreateToolhelp32Snapshot, Process32First, Process32Next, PROCESSENTRY32, TH32CS_SNAPPROCESS,
};

/// Enum describing the different status of a process.
#[derive(Clone, Copy, Debug)]
pub enum ProcessStatus {
    /// Currently runnable.
    Run,
}

impl ProcessStatus {
    /// Used to display `ProcessStatus`.
    pub fn to_string(&self) -> &str {
        match *self {
            ProcessStatus::Run => "Runnable",
        }
    }
}

impl fmt::Display for ProcessStatus {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.to_string())
    }
}

fn get_process_handler(pid: Pid) -> Option<HANDLE> {
    if pid == 0 {
        return None;
    }
    let options = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE;
    let process_handler = unsafe { OpenProcess(options, FALSE, pid as DWORD) };
    if process_handler.is_null() {
        let options = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
        let process_handler = unsafe { OpenProcess(options, FALSE, pid as DWORD) };
        if process_handler.is_null() {
            None
        } else {
            Some(process_handler)
        }
    } else {
        Some(process_handler)
    }
}

/// Struct containing a process' information.
#[derive(Clone)]
pub struct Process {
    name: String,
    cmd: Vec<String>,
    exe: PathBuf,
    pid: Pid,
    environ: Vec<String>,
    cwd: PathBuf,
    root: PathBuf,
    memory: u64,
    parent: Option<Pid>,
    status: ProcessStatus,
    handle: HANDLE,
    old_cpu: u64,
    old_sys_cpu: u64,
    old_user_cpu: u64,
    start_time: u64,
    cpu_usage: f32,
}

// TODO: it's possible to get environment variables like it's done in
// https://github.com/processhacker/processhacker
//
// They have a very nice function called PhGetProcessEnvironment. Just very complicated as it
// seems...
impl ProcessExt for Process {
    fn new(pid: Pid, parent: Option<Pid>, _: u64) -> Process {
        if let Some(process_handler) = get_process_handler(pid) {
            let mut h_mod = ::std::ptr::null_mut();
            let mut process_name = [0u16; MAX_PATH + 1];
            let mut cb_needed = 0;

            unsafe {
                if EnumProcessModulesEx(process_handler,
                                        &mut h_mod,
                                        ::std::mem::size_of::<DWORD>() as DWORD,
                                        &mut cb_needed,
                                        LIST_MODULES_ALL) != 0 {
                    GetModuleBaseNameW(process_handler,
                                       h_mod,
                                       process_name.as_mut_ptr(),
                                       MAX_PATH as DWORD + 1);
                }
                let mut pos = 0;
                for x in process_name.iter() {
                    if *x == 0 {
                        break
                    }
                    pos += 1;
                }
                let name = String::from_utf16_lossy(&process_name[..pos]);
                let environ = get_proc_env(process_handler, pid as u32, &name);

                let mut exe_buf = [0u16; MAX_PATH + 1];
                GetModuleFileNameExW(process_handler,
                                     h_mod,
                                     exe_buf.as_mut_ptr(),
                                     MAX_PATH as DWORD + 1);

                pos = 0;
                for x in exe_buf.iter() {
                    if *x == 0 {
                        break
                    }
                    pos += 1;
                }

                let exe = PathBuf::from(String::from_utf16_lossy(&exe_buf[..pos]));
                let mut root = exe.clone();
                root.pop();
                Process {
                    handle: process_handler,
                    name: name,
                    pid: pid,
                    parent: parent,
                    cmd: get_cmd_line(pid),
                    environ: environ,
                    exe: exe,
                    cwd: PathBuf::new(),
                    root: root,
                    status: ProcessStatus::Run,
                    memory: 0,
                    cpu_usage: 0.,
                    old_cpu: 0,
                    old_sys_cpu: 0,
                    old_user_cpu: 0,
                    start_time: get_start_time(process_handler),
                }
            }
        } else {
            Process {
                handle: ::std::ptr::null_mut(),
                name: String::new(),
                pid: pid,
                parent: parent,
                cmd: get_cmd_line(pid),
                environ: Vec::new(),
                exe: get_executable_path(pid),
                cwd: PathBuf::new(),
                root: PathBuf::new(),
                status: ProcessStatus::Run,
                memory: 0,
                cpu_usage: 0.,
                old_cpu: 0,
                old_sys_cpu: 0,
                old_user_cpu: 0,
                start_time: 0,
            }
        }
    }

    fn kill(&self, signal: ::Signal) -> bool {
        let x = unsafe { TerminateProcess(self.handle, signal as c_uint) };
        x != 0
    }

    fn name(&self) -> &str {
        &self.name
    }

    fn cmd(&self) -> &[String] {
        &self.cmd
    }

    fn exe(&self) -> &Path {
        self.exe.as_path()
    }

    fn pid(&self) -> Pid {
        self.pid
    }

    fn environ(&self) -> &[String] {
        &self.environ
    }

    fn cwd(&self) -> &Path {
        self.cwd.as_path()
    }

    fn root(&self) -> &Path {
        self.root.as_path()
    }

    fn memory(&self) -> u64 {
        self.memory
    }

    fn parent(&self) -> Option<Pid> {
        self.parent
    }

    fn status(&self) -> ProcessStatus {
        self.status
    }

    fn start_time(&self) -> u64 {
        self.start_time
    }

    fn cpu_usage(&self) -> f32 {
        self.cpu_usage
    }
}

impl Drop for Process {
    fn drop(&mut self) {
        unsafe {
            if self.handle.is_null() {
                return
            }
            CloseHandle(self.handle);
        }
    }
}

#[allow(unused_must_use)]
impl Debug for Process {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        writeln!(f, "pid: {}", self.pid);
        writeln!(f, "name: {}", self.name);
        writeln!(f, "environment:");
        for var in self.environ.iter() {
        if var.len() > 0 {
                writeln!(f, "\t{}", var);
            }
        }
        writeln!(f, "command:");
        for arg in &self.cmd {
            writeln!(f, "\t{}", arg);
        }
        writeln!(f, "executable path: {:?}", self.exe);
        writeln!(f, "current working directory: {:?}", self.cwd);
        writeln!(f, "memory usage: {} kB", self.memory);
        writeln!(f, "cpu usage: {}", self.cpu_usage);
        writeln!(f, "root path: {:?}", self.root)
    }
}

unsafe fn get_start_time(handle: HANDLE) -> u64 {
    let mut fstart: FILETIME = zeroed();
    let mut x = zeroed();

    GetProcessTimes(handle,
                    &mut fstart as *mut FILETIME,
                    &mut x as *mut FILETIME,
                    &mut x as *mut FILETIME,
                    &mut x as *mut FILETIME);
    let tmp = (fstart.dwHighDateTime as u64) << 32 | (fstart.dwLowDateTime as u64);
    tmp / 10_000_000 - 11_644_473_600
}

pub unsafe fn get_parent_process_id(pid: Pid) -> Option<Pid> {
    let snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    let mut entry: PROCESSENTRY32 = zeroed();
    entry.dwSize = size_of::<PROCESSENTRY32>() as u32;
    let mut not_the_end = Process32First(snapshot, &mut entry);
    while not_the_end != 0 {
        if pid == entry.th32ProcessID as usize {
            // TODO: if some day I have the motivation to add threads:
            // ListProcessThreads(entry.th32ProcessID);
            CloseHandle(snapshot);
            return Some(entry.th32ParentProcessID as usize);
        }
        not_the_end = Process32Next(snapshot, &mut entry);
    }
    CloseHandle(snapshot);
    None
}

/*fn run_wmi(args: &[&str]) -> Option<String> {
    use std::process::Command;

    if let Ok(out) = Command::new("wmic")
                             .args(args)
                             .output() {
        if out.status.success() {
            return Some(String::from_utf8_lossy(&out.stdout).into_owned());
        }
    }
    None
}*/

fn get_cmd_line(_pid: Pid) -> Vec<String> {
    /*let where_req = format!("ProcessId={}", pid);

    if let Some(ret) = run_wmi(&["process", "where", &where_req, "get", "CommandLine"]) {
        for line in ret.lines() {
            if line.is_empty() || line == "CommandLine" {
                continue
            }
            return vec![line.to_owned()];
        }
    }*/
    Vec::new()
}

unsafe fn get_proc_env(_handle: HANDLE, _pid: u32, _name: &str) -> Vec<String> {
    let ret = Vec::new();
    /*
    println!("current pid: {}", kernel32::GetCurrentProcessId());
    if kernel32::GetCurrentProcessId() == pid {
        println!("current proc!");
        for (key, value) in env::vars() {
            ret.push(format!("{}={}", key, value));
        }
        return ret;
    }
    println!("1");
    let snapshot_handle = kernel32::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if !snapshot_handle.is_null() {
        println!("2");
        let mut target_thread: THREADENTRY32 = zeroed();
        target_thread.dwSize = size_of::<THREADENTRY32>() as DWORD;
        if kernel32::Thread32First(snapshot_handle, &mut target_thread) == TRUE {
            println!("3");
            loop {
                if target_thread.th32OwnerProcessID == pid {
                    println!("4");
                    let thread_handle = kernel32::OpenThread(THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION | THREAD_GET_CONTEXT,
                                                             FALSE,
                                                             target_thread.th32ThreadID);
                    if !thread_handle.is_null() {
                        println!("5 -> {}", pid);
                        if kernel32::SuspendThread(thread_handle) != DWORD::max_value() {
                            println!("6");
                            let mut context = zeroed();
                            if kernel32::GetThreadContext(thread_handle, &mut context) != 0 {
                                println!("7 --> {:?}", context);
                                let mut x = vec![0u8; 10];
                                if kernel32::ReadProcessMemory(handle,
                                                               context.MxCsr as usize as *mut winapi::c_void,
                                                               x.as_mut_ptr() as *mut winapi::c_void,
                                                               x.len() as u64,
                                                               ::std::ptr::null_mut()) != 0 {
                                    for y in x {
                                        print!("{}", y as char);
                                    }
                                    println!("");
                                } else {
                                    println!("failure... {:?}", kernel32::GetLastError());
                                }
                            } else {
                                println!("-> {:?}", kernel32::GetLastError());
                            }
                            kernel32::ResumeThread(thread_handle);
                        }
                        kernel32::CloseHandle(thread_handle);
                    }
                    break;
                }
                if kernel32::Thread32Next(snapshot_handle, &mut target_thread) != TRUE {
                    break;
                }
            }
        }
        kernel32::CloseHandle(snapshot_handle);
    }*/
    ret
}

pub fn get_executable_path(_pid: Pid) -> PathBuf {
    /*let where_req = format!("ProcessId={}", pid);

    if let Some(ret) = run_wmi(&["process", "where", &where_req, "get", "ExecutablePath"]) {
        for line in ret.lines() {
            if line.is_empty() || line == "ExecutablePath" {
                continue
            }
            return line.to_owned();
        }
    }*/
    PathBuf::new()
}

pub fn compute_cpu_usage(p: &mut Process, nb_processors: u64) {
    unsafe {
        let mut now: ULARGE_INTEGER = ::std::mem::zeroed();
        let mut sys: ULARGE_INTEGER = ::std::mem::zeroed();
        let mut user: ULARGE_INTEGER = ::std::mem::zeroed();
        let mut ftime: FILETIME = zeroed();
        let mut fsys: FILETIME = zeroed();
        let mut fuser: FILETIME = zeroed();

        GetSystemTimeAsFileTime(&mut ftime);
        memcpy(&mut now as *mut ULARGE_INTEGER as *mut c_void,
               &mut ftime as *mut FILETIME as *mut c_void,
               size_of::<FILETIME>());

        GetProcessTimes(p.handle,
                        &mut ftime as *mut FILETIME,
                        &mut ftime as *mut FILETIME,
                        &mut fsys as *mut FILETIME,
                        &mut fuser as *mut FILETIME);
        memcpy(&mut sys as *mut ULARGE_INTEGER as *mut c_void,
               &mut fsys as *mut FILETIME as *mut c_void,
               size_of::<FILETIME>());
        memcpy(&mut user as *mut ULARGE_INTEGER as *mut c_void,
               &mut fuser as *mut FILETIME as *mut c_void,
               size_of::<FILETIME>());
        p.cpu_usage = ((*sys.QuadPart() - p.old_sys_cpu) as f32 +
            (*user.QuadPart() - p.old_user_cpu) as f32)
            / (*now.QuadPart() - p.old_cpu) as f32
            / nb_processors as f32 * 100.;
        p.old_cpu = *now.QuadPart();
        p.old_user_cpu = *user.QuadPart();
        p.old_sys_cpu = *sys.QuadPart();
    }
}

pub fn get_handle(p: &Process) -> HANDLE {
    p.handle
}

pub fn update_proc_info(p: &mut Process) {
    update_memory(p);
}

pub fn update_memory(p: &mut Process) {
    unsafe {
        let mut pmc: PROCESS_MEMORY_COUNTERS_EX = zeroed();
        if GetProcessMemoryInfo(p.handle,
                                &mut pmc as *mut PROCESS_MEMORY_COUNTERS_EX as *mut c_void as *mut PROCESS_MEMORY_COUNTERS,
                                size_of::<PROCESS_MEMORY_COUNTERS_EX>() as DWORD) != 0 {
            p.memory = (pmc.PrivateUsage as u64) >> 10u64; // / 1024;
        }
    }
}
<|endoftext|>


<commit_before>extern crate syn;

mod features;

macro_rules! should_parse {
    ($name:ident, { $($in:tt)* }) => {
        #[test]
        fn $name() {
            // Make sure we can parse the file!
            syn::parse_file(stringify!($($in)*)).unwrap();
        }
    }
}

should_parse!(generic_associated_type, {
    impl Foo {
        type Item = &'a i32;
        fn foo<'a>(&'a self) -> Self::Item<'a> {}
    }
});

should_parse!(const_generics_use, {
    type X = Foo<5>;
    type Y = Foo<"foo">;
    type Z = Foo<X>;
    type W = Foo<{ X + 10 }>;
});

should_parse!(trailing_plus_type, {
    type A = Box<Foo>;
    type A = Box<Foo + 'a>;
    type A = Box<'a + Foo>;
});

should_parse!(generic_associated_type_where, {
    trait Foo {
        type Item;
        fn foo<T>(&self, t: T) -> Self::Item<T>;
    }
});

should_parse!(match_with_block_expr, {
    fn main() {
        match false {
            _ => {}.a(),
        }
    }
});
<commit_msg>Skim formatting const generics, which crashes rustfmt<commit_after>extern crate syn;

mod features;

macro_rules! should_parse {
    ($name:ident, { $($in:tt)* }) => {
        #[test]
        fn $name() {
            // Make sure we can parse the file!
            syn::parse_file(stringify!($($in)*)).unwrap();
        }
    }
}

should_parse!(generic_associated_type, {
    impl Foo {
        type Item = &'a i32;
        fn foo<'a>(&'a self) -> Self::Item<'a> {}
    }
});

#[rustfmt::skip]
should_parse!(const_generics_use, {
    type X = Foo<5>;
    type Y = Foo<"foo">;
    type Z = Foo<X>;
    type W = Foo<{ X + 10 }>;
});

should_parse!(trailing_plus_type, {
    type A = Box<Foo>;
    type A = Box<Foo + 'a>;
    type A = Box<'a + Foo>;
});

should_parse!(generic_associated_type_where, {
    trait Foo {
        type Item;
        fn foo<T>(&self, t: T) -> Self::Item<T>;
    }
});

should_parse!(match_with_block_expr, {
    fn main() {
        match false {
            _ => {}.a(),
        }
    }
});
<|endoftext|>


<commit_before>use crate::config::*;
use crate::errors::RunError;
use cargo_metadata::{diagnostic::DiagnosticLevel, CargoOpt, Message, MetadataCommand};
use log::{error, trace};
use std::env;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use walkdir::WalkDir;

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TestBinary {
    path: PathBuf,
    ty: RunType,
    cargo_dir: Option<PathBuf>,
    pkg_name: Option<String>,
    pkg_version: Option<String>,
    pkg_authors: Option<Vec<String>>,
    should_panic: bool,
}

impl TestBinary {
    pub fn new(path: PathBuf, ty: RunType) -> Self {
        Self {
            path,
            ty,
            pkg_name: None,
            pkg_version: None,
            pkg_authors: None,
            cargo_dir: None,
            should_panic: false,
        }
    }

    pub fn path(&self) -> &Path {
        &self.path
    }

    pub fn run_type(&self) -> RunType {
        self.ty
    }

    pub fn manifest_dir(&self) -> &Option<PathBuf> {
        &self.cargo_dir
    }

    pub fn pkg_name(&self) -> &Option<String> {
        &self.pkg_name
    }

    pub fn pkg_version(&self) -> &Option<String> {
        &self.pkg_version
    }

    pub fn pkg_authors(&self) -> &Option<Vec<String>> {
        &self.pkg_authors
    }

    /// Should be `false` for normal tests and for doctests either `true` or
    /// `false` depending on the test attribute
    pub fn should_panic(&self) -> bool {
        self.should_panic
    }
}

pub fn get_tests(config: &Config) -> Result<Vec<TestBinary>, RunError> {
    let mut result = vec![];
    let manifest = match config.manifest.as_path().to_str() {
        Some(s) => s,
        None => "Cargo.toml",
    };
    let metadata = MetadataCommand::new()
        .manifest_path(manifest)
        .features(CargoOpt::AllFeatures)
        .exec()
        .map_err(|e| RunError::Cargo(e.to_string()))?;

    for ty in &config.run_types {
        let mut cmd = create_command(manifest, config, ty);
        cmd.stdout(Stdio::piped());
        if !config.verbose {
            cmd.stderr(Stdio::null());
        }
        trace!("Running command {:?}", cmd);
        let mut child = cmd.spawn().map_err(|e| RunError::Cargo(e.to_string()))?;

        if ty != &RunType::Doctests {
            let mut package_ids = vec![];
            let reader = std::io::BufReader::new(child.stdout.take().unwrap());
            for msg in Message::parse_stream(reader) {
                match msg {
                    Ok(Message::CompilerArtifact(art)) => {
                        if let Some(path) = art.executable {
                            if !art.profile.test && ty == &RunType::Tests {
                                continue;
                            }
                            result.push(TestBinary::new(path, *ty));
                            package_ids.push(art.package_id.clone());
                        }
                    }
                    Ok(Message::CompilerMessage(m)) => match m.message.level {
                        DiagnosticLevel::Error | DiagnosticLevel::Ice => {
                            let _ = child.wait();
                            return Err(RunError::TestCompile(m.message.message));
                        }
                        _ => {}
                    },
                    Err(e) => {
                        error!("Error parsing cargo messages {}", e);
                    }
                    _ => {}
                }
            }
            for (res, package) in result.iter_mut().zip(package_ids.iter()) {
                let package = &metadata[package];
                res.cargo_dir = package.manifest_path.parent().map(|x| x.to_path_buf());
                res.pkg_name = Some(package.name.clone());
                res.pkg_version = Some(package.version.to_string());
                res.pkg_authors = Some(package.authors.clone());
            }
            child.wait().map_err(|e| RunError::Cargo(e.to_string()))?;
        } else {
            // need to wait for compiling to finish before getting doctests
            child.wait().map_err(|e| RunError::Cargo(e.to_string()))?;
            let walker = WalkDir::new(&config.doctest_dir()).into_iter();
            for dt in walker
                .filter_map(|e| e.ok())
                .filter(|e| match e.metadata() {
                    Ok(ref m) if m.is_file() && m.len() != 0 => true,
                    _ => false,
                })
            {
                trace!("Found doctest binary {}", dt.path().display());
                result.push(TestBinary::new(dt.path().to_path_buf(), *ty));
            }
        }
    }
    Ok(result)
}

fn create_command(manifest_path: &str, config: &Config, ty: &RunType) -> Command {
    let mut test_cmd = Command::new("cargo");
    if *ty == RunType::Doctests {
        if let Some(toolchain) = env::var("RUSTUP_TOOLCHAIN")
            .ok()
            .filter(|t| t.starts_with("nightly"))
        {
            test_cmd.args(&[format!("+{}", toolchain).as_str(), "test"]);
        } else {
            test_cmd.args(&["+nightly", "test"]);
        }
    } else {
        if let Ok(toolchain) = env::var("RUSTUP_TOOLCHAIN") {
            test_cmd.arg(format!("+{}", toolchain));
        }
        test_cmd.args(&["test", "--no-run"]);
    }
    test_cmd.args(&["--message-format", "json", "--manifest-path", manifest_path]);
    match ty {
        RunType::Tests => test_cmd.arg("--tests"),
        RunType::Doctests => test_cmd.arg("--doc"),
        RunType::Benchmarks => test_cmd.arg("--benches"),
        RunType::Examples => test_cmd.arg("--examples"),
    };
    init_args(&mut test_cmd, config);
    setup_environment(&mut test_cmd, config);
    test_cmd
}

fn init_args(test_cmd: &mut Command, config: &Config) {
    if config.debug {
        test_cmd.arg("-vvv");
    }
    if config.locked {
        test_cmd.arg("--locked");
    }
    if config.frozen {
        test_cmd.arg("--frozen");
    }
    if let Some(features) = config.features.as_ref() {
        test_cmd.arg("--features");
        test_cmd.arg(features);
    }
    if config.all_features {
        test_cmd.arg("--all-features");
    }
    if config.no_default_features {
        test_cmd.arg("--no-default-features");
    }
    if config.all {
        test_cmd.arg("--workspace");
    }
    if config.release {
        test_cmd.arg("--release");
    }
    config.packages.iter().for_each(|package| {
        test_cmd.arg("--package");
        test_cmd.arg(package);
    });
    config.exclude.iter().for_each(|package| {
        test_cmd.arg("--exclude");
        test_cmd.arg(package);
    });
    if let Some(target) = config.target.as_ref() {
        test_cmd.args(&["--target", target]);
    }
    let args = vec![
        "--target-dir".to_string(),
        format!("{}", config.target_dir().display()),
    ];
    test_cmd.args(args);
    if config.offline {
        test_cmd.arg("--offline");
    }
    for feat in &config.unstable_features {
        test_cmd.arg(format!("-Z{}", feat));
    }
    if !config.varargs.is_empty() {
        let mut args = vec!["--".to_string()];
        args.extend_from_slice(&config.varargs);
        test_cmd.args(args);
    }
}

fn setup_environment(cmd: &mut Command, config: &Config) {
    cmd.env("TARPAULIN", "1");
    let rustflags = "RUSTFLAGS";
    let common_opts = " -C relocation-model=dynamic-no-pic -C link-dead-code -C debuginfo=2 ";
    let mut value = common_opts.to_string();
    if config.release {
        value = format!("{}-C debug-assertions=off ", value);
    }
    if let Ok(vtemp) = env::var(rustflags) {
        value.push_str(vtemp.as_ref());
    }
    cmd.env(rustflags, value);
    // doesn't matter if we don't use it
    let rustdoc = "RUSTDOCFLAGS";
    let mut value = format!(
        "{} --persist-doctests {} -Z unstable-options ",
        common_opts,
        config.doctest_dir().display()
    );
    if let Ok(vtemp) = env::var(rustdoc) {
        if !vtemp.contains("--persist-doctests") {
            value.push_str(vtemp.as_ref());
        }
    }
    trace!("Setting RUSTDOCFLAGS='{}'", value);
    cmd.env(rustdoc, value);
}
<commit_msg>Stop hanging during compile<commit_after>use crate::config::*;
use crate::errors::RunError;
use cargo_metadata::{diagnostic::DiagnosticLevel, CargoOpt, Message, MetadataCommand};
use log::{error, trace};
use std::env;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use walkdir::WalkDir;

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TestBinary {
    path: PathBuf,
    ty: RunType,
    cargo_dir: Option<PathBuf>,
    pkg_name: Option<String>,
    pkg_version: Option<String>,
    pkg_authors: Option<Vec<String>>,
    should_panic: bool,
}

impl TestBinary {
    pub fn new(path: PathBuf, ty: RunType) -> Self {
        Self {
            path,
            ty,
            pkg_name: None,
            pkg_version: None,
            pkg_authors: None,
            cargo_dir: None,
            should_panic: false,
        }
    }

    pub fn path(&self) -> &Path {
        &self.path
    }

    pub fn run_type(&self) -> RunType {
        self.ty
    }

    pub fn manifest_dir(&self) -> &Option<PathBuf> {
        &self.cargo_dir
    }

    pub fn pkg_name(&self) -> &Option<String> {
        &self.pkg_name
    }

    pub fn pkg_version(&self) -> &Option<String> {
        &self.pkg_version
    }

    pub fn pkg_authors(&self) -> &Option<Vec<String>> {
        &self.pkg_authors
    }

    /// Should be `false` for normal tests and for doctests either `true` or
    /// `false` depending on the test attribute
    pub fn should_panic(&self) -> bool {
        self.should_panic
    }
}

pub fn get_tests(config: &Config) -> Result<Vec<TestBinary>, RunError> {
    let mut result = vec![];
    let manifest = match config.manifest.as_path().to_str() {
        Some(s) => s,
        None => "Cargo.toml",
    };
    let metadata = MetadataCommand::new()
        .manifest_path(manifest)
        .features(CargoOpt::AllFeatures)
        .exec()
        .map_err(|e| RunError::Cargo(e.to_string()))?;

    for ty in &config.run_types {
        let mut cmd = create_command(manifest, config, ty);
        cmd.stdout(Stdio::piped());
        if !config.verbose {
            cmd.stderr(Stdio::null());
        }
        trace!("Running command {:?}", cmd);
        let mut child = cmd.spawn().map_err(|e| RunError::Cargo(e.to_string()))?;

        if ty != &RunType::Doctests {
            let mut package_ids = vec![];
            let reader = std::io::BufReader::new(child.stdout.take().unwrap());
            for msg in Message::parse_stream(reader) {
                match msg {
                    Ok(Message::CompilerArtifact(art)) => {
                        if let Some(path) = art.executable {
                            if !art.profile.test && ty == &RunType::Tests {
                                continue;
                            }
                            result.push(TestBinary::new(path, *ty));
                            package_ids.push(art.package_id.clone());
                        }
                    }
                    Ok(Message::CompilerMessage(m)) => match m.message.level {
                        DiagnosticLevel::Error | DiagnosticLevel::Ice => {
                            let _ = child.wait();
                            return Err(RunError::TestCompile(m.message.message));
                        }
                        _ => {}
                    },
                    Err(e) => {
                        error!("Error parsing cargo messages {}", e);
                    }
                    _ => {}
                }
            }
            for (res, package) in result.iter_mut().zip(package_ids.iter()) {
                let package = &metadata[package];
                res.cargo_dir = package.manifest_path.parent().map(|x| x.to_path_buf());
                res.pkg_name = Some(package.name.clone());
                res.pkg_version = Some(package.version.to_string());
                res.pkg_authors = Some(package.authors.clone());
            }
            child.wait().map_err(|e| RunError::Cargo(e.to_string()))?;
        } else {
            // need to wait for compiling to finish before getting doctests
            // also need to wait with output to ensure the stdout buffer doesn't fill up
            let out = child
                .wait_with_output()
                .map_err(|e| RunError::Cargo(e.to_string()))?;
            if !out.status.success() {
                error!("Building doctests failed");
            }
            let walker = WalkDir::new(&config.doctest_dir()).into_iter();
            for dt in walker
                .filter_map(|e| e.ok())
                .filter(|e| match e.metadata() {
                    Ok(ref m) if m.is_file() && m.len() != 0 => true,
                    _ => false,
                })
            {
                trace!("Found doctest binary {}", dt.path().display());
                result.push(TestBinary::new(dt.path().to_path_buf(), *ty));
            }
        }
    }
    Ok(result)
}

fn create_command(manifest_path: &str, config: &Config, ty: &RunType) -> Command {
    let mut test_cmd = Command::new("cargo");
    if *ty == RunType::Doctests {
        if let Some(toolchain) = env::var("RUSTUP_TOOLCHAIN")
            .ok()
            .filter(|t| t.starts_with("nightly"))
        {
            test_cmd.args(&[format!("+{}", toolchain).as_str(), "test"]);
        } else {
            test_cmd.args(&["+nightly", "test"]);
        }
    } else {
        if let Ok(toolchain) = env::var("RUSTUP_TOOLCHAIN") {
            test_cmd.arg(format!("+{}", toolchain));
        }
        test_cmd.args(&["test", "--no-run"]);
    }
    test_cmd.args(&["--message-format", "json", "--manifest-path", manifest_path]);
    match ty {
        RunType::Tests => test_cmd.arg("--tests"),
        RunType::Doctests => test_cmd.arg("--doc"),
        RunType::Benchmarks => test_cmd.arg("--benches"),
        RunType::Examples => test_cmd.arg("--examples"),
    };
    init_args(&mut test_cmd, config);
    setup_environment(&mut test_cmd, config);
    test_cmd
}

fn init_args(test_cmd: &mut Command, config: &Config) {
    if config.debug {
        test_cmd.arg("-vvv");
    }
    if config.locked {
        test_cmd.arg("--locked");
    }
    if config.frozen {
        test_cmd.arg("--frozen");
    }
    if let Some(features) = config.features.as_ref() {
        test_cmd.arg("--features");
        test_cmd.arg(features);
    }
    if config.all_features {
        test_cmd.arg("--all-features");
    }
    if config.no_default_features {
        test_cmd.arg("--no-default-features");
    }
    if config.all {
        test_cmd.arg("--workspace");
    }
    if config.release {
        test_cmd.arg("--release");
    }
    config.packages.iter().for_each(|package| {
        test_cmd.arg("--package");
        test_cmd.arg(package);
    });
    config.exclude.iter().for_each(|package| {
        test_cmd.arg("--exclude");
        test_cmd.arg(package);
    });
    if let Some(target) = config.target.as_ref() {
        test_cmd.args(&["--target", target]);
    }
    let args = vec![
        "--target-dir".to_string(),
        format!("{}", config.target_dir().display()),
    ];
    test_cmd.args(args);
    if config.offline {
        test_cmd.arg("--offline");
    }
    for feat in &config.unstable_features {
        test_cmd.arg(format!("-Z{}", feat));
    }
    if !config.varargs.is_empty() {
        let mut args = vec!["--".to_string()];
        args.extend_from_slice(&config.varargs);
        test_cmd.args(args);
    }
}

fn setup_environment(cmd: &mut Command, config: &Config) {
    cmd.env("TARPAULIN", "1");
    let rustflags = "RUSTFLAGS";
    let common_opts = " -C relocation-model=dynamic-no-pic -C link-dead-code -C debuginfo=2 ";
    let mut value = common_opts.to_string();
    if config.release {
        value = format!("{}-C debug-assertions=off ", value);
    }
    if let Ok(vtemp) = env::var(rustflags) {
        value.push_str(vtemp.as_ref());
    }
    cmd.env(rustflags, value);
    // doesn't matter if we don't use it
    let rustdoc = "RUSTDOCFLAGS";
    let mut value = format!(
        "{} --persist-doctests {} -Z unstable-options ",
        common_opts,
        config.doctest_dir().display()
    );
    if let Ok(vtemp) = env::var(rustdoc) {
        if !vtemp.contains("--persist-doctests") {
            value.push_str(vtemp.as_ref());
        }
    }
    trace!("Setting RUSTDOCFLAGS='{}'", value);
    cmd.env(rustdoc, value);
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::ops::{Deref, DerefMut};
use std::io::BufRead;
use std::result::Result as RResult;

use toml::Value;
use uuid::Uuid;

use task_hookrs::task::Task as TTask;
use task_hookrs::import::{import_task, import_tasks};

use libimagstore::store::{FileLockEntry, Store};
use libimagstore::storeid::{IntoStoreId, StoreIdIterator, StoreId};
use module_path::ModuleEntryPath;

use error::{TodoError, TodoErrorKind, MapErrInto};
use result::Result;

/// Task struct containing a `FileLockEntry`
#[derive(Debug)]
pub struct Task<'a>(FileLockEntry<'a>);

impl<'a> Task<'a> {

    /// Concstructs a new `Task` with a `FileLockEntry`
    pub fn new(fle: FileLockEntry<'a>) -> Task<'a> {
        Task(fle)
    }

    pub fn import<R: BufRead>(store: &'a Store, mut r: R) -> Result<(Task<'a>, Uuid)> {
        let mut line = String::new();
        r.read_line(&mut line);
        import_task(&line.as_str())
            .map_err_into(TodoErrorKind::ImportError)
            .and_then(|t| {
                let uuid = t.uuid().clone();
                t.into_task(store).map(|t| (t, uuid))
            })
    }

    /// Get a task from an import string. That is: read the imported string, get the UUID from it
    /// and try to load this UUID from store.
    ///
    /// Possible return values are:
    ///
    /// * Ok(Ok(Task))
    /// * Ok(Err(String)) - where the String is the String read from the `r` parameter
    /// * Err(_)          - where the error is an error that happened during evaluation
    ///
    pub fn get_from_import<R: BufRead>(store: &'a Store, mut r: R) -> Result<RResult<Task<'a>, String>>
    {
        let mut line = String::new();
        r.read_line(&mut line);
        Task::get_from_string(store, line)
    }

    /// Get a task from a String. The String is expected to contain the JSON-representation of the
    /// Task to get from the store (only the UUID really matters in this case)
    ///
    /// For an explanation on the return values see `Task::get_from_import()`.
    pub fn get_from_string(store: &'a Store, s: String) -> Result<RResult<Task<'a>, String>> {
        import_task(s.as_str())
            .map_err_into(TodoErrorKind::ImportError)
            .map(|t| t.uuid().clone())
            .and_then(|uuid| Task::get_from_uuid(store, uuid))
            .and_then(|o| match o {
                None    => Ok(Err(s)),
                Some(t) => Ok(Ok(t)),
            })
    }

    /// Get a task from an UUID.
    ///
    /// If there is no task with this UUID, this returns `Ok(None)`.
    pub fn get_from_uuid(store: &'a Store, uuid: Uuid) -> Result<Option<Task<'a>>> {
        unimplemented!()
    }

    /// Same as Task::get_from_import() but uses Store::retrieve() rather than Store::get(), to
    /// implicitely create the task if it does not exist.
    pub fn retrieve_from_import<R: BufRead>(store: &'a Store, mut r: R) -> Result<Task<'a>> {
        unimplemented!()
    }

    /// Retrieve a task from a String. The String is expected to contain the JSON-representation of
    /// the Task to retrieve from the store (only the UUID really matters in this case)
    pub fn retrieve_from_string(store: &'a Store, s: String) -> Result<Task<'a>> {
        unimplemented!()
    }

    pub fn delete_by_uuid(store: &Store, uuid: Uuid) -> Result<()> {
        store.delete(ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid())
            .map_err(|e| TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
    }

    pub fn all_as_ids(store: &Store) -> Result<StoreIdIterator> {
        store.retrieve_for_module("todo/taskwarrior")
            .map_err(|e| TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
    }

    pub fn all(store: &Store) -> Result<TaskIterator> {
        Task::all_as_ids(store)
            .map(|iter| TaskIterator::new(store, iter))
    }

}

impl<'a> Deref for Task<'a> {
    type Target = FileLockEntry<'a>;

    fn deref(&self) -> &FileLockEntry<'a> {
        &self.0
    }

}

impl<'a> DerefMut for Task<'a> {

    fn deref_mut(&mut self) -> &mut FileLockEntry<'a> {
        &mut self.0
    }

}

/// A trait to get a `libimagtodo::task::Task` out of the implementing object.
/// This Task struct is merely a wrapper for a `FileLockEntry`, therefore the function name
/// `into_filelockentry`.
pub trait IntoTask<'a> {

    /// # Usage
    /// ```ignore
    /// use std::io::stdin;
    ///
    /// use task_hookrs::task::Task;
    /// use task_hookrs::import::import;
    /// use libimagstore::store::{Store, FileLockEntry};
    ///
    /// if let Ok(task_hookrs_task) = import(stdin()) {
    ///     // Store is given at runtime
    ///     let task = task_hookrs_task.into_filelockentry(store);
    ///     println!("Task with uuid: {}", task.flentry.get_header().get("todo.uuid"));
    /// }
    /// ```
    fn into_task(self, store : &'a Store) -> Result<Task<'a>>;

}

impl<'a> IntoTask<'a> for TTask {

    fn into_task(self, store : &'a Store) -> Result<Task<'a>> {
        let uuid     = self.uuid();
        let store_id = ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid();

        match store.retrieve(store_id) {
            Err(e) => return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))),
            Ok(mut fle) => {
                {
                    let mut header = fle.get_header_mut();
                    match header.read("todo") {
                        Ok(None) => {
                            if let Err(e) = header.set("todo", Value::Table(BTreeMap::new())) {
                                return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
                            }
                        }
                        Ok(Some(_)) => { }
                        Err(e) => {
                            return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
                        }
                    }

                    if let Err(e) = header.set("todo.uuid", Value::String(format!("{}",uuid))) {
                        return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
                    }
                }

                // If none of the errors above have returned the function, everything is fine
                Ok(Task::new(fle))
            }
        }
    }

}

trait FromStoreId {
    fn from_storeid<'a>(&'a Store, StoreId) -> Result<Task<'a>>;
}

impl<'a> FromStoreId for Task<'a> {

    fn from_storeid<'b>(store: &'b Store, id: StoreId) -> Result<Task<'b>> {
        match store.retrieve(id) {
            Err(e) => Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))),
            Ok(c)  => Ok(Task::new( c )),
        }
    }
}

pub struct TaskIterator<'a> {
    store: &'a Store,
    iditer: StoreIdIterator,
}

impl<'a> TaskIterator<'a> {

    pub fn new(store: &'a Store, iditer: StoreIdIterator) -> TaskIterator<'a> {
        TaskIterator {
            store: store,
            iditer: iditer,
        }
    }

}

impl<'a> Iterator for TaskIterator<'a> {
    type Item = Result<Task<'a>>;

    fn next(&mut self) -> Option<Result<Task<'a>>> {
        self.iditer.next().map(|id| Task::from_storeid(self.store, id))
    }
}

<commit_msg>Impl Task::get_from_uuid()<commit_after>use std::collections::BTreeMap;
use std::ops::{Deref, DerefMut};
use std::io::BufRead;
use std::result::Result as RResult;

use toml::Value;
use uuid::Uuid;

use task_hookrs::task::Task as TTask;
use task_hookrs::import::{import_task, import_tasks};

use libimagstore::store::{FileLockEntry, Store};
use libimagstore::storeid::{IntoStoreId, StoreIdIterator, StoreId};
use module_path::ModuleEntryPath;

use error::{TodoError, TodoErrorKind, MapErrInto};
use result::Result;

/// Task struct containing a `FileLockEntry`
#[derive(Debug)]
pub struct Task<'a>(FileLockEntry<'a>);

impl<'a> Task<'a> {

    /// Concstructs a new `Task` with a `FileLockEntry`
    pub fn new(fle: FileLockEntry<'a>) -> Task<'a> {
        Task(fle)
    }

    pub fn import<R: BufRead>(store: &'a Store, mut r: R) -> Result<(Task<'a>, Uuid)> {
        let mut line = String::new();
        r.read_line(&mut line);
        import_task(&line.as_str())
            .map_err_into(TodoErrorKind::ImportError)
            .and_then(|t| {
                let uuid = t.uuid().clone();
                t.into_task(store).map(|t| (t, uuid))
            })
    }

    /// Get a task from an import string. That is: read the imported string, get the UUID from it
    /// and try to load this UUID from store.
    ///
    /// Possible return values are:
    ///
    /// * Ok(Ok(Task))
    /// * Ok(Err(String)) - where the String is the String read from the `r` parameter
    /// * Err(_)          - where the error is an error that happened during evaluation
    ///
    pub fn get_from_import<R: BufRead>(store: &'a Store, mut r: R) -> Result<RResult<Task<'a>, String>>
    {
        let mut line = String::new();
        r.read_line(&mut line);
        Task::get_from_string(store, line)
    }

    /// Get a task from a String. The String is expected to contain the JSON-representation of the
    /// Task to get from the store (only the UUID really matters in this case)
    ///
    /// For an explanation on the return values see `Task::get_from_import()`.
    pub fn get_from_string(store: &'a Store, s: String) -> Result<RResult<Task<'a>, String>> {
        import_task(s.as_str())
            .map_err_into(TodoErrorKind::ImportError)
            .map(|t| t.uuid().clone())
            .and_then(|uuid| Task::get_from_uuid(store, uuid))
            .and_then(|o| match o {
                None    => Ok(Err(s)),
                Some(t) => Ok(Ok(t)),
            })
    }

    /// Get a task from an UUID.
    ///
    /// If there is no task with this UUID, this returns `Ok(None)`.
    pub fn get_from_uuid(store: &'a Store, uuid: Uuid) -> Result<Option<Task<'a>>> {
        let store_id = ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid();

        store.get(store_id)
            .map(|o| o.map(Task::new))
            .map_err_into(TodoErrorKind::StoreError)
    }

    /// Same as Task::get_from_import() but uses Store::retrieve() rather than Store::get(), to
    /// implicitely create the task if it does not exist.
    pub fn retrieve_from_import<R: BufRead>(store: &'a Store, mut r: R) -> Result<Task<'a>> {
        unimplemented!()
    }

    /// Retrieve a task from a String. The String is expected to contain the JSON-representation of
    /// the Task to retrieve from the store (only the UUID really matters in this case)
    pub fn retrieve_from_string(store: &'a Store, s: String) -> Result<Task<'a>> {
        unimplemented!()
    }

    pub fn delete_by_uuid(store: &Store, uuid: Uuid) -> Result<()> {
        store.delete(ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid())
            .map_err(|e| TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
    }

    pub fn all_as_ids(store: &Store) -> Result<StoreIdIterator> {
        store.retrieve_for_module("todo/taskwarrior")
            .map_err(|e| TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
    }

    pub fn all(store: &Store) -> Result<TaskIterator> {
        Task::all_as_ids(store)
            .map(|iter| TaskIterator::new(store, iter))
    }

}

impl<'a> Deref for Task<'a> {
    type Target = FileLockEntry<'a>;

    fn deref(&self) -> &FileLockEntry<'a> {
        &self.0
    }

}

impl<'a> DerefMut for Task<'a> {

    fn deref_mut(&mut self) -> &mut FileLockEntry<'a> {
        &mut self.0
    }

}

/// A trait to get a `libimagtodo::task::Task` out of the implementing object.
/// This Task struct is merely a wrapper for a `FileLockEntry`, therefore the function name
/// `into_filelockentry`.
pub trait IntoTask<'a> {

    /// # Usage
    /// ```ignore
    /// use std::io::stdin;
    ///
    /// use task_hookrs::task::Task;
    /// use task_hookrs::import::import;
    /// use libimagstore::store::{Store, FileLockEntry};
    ///
    /// if let Ok(task_hookrs_task) = import(stdin()) {
    ///     // Store is given at runtime
    ///     let task = task_hookrs_task.into_filelockentry(store);
    ///     println!("Task with uuid: {}", task.flentry.get_header().get("todo.uuid"));
    /// }
    /// ```
    fn into_task(self, store : &'a Store) -> Result<Task<'a>>;

}

impl<'a> IntoTask<'a> for TTask {

    fn into_task(self, store : &'a Store) -> Result<Task<'a>> {
        let uuid     = self.uuid();
        let store_id = ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid();

        match store.retrieve(store_id) {
            Err(e) => return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))),
            Ok(mut fle) => {
                {
                    let mut header = fle.get_header_mut();
                    match header.read("todo") {
                        Ok(None) => {
                            if let Err(e) = header.set("todo", Value::Table(BTreeMap::new())) {
                                return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
                            }
                        }
                        Ok(Some(_)) => { }
                        Err(e) => {
                            return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
                        }
                    }

                    if let Err(e) = header.set("todo.uuid", Value::String(format!("{}",uuid))) {
                        return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
                    }
                }

                // If none of the errors above have returned the function, everything is fine
                Ok(Task::new(fle))
            }
        }
    }

}

trait FromStoreId {
    fn from_storeid<'a>(&'a Store, StoreId) -> Result<Task<'a>>;
}

impl<'a> FromStoreId for Task<'a> {

    fn from_storeid<'b>(store: &'b Store, id: StoreId) -> Result<Task<'b>> {
        match store.retrieve(id) {
            Err(e) => Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))),
            Ok(c)  => Ok(Task::new( c )),
        }
    }
}

pub struct TaskIterator<'a> {
    store: &'a Store,
    iditer: StoreIdIterator,
}

impl<'a> TaskIterator<'a> {

    pub fn new(store: &'a Store, iditer: StoreIdIterator) -> TaskIterator<'a> {
        TaskIterator {
            store: store,
            iditer: iditer,
        }
    }

}

impl<'a> Iterator for TaskIterator<'a> {
    type Item = Result<Task<'a>>;

    fn next(&mut self) -> Option<Result<Task<'a>>> {
        self.iditer.next().map(|id| Task::from_storeid(self.store, id))
    }
}

<|endoftext|>


<commit_before>use std::fmt;
use std::sync::Arc;
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::cell::Cell;
use std::sync::mpsc;

pub trait IrqType: fmt::Debug + Copy + Clone {
    fn index(&self) -> u32;
}

#[derive(Debug, Copy, Clone)]
pub enum IrqType9 {
    Dmac1_0 = 0,
    Dmac1_1 = 1,
    Dmac1_2 = 2,
    Dmac1_3 = 3,
    Dmac1_4 = 4,
    Dmac1_5 = 5,
    Dmac1_6 = 6,
    Dmac1_7 = 7,
    Timer0  = 8,
    Timer1  = 9,
    Timer2  = 10,
    Timer3  = 11,
    PxiSync     = 12,
    PxiNotFull  = 13,
    PxiNotEmpty = 14,
    Aes        = 15,
    Sdio1      = 16,
    Sdio1Async = 17,
    Sdio3      = 18,
    Sdio3Async = 19,
    DebugRecv  = 20,
    DebugSend  = 21,
    RSA        = 22,
    CtrCard1   = 23,
    CtrCard2   = 24,
    Cgc        = 25,
    CgcDet     = 26,
    DsCard     = 27,
    Dmac2      = 28,
    Dmac2Abort = 29
}

impl IrqType for IrqType9 {
    fn index(&self) -> u32 {
        *self as u32
    }
}

#[derive(Debug, Copy, Clone)]
pub enum IrqType11 {
    PxiSync = 80,
}

impl IrqType for IrqType11 {
    fn index(&self) -> u32 {
        *self as u32
    }
}

type RcMut<T> = Rc<Cell<T>>;

type AsyncLine = Arc<AtomicBool>;
type SyncLine = RcMut<bool>;
type AsyncEnabled = Arc<[AtomicUsize; 4]>;
type SyncEnabled = RcMut<u128>;

/// CPU end of the IRQ subsystem, just a simple triggered/not triggered API
#[derive(Clone)]
pub struct IrqLine {
    pub(crate) async: AsyncLine,
    pub(crate) sync: SyncLine,
}

impl IrqLine {
    pub fn is_high_sync(&self) -> bool {
        self.sync.get()
    }
    pub fn is_high_async(&self) -> bool {
        self.async.load(Ordering::Relaxed)
    }
    pub fn is_high(&self) -> bool {
        self.is_high_sync() || self.is_high_async()
    }
}

pub trait IrqClient: Clone {
    fn assert<IRQ: IrqType>(&mut self, irq: IRQ);
    fn is_enabled(&self, u32) -> bool;
}

pub trait IrqServer {
    fn pop(&mut self) -> Option<u32>;
}

#[derive(Clone)]
pub struct IrqSyncClient {
    irqs: RcMut<u128>,
    enabled: SyncEnabled,
    line: SyncLine,
}

impl IrqClient for IrqSyncClient {
    fn assert<IRQ: IrqType>(&mut self, irq: IRQ) {
        let index = irq.index();
        trace!("Trying to assert irq {}", index);
        if !self.is_enabled(index) {
            return
        }

        let set = self.irqs.get();
        self.irqs.set(set | 1u128 << (index as u128));
        self.line.set(true);
    }

    fn is_enabled(&self, index: u32) -> bool {
        self.enabled.get() & (1u128 << (index as u128)) != 0
    }
}

pub struct IrqSyncServer {
    irqs: RcMut<u128>
}

impl IrqServer for IrqSyncServer {
    fn pop(&mut self) -> Option<u32> {
        let set = self.irqs.get();
        if set == 0 {
            return None
        }
        let out = set.trailing_zeros();
        self.irqs.set(set & !(1 << out));
        Some(out)
    }
}

#[derive(Clone)]
pub struct IrqAsyncClient {
    irqs: mpsc::Sender<u32>,
    enabled: AsyncEnabled,
    line: AsyncLine,
}

impl IrqClient for IrqAsyncClient {
    fn assert<IRQ: IrqType>(&mut self, irq: IRQ) {
        let index = irq.index();
        trace!("Trying to assert irq {}", index);
        if !self.is_enabled(index) {
            return
        }
        self.irqs.send(index).unwrap();
        self.line.store(true, Ordering::Relaxed);
    }

    fn is_enabled(&self, index: u32) -> bool {
        let which_word = (index / 32) as usize;
        let enabled = self.enabled[which_word].load(Ordering::Relaxed) as u32;
        enabled & (1 << (index % 32)) != 0
    }
}

pub struct IrqAsyncServer {
    irqs: mpsc::Receiver<u32>
}

impl IrqServer for IrqAsyncServer {
    fn pop(&mut self) -> Option<u32> {
        self.irqs.try_recv().ok()
    }
}

pub struct Aggregator {
    async_rx: IrqAsyncServer,
    async_enabled: AsyncEnabled,
    sync_rx: IrqSyncServer,
    sync_enabled: SyncEnabled,
    line: IrqLine,
    pending: u128,
}

impl fmt::Debug for Aggregator {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Aggregator")
    }
}

impl Aggregator {
    pub(crate) fn set_enabled(&self, new: u128) {
        self.sync_enabled.set(new);
        self.async_enabled[0].store(new as u32 as usize, Ordering::Relaxed);
        self.async_enabled[1].store((new >> 32) as u32 as usize, Ordering::Relaxed);
        self.async_enabled[2].store((new >> 64) as u32 as usize, Ordering::Relaxed);
        self.async_enabled[3].store((new >> 96) as u32 as usize, Ordering::Relaxed);
    }

    pub(crate) fn drain_asserts(&mut self) -> u128 {
        let mut pending = self.pending;
        while let Some(x) = self.sync_rx.pop() {
            pending |= 1 << x;
        }
        while let Some(x) = self.async_rx.pop() {
            pending |= 1 << x;
        }
        self.pending = pending;
        pending
    }

    pub(crate) fn acknowledge(&mut self, which: u128) -> u128 {
        self.pending = self.drain_asserts() & !which;
        self.line.sync.set(self.pending != 0);
        self.line.async.store(self.pending != 0, Ordering::Relaxed);
        self.pending
    }
}

pub struct IrqSubsys {
    pub(crate) agg: Aggregator,
    pub(crate) sync_tx: IrqSyncClient,
    pub(crate) async_tx: IrqAsyncClient,
    pub(crate) line: IrqLine
}

impl IrqSubsys {
    pub(crate) fn create() -> Self {
        let line = IrqLine {
            sync: Rc::new(Cell::new(false)),
            async: Arc::new(AtomicBool::new(false))
        };
        let sync_enabled = Rc::new(Cell::new(0));
        let async_enabled = Arc::new([AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0)]);
        let sync_irqs = Rc::new(Cell::new(0));
        let (async_irqs_tx, async_irqs_rx) = mpsc::channel();
        Self {
            agg: Aggregator {
                async_rx: IrqAsyncServer {
                    irqs: async_irqs_rx,
                },
                async_enabled: async_enabled.clone(),
                sync_rx: IrqSyncServer {
                    irqs: sync_irqs.clone()
                },
                sync_enabled: sync_enabled.clone(),
                line: line.clone(),
                pending: 0
            },
            sync_tx: IrqSyncClient {
                line: line.sync.clone(),
                enabled: sync_enabled,
                irqs: sync_irqs,
            },
            async_tx: IrqAsyncClient {
                line: line.async.clone(),
                enabled: async_enabled,
                irqs: async_irqs_tx,
            },
            line: line
        }
    }
}

<commit_msg>irq.rs: Use appropriately sized Atomic for IRQ bits<commit_after>use std::fmt;
use std::sync::Arc;
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
use std::cell::Cell;
use std::sync::mpsc;

pub trait IrqType: fmt::Debug + Copy + Clone {
    fn index(&self) -> u32;
}

#[derive(Debug, Copy, Clone)]
pub enum IrqType9 {
    Dmac1_0 = 0,
    Dmac1_1 = 1,
    Dmac1_2 = 2,
    Dmac1_3 = 3,
    Dmac1_4 = 4,
    Dmac1_5 = 5,
    Dmac1_6 = 6,
    Dmac1_7 = 7,
    Timer0  = 8,
    Timer1  = 9,
    Timer2  = 10,
    Timer3  = 11,
    PxiSync     = 12,
    PxiNotFull  = 13,
    PxiNotEmpty = 14,
    Aes        = 15,
    Sdio1      = 16,
    Sdio1Async = 17,
    Sdio3      = 18,
    Sdio3Async = 19,
    DebugRecv  = 20,
    DebugSend  = 21,
    RSA        = 22,
    CtrCard1   = 23,
    CtrCard2   = 24,
    Cgc        = 25,
    CgcDet     = 26,
    DsCard     = 27,
    Dmac2      = 28,
    Dmac2Abort = 29
}

impl IrqType for IrqType9 {
    fn index(&self) -> u32 {
        *self as u32
    }
}

#[derive(Debug, Copy, Clone)]
pub enum IrqType11 {
    PxiSync = 80,
}

impl IrqType for IrqType11 {
    fn index(&self) -> u32 {
        *self as u32
    }
}

type RcMut<T> = Rc<Cell<T>>;

type AsyncLine = Arc<AtomicBool>;
type SyncLine = RcMut<bool>;
type AsyncEnabled = Arc<[AtomicU32; 4]>;
type SyncEnabled = RcMut<u128>;

/// CPU end of the IRQ subsystem, just a simple triggered/not triggered API
#[derive(Clone)]
pub struct IrqLine {
    pub(crate) async: AsyncLine,
    pub(crate) sync: SyncLine,
}

impl IrqLine {
    pub fn is_high_sync(&self) -> bool {
        self.sync.get()
    }
    pub fn is_high_async(&self) -> bool {
        self.async.load(Ordering::Relaxed)
    }
    pub fn is_high(&self) -> bool {
        self.is_high_sync() || self.is_high_async()
    }
}

pub trait IrqClient: Clone {
    fn assert<IRQ: IrqType>(&mut self, irq: IRQ);
    fn is_enabled(&self, u32) -> bool;
}

pub trait IrqServer {
    fn pop(&mut self) -> Option<u32>;
}

#[derive(Clone)]
pub struct IrqSyncClient {
    irqs: RcMut<u128>,
    enabled: SyncEnabled,
    line: SyncLine,
}

impl IrqClient for IrqSyncClient {
    fn assert<IRQ: IrqType>(&mut self, irq: IRQ) {
        let index = irq.index();
        trace!("Trying to assert irq {}", index);
        if !self.is_enabled(index) {
            return
        }

        let set = self.irqs.get();
        self.irqs.set(set | 1u128 << (index as u128));
        self.line.set(true);
    }

    fn is_enabled(&self, index: u32) -> bool {
        self.enabled.get() & (1u128 << (index as u128)) != 0
    }
}

pub struct IrqSyncServer {
    irqs: RcMut<u128>
}

impl IrqServer for IrqSyncServer {
    fn pop(&mut self) -> Option<u32> {
        let set = self.irqs.get();
        if set == 0 {
            return None
        }
        let out = set.trailing_zeros();
        self.irqs.set(set & !(1 << out));
        Some(out)
    }
}

#[derive(Clone)]
pub struct IrqAsyncClient {
    irqs: mpsc::Sender<u32>,
    enabled: AsyncEnabled,
    line: AsyncLine,
}

impl IrqClient for IrqAsyncClient {
    fn assert<IRQ: IrqType>(&mut self, irq: IRQ) {
        let index = irq.index();
        trace!("Trying to assert irq {}", index);
        if !self.is_enabled(index) {
            return
        }
        self.irqs.send(index).unwrap();
        self.line.store(true, Ordering::Relaxed);
    }

    fn is_enabled(&self, index: u32) -> bool {
        let which_word = (index / 32) as usize;
        let enabled = self.enabled[which_word].load(Ordering::Relaxed);
        enabled & (1 << (index % 32)) != 0
    }
}

pub struct IrqAsyncServer {
    irqs: mpsc::Receiver<u32>
}

impl IrqServer for IrqAsyncServer {
    fn pop(&mut self) -> Option<u32> {
        self.irqs.try_recv().ok()
    }
}

pub struct Aggregator {
    async_rx: IrqAsyncServer,
    async_enabled: AsyncEnabled,
    sync_rx: IrqSyncServer,
    sync_enabled: SyncEnabled,
    line: IrqLine,
    pending: u128,
}

impl fmt::Debug for Aggregator {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Aggregator")
    }
}

impl Aggregator {
    pub(crate) fn set_enabled(&self, new: u128) {
        self.sync_enabled.set(new);
        self.async_enabled[0].store(new as u32, Ordering::Relaxed);
        self.async_enabled[1].store((new >> 32) as u32, Ordering::Relaxed);
        self.async_enabled[2].store((new >> 64) as u32, Ordering::Relaxed);
        self.async_enabled[3].store((new >> 96) as u32, Ordering::Relaxed);
    }

    pub(crate) fn drain_asserts(&mut self) -> u128 {
        let mut pending = self.pending;
        while let Some(x) = self.sync_rx.pop() {
            pending |= 1u128 << (x as u128);
        }
        while let Some(x) = self.async_rx.pop() {
            pending |= 1u128 << (x as u128);
        }
        self.pending = pending;
        pending
    }

    pub(crate) fn acknowledge(&mut self, which: u128) -> u128 {
        self.pending = self.drain_asserts() & !which;
        self.line.sync.set(self.pending != 0);
        self.line.async.store(self.pending != 0, Ordering::Relaxed);
        self.pending
    }
}

pub struct IrqSubsys {
    pub(crate) agg: Aggregator,
    pub(crate) sync_tx: IrqSyncClient,
    pub(crate) async_tx: IrqAsyncClient,
    pub(crate) line: IrqLine
}

impl IrqSubsys {
    pub(crate) fn create() -> Self {
        let line = IrqLine {
            sync: Rc::new(Cell::new(false)),
            async: Arc::new(AtomicBool::new(false))
        };
        let sync_enabled = Rc::new(Cell::new(0));
        let async_enabled = Arc::new([AtomicU32::new(0), AtomicU32::new(0), AtomicU32::new(0), AtomicU32::new(0)]);
        let sync_irqs = Rc::new(Cell::new(0));
        let (async_irqs_tx, async_irqs_rx) = mpsc::channel();
        Self {
            agg: Aggregator {
                async_rx: IrqAsyncServer {
                    irqs: async_irqs_rx,
                },
                async_enabled: async_enabled.clone(),
                sync_rx: IrqSyncServer {
                    irqs: sync_irqs.clone()
                },
                sync_enabled: sync_enabled.clone(),
                line: line.clone(),
                pending: 0
            },
            sync_tx: IrqSyncClient {
                line: line.sync.clone(),
                enabled: sync_enabled,
                irqs: sync_irqs,
            },
            async_tx: IrqAsyncClient {
                line: line.async.clone(),
                enabled: async_enabled,
                irqs: async_irqs_tx,
            },
            line: line
        }
    }
}

<|endoftext|>