<commit_before>use crate::{
    channels::Channels, promises::Promises, types::ShortUInt, waker::Waker, Error, Result,
};
use crossbeam_channel::{Receiver, Sender};

pub(crate) struct InternalRPC {
    rpc_in: Sender<InternalCommand>,
    rpc_out: Receiver<InternalCommand>,
    waker: Waker,
    internal_promises: Promises<()>,
}

#[derive(Clone)]
pub(crate) struct InternalRPCHandle {
    sender: Sender<InternalCommand>,
    waker: Waker,
}

impl InternalRPCHandle {
    pub(crate) fn close_connection(
        &self,
        reply_code: ShortUInt,
        reply_text: String,
        class_id: ShortUInt,
        method_id: ShortUInt,
    ) -> Result<()> {
        self.send(InternalCommand::CloseConnection(
            reply_code, reply_text, class_id, method_id,
        ))
    }

    pub(crate) fn send_connection_close_ok(&self, error: Error) -> Result<()> {
        self.send(InternalCommand::SendConnectionCloseOk(error))
    }

    pub(crate) fn remove_channel(&self, channel_id: u16, error: Error) -> Result<()> {
        self.send(InternalCommand::RemoveChannel(channel_id, error))
    }

    pub(crate) fn set_connection_closing(&self) -> Result<()> {
        self.send(InternalCommand::SetConnectionClosing)
    }

    pub(crate) fn set_connection_closed(&self, error: Error) -> Result<()> {
        self.send(InternalCommand::SetConnectionClosed(error))
    }

    pub(crate) fn set_connection_error(&self, error: Error) -> Result<()> {
        self.send(InternalCommand::SetConnectionError(error))
    }

    fn send(&self, command: InternalCommand) -> Result<()> {
        self.sender.send(command).expect("internal RPC failed");
        self.waker.wake()
    }
}

enum InternalCommand {
    CloseConnection(ShortUInt, String, ShortUInt, ShortUInt),
    SendConnectionCloseOk(Error),
    RemoveChannel(u16, Error),
    SetConnectionClosing,
    SetConnectionClosed(Error),
    SetConnectionError(Error),
}

impl InternalRPC {
    pub(crate) fn new(waker: Waker, internal_promises: Promises<()>) -> Self {
        let (rpc_in, rpc_out) = crossbeam_channel::unbounded();
        Self {
            rpc_in,
            rpc_out,
            waker,
            internal_promises,
        }
    }

    pub(crate) fn handle(&self) -> InternalRPCHandle {
        InternalRPCHandle {
            sender: self.rpc_in.clone(),
            waker: self.waker.clone(),
        }
    }

    pub(crate) fn poll(&self, channels: &Channels) -> Result<()> {
        while let Ok(command) = self.rpc_out.try_recv() {
            self.run(command, channels)?;
        }
        self.poll_internal_promises(channels)
    }

    fn run(&self, command: InternalCommand, channels: &Channels) -> Result<()> {
        use InternalCommand::*;

        match command {
            CloseConnection(reply_code, reply_text, class_id, method_id) => channels
                .get(0)
                .and_then(|channel0| {
                    self.internal_promises.register(channel0.connection_close(
                        reply_code,
                        &reply_text,
                        class_id,
                        method_id,
                    ))
                })
                .unwrap_or(Ok(())),
            SendConnectionCloseOk(error) => channels
                .get(0)
                .and_then(|channel| {
                    self.internal_promises
                        .register(channel.connection_close_ok(error))
                })
                .unwrap_or(Ok(())),
            RemoveChannel(channel_id, error) => channels.remove(channel_id, error),
            SetConnectionClosing => {
                channels.set_connection_closing();
                Ok(())
            }
            SetConnectionClosed(error) => channels.set_connection_closed(error),
            SetConnectionError(error) => channels.set_connection_error(error),
        }
    }

    fn poll_internal_promises(&self, channels: &Channels) -> Result<()> {
        if let Some(results) = self.internal_promises.try_wait() {
            for res in results {
                if let Err(err) = res {
                    channels.set_connection_error(err)?;
                }
            }
        }
        Ok(())
    }
}
<commit_msg>iternal_rpc: add logging<commit_after>use crate::{
    channels::Channels, promises::Promises, types::ShortUInt, waker::Waker, Error, Result,
};
use crossbeam_channel::{Receiver, Sender};
use log::trace;

pub(crate) struct InternalRPC {
    rpc_in: Sender<InternalCommand>,
    rpc_out: Receiver<InternalCommand>,
    waker: Waker,
    internal_promises: Promises<()>,
}

#[derive(Clone)]
pub(crate) struct InternalRPCHandle {
    sender: Sender<InternalCommand>,
    waker: Waker,
}

impl InternalRPCHandle {
    pub(crate) fn close_connection(
        &self,
        reply_code: ShortUInt,
        reply_text: String,
        class_id: ShortUInt,
        method_id: ShortUInt,
    ) -> Result<()> {
        self.send(InternalCommand::CloseConnection(
            reply_code, reply_text, class_id, method_id,
        ))
    }

    pub(crate) fn send_connection_close_ok(&self, error: Error) -> Result<()> {
        self.send(InternalCommand::SendConnectionCloseOk(error))
    }

    pub(crate) fn remove_channel(&self, channel_id: u16, error: Error) -> Result<()> {
        self.send(InternalCommand::RemoveChannel(channel_id, error))
    }

    pub(crate) fn set_connection_closing(&self) -> Result<()> {
        self.send(InternalCommand::SetConnectionClosing)
    }

    pub(crate) fn set_connection_closed(&self, error: Error) -> Result<()> {
        self.send(InternalCommand::SetConnectionClosed(error))
    }

    pub(crate) fn set_connection_error(&self, error: Error) -> Result<()> {
        self.send(InternalCommand::SetConnectionError(error))
    }

    fn send(&self, command: InternalCommand) -> Result<()> {
        trace!("Queuing internal RPC command: {:?}", command);
        self.sender.send(command).expect("internal RPC failed");
        self.waker.wake()
    }
}

#[derive(Debug)]
enum InternalCommand {
    CloseConnection(ShortUInt, String, ShortUInt, ShortUInt),
    SendConnectionCloseOk(Error),
    RemoveChannel(u16, Error),
    SetConnectionClosing,
    SetConnectionClosed(Error),
    SetConnectionError(Error),
}

impl InternalRPC {
    pub(crate) fn new(waker: Waker, internal_promises: Promises<()>) -> Self {
        let (rpc_in, rpc_out) = crossbeam_channel::unbounded();
        Self {
            rpc_in,
            rpc_out,
            waker,
            internal_promises,
        }
    }

    pub(crate) fn handle(&self) -> InternalRPCHandle {
        InternalRPCHandle {
            sender: self.rpc_in.clone(),
            waker: self.waker.clone(),
        }
    }

    pub(crate) fn poll(&self, channels: &Channels) -> Result<()> {
        while let Ok(command) = self.rpc_out.try_recv() {
            self.run(command, channels)?;
        }
        self.poll_internal_promises(channels)
    }

    fn run(&self, command: InternalCommand, channels: &Channels) -> Result<()> {
        use InternalCommand::*;

        trace!("Handling internal RPC command: {:?}", command);
        match command {
            CloseConnection(reply_code, reply_text, class_id, method_id) => channels
                .get(0)
                .and_then(|channel0| {
                    self.internal_promises.register(channel0.connection_close(
                        reply_code,
                        &reply_text,
                        class_id,
                        method_id,
                    ))
                })
                .unwrap_or(Ok(())),
            SendConnectionCloseOk(error) => channels
                .get(0)
                .and_then(|channel| {
                    self.internal_promises
                        .register(channel.connection_close_ok(error))
                })
                .unwrap_or(Ok(())),
            RemoveChannel(channel_id, error) => channels.remove(channel_id, error),
            SetConnectionClosing => {
                channels.set_connection_closing();
                Ok(())
            }
            SetConnectionClosed(error) => channels.set_connection_closed(error),
            SetConnectionError(error) => channels.set_connection_error(error),
        }
    }

    fn poll_internal_promises(&self, channels: &Channels) -> Result<()> {
        if let Some(results) = self.internal_promises.try_wait() {
            for res in results {
                if let Err(err) = res {
                    channels.set_connection_error(err)?;
                }
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>// Copyright 2018, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi;
use glib_ffi;
use gobject_ffi;
use glib::translate::*;
use glib::object::{Downcast, IsA};
use glib::Object;
use ListBox;
use ListBoxRow;

use gio;

use std::cell::RefCell;
use std::mem::transmute;

pub trait ListBoxExtManual {
    #[cfg(any(feature = "v3_16", feature = "dox"))]
    fn bind_model<'a, 'b, P: IsA<gio::ListModel> + 'a, Q: Into<Option<&'a P>>, R: FnMut(&Object) -> ListBoxRow + 'static>(&self, model: Q, create_widget_func: R);

    #[cfg(any(feature = "v3_14", feature = "dox"))]
    fn selected_foreach<P: FnMut(&Self, &ListBoxRow)>(&self, func: P);

    //#[cfg(any(feature = "v3_10", feature = "dox"))]
    //fn set_filter_func<'a, P: Into<Option<&'a /*Unimplemented*/ListBoxFilterFunc>>>(&self, filter_func: P, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify);

    //#[cfg(any(feature = "v3_10", feature = "dox"))]
    //fn set_header_func<'a, P: Into<Option<&'a /*Unimplemented*/ListBoxUpdateHeaderFunc>>>(&self, update_header: P, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify);

    //#[cfg(any(feature = "v3_10", feature = "dox"))]
    //fn set_sort_func<'a, P: Into<Option<&'a /*Unimplemented*/ListBoxSortFunc>>>(&self, sort_func: P, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify);
}

impl<O: IsA<ListBox> + IsA<Object>> ListBoxExtManual for O {
    #[cfg(any(feature = "v3_16", feature = "dox"))]
    fn bind_model<'a, 'b, P: IsA<gio::ListModel> + 'a, Q: Into<Option<&'a P>>, R: FnMut(&Object) -> ListBoxRow + 'static>(&self, model: Q, create_widget_func: R) {
        unsafe extern "C" fn bind_model_trampoline(
            item: *mut gobject_ffi::GObject,
            func: glib_ffi::gpointer,
        ) -> *mut ffi::GtkWidget
        {
            let func: &RefCell<Box<FnMut(&Object) -> ListBoxRow + 'static>> = transmute(func);

            (&mut *func.borrow_mut())(
                &from_glib_borrow(item),
            ).to_glib_full()
        }

        unsafe extern "C" fn destroy_closure(func: glib_ffi::gpointer) {
            Box::<RefCell<Box<FnMut(&Object) -> ListBoxRow + 'static>>>::from_raw(
                func as *mut _
            );
        }

        let func: Box<RefCell<Box<FnMut(&Object) -> ListBoxRow + 'static>>> =
            Box::new(RefCell::new(Box::new(create_widget_func)));
        let destroy_closure = destroy_closure;

        let model = model.into();
        let model = model.to_glib_none();

        unsafe {
            ffi::gtk_list_box_bind_model(
                self.to_glib_none().0,
                model.0,
                Some(bind_model_trampoline),
                Box::into_raw(func) as glib_ffi::gpointer,
                Some(destroy_closure),
            )
        }
    }

    #[cfg(any(feature = "v3_14", feature = "dox"))]
    fn selected_foreach<P: FnMut(&Self, &ListBoxRow)>(&self, func: P) {
        unsafe extern "C" fn foreach_trampoline<T>(
            this: *mut ffi::GtkListBox,
            row: *mut ffi::GtkListBoxRow,
            func: glib_ffi::gpointer,
        ) where T: IsA<ListBox>
        {
            let func = func as *const &mut (FnMut(&T, &ListBoxRow));

            (*func)(
                &ListBox::from_glib_borrow(this).downcast_unchecked(),
                &from_glib_borrow(row),
            )
        }

        unsafe {
            let mut func = func;
            let func_obj: &mut (FnMut(&Self, &ListBoxRow)) = &mut func;
            let func_ptr = &func_obj as *const &mut (FnMut(&Self, &ListBoxRow)) as glib_ffi::gpointer;

            ffi::gtk_list_box_selected_foreach(
                self.to_glib_none().0,
                Some(foreach_trampoline::<Self>),
                func_ptr
            )
        }
    }

    //#[cfg(any(feature = "v3_10", feature = "dox"))]
    //fn set_filter_func<'a, P: Into<Option<&'a /*Unimplemented*/ListBoxFilterFunc>>>(&self, filter_func: P, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify) {
    //    unsafe { TODO: call ffi::gtk_list_box_set_filter_func() }
    //}

    //#[cfg(any(feature = "v3_10", feature = "dox"))]
    //fn set_header_func<'a, P: Into<Option<&'a /*Unimplemented*/ListBoxUpdateHeaderFunc>>>(&self, update_header: P, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify) {
    //    unsafe { TODO: call ffi::gtk_list_box_set_header_func() }
    //}

    //#[cfg(any(feature = "v3_10", feature = "dox"))]
    //fn set_sort_func<'a, P: Into<Option<&'a /*Unimplemented*/ListBoxSortFunc>>>(&self, sort_func: P, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify) {
    //    unsafe { TODO: call ffi::gtk_list_box_set_sort_func() }
    //}
}
<commit_msg>Fix build with two-phase-borrows (aka NLL)<commit_after>// Copyright 2018, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi;
use glib_ffi;
use gobject_ffi;
use glib::translate::*;
use glib::object::{Downcast, IsA};
use glib::Object;
use ListBox;
use ListBoxRow;

use gio;

use std::cell::RefCell;
use std::mem::transmute;

pub trait ListBoxExtManual {
    #[cfg(any(feature = "v3_16", feature = "dox"))]
    fn bind_model<'a, 'b, P: IsA<gio::ListModel> + 'a, Q: Into<Option<&'a P>>, R: FnMut(&Object) -> ListBoxRow + 'static>(&self, model: Q, create_widget_func: R);

    #[cfg(any(feature = "v3_14", feature = "dox"))]
    fn selected_foreach<P: FnMut(&Self, &ListBoxRow)>(&self, func: P);

    //#[cfg(any(feature = "v3_10", feature = "dox"))]
    //fn set_filter_func<'a, P: Into<Option<&'a /*Unimplemented*/ListBoxFilterFunc>>>(&self, filter_func: P, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify);

    //#[cfg(any(feature = "v3_10", feature = "dox"))]
    //fn set_header_func<'a, P: Into<Option<&'a /*Unimplemented*/ListBoxUpdateHeaderFunc>>>(&self, update_header: P, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify);

    //#[cfg(any(feature = "v3_10", feature = "dox"))]
    //fn set_sort_func<'a, P: Into<Option<&'a /*Unimplemented*/ListBoxSortFunc>>>(&self, sort_func: P, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify);
}

impl<O: IsA<ListBox> + IsA<Object>> ListBoxExtManual for O {
    #[cfg(any(feature = "v3_16", feature = "dox"))]
    fn bind_model<'a, 'b, P: IsA<gio::ListModel> + 'a, Q: Into<Option<&'a P>>, R: FnMut(&Object) -> ListBoxRow + 'static>(&self, model: Q, create_widget_func: R) {
        unsafe extern "C" fn bind_model_trampoline(
            item: *mut gobject_ffi::GObject,
            func: glib_ffi::gpointer,
        ) -> *mut ffi::GtkWidget
        {
            let func: &RefCell<Box<FnMut(&Object) -> ListBoxRow + 'static>> = transmute(func);

            (&mut *func.borrow_mut())(
                &from_glib_borrow(item),
            ).to_glib_full()
        }

        unsafe extern "C" fn destroy_closure(func: glib_ffi::gpointer) {
            Box::<RefCell<Box<FnMut(&Object) -> ListBoxRow + 'static>>>::from_raw(
                func as *mut _
            );
        }

        let func: Box<RefCell<Box<FnMut(&Object) -> ListBoxRow + 'static>>> =
            Box::new(RefCell::new(Box::new(create_widget_func)));
        let destroy_closure = destroy_closure;

        let model = model.into();
        let model = model.to_glib_none();

        unsafe {
            ffi::gtk_list_box_bind_model(
                self.to_glib_none().0,
                model.0,
                Some(bind_model_trampoline),
                Box::into_raw(func) as glib_ffi::gpointer,
                Some(destroy_closure),
            )
        }
    }

    #[cfg(any(feature = "v3_14", feature = "dox"))]
    fn selected_foreach<P: FnMut(&Self, &ListBoxRow)>(&self, func: P) {
        unsafe extern "C" fn foreach_trampoline<T>(
            this: *mut ffi::GtkListBox,
            row: *mut ffi::GtkListBoxRow,
            func: glib_ffi::gpointer,
        ) where T: IsA<ListBox>
        {
            let func = func as *mut &mut (FnMut(&T, &ListBoxRow));

            (*func)(
                &ListBox::from_glib_borrow(this).downcast_unchecked(),
                &from_glib_borrow(row),
            )
        }

        unsafe {
            let mut func = func;
            let func_obj: &mut (FnMut(&Self, &ListBoxRow)) = &mut func;
            let func_ptr = &func_obj as *const &mut (FnMut(&Self, &ListBoxRow)) as glib_ffi::gpointer;

            ffi::gtk_list_box_selected_foreach(
                self.to_glib_none().0,
                Some(foreach_trampoline::<Self>),
                func_ptr
            )
        }
    }

    //#[cfg(any(feature = "v3_10", feature = "dox"))]
    //fn set_filter_func<'a, P: Into<Option<&'a /*Unimplemented*/ListBoxFilterFunc>>>(&self, filter_func: P, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify) {
    //    unsafe { TODO: call ffi::gtk_list_box_set_filter_func() }
    //}

    //#[cfg(any(feature = "v3_10", feature = "dox"))]
    //fn set_header_func<'a, P: Into<Option<&'a /*Unimplemented*/ListBoxUpdateHeaderFunc>>>(&self, update_header: P, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify) {
    //    unsafe { TODO: call ffi::gtk_list_box_set_header_func() }
    //}

    //#[cfg(any(feature = "v3_10", feature = "dox"))]
    //fn set_sort_func<'a, P: Into<Option<&'a /*Unimplemented*/ListBoxSortFunc>>>(&self, sort_func: P, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify) {
    //    unsafe { TODO: call ffi::gtk_list_box_set_sort_func() }
    //}
}
<|endoftext|>


<commit_before>use std::ops::DerefMut;

use libimagerror::into::IntoError;
use libimagrt::runtime::Runtime;
use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;

use result::Result;
use error::EditErrorKind;
use error::MapErrInto;

pub trait Edit {
    fn edit_content(&mut self, rt: &Runtime) -> Result<()>;
}

impl Edit for String {

    fn edit_content(&mut self, rt: &Runtime) -> Result<()> {
        edit_in_tmpfile(rt, self).map(|_| ())
    }

}

impl Edit for Entry {

    fn edit_content(&mut self, rt: &Runtime) -> Result<()> {
        edit_in_tmpfile(rt, self.get_content_mut())
            .map(|_| ())
    }

}

impl<'a> Edit for FileLockEntry<'a> {

    fn edit_content(&mut self, rt: &Runtime) -> Result<()> {
        self.deref_mut().edit_content(rt)
    }

}

pub fn edit_in_tmpfile(rt: &Runtime, s: &mut String) -> Result<()> {
    use tempfile::NamedTempFile;
    use std::io::Seek;
    use std::io::Read;
    use std::io::SeekFrom;
    use std::io::Write;

    let file      = try!(NamedTempFile::new().map_err_into(EditErrorKind::IOError));
    let file_path = file.path();
    let mut file  = try!(file.reopen().map_err_into(EditErrorKind::IOError));

    try!(file.write_all(&s.clone().into_bytes()[..]).map_err_into(EditErrorKind::IOError));
    try!(file.sync_data().map_err_into(EditErrorKind::IOError));

    if let Some(mut editor) = rt.editor() {
        let exit_status = editor.arg(file_path).status();

        match exit_status.map(|s| s.success()).map_err(Box::new) {
            Ok(true)  => {
                file.sync_data()
                    .and_then(|_| file.seek(SeekFrom::Start(0)))
                    .and_then(|_| {
                        let mut new_s = String::new();
                        let res = file.read_to_string(&mut new_s);
                        *s = new_s;
                        res
                    })
                    .map(|_| ())
                    .map_err_into(EditErrorKind::IOError)
            },
            Ok(false) => Err(EditErrorKind::ProcessExitFailure.into()),
            Err(e)    => Err(EditErrorKind::IOError.into_error_with_cause(e)),
        }
    } else {
        Err(EditErrorKind::InstantiateError.into())
    }
}
<commit_msg>[CHERRY-PICK] Refactor edit_in_tmpfile()<commit_after>use std::ops::DerefMut;

use libimagerror::into::IntoError;
use libimagrt::runtime::Runtime;
use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;

use result::Result;
use error::EditErrorKind;
use error::MapErrInto;

pub trait Edit {
    fn edit_content(&mut self, rt: &Runtime) -> Result<()>;
}

impl Edit for String {

    fn edit_content(&mut self, rt: &Runtime) -> Result<()> {
        edit_in_tmpfile(rt, self).map(|_| ())
    }

}

impl Edit for Entry {

    fn edit_content(&mut self, rt: &Runtime) -> Result<()> {
        edit_in_tmpfile(rt, self.get_content_mut())
            .map(|_| ())
    }

}

impl<'a> Edit for FileLockEntry<'a> {

    fn edit_content(&mut self, rt: &Runtime) -> Result<()> {
        self.deref_mut().edit_content(rt)
    }

}

pub fn edit_in_tmpfile(rt: &Runtime, s: &mut String) -> Result<()> {
    edit_in_tmpfile_with_command(rt.editor(), s)
}

pub fn edit_in_tmpfile_with_command(cmd: Command, s: &mut String) -> Result<()> {
    use tempfile::NamedTempFile;
    use std::io::Seek;
    use std::io::Read;
    use std::io::SeekFrom;
    use std::io::Write;

    let file      = try!(NamedTempFile::new().map_err_into(EditErrorKind::IOError));
    let file_path = file.path();
    let mut file  = try!(file.reopen().map_err_into(EditErrorKind::IOError));

    try!(file.write_all(&s.clone().into_bytes()[..]).map_err_into(EditErrorKind::IOError));
    try!(file.sync_data().map_err_into(EditErrorKind::IOError));

    if let Some(mut editor) = rt.editor() {
        let exit_status = editor.arg(file_path).status();

        match exit_status.map(|s| s.success()).map_err(Box::new) {
            Ok(true)  => {
                file.sync_data()
                    .and_then(|_| file.seek(SeekFrom::Start(0)))
                    .and_then(|_| {
                        let mut new_s = String::new();
                        let res = file.read_to_string(&mut new_s);
                        *s = new_s;
                        res
                    })
                    .map(|_| ())
                    .map_err_into(EditErrorKind::IOError)
            },
            Ok(false) => Err(EditErrorKind::ProcessExitFailure.into()),
            Err(e)    => Err(EditErrorKind::IOError.into_error_with_cause(e)),
        }
    } else {
        Err(EditErrorKind::InstantiateError.into())
    }
}

<|endoftext|>


<commit_before>#[deriving(Eq)]
struct RibonucleicAcid {
    nucleotides: ~str
}

impl RibonucleicAcid {
    pub fn new(nucleotides: ~str) -> RibonucleicAcid { RibonucleicAcid { nucleotides: nucleotides } }
}

impl ToStr for RibonucleicAcid {
    fn to_str(&self) -> ~str {
        self.nucleotides.to_str()
    }
}

struct DeoxyribonucleicAcid {
    nucleotides: ~str
}

impl DeoxyribonucleicAcid {
    pub fn new(nucleotides: ~str) -> DeoxyribonucleicAcid { DeoxyribonucleicAcid { nucleotides: nucleotides } }

    pub fn to_rna(&self) -> RibonucleicAcid {
        let rna_nucleotides = self.nucleotides.map_chars(|chr| if chr == 'T' { 'U' } else { chr } );

        RibonucleicAcid { nucleotides: rna_nucleotides }
    }
}

<commit_msg>rust rna-transcription - rust 0.8 no longer has map_chars, use replace instead<commit_after>#[deriving(Eq)]
struct RibonucleicAcid {
    nucleotides: ~str
}

impl RibonucleicAcid {
    pub fn new(nucleotides: ~str) -> RibonucleicAcid {
        RibonucleicAcid { nucleotides: nucleotides }
    }
}

impl ToStr for RibonucleicAcid {
    fn to_str(&self) -> ~str {
        self.nucleotides.to_str()
    }
}

struct DeoxyribonucleicAcid {
    nucleotides: ~str
}

impl DeoxyribonucleicAcid {
    pub fn new(nucleotides: ~str) -> DeoxyribonucleicAcid {
        DeoxyribonucleicAcid { nucleotides: nucleotides }
    }

    pub fn to_rna(&self) -> RibonucleicAcid {
        let rna_nucleotides = self.nucleotides.replace("T", "U");

        RibonucleicAcid { nucleotides: rna_nucleotides }
    }
}

<|endoftext|>


<commit_before>use rusqlite::Connection;
#[derive(Debug)]
pub struct Provider {
    id: i32,
    name: String,
}

pub fn table_create_provider(conn: &Connection) -> &Connection {
    conn.execute(
        "CREATE TABLE PROVIDER (
                  id              INTEGER PRIMARY KEY ASC,
                  name            TEXT NOT NULL UNIQUE
                  )",
        &[],
    ).unwrap();
    return conn;
}

pub fn insert_provider(conn: &Connection, name: &String) -> Result<i32, &'static str> {
    let bill = name.clone();
    let me = Provider { id: 0, name: bill };
    let provider_instance = conn.execute(
        "INSERT INTO PROVIDER (name)
                  VALUES (?1)",
        &[&me.name],
    );
    if provider_instance.is_err() {
        return Err("Insert failed");
    }
    provider_instance.unwrap();
    return Ok(0);
}

pub fn list_provider(conn: &Connection) -> Vec<Provider> {
    let mut stmt = conn.prepare("SELECT id, name  FROM PROVIDER").unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        Provider {
            id: row.get(0),
            name: row.get(1),
        }
    });
    let mut items = Vec::<Provider>::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 provider_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, name FROM PROVIDER").unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        Provider {
            id: row.get(0),
            name: row.get(1),
        }
    }).unwrap();

    for person in person_iter {
        println!("Found provider {:?}", person.unwrap());
    }
}

pub fn pk_provider_by_name(
    conn: &Connection,
    name: &String,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let bill = name.clone();
    let mut stmt = conn.prepare("SELECT id, name  FROM PROVIDER WHERE name = ?1")
        .unwrap();
    let provider_iter = stmt.query_map(&[&bill], |row| {
        Provider {
            id: row.get(0),
            name: row.get(1),
        }
    }).unwrap();
    let mut found = 0;
    for person in provider_iter {
        let bill = person.unwrap();
        *pk = bill.id;
        found = bill.id;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<commit_msg>Use Logging<commit_after>use rusqlite::Connection;
use log;

#[derive(Debug)]
pub struct Provider {
    id: i32,
    name: String,
}

pub fn table_create_provider(conn: &Connection) -> &Connection {
    conn.execute(
        "CREATE TABLE PROVIDER (
                  id              INTEGER PRIMARY KEY ASC,
                  name            TEXT NOT NULL UNIQUE
                  )",
        &[],
    ).unwrap();
    return conn;
}

pub fn insert_provider(conn: &Connection, name: &String) -> Result<i32, &'static str> {
    let bill = name.clone();
    let me = Provider { id: 0, name: bill };
    let provider_instance = conn.execute(
        "INSERT INTO PROVIDER (name)
                  VALUES (?1)",
        &[&me.name],
    );
    if provider_instance.is_err() {
        return Err("Insert failed");
    }
    provider_instance.unwrap();
    return Ok(0);
}

pub fn list_provider(conn: &Connection) -> Vec<Provider> {
    let mut stmt = conn.prepare("SELECT id, name  FROM PROVIDER").unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        Provider {
            id: row.get(0),
            name: row.get(1),
        }
    });
    let mut items = Vec::<Provider>::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 provider_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, name FROM PROVIDER").unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        Provider {
            id: row.get(0),
            name: row.get(1),
        }
    }).unwrap();

    for person in person_iter {
        info!("Found provider {:?}", person.unwrap());
    }
}

pub fn pk_provider_by_name(
    conn: &Connection,
    name: &String,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let bill = name.clone();
    let mut stmt = conn.prepare("SELECT id, name  FROM PROVIDER WHERE name = ?1")
        .unwrap();
    let provider_iter = stmt.query_map(&[&bill], |row| {
        Provider {
            id: row.get(0),
            name: row.get(1),
        }
    }).unwrap();
    let mut found = 0;
    for person in provider_iter {
        let bill = person.unwrap();
        *pk = bill.id;
        found = bill.id;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>//! Wrapper for DPDK's environment abstraction layer (EAL).
use ffi;
use std::convert::TryFrom;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, RwLock};
use thiserror::Error;

#[derive(Debug)]
struct EalSharedInner {} // TODO Remove this if unnecessary

#[derive(Debug)]
struct EalInner {
    shared: RwLock<EalSharedInner>,
}

#[derive(Debug, Clone)]
pub struct Eal {
    inner: Arc<EalInner>,
}

#[derive(Debug, Error)]
pub enum EalError {
    #[error("EAL instance should be only created once")]
    Singleton,
    #[error("EAL function returned an error code: {}", code)]
    ErrorCode { code: i32 },
}

impl Eal {
    /// Create an `Eal` instance (DPDK's environment abstraction layer).
    ///
    /// It takes command-line arguments and returns unused arguments.
    ///
    /// DPDK does not recommand users to repeat initialize and clear.
    /// https://doc.dpdk.org/api/rte__eal_8h.html#a7a745887f62a82dc83f1524e2ff2a236
    /// "It is expected that common usage of this function is to call it just before terminating the process."
    #[inline]
    pub fn new(args: &mut Vec<String>) -> Result<Self, EalError> {
        Ok(Eal {
            inner: Arc::new(EalInner::new(args)?),
        })
    }
}

//static INITIALIZED: AtomicBool = AtomicBool::new(false);

impl EalInner {
    const INITIALIZED: AtomicBool = AtomicBool::new(false);
    // Create `EalInner`.
    #[inline]
    fn new(args: &mut Vec<String>) -> Result<Self, EalError> {
        if EalInner::INITIALIZED
            .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
            .is_ok()
        {
            // 1. DPDK returns number of consumed argc
            // Safety: foriegn function (safe unless there is a bug)
            let ret = unsafe { ffi::run_with_args(dpdk_sys::rte_eal_init, &*args) };
            if ret < 0 {
                Err(EalError::ErrorCode { code: ret })
            } else {
                // 2. Strip first n args and return the remaining
                let _: Vec<_> = args.drain(..usize::try_from(ret).unwrap()).collect();
                Ok(EalInner {
                    shared: RwLock::new(EalSharedInner {}),
                })
            }
        } else {
            Err(EalError::Singleton)
        }
    }
}

impl Drop for EalInner {
    #[inline]
    fn drop(&mut self) {
        // TODO: Release lock when repeating `eal_init` and `eal_cleanup` is stabilized.
        // See `Eal::new` for more information.
        EalInner::INITIALIZED.store(false, Ordering::Release);

        // Safety: foriegn function (safe unless there is a bug)
        unsafe {
            let ret = dpdk_sys::rte_eal_cleanup();
            assert_eq!(ret, 0);
        }
    }
}
<commit_msg>early return<commit_after>//! Wrapper for DPDK's environment abstraction layer (EAL).
use ffi;
use std::convert::TryFrom;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, RwLock};
use thiserror::Error;

#[derive(Debug)]
struct EalSharedInner {} // TODO Remove this if unnecessary

#[derive(Debug)]
struct EalInner {
    shared: RwLock<EalSharedInner>,
}

#[derive(Debug, Clone)]
pub struct Eal {
    inner: Arc<EalInner>,
}

#[derive(Debug, Error)]
pub enum EalError {
    #[error("EAL instance should be only created once")]
    Singleton,
    #[error("EAL function returned an error code: {}", code)]
    ErrorCode { code: i32 },
}

impl Eal {
    /// Create an `Eal` instance (DPDK's environment abstraction layer).
    ///
    /// It takes command-line arguments and returns unused arguments.
    ///
    /// DPDK does not recommand users to repeat initialize and clear.
    /// https://doc.dpdk.org/api/rte__eal_8h.html#a7a745887f62a82dc83f1524e2ff2a236
    /// "It is expected that common usage of this function is to call it just before terminating the process."
    #[inline]
    pub fn new(args: &mut Vec<String>) -> Result<Self, EalError> {
        Ok(Eal {
            inner: Arc::new(EalInner::new(args)?),
        })
    }
}

//static INITIALIZED: AtomicBool = AtomicBool::new(false);

impl EalInner {
    const INITIALIZED: AtomicBool = AtomicBool::new(false);
    // Create `EalInner`.
    #[inline]
    fn new(args: &mut Vec<String>) -> Result<Self, EalError> {
        if EalInner::INITIALIZED
            .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
            .is_err()
        {
            return Err(EalError::Singleton);
        }

        // 1. DPDK returns number of consumed argc
        // Safety: foriegn function (safe unless there is a bug)
        let ret = unsafe { ffi::run_with_args(dpdk_sys::rte_eal_init, &*args) };
        if ret < 0 {
            Err(EalError::ErrorCode { code: ret })
        } else {
            // 2. Strip first n args and return the remaining
            let _: Vec<_> = args.drain(..usize::try_from(ret).unwrap()).collect();
            Ok(EalInner {
                shared: RwLock::new(EalSharedInner {}),
            })
        }
    }
}

impl Drop for EalInner {
    #[inline]
    fn drop(&mut self) {
        // TODO: Release lock when repeating `eal_init` and `eal_cleanup` is stabilized.
        // See `Eal::new` for more information.
        EalInner::INITIALIZED.store(false, Ordering::Release);

        // Safety: foriegn function (safe unless there is a bug)
        unsafe {
            let ret = dpdk_sys::rte_eal_cleanup();
            assert_eq!(ret, 0);
        }
    }
}
<|endoftext|>


<commit_before>use codespan::{ByteIndex, Files, LineIndex, Location, Span};
use std::io;
use termcolor::{Color, ColorSpec, WriteColor};

use crate::{Diagnostic, Label, Severity};

/// Configures how a diagnostic is rendered.
#[derive(Clone, Debug)]
pub struct Config {
    /// The color to use when rendering bugs. Defaults to `Color::Red`.
    pub bug_color: Color,
    /// The color to use when rendering errors. Defaults to `Color::Red`.
    pub error_color: Color,
    /// The color to use when rendering warnings. Defaults to `Color::Yellow`.
    pub warning_color: Color,
    /// The color to use when rendering notes. Defaults to `Color::Green`.
    pub note_color: Color,
    /// The color to use when rendering helps. Defaults to `Color::Cyan`.
    pub help_color: Color,
    /// The color to use when rendering secondary labels. Defaults to
    /// `Color::Blue` (or `Color::Cyan` on windows).
    pub secondary_color: Color,
    /// The color to use when rendering the source code borders. Defaults to
    /// `Color::Blue` (or `Color::Cyan` on windows).
    pub border_color: Color,
    /// The character to use when underlining a primary label. Defaults to: `^`.
    pub primary_mark: char,
    /// The character to use when underlining a secondary label. Defaults to: `-`.
    pub secondary_mark: char,
}

impl Default for Config {
    fn default() -> Config {
        // Blue is really difficult to see on the standard windows command line
        #[cfg(windows)]
        const BLUE: Color = Color::Cyan;
        #[cfg(not(windows))]
        const BLUE: Color = Color::Blue;

        Config {
            bug_color: Color::Red,
            error_color: Color::Red,
            warning_color: Color::Yellow,
            note_color: Color::Green,
            help_color: Color::Cyan,
            secondary_color: BLUE,
            border_color: BLUE,
            primary_mark: '^',
            secondary_mark: '-',
        }
    }
}

impl Config {
    /// The color used to mark a given severity.
    pub fn severity_color(&self, severity: Severity) -> Color {
        match severity {
            Severity::Bug => self.bug_color,
            Severity::Error => self.error_color,
            Severity::Warning => self.warning_color,
            Severity::Note => self.note_color,
            Severity::Help => self.help_color,
        }
    }
}

pub fn emit(
    mut writer: impl WriteColor,
    config: &Config,
    files: &Files,
    diagnostic: &Diagnostic,
) -> io::Result<()> {
    Header::new(diagnostic).emit(&mut writer, config)?;
    write!(writer, "\n")?;

    MarkedSource::new_primary(files, &diagnostic).emit(&mut writer, config)?;
    write!(writer, "\n")?;

    for label in &diagnostic.secondary_labels {
        MarkedSource::new_secondary(files, &label).emit(&mut writer, config)?;
        write!(writer, "\n")?;
    }

    Ok(())
}

/// Diagnostic header.
///
/// ```text
/// error[E0001]: Unexpected type in `+` application
/// ```
#[derive(Copy, Clone, Debug)]
struct Header<'a> {
    severity: Severity,
    code: Option<&'a str>,
    message: &'a str,
}

impl<'a> Header<'a> {
    fn new(diagnostic: &'a Diagnostic) -> Header<'a> {
        Header {
            severity: diagnostic.severity,
            code: diagnostic.code.as_ref().map(String::as_str),
            message: &diagnostic.message,
        }
    }

    fn severity_name(&self) -> &'static str {
        match self.severity {
            Severity::Bug => "bug",
            Severity::Error => "error",
            Severity::Warning => "warning",
            Severity::Help => "help",
            Severity::Note => "note",
        }
    }

    fn emit(&self, writer: &mut impl WriteColor, config: &Config) -> io::Result<()> {
        let message_spec = ColorSpec::new().set_bold(true).set_intense(true).clone();
        let primary_spec = ColorSpec::new()
            .set_bold(true)
            .set_intense(true)
            .set_fg(Some(config.severity_color(self.severity)))
            .clone();

        // Write severity name
        //
        // ```
        // error
        // ```
        writer.set_color(&primary_spec)?;
        write!(writer, "{}", self.severity_name())?;
        if let Some(code) = &self.code {
            // Write error code
            //
            // ```
            // [E0001]
            // ```
            write!(writer, "[{}]", code)?;
        }

        // Write diagnostic message
        //
        // ```
        // : Unexpected type in `+` application
        // ```
        writer.set_color(&message_spec)?;
        write!(writer, ": {}", self.message)?;
        write!(writer, "\n")?;
        writer.reset()?;

        Ok(())
    }
}

enum MarkStyle {
    Primary(Severity),
    Secondary,
}

/// A marked section of source code.
///
/// ```text
///   ┌─ test:2:9 ──
///   │
/// 2 │ (+ test "")
///   │         ^^ expected `Int` but found `String`
///   │
/// ```
struct MarkedSource<'a> {
    files: &'a Files,
    label: &'a Label,
    mark_style: MarkStyle,
}

impl<'a> MarkedSource<'a> {
    fn new_primary(files: &'a Files, diagnostic: &'a Diagnostic) -> MarkedSource<'a> {
        MarkedSource {
            files,
            label: &diagnostic.primary_label,
            mark_style: MarkStyle::Primary(diagnostic.severity),
        }
    }

    fn new_secondary(files: &'a Files, label: &'a Label) -> MarkedSource<'a> {
        MarkedSource {
            files,
            label,
            mark_style: MarkStyle::Secondary,
        }
    }

    fn span(&self) -> Span {
        self.label.span
    }

    fn start(&self) -> ByteIndex {
        self.span().start()
    }

    fn end(&self) -> ByteIndex {
        self.span().end()
    }

    fn file_name(&self) -> &'a str {
        self.files.name(self.label.file_id)
    }

    fn location(&self, byte_index: ByteIndex) -> Result<Location, impl std::error::Error> {
        self.files.location(self.label.file_id, byte_index)
    }

    fn source_slice(&self, span: Span) -> Result<&'a str, impl std::error::Error> {
        self.files.source_slice(self.label.file_id, span)
    }

    fn line_span(&self, line_index: LineIndex) -> Result<Span, impl std::error::Error> {
        self.files.line_span(self.label.file_id, line_index)
    }

    fn label_color(&self, config: &Config) -> Color {
        match self.mark_style {
            MarkStyle::Primary(severity) => config.severity_color(severity),
            MarkStyle::Secondary => config.secondary_color,
        }
    }

    fn underline_char(&self, config: &Config) -> char {
        match self.mark_style {
            MarkStyle::Primary(_) => config.primary_mark,
            MarkStyle::Secondary => config.secondary_mark,
        }
    }

    fn emit(&self, writer: &mut impl WriteColor, config: &Config) -> io::Result<()> {
        let border_spec = ColorSpec::new()
            .set_fg(Some(config.border_color))
            .clone();
        let label_spec = ColorSpec::new()
            .set_fg(Some(self.label_color(config)))
            .clone();

        let start = self.location(self.start()).expect("location_start");
        let end = self.location(self.end()).expect("location_end");
        let start_line_span = self.line_span(start.line).expect("line_span");
        let end_line_span = self.line_span(end.line).expect("line_span");

        // Use the length of the last line number as the gutter padding
        let gutter_padding = format!("{}", end.line.number()).len();

        // Label locus
        //
        // ```
        // ┌── test:2:9 ──
        // ```

        // Write border corner
        writer.set_color(&border_spec)?;
        write!(writer, "{: >width$} ┌── ", "", width = gutter_padding)?;
        writer.reset()?;

        // Write source locus
        SourceLocus::new(self.file_name(), start).emit(writer, config)?;
        writer.set_color(&border_spec)?;

        // Write border end
        writer.set_color(&border_spec)?;
        write!(writer, " ──")?;
        writer.reset()?;

        write!(writer, "\n")?;

        // Source code snippet
        //
        // ```
        //   │
        // 2 │ (+ test "")
        //   │         ^^ expected `Int` but found `String`
        //   │
        // ```

        // Write line number and border
        writer.set_color(&border_spec)?;
        write!(writer, "{: >width$} │ ", "", width = gutter_padding)?;
        write!(writer, "\n")?;
        write!(
            writer,
            "{: >width$} │ ",
            start.line.number(),
            width = gutter_padding,
        )?;
        writer.reset()?;

        let line_trimmer = |ch: char| ch == '\r' || ch == '\n';

        // Write source prefix before marked section
        let prefix_span = start_line_span.with_end(self.start());
        let source_prefix = self.source_slice(prefix_span).expect("prefix");
        write!(writer, "{}", source_prefix)?;

        // Write marked section
        let mark_len = if start.line == end.line {
            // Single line

            // Write marked source section
            let marked_source = self.source_slice(self.span()).expect("marked_source");
            writer.set_color(&label_spec)?;
            write!(writer, "{}", marked_source)?;
            writer.reset()?;
            marked_source.len()
        } else {
            // Multiple lines

            // Write marked source section
            let marked_span = start_line_span.with_start(self.start());
            let marked_source = self.source_slice(marked_span).expect("start_of_marked");
            writer.set_color(&label_spec)?;
            write!(writer, "{}", marked_source)?;

            for line_index in ((start.line.to_usize() + 1)..end.line.to_usize())
                .map(|i| LineIndex::from(i as u32))
            {
                // Write line number and border
                writer.set_color(&border_spec)?;
                write!(
                    writer,
                    "{: >width$} │ ",
                    line_index.number(),
                    width = gutter_padding,
                )?;

                // Write marked source section
                let mark_span = self.line_span(line_index).expect("marked_line_span");
                let marked_source = self.source_slice(mark_span).expect("marked_source");
                writer.set_color(&label_spec)?;
                write!(writer, "{}", marked_source.trim_end_matches(line_trimmer))?;
                write!(writer, "\n")?;
            }

            // Write line number and border
            writer.set_color(&border_spec)?;
            write!(
                writer,
                "{: >width$} │ ",
                end.line.number(),
                width = gutter_padding,
            )?;

            // Write marked source section
            let mark_span = end_line_span.with_end(self.end());
            let marked_source = self.source_slice(mark_span).expect("marked_source");
            writer.set_color(&label_spec)?;
            write!(writer, "{}", marked_source)?;
            writer.reset()?;
            marked_source.len()
        };

        // Write source suffix after marked section
        let suffix_span = end_line_span.with_start(self.end());
        let source_suffix = self.source_slice(suffix_span).expect("suffix");
        write!(writer, "{}", source_suffix.trim_end_matches(line_trimmer))?;
        write!(writer, "\n")?;

        // Write underline border
        writer.set_color(&border_spec)?;
        write!(writer, "{: >width$} │ ", "", width = gutter_padding)?;
        writer.reset()?;

        // Write underline and label
        writer.set_color(&label_spec)?;
        write!(writer, "{: >width$}", "", width = source_prefix.len())?;
        for _ in 0..mark_len {
            write!(writer, "{}", self.underline_char(config))?;
        }
        if !self.label.message.is_empty() {
            write!(writer, " {}", self.label.message)?;
            write!(writer, "\n")?;
        }
        writer.reset()?;

        // Write final border
        writer.set_color(&border_spec)?;
        write!(writer, "{: >width$} │", "", width = gutter_padding)?;
        write!(writer, "\n")?;
        writer.reset()?;

        Ok(())
    }
}

/// The 'location focus' of a source code snippet.
///
/// This is displayed in a way that other tools can understand, for
/// example when command+clicking in iTerm.
///
/// ```text
/// test:2:9
/// ```
struct SourceLocus<'a> {
    file_name: &'a str,
    location: Location,
}

impl<'a> SourceLocus<'a> {
    fn new(file_name: &'a str, location: Location) -> SourceLocus<'a> {
        SourceLocus {
            file_name,
            location,
        }
    }

    fn emit(&self, writer: &mut impl WriteColor, _config: &Config) -> io::Result<()> {
        write!(
            writer,
            "{file}:{line}:{column}",
            file = self.file_name,
            line = self.location.line.number(),
            column = self.location.column.number(),
        )
    }
}
<commit_msg>Add more configs for border and line numbers<commit_after>use codespan::{ByteIndex, Files, LineIndex, LineNumber, Location, Span};
use std::io;
use termcolor::{Color, ColorSpec, WriteColor};

use crate::{Diagnostic, Label, Severity};

/// Configures how a diagnostic is rendered.
#[derive(Clone, Debug)]
pub struct Config {
    /// The color to use when rendering bugs. Defaults to `Color::Red`.
    pub bug_color: Color,
    /// The color to use when rendering errors. Defaults to `Color::Red`.
    pub error_color: Color,
    /// The color to use when rendering warnings. Defaults to `Color::Yellow`.
    pub warning_color: Color,
    /// The color to use when rendering notes. Defaults to `Color::Green`.
    pub note_color: Color,
    /// The color to use when rendering helps. Defaults to `Color::Cyan`.
    pub help_color: Color,
    /// The color to use when rendering secondary labels. Defaults to
    /// `Color::Blue` (or `Color::Cyan` on windows).
    pub secondary_color: Color,
    /// The color to use when rendering the line numbers. Defaults to
    /// `Color::Blue` (or `Color::Cyan` on windows).
    pub line_number_color: Color,
    /// The color to use when rendering the source code borders. Defaults to
    /// `Color::Blue` (or `Color::Cyan` on windows).
    pub border_color: Color,
    /// The character to use when marking the top-left corner of the source.
    /// Defaults to: `┌`.
    pub border_top_left_char: char,
    /// The character to use when marking the top border of the source.
    /// Defaults to: `─`.
    pub border_top_char: char,
    /// The character to use when marking the left border of the source.
    /// Defaults to: `│`.
    pub border_left_char: char,
    /// The character to use when underlining a primary label. Defaults to: `^`.
    pub primary_underline_char: char,
    /// The character to use when underlining a secondary label. Defaults to: `-`.
    pub secondary_underline_char: char,
}

impl Default for Config {
    fn default() -> Config {
        // Blue is really difficult to see on the standard windows command line
        #[cfg(windows)]
        const BLUE: Color = Color::Cyan;
        #[cfg(not(windows))]
        const BLUE: Color = Color::Blue;

        Config {
            bug_color: Color::Red,
            error_color: Color::Red,
            warning_color: Color::Yellow,
            note_color: Color::Green,
            help_color: Color::Cyan,
            secondary_color: BLUE,
            line_number_color: BLUE,
            border_color: BLUE,
            border_top_left_char: '┌',
            border_top_char: '─',
            border_left_char: '│',
            primary_underline_char: '^',
            secondary_underline_char: '-',
        }
    }
}

impl Config {
    /// The color used to mark a given severity.
    pub fn severity_color(&self, severity: Severity) -> Color {
        match severity {
            Severity::Bug => self.bug_color,
            Severity::Error => self.error_color,
            Severity::Warning => self.warning_color,
            Severity::Note => self.note_color,
            Severity::Help => self.help_color,
        }
    }
}

pub fn emit(
    mut writer: impl WriteColor,
    config: &Config,
    files: &Files,
    diagnostic: &Diagnostic,
) -> io::Result<()> {
    Header::new(diagnostic).emit(&mut writer, config)?;
    write!(writer, "\n")?;

    MarkedSource::new_primary(files, &diagnostic).emit(&mut writer, config)?;
    write!(writer, "\n")?;

    for label in &diagnostic.secondary_labels {
        MarkedSource::new_secondary(files, &label).emit(&mut writer, config)?;
        write!(writer, "\n")?;
    }

    Ok(())
}

/// Diagnostic header.
///
/// ```text
/// error[E0001]: Unexpected type in `+` application
/// ```
#[derive(Copy, Clone, Debug)]
struct Header<'a> {
    severity: Severity,
    code: Option<&'a str>,
    message: &'a str,
}

impl<'a> Header<'a> {
    fn new(diagnostic: &'a Diagnostic) -> Header<'a> {
        Header {
            severity: diagnostic.severity,
            code: diagnostic.code.as_ref().map(String::as_str),
            message: &diagnostic.message,
        }
    }

    fn severity_name(&self) -> &'static str {
        match self.severity {
            Severity::Bug => "bug",
            Severity::Error => "error",
            Severity::Warning => "warning",
            Severity::Help => "help",
            Severity::Note => "note",
        }
    }

    fn emit(&self, writer: &mut impl WriteColor, config: &Config) -> io::Result<()> {
        let message_spec = ColorSpec::new().set_bold(true).set_intense(true).clone();
        let primary_spec = ColorSpec::new()
            .set_bold(true)
            .set_intense(true)
            .set_fg(Some(config.severity_color(self.severity)))
            .clone();

        // Write severity name
        //
        // ```
        // error
        // ```
        writer.set_color(&primary_spec)?;
        write!(writer, "{}", self.severity_name())?;
        if let Some(code) = &self.code {
            // Write error code
            //
            // ```
            // [E0001]
            // ```
            write!(writer, "[{}]", code)?;
        }

        // Write diagnostic message
        //
        // ```
        // : Unexpected type in `+` application
        // ```
        writer.set_color(&message_spec)?;
        write!(writer, ": {}", self.message)?;
        write!(writer, "\n")?;
        writer.reset()?;

        Ok(())
    }
}

enum MarkStyle {
    Primary(Severity),
    Secondary,
}

/// A marked section of source code.
///
/// ```text
///   ┌── test:2:9 ───
///   │
/// 2 │ (+ test "")
///   │         ^^ expected `Int` but found `String`
///   │
/// ```
struct MarkedSource<'a> {
    files: &'a Files,
    label: &'a Label,
    mark_style: MarkStyle,
}

impl<'a> MarkedSource<'a> {
    fn new_primary(files: &'a Files, diagnostic: &'a Diagnostic) -> MarkedSource<'a> {
        MarkedSource {
            files,
            label: &diagnostic.primary_label,
            mark_style: MarkStyle::Primary(diagnostic.severity),
        }
    }

    fn new_secondary(files: &'a Files, label: &'a Label) -> MarkedSource<'a> {
        MarkedSource {
            files,
            label,
            mark_style: MarkStyle::Secondary,
        }
    }

    fn span(&self) -> Span {
        self.label.span
    }

    fn start(&self) -> ByteIndex {
        self.span().start()
    }

    fn end(&self) -> ByteIndex {
        self.span().end()
    }

    fn file_name(&self) -> &'a str {
        self.files.name(self.label.file_id)
    }

    fn location(&self, byte_index: ByteIndex) -> Result<Location, impl std::error::Error> {
        self.files.location(self.label.file_id, byte_index)
    }

    fn source_slice(&self, span: Span) -> Result<&'a str, impl std::error::Error> {
        self.files.source_slice(self.label.file_id, span)
    }

    fn line_span(&self, line_index: LineIndex) -> Result<Span, impl std::error::Error> {
        self.files.line_span(self.label.file_id, line_index)
    }

    fn label_color(&self, config: &Config) -> Color {
        match self.mark_style {
            MarkStyle::Primary(severity) => config.severity_color(severity),
            MarkStyle::Secondary => config.secondary_color,
        }
    }

    fn underline_char(&self, config: &Config) -> char {
        match self.mark_style {
            MarkStyle::Primary(_) => config.primary_underline_char,
            MarkStyle::Secondary => config.secondary_underline_char,
        }
    }

    fn emit(&self, writer: &mut impl WriteColor, config: &Config) -> io::Result<()> {
        let label_spec = ColorSpec::new()
            .set_fg(Some(self.label_color(config)))
            .clone();

        let start = self.location(self.start()).expect("location_start");
        let end = self.location(self.end()).expect("location_end");
        let start_line_span = self.line_span(start.line).expect("line_span");
        let end_line_span = self.line_span(end.line).expect("line_span");

        // Use the length of the last line number as the gutter padding
        let gutter_padding = format!("{}", end.line.number()).len();

        // Top left border and locus.
        //
        // ```
        // ┌── test:2:9 ───
        // ```

        Gutter::new(None, gutter_padding).emit(writer, config)?;
        BorderTopLeft::new().emit(writer, config)?;
        BorderTop::new(2).emit(writer, config)?;
        write!(writer, " ")?;

        Locus::new(self.file_name(), start).emit(writer, config)?;

        write!(writer, " ")?;
        BorderTop::new(3).emit(writer, config)?;
        write!(writer, "\n")?;

        // Source code snippet
        //
        // ```
        //   │
        // 2 │ (+ test "")
        //   │         ^^ expected `Int` but found `String`
        //   │
        // ```

        // Write line number and border
        Gutter::new(None, gutter_padding).emit(writer, config)?;
        BorderLeft::new().emit(writer, config)?;
        write!(writer, "\n")?;
        Gutter::new(start.line.number(), gutter_padding).emit(writer, config)?;
        BorderLeft::new().emit(writer, config)?;

        let line_trimmer = |ch: char| ch == '\r' || ch == '\n';

        // Write source prefix before marked section
        let prefix_span = start_line_span.with_end(self.start());
        let source_prefix = self.source_slice(prefix_span).expect("prefix");
        write!(writer, "{}", source_prefix)?;

        // Write marked section
        let mark_len = if start.line == end.line {
            // Single line

            // Write marked source section
            let marked_source = self.source_slice(self.span()).expect("marked_source");
            writer.set_color(&label_spec)?;
            write!(writer, "{}", marked_source)?;
            writer.reset()?;
            marked_source.len()
        } else {
            // Multiple lines

            // Write marked source section
            let marked_span = start_line_span.with_start(self.start());
            let marked_source = self.source_slice(marked_span).expect("start_of_marked");
            writer.set_color(&label_spec)?;
            write!(writer, "{}", marked_source)?;

            for line_index in ((start.line.to_usize() + 1)..end.line.to_usize())
                .map(|i| LineIndex::from(i as u32))
            {
                // Write line number and border
                Gutter::new(line_index.number(), gutter_padding).emit(writer, config)?;
                BorderLeft::new().emit(writer, config)?;

                // Write marked source section
                let mark_span = self.line_span(line_index).expect("marked_line_span");
                let marked_source = self.source_slice(mark_span).expect("marked_source");
                writer.set_color(&label_spec)?;
                write!(writer, "{}", marked_source.trim_end_matches(line_trimmer))?;
                write!(writer, "\n")?;
            }

            // Write line number and border
            Gutter::new(end.line.number(), gutter_padding).emit(writer, config)?;
            BorderLeft::new().emit(writer, config)?;

            // Write marked source section
            let mark_span = end_line_span.with_end(self.end());
            let marked_source = self.source_slice(mark_span).expect("marked_source");
            writer.set_color(&label_spec)?;
            write!(writer, "{}", marked_source)?;
            writer.reset()?;
            marked_source.len()
        };

        // Write source suffix after marked section
        let suffix_span = end_line_span.with_start(self.end());
        let source_suffix = self.source_slice(suffix_span).expect("suffix");
        write!(writer, "{}", source_suffix.trim_end_matches(line_trimmer))?;
        write!(writer, "\n")?;

        // Write underline border
        Gutter::new(None, gutter_padding).emit(writer, config)?;
        BorderLeft::new().emit(writer, config)?;

        // Write underline and label
        writer.set_color(&label_spec)?;
        write!(
            writer,
            "{space: >width$}",
            space = "",
            width = source_prefix.len(),
        )?;
        for _ in 0..mark_len {
            write!(writer, "{}", self.underline_char(config))?;
        }
        if !self.label.message.is_empty() {
            write!(writer, " {}", self.label.message)?;
        }
        write!(writer, "\n")?;
        writer.reset()?;

        // Write final border
        Gutter::new(None, gutter_padding).emit(writer, config)?;
        BorderLeft::new().emit(writer, config)?;
        write!(writer, "\n")?;

        Ok(())
    }
}

/// The 'location focus' of a source code snippet.
///
/// This is displayed in a way that other tools can understand, for
/// example when command+clicking in iTerm.
///
/// ```text
/// test:2:9
/// ```
struct Locus<'a> {
    file_name: &'a str,
    location: Location,
}

impl<'a> Locus<'a> {
    fn new(file_name: &'a str, location: Location) -> Locus<'a> {
        Locus {
            file_name,
            location,
        }
    }

    fn emit(&self, writer: &mut impl WriteColor, _config: &Config) -> io::Result<()> {
        write!(
            writer,
            "{file}:{line}:{column}",
            file = self.file_name,
            line = self.location.line.number(),
            column = self.location.column.number(),
        )
    }
}

/// The left-hand gutter of a source line.
struct Gutter {
    line_number: Option<LineNumber>,
    gutter_padding: usize,
}

impl<'a> Gutter {
    fn new(line_number: impl Into<Option<LineNumber>>, gutter_padding: usize) -> Gutter {
        Gutter {
            line_number: line_number.into(),
            gutter_padding,
        }
    }

    fn emit(&self, writer: &mut impl WriteColor, config: &Config) -> io::Result<()> {
        match self.line_number {
            None => {
                write!(
                    writer,
                    "{space: >width$} ",
                    space = "",
                    width = self.gutter_padding,
                )?;
            },
            Some(line_number) => {
                let line_number_spec = ColorSpec::new()
                    .set_fg(Some(config.line_number_color))
                    .clone();

                writer.set_color(&line_number_spec)?;
                write!(
                    writer,
                    "{line: >width$} ",
                    line = line_number,
                    width = self.gutter_padding,
                )?;
                writer.reset()?;
            },
        }

        Ok(())
    }
}

/// The top-left corner of a source line.
struct BorderTopLeft {}

impl BorderTopLeft {
    fn new() -> BorderTopLeft {
        BorderTopLeft {}
    }

    fn emit(&self, writer: &mut impl WriteColor, config: &Config) -> io::Result<()> {
        let border_spec = ColorSpec::new().set_fg(Some(config.border_color)).clone();

        writer.set_color(&border_spec)?;
        write!(writer, "{top_left}", top_left = config.border_top_left_char)?;
        writer.reset()?;

        Ok(())
    }
}

/// The top border of a source line.
struct BorderTop {
    width: usize,
}

impl BorderTop {
    fn new(width: usize) -> BorderTop {
        BorderTop { width }
    }

    fn emit(&self, writer: &mut impl WriteColor, config: &Config) -> io::Result<()> {
        let border_spec = ColorSpec::new().set_fg(Some(config.border_color)).clone();

        writer.set_color(&border_spec)?;
        for _ in 0..self.width {
            write!(writer, "{top}", top = config.border_top_char)?
        }
        writer.reset()?;

        Ok(())
    }
}

/// The left-hand border of a source line.
struct BorderLeft {}

impl<'a> BorderLeft {
    fn new() -> BorderLeft {
        BorderLeft {}
    }

    fn emit(&self, writer: &mut impl WriteColor, config: &Config) -> io::Result<()> {
        let border_spec = ColorSpec::new().set_fg(Some(config.border_color)).clone();

        writer.set_color(&border_spec)?;
        write!(writer, "{left} ", left = config.border_left_char)?;
        writer.reset()?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>use serde::{Deserialize, Serialize};
use strum::{Display, EnumString};

/// A description of a user's connectivity and availability for chat.
#[derive(Clone, Copy, Debug, PartialEq, Display, EnumString, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum PresenceState {
    /// Disconnected from the service.
    Offline,

    /// Connected to the service.
    Online,

    /// Connected to the service but not available for chat.
    Unavailable,
}

impl Default for PresenceState {
    fn default() -> Self {
        Self::Online
    }
}
<commit_msg>Add presence module documentation<commit_after>//! Common types for the [presence module][presence]
//!
//! [presence]: https://matrix.org/docs/spec/client_server/r0.6.1#id62

use serde::{Deserialize, Serialize};
use strum::{Display, EnumString};

/// A description of a user's connectivity and availability for chat.
#[derive(Clone, Copy, Debug, PartialEq, Display, EnumString, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum PresenceState {
    /// Disconnected from the service.
    Offline,

    /// Connected to the service.
    Online,

    /// Connected to the service but not available for chat.
    Unavailable,
}

impl Default for PresenceState {
    fn default() -> Self {
        Self::Online
    }
}
<|endoftext|>


<commit_before>//! Module defining all sensor related structures.

use std::collections::BTreeMap;
use rustc_serialize::json::{Json, ToJson};
use utils::Optional;
use status::Status;

//--- Templates ---//

/// A trait for all possible sensor templates.
/// the SensorTemplate's are capable of registring themself in a Status struct
pub trait SensorTemplate : Send+Sync {
    fn to_sensor(&self, value_str: &str, status: &mut Status);
}

#[derive(Debug, Clone)]
pub struct PeopleNowPresentSensorTemplate {
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
}

impl SensorTemplate for PeopleNowPresentSensorTemplate {
    fn to_sensor(&self, value_str: &str, status: &mut Status) {
        // TODO error handling
        let value = value_str.parse::<i64>().unwrap();
        let sensor = PeopleNowPresentSensor {
            location: self.location.clone(),
            name: self.name.clone(),
            names: self.names.clone(),
            description: self.description.clone(),
            value: value,
        };
        // TODO handle empty
        status.sensors.as_mut().map_or((), |v| {
            match v.people_now_present {
                Optional::Value(ref mut vec_sensors) => vec_sensors.push(sensor),
                Optional::Absent => v.people_now_present = Optional::Value(vec![sensor]),
            }
        });
    }
}

#[derive(Debug, Clone)]
pub struct TemperatureSensorTemplate {
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
}

impl SensorTemplate for TemperatureSensorTemplate {
    fn to_sensor(&self, value_str: &str, status: &mut Status) {
        // TODO error handling
        let value = value_str.parse::<f64>().unwrap();
        let sensor = TemperatureSensor {
            unit: self.unit.clone(),
            location: self.location.clone(),
            name: self.name.clone(),
            description: self.description.clone(),
            value: value,
        };
        // TODO handle empty
        status.sensors.as_mut().map_or((), |v| {
            match v.temperature {
                Optional::Value(ref mut vec_sensors) => vec_sensors.push(sensor),
                Optional::Absent => v.temperature = Optional::Value(vec![sensor]),
            }
        });
    }
}

//--- Structures ---//

#[derive(Debug, Clone)]
pub struct PeopleNowPresentSensor {
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
    pub value: i64,
}

#[derive(Debug, Clone)]
pub struct TemperatureSensor {
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
    pub value: f64,
}

#[derive(Debug, Clone)]
pub struct Sensors {
    pub people_now_present: Optional<Vec<PeopleNowPresentSensor>>,
    pub temperature: Optional<Vec<TemperatureSensor>>,
}

//--- Serialization ---//

impl ToJson for Sensors {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.people_now_present.as_ref().map_or((), |v| { d.insert("people_now_present".to_string(), v.to_json()); });
        self.temperature.as_ref().map_or((), |v| { d.insert("temperature".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for PeopleNowPresentSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        self.location.as_ref().map_or((), |v| { d.insert("location".to_string(), v.to_json()); });
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.names.as_ref().map_or((), |v| { d.insert("names".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for TemperatureSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        d.insert("unit".to_string(), self.unit.to_json());
        d.insert("location".to_string(), self.location.to_json());
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}
<commit_msg>spaceapi: Fix typos in SensorTemplate documentation<commit_after>//! Module defining all sensor related structures.

use std::collections::BTreeMap;
use rustc_serialize::json::{Json, ToJson};
use utils::Optional;
use status::Status;

//--- Templates ---//

/// A trait for all possible sensor templates.
/// the `SensorTemplate`s are capable of registering themselves in a `Status` struct
pub trait SensorTemplate : Send+Sync {
    fn to_sensor(&self, value_str: &str, status: &mut Status);
}

#[derive(Debug, Clone)]
pub struct PeopleNowPresentSensorTemplate {
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
}

impl SensorTemplate for PeopleNowPresentSensorTemplate {
    fn to_sensor(&self, value_str: &str, status: &mut Status) {
        // TODO error handling
        let value = value_str.parse::<i64>().unwrap();
        let sensor = PeopleNowPresentSensor {
            location: self.location.clone(),
            name: self.name.clone(),
            names: self.names.clone(),
            description: self.description.clone(),
            value: value,
        };
        // TODO handle empty
        status.sensors.as_mut().map_or((), |v| {
            match v.people_now_present {
                Optional::Value(ref mut vec_sensors) => vec_sensors.push(sensor),
                Optional::Absent => v.people_now_present = Optional::Value(vec![sensor]),
            }
        });
    }
}

#[derive(Debug, Clone)]
pub struct TemperatureSensorTemplate {
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
}

impl SensorTemplate for TemperatureSensorTemplate {
    fn to_sensor(&self, value_str: &str, status: &mut Status) {
        // TODO error handling
        let value = value_str.parse::<f64>().unwrap();
        let sensor = TemperatureSensor {
            unit: self.unit.clone(),
            location: self.location.clone(),
            name: self.name.clone(),
            description: self.description.clone(),
            value: value,
        };
        // TODO handle empty
        status.sensors.as_mut().map_or((), |v| {
            match v.temperature {
                Optional::Value(ref mut vec_sensors) => vec_sensors.push(sensor),
                Optional::Absent => v.temperature = Optional::Value(vec![sensor]),
            }
        });
    }
}

//--- Structures ---//

#[derive(Debug, Clone)]
pub struct PeopleNowPresentSensor {
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
    pub value: i64,
}

#[derive(Debug, Clone)]
pub struct TemperatureSensor {
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
    pub value: f64,
}

#[derive(Debug, Clone)]
pub struct Sensors {
    pub people_now_present: Optional<Vec<PeopleNowPresentSensor>>,
    pub temperature: Optional<Vec<TemperatureSensor>>,
}

//--- Serialization ---//

impl ToJson for Sensors {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.people_now_present.as_ref().map_or((), |v| { d.insert("people_now_present".to_string(), v.to_json()); });
        self.temperature.as_ref().map_or((), |v| { d.insert("temperature".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for PeopleNowPresentSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        self.location.as_ref().map_or((), |v| { d.insert("location".to_string(), v.to_json()); });
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.names.as_ref().map_or((), |v| { d.insert("names".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for TemperatureSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        d.insert("unit".to_string(), self.unit.to_json());
        d.insert("location".to_string(), self.location.to_json());
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix basic volume normalisation<commit_after><|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate sputnikvm;
extern crate bigint;
extern crate serde_json;
extern crate gethrpc;

use serde_json::{Value};
use std::process;
use std::fs::File;
use std::path::Path;
use std::io::{BufReader};
use std::str::FromStr;
use std::collections::HashMap;

use sputnikvm::{Gas, Address};
use bigint::{U256, M256, read_hex};
use sputnikvm::vm::{BlockHeader, Context, SeqTransactionVM, Transaction, VM, Log, Patch, AccountCommitment, Account, FRONTIER_PATCH};
use sputnikvm::vm::errors::RequireError;
use gethrpc::{regression, GethRPCClient, RPCCall, RPCBlock, RPCTransaction, RPCLog};

fn from_rpc_block(block: &RPCBlock) -> BlockHeader {
    BlockHeader {
        coinbase: Address::from_str(&block.miner).unwrap(),
        timestamp: M256::from_str(&block.timestamp).unwrap(),
        number: M256::from_str(&block.number).unwrap(),
        difficulty: M256::from_str(&block.difficulty).unwrap(),
        gas_limit: Gas::from_str(&block.gasLimit).unwrap(),
    }
}

fn from_rpc_transaction(transaction: &RPCTransaction) -> Transaction {
    if transaction.to.is_empty() {
        Transaction::ContractCreation {
            caller: Address::from_str(&transaction.from).unwrap(),
            value: U256::from_str(&transaction.value).unwrap(),
            gas_limit: Gas::from_str(&transaction.gas).unwrap(),
            gas_price: Gas::from_str(&transaction.gasPrice).unwrap(),
            init: read_hex(&transaction.input).unwrap(),
        }
    } else {
        Transaction::MessageCall {
            caller: Address::from_str(&transaction.from).unwrap(),
            address: Address::from_str(&transaction.to).unwrap(),
            value: U256::from_str(&transaction.value).unwrap(),
            gas_limit: Gas::from_str(&transaction.gas).unwrap(),
            gas_price: Gas::from_str(&transaction.gasPrice).unwrap(),
            data: read_hex(&transaction.input).unwrap(),
        }
    }
}

fn from_rpc_log(log: &RPCLog) -> Log {
    let mut topics: Vec<M256> = Vec::new();
    for topic in &log.topics {
        topics.push(M256::from_str(&topic).unwrap());
    }
    Log {
        address: Address::from_str(&log.address).unwrap(),
        data: read_hex(&log.data).unwrap(),
        topics: topics,
    }
}

fn handle_fire(client: &mut GethRPCClient, vm: &mut SeqTransactionVM, last_block_number: &str) {
    loop {
        match vm.fire() {
            Ok(()) => {
                println!("VM exited successfully, checking results ...");
                break;
            },
            Err(RequireError::Account(address)) => {
                println!("Feeding VM account at 0x{:x} ...", address);
                let nonce = M256::from_str(&client.get_transaction_count(&format!("0x{:x}", address),
                                                                         &last_block_number)).unwrap();
                let balance = U256::from_str(&client.get_balance(&format!("0x{:x}", address),
                                                                 &last_block_number)).unwrap();
                let code = read_hex(&client.get_code(&format!("0x{:x}", address),
                                                     &last_block_number)).unwrap();
                vm.commit_account(AccountCommitment::Full {
                    nonce: nonce,
                    address: address,
                    balance: balance,
                    code: code,
                });
            },
            Err(RequireError::AccountStorage(address, index)) => {
                println!("Feeding VM account storage at 0x{:x} with index 0x{:x} ...", address, index);
                let value = M256::from_str(&client.get_storage_at(&format!("0x{:x}", address),
                                                                  &format!("0x{:x}", index),
                                                                  &last_block_number)).unwrap();
                vm.commit_account(AccountCommitment::Storage {
                    address: address,
                    index: index,
                    value: value,
                });
            },
            Err(RequireError::AccountCode(address)) => {
                println!("Feeding VM account code at 0x{:x} ...", address);
                let code = read_hex(&client.get_code(&format!("0x{:x}", address),
                                                     &last_block_number)).unwrap();
                vm.commit_account(AccountCommitment::Code {
                    address: address,
                    code: code,
                });
            }
            Err(err) => {
                println!("Unhandled require: {:?}", err);
                unimplemented!()
            },
        }
    }
}

fn test_block(client: &mut GethRPCClient, number: usize) {
    let block = client.get_block_by_number(format!("0x{:x}", number).as_str());
    println!("block {}, transaction count: {}", block.number, block.transactions.len());
    let last_number = number - 1;
    let block_header = from_rpc_block(&block);

    let mut last_vm: Option<SeqTransactionVM> = None;
    for transaction_hash in block.transactions {
        println!("\nworking on transaction {}", transaction_hash);
        let transaction = from_rpc_transaction(&client.get_transaction_by_hash(&transaction_hash));
        let receipt = client.get_transaction_receipt(&transaction_hash);

        let mut vm = if last_vm.is_none() {
            SeqTransactionVM::new(transaction, block_header.clone(), &FRONTIER_PATCH)
        } else {
            SeqTransactionVM::with_previous(transaction, block_header.clone(), &FRONTIER_PATCH, last_vm.as_ref().unwrap())
        };

        handle_fire(client, &mut vm, &format!("0x{:x}", last_number));

        assert!(Gas::from_str(&receipt.gasUsed).unwrap() == vm.used_gas());
        assert!(receipt.logs.len() == vm.logs().len());
        for i in 0..receipt.logs.len() {
            assert!(from_rpc_log(&receipt.logs[i]) == vm.logs()[i]);
        }
    }

    if last_vm.is_some() {
        for account in last_vm.as_ref().unwrap().accounts() {
            match account {
                &Account::Full {
                    address,
                    balance,
                    ref changing_storage,
                    ..
                } => {
                    let expected_balance = client.get_balance(&format!("0x{:x}", address),
                                                              &block.number);
                    assert!(U256::from_str(&expected_balance).unwrap() == balance);
                    let changing_storage: HashMap<M256, M256> = changing_storage.clone().into();
                    for (key, value) in changing_storage {
                        let expected_value = client.get_storage_at(&format!("0x{:x}", address),
                                                                   &format!("0x{:x}", key),
                                                                   &block.number);
                        assert!(M256::from_str(&expected_value).unwrap() == value);
                    }
                },
                _ => unimplemented!(),
            }
        }
    }
}

fn main() {
    let matches = clap_app!(regtests =>
        (version: "0.1")
        (author: "Ethereum Classic Contributors")
        (about: "Performs an regression test on the entire Ethereum Classic blockchain.\n\nSteps to reproduce:\n* Install Ethereum Classic Geth: `$ go install github.com/ethereumproject/go-ethereum/cmd/geth`.\n* Run Geth with this command: `$ ~/go/bin/geth --rpc --rpcaddr 127.0.0.1 --rpcport 8545`.\n* Wait for the chain to sync.\n* Change directory into the `regtests` directory `$ cd regtests`\n* Run this command: `$ RUST_BACKTRACE=1 cargo run --bin regtests -- -r http://127.0.0.1:8545")
        (@arg RPC: -r --rpc +takes_value +required "Domain of Ethereum Classic Geth's RPC endpoint. e.g. `-r http://127.0.0.1:8545`.")
    ).get_matches();

    let address = matches.value_of("RPC").unwrap();
    let mut client = GethRPCClient::new(address);
    println!("net version: {}", client.net_version());

    test_block(&mut client, 49439);
}
<commit_msg>Problem: missing parameterize of block number for #122<commit_after>#[macro_use]
extern crate clap;
extern crate sputnikvm;
extern crate bigint;
extern crate serde_json;
extern crate gethrpc;

use serde_json::{Value};
use std::process;
use std::fs::File;
use std::path::Path;
use std::io::{BufReader};
use std::str::FromStr;
use std::collections::HashMap;

use sputnikvm::{Gas, Address};
use bigint::{U256, M256, read_hex};
use sputnikvm::vm::{BlockHeader, Context, SeqTransactionVM, Transaction, VM, Log, Patch, AccountCommitment, Account, FRONTIER_PATCH};
use sputnikvm::vm::errors::RequireError;
use gethrpc::{regression, GethRPCClient, RPCCall, RPCBlock, RPCTransaction, RPCLog};

fn from_rpc_block(block: &RPCBlock) -> BlockHeader {
    BlockHeader {
        coinbase: Address::from_str(&block.miner).unwrap(),
        timestamp: M256::from_str(&block.timestamp).unwrap(),
        number: M256::from_str(&block.number).unwrap(),
        difficulty: M256::from_str(&block.difficulty).unwrap(),
        gas_limit: Gas::from_str(&block.gasLimit).unwrap(),
    }
}

fn from_rpc_transaction(transaction: &RPCTransaction) -> Transaction {
    if transaction.to.is_empty() {
        Transaction::ContractCreation {
            caller: Address::from_str(&transaction.from).unwrap(),
            value: U256::from_str(&transaction.value).unwrap(),
            gas_limit: Gas::from_str(&transaction.gas).unwrap(),
            gas_price: Gas::from_str(&transaction.gasPrice).unwrap(),
            init: read_hex(&transaction.input).unwrap(),
        }
    } else {
        Transaction::MessageCall {
            caller: Address::from_str(&transaction.from).unwrap(),
            address: Address::from_str(&transaction.to).unwrap(),
            value: U256::from_str(&transaction.value).unwrap(),
            gas_limit: Gas::from_str(&transaction.gas).unwrap(),
            gas_price: Gas::from_str(&transaction.gasPrice).unwrap(),
            data: read_hex(&transaction.input).unwrap(),
        }
    }
}

fn from_rpc_log(log: &RPCLog) -> Log {
    let mut topics: Vec<M256> = Vec::new();
    for topic in &log.topics {
        topics.push(M256::from_str(&topic).unwrap());
    }
    Log {
        address: Address::from_str(&log.address).unwrap(),
        data: read_hex(&log.data).unwrap(),
        topics: topics,
    }
}

fn handle_fire(client: &mut GethRPCClient, vm: &mut SeqTransactionVM, last_block_number: &str) {
    loop {
        match vm.fire() {
            Ok(()) => {
                println!("VM exited successfully, checking results ...");
                break;
            },
            Err(RequireError::Account(address)) => {
                println!("Feeding VM account at 0x{:x} ...", address);
                let nonce = M256::from_str(&client.get_transaction_count(&format!("0x{:x}", address),
                                                                         &last_block_number)).unwrap();
                let balance = U256::from_str(&client.get_balance(&format!("0x{:x}", address),
                                                                 &last_block_number)).unwrap();
                let code = read_hex(&client.get_code(&format!("0x{:x}", address),
                                                     &last_block_number)).unwrap();
                vm.commit_account(AccountCommitment::Full {
                    nonce: nonce,
                    address: address,
                    balance: balance,
                    code: code,
                });
            },
            Err(RequireError::AccountStorage(address, index)) => {
                println!("Feeding VM account storage at 0x{:x} with index 0x{:x} ...", address, index);
                let value = M256::from_str(&client.get_storage_at(&format!("0x{:x}", address),
                                                                  &format!("0x{:x}", index),
                                                                  &last_block_number)).unwrap();
                vm.commit_account(AccountCommitment::Storage {
                    address: address,
                    index: index,
                    value: value,
                });
            },
            Err(RequireError::AccountCode(address)) => {
                println!("Feeding VM account code at 0x{:x} ...", address);
                let code = read_hex(&client.get_code(&format!("0x{:x}", address),
                                                     &last_block_number)).unwrap();
                vm.commit_account(AccountCommitment::Code {
                    address: address,
                    code: code,
                });
            }
            Err(err) => {
                println!("Unhandled require: {:?}", err);
                unimplemented!()
            },
        }
    }
}

fn test_block(client: &mut GethRPCClient, number: usize) {
    let block = client.get_block_by_number(format!("0x{:x}", number).as_str());
    println!("block {}, transaction count: {}", block.number, block.transactions.len());
    let last_number = number - 1;
    let block_header = from_rpc_block(&block);

    let mut last_vm: Option<SeqTransactionVM> = None;
    for transaction_hash in block.transactions {
        println!("\nworking on transaction {}", transaction_hash);
        let transaction = from_rpc_transaction(&client.get_transaction_by_hash(&transaction_hash));
        let receipt = client.get_transaction_receipt(&transaction_hash);

        let mut vm = if last_vm.is_none() {
            SeqTransactionVM::new(transaction, block_header.clone(), &FRONTIER_PATCH)
        } else {
            SeqTransactionVM::with_previous(transaction, block_header.clone(), &FRONTIER_PATCH, last_vm.as_ref().unwrap())
        };

        handle_fire(client, &mut vm, &format!("0x{:x}", last_number));

        assert!(Gas::from_str(&receipt.gasUsed).unwrap() == vm.used_gas());
        assert!(receipt.logs.len() == vm.logs().len());
        for i in 0..receipt.logs.len() {
            assert!(from_rpc_log(&receipt.logs[i]) == vm.logs()[i]);
        }
    }

    if last_vm.is_some() {
        for account in last_vm.as_ref().unwrap().accounts() {
            match account {
                &Account::Full {
                    address,
                    balance,
                    ref changing_storage,
                    ..
                } => {
                    let expected_balance = client.get_balance(&format!("0x{:x}", address),
                                                              &block.number);
                    assert!(U256::from_str(&expected_balance).unwrap() == balance);
                    let changing_storage: HashMap<M256, M256> = changing_storage.clone().into();
                    for (key, value) in changing_storage {
                        let expected_value = client.get_storage_at(&format!("0x{:x}", address),
                                                                   &format!("0x{:x}", key),
                                                                   &block.number);
                        assert!(M256::from_str(&expected_value).unwrap() == value);
                    }
                },
                _ => unimplemented!(),
            }
        }
    }
}

fn main() {
    let matches = clap_app!(regtests =>
        (version: "0.1")
        (author: "Ethereum Classic Contributors")
        (about: "Performs an regression test on the entire Ethereum Classic blockchain.\n\nSteps to reproduce:\n* Install Ethereum Classic Geth: `$ go install github.com/ethereumproject/go-ethereum/cmd/geth`.\n* Run Geth with this command: `$ ~/go/bin/geth --rpc --rpcaddr 127.0.0.1 --rpcport 8545`.\n* Wait for the chain to sync.\n* Change directory into the `regtests` directory `$ cd regtests`\n* Run this command: `$ RUST_BACKTRACE=1 cargo run --bin regtests -- -r http://127.0.0.1:8545")
        (@arg RPC: -r --rpc +takes_value +required "Domain of Ethereum Classic Geth's RPC endpoint. e.g. `-r http://127.0.0.1:8545`.")
        (@arg NUMBER: -n --number +takes_value + required "Block number to run this test. Radix is 10. e.g. `-n 49439`.")
    ).get_matches();

    let address = matches.value_of("RPC").unwrap();
    let number = usize::from_str_radix(&matches.value_of("NUMBER").unwrap(), 10).unwrap();
    let mut client = GethRPCClient::new(address);
    println!("net version: {}", client.net_version());

    test_block(&mut client, number);
}
<|endoftext|>


<commit_before>use super::util::{CacheKeyPath,
                  ConfigOptCacheKeyPath};
use configopt::ConfigOpt;
use structopt::StructOpt;

arg_enum! {
    #[derive(Deserialize)]
    pub enum Shell {
        Bash,
        Fish,
        Zsh,
        PowerShell,
    }
}

#[derive(ConfigOpt, StructOpt)]
#[structopt(no_version)]
/// Commands relating to Habitat runtime config
pub enum Cli {
    /// Sets up the CLI with reasonable defaults
    Setup(CacheKeyPath),
    /// Creates command-line completers for your shell
    #[structopt(no_version)]
    Completers {
        /// The name of the shell you want to generate the command-completion
        #[structopt(name = "SHELL",
                    short = "s",
                    long = "shell",
                    possible_values = &Shell::variants(),
                    case_insensitive = true)]
        shell: Shell,
    },
}

#[derive(ConfigOpt, StructOpt)]
#[structopt(name = "setup", no_version, rename_all = "screamingsnake")]
/// Sets up the CLI with reasonable defaults
pub struct CliSetup {
    #[structopt(flatten)]
    cache_key_path: CacheKeyPath
}<commit_msg>[Refactor] move cli completers into its own struct<commit_after>use super::util::{CacheKeyPath,
                  ConfigOptCacheKeyPath};
use configopt::ConfigOpt;
use structopt::StructOpt;

arg_enum! {
    #[derive(Serialize, Deserialize)]
    pub enum Shell {
        Bash,
        Fish,
        Zsh,
        PowerShell,
    }
}

#[derive(ConfigOpt, StructOpt)]
#[structopt(no_version)]
/// Commands relating to Habitat runtime config
pub enum Cli {
    /// Sets up the CLI with reasonable defaults
    Setup(CacheKeyPath),
    /// Creates command-line completers for your shell
    Completers(CliCompleters),
}

#[derive(ConfigOpt, StructOpt)]
#[structopt(name = "setup", no_version, rename_all = "screamingsnake")]
/// Sets up the CLI with reasonable defaults
pub struct CliSetup {
    #[structopt(flatten)]
    cache_key_path: CacheKeyPath
}

#[derive(ConfigOpt, StructOpt)]
#[structopt(name = "completers", no_version, rename_all = "screamingsnake")]
/// Creates command-line completers for your shell
pub struct CliCompleters {
    /// The name of the shell you want to generate the command-completion
    #[structopt(name = "SHELL",
                short = "s",
                long = "shell",
                possible_values = &Shell::variants(),
                case_insensitive = true)]
    shell: Shell,
}<|endoftext|>