<commit_before>/// External linking is a complex implementation to be able to serve a clean and easy-to-use
/// interface.
///
/// Internally, there are no such things as "external links" (plural). Each Entry in the store can
/// only have _one_ external link.
///
/// This library does the following therefor: It allows you to have several external links with one
/// entry, which are internally one file in the store for each link, linked with "internal
/// linking".
///
/// This helps us greatly with deduplication of URLs.
///

use std::convert::Into;
use std::ops::Deref;
use std::ops::DerefMut;
use std::collections::BTreeMap;

use libimagstore::store::Entry;
use libimagstore::store::EntryHeader;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;

use error::LinkError as LE;
use error::LinkErrorKind as LEK;
use result::Result;
use internal::InternalLinker;
use module_path::ModuleEntryPath;

use toml::Value;
use toml::Table;
use url::Url;
use crypto::sha1::Sha1;
use crypto::digest::Digest;

/// "Link" Type, just an abstraction over FileLockEntry to have some convenience internally.
struct Link<'a> {
    link: FileLockEntry<'a>
}

impl<'a> Link<'a> {

    pub fn new(fle: FileLockEntry<'a>) -> Link<'a> {
        Link { link: fle }
    }

    /// For interal use only. Load an Link from a store id, if this is actually a Link
    fn retrieve(store: &'a Store, id: StoreId) -> Result<Option<Link<'a>>> {
        store.retrieve(id)
            .map(|fle| {
                if let Some(_) = Link::get_link_uri_from_filelockentry(&fle) {
                    Some(Link {
                        link: fle
                    })
                } else {
                    None
                }
            })
            .map_err(|e| LE::new(LEK::StoreReadError, Some(Box::new(e))))
    }

    /// Get a link Url object from a FileLockEntry, ignore errors.
    fn get_link_uri_from_filelockentry(file: &FileLockEntry<'a>) -> Option<Url> {
        file.deref()
            .get_header()
            .read("imag.content.uri")
            .ok()
            .and_then(|opt| {
                match opt {
                    Some(Value::String(s)) => Url::parse(&s[..]).ok(),
                    _ => None
                }
            })
    }

    pub fn get_url(&self) -> Result<Option<Url>> {
        let opt = self.link
            .deref()
            .get_header()
            .read("imag.content.uri");

        match opt {
            Ok(Some(Value::String(s))) => {
                Url::parse(&s[..])
                     .map(|s| Some(s))
                     .map_err(|e| LE::new(LEK::EntryHeaderReadError, Some(Box::new(e))))
            },
            Ok(None) => Ok(None),
            _ => Err(LE::new(LEK::EntryHeaderReadError, None))
        }
    }

}

pub trait ExternalLinker : InternalLinker {

    /// Get the external links from the implementor object
    fn get_external_links(&self, store: &Store) -> Result<Vec<Url>>;

    /// Set the external links for the implementor object
    fn set_external_links(&mut self, store: &Store, links: Vec<Url>) -> Result<()>;

    /// Add an external link to the implementor object
    fn add_external_link(&mut self, store: &Store, link: Url) -> Result<()>;

    /// Remove an external link from the implementor object
    fn remove_external_link(&mut self, store: &Store, link: Url) -> Result<()>;

}

/// Check whether the StoreId starts with `/link/external/`
fn is_link_store_id(id: &StoreId) -> bool {
    debug!("Checking whether this is a /link/external/*: '{:?}'", id);
    id.starts_with("/link/external/")
}

fn get_external_link_from_file(entry: &FileLockEntry) -> Result<Url> {
    Link::get_link_uri_from_filelockentry(entry) // TODO: Do not hide error by using this function
        .ok_or(LE::new(LEK::StoreReadError, None))
}

/// Implement ExternalLinker for Entry, hiding the fact that there is no such thing as an external
/// link in an entry, but internal links to other entries which serve as external links, as one
/// entry in the store can only have one external link.
impl ExternalLinker for Entry {

    /// Get the external links from the implementor object
    fn get_external_links(&self, store: &Store) -> Result<Vec<Url>> {
        // Iterate through all internal links and filter for FileLockEntries which live in
        // /link/external/<SHA> -> load these files and get the external link from their headers,
        // put them into the return vector.
        self.get_internal_links()
            .map(|vect| {
                debug!("Getting external links");
                vect.into_iter()
                    .filter(is_link_store_id)
                    .map(|id| {
                        debug!("Retrieving entry for id: '{:?}'", id);
                        match store.retrieve(id.clone()) {
                            Ok(f) => get_external_link_from_file(&f),
                            Err(e) => {
                                debug!("Retrieving entry for id: '{:?}' failed", id);
                                Err(LE::new(LEK::StoreReadError, Some(Box::new(e))))
                            }
                        }
                    })
                    .filter_map(|x| x.ok()) // TODO: Do not ignore error here
                    .collect()
            })
            .map_err(|e| LE::new(LEK::StoreReadError, Some(Box::new(e))))
    }

    /// Set the external links for the implementor object
    fn set_external_links(&mut self, store: &Store, links: Vec<Url>) -> Result<()> {
        // Take all the links, generate a SHA sum out of each one, filter out the already existing
        // store entries and store the other URIs in the header of one FileLockEntry each, in
        // the path /link/external/<SHA of the URL>

        debug!("Iterating {} links = {:?}", links.len(), links);
        for link in links { // for all links
            let hash = {
                let mut s = Sha1::new();
                s.input_str(&link.serialize()[..]);
                s.result_str()
            };
            let file_id = ModuleEntryPath::new(format!("external/{}", hash)).into_storeid();

            debug!("Link    = '{:?}'", link);
            debug!("Hash    = '{:?}'", hash);
            debug!("StoreId = '{:?}'", file_id);

            let mut file = {
                if let Ok(mut file) = store.retrieve(file_id.clone()) { // retrieve the file from the store
                    debug!("Woha, there is already a file for this link: '{:?}'", link);
                    file
                } else { // or
                    debug!("Generating file for link = '{:?}' on id = {:?}", link, file_id);
                    let res = store.create(file_id) // create it
                        .and_then(|mut file| {
                            {
                                debug!("Generating header content!");
                                let mut hdr = file.deref_mut().get_header_mut();

                                // Write the URI into the header
                                match hdr.set("imag.content", Value::Table(BTreeMap::new())) {
                                    Ok(_) => {
                                        let v = Value::String(link.serialize());
                                        debug!("setting URL = '{:?}", v);
                                        hdr.set("imag.content.uri", v);
                                        Ok(())
                                    },
                                    Err(e) => {
                                        debug!("Failed to generate a table in header at 'imag.content'");
                                        Err(e)
                                    },
                                }
                            }.map(|_| file)
                        })
                        .map_err(|e| LE::new(LEK::StoreWriteError, Some(Box::new(e))));

                    // And if that fails we can error
                    if let Err(e) = res {
                        debug!("Failed to create or retrieve an file for this link '{:?}'", link);
                        return Err(e);
                    }
                    debug!("Success creating or retrieving an file for this link '{:?}'", link);
                    res.unwrap()
                }
            };

            // then add an internal link to the new file or return an error if this fails
            if let Err(e) = self.add_internal_link(file.deref_mut()) {
                debug!("Error adding internal link");
                return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e))));
            }
        }
        debug!("Ready iterating");
        Ok(())
    }

    /// Add an external link to the implementor object
    fn add_external_link(&mut self, store: &Store, link: Url) -> Result<()> {
        // get external links, add this one, save them
        debug!("Getting links");
        self.get_external_links(store)
            .and_then(|mut links| {
                debug!("Adding link = '{:?}' to links = {:?}", link, links);
                links.push(link);
                debug!("Setting {} links = {:?}", links.len(), links);
                self.set_external_links(store, links)
            })
    }

    /// Remove an external link from the implementor object
    fn remove_external_link(&mut self, store: &Store, link: Url) -> Result<()> {
        // get external links, remove this one, save them
        self.get_external_links(store)
            .and_then(|mut links| {
                debug!("Removing link = '{:?}' from links = {:?}", link, links);
                let links = links.into_iter()
                    .filter(|l| l.serialize() != link.serialize())
                    .collect();
                self.set_external_links(store, links)
            })
    }

}

<commit_msg>Rewrite set_external_links()<commit_after>/// External linking is a complex implementation to be able to serve a clean and easy-to-use
/// interface.
///
/// Internally, there are no such things as "external links" (plural). Each Entry in the store can
/// only have _one_ external link.
///
/// This library does the following therefor: It allows you to have several external links with one
/// entry, which are internally one file in the store for each link, linked with "internal
/// linking".
///
/// This helps us greatly with deduplication of URLs.
///

use std::convert::Into;
use std::ops::Deref;
use std::ops::DerefMut;
use std::collections::BTreeMap;

use libimagstore::store::Entry;
use libimagstore::store::EntryHeader;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;

use error::LinkError as LE;
use error::LinkErrorKind as LEK;
use result::Result;
use internal::InternalLinker;
use module_path::ModuleEntryPath;

use toml::Value;
use toml::Table;
use url::Url;
use crypto::sha1::Sha1;
use crypto::digest::Digest;

/// "Link" Type, just an abstraction over FileLockEntry to have some convenience internally.
struct Link<'a> {
    link: FileLockEntry<'a>
}

impl<'a> Link<'a> {

    pub fn new(fle: FileLockEntry<'a>) -> Link<'a> {
        Link { link: fle }
    }

    /// For interal use only. Load an Link from a store id, if this is actually a Link
    fn retrieve(store: &'a Store, id: StoreId) -> Result<Option<Link<'a>>> {
        store.retrieve(id)
            .map(|fle| {
                if let Some(_) = Link::get_link_uri_from_filelockentry(&fle) {
                    Some(Link {
                        link: fle
                    })
                } else {
                    None
                }
            })
            .map_err(|e| LE::new(LEK::StoreReadError, Some(Box::new(e))))
    }

    /// Get a link Url object from a FileLockEntry, ignore errors.
    fn get_link_uri_from_filelockentry(file: &FileLockEntry<'a>) -> Option<Url> {
        file.deref()
            .get_header()
            .read("imag.content.uri")
            .ok()
            .and_then(|opt| {
                match opt {
                    Some(Value::String(s)) => Url::parse(&s[..]).ok(),
                    _ => None
                }
            })
    }

    pub fn get_url(&self) -> Result<Option<Url>> {
        let opt = self.link
            .deref()
            .get_header()
            .read("imag.content.uri");

        match opt {
            Ok(Some(Value::String(s))) => {
                Url::parse(&s[..])
                     .map(|s| Some(s))
                     .map_err(|e| LE::new(LEK::EntryHeaderReadError, Some(Box::new(e))))
            },
            Ok(None) => Ok(None),
            _ => Err(LE::new(LEK::EntryHeaderReadError, None))
        }
    }

}

pub trait ExternalLinker : InternalLinker {

    /// Get the external links from the implementor object
    fn get_external_links(&self, store: &Store) -> Result<Vec<Url>>;

    /// Set the external links for the implementor object
    fn set_external_links(&mut self, store: &Store, links: Vec<Url>) -> Result<()>;

    /// Add an external link to the implementor object
    fn add_external_link(&mut self, store: &Store, link: Url) -> Result<()>;

    /// Remove an external link from the implementor object
    fn remove_external_link(&mut self, store: &Store, link: Url) -> Result<()>;

}

/// Check whether the StoreId starts with `/link/external/`
fn is_link_store_id(id: &StoreId) -> bool {
    debug!("Checking whether this is a /link/external/*: '{:?}'", id);
    id.starts_with("/link/external/")
}

fn get_external_link_from_file(entry: &FileLockEntry) -> Result<Url> {
    Link::get_link_uri_from_filelockentry(entry) // TODO: Do not hide error by using this function
        .ok_or(LE::new(LEK::StoreReadError, None))
}

/// Implement ExternalLinker for Entry, hiding the fact that there is no such thing as an external
/// link in an entry, but internal links to other entries which serve as external links, as one
/// entry in the store can only have one external link.
impl ExternalLinker for Entry {

    /// Get the external links from the implementor object
    fn get_external_links(&self, store: &Store) -> Result<Vec<Url>> {
        // Iterate through all internal links and filter for FileLockEntries which live in
        // /link/external/<SHA> -> load these files and get the external link from their headers,
        // put them into the return vector.
        self.get_internal_links()
            .map(|vect| {
                debug!("Getting external links");
                vect.into_iter()
                    .filter(is_link_store_id)
                    .map(|id| {
                        debug!("Retrieving entry for id: '{:?}'", id);
                        match store.retrieve(id.clone()) {
                            Ok(f) => get_external_link_from_file(&f),
                            Err(e) => {
                                debug!("Retrieving entry for id: '{:?}' failed", id);
                                Err(LE::new(LEK::StoreReadError, Some(Box::new(e))))
                            }
                        }
                    })
                    .filter_map(|x| x.ok()) // TODO: Do not ignore error here
                    .collect()
            })
            .map_err(|e| LE::new(LEK::StoreReadError, Some(Box::new(e))))
    }

    /// Set the external links for the implementor object
    fn set_external_links(&mut self, store: &Store, links: Vec<Url>) -> Result<()> {
        // Take all the links, generate a SHA sum out of each one, filter out the already existing
        // store entries and store the other URIs in the header of one FileLockEntry each, in
        // the path /link/external/<SHA of the URL>

        debug!("Iterating {} links = {:?}", links.len(), links);
        for link in links { // for all links
            let hash = {
                let mut s = Sha1::new();
                s.input_str(&link.serialize()[..]);
                s.result_str()
            };
            let file_id = ModuleEntryPath::new(format!("external/{}", hash)).into_storeid();

            debug!("Link    = '{:?}'", link);
            debug!("Hash    = '{:?}'", hash);
            debug!("StoreId = '{:?}'", file_id);

            // retrieve the file from the store, which implicitely creates the entry if it does not
            // exist
            let file = store.retrieve(file_id.clone());
            if file.is_err() {
                debug!("Failed to create or retrieve an file for this link '{:?}'", link);
                return Err(LE::new(LEK::StoreWriteError, Some(Box::new(file.err().unwrap()))));
            }
            let mut file = file.unwrap();

            debug!("Generating header content!");
            {
                let mut hdr = file.deref_mut().get_header_mut();

                let mut table = match hdr.read("imag.content") {
                    Ok(Some(Value::Table(table))) => table,
                    Ok(Some(_)) => {
                        warn!("There is a value at 'imag.content' which is not a table.");
                        warn!("Going to override this value");
                        BTreeMap::new()
                    },
                    Ok(None) => BTreeMap::new(),
                    Err(e)   => return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e)))),
                };

                let v = Value::String(link.serialize());

                debug!("setting URL = '{:?}", v);
                table.insert(String::from("url"), v);

                if let Err(e) = hdr.set("imag.content", Value::Table(table)) {
                    return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e))));
                } else {
                    debug!("Setting URL worked");
                }
            }

            // then add an internal link to the new file or return an error if this fails
            if let Err(e) = self.add_internal_link(file.deref_mut()) {
                debug!("Error adding internal link");
                return Err(LE::new(LEK::StoreWriteError, Some(Box::new(e))));
            }
        }
        debug!("Ready iterating");
        Ok(())
    }

    /// Add an external link to the implementor object
    fn add_external_link(&mut self, store: &Store, link: Url) -> Result<()> {
        // get external links, add this one, save them
        debug!("Getting links");
        self.get_external_links(store)
            .and_then(|mut links| {
                debug!("Adding link = '{:?}' to links = {:?}", link, links);
                links.push(link);
                debug!("Setting {} links = {:?}", links.len(), links);
                self.set_external_links(store, links)
            })
    }

    /// Remove an external link from the implementor object
    fn remove_external_link(&mut self, store: &Store, link: Url) -> Result<()> {
        // get external links, remove this one, save them
        self.get_external_links(store)
            .and_then(|mut links| {
                debug!("Removing link = '{:?}' from links = {:?}", link, links);
                let links = links.into_iter()
                    .filter(|l| l.serialize() != link.serialize())
                    .collect();
                self.set_external_links(store, links)
            })
    }

}

<|endoftext|>


<commit_before>use sprite::Sprite;
use opengl_graphics::Texture;

use std::collections::HashMap;
use std::ops::{Index, IndexMut};

pub struct AssetManager {
    pub sprites: SpriteManager,
}

pub struct SpriteManager {
    sprite_map: HashMap<u64, Sprite<Texture>>,
}

impl<'a> Index<&'a u64> for SpriteManager {
    type Output = Sprite<Texture>;

    fn index(&self, _index: &u64) -> &Sprite<Texture> {
        self.sprite_map.get(_index).expect("key not present")
    }
}

impl<'a> IndexMut<&'a u64> for SpriteManager {
    fn index_mut(&mut self, _index: &u64) -> &mut Sprite<Texture> {
        self.sprite_map.get_mut(_index).expect("key not present")
    }
}
<commit_msg>Added ability to load sprite from path<commit_after>use sprite::Sprite;
use opengl_graphics::Texture;

use std::collections::{HashMap};
use std::path::Path;
use std::rc::Rc;

pub struct SpriteManager {
    sprite_map: HashMap<u64, Sprite<Texture>>,
    deleted_ids: Vec<u64>,
    prev_max_id: u64,
}

impl SpriteManager {
    fn new() -> SpriteManager {
        SpriteManager{sprite_map: HashMap::<u64, Sprite<Texture>>::new(), prev_max_id: 0, deleted_ids: Vec::<u64>::new()}
    }

    fn get(&self, id: &u64) -> Option<&Sprite<Texture>> {
        self.sprite_map.get(id)
    }

    fn get_mut(&mut self, id: &u64) -> Option<&mut Sprite<Texture>> {
        self.sprite_map.get_mut(id)
    }

    fn load_from_path(&mut self, path: &Path) -> Result<u64, &str> {
        let deleted_ids = &mut self.deleted_ids;
        let prev_max_id = &mut self.prev_max_id;
        let id =
            if deleted_ids.is_empty() {
                if *prev_max_id == u64::max_value() { return Err("no available ids") }
                else { *prev_max_id += 1; prev_max_id.clone() }
            } else {
                deleted_ids.pop().expect("couldn't get deleted id")
            };

        let tex = Rc::new(
            match Texture::from_path(&path) {
                Ok(tex) => tex,
                Err(_)  => { return Err("couldn't load texture from path");},
            }
            );
        let sprite = Sprite::from_texture(tex.clone());

        match self.sprite_map.insert(id.clone(), sprite) {
            None => Ok(id),
            Some(_) => Err("existing sprite at id error"),
        }
    }
}

pub struct AssetManager {
    pub sprites: SpriteManager,
}

impl AssetManager {
    fn new() -> AssetManager {
        AssetManager{sprites: SpriteManager::new()}
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::marker::PhantomData;
use gl;
use gl::types::*;
use context::Context;
use framebuffer::FramebufferBinding;
use types::{DrawingMode, GLError};
use index_data::{IndexData, IndexDatum, IndexDatumType};

pub struct Buffer {
    gl_id: GLuint
}

impl Buffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteBuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl Context {
    pub fn gen_buffer(&self) -> Buffer {
        unsafe {
            let mut id : GLuint = mem::uninitialized();

            gl::GenBuffers(1, &mut id as *mut GLuint);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`n` is negative",
                _ => "Unknown error"
            }

            Buffer { gl_id: id }
        }
    }
}

gl_enum! {
    pub gl_enum BufferDataUsage {
        StreamDraw as STREAM_DRAW = gl::STREAM_DRAW,
        StaticDraw as STATIC_DRAW = gl::STATIC_DRAW,
        DynamicDraw as DYNAMIC_DRAW = gl::DYNAMIC_DRAW
    }
}

gl_enum! {
    pub gl_enum BufferBindingTarget {
        ArrayBuffer as ARRAY_BUFFER = gl::ARRAY_BUFFER,
        ElementArrayBuffer as ELEMENT_ARRAY_BUFFER = gl::ELEMENT_ARRAY_BUFFER
    }
}

pub trait BufferBinding {
    fn target(&self) -> BufferBindingTarget;

    fn buffer_bytes(&mut self, bytes: &[u8], usage: BufferDataUsage) {
        let ptr = bytes.as_ptr();
        let size = bytes.len() * mem::size_of::<u8>();
        unsafe {
            gl::BufferData(self.target().gl_enum(),
                           size as GLsizeiptr,
                           ptr as *const GLvoid,
                           usage.gl_enum());
            dbg_gl_error! {
                GLError::InvalidEnum => "Invalid `target` or `usage`",
                GLError::InvalidValue => "`size` is negative",
                GLError::InvalidOperation => "Object 0 is bound to buffer target",
                GLError::OutOfMemory => "Unable to create a large enough buffer",
                _ => "Unknown error"
            }
        }
    }
}

pub struct ArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ARRAY_BUFFER
    }
}

unsafe fn _draw_elements(mode: DrawingMode,
                         count: usize,
                         index_type: IndexDatumType,
                         indicies: *const GLvoid)
{
    let gl_index_type: GLenum = match index_type {
        IndexDatumType::UnsignedByte => gl::UNSIGNED_BYTE,
        IndexDatumType::UnsignedShort => gl::UNSIGNED_SHORT
    };
    gl::DrawElements(mode.gl_enum(),
                     count as GLsizei,
                     gl_index_type,
                     indicies);
    dbg_gl_error! {
        GLError::InvalidEnum => "`mode` or `type` is not an accepted value",
        GLError::InvalidValue => "`count` is negative",
        GLError::InvalidFramebufferOperation => "The current framebuffer is not framebuffer-complete",
        _ => "Unknown error"
    }
}

impl<'a> ArrayBufferBinding<'a> {
    pub unsafe fn vertex_attrib_pointer(&self,
                                        attrib: super::ProgramAttrib,
                                        components: i8,
                                        gl_type: super::DataType,
                                        normalized: bool,
                                        stride: usize,
                                        offset: usize)
    {
        debug_assert!(1 <= components && components <= 4);

        let gl_normalized = if normalized { gl::TRUE } else { gl::FALSE };
        gl::VertexAttribPointer(attrib.gl_index,
                                components as GLint,
                                gl_type.gl_enum(),
                                gl_normalized,
                                stride as GLsizei,
                                offset as *const GLvoid);
        dbg_gl_error! {
            GLError::InvalidEnum => "Illegal vertex attribute type",
            GLError::InvalidValue => "`stride` is negative, `size` is not in range, or `index` is >= GL_MAX_VERTEX_ATTRIBS",
            GLError::InvalidFramebufferOperation => "Currently bound framebuffer is not framebuffer complete",
            _ => "Unknown error"
        }
    }
}

impl<'a> FramebufferBinding<'a> {
    pub unsafe fn draw_arrays_range(&mut self,
                                    _ab: &ArrayBufferBinding,
                                    mode: DrawingMode,
                                    first: u32,
                                    count: usize)
    {
        gl::DrawArrays(mode.gl_enum(), first as GLint, count as GLsizei);
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`mode` is not an accepted value",
            GLError::InvalidValue => "`count` is negative",
            _ => "Unknown error"
        }
    }

    pub unsafe fn draw_n_elements_buffered(&mut self,
                                           _ab: &ArrayBufferBinding,
                                           _eab: &ElementArrayBufferBinding,
                                           mode: DrawingMode,
                                           count: usize,
                                           index_type: IndexDatumType)
    {
        _draw_elements(mode, count, index_type, ptr::null());
    }

    pub unsafe fn draw_n_elements<I>(&mut self,
                                     _ab: &ArrayBufferBinding,
                                     mode: DrawingMode,
                                     count: usize,
                                     indicies: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        debug_assert!(count <= indicies.len());

        let ptr = indicies.index_bytes().as_ptr();
        let index_type = I::index_datum_type();
        _draw_elements(mode, count, index_type, mem::transmute(ptr));
    }

    pub unsafe fn draw_elements<I>(&mut self,
                                   _ab: &ArrayBufferBinding,
                                   mode: DrawingMode,
                                   indicies: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        self.draw_n_elements(_ab, mode, indicies.len(), indicies);
    }
}

pub struct ElementArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ElementArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ELEMENT_ARRAY_BUFFER
    }
}

unsafe fn _bind_buffer(target: BufferBindingTarget, buffer: &mut Buffer) {
    gl::BindBuffer(target as GLuint, buffer.gl_id());
    dbg_gl_sanity_check! {
        GLError::InvalidEnum => "`target` is not an allowed value",
        _ => "Unknown error"
    }
}

pub struct ArrayBufferBinder;
impl ArrayBufferBinder {
    pub fn bind<'a>(&'a mut self, buffer: &mut Buffer)
        -> ArrayBufferBinding<'a>
    {
        let binding = ArrayBufferBinding { phantom: PhantomData };
        unsafe {
            _bind_buffer(binding.target(), buffer);
        }
        binding
    }
}

pub struct ElementArrayBufferBinder;
impl ElementArrayBufferBinder {
    pub fn bind<'a>(&'a mut self, buffer: &mut Buffer)
        -> ElementArrayBufferBinding<'a>
    {
        let binding = ElementArrayBufferBinding { phantom: PhantomData };
        unsafe {
            _bind_buffer(binding.target(), buffer);
        }
        binding
    }
}
<commit_msg>Replace unnecessary use of `mem::uninitialized()` with initialization<commit_after>use std::mem;
use std::ptr;
use std::marker::PhantomData;
use gl;
use gl::types::*;
use context::Context;
use framebuffer::FramebufferBinding;
use types::{DrawingMode, GLError};
use index_data::{IndexData, IndexDatum, IndexDatumType};

pub struct Buffer {
    gl_id: GLuint
}

impl Buffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteBuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl Context {
    pub fn gen_buffer(&self) -> Buffer {
        unsafe {
            let mut id : GLuint = 0;

            gl::GenBuffers(1, &mut id as *mut GLuint);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`n` is negative",
                _ => "Unknown error"
            }

            Buffer { gl_id: id }
        }
    }
}

gl_enum! {
    pub gl_enum BufferDataUsage {
        StreamDraw as STREAM_DRAW = gl::STREAM_DRAW,
        StaticDraw as STATIC_DRAW = gl::STATIC_DRAW,
        DynamicDraw as DYNAMIC_DRAW = gl::DYNAMIC_DRAW
    }
}

gl_enum! {
    pub gl_enum BufferBindingTarget {
        ArrayBuffer as ARRAY_BUFFER = gl::ARRAY_BUFFER,
        ElementArrayBuffer as ELEMENT_ARRAY_BUFFER = gl::ELEMENT_ARRAY_BUFFER
    }
}

pub trait BufferBinding {
    fn target(&self) -> BufferBindingTarget;

    fn buffer_bytes(&mut self, bytes: &[u8], usage: BufferDataUsage) {
        let ptr = bytes.as_ptr();
        let size = bytes.len() * mem::size_of::<u8>();
        unsafe {
            gl::BufferData(self.target().gl_enum(),
                           size as GLsizeiptr,
                           ptr as *const GLvoid,
                           usage.gl_enum());
            dbg_gl_error! {
                GLError::InvalidEnum => "Invalid `target` or `usage`",
                GLError::InvalidValue => "`size` is negative",
                GLError::InvalidOperation => "Object 0 is bound to buffer target",
                GLError::OutOfMemory => "Unable to create a large enough buffer",
                _ => "Unknown error"
            }
        }
    }
}

pub struct ArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ARRAY_BUFFER
    }
}

unsafe fn _draw_elements(mode: DrawingMode,
                         count: usize,
                         index_type: IndexDatumType,
                         indicies: *const GLvoid)
{
    let gl_index_type: GLenum = match index_type {
        IndexDatumType::UnsignedByte => gl::UNSIGNED_BYTE,
        IndexDatumType::UnsignedShort => gl::UNSIGNED_SHORT
    };
    gl::DrawElements(mode.gl_enum(),
                     count as GLsizei,
                     gl_index_type,
                     indicies);
    dbg_gl_error! {
        GLError::InvalidEnum => "`mode` or `type` is not an accepted value",
        GLError::InvalidValue => "`count` is negative",
        GLError::InvalidFramebufferOperation => "The current framebuffer is not framebuffer-complete",
        _ => "Unknown error"
    }
}

impl<'a> ArrayBufferBinding<'a> {
    pub unsafe fn vertex_attrib_pointer(&self,
                                        attrib: super::ProgramAttrib,
                                        components: i8,
                                        gl_type: super::DataType,
                                        normalized: bool,
                                        stride: usize,
                                        offset: usize)
    {
        debug_assert!(1 <= components && components <= 4);

        let gl_normalized = if normalized { gl::TRUE } else { gl::FALSE };
        gl::VertexAttribPointer(attrib.gl_index,
                                components as GLint,
                                gl_type.gl_enum(),
                                gl_normalized,
                                stride as GLsizei,
                                offset as *const GLvoid);
        dbg_gl_error! {
            GLError::InvalidEnum => "Illegal vertex attribute type",
            GLError::InvalidValue => "`stride` is negative, `size` is not in range, or `index` is >= GL_MAX_VERTEX_ATTRIBS",
            GLError::InvalidFramebufferOperation => "Currently bound framebuffer is not framebuffer complete",
            _ => "Unknown error"
        }
    }
}

impl<'a> FramebufferBinding<'a> {
    pub unsafe fn draw_arrays_range(&mut self,
                                    _ab: &ArrayBufferBinding,
                                    mode: DrawingMode,
                                    first: u32,
                                    count: usize)
    {
        gl::DrawArrays(mode.gl_enum(), first as GLint, count as GLsizei);
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`mode` is not an accepted value",
            GLError::InvalidValue => "`count` is negative",
            _ => "Unknown error"
        }
    }

    pub unsafe fn draw_n_elements_buffered(&mut self,
                                           _ab: &ArrayBufferBinding,
                                           _eab: &ElementArrayBufferBinding,
                                           mode: DrawingMode,
                                           count: usize,
                                           index_type: IndexDatumType)
    {
        _draw_elements(mode, count, index_type, ptr::null());
    }

    pub unsafe fn draw_n_elements<I>(&mut self,
                                     _ab: &ArrayBufferBinding,
                                     mode: DrawingMode,
                                     count: usize,
                                     indicies: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        debug_assert!(count <= indicies.len());

        let ptr = indicies.index_bytes().as_ptr();
        let index_type = I::index_datum_type();
        _draw_elements(mode, count, index_type, mem::transmute(ptr));
    }

    pub unsafe fn draw_elements<I>(&mut self,
                                   _ab: &ArrayBufferBinding,
                                   mode: DrawingMode,
                                   indicies: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        self.draw_n_elements(_ab, mode, indicies.len(), indicies);
    }
}

pub struct ElementArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ElementArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ELEMENT_ARRAY_BUFFER
    }
}

unsafe fn _bind_buffer(target: BufferBindingTarget, buffer: &mut Buffer) {
    gl::BindBuffer(target as GLuint, buffer.gl_id());
    dbg_gl_sanity_check! {
        GLError::InvalidEnum => "`target` is not an allowed value",
        _ => "Unknown error"
    }
}

pub struct ArrayBufferBinder;
impl ArrayBufferBinder {
    pub fn bind<'a>(&'a mut self, buffer: &mut Buffer)
        -> ArrayBufferBinding<'a>
    {
        let binding = ArrayBufferBinding { phantom: PhantomData };
        unsafe {
            _bind_buffer(binding.target(), buffer);
        }
        binding
    }
}

pub struct ElementArrayBufferBinder;
impl ElementArrayBufferBinder {
    pub fn bind<'a>(&'a mut self, buffer: &mut Buffer)
        -> ElementArrayBufferBinding<'a>
    {
        let binding = ElementArrayBufferBinding { phantom: PhantomData };
        unsafe {
            _bind_buffer(binding.target(), buffer);
        }
        binding
    }
}
<|endoftext|>


<commit_before>/* Copyright 2017 David Li.

 * This file is part of BigRedRPG.

 * BigRedRPG is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.

 * BigRedRPG is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU Affero General Public License
 * along with BigRedRPG.  If not, see <http://www.gnu.org/licenses/>.
 */

use std::cmp;
use std::ops;

use student::Student;

#[derive(Clone,Copy,Debug,Eq,Hash,PartialEq)]
pub struct Chance(pub u32);

impl ops::Add<i32> for Chance {
    type Output = Chance;

    fn add(self, other: i32) -> Chance {
        let val = self.0 as i32 + other;
        if val < 0 {
            Chance(0)
        }
        else {
            Chance(val as u32)
        }
    }
}

impl ops::AddAssign<i32> for Chance {
    fn add_assign(&mut self, other: i32) {
        let val = self.0 as i32 + other;
        if val < 0 {
            self.0 = 0;
        }
        else {
            self.0 = val as u32;
        }
    }
}

impl cmp::PartialEq<u32> for Chance {
    fn eq(&self, other: &u32) -> bool {
        self.0 == *other
    }
}

impl cmp::PartialOrd<u32> for Chance {
    fn partial_cmp(&self, other: &u32) -> Option<cmp::Ordering> {
        cmp::PartialOrd::partial_cmp(&self.0, other)
    }
}

pub enum Disposition {
    Nature {
        name: String,
        modifier: i32,
    }
}

impl Disposition {
    pub fn value(&self, student: &Student) -> i32 {
        use self::Disposition::*;

        match self {
            &Nature { ref name, modifier } => {
                if student.has_nature(name.as_str()) {
                    return modifier
                }
            }
        }

        0
    }
}
<commit_msg>fix: make chances ordered<commit_after>/* Copyright 2017 David Li.

 * This file is part of BigRedRPG.

 * BigRedRPG is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.

 * BigRedRPG is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU Affero General Public License
 * along with BigRedRPG.  If not, see <http://www.gnu.org/licenses/>.
 */

use std::cmp;
use std::ops;

use student::Student;

#[derive(Clone,Copy,Debug,Eq,Hash,PartialEq,PartialOrd,Ord)]
pub struct Chance(pub u32);

impl ops::Add<i32> for Chance {
    type Output = Chance;

    fn add(self, other: i32) -> Chance {
        let val = self.0 as i32 + other;
        if val < 0 {
            Chance(0)
        }
        else {
            Chance(val as u32)
        }
    }
}

impl ops::AddAssign<i32> for Chance {
    fn add_assign(&mut self, other: i32) {
        let val = self.0 as i32 + other;
        if val < 0 {
            self.0 = 0;
        }
        else {
            self.0 = val as u32;
        }
    }
}

impl cmp::PartialEq<u32> for Chance {
    fn eq(&self, other: &u32) -> bool {
        self.0 == *other
    }
}

impl cmp::PartialOrd<u32> for Chance {
    fn partial_cmp(&self, other: &u32) -> Option<cmp::Ordering> {
        cmp::PartialOrd::partial_cmp(&self.0, other)
    }
}

pub enum Disposition {
    Nature {
        name: String,
        modifier: i32,
    }
}

impl Disposition {
    pub fn value(&self, student: &Student) -> i32 {
        use self::Disposition::*;

        match self {
            &Nature { ref name, modifier } => {
                if student.has_nature(name.as_str()) {
                    return modifier
                }
            }
        }

        0
    }
}
<|endoftext|>


<commit_before>extern crate capnp;
extern crate capnp_rpc;

use capnp_rpc::ez_rpc::EzRpcClient;
use capnp_rpc::capability::{InitRequest, LocalClient, WaitForContent};

pub mod ramp_capnp {
  include!(concat!(env!("OUT_DIR"), "/ramp_capnp.rs"));
}

use ramp_capnp::ramp_interface;

fn main() {
    println!("Starting up test");

    let mut rpc_client = EzRpcClient::new("127.0.0.1:6000").unwrap();
    let mut client : ramp_interface::Client = rpc_client.get_main();

    { // this scoping is kind of ridiculous
        println!("Preparing");
        let mut request = client.prepare_request();
        {
            let mut builder = request.init();
            builder.set_key("test");
            builder.set_value("haddad");
            builder.set_timestamp(1);
            // add dependencies
        }
        let promise = request.send();
        // println!("Response: {:?}",
    }
    // get request, check value

    {
        let mut request = client.commit_request();
        {
            let mut builder = request.init();
            builder.set_timestamp(1);
        }
        let promise = request.send();
    }

    println!("Punisher client test ended");
}
<commit_msg>adding a transaction manager<commit_after>extern crate capnp;
extern crate capnp_rpc;

use capnp_rpc::ez_rpc::EzRpcClient;
use capnp_rpc::capability::{InitRequest, LocalClient, WaitForContent};

pub mod ramp_capnp {
  include!(concat!(env!("OUT_DIR"), "/ramp_capnp.rs"));
}

use ramp_capnp::ramp_interface;

struct Transaction {
    timestamp: i64
}

impl Transaction {
    fn prepare(key: &str, value: &str) {

    }
    fn commit() {

    }

}

fn main() {
    println!("Starting up test");

    let mut rpc_client = EzRpcClient::new("127.0.0.1:6000").unwrap();
    let mut client : ramp_interface::Client = rpc_client.get_main();

    { // this scoping is kind of ridiculous
        println!("Preparing");
        let mut request = client.prepare_request();
        {
            let mut builder = request.init();
            builder.set_key("test");
            builder.set_value("haddad");
            builder.set_timestamp(1);
            // add dependencies
        }
        let promise = request.send();
        // println!("Response: {:?}",
    }
    // get request, check value

    {
        let mut request = client.commit_request();
        {
            let mut builder = request.init();
            builder.set_timestamp(1);
        }
        let promise = request.send();
    }

    println!("Punisher client test ended");
}
<|endoftext|>


<commit_before>extern crate std;
extern crate num;
extern crate uuid;

use std::collections::BTreeMap;
use std::borrow::Cow;
use std::path::Path;
use std::error::Error;

use super::def::*;
use super::def::OpcodeRequest::*;
use super::def::CqlRequestBody::*;
use super::def::RCErrorType::*;
use super::def::CqlResponseBody::*;
use super::serialize::CqlSerializable;
use super::reader::*;

pub static CQL_VERSION_STRINGS:  [&'static str; 3] = ["3.0.0", "3.0.0", "3.0.0"];
pub static CQL_MAX_SUPPORTED_VERSION:u8 = 0x03;

type PrepsStore = BTreeMap<String, Box<CqlPreparedStat>>;

pub struct Client {
    socket: std::net::TcpStream,
    pub version: u8,
    prepared: PrepsStore
}

impl Client {

    fn new(socket: std::net::TcpStream, version: u8) -> Client {
        Client {socket: socket, version: version, prepared: BTreeMap::new()}
    }

    fn build_auth<'a>(&self, creds: &'a Vec<CowStr>, stream: i8) -> CqlRequest<'a> {
        return CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: stream,
            opcode: OpcodeOptions,
            body: RequestCred(creds),
        };
    }

    fn build_options(&self) -> CqlRequest {
        return CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeOptions,
            body: RequestOptions,
        };
    }

    pub fn get_prepared_statement(&mut self, ps_id: &str) -> RCResult<&CqlPreparedStat> {
        match self.prepared.get(ps_id) {
            Some(ps) => Ok(&**ps),
            None => return Err(RCError::new(format!("Unknown prepared statement <{}>", ps_id), GenericError))
        }
    }

    pub fn exec_query(&mut self, query_str: &str, con: Consistency) -> RCResult<CqlResponse> {
        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeQuery,
            body: RequestQuery(query_str, con, 0)};

        let mut socket = try_io!(self.socket.try_clone(), "Cannot clone tcp handle");
        try_rc!(q.serialize(&mut socket, self.version), "Error serializing query");
        Ok(try_rc!(socket.read_cql_response(self.version), "Error reading query"))
    }

    pub fn exec_prepared(&mut self, preps: &Vec<u8>, params: &[CqlValue], con: Consistency) -> RCResult<CqlResponse> {

        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeExecute,
            body: RequestExec(preps.clone(), params, con, 0x01),
        };

        let mut socket = try_io!(self.socket.try_clone(), "Cannot clone tcp handle");
        try_rc!(q.serialize(&mut socket, self.version), "Error serializing prepared statement execution");

        // Code to debug prepared statements. Write to file the serialization of the request
        let path = Path::new("prepared_data.bin");
        let display = path.display();
        let mut file = match std::fs::File::create(&path) {
            Err(err) => panic!("couldn't create {}: {}", display, err.description()),
            Ok(file) => file,
        };
        try_rc!(q.serialize(&mut file, self.version), "Error serializing query to file");

        Ok(try_rc!(socket.read_cql_response(self.version), "Error reading prepared statement execution result"))
    }

    pub fn exec_batch(&mut self, q_type: BatchType, q_vec: Vec<Query>, con: Consistency) -> RCResult<CqlResponse> {
        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeBatch,
            body: RequestBatch(q_vec, q_type, con, 0)};

        /* Code to debug batch statements. Write to file the serialization of the request

        let path = Path::new("batch_data.bin");
        let display = path.display();
        let mut file = match std::old_io::File::create(&path) {
            Err(why) => panic!("couldn't create {}: {}", display, why.desc),
            Ok(file) => file,
        };

        serialize_and_check_io_error!(serialize_with_client, &mut file, q, self, "Error serializing to file");
        */

        let mut socket = try_io!(self.socket.try_clone(), "Cannot clone tcp handle");
        try_rc!(q.serialize(&mut socket, self.version), "Error serializing BATCH request");
        let res = try_rc!(socket.read_cql_response(self.version), "Error reading query");
        Ok(res)
    }

    pub fn prepared_statement(&mut self, query_str: &str) -> RCResult<CqlPreparedStat> {
        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodePrepare,
            body: RequestPrepare(query_str),
        };

        let mut socket = try_io!(self.socket.try_clone(), "Cannot clone tcp handle");
        try_rc!(q.serialize(&mut socket, self.version), "Error serializing prepared statement");

        let res = try_rc!(socket.read_cql_response(self.version), "Error reading query");
        match res.body {
            ResultPrepared(preps) => {
                Ok(preps)
            },
            _ => Err(RCError::new("Response does not contain prepared statement", ReadError))
        }
    }
}

fn send_startup(socket: &mut std::net::TcpStream, version: u8, creds: Option<&Vec<CowStr>>) -> RCResult<()> {
    let body = CqlStringMap {
        pairs:vec![CqlPair{key: "CQL_VERSION", value: CQL_VERSION_STRINGS[(version-1) as usize]}],
    };
    let msg_startup = CqlRequest {
        version: version,
        flags: 0x00,
        stream: 0x01,
        opcode: OpcodeStartup,
        body: RequestStartup(body),
    };

    try_rc!(msg_startup.serialize(socket, version), "Error serializing startup message");

    let response = try_rc!(socket.read_cql_response(version), "Error reding response");
    match response.body {
        ResponseReady =>  Ok(()),
        ResponseAuth(_) => {
            match creds {
                Some(cred) => {
                    let msg_auth = CqlRequest {
                        version: version,
                        flags: 0x00,
                        stream: 0x01,
                        opcode: OpcodeOptions,
                        body: RequestCred(cred),
                    };
                    try_rc!(msg_auth.serialize(socket, version), "Error serializing request (auth)");

                    let response = try_rc!(socket.read_cql_response(version), "Error reding authenticaton response");
                    match response.body {
                        ResponseReady => Ok(()),
                        ResponseError(_, ref msg) => Err(RCError::new(format!("Error in authentication: {}", msg), ReadError)),
                        _ => Err(RCError::new("Server returned unknown message", ReadError))
                    }
                },
                None => Err(RCError::new("Credential should be provided for authentication", ReadError))
            }
        },
        ResponseError(_, ref msg) => Err(RCError::new(format!("Error connecting: {}", msg), ReadError)),
        _ => Err(RCError::new("Wrong response to startup", ReadError))
    }
}

pub fn connect(ip: &'static str, port: u16, creds:Option<&Vec<CowStr>>) -> RCResult<Client> {

    let mut version = CQL_MAX_SUPPORTED_VERSION;

    while version >= 0x01 {
        let res = std::net::TcpStream::connect((ip, port));
        if res.is_err() {
            return Err(RCError::new(format!("Failed to connect to server at {}:{}", ip, port), ConnectionError));
        }

        let mut socket = res.unwrap();

        match send_startup(& mut socket, version, creds) {
            Ok(_) => return Ok(Client::new(socket, version)),
            Err(e) => println!("Error connecting with protocol version v{}: {}", version, e.desc)
        }
        version -= 1;
    }
    Err(RCError::new("Unable to find suitable protocol version (v1, v2, v3)", ReadError))
}
<commit_msg>Fix typos in client error messages<commit_after>extern crate std;
extern crate num;
extern crate uuid;

use std::collections::BTreeMap;
use std::borrow::Cow;
use std::path::Path;
use std::error::Error;

use super::def::*;
use super::def::OpcodeRequest::*;
use super::def::CqlRequestBody::*;
use super::def::RCErrorType::*;
use super::def::CqlResponseBody::*;
use super::serialize::CqlSerializable;
use super::reader::*;

pub static CQL_VERSION_STRINGS:  [&'static str; 3] = ["3.0.0", "3.0.0", "3.0.0"];
pub static CQL_MAX_SUPPORTED_VERSION:u8 = 0x03;

type PrepsStore = BTreeMap<String, Box<CqlPreparedStat>>;

pub struct Client {
    socket: std::net::TcpStream,
    pub version: u8,
    prepared: PrepsStore
}

impl Client {

    fn new(socket: std::net::TcpStream, version: u8) -> Client {
        Client {socket: socket, version: version, prepared: BTreeMap::new()}
    }

    fn build_auth<'a>(&self, creds: &'a Vec<CowStr>, stream: i8) -> CqlRequest<'a> {
        return CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: stream,
            opcode: OpcodeOptions,
            body: RequestCred(creds),
        };
    }

    fn build_options(&self) -> CqlRequest {
        return CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeOptions,
            body: RequestOptions,
        };
    }

    pub fn get_prepared_statement(&mut self, ps_id: &str) -> RCResult<&CqlPreparedStat> {
        match self.prepared.get(ps_id) {
            Some(ps) => Ok(&**ps),
            None => return Err(RCError::new(format!("Unknown prepared statement <{}>", ps_id), GenericError))
        }
    }

    pub fn exec_query(&mut self, query_str: &str, con: Consistency) -> RCResult<CqlResponse> {
        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeQuery,
            body: RequestQuery(query_str, con, 0)};

        let mut socket = try_io!(self.socket.try_clone(), "Cannot clone tcp handle");
        try_rc!(q.serialize(&mut socket, self.version), "Error serializing query");
        Ok(try_rc!(socket.read_cql_response(self.version), "Error reading query"))
    }

    pub fn exec_prepared(&mut self, preps: &Vec<u8>, params: &[CqlValue], con: Consistency) -> RCResult<CqlResponse> {

        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeExecute,
            body: RequestExec(preps.clone(), params, con, 0x01),
        };

        let mut socket = try_io!(self.socket.try_clone(), "Cannot clone tcp handle");
        try_rc!(q.serialize(&mut socket, self.version), "Error serializing prepared statement execution");

        // Code to debug prepared statements. Write to file the serialization of the request
        let path = Path::new("prepared_data.bin");
        let display = path.display();
        let mut file = match std::fs::File::create(&path) {
            Err(err) => panic!("couldn't create {}: {}", display, err.description()),
            Ok(file) => file,
        };
        try_rc!(q.serialize(&mut file, self.version), "Error serializing query to file");

        Ok(try_rc!(socket.read_cql_response(self.version), "Error reading prepared statement execution result"))
    }

    pub fn exec_batch(&mut self, q_type: BatchType, q_vec: Vec<Query>, con: Consistency) -> RCResult<CqlResponse> {
        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodeBatch,
            body: RequestBatch(q_vec, q_type, con, 0)};

        /* Code to debug batch statements. Write to file the serialization of the request

        let path = Path::new("batch_data.bin");
        let display = path.display();
        let mut file = match std::old_io::File::create(&path) {
            Err(why) => panic!("couldn't create {}: {}", display, why.desc),
            Ok(file) => file,
        };

        serialize_and_check_io_error!(serialize_with_client, &mut file, q, self, "Error serializing to file");
        */

        let mut socket = try_io!(self.socket.try_clone(), "Cannot clone tcp handle");
        try_rc!(q.serialize(&mut socket, self.version), "Error serializing BATCH request");
        let res = try_rc!(socket.read_cql_response(self.version), "Error reading query");
        Ok(res)
    }

    pub fn prepared_statement(&mut self, query_str: &str) -> RCResult<CqlPreparedStat> {
        let q = CqlRequest {
            version: self.version,
            flags: 0x00,
            stream: 0x01,
            opcode: OpcodePrepare,
            body: RequestPrepare(query_str),
        };

        let mut socket = try_io!(self.socket.try_clone(), "Cannot clone tcp handle");
        try_rc!(q.serialize(&mut socket, self.version), "Error serializing prepared statement");

        let res = try_rc!(socket.read_cql_response(self.version), "Error reading query");
        match res.body {
            ResultPrepared(preps) => {
                Ok(preps)
            },
            _ => Err(RCError::new("Response does not contain prepared statement", ReadError))
        }
    }
}

fn send_startup(socket: &mut std::net::TcpStream, version: u8, creds: Option<&Vec<CowStr>>) -> RCResult<()> {
    let body = CqlStringMap {
        pairs:vec![CqlPair{key: "CQL_VERSION", value: CQL_VERSION_STRINGS[(version-1) as usize]}],
    };
    let msg_startup = CqlRequest {
        version: version,
        flags: 0x00,
        stream: 0x01,
        opcode: OpcodeStartup,
        body: RequestStartup(body),
    };

    try_rc!(msg_startup.serialize(socket, version), "Error serializing startup message");

    let response = try_rc!(socket.read_cql_response(version), "Error reading response");
    match response.body {
        ResponseReady =>  Ok(()),
        ResponseAuth(_) => {
            match creds {
                Some(cred) => {
                    let msg_auth = CqlRequest {
                        version: version,
                        flags: 0x00,
                        stream: 0x01,
                        opcode: OpcodeOptions,
                        body: RequestCred(cred),
                    };
                    try_rc!(msg_auth.serialize(socket, version), "Error serializing request (auth)");

                    let response = try_rc!(socket.read_cql_response(version), "Error reading authenticaton response");
                    match response.body {
                        ResponseReady => Ok(()),
                        ResponseError(_, ref msg) => Err(RCError::new(format!("Error in authentication: {}", msg), ReadError)),
                        _ => Err(RCError::new("Server returned unknown message", ReadError))
                    }
                },
                None => Err(RCError::new("Credential should be provided for authentication", ReadError))
            }
        },
        ResponseError(_, ref msg) => Err(RCError::new(format!("Error connecting: {}", msg), ReadError)),
        _ => Err(RCError::new("Wrong response to startup", ReadError))
    }
}

pub fn connect(ip: &'static str, port: u16, creds:Option<&Vec<CowStr>>) -> RCResult<Client> {

    let mut version = CQL_MAX_SUPPORTED_VERSION;

    while version >= 0x01 {
        let res = std::net::TcpStream::connect((ip, port));
        if res.is_err() {
            return Err(RCError::new(format!("Failed to connect to server at {}:{}", ip, port), ConnectionError));
        }

        let mut socket = res.unwrap();

        match send_startup(& mut socket, version, creds) {
            Ok(_) => return Ok(Client::new(socket, version)),
            Err(e) => println!("Error connecting with protocol version v{}: {}", version, e.desc)
        }
        version -= 1;
    }
    Err(RCError::new("Unable to find suitable protocol version (v1, v2, v3)", ReadError))
}
<|endoftext|>


<commit_before>use monsters::MonsterId;
use game_map::RoomContents;
use game_state::{GameState, GameMode};
use platform;

use self::CombatPhase::*;

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum CombatPhase {
  Preparation,
  Battle,
  Aftermath,
}

#[derive(Debug, PartialEq, Copy, Clone)]
pub struct CombatState {
  phase: CombatPhase,
  enemy: MonsterId,
  ff: i32,
}

impl GameState {
  pub fn maybe_start_combat(&mut self) -> bool {
    if let Some(RoomContents::Terror(monster_id)) =
        self.map.room(self.curr_room).contents {
      println!("\nDanger... There is a monster here....");
      Self::pause();
      println!("\nIt is a {}!", monster_id);
      let ff = self.get_modified_ff(monster_id.ferocity_factor());
      println!("\nThe danger level is {}!!\n", ff);
      Self::pause();
      self.set_mode(GameMode::Combat(CombatState {
        phase: Preparation,
        enemy: monster_id,
        ff: ff,
      }));
      return true;
    }
    false
  }

  fn get_modified_ff(&self, base_ff: i32) -> i32 {
    let mut ff = base_ff;

    if self.suit { ff = 3 * (ff / 4); }
    if !self.axe && !self.sword {
      ff + (ff / 5)
    } else if self.axe && !self.sword {
      4 * (ff / 5)
    } else if self.sword && !self.axe {
      3 * (ff / 4)
    } else {
      3 * (ff / 5)
    }
  }

  fn prepare(&self) {
    if self.suit {
      println!("Your armor increases your chance of success.");
    }
    if !self.axe && !self.sword {
      println!("You have no weapons.");
      println!("You must fight with bare hands.");
    } else if self.axe && !self.sword {
      println!("You have only an axe to fight with.");
    } else if self.sword && !self.axe {
      println!("You must fight with your sword.");
    } else {
      println!("You are dual-wielding a sword and axe like a boss.");
    }
    Self::pause();
  }

  fn tick_preparation_phase(&mut self, state: &CombatState) {
    platform::show_prompt("Press enter to fight! ");
    platform::read_input().map(|_| {
      self.prepare();
      println!("\n");
      self.curr_mode = GameMode::Combat(CombatState {
        phase: Battle,
        .. *state
      });
    });
  }

  fn tick_battle_phase(&mut self, state: &CombatState) {
    let mut ff = state.ff;
    let mut phase = state.phase;

    if platform::random() > 0.5 {
      println!("The {} attacks!", state.enemy);
    } else {
      println!("You attack!");
    }
    Self::pause();
    if platform::random() > 0.5 {
      println!("\nYou manage to wound it!");
      ff = 5 * ff / 6;
      Self::pause();
    }
    if platform::random() > 0.5 {
      self.strength -= 5;
      if self.strength > 0 {
        println!("\nThe monster wounds you!");
      } else {
        println!("\nThe monster lands a killing blow!");
      }
      Self::pause();
    }
    if platform::random() <= 0.35 {
      phase = Aftermath;
    }
    self.curr_mode = GameMode::Combat(CombatState {
      phase: phase,
      ff: ff,
      .. *state
    });
  }

  fn tick_aftermath_phase(&mut self, state: &CombatState) {
    if platform::random_i32(0, 16) > state.ff {
      println!("\nWounded and ashamed, the {} scurries off.",
               state.enemy);
      println!("\nYou are victorious!");
      self.monsters_killed += 1;
    } else {
      println!("\nThe {} knocks you down!", state.enemy);
      println!("\nYou are at its mercy!");
      Self::pause();
      println!("\nIt appears to be in a generous mood and wanders off.");
      self.strength /= 2;
    }
    println!("\n");
    Self::pause();
    self.map.mut_room(self.curr_room).contents = None;
    self.set_mode(GameMode::Primary);
  }

  pub fn tick_combat_mode(&mut self, state: &CombatState) {
    match state.phase {
      Preparation => { self.tick_preparation_phase(state) },
      Battle => { self.tick_battle_phase(state) },
      Aftermath => { self.tick_aftermath_phase(state) },
    }
  }
}
<commit_msg>Use new read_input() in combat.rs.<commit_after>use monsters::MonsterId;
use game_map::RoomContents;
use game_state::{GameState, GameMode};
use platform;

use self::CombatPhase::*;

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum CombatPhase {
  Preparation,
  Battle,
  Aftermath,
}

#[derive(Debug, PartialEq, Copy, Clone)]
pub struct CombatState {
  phase: CombatPhase,
  enemy: MonsterId,
  ff: i32,
}

impl GameState {
  pub fn maybe_start_combat(&mut self) -> bool {
    if let Some(RoomContents::Terror(monster_id)) =
        self.map.room(self.curr_room).contents {
      println!("\nDanger... There is a monster here....");
      Self::pause();
      println!("\nIt is a {}!", monster_id);
      let ff = self.get_modified_ff(monster_id.ferocity_factor());
      println!("\nThe danger level is {}!!\n", ff);
      Self::pause();
      self.set_mode(GameMode::Combat(CombatState {
        phase: Preparation,
        enemy: monster_id,
        ff: ff,
      }));
      return true;
    }
    false
  }

  fn get_modified_ff(&self, base_ff: i32) -> i32 {
    let mut ff = base_ff;

    if self.suit { ff = 3 * (ff / 4); }
    if !self.axe && !self.sword {
      ff + (ff / 5)
    } else if self.axe && !self.sword {
      4 * (ff / 5)
    } else if self.sword && !self.axe {
      3 * (ff / 4)
    } else {
      3 * (ff / 5)
    }
  }

  fn prepare(&self) {
    if self.suit {
      println!("Your armor increases your chance of success.");
    }
    if !self.axe && !self.sword {
      println!("You have no weapons.");
      println!("You must fight with bare hands.");
    } else if self.axe && !self.sword {
      println!("You have only an axe to fight with.");
    } else if self.sword && !self.axe {
      println!("You must fight with your sword.");
    } else {
      println!("You are dual-wielding a sword and axe like a boss.");
    }
    Self::pause();
  }

  fn tick_preparation_phase(&mut self, state: &CombatState) {
    platform::show_prompt("Press enter to fight! ");
    let state = *state;
    self.read_input(move |game_state, _| {
      game_state.prepare();
      println!("\n");
      game_state.curr_mode = GameMode::Combat(CombatState {
        phase: Battle,
        .. state
      });
    });
  }

  fn tick_battle_phase(&mut self, state: &CombatState) {
    let mut ff = state.ff;
    let mut phase = state.phase;

    if platform::random() > 0.5 {
      println!("The {} attacks!", state.enemy);
    } else {
      println!("You attack!");
    }
    Self::pause();
    if platform::random() > 0.5 {
      println!("\nYou manage to wound it!");
      ff = 5 * ff / 6;
      Self::pause();
    }
    if platform::random() > 0.5 {
      self.strength -= 5;
      if self.strength > 0 {
        println!("\nThe monster wounds you!");
      } else {
        println!("\nThe monster lands a killing blow!");
      }
      Self::pause();
    }
    if platform::random() <= 0.35 {
      phase = Aftermath;
    }
    self.curr_mode = GameMode::Combat(CombatState {
      phase: phase,
      ff: ff,
      .. *state
    });
  }

  fn tick_aftermath_phase(&mut self, state: &CombatState) {
    if platform::random_i32(0, 16) > state.ff {
      println!("\nWounded and ashamed, the {} scurries off.",
               state.enemy);
      println!("\nYou are victorious!");
      self.monsters_killed += 1;
    } else {
      println!("\nThe {} knocks you down!", state.enemy);
      println!("\nYou are at its mercy!");
      Self::pause();
      println!("\nIt appears to be in a generous mood and wanders off.");
      self.strength /= 2;
    }
    println!("\n");
    Self::pause();
    self.map.mut_room(self.curr_room).contents = None;
    self.set_mode(GameMode::Primary);
  }

  pub fn tick_combat_mode(&mut self, state: &CombatState) {
    match state.phase {
      Preparation => { self.tick_preparation_phase(state) },
      Battle => { self.tick_battle_phase(state) },
      Aftermath => { self.tick_aftermath_phase(state) },
    }
  }
}
<|endoftext|>


<commit_before>use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::collections::HashMap;
use std::fmt::Debug;
use std::ops::Deref;
use std::str::FromStr;

use error::*;
use ser::ConfigSerializer;
use source::Source;

use path;
use value::{Table, Value, ValueKind};

#[derive(Clone, Debug)]
enum ConfigKind {
    // A mutable configuration. This is the default.
    Mutable {
        defaults: HashMap<path::Expression, Value>,
        overrides: HashMap<path::Expression, Value>,
        sources: Vec<Box<dyn Source + Send + Sync>>,
    },

    // A frozen configuration.
    // Configuration can no longer be mutated.
    Frozen,
}

impl Default for ConfigKind {
    fn default() -> Self {
        ConfigKind::Mutable {
            defaults: HashMap::new(),
            overrides: HashMap::new(),
            sources: Vec::new(),
        }
    }
}

/// A prioritized configuration repository. It maintains a set of
/// configuration sources, fetches values to populate those, and provides
/// them according to the source's priority.
#[derive(Default, Clone, Debug)]
pub struct Config {
    kind: ConfigKind,

    /// Root of the cached configuration.
    pub cache: Value,
}

impl Config {
    pub fn new() -> Self {
        Self {
            kind: ConfigKind::default(),
            // Config root should be instantiated as an empty table
            // to avoid deserialization errors.
            cache: Value::new(None, Table::new()),
        }
    }

    /// Merge in a configuration property source.
    pub fn merge<T>(&mut self, source: T) -> Result<&mut Config>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut sources, ..
            } => {
                sources.push(Box::new(source));
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        }

        self.refresh()
    }

    /// Refresh the configuration cache with fresh
    /// data from added sources.
    ///
    /// Configuration is automatically refreshed after a mutation
    /// operation (`set`, `merge`, `set_default`, etc.).
    pub fn refresh(&mut self) -> Result<&mut Config> {
        self.cache = match self.kind {
            // TODO: We need to actually merge in all the stuff
            ConfigKind::Mutable {
                ref overrides,
                ref sources,
                ref defaults,
            } => {
                let mut cache: Value = HashMap::<String, Value>::new().into();

                // Add defaults
                for (key, val) in defaults {
                    key.set(&mut cache, val.clone());
                }

                // Add sources
                sources.collect_to(&mut cache)?;

                // Add overrides
                for (key, val) in overrides {
                    key.set(&mut cache, val.clone());
                }

                cache
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        };

        Ok(self)
    }

    pub fn set_default<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
    where
        T: Into<Value>,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut defaults, ..
            } => {
                defaults.insert(key.parse()?, value.into());
            }

            ConfigKind::Frozen => return Err(ConfigError::Frozen),
        };

        self.refresh()
    }

    pub fn set<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
    where
        T: Into<Value>,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut overrides, ..
            } => {
                overrides.insert(key.parse()?, value.into());
            }

            ConfigKind::Frozen => return Err(ConfigError::Frozen),
        };

        self.refresh()
    }

    pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
        // Parse the key into a path expression
        let expr: path::Expression = key.parse()?;

        // Traverse the cache using the path to (possibly) retrieve a value
        let value = expr.get(&self.cache).cloned();

        match value {
            Some(value) => {
                // Deserialize the received value into the requested type
                T::deserialize(value).map_err(|e| e.extend_with_key(key))
            }

            None => Err(ConfigError::NotFound(key.into())),
        }
    }

    pub fn get_str(&self, key: &str) -> Result<String> {
        self.get(key).and_then(Value::into_str)
    }

    pub fn get_int(&self, key: &str) -> Result<i64> {
        self.get(key).and_then(Value::into_int)
    }

    pub fn get_float(&self, key: &str) -> Result<f64> {
        self.get(key).and_then(Value::into_float)
    }

    pub fn get_bool(&self, key: &str) -> Result<bool> {
        self.get(key).and_then(Value::into_bool)
    }

    pub fn get_table(&self, key: &str) -> Result<HashMap<String, Value>> {
        self.get(key).and_then(Value::into_table)
    }

    pub fn get_array(&self, key: &str) -> Result<Vec<Value>> {
        self.get(key).and_then(Value::into_array)
    }

    /// Attempt to deserialize the entire configuration into the requested type.
    pub fn try_into<'de, T: Deserialize<'de>>(self) -> Result<T> {
        T::deserialize(self)
    }

    /// Attempt to serialize the entire configuration from the given type.
    pub fn try_from<T: Serialize>(from: &T) -> Result<Self> {
        let mut serializer = ConfigSerializer::default();
        from.serialize(&mut serializer)?;
        Ok(serializer.output)
    }

    #[deprecated(since = "0.7.0", note = "please use 'try_into' instead")]
    pub fn deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
        self.try_into()
    }
}

impl Source for Config {
    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
        Box::new((*self).clone())
    }

    fn collect(&self) -> Result<HashMap<String, Value>> {
        self.cache.clone().into_table()
    }
}
<commit_msg>Add Config::with_merged()<commit_after>use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::collections::HashMap;
use std::fmt::Debug;
use std::ops::Deref;
use std::str::FromStr;

use error::*;
use ser::ConfigSerializer;
use source::Source;

use path;
use value::{Table, Value, ValueKind};

#[derive(Clone, Debug)]
enum ConfigKind {
    // A mutable configuration. This is the default.
    Mutable {
        defaults: HashMap<path::Expression, Value>,
        overrides: HashMap<path::Expression, Value>,
        sources: Vec<Box<dyn Source + Send + Sync>>,
    },

    // A frozen configuration.
    // Configuration can no longer be mutated.
    Frozen,
}

impl Default for ConfigKind {
    fn default() -> Self {
        ConfigKind::Mutable {
            defaults: HashMap::new(),
            overrides: HashMap::new(),
            sources: Vec::new(),
        }
    }
}

/// A prioritized configuration repository. It maintains a set of
/// configuration sources, fetches values to populate those, and provides
/// them according to the source's priority.
#[derive(Default, Clone, Debug)]
pub struct Config {
    kind: ConfigKind,

    /// Root of the cached configuration.
    pub cache: Value,
}

impl Config {
    pub fn new() -> Self {
        Self {
            kind: ConfigKind::default(),
            // Config root should be instantiated as an empty table
            // to avoid deserialization errors.
            cache: Value::new(None, Table::new()),
        }
    }

    /// Merge in a configuration property source.
    pub fn merge<T>(&mut self, source: T) -> Result<&mut Config>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut sources, ..
            } => {
                sources.push(Box::new(source));
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        }

        self.refresh()
    }

    /// Merge in a configuration property source.
    pub fn with_merged<T>(mut self, source: T) -> Result<Self>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut sources, ..
            } => {
                sources.push(Box::new(source));
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        }

        self.refresh()?;
        Ok(self)
    }

    /// Refresh the configuration cache with fresh
    /// data from added sources.
    ///
    /// Configuration is automatically refreshed after a mutation
    /// operation (`set`, `merge`, `set_default`, etc.).
    pub fn refresh(&mut self) -> Result<&mut Config> {
        self.cache = match self.kind {
            // TODO: We need to actually merge in all the stuff
            ConfigKind::Mutable {
                ref overrides,
                ref sources,
                ref defaults,
            } => {
                let mut cache: Value = HashMap::<String, Value>::new().into();

                // Add defaults
                for (key, val) in defaults {
                    key.set(&mut cache, val.clone());
                }

                // Add sources
                sources.collect_to(&mut cache)?;

                // Add overrides
                for (key, val) in overrides {
                    key.set(&mut cache, val.clone());
                }

                cache
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        };

        Ok(self)
    }

    pub fn set_default<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
    where
        T: Into<Value>,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut defaults, ..
            } => {
                defaults.insert(key.parse()?, value.into());
            }

            ConfigKind::Frozen => return Err(ConfigError::Frozen),
        };

        self.refresh()
    }

    pub fn set<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
    where
        T: Into<Value>,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut overrides, ..
            } => {
                overrides.insert(key.parse()?, value.into());
            }

            ConfigKind::Frozen => return Err(ConfigError::Frozen),
        };

        self.refresh()
    }

    pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
        // Parse the key into a path expression
        let expr: path::Expression = key.parse()?;

        // Traverse the cache using the path to (possibly) retrieve a value
        let value = expr.get(&self.cache).cloned();

        match value {
            Some(value) => {
                // Deserialize the received value into the requested type
                T::deserialize(value).map_err(|e| e.extend_with_key(key))
            }

            None => Err(ConfigError::NotFound(key.into())),
        }
    }

    pub fn get_str(&self, key: &str) -> Result<String> {
        self.get(key).and_then(Value::into_str)
    }

    pub fn get_int(&self, key: &str) -> Result<i64> {
        self.get(key).and_then(Value::into_int)
    }

    pub fn get_float(&self, key: &str) -> Result<f64> {
        self.get(key).and_then(Value::into_float)
    }

    pub fn get_bool(&self, key: &str) -> Result<bool> {
        self.get(key).and_then(Value::into_bool)
    }

    pub fn get_table(&self, key: &str) -> Result<HashMap<String, Value>> {
        self.get(key).and_then(Value::into_table)
    }

    pub fn get_array(&self, key: &str) -> Result<Vec<Value>> {
        self.get(key).and_then(Value::into_array)
    }

    /// Attempt to deserialize the entire configuration into the requested type.
    pub fn try_into<'de, T: Deserialize<'de>>(self) -> Result<T> {
        T::deserialize(self)
    }

    /// Attempt to serialize the entire configuration from the given type.
    pub fn try_from<T: Serialize>(from: &T) -> Result<Self> {
        let mut serializer = ConfigSerializer::default();
        from.serialize(&mut serializer)?;
        Ok(serializer.output)
    }

    #[deprecated(since = "0.7.0", note = "please use 'try_into' instead")]
    pub fn deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
        self.try_into()
    }
}

impl Source for Config {
    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
        Box::new((*self).clone())
    }

    fn collect(&self) -> Result<HashMap<String, Value>> {
        self.cache.clone().into_table()
    }
}
<|endoftext|>


<commit_before>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::error;
use std::fmt;
use std::slice;
use std::result;

use serde;
use serde::de;

use Sexp;

// loosely based on serde-yaml

// TODO: get rid of some of the clones

use error::{Result,Error};

pub fn decode<T:serde::Deserialize>(exp: Sexp) -> Result<T> {
    serde::Deserialize::deserialize(&mut Deserializer::new(exp))
}

pub struct Deserializer {
    pub exp: Sexp,
}

impl Deserializer {
    pub fn new(exp: Sexp) -> Deserializer {
        Deserializer { exp: exp }
    }

     fn deserialize_sexp_list<V:de::Visitor>(&mut self, mut visitor: V, v:Vec<Sexp>) -> Result<V::Value> {
        match v[0] {
            // if first element is a string, we consider it a struct
            Sexp::String(s) => {
                // if all other elements are tuples with the first
                // being a name, consider it a struct
                let mut is_struct = true;
                for e in &v[1..] {
                    match *e {
                        Sexp::List(v2) => {
                            if v2.len() != 2 {
                                is_struct = false
                            }
                        },
                        _ => {
                            is_struct = false
                        },
                    }
                }
                if is_struct {
                    return visitor.visit_map(MapVisitor::new(v))
                }
                // else consider it a tuple struct; skip first element
                visitor.visit_seq(SeqVisitor::new(v, true))

            },
            // if first element is not a string, we consider it a plain sequence
            _ => {
                visitor.visit_seq(SeqVisitor::new(v, false))
            },
        }
    }
}

impl de::Deserializer for Deserializer {
    type Error = Error;

    fn deserialize<V>(&mut self, mut visitor: V)
                      -> Result<V::Value>
        where V: de::Visitor
    {
        match self.exp {
            Sexp::Empty => visitor.visit_unit(),
            Sexp::String(s) => visitor.visit_string(s),
            Sexp::List(v) => {
                if v.is_empty() {
                    visitor.visit_unit()
                } else {
                    self.deserialize_sexp_list(visitor, v)
                }
            }
        }
    }

    /// deserialize any string in a symbolic expression
    fn deserialize_string<V>(&mut self, visitor: V) -> Result<V::Value>
        where V: de::Visitor {
        match self.exp {
            Sexp::String(s) => visitor.visit_string(s),
            _ => Err(Error::Decode(format!("expecting string got {}", self.exp)))
        }
    }

    /// the  symbolic-expression
    fn deserialize_unit<V>(&mut self, visitor: V) -> Result<V::Value>
        where V: de::Visitor {
        match self.exp {
            Sexp::Empty => visitor.visit_unit(),
            _ => Err(Error::Decode(format!("expecting unit got {}", self.exp)))
        }
    }

    /// a symbolic expression of the form (name value1 value2 ...)
    fn deserialize_tuple_struct<V>(&mut self,
                               name: &'static str,
                               len: usize,
                               visitor: V)
                               -> Result<V::Value, Self::Error>
        where V: de::Visitor {
        match self.exp {
            Sexp::List(v) => {
                if v.len() != len+1 {
                    return Err(Error::Decode(format!("expecting {} elements for tuple struct in {}", len, self.exp)))
                }
                match v[0] {
                    Sexp::String(name2) => {
                        if name != name2.as_str() {
                            return Err(Error::Decode(format!("expecting name {} got {} in {}", name, name2, self.exp)))
                        }
                        visitor.visit_seq(SeqVisitor::new(v, true))
                    }
                    _ => Err(Error::Decode(format!("expecting string as first element of list got {}", self.exp)))
                }
            }
            _ => Err(Error::Decode(format!("expecting list got {}", self.exp)))
        }
    }

    /// Parses a newtype struct as the underlying value.
    fn deserialize_newtype_struct<V>(
        &mut self,
        _name: &str,
        mut visitor: V
    ) -> Result<V::Value>
        where V: de::Visitor,
    {
        visitor.visit_newtype_struct(self)
    }

    forward_to_deserialize!{
        bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str
        unit seq seq_fixed_size bytes map unit_struct tuple_struct struct
        struct_field tuple ignored_any option enum
    }
}

struct SeqVisitor<'a> {
    iter: slice::Iter<'a, Sexp>,
}

impl<'a> SeqVisitor<'a> {
    fn new(seq: Vec<Sexp>, skip:bool) -> Self {
        let mut iter = seq.iter();
        if skip {
            iter.next();
        }
        SeqVisitor {
            iter: iter,
        }
    }
}

impl<'a> de::SeqVisitor for SeqVisitor<'a> {
    type Error = Error;

    fn visit<T>(&mut self) -> Result<Option<T>>
        where T: de::Deserialize,
    {
        match self.iter.next() {
            None => Ok(None),
            Some(t) => {
                de::Deserialize::deserialize(&mut Deserializer::new(t.clone())).map(Some)
            }
        }
    }

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

struct MapVisitor<'a> {
    iter: slice::Iter<'a, Sexp>,
    /// Value associated with the most recently visited key.
    v: Option<&'a Sexp>,
}

impl<'a> MapVisitor<'a> {
    fn new(seq: Vec<Sexp>) -> Self {
        let iter = seq.iter();
        iter.next(); // skip name element
        MapVisitor {
            iter: iter,
            v: None,
        }
    }
}

impl<'a> de::MapVisitor for MapVisitor<'a> {
    type Error = Error;

    fn visit_key<K>(&mut self) -> Result<Option<K>>
        where K: de::Deserialize,
    {
        match self.iter.next() {
            None => Ok(None),
            Some(exp) => {
                match exp {
                    Sexp::List(v) => {
                        if v.len() != 2 {
                            return Err(Error::Decode("can't decode as map 1".into()))
                        }
                        if let Ok(k) = v[0].string() {
                            self.v = v[1];
                            de::Deserialize::deserialize(&mut Deserializer::new(k)).map(Some)
                        } else {
                            return Err(Error::Decode("can't decode as map 2".into()))
                        }
                        self.v = Some(v);
                        de::Deserialize::deserialize(&mut Deserializer::new(k)).map(Some)
                    },
                    _ => Err(Error::Decode("can't decode as map 3".into()))
            }
        }
        }
    }

    fn visit_value<V>(&mut self) -> Result<V>
        where V: de::Deserialize,
    {
        if let Some(v) = self.v {
            de::Deserialize::deserialize(&mut Deserializer::new(v.clone()))
        } else {
            panic!("must call visit_key before visit_value")
        }
    }

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

    fn missing_field<V>(&mut self, field: &'static str) -> Result<V>
        where V: de::Deserialize,
    {
        struct MissingFieldDeserializer(&'static str);

        impl de::Deserializer for MissingFieldDeserializer {
            type Error = Error;

            fn deserialize<V>(&mut self, _visitor: V) -> Result<V::Value>
                where V: de::Visitor,
            {
                Err(de::Error::missing_field(self.0))
            }

            fn deserialize_option<V>(
                &mut self,
                mut visitor: V
            ) -> Result<V::Value>
                where V: de::Visitor,
            {
                visitor.visit_none()
            }

            forward_to_deserialize!{
                bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str
                string unit seq seq_fixed_size bytes map unit_struct
                newtype_struct tuple_struct struct struct_field tuple enum
                ignored_any
            }
        }

        let mut de = MissingFieldDeserializer(field);
        Ok(try!(de::Deserialize::deserialize(&mut de)))
    }
}
<commit_msg>compiles again<commit_after>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use serde;
use serde::de;

use Sexp;

// loosely based on serde-yaml

// TODO: get rid of some of the clones

use error::{Result,Error};

pub fn decode<T:serde::Deserialize>(exp: Sexp) -> Result<T> {
    serde::Deserialize::deserialize(&mut Deserializer::new(exp))
}

pub struct Deserializer {
    pub exp: Sexp,
}

impl Deserializer {
    pub fn new(exp: Sexp) -> Deserializer {
        Deserializer { exp: exp }
    }
}

impl de::Deserializer for Deserializer {
    type Error = Error;

    /// not used
    fn deserialize<V>(&mut self, mut visitor: V)
                      -> Result<V::Value>
        where V: de::Visitor
    {
        Err(Error::Decoder("expecting specific deserializer to be called".into()))
    }

    /// deserialize any string in a symbolic expression
    fn deserialize_string<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor {
        match self.exp {
            Sexp::String(ref s) => visitor.visit_string(s.clone()),
            _ => Err(Error::Decoder(format!("expecting string got {}", self.exp)))
        }
    }

    /// the empty symbolic-expression
    fn deserialize_unit<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor {
        match self.exp {
            Sexp::Empty => visitor.visit_unit(),
            _ => Err(Error::Decoder(format!("expecting unit got {}", self.exp)))
        }
    }

    /// a symbolic expression of the form (name value1 value2 ...)
    fn deserialize_tuple_struct<V>(&mut self,
                               name: &'static str,
                               len: usize,
                               mut visitor: V)
                               -> Result<V::Value>
        where V: de::Visitor {
        match self.exp {
            Sexp::List(ref v) => {
                if v.len() != len+1 {
                    return Err(Error::Decoder(format!("expecting {} elements for tuple struct in {}", len, self.exp)))
                }
                match v[0] {
                    Sexp::String(ref name2) => {
                        if name != name2.as_str() {
                            return Err(Error::Decoder(format!("expecting name {} got {} in {}", name, name2, self.exp)))
                        }
                        visitor.visit_seq(SeqVisitor::new(v, true))
                    }
                    _ => Err(Error::Decoder(format!("expecting string as first element of list got {}", self.exp)))
                }
            },
            _ => Err(Error::Decoder(format!("expecting list got {}", self.exp)))
        }
    }

    fn deserialize_struct<V>(&mut self,
                         name: &'static str,
                         fields: &'static [&'static str],
                         mut visitor: V)
                         -> Result<V::Value>
        where V: de::Visitor {
        match self.exp {
            Sexp::List(ref v) => {
                if v.len() != fields.len()+1 {
                    return Err(Error::Decoder(format!("expecting {} elements for struct in {}", fields.len(), self.exp)))
                }
                match v[0] {
                    Sexp::String(ref name2) => {
                        if name != name2.as_str() {
                            return Err(Error::Decoder(format!("expecting name {} got {} in {}", name, name2, self.exp)))
                        }
                        visitor.visit_map(StructVisitor::new(v))
                    }
                    _ => Err(Error::Decoder(format!("expecting string as first element of list got {}", self.exp)))
                }
            },
            _ => Err(Error::Decoder(format!("expecting list got {}", self.exp))),
        }
    }

    fn deserialize_seq<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor {
        match self.exp {
            Sexp::List(ref v) => visitor.visit_seq(SeqVisitor::new(v, false)),
            _ => Err(Error::Decoder(format!("expecting seq got {}", self.exp))),
        }
    }

    /// Parses a newtype struct as the underlying value.
    fn deserialize_newtype_struct<V>(
        &mut self,
        _name: &str,
        mut visitor: V
    ) -> Result<V::Value>
        where V: de::Visitor,
    {
        visitor.visit_newtype_struct(self)
    }

    forward_to_deserialize!{
        bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str
        seq_fixed_size bytes map unit_struct
        struct_field tuple ignored_any option enum
    }
}

struct SeqVisitor<'a> {
    seq: &'a Vec<Sexp>,
    i:usize,
}

impl<'a> SeqVisitor<'a> {
    fn new(seq: &'a Vec<Sexp>, skip:bool) -> Self {
        let i = if skip { 1 } else { 0 };
        SeqVisitor {
            seq: seq,
            i: i,
        }
    }
}

impl<'a> de::SeqVisitor for SeqVisitor<'a> {
    type Error = Error;

    fn visit<T>(&mut self) -> Result<Option<T>>
        where T: de::Deserialize,
    {
        if self.i >= self.seq.len() {
            return Ok(None)
        }
        let ref t = self.seq[self.i];
        self.i += 1;
        de::Deserialize::deserialize(&mut Deserializer::new(t.clone())).map(Some)
    }

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

struct StructVisitor<'a> {
    seq: &'a Vec<Sexp>,
    i:usize,
    value: Option<Sexp>,
}

impl<'a> StructVisitor<'a> {
    fn new(seq:&'a Vec<Sexp>) -> Self {
        StructVisitor {
            seq: seq,
            i:1,
            value: None,
        }
    }
}

impl<'a> de::MapVisitor for StructVisitor<'a> {
    type Error = Error;

    fn visit_key<K>(&mut self) -> Result<Option<K>>
        where K: de::Deserialize,
    {
        if self.i >= self.seq.len() {
            return Ok(None)
        }
        let ref exp = self.seq[self.i];
        self.i += 1;
        match *exp {
            Sexp::List(ref v) => {
                if v.len() != 2 {
                    return Err(Error::Decoder("can't decode as map 1".into()))
                }
                if let Ok(k) = v[0].string() {
                    self.value = Some(v[1].clone());
                    de::Deserialize::deserialize(&mut Deserializer::new(v[0].clone())).map(Some)
                } else {
                    return Err(Error::Decoder(format!("key is not a string: {}", v[0])))
                }
            },
            _ => Err(Error::Decoder("can't decode as map 3".into()))
        }
    }

    fn visit_value<V>(&mut self) -> Result<V>
        where V: de::Deserialize,
    {
        if let Some(ref v) = self.value {
            de::Deserialize::deserialize(&mut Deserializer::new(v.clone()))
        } else {
            panic!("must call visit_key before visit_value")
        }
    }

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

    fn missing_field<V>(&mut self, field: &'static str) -> Result<V>
        where V: de::Deserialize,
    {
        struct MissingFieldDeserializer(&'static str);

        impl de::Deserializer for MissingFieldDeserializer {
            type Error = Error;

            fn deserialize<V>(&mut self, _visitor: V) -> Result<V::Value>
                where V: de::Visitor,
            {
                Err(de::Error::missing_field(self.0))
            }

            fn deserialize_option<V>(
                &mut self,
                mut visitor: V
            ) -> Result<V::Value>
                where V: de::Visitor,
            {
                visitor.visit_none()
            }

            forward_to_deserialize!{
                bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str
                string unit seq seq_fixed_size bytes map unit_struct
                newtype_struct tuple_struct struct struct_field tuple enum
                ignored_any
            }
        }

        let mut de = MissingFieldDeserializer(field);
        Ok(try!(de::Deserialize::deserialize(&mut de)))
    }
}
<|endoftext|>