<commit_before>use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fs::File as FSFile;
use std::ops::Deref;
use std::io::Write;
use std::io::Read;

pub mod path;
pub mod file;
pub mod parser;
pub mod json;

use module::Module;
use runtime::Runtime;
use storage::file::File;
use storage::file::id::FileID;
use storage::file::id_type::FileIDType;
use storage::file::hash::FileHash;
use storage::parser::{FileHeaderParser, Parser, ParserError};
use storage::file::header::data::FileHeaderData;

type Cache = HashMap<FileID, Rc<RefCell<File>>>;

pub struct Store {
    storepath: String,
    cache : RefCell<Cache>,
}

/**
 * Store object
 *
 * This object is an abstraction layer over FS and an interface to the object store of this
 * software.
 */
impl Store {

    pub fn new(storepath: String) -> Store {
        Store {
            storepath: storepath,
            cache: RefCell::new(HashMap::new()),
        }
    }

    /**
     * Put a file into the cache
     */
    fn put_in_cache(&self, f: File) -> FileID {
        let res = f.id().clone();
        self.cache.borrow_mut().insert(f.id().clone(), Rc::new(RefCell::new(f)));
        res
    }

    /**
     * Generate a new file for a module.
     *
     * Returns the new FileID object then
     */
    pub fn new_file(&self, module: &Module)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: FileHeaderData::Null,
            data: String::from(""),
            id: self.get_new_file_id(),
        };

        debug!("Create new File object: {:?}", &f);
        self.put_in_cache(f)
    }

    /**
     * Generate a new file from a parser result.
     *
     * @deprecated This function shouldn't be needed anymore
     */
    pub fn new_file_from_parser_result(&self,
                                       module: &Module,
                                       id: FileID,
                                       header: FileHeaderData,
                                       data: String)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: header,
            data: data,
            id: id,
        };
        debug!("Create new File object from parser result: {:?}", f);
        self.put_in_cache(f)
    }

    /**
     * Generate a new file for a module, providing some header data
     *
     * Returns the new FileID object then
     */
    pub fn new_file_with_header(&self,
                                module: &Module,
                                h: FileHeaderData)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: h,
            data: String::from(""),
            id: self.get_new_file_id(),
        };
        debug!("Create new File object with header: {:?}", f);
        self.put_in_cache(f)
    }

    /**
     * Generate a new file for a module, providing some initial data
     *
     * Returns the new FileID object then
     */
    pub fn new_file_with_data(&self, module: &Module, d: String)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: FileHeaderData::Null,
            data: d,
            id: self.get_new_file_id(),
        };
        debug!("Create new File object with data: {:?}", f);
        self.put_in_cache(f)
    }

    /**
     * Generate a new file for a module, providing some initial data and some header
     *
     * Returns the new FileID object then
     */
    pub fn new_file_with_content(&self,
                                 module: &Module,
                                 h: FileHeaderData,
                                 d: String)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: h,
            data: d,
            id: self.get_new_file_id(),
        };
        debug!("Create new File object with content: {:?}", f);
        self.put_in_cache(f)
    }

    /**
     * Persist a File on the filesystem
     *
     * Returns true if this worked
     */
    pub fn persist<HP>(&self,
                       p: &Parser<HP>,
                       f: Rc<RefCell<File>>) -> bool
        where HP: FileHeaderParser
    {
        let file = f.deref().borrow();
        let text = p.write(file.contents());
        if text.is_err() {
            error!("Error: {}", text.err().unwrap());
            return false;
        }

        let path = {
            let ids : String = file.id().clone().into();
            format!("{}/{}-{}.imag", self.storepath, file.owning_module_name, ids)
        };

        self.ensure_store_path_exists();

        FSFile::create(&path).map(|mut fsfile| {
            fsfile.write_all(&text.unwrap().clone().into_bytes()[..])
        }).map_err(|writeerr|  {
            debug!("Could not create file at '{}'", path);
        }).and(Ok(true)).unwrap()

        // TODO: Is this unwrap() save?
    }

    /**
     * Helper to generate the store path
     *
     * Kills the program if it fails
     */
    fn ensure_store_path_exists(&self) {
        use std::fs::create_dir_all;
        use std::process::exit;

        create_dir_all(&self.storepath).unwrap_or_else(|e| {
            error!("Could not create store: '{}'", self.storepath);
            error!("Error                 : '{}'", e);
            error!("Killing myself now");
            exit(1);
        })
    }

    /**
     * Load a file by ID into the cache and return it afterwards
     *
     * Returns None if the file could be loaded from the Filesystem
     */
    fn load_into_cache<HP>(&self, m: &Module, parser: &Parser<HP>, id: &FileID)
        -> bool
        where HP: FileHeaderParser
    {
        let idstr : String = id.clone().into();
        let path = format!("{}/{}-{}.imag", self.storepath, m.name(), idstr);
        debug!("Loading path = '{}'", path);
        let mut string = String::new();

        FSFile::open(&path).map(|mut file| {
            file.read_to_string(&mut string)
                .map_err(|e| error!("Failed reading file: '{}'", path));
        });

        parser.read(string).map(|(header, data)| {
            self.new_file_from_parser_result(m, id.clone(), header, data);
            true
        }).unwrap_or(false)
    }

    /**
     * Load a file from the cache by FileID
     *
     * TODO: Semantics: This function should load from FS if the file is not in the cache yet or
     * fail if the file is not available.
     */
    pub fn load<HP>(&self, m: &Module, parser: &Parser<HP>, id: &FileID)
        -> Option<Rc<RefCell<File>>>
        where HP: FileHeaderParser
    {
        if !self.cache.borrow().contains_key(id) {
            self.load_into_cache(m, parser, id);
        }
        debug!("Loading '{:?}'", id);
        self.cache.borrow().get(id).cloned()
    }

    /**
     * Load a file from the filesystem/cache by a FileHash
     */
    pub fn load_by_hash<HP>(&self,
                            m: &Module,
                            parser: &Parser<HP>,
                            hash: FileHash)
        -> Option<Rc<RefCell<File>>>
        where HP: FileHeaderParser
    {
        macro_rules! try_some {
            ($expr:expr) => (match $expr {
                ::std::option::Option::Some(val) => val,
                ::std::option::Option::None => return ::std::option::Option::None,
            });

            ($expr:expr => return) => (match $expr {
                ::std::option::Option::Some(val) => val,
                ::std::option::Option::None => return,
            })
        }

        use glob::{glob, Paths, PatternError};

        let hashstr : String = hash.into();
        let globstr = format!("{}/*-{}.imag", self.storepath, hashstr);
        debug!("glob({})", globstr);

        let globs = glob(&globstr[..]);
        if globs.is_err() {
            return None;
        }

        let path = globs.unwrap().last();
        debug!("path = {:?}", path);

        let pathbuf = try_some!(path);
        if pathbuf.is_err() { return None; }

        let pathbuf_un  = pathbuf.unwrap();
        let filename    = pathbuf_un.file_name();
        let s           = try_some!(filename).to_str();
        let string      = String::from(try_some!(s));
        let id          = try_some!(FileID::parse(&string));

        debug!("Loaded ID = '{:?}'", id);

        self.load(m, parser, &id)
    }

    /**
     * Remove a file from the filesystem by FileID
     *
     * Returns true if this works.
     */
    pub fn remove(&self, id: FileID) -> bool {
        use std::fs::remove_file;

        self.cache
            .borrow_mut()
            .remove(&id)
            .map(|file| {
                let idstr : String = id.into();
                let path = format!("{}/{}-{}.imag",
                                   self.storepath,
                                   file.deref().borrow().owner_name(),
                                   idstr);
                debug!("Removing file NOW: '{}'", path);
                remove_file(path).is_ok()
            })
            .unwrap_or(false)
    }

    /**
     * Load all files for a module
     */
    pub fn load_for_module<HP>(&self, m: &Module, parser: &Parser<HP>)
        -> Vec<Rc<RefCell<File>>>
        where HP: FileHeaderParser
    {
        use glob::{glob, Paths, PatternError};

        let globstr = format!("{}/{}-*.imag", self.storepath, m.name());
        let mut res = vec![];

        glob(&globstr[..]).map(|paths| {
            for path in paths {
                if let Ok(pathbuf) = path {
                    let fname = pathbuf.file_name().and_then(|s| s.to_str());
                    fname.map(|s| {
                        FileID::parse(&String::from(s)).map(|id| {
                            self.load(m, parser, &id).map(|file| {
                                res.push(file);
                            })
                        });
                    });
                }
            }
        });
        res
    }

    /**
     * Helper to generate a new FileID object
     */
    fn get_new_file_id(&self) -> FileID {
        use uuid::Uuid;
        let hash = FileHash::from(Uuid::new_v4().to_hyphenated_string());
        FileID::new(FileIDType::UUID, hash)
    }

}
<commit_msg>Store::remove(): Move function so we have a better order<commit_after>use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fs::File as FSFile;
use std::ops::Deref;
use std::io::Write;
use std::io::Read;

pub mod path;
pub mod file;
pub mod parser;
pub mod json;

use module::Module;
use runtime::Runtime;
use storage::file::File;
use storage::file::id::FileID;
use storage::file::id_type::FileIDType;
use storage::file::hash::FileHash;
use storage::parser::{FileHeaderParser, Parser, ParserError};
use storage::file::header::data::FileHeaderData;

type Cache = HashMap<FileID, Rc<RefCell<File>>>;

pub struct Store {
    storepath: String,
    cache : RefCell<Cache>,
}

/**
 * Store object
 *
 * This object is an abstraction layer over FS and an interface to the object store of this
 * software.
 */
impl Store {

    pub fn new(storepath: String) -> Store {
        Store {
            storepath: storepath,
            cache: RefCell::new(HashMap::new()),
        }
    }

    /**
     * Put a file into the cache
     */
    fn put_in_cache(&self, f: File) -> FileID {
        let res = f.id().clone();
        self.cache.borrow_mut().insert(f.id().clone(), Rc::new(RefCell::new(f)));
        res
    }

    /**
     * Generate a new file for a module.
     *
     * Returns the new FileID object then
     */
    pub fn new_file(&self, module: &Module)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: FileHeaderData::Null,
            data: String::from(""),
            id: self.get_new_file_id(),
        };

        debug!("Create new File object: {:?}", &f);
        self.put_in_cache(f)
    }

    /**
     * Generate a new file from a parser result.
     *
     * @deprecated This function shouldn't be needed anymore
     */
    pub fn new_file_from_parser_result(&self,
                                       module: &Module,
                                       id: FileID,
                                       header: FileHeaderData,
                                       data: String)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: header,
            data: data,
            id: id,
        };
        debug!("Create new File object from parser result: {:?}", f);
        self.put_in_cache(f)
    }

    /**
     * Generate a new file for a module, providing some header data
     *
     * Returns the new FileID object then
     */
    pub fn new_file_with_header(&self,
                                module: &Module,
                                h: FileHeaderData)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: h,
            data: String::from(""),
            id: self.get_new_file_id(),
        };
        debug!("Create new File object with header: {:?}", f);
        self.put_in_cache(f)
    }

    /**
     * Generate a new file for a module, providing some initial data
     *
     * Returns the new FileID object then
     */
    pub fn new_file_with_data(&self, module: &Module, d: String)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: FileHeaderData::Null,
            data: d,
            id: self.get_new_file_id(),
        };
        debug!("Create new File object with data: {:?}", f);
        self.put_in_cache(f)
    }

    /**
     * Generate a new file for a module, providing some initial data and some header
     *
     * Returns the new FileID object then
     */
    pub fn new_file_with_content(&self,
                                 module: &Module,
                                 h: FileHeaderData,
                                 d: String)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: h,
            data: d,
            id: self.get_new_file_id(),
        };
        debug!("Create new File object with content: {:?}", f);
        self.put_in_cache(f)
    }

    /**
     * Persist a File on the filesystem
     *
     * Returns true if this worked
     */
    pub fn persist<HP>(&self,
                       p: &Parser<HP>,
                       f: Rc<RefCell<File>>) -> bool
        where HP: FileHeaderParser
    {
        let file = f.deref().borrow();
        let text = p.write(file.contents());
        if text.is_err() {
            error!("Error: {}", text.err().unwrap());
            return false;
        }

        let path = {
            let ids : String = file.id().clone().into();
            format!("{}/{}-{}.imag", self.storepath, file.owning_module_name, ids)
        };

        self.ensure_store_path_exists();

        FSFile::create(&path).map(|mut fsfile| {
            fsfile.write_all(&text.unwrap().clone().into_bytes()[..])
        }).map_err(|writeerr|  {
            debug!("Could not create file at '{}'", path);
        }).and(Ok(true)).unwrap()

        // TODO: Is this unwrap() save?
    }

    /**
     * Helper to generate the store path
     *
     * Kills the program if it fails
     */
    fn ensure_store_path_exists(&self) {
        use std::fs::create_dir_all;
        use std::process::exit;

        create_dir_all(&self.storepath).unwrap_or_else(|e| {
            error!("Could not create store: '{}'", self.storepath);
            error!("Error                 : '{}'", e);
            error!("Killing myself now");
            exit(1);
        })
    }

    /**
     * Load a file by ID into the cache and return it afterwards
     *
     * Returns None if the file could be loaded from the Filesystem
     */
    fn load_into_cache<HP>(&self, m: &Module, parser: &Parser<HP>, id: &FileID)
        -> bool
        where HP: FileHeaderParser
    {
        let idstr : String = id.clone().into();
        let path = format!("{}/{}-{}.imag", self.storepath, m.name(), idstr);
        debug!("Loading path = '{}'", path);
        let mut string = String::new();

        FSFile::open(&path).map(|mut file| {
            file.read_to_string(&mut string)
                .map_err(|e| error!("Failed reading file: '{}'", path));
        });

        parser.read(string).map(|(header, data)| {
            self.new_file_from_parser_result(m, id.clone(), header, data);
            true
        }).unwrap_or(false)
    }

    /**
     * Load a file from the cache by FileID
     *
     * TODO: Semantics: This function should load from FS if the file is not in the cache yet or
     * fail if the file is not available.
     */
    pub fn load<HP>(&self, m: &Module, parser: &Parser<HP>, id: &FileID)
        -> Option<Rc<RefCell<File>>>
        where HP: FileHeaderParser
    {
        if !self.cache.borrow().contains_key(id) {
            self.load_into_cache(m, parser, id);
        }
        debug!("Loading '{:?}'", id);
        self.cache.borrow().get(id).cloned()
    }

    /**
     * Load a file from the filesystem/cache by a FileHash
     */
    pub fn load_by_hash<HP>(&self,
                            m: &Module,
                            parser: &Parser<HP>,
                            hash: FileHash)
        -> Option<Rc<RefCell<File>>>
        where HP: FileHeaderParser
    {
        macro_rules! try_some {
            ($expr:expr) => (match $expr {
                ::std::option::Option::Some(val) => val,
                ::std::option::Option::None => return ::std::option::Option::None,
            });

            ($expr:expr => return) => (match $expr {
                ::std::option::Option::Some(val) => val,
                ::std::option::Option::None => return,
            })
        }

        use glob::{glob, Paths, PatternError};

        let hashstr : String = hash.into();
        let globstr = format!("{}/*-{}.imag", self.storepath, hashstr);
        debug!("glob({})", globstr);

        let globs = glob(&globstr[..]);
        if globs.is_err() {
            return None;
        }

        let path = globs.unwrap().last();
        debug!("path = {:?}", path);

        let pathbuf = try_some!(path);
        if pathbuf.is_err() { return None; }

        let pathbuf_un  = pathbuf.unwrap();
        let filename    = pathbuf_un.file_name();
        let s           = try_some!(filename).to_str();
        let string      = String::from(try_some!(s));
        let id          = try_some!(FileID::parse(&string));

        debug!("Loaded ID = '{:?}'", id);

        self.load(m, parser, &id)
    }

    /**
     * Load all files for a module
     */
    pub fn load_for_module<HP>(&self, m: &Module, parser: &Parser<HP>)
        -> Vec<Rc<RefCell<File>>>
        where HP: FileHeaderParser
    {
        use glob::{glob, Paths, PatternError};

        let globstr = format!("{}/{}-*.imag", self.storepath, m.name());
        let mut res = vec![];

        glob(&globstr[..]).map(|paths| {
            for path in paths {
                if let Ok(pathbuf) = path {
                    let fname = pathbuf.file_name().and_then(|s| s.to_str());
                    fname.map(|s| {
                        FileID::parse(&String::from(s)).map(|id| {
                            self.load(m, parser, &id).map(|file| {
                                res.push(file);
                            })
                        });
                    });
                }
            }
        });
        res
    }

    /**
     * Remove a file from the filesystem by FileID
     *
     * Returns true if this works.
     */
    pub fn remove(&self, id: FileID) -> bool {
        use std::fs::remove_file;

        self.cache
            .borrow_mut()
            .remove(&id)
            .map(|file| {
                let idstr : String = id.into();
                let path = format!("{}/{}-{}.imag",
                                   self.storepath,
                                   file.deref().borrow().owner_name(),
                                   idstr);
                debug!("Removing file NOW: '{}'", path);
                remove_file(path).is_ok()
            })
            .unwrap_or(false)
    }

    /**
     * Helper to generate a new FileID object
     */
    fn get_new_file_id(&self) -> FileID {
        use uuid::Uuid;
        let hash = FileHash::from(Uuid::new_v4().to_hyphenated_string());
        FileID::new(FileIDType::UUID, hash)
    }

}
<|endoftext|>


<commit_before>/* Copyright (C)  2016 nokaa <nokaa@cock.li>
 * This software is licensed under the terms of the
 * GNU Affero General Public License. You should have
 * received a copy of this license with this software.
 * The license may also be found at https://gnu.org/licenses/agpl.txt
 */

use super::Term;

pub fn handle(term: &mut Term, ch: char) {
    match ch {
        '\x1b' => { // Escape key
            term.editor.switch_mode();
        }
        '\x7f' => { // Backspace key
            let line = term.current_line() + term.cursor.pos.y;
            term.cursor.save_pos();
            if term.cursor.pos.x == 0 {
                let mut rem = term.editor.contents[line].clone();
                let pos = term.editor.contents[line - 1].len() - 1;
                term.editor.contents[line - 1].remove(pos);
                term.editor.contents[line - 1].append(&mut rem);
                term.editor.contents.remove(line);
                if term.cursor.pos.y != 0 {
                    term.cursor.pos.y -= 1;
                }

                //let line = term.current_line() + term.cursor.pos.y;
                //let len = term.editor.contents[line].len() - 1;
                term.cursor.pos.x = pos;
                term.redraw_file();
            } else {
                term.cursor.pos.x -= 1;
                let pos = term.cursor.pos.x;
                term.editor.contents[line].remove(pos);
                term.redraw_file();
            }
        }
        '\r' => {
            let line = term.current_line() + term.cursor.pos.y;
            term.editor.contents.insert(line, vec![b'\n']);
            term.cursor.save_pos();
            term.cursor.pos.x = 0;
            term.cursor.pos.y += 1;
            term.redraw_file();
        }
        '\t' => {
            for i in 0..4 {
                let x = term.cursor.pos.x + i;
                term.term[(x, term.cursor.pos.y)].set_ch(' ');
            }
            term.cursor.save_pos();
            term.cursor.pos.x += 4;
        }
        c @ _ => {
            /*let line = term.current_line() + term.cursor.pos.y;
            let pos = term.cursor.pos.x;
            term.editor.contents[line, pos*/
            term.term[term.cursor.current_pos()].set_ch(c);
            term.cursor.save_pos();
            term.cursor.pos.x += 1;
        }
    }
}
<commit_msg>Implement general insertion<commit_after>/* Copyright (C)  2016 nokaa <nokaa@cock.li>
 * This software is licensed under the terms of the
 * GNU Affero General Public License. You should have
 * received a copy of this license with this software.
 * The license may also be found at https://gnu.org/licenses/agpl.txt
 */

use super::Term;

pub fn handle(term: &mut Term, ch: char) {
    match ch {
        '\x1b' => { // Escape key
            term.editor.switch_mode();
        }
        '\x7f' => { // Backspace key
            let line = term.current_line() + term.cursor.pos.y;
            term.cursor.save_pos();

            if term.cursor.pos.x == 0 {
                let mut rem = term.editor.contents[line].clone();
                let pos = term.editor.contents[line - 1].len() - 1;

                term.editor.contents[line - 1].remove(pos);
                term.editor.contents[line - 1].append(&mut rem);
                term.editor.contents.remove(line);

                if term.cursor.pos.y != 0 {
                    term.cursor.pos.y -= 1;
                }

                term.cursor.pos.x = pos;
                term.redraw_file();
            } else {
                term.cursor.pos.x -= 1;
                let pos = term.cursor.pos.x;

                term.editor.contents[line].remove(pos);
                term.redraw_file();
            }
        }
        '\r' => {
            let line = term.current_line() + term.cursor.pos.y;
            term.editor.contents.insert(line, vec![b'\n']);

            term.cursor.save_pos();
            term.cursor.pos.x = 0;
            term.cursor.pos.y += 1;

            term.redraw_file();
        }
        '\t' => {
            for i in 0..4 {
                let x = term.cursor.pos.x + i;
                term.term[(x, term.cursor.pos.y)].set_ch(' ');
            }

            term.cursor.save_pos();
            term.cursor.pos.x += 4;
        }
        c @ _ => {
            let line = term.current_line() + term.cursor.pos.y;
            let pos = term.cursor.pos.x;

            term.editor.contents[line].insert(pos, c as u8);

            term.cursor.save_pos();
            term.cursor.pos.x += 1;
            term.redraw_file();
        }
    }
}
<|endoftext|>


<commit_before>use super::Timestamp;

use std::clone::Clone;

use std::collections::HashMap;

pub struct Chapter {
    pub id: String,
    pub start: Timestamp,
    pub end: Timestamp,
    pub metadata: HashMap<String, String>,
}

impl Chapter {
    pub fn new(id: &str, title: &str, start: Timestamp, end: Timestamp) -> Self {
        let mut this = Chapter {
            id: id.to_owned(),
            start: start,
            end: end,
            metadata: HashMap::new(),
        };

        this.metadata.insert("title".to_owned(), title.to_string());

        this
    }

    pub fn get_title(&self) -> Option<&String> {
        self.metadata.get(super::METADATA_TITLE)
    }
}

impl Clone for Chapter {
    fn clone(&self) -> Self {
        Chapter {
            id: self.id.clone(),
            start: self.start,
            end: self.end,
            metadata: self.metadata.clone(),
        }
    }
}
<commit_msg>Add Chapter::empty (#77)<commit_after>use super::Timestamp;

use std::clone::Clone;

use std::collections::HashMap;

pub struct Chapter {
    pub id: String,
    pub start: Timestamp,
    pub end: Timestamp,
    pub metadata: HashMap<String, String>,
}

impl Chapter {
    pub fn new(id: &str, title: &str, start: Timestamp, end: Timestamp) -> Self {
        let mut this = Chapter {
            id: id.to_owned(),
            start: start,
            end: end,
            metadata: HashMap::new(),
        };

        this.metadata.insert("title".to_owned(), title.to_string());

        this
    }

    pub fn empty() -> Self {
        Chapter {
            id: String::new(),
            start: Timestamp::new(),
            end: Timestamp::new(),
            metadata: HashMap::new(),
        }
    }

    pub fn set_title(&mut self, title: &str) {
        self.metadata.insert(super::METADATA_TITLE.to_owned(), title.to_owned());
    }

    pub fn get_title(&self) -> Option<&String> {
        self.metadata.get(super::METADATA_TITLE)
    }
}

impl Clone for Chapter {
    fn clone(&self) -> Self {
        Chapter {
            id: self.id.clone(),
            start: self.start,
            end: self.end,
            metadata: self.metadata.clone(),
        }
    }
}
<|endoftext|>


<commit_before>
/// Implemented by contexts that can transform.
pub trait Transform2d<'a> {
    /// Translate x and y.
    fn trans(&'a self, x: f64, y: f64) -> Self;

    /// Rotates degrees.
    #[inline(always)]
    fn rot_deg(&'a self, angle: f64) -> Self {
        let pi: f64 = Float::pi();
        self.rot_rad(angle * pi / 180.0)
    }

    /// Rotate radians.
    fn rot_rad(&'a self, angle: f64) -> Self;
    /// Scale.
    fn scale(&'a self, sx: f64, sy: f64) -> Self;

    /// Scales in both directions.
    #[inline(always)]
    fn zoom(&'a self, s: f64) -> Self {
        self.scale(s, s)
    }

    /// Shear.
    fn shear(&'a self, sx: f64, sy: f64) -> Self;
}
<commit_msg>Added `flip_v` and `flip_h`<commit_after>
/// Implemented by contexts that can transform.
pub trait Transform2d<'a> {
    /// Translate x and y.
    fn trans(&'a self, x: f64, y: f64) -> Self;

    /// Rotates degrees.
    #[inline(always)]
    fn rot_deg(&'a self, angle: f64) -> Self {
        let pi: f64 = Float::pi();
        self.rot_rad(angle * pi / 180.0)
    }

    /// Rotate radians.
    fn rot_rad(&'a self, angle: f64) -> Self;
    /// Scale.
    fn scale(&'a self, sx: f64, sy: f64) -> Self;

    /// Scales in both directions.
    #[inline(always)]
    fn zoom(&'a self, s: f64) -> Self {
        self.scale(s, s)
    }

    /// Flips vertically.
    #[inline(always)]
    fn flip_v(&'a self) -> Self {
        self.scale(1.0, -1.0)
    }

    /// Flips horizontally.
    #[inline(always)]
    fn flip_h(&'a self) -> Self {
        self.scale(-1.0, 0.0)
    }

    /// Shear.
    fn shear(&'a self, sx: f64, sy: f64) -> Self;
}
<|endoftext|>


<commit_before>use color::Color3;
use id_allocator::IdAllocator;
use nalgebra::{Pnt3, Vec3, normalize};
use ncollide::bounding_volume::AABB;
use noise::Seed;
use state::EntityId;
use std::cmp::{partial_min, partial_max};
use terrain_block::TerrainBlock;
use terrain_heightmap::HeightMap;

/// Use one-octave perlin noise local maxima to place trees.
pub struct TreePlacer {
  tree_field: HeightMap,
}

impl TreePlacer {
  pub fn new(seed: Seed) -> TreePlacer {
    let octaves = 1;
    let frequency = 1.0 / 4.0;
    let persistence = 1.0;
    let lacunarity = 1.0;
    let amplitude = 1.0;
    TreePlacer {
      tree_field: HeightMap::new(seed, octaves, frequency, persistence, lacunarity, amplitude),
    }
  }

  pub fn should_place_tree(&self, center: &Pnt3<f32>) -> bool {
    let center = self.tree_field.point_at(center.x, center.z);

    let delta = 0.1;
    let corners = [
      (-delta, -delta),
      (-delta,  delta),
      ( delta,  delta),
      ( delta, -delta),
    ];

    corners.iter()
      .all(|&(l, h)| center.y > self.tree_field.point_at(center.x + l, center.z + h).y)
  }

  pub fn place_tree(
    &self,
    mut center: Pnt3<f32>,
    id_allocator: &mut IdAllocator<EntityId>,
    block: &mut TerrainBlock,
  ) {
    let normals = [
      normalize(&Vec3::new(-1.0, -1.0, -1.0)),
      normalize(&Vec3::new(-1.0, -1.0,  1.0)),
      normalize(&Vec3::new( 1.0, -1.0,  1.0)),
      normalize(&Vec3::new( 1.0, -1.0, -1.0)),
      normalize(&Vec3::new(-1.0,  1.0, -1.0)),
      normalize(&Vec3::new(-1.0,  1.0,  1.0)),
      normalize(&Vec3::new( 1.0,  1.0,  1.0)),
      normalize(&Vec3::new( 1.0,  1.0, -1.0)),
    ];

    let mut place_side =
      |&mut:
        corners: &[Pnt3<f32>],
        color: &Color3<f32>,
        idx1,
        idx2,
        idx3,
        idx4,
      | {
        let n1 = normals.get(idx1).unwrap();
        let n2 = normals.get(idx2).unwrap();
        let n3 = normals.get(idx3).unwrap();
        let n4 = normals.get(idx4).unwrap();

        let v1 = corners.get(idx1).unwrap();
        let v2 = corners.get(idx2).unwrap();
        let v3 = corners.get(idx3).unwrap();
        let v4 = corners.get(idx4).unwrap();

        block.vertex_coordinates.push_all(&[
          v1.x, v1.y, v1.z,
          v2.x, v2.y, v2.z,
          v4.x, v4.y, v4.z,

          v1.x, v1.y, v1.z,
          v4.x, v4.y, v4.z,
          v3.x, v3.y, v3.z,
        ]);

        block.normals.push_all(&[
          n1.x, n1.y, n1.z,
          n2.x, n2.y, n2.z,
          n4.x, n4.y, n4.z,

          n2.x, n2.y, n2.z,
          n4.x, n4.y, n4.z,
          n3.x, n3.y, n3.z,
        ]);

        block.colors.push_all(&[
          color.r, color.g, color.b,
          color.r, color.g, color.b,
        ]);

        let minx = partial_min(v1.x, v2.x).unwrap();
        let maxx = partial_max(v1.x, v2.x).unwrap();
        let minz = partial_min(v1.z, v2.z).unwrap();
        let maxz = partial_max(v1.z, v2.z).unwrap();

        let bounds =
          AABB::new(
            Pnt3::new(minx, v1.y, minz),
            Pnt3::new(maxx, v3.y, maxz),
          );

        let id1 = id_allocator.allocate();
        let id2 = id_allocator.allocate();
        block.ids.push_all(&[id1, id2]);

        block.bounds.insert(id1, bounds.clone());
        block.bounds.insert(id2, bounds);
      };

    let mass = 1.0 - self.tree_field.point_at(center.x, center.z).y;

    {
      let radius = mass * mass * 2.0;
      let height = mass * 16.0;
      let corners = [
        center + Vec3::new(-radius, 0.0, -radius),
        center + Vec3::new(-radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0, -radius),
        center + Vec3::new(-radius, height, -radius),
        center + Vec3::new(-radius, height,  radius),
        center + Vec3::new( radius, height,  radius),
        center + Vec3::new( radius, height, -radius),
      ];

      let color = Color3::of_rgb(0.4, 0.3, 0.1);
      place_side(&corners, &color, 0, 1, 4, 5);
      place_side(&corners, &color, 1, 2, 5, 6);
      place_side(&corners, &color, 2, 3, 6, 7);
      place_side(&corners, &color, 3, 0, 7, 4);

      center = center + Vec3::new(0.0, height, 0.0);
    }

    {
      let radius = mass * mass * 16.0;
      let height = mass * mass * 16.0;
      let corners = [
        center + Vec3::new(-radius, 0.0, -radius),
        center + Vec3::new(-radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0, -radius),
        center + Vec3::new(-radius, height, -radius),
        center + Vec3::new(-radius, height,  radius),
        center + Vec3::new( radius, height,  radius),
        center + Vec3::new( radius, height, -radius),
      ];

      let color = Color3::of_rgb(0.0, 0.4, 0.0);
      place_side(&corners, &color, 0, 1, 4, 5);
      place_side(&corners, &color, 1, 2, 5, 6);
      place_side(&corners, &color, 2, 3, 6, 7);
      place_side(&corners, &color, 3, 0, 7, 4);
      place_side(&corners, &color, 4, 5, 7, 6);
      place_side(&corners, &color, 1, 0, 2, 3);
    }
  }
}
<commit_msg>Clamp & warn on unexpected tree seed values.<commit_after>use color::Color3;
use id_allocator::IdAllocator;
use nalgebra::{Pnt3, Vec3, normalize};
use ncollide::bounding_volume::AABB;
use noise::Seed;
use state::EntityId;
use std::cmp::{partial_min, partial_max};
use terrain_block::TerrainBlock;
use terrain_heightmap::HeightMap;

/// Use one-octave perlin noise local maxima to place trees.
pub struct TreePlacer {
  tree_field: HeightMap,
}

impl TreePlacer {
  pub fn new(seed: Seed) -> TreePlacer {
    let octaves = 1;
    let frequency = 1.0 / 4.0;
    let persistence = 1.0;
    let lacunarity = 1.0;
    let amplitude = 1.0;
    TreePlacer {
      tree_field: HeightMap::new(seed, octaves, frequency, persistence, lacunarity, amplitude),
    }
  }

  pub fn should_place_tree(&self, center: &Pnt3<f32>) -> bool {
    let center = self.tree_field.point_at(center.x, center.z);

    let delta = 0.1;
    let corners = [
      (-delta, -delta),
      (-delta,  delta),
      ( delta,  delta),
      ( delta, -delta),
    ];

    corners.iter()
      .all(|&(l, h)| center.y > self.tree_field.point_at(center.x + l, center.z + h).y)
  }

  pub fn place_tree(
    &self,
    mut center: Pnt3<f32>,
    id_allocator: &mut IdAllocator<EntityId>,
    block: &mut TerrainBlock,
  ) {
    let normals = [
      normalize(&Vec3::new(-1.0, -1.0, -1.0)),
      normalize(&Vec3::new(-1.0, -1.0,  1.0)),
      normalize(&Vec3::new( 1.0, -1.0,  1.0)),
      normalize(&Vec3::new( 1.0, -1.0, -1.0)),
      normalize(&Vec3::new(-1.0,  1.0, -1.0)),
      normalize(&Vec3::new(-1.0,  1.0,  1.0)),
      normalize(&Vec3::new( 1.0,  1.0,  1.0)),
      normalize(&Vec3::new( 1.0,  1.0, -1.0)),
    ];

    let mut place_side =
      |&mut:
        corners: &[Pnt3<f32>],
        color: &Color3<f32>,
        idx1,
        idx2,
        idx3,
        idx4,
      | {
        let n1 = normals.get(idx1).unwrap();
        let n2 = normals.get(idx2).unwrap();
        let n3 = normals.get(idx3).unwrap();
        let n4 = normals.get(idx4).unwrap();

        let v1 = corners.get(idx1).unwrap();
        let v2 = corners.get(idx2).unwrap();
        let v3 = corners.get(idx3).unwrap();
        let v4 = corners.get(idx4).unwrap();

        block.vertex_coordinates.push_all(&[
          v1.x, v1.y, v1.z,
          v2.x, v2.y, v2.z,
          v4.x, v4.y, v4.z,

          v1.x, v1.y, v1.z,
          v4.x, v4.y, v4.z,
          v3.x, v3.y, v3.z,
        ]);

        block.normals.push_all(&[
          n1.x, n1.y, n1.z,
          n2.x, n2.y, n2.z,
          n4.x, n4.y, n4.z,

          n2.x, n2.y, n2.z,
          n4.x, n4.y, n4.z,
          n3.x, n3.y, n3.z,
        ]);

        block.colors.push_all(&[
          color.r, color.g, color.b,
          color.r, color.g, color.b,
        ]);

        let minx = partial_min(v1.x, v2.x).unwrap();
        let maxx = partial_max(v1.x, v2.x).unwrap();
        let minz = partial_min(v1.z, v2.z).unwrap();
        let maxz = partial_max(v1.z, v2.z).unwrap();

        let bounds =
          AABB::new(
            Pnt3::new(minx, v1.y, minz),
            Pnt3::new(maxx, v3.y, maxz),
          );

        let id1 = id_allocator.allocate();
        let id2 = id_allocator.allocate();
        block.ids.push_all(&[id1, id2]);

        block.bounds.insert(id1, bounds.clone());
        block.bounds.insert(id2, bounds);
      };

    let mut mass = self.tree_field.point_at(center.x, center.z).y;
    if mass < 0.0 || mass > 1.0 {
      warn!("clamping out-of-bounds mass: {}", mass);
      mass = partial_min(partial_max(0.0, mass).unwrap(), 1.0).unwrap();
    }
    mass = 1.0 - mass;

    {
      let radius = mass * mass * 2.0;
      let height = mass * 16.0;
      let corners = [
        center + Vec3::new(-radius, 0.0, -radius),
        center + Vec3::new(-radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0, -radius),
        center + Vec3::new(-radius, height, -radius),
        center + Vec3::new(-radius, height,  radius),
        center + Vec3::new( radius, height,  radius),
        center + Vec3::new( radius, height, -radius),
      ];

      let color = Color3::of_rgb(0.4, 0.3, 0.1);
      place_side(&corners, &color, 0, 1, 4, 5);
      place_side(&corners, &color, 1, 2, 5, 6);
      place_side(&corners, &color, 2, 3, 6, 7);
      place_side(&corners, &color, 3, 0, 7, 4);

      center = center + Vec3::new(0.0, height, 0.0);
    }

    {
      let radius = mass * mass * 16.0;
      let height = mass * mass * 16.0;
      let corners = [
        center + Vec3::new(-radius, 0.0, -radius),
        center + Vec3::new(-radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0,  radius),
        center + Vec3::new( radius, 0.0, -radius),
        center + Vec3::new(-radius, height, -radius),
        center + Vec3::new(-radius, height,  radius),
        center + Vec3::new( radius, height,  radius),
        center + Vec3::new( radius, height, -radius),
      ];

      let color = Color3::of_rgb(0.0, 0.4, 0.0);
      place_side(&corners, &color, 0, 1, 4, 5);
      place_side(&corners, &color, 1, 2, 5, 6);
      place_side(&corners, &color, 2, 3, 6, 7);
      place_side(&corners, &color, 3, 0, 7, 4);
      place_side(&corners, &color, 4, 5, 7, 6);
      place_side(&corners, &color, 1, 0, 2, 3);
    }
  }
}
<|endoftext|>


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

//!
//! A tree stream is the result of annotating an annotated stream. This forms a tree structure with the original input
//! stream at the leaves. This can be used to represent the result of parsing an input.
//!

use super::countable::*;
use super::symbol_reader::*;
use super::annotated_stream::*;
use super::symbol_range_dfa::*;

///
/// Represents a stream that has been decomposed into a tree
///
#[derive(Clone)]
pub struct TreeStream<InputSymbol, TokenType> {
    /// How the original input stream maps onto tokens
    tokens: AnnotatedStream<InputSymbol, TokenType>,

    /// The hierarchy of annotations. As a tree, the 'root' is considered to be the last entry in this list (it's built from the bottom up)
    annotations: Vec<AnnotatedStream<TokenType, TokenType>>
}

impl<InputSymbol: Clone+Ord+Countable, TokenType: Clone+Ord+Countable+'static> TreeStream<InputSymbol, TokenType> {
    ///
    /// Creates a new tree stream from a tokenized stream
    ///
    pub fn new_with_tokens(tokens: AnnotatedStream<InputSymbol, TokenType>) -> Self {
        TreeStream { tokens: tokens, annotations: vec![] }
    }

    ///
    /// Reads the input that made up this tree stream
    ///
    pub fn read_input<'a>(&'a self) -> Box<SymbolReader<InputSymbol>+'a> {
        self.tokens.read_input()
    }

    ///
    /// Works out the depth of this tree
    ///
    pub fn depth(&self) -> usize {
        self.annotations.len()+1
    }

    ///
    /// Reads a the tokens on a particular level of the tree as a stream
    ///
    /// `0` is the top-most level of the tree, and `depth()-1` represent the bottom-most level (the level containing the tokens)
    ///
    pub fn read_level_tokens<'a>(&'a self, depth: usize) -> Box<SymbolReader<Token<TokenType>>+'a> {
        if depth == self.annotations.len() {
            // Just the tokens, mapping onto the original input stream
            self.tokens.read_tokens()
        } else {
            // Build up a symbol reader from the output and input of this stream
            let level  = (self.annotations.len()-1) - depth;
            let stream = &self.annotations[level];

            let mut tokens   = vec![];
            let mut last_pos = 0..0;
            let mut reader   = stream.read_tokens();

            loop {
                if let Some(level_token) = reader.next_symbol() {
                    // Append input symbols if there is a gap
                    if last_pos.end != level_token.location.start {
                        let gap_range         = last_pos.end..level_token.location.start;
                        let from_higher_level = stream.input_for_range(gap_range.clone());

                        for pos in gap_range.clone() {
                            tokens.push(Token::new(pos..pos+1, from_higher_level[pos-gap_range.start].clone()));
                        }
                    }

                    // Update the last pos so we can detect gaps after it
                    last_pos = level_token.location.clone();

                    // Add this token
                    tokens.push(level_token);
                } else {
                    // End of stream
                    break;
                }
            }

            // Append input tokens from the end of the stream
            let end_pos  = stream.input_len();
            let end_gap  = last_pos.end..end_pos;
            let from_end = stream.input_for_range(end_gap.clone());

            for pos in end_gap.clone() {
                tokens.push(Token::new(pos..pos+1, from_end[pos-end_gap.start].clone()));
            }

            // Result is a new vector stream
            Box::new(VecReader::from_vec(tokens))
        }
    }

    ///
    /// Reads a particular level of the tree as a stream
    ///
    /// `0` is the top-most level of the tree, and `depth()-1` represent the bottom-most level (the level containing the tokens)
    ///
    pub fn read_level<'a>(&'a self, depth: usize) -> Box<SymbolReader<TokenType>+'a> {
        Box::new(self.read_level_tokens(depth).map_symbols(|token| token.output))
    }

    ///
    /// Performs pattern matching on the 'top level', adding another level to the tree. Returns the number of symbols in the new stream
    ///
    /// By matching a series of tokens against a regular pattern, we can further reduce a tokenized string, and build up a tree
    /// representation of the string's contents. 'Holes' that do not match the pattern allow the tree to have variable depth:
    ///
    pub fn tokenize_top_level(&mut self, dfa: &SymbolRangeDfa<TokenType, TokenType>) -> usize {
        // Read the tokens at the top level
        let next_level  = AnnotatedStream::from_tokenizer(dfa, self.read_level(0));
        let num_matched = next_level.output_len();

        self.annotations.push(next_level);

        num_matched
    }
}

///
/// Represents a node in a tree stream
///
pub struct TreeNode<'a, InputSymbol: 'a, OutputSymbol: 'a> {
    /// The tree that this node is a part of
    tree: &'a TreeStream<InputSymbol, OutputSymbol>,

    /// The distance from the bottom of the tree that this node represents (0 = tokens, 1+ = a leven in the annotations)
    level: usize,

    /// The token representing the 'root' of this tree
    token: Token<OutputSymbol>
}

impl<'a, InputSymbol: 'a, OutputSymbol: Clone+'a> TreeNode<'a, InputSymbol, OutputSymbol> {
    ///
    /// Retrieves the output symbol represented by this tree node
    ///
    pub fn get_symbol(&self) -> OutputSymbol {
        self.token.output.clone()
    }

    ///
    /// Retrieves the child nodes of this node (the empty set if this is a leaf node)
    ///
    pub fn get_children(&self) -> Vec<TreeNode<'a, InputSymbol, OutputSymbol>> {
        if self.level == 0 {
            // Level 0 is at the bottom
            vec![]
        } else {
            unimplemented!()
        }
    }
}

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

    #[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
    enum TestToken {
        Digit,
        Identifier,
        Operator,
        Whitespace,

        Expression
    }

    impl Countable for TestToken {
        fn next(&self) -> Self {
            match *self {
                TestToken::Digit        => TestToken::Identifier,
                TestToken::Identifier   => TestToken::Operator,
                TestToken::Operator     => TestToken::Whitespace,
                TestToken::Whitespace   => TestToken::Expression,
                TestToken::Expression   => TestToken::Digit
            }
        }

        fn prev(&self) -> Self {
            match *self {
                TestToken::Digit        => TestToken::Expression,
                TestToken::Identifier   => TestToken::Digit,
                TestToken::Operator     => TestToken::Identifier,
                TestToken::Whitespace   => TestToken::Operator,
                TestToken::Expression   => TestToken::Whitespace
            }
        }
    }

    fn create_simple_tokenizer() -> SymbolRangeDfa<char, TestToken> {
        let mut token_matcher = TokenMatcher::new();

        token_matcher.add_pattern(MatchRange('0', '9').repeat_forever(1), TestToken::Digit);
        token_matcher.add_pattern(MatchRange('a', 'z').repeat_forever(1), TestToken::Identifier);
        token_matcher.add_pattern("+".into_pattern(), TestToken::Operator);
        token_matcher.add_pattern(" ".repeat_forever(1), TestToken::Whitespace);

        token_matcher.prepare_to_match()
    }

    fn create_expression_parser() -> SymbolRangeDfa<TestToken, TestToken> {
        let mut token_matcher = TokenMatcher::new();

        token_matcher.add_pattern(Match(vec![TestToken::Digit]), TestToken::Expression);
        token_matcher.add_pattern(Match(vec![TestToken::Identifier]), TestToken::Expression);
        token_matcher.add_pattern(Match(vec![TestToken::Expression, TestToken::Operator, TestToken::Expression]), TestToken::Expression);

        token_matcher.prepare_to_match()
    }

    #[test]
    pub fn can_iterate_over_base_stream() {
        let tokenizer        = create_simple_tokenizer();
        let tokenized_stream = AnnotatedStream::from_tokenizer(&tokenizer, "a+1".read_symbols());
        let tokenized_tree   = TreeStream::new_with_tokens(tokenized_stream);

        assert!(tokenized_tree.depth() == 1);
        assert!(tokenized_tree.read_input().to_vec() == vec!['a', '+', '1']);
    }

    #[test]
    pub fn can_reduce_expression() {
        let tokenizer          = create_simple_tokenizer();
        let parser             = create_expression_parser();
        let tokenized_stream   = AnnotatedStream::from_tokenizer(&tokenizer, "a+1".read_symbols());
        let mut tokenized_tree = TreeStream::new_with_tokens(tokenized_stream);

        let num_expressions_1  = tokenized_tree.tokenize_top_level(&parser);
        let num_expressions_2  = tokenized_tree.tokenize_top_level(&parser);

        assert!(tokenized_tree.read_level(2).to_vec() == vec![TestToken::Identifier, TestToken::Operator, TestToken::Digit]);
        assert!(tokenized_tree.read_level(1).to_vec() == vec![TestToken::Expression, TestToken::Operator, TestToken::Expression]);
        assert!(tokenized_tree.read_level(0).to_vec() == vec![TestToken::Expression]);
        assert!(num_expressions_1 == 2);            // 'Expression Operator Expression'
        assert!(num_expressions_2 == 1);            // 'Expression'
    }

    #[test]
    pub fn can_reduce_longer_expression() {
        let tokenizer          = create_simple_tokenizer();
        let parser             = create_expression_parser();
        let tokenized_stream   = AnnotatedStream::from_tokenizer(&tokenizer, "a+1+b".read_symbols());
        let mut tokenized_tree = TreeStream::new_with_tokens(tokenized_stream);

        let num_expressions_1  = tokenized_tree.tokenize_top_level(&parser);
        let num_expressions_2  = tokenized_tree.tokenize_top_level(&parser);
        let num_expressions_3  = tokenized_tree.tokenize_top_level(&parser);

        assert!(tokenized_tree.read_level(3).to_vec() == vec![TestToken::Identifier, TestToken::Operator, TestToken::Digit, TestToken::Operator, TestToken::Identifier]);
        assert!(tokenized_tree.read_level(2).to_vec() == vec![TestToken::Expression, TestToken::Operator, TestToken::Expression, TestToken::Operator, TestToken::Expression]);
        assert!(tokenized_tree.read_level(1).to_vec() == vec![TestToken::Expression, TestToken::Operator, TestToken::Expression]);
        assert!(tokenized_tree.read_level(0).to_vec() == vec![TestToken::Expression]);
        assert!(num_expressions_1 == 3);            // 'Expression Operator Expression Operator Expression'
        assert!(num_expressions_2 == 1);            // 'Expression Operator Expression'
        assert!(num_expressions_3 == 1);            // 'Expression'
    }
}
<commit_msg>Initial adjustments to the tree stream<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! A tree stream is the result of annotating an annotated stream. This forms a tree structure with the original input
//! stream at the leaves. This can be used to represent the result of parsing an input.
//!

use super::countable::*;
use super::symbol_reader::*;
use super::annotated_stream::*;
use super::symbol_range_dfa::*;

///
/// Represents a stream that has been decomposed into a tree
///
#[derive(Clone)]
pub struct TreeStream<InputSymbol, TokenType> {
    /// The original input for this stream
    input: Vec<InputSymbol>,

    /// How the original input stream maps onto tokens
    tokens: AnnotatedStream<TokenType>,

    /// The hierarchy of annotations. As a tree, the 'root' is considered to be the last entry in this list (it's built from the bottom up)
    annotations: Vec<AnnotatedStream<TokenType>>
}

impl<InputSymbol: Clone+Ord+Countable, TokenType: Clone+Ord+Countable+'static> TreeStream<InputSymbol, TokenType> {
    ///
    /// Creates a new tree stream from a tokenized stream
    ///
    pub fn new_with_tokens(input: Vec<InputSymbol>, tokens: AnnotatedStream<TokenType>) -> Self {
        TreeStream { input: input, tokens: tokens, annotations: vec![] }
    }

    ///
    /// Reads the input that made up this tree stream
    ///
    pub fn read_input<'a>(&'a self) -> Box<SymbolReader<InputSymbol>+'a> {
        Box::new(self.input.read_symbols())
    }

    ///
    /// Works out the depth of this tree
    ///
    pub fn depth(&self) -> usize {
        self.annotations.len()+1
    }

    ///
    /// Reads a the tokens on a particular level of the tree as a stream
    ///
    /// `0` is the top-most level of the tree, and `depth()-1` represent the bottom-most level (the level containing the tokens)
    ///
    pub fn read_level_tokens<'a>(&'a self, depth: usize) -> Box<SymbolReader<Token<TokenType>>+'a> {
        if depth == self.annotations.len() {
            // Just the tokens, mapping onto the original input stream
            self.tokens.read_tokens()
        } else {
            // Build up a symbol reader from the output and input of this stream
            let level  = (self.annotations.len()-1) - depth;
            let stream = &self.annotations[level];

            let mut tokens   = vec![];
            let mut last_pos = 0..0;
            let mut reader   = stream.read_tokens();

            loop {
                if let Some(level_token) = reader.next_symbol() {
                    // Append input symbols if there is a gap
                    if last_pos.end != level_token.location.start {
                        let gap_range         = last_pos.end..level_token.location.start;
                        let from_higher_level = stream.input_for_range(gap_range.clone());

                        for pos in gap_range.clone() {
                            tokens.push(Token::new(pos..pos+1, from_higher_level[pos-gap_range.start].clone()));
                        }
                    }

                    // Update the last pos so we can detect gaps after it
                    last_pos = level_token.location.clone();

                    // Add this token
                    tokens.push(level_token);
                } else {
                    // End of stream
                    break;
                }
            }

            // Append input tokens from the end of the stream
            let end_pos  = stream.input_len();
            let end_gap  = last_pos.end..end_pos;
            let from_end = stream.input_for_range(end_gap.clone());

            for pos in end_gap.clone() {
                tokens.push(Token::new(pos..pos+1, from_end[pos-end_gap.start].clone()));
            }

            // Result is a new vector stream
            Box::new(VecReader::from_vec(tokens))
        }
    }

    ///
    /// Reads a particular level of the tree as a stream
    ///
    /// `0` is the top-most level of the tree, and `depth()-1` represent the bottom-most level (the level containing the tokens)
    ///
    pub fn read_level<'a>(&'a self, depth: usize) -> Box<SymbolReader<TokenType>+'a> {
        Box::new(self.read_level_tokens(depth).map_symbols(|token| token.output))
    }

    ///
    /// Performs pattern matching on the 'top level', adding another level to the tree. Returns the number of symbols in the new stream
    ///
    /// By matching a series of tokens against a regular pattern, we can further reduce a tokenized string, and build up a tree
    /// representation of the string's contents. 'Holes' that do not match the pattern allow the tree to have variable depth:
    ///
    pub fn tokenize_top_level(&mut self, dfa: &SymbolRangeDfa<TokenType, TokenType>) -> usize {
        // Read the tokens at the top level
        let next_level  = AnnotatedStream::from_tokenizer(dfa, self.read_level(0));
        let num_matched = next_level.output_len();

        self.annotations.push(next_level);

        num_matched
    }
}

///
/// Represents a node in a tree stream
///
pub struct TreeNode<'a, InputSymbol: 'a, OutputSymbol: 'a> {
    /// The tree that this node is a part of
    tree: &'a TreeStream<InputSymbol, OutputSymbol>,

    /// The distance from the bottom of the tree that this node represents (0 = tokens, 1+ = a leven in the annotations)
    level: usize,

    /// The token representing the 'root' of this tree
    token: Token<OutputSymbol>
}

impl<'a, InputSymbol: 'a, OutputSymbol: Clone+'a> TreeNode<'a, InputSymbol, OutputSymbol> {
    ///
    /// Retrieves the output symbol represented by this tree node
    ///
    pub fn get_symbol(&self) -> OutputSymbol {
        self.token.output.clone()
    }

    ///
    /// Retrieves the child nodes of this node (the empty set if this is a leaf node)
    ///
    pub fn get_children(&self) -> Vec<TreeNode<'a, InputSymbol, OutputSymbol>> {
        if self.level == 0 {
            // Level 0 is at the bottom
            vec![]
        } else {
            unimplemented!()
        }
    }
}

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

    #[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
    enum TestToken {
        Digit,
        Identifier,
        Operator,
        Whitespace,

        Expression
    }

    impl Countable for TestToken {
        fn next(&self) -> Self {
            match *self {
                TestToken::Digit        => TestToken::Identifier,
                TestToken::Identifier   => TestToken::Operator,
                TestToken::Operator     => TestToken::Whitespace,
                TestToken::Whitespace   => TestToken::Expression,
                TestToken::Expression   => TestToken::Digit
            }
        }

        fn prev(&self) -> Self {
            match *self {
                TestToken::Digit        => TestToken::Expression,
                TestToken::Identifier   => TestToken::Digit,
                TestToken::Operator     => TestToken::Identifier,
                TestToken::Whitespace   => TestToken::Operator,
                TestToken::Expression   => TestToken::Whitespace
            }
        }
    }

    fn create_simple_tokenizer() -> SymbolRangeDfa<char, TestToken> {
        let mut token_matcher = TokenMatcher::new();

        token_matcher.add_pattern(MatchRange('0', '9').repeat_forever(1), TestToken::Digit);
        token_matcher.add_pattern(MatchRange('a', 'z').repeat_forever(1), TestToken::Identifier);
        token_matcher.add_pattern("+".into_pattern(), TestToken::Operator);
        token_matcher.add_pattern(" ".repeat_forever(1), TestToken::Whitespace);

        token_matcher.prepare_to_match()
    }

    fn create_expression_parser() -> SymbolRangeDfa<TestToken, TestToken> {
        let mut token_matcher = TokenMatcher::new();

        token_matcher.add_pattern(Match(vec![TestToken::Digit]), TestToken::Expression);
        token_matcher.add_pattern(Match(vec![TestToken::Identifier]), TestToken::Expression);
        token_matcher.add_pattern(Match(vec![TestToken::Expression, TestToken::Operator, TestToken::Expression]), TestToken::Expression);

        token_matcher.prepare_to_match()
    }

    #[test]
    pub fn can_iterate_over_base_stream() {
        let tokenizer        = create_simple_tokenizer();
        let tokenized_stream = AnnotatedStream::from_tokenizer(&tokenizer, "a+1".read_symbols());
        let tokenized_tree   = TreeStream::new_with_tokens(tokenized_stream);

        assert!(tokenized_tree.depth() == 1);
        assert!(tokenized_tree.read_input().to_vec() == vec!['a', '+', '1']);
    }

    #[test]
    pub fn can_reduce_expression() {
        let tokenizer          = create_simple_tokenizer();
        let parser             = create_expression_parser();
        let tokenized_stream   = AnnotatedStream::from_tokenizer(&tokenizer, "a+1".read_symbols());
        let mut tokenized_tree = TreeStream::new_with_tokens(tokenized_stream);

        let num_expressions_1  = tokenized_tree.tokenize_top_level(&parser);
        let num_expressions_2  = tokenized_tree.tokenize_top_level(&parser);

        assert!(tokenized_tree.read_level(2).to_vec() == vec![TestToken::Identifier, TestToken::Operator, TestToken::Digit]);
        assert!(tokenized_tree.read_level(1).to_vec() == vec![TestToken::Expression, TestToken::Operator, TestToken::Expression]);
        assert!(tokenized_tree.read_level(0).to_vec() == vec![TestToken::Expression]);
        assert!(num_expressions_1 == 2);            // 'Expression Operator Expression'
        assert!(num_expressions_2 == 1);            // 'Expression'
    }

    #[test]
    pub fn can_reduce_longer_expression() {
        let tokenizer          = create_simple_tokenizer();
        let parser             = create_expression_parser();
        let tokenized_stream   = AnnotatedStream::from_tokenizer(&tokenizer, "a+1+b".read_symbols());
        let mut tokenized_tree = TreeStream::new_with_tokens(tokenized_stream);

        let num_expressions_1  = tokenized_tree.tokenize_top_level(&parser);
        let num_expressions_2  = tokenized_tree.tokenize_top_level(&parser);
        let num_expressions_3  = tokenized_tree.tokenize_top_level(&parser);

        assert!(tokenized_tree.read_level(3).to_vec() == vec![TestToken::Identifier, TestToken::Operator, TestToken::Digit, TestToken::Operator, TestToken::Identifier]);
        assert!(tokenized_tree.read_level(2).to_vec() == vec![TestToken::Expression, TestToken::Operator, TestToken::Expression, TestToken::Operator, TestToken::Expression]);
        assert!(tokenized_tree.read_level(1).to_vec() == vec![TestToken::Expression, TestToken::Operator, TestToken::Expression]);
        assert!(tokenized_tree.read_level(0).to_vec() == vec![TestToken::Expression]);
        assert!(num_expressions_1 == 3);            // 'Expression Operator Expression Operator Expression'
        assert!(num_expressions_2 == 1);            // 'Expression Operator Expression'
        assert!(num_expressions_3 == 1);            // 'Expression'
    }
}
<|endoftext|>


<commit_before>
use std::collections::HashMap;
use std::collections::hash_map::{Entry};
use std::hash::Hash;
use std::fmt;

/// An iterator adapter to filter out duplicate elements.
///
/// See [`.unique_by()`](../trait.Itertools.html#method.unique) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct UniqueBy<I: Iterator, V, F> {
    iter: I,
    // Use a hashmap for the entry API
    used: HashMap<V, ()>,
    f: F,
}

impl<I, V, F> fmt::Debug for UniqueBy<I, V, F>
    where I: Iterator + fmt::Debug,
          V: fmt::Debug + Hash + Eq,
{
    debug_fmt_fields!(UniqueBy, iter, used);
}

/// Create a new `UniqueBy` iterator.
pub fn unique_by<I, V, F>(iter: I, f: F) -> UniqueBy<I, V, F>
    where V: Eq + Hash,
          F: FnMut(&I::Item) -> V,
          I: Iterator,
{
    UniqueBy {
        iter: iter,
        used: HashMap::new(),
        f: f,
    }
}

impl<I, V, F> Iterator for UniqueBy<I, V, F>
    where I: Iterator,
          V: Eq + Hash,
          F: FnMut(&I::Item) -> V
{
    type Item = I::Item;

    fn next(&mut self) -> Option<I::Item> {
        loop {
            match self.iter.next() {
                None => return None,
                Some(v) => {
                    let key = (self.f)(&v);
                    if self.used.insert(key, ()).is_none() {
                        return Some(v);
                    }
                }
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (low, hi) = self.iter.size_hint();
        ((low > 0 && self.used.is_empty()) as usize, hi)
    }
}

impl<I> Iterator for Unique<I>
    where I: Iterator,
          I::Item: Eq + Hash + Clone
{
    type Item = I::Item;

    fn next(&mut self) -> Option<I::Item> {
        loop {
            match self.iter.iter.next() {
                None => return None,
                Some(v) => {
                    match self.iter.used.entry(v) {
                        Entry::Occupied(_) => { }
                        Entry::Vacant(entry) => {
                            let elt = entry.key().clone();
                            entry.insert(());
                            return Some(elt);
                        }
                    }
                }
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (low, hi) = self.iter.iter.size_hint();
        ((low > 0 && self.iter.used.is_empty()) as usize, hi)
    }
}

/// An iterator adapter to filter out duplicate elements.
///
/// See [`.unique()`](../trait.Itertools.html#method.unique) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Unique<I: Iterator> {
    iter: UniqueBy<I, I::Item, ()>,
}

impl<I> fmt::Debug for Unique<I>
    where I: Iterator + fmt::Debug,
          I::Item: Hash + Eq + fmt::Debug,
{
    debug_fmt_fields!(Unique, iter);
}

pub fn unique<I>(iter: I) -> Unique<I>
    where I: Iterator,
          I::Item: Eq + Hash,
{
    Unique {
        iter: UniqueBy {
            iter: iter,
            used: HashMap::new(),
            f: (),
        }
    }
}
<commit_msg>FEAT: Special case .count() for .unique() and .unique_by()<commit_after>
use std::collections::HashMap;
use std::collections::hash_map::{Entry};
use std::hash::Hash;
use std::fmt;

/// An iterator adapter to filter out duplicate elements.
///
/// See [`.unique_by()`](../trait.Itertools.html#method.unique) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct UniqueBy<I: Iterator, V, F> {
    iter: I,
    // Use a hashmap for the entry API
    used: HashMap<V, ()>,
    f: F,
}

impl<I, V, F> fmt::Debug for UniqueBy<I, V, F>
    where I: Iterator + fmt::Debug,
          V: fmt::Debug + Hash + Eq,
{
    debug_fmt_fields!(UniqueBy, iter, used);
}

/// Create a new `UniqueBy` iterator.
pub fn unique_by<I, V, F>(iter: I, f: F) -> UniqueBy<I, V, F>
    where V: Eq + Hash,
          F: FnMut(&I::Item) -> V,
          I: Iterator,
{
    UniqueBy {
        iter: iter,
        used: HashMap::new(),
        f: f,
    }
}

// count the number of new unique keys in iterable (`used` is the set already seen)
fn count_new_keys<I, K>(mut used: HashMap<K, ()>, iterable: I) -> usize
    where I: IntoIterator<Item=K>,
          K: Hash + Eq,
{
    let iter = iterable.into_iter();
    let current_used = used.len();
    used.extend(iter.map(|key| (key, ())));
    used.len() - current_used
}

impl<I, V, F> Iterator for UniqueBy<I, V, F>
    where I: Iterator,
          V: Eq + Hash,
          F: FnMut(&I::Item) -> V
{
    type Item = I::Item;

    fn next(&mut self) -> Option<I::Item> {
        loop {
            match self.iter.next() {
                None => return None,
                Some(v) => {
                    let key = (self.f)(&v);
                    if self.used.insert(key, ()).is_none() {
                        return Some(v);
                    }
                }
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (low, hi) = self.iter.size_hint();
        ((low > 0 && self.used.is_empty()) as usize, hi)
    }

    fn count(self) -> usize {
        let mut key_f = self.f;
        count_new_keys(self.used, self.iter.map(move |elt| key_f(&elt)))
    }
}

impl<I> Iterator for Unique<I>
    where I: Iterator,
          I::Item: Eq + Hash + Clone
{
    type Item = I::Item;

    fn next(&mut self) -> Option<I::Item> {
        loop {
            match self.iter.iter.next() {
                None => return None,
                Some(v) => {
                    match self.iter.used.entry(v) {
                        Entry::Occupied(_) => { }
                        Entry::Vacant(entry) => {
                            let elt = entry.key().clone();
                            entry.insert(());
                            return Some(elt);
                        }
                    }
                }
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (low, hi) = self.iter.iter.size_hint();
        ((low > 0 && self.iter.used.is_empty()) as usize, hi)
    }

    fn count(self) -> usize {
        count_new_keys(self.iter.used, self.iter.iter)
    }
}

/// An iterator adapter to filter out duplicate elements.
///
/// See [`.unique()`](../trait.Itertools.html#method.unique) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Unique<I: Iterator> {
    iter: UniqueBy<I, I::Item, ()>,
}

impl<I> fmt::Debug for Unique<I>
    where I: Iterator + fmt::Debug,
          I::Item: Hash + Eq + fmt::Debug,
{
    debug_fmt_fields!(Unique, iter);
}

pub fn unique<I>(iter: I) -> Unique<I>
    where I: Iterator,
          I::Item: Eq + Hash,
{
    Unique {
        iter: UniqueBy {
            iter: iter,
            used: HashMap::new(),
            f: (),
        }
    }
}
<|endoftext|>


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

use arena::TypedArena;

use errors::Result;

// ----------------------------------------------------------------------
// Buffer classes

/// Basic APIs for byte buffers. A byte buffer has two attributes:
/// `capacity` and `size`: the former is the total bytes allocated for
/// the buffer, while the latter is the actual bytes that have valid data.
/// Invariant: `capacity` >= `size`.
///
/// A `Buffer` is immutable, meaning that one can only obtain the
/// underlying data for read only
pub trait Buffer {
  /// Get a shared reference to the underlying data
  fn data(&self) -> &[u8];

  /// Get the capacity of this buffer
  fn capacity(&self) -> usize;

  /// Get the size for this buffer
  fn size(&self) -> usize;
}

/// A byte buffer where client can obtain a unique reference to
/// the underlying data for both read and write
pub trait MutableBuffer: Buffer {
  /// Get a unique reference to the underlying data
  fn mut_data(&mut self) -> &mut [u8];

  /// Set the internal buffer to be `new_data`, discarding the old buffer.
  fn set_data(&mut self, new_data: Vec<u8>);
}

/// A type of buffer where the underlying data can grow and shrink
pub trait ResizableBuffer: MutableBuffer {
  fn resize(&mut self, new_cap: usize) -> Result<()>;
}

pub struct ByteBuffer {
  data: Vec<u8>
}

impl ByteBuffer {
  pub fn new(size: usize) -> Self {
    let data = vec![0; size];
    ByteBuffer { data: data }
  }
}

impl Buffer for ByteBuffer {
  fn data(&self) -> &[u8] {
    self.data.as_slice()
  }

  fn capacity(&self) -> usize {
    self.data.capacity()
  }

  fn size(&self) -> usize {
    self.data.len()
  }
}

impl MutableBuffer for ByteBuffer {
  fn mut_data(&mut self) -> &mut [u8] {
    self.data.as_mut_slice()
  }

  fn set_data(&mut self, new_data: Vec<u8>) {
    self.data = new_data;
  }
}

impl ResizableBuffer for ByteBuffer {
  fn resize(&mut self, new_cap: usize) -> Result<()> {
    self.data.resize(new_cap, 0);
    Ok(())
  }
}

// ----------------------------------------------------------------------
// MemoryPool classes

/// A central place for managing memory.
/// NOTE: client can only acquire byte buffers through this API, but not releasing.
/// All the memory will be released once the instance of this trait goes out of scope.
pub trait MemoryPool {
  /// Acquire a new byte buffer of at least `size` bytes
  /// Return a unique reference to the buffer
  fn acquire(&mut self, size: usize) -> Result<&mut Box<Buffer>>;

  /// Consume `buf` and add it to this memory pool
  /// After the call, `buf` has the same lifetime as the pool.
  /// Return a unique reference to the consumed buffer.
  fn consume(&mut self, buf: Box<Buffer>) -> &mut Box<Buffer>;

  /// Return the total number of bytes allocated so far
  fn cur_allocated(&self) -> i64;

  /// Return the maximum number of bytes allocated so far
  fn max_allocated(&self) -> i64;
}

pub struct DefaultMemoryPool {
  arena: TypedArena<Box<Buffer>>,
  cur_bytes_allocated: i64,
  max_bytes_allocated: i64
}

impl DefaultMemoryPool {
  fn new() -> Self {
    let arena = TypedArena::new();
    DefaultMemoryPool{ arena: arena, cur_bytes_allocated: 0, max_bytes_allocated: 0 }
  }
}

impl MemoryPool for DefaultMemoryPool {
  fn acquire(&mut self, size: usize) -> Result<&mut Box<Buffer>> {
    let buf = Box::new(ByteBuffer::new(size));
    let result: &mut Box<Buffer> = self.arena.alloc(buf);
    Ok(result)
  }

  fn consume(&mut self, buf: Box<Buffer>) -> &mut Box<Buffer> {
    self.arena.alloc(buf)
  }

  fn cur_allocated(&self) -> i64 {
    self.cur_bytes_allocated
  }

  fn max_allocated(&self) -> i64 {
    self.max_bytes_allocated
  }
}
<commit_msg>A few fixes on Buffer & MemoryPool utilities<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use std::cmp;
use arena::TypedArena;

use errors::Result;

// ----------------------------------------------------------------------
// Buffer classes

/// Basic APIs for byte buffers. A byte buffer has two attributes:
/// `capacity` and `size`: the former is the total bytes allocated for
/// the buffer, while the latter is the actual bytes that have valid data.
/// Invariant: `capacity` >= `size`.
///
/// A `Buffer` is immutable, meaning that one can only obtain the
/// underlying data for read only
pub trait Buffer {
  /// Get a shared reference to the underlying data
  fn data(&self) -> &[u8];

  /// Get the capacity of this buffer
  fn capacity(&self) -> usize;

  /// Get the size for this buffer
  fn size(&self) -> usize;
}

/// A byte buffer where client can obtain a unique reference to
/// the underlying data for both read and write
pub trait MutableBuffer: Buffer {
  /// Get a unique reference to the underlying data
  fn mut_data(&mut self) -> &mut [u8];

  /// Set the internal buffer to be `new_data`, discarding the old buffer.
  fn set_data(&mut self, new_data: Vec<u8>);

  /// Adjust the internal buffer's capacity to be `new_cap`.
  /// If the current size of the buffer is smaller than `new_cap`, data
  /// will be truncated.
  fn resize(&mut self, new_cap: usize) -> Result<()>;
}

// A mutable byte buffer struct

pub struct ByteBuffer {
  data: Vec<u8>
}

impl ByteBuffer {
  pub fn new(size: usize) -> Self {
    let data = vec![0; size];
    ByteBuffer { data: data }
  }
}

impl Buffer for ByteBuffer {
  fn data(&self) -> &[u8] {
    self.data.as_slice()
  }

  fn capacity(&self) -> usize {
    self.data.capacity()
  }

  fn size(&self) -> usize {
    self.data.len()
  }
}

impl MutableBuffer for ByteBuffer {
  fn mut_data(&mut self) -> &mut [u8] {
    self.data.as_mut_slice()
  }

  fn set_data(&mut self, new_data: Vec<u8>) {
    self.data = new_data;
  }

  fn resize(&mut self, new_cap: usize) -> Result<()> {
    self.data.resize(new_cap, 0);
    Ok(())
  }
}

// A immutable byte buffer struct

pub struct ImmutableByteBuffer<'a> {
  data: &'a [u8]
}

impl<'a> Buffer for ImmutableByteBuffer<'a> {
  fn data(&self) -> &[u8] {
    self.data
  }

  fn capacity(&self) -> usize {
    self.data.len()
  }

  fn size(&self) -> usize {
    self.data.len()
  }
}

// ----------------------------------------------------------------------
// MemoryPool classes

/// A central place for managing memory.
/// NOTE: client can only acquire bytes through this API, but not releasing.
/// All the memory will be released once the instance of this trait goes out of scope.
pub trait MemoryPool {
  /// Acquire a new byte buffer of at least `size` bytes
  /// Return a unique reference to the buffer
  fn acquire(&mut self, size: usize) -> Result<&mut [u8]>;

  /// Consume `buf` and add it to this memory pool
  /// After the call, `buf` has the same lifetime as the pool.
  /// Return a unique reference to the consumed buffer.
  fn consume(&mut self, buf: Vec<u8>) -> &mut [u8];

  /// Return the total number of bytes allocated so far
  fn cur_allocated(&self) -> i64;

  /// Return the maximum number of bytes allocated so far
  fn max_allocated(&self) -> i64;
}

pub struct DefaultMemoryPool {
  arena: TypedArena<Vec<u8>>,
  cur_bytes_allocated: i64,
  max_bytes_allocated: i64
}

impl DefaultMemoryPool {
  fn new() -> Self {
    let arena = TypedArena::new();
    DefaultMemoryPool{ arena: arena, cur_bytes_allocated: 0, max_bytes_allocated: 0 }
  }

  fn arena_alloc(&mut self, buf: Vec<u8>) -> &mut [u8] {
    let buf_len = buf.len() as i64;
    let result = self.arena.alloc(buf);
    self.cur_bytes_allocated += buf_len as i64;
    self.max_bytes_allocated = cmp::max(self.max_bytes_allocated, self.cur_bytes_allocated);
    result.as_mut_slice()
  }
}

impl MemoryPool for DefaultMemoryPool {
  fn acquire(&mut self, size: usize) -> Result<&mut [u8]> {
    let buf = vec![0; size];
    let result = self.arena_alloc(buf);
    Ok(result)
  }

  fn consume(&mut self, buf: Vec<u8>) -> &mut [u8] {
    self.arena_alloc(buf)
  }

  fn cur_allocated(&self) -> i64 {
    self.cur_bytes_allocated
  }

  fn max_allocated(&self) -> i64 {
    self.max_bytes_allocated
  }
}
<|endoftext|>


<commit_before>use std::any::Any;
use view::{View, ViewPath, ViewWrapper};
use views::{IdView, ViewRef};

/// Provides `call_on<V: View>` to views.
///
/// This trait is mostly a wrapper around [`View::call_on_any`].
///
/// It provides a nicer interface to find a view when you know its type.
///
/// [`View::call_on_any`]: ./trait.View.html#method.call_on_any
pub trait Finder {
    /// Tries to find the view pointed to by the given selector.
    ///
    /// If the view is not found, or if it is not of the asked type,
    /// it returns None.
    fn call_on<V, F, R>(&mut self, sel: &Selector, callback: F) -> Option<R>
    where
        V: View + Any,
        F: FnOnce(&mut V) -> R;

    /// Convenient method to use `call_on` with a `view::Selector::Id`.
    fn call_on_id<V, F, R>(&mut self, id: &str, callback: F) -> Option<R>
    where
        V: View + Any,
        F: FnOnce(&mut V) -> R,
    {
        self.call_on(&Selector::Id(id), callback)
    }

    /// Convenient method to find a view wrapped in an [`IdView`].
    ///
    /// [`IdView`]: views/struct.IdView.html
    fn find_id<V>(&mut self, id: &str) -> Option<ViewRef<V>>
    where
        V: View + Any,
    {
        self.call_on_id(id, IdView::<V>::get_mut)
    }
}

impl<T: View> Finder for T {
    fn call_on<V, F, R>(&mut self, sel: &Selector, callback: F) -> Option<R>
    where
        V: View + Any,
        F: FnOnce(&mut V) -> R,
    {
        let mut result = None;
        {
            let result_ref = &mut result;

            let mut callback = Some(callback);
            let callback = |v: &mut Any| {
                if let Some(callback) = callback.take() {
                    if v.is::<V>() {
                        *result_ref =
                            v.downcast_mut::<V>().map(|v| callback(v));
                    } else if v.is::<IdView<V>>() {
                        *result_ref = v
                            .downcast_mut::<IdView<V>>()
                            .and_then(|v| v.with_view_mut(callback));
                    }
                }
            };
            self.call_on_any(sel, Box::new(callback));
        }
        result
    }
}

/// Selects a single view (if any) in the tree.
pub enum Selector<'a> {
    /// Selects a view from its ID.
    Id(&'a str),
    /// Selects a view from its path.
    Path(&'a ViewPath),
}
<commit_msg>Fix doc for Finder::call_on<commit_after>use std::any::Any;
use view::{View, ViewPath, ViewWrapper};
use views::{IdView, ViewRef};

/// Provides `call_on<V: View>` to views.
///
/// This trait is mostly a wrapper around [`View::call_on_any`].
///
/// It provides a nicer interface to find a view when you know its type.
///
/// [`View::call_on_any`]: ./trait.View.html#method.call_on_any
pub trait Finder {
    /// Runs a callback on the view identified by `sel`.
    ///
    /// If the view is found, return the result of `callback`.
    ///
    /// If the view is not found, or if it is not of the asked type,
    /// it returns `None`.
    fn call_on<V, F, R>(&mut self, sel: &Selector, callback: F) -> Option<R>
    where
        V: View + Any,
        F: FnOnce(&mut V) -> R;

    /// Convenient method to use `call_on` with a `view::Selector::Id`.
    fn call_on_id<V, F, R>(&mut self, id: &str, callback: F) -> Option<R>
    where
        V: View + Any,
        F: FnOnce(&mut V) -> R,
    {
        self.call_on(&Selector::Id(id), callback)
    }

    /// Convenient method to find a view wrapped in an [`IdView`].
    ///
    /// [`IdView`]: views/struct.IdView.html
    fn find_id<V>(&mut self, id: &str) -> Option<ViewRef<V>>
    where
        V: View + Any,
    {
        self.call_on_id(id, IdView::<V>::get_mut)
    }
}

impl<T: View> Finder for T {
    fn call_on<V, F, R>(&mut self, sel: &Selector, callback: F) -> Option<R>
    where
        V: View + Any,
        F: FnOnce(&mut V) -> R,
    {
        let mut result = None;
        {
            let result_ref = &mut result;

            let mut callback = Some(callback);
            let callback = |v: &mut Any| {
                if let Some(callback) = callback.take() {
                    if v.is::<V>() {
                        *result_ref =
                            v.downcast_mut::<V>().map(|v| callback(v));
                    } else if v.is::<IdView<V>>() {
                        *result_ref = v
                            .downcast_mut::<IdView<V>>()
                            .and_then(|v| v.with_view_mut(callback));
                    }
                }
            };
            self.call_on_any(sel, Box::new(callback));
        }
        result
    }
}

/// Selects a single view (if any) in the tree.
pub enum Selector<'a> {
    /// Selects a view from its ID.
    Id(&'a str),
    /// Selects a view from its path.
    Path(&'a ViewPath),
}
<|endoftext|>