<commit_before>use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;
use std::fs::File as FSFile;
use std::fs::create_dir_all;
use std::fs::remove_file;
use std::io::Read;
use std::io::Write;
use std::vec::IntoIter;

use glob::glob;
use glob::Paths;

use storage::file::File;
use storage::file_id::*;
use storage::parser::{FileHeaderParser, Parser, ParserError};

use module::Module;
use runtime::Runtime;

pub type BackendOperationResult<T = ()> = Result<T, StorageBackendError>;

pub struct StorageBackend {
    basepath: String,
    storepath: String,
}

impl StorageBackend {

    pub fn new(rt: &Runtime) -> BackendOperationResult<StorageBackend> {
        let storepath = rt.get_rtp() + "/store/";
        debug!("Trying to create {}", storepath);
        create_dir_all(&storepath).and_then(|_| {
            debug!("Creating succeeded, constructing backend instance");
            Ok(StorageBackend {
                basepath: rt.get_rtp(),
                storepath: storepath.clone(),
            })
        }).or_else(|e| {
            debug!("Creating failed, constructing error instance");
            let mut serr = StorageBackendError::build(
                "create_dir_all()",
                "Could not create store directories",
                Some(storepath)
            );
            serr.caused_by = Some(Box::new(e));
            Err(serr)
        })
    }

    fn build<M: Module>(rt: &Runtime, m: &M) -> StorageBackend {
        let path = rt.get_rtp() + m.name() + "/store";
        // TODO: Don't use "/store" but value from configuration
        debug!("Building StorageBackend for {}", path);
        StorageBackend::new(path)
    }

    fn get_file_ids(&self, m: &Module) -> Option<Vec<FileID>> {
        let list = glob(&self.prefix_of_files_for_module(m)[..]);

        if let Ok(globlist) = list {
            let mut v = vec![];
            for entry in globlist {
                if let Ok(path) = entry {
                    debug!(" - File: {:?}", path);
                    v.push(from_pathbuf(&path));
                } else {
                    // Entry is not a path
                }
            }

            Some(v)
        } else {
            None
        }
    }

    pub fn iter_ids(&self, m: &Module) -> Option<IntoIter<FileID>>
    {
        glob(&self.prefix_of_files_for_module(m)[..]).and_then(|globlist| {
            let v = globlist.filter_map(Result::ok)
                            .map(|pbuf| from_pathbuf(&pbuf))
                            .collect::<Vec<FileID>>()
                            .into_iter();
            Ok(v)
        }).ok()
    }

    pub fn iter_files<'a, HP>(&self, m: &'a Module, p: &Parser<HP>)
        -> Option<IntoIter<File<'a>>>
        where HP: FileHeaderParser
    {
        self.iter_ids(m).and_then(|ids| {
            Some(ids.filter_map(|id| self.get_file_by_id(m, &id, p))
                    .collect::<Vec<File>>()
                    .into_iter())
        })
    }

    /*
     * Write a file to disk.
     *
     * The file is moved to this function as the file won't be edited afterwards
     */
    pub fn put_file<HP>(&self, f: File, p: &Parser<HP>) -> BackendOperationResult
        where HP: FileHeaderParser
    {
        let written = write_with_parser(&f, p);
        if written.is_err() { return Err(written.err().unwrap()); }
        let string = written.unwrap();

        let path = self.build_filepath(&f);
        debug!("Writing file: {}", path);
        debug!("      string: {}", string);

        FSFile::create(&path).map(|mut file| {
            debug!("Created file at '{}'", path);
            file.write_all(&string.clone().into_bytes())
                .map_err(|ioerr| {
                    debug!("Could not write file");
                    let mut err = StorageBackendError::build(
                            "File::write_all()",
                            "Could not write out File contents",
                            None
                        );
                    err.caused_by = Some(Box::new(ioerr));
                    err
                })
        }).map_err(|writeerr| {
            debug!("Could not create file at '{}'", path);
            let mut err = StorageBackendError::build(
                "File::create()",
                "Creating file on disk failed",
                None
            );
            err.caused_by = Some(Box::new(writeerr));
            err
        }).and(Ok(()))
    }

    /*
     * Update a file. We have the UUID and can find the file on FS with it and
     * then replace its contents with the contents of the passed file object
     */
    pub fn update_file<HP>(&self, f: File, p: &Parser<HP>) -> BackendOperationResult
        where HP: FileHeaderParser
    {
        let contents = write_with_parser(&f, p);
        if contents.is_err() { return Err(contents.err().unwrap()); }
        let string = contents.unwrap();

        let path = self.build_filepath(&f);
        debug!("Writing file: {}", path);
        debug!("      string: {}", string);

        FSFile::open(&path).map(|mut file| {
            debug!("Open file at '{}'", path);
            file.write_all(&string.clone().into_bytes())
                .map_err(|ioerr| {
                    debug!("Could not write file");
                    let mut err = StorageBackendError::build(
                            "File::write()",
                            "Tried to write contents of this file, though operation did not succeed",
                            Some(string)
                        );
                    err.caused_by = Some(Box::new(ioerr));
                    err
                })
        }).map_err(|writeerr| {
            debug!("Could not write file at '{}'", path);
            let mut err = StorageBackendError::build(
                "File::open()",
                "Tried to update contents of this file, though file doesn't exist",
                None
            );
            err.caused_by = Some(Box::new(writeerr));
            err
        }).and(Ok(()))
    }

    /*
     * Find a file by its ID and return it if found. Return nothing if not
     * found, of course.
     *
     * TODO: Needs refactoring, as there might be an error when reading from
     * disk OR the id just does not exist.
     */
    pub fn get_file_by_id<HP>(&self, id: FileID, p: &Parser<HP>) -> Option<File>
        where HP: FileHeaderParser
    {
        debug!("Searching for file with id '{}'", id);
        if let Ok(mut fs) = FSFile::open(self.build_filepath_with_id(m, id.clone())) {
            let mut s = String::new();
            fs.read_to_string(&mut s);
            debug!("Success reading file with id '{}'", id);
            debug!("Parsing to internal structure now");
            p.read(s).and_then(|(h, d)| Ok(File::from_parser_result(m, id.clone(), h, d))).ok()
        } else {
            debug!("No file with id '{}'", id);
            None
        }
    }

    pub fn remove_file(&self, m: &Module, file: File, checked: bool) -> BackendOperationResult {
        if checked {
            error!("Checked remove not implemented yet. I will crash now");
            unimplemented!()
        }

        debug!("Doing unchecked remove");
        info!("Going to remove file: {}", file);

        let fp = self.build_filepath(&file);
        remove_file(fp).map_err(|e| {
            let mut serr = StorageBackendError::build(
                "remove_file()",
                "File removal failed",
                Some(format!("{}", file))
            );
            serr.caused_by = Some(Box::new(e));
            serr
        })
    }

    fn build_filepath(&self, f: &File) -> String {
        self.build_filepath_with_id(f.owner(), f.id())
    }

    fn build_filepath_with_id(&self, owner: &Module, id: FileID) -> String {
        debug!("Building filepath with id");
        debug!("  basepath: '{}'", self.basepath);
        debug!(" storepath: '{}'", self.storepath);
        debug!("  id      : '{}'", id);
        self.prefix_of_files_for_module(owner) + "-" + &id[..] + ".imag"
    }

    fn prefix_of_files_for_module(&self, m: &Module) -> String {
        self.storepath.clone() + m.name()
    }

}

#[derive(Debug)]
pub struct StorageBackendError {
    pub action: String,             // The file system action in words
    pub desc: String,               // A short description
    pub data_dump: Option<String>,  // Data dump, if any
    pub caused_by: Option<Box<Error>>,  // caused from this error
}

impl StorageBackendError {
    fn new(action: String,
           desc  : String,
           data  : Option<String>) -> StorageBackendError
    {
        StorageBackendError {
            action:         action,
            desc:           desc,
            data_dump:      data,
            caused_by:      None,
        }
    }

    fn build(action: &'static str,
             desc:   &'static str,
           data  : Option<String>) -> StorageBackendError
    {
        StorageBackendError {
            action:         String::from(action),
            desc:           String::from(desc),
            dataDump:       data,
            caused_by:      None,
        }
    }

}

impl Error for StorageBackendError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        self.caused_by.as_ref().map(|e| &**e)
    }

}

impl Display for StorageBackendError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "StorageBackendError[{}]: {}",
               self.action, self.desc)
    }
}

fn write_with_parser<'a, HP>(f: &File, p: &Parser<HP>) -> Result<String, StorageBackendError>
    where HP: FileHeaderParser
{
    p.write(f.contents())
        .or_else(|err| {
            let mut serr = StorageBackendError::build(
                "Parser::write()",
                "Cannot translate internal representation of file contents into on-disk representation",
                None
            );
            serr.caused_by = Some(Box::new(err));
            Err(serr)
        })
}
<commit_msg>Add some debug output in StorageBackend::build_filepath_with_id()<commit_after>use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;
use std::fs::File as FSFile;
use std::fs::create_dir_all;
use std::fs::remove_file;
use std::io::Read;
use std::io::Write;
use std::vec::IntoIter;

use glob::glob;
use glob::Paths;

use storage::file::File;
use storage::file_id::*;
use storage::parser::{FileHeaderParser, Parser, ParserError};

use module::Module;
use runtime::Runtime;

pub type BackendOperationResult<T = ()> = Result<T, StorageBackendError>;

pub struct StorageBackend {
    basepath: String,
    storepath: String,
}

impl StorageBackend {

    pub fn new(rt: &Runtime) -> BackendOperationResult<StorageBackend> {
        let storepath = rt.get_rtp() + "/store/";
        debug!("Trying to create {}", storepath);
        create_dir_all(&storepath).and_then(|_| {
            debug!("Creating succeeded, constructing backend instance");
            Ok(StorageBackend {
                basepath: rt.get_rtp(),
                storepath: storepath.clone(),
            })
        }).or_else(|e| {
            debug!("Creating failed, constructing error instance");
            let mut serr = StorageBackendError::build(
                "create_dir_all()",
                "Could not create store directories",
                Some(storepath)
            );
            serr.caused_by = Some(Box::new(e));
            Err(serr)
        })
    }

    fn build<M: Module>(rt: &Runtime, m: &M) -> StorageBackend {
        let path = rt.get_rtp() + m.name() + "/store";
        // TODO: Don't use "/store" but value from configuration
        debug!("Building StorageBackend for {}", path);
        StorageBackend::new(path)
    }

    fn get_file_ids(&self, m: &Module) -> Option<Vec<FileID>> {
        let list = glob(&self.prefix_of_files_for_module(m)[..]);

        if let Ok(globlist) = list {
            let mut v = vec![];
            for entry in globlist {
                if let Ok(path) = entry {
                    debug!(" - File: {:?}", path);
                    v.push(from_pathbuf(&path));
                } else {
                    // Entry is not a path
                }
            }

            Some(v)
        } else {
            None
        }
    }

    pub fn iter_ids(&self, m: &Module) -> Option<IntoIter<FileID>>
    {
        glob(&self.prefix_of_files_for_module(m)[..]).and_then(|globlist| {
            let v = globlist.filter_map(Result::ok)
                            .map(|pbuf| from_pathbuf(&pbuf))
                            .collect::<Vec<FileID>>()
                            .into_iter();
            Ok(v)
        }).ok()
    }

    pub fn iter_files<'a, HP>(&self, m: &'a Module, p: &Parser<HP>)
        -> Option<IntoIter<File<'a>>>
        where HP: FileHeaderParser
    {
        self.iter_ids(m).and_then(|ids| {
            Some(ids.filter_map(|id| self.get_file_by_id(m, &id, p))
                    .collect::<Vec<File>>()
                    .into_iter())
        })
    }

    /*
     * Write a file to disk.
     *
     * The file is moved to this function as the file won't be edited afterwards
     */
    pub fn put_file<HP>(&self, f: File, p: &Parser<HP>) -> BackendOperationResult
        where HP: FileHeaderParser
    {
        let written = write_with_parser(&f, p);
        if written.is_err() { return Err(written.err().unwrap()); }
        let string = written.unwrap();

        let path = self.build_filepath(&f);
        debug!("Writing file: {}", path);
        debug!("      string: {}", string);

        FSFile::create(&path).map(|mut file| {
            debug!("Created file at '{}'", path);
            file.write_all(&string.clone().into_bytes())
                .map_err(|ioerr| {
                    debug!("Could not write file");
                    let mut err = StorageBackendError::build(
                            "File::write_all()",
                            "Could not write out File contents",
                            None
                        );
                    err.caused_by = Some(Box::new(ioerr));
                    err
                })
        }).map_err(|writeerr| {
            debug!("Could not create file at '{}'", path);
            let mut err = StorageBackendError::build(
                "File::create()",
                "Creating file on disk failed",
                None
            );
            err.caused_by = Some(Box::new(writeerr));
            err
        }).and(Ok(()))
    }

    /*
     * Update a file. We have the UUID and can find the file on FS with it and
     * then replace its contents with the contents of the passed file object
     */
    pub fn update_file<HP>(&self, f: File, p: &Parser<HP>) -> BackendOperationResult
        where HP: FileHeaderParser
    {
        let contents = write_with_parser(&f, p);
        if contents.is_err() { return Err(contents.err().unwrap()); }
        let string = contents.unwrap();

        let path = self.build_filepath(&f);
        debug!("Writing file: {}", path);
        debug!("      string: {}", string);

        FSFile::open(&path).map(|mut file| {
            debug!("Open file at '{}'", path);
            file.write_all(&string.clone().into_bytes())
                .map_err(|ioerr| {
                    debug!("Could not write file");
                    let mut err = StorageBackendError::build(
                            "File::write()",
                            "Tried to write contents of this file, though operation did not succeed",
                            Some(string)
                        );
                    err.caused_by = Some(Box::new(ioerr));
                    err
                })
        }).map_err(|writeerr| {
            debug!("Could not write file at '{}'", path);
            let mut err = StorageBackendError::build(
                "File::open()",
                "Tried to update contents of this file, though file doesn't exist",
                None
            );
            err.caused_by = Some(Box::new(writeerr));
            err
        }).and(Ok(()))
    }

    /*
     * Find a file by its ID and return it if found. Return nothing if not
     * found, of course.
     *
     * TODO: Needs refactoring, as there might be an error when reading from
     * disk OR the id just does not exist.
     */
    pub fn get_file_by_id<HP>(&self, id: FileID, p: &Parser<HP>) -> Option<File>
        where HP: FileHeaderParser
    {
        debug!("Searching for file with id '{}'", id);
        if let Ok(mut fs) = FSFile::open(self.build_filepath_with_id(m, id.clone())) {
            let mut s = String::new();
            fs.read_to_string(&mut s);
            debug!("Success reading file with id '{}'", id);
            debug!("Parsing to internal structure now");
            p.read(s).and_then(|(h, d)| Ok(File::from_parser_result(m, id.clone(), h, d))).ok()
        } else {
            debug!("No file with id '{}'", id);
            None
        }
    }

    pub fn remove_file(&self, m: &Module, file: File, checked: bool) -> BackendOperationResult {
        if checked {
            error!("Checked remove not implemented yet. I will crash now");
            unimplemented!()
        }

        debug!("Doing unchecked remove");
        info!("Going to remove file: {}", file);

        let fp = self.build_filepath(&file);
        remove_file(fp).map_err(|e| {
            let mut serr = StorageBackendError::build(
                "remove_file()",
                "File removal failed",
                Some(format!("{}", file))
            );
            serr.caused_by = Some(Box::new(e));
            serr
        })
    }

    fn build_filepath(&self, f: &File) -> String {
        self.build_filepath_with_id(f.owner(), f.id())
    }

    fn build_filepath_with_id(&self, owner: &Module, id: FileID) -> String {
        debug!("Building filepath with id");
        debug!("  basepath: '{}'", self.basepath);
        debug!(" storepath: '{}'", self.storepath);
        debug!("  id      : '{}'", id);
        self.prefix_of_files_for_module(owner) + "-" + &id[..] + ".imag"
    }

    fn build_filepath_with_id(&self, id: FileID) -> String {
        debug!("Building filepath with id");
        debug!("  basepath: '{}'", self.basepath);
        debug!("  id      : '{}'", id);
        self.basepath.clone() + &id[..]
    }

}

#[derive(Debug)]
pub struct StorageBackendError {
    pub action: String,             // The file system action in words
    pub desc: String,               // A short description
    pub data_dump: Option<String>,  // Data dump, if any
    pub caused_by: Option<Box<Error>>,  // caused from this error
}

impl StorageBackendError {
    fn new(action: String,
           desc  : String,
           data  : Option<String>) -> StorageBackendError
    {
        StorageBackendError {
            action:         action,
            desc:           desc,
            data_dump:      data,
            caused_by:      None,
        }
    }

    fn build(action: &'static str,
             desc:   &'static str,
           data  : Option<String>) -> StorageBackendError
    {
        StorageBackendError {
            action:         String::from(action),
            desc:           String::from(desc),
            dataDump:       data,
            caused_by:      None,
        }
    }

}

impl Error for StorageBackendError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        self.caused_by.as_ref().map(|e| &**e)
    }

}

impl Display for StorageBackendError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "StorageBackendError[{}]: {}",
               self.action, self.desc)
    }
}

fn write_with_parser<'a, HP>(f: &File, p: &Parser<HP>) -> Result<String, StorageBackendError>
    where HP: FileHeaderParser
{
    p.write(f.contents())
        .or_else(|err| {
            let mut serr = StorageBackendError::build(
                "Parser::write()",
                "Cannot translate internal representation of file contents into on-disk representation",
                None
            );
            serr.caused_by = Some(Box::new(err));
            Err(serr)
        })
}
<|endoftext|>


<commit_before>extern crate futures;

use futures::*;

type MyFuture<T> = Future<Item=T,Error=()>;

fn fetch_item() -> Box<MyFuture<Option<Foo>>> {
    return fetch_item2(fetch_replica_a(), fetch_replica_b());
}

fn fetch_item2(a: Box<MyFuture<Foo>>, b: Box<MyFuture<Foo>>) -> Box<MyFuture<Option<Foo>>> {
    let a = a.then(|a| disambiguate(a, 0));
    let b = b.then(|b| disambiguate(b, 1));
    a.select2(b).map(Some).select2(timeout()).then(|res| {
        let (to_restart, other) = match res {
            // Something finished successfully, see if it's a valid response
            Ok((Some(((val, which), next)), _next_timeout)) => {
                if val.is_valid() {
                    return finished(Some(val)).boxed()
                }
                (which, next)
            }
            // timeout, we're done
            Ok((None, _)) => return finished(None).boxed(),

            Err(((((), which), next), _next_timeout)) => (which, next),
        };
        let other = other.then(reambiguate);
        if to_restart == 0 {
            fetch_item2(fetch_replica_a(), other.boxed())
        } else {
            fetch_item2(other.boxed(), fetch_replica_b())
        }
    }).boxed()
}

fn disambiguate<T, E, U>(r: Result<T, E>, u: U) -> Result<(T, U), (E, U)> {
    match r {
        Ok(t) => Ok((t, u)),
        Err(e) => Err((e, u)),
    }
}

fn reambiguate<T, E, U>(r: Result<(T, U), (E, U)>) -> Result<T, E> {
    match r {
        Ok((t, _u)) => Ok(t),
        Err((e, _u)) => Err(e),
    }
}

struct Foo;

impl Foo {
    fn is_valid(&self) -> bool { false }
}

fn fetch_replica_a() -> Box<MyFuture<Foo>> { loop {} }
fn fetch_replica_b() -> Box<MyFuture<Foo>> { loop {} }
fn timeout<T, E>() -> Box<Future<Item=Option<T>,Error=E>> { loop {} }

fn main() {
    fetch_item();
}
<commit_msg>Fix the slow retry example<commit_after>extern crate futures;

use futures::*;

type MyFuture<T> = Future<Item=T,Error=()>;

fn fetch_item() -> Box<MyFuture<Option<Foo>>> {
    return fetch_item2(fetch_replica_a(), fetch_replica_b());
}

fn fetch_item2(a: Box<MyFuture<Foo>>, b: Box<MyFuture<Foo>>) -> Box<MyFuture<Option<Foo>>> {
    let a = a.then(|a| disambiguate(a, 0));
    let b = b.then(|b| disambiguate(b, 1));
    a.select(b).map(Some).select(timeout()).then(|res| {
        let (to_restart, other) = match res {
            // Something finished successfully, see if it's a valid response
            Ok((Some(((val, which), next)), _next_timeout)) => {
                if val.is_valid() {
                    return finished(Some(val)).boxed()
                }
                (which, next)
            }
            // timeout, we're done
            Ok((None, _)) => return finished(None).boxed(),

            Err(((((), which), next), _next_timeout)) => (which, next),
        };
        let other = other.then(reambiguate);
        if to_restart == 0 {
            fetch_item2(fetch_replica_a(), other.boxed())
        } else {
            fetch_item2(other.boxed(), fetch_replica_b())
        }
    }).boxed()
}

fn disambiguate<T, E, U>(r: Result<T, E>, u: U) -> Result<(T, U), (E, U)> {
    match r {
        Ok(t) => Ok((t, u)),
        Err(e) => Err((e, u)),
    }
}

fn reambiguate<T, E, U>(r: Result<(T, U), (E, U)>) -> Result<T, E> {
    match r {
        Ok((t, _u)) => Ok(t),
        Err((e, _u)) => Err(e),
    }
}

struct Foo;

impl Foo {
    fn is_valid(&self) -> bool { false }
}

fn fetch_replica_a() -> Box<MyFuture<Foo>> { loop {} }
fn fetch_replica_b() -> Box<MyFuture<Foo>> { loop {} }
fn timeout<T, E>() -> Box<Future<Item=Option<T>,Error=E>> { loop {} }

fn main() {
    fetch_item();
}
<|endoftext|>


<commit_before><commit_msg>More?<commit_after><|endoftext|>


<commit_before>use alloc::arc::{Arc, Weak};
use alloc::boxed::Box;

use collections::{BTreeMap, String};
use collections::string::ToString;

use core::cell::Cell;
use core::mem::size_of;
use core::ops::DerefMut;

use scheduler::context::{context_switch, Context, ContextMemory};

use schemes::{Result, Resource, ResourceSeek, KScheme, Url};

use sync::Intex;

use system::error::{Error, EBADF, EFAULT, EINVAL, ENOENT, ESPIPE, ESRCH};
use system::scheme::Packet;
use system::syscall::{SYS_CLOSE, SYS_FSYNC, SYS_FTRUNCATE,
                    SYS_LSEEK, SEEK_SET, SEEK_CUR, SEEK_END,
                    SYS_OPEN, SYS_READ, SYS_WRITE, SYS_UNLINK};

struct SchemeInner {
    name: String,
    context: *mut Context,
    next_id: Cell<usize>,
    todo: Intex<BTreeMap<usize, (usize, usize, usize, usize)>>,
    done: Intex<BTreeMap<usize, (usize, usize, usize, usize)>>,
}

impl SchemeInner {
    fn new(name: String, context: *mut Context) -> SchemeInner {
        SchemeInner {
            name: name,
            context: context,
            next_id: Cell::new(1),
            todo: Intex::new(BTreeMap::new()),
            done: Intex::new(BTreeMap::new()),
        }
    }

    fn call(inner: &Weak<SchemeInner>, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        let id;
        if let Some(scheme) = inner.upgrade() {
            id = scheme.next_id.get();

            //TODO: What should be done about collisions in self.todo or self.done?
            let mut next_id = id + 1;
            if next_id <= 0 {
                next_id = 1;
            }
            scheme.next_id.set(next_id);

            scheme.todo.lock().insert(id, (a, b, c, d));
        } else {
            return Err(Error::new(EBADF));
        }

        loop {
            if let Some(scheme) = inner.upgrade() {
                if let Some(regs) = scheme.done.lock().remove(&id) {
                    return Error::demux(regs.0);
                }
            } else {
                return Err(Error::new(EBADF));
            }

            unsafe { context_switch(false) } ;
        }
    }
}

impl Drop for SchemeInner {
    fn drop(&mut self) {
        let mut schemes = ::env().schemes.lock();

        let mut i = 0;
        while i < schemes.len() {
            let mut remove = false;
            if let Some(scheme) = schemes.get(i){
                if scheme.scheme() == self.name {
                    remove = true;
                }
            }

            if remove {
                schemes.remove(i);
            } else {
                i += 1;
            }
        }
    }
}

pub struct SchemeResource {
    inner: Weak<SchemeInner>,
    file_id: usize,
}

impl SchemeResource {
    fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        SchemeInner::call(&self.inner, a, b, c, d)
    }
}

impl Resource for SchemeResource {
    /// Duplicate the resource
    fn dup(&self) -> Result<Box<Resource>> {
        Err(Error::new(EBADF))
    }

    /// Return the url of this resource
    fn url(&self) -> Url {
        Url::new()
    }

    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let contexts = ::env().contexts.lock();
        if let Some(current) = contexts.current() {
            if let Some(physical_address) = unsafe { current.translate(buf.as_mut_ptr() as usize) } {
                let offset = physical_address % 4096;

                let mut virtual_address = 0;
                let virtual_size = (buf.len() + offset + 4095)/4096 * 4096;
                if let Some(scheme) = self.inner.upgrade() {
                    unsafe {
                        virtual_address = (*scheme.context).next_mem();
                        (*(*scheme.context).memory.get()).push(ContextMemory {
                            physical_address: physical_address - offset,
                            virtual_address: virtual_address,
                            virtual_size: virtual_size,
                            writeable: true,
                            allocated: false,
                        });
                    }
                }

                if virtual_address > 0 {
                    let result = self.call(SYS_READ, self.file_id, virtual_address + offset, buf.len());

                    //debugln!("Read {:X} mapped from {:X} to {:X} offset {} length {} size {} result {:?}", physical_address, buf.as_ptr() as usize, virtual_address + offset, offset, buf.len(), virtual_size, result);

                    if let Some(scheme) = self.inner.upgrade() {
                        unsafe {
                            if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                                mem.virtual_size = 0;
                            }
                            (*scheme.context).clean_mem();
                        }
                    }

                    result
                } else {
                    Err(Error::new(EBADF))
                }
            } else {
                Err(Error::new(EFAULT))
            }
        } else {
            Err(Error::new(ESRCH))
        }
    }

    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let contexts = ::env().contexts.lock();
        if let Some(current) = contexts.current() {
            if let Some(physical_address) = unsafe { current.translate(buf.as_ptr() as usize) } {
                let offset = physical_address % 4096;

                let mut virtual_address = 0;
                let virtual_size = (buf.len() + offset + 4095)/4096 * 4096;
                if let Some(scheme) = self.inner.upgrade() {
                    unsafe {
                        virtual_address = (*scheme.context).next_mem();
                        (*(*scheme.context).memory.get()).push(ContextMemory {
                            physical_address: physical_address - offset,
                            virtual_address: virtual_address,
                            virtual_size: buf.len() + offset,
                            writeable: true,
                            allocated: false,
                        });
                    }
                }

                if virtual_address > 0 {
                    let result = self.call(SYS_WRITE, self.file_id, virtual_address + offset, buf.len());

                    //debugln!("Write {:X} mapped from {:X} to {:X} offset {} length {} size {} result {:?}", physical_address, buf.as_ptr() as usize, virtual_address + offset, offset, buf.len(), virtual_size, result);

                    if let Some(scheme) = self.inner.upgrade() {
                        unsafe {
                            if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                                mem.virtual_size = 0;
                            }
                            (*scheme.context).clean_mem();
                        }
                    }

                    result
                } else {
                    Err(Error::new(EBADF))
                }
            } else {
                Err(Error::new(EFAULT))
            }
        } else {
            Err(Error::new(ESRCH))
        }
    }

    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Result<usize> {
        let (whence, offset) = match pos {
            ResourceSeek::Start(offset) => (SEEK_SET, offset as usize),
            ResourceSeek::Current(offset) => (SEEK_CUR, offset as usize),
            ResourceSeek::End(offset) => (SEEK_END, offset as usize)
        };

        self.call(SYS_LSEEK, self.file_id, offset, whence)
    }

    /// Sync the resource
    fn sync(&mut self) -> Result<()> {
        self.call(SYS_FSYNC, self.file_id, 0, 0).and(Ok(()))
    }

    fn truncate(&mut self, len: usize) -> Result<()> {
        self.call(SYS_FTRUNCATE, self.file_id, len, 0).and(Ok(()))
    }
}

impl Drop for SchemeResource {
    fn drop(&mut self) {
        let _ = self.call(SYS_CLOSE, self.file_id, 0, 0);
    }
}

pub struct SchemeServerResource {
    inner: Arc<SchemeInner>,
}

impl Resource for SchemeServerResource {
    /// Duplicate the resource
    fn dup(&self) -> Result<Box<Resource>> {
        Ok(box SchemeServerResource {
            inner: self.inner.clone()
        })
    }

    /// Return the url of this resource
    fn url(&self) -> Url {
        Url::from_string(":".to_string() + &self.inner.name)
    }

    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        if buf.len() == size_of::<Packet>() {
            let packet_ptr: *mut Packet = buf.as_mut_ptr() as *mut Packet;
            let packet = unsafe { &mut *packet_ptr };

            let mut todo = self.inner.todo.lock();

            packet.id = if let Some(id) = todo.keys().next() {
                *id
            } else {
                0
            };

            if packet.id > 0 {
                if let Some(regs) = todo.remove(&packet.id) {
                    packet.a = regs.0;
                    packet.b = regs.1;
                    packet.c = regs.2;
                    packet.d = regs.3;
                    return Ok(size_of::<Packet>())
                }
            }

            Ok(0)
        } else {
            Err(Error::new(EINVAL))
        }
    }

    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        if buf.len() == size_of::<Packet>() {
            let packet_ptr: *const Packet = buf.as_ptr() as *const Packet;
            let packet = unsafe { & *packet_ptr };
            self.inner.done.lock().insert(packet.id, (packet.a, packet.b, packet.c, packet.d));
            Ok(size_of::<Packet>())
        } else {
            Err(Error::new(EINVAL))
        }
    }

    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Result<usize> {
        Err(Error::new(ESPIPE))
    }

    /// Sync the resource
    fn sync(&mut self) -> Result<()> {
        Err(Error::new(EINVAL))
    }

    fn truncate(&mut self, len: usize) -> Result<()> {
        Err(Error::new(EINVAL))
    }
}

/// Scheme has to be wrapped
pub struct Scheme {
    name: String,
    inner: Weak<SchemeInner>
}

impl Scheme {
    pub fn new(name: String) -> Result<(Box<Scheme>, Box<Resource>)> {
        if let Some(context) = ::env().contexts.lock().current_mut() {
            let server = box SchemeServerResource {
                inner: Arc::new(SchemeInner::new(name.clone(), context.deref_mut()))
            };
            let scheme = box Scheme {
                name: name,
                inner: Arc::downgrade(&server.inner)
            };
            Ok((scheme, server))
        } else {
            Err(Error::new(ESRCH))
        }
    }

    fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        SchemeInner::call(&self.inner, a, b, c, d)
    }
}

impl KScheme for Scheme {
    fn on_irq(&mut self, irq: u8) {

    }

    fn on_poll(&mut self) {

    }

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

    fn open(&mut self, url: &Url, flags: usize) -> Result<Box<Resource>> {
        let c_str = url.string.clone() + "\0";

        let physical_address = c_str.as_ptr() as usize;

        let mut virtual_address = 0;
        if let Some(scheme) = self.inner.upgrade() {
            unsafe {
                virtual_address = (*scheme.context).next_mem();
                (*(*scheme.context).memory.get()).push(ContextMemory {
                    physical_address: physical_address,
                    virtual_address: virtual_address,
                    virtual_size: c_str.len(),
                    writeable: false,
                    allocated: false,
                });
            }
        }

        if virtual_address > 0 {
            let result = self.call(SYS_OPEN, virtual_address, flags, 0);

            if let Some(scheme) = self.inner.upgrade() {
                unsafe {
                    if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                        mem.virtual_size = 0;
                    }
                    (*scheme.context).clean_mem();
                }
            }

            match result {
                Ok(file_id) => Ok(box SchemeResource {
                    inner: self.inner.clone(),
                    file_id: file_id,
                }),
                Err(err) => Err(err)
            }
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn unlink(&mut self, url: &Url) -> Result<()> {
        let c_str = url.string.clone() + "\0";

        let physical_address = c_str.as_ptr() as usize;

        let mut virtual_address = 0;
        if let Some(scheme) = self.inner.upgrade() {
            unsafe {
                virtual_address = (*scheme.context).next_mem();
                (*(*scheme.context).memory.get()).push(ContextMemory {
                    physical_address: physical_address,
                    virtual_address: virtual_address,
                    virtual_size: c_str.len(),
                    writeable: false,
                    allocated: false,
                });
            }
        }

        if virtual_address > 0 {
            let result = self.call(SYS_UNLINK, virtual_address, 0, 0);

            if let Some(scheme) = self.inner.upgrade() {
                unsafe {
                    if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                        mem.virtual_size = 0;
                    }
                    (*scheme.context).clean_mem();
                }
            }

            result.and(Ok(()))
        } else {
            Err(Error::new(EBADF))
        }
    }
}
<commit_msg>Incorrect virtual size in write<commit_after>use alloc::arc::{Arc, Weak};
use alloc::boxed::Box;

use collections::{BTreeMap, String};
use collections::string::ToString;

use core::cell::Cell;
use core::mem::size_of;
use core::ops::DerefMut;

use scheduler::context::{context_switch, Context, ContextMemory};

use schemes::{Result, Resource, ResourceSeek, KScheme, Url};

use sync::Intex;

use system::error::{Error, EBADF, EFAULT, EINVAL, ENOENT, ESPIPE, ESRCH};
use system::scheme::Packet;
use system::syscall::{SYS_CLOSE, SYS_FSYNC, SYS_FTRUNCATE,
                    SYS_LSEEK, SEEK_SET, SEEK_CUR, SEEK_END,
                    SYS_OPEN, SYS_READ, SYS_WRITE, SYS_UNLINK};

struct SchemeInner {
    name: String,
    context: *mut Context,
    next_id: Cell<usize>,
    todo: Intex<BTreeMap<usize, (usize, usize, usize, usize)>>,
    done: Intex<BTreeMap<usize, (usize, usize, usize, usize)>>,
}

impl SchemeInner {
    fn new(name: String, context: *mut Context) -> SchemeInner {
        SchemeInner {
            name: name,
            context: context,
            next_id: Cell::new(1),
            todo: Intex::new(BTreeMap::new()),
            done: Intex::new(BTreeMap::new()),
        }
    }

    fn call(inner: &Weak<SchemeInner>, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        let id;
        if let Some(scheme) = inner.upgrade() {
            id = scheme.next_id.get();

            //TODO: What should be done about collisions in self.todo or self.done?
            let mut next_id = id + 1;
            if next_id <= 0 {
                next_id = 1;
            }
            scheme.next_id.set(next_id);

            scheme.todo.lock().insert(id, (a, b, c, d));
        } else {
            return Err(Error::new(EBADF));
        }

        loop {
            if let Some(scheme) = inner.upgrade() {
                if let Some(regs) = scheme.done.lock().remove(&id) {
                    return Error::demux(regs.0);
                }
            } else {
                return Err(Error::new(EBADF));
            }

            unsafe { context_switch(false) } ;
        }
    }
}

impl Drop for SchemeInner {
    fn drop(&mut self) {
        let mut schemes = ::env().schemes.lock();

        let mut i = 0;
        while i < schemes.len() {
            let mut remove = false;
            if let Some(scheme) = schemes.get(i){
                if scheme.scheme() == self.name {
                    remove = true;
                }
            }

            if remove {
                schemes.remove(i);
            } else {
                i += 1;
            }
        }
    }
}

pub struct SchemeResource {
    inner: Weak<SchemeInner>,
    file_id: usize,
}

impl SchemeResource {
    fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        SchemeInner::call(&self.inner, a, b, c, d)
    }
}

impl Resource for SchemeResource {
    /// Duplicate the resource
    fn dup(&self) -> Result<Box<Resource>> {
        Err(Error::new(EBADF))
    }

    /// Return the url of this resource
    fn url(&self) -> Url {
        Url::new()
    }

    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let contexts = ::env().contexts.lock();
        if let Some(current) = contexts.current() {
            if let Some(physical_address) = unsafe { current.translate(buf.as_mut_ptr() as usize) } {
                let offset = physical_address % 4096;

                let mut virtual_address = 0;
                let virtual_size = (buf.len() + offset + 4095)/4096 * 4096;
                if let Some(scheme) = self.inner.upgrade() {
                    unsafe {
                        virtual_address = (*scheme.context).next_mem();
                        (*(*scheme.context).memory.get()).push(ContextMemory {
                            physical_address: physical_address - offset,
                            virtual_address: virtual_address,
                            virtual_size: virtual_size,
                            writeable: true,
                            allocated: false,
                        });
                    }
                }

                if virtual_address > 0 {
                    let result = self.call(SYS_READ, self.file_id, virtual_address + offset, buf.len());

                    //debugln!("Read {:X} mapped from {:X} to {:X} offset {} length {} size {} result {:?}", physical_address, buf.as_ptr() as usize, virtual_address + offset, offset, buf.len(), virtual_size, result);

                    if let Some(scheme) = self.inner.upgrade() {
                        unsafe {
                            if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                                mem.virtual_size = 0;
                            }
                            (*scheme.context).clean_mem();
                        }
                    }

                    result
                } else {
                    Err(Error::new(EBADF))
                }
            } else {
                Err(Error::new(EFAULT))
            }
        } else {
            Err(Error::new(ESRCH))
        }
    }

    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let contexts = ::env().contexts.lock();
        if let Some(current) = contexts.current() {
            if let Some(physical_address) = unsafe { current.translate(buf.as_ptr() as usize) } {
                let offset = physical_address % 4096;

                let mut virtual_address = 0;
                let virtual_size = (buf.len() + offset + 4095)/4096 * 4096;
                if let Some(scheme) = self.inner.upgrade() {
                    unsafe {
                        virtual_address = (*scheme.context).next_mem();
                        (*(*scheme.context).memory.get()).push(ContextMemory {
                            physical_address: physical_address - offset,
                            virtual_address: virtual_address,
                            virtual_size: virtual_size,
                            writeable: true,
                            allocated: false,
                        });
                    }
                }

                if virtual_address > 0 {
                    let result = self.call(SYS_WRITE, self.file_id, virtual_address + offset, buf.len());

                    //debugln!("Write {:X} mapped from {:X} to {:X} offset {} length {} size {} result {:?}", physical_address, buf.as_ptr() as usize, virtual_address + offset, offset, buf.len(), virtual_size, result);

                    if let Some(scheme) = self.inner.upgrade() {
                        unsafe {
                            if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                                mem.virtual_size = 0;
                            }
                            (*scheme.context).clean_mem();
                        }
                    }

                    result
                } else {
                    Err(Error::new(EBADF))
                }
            } else {
                Err(Error::new(EFAULT))
            }
        } else {
            Err(Error::new(ESRCH))
        }
    }

    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Result<usize> {
        let (whence, offset) = match pos {
            ResourceSeek::Start(offset) => (SEEK_SET, offset as usize),
            ResourceSeek::Current(offset) => (SEEK_CUR, offset as usize),
            ResourceSeek::End(offset) => (SEEK_END, offset as usize)
        };

        self.call(SYS_LSEEK, self.file_id, offset, whence)
    }

    /// Sync the resource
    fn sync(&mut self) -> Result<()> {
        self.call(SYS_FSYNC, self.file_id, 0, 0).and(Ok(()))
    }

    fn truncate(&mut self, len: usize) -> Result<()> {
        self.call(SYS_FTRUNCATE, self.file_id, len, 0).and(Ok(()))
    }
}

impl Drop for SchemeResource {
    fn drop(&mut self) {
        let _ = self.call(SYS_CLOSE, self.file_id, 0, 0);
    }
}

pub struct SchemeServerResource {
    inner: Arc<SchemeInner>,
}

impl Resource for SchemeServerResource {
    /// Duplicate the resource
    fn dup(&self) -> Result<Box<Resource>> {
        Ok(box SchemeServerResource {
            inner: self.inner.clone()
        })
    }

    /// Return the url of this resource
    fn url(&self) -> Url {
        Url::from_string(":".to_string() + &self.inner.name)
    }

    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        if buf.len() == size_of::<Packet>() {
            let packet_ptr: *mut Packet = buf.as_mut_ptr() as *mut Packet;
            let packet = unsafe { &mut *packet_ptr };

            let mut todo = self.inner.todo.lock();

            packet.id = if let Some(id) = todo.keys().next() {
                *id
            } else {
                0
            };

            if packet.id > 0 {
                if let Some(regs) = todo.remove(&packet.id) {
                    packet.a = regs.0;
                    packet.b = regs.1;
                    packet.c = regs.2;
                    packet.d = regs.3;
                    return Ok(size_of::<Packet>())
                }
            }

            Ok(0)
        } else {
            Err(Error::new(EINVAL))
        }
    }

    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        if buf.len() == size_of::<Packet>() {
            let packet_ptr: *const Packet = buf.as_ptr() as *const Packet;
            let packet = unsafe { & *packet_ptr };
            self.inner.done.lock().insert(packet.id, (packet.a, packet.b, packet.c, packet.d));
            Ok(size_of::<Packet>())
        } else {
            Err(Error::new(EINVAL))
        }
    }

    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Result<usize> {
        Err(Error::new(ESPIPE))
    }

    /// Sync the resource
    fn sync(&mut self) -> Result<()> {
        Err(Error::new(EINVAL))
    }

    fn truncate(&mut self, len: usize) -> Result<()> {
        Err(Error::new(EINVAL))
    }
}

/// Scheme has to be wrapped
pub struct Scheme {
    name: String,
    inner: Weak<SchemeInner>
}

impl Scheme {
    pub fn new(name: String) -> Result<(Box<Scheme>, Box<Resource>)> {
        if let Some(context) = ::env().contexts.lock().current_mut() {
            let server = box SchemeServerResource {
                inner: Arc::new(SchemeInner::new(name.clone(), context.deref_mut()))
            };
            let scheme = box Scheme {
                name: name,
                inner: Arc::downgrade(&server.inner)
            };
            Ok((scheme, server))
        } else {
            Err(Error::new(ESRCH))
        }
    }

    fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        SchemeInner::call(&self.inner, a, b, c, d)
    }
}

impl KScheme for Scheme {
    fn on_irq(&mut self, irq: u8) {

    }

    fn on_poll(&mut self) {

    }

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

    fn open(&mut self, url: &Url, flags: usize) -> Result<Box<Resource>> {
        let c_str = url.string.clone() + "\0";

        let physical_address = c_str.as_ptr() as usize;

        let mut virtual_address = 0;
        if let Some(scheme) = self.inner.upgrade() {
            unsafe {
                virtual_address = (*scheme.context).next_mem();
                (*(*scheme.context).memory.get()).push(ContextMemory {
                    physical_address: physical_address,
                    virtual_address: virtual_address,
                    virtual_size: c_str.len(),
                    writeable: false,
                    allocated: false,
                });
            }
        }

        if virtual_address > 0 {
            let result = self.call(SYS_OPEN, virtual_address, flags, 0);

            if let Some(scheme) = self.inner.upgrade() {
                unsafe {
                    if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                        mem.virtual_size = 0;
                    }
                    (*scheme.context).clean_mem();
                }
            }

            match result {
                Ok(file_id) => Ok(box SchemeResource {
                    inner: self.inner.clone(),
                    file_id: file_id,
                }),
                Err(err) => Err(err)
            }
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn unlink(&mut self, url: &Url) -> Result<()> {
        let c_str = url.string.clone() + "\0";

        let physical_address = c_str.as_ptr() as usize;

        let mut virtual_address = 0;
        if let Some(scheme) = self.inner.upgrade() {
            unsafe {
                virtual_address = (*scheme.context).next_mem();
                (*(*scheme.context).memory.get()).push(ContextMemory {
                    physical_address: physical_address,
                    virtual_address: virtual_address,
                    virtual_size: c_str.len(),
                    writeable: false,
                    allocated: false,
                });
            }
        }

        if virtual_address > 0 {
            let result = self.call(SYS_UNLINK, virtual_address, 0, 0);

            if let Some(scheme) = self.inner.upgrade() {
                unsafe {
                    if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                        mem.virtual_size = 0;
                    }
                    (*scheme.context).clean_mem();
                }
            }

            result.and(Ok(()))
        } else {
            Err(Error::new(EBADF))
        }
    }
}
<|endoftext|>


<commit_before>//! IO

use {fmt, str};
use string::String;
use vec::{IntoIter, Vec};
pub use system::error::Error;
use system::syscall::{sys_read, sys_write};

pub mod prelude;

pub type Result<T> = ::core::result::Result<T, Error>;

/// Types you can read
pub trait Read {
    /// Read a file to a buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize>;

    /// Read the file to the end
    fn read_to_end(&mut self, vec: &mut Vec<u8>) -> Result<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 4096];
            match self.read(&mut bytes) {
                Ok(0) => return Ok(read),
                Err(err) => return Err(err),
                Ok(count) => {
                    vec.push_all(&bytes[0..count]);
                    read += count;
                }
            }
        }
    }

    /// Read the file to a string
    fn read_to_string(&mut self, string: &mut String) -> Result<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 4096];
            match self.read(&mut bytes) {
                Ok(0) => return Ok(read),
                Err(err) => return Err(err),
                Ok(count) => {
                    string.push_str(unsafe { &str::from_utf8_unchecked(&bytes[0..count]) });
                    read += count;
                }
            }
        }
    }

    /// Return an iterator of the bytes
    fn bytes(&mut self) -> IntoIter<u8> {
        // TODO: This is only a temporary implementation. Make this read one byte at a time.
        let mut buf = Vec::new();
        let _ = self.read_to_end(&mut buf);

        buf.into_iter()
    }
}

/// Types you can write
pub trait Write {
    /// Write to the file
    fn write(&mut self, buf: &[u8]) -> Result<usize>;

    /// Write a format to the file
    fn write_fmt(&mut self, args: fmt::Arguments) -> Result<()> {
        match self.write(fmt::format(args).as_bytes()) {
            Ok(_) => Ok(()),
            Err(err) => Err(err),
        }
    }

    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}

/// Seek Location
pub enum SeekFrom {
    /// The start point
    Start(u64),
    /// The current point
    Current(i64),
    /// The end point
    End(i64),
}

pub trait Seek {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
}

pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64> where R: Read, W: Write {
    let mut copied = 0;
    loop {
        let mut bytes = [0; 4096];
        match reader.read(&mut bytes) {
            Ok(0) => return Ok(copied),
            Err(err) => return Err(err),
            Ok(count) => match writer.write(&bytes[0 .. count]){
                Ok(0) => return Ok(copied),
                Err(err) => return Err(err),
                Ok(count) => copied += count as u64
            }
        }
    }
}

/// Standard Input
pub struct Stdin;

/// Create a standard input
pub fn stdin() -> Stdin {
    Stdin
}

impl Stdin {
    pub fn read_line(&mut self, string: &mut String) -> Result<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 4096];
            match self.read(&mut bytes) {
                Ok(0) => return Ok(read),
                Err(err) => return Err(err),
                Ok(count) => {
                    string.push_str(unsafe { &str::from_utf8_unchecked(&bytes[0..count]) });
                    read += count;
                }
            }
        }
    }
}

/// Read implementation for standard input
impl Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        Error::demux(unsafe { sys_read(0, buf.as_mut_ptr(), buf.len()) })
    }
}

/// Standard Output
pub struct Stdout;

/// Create a standard output
pub fn stdout() -> Stdout {
    Stdout
}

/// Write implementation for standard output
impl Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        Error::demux(unsafe { sys_write(1, buf.as_ptr(), buf.len()) })
    }
}

/// Standard Error
pub struct Stderr;

/// Create a standard error
pub fn stderr() -> Stderr {
    Stderr
}

/// Write implementation for standard error
impl Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        Error::demux(unsafe { sys_write(2, buf.as_ptr(), buf.len()) })
    }
}

#[allow(unused_must_use)]
pub fn _print(args: fmt::Arguments) {
    stdout().write_fmt(args);
}
<commit_msg>Compatibility with libstd's Bytes iterator<commit_after>//! IO

use {fmt, str};
use string::String;
use vec::Vec;
pub use system::error::Error;
use system::syscall::{sys_read, sys_write};

pub mod prelude;

pub type Result<T> = ::core::result::Result<T, Error>;

pub struct Bytes<R: Read> {
    reader: R,
}

impl<R: Read> Iterator for Bytes<R> {
    type Item = Result<u8>;

    fn next(&mut self) -> Option<Result<u8>> {
        let mut byte = [4];
        if let Ok(1) = self.reader.read(&mut byte) {
            if byte[0] == 4 {
                None
            } else {
                Some(Ok(byte[0]))
            }
        } else {
            None
        }
    }
}

/// Types you can read
pub trait Read {
    /// Read a file to a buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize>;

    /// Read the file to the end
    fn read_to_end(&mut self, vec: &mut Vec<u8>) -> Result<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 4096];
            match self.read(&mut bytes) {
                Ok(0) => return Ok(read),
                Err(err) => return Err(err),
                Ok(count) => {
                    vec.push_all(&bytes[0..count]);
                    read += count;
                }
            }
        }
    }

    /// Read the file to a string
    fn read_to_string(&mut self, string: &mut String) -> Result<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 4096];
            match self.read(&mut bytes) {
                Ok(0) => return Ok(read),
                Err(err) => return Err(err),
                Ok(count) => {
                    string.push_str(unsafe { &str::from_utf8_unchecked(&bytes[0..count]) });
                    read += count;
                }
            }
        }
    }

    /// Return an iterator of the bytes
    fn bytes(self) -> Bytes<Self> where Self: Sized {
        Bytes {
            reader: self,
        }
    }
}

/// Types you can write
pub trait Write {
    /// Write to the file
    fn write(&mut self, buf: &[u8]) -> Result<usize>;

    /// Write a format to the file
    fn write_fmt(&mut self, args: fmt::Arguments) -> Result<()> {
        match self.write(fmt::format(args).as_bytes()) {
            Ok(_) => Ok(()),
            Err(err) => Err(err),
        }
    }

    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}

/// Seek Location
pub enum SeekFrom {
    /// The start point
    Start(u64),
    /// The current point
    Current(i64),
    /// The end point
    End(i64),
}

pub trait Seek {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
}

pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64> where R: Read, W: Write {
    let mut copied = 0;
    loop {
        let mut bytes = [0; 4096];
        match reader.read(&mut bytes) {
            Ok(0) => return Ok(copied),
            Err(err) => return Err(err),
            Ok(count) => match writer.write(&bytes[0 .. count]){
                Ok(0) => return Ok(copied),
                Err(err) => return Err(err),
                Ok(count) => copied += count as u64
            }
        }
    }
}

/// Standard Input
pub struct Stdin;

/// Create a standard input
pub fn stdin() -> Stdin {
    Stdin
}

impl Stdin {
    pub fn read_line(&mut self, string: &mut String) -> Result<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 4096];
            match self.read(&mut bytes) {
                Ok(0) => return Ok(read),
                Err(err) => return Err(err),
                Ok(count) => {
                    string.push_str(unsafe { &str::from_utf8_unchecked(&bytes[0..count]) });
                    read += count;
                }
            }
        }
    }
}

/// Read implementation for standard input
impl Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        Error::demux(unsafe { sys_read(0, buf.as_mut_ptr(), buf.len()) })
    }
}

/// Standard Output
pub struct Stdout;

/// Create a standard output
pub fn stdout() -> Stdout {
    Stdout
}

/// Write implementation for standard output
impl Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        Error::demux(unsafe { sys_write(1, buf.as_ptr(), buf.len()) })
    }
}

/// Standard Error
pub struct Stderr;

/// Create a standard error
pub fn stderr() -> Stderr {
    Stderr
}

/// Write implementation for standard error
impl Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        Error::demux(unsafe { sys_write(2, buf.as_ptr(), buf.len()) })
    }
}

#[allow(unused_must_use)]
pub fn _print(args: fmt::Arguments) {
    stdout().write_fmt(args);
}
<|endoftext|>


<commit_before><commit_msg>Adding tiny tries<commit_after>use std::io::{self, BufRead};

fn main(){

    let stdin = io::stdin();
    for line in stdin.lock().lines(){
        println!("{:?}", line);
    }
}

/*

pub fn stdin() -> Stdin

[−]

Constructs a new handle to the standard input of the current process.

Each handle returned is a reference to a shared global buffer whose access is synchronized via a mutex.
If you need more explicit control over locking, see the lock() method.

*/

/*

Q. Why doesn't this work ?

for line in io::stdin().lock().lines(){
        println!("{:?}", line);
}

stdin() returns handle of stdin buffer and lock() returns a reference to the handle. Since hadle isn't binded by any variable, it
gets destroyed at the end of statement and reference returned by lock() would have been pointing to destroyed handle.

http://stackoverflow.com/questions/27468558/rust-lifetime-chaining-function-calls-vs-using-intermediate-variables

http://stackoverflow.com/questions/23440793/why-do-i-get-borrowed-value-does-not-live-long-enough-in-this-example
*/
<|endoftext|>


<commit_before><commit_msg>Add assignment to the interpreter<commit_after><|endoftext|>


<commit_before><commit_msg>config: remove duplicate property<commit_after><|endoftext|>


<commit_before><commit_msg>Don't insist on Path ref in fn signatures<commit_after><|endoftext|>


<commit_before><commit_msg>Add texture structs<commit_after>use orbclient;
use orbimage;

fn get_by_coord(texture: &orbimage::Image, x: u32, y: u32) -> orbclient::color::Color {
    let data  =  texture.data();
    let width = texture.width();

    if (x + y * width) as usize > data.len() {
        return orbclient::color::Color::rgb(0, 0, 0);
    }
    data[(x + y * width) as usize]
}

fn get_by_barycentric(texture: &orbimage::Image, a: (u32, u32), b: (u32, u32), g: (u32, u32),
                                                 alpha: f32,    beta: f32,     gamma: f32,  ) -> orbclient::color::Color {
    let x = (a.0 as f32 * alpha + b.0 as f32 * beta + g.0 as f32 * gamma) as u32;
    let y = (a.1 as f32 * alpha + b.1 as f32 * beta + g.1 as f32 * gamma) as u32;

    get_by_coord(texture, x, y)
}

fn get_by_barycentric_f(texture: &orbimage::Image, a: (f32, f32), b: (f32, f32), g: (f32, f32),
                                                 alpha: f32,    beta: f32,     gamma: f32,  ) -> orbclient::color::Color {

    let width = texture.width();
    let height = texture.height();
    let a = ((a.0 * width as f32) as u32, (a.1 * height as f32) as u32);
    let b = ((b.0 * width as f32) as u32, (b.1 * height as f32) as u32);
    let g = ((g.0 * width as f32) as u32, (g.1 * height as f32) as u32);

    get_by_barycentric(texture, a, b, g, alpha, beta, gamma)

}

pub trait GetColor {
    fn get(&self, alpha: f32, beta: f32, gamma: f32) -> orbclient::color::Color;
}

pub struct Texture<'a> {
    img: &'a orbimage::Image,
    map_alpha: (u32, u32),
    map_beta: (u32, u32),
    map_gamma: (u32, u32),
}

impl<'a> Texture<'a> {
    pub fn from_image(img: &'a orbimage::Image, map_alpha: (u32, u32), map_beta: (u32, u32), map_gamma: (u32, u32)) -> Texture<'a> {
        Texture {
            img: img,
            map_alpha: map_alpha,
            map_beta: map_beta,
            map_gamma: map_gamma,
        }
    }

    pub fn get(&self, alpha: f32, beta: f32, gamma: f32) -> orbclient::color::Color {
        get_by_barycentric(&self.img, self.map_alpha, self.map_beta, self.map_gamma, alpha, beta, gamma)
    }
}

impl<'a> GetColor for Texture<'a> {
    fn get(&self, alpha: f32, beta: f32, gamma: f32) -> orbclient::color::Color {
        get_by_barycentric(&self.img, self.map_alpha, self.map_beta, self.map_gamma, alpha, beta, gamma)
    }
}

pub struct FloatTexture<'a> {
    img: &'a orbimage::Image,
    map_alpha: (f32, f32),
    map_beta: (f32, f32),
    map_gamma: (f32, f32),
}

impl<'a> FloatTexture<'a> {
    pub fn from_image(img: &'a orbimage::Image, map_alpha: (f32, f32), map_beta: (f32, f32), map_gamma: (f32, f32)) -> FloatTexture<'a> {
        FloatTexture {
            img: img,
            map_alpha: map_alpha,
            map_beta: map_beta,
            map_gamma: map_gamma,
        }
    }
}

impl<'a> GetColor for FloatTexture<'a> {
    fn get(&self, alpha: f32, beta: f32, gamma: f32) -> orbclient::color::Color {
        get_by_barycentric_f(&self.img, self.map_alpha, self.map_beta, self.map_gamma, alpha, beta, gamma)
    }
}<|endoftext|>


<commit_before><commit_msg>Instead of using a single underscore to avoid warnings, prepend underscore to parameter names<commit_after><|endoftext|>


<commit_before><commit_msg>Note.<commit_after><|endoftext|>


<commit_before><commit_msg>Problem 23<commit_after>use std::rand::{task_rng, Rng};

fn rnd_select<'a, T: Clone>(list: &'a [T], n: uint) -> ~[&'a T] {
    task_rng().sample(list.iter(), n)
}

fn main() {
    let list = ~['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
    println!("{:?}", rnd_select(list, 3));
}

<|endoftext|>


<commit_before>use core::mem;

use redox::*;

use super::{XdrOps, XdrError, XdrResult};

pub struct MemOps {
    pos: usize,
    buffer: Vec<u8>,
}

impl XdrOps for MemOps {
    fn get_long(&mut self) -> XdrResult<usize> {
        if self.buffer.len()-self.pos < 4 {
            Err(XdrError)
        } else {
            let d: &usize = unsafe { mem::transmute(&self.buffer[self.pos]) };
            self.pos += 4;
            Ok(usize::from_be(*d))
        }
    }

    fn put_long(&mut self, l: usize) -> XdrResult<()> {
        Ok(())
    }

    fn get_i32(&mut self) -> XdrResult<i32> {
        Ok(0)
    }

    fn put_i32(&mut self, i: i32) -> XdrResult<()> {
        Ok(())
    }

    fn get_bytes(&mut self, bytes: &mut [u8]) -> XdrResult<()> {
        Ok(())
    }

    fn put_bytes(&mut self, bytes: &[u8]) -> XdrResult<()> {
        Ok(())
    }

    fn get_pos(&self) -> usize {
        self.pos
    }

    fn set_pos(&mut self, offset: usize) -> XdrResult<()> {
        Ok(())
    }

    fn destroy(&mut self) {
    }
}
<commit_msg>More MemOps stuff. Added a unit test<commit_after>use core::mem;

use redox::*;

use super::{XdrOps, XdrError, XdrResult};

pub struct MemOps {
    pos: usize,
    buffer: Vec<u8>,
}

impl MemOps {
    pub fn new(buffer: Vec<u8>) -> MemOps {
        MemOps {
            pos: 0,
            buffer: buffer,
        }
    }
}

impl XdrOps for MemOps {
    fn get_long(&mut self) -> XdrResult<usize> {
        if self.buffer.len()-self.pos < 4 {
            Err(XdrError)
        } else {
            let d: &usize = unsafe { mem::transmute(&self.buffer[self.pos]) };
            self.pos += 4;
            Ok(usize::from_be(*d))
        }
    }

    fn put_long(&mut self, l: usize) -> XdrResult<()> {
        Ok(())
    }

    fn get_i32(&mut self) -> XdrResult<i32> {
        if self.buffer.len()-self.pos < 4 {
            Err(XdrError)
        } else {
            let d: &i32 = unsafe { mem::transmute(&self.buffer[self.pos]) };
            self.pos += 4;
            Ok(i32::from_be(*d))
        }
    }

    fn put_i32(&mut self, i: i32) -> XdrResult<()> {
        Ok(())
    }

    fn get_bytes(&mut self, bytes: &mut [u8]) -> XdrResult<()> {
        Ok(())
    }

    fn put_bytes(&mut self, bytes: &[u8]) -> XdrResult<()> {
        Ok(())
    }

    fn get_pos(&self) -> usize {
        self.pos
    }

    fn set_pos(&mut self, new_pos: usize) -> XdrResult<()> {
        self.pos = new_pos;
        Ok(())
    }

    fn destroy(&mut self) {
    }
}

#[test]
fn test_mem_ops_u32() {
    let mem_ops = MemOps::new(vec![1, 1, 0, 0]);
    assert!(mem_ops.get_u32() == 257);
}
<|endoftext|>


<commit_before><commit_msg>Add problem #29<commit_after>use to_bytes::{ IterBytes, Cb };

extern mod std;
use std::map::{ HashMap, set_add};

extern mod euler;
use euler::prime::{ Prime, factors };

impl (uint, uint) : IterBytes {
    #[inline(always)]
    pure fn iter_bytes(++lsb0: bool, f: Cb) {
        if lsb0 {
            self.first().iter_bytes(lsb0, f);
            self.second().iter_bytes(lsb0, f);
        } else {
            self.second().iter_bytes(lsb0, f);
            self.first().iter_bytes(lsb0, f);
        }
    }
}

fn main() {
    let ps  = Prime();
    let set = HashMap::<~[(uint, uint)], ()>();

    for uint::range(2, 101) |a| {
        let mut fs = ~[];
        for factors(a, &ps) |f| {
            fs += ~[f];
        }
        for uint::range(2, 101) |b| {
            set_add(set, fs.map(|f| { (f.first(), f.second() * b) }));
        }
    }
    io::println(fmt!("%u", set.size()));
}
<|endoftext|>


<commit_before><commit_msg>Added some requested calculations methods (#303)<commit_after><|endoftext|>


<commit_before><commit_msg>practice<commit_after>fn diverges() -> ! {
    panic!("This function never returns");
}
fn main() {
    diverges();
}
<|endoftext|>


<commit_before>//! Definition of the Shared combinator, a future that is cloneable,
//! and can be polled in multiple threads.
//!
//! # Examples
//!
//! ```
//! use futures::future::*;
//!
//! let future = ok::<_, bool>(6);
//! let shared1 = future.shared();
//! let shared2 = shared1.clone();
//! assert_eq!(6, *shared1.wait().unwrap());
//! assert_eq!(6, *shared2.wait().unwrap());
//! ```

use std::mem;
use std::vec::Vec;
use std::sync::{Arc, RwLock};
use std::sync::atomic::{AtomicBool, Ordering};
use std::ops::Deref;

use {Future, Poll, Async};
use task::{self, Task};
use lock::Lock;

/// A future that is cloneable and can be polled in multiple threads.
/// Use Future::shared() method to convert any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F>
    where F: Future
{
    inner: Arc<Inner<F>>,
}

struct Inner<F>
    where F: Future
{
    /// The original future.
    original_future: Lock<F>,
    /// Indicates whether the result is ready, and the state is `State::Done`.
    result_ready: AtomicBool,
    /// The state of the shared future.
    state: RwLock<State<F::Item, F::Error>>,
}

/// The state of the shared future. It can be one of the following:
/// 1. Done - contains the result of the original future.
/// 2. Waiting - contains the waiting tasks.
enum State<T, E> {
    Waiting(Vec<Task>),
    Done(Result<SharedItem<T>, SharedError<E>>),
}

impl<F> Shared<F>
    where F: Future
{
    /// Creates a new `Shared` from another future.
    pub fn new(future: F) -> Self {
        Shared {
            inner: Arc::new(Inner {
                original_future: Lock::new(future),
                result_ready: AtomicBool::new(false),
                state: RwLock::new(State::Waiting(vec![])),
            }),
        }
    }

    /// Clones the result from self.inner.state.
    /// Assumes state is `State::Done`.
    fn read_result(&self) -> Result<Async<SharedItem<F::Item>>, SharedError<F::Error>> {
        match *self.inner.state.read().unwrap() {
            State::Done(ref result) => result.clone().map(Async::Ready),
            State::Waiting(_) => panic!("read_result() was called but State is not Done"),
        }
    }

    /// Stores the result in self.inner.state, unparks the waiting tasks,
    /// and returns the result.
    fn store_result(&self,
                    result: Result<SharedItem<F::Item>, SharedError<F::Error>>)
                    -> Result<Async<SharedItem<F::Item>>, SharedError<F::Error>> {
        let ref mut state = *self.inner.state.write().unwrap();

        match mem::replace(state, State::Done(result.clone())) {
            State::Waiting(waiters) => {
                self.inner.result_ready.store(true, Ordering::Relaxed);
                for task in waiters {
                    task.unpark();
                }
            }
            State::Done(_) => panic!("store_result() was called twice"),
        }

        result.map(Async::Ready)
    }
}

impl<F> Future for Shared<F>
    where F: Future
{
    type Item = SharedItem<F::Item>;
    type Error = SharedError<F::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // The logic is as follows:
        // 1. Check if the result is ready (with result_ready)
        //  - If the result is ready, return it.
        //  - Otherwise:
        // 2. Try lock the self.inner.original_future:
        //    - If successfully locked, check again if the result is ready.
        //      If it's ready, just return it.
        //      Otherwise, poll the original future.
        //      If the future is ready, unpark the waiting tasks from
        //      self.inner.state and return the result.
        //    - If the future is not ready, or if the lock failed:
        // 3. Lock the state for write.
        // 4. If the state is `State::Done`, return the result. Otherwise:
        // 5. Create a task, push it to the waiters vector, and return `Ok(Async::NotReady)`.

        // If the result is ready, just return it
        if self.inner.result_ready.load(Ordering::Relaxed) {
            return self.read_result();
        }

        // The result was not ready.
        // Try lock the original future.
        match self.inner.original_future.try_lock() {
            Some(mut original_future) => {
                // Other thread could already poll the result, so we check if result_ready.
                if self.inner.result_ready.load(Ordering::Relaxed) {
                    return self.read_result();
                }

                match original_future.poll() {
                    Ok(Async::Ready(item)) => {
                        return self.store_result(Ok(SharedItem::new(item)));
                    }
                    Err(error) => {
                        return self.store_result(Err(SharedError::new(error)));
                    }
                    Ok(Async::NotReady) => {} // A task will be parked
                }
            }
            None => {} // A task will be parked
        }

        let ref mut state = *self.inner.state.write().unwrap();
        match state {
            &mut State::Done(ref result) => return result.clone().map(Async::Ready),
            &mut State::Waiting(ref mut waiters) => {
                waiters.push(task::park());
            }
        }

        Ok(Async::NotReady)
    }
}

impl<F> Clone for Shared<F>
    where F: Future
{
    fn clone(&self) -> Self {
        Shared { inner: self.inner.clone() }
    }
}

/// A wrapped item of the original future.
/// It is clonable and implements Deref for ease of use.
#[derive(Debug)]
pub struct SharedItem<T> {
    item: Arc<T>,
}

impl<T> SharedItem<T> {
    fn new(item: T) -> Self {
        SharedItem { item: Arc::new(item) }
    }
}

impl<T> Clone for SharedItem<T> {
    fn clone(&self) -> Self {
        SharedItem { item: self.item.clone() }
    }
}

impl<T> Deref for SharedItem<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.item.as_ref()
    }
}

/// A wrapped error of the original future.
/// It is clonable and implements Deref for ease of use.
#[derive(Debug)]
pub struct SharedError<E> {
    error: Arc<E>,
}

impl<E> SharedError<E> {
    fn new(error: E) -> Self {
        SharedError { error: Arc::new(error) }
    }
}

impl<T> Clone for SharedError<T> {
    fn clone(&self) -> Self {
        SharedError { error: self.error.clone() }
    }
}

impl<E> Deref for SharedError<E> {
    type Target = E;

    fn deref(&self) -> &E {
        &self.error.as_ref()
    }
}
<commit_msg>Store original_future as Option and set it to None when the result is ready<commit_after>//! Definition of the Shared combinator, a future that is cloneable,
//! and can be polled in multiple threads.
//!
//! # Examples
//!
//! ```
//! use futures::future::*;
//!
//! let future = ok::<_, bool>(6);
//! let shared1 = future.shared();
//! let shared2 = shared1.clone();
//! assert_eq!(6, *shared1.wait().unwrap());
//! assert_eq!(6, *shared2.wait().unwrap());
//! ```

use std::mem;
use std::vec::Vec;
use std::sync::{Arc, RwLock};
use std::sync::atomic::{AtomicBool, Ordering};
use std::ops::Deref;

use {Future, Poll, Async};
use task::{self, Task};
use lock::Lock;

/// A future that is cloneable and can be polled in multiple threads.
/// Use Future::shared() method to convert any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F>
    where F: Future
{
    inner: Arc<Inner<F>>,
}

struct Inner<F>
    where F: Future
{
    /// The original future.
    original_future: Lock<Option<F>>,
    /// Indicates whether the result is ready, and the state is `State::Done`.
    result_ready: AtomicBool,
    /// The state of the shared future.
    state: RwLock<State<F::Item, F::Error>>,
}

/// The state of the shared future. It can be one of the following:
/// 1. Done - contains the result of the original future.
/// 2. Waiting - contains the waiting tasks.
enum State<T, E> {
    Waiting(Vec<Task>),
    Done(Result<SharedItem<T>, SharedError<E>>),
}

impl<F> Shared<F>
    where F: Future
{
    /// Creates a new `Shared` from another future.
    pub fn new(future: F) -> Self {
        Shared {
            inner: Arc::new(Inner {
                original_future: Lock::new(Some(future)),
                result_ready: AtomicBool::new(false),
                state: RwLock::new(State::Waiting(vec![])),
            }),
        }
    }

    /// Clones the result from self.inner.state.
    /// Assumes state is `State::Done`.
    fn read_result(&self) -> Result<Async<SharedItem<F::Item>>, SharedError<F::Error>> {
        match *self.inner.state.read().unwrap() {
            State::Done(ref result) => result.clone().map(Async::Ready),
            State::Waiting(_) => panic!("read_result() was called but State is not Done"),
        }
    }

    /// Stores the result in self.inner.state, unparks the waiting tasks,
    /// and returns the result.
    fn store_result(&self,
                    result: Result<SharedItem<F::Item>, SharedError<F::Error>>)
                    -> Result<Async<SharedItem<F::Item>>, SharedError<F::Error>> {
        let ref mut state = *self.inner.state.write().unwrap();

        match mem::replace(state, State::Done(result.clone())) {
            State::Waiting(waiters) => {
                self.inner.result_ready.store(true, Ordering::Relaxed);
                for task in waiters {
                    task.unpark();
                }
            }
            State::Done(_) => panic!("store_result() was called twice"),
        }

        result.map(Async::Ready)
    }
}

impl<F> Future for Shared<F>
    where F: Future
{
    type Item = SharedItem<F::Item>;
    type Error = SharedError<F::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // The logic is as follows:
        // 1. Check if the result is ready (with result_ready)
        //  - If the result is ready, return it.
        //  - Otherwise:
        // 2. Try lock the self.inner.original_future:
        //    - If successfully locked, check again if the result is ready.
        //      If it's ready, just return it.
        //      Otherwise, poll the original future.
        //      If the future is ready, unpark the waiting tasks from
        //      self.inner.state and return the result.
        //    - If the future is not ready, or if the lock failed:
        // 3. Lock the state for write.
        // 4. If the state is `State::Done`, return the result. Otherwise:
        // 5. Create a task, push it to the waiters vector, and return `Ok(Async::NotReady)`.

        // If the result is ready, just return it
        if self.inner.result_ready.load(Ordering::Relaxed) {
            return self.read_result();
        }

        // The result was not ready.
        // Try lock the original future.
        match self.inner.original_future.try_lock() {
            Some(mut original_future_option) => {
                // Other thread could already poll the result, so we check if result_ready.
                if self.inner.result_ready.load(Ordering::Relaxed) {
                    return self.read_result();
                }

                let mut result = None;
                match *original_future_option {
                    Some(ref mut original_future) => {
                        match original_future.poll() {
                            Ok(Async::Ready(item)) => {
                                result = Some(self.store_result(Ok(SharedItem::new(item))));
                            }
                            Err(error) => {
                                result = Some(self.store_result(Err(SharedError::new(error))));
                            }
                            Ok(Async::NotReady) => {} // A task will be parked
                        }
                    }
                    None => panic!("result_ready is false but original_future is None"),
                }

                if let Some(result) = result {
                    *original_future_option = None;
                    return result;
                }
            }
            None => {} // A task will be parked
        }

        let ref mut state = *self.inner.state.write().unwrap();
        match state {
            &mut State::Done(ref result) => return result.clone().map(Async::Ready),
            &mut State::Waiting(ref mut waiters) => {
                waiters.push(task::park());
            }
        }

        Ok(Async::NotReady)
    }
}

impl<F> Clone for Shared<F>
    where F: Future
{
    fn clone(&self) -> Self {
        Shared { inner: self.inner.clone() }
    }
}

/// A wrapped item of the original future.
/// It is clonable and implements Deref for ease of use.
#[derive(Debug)]
pub struct SharedItem<T> {
    item: Arc<T>,
}

impl<T> SharedItem<T> {
    fn new(item: T) -> Self {
        SharedItem { item: Arc::new(item) }
    }
}

impl<T> Clone for SharedItem<T> {
    fn clone(&self) -> Self {
        SharedItem { item: self.item.clone() }
    }
}

impl<T> Deref for SharedItem<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.item.as_ref()
    }
}

/// A wrapped error of the original future.
/// It is clonable and implements Deref for ease of use.
#[derive(Debug)]
pub struct SharedError<E> {
    error: Arc<E>,
}

impl<E> SharedError<E> {
    fn new(error: E) -> Self {
        SharedError { error: Arc::new(error) }
    }
}

impl<T> Clone for SharedError<T> {
    fn clone(&self) -> Self {
        SharedError { error: self.error.clone() }
    }
}

impl<E> Deref for SharedError<E> {
    type Target = E;

    fn deref(&self) -> &E {
        &self.error.as_ref()
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove unused internal method.<commit_after><|endoftext|>


<commit_before>use std::old_io::{fs, IoResult};
use file::{File, GREY};

#[cfg(feature="git")] use ansi_term::{ANSIString, ANSIStrings};
#[cfg(feature="git")] use ansi_term::Colour::*;
#[cfg(feature="git")] use git2;

/// A **Dir** provides a cached list of the file paths in a directory that's
/// being listed.
///
/// This object gets passed to the Files themselves, in order for them to
/// check the existence of surrounding files, then highlight themselves
/// accordingly. (See `File#get_source_files`)
pub struct Dir {
    contents: Vec<Path>,
    path: Path,
    git: Option<Git>,
}

impl Dir {
    /// Create a new Dir object filled with all the files in the directory
    /// pointed to by the given path. Fails if the directory can't be read, or
    /// isn't actually a directory.
    pub fn readdir(path: &Path) -> IoResult<Dir> {
        fs::readdir(path).map(|paths| Dir {
            contents: paths,
            path: path.clone(),
            git: Git::scan(path).ok(),
        })
    }

    /// Produce a vector of File objects from an initialised directory,
    /// printing out an error if any of the Files fail to be created.
    ///
    /// Passing in `recurse` means that any directories will be scanned for
    /// their contents, as well.
    pub fn files(&self, recurse: bool) -> Vec<File> {
        let mut files = vec![];

        for path in self.contents.iter() {
            match File::from_path(path, Some(self), recurse) {
                Ok(file) => files.push(file),
                Err(e)   => println!("{}: {}", path.display(), e),
            }
        }

        files
    }

    /// Whether this directory contains a file with the given path.
    pub fn contains(&self, path: &Path) -> bool {
        self.contents.contains(path)
    }

    /// Append a path onto the path specified by this directory.
    pub fn join(&self, child: Path) -> Path {
        self.path.join(child)
    }

    /// Return whether there's a Git repository on or above this directory.
    pub fn has_git_repo(&self) -> bool {
        self.git.is_some()
    }

    /// Get a string describing the Git status of the given file.
    pub fn git_status(&self, path: &Path, prefix_lookup: bool) -> String {
        match (&self.git, prefix_lookup) {
            (&Some(ref git), false) => git.status(path),
            (&Some(ref git), true)  => git.dir_status(path),
            (&None, _)              => GREY.paint("--").to_string(),
        }
    }
}

/// Container of Git statuses for all the files in this folder's Git repository.
#[cfg(feature="git")]
struct Git {
    statuses: Vec<(Path, git2::Status)>,
}

#[cfg(feature="git")]
impl Git {

    /// Discover a Git repository on or above this directory, scanning it for
    /// the files' statuses if one is found.
    fn scan(path: &Path) -> Result<Git, git2::Error> {
        use std::os::unix::OsStrExt;
        use std::ffi::AsOsStr;

        // TODO: libgit2-rs uses the new Path module, but exa still uses the
        // old_path one, and will have to continue to do so until the new IO
        // module gets a bit more developed. So we have to turn Paths into
        // old_path::Paths. Yes, this is hacky, but hopefully temporary.
        let repo = try!(git2::Repository::discover(path));
        let workdir = match repo.workdir() {
            Some(w) => Path::new(w.as_os_str().as_bytes()),
            None => return Ok(Git { statuses: vec![] }),  // bare repo
        };

        let statuses = try!(repo.statuses(None)).iter()
                                                .map(|e| (workdir.join(e.path_bytes()), e.status()))
                                                .collect();
        Ok(Git { statuses: statuses })
    }

    /// Get the status for the file at the given path, if present.
    fn status(&self, path: &Path) -> String {
        let status = self.statuses.iter()
                                  .find(|p| &p.0 == path);
        match status {
            Some(&(_, s)) => ANSIStrings( &[Git::index_status(s), Git::working_tree_status(s) ]).to_string(),
            None => GREY.paint("--").to_string(),
        }
    }

    /// Get the combined status for all the files whose paths begin with the
    /// path that gets passed in. This is used for getting the status of
    /// directories, which don't really have an 'official' status.
    fn dir_status(&self, dir: &Path) -> String {
        let s = self.statuses.iter()
                             .filter(|p| dir.is_ancestor_of(&p.0))
                             .fold(git2::Status::empty(), |a, b| a | b.1);

        ANSIStrings( &[Git::index_status(s), Git::working_tree_status(s)] ).to_string()
    }

    /// The character to display if the file has been modified, but not staged.
    fn working_tree_status(status: git2::Status) -> ANSIString<'static> {
        match status {
            s if s.contains(git2::STATUS_WT_NEW) => Green.paint("A"),
            s if s.contains(git2::STATUS_WT_MODIFIED) => Blue.paint("M"),
            s if s.contains(git2::STATUS_WT_DELETED) => Red.paint("D"),
            s if s.contains(git2::STATUS_WT_RENAMED) => Yellow.paint("R"),
            s if s.contains(git2::STATUS_WT_TYPECHANGE) => Purple.paint("T"),
            _ => GREY.paint("-"),
        }
    }

    /// The character to display if the file has been modified, and the change
    /// has been staged.
    fn index_status(status: git2::Status) -> ANSIString<'static> {
        match status {
            s if s.contains(git2::STATUS_INDEX_NEW) => Green.paint("A"),
            s if s.contains(git2::STATUS_INDEX_MODIFIED) => Blue.paint("M"),
            s if s.contains(git2::STATUS_INDEX_DELETED) => Red.paint("D"),
            s if s.contains(git2::STATUS_INDEX_RENAMED) => Yellow.paint("R"),
            s if s.contains(git2::STATUS_INDEX_TYPECHANGE) => Purple.paint("T"),
            _ => GREY.paint("-"),
        }
    }
}

#[cfg(not(feature="git"))]
struct Git;

#[cfg(not(feature="git"))]
impl Git {
    fn scan(_: &Path) -> Result<Git, ()> {
        // Don't do anything without Git support
        Err(())
    }

    fn status(&self, _: &Path) -> String {
        // The Err above means that this should never happen
        panic!("Tried to access a Git repo without Git support!");
    }

    fn dir_status(&self, path: &Path) -> String {
        self.status(path)
    }
}
<commit_msg>Apparently std::os::unix::osStrExt is now std::os::unix::ffi::OsStrExt.<commit_after>use std::old_io::{fs, IoResult};
use file::{File, GREY};

#[cfg(feature="git")] use ansi_term::{ANSIString, ANSIStrings};
#[cfg(feature="git")] use ansi_term::Colour::*;
#[cfg(feature="git")] use git2;

/// A **Dir** provides a cached list of the file paths in a directory that's
/// being listed.
///
/// This object gets passed to the Files themselves, in order for them to
/// check the existence of surrounding files, then highlight themselves
/// accordingly. (See `File#get_source_files`)
pub struct Dir {
    contents: Vec<Path>,
    path: Path,
    git: Option<Git>,
}

impl Dir {
    /// Create a new Dir object filled with all the files in the directory
    /// pointed to by the given path. Fails if the directory can't be read, or
    /// isn't actually a directory.
    pub fn readdir(path: &Path) -> IoResult<Dir> {
        fs::readdir(path).map(|paths| Dir {
            contents: paths,
            path: path.clone(),
            git: Git::scan(path).ok(),
        })
    }

    /// Produce a vector of File objects from an initialised directory,
    /// printing out an error if any of the Files fail to be created.
    ///
    /// Passing in `recurse` means that any directories will be scanned for
    /// their contents, as well.
    pub fn files(&self, recurse: bool) -> Vec<File> {
        let mut files = vec![];

        for path in self.contents.iter() {
            match File::from_path(path, Some(self), recurse) {
                Ok(file) => files.push(file),
                Err(e)   => println!("{}: {}", path.display(), e),
            }
        }

        files
    }

    /// Whether this directory contains a file with the given path.
    pub fn contains(&self, path: &Path) -> bool {
        self.contents.contains(path)
    }

    /// Append a path onto the path specified by this directory.
    pub fn join(&self, child: Path) -> Path {
        self.path.join(child)
    }

    /// Return whether there's a Git repository on or above this directory.
    pub fn has_git_repo(&self) -> bool {
        self.git.is_some()
    }

    /// Get a string describing the Git status of the given file.
    pub fn git_status(&self, path: &Path, prefix_lookup: bool) -> String {
        match (&self.git, prefix_lookup) {
            (&Some(ref git), false) => git.status(path),
            (&Some(ref git), true)  => git.dir_status(path),
            (&None, _)              => GREY.paint("--").to_string(),
        }
    }
}

/// Container of Git statuses for all the files in this folder's Git repository.
#[cfg(feature="git")]
struct Git {
    statuses: Vec<(Path, git2::Status)>,
}

#[cfg(feature="git")]
impl Git {

    /// Discover a Git repository on or above this directory, scanning it for
    /// the files' statuses if one is found.
    fn scan(path: &Path) -> Result<Git, git2::Error> {
        use std::os::unix::ffi::OsStrExt;
        use std::ffi::AsOsStr;

        // TODO: libgit2-rs uses the new Path module, but exa still uses the
        // old_path one, and will have to continue to do so until the new IO
        // module gets a bit more developed. So we have to turn Paths into
        // old_path::Paths. Yes, this is hacky, but hopefully temporary.
        let repo = try!(git2::Repository::discover(path));
        let workdir = match repo.workdir() {
            Some(w) => Path::new(w.as_os_str().as_bytes()),
            None => return Ok(Git { statuses: vec![] }),  // bare repo
        };

        let statuses = try!(repo.statuses(None)).iter()
                                                .map(|e| (workdir.join(e.path_bytes()), e.status()))
                                                .collect();
        Ok(Git { statuses: statuses })
    }

    /// Get the status for the file at the given path, if present.
    fn status(&self, path: &Path) -> String {
        let status = self.statuses.iter()
                                  .find(|p| &p.0 == path);
        match status {
            Some(&(_, s)) => ANSIStrings( &[Git::index_status(s), Git::working_tree_status(s) ]).to_string(),
            None => GREY.paint("--").to_string(),
        }
    }

    /// Get the combined status for all the files whose paths begin with the
    /// path that gets passed in. This is used for getting the status of
    /// directories, which don't really have an 'official' status.
    fn dir_status(&self, dir: &Path) -> String {
        let s = self.statuses.iter()
                             .filter(|p| dir.is_ancestor_of(&p.0))
                             .fold(git2::Status::empty(), |a, b| a | b.1);

        ANSIStrings( &[Git::index_status(s), Git::working_tree_status(s)] ).to_string()
    }

    /// The character to display if the file has been modified, but not staged.
    fn working_tree_status(status: git2::Status) -> ANSIString<'static> {
        match status {
            s if s.contains(git2::STATUS_WT_NEW) => Green.paint("A"),
            s if s.contains(git2::STATUS_WT_MODIFIED) => Blue.paint("M"),
            s if s.contains(git2::STATUS_WT_DELETED) => Red.paint("D"),
            s if s.contains(git2::STATUS_WT_RENAMED) => Yellow.paint("R"),
            s if s.contains(git2::STATUS_WT_TYPECHANGE) => Purple.paint("T"),
            _ => GREY.paint("-"),
        }
    }

    /// The character to display if the file has been modified, and the change
    /// has been staged.
    fn index_status(status: git2::Status) -> ANSIString<'static> {
        match status {
            s if s.contains(git2::STATUS_INDEX_NEW) => Green.paint("A"),
            s if s.contains(git2::STATUS_INDEX_MODIFIED) => Blue.paint("M"),
            s if s.contains(git2::STATUS_INDEX_DELETED) => Red.paint("D"),
            s if s.contains(git2::STATUS_INDEX_RENAMED) => Yellow.paint("R"),
            s if s.contains(git2::STATUS_INDEX_TYPECHANGE) => Purple.paint("T"),
            _ => GREY.paint("-"),
        }
    }
}

#[cfg(not(feature="git"))]
struct Git;

#[cfg(not(feature="git"))]
impl Git {
    fn scan(_: &Path) -> Result<Git, ()> {
        // Don't do anything without Git support
        Err(())
    }

    fn status(&self, _: &Path) -> String {
        // The Err above means that this should never happen
        panic!("Tried to access a Git repo without Git support!");
    }

    fn dir_status(&self, path: &Path) -> String {
        self.status(path)
    }
}
<|endoftext|>


<commit_before><commit_msg>Added SubCommand examples<commit_after>extern crate clap;

use clap::{App, Arg, SubCommand};

fn main() {

	// SubCommands function exactly like sub-Apps, because that's exactly what they are. Each
	// instance of a SubCommand can have it's own version, author(s), Args, and even it's own
	// subcommands.
	//
	// # Help and Version
	// Just like Apps, each subcommand will get it's own "help" and "version" flags automatically
	// generated. Also, like Apps, you can override "-v" or "-h" safely and still get "--help" and
	// "--version" auto generated.
	//
	// NOTE: If you specify a subcommand for your App, clap will also autogenerate a "help"
	// subcommand along with "-h" and "--help" (applies to sub-subcommands as well).
	//
	// Just like arg() and args(), subcommands can be specified one at a time via subcommand() or
	// multiple ones at once with a Vec<SubCommand> provided to subcommands().
    let matches = App::new("MyApp")
    					// Normal App and Arg configuration goes here...

    					// In the following example assume we wanted an application which
    					// supported an "add" subcommand, this "add" subcommand also took
    					// one positional argument of a file to add:
    					.subcommand(SubCommand::new("add")								// The name we call argument with
    											.about("Adds files to myapp")		    // The message displayed in "myapp -h"
    																					// or "myapp help"
    											.version("0.1")							// Subcommands can have independant version
    											.author("Kevin K.")						// And authors
    											.arg(Arg::new("input")					// And their own arguments
    														.help("the file to add")
    														.index(1)
    														.required(true)))
                        .get_matches();

    // You can check if a subcommand was used like normal
    if matches.is_present("add") {
    	println!("'myapp add' was run.");
    }

    // You can get the independant subcommand matches (which function exactly like App matches)
    if let Some(ref matches) = matches.subcommand_matches("add") {
    	// Safe to use unwrap() becasue of the required() option
    	println!("Adding file: {}", matches.value_of("input").unwrap());
    }

    // You can also match on a subcommand's name
    match matches.subcommand_name() {
    	Some("add") => println!("'myapp add' was used"),
    	None        => println!("No subcommand was used"),
    	_			=> println!("Some other subcommand was used"),
    }

    // Continued program logic goes here...
}
<|endoftext|>