<commit_before>extern crate libc;
use self::libc::*;

use low_level as ll;
use error::Error;
use device::Device;
use context::Context;
use event::{Event, EventStatus, EventLike};
use kernel::Kernel;
use mem::Mem;

use std::ptr;
use std::mem::{size_of, transmute};

pub struct CommandQueue {
    pub id: ll::CommandQueue,
}

pub struct ReadLock<'a, T: Sized + 'a> {
    #[allow(dead_code)]
    sl: &'a [T],
    evt: Event,
}

pub struct WriteLock<'a, T: Sized + 'a> {
    #[allow(dead_code)]
    sl: &'a mut [T],
    evt: Event,
}

impl<'a, T: Sized> Drop for ReadLock<'a, T> {
    fn drop(self: &mut Self) -> () {
        self.evt.wait().ok().expect(
            "error waiting to finish write for ReadLock");
    }
}

impl<'a, T: Sized> EventLike for ReadLock<'a, T> {
    fn status(self: &Self) -> Result<EventStatus, Error> {
        self.evt.status()
    }

    fn wait(self: &Self) -> Result<(), Error> {
        self.evt.wait()
    }
}

impl<'a, T: Sized> Drop for WriteLock<'a, T> {
    fn drop(self: &mut Self) -> () {
        self.evt.wait().ok().expect(
            "error waiting to finish write for ReadLock");
    }
}

impl<'a, T: Sized> EventLike for WriteLock<'a, T> {
    fn status(self: &Self) -> Result<EventStatus, Error> {
        self.evt.status()
    }

    fn wait(self: &Self) -> Result<(), Error> {
        self.evt.wait()
    }
}

unsafe impl Send for CommandQueue { }

impl CommandQueue {
    pub fn new(context: Context,
               device: Device) -> Result<CommandQueue, Error> {
        let props: c_ulong = if try!(device.out_of_order_supported()) {
            1
        } else {
            0
        };
        let id = unsafe {
            let mut err: i32 = 0;
            let id = ll::clCreateCommandQueue(context.id,
                                              device.id,
                                              props,
                                              &mut err);
            try!(Error::check(err));
            id
        };
        Ok(CommandQueue{ id: id })
    }

    fn get_info(self: &Self, param: u32) -> Result<*mut c_void, Error> {
        let mut tr: *mut c_void = ptr::null_mut();
        unsafe {
            try!(Error::check(ll::clGetCommandQueueInfo(self.id,
                                                   param,
                                                   size_of::<*mut c_void>() as size_t,
                                                   transmute(&mut tr),
                                                   ptr::null_mut())));
        }
        Ok(tr)
    }

    pub fn context(self: &Self) -> Result<Context, Error> {
        let val = try!(self.get_info(0x1090));
        let id = unsafe { transmute(val) };
        unsafe {
            try!(Error::check(ll::clRetainContext(id)));
        }
        Ok(Context{id: id})
    }

    pub fn device(self: &Self) -> Result<Device, Error> {
        let val = try!(self.get_info(0x1091));
        let id = unsafe { transmute(val) };
        Ok(Device{id: id})
    }

    fn alloc_ll_buffer(self: &Self,
                    flags: c_ulong,
                    size_bytes: usize) -> Result<ll::Mem, Error> {
        let context = try!(self.context());
        let id = unsafe {
            let mut err: i32 = 0;
            let id = ll::clCreateBuffer(context.id,
                                        flags,
                                        size_bytes as size_t,
                                        ptr::null_mut(),
                                        &mut err);
            try!(Error::check(err));
            id
        };
        Ok(id)
    }

    fn write_buffer_raw<T: Sized>(self: &Self,
                       buf: &mut Mem,
                       offset: usize,
                       size: usize,
                       data: &[T]) -> Result<Event, Error> {
        let mut event_id: ll::Event = ptr::null_mut();
        let host_ptr = &data[0] as *const T;

        unsafe {
            try!(Error::check(ll::clEnqueueWriteBuffer(self.id,
                                                       buf.id,
                                                       0, // don't block
                                                       offset as size_t,
                                                       size as size_t,
                                                       transmute(host_ptr),
                                                       0,
                                                       ptr::null(),
                                                       &mut event_id)));
        }

        let event = Event{id: event_id};
        Ok(event)
    }

    fn read_buffer_raw<T: Sized>(self: &Self,
                                 buf: &Mem,
                                 offset: usize,
                                 size: usize,
                                 data: &mut [T]) -> Result<Event, Error> {
        let mut event_id: ll::Event = ptr::null_mut();
        let host_ptr = &mut data[0] as *mut T;

        unsafe {
            try!(Error::check(ll::clEnqueueReadBuffer(self.id,
                                                      buf.id,
                                                      0, // don't block,
                                                      offset as size_t,
                                                      size as size_t,
                                                      transmute(host_ptr),
                                                      0,
                                                      ptr::null(),
                                                      &mut event_id)));
        }

        let event = Event{id: event_id};
        Ok(event)
    }

    pub fn create_buffer(self: &Self,
                               size_bytes: usize) -> Result<Mem, Error> {
        let id = try!(self.alloc_ll_buffer(0, size_bytes));
        let tr = Mem::new(id);
        Ok(tr)
    }

    pub fn create_buffer_from_slice<T: Sized>(self: &Self,
                                    slice: &[T]) -> Result<Mem, Error> {
        let num_bytes = slice.len() * size_of::<T>();
        let mut buf = try!(self.create_buffer(num_bytes));
        try!(self.write_buffer(&mut buf, slice));
        Ok(buf)
    }

    pub fn write_buffer_unscoped<T: Sized>(self: &Self,
                                  mem: &mut Mem,
                                  slice: &[T]) -> Result<Event, Error> {
        let size_bytes = size_of::<T>()*slice.len();
        let evt = try!(self.write_buffer_raw(mem,
                                             0,
                                             size_bytes,
                                             slice));
        Ok(evt)
    }

    pub fn read_buffer_unscoped<T: Sized>(self: &Self,
                                                 mem: &Mem,
                                                 slice: &mut [T]) -> Result<Event, Error> {
        let size_bytes = size_of::<T>()*slice.len();
        let evt = try!(self.read_buffer_raw(mem,
                                            0,
                                            size_bytes,
                                            slice));
        Ok(evt)
    }

    pub fn write_buffer<'a, 'b, T: Sized + 'a>(self: &Self,
                                  mem: &'b mut Mem,
                                  slice: &'a [T]) -> Result<ReadLock<'a, T>, Error> {
        let size_bytes = size_of::<T>()*slice.len();
        let evt = try!(self.write_buffer_raw(mem,
                                             0,
                                             size_bytes,
                                             slice));
        Ok(ReadLock{ evt: evt, sl: slice })
    }

    pub fn read_buffer<'a, T: Sized>(self: &Self,
                                 mem: &Mem,
                                 slice: &'a mut [T]) -> Result<WriteLock<'a, T>, Error> {
        let size_bytes = size_of::<T>()*slice.len();
        let evt = try!(self.read_buffer_raw(mem,
                                            0,
                                            size_bytes,
                                            slice));
        Ok(WriteLock{ evt: evt, sl: slice })
    }

    fn next_mul(self: &Self, global: usize, local: usize) -> usize {
        if global % local == 0 {
            global
        } else {
            ((global/local)+1)*local
        }
    }

    pub fn run(
                self: &Self,
                kernel: &mut Kernel,
                local_size: (usize, usize, usize),
                global_size: (usize, usize, usize)) -> Result<Event, Error> {
        let global_size_fixed = (self.next_mul(global_size.0, local_size.0),
                                self.next_mul(global_size.1, local_size.1),
                                self.next_mul(global_size.2, local_size.2));

        let local_vec = vec!(local_size.0 as size_t,
                             local_size.1 as size_t,
                             local_size.2 as size_t);
        let global_vec = vec!(global_size_fixed.0 as size_t,
                              global_size_fixed.1 as size_t,
                              global_size_fixed.2 as size_t);

        let mut event_id: ll::Event = ptr::null_mut();
        unsafe {
            let events_val = ptr::null_mut();
            try!(Error::check(ll::clEnqueueNDRangeKernel(self.id,
                                                         kernel.id,
                                                         3,
                                                         ptr::null(),
                                                         &global_vec[0],
                                                         &local_vec[0],
                                                         0,
                                                         events_val,
                                                         &mut event_id)));
        }
        let event = Event{id: event_id};

        Ok(event)
    }

    pub fn run_with_events(
                self: &Self,
                kernel: &mut Kernel,
                local_size: (usize, usize, usize),
                global_size: (usize, usize, usize),
                events: &[Event]) -> Result<Event, Error> {
        let global_size_fixed = (self.next_mul(global_size.0, local_size.0),
                                self.next_mul(global_size.1, local_size.1),
                                self.next_mul(global_size.2, local_size.2));

        let local_vec = vec!(local_size.0 as size_t,
                             local_size.1 as size_t,
                             local_size.2 as size_t);
        let global_vec = vec!(global_size_fixed.0 as size_t,
                              global_size_fixed.1 as size_t,
                              global_size_fixed.2 as size_t);

        let mut event_id: ll::Event = ptr::null_mut();
        unsafe {
            let events_val = if events.len() > 0 {
                transmute(&events[0])
            } else {
                ptr::null_mut()
            };
            try!(Error::check(ll::clEnqueueNDRangeKernel(self.id,
                                                         kernel.id,
                                                         3,
                                                         ptr::null(),
                                                         &global_vec[0],
                                                         &local_vec[0],
                                                         events.len() as u32,
                                                         events_val,
                                                         &mut event_id)));
        }
        let event = Event{id: event_id};

        Ok(event)
    }
}

impl Drop for CommandQueue {
    fn drop(self: &mut Self) -> () {
        unsafe {
            Error::check(ll::clReleaseCommandQueue(self.id))
                .ok().expect("Error releasing command queue");
        }
    }
}

impl Clone for CommandQueue {
    fn clone(self: &Self) -> Self {
        unsafe {
            Error::check(ll::clRetainCommandQueue(self.id))
                .ok().expect("Error retaining command queue");
        }
        CommandQueue{ id: self.id }
    }
}

<commit_msg>hopefully fixes bug with queued NDKernels<commit_after>extern crate libc;
use self::libc::*;

use low_level as ll;
use error::Error;
use device::Device;
use context::Context;
use event::{Event, EventStatus, EventLike};
use kernel::Kernel;
use mem::Mem;

use std::ptr;
use std::mem::{size_of, transmute};

pub struct CommandQueue {
    pub id: ll::CommandQueue,
}

pub struct ReadLock<'a, T: Sized + 'a> {
    #[allow(dead_code)]
    sl: &'a [T],
    evt: Event,
}

pub struct WriteLock<'a, T: Sized + 'a> {
    #[allow(dead_code)]
    sl: &'a mut [T],
    evt: Event,
}

impl<'a, T: Sized> Drop for ReadLock<'a, T> {
    fn drop(self: &mut Self) -> () {
        self.evt.wait().ok().expect(
            "error waiting to finish write for ReadLock");
    }
}

impl<'a, T: Sized> EventLike for ReadLock<'a, T> {
    fn status(self: &Self) -> Result<EventStatus, Error> {
        self.evt.status()
    }

    fn wait(self: &Self) -> Result<(), Error> {
        self.evt.wait()
    }
}

impl<'a, T: Sized> Drop for WriteLock<'a, T> {
    fn drop(self: &mut Self) -> () {
        self.evt.wait().ok().expect(
            "error waiting to finish write for ReadLock");
    }
}

impl<'a, T: Sized> EventLike for WriteLock<'a, T> {
    fn status(self: &Self) -> Result<EventStatus, Error> {
        self.evt.status()
    }

    fn wait(self: &Self) -> Result<(), Error> {
        self.evt.wait()
    }
}

unsafe impl Send for CommandQueue { }

impl CommandQueue {
    pub fn new(context: Context,
               device: Device) -> Result<CommandQueue, Error> {
        let props: c_ulong = if try!(device.out_of_order_supported()) {
            1
        } else {
            0
        };
        let id = unsafe {
            let mut err: i32 = 0;
            let id = ll::clCreateCommandQueue(context.id,
                                              device.id,
                                              props,
                                              &mut err);
            try!(Error::check(err));
            id
        };
        Ok(CommandQueue{ id: id })
    }

    fn get_info(self: &Self, param: u32) -> Result<*mut c_void, Error> {
        let mut tr: *mut c_void = ptr::null_mut();
        unsafe {
            try!(Error::check(ll::clGetCommandQueueInfo(self.id,
                                                   param,
                                                   size_of::<*mut c_void>() as size_t,
                                                   transmute(&mut tr),
                                                   ptr::null_mut())));
        }
        Ok(tr)
    }

    pub fn context(self: &Self) -> Result<Context, Error> {
        let val = try!(self.get_info(0x1090));
        let id = unsafe { transmute(val) };
        unsafe {
            try!(Error::check(ll::clRetainContext(id)));
        }
        Ok(Context{id: id})
    }

    pub fn device(self: &Self) -> Result<Device, Error> {
        let val = try!(self.get_info(0x1091));
        let id = unsafe { transmute(val) };
        Ok(Device{id: id})
    }

    fn alloc_ll_buffer(self: &Self,
                    flags: c_ulong,
                    size_bytes: usize) -> Result<ll::Mem, Error> {
        let context = try!(self.context());
        let id = unsafe {
            let mut err: i32 = 0;
            let id = ll::clCreateBuffer(context.id,
                                        flags,
                                        size_bytes as size_t,
                                        ptr::null_mut(),
                                        &mut err);
            try!(Error::check(err));
            id
        };
        Ok(id)
    }

    fn write_buffer_raw<T: Sized>(self: &Self,
                       buf: &mut Mem,
                       offset: usize,
                       size: usize,
                       data: &[T]) -> Result<Event, Error> {
        let mut event_id: ll::Event = ptr::null_mut();
        let host_ptr = &data[0] as *const T;

        unsafe {
            try!(Error::check(ll::clEnqueueWriteBuffer(self.id,
                                                       buf.id,
                                                       0, // don't block
                                                       offset as size_t,
                                                       size as size_t,
                                                       transmute(host_ptr),
                                                       0,
                                                       ptr::null(),
                                                       &mut event_id)));
        }

        let event = Event{id: event_id};
        Ok(event)
    }

    fn read_buffer_raw<T: Sized>(self: &Self,
                                 buf: &Mem,
                                 offset: usize,
                                 size: usize,
                                 data: &mut [T]) -> Result<Event, Error> {
        let mut event_id: ll::Event = ptr::null_mut();
        let host_ptr = &mut data[0] as *mut T;

        unsafe {
            try!(Error::check(ll::clEnqueueReadBuffer(self.id,
                                                      buf.id,
                                                      0, // don't block,
                                                      offset as size_t,
                                                      size as size_t,
                                                      transmute(host_ptr),
                                                      0,
                                                      ptr::null(),
                                                      &mut event_id)));
        }

        let event = Event{id: event_id};
        Ok(event)
    }

    pub fn create_buffer(self: &Self,
                               size_bytes: usize) -> Result<Mem, Error> {
        let id = try!(self.alloc_ll_buffer(0, size_bytes));
        let tr = Mem::new(id);
        Ok(tr)
    }

    pub fn create_buffer_from_slice<T: Sized>(self: &Self,
                                    slice: &[T]) -> Result<Mem, Error> {
        let num_bytes = slice.len() * size_of::<T>();
        let mut buf = try!(self.create_buffer(num_bytes));
        try!(self.write_buffer(&mut buf, slice));
        Ok(buf)
    }

    pub fn write_buffer_unscoped<T: Sized>(self: &Self,
                                  mem: &mut Mem,
                                  slice: &[T]) -> Result<Event, Error> {
        let size_bytes = size_of::<T>()*slice.len();
        let evt = try!(self.write_buffer_raw(mem,
                                             0,
                                             size_bytes,
                                             slice));
        Ok(evt)
    }

    pub fn read_buffer_unscoped<T: Sized>(self: &Self,
                                                 mem: &Mem,
                                                 slice: &mut [T]) -> Result<Event, Error> {
        let size_bytes = size_of::<T>()*slice.len();
        let evt = try!(self.read_buffer_raw(mem,
                                            0,
                                            size_bytes,
                                            slice));
        Ok(evt)
    }

    pub fn write_buffer<'a, 'b, T: Sized + 'a>(self: &Self,
                                  mem: &'b mut Mem,
                                  slice: &'a [T]) -> Result<ReadLock<'a, T>, Error> {
        let size_bytes = size_of::<T>()*slice.len();
        let evt = try!(self.write_buffer_raw(mem,
                                             0,
                                             size_bytes,
                                             slice));
        Ok(ReadLock{ evt: evt, sl: slice })
    }

    pub fn read_buffer<'a, T: Sized>(self: &Self,
                                 mem: &Mem,
                                 slice: &'a mut [T]) -> Result<WriteLock<'a, T>, Error> {
        let size_bytes = size_of::<T>()*slice.len();
        let evt = try!(self.read_buffer_raw(mem,
                                            0,
                                            size_bytes,
                                            slice));
        Ok(WriteLock{ evt: evt, sl: slice })
    }

    fn next_mul(self: &Self, global: usize, local: usize) -> usize {
        if global % local == 0 {
            global
        } else {
            ((global/local)+1)*local
        }
    }

    pub fn run(
                self: &Self,
                kernel: &mut Kernel,
                local_size: (usize, usize, usize),
                global_size: (usize, usize, usize)) -> Result<Event, Error> {
        let global_size_fixed = (self.next_mul(global_size.0, local_size.0),
                                self.next_mul(global_size.1, local_size.1),
                                self.next_mul(global_size.2, local_size.2));

        let local_vec = vec!(local_size.0 as size_t,
                             local_size.1 as size_t,
                             local_size.2 as size_t);
        let global_vec = vec!(global_size_fixed.0 as size_t,
                              global_size_fixed.1 as size_t,
                              global_size_fixed.2 as size_t);

        let mut event_id: ll::Event = ptr::null_mut();
        unsafe {
            let events_val = ptr::null_mut();
            try!(Error::check(ll::clEnqueueNDRangeKernel(self.id,
                                                         kernel.id,
                                                         3,
                                                         ptr::null(),
                                                         &global_vec[0],
                                                         &local_vec[0],
                                                         0,
                                                         events_val,
                                                         &mut event_id)));
        }
        let event = Event{id: event_id};

        Ok(event)
    }

    pub fn run_with_events(
                self: &Self,
                kernel: &mut Kernel,
                local_size: (usize, usize, usize),
                global_size: (usize, usize, usize),
                events_in: &[Event]) -> Result<Event, Error> {
        let events = events_in.to_owned();
        let global_size_fixed = (self.next_mul(global_size.0, local_size.0),
                                self.next_mul(global_size.1, local_size.1),
                                self.next_mul(global_size.2, local_size.2));

        let local_vec = vec!(local_size.0 as size_t,
                             local_size.1 as size_t,
                             local_size.2 as size_t);
        let global_vec = vec!(global_size_fixed.0 as size_t,
                              global_size_fixed.1 as size_t,
                              global_size_fixed.2 as size_t);

        let mut event_id: ll::Event = ptr::null_mut();
        unsafe {
            let events_val = if events.len() > 0 {
                transmute(&events[0])
            } else {
                ptr::null_mut()
            };
            try!(Error::check(ll::clEnqueueNDRangeKernel(self.id,
                                                         kernel.id,
                                                         3,
                                                         ptr::null(),
                                                         &global_vec[0],
                                                         &local_vec[0],
                                                         events.len() as u32,
                                                         events_val,
                                                         &mut event_id)));
        }
        let event = Event{id: event_id};

        Ok(event)
    }
}

impl Drop for CommandQueue {
    fn drop(self: &mut Self) -> () {
        unsafe {
            Error::check(ll::clReleaseCommandQueue(self.id))
                .ok().expect("Error releasing command queue");
        }
    }
}

impl Clone for CommandQueue {
    fn clone(self: &Self) -> Self {
        unsafe {
            Error::check(ll::clRetainCommandQueue(self.id))
                .ok().expect("Error retaining command queue");
        }
        CommandQueue{ id: self.id }
    }
}

<|endoftext|>


<commit_before>// Copyright 2014 The Rooster Developers
//
// 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.

use super::super::getopts;
use super::super::password;
use std::iter::{Iterator, FromIterator, repeat};

pub fn callback_help() {
    println!("Usage:");
    println!("    rooster list -h");
    println!("    rooster list");
    println!("");
    println!("Example:");
    println!("    rooster list");
}

pub fn callback_exec(_matches: &getopts::Matches,
                     store: &mut password::v2::PasswordStore)
                     -> Result<(), i32> {
    let all_passwords = store.get_all_passwords();

    if all_passwords.len() == 0 {
        println!("No passwords on record yet. Add one with 'rooster add <app> <username>'.");
    } else {
        // We'll now print the password in a table.
        // The table is delimited by borders.
        let horizontal_border = String::from_iter(repeat('-').take(73));

        println!("{}", horizontal_border);
        println!("| {:2} | {:30} | {:30} |", "id", "app", "username");
        println!("{}", horizontal_border);
        for (i, p) in all_passwords.iter().enumerate() {
            println!("| {:2?} | {:30} | {:30} |", i, p.name, p.username);
        }
        println!("{}", horizontal_border);
    }

    Ok(())
}
<commit_msg>improves output of "rooster list" when piped to grep<commit_after>// Copyright 2014 The Rooster Developers
//
// 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.

use super::super::getopts;
use super::super::password;
use std::iter::{Iterator, FromIterator, repeat};
use libc::isatty;

pub fn callback_help() {
    println!("Usage:");
    println!("    rooster list -h");
    println!("    rooster list");
    println!("");
    println!("Example:");
    println!("    rooster list");
}

pub fn callback_exec(_matches: &getopts::Matches,
                     store: &mut password::v2::PasswordStore)
                     -> Result<(), i32> {
    let all_passwords = store.get_all_passwords();

    let output_is_piped = unsafe { isatty(1) } == 0;

    if all_passwords.len() == 0 {
        if !output_is_piped {
            println!("No passwords on record yet. Add one with 'rooster add <app> <username>'.");
        }
    } else {
        // We'll now print the password in a table.
        // The table is delimited by borders.
        let horizontal_border = String::from_iter(repeat('-').take(73));

        if !output_is_piped {
            println!("{}", horizontal_border);
            println!("| {:2} | {:30} | {:30} |", "id", "app", "username");
            println!("{}", horizontal_border);
        }
        for (i, p) in all_passwords.iter().enumerate() {
            println!("| {:2?} | {:30} | {:30} |", i, p.name, p.username);
        }
        if !output_is_piped {
            println!("{}", horizontal_border);
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::fmt::{Debug, Formatter, Error};
use std::path::Path;

use config::reader::from_file;
use config::types::Config as Cfg;
use cli::CliConfig;

pub struct Configuration {
    pub rtp         : String,
    pub store_sub   : String,
    pub verbose     : bool,
    pub debugging   : bool,
}

impl Configuration {

    pub fn new(config: &CliConfig) -> Configuration {
        let rtp = rtp_path(config).or(default_path());

        let mut verbose     = false;
        let mut debugging   = false;
        let mut store_sub   = String::from("/store");

        if let Some(cfg) = fetch_config(rtp.clone()) {
            if let Some(v) = cfg.lookup_boolean("verbose") {
                verbose = v;
            }
            if let Some(d) = cfg.lookup_boolean("debug") {
                debugging = d;
            }
            if let Some(s) = cfg.lookup_str("store") {
                store_sub = String::from(s);
            }
        }

        let runtimepath = rtp.unwrap_or(String::from("/tmp/"));

        debug!("Building configuration");
        debug!("  - verbose    : {}", verbose);
        debug!("  - debugging  : {}", debugging);
        debug!("  - store sub  : {}", store_sub);
        debug!("  - runtimepath: {}", runtimepath);

        Configuration {
            verbose: verbose,
            debugging: debugging,
            store_sub: store_sub,
            rtp: runtimepath,
        }
    }

    pub fn is_verbose(&self) -> bool {
        self.verbose
    }

    pub fn is_debugging(&self) -> bool {
        self.debugging
    }

    pub fn store_path(&self) -> String {
        format!("{}{}", self.rtp, self.store_sub)
    }

    pub fn get_rtp(&self) -> String {
        self.rtp.clone()
    }

}

fn rtp_path(config: &CliConfig) -> Option<String> {
    config.cli_matches.value_of("rtp")
                      .and_then(|s| Some(String::from(s)))
}

fn fetch_config(rtp: Option<String>) -> Option<Cfg> {
    rtp.and_then(|r| from_file(Path::new(&(r.clone() + "/config"))).ok())
}

fn default_path() -> Option<String> {
    use std::env::home_dir;

    home_dir().and_then(|mut buf| {
        buf.push("/.imag");
        buf.to_str().map(|s| String::from(s))
    })

}

impl Debug for Configuration {

    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "Configuration (verbose: {}, debugging: {}, rtp: {}, store path: {})",
            self.is_verbose(),
            self.is_debugging(),
            self.get_rtp(),
            self.store_path()
            )
    }

}

<commit_msg>configuration.rs: Add possibility to fetch editor<commit_after>use std::fmt::{Debug, Formatter, Error};
use std::path::Path;

use config::reader::from_file;
use config::types::Config as Cfg;
use cli::CliConfig;

pub struct Configuration {
    pub rtp         : String,
    pub store_sub   : String,
    pub verbose     : bool,
    pub debugging   : bool,
    pub editor      : Option<String>,
}

impl Configuration {

    pub fn new(config: &CliConfig) -> Configuration {
        let rtp = rtp_path(config).or(default_path());

        let mut verbose     = false;
        let mut debugging   = false;
        let mut store_sub   = String::from("/store");
        let mut editor      = None;

        if let Some(cfg) = fetch_config(rtp.clone()) {
            if let Some(v) = cfg.lookup_boolean("verbose") {
                verbose = v;
            }
            if let Some(d) = cfg.lookup_boolean("debug") {
                debugging = d;
            }
            if let Some(s) = cfg.lookup_str("store") {
                store_sub = String::from(s);
            }
            if let Some(s) = cfg.lookup_str("editor") {
                editor = Some(String::from(s));
            }
        }

        let runtimepath = rtp.unwrap_or(String::from("/tmp/"));

        debug!("Building configuration");
        debug!("  - verbose    : {}", verbose);
        debug!("  - debugging  : {}", debugging);
        debug!("  - store sub  : {}", store_sub);
        debug!("  - runtimepath: {}", runtimepath);
        debug!("  - editor     : {}", editor.unwrap_or(String::from("")));

        Configuration {
            verbose: verbose,
            debugging: debugging,
            store_sub: store_sub,
            rtp: runtimepath,
            editor: editor,
        }
    }

    pub fn is_verbose(&self) -> bool {
        self.verbose
    }

    pub fn is_debugging(&self) -> bool {
        self.debugging
    }

    pub fn store_path(&self) -> String {
        format!("{}{}", self.rtp, self.store_sub)
    }

    pub fn get_rtp(&self) -> String {
        self.rtp.clone()
    }

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

}

fn rtp_path(config: &CliConfig) -> Option<String> {
    config.cli_matches.value_of("rtp")
                      .and_then(|s| Some(String::from(s)))
}

fn fetch_config(rtp: Option<String>) -> Option<Cfg> {
    rtp.and_then(|r| from_file(Path::new(&(r.clone() + "/config"))).ok())
}

fn default_path() -> Option<String> {
    use std::env::home_dir;

    home_dir().and_then(|mut buf| {
        buf.push("/.imag");
        buf.to_str().map(|s| String::from(s))
    })

}

impl Debug for Configuration {

    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "Configuration (verbose: {}, debugging: {}, rtp: {}, store path: {})",
            self.is_verbose(),
            self.is_debugging(),
            self.get_rtp(),
            self.store_path()
            )
    }

}

<|endoftext|>


<commit_before>use std::os::raw::*;
use std::sync::Arc;

use parking_lot::Mutex;

use super::ffi::{
    RRCrtcChangeNotifyMask,
    RROutputPropertyNotifyMask,
    RRScreenChangeNotifyMask,
    True,
    Window,
    XRRScreenResources,
};
use super::{util, XConnection, XError};

// Used to test XRandR < 1.5 code path. This should always be committed as false.
const FORCE_RANDR_COMPAT: bool = false;
// Also used for testing. This should always be committed as false.
const DISABLE_MONITOR_LIST_CACHING: bool = false;

lazy_static! {
    static ref MONITORS: Mutex<Option<Vec<MonitorId>>> = Mutex::new(None);
}

pub fn invalidate_cached_monitor_list() -> Option<Vec<MonitorId>> {
    // We update this lazily.
    (*MONITORS.lock()).take()
}

#[derive(Debug, Clone)]
pub struct MonitorId {
    /// The actual id
    id: u32,
    /// The name of the monitor
    name: String,
    /// The size of the monitor
    dimensions: (u32, u32),
    /// The position of the monitor in the X screen
    position: (i32, i32),
    /// If the monitor is the primary one
    primary: bool,
    /// The DPI scale factor
    pub(crate) hidpi_factor: f32,
    /// Used to determine which windows are on this monitor
    pub(crate) rect: util::Rect,
}

impl MonitorId {
    fn from_repr(
        xconn: &Arc<XConnection>,
        resources: *mut XRRScreenResources,
        id: u32,
        repr: util::MonitorRepr,
        primary: bool,
    ) -> Self {
        let (name, hidpi_factor) = unsafe { util::get_output_info(xconn, resources, &repr) };
        let (dimensions, position) = unsafe { (repr.get_dimensions(), repr.get_position()) };
        let rect = util::Rect::new(position, dimensions);
        MonitorId {
            id,
            name,
            hidpi_factor,
            dimensions,
            position,
            primary,
            rect,
        }
    }

    pub fn get_name(&self) -> Option<String> {
        Some(self.name.clone())
    }

    #[inline]
    pub fn get_native_identifier(&self) -> u32 {
        self.id as u32
    }

    pub fn get_dimensions(&self) -> (u32, u32) {
        self.dimensions
    }

    pub fn get_position(&self) -> (i32, i32) {
        self.position
    }

    #[inline]
    pub fn get_hidpi_factor(&self) -> f32 {
        self.hidpi_factor
    }
}

pub fn get_monitor_for_window(
    xconn: &Arc<XConnection>,
    window_rect: Option<util::Rect>,
) -> MonitorId {
    let monitors = get_available_monitors(xconn);
    let default = monitors
        .get(0)
        .expect("[winit] Failed to find any monitors using XRandR.");

    let window_rect = match window_rect {
        Some(rect) => rect,
        None => return default.to_owned(),
    };

    let mut largest_overlap = 0;
    let mut matched_monitor = default;
    for monitor in &monitors {
        let overlapping_area = window_rect.get_overlapping_area(&monitor.rect);
        if overlapping_area > largest_overlap {
            largest_overlap = overlapping_area;
            matched_monitor = &monitor;
        }
    }

    matched_monitor.to_owned()
}

fn query_monitor_list(xconn: &Arc<XConnection>) -> Vec<MonitorId> {
    unsafe {
        let root = (xconn.xlib.XDefaultRootWindow)(xconn.display);
        // WARNING: this function is supposedly very slow, on the order of hundreds of ms.
        // Upon failure, `resources` will be null.
        let resources = (xconn.xrandr.XRRGetScreenResources)(xconn.display, root);
        if resources.is_null() {
            panic!("[winit] `XRRGetScreenResources` returned NULL. That should only happen if the root window doesn't exist.");
        }

        let mut available;

        if xconn.xrandr_1_5.is_some() && !FORCE_RANDR_COMPAT {
            // We're in XRandR >= 1.5, enumerate monitors. This supports things like MST and
            // videowalls.
            let xrandr_1_5 = xconn.xrandr_1_5.as_ref().unwrap();
            let mut monitor_count = 0;
            let monitors = (xrandr_1_5.XRRGetMonitors)(xconn.display, root, 1, &mut monitor_count);
            available = Vec::with_capacity(monitor_count as usize);
            for monitor_index in 0..monitor_count {
                let monitor = monitors.offset(monitor_index as isize);
                let is_primary = (*monitor).primary != 0;
                available.push(MonitorId::from_repr(
                    xconn,
                    resources,
                    monitor_index as u32,
                    monitor.into(),
                    is_primary,
                ));
            }
            (xrandr_1_5.XRRFreeMonitors)(monitors);
        } else {
            // We're in XRandR < 1.5, enumerate CRTCs. Everything will work except MST and
            // videowall setups will also show monitors that aren't in the logical groups the user
            // cares about.
            let primary = (xconn.xrandr.XRRGetOutputPrimary)(xconn.display, root);
            available = Vec::with_capacity((*resources).ncrtc as usize);
            for crtc_index in 0..(*resources).ncrtc {
                let crtc_id = *((*resources).crtcs.offset(crtc_index as isize));
                let crtc = (xconn.xrandr.XRRGetCrtcInfo)(xconn.display, resources, crtc_id);
                let is_active = (*crtc).width > 0 && (*crtc).height > 0 && (*crtc).noutput > 0;
                if is_active {
                    let crtc = util::MonitorRepr::from(crtc);
                    let is_primary = crtc.get_output() == primary;
                    available.push(MonitorId::from_repr(
                        xconn,
                        resources,
                        crtc_id as u32,
                        crtc,
                        is_primary,
                    ));
                }
                (xconn.xrandr.XRRFreeCrtcInfo)(crtc);
            }
        }

        (xconn.xrandr.XRRFreeScreenResources)(resources);
        available
    }
}

pub fn get_available_monitors(xconn: &Arc<XConnection>) -> Vec<MonitorId> {
    let mut monitors_lock = MONITORS.lock();
    (*monitors_lock)
        .as_ref()
        .cloned()
        .or_else(|| {
            let monitors = Some(query_monitor_list(xconn));
            if !DISABLE_MONITOR_LIST_CACHING {
                (*monitors_lock) = monitors.clone();
            }
            monitors
        })
        .unwrap()
}

#[inline]
pub fn get_primary_monitor(x: &Arc<XConnection>) -> MonitorId {
    let mut available_monitors = get_available_monitors(x).into_iter();
    available_monitors
        .find(|m| m.primary)
        // If no monitors were detected as being primary, we just pick one ourselves!
        .or_else(|| available_monitors.next())
        .expect("[winit] Failed to find any monitors using XRandR.")
}

pub fn select_input(xconn: &Arc<XConnection>, root: Window) -> Result<c_int, XError> {
    let mut major = 0;
    let mut minor = 0;
    let has_extension = unsafe {
        (xconn.xrandr.XRRQueryExtension)(
            xconn.display,
            &mut major,
            &mut minor,
        )
    };
    if has_extension != True {
        panic!("[winit] XRandR extension not available.");
    }

    let mut event_offset = 0;
    let mut error_offset = 0;
    let status = unsafe {
        (xconn.xrandr.XRRQueryExtension)(
            xconn.display,
            &mut event_offset,
            &mut error_offset,
        )
    };

    if status != True {
        xconn.check_errors()?;
        unreachable!("[winit] `XRRQueryExtension` failed but no error was received.");
    }

    let mask = RRCrtcChangeNotifyMask
        | RROutputPropertyNotifyMask
        | RRScreenChangeNotifyMask;
    unsafe { (xconn.xrandr.XRRSelectInput)(xconn.display, root, mask) };

    Ok(event_offset)
}
<commit_msg>X11: Fix primary monitor fallback regression (#532)<commit_after>use std::os::raw::*;
use std::sync::Arc;

use parking_lot::Mutex;

use super::ffi::{
    RRCrtcChangeNotifyMask,
    RROutputPropertyNotifyMask,
    RRScreenChangeNotifyMask,
    True,
    Window,
    XRRScreenResources,
};
use super::{util, XConnection, XError};

// Used to test XRandR < 1.5 code path. This should always be committed as false.
const FORCE_RANDR_COMPAT: bool = false;
// Also used for testing. This should always be committed as false.
const DISABLE_MONITOR_LIST_CACHING: bool = false;

lazy_static! {
    static ref XRANDR_VERSION: Mutex<Option<(c_int, c_int)>> = Mutex::default();
    static ref MONITORS: Mutex<Option<Vec<MonitorId>>> = Mutex::default();
}

fn version_is_at_least(major: c_int, minor: c_int) -> bool {
    if let Some((avail_major, avail_minor)) = *XRANDR_VERSION.lock() {
        if avail_major == major {
            avail_minor >= minor
        } else {
            avail_major > major
        }
    } else {
        unreachable!();
    }
}

pub fn invalidate_cached_monitor_list() -> Option<Vec<MonitorId>> {
    // We update this lazily.
    (*MONITORS.lock()).take()
}

#[derive(Debug, Clone)]
pub struct MonitorId {
    /// The actual id
    id: u32,
    /// The name of the monitor
    name: String,
    /// The size of the monitor
    dimensions: (u32, u32),
    /// The position of the monitor in the X screen
    position: (i32, i32),
    /// If the monitor is the primary one
    primary: bool,
    /// The DPI scale factor
    pub(crate) hidpi_factor: f32,
    /// Used to determine which windows are on this monitor
    pub(crate) rect: util::Rect,
}

impl MonitorId {
    fn from_repr(
        xconn: &Arc<XConnection>,
        resources: *mut XRRScreenResources,
        id: u32,
        repr: util::MonitorRepr,
        primary: bool,
    ) -> Self {
        let (name, hidpi_factor) = unsafe { util::get_output_info(xconn, resources, &repr) };
        let (dimensions, position) = unsafe { (repr.get_dimensions(), repr.get_position()) };
        let rect = util::Rect::new(position, dimensions);
        MonitorId {
            id,
            name,
            hidpi_factor,
            dimensions,
            position,
            primary,
            rect,
        }
    }

    pub fn get_name(&self) -> Option<String> {
        Some(self.name.clone())
    }

    #[inline]
    pub fn get_native_identifier(&self) -> u32 {
        self.id as u32
    }

    pub fn get_dimensions(&self) -> (u32, u32) {
        self.dimensions
    }

    pub fn get_position(&self) -> (i32, i32) {
        self.position
    }

    #[inline]
    pub fn get_hidpi_factor(&self) -> f32 {
        self.hidpi_factor
    }
}

pub fn get_monitor_for_window(
    xconn: &Arc<XConnection>,
    window_rect: Option<util::Rect>,
) -> MonitorId {
    let monitors = get_available_monitors(xconn);
    let default = monitors
        .get(0)
        .expect("[winit] Failed to find any monitors using XRandR.");

    let window_rect = match window_rect {
        Some(rect) => rect,
        None => return default.to_owned(),
    };

    let mut largest_overlap = 0;
    let mut matched_monitor = default;
    for monitor in &monitors {
        let overlapping_area = window_rect.get_overlapping_area(&monitor.rect);
        if overlapping_area > largest_overlap {
            largest_overlap = overlapping_area;
            matched_monitor = &monitor;
        }
    }

    matched_monitor.to_owned()
}

fn query_monitor_list(xconn: &Arc<XConnection>) -> Vec<MonitorId> {
    unsafe {
        let root = (xconn.xlib.XDefaultRootWindow)(xconn.display);
        // WARNING: this function is supposedly very slow, on the order of hundreds of ms.
        // Upon failure, `resources` will be null.
        let resources = (xconn.xrandr.XRRGetScreenResources)(xconn.display, root);
        if resources.is_null() {
            panic!("[winit] `XRRGetScreenResources` returned NULL. That should only happen if the root window doesn't exist.");
        }

        let mut available;
        let mut has_primary = false;

        if xconn.xrandr_1_5.is_some() && version_is_at_least(1, 5) && !FORCE_RANDR_COMPAT {
            // We're in XRandR >= 1.5, enumerate monitors. This supports things like MST and
            // videowalls.
            let xrandr_1_5 = xconn.xrandr_1_5.as_ref().unwrap();
            let mut monitor_count = 0;
            let monitors = (xrandr_1_5.XRRGetMonitors)(xconn.display, root, 1, &mut monitor_count);
            assert!(monitor_count >= 0);
            available = Vec::with_capacity(monitor_count as usize);
            for monitor_index in 0..monitor_count {
                let monitor = monitors.offset(monitor_index as isize);
                let is_primary = (*monitor).primary != 0;
                has_primary |= is_primary;
                available.push(MonitorId::from_repr(
                    xconn,
                    resources,
                    monitor_index as u32,
                    monitor.into(),
                    is_primary,
                ));
            }
            (xrandr_1_5.XRRFreeMonitors)(monitors);
        } else {
            // We're in XRandR < 1.5, enumerate CRTCs. Everything will work except MST and
            // videowall setups will also show monitors that aren't in the logical groups the user
            // cares about.
            let primary = (xconn.xrandr.XRRGetOutputPrimary)(xconn.display, root);
            available = Vec::with_capacity((*resources).ncrtc as usize);
            for crtc_index in 0..(*resources).ncrtc {
                let crtc_id = *((*resources).crtcs.offset(crtc_index as isize));
                let crtc = (xconn.xrandr.XRRGetCrtcInfo)(xconn.display, resources, crtc_id);
                let is_active = (*crtc).width > 0 && (*crtc).height > 0 && (*crtc).noutput > 0;
                if is_active {
                    let crtc = util::MonitorRepr::from(crtc);
                    let is_primary = crtc.get_output() == primary;
                    has_primary |= is_primary;
                    available.push(MonitorId::from_repr(
                        xconn,
                        resources,
                        crtc_id as u32,
                        crtc,
                        is_primary,
                    ));
                }
                (xconn.xrandr.XRRFreeCrtcInfo)(crtc);
            }
        }

        // If no monitors were detected as being primary, we just pick one ourselves!
        if !has_primary {
            if let Some(ref mut fallback) = available.first_mut() {
                // Setting this here will come in handy if we ever add an `is_primary` method.
                fallback.primary = true;
            }
        }

        (xconn.xrandr.XRRFreeScreenResources)(resources);
        available
    }
}

pub fn get_available_monitors(xconn: &Arc<XConnection>) -> Vec<MonitorId> {
    let mut monitors_lock = MONITORS.lock();
    (*monitors_lock)
        .as_ref()
        .cloned()
        .or_else(|| {
            let monitors = Some(query_monitor_list(xconn));
            if !DISABLE_MONITOR_LIST_CACHING {
                (*monitors_lock) = monitors.clone();
            }
            monitors
        })
        .unwrap()
}

#[inline]
pub fn get_primary_monitor(xconn: &Arc<XConnection>) -> MonitorId {
    get_available_monitors(xconn)
        .into_iter()
        .find(|monitor| monitor.primary)
        .expect("[winit] Failed to find any monitors using XRandR.")
}

pub fn select_input(xconn: &Arc<XConnection>, root: Window) -> Result<c_int, XError> {
    {
        let mut version_lock = XRANDR_VERSION.lock();
        if version_lock.is_none() {
            let mut major = 0;
            let mut minor = 0;
            let has_extension = unsafe {
                (xconn.xrandr.XRRQueryVersion)(
                    xconn.display,
                    &mut major,
                    &mut minor,
                )
            };
            if has_extension != True {
                panic!("[winit] XRandR extension not available.");
            }
            *version_lock = Some((major, minor));
        }
    }

    let mut event_offset = 0;
    let mut error_offset = 0;
    let status = unsafe {
        (xconn.xrandr.XRRQueryExtension)(
            xconn.display,
            &mut event_offset,
            &mut error_offset,
        )
    };

    if status != True {
        xconn.check_errors()?;
        unreachable!("[winit] `XRRQueryExtension` failed but no error was received.");
    }

    let mask = RRCrtcChangeNotifyMask
        | RROutputPropertyNotifyMask
        | RRScreenChangeNotifyMask;
    unsafe { (xconn.xrandr.XRRSelectInput)(xconn.display, root, mask) };

    Ok(event_offset)
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::cmp::{Ord, Ordering, PartialOrd};
use std::collections::BTreeMap;
use std::fmt;
use std::hash;
use std::ops::{Add, Sub};
use std::path::{Path, PathBuf};
use std::process::{self, Command, Stdio};
use std::str::FromStr;

use chrono::naive::NaiveDate;
use chrono::{DateTime, Datelike, Duration, TimeZone, Utc};
use serde::{Deserialize, Serialize};

pub mod api;
pub mod git;

#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct Commit {
    pub sha: String,
    pub date: Date,
}

impl Commit {
    pub fn is_try(&self) -> bool {
        self.date.0.naive_utc().date() == NaiveDate::from_ymd(2000, 1, 1)
    }
}

impl hash::Hash for Commit {
    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
        self.sha.hash(hasher);
    }
}

impl PartialEq for Commit {
    fn eq(&self, other: &Self) -> bool {
        self.sha == other.sha
    }
}

impl Eq for Commit {}

impl PartialOrd for Commit {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(&other))
    }
}

impl Ord for Commit {
    fn cmp(&self, other: &Self) -> Ordering {
        self.date
            .cmp(&other.date)
            .then_with(|| self.sha.cmp(&other.sha))
    }
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Patch {
    index: usize,
    pub name: String,
    path: PathBuf,
}

impl PartialEq for Patch {
    fn eq(&self, other: &Self) -> bool {
        self.name == other.name
    }
}

impl Eq for Patch {}

impl hash::Hash for Patch {
    fn hash<H: hash::Hasher>(&self, h: &mut H) {
        self.name.hash(h);
    }
}

impl Patch {
    pub fn new(path: PathBuf) -> Self {
        assert!(path.is_file());
        let (index, name) = {
            let file_name = path.file_name().unwrap().to_string_lossy();
            let mut parts = file_name.split("-");
            let index = parts.next().unwrap().parse().unwrap_or_else(|e| {
                panic!(
                    "{:?} should be in the format 000-name.patch, \
                     but did not start with a number: {:?}",
                    &path, e
                );
            });
            let mut name = parts.fold(String::new(), |mut acc, part| {
                acc.push_str(part);
                acc.push(' ');
                acc
            });
            let len = name.len();
            // take final space off
            name.truncate(len - 1);
            let name = name.replace(".patch", "");
            (index, name)
        };

        Patch {
            path: PathBuf::from(path.file_name().unwrap()),
            index,
            name,
        }
    }

    pub fn apply(&self, dir: &Path) -> Result<(), String> {
        log::debug!("applying {} to {:?}", self.name, dir);
        let mut cmd = process::Command::new("patch");
        cmd.current_dir(dir).args(&["-Np1", "-i"]).arg(&self.path);
        cmd.stdout(Stdio::null());
        if cmd.status().map(|s| !s.success()).unwrap_or(false) {
            return Err(format!("could not execute {:?}.", cmd));
        }
        Ok(())
    }
}

#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize, Serialize)]
pub enum BenchmarkState {
    Clean,
    Nll,
    IncrementalStart,
    IncrementalClean,
    IncrementalPatched(Patch),
}

impl BenchmarkState {
    pub fn is_base_compile(&self) -> bool {
        if let BenchmarkState::Clean = *self {
            true
        } else {
            false
        }
    }

    pub fn is_patch(&self) -> bool {
        if let BenchmarkState::IncrementalPatched(_) = *self {
            true
        } else {
            false
        }
    }

    pub fn name(&self) -> Cow<'static, str> {
        match *self {
            BenchmarkState::Clean => "clean".into(),
            BenchmarkState::Nll => "nll".into(),
            BenchmarkState::IncrementalStart => "baseline incremental".into(),
            BenchmarkState::IncrementalClean => "clean incremental".into(),
            BenchmarkState::IncrementalPatched(ref patch) => {
                format!("patched incremental: {}", patch.name).into()
            }
        }
    }

    // Otherwise we end up with "equivalent benchmarks" looking different,
    // e.g. 8-println.patch vs. 0-println.patch
    pub fn erase_path(mut self) -> Self {
        match &mut self {
            BenchmarkState::IncrementalPatched(patch) => {
                patch.index = 0;
                patch.path = PathBuf::new();
            }
            _ => {}
        }
        self
    }
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Benchmark {
    pub runs: Vec<Run>,
    pub name: String,
}

#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub struct Stat {
    pub name: String,
    pub cnt: f64,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Run {
    pub stats: Vec<Stat>,
    #[serde(default)]
    pub check: bool,
    pub release: bool,
    pub state: BenchmarkState,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RunId {
    check: bool,
    release: bool,
    state: BenchmarkState,
}

impl RunId {
    pub fn name(&self) -> String {
        self.to_string()
    }
}

impl fmt::Display for RunId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let opt = if self.release {
            "-opt"
        } else if self.check {
            "-check"
        } else {
            ""
        };
        write!(f, "{}{}", self.state.name(), opt)
    }
}

impl PartialEq for Run {
    fn eq(&self, other: &Self) -> bool {
        self.release == other.release && self.check == other.check && self.state == other.state
    }
}

impl PartialEq<RunId> for Run {
    fn eq(&self, other: &RunId) -> bool {
        self.release == other.release && self.check == other.check && self.state == other.state
    }
}

impl Run {
    pub fn is_clean(&self) -> bool {
        self.state == BenchmarkState::Clean
    }

    pub fn is_base_incr(&self) -> bool {
        self.state == BenchmarkState::IncrementalStart
    }

    pub fn is_clean_incr(&self) -> bool {
        self.state == BenchmarkState::IncrementalClean
    }

    pub fn is_println_incr(&self) -> bool {
        if let BenchmarkState::IncrementalPatched(ref patch) = self.state {
            return patch.name == "println";
        }
        false
    }

    pub fn id(&self) -> RunId {
        let state = self.state.clone();
        let state = state.erase_path();
        RunId {
            check: self.check,
            release: self.release,
            state: state,
        }
    }

    pub fn name(&self) -> String {
        self.id().name()
    }

    pub fn get_stat(&self, stat: &str) -> Option<f64> {
        self.stats.iter().find(|s| s.name == stat).map(|s| s.cnt)
    }
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ArtifactData {
    pub id: String,
    // String in Result is the output of the command that failed
    pub benchmarks: BTreeMap<String, Result<Benchmark, String>>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CommitData {
    pub commit: Commit,
    // String in Result is the output of the command that failed
    pub benchmarks: BTreeMap<String, Result<Benchmark, String>>,
    pub triple: String,
}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct DeltaTime(#[serde(with = "round_float")] pub f64);

#[derive(Debug, Hash, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Date(pub DateTime<Utc>);

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Bound {
    // sha, unverified
    Commit(String),
    Date(NaiveDate),
    None,
}

impl Serialize for Bound {
    fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
    where
        S: serde::ser::Serializer,
    {
        let s = match *self {
            Bound::Commit(ref s) => s.clone(),
            Bound::Date(ref date) => date.format("%Y-%m-%d").to_string(),
            Bound::None => String::new(),
        };
        serializer.serialize_str(&s)
    }
}

impl<'de> Deserialize<'de> for Bound {
    fn deserialize<D>(deserializer: D) -> ::std::result::Result<Bound, D::Error>
    where
        D: serde::de::Deserializer<'de>,
    {
        struct BoundVisitor;

        impl<'de> serde::de::Visitor<'de> for BoundVisitor {
            type Value = Bound;

            fn visit_str<E>(self, value: &str) -> ::std::result::Result<Bound, E>
            where
                E: serde::de::Error,
            {
                if value.is_empty() {
                    return Ok(Bound::None);
                }

                let bound = value
                    .parse::<NaiveDate>()
                    .map(|d| Bound::Date(d))
                    .unwrap_or(Bound::Commit(value.to_string()));
                if let Bound::Commit(ref sha) = bound {
                    if sha.len() != 40 {
                        return Err(serde::de::Error::invalid_value(
                            serde::de::Unexpected::Str(value),
                            &self,
                        ));
                    }
                }
                Ok(bound)
            }

            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.write_str("either a YYYY-mm-dd date or a 40 character long git commit hash")
            }
        }

        deserializer.deserialize_str(BoundVisitor)
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DateParseError {
    pub input: String,
    pub format: String,
    pub error: chrono::ParseError,
}

impl FromStr for Date {
    type Err = DateParseError;
    fn from_str(s: &str) -> Result<Date, DateParseError> {
        match DateTime::parse_from_rfc3339(s) {
            Ok(value) => Ok(Date(value.with_timezone(&Utc))),
            Err(error) => Err(DateParseError {
                input: s.to_string(),
                format: format!("RFC 3339"),
                error,
            }),
        }
    }
}

impl Date {
    pub fn from_format(date: &str, format: &str) -> Result<Date, DateParseError> {
        match DateTime::parse_from_str(date, format) {
            Ok(value) => Ok(Date(value.with_timezone(&Utc))),
            Err(_) => match Utc.datetime_from_str(date, format) {
                Ok(dt) => Ok(Date(dt)),
                Err(err) => Err(DateParseError {
                    input: date.to_string(),
                    format: format.to_string(),
                    error: err,
                }),
            },
        }
    }

    pub fn ymd_hms(year: i32, month: u32, day: u32, h: u32, m: u32, s: u32) -> Date {
        Date(Utc.ymd(year, month, day).and_hms(h, m, s))
    }

    pub fn start_of_week(&self) -> Date {
        let weekday = self.0.weekday();
        // num_days_from_sunday is 0 for Sunday
        Date(self.0 - Duration::days(weekday.num_days_from_sunday() as i64))
    }
}

impl fmt::Display for Date {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(&self.0.to_rfc3339())
    }
}

impl From<DateTime<Utc>> for Date {
    fn from(datetime: DateTime<Utc>) -> Date {
        Date(datetime)
    }
}

impl PartialEq<DateTime<Utc>> for Date {
    fn eq(&self, other: &DateTime<Utc>) -> bool {
        self.0 == *other
    }
}

impl Sub<Duration> for Date {
    type Output = Date;
    fn sub(self, rhs: Duration) -> Date {
        Date(self.0 - rhs)
    }
}

impl Add<Duration> for Date {
    type Output = Date;
    fn add(self, rhs: Duration) -> Date {
        Date(self.0 + rhs)
    }
}

impl Serialize for Date {
    fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
    where
        S: serde::ser::Serializer,
    {
        serializer.serialize_str(&self.0.to_rfc3339())
    }
}

impl<'de> Deserialize<'de> for Date {
    fn deserialize<D>(deserializer: D) -> ::std::result::Result<Date, D::Error>
    where
        D: serde::de::Deserializer<'de>,
    {
        struct DateVisitor;

        impl<'de> serde::de::Visitor<'de> for DateVisitor {
            type Value = Date;

            fn visit_str<E>(self, value: &str) -> ::std::result::Result<Date, E>
            where
                E: serde::de::Error,
            {
                Date::from_str(value).map_err(|_| {
                    serde::de::Error::invalid_value(serde::de::Unexpected::Str(value), &self)
                })
            }

            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.write_str("an RFC 3339 date")
            }
        }

        deserializer.deserialize_str(DateVisitor)
    }
}

pub fn null_means_nan<'de, D>(deserializer: D) -> ::std::result::Result<f64, D::Error>
where
    D: serde::de::Deserializer<'de>,
{
    Ok(Option::deserialize(deserializer)?.unwrap_or(0.0))
}

pub fn version_supports_incremental(version_str: &str) -> bool {
    if let Some(version) = version_str.parse::<semver::Version>().ok() {
        version >= semver::Version::new(1, 24, 0)
    } else {
        assert!(version_str == "beta" || version_str.starts_with("master"));
        true
    }
}

/// Rounds serialized and deserialized floats to 2 decimal places.
pub mod round_float {
    use serde::{Deserialize, Deserializer, Serializer};

    pub fn serialize<S>(n: &f64, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_f64((*n * 100.0).round() / 100.0)
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result<f64, D::Error>
    where
        D: Deserializer<'de>,
    {
        let n = f64::deserialize(deserializer)?;
        Ok((n * 100.0).round() / 100.0)
    }
}

pub fn run_command(cmd: &mut Command) -> Result<(), failure::Error> {
    log::trace!("running: {:?}", cmd);
    let status = cmd.status()?;
    if !status.success() {
        failure::bail!("expected success {:?}", status);
    }
    Ok(())
}

pub fn command_output(cmd: &mut Command) -> Result<process::Output, failure::Error> {
    log::trace!("running: {:?}", cmd);
    let output = cmd.output()?;
    if !output.status.success() {
        failure::bail!(
            "expected success, got {}\n\nstderr={}\n\n stdout={}",
            output.status,
            String::from_utf8_lossy(&output.stderr),
            String::from_utf8_lossy(&output.stdout)
        );
    }
    Ok(output)
}
<commit_msg>Remove restriction that identifiers must be commit hashes<commit_after>use std::borrow::Cow;
use std::cmp::{Ord, Ordering, PartialOrd};
use std::collections::BTreeMap;
use std::fmt;
use std::hash;
use std::ops::{Add, Sub};
use std::path::{Path, PathBuf};
use std::process::{self, Command, Stdio};
use std::str::FromStr;

use chrono::naive::NaiveDate;
use chrono::{DateTime, Datelike, Duration, TimeZone, Utc};
use serde::{Deserialize, Serialize};

pub mod api;
pub mod git;

#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct Commit {
    pub sha: String,
    pub date: Date,
}

impl Commit {
    pub fn is_try(&self) -> bool {
        self.date.0.naive_utc().date() == NaiveDate::from_ymd(2000, 1, 1)
    }
}

impl hash::Hash for Commit {
    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
        self.sha.hash(hasher);
    }
}

impl PartialEq for Commit {
    fn eq(&self, other: &Self) -> bool {
        self.sha == other.sha
    }
}

impl Eq for Commit {}

impl PartialOrd for Commit {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(&other))
    }
}

impl Ord for Commit {
    fn cmp(&self, other: &Self) -> Ordering {
        self.date
            .cmp(&other.date)
            .then_with(|| self.sha.cmp(&other.sha))
    }
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Patch {
    index: usize,
    pub name: String,
    path: PathBuf,
}

impl PartialEq for Patch {
    fn eq(&self, other: &Self) -> bool {
        self.name == other.name
    }
}

impl Eq for Patch {}

impl hash::Hash for Patch {
    fn hash<H: hash::Hasher>(&self, h: &mut H) {
        self.name.hash(h);
    }
}

impl Patch {
    pub fn new(path: PathBuf) -> Self {
        assert!(path.is_file());
        let (index, name) = {
            let file_name = path.file_name().unwrap().to_string_lossy();
            let mut parts = file_name.split("-");
            let index = parts.next().unwrap().parse().unwrap_or_else(|e| {
                panic!(
                    "{:?} should be in the format 000-name.patch, \
                     but did not start with a number: {:?}",
                    &path, e
                );
            });
            let mut name = parts.fold(String::new(), |mut acc, part| {
                acc.push_str(part);
                acc.push(' ');
                acc
            });
            let len = name.len();
            // take final space off
            name.truncate(len - 1);
            let name = name.replace(".patch", "");
            (index, name)
        };

        Patch {
            path: PathBuf::from(path.file_name().unwrap()),
            index,
            name,
        }
    }

    pub fn apply(&self, dir: &Path) -> Result<(), String> {
        log::debug!("applying {} to {:?}", self.name, dir);
        let mut cmd = process::Command::new("patch");
        cmd.current_dir(dir).args(&["-Np1", "-i"]).arg(&self.path);
        cmd.stdout(Stdio::null());
        if cmd.status().map(|s| !s.success()).unwrap_or(false) {
            return Err(format!("could not execute {:?}.", cmd));
        }
        Ok(())
    }
}

#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize, Serialize)]
pub enum BenchmarkState {
    Clean,
    Nll,
    IncrementalStart,
    IncrementalClean,
    IncrementalPatched(Patch),
}

impl BenchmarkState {
    pub fn is_base_compile(&self) -> bool {
        if let BenchmarkState::Clean = *self {
            true
        } else {
            false
        }
    }

    pub fn is_patch(&self) -> bool {
        if let BenchmarkState::IncrementalPatched(_) = *self {
            true
        } else {
            false
        }
    }

    pub fn name(&self) -> Cow<'static, str> {
        match *self {
            BenchmarkState::Clean => "clean".into(),
            BenchmarkState::Nll => "nll".into(),
            BenchmarkState::IncrementalStart => "baseline incremental".into(),
            BenchmarkState::IncrementalClean => "clean incremental".into(),
            BenchmarkState::IncrementalPatched(ref patch) => {
                format!("patched incremental: {}", patch.name).into()
            }
        }
    }

    // Otherwise we end up with "equivalent benchmarks" looking different,
    // e.g. 8-println.patch vs. 0-println.patch
    pub fn erase_path(mut self) -> Self {
        match &mut self {
            BenchmarkState::IncrementalPatched(patch) => {
                patch.index = 0;
                patch.path = PathBuf::new();
            }
            _ => {}
        }
        self
    }
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Benchmark {
    pub runs: Vec<Run>,
    pub name: String,
}

#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub struct Stat {
    pub name: String,
    pub cnt: f64,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Run {
    pub stats: Vec<Stat>,
    #[serde(default)]
    pub check: bool,
    pub release: bool,
    pub state: BenchmarkState,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RunId {
    check: bool,
    release: bool,
    state: BenchmarkState,
}

impl RunId {
    pub fn name(&self) -> String {
        self.to_string()
    }
}

impl fmt::Display for RunId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let opt = if self.release {
            "-opt"
        } else if self.check {
            "-check"
        } else {
            ""
        };
        write!(f, "{}{}", self.state.name(), opt)
    }
}

impl PartialEq for Run {
    fn eq(&self, other: &Self) -> bool {
        self.release == other.release && self.check == other.check && self.state == other.state
    }
}

impl PartialEq<RunId> for Run {
    fn eq(&self, other: &RunId) -> bool {
        self.release == other.release && self.check == other.check && self.state == other.state
    }
}

impl Run {
    pub fn is_clean(&self) -> bool {
        self.state == BenchmarkState::Clean
    }

    pub fn is_base_incr(&self) -> bool {
        self.state == BenchmarkState::IncrementalStart
    }

    pub fn is_clean_incr(&self) -> bool {
        self.state == BenchmarkState::IncrementalClean
    }

    pub fn is_println_incr(&self) -> bool {
        if let BenchmarkState::IncrementalPatched(ref patch) = self.state {
            return patch.name == "println";
        }
        false
    }

    pub fn id(&self) -> RunId {
        let state = self.state.clone();
        let state = state.erase_path();
        RunId {
            check: self.check,
            release: self.release,
            state: state,
        }
    }

    pub fn name(&self) -> String {
        self.id().name()
    }

    pub fn get_stat(&self, stat: &str) -> Option<f64> {
        self.stats.iter().find(|s| s.name == stat).map(|s| s.cnt)
    }
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ArtifactData {
    pub id: String,
    // String in Result is the output of the command that failed
    pub benchmarks: BTreeMap<String, Result<Benchmark, String>>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CommitData {
    pub commit: Commit,
    // String in Result is the output of the command that failed
    pub benchmarks: BTreeMap<String, Result<Benchmark, String>>,
    pub triple: String,
}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct DeltaTime(#[serde(with = "round_float")] pub f64);

#[derive(Debug, Hash, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Date(pub DateTime<Utc>);

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Bound {
    // sha, unverified
    Commit(String),
    Date(NaiveDate),
    None,
}

impl Serialize for Bound {
    fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
    where
        S: serde::ser::Serializer,
    {
        let s = match *self {
            Bound::Commit(ref s) => s.clone(),
            Bound::Date(ref date) => date.format("%Y-%m-%d").to_string(),
            Bound::None => String::new(),
        };
        serializer.serialize_str(&s)
    }
}

impl<'de> Deserialize<'de> for Bound {
    fn deserialize<D>(deserializer: D) -> ::std::result::Result<Bound, D::Error>
    where
        D: serde::de::Deserializer<'de>,
    {
        struct BoundVisitor;

        impl<'de> serde::de::Visitor<'de> for BoundVisitor {
            type Value = Bound;

            fn visit_str<E>(self, value: &str) -> ::std::result::Result<Bound, E>
            where
                E: serde::de::Error,
            {
                if value.is_empty() {
                    return Ok(Bound::None);
                }

                let bound = value
                    .parse::<NaiveDate>()
                    .map(|d| Bound::Date(d))
                    .unwrap_or(Bound::Commit(value.to_string()));
                Ok(bound)
            }

            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.write_str("either a YYYY-mm-dd date or a collection ID (usually commit hash)")
            }
        }

        deserializer.deserialize_str(BoundVisitor)
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DateParseError {
    pub input: String,
    pub format: String,
    pub error: chrono::ParseError,
}

impl FromStr for Date {
    type Err = DateParseError;
    fn from_str(s: &str) -> Result<Date, DateParseError> {
        match DateTime::parse_from_rfc3339(s) {
            Ok(value) => Ok(Date(value.with_timezone(&Utc))),
            Err(error) => Err(DateParseError {
                input: s.to_string(),
                format: format!("RFC 3339"),
                error,
            }),
        }
    }
}

impl Date {
    pub fn from_format(date: &str, format: &str) -> Result<Date, DateParseError> {
        match DateTime::parse_from_str(date, format) {
            Ok(value) => Ok(Date(value.with_timezone(&Utc))),
            Err(_) => match Utc.datetime_from_str(date, format) {
                Ok(dt) => Ok(Date(dt)),
                Err(err) => Err(DateParseError {
                    input: date.to_string(),
                    format: format.to_string(),
                    error: err,
                }),
            },
        }
    }

    pub fn ymd_hms(year: i32, month: u32, day: u32, h: u32, m: u32, s: u32) -> Date {
        Date(Utc.ymd(year, month, day).and_hms(h, m, s))
    }

    pub fn start_of_week(&self) -> Date {
        let weekday = self.0.weekday();
        // num_days_from_sunday is 0 for Sunday
        Date(self.0 - Duration::days(weekday.num_days_from_sunday() as i64))
    }
}

impl fmt::Display for Date {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(&self.0.to_rfc3339())
    }
}

impl From<DateTime<Utc>> for Date {
    fn from(datetime: DateTime<Utc>) -> Date {
        Date(datetime)
    }
}

impl PartialEq<DateTime<Utc>> for Date {
    fn eq(&self, other: &DateTime<Utc>) -> bool {
        self.0 == *other
    }
}

impl Sub<Duration> for Date {
    type Output = Date;
    fn sub(self, rhs: Duration) -> Date {
        Date(self.0 - rhs)
    }
}

impl Add<Duration> for Date {
    type Output = Date;
    fn add(self, rhs: Duration) -> Date {
        Date(self.0 + rhs)
    }
}

impl Serialize for Date {
    fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
    where
        S: serde::ser::Serializer,
    {
        serializer.serialize_str(&self.0.to_rfc3339())
    }
}

impl<'de> Deserialize<'de> for Date {
    fn deserialize<D>(deserializer: D) -> ::std::result::Result<Date, D::Error>
    where
        D: serde::de::Deserializer<'de>,
    {
        struct DateVisitor;

        impl<'de> serde::de::Visitor<'de> for DateVisitor {
            type Value = Date;

            fn visit_str<E>(self, value: &str) -> ::std::result::Result<Date, E>
            where
                E: serde::de::Error,
            {
                Date::from_str(value).map_err(|_| {
                    serde::de::Error::invalid_value(serde::de::Unexpected::Str(value), &self)
                })
            }

            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.write_str("an RFC 3339 date")
            }
        }

        deserializer.deserialize_str(DateVisitor)
    }
}

pub fn null_means_nan<'de, D>(deserializer: D) -> ::std::result::Result<f64, D::Error>
where
    D: serde::de::Deserializer<'de>,
{
    Ok(Option::deserialize(deserializer)?.unwrap_or(0.0))
}

pub fn version_supports_incremental(version_str: &str) -> bool {
    if let Some(version) = version_str.parse::<semver::Version>().ok() {
        version >= semver::Version::new(1, 24, 0)
    } else {
        assert!(version_str == "beta" || version_str.starts_with("master"));
        true
    }
}

/// Rounds serialized and deserialized floats to 2 decimal places.
pub mod round_float {
    use serde::{Deserialize, Deserializer, Serializer};

    pub fn serialize<S>(n: &f64, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_f64((*n * 100.0).round() / 100.0)
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result<f64, D::Error>
    where
        D: Deserializer<'de>,
    {
        let n = f64::deserialize(deserializer)?;
        Ok((n * 100.0).round() / 100.0)
    }
}

pub fn run_command(cmd: &mut Command) -> Result<(), failure::Error> {
    log::trace!("running: {:?}", cmd);
    let status = cmd.status()?;
    if !status.success() {
        failure::bail!("expected success {:?}", status);
    }
    Ok(())
}

pub fn command_output(cmd: &mut Command) -> Result<process::Output, failure::Error> {
    log::trace!("running: {:?}", cmd);
    let output = cmd.output()?;
    if !output.status.success() {
        failure::bail!(
            "expected success, got {}\n\nstderr={}\n\n stdout={}",
            output.status,
            String::from_utf8_lossy(&output.stderr),
            String::from_utf8_lossy(&output.stdout)
        );
    }
    Ok(output)
}
<|endoftext|>


<commit_before>use rusqlite::Connection;

#[derive(Debug)]
pub struct JobProvide {
    id: i32,
    fk_job: i32,
    fk_provider: i32,
}

pub fn table_create_job_provide(conn: &Connection) -> Result<(), &'static str> {
    let load_table = conn.execute_batch(
        "CREATE TABLE JOBPROVIDE (
                  id            INTEGER PRIMARY KEY ASC,
                  fk_job           INTEGER,
                  fk_provider      INTEGER,
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_provider) REFERENCES PROVIDER(id) ON UPDATE CASCADE
                  )",
    );
    if load_table.is_err() {
        return Err("table_create_session Failed");
    }
    load_table.unwrap();
    return Ok(());
}

pub fn insert_job_provide(
    conn: &Connection,
    job: &i32,
    provider: &i32,
) -> Result<i32, &'static str> {

    let me = JobProvide {
        id: 0,
        fk_job: *job,
        fk_provider: *provider,
    };
    let load_instance = conn.execute(
        "INSERT INTO JOBPROVIDE (fk_job, fk_provider)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_provider],
    );
    if load_instance.is_err() {
        return Err("Insert failed");
    }
    load_instance.unwrap();
    return Ok(0);
}

pub fn list_job_provide(conn: &Connection) -> Vec<JobProvide> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_provider FROM JOBPROVIDE")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobProvide {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
        }
    });
    let mut items = Vec::<JobProvide>::new();
    if wraped_fs_file_iter.is_err() {
        return items;
    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_job_provide_by_all(
    conn: &Connection,
    fk_job: &i32,
    provider: &i32,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let mut stmt = conn.prepare("SELECT JOBPROVIDE.id, JOBPROVIDE.fk_job, JOBPROVIDE.fk_provider FROM JOBPROVIDE WHERE JOBPROVIDE.fk_job = ?1 AND JOBPROVIDE.fk_provider=?2").unwrap();
    let job_provide_iter = stmt.query_map(&[fk_job, provider], |row| {
        JobProvide {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
        }
    });
    if job_provide_iter.is_err() {
        return Err("Insert failed");
    }
    let result = job_provide_iter.unwrap();
    let mut found = 0;
    for person in result {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<commit_msg>Move away from using PROVIDER<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub struct JobProvide {
    id: i32,
    fk_job: i32,
    fk_variable: i32,
}

pub fn table_create_job_provide(conn: &Connection) -> Result<(), &'static str> {
    let load_table = conn.execute_batch(
        "CREATE TABLE JOBPROVIDE (
                  id            INTEGER PRIMARY KEY ASC,
                  fk_job           INTEGER,
                  fk_variable      INTEGER,
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_variable) REFERENCES VARIABLE_NAME(id) ON UPDATE CASCADE
                  )",
    );
    if load_table.is_err() {
        return Err("table_create_session Failed");
    }
    load_table.unwrap();
    return Ok(());
}

pub fn insert_job_provide(
    conn: &Connection,
    job: &i32,
    provider: &i32,
) -> Result<i32, &'static str> {

    let me = JobProvide {
        id: 0,
        fk_job: *job,
        fk_variable: *provider,
    };
    let load_instance = conn.execute(
        "INSERT INTO JOBPROVIDE (fk_job, fk_variable)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_variable],
    );
    if load_instance.is_err() {
        return Err("Insert failed");
    }
    load_instance.unwrap();
    return Ok(0);
}

pub fn list_job_provide(conn: &Connection) -> Vec<JobProvide> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable FROM JOBPROVIDE")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobProvide {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    let mut items = Vec::<JobProvide>::new();
    if wraped_fs_file_iter.is_err() {
        return items;
    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_job_provide_by_all(
    conn: &Connection,
    fk_job: &i32,
    provider: &i32,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let mut stmt = conn.prepare("SELECT JOBPROVIDE.id, JOBPROVIDE.fk_job, JOBPROVIDE.fk_variable FROM JOBPROVIDE WHERE JOBPROVIDE.fk_job = ?1 AND JOBPROVIDE.fk_variable=?2").unwrap();
    let job_provide_iter = stmt.query_map(&[fk_job, provider], |row| {
        JobProvide {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    if job_provide_iter.is_err() {
        return Err("Insert failed");
    }
    let result = job_provide_iter.unwrap();
    let mut found = 0;
    for person in result {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>

pub trait StaticSymbolTable<'a>
{
	/// Return all symbols in this table with the specified name (in any namespace)
	fn lookup_name(name: &str) -> Vec<Symbol<'a>>;

	/// Return all symbols in this table with the specified namespace
	fn lookup_namespace(namespace: &str) -> Vec<Symbol<'a>>;

	/// Lookup a symbol by its name and namespace. Duplicate symbols are not allowed, so the result will be unique
	/// @return the specified symbol or None if the specified symbol is not in this namespace
	fn lookup_variable(namespace: &str, name: &str) -> Option<Symbol<'a>>;

	/// Lookup a symbol by its name and namespace. Duplicate symbols are not allowed, so the result will be unique
	/// @return the specified symbol or None if the specified symbol is not in this namespace
	fn lookup_function(namespace: &str, name: &str, argument_types: &Vec<&str>) -> Option<Symbol<'a>>;

	/// Adds a symbol to this table and allocates it's location
	/// Returns true if the symbol could be added; false otherwise
	/// Duplicate symbols are not allowed
	/// TODO: support overloaded methods
	fn add(class: SymbolClass<'a>, namespace: &'a str, name: &'a str) -> bool;
}

pub enum SymbolLocation<'a>
{
	/// Indicates that a register has been reserved for a specific use (e.g. by a variable)
	Register { name: &'a str },

	/// Indicates a location in memory
	Memory { address: MemoryAddress<'a> },

	/// Indicates that the symbol should not be accessed, as it represents a structured entity
	Structured
}

pub enum SymbolClass<'a>
{
	Variable { variable_type: &'a str },

	/// Function signature //TODO: support exceptions
	Function { return_type: &'a str, argument_types: &'a Vec<&'a str> },

	/// Includes class, enum, and interface
	Structure { subtype: &'a str },
}

pub struct Symbol<'a>
{
	/// Namespace of this symbol, without the final "." or the name of this symbol
	pub namespace: &'a str,

	/// Identifier for the symbol (e.g. name of variable, function, class, etc. without it's namespace)
	pub name: &'a str,

	/// What this symbol represents (class, enum, variable, function, etc)
	pub symbol_class: SymbolClass<'a>,

	/// Memory location of this symbol. Methods will always map to a SymbolLocation::Memory label with a 0 offset
	pub location: SymbolLocation<'a>,
}

pub struct MemoryAddress<'a>
{
	/// Label marking the base address where the symbol is stored
	pub label_name: &'a str,

	/// Offset from the base address to access the symbol. Methods will always have an offset of 0
	pub offset: u16,
}
<commit_msg>Update SymbolTable<commit_after>use std::collections::HashMap;

pub trait StaticSymbolTable<'a>
{
	/// Return all symbols in this table with the specified name (in any namespace)
	fn lookup_by_name(name: &str) -> Vec<Symbol<'a>>;

	/// Return all symbols in this table with the specified namespace
	fn lookup_by_namespace(namespace: &str) -> Vec<Symbol<'a>>;

	/// Lookup a symbol by its name and namespace. Duplicate symbols are not allowed, so the result will be unique
	/// @return the specified symbol or None if the specified symbol is not in this namespace
	fn lookup_variable(namespace: &str, name: &str) -> Option<Symbol<'a>>;

	/// Lookup a symbol by its name and namespace. Duplicate symbols are not allowed, so the result will be unique
	/// If no result is found in the direct namespace, the parent namespaces will be searched
	/// @return the specified symbol or None if the specified symbol is not in this namespace or a parent namespace
	fn lookup_function(namespace: &str, name: &str, argument_types: &Vec<&str>) -> Option<Symbol<'a>>;

	/// Adds a symbol to this table and allocates it's location
	/// Returns true if the symbol could be added; false otherwise
	/// Duplicate symbols are not allowed
	/// TODO: support overloaded methods
	fn add(class: SymbolClass<'a>, namespace: &'a str, name: &'a str) -> bool;
}

pub enum SymbolLocation<'a>
{
	/// Indicates that a register has been reserved for a specific use (e.g. by a variable)
	Register { name: &'a str },

	/// Indicates a location in memory
	Memory { address: MemoryAddress<'a> },

	/// Indicates that the symbol should not be accessed, as it represents a structured entity
	Structured
}

pub enum SymbolClass<'a>
{
	Variable { variable_type: &'a str },

	/// Function signature //TODO: support exceptions
	Function { return_type: &'a str, argument_types: &'a Vec<&'a str> },

	/// Includes class, enum, and interface
	Structure { subtype: &'a str, specification: Structure<'a> },
}

pub struct Structure<'a>
{
	/// Map from memberName -> (mmberType, offset)
	pub members: HashMap<&'a str, (&'a str, u16)>,
}

pub struct Symbol<'a>
{
	/// Namespace of this symbol, without the final "." or the name of this symbol
	pub namespace: &'a str,

	/// Identifier for the symbol (e.g. name of variable, function, class, etc. without it's namespace)
	pub name: &'a str,

	/// What this symbol represents (class, enum, variable, function, etc)
	pub symbol_class: SymbolClass<'a>,

	/// Memory location of this symbol. Methods will always map to a SymbolLocation::Memory label with a 0 offset
	pub location: SymbolLocation<'a>,
}

pub struct MemoryAddress<'a>
{
	/// Label marking the base address where the symbol is stored
	pub label_name: &'a str,

	/// Offset from the base address to access the symbol. Methods will always have an offset of 0
	pub offset: u16,
}
<|endoftext|>