<commit_before>//! Storage Engine trait and several implementations
//!
//!

use std::path::Path;
use std::convert::From;
use byteorder::Error;
use std::io::prelude::*;
use std::io;
use std::fs::{ OpenOptions,File,create_dir };

use byteorder::{ WriteBytesExt, ReadBytesExt, BigEndian };

use bincode::SizeLimit;
use bincode::rustc_serialize::{ EncodingError,DecodingError,encode_into,decode_from };

/// constants
 const MAGIC_NUMBER: u64 = 0x6561742073686974; // secret
 const MAGIC_NUMBER_BYTES: usize = 8;

/// Storage Engine Interface.
///
/// A storage engine, like MyISAM and InnoDB, is responsible for reading and
/// writing data to disk, maintain and use indices, check for data corruption
/// and repair corrupt files.
///
/// Each table in a database may use a different storage engine.
pub trait Engine {

}

/// A database table
///
/// Through this type, you can retreive certain meta information about the
/// table (like column names, column types, storage engine, ...). It's `access`
/// method locks the table globally and returns a storage engine to access
/// the table data.
#[derive(Debug)]
pub enum DatabaseError {
    Io(io::Error),
    BinEn(EncodingError),
    BinDe(DecodingError),
    Byteorder(::byteorder::Error),
    MagicNmbr,
}

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

impl  From<EncodingError> for DatabaseError {
    fn from(err: EncodingError) -> DatabaseError {
        DatabaseError::BinEn(err)
    }
}

impl From<DecodingError> for DatabaseError {
    fn from(err: DecodingError) -> DatabaseError {
        DatabaseError::BinDe(err)
    }
}

impl From< ::byteorder::Error> for DatabaseError {
    fn from(err: ::byteorder::Error) -> DatabaseError {
        DatabaseError::Byteorder(err)
    }
}

/// A Enum for File Modes
///
/// Can be used to define the save and load configuration of open_file
#[derive(Debug)]
enum FileMode{ LoadDefault, SaveDefault, }

/// A Enum for Datatypes (will be removed later)
#[repr(u8)]
#[derive(Clone,Copy,Debug,RustcDecodable, RustcEncodable)]
pub enum DataType{ Integer = 1, Float = 2,}
impl DataType {
    pub fn value(&self) -> u8 {
       *self as u8
    }
}

pub struct Database {
    name: String,
}

impl Database {
    pub fn new_database(database_name: &str) -> Database {
        Database{ name: database_name.to_string() }
    }
    pub fn create_database(&self) -> Result<(),DatabaseError> {
        println!("trying to create dir!");
        try!(create_dir(&self.name));
        println!("created dir");
        Ok(())
    }
}

#[derive(Debug,RustcDecodable, RustcEncodable)]
pub struct Table {
    name: String,
    engine_id: u8,
    version_nmbr: u8,
    column_nmbr: u16,
    columns: Vec<Column>,

}

impl Default for Table {
    fn default() -> Table {
        let mut t: Vec<Column> = Vec::new();
        t.push(Default::default());
        Table { name:"default".to_string(), engine_id: 3, version_nmbr:  1, column_nmbr: 1, columns: t }
    }
}

impl Table {
    pub fn load(database: &str, table: &str) -> Result<(), DatabaseError> {
        // TODO: Read the .tbl file from disk and parse it
        let mut file = try!(Self::open_file(database,table,FileMode::LoadDefault));

        let ma_nmbr = try!(file.read_uint::<BigEndian>(MAGIC_NUMBER_BYTES));

        if ma_nmbr != MAGIC_NUMBER {
            println!("Magic Number not correct");
            return Err(DatabaseError::MagicNmbr)
        }
        let data: Table = try!(decode_from(&mut file, SizeLimit::Infinite));
        println!("{:?}", data);
        Ok(())
    }

    pub fn create_new(engine: u8, name: &str) -> Table {

        Table { name: name.to_string(), engine_id: engine, version_nmbr: 1, column_nmbr: 0, columns: Vec::new() }
    }

    pub fn save(&self,database: &str, table: &str) -> Result<(), DatabaseError> {
        // call for open file
        let mut file = try!(Self::open_file(database,table,FileMode::SaveDefault));
        try!(file.write_u64::<BigEndian>(MAGIC_NUMBER));//MAGIC_NUMBER
        try!(encode_into(&self,&mut file,SizeLimit::Infinite));

        // debug message all okay
        println!("I Wrote my File");
        Ok(())
    }

    fn open_file(database: &str, table: &str, mode: FileMode) -> Result<File, DatabaseError> {
        // create new file or open new one
        let st = format!("{}/{}",database,table);
        let path = Path::new(&st);

        match mode {
            FileMode::SaveDefault => OpenOptions::new()
                .write(true)
                .create(true)
                .open(path),
            FileMode::LoadDefault => OpenOptions::new()
                .read(true)
                .open(path),
        }.map_err(|e| e.into())
    }

    pub fn columns(&self) -> &[Column] {
        // TODO: Return real columns
        &self.columns
    }

    pub fn add_column(&mut self, name: &str, dtype: DataType) {
        self.columns.push(Column::create_new(name, dtype));
    }

    pub fn remove_column(&mut self, name: &str, data_type: DataType) {

    }
}

/// A table column. Has a name, a type, ...
#[derive(Debug,RustcDecodable, RustcEncodable,Clone)]
pub struct Column {
    name: String, //name of column
    data_type: DataType, //name of the data type that is contained in this column
}

impl Default for Column {
    fn default() -> Column
    {
        Column{name: "default".to_string(), data_type: DataType::Integer}
    }
}

impl Column {
    pub fn create_new(name: &str, dtype: DataType) -> Column {
        Column{ name: name.to_string(), data_type: dtype.clone() }
    }
}

// # Some information for the `storage` working group:
//
// You work at the very bottom of the database: The thing that actually
// writes the data disk. Everything in this module is used only by the
// query execution module.
//
// The file layout may look like this:
// We have some `db_dir` where everything lives. In that directory, there are
// subdirectories for every database. In each of those subdirs is optionally
// a file `db.meta` that contains information about the database (such as
// permissions). The tables of each database are saved in *.tbl files that
// live inside the database directory.
//
// Your task is to provide types and method to:
// - read a specific table from a specific
//   database from file
// - create a new table in a database
// - query meta information about a table (columns for example)
// - lock a table for reading/writing it's data through a storage engine
//
// The other main task is to:
// - specify the storage engine interface
// - implement a simple storage engine (heap/flatfiles)
//
<commit_msg>More Code Formatting<commit_after>//! Storage Engine trait and several implementations
//!
//!

use std::path::Path;
use std::convert::From;
use byteorder::Error;
use std::io::prelude::*;
use std::io;
use std::fs::{ OpenOptions,File,create_dir };

use byteorder::{ WriteBytesExt, ReadBytesExt, BigEndian };

use bincode::SizeLimit;
use bincode::rustc_serialize::{ EncodingError,DecodingError,encode_into,decode_from };

/// constants
 const MAGIC_NUMBER: u64 = 0x6561742073686974; // secret
 const MAGIC_NUMBER_BYTES: usize = 8;

/// Storage Engine Interface.
///
/// A storage engine, like MyISAM and InnoDB, is responsible for reading and
/// writing data to disk, maintain and use indices, check for data corruption
/// and repair corrupt files.
///
/// Each table in a database may use a different storage engine.
pub trait Engine {

}

/// A database table
///
/// Through this type, you can retreive certain meta information about the
/// table (like column names, column types, storage engine, ...). It's `access`
/// method locks the table globally and returns a storage engine to access
/// the table data.
#[derive(Debug)]
pub enum DatabaseError {
    Io(io::Error),
    BinEn(EncodingError),
    BinDe(DecodingError),
    Byteorder(::byteorder::Error),
    MagicNmbr,
}

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

impl  From<EncodingError> for DatabaseError {
    fn from(err: EncodingError) -> DatabaseError {
        DatabaseError::BinEn(err)
    }
}

impl From<DecodingError> for DatabaseError {
    fn from(err: DecodingError) -> DatabaseError {
        DatabaseError::BinDe(err)
    }
}

impl From< ::byteorder::Error> for DatabaseError {
    fn from(err: ::byteorder::Error) -> DatabaseError {
        DatabaseError::Byteorder(err)
    }
}

/// A Enum for File Modes
///
/// Can be used to define the save and load configuration of open_file
#[derive(Debug)]
enum FileMode{ LoadDefault, SaveDefault, }

/// A Enum for Datatypes (will be removed later)
#[repr(u8)]
#[derive(Clone,Copy,Debug,RustcDecodable, RustcEncodable)]
pub enum DataType{ Integer = 1, Float = 2,}
impl DataType {
    pub fn value(&self) -> u8 {
       *self as u8
    }
}

pub struct Database {
    name: String,
}

impl Database {
    pub fn new_database(database_name: &str) -> Database {
        Database{ name: database_name.to_string() }
    }
    pub fn create_database(&self) -> Result<(),DatabaseError> {
        println!("trying to create dir!");
        try!(create_dir(&self.name));
        println!("created dir");
        Ok(())
    }
}

#[derive(Debug,RustcDecodable, RustcEncodable)]
pub struct Table {
    name: String,
    engine_id: u8,
    version_nmbr: u8,
    column_nmbr: u16,
    columns: Vec<Column>,

}

impl Default for Table {
    fn default() -> Table {
        let mut t: Vec<Column> = Vec::new();
        t.push(Default::default());
        Table {
            name:"default".to_string(),
            engine_id: 3,
            version_nmbr: 1,
            column_nmbr: 1,
            columns: t
        }
    }
}

impl Table {
    pub fn load(database: &str, table: &str) -> Result<(), DatabaseError> {
        // TODO: Read the .tbl file from disk and parse it
        let mut file = try!(Self::open_file(database,table,FileMode::LoadDefault));

        let ma_nmbr = try!(file.read_uint::<BigEndian>(MAGIC_NUMBER_BYTES));

        if ma_nmbr != MAGIC_NUMBER {
            println!("Magic Number not correct");
            return Err(DatabaseError::MagicNmbr)
        }
        let data: Table = try!(decode_from(&mut file, SizeLimit::Infinite));
        println!("{:?}", data);
        Ok(())
    }

    pub fn create_new(engine: u8, name: &str) -> Table {

        Table {
            name: name.to_string(),
            engine_id: engine,
            version_nmbr: 1,
            column_nmbr: 0,
            columns: Vec::new()
        }
    }

    pub fn save(&self,database: &str, table: &str) -> Result<(), DatabaseError> {
        // call for open file
        let mut file = try!(Self::open_file(database, table, FileMode::SaveDefault));
        try!(file.write_u64::<BigEndian>(MAGIC_NUMBER));//MAGIC_NUMBER
        try!(encode_into(&self, &mut file,SizeLimit::Infinite));

        // debug message all okay
        println!("I Wrote my File");
        Ok(())
    }

    fn open_file(database: &str, table: &str, mode: FileMode) -> Result<File, DatabaseError> {
        // create new file or open new one
        let st = format!("{}/{}",database,table);
        let path = Path::new(&st);

        match mode {
            FileMode::SaveDefault => OpenOptions::new()
                .write(true)
                .create(true)
                .open(path),
            FileMode::LoadDefault => OpenOptions::new()
                .read(true)
                .open(path),
        }.map_err(|e| e.into())
    }

    pub fn columns(&self) -> &[Column] {
        // TODO: Return real columns
        &self.columns
    }

    pub fn add_column(&mut self, name: &str, dtype: DataType) {
        self.columns.push(Column::create_new(name, dtype));
    }

    pub fn remove_column(&mut self, name: &str, data_type: DataType) {

    }
}

/// A table column. Has a name, a type, ...
#[derive(Debug,RustcDecodable, RustcEncodable,Clone)]
pub struct Column {
    name: String, //name of column
    data_type: DataType, //name of the data type that is contained in this column
}

impl Default for Column {
    fn default() -> Column {
        Column {
            name: "default".to_string(),
            data_type: DataType::Integer
        }
    }
}

impl Column {
    pub fn create_new(name: &str, dtype: DataType) -> Column {
        Column {
            name: name.to_string(),
            data_type: dtype.clone()
        }
    }
}

// # Some information for the `storage` working group:
//
// You work at the very bottom of the database: The thing that actually
// writes the data disk. Everything in this module is used only by the
// query execution module.
//
// The file layout may look like this:
// We have some `db_dir` where everything lives. In that directory, there are
// subdirectories for every database. In each of those subdirs is optionally
// a file `db.meta` that contains information about the database (such as
// permissions). The tables of each database are saved in *.tbl files that
// live inside the database directory.
//
// Your task is to provide types and method to:
// - read a specific table from a specific
//   database from file
// - create a new table in a database
// - query meta information about a table (columns for example)
// - lock a table for reading/writing it's data through a storage engine
//
// The other main task is to:
// - specify the storage engine interface
// - implement a simple storage engine (heap/flatfiles)
//
<|endoftext|>


<commit_before>use crate::{ids};

use super::auto::{AsAny, HasInner, Abstract};
use super::application::Application;
use super::container::MaybeContainer;
use super::control::MaybeControl;
use super::closeable::MaybeCloseable;
use super::clickable::MaybeClickable;
use super::has_native_id::{HasNativeId, HasNativeIdInner};
use super::has_size::MaybeHasSize;
use super::has_visibility::MaybeHasVisibility;
use super::window::MaybeWindow;
use super::message::MaybeMessage;
use super::tray::MaybeTray;
use super::seal::Sealed;
use super::has_image::MaybeHasImage;
use super::has_layout::MaybeHasLayout;
use super::has_label::MaybeHasLabel;
use super::has_progress::MaybeHasProgress;

#[cfg(feature = "type_check")]
use std::any::TypeId;

use std::any::Any;
use std::borrow::Cow;
use std::marker::PhantomData;
use std::rc::Rc;

pub trait Member: HasNativeId + AsAny + Sealed
        + MaybeControl + MaybeContainer + MaybeHasSize + MaybeHasVisibility + MaybeHasImage + MaybeHasLayout + MaybeHasLabel + MaybeHasProgress + MaybeCloseable + MaybeClickable
        + MaybeWindow + MaybeTray + MaybeMessage {
    fn id(&self) -> ids::Id;
    fn tag(&self) -> Option<Cow<str>>;
    fn set_tag(&mut self, tag: Option<Cow<str>>);

    #[cfg(feature = "type_check")]
    unsafe fn type_id(&self) -> TypeId;

    fn as_member(&self) -> &dyn Member;
    fn as_member_mut(&mut self) -> &mut dyn Member;
    fn into_member(self: Box<Self>) -> Box<dyn Member>;
}

pub trait MemberInner: HasNativeIdInner + Sized + 'static {}

impl<T: MemberInner> Abstract for AMember<T> {}
impl<II: MemberInner, T: HasInner<I = II> + Abstract + 'static> MemberInner for T {}

#[repr(C)]
pub struct MemberBase {
    id: ids::Id,
    tag: Option<String>,

    _as_member: unsafe fn(&MemberBase) -> &dyn Member,
    _as_member_mut: unsafe fn(&mut MemberBase) -> &mut dyn Member,
    _no_threads: PhantomData<Rc<()>>,
}
#[repr(C)]
pub struct AMember<T: MemberInner> {
    pub base: MemberBase,
    pub inner: T,
}

impl MemberBase {
    #[inline]
    pub fn with_type<T: Member>() -> Self {
        MemberBase {
            id: ids::Id::next(),
            tag: None,
            _as_member: crate::utils::base_to_member::<T>,
            _as_member_mut: crate::utils::base_to_member_mut::<T>,
            _no_threads: PhantomData,
        }
    }
    pub fn application<A: Application>(&self) -> &A {
        crate::runtime::get().expect("Application not initialized. Please run `plygui::imp::Application::with_name()` first.")
    }
    pub fn application_mut<A: Application>(&mut self) -> &mut A {
        crate::runtime::get().expect("Application not initialized. Please run `plygui::imp::Application::with_name()` first.")
    }
    pub fn id(&self) -> ids::Id {
        self.id
    }
    pub fn tag(&self) -> Option<Cow<str>> {
        self.tag.as_ref().map(|t| t.as_str().into())
    }
    pub fn set_tag(&mut self, tag: Option<Cow<str>>) {
        self.tag = tag.map(|t| t.into());
    }
    #[inline]
    pub fn as_any(&self) -> &dyn Any {
        unsafe { (self._as_member)(self) }.as_any()
    }
    #[inline]
    pub fn as_any_mut(&mut self) -> &mut dyn Any {
        unsafe { (self._as_member_mut)(self) }.as_any_mut()
    }
    #[inline]
    pub fn as_member(&self) -> &dyn Member {
        unsafe { (self._as_member)(self) }
    }
    #[inline]
    pub fn as_member_mut(&mut self) -> &mut dyn Member {
        unsafe { (self._as_member_mut)(self) }
    }
}
impl<T: MemberInner> HasNativeId for AMember<T> {
    #[inline]
    unsafe fn native_id(&self) -> usize {
        self.inner.native_id().into()
    }
}
impl<T: MemberInner> Member for AMember<T> {
    #[inline]
    fn id(&self) -> ids::Id {
        self.base.id
    }
    fn tag(&self) -> Option<Cow<str>> {
        self.base.tag()
    }
    fn set_tag(&mut self, tag: Option<Cow<str>>) {
        self.base.set_tag(tag)
    }
    #[cfg(feature = "type_check")]
    unsafe fn type_id(&self) -> TypeId {
        self.inner.native_id().type_id()
    }

    #[inline]
    fn as_member(&self) -> &dyn Member {
        self
    }
    #[inline]
    fn as_member_mut(&mut self) -> &mut dyn Member {
        self
    }
    #[inline]
    fn into_member(self: Box<Self>) -> Box<dyn Member> {
        self
    }
}
impl<T: MemberInner> AsAny for AMember<T> {
    #[inline]
    fn as_any(&self) -> &dyn Any {
        self
    }
    #[inline]
    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
    #[inline]
    fn into_any(self: Box<Self>) -> Box<dyn Any> {
        self
    }
}
impl<T: MemberInner> AMember<T> {
    #[inline]
    pub fn with_inner(inner: T) -> Self {
        AMember {
            inner: inner,
            base: MemberBase::with_type::<Self>(),
        }
    }
}

impl<T: MemberInner> HasInner for AMember<T> {
    type I = T;

    #[inline]
    fn inner(&self) -> &Self::I {
        &self.inner
    }
    #[inline]
    fn inner_mut(&mut self) -> &mut Self::I {
        &mut self.inner
    }
    #[inline]
    fn into_inner(self) -> Self::I {
        self.inner
    }
}

impl<T: MemberInner> Sealed for AMember<T> {}
<commit_msg>Member api fix<commit_after>use crate::{ids};

use super::auto::{AsAny, HasInner, Abstract};
use super::application::Application;
use super::container::MaybeContainer;
use super::control::MaybeControl;
use super::closeable::MaybeCloseable;
use super::clickable::MaybeClickable;
use super::has_native_id::{HasNativeId, HasNativeIdInner};
use super::has_size::MaybeHasSize;
use super::has_visibility::MaybeHasVisibility;
use super::window::MaybeWindow;
use super::message::MaybeMessage;
use super::tray::MaybeTray;
use super::seal::Sealed;
use super::has_image::MaybeHasImage;
use super::has_layout::MaybeHasLayout;
use super::has_label::MaybeHasLabel;
use super::has_progress::MaybeHasProgress;

#[cfg(feature = "type_check")]
use std::any::TypeId;

use std::any::Any;
use std::borrow::Cow;
use std::marker::PhantomData;
use std::rc::Rc;

pub trait Member: HasNativeId + AsAny + Sealed
        + MaybeControl + MaybeContainer + MaybeHasSize + MaybeHasVisibility + MaybeHasImage + MaybeHasLayout + MaybeHasLabel + MaybeHasProgress + MaybeCloseable + MaybeClickable
        + MaybeWindow + MaybeTray + MaybeMessage {
    fn id(&self) -> ids::Id;
    fn tag(&self) -> Option<Cow<str>>;
    fn set_tag(&mut self, tag: Option<Cow<str>>);

    #[cfg(feature = "type_check")]
    unsafe fn type_id(&self) -> TypeId;

    fn as_member(&self) -> &dyn Member;
    fn as_member_mut(&mut self) -> &mut dyn Member;
    fn into_member(self: Box<Self>) -> Box<dyn Member>;

    fn as_base(&self) -> &MemberBase;
    fn as_base_mut(&mut self) -> &mut MemberBase;
}

pub trait MemberInner: HasNativeIdInner + Sized + 'static {}

impl<T: MemberInner> Abstract for AMember<T> {}
impl<II: MemberInner, T: HasInner<I = II> + Abstract + 'static> MemberInner for T {}

#[repr(C)]
pub struct MemberBase {
    id: ids::Id,
    tag: Option<String>,

    _as_member: unsafe fn(&MemberBase) -> &dyn Member,
    _as_member_mut: unsafe fn(&mut MemberBase) -> &mut dyn Member,
    _no_threads: PhantomData<Rc<()>>,
}
#[repr(C)]
pub struct AMember<T: MemberInner> {
    pub base: MemberBase,
    pub inner: T,
}

impl MemberBase {
    #[inline]
    pub fn with_type<T: Member>() -> Self {
        MemberBase {
            id: ids::Id::next(),
            tag: None,
            _as_member: crate::utils::base_to_member::<T>,
            _as_member_mut: crate::utils::base_to_member_mut::<T>,
            _no_threads: PhantomData,
        }
    }
    pub fn application<A: Application>(&self) -> &A {
        crate::runtime::get().expect("Application not initialized. Please run `plygui::imp::Application::with_name()` first.")
    }
    pub fn application_mut<A: Application>(&mut self) -> &mut A {
        crate::runtime::get().expect("Application not initialized. Please run `plygui::imp::Application::with_name()` first.")
    }
    pub fn id(&self) -> ids::Id {
        self.id
    }
    pub fn tag(&self) -> Option<Cow<str>> {
        self.tag.as_ref().map(|t| t.as_str().into())
    }
    pub fn set_tag(&mut self, tag: Option<Cow<str>>) {
        self.tag = tag.map(|t| t.into());
    }
    #[inline]
    pub fn as_any(&self) -> &dyn Any {
        unsafe { (self._as_member)(self) }.as_any()
    }
    #[inline]
    pub fn as_any_mut(&mut self) -> &mut dyn Any {
        unsafe { (self._as_member_mut)(self) }.as_any_mut()
    }
    #[inline]
    pub fn as_member(&self) -> &dyn Member {
        unsafe { (self._as_member)(self) }
    }
    #[inline]
    pub fn as_member_mut(&mut self) -> &mut dyn Member {
        unsafe { (self._as_member_mut)(self) }
    }
}
impl<T: MemberInner> HasNativeId for AMember<T> {
    #[inline]
    unsafe fn native_id(&self) -> usize {
        self.inner.native_id().into()
    }
}
impl<T: MemberInner> Member for AMember<T> {
    #[inline]
    fn id(&self) -> ids::Id {
        self.base.id
    }
    fn tag(&self) -> Option<Cow<str>> {
        self.base.tag()
    }
    fn set_tag(&mut self, tag: Option<Cow<str>>) {
        self.base.set_tag(tag)
    }
    #[cfg(feature = "type_check")]
    unsafe fn type_id(&self) -> TypeId {
        self.inner.native_id().type_id()
    }

    #[inline]
    fn as_member(&self) -> &dyn Member {
        self
    }
    #[inline]
    fn as_member_mut(&mut self) -> &mut dyn Member {
        self
    }
    #[inline]
    fn into_member(self: Box<Self>) -> Box<dyn Member> {
        self
    }

    #[inline]
    fn as_base(&self) -> &MemberBase {
    	&self.base
    }
    #[inline]
    fn as_base_mut(&mut self) -> &mut MemberBase {
    	&mut self.base
    }
}
impl<T: MemberInner> AsAny for AMember<T> {
    #[inline]
    fn as_any(&self) -> &dyn Any {
        self
    }
    #[inline]
    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
    #[inline]
    fn into_any(self: Box<Self>) -> Box<dyn Any> {
        self
    }
}
impl<T: MemberInner> AMember<T> {
    #[inline]
    pub fn with_inner(inner: T) -> Self {
        AMember {
            inner: inner,
            base: MemberBase::with_type::<Self>(),
        }
    }
}

impl<T: MemberInner> HasInner for AMember<T> {
    type I = T;

    #[inline]
    fn inner(&self) -> &Self::I {
        &self.inner
    }
    #[inline]
    fn inner_mut(&mut self) -> &mut Self::I {
        &mut self.inner
    }
    #[inline]
    fn into_inner(self) -> Self::I {
        self.inner
    }
}

impl<T: MemberInner> Sealed for AMember<T> {}
<|endoftext|>


<commit_before>use error::BrokerError;
use futures::{Future, Stream, future};
use config::    Config;
use hyper::header::{ContentLength, CacheControl, CacheDirective};
use redis::Commands;
use serde_json::de::from_str;
use serde_json::value::Value;
use std::cmp::max;
use std::rc::Rc;
use std::str::from_utf8;

/// Represents a Redis key.
pub enum CacheKey<'a> {
    Discovery { domain: &'a str },
    KeySet { domain: &'a str },
}

impl<'a> CacheKey<'a> {
    fn to_string(&self) -> String {
        match *self {
            CacheKey::Discovery { domain } => {
                format!("cache:discovery:{}", domain)
            },
            CacheKey::KeySet { domain } => {
                format!("cache:key-set:{}", domain)
            }
        }
    }
}

/// Fetch `url` from cache or using a HTTP GET request, and parse the response as JSON. The
/// cache is stored in `app.store` with `key`. The `client` is used to make the HTTP GET request,
/// if necessary.
pub fn fetch_json_url(app: &Rc<Config>, url: &str, key: &CacheKey)
                      -> Box<Future<Item=Value, Error=BrokerError>> {

    // Try to retrieve the result from cache.
    let key_str = key.to_string();
    let data: Option<String> = match app.store.client.get(&key_str) {
        Ok(data) => data,
        Err(e) => return Box::new(future::err(e.into())),
    };

    let f: Box<Future<Item=String, Error=BrokerError>> = if let Some(data) = data {
        Box::new(future::ok(data))
    } else {
        // Cache miss, make a request.
        let url = url.parse().expect("could not parse request url");
        let f = app.http_client.get(url).map_err(|err| err.into());

        let app = app.clone();
        let f = f.and_then(move |res| {
            // Check the Content-Length. We require it.
            let size = match res.headers().get() {
                Some(&ContentLength(size)) => size,
                None => return future::err(BrokerError::Custom(
                    "missing content-length header in response".to_string())),
            };

            if size > app.store.max_response_size {
                return future::err(BrokerError::Custom(
                    "response exceeds the size limit".to_string()));
            }

            // Grab the max-age directive from the Cache-Control header.
            let max_age = res.headers().get().map_or(0, |header: &CacheControl| {
                for dir in header.iter() {
                    if let CacheDirective::MaxAge(seconds) = *dir {
                        return seconds;
                    }
                }
                0
            });

            future::ok((app, res, max_age))
        });

        // Receive the body.
        let f = f.and_then(|(app, res, max_age)| {
            res.body().concat2()
                .map(move |chunk| (app, chunk, max_age))
                .map_err(|err| err.into())
        });

        let f = f.and_then(|(app, chunk, max_age)| {
            let result = from_utf8(&chunk)
                .map_err(|_| BrokerError::Custom("response contained invalid utf-8".to_string()))
                .map(|data| data.to_owned())
                .and_then(move |data| {
                    // Cache the response for at least `expire_cache`, but honor longer `max-age`.
                    let seconds = max(app.store.expire_cache, max_age as usize);
                    app.store.client.set_ex::<_, _, ()>(&key_str, &data, seconds)
                        .map_err(|err| err.into())
                        .map(|_| data)
                });
            future::result(result)
        });

        Box::new(f)
    };

    let f = f.and_then(|data| {
        future::result(from_str(&data).map_err(|_| {
            BrokerError::Custom("failed to parse response as JSON".to_string())
        }))
    });

    Box::new(f)
}
<commit_msg>Don't require Content-Length<commit_after>use error::BrokerError;
use futures::{Future, Stream, future};
use config::Config;
use hyper::{Chunk, Error as HyperError};
use hyper::header::{CacheControl, CacheDirective};
use redis::Commands;
use serde_json::de::from_str;
use serde_json::value::Value;
use std::cmp::max;
use std::rc::Rc;
use std::str::from_utf8;

/// Represents a Redis key.
pub enum CacheKey<'a> {
    Discovery { domain: &'a str },
    KeySet { domain: &'a str },
}

impl<'a> CacheKey<'a> {
    fn to_string(&self) -> String {
        match *self {
            CacheKey::Discovery { domain } => {
                format!("cache:discovery:{}", domain)
            },
            CacheKey::KeySet { domain } => {
                format!("cache:key-set:{}", domain)
            }
        }
    }
}

/// Fetch `url` from cache or using a HTTP GET request, and parse the response as JSON. The
/// cache is stored in `app.store` with `key`. The `client` is used to make the HTTP GET request,
/// if necessary.
pub fn fetch_json_url(app: &Rc<Config>, url: &str, key: &CacheKey)
                      -> Box<Future<Item=Value, Error=BrokerError>> {

    // Try to retrieve the result from cache.
    let key_str = key.to_string();
    let data: Option<String> = match app.store.client.get(&key_str) {
        Ok(data) => data,
        Err(e) => return Box::new(future::err(e.into())),
    };

    let f: Box<Future<Item=String, Error=BrokerError>> = if let Some(data) = data {
        Box::new(future::ok(data))
    } else {
        // Cache miss, make a request.
        let url = url.parse().expect("could not parse request url");
        let f = app.http_client.get(url).map_err(|err| err.into());

        let app = app.clone();
        let f = f.and_then(move |res| {
            // Grab the max-age directive from the Cache-Control header.
            let max_age = res.headers().get().map_or(0, |header: &CacheControl| {
                for dir in header.iter() {
                    if let CacheDirective::MaxAge(seconds) = *dir {
                        return seconds;
                    }
                }
                0
            });

            // Receive the body.
            let max_size = app.store.max_response_size as usize;
            res.body()
                .fold(Chunk::default(), move |mut acc, chunk| {
                    if acc.len() + chunk.len() > max_size {
                        future::err(HyperError::TooLarge)
                    } else {
                        acc.extend(chunk);
                        future::ok(acc)
                    }
                })
                .map(move |chunk| (app, chunk, max_age))
                .map_err(|err| err.into())
        });

        let f = f.and_then(|(app, chunk, max_age)| {
            let result = from_utf8(&chunk)
                .map_err(|_| BrokerError::Custom("response contained invalid utf-8".to_string()))
                .map(|data| data.to_owned())
                .and_then(move |data| {
                    // Cache the response for at least `expire_cache`, but honor longer `max-age`.
                    let seconds = max(app.store.expire_cache, max_age as usize);
                    app.store.client.set_ex::<_, _, ()>(&key_str, &data, seconds)
                        .map_err(|err| err.into())
                        .map(|_| data)
                });
            future::result(result)
        });

        Box::new(f)
    };

    let f = f.and_then(|data| {
        future::result(from_str(&data).map_err(|_| {
            BrokerError::Custom("failed to parse response as JSON".to_string())
        }))
    });

    Box::new(f)
}
<|endoftext|>


<commit_before>extern crate libc;
use std::ptr;
use std::mem;
use std::slice::from_raw_parts;
use std::string::String;
use std::collections::HashMap;
use std::boxed::Box;
use x11::xlib;
use x11::keysym;

use super::config::Config;
use super::workspace::{ Workspace, Workspaces };
use super::handler;

fn get_text_property(display: *mut xlib::Display, window: xlib::Window, atom: xlib::Atom) -> Option<String>{
    unsafe{
        let mut prop: xlib::XTextProperty = mem::zeroed();
        let r = xlib::XGetTextProperty(display, window, &mut prop, atom);
        if r == 0 {
            None
        }else{
            let s = String::from_raw_parts(prop.value, prop.nitems as usize, prop.nitems as usize + 1 ).clone();
            let text = Some(s);
            xlib::XFree(prop.value as *mut libc::c_void);
            text
        }
    }
}

pub struct WindowManager {
    pub display: *mut xlib::Display,
    pub screen_num: libc::c_int,
    pub root:    xlib::Window,

    pub workspaces: Workspaces,
    config: Config
}

impl WindowManager {
    pub fn new() -> WindowManager {
	unsafe {
	    let display = xlib::XOpenDisplay(ptr::null());
            if display == ptr::null_mut() {
                panic!("can't open display")
            }
	    let screen_num  = xlib::XDefaultScreen(display);
	    let root    = xlib::XRootWindow(display, screen_num);

	    let mut wm = WindowManager {
	        display: display,
                screen_num: screen_num,
	        root:    root,

                config: Config::load(),
                workspaces: Workspaces::new()
            };
            wm.workspaces.create_workspace('1');
            wm
	}
    }

    pub fn run(&mut self) {
        let mask = xlib::SubstructureRedirectMask | xlib::SubstructureNotifyMask;
        let keymask = xlib::KeyPressMask | xlib::KeyReleaseMask;
        unsafe{
            xlib::XSelectInput(self.display, self.root,
                               mask | keymask);
            xlib::XSync(self.display, 0);
        }

        loop {
            //handle events here
            let mut e = xlib::XEvent{
                pad: [0; 24],
            };

            unsafe {
                xlib::XNextEvent(self.display, &mut e);
                let t = e.get_type();
                match t {
                    xlib::CreateNotify => {
                        let event: xlib::XCreateWindowEvent = From::from(e);

                        if event.override_redirect != 0 {
                            continue;
                        }

                        // change attributes before display
                        let mut attrs: xlib::XSetWindowAttributes = mem::zeroed();
                        attrs.event_mask = xlib::KeyReleaseMask;
                        let valuemask = xlib::CWEventMask;
                        xlib::XChangeWindowAttributes(self.display, event.window, valuemask, &mut attrs);

                        // add to workspace
                        // let mut w = self.workspaces.get_mut(&'1');
                        // match w {
                        //     Some(workspace) => {
                        //         workspace.add(event.window);
                        //         workspace.config(self);
                        //     }
                        //     None => {}
                        // }

                        // get window property
                        let n = get_text_property(self.display, event.window, xlib::XA_WM_NAME);
                        match n {
                            Some(s) => {debug!("create window {} for {}", event.window, s);}
                            None => {}
                        }

                        // let mut actual_type_return: u64 = 0;
                        // let mut actual_format_return: i32 = 0;
                        // let mut nitem_return: libc::c_ulong = 0;
                        // let mut bytes_after_return: libc::c_ulong = 0;
                        // let mut prop_return: *mut libc::c_uchar = mem::zeroed();
                        // let r = xlib::XGetWindowProperty(self.display, event.window, xlib::XA_WM_NAME,
                        //                          0, 0xFFFFFFFF, 0, 0,
                        //                          &mut actual_type_return,
                        //                          &mut actual_format_return,
                        //                          &mut nitem_return,
                        //                          &mut bytes_after_return,
                        //                          &mut prop_return);

                        // debug!("result get wp {}", r);
                        // if r == 0 {

                        // }else{
                        //     debug!("actual format return {}", actual_format_return);
                        //     if actual_format_return == 0 {

                        //     }
                        //     else {
                        //         // let s = from_raw_parts(prop_return as *const libc::c_ulong, nitems_return as usize).iter()
                        //         //     .map(|&c| c as u64)
                        //         //     .collect();
                        //         let s = String::from_raw_parts(prop_return, nitem_return as usize, nitem_return as usize + 1 );
                        //         println!("{}", s);

                        //     }
                        // }

                    }
                    xlib::DestroyNotify => {
                        debug!("destroy notify");
                        let event: xlib::XDestroyWindowEvent = From::from(e);
                    }
                    xlib::MapNotify => {
                        debug!("map notify");
                        let event: xlib::XMapEvent = From::from(e);
                        println!("event {}", event.event);
                        println!("w {}", event.window);
                    }
                    xlib::UnmapNotify => {
                        debug!("unmap notify");
                        let event: xlib::XUnmapEvent = From::from(e);
                        let workspace = self.workspaces.current_workspace();
                        match workspace.contain(event.window) {
                            Some(index) => {
                                workspace.remove(event.window);
                                workspace.config(self.display, self.screen_num);
                            }
                            None => {}
                        }
                    }
                    xlib::MapRequest => {
                        debug!("map request");
                        let event: xlib::XMapRequestEvent = From::from(e);
                        println!("w {}", event.window);
                        xlib::XMapWindow(self.display, event.window);

                        // add app top-level window to workspace
                        let mut attrs: xlib::XWindowAttributes = mem::zeroed();
                        xlib::XGetWindowAttributes(self.display, event.window, &mut attrs);

                        if attrs.override_redirect == 0{
                            debug!("top level window");
                            let mut workspace = self.workspaces.current_workspace();
                            if workspace.contain(event.window).is_none() {
                                workspace.add(event.window);
                                workspace.config(self.display, self.screen_num);
                            }
                        }

                    }
                    xlib::ClientMessage => {
                        debug!("client message");
                        // let event = cast_event::<xlib::XClientMessageEvent>(&e);
                        let event: xlib::XClientMessageEvent = From::from(e);
                    }
                    xlib::KeyRelease => {
                        debug!("key release");
                        let mut event: xlib::XKeyEvent = From::from(e);

                        if event.state > 0 {
                            let mut sym: xlib::KeySym = 0;
                            let status: *mut xlib::XComposeStatus = ptr::null_mut();
                            xlib::XLookupString(&mut event, ptr::null_mut(), 0, &mut sym, status);

                            let b = handler::KeyBind {
                                key: sym,
                                mask: event.state,
                            };
                            debug!("key {} {}", event.state, sym);
                            // let mut h: Box<handler::Handler>;
                            match self.config.bindsyms.get_mut(&b) {
                                Some(handler) => {
                                    handler.handle(&mut self.workspaces, self.display, self.screen_num);
                                }
                                None => {
                                    println!("no bind");
                                    continue;
                                }
                            }
                        }
                    }
                    xlib::ConfigureNotify => {
                        debug!("configure notify");
                    }
                    xlib::ConfigureRequest =>{
                        debug!("configure request");
                        // let mut change = xlib::XWindowChanges {
                        //     x: event.x,
                        //     y: event.y,
                        //     width: event.width,
                        //     height: event.height,
                        //     border_width: event.border_width,
                        //     sibling: event.above,
                        //     stack_mode: event.detail
                        // };
                        // debug!("config x: {}, y: {}, width: {}, height: {}",
                        //        change.x, change.y, change.width, change.height);
                        let mut event: xlib::XConfigureRequestEvent = From::from(e);
                        // xlib::XConfigureWindow(event.display, event.window, event.value_mask as u32, &mut change);

                    }
                    _ => {
                        debug!("unhandled event {}", t);
                    }
                }
            }
        }
    }
}
<commit_msg>add get_window_property fn<commit_after>extern crate libc;
use std::ptr;
use std::mem;
use std::slice::from_raw_parts;
use std::string::String;
use std::collections::HashMap;
use std::boxed::Box;
use x11::xlib;
use x11::keysym;

use super::config::Config;
use super::workspace::{ Workspace, Workspaces };
use super::handler;

fn get_text_property(display: *mut xlib::Display, window: xlib::Window, atom: xlib::Atom) -> Option<String>{
    unsafe{
        let mut prop: xlib::XTextProperty = mem::zeroed();
        let r = xlib::XGetTextProperty(display, window, &mut prop, atom);
        if r == 0 {
            None
        }else{
            let s = String::from_raw_parts(prop.value, prop.nitems as usize, prop.nitems as usize + 1 ).clone();
            let text = Some(s);
            xlib::XFree(prop.value as *mut libc::c_void);
            text
        }
    }
}

fn get_window_property(display: *mut xlib::Display, window: xlib::Window, atom: xlib::Atom) {
    unsafe {
        let mut actual_type_return: u64 = 0;
        let mut actual_format_return: i32 = 0;
        let mut nitem_return: libc::c_ulong = 0;
        let mut bytes_after_return: libc::c_ulong = 0;
        let mut prop_return: *mut libc::c_uchar = mem::zeroed();

        let r = xlib::XGetWindowProperty(display, window, xlib::XA_WM_NAME,
                                         0, 0xFFFFFFFF, 0, 0,
                                         &mut actual_type_return,
                                         &mut actual_format_return,
                                         &mut nitem_return,
                                         &mut bytes_after_return,
                                         &mut prop_return);

        debug!("result get wp {}", r);
        if r == 0 {

        }else{
            debug!("actual format return {}", actual_format_return);
            if actual_format_return == 0 {

            }
            else {
                // let s = from_raw_parts(prop_return as *const libc::c_ulong, nitems_return as usize).iter()
                //     .map(|&c| c as u64)
                //     .collect();
                let s = String::from_raw_parts(prop_return, nitem_return as usize, nitem_return as usize + 1 );
                println!("{}", s);

            }
        }
    }
}

pub struct WindowManager {
    pub display: *mut xlib::Display,
    pub screen_num: libc::c_int,
    pub root:    xlib::Window,

    pub workspaces: Workspaces,
    config: Config
}

impl WindowManager {
    pub fn new() -> WindowManager {
	unsafe {
	    let display = xlib::XOpenDisplay(ptr::null());
            if display == ptr::null_mut() {
                panic!("can't open display")
            }
	    let screen_num  = xlib::XDefaultScreen(display);
	    let root    = xlib::XRootWindow(display, screen_num);

	    let mut wm = WindowManager {
	        display: display,
                screen_num: screen_num,
	        root:    root,

                config: Config::load(),
                workspaces: Workspaces::new()
            };
            wm.workspaces.create_workspace('1');
            wm
	}
    }

    pub fn run(&mut self) {
        let mask = xlib::SubstructureRedirectMask | xlib::SubstructureNotifyMask;
        let keymask = xlib::KeyPressMask | xlib::KeyReleaseMask;
        unsafe{
            xlib::XSelectInput(self.display, self.root,
                               mask | keymask);
            xlib::XSync(self.display, 0);
        }

        loop {
            //handle events here
            let mut e = xlib::XEvent{
                pad: [0; 24],
            };

            unsafe {
                xlib::XNextEvent(self.display, &mut e);
                let t = e.get_type();
                match t {
                    xlib::CreateNotify => {
                        let event: xlib::XCreateWindowEvent = From::from(e);

                        if event.override_redirect != 0 {
                            continue;
                        }

                        // change attributes before display
                        let mut attrs: xlib::XSetWindowAttributes = mem::zeroed();
                        attrs.event_mask = xlib::KeyReleaseMask;
                        let valuemask = xlib::CWEventMask;
                        xlib::XChangeWindowAttributes(self.display, event.window, valuemask, &mut attrs);

                        // add to workspace
                        // let mut w = self.workspaces.get_mut(&'1');
                        // match w {
                        //     Some(workspace) => {
                        //         workspace.add(event.window);
                        //         workspace.config(self);
                        //     }
                        //     None => {}
                        // }

                        // get window property
                        let n = get_text_property(self.display, event.window, xlib::XA_WM_NAME);
                        match n {
                            Some(s) => {debug!("create window {} for {}", event.window, s);}
                            None => {}
                        }
                    }
                    xlib::DestroyNotify => {
                        debug!("destroy notify");
                        let event: xlib::XDestroyWindowEvent = From::from(e);
                    }
                    xlib::MapNotify => {
                        debug!("map notify");
                        let event: xlib::XMapEvent = From::from(e);
                        println!("event {}", event.event);
                        println!("w {}", event.window);
                    }
                    xlib::UnmapNotify => {
                        debug!("unmap notify");
                        let event: xlib::XUnmapEvent = From::from(e);
                        let workspace = self.workspaces.current_workspace();
                        match workspace.contain(event.window) {
                            Some(index) => {
                                workspace.remove(event.window);
                                workspace.config(self.display, self.screen_num);
                            }
                            None => {}
                        }
                    }
                    xlib::MapRequest => {
                        debug!("map request");
                        let event: xlib::XMapRequestEvent = From::from(e);
                        println!("w {}", event.window);
                        xlib::XMapWindow(self.display, event.window);

                        // add app top-level window to workspace
                        let mut attrs: xlib::XWindowAttributes = mem::zeroed();
                        xlib::XGetWindowAttributes(self.display, event.window, &mut attrs);

                        if attrs.override_redirect == 0{
                            debug!("top level window");
                            let mut workspace = self.workspaces.current_workspace();
                            if workspace.contain(event.window).is_none() {
                                workspace.add(event.window);
                                workspace.config(self.display, self.screen_num);
                            }
                        }

                    }
                    xlib::ClientMessage => {
                        debug!("client message");
                        // let event = cast_event::<xlib::XClientMessageEvent>(&e);
                        let event: xlib::XClientMessageEvent = From::from(e);
                    }
                    xlib::KeyRelease => {
                        debug!("key release");
                        let mut event: xlib::XKeyEvent = From::from(e);

                        if event.state > 0 {
                            let mut sym: xlib::KeySym = 0;
                            let status: *mut xlib::XComposeStatus = ptr::null_mut();
                            xlib::XLookupString(&mut event, ptr::null_mut(), 0, &mut sym, status);

                            let b = handler::KeyBind {
                                key: sym,
                                mask: event.state,
                            };
                            debug!("key {} {}", event.state, sym);
                            // let mut h: Box<handler::Handler>;
                            match self.config.bindsyms.get_mut(&b) {
                                Some(handler) => {
                                    handler.handle(&mut self.workspaces, self.display, self.screen_num);
                                }
                                None => {
                                    println!("no bind");
                                    continue;
                                }
                            }
                        }
                    }
                    xlib::ConfigureNotify => {
                        debug!("configure notify");
                    }
                    xlib::ConfigureRequest =>{
                        debug!("configure request");
                        // let mut change = xlib::XWindowChanges {
                        //     x: event.x,
                        //     y: event.y,
                        //     width: event.width,
                        //     height: event.height,
                        //     border_width: event.border_width,
                        //     sibling: event.above,
                        //     stack_mode: event.detail
                        // };
                        // debug!("config x: {}, y: {}, width: {}, height: {}",
                        //        change.x, change.y, change.width, change.height);
                        let mut event: xlib::XConfigureRequestEvent = From::from(e);
                        // xlib::XConfigureWindow(event.display, event.window, event.value_mask as u32, &mut change);

                    }
                    _ => {
                        debug!("unhandled event {}", t);
                    }
                }
            }
        }
    }
}
<|endoftext|>


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

use download;
use extract;
use verify;
use find_package;
use find_package::Package;

fn _install_package(package: &Package, path: &Path) -> Result<bool, String> {
    let mut download_path = PathBuf::new();
        download_path.push(path);
        download_path.push(format!("download/{}", package.name));

    if !download_path.exists() {
        download::download_file(&package.url, download_path.as_path())?;

        let target = match File::open(download_path.as_path()) {
            Ok(x) => x,
            Err(why) => return Err(format!("{}", why))
        };

        if verify::verify_file_crc32(&target) != package.crc32 {
            fs::remove_file(download_path.as_path())
                .ok()
                .expect(
                    &format!(
                        "Failed to remove file: {}",
                        download_path.as_path().to_str().unwrap_or("Invalid File")
                    )
                );
            return Err(String::from("The downloaded file is corrupted.\nwiz will delete the file now."))
        }
    }

    let mut tar_path = PathBuf::new();
        tar_path.push(path);
        tar_path.push(format!("download/{}.tar", package.name));

    if !tar_path.exists() {
        extract::extract_gz(download_path.as_path(), tar_path.as_path())?;
    }

    let mut install_path = PathBuf::new();
        tar_path.push(path);
        tar_path.push(format!("install/{}", package.name));

    if !install_path.exists() {
        extract::extract_tar(tar_path.as_path(), install_path.as_path())?;
    } else {
        return Ok(false)
    }

    return Ok(true)
}

pub fn install_package(name: &str, path: &Path) -> Result<bool, String> {
    let package = find_package::select_package(name, path)?;
    return Ok(_install_package(&package, path)?)
}
<commit_msg>Make it install dependencies, too.<commit_after>use std::fs;
use std::fs::File;
use std::path::{ Path, PathBuf };

use download;
use extract;
use verify;
use find_package;
use find_package::Package;

fn _install_package(package: &Package, path: &Path) -> Result<bool, String> {
    let mut download_path = PathBuf::new();
        download_path.push(path);
        download_path.push(format!("download/{}", package.name));

    if !download_path.exists() {
        download::download_file(&package.url, download_path.as_path())?;

        let target = match File::open(download_path.as_path()) {
            Ok(x) => x,
            Err(why) => return Err(format!("{}", why))
        };

        if verify::verify_file_crc32(&target) != package.crc32 {
            fs::remove_file(download_path.as_path())
                .ok()
                .expect(
                    &format!(
                        "Failed to remove file: {}",
                        download_path.as_path().to_str().unwrap_or("Invalid File")
                    )
                );
            return Err(String::from("The downloaded file is corrupted.\nwiz will delete the file now."))
        }
    }

    let mut tar_path = PathBuf::new();
        tar_path.push(path);
        tar_path.push(format!("download/{}.tar", package.name));

    if !tar_path.exists() {
        extract::extract_gz(download_path.as_path(), tar_path.as_path())?;
    }

    let mut install_path = PathBuf::new();
        tar_path.push(path);
        tar_path.push(format!("install/{}", package.name));

    if !install_path.exists() {
        extract::extract_tar(tar_path.as_path(), install_path.as_path())?;
    } else {
        return Ok(false)
    }

    return Ok(true)
}

pub fn install_package(name: &str, path: &Path) -> Result<bool, String> {
    let package = find_package::select_package(name, path).unwrap();
    for dep in package.dependencies {
        install_package(&dep.name, path)?;
    }
    return install_package(name, path)
}<|endoftext|>


<commit_before>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 Lumol's contributors — BSD license

use sys::System;

use sim::Propagator;
use sim::TemperatureStrategy;
use out::Output;

/// Writing an output at a given frequency
struct OutputFrequency {
    /// The output to use
    output: Box<Output>,
    /// The frequency. `output` will be used every time the system step matches
    /// this frequency.
    frequency: u64,
}

impl OutputFrequency {
    pub fn new(output: Box<Output>) -> OutputFrequency {
        OutputFrequency{
            frequency: 1,
            output: output,
        }
    }

    pub fn with_frequency(output: Box<Output>, frequency: u64) -> OutputFrequency {
        OutputFrequency{
            frequency: frequency,
            output: output,
        }
    }
}

impl Output for OutputFrequency {
    fn setup(&mut self, system: &System) {
        self.output.setup(system);
    }

    fn write(&mut self, system: &System) {
        if system.step() % self.frequency == 0 {
            self.output.write(system);
        }
    }

    fn finish(&mut self, system: &System) {
        self.output.finish(system);
    }
}

/// The Simulation struct holds all the needed algorithms for running the
/// simulation. It should be use together with a `System` to perform the
/// simulation.
pub struct Simulation {
    propagator: Box<Propagator>,
    outputs: Vec<OutputFrequency>
}

impl Simulation {
    /// Create a new Simulation from a Propagator.
    pub fn new(propagator: Box<Propagator>) -> Simulation {
        Simulation {
            propagator: propagator,
            outputs: Vec::new(),
        }
    }

    /// Run the simulation on System for `nsteps` steps.
    pub fn run(&mut self, system: &mut System, nsteps: usize) {
        match self.propagator.temperature_strategy() {
            TemperatureStrategy::External(temperature) => {
                system.external_temperature(Some(temperature))
            }
            TemperatureStrategy::Velocities => system.external_temperature(None),
            TemperatureStrategy::None => {}
        }

        self.setup(system);
        for _ in 0..nsteps {
            self.propagator.propagate(system);
            system.increment_step();
            for output in &mut self.outputs {
                output.write(system);
            }
        }
        self.finish(system);
    }

    /// Add a new `Output` algorithm in the outputs list
    pub fn add_output(&mut self, output: Box<Output>) {
        self.outputs.push(OutputFrequency::new(output));
    }

    /// Add a new `Output` algorithm in the outputs list, which will be used
    /// at the given frequency. The output will be used every time the system
    /// step matches this frequency.
    pub fn add_output_with_frequency(&mut self, output: Box<Output>, frequency: u64) {
        self.outputs.push(OutputFrequency::with_frequency(output, frequency));
    }

    fn setup(&mut self, system: &mut System) {
        self.propagator.setup(system);
        for output in &mut self.outputs {
            output.setup(system);
        }
    }

    fn finish(&mut self, system: &mut System) {
        self.propagator.finish(system);
        for output in &mut self.outputs {
            output.finish(system);
        }
    }
}
<commit_msg>Add a sanity check for positions and velocities in the system<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 Lumol's contributors — BSD license

use sys::System;
use types::Vector3D;

use sim::Propagator;
use sim::TemperatureStrategy;
use out::Output;

/// Writing an output at a given frequency
struct OutputFrequency {
    /// The output to use
    output: Box<Output>,
    /// The frequency. `output` will be used every time the system step matches
    /// this frequency.
    frequency: u64,
}

impl OutputFrequency {
    pub fn new(output: Box<Output>) -> OutputFrequency {
        OutputFrequency{
            frequency: 1,
            output: output,
        }
    }

    pub fn with_frequency(output: Box<Output>, frequency: u64) -> OutputFrequency {
        OutputFrequency{
            frequency: frequency,
            output: output,
        }
    }
}

impl Output for OutputFrequency {
    fn setup(&mut self, system: &System) {
        self.output.setup(system);
    }

    fn write(&mut self, system: &System) {
        if system.step() % self.frequency == 0 {
            self.output.write(system);
        }
    }

    fn finish(&mut self, system: &System) {
        self.output.finish(system);
    }
}

/// The Simulation struct holds all the needed algorithms for running the
/// simulation. It should be use together with a `System` to perform the
/// simulation.
pub struct Simulation {
    propagator: Box<Propagator>,
    outputs: Vec<OutputFrequency>
}

impl Simulation {
    /// Create a new Simulation from a Propagator.
    pub fn new(propagator: Box<Propagator>) -> Simulation {
        Simulation {
            propagator: propagator,
            outputs: Vec::new(),
        }
    }

    /// Run the simulation on System for `nsteps` steps.
    pub fn run(&mut self, system: &mut System, nsteps: usize) {
        match self.propagator.temperature_strategy() {
            TemperatureStrategy::External(temperature) => {
                system.external_temperature(Some(temperature))
            }
            TemperatureStrategy::Velocities => system.external_temperature(None),
            TemperatureStrategy::None => {}
        }

        self.setup(system);
        for i in 0..nsteps {
            self.propagator.propagate(system);
            system.increment_step();
            for output in &mut self.outputs {
                output.write(system);
            }

            if i % 10000 == 0 {
                self.sanity_check(system);
            }
        }
        self.finish(system);
    }

    /// Add a new `Output` algorithm in the outputs list
    pub fn add_output(&mut self, output: Box<Output>) {
        self.outputs.push(OutputFrequency::new(output));
    }

    /// Add a new `Output` algorithm in the outputs list, which will be used
    /// at the given frequency. The output will be used every time the system
    /// step matches this frequency.
    pub fn add_output_with_frequency(&mut self, output: Box<Output>, frequency: u64) {
        self.outputs.push(OutputFrequency::with_frequency(output, frequency));
    }

    fn setup(&mut self, system: &mut System) {
        self.propagator.setup(system);
        for output in &mut self.outputs {
            output.setup(system);
        }
    }

    fn finish(&mut self, system: &mut System) {
        self.propagator.finish(system);
        for output in &mut self.outputs {
            output.finish(system);
        }
    }

    /// Perform some sanity checks on the system
    fn sanity_check(&self, system: &System) {
        for particle in system {
            // The value of 1e6 A should be a good enough threshold. Even with
            // big boxes (100 A), and going through the boxes multiple time,
            // the particles positions should stay bellow this point.
            if any(&particle.position, |x| x.abs() > 1e6) {
                warn!(
                    "Some particles have moved very far from the origin, \
                    the simulation might be exploding"
                );
                // we don't want to spam the output, so we return early if a
                // problem was found
                return;
            }

            // Velocity threshold is 1000 A / fs
            if any(&particle.velocity, |x| x.abs() > 1000.0) {
                warn!(
                    "Some particles have a very high velocity, \
                    the simulation might be exploding"
                );
                return;
            }
        }
    }
}

fn any<F: Fn(f64) -> bool>(vector: &Vector3D, function: F) -> bool {
    function(vector[0]) || function(vector[1]) || function(vector[2])
}
<|endoftext|>


<commit_before>use calx::{V2, color, Anchor};
use calx::backend::{Key, Event};
use calx::backend::{Canvas, CanvasUtil, Fonter, Align};
use tilecache;
use {Screen, ScreenAction};
use gamescreen::GameScreen;

pub struct TitleScreen;

impl TitleScreen {
    pub fn new() -> TitleScreen {
        TitleScreen
    }
}

impl Screen for TitleScreen {
    fn update(&mut self, ctx: &mut Canvas) -> Option<ScreenAction> {
        ctx.draw_image(tilecache::get(tilecache::LOGO),
                       V2(274.0, 180.0),
                       0.0,
                       color::FIREBRICK,
                       color::BLACK);
        Fonter::new(ctx)
            .color(color::DARKRED)
            .anchor(Anchor::Bottom)
            .align(Align::Center)
            .text(format!("Copyright (C) Risto Saarelma 2011 - 2016\nv{}{}",
                          ::version(),
                          if cfg!(debug_assertions) {
                              " debug"
                          } else {
                              ""
                          }))
            .draw(V2(320.0, 352.0));

        for event in ctx.events().into_iter() {
            match event {
                Event::KeyPress(Key::Escape) => {
                    return Some(ScreenAction::Quit);
                }
                Event::Quit => {
                    return Some(ScreenAction::Quit);
                }
                Event::KeyPress(Key::F12) => {
                    ctx.save_screenshot(&"magog");
                }
                Event::KeyPress(_) => {
                    return Some(ScreenAction::Change(Box::new(GameScreen::new())));
                }
                _ => (),
            }
        }

        None
    }
}
<commit_msg>WIP expunge tilecache<commit_after>use calx::{V2, color, Anchor};
use calx::backend::{Key, Event};
use calx::backend::{Canvas, CanvasUtil, Fonter, Align};
use content::Brush;
use {Screen, ScreenAction};
use gamescreen::GameScreen;

pub struct TitleScreen;

impl TitleScreen {
    pub fn new() -> TitleScreen {
        TitleScreen
    }
}

impl Screen for TitleScreen {
    fn update(&mut self, ctx: &mut Canvas) -> Option<ScreenAction> {
        ctx.draw_image(Brush::Logo.get(0),
                       V2(274.0, 180.0),
                       0.0,
                       color::FIREBRICK,
                       color::BLACK);
        Fonter::new(ctx)
            .color(color::DARKRED)
            .anchor(Anchor::Bottom)
            .align(Align::Center)
            .text(format!("Copyright (C) Risto Saarelma 2011 - 2016\nv{}{}",
                          ::version(),
                          if cfg!(debug_assertions) {
                              " debug"
                          } else {
                              ""
                          }))
            .draw(V2(320.0, 352.0));

        for event in ctx.events().into_iter() {
            match event {
                Event::KeyPress(Key::Escape) => {
                    return Some(ScreenAction::Quit);
                }
                Event::Quit => {
                    return Some(ScreenAction::Quit);
                }
                Event::KeyPress(Key::F12) => {
                    ctx.save_screenshot(&"magog");
                }
                Event::KeyPress(_) => {
                    return Some(ScreenAction::Change(Box::new(GameScreen::new())));
                }
                _ => (),
            }
        }

        None
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![license = "MIT/ASL2"]
#![crate_id = "github.com/DaGenix/rust-crypto#rust-crypto:0.1"]

#![feature(asm)]
#![feature(macro_rules)]
#![feature(simd)]

extern crate serialize;

pub mod aes;
pub mod aesni;
pub mod aessafe;
pub mod bcrypt;
pub mod bcrypt_pbkdf;
pub mod blockmodes;
pub mod blowfish;
pub mod buffer;
pub mod chacha20;
mod cryptoutil;
pub mod digest;
pub mod hmac;
pub mod mac;
pub mod md5;
pub mod pbkdf2;
pub mod poly1305;
pub mod rc4;
pub mod salsa20;
pub mod scrypt;
pub mod sha1;
pub mod sha2;
pub mod symmetriccipher;
pub mod util;
<commit_msg>make 'cargo test' work<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![license = "MIT/ASL2"]
#![crate_id = "github.com/DaGenix/rust-crypto#rust-crypto:0.1"]

#![feature(asm)]
#![feature(macro_rules)]
#![feature(simd)]

extern crate serialize;
#[cfg(test)] extern crate test;

pub mod aes;
pub mod aesni;
pub mod aessafe;
pub mod bcrypt;
pub mod bcrypt_pbkdf;
pub mod blockmodes;
pub mod blowfish;
pub mod buffer;
pub mod chacha20;
mod cryptoutil;
pub mod digest;
pub mod hmac;
pub mod mac;
pub mod md5;
pub mod pbkdf2;
pub mod poly1305;
pub mod rc4;
pub mod salsa20;
pub mod scrypt;
pub mod sha1;
pub mod sha2;
pub mod symmetriccipher;
pub mod util;
<|endoftext|>


<commit_before>extern crate core;
extern crate libc;
extern crate minifb;
extern crate prodbg_api;
extern crate bgfx_rs;
extern crate imgui_sys;

pub mod windows;
pub mod menu;

use bgfx_rs::Bgfx;
use core::session::Sessions;
use windows::Windows;
use core::{DynamicReload, Search};
use core::view_plugins::{ViewPlugins};
use core::backend_plugin::{BackendPlugins};
use std::cell::RefCell;
use std::rc::Rc;

use core::plugins::*;

fn main() {
    let bgfx = Bgfx::new();
    let mut sessions = Sessions::new();
    let mut windows = Windows::new();

    let mut lib_handler = DynamicReload::new(None, Some("t2-output"), Search::Backwards);
    let mut plugins = Plugins::new();

    let view_plugins = Rc::new(RefCell::new(ViewPlugins::new()));
    let backend_plugins = Rc::new(RefCell::new(BackendPlugins::new()));

    let _ = sessions.create_instance();

    plugins.add_handler(&view_plugins);
    plugins.add_handler(&backend_plugins);

    plugins.add_plugin(&mut lib_handler, "dummy_backend_plugin");
    plugins.add_plugin(&mut lib_handler, "amiga_uae_plugin");
    plugins.add_plugin(&mut lib_handler, "bitmap_memory");
    plugins.add_plugin(&mut lib_handler, "registers_plugin");
    plugins.add_plugin(&mut lib_handler, "hex_memory_plugin");

    windows.create_default();

    loop {
        bgfx.pre_update();

        plugins.update(&mut lib_handler);
        sessions.update(&mut backend_plugins.borrow_mut());
        windows.update(&mut sessions, &mut view_plugins.borrow_mut(), &mut backend_plugins.borrow_mut());

        if windows.should_exit() {
            break;
        }

        bgfx.post_update();
    }
}

// dummy
#[no_mangle]
pub fn init_plugin() {
}
<commit_msg>Load disassembly plugin<commit_after>extern crate core;
extern crate libc;
extern crate minifb;
extern crate prodbg_api;
extern crate bgfx_rs;
extern crate imgui_sys;

pub mod windows;
pub mod menu;

use bgfx_rs::Bgfx;
use core::session::Sessions;
use windows::Windows;
use core::{DynamicReload, Search};
use core::view_plugins::{ViewPlugins};
use core::backend_plugin::{BackendPlugins};
use std::cell::RefCell;
use std::rc::Rc;

use core::plugins::*;

fn main() {
    let bgfx = Bgfx::new();
    let mut sessions = Sessions::new();
    let mut windows = Windows::new();

    let mut lib_handler = DynamicReload::new(None, Some("t2-output"), Search::Backwards);
    let mut plugins = Plugins::new();

    let view_plugins = Rc::new(RefCell::new(ViewPlugins::new()));
    let backend_plugins = Rc::new(RefCell::new(BackendPlugins::new()));

    let _ = sessions.create_instance();

    plugins.add_handler(&view_plugins);
    plugins.add_handler(&backend_plugins);

    plugins.add_plugin(&mut lib_handler, "dummy_backend_plugin");
    plugins.add_plugin(&mut lib_handler, "amiga_uae_plugin");
    plugins.add_plugin(&mut lib_handler, "bitmap_memory");
    plugins.add_plugin(&mut lib_handler, "registers_plugin");
    plugins.add_plugin(&mut lib_handler, "disassembly_plugin");
    plugins.add_plugin(&mut lib_handler, "hex_memory_plugin");

    windows.create_default();

    loop {
        bgfx.pre_update();

        plugins.update(&mut lib_handler);
        sessions.update(&mut backend_plugins.borrow_mut());
        windows.update(&mut sessions, &mut view_plugins.borrow_mut(), &mut backend_plugins.borrow_mut());

        if windows.should_exit() {
            break;
        }

        bgfx.post_update();
    }
}

// dummy
#[no_mangle]
pub fn init_plugin() {
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>uncommited stuff<commit_after>fn requestSomething() {
  let client = Client::new();
  let respose = client.get("www.google.com").send().unwrap();
  if res.status == hyper::Ok {
    println!("success")
  }
}
<|endoftext|>


<commit_before>use unicode_width::{UnicodeWidthStr,UnicodeWidthChar};
use super::Renderer;
use std::mem;

/// State corresponding to a partially constructed line.
struct PartialLine {
    text: String,
    /// The width in character cells of the text, or
    /// current position.
    pos: usize,
}

impl PartialLine {
    pub fn new() -> PartialLine {
        PartialLine {
            text: String::new(),
            pos: 0,
        }
    }
}

/// A renderer which just outputs plain text.
pub struct TextRenderer {
    width: usize,
    lines: Vec<String>,
    /// True at the end of a block, meaning we should add
    /// a blank line if any other text is added.
    at_block_end: bool,
    partial_line: Option<PartialLine>,
    /// Set to true when adding text (eg markup) that doesn't require
    /// a space before the next word.
    no_space_needed: bool,
    links: Vec<String>,
}

impl TextRenderer {
    /// Construct a new empty TextRenderer.
    pub fn new(width: usize) -> TextRenderer {
        html_trace!("new({})", width);
        TextRenderer {
            width: width,
            lines: Vec::new(),
            at_block_end: false,
            partial_line: None,
            links: Vec::new(),
            no_space_needed: false,
        }
    }

    /// Take the partial line out of self, or create one
    /// if there wasn't one.
    fn take_partial_line(&mut self) -> PartialLine {
        if let Some(p) = self.partial_line.take() {
            p
        } else {
            PartialLine::new()
        }
    }

    pub fn add_subblock(&mut self, s: &str) {
        html_trace!("add_subblock({}, {})", self.width, s);
        self.lines.extend(s.lines().map(|l| l.into()));
    }

    fn push_line(&mut self, s: String) {
        self.lines.push(s);
    }
    fn flush_line(&mut self) {
        if let Some(s) = self.partial_line.take() {
            if s.text.len() > 0 {
                self.push_line(s.text);
            }
        }
    }

    pub fn into_string(self) -> String {
        let mut result = String::new();
        for s in self.into_lines() {
            result.push_str(&s);
            result.push('\n');
        }
        html_trace!("into_string({}, {:?})", self.width, result);
        result
    }

    fn into_lines(mut self) -> Vec<String> {
        self.flush_line();
        // And add the links
        if self.links.len() > 0 {
            self.start_block();
            for (idx, target) in self.links.drain((0..)).enumerate() {
                /* Hard wrap */
                let mut output = String::new();
                let mut pos = 0;
                for c in format!("[{}] {}", idx+1, target).chars() {
                    let c_width = UnicodeWidthChar::width(c).unwrap();
                    if pos + c_width > self.width {
                        let mut tmp_s = String::new();
                        mem::swap(&mut output, &mut tmp_s);
                        self.lines.push(tmp_s);
                        output.push(c);
                        pos = c_width;
                    } else {
                        output.push(c);
                        pos += c_width;
                    }
                }
                self.lines.push(output);
            }
        }
        self.lines
    }
}

impl Renderer for TextRenderer {
    type Sub = TextRenderer;

    fn add_empty_line(&mut self) {
        html_trace!("add_empty_line()");
        self.flush_line();
        self.lines.push("".into());
        html_trace_quiet!("add_empty_line: at_block_end <- false");
        self.at_block_end = false;
        html_trace_quiet!("add_empty_line: new lines: {:?}", self.lines);
    }

    fn new_sub_renderer(&self, width: usize) -> Self::Sub {
        TextRenderer::new(width)
    }

    fn start_block(&mut self) {
        html_trace!("start_block({})", self.width);
        self.flush_line();
        if self.lines.len() > 0 {
            self.add_empty_line();
        }
        html_trace_quiet!("start_block; at_block_end <- false");
        self.at_block_end = false;
    }

    fn add_preformatted_block(&mut self, text: &str) {
        html_trace!("add_block({}, {})", self.width, text);
        self.start_block();
        self.add_subblock(text);
        html_trace_quiet!("add_block: at_block_end <- true");
        self.at_block_end = true;
    }

    fn end_block(&mut self) {
        self.at_block_end = true;
    }

    fn add_inline_text(&mut self, text: &str) {
        html_trace!("add_inline_text({}, {})", self.width, text);
        let mut partial = self.take_partial_line();
        for word in text.split_whitespace() {
            let mut need_space = (partial.pos > 0) && !(self.no_space_needed);
            let space_space = if need_space { 1 } else { 0 };
            // We've used up the "no space needed" condition now.
            self.no_space_needed = false;
            if self.width <= (partial.pos + space_space) {
                self.push_line(partial.text);
                partial = self.take_partial_line();
                need_space = false;
            }
            let space_left = self.width - partial.pos - space_space;
            let word_width = UnicodeWidthStr::width(word);
            if word_width <= space_left {
                /* It fits; no problem.  Add a space if not at the
                 * start of line.*/
                if need_space {
                    partial.text.push(' ');
                    partial.pos += 1;
                }
                partial.text.push_str(word);
                partial.pos += word_width;
                continue;
            }

            /* It doesn't fit.  If we're not at the start of the line,
             * then go to a new line. */
            if partial.pos > 0 {
                self.push_line(partial.text);
                partial = self.take_partial_line();
            }

            /* We're now at the start of a line. */
            if word_width > self.width {
                /* It doesn't fit at all on the line, so break it. */
                for c in word.chars() {
                    let c_width = UnicodeWidthChar::width(c).unwrap();
                    if c_width + partial.pos > self.width {
                        /* Break here */
                        self.push_line(partial.text);
                        partial = self.take_partial_line();
                    }
                    /* This might happen with really narrow spaces... */
                    assert!(c_width <= self.width);

                    partial.text.push(c);
                    partial.pos += c_width;
                }
            } else {
                partial.text.push_str(word);
                partial.pos += word_width;
            }
        }
        self.partial_line = Some(partial);
    }

    fn width(&self) -> usize {
        self.width
    }

    fn add_block_line(&mut self, line: &str)
    {
        self.add_subblock(line);
    }

    fn append_subrender<'a, I>(&mut self, other: Self::Sub,
                               prefixes: I)
                           where I:Iterator<Item=&'a str>
    {
        self.flush_line();
        self.lines.extend(other.into_lines()
                               .into_iter()
                               .zip(prefixes)
                               .map(|(line, prefix)| prefix.to_string() + &line));
    }

    fn append_columns<I>(&mut self, cols: I, separator: char)
                           where I:IntoIterator<Item=Self::Sub> {
        self.flush_line();

        let line_sets = cols.into_iter()
                            .map(|sub_r| {
                                let width = sub_r.width;
                                (width, sub_r.into_lines()
                                             .into_iter()
                                             .map(|line| format!("{: <width$}", line, width=width))
                                             .collect())
                                 })
                            .collect::<Vec<(usize, Vec<String>)>>();

        let cell_height = line_sets.iter()
                                   .map(|&(_, ref v)| v.len())
                                   .max().unwrap_or(0);
        let spaces:String = (0..self.width).map(|_| ' ').collect();
        for i in 0..cell_height {
            let mut line = String::new();
            for (cellno, &(width, ref ls)) in line_sets.iter().enumerate() {
                let piece = ls.get(i).map(|s| s.as_str()).unwrap_or(&spaces[0..width]);
                line.push_str(piece);
                if cellno != line_sets.len()-1 {
                    line.push(separator)
                }
            }
            self.add_block_line(&line);
        }
    }

    fn empty(&self) -> bool {
        self.lines.len() == 0 && self.partial_line.is_none()
    }

    fn text_len(&self) -> usize {
        let mut result = 0;
        for line in &self.lines {
            result += UnicodeWidthStr::width(line.as_str());
        }
        if let Some(ref line) = self.partial_line {
            result += line.pos;
        }
        result
    }

    fn start_link(&mut self, target: &str)
    {
        self.links.push(target.to_string());
        self.add_inline_text("[");
        self.no_space_needed = true;
    }
    fn end_link(&mut self)
    {
        let idx = self.links.len();
        self.no_space_needed = true;
        self.add_inline_text(&format!("][{}]", idx));
    }
}<commit_msg>Mostly working refactoring of the text wrapping.<commit_after>use unicode_width::{UnicodeWidthStr,UnicodeWidthChar};
use super::Renderer;
use std::mem;
use std::fmt::Debug;

/// A wrapper around a String with extra metadata.
#[derive(Debug)]
struct TaggedString<T:Debug> {
    s: String,
    tag: T,
}

/// A type to build up wrapped text, allowing extra metadata for
/// spans.
#[derive(Debug)]
struct WrappedBlock<T:Clone+Eq+Debug> {
    width: usize,
    text: Vec<Vec<TaggedString<T>>>,
    textlen: usize,
    line: Vec<TaggedString<T>>,
    linelen: usize,
    spacetag: Option<T>,         // Tag for the whitespace before the current word
    word: Vec<TaggedString<T>>,  // The current word (with no whitespace).
    wordlen: usize,
}

impl<T:Clone+Eq+Debug> WrappedBlock<T> {
    pub fn new(width: usize) -> WrappedBlock<T> {
        WrappedBlock {
            width: width,
            text: Vec::new(),
            textlen: 0,
            line: Vec::new(),
            linelen: 0,
            spacetag: None,
            word: Vec::new(),
            wordlen: 0,
        }
    }

    fn flush_word(&mut self) {
        /* Finish the word. */
        if self.word.len() > 0 {
            let space_in_line = self.width - self.linelen
                        - if self.linelen > 0 { 1 } else { 0 }; // space
            if self.wordlen <= space_in_line {
                if self.linelen > 0 {
                    self.line.push(TaggedString{s: " ".into(), tag: self.spacetag.take().unwrap()});
                    self.linelen += 1;
                }
                self.line.extend(self.word.drain(..));
                self.linelen += self.wordlen;
                self.wordlen = 0;
            } else {
                unimplemented!()
            }
        }
    }

    fn flush(&mut self) {
        self.flush_word();
        if self.line.len() > 0 {
            let mut tmp_line = Vec::new();
            mem::swap(&mut tmp_line, &mut self.line);
            self.text.push(tmp_line);
        }
    }

    /// Consume self and return a vector of lines.
    pub fn into_untagged_lines(mut self) -> Vec<String> {
        self.flush();

        let mut result = Vec::new();
        for line in self.text.into_iter() {
            let mut line_s = String::new();
            for TaggedString{ s, .. } in line.into_iter() {
                line_s.push_str(&s);
            }
            result.push(line_s);
        }
        result
    }

    pub fn add_text(&mut self, text: &str, tag: T) {
        for c in text.chars() {
            if c.is_whitespace() {
                /* Whitespace is mostly ignored, except to terminate words. */
                self.flush_word();
                self.spacetag = Some(tag.clone());
            } else {
                /* Not whitespace; add to the current word. */
                if self.word.len() > 0 && self.word[self.word.len()-1].tag == tag {
                    /* Just add a character to the last piece */
                    let last_idx = self.word.len() - 1;
                    self.word[last_idx].s.push(c);
                } else {
                    /* Starting a new word; easy. */
                    let mut s = String::new();
                    s.push(c);
                    self.word.push(TaggedString{ s: s, tag: tag.clone()});
                }
                self.wordlen += UnicodeWidthChar::width(c).unwrap();
            }
        }
    }

    pub fn text_len(&self) -> usize {
        self.textlen + self.linelen + self.wordlen
    }
}

/// A renderer which just outputs plain text.
pub struct TextRenderer {
    width: usize,
    lines: Vec<String>,
    /// True at the end of a block, meaning we should add
    /// a blank line if any other text is added.
    at_block_end: bool,
    links: Vec<String>,
    wrapping: Option<WrappedBlock<()>>,
}

impl TextRenderer {
    /// Construct a new empty TextRenderer.
    pub fn new(width: usize) -> TextRenderer {
        html_trace!("new({})", width);
        TextRenderer {
            width: width,
            lines: Vec::new(),
            at_block_end: false,
            links: Vec::new(),
            wrapping: None,
        }
    }

    /// Get the current line wrapping context (and create if
    /// needed).
    fn current_text(&mut self) -> &mut WrappedBlock<()> {
        if self.wrapping.is_none() {
            self.wrapping = Some(WrappedBlock::new(self.width));
        }
        self.wrapping.as_mut().unwrap()
    }

    pub fn add_subblock(&mut self, s: &str) {
        html_trace!("add_subblock({}, {})", self.width, s);
        self.lines.extend(s.lines().map(|l| l.into()));
    }

    fn flush_wrapping(&mut self) {
        if let Some(w) = self.wrapping.take() {
            self.lines.extend(w.into_untagged_lines())
        }
    }

    pub fn into_string(self) -> String {
        let mut result = String::new();
        for s in self.into_lines() {
            result.push_str(&s);
            result.push('\n');
        }
        html_trace!("into_string({}, {:?})", self.width, result);
        result
    }

    fn into_lines(mut self) -> Vec<String> {
        self.flush_wrapping();
        // And add the links
        if self.links.len() > 0 {
            self.start_block();
            for (idx, target) in self.links.drain((0..)).enumerate() {
                /* Hard wrap */
                let mut output = String::new();
                let mut pos = 0;
                for c in format!("[{}] {}", idx+1, target).chars() {
                    let c_width = UnicodeWidthChar::width(c).unwrap();
                    if pos + c_width > self.width {
                        let mut tmp_s = String::new();
                        mem::swap(&mut output, &mut tmp_s);
                        self.lines.push(tmp_s);
                        output.push(c);
                        pos = c_width;
                    } else {
                        output.push(c);
                        pos += c_width;
                    }
                }
                self.lines.push(output);
            }
        }
        self.lines
    }
}

impl Renderer for TextRenderer {
    type Sub = TextRenderer;

    fn add_empty_line(&mut self) {
        html_trace!("add_empty_line()");
        self.flush_wrapping();
        self.lines.push("".into());
        html_trace_quiet!("add_empty_line: at_block_end <- false");
        self.at_block_end = false;
        html_trace_quiet!("add_empty_line: new lines: {:?}", self.lines);
    }

    fn new_sub_renderer(&self, width: usize) -> Self::Sub {
        TextRenderer::new(width)
    }

    fn start_block(&mut self) {
        html_trace!("start_block({})", self.width);
        self.flush_wrapping();
        if self.lines.len() > 0 {
            self.add_empty_line();
        }
        html_trace_quiet!("start_block; at_block_end <- false");
        self.at_block_end = false;
    }

    fn add_preformatted_block(&mut self, text: &str) {
        html_trace!("add_block({}, {})", self.width, text);
        self.start_block();
        self.add_subblock(text);
        html_trace_quiet!("add_block: at_block_end <- true");
        self.at_block_end = true;
    }

    fn end_block(&mut self) {
        self.at_block_end = true;
    }

    fn add_inline_text(&mut self, text: &str) {
        html_trace!("add_inline_text({}, {})", self.width, text);
        let mut partial = self.current_text();
        partial.add_text(text, ());
    }

    fn width(&self) -> usize {
        self.width
    }

    fn add_block_line(&mut self, line: &str)
    {
        self.add_subblock(line);
    }

    fn append_subrender<'a, I>(&mut self, other: Self::Sub,
                               prefixes: I)
                           where I:Iterator<Item=&'a str>
    {
        self.flush_wrapping();
        self.lines.extend(other.into_lines()
                               .into_iter()
                               .zip(prefixes)
                               .map(|(line, prefix)| prefix.to_string() + &line));
    }

    fn append_columns<I>(&mut self, cols: I, separator: char)
                           where I:IntoIterator<Item=Self::Sub> {
        self.flush_wrapping();

        let line_sets = cols.into_iter()
                            .map(|sub_r| {
                                let width = sub_r.width;
                                (width, sub_r.into_lines()
                                             .into_iter()
                                             .map(|line| format!("{: <width$}", line, width=width))
                                             .collect())
                                 })
                            .collect::<Vec<(usize, Vec<String>)>>();

        let cell_height = line_sets.iter()
                                   .map(|&(_, ref v)| v.len())
                                   .max().unwrap_or(0);
        let spaces:String = (0..self.width).map(|_| ' ').collect();
        for i in 0..cell_height {
            let mut line = String::new();
            for (cellno, &(width, ref ls)) in line_sets.iter().enumerate() {
                let piece = ls.get(i).map(|s| s.as_str()).unwrap_or(&spaces[0..width]);
                line.push_str(piece);
                if cellno != line_sets.len()-1 {
                    line.push(separator)
                }
            }
            self.add_block_line(&line);
        }
    }

    fn empty(&self) -> bool {
        self.lines.len() == 0 && self.wrapping.is_none()
    }

    fn text_len(&self) -> usize {
        let mut result = 0;
        for line in &self.lines {
            result += UnicodeWidthStr::width(line.as_str());
        }
        if let Some(ref w) = self.wrapping {
            result += w.text_len();
        }
        result
    }

    fn start_link(&mut self, target: &str)
    {
        self.links.push(target.to_string());
        self.add_inline_text("[");
    }
    fn end_link(&mut self)
    {
        let idx = self.links.len();
        self.add_inline_text(&format!("][{}]", idx));
    }
}<|endoftext|>