<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013, 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#![crate_name = "grust_Gio_2_0"]
#![crate_type = "lib"]

#![allow(trivial_numeric_casts)]
#![allow(unstable_features)]

#![feature(core)]

#[macro_use]
extern crate grust;

#[macro_use]
#[no_link]
extern crate bitflags;

extern crate gio_2_0_sys as ffi;
extern crate glib_2_0_sys as glib_ffi;
extern crate gobject_2_0_sys as gobject_ffi;
extern crate grust_GLib_2_0 as glib;
extern crate grust_GObject_2_0 as gobject;

use grust::enumeration;
use grust::enumeration::IntrospectedEnum as _grust_IntrospectedEnumTrait;
use grust::error;
use grust::gstr;
use grust::gtype::GType;
use grust::marker;
use grust::object;
use grust::quark;
use grust::refcount;
use grust::types::{gint, gpointer};
use grust::wrap;

use std::fmt;
use std::mem;
use std::num;
use std::ptr;
use std::result;

#[repr(C)]
pub struct AsyncResult {
    raw: ffi::GAsyncResult,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for AsyncResult {
    type Raw = ffi::GAsyncResult;
}

#[repr(C)]
pub struct File {
    raw: ffi::GFile,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for File {
    type Raw = ffi::GFile;
}

#[repr(C)]
pub struct Cancellable {
    raw: ffi::GCancellable,
    _marker: marker::ObjectMarker
}

unsafe impl Send for Cancellable { }
unsafe impl Sync for Cancellable { }
unsafe impl wrap::Wrapper for Cancellable {
    type Raw = ffi::GCancellable;
}

#[repr(C)]
pub struct InputStream {
    raw: ffi::GInputStream,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for InputStream {
    type Raw = ffi::GInputStream;
}

#[repr(C)]
pub struct FileInputStream {
    raw: ffi::GFileInputStream,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for FileInputStream {
    type Raw = ffi::GFileInputStream;
}

#[derive(Copy, PartialEq, Eq, FromPrimitive, Debug)]
#[repr(C)]
pub enum IOErrorEnum {
    Failed = 0,
    NotFound = 1,
    Exists = 2,
    // ...
}

impl enumeration::IntrospectedEnum for IOErrorEnum {

    fn from_int(v: gint) -> Result<Self, enumeration::UnknownValue> {
        num::from_i32(v as i32)
            .ok_or_else(|| enumeration::UnknownValue(v))
    }

    fn to_int(&self) -> gint {
        *self as gint
    }

    fn name(&self) -> &'static str {
        match *self {
            IOErrorEnum::Failed => "failed",
            IOErrorEnum::NotFound => "not-found",
            IOErrorEnum::Exists   => "exists",
            // ...
        }
    }
}

impl enumeration::EnumType for IOErrorEnum {
    fn get_type() -> GType {
        unsafe { GType::from_raw(ffi::g_io_error_enum_get_type()) }
    }
}

impl error::Domain for IOErrorEnum {
    fn domain() -> quark::Quark {
        g_static_quark!(b"g-io-error-quark\0")
    }
}

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

pub mod flags {

    pub mod file_attribute_info {
        use grust::flags::prelude::*;
        use ffi;
        use std::fmt;

        bitflags! {
            flags Flags: guint {
                const NONE            = 0,
                const COPY_WITH_FILE  = 1,
                const COPY_WHEN_MOVED = 2,
            }
        }

        impl IntrospectedFlags for Flags {

            fn from_uint(v: guint) -> Result<Flags, UnknownFlags> {
                Flags::from_bits(v)
                    .ok_or_else(|| UnknownFlags::new(v, Flags::all().bits()))
            }

            #[inline]
            fn to_uint(&self) -> guint {
                self.bits()
            }
        }

        impl FlagsType for Flags {
            fn get_type() -> GType {
                unsafe {
                    let raw = ffi::g_file_attribute_info_flags_get_type();
                    GType::from_raw(raw)
                }
            }
        }

        impl fmt::Debug for Flags {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                const FLAG_INFO: &'static [(Flags, &'static str)] = &[
                    (COPY_WITH_FILE,  "COPY_WITH_FILE"),
                    (COPY_WHEN_MOVED, "COPY_WHEN_MOVED")
                ];
                let mut contents = String::new();
                for &(flag, name) in FLAG_INFO.iter() {
                    if self.contains(flag) {
                        if contents.is_empty() {
                            contents.push_str(name);
                        } else {
                            contents.push('|');
                            contents.push_str(name);
                        }
                    }
                }
                write!(f, "FileAttributeInfoFlags({})", contents)
            }
        }
    }
}

pub use flags::file_attribute_info::Flags as FileAttributeInfoFlags;

mod async {
    use ffi;
    use gobject_ffi;
    use gobject;

    use grust::types::gpointer;
    use grust::wrap;
    use std::mem;

    pub extern "C" fn async_ready_callback<F>(source_object: *mut gobject_ffi::GObject,
                                              res: *mut ffi::GAsyncResult,
                                              user_data: gpointer)
        where F: FnOnce(&gobject::Object, &super::AsyncResult)
    {
        let cb: Box<F> = unsafe { mem::transmute(user_data) };
        let arg1 = unsafe { wrap::from_raw::<gobject::Object>(source_object) };
        let arg2 = unsafe { wrap::from_raw::<super::AsyncResult>(res) };
        cb(arg1, arg2);
    }
}

pub mod cast {
    use grust::object;

    use gobject;

    pub trait AsAsyncResult {
        fn as_async_result(&self) -> &super::AsyncResult;
    }

    impl<T> AsAsyncResult for T where T: object::Upcast<super::AsyncResult> {

        #[inline]
        fn as_async_result(&self) -> &super::AsyncResult {
            self.upcast()
        }
    }

    pub trait AsCancellable : gobject::cast::AsObject {
        fn as_cancellable(&self) -> &super::Cancellable;
    }

    impl<T> AsCancellable for T
        where T: object::Upcast<super::Cancellable>,
              T: object::Upcast<gobject::Object>
    {
        #[inline]
        fn as_cancellable(&self) -> &super::Cancellable {
            self.upcast()
        }
    }

    pub trait AsInputStream : gobject::cast::AsObject {
        fn as_input_stream(&self) -> &super::InputStream;
    }

    impl<T> AsInputStream for T
        where T: object::Upcast<super::InputStream>,
              T: object::Upcast<gobject::Object>
    {
        #[inline]
        fn as_input_stream(&self) -> &super::InputStream {
            self.upcast()
        }
    }

    pub trait AsFileInputStream : AsInputStream {
        fn as_file_input_stream(&self) -> &super::FileInputStream;
    }

    impl<T> AsFileInputStream for T
        where T: object::Upcast<super::FileInputStream>,
              T: object::Upcast<super::InputStream>,
              T: object::Upcast<gobject::Object>
    {
        #[inline]
        fn as_file_input_stream(&self) -> &super::FileInputStream {
            self.upcast()
        }
    }

    pub trait AsFile {
        fn as_file(&self) -> &super::File;
    }

    impl<T> AsFile for T where T: object::Upcast<super::File> {

        #[inline]
        fn as_file(&self) -> &super::File {
            self.upcast()
        }
    }
}

impl File {

    pub fn new_for_path(path: &gstr::Utf8) -> refcount::Ref<File> {
        unsafe {
            let ret = ffi::g_file_new_for_path(path.as_ptr());
            refcount::Ref::from_raw(ret)
        }
    }

    pub fn get_path(&self) -> gstr::OwnedGStr {
        unsafe {
            use grust::wrap::Wrapper;
            let ret = ffi::g_file_get_path(self.as_mut_ptr());
            gstr::OwnedGStr::from_ptr(ret)
        }
    }

    pub fn read_async<F>(&self,
                         io_priority: gint,
                         cancellable: Option<&Cancellable>,
                         callback: F)
        where F: FnOnce(&gobject::Object, &AsyncResult),
              F: 'static
    {
        unsafe {
            use grust::wrap::Wrapper;
            let self_raw = self.as_mut_ptr();
            let cancellable = {
                match cancellable {
                    Some(c) => c.as_mut_ptr(),
                    None    => std::ptr::null_mut()
                }
            };
            let callback: gpointer = mem::transmute(Box::new(callback));

            ffi::g_file_read_async(self_raw,
                                   io_priority,
                                   cancellable,
                                   async::async_ready_callback::<F>,
                                   callback);
        }
    }

    pub fn read_finish(&self, res: &AsyncResult)
                      -> result::Result<refcount::Ref<FileInputStream>,
                                        error::Error> {
        let mut err: *mut glib_ffi::GError = ptr::null_mut();
        let ret = unsafe {
            use grust::wrap::Wrapper;
            ffi::g_file_read_finish(self.as_mut_ptr(),
                                    res.as_mut_ptr(),
                                    &mut err)
        };
        if err.is_null() {
            Ok(unsafe { refcount::Ref::from_raw(ret) })
        } else {
            Err(unsafe { error::Error::from_raw(err) })
        }
    }
}

unsafe impl object::ObjectType for AsyncResult {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_async_result_get_type())
        }
    }
}

unsafe impl object::ObjectType for File {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_file_get_type())
        }
    }
}

unsafe impl object::ObjectType for InputStream {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_input_stream_get_type())
        }
    }
}

unsafe impl object::ObjectType for FileInputStream {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_file_input_stream_get_type())
        }
    }
}

impl object::Upcast<gobject::Object> for Cancellable {

    #[inline]
    fn upcast(&self) -> &gobject::Object {
        unsafe {
            wrap::from_raw(&self.raw.parent_instance)
        }
    }
}

impl object::Upcast<gobject::Object> for InputStream {

    #[inline]
    fn upcast(&self) -> &gobject::Object {
        unsafe {
            wrap::from_raw(&self.raw.parent_instance)
        }
    }
}

impl object::Upcast<InputStream> for FileInputStream {

    #[inline]
    fn upcast(&self) -> &InputStream {
        unsafe {
            wrap::from_raw(&self.raw.parent_instance)
        }
    }
}

impl object::Upcast<gobject::Object> for FileInputStream {

    #[inline]
    fn upcast(&self) -> &gobject::Object {
        use cast::AsInputStream;
        self.as_input_stream().upcast()
    }
}
<commit_msg>Updated to recent Rust nightly<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013, 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#![crate_name = "grust_Gio_2_0"]
#![crate_type = "lib"]

#![allow(trivial_numeric_casts)]
#![allow(unstable_features)]

#![feature(core)]

#[macro_use]
extern crate grust;

#[macro_use]
#[no_link]
extern crate bitflags;

extern crate gio_2_0_sys as ffi;
extern crate glib_2_0_sys as glib_ffi;
extern crate gobject_2_0_sys as gobject_ffi;
extern crate grust_GLib_2_0 as glib;
extern crate grust_GObject_2_0 as gobject;

use grust::enumeration;
use grust::enumeration::IntrospectedEnum as _grust_IntrospectedEnumTrait;
use grust::error;
use grust::gstr;
use grust::gtype::GType;
use grust::marker;
use grust::object;
use grust::quark;
use grust::refcount;
use grust::types::{gint, gpointer};
use grust::wrap;

use std::fmt;
use std::mem;
use std::num;
use std::ptr;
use std::result;

#[repr(C)]
pub struct AsyncResult {
    raw: ffi::GAsyncResult,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for AsyncResult {
    type Raw = ffi::GAsyncResult;
}

#[repr(C)]
pub struct File {
    raw: ffi::GFile,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for File {
    type Raw = ffi::GFile;
}

#[repr(C)]
pub struct Cancellable {
    raw: ffi::GCancellable,
    _marker: marker::ObjectMarker
}

unsafe impl Send for Cancellable { }
unsafe impl Sync for Cancellable { }
unsafe impl wrap::Wrapper for Cancellable {
    type Raw = ffi::GCancellable;
}

#[repr(C)]
pub struct InputStream {
    raw: ffi::GInputStream,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for InputStream {
    type Raw = ffi::GInputStream;
}

#[repr(C)]
pub struct FileInputStream {
    raw: ffi::GFileInputStream
}

unsafe impl wrap::Wrapper for FileInputStream {
    type Raw = ffi::GFileInputStream;
}

#[derive(Copy, Clone, PartialEq, Eq, FromPrimitive, Debug)]
#[repr(C)]
pub enum IOErrorEnum {
    Failed = 0,
    NotFound = 1,
    Exists = 2,
    // ...
}

impl enumeration::IntrospectedEnum for IOErrorEnum {

    fn from_int(v: gint) -> Result<Self, enumeration::UnknownValue> {
        num::from_i32(v as i32)
            .ok_or_else(|| enumeration::UnknownValue(v))
    }

    fn to_int(&self) -> gint {
        *self as gint
    }

    fn name(&self) -> &'static str {
        match *self {
            IOErrorEnum::Failed => "failed",
            IOErrorEnum::NotFound => "not-found",
            IOErrorEnum::Exists   => "exists",
            // ...
        }
    }
}

impl enumeration::EnumType for IOErrorEnum {
    fn get_type() -> GType {
        unsafe { GType::from_raw(ffi::g_io_error_enum_get_type()) }
    }
}

impl error::Domain for IOErrorEnum {
    fn domain() -> quark::Quark {
        g_static_quark!(b"g-io-error-quark\0")
    }
}

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

pub mod flags {

    pub mod file_attribute_info {
        use grust::flags::prelude::*;
        use ffi;
        use std::fmt;

        bitflags! {
            flags Flags: guint {
                const NONE            = 0,
                const COPY_WITH_FILE  = 1,
                const COPY_WHEN_MOVED = 2,
            }
        }

        impl IntrospectedFlags for Flags {

            fn from_uint(v: guint) -> Result<Flags, UnknownFlags> {
                Flags::from_bits(v)
                    .ok_or_else(|| UnknownFlags::new(v, Flags::all().bits()))
            }

            #[inline]
            fn to_uint(&self) -> guint {
                self.bits()
            }
        }

        impl FlagsType for Flags {
            fn get_type() -> GType {
                unsafe {
                    let raw = ffi::g_file_attribute_info_flags_get_type();
                    GType::from_raw(raw)
                }
            }
        }

        impl fmt::Debug for Flags {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                const FLAG_INFO: &'static [(Flags, &'static str)] = &[
                    (COPY_WITH_FILE,  "COPY_WITH_FILE"),
                    (COPY_WHEN_MOVED, "COPY_WHEN_MOVED")
                ];
                let mut contents = String::new();
                for &(flag, name) in FLAG_INFO.iter() {
                    if self.contains(flag) {
                        if contents.is_empty() {
                            contents.push_str(name);
                        } else {
                            contents.push('|');
                            contents.push_str(name);
                        }
                    }
                }
                write!(f, "FileAttributeInfoFlags({})", contents)
            }
        }
    }
}

pub use flags::file_attribute_info::Flags as FileAttributeInfoFlags;

mod async {
    use ffi;
    use gobject_ffi;
    use gobject;

    use grust::types::gpointer;
    use grust::wrap;
    use std::mem;

    pub extern "C" fn async_ready_callback<F>(source_object: *mut gobject_ffi::GObject,
                                              res: *mut ffi::GAsyncResult,
                                              user_data: gpointer)
        where F: FnOnce(&gobject::Object, &super::AsyncResult)
    {
        let cb: Box<F> = unsafe { mem::transmute(user_data) };
        let arg1 = unsafe { wrap::from_raw::<gobject::Object>(source_object) };
        let arg2 = unsafe { wrap::from_raw::<super::AsyncResult>(res) };
        cb(arg1, arg2);
    }
}

pub mod cast {
    use grust::object;

    use gobject;

    pub trait AsAsyncResult {
        fn as_async_result(&self) -> &super::AsyncResult;
    }

    impl<T> AsAsyncResult for T where T: object::Upcast<super::AsyncResult> {

        #[inline]
        fn as_async_result(&self) -> &super::AsyncResult {
            self.upcast()
        }
    }

    pub trait AsCancellable : gobject::cast::AsObject {
        fn as_cancellable(&self) -> &super::Cancellable;
    }

    impl<T> AsCancellable for T
        where T: object::Upcast<super::Cancellable>,
              T: object::Upcast<gobject::Object>
    {
        #[inline]
        fn as_cancellable(&self) -> &super::Cancellable {
            self.upcast()
        }
    }

    pub trait AsInputStream : gobject::cast::AsObject {
        fn as_input_stream(&self) -> &super::InputStream;
    }

    impl<T> AsInputStream for T
        where T: object::Upcast<super::InputStream>,
              T: object::Upcast<gobject::Object>
    {
        #[inline]
        fn as_input_stream(&self) -> &super::InputStream {
            self.upcast()
        }
    }

    pub trait AsFileInputStream : AsInputStream {
        fn as_file_input_stream(&self) -> &super::FileInputStream;
    }

    impl<T> AsFileInputStream for T
        where T: object::Upcast<super::FileInputStream>,
              T: object::Upcast<super::InputStream>,
              T: object::Upcast<gobject::Object>
    {
        #[inline]
        fn as_file_input_stream(&self) -> &super::FileInputStream {
            self.upcast()
        }
    }

    pub trait AsFile {
        fn as_file(&self) -> &super::File;
    }

    impl<T> AsFile for T where T: object::Upcast<super::File> {

        #[inline]
        fn as_file(&self) -> &super::File {
            self.upcast()
        }
    }
}

impl File {

    pub fn new_for_path(path: &gstr::Utf8) -> refcount::Ref<File> {
        unsafe {
            let ret = ffi::g_file_new_for_path(path.as_ptr());
            refcount::Ref::from_raw(ret)
        }
    }

    pub fn get_path(&self) -> gstr::OwnedGStr {
        unsafe {
            use grust::wrap::Wrapper;
            let ret = ffi::g_file_get_path(self.as_mut_ptr());
            gstr::OwnedGStr::from_ptr(ret)
        }
    }

    pub fn read_async<F>(&self,
                         io_priority: gint,
                         cancellable: Option<&Cancellable>,
                         callback: F)
        where F: FnOnce(&gobject::Object, &AsyncResult),
              F: 'static
    {
        unsafe {
            use grust::wrap::Wrapper;
            let self_raw = self.as_mut_ptr();
            let cancellable = {
                match cancellable {
                    Some(c) => c.as_mut_ptr(),
                    None    => std::ptr::null_mut()
                }
            };
            let callback: gpointer = mem::transmute(Box::new(callback));

            ffi::g_file_read_async(self_raw,
                                   io_priority,
                                   cancellable,
                                   async::async_ready_callback::<F>,
                                   callback);
        }
    }

    pub fn read_finish(&self, res: &AsyncResult)
                      -> result::Result<refcount::Ref<FileInputStream>,
                                        error::Error> {
        let mut err: *mut glib_ffi::GError = ptr::null_mut();
        let ret = unsafe {
            use grust::wrap::Wrapper;
            ffi::g_file_read_finish(self.as_mut_ptr(),
                                    res.as_mut_ptr(),
                                    &mut err)
        };
        if err.is_null() {
            Ok(unsafe { refcount::Ref::from_raw(ret) })
        } else {
            Err(unsafe { error::Error::from_raw(err) })
        }
    }
}

unsafe impl object::ObjectType for AsyncResult {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_async_result_get_type())
        }
    }
}

unsafe impl object::ObjectType for File {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_file_get_type())
        }
    }
}

unsafe impl object::ObjectType for InputStream {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_input_stream_get_type())
        }
    }
}

unsafe impl object::ObjectType for FileInputStream {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_file_input_stream_get_type())
        }
    }
}

impl object::Upcast<gobject::Object> for Cancellable {

    #[inline]
    fn upcast(&self) -> &gobject::Object {
        unsafe {
            wrap::from_raw(&self.raw.parent_instance)
        }
    }
}

impl object::Upcast<gobject::Object> for InputStream {

    #[inline]
    fn upcast(&self) -> &gobject::Object {
        unsafe {
            wrap::from_raw(&self.raw.parent_instance)
        }
    }
}

impl object::Upcast<InputStream> for FileInputStream {

    #[inline]
    fn upcast(&self) -> &InputStream {
        unsafe {
            wrap::from_raw(&self.raw.parent_instance)
        }
    }
}

impl object::Upcast<gobject::Object> for FileInputStream {

    #[inline]
    fn upcast(&self) -> &gobject::Object {
        use cast::AsInputStream;
        self.as_input_stream().upcast()
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

use toml;

fn search_template_in_dirs<'a>(dirs: &'a [PathBuf], path: &Path) -> Option<&'a PathBuf> {
    dirs.iter().find(|dir| dir.join(path).exists())
}

pub fn get_template_source(tpl_path: &Path) -> String {
    let dirs = template_dirs();
    let path = search_template_in_dirs(&dirs, tpl_path)
        .map(|dir| dir.join(tpl_path))
        .expect(&format!(
            "template file '{}' does not exist",
            tpl_path.to_str().unwrap()
        ));

    let mut f = match File::open(&path) {
        Err(_) => panic!("unable to open template file '{}'", &path.to_str().unwrap()),
        Ok(f) => f,
    };

    let mut s = String::new();
    f.read_to_string(&mut s).unwrap();
    if s.ends_with('\n') {
        let _ = s.pop();
    }
    s
}

pub fn find_template_from_path(path: &str, start_at: Option<&Path>) -> PathBuf {
    let dirs = template_dirs();
    if let Some(rel) = start_at {
        let root = search_template_in_dirs(&dirs, rel).expect(&format!(
            "unable to find previously available template file '{}'",
            rel.to_str().unwrap()
        ));
        let fs_rel_path = root.join(rel).with_file_name(path);
        if fs_rel_path.exists() {
            return fs_rel_path.strip_prefix(&root).unwrap().to_owned();
        }
    }

    let path = Path::new(path);
    search_template_in_dirs(&dirs, &path).expect(&format!(
        "template {:?} not found in directories {:?}",
        path.to_str().unwrap(),
        dirs
    ));
    path.to_owned()
}

pub fn template_dirs() -> Vec<PathBuf> {
    Config::from_file().dirs
}

struct Config {
    dirs: Vec<PathBuf>,
}

impl Config {
    fn from_file() -> Config {
        let root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
        let filename = root.join(CONFIG_FILE_NAME);
        RawConfig::from_file(&filename).map_or_else(
            || Config {
                dirs: vec![root.join("templates")],
            },
            |config| Config {
                dirs: config
                    .dirs
                    .unwrap_or_else(|| Vec::new())
                    .into_iter()
                    .map(|directory| root.join(directory))
                    .collect(),
            },
        )
    }
}

#[derive(Deserialize)]
struct RawConfig {
    dirs: Option<Vec<String>>,
}

impl RawConfig {
    fn from_file(filename: &PathBuf) -> Option<RawConfig> {
        if filename.exists() {
            let mut contents = String::new();
            File::open(filename)
                .unwrap()
                .read_to_string(&mut contents)
                .unwrap();
            Some(toml::from_str(&contents).unwrap())
        } else {
            None
        }
    }
}

static CONFIG_FILE_NAME: &str = "askama.toml";

#[cfg(test)]
mod tests {
    use super::Path;
    use super::{find_template_from_path, get_template_source};

    #[test]
    fn get_source() {
        assert_eq!(get_template_source(Path::new("sub/b.html")), "bar");
    }

    #[test]
    fn find_absolute() {
        let path = find_template_from_path("sub/b.html", Some(Path::new("a.html")));
        assert_eq!(path, Path::new("sub/b.html"));
    }

    #[test]
    #[should_panic]
    fn find_relative_nonexistent() {
        find_template_from_path("b.html", Some(Path::new("a.html")));
    }

    #[test]
    fn find_relative() {
        let path = find_template_from_path("c.html", Some(Path::new("sub/b.html")));
        assert_eq!(path, Path::new("sub/c.html"));
    }

    #[test]
    fn find_relative_sub() {
        let path = find_template_from_path("sub1/d.html", Some(Path::new("sub/b.html")));
        assert_eq!(path, Path::new("sub/sub1/d.html"));
    }
}
<commit_msg>Simplify code to read configuration<commit_after>use std::env;
use std::fs::{self, File};
use std::io::Read;
use std::path::{Path, PathBuf};

use toml;

fn search_template_in_dirs<'a>(dirs: &'a [PathBuf], path: &Path) -> Option<&'a PathBuf> {
    dirs.iter().find(|dir| dir.join(path).exists())
}

pub fn get_template_source(tpl_path: &Path) -> String {
    let dirs = template_dirs();
    let path = search_template_in_dirs(&dirs, tpl_path)
        .map(|dir| dir.join(tpl_path))
        .expect(&format!(
            "template file '{}' does not exist",
            tpl_path.to_str().unwrap()
        ));

    let mut f = match File::open(&path) {
        Err(_) => panic!("unable to open template file '{}'", &path.to_str().unwrap()),
        Ok(f) => f,
    };

    let mut s = String::new();
    f.read_to_string(&mut s).unwrap();
    if s.ends_with('\n') {
        let _ = s.pop();
    }
    s
}

pub fn find_template_from_path(path: &str, start_at: Option<&Path>) -> PathBuf {
    let dirs = template_dirs();
    if let Some(rel) = start_at {
        let root = search_template_in_dirs(&dirs, rel).expect(&format!(
            "unable to find previously available template file '{}'",
            rel.to_str().unwrap()
        ));
        let fs_rel_path = root.join(rel).with_file_name(path);
        if fs_rel_path.exists() {
            return fs_rel_path.strip_prefix(&root).unwrap().to_owned();
        }
    }

    let path = Path::new(path);
    search_template_in_dirs(&dirs, &path).expect(&format!(
        "template {:?} not found in directories {:?}",
        path.to_str().unwrap(),
        dirs
    ));
    path.to_owned()
}

pub fn template_dirs() -> Vec<PathBuf> {
    Config::from_file().dirs
}

struct Config {
    dirs: Vec<PathBuf>,
}

impl Config {
    fn from_file() -> Config {
        let root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
        let filename = root.join(CONFIG_FILE_NAME);

        let default = vec![root.join("templates")];
        let dirs = if filename.exists() {
            let config_str = fs::read_to_string(&filename)
                .expect(&format!("unable to read {}", filename.to_str().unwrap()));
            let raw: RawConfig = toml::from_str(&config_str)
                .expect(&format!("invalid TOML in {}", filename.to_str().unwrap()));
            raw.dirs
                .map(|dirs| dirs.into_iter().map(|dir| root.join(dir)).collect())
                .unwrap_or_else(|| default)
        } else {
            default
        };

        Config { dirs }
    }
}

#[derive(Deserialize)]
struct RawConfig {
    dirs: Option<Vec<String>>,
}

static CONFIG_FILE_NAME: &str = "askama.toml";

#[cfg(test)]
mod tests {
    use super::Path;
    use super::{find_template_from_path, get_template_source};

    #[test]
    fn get_source() {
        assert_eq!(get_template_source(Path::new("sub/b.html")), "bar");
    }

    #[test]
    fn find_absolute() {
        let path = find_template_from_path("sub/b.html", Some(Path::new("a.html")));
        assert_eq!(path, Path::new("sub/b.html"));
    }

    #[test]
    #[should_panic]
    fn find_relative_nonexistent() {
        find_template_from_path("b.html", Some(Path::new("a.html")));
    }

    #[test]
    fn find_relative() {
        let path = find_template_from_path("c.html", Some(Path::new("sub/b.html")));
        assert_eq!(path, Path::new("sub/c.html"));
    }

    #[test]
    fn find_relative_sub() {
        let path = find_template_from_path("sub1/d.html", Some(Path::new("sub/b.html")));
        assert_eq!(path, Path::new("sub/sub1/d.html"));
    }
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::io;
use std::fs::File;
use std::convert;

use serde_json;

use gerrit;
use spark;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct User {
    spark_person_id: spark::PersonId,
    email: spark::Email,
    enabled: bool,
}

impl User {
    fn new(person_id: spark::PersonId, email: spark::Email) -> User {
        User {
            spark_person_id: person_id,
            email: email,
            enabled: true,
        }
    }
}

/// Describes a state of the bot
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Bot {
    gerrit_username: Option<String>, // TODO: this should not be part of the state
    users: Vec<User>,
}

#[derive(Debug)]
pub enum BotError {
    Io(io::Error),
    Serialization(serde_json::Error),
}

impl convert::From<io::Error> for BotError {
    fn from(err: io::Error) -> BotError {
        BotError::Io(err)
    }
}

impl convert::From<serde_json::Error> for BotError {
    fn from(err: serde_json::Error) -> BotError {
        BotError::Serialization(err)
    }
}

impl Bot {
    pub fn new(gerrit_username: gerrit::Username) -> Bot {
        Bot {
            gerrit_username: Some(gerrit_username),
            users: Vec::new(),
        }
    }

    pub fn default() -> Bot {
        Bot {
            gerrit_username: None,
            users: Vec::new(),
        }
    }

    fn enable<'a>(&'a mut self, person_id: &str, email: &str, enabled: bool) -> &'a User {
        // FIXME: Replace linear search
        let pos = self.users.iter().position(
            |u| u.spark_person_id == person_id,
        );
        let user: &'a mut User = match pos {
            Some(pos) => &mut self.users[pos],
            None => {
                self.users.push(User::new(
                    String::from(person_id),
                    String::from(email),
                ));
                self.users.iter_mut().last().unwrap()
            }
        };
        user.enabled = enabled;
        user
    }

    fn get_approvals_msg(&self, event: gerrit::Event) -> Option<(&User, String)> {
        println!("[D] Incoming approvals: {:?}", event);

        let author = event.author;
        let change = event.change;
        let approvals = event.approvals;

        let approver = author.unwrap().username.clone();
        if approver == change.owner.username {
            // No need to notify about user's own approvals.
            return None;
        }

        if let Some(ref owner_email) = change.owner.email {
            // TODO: Fix linear search
            let users = &self.users;
            for user in users.iter() {
                if &user.email == owner_email {
                    if !user.enabled {
                        break;
                    }

                    if let Some(approvals) = approvals {
                        let msgs: Vec<String> = approvals
                            .iter()
                            .filter(|approval| {
                                let filtered = if let Some(ref old_value) = approval.old_value {
                                    old_value != &approval.value && approval.value != "0"
                                } else {
                                    approval.value != "0"
                                };
                                println!("Filtered approval: {:?}", !filtered);
                                filtered
                            })
                            .map(|approval| {
                                let value: i8 = approval.value.parse().unwrap_or(0);
                                format!(
                                    "{}: {}{} ({}) from {}",
                                    change.subject,
                                    if value > 0 { "+" } else { "" },
                                    value,
                                    approval.approval_type,
                                    approver
                                )
                            })
                            .collect();
                        return if !msgs.is_empty() {
                            Some((user, msgs.join("\n")))
                        } else {
                            None
                        };
                    }
                }
            }
        }
        None
    }

    pub fn save<P>(self, filename: P) -> Result<(), BotError>
    where
        P: AsRef<Path>,
    {
        let f = File::create(filename)?;
        serde_json::to_writer(f, &self)?;
        Ok(())
    }

    pub fn load<P>(filename: P) -> Result<Self, BotError>
    where
        P: AsRef<Path>,
    {
        let f = File::open(filename)?;
        let bot: Bot = serde_json::from_reader(f)?;
        Ok(bot)
    }

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

#[derive(Debug)]
pub enum Action {
    Enable(spark::PersonId, spark::Email),
    Disable(spark::PersonId, spark::Email),
    UpdateApprovals(gerrit::Event),
    Help(spark::PersonId),
    Unknown(spark::PersonId),
    NoOp,
}

#[derive(Debug)]
pub struct Response {
    // TODO: Switch to a reference, since it should be alive inside of the Bot state
    pub person_id: spark::PersonId,
    pub message: String,
}

impl Response {
    pub fn new(person_id: spark::PersonId, message: String) -> Response {
        Response {
            person_id: person_id,
            message: message,
        }
    }
}

#[derive(Debug)]
pub enum Task {
    Reply(Response),
    ReplyAndSave(Response),
}

const GREETINGS_MSG: &'static str =
    r#"Hi. I am GerritBot (**in a very early alpha**). I can watch Gerrit reviews for you, and notify you about new +1/-1's.

To enable notifications, just type in 'enable'. A small note: your email in Spark and in Gerrit has to be the same. Otherwise, I can't match your accounts.

For more information, type in **help**.

By the way, my icon is made by
[ Madebyoliver ](http://www.flaticon.com/authors/madebyoliver)
from
[ www.flaticon.com ](http://www.flaticon.com)
and is licensed by
[ CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).
"#;

const HELP_MSG: &'static str = r#"Commands:

`enable` I will start notifying you.

`disable` I will stop notifying you.

`status` I will tell if notification are enabled or disabled for you.

`help` This message
"#;

/// Action controller
/// Return new bot state and an optional message to send to the user
pub fn update(action: Action, bot: Bot) -> (Bot, Option<Task>) {
    let mut bot = bot;
    let task = match action {
        Action::Enable(person_id, email) => {
            bot.enable(&person_id, &email, true);
            let task = Task::ReplyAndSave(Response::new(
                person_id,
                String::from("Got it! Happy reviewing!"),
            ));
            Some(task)
        }
        Action::Disable(person_id, email) => {
            bot.enable(&person_id, &email, false);
            let task = Task::ReplyAndSave(Response::new(
                person_id,
                String::from("Got it! I will stay silent."),
            ));
            Some(task)
        }
        Action::UpdateApprovals(event) => {
            bot.get_approvals_msg(event).map(|(user, message)| {
                Task::Reply(Response::new(user.spark_person_id.clone(), message))
            })
        }
        Action::Help(person_id) => {
            Some(Task::Reply(
                Response::new(person_id, String::from(HELP_MSG)),
            ))
        }
        Action::Unknown(person_id) => {
            Some(Task::Reply(
                Response::new(person_id, String::from(GREETINGS_MSG)),
            ))
        }
        _ => None,
    };
    (bot, task)
}
<commit_msg>Remove status command from help<commit_after>use std::path::Path;
use std::io;
use std::fs::File;
use std::convert;

use serde_json;

use gerrit;
use spark;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct User {
    spark_person_id: spark::PersonId,
    email: spark::Email,
    enabled: bool,
}

impl User {
    fn new(person_id: spark::PersonId, email: spark::Email) -> User {
        User {
            spark_person_id: person_id,
            email: email,
            enabled: true,
        }
    }
}

/// Describes a state of the bot
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Bot {
    gerrit_username: Option<String>, // TODO: this should not be part of the state
    users: Vec<User>,
}

#[derive(Debug)]
pub enum BotError {
    Io(io::Error),
    Serialization(serde_json::Error),
}

impl convert::From<io::Error> for BotError {
    fn from(err: io::Error) -> BotError {
        BotError::Io(err)
    }
}

impl convert::From<serde_json::Error> for BotError {
    fn from(err: serde_json::Error) -> BotError {
        BotError::Serialization(err)
    }
}

impl Bot {
    pub fn new(gerrit_username: gerrit::Username) -> Bot {
        Bot {
            gerrit_username: Some(gerrit_username),
            users: Vec::new(),
        }
    }

    pub fn default() -> Bot {
        Bot {
            gerrit_username: None,
            users: Vec::new(),
        }
    }

    fn enable<'a>(&'a mut self, person_id: &str, email: &str, enabled: bool) -> &'a User {
        // FIXME: Replace linear search
        let pos = self.users.iter().position(
            |u| u.spark_person_id == person_id,
        );
        let user: &'a mut User = match pos {
            Some(pos) => &mut self.users[pos],
            None => {
                self.users.push(User::new(
                    String::from(person_id),
                    String::from(email),
                ));
                self.users.iter_mut().last().unwrap()
            }
        };
        user.enabled = enabled;
        user
    }

    fn get_approvals_msg(&self, event: gerrit::Event) -> Option<(&User, String)> {
        println!("[D] Incoming approvals: {:?}", event);

        let author = event.author;
        let change = event.change;
        let approvals = event.approvals;

        let approver = author.unwrap().username.clone();
        if approver == change.owner.username {
            // No need to notify about user's own approvals.
            return None;
        }

        if let Some(ref owner_email) = change.owner.email {
            // TODO: Fix linear search
            let users = &self.users;
            for user in users.iter() {
                if &user.email == owner_email {
                    if !user.enabled {
                        break;
                    }

                    if let Some(approvals) = approvals {
                        let msgs: Vec<String> = approvals
                            .iter()
                            .filter(|approval| {
                                let filtered = if let Some(ref old_value) = approval.old_value {
                                    old_value != &approval.value && approval.value != "0"
                                } else {
                                    approval.value != "0"
                                };
                                println!("Filtered approval: {:?}", !filtered);
                                filtered
                            })
                            .map(|approval| {
                                let value: i8 = approval.value.parse().unwrap_or(0);
                                format!(
                                    "{}: {}{} ({}) from {}",
                                    change.subject,
                                    if value > 0 { "+" } else { "" },
                                    value,
                                    approval.approval_type,
                                    approver
                                )
                            })
                            .collect();
                        return if !msgs.is_empty() {
                            Some((user, msgs.join("\n")))
                        } else {
                            None
                        };
                    }
                }
            }
        }
        None
    }

    pub fn save<P>(self, filename: P) -> Result<(), BotError>
    where
        P: AsRef<Path>,
    {
        let f = File::create(filename)?;
        serde_json::to_writer(f, &self)?;
        Ok(())
    }

    pub fn load<P>(filename: P) -> Result<Self, BotError>
    where
        P: AsRef<Path>,
    {
        let f = File::open(filename)?;
        let bot: Bot = serde_json::from_reader(f)?;
        Ok(bot)
    }

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

#[derive(Debug)]
pub enum Action {
    Enable(spark::PersonId, spark::Email),
    Disable(spark::PersonId, spark::Email),
    UpdateApprovals(gerrit::Event),
    Help(spark::PersonId),
    Unknown(spark::PersonId),
    NoOp,
}

#[derive(Debug)]
pub struct Response {
    // TODO: Switch to a reference, since it should be alive inside of the Bot state
    pub person_id: spark::PersonId,
    pub message: String,
}

impl Response {
    pub fn new(person_id: spark::PersonId, message: String) -> Response {
        Response {
            person_id: person_id,
            message: message,
        }
    }
}

#[derive(Debug)]
pub enum Task {
    Reply(Response),
    ReplyAndSave(Response),
}

const GREETINGS_MSG: &'static str =
    r#"Hi. I am GerritBot (**in a very early alpha**). I can watch Gerrit reviews for you, and notify you about new +1/-1's.

To enable notifications, just type in 'enable'. A small note: your email in Spark and in Gerrit has to be the same. Otherwise, I can't match your accounts.

For more information, type in **help**.

By the way, my icon is made by
[ Madebyoliver ](http://www.flaticon.com/authors/madebyoliver)
from
[ www.flaticon.com ](http://www.flaticon.com)
and is licensed by
[ CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).
"#;

const HELP_MSG: &'static str = r#"Commands:

`enable` I will start notifying you.

`disable` I will stop notifying you.

`help` This message
"#;

/// Action controller
/// Return new bot state and an optional message to send to the user
pub fn update(action: Action, bot: Bot) -> (Bot, Option<Task>) {
    let mut bot = bot;
    let task = match action {
        Action::Enable(person_id, email) => {
            bot.enable(&person_id, &email, true);
            let task = Task::ReplyAndSave(Response::new(
                person_id,
                String::from("Got it! Happy reviewing!"),
            ));
            Some(task)
        }
        Action::Disable(person_id, email) => {
            bot.enable(&person_id, &email, false);
            let task = Task::ReplyAndSave(Response::new(
                person_id,
                String::from("Got it! I will stay silent."),
            ));
            Some(task)
        }
        Action::UpdateApprovals(event) => {
            bot.get_approvals_msg(event).map(|(user, message)| {
                Task::Reply(Response::new(user.spark_person_id.clone(), message))
            })
        }
        Action::Help(person_id) => {
            Some(Task::Reply(
                Response::new(person_id, String::from(HELP_MSG)),
            ))
        }
        Action::Unknown(person_id) => {
            Some(Task::Reply(
                Response::new(person_id, String::from(GREETINGS_MSG)),
            ))
        }
        _ => None,
    };
    (bot, task)
}
<|endoftext|>


<commit_before>use std::string::String;
use std::io;
use std::io::prelude::*;

use regex::Regex;

use platform::EOL_LEN;
use commands::*;
use REHolder;

static CLI_PROMPT: &'static str = "#> ";

fn cli_request(command: &mut String) {
    print!("\n{welcome}", welcome = CLI_PROMPT);
    io::stdout().flush().unwrap();
    io::stdin().read_line(command).expect("Failed to read command!");
    let len = command.len();
    command.truncate(len - EOL_LEN as usize);
}

fn parse_and_execute(command: &String, mut current_re: &mut REHolder) -> String {

    let space_pos = match command.find(' ') {
        None => command.len(),
        Some(pos) => pos
    };

    let (com, arg) = command.split_at(space_pos);
    let arg = arg.trim();

    match com.as_ref() {
        "help" => show_help(),
        "re" => set_regex(&arg, &mut current_re),
        _ => default_command()
    }
}

pub fn cli_parse_command(mut current_re: &mut REHolder) -> bool {
    let mut command = String::new();
    cli_request(&mut command);

    if command == "exit" {
        return false;
    }

    if command.len() > 0 {
        let result = parse_and_execute(&command, &mut current_re);
        println!("{}", result);
    }

    true
}

<commit_msg>remove use<commit_after>use std::string::String;
use std::io;
use std::io::prelude::*;

use platform::EOL_LEN;
use commands::*;
use REHolder;

static CLI_PROMPT: &'static str = "#> ";

fn cli_request(command: &mut String) {
    print!("\n{welcome}", welcome = CLI_PROMPT);
    io::stdout().flush().unwrap();
    io::stdin().read_line(command).expect("Failed to read command!");
    let len = command.len();
    command.truncate(len - EOL_LEN as usize);
}

fn parse_and_execute(command: &String, mut current_re: &mut REHolder) -> String {

    let space_pos = match command.find(' ') {
        None => command.len(),
        Some(pos) => pos
    };

    let (com, arg) = command.split_at(space_pos);
    let arg = arg.trim();

    match com.as_ref() {
        "help" => show_help(),
        "re" => set_regex(&arg, &mut current_re),
        _ => default_command()
    }
}

pub fn cli_parse_command(mut current_re: &mut REHolder) -> bool {
    let mut command = String::new();
    cli_request(&mut command);

    if command == "exit" {
        return false;
    }

    if command.len() > 0 {
        let result = parse_and_execute(&command, &mut current_re);
        println!("{}", result);
    }

    true
}

<|endoftext|>


<commit_before>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
// Copyright 2017 Google LLC.
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! tlsa records for storing TLS authentication records

use error::*;
use rr::rdata::TLSA;
use rr::rdata::tlsa::CertUsage;

const HEX: ::data_encoding::Encoding = new_encoding!{
    symbols: "0123456789abcdef",
    ignore: " \t\r\n",
    translate_from: "ABCDEF",
    translate_to: "abcdef",
};

fn to_u8(data: &str) -> ParseResult<u8> {
    u8::from_str_radix(data, 10).map_err(ParseError::from)
}

/// Parse the RData from a set of Tokens
///
/// [RFC 6698, DNS-Based Authentication for TLS](https://tools.ietf.org/html/rfc6698#section-2.2)
///
/// ```text
/// 2.2.  TLSA RR Presentation Format
///
///    The presentation format of the RDATA portion (as defined in
///    [RFC1035]) is as follows:
///
///    o  The certificate usage field MUST be represented as an 8-bit
///       unsigned integer.
///
///    o  The selector field MUST be represented as an 8-bit unsigned
///       integer.
///
///    o  The matching type field MUST be represented as an 8-bit unsigned
///       integer.
///
///    o  The certificate association data field MUST be represented as a
///       string of hexadecimal characters.  Whitespace is allowed within
///       the string of hexadecimal characters, as described in [RFC1035].
/// ```
pub fn parse<'i, I: Iterator<Item = &'i str>>(tokens: I) -> ParseResult<TLSA> {
    let mut iter = tokens;

    let token: &str = iter.next().ok_or_else(|| {
        ParseError::from(ParseErrorKind::Message("TLSA usage field missing"))
    })?;
    let usage = CertUsage::from(to_u8(token)?);

    let token = iter.next().ok_or_else(|| {
        ParseErrorKind::Message("TLSA selector field missing")
    })?;
    let selector = to_u8(token)?.into();

    let token = iter.next().ok_or_else(|| {
        ParseErrorKind::Message("TLSA matching field missing")
    })?;
    let matching = to_u8(token)?.into();

    // these are all in hex: "a string of hexadecimal characters"
    //   aside: personally I find it funny that the other fields are decimal, while this is hex encoded...
    let cert_data = iter.fold(String::new(), |mut cert_data, data| {
        cert_data.extend(data.chars());
        cert_data
    }).to_uppercase();
    println!("cert_data: {}", cert_data);
    let cert_data = HEX.decode(cert_data.as_bytes())?;

    if !cert_data.is_empty() {
        Ok(TLSA::new(usage, selector, matching, cert_data))
    } else {
        Err(ParseErrorKind::Message("TLSA data field missing").into())
    }
}

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

    #[test]
    fn test_parsing() {
        assert!(parse(vec![
            "0", "0", "1", "d2abde240d7cd3ee6b4b28c54df034b9",
            "7983a1d16e8a410e4561cb106618e971"].into_iter()).is_ok());
        assert!(parse(vec![
            "1", "1", "2", "92003ba34942dc74152e2f2c408d29ec",
            "a5a520e7f2e06bb944f4dca346baf63c",
            "1b177615d466f6c4b71c216a50292bd5",
            "8c9ebdd2f74e38fe51ffd48c43326cbc"].into_iter()).is_ok());
    }
}
<commit_msg>Remove unnecessary to_uppercase<commit_after>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
// Copyright 2017 Google LLC.
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! tlsa records for storing TLS authentication records

use error::*;
use rr::rdata::TLSA;
use rr::rdata::tlsa::CertUsage;

const HEX: ::data_encoding::Encoding = new_encoding!{
    symbols: "0123456789abcdef",
    ignore: " \t\r\n",
    translate_from: "ABCDEF",
    translate_to: "abcdef",
};

fn to_u8(data: &str) -> ParseResult<u8> {
    u8::from_str_radix(data, 10).map_err(ParseError::from)
}

/// Parse the RData from a set of Tokens
///
/// [RFC 6698, DNS-Based Authentication for TLS](https://tools.ietf.org/html/rfc6698#section-2.2)
///
/// ```text
/// 2.2.  TLSA RR Presentation Format
///
///    The presentation format of the RDATA portion (as defined in
///    [RFC1035]) is as follows:
///
///    o  The certificate usage field MUST be represented as an 8-bit
///       unsigned integer.
///
///    o  The selector field MUST be represented as an 8-bit unsigned
///       integer.
///
///    o  The matching type field MUST be represented as an 8-bit unsigned
///       integer.
///
///    o  The certificate association data field MUST be represented as a
///       string of hexadecimal characters.  Whitespace is allowed within
///       the string of hexadecimal characters, as described in [RFC1035].
/// ```
pub fn parse<'i, I: Iterator<Item = &'i str>>(tokens: I) -> ParseResult<TLSA> {
    let mut iter = tokens;

    let token: &str = iter.next().ok_or_else(|| {
        ParseError::from(ParseErrorKind::Message("TLSA usage field missing"))
    })?;
    let usage = CertUsage::from(to_u8(token)?);

    let token = iter.next().ok_or_else(|| {
        ParseErrorKind::Message("TLSA selector field missing")
    })?;
    let selector = to_u8(token)?.into();

    let token = iter.next().ok_or_else(|| {
        ParseErrorKind::Message("TLSA matching field missing")
    })?;
    let matching = to_u8(token)?.into();

    // these are all in hex: "a string of hexadecimal characters"
    //   aside: personally I find it funny that the other fields are decimal, while this is hex encoded...
    let cert_data = iter.fold(String::new(), |mut cert_data, data| {
        cert_data.extend(data.chars());
        cert_data
    });
    println!("cert_data: {}", cert_data);
    let cert_data = HEX.decode(cert_data.as_bytes())?;

    if !cert_data.is_empty() {
        Ok(TLSA::new(usage, selector, matching, cert_data))
    } else {
        Err(ParseErrorKind::Message("TLSA data field missing").into())
    }
}

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

    #[test]
    fn test_parsing() {
        assert!(parse(vec![
            "0", "0", "1", "d2abde240d7cd3ee6b4b28c54df034b9",
            "7983a1d16e8a410e4561cb106618e971"].into_iter()).is_ok());
        assert!(parse(vec![
            "1", "1", "2", "92003ba34942dc74152e2f2c408d29ec",
            "a5a520e7f2e06bb944f4dca346baf63c",
            "1b177615d466f6c4b71c216a50292bd5",
            "8c9ebdd2f74e38fe51ffd48c43326cbc"].into_iter()).is_ok());
    }
}
<|endoftext|>


<commit_before>pub mod function;
pub mod backend;

pub use backend::*;
pub use self::backend::*;
pub use self::function::*;<commit_msg>Removed old files<commit_after><|endoftext|>


<commit_before>pub struct Core {
	pub pc: u32,
	pub mem: [u8; 1024],
}

impl Core {
	pub fn new(base: u32) -> Core {
		Core { pc: base, mem: [0u8; 1024] }
	}
	pub fn new_mem(base: u32, contents: &[u8]) -> Core {
		let mut m = [0u8; 1024];
		let mut b = base as usize;
		for byte in contents {
			m[b] = *byte;
			b+=1;
		}
		Core { pc: base, mem: m }
	}
	pub fn read_imm_32(&mut self) -> u32 {
		let b = self.pc as usize;
		self.pc += 4;
		return ((self.mem[b+0] as u32) << 24
			|   (self.mem[b+1] as u32) << 16
			|   (self.mem[b+2] as u32) <<  8
			|   (self.mem[b+3] as u32) <<  0
			) as u32;
	}
	pub fn jump(&mut self, pc: u32) {
    	self.pc = pc;
	}
}

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

	#[test]
	fn new_sets_pc() {
		let cpu = Core::new(256);
	    assert_eq!(256, cpu.pc);
	}

	#[test]
	fn new_mem_sets_pc_and_mem() {
		let base = 128;
		let cpu = Core::new_mem(base, &[1u8, 2u8, 3u8, 4u8, 5u8, 6u8]);
	    assert_eq!(128, cpu.pc);
	    assert_eq!(1, cpu.mem[128]);
	    assert_eq!(2, cpu.mem[129]);
	}

	#[test]
	fn a_jump_changes_pc() {
		let mut cpu = Core::new(0);
		cpu.jump(128);
	    assert_eq!(128, cpu.pc);
	}

	#[test]
	fn an_imm_read32_changes_pc() {
		let base = 128;
		let mut cpu = Core::new(base);
		cpu.read_imm_32();
	    assert_eq!(base+4, cpu.pc);
	}

	#[test]
	fn an_imm_read32_reads_from_pc() {
		let base = 128;
		let mut cpu = Core::new_mem(base, &[2u8, 1u8, 3u8, 4u8]);
		let val = cpu.read_imm_32();
	    assert_eq!((2<<24)+(1<<16)+(3<<8)+4, val);
	}
}<commit_msg>Add stackpointer, and reset method<commit_after>pub struct Core {
	pub pc: u32,
	pub sp: u32,
	pub mem: [u8; 1024],
}

impl Core {
	pub fn new(base: u32) -> Core {
		Core { pc: base, sp: 0, mem: [0u8; 1024] }
	}
	pub fn new_mem(base: u32, contents: &[u8]) -> Core {
		let mut m = [0u8; 1024];
		let mut b = base as usize;
		for byte in contents {
			m[b] = *byte;
			b+=1;
		}
		Core { pc: base, sp: 0, mem: m }
	}
	pub fn reset(&mut self) {
		self.jump(0);
		self.sp = self.read_imm_32();
		let new_pc = self.read_imm_32();
		self.jump(new_pc);
	}
	pub fn read_imm_32(&mut self) -> u32 {
		let b = self.pc as usize;
		self.pc += 4;
		return ((self.mem[b+0] as u32) << 24
			|   (self.mem[b+1] as u32) << 16
			|   (self.mem[b+2] as u32) <<  8
			|   (self.mem[b+3] as u32) <<  0
			) as u32;
	}
	pub fn jump(&mut self, pc: u32) {
    	self.pc = pc;
	}
}

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

	#[test]
	fn new_sets_pc() {
		let cpu = Core::new(256);
	    assert_eq!(256, cpu.pc);
	}

	#[test]
	fn new_mem_sets_pc_and_mem() {
		let base = 128;
		let cpu = Core::new_mem(base, &[1u8, 2u8, 3u8, 4u8, 5u8, 6u8]);
	    assert_eq!(128, cpu.pc);
	    assert_eq!(1, cpu.mem[128]);
	    assert_eq!(2, cpu.mem[129]);
	}

	#[test]
	fn a_jump_changes_pc() {
		let mut cpu = Core::new(0);
		cpu.jump(128);
	    assert_eq!(128, cpu.pc);
	}

	#[test]
	fn an_imm_read32_changes_pc() {
		let base = 128;
		let mut cpu = Core::new(base);
		cpu.read_imm_32();
	    assert_eq!(base+4, cpu.pc);
	}

	#[test]
	fn an_imm_read32_reads_from_pc() {
		let base = 128;
		let mut cpu = Core::new_mem(base, &[2u8, 1u8, 3u8, 4u8]);
		let val = cpu.read_imm_32();
	    assert_eq!((2<<24)+(1<<16)+(3<<8)+4, val);
	}

	#[test]
	fn a_reset_reads_sp_and_pc_from_0() {
		let mut cpu = Core::new_mem(0, &[0u8,0u8,1u8,0u8, 0u8,0u8,0u8,128u8]);
		cpu.reset();
	    assert_eq!(256, cpu.sp);
	    assert_eq!(128, cpu.pc);
	}
}<|endoftext|>


<commit_before>use super::memory;

#[derive(Debug)]
pub struct Cpu {
    af: u16,
    bc: u16,
    de: u16,
    hl: u16,
    af_: u16,
    bc_: u16,
    de_: u16,
    hl_: u16,
    ir: u16,
    ix: u16,
    iy: u16,
    sp: u16,
    pc: u16,

    iff1: bool,
    iff2: bool,

    memory: memory::Memory
}

impl Cpu {
    pub fn new(memory: memory::Memory) -> Cpu {
        Cpu {
            af: 0,
            bc: 0,
            de: 0,
            hl: 0,
            af_: 0,
            bc_: 0,
            de_: 0,
            hl_: 0,
            ir: 0,
            ix: 0,
            iy: 0,
            sp: 0,
            pc: 0,

            iff1: false,
            iff2: false,

            memory: memory
        }
    }

    pub fn run(&mut self) {
        loop {
            let instruction = self.read_word(self.pc);
            panic!("Opcode: {:#x}", instruction);
        }
    }

    fn read_word(&self, addr: u16) -> u8 {
        self.memory.read_word(addr)
    }
}

<commit_msg>Implement DI instruction<commit_after>use super::memory;

#[derive(Debug)]
pub struct Cpu {
    af: u16,
    bc: u16,
    de: u16,
    hl: u16,
    af_: u16,
    bc_: u16,
    de_: u16,
    hl_: u16,
    ir: u16,
    ix: u16,
    iy: u16,
    sp: u16,
    pc: u16,

    iff1: bool,
    iff2: bool,

    memory: memory::Memory
}

impl Cpu {
    pub fn new(memory: memory::Memory) -> Cpu {
        Cpu {
            af: 0,
            bc: 0,
            de: 0,
            hl: 0,
            af_: 0,
            bc_: 0,
            de_: 0,
            hl_: 0,
            ir: 0,
            ix: 0,
            iy: 0,
            sp: 0,
            pc: 0,

            iff1: false,
            iff2: false,

            memory: memory
        }
    }

    pub fn run(&mut self) {
        loop {
            self.run_instruction();
        }
    }

    fn run_instruction(&mut self) {
        let instruction = self.read_word(self.pc);

        match instruction {
            0b11110011 => {
                println!("{:#x}: DI", self.pc);
                self.iff1 = false;
                self.iff1 = false;
                self.pc += 1;
            },
            _ => {
                panic!("Unrecognized instruction: {:#x}", instruction);
            }
        }

    }

    fn read_word(&self, addr: u16) -> u8 {
        self.memory.read_word(addr)
    }
}

<|endoftext|>


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

//! Basic status view definition

use chrono::prelude::Utc;
use cursive::direction::Orientation;
use cursive::traits::Identifiable;
use cursive::view::View;
use cursive::views::{BoxView, LinearLayout, TextView};
use cursive::Cursive;

use crate::tui::constants::VIEW_BASIC_STATUS;
use crate::tui::types::TUIStatusListener;

use crate::servers::common::types::SyncStatus;
use crate::servers::ServerStats;

const NANO_TO_MILLIS: f64 = 1.0 / 1_000_000.0;

pub struct TUIStatusView;

impl TUIStatusListener for TUIStatusView {
	/// Create basic status view
	fn create() -> Box<dyn View> {
		let basic_status_view = BoxView::with_full_screen(
			LinearLayout::new(Orientation::Vertical)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Current Status: "))
						.child(TextView::new("Starting").with_id("basic_current_status")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Connected Peers: "))
						.child(TextView::new("0").with_id("connected_peers")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("------------------------")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Header Tip Hash: "))
						.child(TextView::new("  ").with_id("basic_header_tip_hash")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Header Chain Height: "))
						.child(TextView::new("  ").with_id("basic_header_chain_height")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Header Cumulative Difficulty: "))
						.child(TextView::new("  ").with_id("basic_header_total_difficulty")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("------------------------")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Tip Hash: "))
						.child(TextView::new("  ").with_id("tip_hash")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Chain Height: "))
						.child(TextView::new("  ").with_id("chain_height")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Cumulative Difficulty: "))
						.child(TextView::new("  ").with_id("basic_total_difficulty")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("------------------------")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("  ").with_id("basic_mining_config_status")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("  ").with_id("basic_mining_status")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("  ").with_id("basic_network_info")),
				), //.child(logo_view)
		);
		Box::new(basic_status_view.with_id(VIEW_BASIC_STATUS))
	}

	/// update
	fn update(c: &mut Cursive, stats: &ServerStats) {
		//find and update here as needed
		let basic_status = {
			match stats.sync_status {
				SyncStatus::Initial => "Initializing".to_string(),
				SyncStatus::NoSync => "Running".to_string(),
				SyncStatus::AwaitingPeers(_) => "Waiting for peers".to_string(),
				SyncStatus::HeaderSync {
					current_height,
					highest_height,
				} => {
					let percent = if highest_height == 0 {
						0
					} else {
						current_height * 100 / highest_height
					};
					format!("Downloading headers: {}%, step 1/4", percent)
				}
				SyncStatus::TxHashsetDownload {
					start_time,
					downloaded_size,
					total_size,
				} => {
					if total_size > 0 {
						let percent = if total_size > 0 {
							downloaded_size * 100 / total_size
						} else {
							0
						};
						let start = start_time.timestamp_nanos();
						let fin = Utc::now().timestamp_nanos();
						let dur_ms = (fin - start) as f64 * NANO_TO_MILLIS;

						format!("Downloading {}(MB) chain state for state sync: {}% at {:.1?}(kB/s), step 2/4",
						total_size / 1_000_000,
						percent,
						if dur_ms > 1.0f64 { downloaded_size as f64 / dur_ms as f64 } else { 0f64 },
						)
					} else {
						let start = start_time.timestamp_millis();
						let fin = Utc::now().timestamp_millis();
						let dur_secs = (fin - start) / 1000;

						format!("Downloading chain state for state sync. Waiting remote peer to start: {}s, step 2/4",
										dur_secs,
										)
					}
				}
				SyncStatus::TxHashsetSetup => {
					"Preparing chain state for validation, step 3/4".to_string()
				}
				SyncStatus::TxHashsetValidation {
					kernels,
					kernel_total,
					rproofs,
					rproof_total,
				} => {
					// 10% of overall progress is attributed to kernel validation
					// 90% to range proofs (which are much longer)
					let mut percent = if kernel_total > 0 {
						kernels * 10 / kernel_total
					} else {
						0
					};
					percent += if rproof_total > 0 {
						rproofs * 90 / rproof_total
					} else {
						0
					};
					format!("Validating chain state: {}%, step 3/4", percent)
				}
				SyncStatus::TxHashsetSave => {
					"Finalizing chain state for state sync, step 3/4".to_string()
				}
				SyncStatus::TxHashsetDone => {
					"Finalized chain state for state sync, step 3/4".to_string()
				}
				SyncStatus::BodySync {
					current_height,
					highest_height,
				} => {
					let percent = if highest_height == 0 {
						0
					} else {
						current_height * 100 / highest_height
					};
					format!("Downloading blocks: {}%, step 4/4", percent)
				}
			}
		};
		/*let basic_mining_config_status = {
			if stats.mining_stats.is_enabled {
				"Configured as mining node"
			} else {
				"Configured as validating node only (not mining)"
			}
		};
		let (basic_mining_status, basic_network_info) = {
			if stats.mining_stats.is_enabled {
				if stats.is_syncing {
					(
						"Mining Status: Paused while syncing".to_string(),
						" ".to_string(),
					)
				} else if stats.mining_stats.combined_gps == 0.0 {
					(
						"Mining Status: Starting miner and awaiting first solution...".to_string(),
						" ".to_string(),
					)
				} else {
					(
						format!(
							"Mining Status: Mining at height {} at {:.*} GPS",
							stats.mining_stats.block_height, 4, stats.mining_stats.combined_gps
						),
						format!(
							"Cuckoo {} - Network Difficulty {}",
							stats.mining_stats.edge_bits,
							stats.mining_stats.network_difficulty.to_string()
						),
					)
				}
			} else {
				(" ".to_string(), " ".to_string())
			}
		};*/
		c.call_on_id("basic_current_status", |t: &mut TextView| {
			t.set_content(basic_status);
		});
		c.call_on_id("connected_peers", |t: &mut TextView| {
			t.set_content(stats.peer_count.to_string());
		});
		c.call_on_id("tip_hash", |t: &mut TextView| {
			t.set_content(stats.head.last_block_h.to_string());
		});
		c.call_on_id("chain_height", |t: &mut TextView| {
			t.set_content(stats.head.height.to_string());
		});
		c.call_on_id("basic_total_difficulty", |t: &mut TextView| {
			t.set_content(stats.head.total_difficulty.to_string());
		});
		c.call_on_id("basic_header_tip_hash", |t: &mut TextView| {
			t.set_content(stats.header_head.last_block_h.to_string());
		});
		c.call_on_id("basic_header_chain_height", |t: &mut TextView| {
			t.set_content(stats.header_head.height.to_string());
		});
		c.call_on_id("basic_header_total_difficulty", |t: &mut TextView| {
			t.set_content(stats.header_head.total_difficulty.to_string());
		});
		/*c.call_on_id("basic_mining_config_status", |t: &mut TextView| {
			t.set_content(basic_mining_config_status);
		});
		c.call_on_id("basic_mining_status", |t: &mut TextView| {
			t.set_content(basic_mining_status);
		});
		c.call_on_id("basic_network_info", |t: &mut TextView| {
			t.set_content(basic_network_info);
		});*/
	}
}
<commit_msg>TUI basis status text align (#2150)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Basic status view definition

use chrono::prelude::Utc;
use cursive::direction::Orientation;
use cursive::traits::Identifiable;
use cursive::view::View;
use cursive::views::{BoxView, LinearLayout, TextView};
use cursive::Cursive;

use crate::tui::constants::VIEW_BASIC_STATUS;
use crate::tui::types::TUIStatusListener;

use crate::servers::common::types::SyncStatus;
use crate::servers::ServerStats;

const NANO_TO_MILLIS: f64 = 1.0 / 1_000_000.0;

pub struct TUIStatusView;

impl TUIStatusListener for TUIStatusView {
	/// Create basic status view
	fn create() -> Box<dyn View> {
		let basic_status_view = BoxView::with_full_screen(
			LinearLayout::new(Orientation::Vertical)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Current Status:               "))
						.child(TextView::new("Starting").with_id("basic_current_status")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Connected Peers:              "))
						.child(TextView::new("0").with_id("connected_peers")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal).child(TextView::new(
						"------------------------------------------------",
					)),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Header Tip Hash:              "))
						.child(TextView::new("  ").with_id("basic_header_tip_hash")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Header Chain Height:          "))
						.child(TextView::new("  ").with_id("basic_header_chain_height")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Header Cumulative Difficulty: "))
						.child(TextView::new("  ").with_id("basic_header_total_difficulty")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal).child(TextView::new(
						"------------------------------------------------",
					)),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Chain Tip Hash:               "))
						.child(TextView::new("  ").with_id("tip_hash")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Chain Height:                 "))
						.child(TextView::new("  ").with_id("chain_height")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("Chain Cumulative Difficulty:  "))
						.child(TextView::new("  ").with_id("basic_total_difficulty")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal).child(TextView::new(
						"------------------------------------------------",
					)),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("  ").with_id("basic_mining_config_status")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("  ").with_id("basic_mining_status")),
				)
				.child(
					LinearLayout::new(Orientation::Horizontal)
						.child(TextView::new("  ").with_id("basic_network_info")),
				), //.child(logo_view)
		);
		Box::new(basic_status_view.with_id(VIEW_BASIC_STATUS))
	}

	/// update
	fn update(c: &mut Cursive, stats: &ServerStats) {
		//find and update here as needed
		let basic_status = {
			match stats.sync_status {
				SyncStatus::Initial => "Initializing".to_string(),
				SyncStatus::NoSync => "Running".to_string(),
				SyncStatus::AwaitingPeers(_) => "Waiting for peers".to_string(),
				SyncStatus::HeaderSync {
					current_height,
					highest_height,
				} => {
					let percent = if highest_height == 0 {
						0
					} else {
						current_height * 100 / highest_height
					};
					format!("Downloading headers: {}%, step 1/4", percent)
				}
				SyncStatus::TxHashsetDownload {
					start_time,
					downloaded_size,
					total_size,
				} => {
					if total_size > 0 {
						let percent = if total_size > 0 {
							downloaded_size * 100 / total_size
						} else {
							0
						};
						let start = start_time.timestamp_nanos();
						let fin = Utc::now().timestamp_nanos();
						let dur_ms = (fin - start) as f64 * NANO_TO_MILLIS;

						format!("Downloading {}(MB) chain state for state sync: {}% at {:.1?}(kB/s), step 2/4",
						total_size / 1_000_000,
						percent,
						if dur_ms > 1.0f64 { downloaded_size as f64 / dur_ms as f64 } else { 0f64 },
						)
					} else {
						let start = start_time.timestamp_millis();
						let fin = Utc::now().timestamp_millis();
						let dur_secs = (fin - start) / 1000;

						format!("Downloading chain state for state sync. Waiting remote peer to start: {}s, step 2/4",
										dur_secs,
										)
					}
				}
				SyncStatus::TxHashsetSetup => {
					"Preparing chain state for validation, step 3/4".to_string()
				}
				SyncStatus::TxHashsetValidation {
					kernels,
					kernel_total,
					rproofs,
					rproof_total,
				} => {
					// 10% of overall progress is attributed to kernel validation
					// 90% to range proofs (which are much longer)
					let mut percent = if kernel_total > 0 {
						kernels * 10 / kernel_total
					} else {
						0
					};
					percent += if rproof_total > 0 {
						rproofs * 90 / rproof_total
					} else {
						0
					};
					format!("Validating chain state: {}%, step 3/4", percent)
				}
				SyncStatus::TxHashsetSave => {
					"Finalizing chain state for state sync, step 3/4".to_string()
				}
				SyncStatus::TxHashsetDone => {
					"Finalized chain state for state sync, step 3/4".to_string()
				}
				SyncStatus::BodySync {
					current_height,
					highest_height,
				} => {
					let percent = if highest_height == 0 {
						0
					} else {
						current_height * 100 / highest_height
					};
					format!("Downloading blocks: {}%, step 4/4", percent)
				}
			}
		};
		/*let basic_mining_config_status = {
			if stats.mining_stats.is_enabled {
				"Configured as mining node"
			} else {
				"Configured as validating node only (not mining)"
			}
		};
		let (basic_mining_status, basic_network_info) = {
			if stats.mining_stats.is_enabled {
				if stats.is_syncing {
					(
						"Mining Status: Paused while syncing".to_string(),
						" ".to_string(),
					)
				} else if stats.mining_stats.combined_gps == 0.0 {
					(
						"Mining Status: Starting miner and awaiting first solution...".to_string(),
						" ".to_string(),
					)
				} else {
					(
						format!(
							"Mining Status: Mining at height {} at {:.*} GPS",
							stats.mining_stats.block_height, 4, stats.mining_stats.combined_gps
						),
						format!(
							"Cuckoo {} - Network Difficulty {}",
							stats.mining_stats.edge_bits,
							stats.mining_stats.network_difficulty.to_string()
						),
					)
				}
			} else {
				(" ".to_string(), " ".to_string())
			}
		};*/
		c.call_on_id("basic_current_status", |t: &mut TextView| {
			t.set_content(basic_status);
		});
		c.call_on_id("connected_peers", |t: &mut TextView| {
			t.set_content(stats.peer_count.to_string());
		});
		c.call_on_id("tip_hash", |t: &mut TextView| {
			t.set_content(stats.head.last_block_h.to_string());
		});
		c.call_on_id("chain_height", |t: &mut TextView| {
			t.set_content(stats.head.height.to_string());
		});
		c.call_on_id("basic_total_difficulty", |t: &mut TextView| {
			t.set_content(stats.head.total_difficulty.to_string());
		});
		c.call_on_id("basic_header_tip_hash", |t: &mut TextView| {
			t.set_content(stats.header_head.last_block_h.to_string());
		});
		c.call_on_id("basic_header_chain_height", |t: &mut TextView| {
			t.set_content(stats.header_head.height.to_string());
		});
		c.call_on_id("basic_header_total_difficulty", |t: &mut TextView| {
			t.set_content(stats.header_head.total_difficulty.to_string());
		});
		/*c.call_on_id("basic_mining_config_status", |t: &mut TextView| {
			t.set_content(basic_mining_config_status);
		});
		c.call_on_id("basic_mining_status", |t: &mut TextView| {
			t.set_content(basic_mining_status);
		});
		c.call_on_id("basic_network_info", |t: &mut TextView| {
			t.set_content(basic_network_info);
		});*/
	}
}
<|endoftext|>


<commit_before>extern crate turtle;

use turtle::{Turtle, Color, random};

fn main() {
    let mut turtle = Turtle::new();

    turtle.set_speed(10);
    turtle.set_pen_size(2.0);
    for i in 0..300 {
        turtle.set_background_color(random::<Color>().opaque());

        turtle.set_pen_color(random::<Color>().opaque());
        turtle.forward(5.0 + i as f64);

        turtle.right(30.0);
    }
}
<commit_msg>Improving the random colors example<commit_after>extern crate turtle;

use turtle::{Turtle, Color, random};

fn main() {
    let mut turtle = Turtle::new();

    turtle.set_speed(10);
    turtle.set_pen_size(2.0);
    for i in 0..300 {
        turtle.set_background_color(random::<Color>().opaque());

        turtle.set_pen_color(random::<Color>().opaque());
        turtle.forward(i as f64);

        turtle.right(60.0);
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::error::Error;

use byteorder::{ByteOrder, LittleEndian};
use serde_json::value::{Value, Number};

use super::Result as EncodingResult;
use super::Error as EncodingError;
use encoding::{CheckedOffset, Field, Offset};
use encoding::serialize::WriteBufferWrapper;
use encoding::serialize::json::ExonumJson;

/// Wrapper for the `f32` type that restricts non-finite (NaN and Infinity) values.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct F32 {
    value: f32,
}

impl F32 {
    /// Creates a new `F32` instance with the given `value`.
    ///
    /// # Panics
    ///
    /// Panics if `is_finite()` returns `false` for the given `value`.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::encoding::F32;
    ///
    /// let val = F32::new(1.0);
    /// assert_eq!(val.get(), 1.0);
    /// ```
    pub fn new(value: f32) -> Self {
        Self::try_from(value).expect("Unexpected non-finite value")
    }

    /// Creates a new `F32` instance with the given `value`. Returns `None` if the given value
    /// isn't finite.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::encoding::F32;
    ///
    /// let val = F32::try_from(1.0);
    /// assert!(val.is_some());
    ///
    /// let val = F32::try_from(f32::NaN);
    /// assert!(val.is_none());
    /// ```
    pub fn try_from(value: f32) -> Option<Self> {
        if value.is_finite() {
            Some(Self { value })
        } else {
            None
        }
    }

    /// Returns value contained in this wrapper.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::encoding::F32;
    ///
    /// let wrapper = F32::new(1.0);
    /// let value = wrapper.get();
    /// ```
    pub fn get(&self) -> f32 {
        self.value
    }
}

/// Wrapper for the `f64` type that restricts non-numeric (NaN and Infinity) values.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct F64 {
    value: f64,
}

impl F64 {
    /// Creates a new `F64` instance with the given `value`.
    ///
    /// # Panics
    ///
    /// Panics if `is_finite()` returns `false` for the given `value`.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::encoding::F64;
    ///
    /// let val = F64::new(1.0);
    /// assert_eq!(val.get(), 1.0);
    /// ```
    pub fn new(value: f64) -> Self {
        Self::try_from(value).expect("Unexpected non-finite value")
    }

    /// Creates a new `F64` instance with the given `value`. Returns `None` if the given value
    /// isn't finite.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::encoding::F64;
    ///
    /// let val = F64::try_from(1.0);
    /// assert!(val.is_some());
    ///
    /// let val = F64::try_from(f64::NaN);
    /// assert!(val.is_none());
    /// ```
    pub fn try_from(value: f64) -> Option<Self> {
        if value.is_finite() {
            Some(Self { value })
        } else {
            None
        }
    }

    /// Returns value contained in this wrapper.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::encoding::F64;
    ///
    /// let wrapper = F64::new(1.0);
    /// let value = wrapper.get();
    /// ```
    pub fn get(&self) -> f64 {
        self.value
    }
}

impl<'a> Field<'a> for F32 {
    fn field_size() -> Offset {
        mem::size_of::<Self>() as Offset
    }

    unsafe fn read(buffer: &'a [u8], from: Offset, to: Offset) -> Self {
        Self::new(LittleEndian::read_f32(&buffer[from as usize..to as usize]))
    }

    fn write(&self, buffer: &mut Vec<u8>, from: Offset, to: Offset) {
        LittleEndian::write_f32(&mut buffer[from as usize..to as usize], self.get());
    }

    fn check(
        buffer: &'a [u8],
        from: CheckedOffset,
        to: CheckedOffset,
        latest_segment: CheckedOffset,
    ) -> EncodingResult {
        debug_assert_eq!((to - from)?.unchecked_offset(), Self::field_size());

        let from = from.unchecked_offset();
        let to = to.unchecked_offset();

        let value = LittleEndian::read_f32(&buffer[from as usize..to as usize]);
        match Self::try_from(value) {
            Some(_) => Ok(latest_segment),
            None => Err(EncodingError::UnsupportedFloat {
                position: from,
                value: f64::from(value),
            }),
        }
    }
}

impl<'a> Field<'a> for F64 {
    fn field_size() -> Offset {
        mem::size_of::<Self>() as Offset
    }

    unsafe fn read(buffer: &'a [u8], from: Offset, to: Offset) -> Self {
        Self::new(LittleEndian::read_f64(&buffer[from as usize..to as usize]))
    }

    fn write(&self, buffer: &mut Vec<u8>, from: Offset, to: Offset) {
        LittleEndian::write_f64(&mut buffer[from as usize..to as usize], self.get());
    }

    fn check(
        buffer: &'a [u8],
        from: CheckedOffset,
        to: CheckedOffset,
        latest_segment: CheckedOffset,
    ) -> EncodingResult {
        debug_assert_eq!((to - from)?.unchecked_offset(), Self::field_size());

        let from = from.unchecked_offset();
        let to = to.unchecked_offset();

        let value = LittleEndian::read_f64(&buffer[from as usize..to as usize]);
        match Self::try_from(value) {
            Some(_) => Ok(latest_segment),
            None => Err(EncodingError::UnsupportedFloat {
                position: from,
                value,
            }),
        }
    }
}

impl ExonumJson for F32 {
    fn deserialize_field<B: WriteBufferWrapper>(
        value: &Value,
        buffer: &mut B,
        from: Offset,
        to: Offset,
    ) -> Result<(), Box<Error>> {
        let number = value.as_f64().ok_or("Can't cast json as float")?;
        buffer.write(from, to, Self::new(number as f32));
        Ok(())
    }

    fn serialize_field(&self) -> Result<Value, Box<Error>> {
        Ok(Value::Number(
            Number::from_f64(f64::from(self.get())).ok_or(
                "Can't cast float as json",
            )?,
        ))
    }
}

#[cfg(feature="float_serialize")]
impl ExonumJson for F64 {
    fn deserialize_field<B: WriteBufferWrapper>(
        value: &Value,
        buffer: &mut B,
        from: Offset,
        to: Offset,
    ) -> Result<(), Box<Error>> {
        let number = value.as_f64().ok_or("Can't cast json as float")?;
        buffer.write(from, to, Self::new(number));
        Ok(())
    }

    fn serialize_field(&self) -> Result<Value, Box<Error>> {
        Ok(Value::Number(Number::from_f64(self.get()).ok_or(
            "Can't cast float as json",
        )?))
    }
}
<commit_msg>Add license to float module; fix doc tests<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::mem;
use std::error::Error;

use byteorder::{ByteOrder, LittleEndian};
use serde_json::value::{Value, Number};

use super::Result as EncodingResult;
use super::Error as EncodingError;
use encoding::{CheckedOffset, Field, Offset};
use encoding::serialize::WriteBufferWrapper;
use encoding::serialize::json::ExonumJson;

/// Wrapper for the `f32` type that restricts non-finite (NaN and Infinity) values.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct F32 {
    value: f32,
}

impl F32 {
    /// Creates a new `F32` instance with the given `value`.
    ///
    /// # Panics
    ///
    /// Panics if `is_finite()` returns `false` for the given `value`.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::encoding::F32;
    ///
    /// let val = F32::new(1.0);
    /// assert_eq!(val.get(), 1.0);
    /// ```
    pub fn new(value: f32) -> Self {
        Self::try_from(value).expect("Unexpected non-finite value")
    }

    /// Creates a new `F32` instance with the given `value`. Returns `None` if the given value
    /// isn't finite.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::encoding::F32;
    /// use std::f32;
    ///
    /// let val = F32::try_from(1.0);
    /// assert!(val.is_some());
    ///
    /// let val = F32::try_from(f32::NAN);
    /// assert!(val.is_none());
    /// ```
    pub fn try_from(value: f32) -> Option<Self> {
        if value.is_finite() {
            Some(Self { value })
        } else {
            None
        }
    }

    /// Returns value contained in this wrapper.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::encoding::F32;
    ///
    /// let wrapper = F32::new(1.0);
    /// let value = wrapper.get();
    /// ```
    pub fn get(&self) -> f32 {
        self.value
    }
}

/// Wrapper for the `f64` type that restricts non-numeric (NaN and Infinity) values.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct F64 {
    value: f64,
}

impl F64 {
    /// Creates a new `F64` instance with the given `value`.
    ///
    /// # Panics
    ///
    /// Panics if `is_finite()` returns `false` for the given `value`.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::encoding::F64;
    ///
    /// let val = F64::new(1.0);
    /// assert_eq!(val.get(), 1.0);
    /// ```
    pub fn new(value: f64) -> Self {
        Self::try_from(value).expect("Unexpected non-finite value")
    }

    /// Creates a new `F64` instance with the given `value`. Returns `None` if the given value
    /// isn't finite.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::encoding::F64;
    /// use std::f64;
    ///
    /// let val = F64::try_from(1.0);
    /// assert!(val.is_some());
    ///
    /// let val = F64::try_from(f64::NAN);
    /// assert!(val.is_none());
    /// ```
    pub fn try_from(value: f64) -> Option<Self> {
        if value.is_finite() {
            Some(Self { value })
        } else {
            None
        }
    }

    /// Returns value contained in this wrapper.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::encoding::F64;
    ///
    /// let wrapper = F64::new(1.0);
    /// let value = wrapper.get();
    /// ```
    pub fn get(&self) -> f64 {
        self.value
    }
}

impl<'a> Field<'a> for F32 {
    fn field_size() -> Offset {
        mem::size_of::<Self>() as Offset
    }

    unsafe fn read(buffer: &'a [u8], from: Offset, to: Offset) -> Self {
        Self::new(LittleEndian::read_f32(&buffer[from as usize..to as usize]))
    }

    fn write(&self, buffer: &mut Vec<u8>, from: Offset, to: Offset) {
        LittleEndian::write_f32(&mut buffer[from as usize..to as usize], self.get());
    }

    fn check(
        buffer: &'a [u8],
        from: CheckedOffset,
        to: CheckedOffset,
        latest_segment: CheckedOffset,
    ) -> EncodingResult {
        debug_assert_eq!((to - from)?.unchecked_offset(), Self::field_size());

        let from = from.unchecked_offset();
        let to = to.unchecked_offset();

        let value = LittleEndian::read_f32(&buffer[from as usize..to as usize]);
        match Self::try_from(value) {
            Some(_) => Ok(latest_segment),
            None => Err(EncodingError::UnsupportedFloat {
                position: from,
                value: f64::from(value),
            }),
        }
    }
}

impl<'a> Field<'a> for F64 {
    fn field_size() -> Offset {
        mem::size_of::<Self>() as Offset
    }

    unsafe fn read(buffer: &'a [u8], from: Offset, to: Offset) -> Self {
        Self::new(LittleEndian::read_f64(&buffer[from as usize..to as usize]))
    }

    fn write(&self, buffer: &mut Vec<u8>, from: Offset, to: Offset) {
        LittleEndian::write_f64(&mut buffer[from as usize..to as usize], self.get());
    }

    fn check(
        buffer: &'a [u8],
        from: CheckedOffset,
        to: CheckedOffset,
        latest_segment: CheckedOffset,
    ) -> EncodingResult {
        debug_assert_eq!((to - from)?.unchecked_offset(), Self::field_size());

        let from = from.unchecked_offset();
        let to = to.unchecked_offset();

        let value = LittleEndian::read_f64(&buffer[from as usize..to as usize]);
        match Self::try_from(value) {
            Some(_) => Ok(latest_segment),
            None => Err(EncodingError::UnsupportedFloat {
                position: from,
                value,
            }),
        }
    }
}

impl ExonumJson for F32 {
    fn deserialize_field<B: WriteBufferWrapper>(
        value: &Value,
        buffer: &mut B,
        from: Offset,
        to: Offset,
    ) -> Result<(), Box<Error>> {
        let number = value.as_f64().ok_or("Can't cast json as float")?;
        buffer.write(from, to, Self::new(number as f32));
        Ok(())
    }

    fn serialize_field(&self) -> Result<Value, Box<Error>> {
        Ok(Value::Number(
            Number::from_f64(f64::from(self.get())).ok_or(
                "Can't cast float as json",
            )?,
        ))
    }
}

#[cfg(feature="float_serialize")]
impl ExonumJson for F64 {
    fn deserialize_field<B: WriteBufferWrapper>(
        value: &Value,
        buffer: &mut B,
        from: Offset,
        to: Offset,
    ) -> Result<(), Box<Error>> {
        let number = value.as_f64().ok_or("Can't cast json as float")?;
        buffer.write(from, to, Self::new(number));
        Ok(())
    }

    fn serialize_field(&self) -> Result<Value, Box<Error>> {
        Ok(Value::Number(Number::from_f64(self.get()).ok_or(
            "Can't cast float as json",
        )?))
    }
}
<|endoftext|>