<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::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,
}

impl StorageBackend {

    pub fn new(basepath: String) -> StorageBackend {
        StorageBackend {
            basepath: basepath,
        }
    }

    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) -> Option<Vec<FileID>> {
        debug!("Getting files from {}", self.basepath);
        let list = glob(&self.basepath[..]);

        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<'a, HP>(&self, m: &'a Module, id: &FileID, p: &Parser<HP>) -> Option<File<'a>>
        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>Fixup: Import remove_file()<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::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,
}

impl StorageBackend {

    pub fn new(basepath: String) -> StorageBackend {
        StorageBackend {
            basepath: basepath,
        }
    }

    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) -> Option<Vec<FileID>> {
        debug!("Getting files from {}", self.basepath);
        let list = glob(&self.basepath[..]);

        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<'a, HP>(&self, m: &'a Module, id: &FileID, p: &Parser<HP>) -> Option<File<'a>>
        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)
        })
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;

use error::StreamError;
use stream::{Positioned, Resetable, StreamErrorFor, StreamOnce};

#[derive(Debug, PartialEq)]
pub struct BufferedStream<I>
where
    I: StreamOnce + Positioned,
{
    offset: usize,
    iter: I,
    buffer_offset: usize,
    buffer: VecDeque<(I::Item, I::Position)>,
}

impl<I> Resetable for BufferedStream<I>
where
    I: Positioned,
{
    type Checkpoint = usize;
    fn checkpoint(&self) -> Self::Checkpoint {
        self.offset
    }
    fn reset(&mut self, checkpoint: Self::Checkpoint) {
        self.offset = checkpoint;
    }
}

impl<I> BufferedStream<I>
where
    I: StreamOnce + Positioned,
    I::Position: Clone,
    I::Item: Clone,
{
    /// Constructs a new `BufferedStream` from a `StreamOnce` instance with a `lookahead`
    /// number of elements that can be stored in the buffer.
    pub fn new(iter: I, lookahead: usize) -> BufferedStream<I> {
        BufferedStream {
            offset: 0,
            iter: iter,
            buffer_offset: 0,
            buffer: VecDeque::with_capacity(lookahead),
        }
    }
}

impl<I> Positioned for BufferedStream<I>
where
    I: StreamOnce + Positioned,
{
    #[inline(always)]
    fn position(&self) -> Self::Position {
        if self.offset >= self.buffer_offset {
            self.iter.position()
        } else if self.offset < self.buffer_offset - self.buffer.len() {
            self.buffer
                .front()
                .expect("Atleast 1 element in the buffer")
                .1
                .clone()
        } else {
            self.buffer[self.buffer.len() - (self.buffer_offset - self.offset)]
                .1
                .clone()
        }
    }
}

impl<I> StreamOnce for BufferedStream<I>
where
    I: StreamOnce + Positioned,
    I::Item: Clone + PartialEq,
{
    type Item = I::Item;
    type Range = I::Range;
    type Position = I::Position;
    type Error = I::Error;

    #[inline]
    fn uncons(&mut self) -> Result<I::Item, StreamErrorFor<Self>> {
        if self.offset >= self.buffer_offset {
            let position = self.iter.position();
            let item = try!(self.iter.uncons());
            self.buffer_offset += 1;
            // We want the VecDeque to only keep the last .capacity() elements so we need to remove
            // an element if it gets to large
            if self.buffer.len() == self.buffer.capacity() {
                self.buffer.pop_front();
            }
            self.buffer.push_back((item.clone(), position.clone()));
            self.offset += 1;
            Ok(item)
        } else if self.offset < self.buffer_offset - self.buffer.len() {
            // We have backtracked to far
            Err(StreamError::message_static_message(
                "Backtracked to far".into(),
            ))
        } else {
            let value = self.buffer[self.buffer.len() - (self.buffer_offset - self.offset)]
                .0
                .clone();
            self.offset += 1;
            Ok(value)
        }
    }
}
<commit_msg>docs: Add docs on BufferedStream<commit_after>use std::collections::VecDeque;

use error::StreamError;
use stream::{Positioned, Resetable, StreamErrorFor, StreamOnce};

/// `Stream` which buffers items from an instance of `StreamOnce` into a ring buffer.
/// Instancs of `StreamOnce` which is not able to implement `Resetable` (such as `ReadStream`) may
/// use this as a way to implement `Resetable` and become a full `Stream` instance.
///
/// The drawback is that the buffer only stores a limited number of items which limits how many
/// tokens that can be reset and replayed. If a `BufferedStream` is reset past this limit an error
/// will be returned when `uncons` is next called.
///
/// NOTE: If this stream is used in conjunction with an error enhancing stream such as
/// `easy::Stream` (also via the `easy_parser` method) it is recommended that the `BufferedStream`
/// instance wraps the `easy::Stream` instance instead of the other way around.
///
/// ```ignore
/// // DO
/// BufferedStream::new(easy::Stream(..), ..)
/// // DONT
/// easy::Stream(BufferedStream::new(.., ..))
/// parser.easy_parse(BufferedStream::new(..));
/// ```
#[derive(Debug, PartialEq)]
pub struct BufferedStream<I>
where
    I: StreamOnce + Positioned,
{
    offset: usize,
    iter: I,
    buffer_offset: usize,
    buffer: VecDeque<(I::Item, I::Position)>,
}

impl<I> Resetable for BufferedStream<I>
where
    I: Positioned,
{
    type Checkpoint = usize;
    fn checkpoint(&self) -> Self::Checkpoint {
        self.offset
    }
    fn reset(&mut self, checkpoint: Self::Checkpoint) {
        self.offset = checkpoint;
    }
}

impl<I> BufferedStream<I>
where
    I: StreamOnce + Positioned,
    I::Position: Clone,
    I::Item: Clone,
{
    /// Constructs a new `BufferedStream` from a `StreamOnce` instance with a `lookahead`
    /// number of elements that can be stored in the buffer.
    pub fn new(iter: I, lookahead: usize) -> BufferedStream<I> {
        BufferedStream {
            offset: 0,
            iter: iter,
            buffer_offset: 0,
            buffer: VecDeque::with_capacity(lookahead),
        }
    }
}

impl<I> Positioned for BufferedStream<I>
where
    I: StreamOnce + Positioned,
{
    #[inline(always)]
    fn position(&self) -> Self::Position {
        if self.offset >= self.buffer_offset {
            self.iter.position()
        } else if self.offset < self.buffer_offset - self.buffer.len() {
            self.buffer
                .front()
                .expect("Atleast 1 element in the buffer")
                .1
                .clone()
        } else {
            self.buffer[self.buffer.len() - (self.buffer_offset - self.offset)]
                .1
                .clone()
        }
    }
}

impl<I> StreamOnce for BufferedStream<I>
where
    I: StreamOnce + Positioned,
    I::Item: Clone + PartialEq,
{
    type Item = I::Item;
    type Range = I::Range;
    type Position = I::Position;
    type Error = I::Error;

    #[inline]
    fn uncons(&mut self) -> Result<I::Item, StreamErrorFor<Self>> {
        if self.offset >= self.buffer_offset {
            let position = self.iter.position();
            let item = try!(self.iter.uncons());
            self.buffer_offset += 1;
            // We want the VecDeque to only keep the last .capacity() elements so we need to remove
            // an element if it gets to large
            if self.buffer.len() == self.buffer.capacity() {
                self.buffer.pop_front();
            }
            self.buffer.push_back((item.clone(), position.clone()));
            self.offset += 1;
            Ok(item)
        } else if self.offset < self.buffer_offset - self.buffer.len() {
            // We have backtracked to far
            Err(StreamError::message_static_message(
                "Backtracked to far".into(),
            ))
        } else {
            let value = self.buffer[self.buffer.len() - (self.buffer_offset - self.offset)]
                .0
                .clone();
            self.offset += 1;
            Ok(value)
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("InheritedBox", inherited=True, gecko_name="Visibility") %>

// TODO: collapse. Well, do tables first.
${helpers.single_keyword("visibility",
                         "visible hidden",
                         extra_gecko_values="collapse",
                         gecko_ffi_name="mVisible",
                         animation_value_type="ComputedValue",
                         spec="https://drafts.csswg.org/css-box/#propdef-visibility")}

// CSS Writing Modes Level 3
// https://drafts.csswg.org/css-writing-modes-3
${helpers.single_keyword("writing-mode",
                         "horizontal-tb vertical-rl vertical-lr",
                         extra_gecko_values="sideways-rl sideways-lr",
                         extra_gecko_aliases="lr=horizontal-tb lr-tb=horizontal-tb \
                                              rl=horizontal-tb rl-tb=horizontal-tb \
                                              tb=vertical-rl   tb-rl=vertical-rl",
                         experimental=True,
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-writing-modes/#propdef-writing-mode")}

${helpers.single_keyword("direction", "ltr rtl", animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction",
                         needs_conversion=True)}

${helpers.single_keyword("text-orientation",
                         "mixed upright sideways",
                         extra_gecko_aliases="sideways-right=sideways",
                         products="gecko",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-writing-modes/#propdef-text-orientation")}

// CSS Color Module Level 4
// https://drafts.csswg.org/css-color/
${helpers.single_keyword("color-adjust",
                         "economy exact", products="gecko",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-color/#propdef-color-adjust")}

<% image_rendering_custom_consts = { "crisp-edges": "CRISPEDGES",
                                     "-moz-crisp-edges": "CRISPEDGES" } %>
// According to to CSS-IMAGES-3, `optimizespeed` and `optimizequality` are synonyms for `auto`
// And, firefox doesn't support `pixelated` yet (https://bugzilla.mozilla.org/show_bug.cgi?id=856337)
${helpers.single_keyword("image-rendering",
                         "auto",
                         extra_gecko_values="optimizespeed optimizequality -moz-crisp-edges",
                         extra_servo_values="pixelated crisp-edges",
                         custom_consts=image_rendering_custom_consts,
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-images/#propdef-image-rendering")}

// Image Orientation
<%helpers:longhand name="image-orientation"
                   products="gecko"
                   animation_value_type="none"
    spec="https://drafts.csswg.org/css-images/#propdef-image-orientation, \
      /// additional values in https://developer.mozilla.org/en-US/docs/Web/CSS/image-orientation">
    use std::fmt;
    use style_traits::ToCss;
    use values::specified::Angle;

    no_viewport_percentage!(SpecifiedValue);

    use std::f64::consts::PI;
    const TWO_PI: f64 = 2.0 * PI;

    #[derive(Clone, PartialEq, Copy, Debug)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
    pub struct SpecifiedValue {
        pub angle: Option<Angle>,
        pub flipped: bool
    }

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            if let Some(angle) = self.angle {
                angle.to_css(dest)?;
                if self.flipped {
                    dest.write_str(" flip")
                } else {
                    Ok(())
                }
            } else {
                if self.flipped {
                    dest.write_str("flip")
                } else {
                    dest.write_str("from-image")
                }
            }
        }
    }

    pub mod computed_value {
        use std::fmt;
        use style_traits::ToCss;
        use values::specified::Angle;

        #[derive(Copy, Clone, Debug, Eq, PartialEq)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub enum Orientation {
            Angle0 = 0,
            Angle90,
            Angle180,
            Angle270,
        }

        impl Orientation {
            pub fn angle(&self) -> Angle {
                match *self {
                    Orientation::Angle0 => Angle::from_degrees(0.0, false),
                    Orientation::Angle90 => Angle::from_degrees(90.0, false),
                    Orientation::Angle180 => Angle::from_degrees(180.0, false),
                    Orientation::Angle270 => Angle::from_degrees(270.0, false),
                }
            }
        }

        impl ToCss for Orientation {
            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                // Should agree with Angle::to_css.
                match *self {
                    Orientation::Angle0 => dest.write_str("0deg"),
                    Orientation::Angle90 => dest.write_str("90deg"),
                    Orientation::Angle180 => dest.write_str("180deg"),
                    Orientation::Angle270 => dest.write_str("270deg"),
                }
            }
        }

        #[derive(Clone, PartialEq, Copy, Debug)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub enum T {
            FromImage,
            AngleWithFlipped(Orientation, bool),
        }
    }

    use self::computed_value::Orientation;

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T::AngleWithFlipped(Orientation::Angle0, false)
    }

    // According to CSS Content Module Level 3:
    // The computed value of the property is calculated by rounding the specified angle
    // to the nearest quarter-turn, rounding away from 0, then moduloing the value by 1 turn.
    // This mirrors the Gecko implementation in
    // nsStyleImageOrientation::CreateAsAngleAndFlip.
    #[inline]
    fn orientation_of_angle(angle: &computed::Angle) -> Orientation {
        // Note that `angle` can be negative.
        let mut rounded_angle = angle.radians64() % TWO_PI;
        if rounded_angle < 0.0 {
            // This computation introduces rounding error. Gecko previously
            // didn't handle the negative case correctly; by branching we can
            // match Gecko's behavior when it was correct.
            rounded_angle = rounded_angle + TWO_PI;
        }
        if      rounded_angle < 0.25 * PI { Orientation::Angle0   }
        else if rounded_angle < 0.75 * PI { Orientation::Angle90  }
        else if rounded_angle < 1.25 * PI { Orientation::Angle180 }
        else if rounded_angle < 1.75 * PI { Orientation::Angle270 }
        else                              { Orientation::Angle0   }
    }

    impl ToComputedValue for SpecifiedValue {
        type ComputedValue = computed_value::T;

        #[inline]
        fn to_computed_value(&self, context: &Context) -> computed_value::T {
            if let Some(ref angle) = self.angle {
                let angle = angle.to_computed_value(context);
                let orientation = orientation_of_angle(&angle);
                computed_value::T::AngleWithFlipped(orientation, self.flipped)
            } else {
                if self.flipped {
                    computed_value::T::AngleWithFlipped(Orientation::Angle0, true)
                } else {
                    computed_value::T::FromImage
                }
            }
        }

        #[inline]
        fn from_computed_value(computed: &computed_value::T) -> Self {
            match *computed {
                computed_value::T::FromImage => SpecifiedValue { angle: None, flipped: false },
                computed_value::T::AngleWithFlipped(ref orientation, flipped) => {
                    SpecifiedValue {
                        angle: Some(orientation.angle()),
                        flipped: flipped,
                    }
                }
            }
        }
    }

    impl ToCss for computed_value::T {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            match *self {
                computed_value::T::FromImage => dest.write_str("from-image"),
                computed_value::T::AngleWithFlipped(angle, flipped) => {
                    angle.to_css(dest)?;
                    if flipped {
                        dest.write_str(" flip")?;
                    }
                    Ok(())
                },
            }
        }
    }

    // from-image | <angle> | [<angle>? flip]
    pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                         -> Result<SpecifiedValue, ParseError<'i>> {
        if input.try(|input| input.expect_ident_matching("from-image")).is_ok() {
            // Handle from-image
            Ok(SpecifiedValue { angle: None, flipped: false })
        } else if input.try(|input| input.expect_ident_matching("flip")).is_ok() {
            // Handle flip
            Ok(SpecifiedValue { angle: Some(Angle::zero()), flipped: true })
        } else {
            // Handle <angle> | <angle> flip
            let angle = input.try(|input| Angle::parse(context, input)).ok();
            if angle.is_none() {
                return Err(StyleParseError::UnspecifiedError.into());
            }

            let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();
            Ok(SpecifiedValue { angle: angle, flipped: flipped })
        }
    }
</%helpers:longhand>

// Used in the bottom-up flow construction traversal to avoid constructing flows for
// descendants of nodes with `display: none`.
<%helpers:longhand name="-servo-under-display-none"
                   derived_from="display"
                   products="servo"
                   animation_value_type="none"
                   spec="Nonstandard (internal layout use only)">
    use std::fmt;
    use style_traits::ToCss;
    use values::computed::ComputedValueAsSpecified;

    no_viewport_percentage!(SpecifiedValue);

    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
    pub struct SpecifiedValue(pub bool);

    pub mod computed_value {
        pub type T = super::SpecifiedValue;
    }
    impl ComputedValueAsSpecified for SpecifiedValue {}

    pub fn get_initial_value() -> computed_value::T {
        SpecifiedValue(false)
    }

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
            Ok(()) // Internal property
        }
    }

    #[inline]
    pub fn derive_from_display(context: &mut Context) {
        use super::display::computed_value::T as Display;

        if context.style().get_box().clone_display() == Display::none {
            context.mutate_style().mutate_inheritedbox()
                                  .set__servo_under_display_none(SpecifiedValue(true));
        }
    }
</%helpers:longhand>
<commit_msg>Auto merge of #17745 - SergeevPavel:cleanup, r=emilio<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("InheritedBox", inherited=True, gecko_name="Visibility") %>

// TODO: collapse. Well, do tables first.
${helpers.single_keyword("visibility",
                         "visible hidden",
                         extra_gecko_values="collapse",
                         gecko_ffi_name="mVisible",
                         animation_value_type="ComputedValue",
                         spec="https://drafts.csswg.org/css-box/#propdef-visibility")}

// CSS Writing Modes Level 3
// https://drafts.csswg.org/css-writing-modes-3
${helpers.single_keyword("writing-mode",
                         "horizontal-tb vertical-rl vertical-lr",
                         extra_gecko_values="sideways-rl sideways-lr",
                         extra_gecko_aliases="lr=horizontal-tb lr-tb=horizontal-tb \
                                              rl=horizontal-tb rl-tb=horizontal-tb \
                                              tb=vertical-rl   tb-rl=vertical-rl",
                         experimental=True,
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-writing-modes/#propdef-writing-mode")}

${helpers.single_keyword("direction", "ltr rtl", animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction",
                         needs_conversion=True)}

${helpers.single_keyword("text-orientation",
                         "mixed upright sideways",
                         extra_gecko_aliases="sideways-right=sideways",
                         products="gecko",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-writing-modes/#propdef-text-orientation")}

// CSS Color Module Level 4
// https://drafts.csswg.org/css-color/
${helpers.single_keyword("color-adjust",
                         "economy exact", products="gecko",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-color/#propdef-color-adjust")}

<% image_rendering_custom_consts = { "crisp-edges": "CRISPEDGES",
                                     "-moz-crisp-edges": "CRISPEDGES" } %>
// According to to CSS-IMAGES-3, `optimizespeed` and `optimizequality` are synonyms for `auto`
// And, firefox doesn't support `pixelated` yet (https://bugzilla.mozilla.org/show_bug.cgi?id=856337)
${helpers.single_keyword("image-rendering",
                         "auto",
                         extra_gecko_values="optimizespeed optimizequality -moz-crisp-edges",
                         extra_servo_values="pixelated crisp-edges",
                         custom_consts=image_rendering_custom_consts,
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-images/#propdef-image-rendering")}

// Image Orientation
<%helpers:longhand name="image-orientation"
                   products="gecko"
                   animation_value_type="none"
    spec="https://drafts.csswg.org/css-images/#propdef-image-orientation, \
      /// additional values in https://developer.mozilla.org/en-US/docs/Web/CSS/image-orientation">
    use std::fmt;
    use style_traits::ToCss;
    use values::specified::Angle;

    no_viewport_percentage!(SpecifiedValue);

    use std::f64::consts::PI;
    const TWO_PI: f64 = 2.0 * PI;

    #[derive(Clone, PartialEq, Copy, Debug)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
    pub struct SpecifiedValue {
        pub angle: Option<Angle>,
        pub flipped: bool
    }

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            if let Some(angle) = self.angle {
                angle.to_css(dest)?;
                if self.flipped {
                    dest.write_str(" flip")
                } else {
                    Ok(())
                }
            } else {
                if self.flipped {
                    dest.write_str("flip")
                } else {
                    dest.write_str("from-image")
                }
            }
        }
    }

    pub mod computed_value {
        use std::fmt;
        use style_traits::ToCss;
        use values::specified::Angle;

        #[derive(Copy, Clone, Debug, Eq, PartialEq)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub enum Orientation {
            Angle0 = 0,
            Angle90,
            Angle180,
            Angle270,
        }

        impl Orientation {
            pub fn angle(&self) -> Angle {
                match *self {
                    Orientation::Angle0 => Angle::from_degrees(0.0, false),
                    Orientation::Angle90 => Angle::from_degrees(90.0, false),
                    Orientation::Angle180 => Angle::from_degrees(180.0, false),
                    Orientation::Angle270 => Angle::from_degrees(270.0, false),
                }
            }
        }

        impl ToCss for Orientation {
            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                // Should agree with Angle::to_css.
                match *self {
                    Orientation::Angle0 => dest.write_str("0deg"),
                    Orientation::Angle90 => dest.write_str("90deg"),
                    Orientation::Angle180 => dest.write_str("180deg"),
                    Orientation::Angle270 => dest.write_str("270deg"),
                }
            }
        }

        #[derive(Clone, PartialEq, Copy, Debug)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub enum T {
            FromImage,
            AngleWithFlipped(Orientation, bool),
        }
    }

    use self::computed_value::Orientation;

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T::AngleWithFlipped(Orientation::Angle0, false)
    }

    // According to CSS Content Module Level 3:
    // The computed value of the property is calculated by rounding the specified angle
    // to the nearest quarter-turn, rounding away from 0, then moduloing the value by 1 turn.
    // This mirrors the Gecko implementation in
    // nsStyleImageOrientation::CreateAsAngleAndFlip.
    #[inline]
    fn orientation_of_angle(angle: &computed::Angle) -> Orientation {
        // Note that `angle` can be negative.
        let mut rounded_angle = angle.radians64() % TWO_PI;
        if rounded_angle < 0.0 {
            // This computation introduces rounding error. Gecko previously
            // didn't handle the negative case correctly; by branching we can
            // match Gecko's behavior when it was correct.
            rounded_angle = rounded_angle + TWO_PI;
        }
        if rounded_angle < 0.25 * PI {
            return Orientation::Angle0
        }
        if rounded_angle < 0.75 * PI {
            return Orientation::Angle90
        }
        if rounded_angle < 1.25 * PI {
            return Orientation::Angle180
        }
        if rounded_angle < 1.75 * PI {
            return Orientation::Angle270
        }
        Orientation::Angle0
    }

    impl ToComputedValue for SpecifiedValue {
        type ComputedValue = computed_value::T;

        #[inline]
        fn to_computed_value(&self, context: &Context) -> computed_value::T {
            if let Some(ref angle) = self.angle {
                let angle = angle.to_computed_value(context);
                let orientation = orientation_of_angle(&angle);
                computed_value::T::AngleWithFlipped(orientation, self.flipped)
            } else {
                if self.flipped {
                    computed_value::T::AngleWithFlipped(Orientation::Angle0, true)
                } else {
                    computed_value::T::FromImage
                }
            }
        }

        #[inline]
        fn from_computed_value(computed: &computed_value::T) -> Self {
            match *computed {
                computed_value::T::FromImage => SpecifiedValue { angle: None, flipped: false },
                computed_value::T::AngleWithFlipped(ref orientation, flipped) => {
                    SpecifiedValue {
                        angle: Some(orientation.angle()),
                        flipped: flipped,
                    }
                }
            }
        }
    }

    impl ToCss for computed_value::T {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            match *self {
                computed_value::T::FromImage => dest.write_str("from-image"),
                computed_value::T::AngleWithFlipped(angle, flipped) => {
                    angle.to_css(dest)?;
                    if flipped {
                        dest.write_str(" flip")?;
                    }
                    Ok(())
                },
            }
        }
    }

    // from-image | <angle> | [<angle>? flip]
    pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                         -> Result<SpecifiedValue, ParseError<'i>> {
        if input.try(|input| input.expect_ident_matching("from-image")).is_ok() {
            // Handle from-image
            Ok(SpecifiedValue { angle: None, flipped: false })
        } else if input.try(|input| input.expect_ident_matching("flip")).is_ok() {
            // Handle flip
            Ok(SpecifiedValue { angle: Some(Angle::zero()), flipped: true })
        } else {
            // Handle <angle> | <angle> flip
            let angle = input.try(|input| Angle::parse(context, input)).ok();
            if angle.is_none() {
                return Err(StyleParseError::UnspecifiedError.into());
            }

            let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();
            Ok(SpecifiedValue { angle: angle, flipped: flipped })
        }
    }
</%helpers:longhand>

// Used in the bottom-up flow construction traversal to avoid constructing flows for
// descendants of nodes with `display: none`.
<%helpers:longhand name="-servo-under-display-none"
                   derived_from="display"
                   products="servo"
                   animation_value_type="none"
                   spec="Nonstandard (internal layout use only)">
    use std::fmt;
    use style_traits::ToCss;
    use values::computed::ComputedValueAsSpecified;

    no_viewport_percentage!(SpecifiedValue);

    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
    pub struct SpecifiedValue(pub bool);

    pub mod computed_value {
        pub type T = super::SpecifiedValue;
    }
    impl ComputedValueAsSpecified for SpecifiedValue {}

    pub fn get_initial_value() -> computed_value::T {
        SpecifiedValue(false)
    }

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
            Ok(()) // Internal property
        }
    }

    #[inline]
    pub fn derive_from_display(context: &mut Context) {
        use super::display::computed_value::T as Display;

        if context.style().get_box().clone_display() == Display::none {
            context.mutate_style().mutate_inheritedbox()
                                  .set__servo_under_display_none(SpecifiedValue(true));
        }
    }
</%helpers:longhand>
<|endoftext|>


<commit_before>%-------------------------------------------------------------
% Nonlinear New Keynesian Model
% Reference: Foerster, Rubio-Ramirez, Waggoner and Zha (2013)
% Perturbation Methods for Markov Switching Models.
%-------------------------------------------------------------

endogenous PAI, "Inflation", Y, "Output gap", R, "Interest rate"

exogenous EPS_R	"Monetary policy shock"

parameters betta, eta, kappa, rhor sigr a_tp_1_2, a_tp_2_1 %, mu_bar

parameters(a,2) mu, psi

model
	1-betta*(1-.5*kappa*(PAI-1)^2)*Y*R/((1-.5*kappa*(PAI{+1}-1)^2)*Y{+1}*exp(mu)*PAI{+1});

	1-eta+eta*(1-.5*kappa*(PAI-1)^2)*Y+betta*kappa*(1-.5*kappa*(PAI-1)^2)*(PAI{+1}-1)*PAI{+1}/(1-.5*kappa*(PAI{+1}-1)^2)
	-kappa*(PAI-1)*PAI;

	(R{-1}/steady_state(R))^rhor*(PAI/steady_state(PAI))^((1-rhor)*psi)*exp(sigr*EPS_R)-R/steady_state(R);

steady_state_model
    PAI=1;
    Y=(eta-1)/eta;
    R=exp(mu)/betta*PAI;

parameterization
	a_tp_1_2,1-.9;
	a_tp_2_1,1-.9;
	betta, .99;
	kappa, 161;
	eta, 10;
	rhor, .8;
	sigr, 0.0025;
	%%mu_bar,0.02;
	mu(a,1), 0.03;
	mu(a,2), 0.01;
	psi(a,1), 3.1;
	psi(a,2), 0.9;
<commit_msg>cosmetics<commit_after>%-------------------------------------------------------------
% Nonlinear New Keynesian Model
% Reference: Foerster, Rubio-Ramirez, Waggoner and Zha (2013)
% Perturbation Methods for Markov Switching Models.
%-------------------------------------------------------------

endogenous PAI, "Inflation", Y, "Output gap", R, "Interest rate"

exogenous EPS_R	"Monetary policy shock"

parameters betta, eta, kappa, rhor sigr a_tp_1_2, a_tp_2_1

parameters(a,2) mu, psi

model
	1-betta*(1-.5*kappa*(PAI-1)^2)*Y*R/((1-.5*kappa*(PAI{+1}-1)^2)*Y{+1}*exp(mu)*PAI{+1});

	1-eta+eta*(1-.5*kappa*(PAI-1)^2)*Y+betta*kappa*(1-.5*kappa*(PAI-1)^2)*(PAI{+1}-1)*PAI{+1}/(1-.5*kappa*(PAI{+1}-1)^2)
	-kappa*(PAI-1)*PAI;

	(R{-1}/steady_state(R))^rhor*(PAI/steady_state(PAI))^((1-rhor)*psi)*exp(sigr*EPS_R)-R/steady_state(R);

steady_state_model
    PAI=1;
    Y=(eta-1)/eta;
    R=exp(mu)/betta*PAI;

parameterization
	a_tp_1_2,1-.9;
	a_tp_2_1,1-.9;
	betta, .99;
	kappa, 161;
	eta, 10;
	rhor, .8;
	sigr, 0.0025;
	mu(a,1), 0.03;
	mu(a,2), 0.01;
	psi(a,1), 3.1;
	psi(a,2), 0.9;
<|endoftext|>


<commit_before>//
// zhttpto.rs
//
// Starting code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str};
use std::io::buffered::BufferedReader;

static IP: &'static str  = "127.0.0.1";
static PORT:        int  = 4414;
static mut visitor_count: uint = 0;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {
        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                             match s.peer_name() {
                                Some(pn) => {println(format!("Received connection from: [{:s}]", pn.to_str()));},
                                None => ()
                             }
                           },
                None => ()
            }
            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);
            let lines: ~[&str] = request_str.split('\n').collect();
            let firstline = lines[0];
            let after=firstline.slice_from(4).to_owned();
            let then: ~[&str]=after.split(' ').collect();
            let filename = then[0].slice_from(1);
            println!("filename: {:s}", filename);
            println!("Received request :\n{:s}", request_str);
            unsafe { atomic_add(&mut visitor_count, 1);
                     println!("Visitor count: {:u}", visitor_count);
            }
            let filepath = Path::new(filename);
            match File::open(&filepath) {
                Some (file) => {
                    let mut filereader = ~BufferedReader::new(file);
                    let mut contents : ~str = ~"";
                    println("Reading file ...");
                    for line in filereader.lines() {
                        println!("Found line: {:s}.", line);
                        contents = contents + "
" + line;
                    }
                    let response: ~str =
                        ~"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                        <doctype !html><title>Hello, Rust!</title>
                        "
                        + contents
                            + unsafe{
                                visitor_count.to_str()
                            } + "

                        \r\n";
                    stream.write(response.as_bytes());
                    println("Connection terminates.");
                }
                None => {
                    let response: ~str =
                        ~"HTTP/1.1 404 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                        <doctype !html><title>Hello, Rust!</title>

                        \r\n";
                    stream.write(response.as_bytes());
                    println!("Mad world.");
                }
            }
        }
    }
}

fn atomic_add(var: &mut uint, count: uint) -> uint {
    let oldval = var.clone();
    *var = *var + count;
    return oldval;
}
<commit_msg>refactors core components into functions<commit_after>//
// zhttpto.rs
//
// Starting code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str};
use std::io::buffered::BufferedReader;

static IP: &'static str  = "127.0.0.1";
static PORT:        int  = 4414;
static mut visitor_count: uint = 0;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {
        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                    match s.peer_name() {
                        Some(pn) => {
                            println(format!("Received connection from: [{:s}]", pn.to_str()));
                            },
                        None => ()
                    }
                },
                None => ()
            }
            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);
            let filename = get_requested_filename(request_str);
            println!("filename: {:s}", filename);
            println!("Received request :\n{:s}", request_str);
            unsafe { atomic_add(&mut visitor_count, 1);
                     println!("Visitor count: {:u}", visitor_count);
            }
            let filepath = Path::new(filename);
            match File::open(&filepath) {
                Some (file) => {
                    let contents = get_file_contents(file);
                    let response: ~str =
                        ~"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                        <doctype !html><title>Hello, Rust!</title>
                        "
                        + contents
                            + unsafe{
                                visitor_count.to_str()
                            } + "

                        \r\n";
                    stream.write(response.as_bytes());
                    println("Connection terminates.");
                },
                None => {
                    let response: ~str =
                        ~"HTTP/1.1 404 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                        <doctype !html><title>Hello, Rust!</title>

                        \r\n";
                    stream.write(response.as_bytes());
                    println!("Mad world.");
                }
            }
        }
    }
}

fn get_requested_filename(request: &str) -> &str {
    let lines: ~[&str] = request.split('\n').collect();
    let firstline = lines[0];
    let after=firstline.slice_from(4).to_owned();
    let then: ~[&str]=after.split(' ').collect();
    let filename = then[0].slice_from(1);
    filename
}

fn get_file_contents(file: File) -> ~str {
    let mut filereader = ~BufferedReader::new(file);
    let mut contents : ~str = ~"";
    println("Reading file ...");
    for line in filereader.lines() {
        contents = contents + "
" + line;
    }
    contents
}

fn atomic_add(var: &mut uint, count: uint) -> uint {
    let oldval = var.clone();
    *var = *var + count;
    return oldval;
}
<|endoftext|>


<commit_before>//!
//! Generic addresses
//!

use std::{fmt, mem};

/// A trait for all 16-bit address types
pub trait Address: Copy + Ord + Eq + fmt::UpperHex {
    /// The zero address
    /// TODO: Use std::num::Zero instead when it becomes stable
    fn zero () -> Self;

    /// The address as an unsigned integer
    fn to_u16 (&self) -> u16;

    /// The succeeding address (wrapping)
    fn next (&self) -> Self;

    /// Calculate new address with given offset (wrapping)
    fn offset (&self, offset: i16) -> Self;

    /// Return an iterator for getting successive addresses (wrapping)
    fn successive (&self) -> Iter<Self> {
        Iter { addr: *self }
    }

    /// Return an object for displaying the address
    fn display (&self) -> Display<Self> {
        Display { addr: self }
    }
}

impl Address for u16 {
    fn zero () -> u16 { 0 }

    fn to_u16 (&self) -> u16 { *self }

    fn next (&self) -> u16 { self.wrapping_add(1) }

    fn offset (&self, offset: i16) -> u16 {
        if offset < 0 {
            self.wrapping_sub((-offset as u16))
        } else {
            self.wrapping_add(offset as u16)
        }
    }
}

/// Iterator for getting successive addresses
pub struct Iter<A> {
    addr: A,
}

impl<A: Address> Iter<A> {
    /// Bound iterator to only run until the given last address
    pub fn upto (self, last_addr: A) -> UpTo<A> {
        UpTo { it: self, last_addr: last_addr, flag: false }
    }
}

impl<A: Address> Iterator for Iter<A> {
    type Item = A;

    fn next (&mut self) -> Option<A> {
        let addr = self.addr;
        self.addr = self.addr.next();
        Some(addr)
    }
}

/// Iterator for getting successive addresses until a given last address
pub struct UpTo<A> {
    it: Iter<A>,
    last_addr: A,
    flag: bool,
}

impl<A: Address> Iterator for UpTo<A> {
    type Item = A;

    fn next (&mut self) -> Option<A> {
        if self.flag {
            None
        } else {
            self.it.next().and_then(|x| {
                if x == self.last_addr { self.flag = true; }
                Some(x)
            })
        }
    }
}

/// Helper struct for displaying an address
pub struct Display<'a, A: 'a> {
    addr: &'a A,
}

impl<'a, A: Address> fmt::Display for Display<'a, A> {
    fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result {
        match mem::size_of::<A>() {
            1 => write!(f, "${:02X}", self.addr),
            2 => write!(f, "${:04X}", self.addr),
            4 => write!(f, "${:08X}", self.addr),
            _ => write!(f, "${:X}", self.addr),
        }
    }
}

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

    #[test]
    fn zero () {
        assert_eq!(u16::zero(), 0x0000);
    }

    #[test]
    fn next () {
        assert_eq!(0x1234.next(), 0x1235);
        assert_eq!(0xffff.next(), 0x0000);
    }

    #[test]
    fn offset () {
        assert_eq!(0x1234.offset( 5), 0x1239);
        assert_eq!(0x1234.offset(-3), 0x1231);
    }

    #[test]
    fn offset_wrapping () {
        assert_eq!(0xffff.offset( 1), 0x0000);
        assert_eq!(0x0000.offset(-1), 0xffff);
    }

    #[test]
    fn iterating () {
        let mut it = 0xfffe.successive();
        assert_eq!(it.next(), Some(0xfffe));
        assert_eq!(it.next(), Some(0xffff));
        assert_eq!(it.next(), Some(0x0000));
        assert_eq!(it.next(), Some(0x0001));
    }

    #[test]
    fn bounded_iterating () {
        let mut it = 0xfffe.successive().upto(0xffff);
        assert_eq!(it.next(), Some(0xfffe));
        assert_eq!(it.next(), Some(0xffff));
        assert_eq!(it.next(), None);
        assert_eq!(it.next(), None);
    }

    #[test]
    fn displaying () {
        assert_eq!(format!("{}", 0x01ff.display()), "$01FF");
    }
}
<commit_msg>Remove unnecessary parentheses<commit_after>//!
//! Generic addresses
//!

use std::{fmt, mem};

/// A trait for all 16-bit address types
pub trait Address: Copy + Ord + Eq + fmt::UpperHex {
    /// The zero address
    /// TODO: Use std::num::Zero instead when it becomes stable
    fn zero () -> Self;

    /// The address as an unsigned integer
    fn to_u16 (&self) -> u16;

    /// The succeeding address (wrapping)
    fn next (&self) -> Self;

    /// Calculate new address with given offset (wrapping)
    fn offset (&self, offset: i16) -> Self;

    /// Return an iterator for getting successive addresses (wrapping)
    fn successive (&self) -> Iter<Self> {
        Iter { addr: *self }
    }

    /// Return an object for displaying the address
    fn display (&self) -> Display<Self> {
        Display { addr: self }
    }
}

impl Address for u16 {
    fn zero () -> u16 { 0 }

    fn to_u16 (&self) -> u16 { *self }

    fn next (&self) -> u16 { self.wrapping_add(1) }

    fn offset (&self, offset: i16) -> u16 {
        if offset < 0 {
            self.wrapping_sub(-offset as u16)
        } else {
            self.wrapping_add(offset as u16)
        }
    }
}

/// Iterator for getting successive addresses
pub struct Iter<A> {
    addr: A,
}

impl<A: Address> Iter<A> {
    /// Bound iterator to only run until the given last address
    pub fn upto (self, last_addr: A) -> UpTo<A> {
        UpTo { it: self, last_addr: last_addr, flag: false }
    }
}

impl<A: Address> Iterator for Iter<A> {
    type Item = A;

    fn next (&mut self) -> Option<A> {
        let addr = self.addr;
        self.addr = self.addr.next();
        Some(addr)
    }
}

/// Iterator for getting successive addresses until a given last address
pub struct UpTo<A> {
    it: Iter<A>,
    last_addr: A,
    flag: bool,
}

impl<A: Address> Iterator for UpTo<A> {
    type Item = A;

    fn next (&mut self) -> Option<A> {
        if self.flag {
            None
        } else {
            self.it.next().and_then(|x| {
                if x == self.last_addr { self.flag = true; }
                Some(x)
            })
        }
    }
}

/// Helper struct for displaying an address
pub struct Display<'a, A: 'a> {
    addr: &'a A,
}

impl<'a, A: Address> fmt::Display for Display<'a, A> {
    fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result {
        match mem::size_of::<A>() {
            1 => write!(f, "${:02X}", self.addr),
            2 => write!(f, "${:04X}", self.addr),
            4 => write!(f, "${:08X}", self.addr),
            _ => write!(f, "${:X}", self.addr),
        }
    }
}

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

    #[test]
    fn zero () {
        assert_eq!(u16::zero(), 0x0000);
    }

    #[test]
    fn next () {
        assert_eq!(0x1234.next(), 0x1235);
        assert_eq!(0xffff.next(), 0x0000);
    }

    #[test]
    fn offset () {
        assert_eq!(0x1234.offset( 5), 0x1239);
        assert_eq!(0x1234.offset(-3), 0x1231);
    }

    #[test]
    fn offset_wrapping () {
        assert_eq!(0xffff.offset( 1), 0x0000);
        assert_eq!(0x0000.offset(-1), 0xffff);
    }

    #[test]
    fn iterating () {
        let mut it = 0xfffe.successive();
        assert_eq!(it.next(), Some(0xfffe));
        assert_eq!(it.next(), Some(0xffff));
        assert_eq!(it.next(), Some(0x0000));
        assert_eq!(it.next(), Some(0x0001));
    }

    #[test]
    fn bounded_iterating () {
        let mut it = 0xfffe.successive().upto(0xffff);
        assert_eq!(it.next(), Some(0xfffe));
        assert_eq!(it.next(), Some(0xffff));
        assert_eq!(it.next(), None);
        assert_eq!(it.next(), None);
    }

    #[test]
    fn displaying () {
        assert_eq!(format!("{}", 0x01ff.display()), "$01FF");
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(test, allow(dead_code))]

extern crate arguments;
extern crate log;
extern crate random;

#[macro_use]
extern crate streamer;

use std::path::PathBuf;
use streamer::{Error, Result, Streamer};

mod logger;

const USAGE: &'static str = "
Usage: streamer [options]

Options:
    --config <path>          Configuration file (required).

    --help                   Display this message.
";

fn main() {
    logger::setup();
    start().unwrap_or_else(|error| fail(error));
}

fn start() -> Result<()> {
    let arguments = ok!(arguments::parse(std::env::args()));

    if arguments.get::<bool>("help").unwrap_or(false) {
        help();
    }
    let streamer = match arguments.get::<String>("config").map(|config| PathBuf::from(config)) {
        Some(ref config) => try!(Streamer::new(config)),
        _ => raise!("a configuration file is required"),
    };

    let mut source = random::default().seed([0x12345678, 0x87654321]);

    for state in streamer.iter(&mut source) {
        println!("{}", state);
    }

    Ok(())
}

fn help() -> ! {
    println!("{}", USAGE.trim());
    std::process::exit(0);
}

fn fail(error: Error) -> ! {
    use std::io::{stderr, Write};
    stderr().write_all(format!("Error: {}.\n", &*error).as_bytes()).unwrap();
    std::process::exit(1);
}
<commit_msg>Limit the number of samples<commit_after>#![cfg_attr(test, allow(dead_code))]

extern crate arguments;
extern crate log;
extern crate random;

#[macro_use]
extern crate streamer;

use std::path::PathBuf;
use streamer::{Error, Result, Streamer};

mod logger;

const USAGE: &'static str = "
Usage: streamer [options]

Options:
    --config <path>          Configuration file (required).

    --help                   Display this message.
";

fn main() {
    logger::setup();
    start().unwrap_or_else(|error| fail(error));
}

fn start() -> Result<()> {
    let arguments = ok!(arguments::parse(std::env::args()));

    if arguments.get::<bool>("help").unwrap_or(false) {
        help();
    }
    let streamer = match arguments.get::<String>("config").map(|config| PathBuf::from(config)) {
        Some(ref config) => try!(Streamer::new(config)),
        _ => raise!("a configuration file is required"),
    };

    let mut source = random::default().seed([0x42, 0x69]);

    for state in streamer.iter(&mut source).take(100) {
        println!("{}", state);
    }

    Ok(())
}

fn help() -> ! {
    println!("{}", USAGE.trim());
    std::process::exit(0);
}

fn fail(error: Error) -> ! {
    use std::io::{stderr, Write};
    stderr().write_all(format!("Error: {}.\n", &*error).as_bytes()).unwrap();
    std::process::exit(1);
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015 dinowernli
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use std::f64;

use bitstring::Bit;
use bitstring::Bitstring;

// Open questions:
// - How to declare some fields final
// - How to declare some fields mutable (can be changed for non-mut self)
// - Have the tree implement iter and simplify some methods with "fold".

/// An object capable of predicting observations and rewards based on
/// experience. Predictors have an abstract notion of history which
/// grows over time and represents the experience.
pub trait Predictor {
  /// Returns the size of the currently tracked history.
  fn history_size(&self) -> usize;

  /// Appends the provided bit string to the tracked history.
  fn update(&mut self, bitstring: &Bitstring);

  /// Reverts the context tree to a previous state by undoing update
  /// operations. The specified size must be at most the current size.
  fn revert_to_history_size(&mut self, target_size: usize);
}

/// Context tree which computes a probability estimate for a sequence of
/// bits based on a mixture model of Markov chains. Lower-degree Markov
/// chains have higher priors in the mixture model, thus formalizing the
/// notion of Occam's Razor.
///
/// In order to get a probability for a sequence, all bits in the sequence
/// must be processed in-order.
pub struct ContextTree {
  root: Node,
  history: Bitstring,
  depth: usize,
}

impl Predictor for ContextTree {
  fn history_size(&self) -> usize {
    self.history.len()
  }

  fn revert_to_history_size(&mut self, target_size: usize) {
    assert!(target_size <= self.history_size());
    while target_size > self.history_size() {
      self.revert_last();
    }
  }

  fn update(&mut self, bitstring: &Bitstring) {
    for bit in bitstring.bits() {
      self.update_bit(*bit);
    }
  }
}

impl ContextTree {
  /// The depth of the tree is the distance between leaves and the root.
  /// For a given depth d, the tree will compute a mixture model of all
  /// Markov chains of degree at most d.
  pub fn create(depth: usize) -> Self {
    ContextTree {
      root: Node::create_root(depth, 0),
      history: Bitstring::new(),
      depth: depth,
    }
  }

  /// Returns the total number of nodes in the tree.
  pub fn size(&self) -> usize {
    self.root.size()
  }

  fn update_bit(&mut self, bit: Bit) {
    if self.history_size() < self.depth {
      self.history.push(bit);
      return;
    }
    // TODO(dinowernli): Find current context path and update from leaf
    // to root.
  }

  fn revert_last(&mut self) {
    let bit = self.history.pop();
    self.root.revert(bit);
  }

  /// Returns log2 of the estimated probability of the current history.
  fn log_block_prob(&mut self) -> f64 {
    return self.root.log_weighted_prob();
  }
}

/// One node in the context tree. Maintains a count of the number
/// of zeroes and ones seen and provides access to partial results
/// of the overall probability estimates computed in the context
/// tree.
struct Node {
  /// Children.
  zero_child: Option<Box<Node>>,
  one_child: Option<Box<Node>>,

  /// Frequencies.
  zeroes: u64,
  ones: u64,

  /// The log2 of the probability of a sequence with self.zeroes zeroes
  /// and self.ones one. Computed using the Krichevsky Trofimov
  /// estimator algorithm.
  log_kt_prob: f64,

  /// The log2 of the weighted block probability of the current sequence.
  /// Funtion of self.zeroes and self.ones and the values recursively
  /// provided by the children of this node (if any), lazily recomputed.
  log_weighted_prob: f64,
}

impl Node {
  /// Creates a node and all its children recursively until the provided
  /// depth is reached.
  pub fn create_root(target_depth: usize, current_depth: usize) -> Self {
    if target_depth == current_depth {
      return Node::new(None, None);  // Leaf.
    } else {
      return Node::new(
          Some(Box::new(Node::create_root(target_depth, current_depth + 1))),
          Some(Box::new(Node::create_root(target_depth, current_depth + 1))));
    }
  }

  fn new(zero_child: Option<Box<Node>>, one_child: Option<Box<Node>>) -> Self {
    // Context trees are complete trees (either both children or no children).
    assert!(zero_child.is_none() == one_child.is_none());

    return Node {
      zero_child: zero_child,
      one_child: one_child,
      zeroes: 0,
      ones: 0,
      log_kt_prob: 0.0,
      log_weighted_prob: 0.0,
    };
  }

  pub fn log_weighted_prob(&self) -> f64 {
    self.log_weighted_prob
  }

  /// Updates the state of the node based on the value of the new bit.
  /// Assumes that child nodes (if any) have already been updated.
  pub fn update(&mut self, bit: Bit) {
    match bit {
      Bit::Zero => self.zeroes += 1,
      Bit::One => self.ones += 1,
    }

    // Old value + 0.5 is the same as new value - 0.5.
    let first_summand = match bit {
      Bit::Zero => self.zeroes as f64 - 0.5,
      Bit::One => self.ones as f64 - 0.5,
    }.log2();
    let norm_summand = ((self.zeroes + self.ones) as f64).log2();

    self.log_kt_prob = first_summand - norm_summand + self.log_kt_prob;
    self.update_weighted_prob();
  }

  /// Corresponds to undoing one update for the specified bit value.
  /// Assumes that child nodes (if any) have already been reverted.
  pub fn revert(&mut self, bit: Bit) {
    match bit {
      Bit::Zero => self.zeroes -= 1,
      Bit::One => self.ones -= 1,
    }
    // TODO(dinowernli): Update kt probs.
    self.update_weighted_prob();
  }

  /// Updates the value of log_weighted_prob. Assumes that log_kt_prob
  /// as well as all values in all children (if any) are up-to-date.
  fn update_weighted_prob(&mut self) {
    if self.is_leaf() {
      self.log_weighted_prob = self.log_kt_prob;
      return;
    }

    let log_weighted_probs =
        self.zero_child.as_ref().unwrap().log_weighted_prob() +
        self.one_child.as_ref().unwrap().log_weighted_prob();
    let exponent = log_weighted_probs - self.log_kt_prob;
    let power = exponent.exp2();

    // The recursive term should be log2(1 + 2^exponent). If the exponent is
    // large enough, 2^exponent is inf. In this case, we approximate
    // log2(1 + 2^exponent) by log2(2^exponent) = exponent.
    let recursive_term =
        if power == f64::INFINITY { exponent } else { (power + 1.0).log2() };

    self.log_weighted_prob = self.log_kt_prob + recursive_term - 1.0;
  }

  /// Returns the number of nodes in the subtree rooted at this node.
  fn size(&self) -> usize {
    1 + match self.zero_child {
      None => 0,
      Some(ref node) => node.size(),
    } + match self.one_child {
      None => 0,
      Some(ref node) => node.size(),
    }
  }

  fn is_leaf(&self) -> bool {
    // By construction we have either both children or none.
    return self.zero_child.is_none();
  }
}
<commit_msg>Add support for determining a context tree's context, and use that to allow updating and reverting single bits in the tree.<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 dinowernli
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use std::f64;

use bitstring::Bit;
use bitstring::Bitstring;

// Open questions:
// - How to declare some fields final
// - How to declare some fields mutable (can be changed for non-mut self)
// - Have the tree implement iter and simplify some methods with "fold".

/// An object capable of predicting observations and rewards based on
/// experience. Predictors have an abstract notion of history which
/// grows over time and represents the experience.
pub trait Predictor {
  /// Returns the size of the currently tracked history.
  fn history_size(&self) -> usize;

  /// Appends the provided bit string to the tracked history.
  fn update(&mut self, bitstring: &Bitstring);

  /// Reverts the context tree to a previous state by undoing update
  /// operations. The specified size must be at most the current size.
  fn revert_to_history_size(&mut self, target_size: usize);
}

/// Context tree which computes a probability estimate for a sequence of
/// bits based on a mixture model of Markov chains. Lower-degree Markov
/// chains have higher priors in the mixture model, thus formalizing the
/// notion of Occam's Razor.
///
/// In order to get a probability for a sequence, all bits in the sequence
/// must be processed in-order.
pub struct ContextTree {
  root: Node,
  history: Bitstring,
  depth: usize,
}

impl Predictor for ContextTree {
  fn history_size(&self) -> usize {
    self.history.len()
  }

  fn revert_to_history_size(&mut self, target_size: usize) {
    assert!(target_size <= self.history_size());
    while target_size > self.history_size() {
      self.revert_last();
    }
  }

  fn update(&mut self, bitstring: &Bitstring) {
    for bit in bitstring.bits() {
      self.update_bit(*bit);
    }
  }
}

impl ContextTree {
  /// The depth of the tree is the distance between leaves and the root.
  /// For a given depth d, the tree will compute a mixture model of all
  /// Markov chains of degree at most d.
  pub fn create(depth: usize) -> Self {
    ContextTree {
      root: Node::create_root(depth, 0),
      history: Bitstring::new(),
      depth: depth,
    }
  }

  /// Returns the total number of nodes in the tree.
  pub fn size(&self) -> usize {
    self.root.size()
  }

  /// Adds a single bit to the history seen by this tree, updating all the
  /// involved nodes if necessary.
  fn update_bit(&mut self, bit: Bit) {
    self.for_node_in_context(&|node: &mut Node| {
      node.update(bit);
    });
    self.history.push(bit);
  }

  /// Removes a single bit from the history seen by this tree, updating all the
  /// involved nodes if necessary.
  fn revert_last(&mut self) {
    let bit = self.history.pop();
    self.for_node_in_context(&|node: &mut Node| {
      node.revert(bit);
    });
  }

  /// Returns log2 of the estimated probability of the current history.
  fn log_block_prob(&mut self) -> f64 {
    return self.root.log_weighted_prob();
  }

  /// Executes the provided closure on the current context, i.e., follows the
  /// current history down to a leaf and executes the closure on every node
  /// from the leaf to the root. Does nothing if the current history is not
  /// long enough to reach a leaf.
  fn for_node_in_context<F: Fn(&mut Node)>(&mut self, closure: &F) {
    if self.history_size() < self.depth {
      return;
    }
    self.root.execute(closure, &self.history, 0);
  }
}

/// One node in the context tree. Maintains a count of the number
/// of zeroes and ones seen and provides access to partial results
/// of the overall probability estimates computed in the context
/// tree.
struct Node {
  /// Children.
  zero_child: Option<Box<Node>>,
  one_child: Option<Box<Node>>,

  /// Frequencies.
  zeroes: u64,
  ones: u64,

  /// The log2 of the probability of a sequence with self.zeroes zeroes
  /// and self.ones one. Computed using the Krichevsky Trofimov
  /// estimator algorithm.
  log_kt_prob: f64,

  /// The log2 of the weighted block probability of the current sequence.
  /// Funtion of self.zeroes and self.ones and the values recursively
  /// provided by the children of this node (if any), lazily recomputed.
  log_weighted_prob: f64,
}

impl Node {
  /// Creates a node and all its children recursively until the provided
  /// depth is reached.
  pub fn create_root(target_depth: usize, current_depth: usize) -> Self {
    if target_depth == current_depth {
      return Node::new(None, None);  // Leaf.
    } else {
      return Node::new(
          Some(Box::new(Node::create_root(target_depth, current_depth + 1))),
          Some(Box::new(Node::create_root(target_depth, current_depth + 1))));
    }
  }

  fn new(zero_child: Option<Box<Node>>, one_child: Option<Box<Node>>) -> Self {
    // Context trees are complete trees (either both children or no children).
    assert!(zero_child.is_none() == one_child.is_none());

    return Node {
      zero_child: zero_child,
      one_child: one_child,
      zeroes: 0,
      ones: 0,
      log_kt_prob: 0.0,
      log_weighted_prob: 0.0,
    };
  }

  pub fn log_weighted_prob(&self) -> f64 {
    self.log_weighted_prob
  }

  /// Executes the given closure on the appropriate child (if any) and then on
  /// itself.
  pub fn execute<F: Fn(&mut Node)>(
      &mut self,
      closure: &F,
      history: &Bitstring,
      depth: usize) {
    if !self.is_leaf() {
      let bit = history.bit(history.len() - depth);
      self.mut_child(bit).execute(closure, history, depth + 1);
    }
    closure(self);
  }

  /// Updates the state of the node based on the value of the new bit.
  /// Assumes that child nodes (if any) have already been updated.
  pub fn update(&mut self, bit: Bit) {
    match bit {
      Bit::Zero => self.zeroes += 1,
      Bit::One => self.ones += 1,
    }

    // Old value + 0.5 is the same as new value - 0.5.
    let first_summand = match bit {
      Bit::Zero => self.zeroes as f64 - 0.5,
      Bit::One => self.ones as f64 - 0.5,
    }.log2();
    let norm_summand = ((self.zeroes + self.ones) as f64).log2();

    self.log_kt_prob = first_summand - norm_summand + self.log_kt_prob;
    self.update_weighted_prob();
  }

  /// Corresponds to undoing one update for the specified bit value.
  /// Assumes that child nodes (if any) have already been reverted.
  pub fn revert(&mut self, bit: Bit) {
    match bit {
      Bit::Zero => self.zeroes -= 1,
      Bit::One => self.ones -= 1,
    }
    // TODO(dinowernli): Update kt probs.
    self.update_weighted_prob();
  }

  /// Returns the child corresponding to the supplied bit. Must not be called
  /// on leaf nodes.
  fn mut_child(&mut self, bit: Bit) -> &mut Node {
    assert!(!self.is_leaf());
    match bit {
      Bit::Zero => self.zero_child.as_mut().unwrap(),
      Bit::One => self.one_child.as_mut().unwrap(),
    }
  }

  /// Updates the value of log_weighted_prob. Assumes that log_kt_prob
  /// as well as all values in all children (if any) are up-to-date.
  fn update_weighted_prob(&mut self) {
    if self.is_leaf() {
      self.log_weighted_prob = self.log_kt_prob;
      return;
    }

    let log_weighted_probs =
        self.zero_child.as_ref().unwrap().log_weighted_prob() +
        self.one_child.as_ref().unwrap().log_weighted_prob();
    let exponent = log_weighted_probs - self.log_kt_prob;
    let power = exponent.exp2();

    // The recursive term should be log2(1 + 2^exponent). If the exponent is
    // large enough, 2^exponent is inf. In this case, we approximate
    // log2(1 + 2^exponent) by log2(2^exponent) = exponent.
    let recursive_term =
        if power == f64::INFINITY { exponent } else { (power + 1.0).log2() };

    self.log_weighted_prob = self.log_kt_prob + recursive_term - 1.0;
  }

  /// Returns the number of nodes in the subtree rooted at this node.
  fn size(&self) -> usize {
    1 + match self.zero_child {
      None => 0,
      Some(ref node) => node.size(),
    } + match self.one_child {
      None => 0,
      Some(ref node) => node.size(),
    }
  }

  fn is_leaf(&self) -> bool {
    // By construction we have either both children or none.
    return self.zero_child.is_none();
  }
}
<|endoftext|>