<commit_before>use std::marker;
use std::ptr;
use std::slice;
use libc::{c_int, c_uint, c_void, size_t};

use {raw, panic, Repository, Error, Oid, Revwalk, Buf};
use util::Binding;

/// Stages that are reported by the PackBuilder progress callback.
pub enum PackBuilderStage {
    /// Adding objects to the pack
    AddingObjects,
    /// Deltafication of the pack
    Deltafication,
}

pub type ProgressCb<'a> = FnMut(PackBuilderStage, u32, u32) -> bool + 'a;
pub type ForEachCb<'a> = FnMut(&[u8]) -> bool + 'a;

/// A builder for creating a packfile
pub struct PackBuilder<'repo> {
    raw: *mut raw::git_packbuilder,
    progress: Option<Box<Box<ProgressCb<'repo>>>>,
    _marker: marker::PhantomData<&'repo Repository>,
}

impl<'repo> PackBuilder<'repo> {
    /// Insert a single object. For an optimal pack it's mandatory to insert
    /// objects in recency order, commits followed by trees and blobs.
    pub fn insert_object(&mut self,
                         id: Oid,
                         name: Option<&str>)
                         -> Result<(), Error> {
        let name = try!(::opt_cstr(name));
        unsafe {
            try_call!(raw::git_packbuilder_insert(self.raw, &*id.raw(), name));
        }
        Ok(())
    }

    /// Insert a root tree object. This will add the tree as well as all
    /// referenced trees and blobs.
    pub fn insert_tree(&mut self, id: Oid) -> Result<(), Error> {
        unsafe {
            try_call!(raw::git_packbuilder_insert_tree(self.raw, &*id.raw()));
        }
        Ok(())
    }

    /// Insert a commit object. This will add a commit as well as the completed
    /// referenced tree.
    pub fn insert_commit(&mut self, id: Oid) -> Result<(), Error> {
        unsafe {
            try_call!(raw::git_packbuilder_insert_commit(self.raw, &*id.raw()));
        }
        Ok(())
    }

    /// Insert objects as given by the walk. Those commits and all objects they
    /// reference will be inserted into the packbuilder.
    pub fn insert_walk(&mut self, walk: &mut Revwalk) -> Result<(), Error> {
        unsafe {
            try_call!(raw::git_packbuilder_insert_walk(self.raw, walk.raw()));
        }
        Ok(())
    }

    /// Recursively insert an object and its referenced objects. Insert the
    /// object as well as any object it references.
    pub fn insert_recursive(&mut self,
                            id: Oid,
                            name: Option<&str>)
                            -> Result<(), Error> {
        let name = try!(::opt_cstr(name));
        unsafe {
            try_call!(raw::git_packbuilder_insert_recur(self.raw,
                                                        &*id.raw(),
                                                        name));
        }
        Ok(())
    }

    /// Write the contents of the packfile to an in-memory buffer. The contents
    /// of the buffer will become a valid packfile, even though there will be
    /// no attached index.
    pub fn write_buf(&mut self, buf: &mut Buf) -> Result<(), Error> {
        unsafe {
            try_call!(raw::git_packbuilder_write_buf(buf.raw(), self.raw));
        }
        Ok(())
    }

    /// Create the new pack and pass each object to the callback.
    pub fn foreach<F>(&mut self, mut cb: F) -> Result<(), Error>
        where F: FnMut(&[u8]) -> bool {
        let mut cb = &mut cb as &mut ForEachCb;
        let ptr = &mut cb as *mut _;
        unsafe {
            try_call!(raw::git_packbuilder_foreach(self.raw,
                                                   foreach_c,
                                                   ptr as *mut _));
        }
        Ok(())
    }

    /// `progress` will be called with progress information during pack
    /// building. Be aware that this is called inline with pack building
    /// operations, so performance may be affected.
    ///
    /// There can only be one progress callback attached, this will replace any
    /// existing one. See `unset_progress_callback` to remove the current
    /// progress callback without attaching a new one.
    pub fn set_progress_callback<F>(&mut self, progress: F) -> Result<(), Error>
        where F: FnMut(PackBuilderStage, u32, u32) -> bool + 'repo {
        let ptr = Box::into_raw(Box::new(Box::new(progress) as Box<ProgressCb>));
        let progress_c = Some(progress_c as raw::git_packbuilder_progress);
        let ret;
        unsafe {
            ret = ::call::try(call!(
                    raw::git_packbuilder_set_callbacks(self.raw,
                                                       progress_c,
                                                       ptr as *mut _)));
            // Current implementation will never return an error, but since it
            // may change in the future...
            // If an error is returned we don't know if it has kept the old
            // pointers or the new ones. So to avoid dropping a callback that
            // may actually get called in the future we keep the old callback
            // stored and just leak the new one by not recreating a `Box` from
            // the raw pointer.
            if ret.is_ok() {
                self.progress = Some(Box::from_raw(ptr));
            }
        }
        ret.map(|_| ())
    }

    /// Remove the current progress callback.  See `set_progress_callback` to
    /// set the progress callback.
    pub fn unset_progress_callback(&mut self) -> Result<(), Error> {
        unsafe {
            try_call!(raw::git_packbuilder_set_callbacks(self.raw,
                                                         None,
                                                         ptr::null_mut()));
            self.progress = None;
        }
        Ok(())
    }

    /// Get the total number of objects the packbuilder will write out.
    pub fn object_count(&self) -> usize {
        unsafe { raw::git_packbuilder_object_count(self.raw) as usize }
    }

    /// Get the number of objects the packbuilder has already written out.
    pub fn written(&self) -> usize {
        unsafe { raw::git_packbuilder_written(self.raw) as usize }
    }

    /// Get the packfile's hash. A packfile's name is derived from the sorted
    /// hashing of all object names. This is only correct after the packfile
    /// has been written.
    pub fn hash(&self) -> Option<Oid> {
        if self.object_count() == 0 {
            unsafe {
                Some(Binding::from_raw(raw::git_packbuilder_hash(self.raw)))
            }
        } else {
            None
        }
    }
}

impl<'repo> Binding for PackBuilder<'repo> {
    type Raw = *mut raw::git_packbuilder;
    unsafe fn from_raw(ptr: *mut raw::git_packbuilder) -> PackBuilder<'repo> {
        PackBuilder {
            raw: ptr,
            progress: None,
            _marker: marker::PhantomData,
        }
    }
    fn raw(&self) -> *mut raw::git_packbuilder {
        self.raw
    }
}

impl<'repo> Drop for PackBuilder<'repo> {
    fn drop(&mut self) {
        unsafe {
            raw::git_packbuilder_set_callbacks(self.raw, None, ptr::null_mut());
            raw::git_packbuilder_free(self.raw);
        }
    }
}

impl Binding for PackBuilderStage {
    type Raw = raw::git_packbuilder_stage_t;
    unsafe fn from_raw(raw: raw::git_packbuilder_stage_t) -> PackBuilderStage {
        match raw {
            raw::GIT_PACKBUILDER_ADDING_OBJECTS => PackBuilderStage::AddingObjects,
            raw::GIT_PACKBUILDER_DELTAFICATION => PackBuilderStage::Deltafication,
            _ => panic!("Unknown git diff binary kind"),
        }
    }
    fn raw(&self) -> raw::git_packbuilder_stage_t {
        match *self {
            PackBuilderStage::AddingObjects => raw::GIT_PACKBUILDER_ADDING_OBJECTS,
            PackBuilderStage::Deltafication => raw::GIT_PACKBUILDER_DELTAFICATION,
        }
    }
}

extern "C" fn foreach_c(buf: *const c_void,
                        size: size_t,
                        data: *mut c_void)
                        -> c_int {
    unsafe {
        let buf = slice::from_raw_parts(buf as *const u8, size as usize);

        let r = panic::wrap(|| {
            let data = data as *mut &mut ForEachCb;
            (*data)(buf)
        });
        if r == Some(true) {
            0
        } else {
            -1
        }
    }
}

extern "C" fn progress_c(stage: raw::git_packbuilder_stage_t,
                         current: c_uint,
                         total: c_uint,
                         data: *mut c_void)
                         -> c_int {
    unsafe {
        let stage = Binding::from_raw(stage);

        let r = panic::wrap(|| {
            let data = data as *mut Box<ProgressCb>;
            (*data)(stage, current, total)
        });
        if r == Some(true) {
            0
        } else {
            -1
        }
    }
}

#[cfg(test)]
mod tests {
    use std::fs::File;
    use std::path::Path;
    use {Buf, Repository, Oid};

    fn commit(repo: &Repository) -> (Oid, Oid) {
        let mut index = t!(repo.index());
        let root = repo.path().parent().unwrap();
        t!(File::create(&root.join("foo")));
        t!(index.add_path(Path::new("foo")));

        let tree_id = t!(index.write_tree());
        let tree = t!(repo.find_tree(tree_id));
        let sig = t!(repo.signature());
        let head_id = t!(repo.refname_to_id("HEAD"));
        let parent = t!(repo.find_commit(head_id));
        let commit = t!(repo.commit(Some("HEAD"),
                                    &sig,
                                    &sig,
                                    "commit",
                                    &tree,
                                    &[&parent]));
        (commit, tree_id)
    }

    fn pack_header(len: u8) -> Vec<u8> {
        [].into_iter()
          .chain(b"PACK") // signature
          .chain(&[0, 0, 0, 2]) // version number
          .chain(&[0, 0, 0, len]) // number of objects
          .cloned().collect::<Vec<u8>>()
    }

    fn empty_pack_header() -> Vec<u8> {
        pack_header(0).iter()
          .chain(&[0x02, 0x9d, 0x08, 0x82, 0x3b,  // ^
                   0xd8, 0xa8, 0xea, 0xb5, 0x10,  // | SHA-1 of the zero
                   0xad, 0x6a, 0xc7, 0x5c, 0x82,  // | object pack header
                   0x3c, 0xfd, 0x3e, 0xd3, 0x1e]) // v
          .cloned().collect::<Vec<u8>>()
    }

    #[test]
    fn smoke() {
        let (_td, repo) = ::test::repo_init();
        let _builder = t!(repo.packbuilder());
    }

    #[test]
    fn smoke_write_buf() {
        let (_td, repo) = ::test::repo_init();
        let mut builder = t!(repo.packbuilder());
        let mut buf = Buf::new();
        t!(builder.write_buf(&mut buf));
        assert!(builder.hash().unwrap().is_zero());
        assert_eq!(&*buf, &*empty_pack_header());
    }

    #[test]
    fn smoke_foreach() {
        let (_td, repo) = ::test::repo_init();
        let mut builder = t!(repo.packbuilder());
        let mut buf = Vec::<u8>::new();
        t!(builder.foreach(|bytes| {
            buf.extend(bytes);
            true
        }));
        assert_eq!(&*buf, &*empty_pack_header());
    }

    #[test]
    fn insert_write_buf() {
        let (_td, repo) = ::test::repo_init();
        let mut builder = t!(repo.packbuilder());
        let mut buf = Buf::new();
        let (commit, _tree) = commit(&repo);
        t!(builder.insert_object(commit, None));
        assert_eq!(builder.object_count(), 1);
        t!(builder.write_buf(&mut buf));
        // Just check that the correct number of objects are written
        assert_eq!(&buf[0..12], &*pack_header(1));
    }

    #[test]
    fn insert_tree_write_buf() {
        let (_td, repo) = ::test::repo_init();
        let mut builder = t!(repo.packbuilder());
        let mut buf = Buf::new();
        let (_commit, tree) = commit(&repo);
        // will insert the tree itself and the blob, 2 objects
        t!(builder.insert_tree(tree));
        assert_eq!(builder.object_count(), 2);
        t!(builder.write_buf(&mut buf));
        // Just check that the correct number of objects are written
        assert_eq!(&buf[0..12], &*pack_header(2));
    }

    #[test]
    fn insert_commit_write_buf() {
        let (_td, repo) = ::test::repo_init();
        let mut builder = t!(repo.packbuilder());
        let mut buf = Buf::new();
        let (commit, _tree) = commit(&repo);
        // will insert the commit, its tree and the blob, 3 objects
        t!(builder.insert_commit(commit));
        assert_eq!(builder.object_count(), 3);
        t!(builder.write_buf(&mut buf));
        // Just check that the correct number of objects are written
        assert_eq!(&buf[0..12], &*pack_header(3));
    }

    #[test]
    fn progress_callback() {
        let mut progress_called = false;
        {
            let (_td, repo) = ::test::repo_init();
            let mut builder = t!(repo.packbuilder());
            let (commit, _tree) = commit(&repo);
            t!(builder.set_progress_callback(|_, _, _| {
                progress_called = true;
                true
            }));
            t!(builder.insert_commit(commit));
            t!(builder.write_buf(&mut Buf::new()));
        }
        assert_eq!(progress_called, true);
    }

    #[test]
    fn clear_progress_callback() {
        let mut progress_called = false;
        {
            let (_td, repo) = ::test::repo_init();
            let mut builder = t!(repo.packbuilder());
            let (commit, _tree) = commit(&repo);
            t!(builder.set_progress_callback(|_, _, _| {
                progress_called = true;
                true
            }));
            t!(builder.unset_progress_callback());
            t!(builder.insert_commit(commit));
            t!(builder.write_buf(&mut Buf::new()));
        }
        assert_eq!(progress_called, false);
    }
}
<commit_msg>Remove Box::into_raw -> Box::from_raw, trust libgit2 won't error<commit_after>use std::marker;
use std::ptr;
use std::slice;
use libc::{c_int, c_uint, c_void, size_t};

use {raw, panic, Repository, Error, Oid, Revwalk, Buf};
use util::Binding;

/// Stages that are reported by the PackBuilder progress callback.
pub enum PackBuilderStage {
    /// Adding objects to the pack
    AddingObjects,
    /// Deltafication of the pack
    Deltafication,
}

pub type ProgressCb<'a> = FnMut(PackBuilderStage, u32, u32) -> bool + 'a;
pub type ForEachCb<'a> = FnMut(&[u8]) -> bool + 'a;

/// A builder for creating a packfile
pub struct PackBuilder<'repo> {
    raw: *mut raw::git_packbuilder,
    progress: Option<Box<Box<ProgressCb<'repo>>>>,
    _marker: marker::PhantomData<&'repo Repository>,
}

impl<'repo> PackBuilder<'repo> {
    /// Insert a single object. For an optimal pack it's mandatory to insert
    /// objects in recency order, commits followed by trees and blobs.
    pub fn insert_object(&mut self,
                         id: Oid,
                         name: Option<&str>)
                         -> Result<(), Error> {
        let name = try!(::opt_cstr(name));
        unsafe {
            try_call!(raw::git_packbuilder_insert(self.raw, &*id.raw(), name));
        }
        Ok(())
    }

    /// Insert a root tree object. This will add the tree as well as all
    /// referenced trees and blobs.
    pub fn insert_tree(&mut self, id: Oid) -> Result<(), Error> {
        unsafe {
            try_call!(raw::git_packbuilder_insert_tree(self.raw, &*id.raw()));
        }
        Ok(())
    }

    /// Insert a commit object. This will add a commit as well as the completed
    /// referenced tree.
    pub fn insert_commit(&mut self, id: Oid) -> Result<(), Error> {
        unsafe {
            try_call!(raw::git_packbuilder_insert_commit(self.raw, &*id.raw()));
        }
        Ok(())
    }

    /// Insert objects as given by the walk. Those commits and all objects they
    /// reference will be inserted into the packbuilder.
    pub fn insert_walk(&mut self, walk: &mut Revwalk) -> Result<(), Error> {
        unsafe {
            try_call!(raw::git_packbuilder_insert_walk(self.raw, walk.raw()));
        }
        Ok(())
    }

    /// Recursively insert an object and its referenced objects. Insert the
    /// object as well as any object it references.
    pub fn insert_recursive(&mut self,
                            id: Oid,
                            name: Option<&str>)
                            -> Result<(), Error> {
        let name = try!(::opt_cstr(name));
        unsafe {
            try_call!(raw::git_packbuilder_insert_recur(self.raw,
                                                        &*id.raw(),
                                                        name));
        }
        Ok(())
    }

    /// Write the contents of the packfile to an in-memory buffer. The contents
    /// of the buffer will become a valid packfile, even though there will be
    /// no attached index.
    pub fn write_buf(&mut self, buf: &mut Buf) -> Result<(), Error> {
        unsafe {
            try_call!(raw::git_packbuilder_write_buf(buf.raw(), self.raw));
        }
        Ok(())
    }

    /// Create the new pack and pass each object to the callback.
    pub fn foreach<F>(&mut self, mut cb: F) -> Result<(), Error>
        where F: FnMut(&[u8]) -> bool {
        let mut cb = &mut cb as &mut ForEachCb;
        let ptr = &mut cb as *mut _;
        unsafe {
            try_call!(raw::git_packbuilder_foreach(self.raw,
                                                   foreach_c,
                                                   ptr as *mut _));
        }
        Ok(())
    }

    /// `progress` will be called with progress information during pack
    /// building. Be aware that this is called inline with pack building
    /// operations, so performance may be affected.
    ///
    /// There can only be one progress callback attached, this will replace any
    /// existing one. See `unset_progress_callback` to remove the current
    /// progress callback without attaching a new one.
    pub fn set_progress_callback<F>(&mut self, progress: F) -> Result<(), Error>
        where F: FnMut(PackBuilderStage, u32, u32) -> bool + 'repo {
        let mut progress = Box::new(Box::new(progress) as Box<ProgressCb>);
        let ptr = &mut *progress as *mut _;
        let progress_c = Some(progress_c as raw::git_packbuilder_progress);
        unsafe {
            try_call!(raw::git_packbuilder_set_callbacks(self.raw,
                                                         progress_c,
                                                         ptr as *mut _));
        }
        self.progress = Some(progress);
        Ok(())
    }

    /// Remove the current progress callback.  See `set_progress_callback` to
    /// set the progress callback.
    pub fn unset_progress_callback(&mut self) -> Result<(), Error> {
        unsafe {
            try_call!(raw::git_packbuilder_set_callbacks(self.raw,
                                                         None,
                                                         ptr::null_mut()));
            self.progress = None;
        }
        Ok(())
    }

    /// Get the total number of objects the packbuilder will write out.
    pub fn object_count(&self) -> usize {
        unsafe { raw::git_packbuilder_object_count(self.raw) as usize }
    }

    /// Get the number of objects the packbuilder has already written out.
    pub fn written(&self) -> usize {
        unsafe { raw::git_packbuilder_written(self.raw) as usize }
    }

    /// Get the packfile's hash. A packfile's name is derived from the sorted
    /// hashing of all object names. This is only correct after the packfile
    /// has been written.
    pub fn hash(&self) -> Option<Oid> {
        if self.object_count() == 0 {
            unsafe {
                Some(Binding::from_raw(raw::git_packbuilder_hash(self.raw)))
            }
        } else {
            None
        }
    }
}

impl<'repo> Binding for PackBuilder<'repo> {
    type Raw = *mut raw::git_packbuilder;
    unsafe fn from_raw(ptr: *mut raw::git_packbuilder) -> PackBuilder<'repo> {
        PackBuilder {
            raw: ptr,
            progress: None,
            _marker: marker::PhantomData,
        }
    }
    fn raw(&self) -> *mut raw::git_packbuilder {
        self.raw
    }
}

impl<'repo> Drop for PackBuilder<'repo> {
    fn drop(&mut self) {
        unsafe {
            raw::git_packbuilder_set_callbacks(self.raw, None, ptr::null_mut());
            raw::git_packbuilder_free(self.raw);
        }
    }
}

impl Binding for PackBuilderStage {
    type Raw = raw::git_packbuilder_stage_t;
    unsafe fn from_raw(raw: raw::git_packbuilder_stage_t) -> PackBuilderStage {
        match raw {
            raw::GIT_PACKBUILDER_ADDING_OBJECTS => PackBuilderStage::AddingObjects,
            raw::GIT_PACKBUILDER_DELTAFICATION => PackBuilderStage::Deltafication,
            _ => panic!("Unknown git diff binary kind"),
        }
    }
    fn raw(&self) -> raw::git_packbuilder_stage_t {
        match *self {
            PackBuilderStage::AddingObjects => raw::GIT_PACKBUILDER_ADDING_OBJECTS,
            PackBuilderStage::Deltafication => raw::GIT_PACKBUILDER_DELTAFICATION,
        }
    }
}

extern "C" fn foreach_c(buf: *const c_void,
                        size: size_t,
                        data: *mut c_void)
                        -> c_int {
    unsafe {
        let buf = slice::from_raw_parts(buf as *const u8, size as usize);

        let r = panic::wrap(|| {
            let data = data as *mut &mut ForEachCb;
            (*data)(buf)
        });
        if r == Some(true) {
            0
        } else {
            -1
        }
    }
}

extern "C" fn progress_c(stage: raw::git_packbuilder_stage_t,
                         current: c_uint,
                         total: c_uint,
                         data: *mut c_void)
                         -> c_int {
    unsafe {
        let stage = Binding::from_raw(stage);

        let r = panic::wrap(|| {
            let data = data as *mut Box<ProgressCb>;
            (*data)(stage, current, total)
        });
        if r == Some(true) {
            0
        } else {
            -1
        }
    }
}

#[cfg(test)]
mod tests {
    use std::fs::File;
    use std::path::Path;
    use {Buf, Repository, Oid};

    fn commit(repo: &Repository) -> (Oid, Oid) {
        let mut index = t!(repo.index());
        let root = repo.path().parent().unwrap();
        t!(File::create(&root.join("foo")));
        t!(index.add_path(Path::new("foo")));

        let tree_id = t!(index.write_tree());
        let tree = t!(repo.find_tree(tree_id));
        let sig = t!(repo.signature());
        let head_id = t!(repo.refname_to_id("HEAD"));
        let parent = t!(repo.find_commit(head_id));
        let commit = t!(repo.commit(Some("HEAD"),
                                    &sig,
                                    &sig,
                                    "commit",
                                    &tree,
                                    &[&parent]));
        (commit, tree_id)
    }

    fn pack_header(len: u8) -> Vec<u8> {
        [].into_iter()
          .chain(b"PACK") // signature
          .chain(&[0, 0, 0, 2]) // version number
          .chain(&[0, 0, 0, len]) // number of objects
          .cloned().collect::<Vec<u8>>()
    }

    fn empty_pack_header() -> Vec<u8> {
        pack_header(0).iter()
          .chain(&[0x02, 0x9d, 0x08, 0x82, 0x3b,  // ^
                   0xd8, 0xa8, 0xea, 0xb5, 0x10,  // | SHA-1 of the zero
                   0xad, 0x6a, 0xc7, 0x5c, 0x82,  // | object pack header
                   0x3c, 0xfd, 0x3e, 0xd3, 0x1e]) // v
          .cloned().collect::<Vec<u8>>()
    }

    #[test]
    fn smoke() {
        let (_td, repo) = ::test::repo_init();
        let _builder = t!(repo.packbuilder());
    }

    #[test]
    fn smoke_write_buf() {
        let (_td, repo) = ::test::repo_init();
        let mut builder = t!(repo.packbuilder());
        let mut buf = Buf::new();
        t!(builder.write_buf(&mut buf));
        assert!(builder.hash().unwrap().is_zero());
        assert_eq!(&*buf, &*empty_pack_header());
    }

    #[test]
    fn smoke_foreach() {
        let (_td, repo) = ::test::repo_init();
        let mut builder = t!(repo.packbuilder());
        let mut buf = Vec::<u8>::new();
        t!(builder.foreach(|bytes| {
            buf.extend(bytes);
            true
        }));
        assert_eq!(&*buf, &*empty_pack_header());
    }

    #[test]
    fn insert_write_buf() {
        let (_td, repo) = ::test::repo_init();
        let mut builder = t!(repo.packbuilder());
        let mut buf = Buf::new();
        let (commit, _tree) = commit(&repo);
        t!(builder.insert_object(commit, None));
        assert_eq!(builder.object_count(), 1);
        t!(builder.write_buf(&mut buf));
        // Just check that the correct number of objects are written
        assert_eq!(&buf[0..12], &*pack_header(1));
    }

    #[test]
    fn insert_tree_write_buf() {
        let (_td, repo) = ::test::repo_init();
        let mut builder = t!(repo.packbuilder());
        let mut buf = Buf::new();
        let (_commit, tree) = commit(&repo);
        // will insert the tree itself and the blob, 2 objects
        t!(builder.insert_tree(tree));
        assert_eq!(builder.object_count(), 2);
        t!(builder.write_buf(&mut buf));
        // Just check that the correct number of objects are written
        assert_eq!(&buf[0..12], &*pack_header(2));
    }

    #[test]
    fn insert_commit_write_buf() {
        let (_td, repo) = ::test::repo_init();
        let mut builder = t!(repo.packbuilder());
        let mut buf = Buf::new();
        let (commit, _tree) = commit(&repo);
        // will insert the commit, its tree and the blob, 3 objects
        t!(builder.insert_commit(commit));
        assert_eq!(builder.object_count(), 3);
        t!(builder.write_buf(&mut buf));
        // Just check that the correct number of objects are written
        assert_eq!(&buf[0..12], &*pack_header(3));
    }

    #[test]
    fn progress_callback() {
        let mut progress_called = false;
        {
            let (_td, repo) = ::test::repo_init();
            let mut builder = t!(repo.packbuilder());
            let (commit, _tree) = commit(&repo);
            t!(builder.set_progress_callback(|_, _, _| {
                progress_called = true;
                true
            }));
            t!(builder.insert_commit(commit));
            t!(builder.write_buf(&mut Buf::new()));
        }
        assert_eq!(progress_called, true);
    }

    #[test]
    fn clear_progress_callback() {
        let mut progress_called = false;
        {
            let (_td, repo) = ::test::repo_init();
            let mut builder = t!(repo.packbuilder());
            let (commit, _tree) = commit(&repo);
            t!(builder.set_progress_callback(|_, _, _| {
                progress_called = true;
                true
            }));
            t!(builder.unset_progress_callback());
            t!(builder.insert_commit(commit));
            t!(builder.write_buf(&mut Buf::new()));
        }
        assert_eq!(progress_called, false);
    }
}
<|endoftext|>


<commit_before>//! Encoding of PPM Images

use std::io::IoResult;
use std:: {
    num,
    fmt,
};

use color;
use color::ColorType:: {
    Grey,
    Palette,
    GreyA,
    RGB,
    RGBA
};

/// A representation of a PPM encoder.
pub struct PPMEncoder<W> {
    w: W
}

impl<W: Writer> PPMEncoder<W> {
    /// Create a new PPMEncoder from the Writer ```w```.
    /// This function takes ownership of the Writer.
    pub fn new(w: W) -> PPMEncoder<W> {
        PPMEncoder {w: w}
    }

    /// Encode the buffer ```im``` as a PPM image.
    /// ```width``` and ```height``` are the dimensions of the buffer.
    /// ```color``` is the buffers ColorType.
    pub fn encode(&mut self, im: &[u8], width: u32, height: u32, color: color::ColorType) -> IoResult<()> {
        let _ = try!(self.write_magic_number());
        let _ = try!(self.write_metadata(width, height, color));

        self.write_image(im, color, width, height)
    }

    fn write_magic_number(&mut self) -> IoResult<()> {
        self.w.write_str("P6\n")
    }

    fn write_metadata(&mut self, width: u32, height: u32, pixel_type: color::ColorType) -> IoResult<()> {
        let w = fmt::radix(width, 10);
        let h = fmt::radix(height, 10);
        let m = max_pixel_value(pixel_type);

        self.w.write_str(format!("{0} {1}\n{2}\n", w, h, m).as_slice())
    }

    fn write_image(
        &mut self,
        buf: &[u8],
        pixel_type: color::ColorType,
        width: u32,
        height: u32) -> IoResult<()> {

        assert!(buf.len() > 0);
        match pixel_type {
            Grey(8) => {
                for i in range(0, (width * height) as uint) {
                    let _ = try!(self.w.write_u8(buf[i]));
                    let _ = try!(self.w.write_u8(buf[i]));
                    let _ = try!(self.w.write_u8(buf[i]));
                }
            }

            RGB(8)  => try!(self.w.write(buf)),
            RGB(16) => try!(self.w.write(buf)),
            RGBA(8) => {
                for x in buf.chunks(4) {

                    let _ = try!(self.w.write_u8(x[0]));

                    let _ = try!(self.w.write_u8(x[1]));

                    let _ = try!(self.w.write_u8(x[2]));
                }
            }

            a => panic!(format!("not implemented: {}", a))
        }

        Ok(())
    }
}

fn max_pixel_value(pixel_type: color::ColorType) -> u16 {
    match pixel_type {
        Grey(n)    => num::pow(2u16, n as uint) - 1,
        RGB(n)     => num::pow(2u16, n as uint) - 1,
        Palette(n) => num::pow(2u16, n as uint) - 1,
        GreyA(n)   => num::pow(2u16, n as uint) - 1,
        RGBA(n)    => num::pow(2u16, n as uint) - 1
    }
}
<commit_msg>Fixed compiler warnings<commit_after>//! Encoding of PPM Images

use std::io::IoResult;
use std::fmt;

use color;
use color::ColorType:: {
    Grey,
    Palette,
    GreyA,
    RGB,
    RGBA
};

/// A representation of a PPM encoder.
pub struct PPMEncoder<W> {
    w: W
}

impl<W: Writer> PPMEncoder<W> {
    /// Create a new PPMEncoder from the Writer ```w```.
    /// This function takes ownership of the Writer.
    pub fn new(w: W) -> PPMEncoder<W> {
        PPMEncoder {w: w}
    }

    /// Encode the buffer ```im``` as a PPM image.
    /// ```width``` and ```height``` are the dimensions of the buffer.
    /// ```color``` is the buffers ColorType.
    pub fn encode(&mut self, im: &[u8], width: u32, height: u32, color: color::ColorType) -> IoResult<()> {
        let _ = try!(self.write_magic_number());
        let _ = try!(self.write_metadata(width, height, color));

        self.write_image(im, color, width, height)
    }

    fn write_magic_number(&mut self) -> IoResult<()> {
        self.w.write_str("P6\n")
    }

    fn write_metadata(&mut self, width: u32, height: u32, pixel_type: color::ColorType) -> IoResult<()> {
        let w = fmt::radix(width, 10);
        let h = fmt::radix(height, 10);
        let m = max_pixel_value(pixel_type);

        self.w.write_str(format!("{0} {1}\n{2}\n", w, h, m).as_slice())
    }

    fn write_image(
        &mut self,
        buf: &[u8],
        pixel_type: color::ColorType,
        width: u32,
        height: u32) -> IoResult<()> {

        assert!(buf.len() > 0);
        match pixel_type {
            Grey(8) => {
                for i in range(0, (width * height) as uint) {
                    let _ = try!(self.w.write_u8(buf[i]));
                    let _ = try!(self.w.write_u8(buf[i]));
                    let _ = try!(self.w.write_u8(buf[i]));
                }
            }

            RGB(8)  => try!(self.w.write(buf)),
            RGB(16) => try!(self.w.write(buf)),
            RGBA(8) => {
                for x in buf.chunks(4) {

                    let _ = try!(self.w.write_u8(x[0]));

                    let _ = try!(self.w.write_u8(x[1]));

                    let _ = try!(self.w.write_u8(x[2]));
                }
            }

            a => panic!(format!("not implemented: {}", a))
        }

        Ok(())
    }
}

fn max_pixel_value(pixel_type: color::ColorType) -> u16 {
    use std::num::Int;

    match pixel_type {
        Grey(n)    => 2u16.pow(n as uint) - 1,
        RGB(n)     => 2u16.pow(n as uint) - 1,
        Palette(n) => 2u16.pow(n as uint) - 1,
        GreyA(n)   => 2u16.pow(n as uint) - 1,
        RGBA(n)    => 2u16.pow(n as uint) - 1
    }
}
<|endoftext|>


<commit_before>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use futures::future::{self, Future};
use httparse;
use hyper::{Error, Method, StatusCode, Headers};
use hyper::header::{Origin, IfNoneMatch, ETag, EntityTag};
use hyper::server::{Request, Response};
use farmhash;

use super::header::ProxyHeader;
use super::tunnel::ProxyTunnel;
use header::janitor::HeaderJanitor;
use header::request_shard::HeaderRequestBloomRequestShard;
use header::status::{HeaderBloomStatus, HeaderBloomStatusValue};
use cache::read::CacheRead;
use cache::write::CacheWrite;
use cache::route::CacheRoute;
use LINE_FEED;

pub struct ProxyServe;

const CACHED_PARSE_MAX_HEADERS: usize = 100;

pub type ProxyServeFuture = Box<Future<Item = Response, Error = Error>>;

impl ProxyServe {
    pub fn handle(req: Request) -> ProxyServeFuture {
        info!("handled request: {} on {}", req.method(), req.path());

        if req.headers().has::<HeaderRequestBloomRequestShard>() == true {
            match *req.method() {
                Method::Options | Method::Head | Method::Get | Method::Post | Method::Patch |
                Method::Put | Method::Delete => Self::accept(req),
                _ => Self::reject(req, StatusCode::MethodNotAllowed),
            }
        } else {
            Self::reject(req, StatusCode::NotExtended)
        }
    }

    fn accept(req: Request) -> ProxyServeFuture {
        Self::tunnel(req)
    }

    fn reject(req: Request, status: StatusCode) -> ProxyServeFuture {
        let mut headers = Headers::new();

        headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Reject));

        Self::respond(&req.method(), status, headers, format!("{}", status))
    }

    fn tunnel(req: Request) -> ProxyServeFuture {
        let (method, uri, version, headers, body) = req.deconstruct();
        let (auth, shard) = ProxyHeader::parse_from_request(&headers);

        let ns = CacheRoute::gen_ns(
            shard,
            auth,
            version,
            &method,
            uri.path(),
            uri.query(),
            headers.get::<Origin>(),
        );

        info!("tunneling for ns = {}", ns);

        match CacheRead::acquire(ns.as_ref(), &method) {
            Ok(cached_value) => Self::dispatch_cached(&method, &headers, &cached_value),
            Err(_) => {
                // Clone method value for closures. Sadly, it looks like Rust borrow checker \
                //   doesnt discriminate properly on this check.
                let method_success = method.to_owned();
                let method_failure = method.to_owned();

                Box::new(
                    ProxyTunnel::run(&method, &uri, &headers, body, shard)
                        .and_then(move |tunnel_res| {
                            let res_status = tunnel_res.status();
                            let res_headers = tunnel_res.headers().to_owned();

                            CacheWrite::save(
                                ns,
                                method,
                                version,
                                res_status,
                                res_headers,
                                tunnel_res.body(),
                            )
                        })
                        .and_then(move |result| match result.body {
                            Ok(body_string) => {
                                Self::dispatch_fetched(
                                    &method_success,
                                    &result.status,
                                    result.headers,
                                    HeaderBloomStatusValue::Miss,
                                    body_string,
                                    result.value,
                                )
                            }
                            Err(body_string_values) => {
                                match body_string_values {
                                    Some(body_string) => {
                                        Self::dispatch_fetched(
                                            &method_success,
                                            &result.status,
                                            result.headers,
                                            HeaderBloomStatusValue::Direct,
                                            body_string,
                                            result.value,
                                        )
                                    }
                                    _ => Self::dispatch_failure(&method_success),
                                }
                            }
                        })
                        .or_else(move |_| Self::dispatch_failure(&method_failure)),
                )
            }
        }
    }

    fn dispatch_cached(method: &Method, headers: &Headers, res_string: &str) -> ProxyServeFuture {
        // Process ETag for cached content
        let (res_hash, res_etag) = Self::body_fingerprint(res_string);

        let isnt_modified = match headers.get::<IfNoneMatch>() {
            Some(req_if_none_match) => {
                (*req_if_none_match == IfNoneMatch::Items(vec![EntityTag::new(false, res_hash)]))
            }
            _ => false,
        };

        // Response not modified for client?
        if isnt_modified == true {
            // Process non-modified + cached headers
            let mut headers = Headers::new();

            ProxyHeader::set_common(&mut headers, res_etag);
            headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Hit));

            // Serve non-modified response
            return Self::respond(method, StatusCode::NotModified, headers, String::from(""));
        }

        // Response modified
        let mut headers = [httparse::EMPTY_HEADER; CACHED_PARSE_MAX_HEADERS];
        let mut res = httparse::Response::new(&mut headers);

        // Split headers from body
        let mut res_body_string = String::new();
        let mut is_last_line_empty = false;

        for res_line in res_string.lines() {
            if res_body_string.is_empty() == false || is_last_line_empty == true {
                // Write to body
                res_body_string.push_str(res_line.as_ref());
                res_body_string.push_str(LINE_FEED);
            }

            is_last_line_empty = res_line.is_empty();
        }

        match res.parse(res_string.as_bytes()) {
            Ok(_) => {
                // Process cached status
                let code = res.code.unwrap_or(500u16);
                let status = StatusCode::try_from(code).unwrap_or(StatusCode::Unregistered(code));

                // Process cached headers
                let mut headers = Headers::new();

                for header in res.headers {
                    if let (Ok(header_name), Ok(header_value)) =
                        (
                            String::from_utf8(Vec::from(header.name)),
                            String::from_utf8(Vec::from(header.value)),
                        )
                    {
                        headers.set_raw(header_name, header_value);
                    }
                }

                ProxyHeader::set_common(&mut headers, res_etag);
                headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Hit));

                // Serve cached response
                Self::respond(method, status, headers, res_body_string)
            }
            Err(err) => {
                error!("failed parsing cached response: {}", err);

                Self::dispatch_failure(method)
            }
        }
    }

    fn dispatch_fetched(
        method: &Method,
        status: &StatusCode,
        mut headers: Headers,
        bloom_status: HeaderBloomStatusValue,
        body_string: String,
        result_string: Option<String>,
    ) -> ProxyServeFuture {
        // Map headers to clean-up
        let mut headers_remove: Vec<String> = Vec::new();

        for header_view in headers.iter() {
            // Do not forward contextual and internal headers \
            //   (ie. 'Bloom-Response-*' headers)
            if HeaderJanitor::is_contextual(&header_view) == true ||
                HeaderJanitor::is_internal(&header_view) == true
            {
                headers_remove.push(String::from(header_view.name()));
            }
        }

        // Proceed headers clean-up
        for header_remove in headers_remove.iter() {
            headers.remove_raw(header_remove.as_ref());
        }

        // Process ETag for content?
        if let Some(result_string_value) = result_string {
            let (_, res_etag) = Self::body_fingerprint(&result_string_value);

            ProxyHeader::set_common(&mut headers, res_etag);
        }

        headers.set(HeaderBloomStatus(bloom_status));

        Self::respond(method, *status, headers, body_string)
    }

    fn dispatch_failure(method: &Method) -> ProxyServeFuture {
        let status = StatusCode::BadGateway;

        let mut headers = Headers::new();

        headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Offline));

        Self::respond(method, status, headers, format!("{}", status))
    }

    fn body_fingerprint(body_string: &str) -> (String, ETag) {
        let body_hash = format!("{:x}", farmhash::fingerprint64(body_string.as_bytes()));
        let body_etag = ETag(EntityTag::new(false, body_hash.to_owned()));

        (body_hash, body_etag)
    }

    fn respond(
        method: &Method,
        status: StatusCode,
        headers: Headers,
        body_string: String,
    ) -> ProxyServeFuture {
        Box::new(future::ok(match method {
            &Method::Get | &Method::Post | &Method::Patch | &Method::Put => {
                Response::new()
                    .with_status(status)
                    .with_headers(headers)
                    .with_body(body_string)
            }
            _ => Response::new().with_status(status).with_headers(headers),
        }))
    }
}
<commit_msg>Cleanup headers before writing cache<commit_after>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use futures::future::{self, Future};
use httparse;
use hyper::{Error, Method, StatusCode, Headers};
use hyper::header::{Origin, IfNoneMatch, ETag, EntityTag};
use hyper::server::{Request, Response};
use farmhash;

use super::header::ProxyHeader;
use super::tunnel::ProxyTunnel;
use header::janitor::HeaderJanitor;
use header::request_shard::HeaderRequestBloomRequestShard;
use header::status::{HeaderBloomStatus, HeaderBloomStatusValue};
use cache::read::CacheRead;
use cache::write::CacheWrite;
use cache::route::CacheRoute;
use LINE_FEED;

pub struct ProxyServe;

const CACHED_PARSE_MAX_HEADERS: usize = 100;

pub type ProxyServeFuture = Box<Future<Item = Response, Error = Error>>;

impl ProxyServe {
    pub fn handle(req: Request) -> ProxyServeFuture {
        info!("handled request: {} on {}", req.method(), req.path());

        if req.headers().has::<HeaderRequestBloomRequestShard>() == true {
            match *req.method() {
                Method::Options | Method::Head | Method::Get | Method::Post | Method::Patch |
                Method::Put | Method::Delete => Self::accept(req),
                _ => Self::reject(req, StatusCode::MethodNotAllowed),
            }
        } else {
            Self::reject(req, StatusCode::NotExtended)
        }
    }

    fn accept(req: Request) -> ProxyServeFuture {
        Self::tunnel(req)
    }

    fn reject(req: Request, status: StatusCode) -> ProxyServeFuture {
        let mut headers = Headers::new();

        headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Reject));

        Self::respond(&req.method(), status, headers, format!("{}", status))
    }

    fn tunnel(req: Request) -> ProxyServeFuture {
        let (method, uri, version, headers, body) = req.deconstruct();
        let (auth, shard) = ProxyHeader::parse_from_request(&headers);

        let ns = CacheRoute::gen_ns(
            shard,
            auth,
            version,
            &method,
            uri.path(),
            uri.query(),
            headers.get::<Origin>(),
        );

        info!("tunneling for ns = {}", ns);

        match CacheRead::acquire(ns.as_ref(), &method) {
            Ok(cached_value) => Self::dispatch_cached(&method, &headers, &cached_value),
            Err(_) => {
                // Clone method value for closures. Sadly, it looks like Rust borrow checker \
                //   doesnt discriminate properly on this check.
                let method_success = method.to_owned();
                let method_failure = method.to_owned();

                Box::new(
                    ProxyTunnel::run(&method, &uri, &headers, body, shard)
                        .and_then(move |tunnel_res| {
                            let res_status = tunnel_res.status();
                            let mut res_headers = tunnel_res.headers().to_owned();

                            // Map headers to clean-up
                            let mut headers_remove: Vec<String> = Vec::new();

                            for header_view in res_headers.iter() {
                                // Do not forward contextual and internal headers \
                                //   (ie. 'Bloom-Response-*' headers)
                                if HeaderJanitor::is_contextual(&header_view) == true ||
                                    HeaderJanitor::is_internal(&header_view) == true
                                {
                                    headers_remove.push(String::from(header_view.name()));
                                }
                            }

                            // Proceed headers clean-up
                            for header_remove in headers_remove.iter() {
                                res_headers.remove_raw(header_remove.as_ref());
                            }

                            CacheWrite::save(
                                ns,
                                method,
                                version,
                                res_status,
                                res_headers,
                                tunnel_res.body(),
                            )
                        })
                        .and_then(move |result| match result.body {
                            Ok(body_string) => {
                                Self::dispatch_fetched(
                                    &method_success,
                                    &result.status,
                                    result.headers,
                                    HeaderBloomStatusValue::Miss,
                                    body_string,
                                    result.value,
                                )
                            }
                            Err(body_string_values) => {
                                match body_string_values {
                                    Some(body_string) => {
                                        Self::dispatch_fetched(
                                            &method_success,
                                            &result.status,
                                            result.headers,
                                            HeaderBloomStatusValue::Direct,
                                            body_string,
                                            result.value,
                                        )
                                    }
                                    _ => Self::dispatch_failure(&method_success),
                                }
                            }
                        })
                        .or_else(move |_| Self::dispatch_failure(&method_failure)),
                )
            }
        }
    }

    fn dispatch_cached(method: &Method, headers: &Headers, res_string: &str) -> ProxyServeFuture {
        // Process ETag for cached content
        let (res_hash, res_etag) = Self::body_fingerprint(res_string);

        let isnt_modified = match headers.get::<IfNoneMatch>() {
            Some(req_if_none_match) => {
                (*req_if_none_match == IfNoneMatch::Items(vec![EntityTag::new(false, res_hash)]))
            }
            _ => false,
        };

        // Response not modified for client?
        if isnt_modified == true {
            // Process non-modified + cached headers
            let mut headers = Headers::new();

            ProxyHeader::set_common(&mut headers, res_etag);
            headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Hit));

            // Serve non-modified response
            return Self::respond(method, StatusCode::NotModified, headers, String::from(""));
        }

        // Response modified
        let mut headers = [httparse::EMPTY_HEADER; CACHED_PARSE_MAX_HEADERS];
        let mut res = httparse::Response::new(&mut headers);

        // Split headers from body
        let mut res_body_string = String::new();
        let mut is_last_line_empty = false;

        for res_line in res_string.lines() {
            if res_body_string.is_empty() == false || is_last_line_empty == true {
                // Write to body
                res_body_string.push_str(res_line.as_ref());
                res_body_string.push_str(LINE_FEED);
            }

            is_last_line_empty = res_line.is_empty();
        }

        match res.parse(res_string.as_bytes()) {
            Ok(_) => {
                // Process cached status
                let code = res.code.unwrap_or(500u16);
                let status = StatusCode::try_from(code).unwrap_or(StatusCode::Unregistered(code));

                // Process cached headers
                let mut headers = Headers::new();

                for header in res.headers {
                    if let (Ok(header_name), Ok(header_value)) =
                        (
                            String::from_utf8(Vec::from(header.name)),
                            String::from_utf8(Vec::from(header.value)),
                        )
                    {
                        headers.set_raw(header_name, header_value);
                    }
                }

                ProxyHeader::set_common(&mut headers, res_etag);
                headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Hit));

                // Serve cached response
                Self::respond(method, status, headers, res_body_string)
            }
            Err(err) => {
                error!("failed parsing cached response: {}", err);

                Self::dispatch_failure(method)
            }
        }
    }

    fn dispatch_fetched(
        method: &Method,
        status: &StatusCode,
        mut headers: Headers,
        bloom_status: HeaderBloomStatusValue,
        body_string: String,
        result_string: Option<String>,
    ) -> ProxyServeFuture {
        // Process ETag for content?
        if let Some(result_string_value) = result_string {
            let (_, res_etag) = Self::body_fingerprint(&result_string_value);

            ProxyHeader::set_common(&mut headers, res_etag);
        }

        headers.set(HeaderBloomStatus(bloom_status));

        Self::respond(method, *status, headers, body_string)
    }

    fn dispatch_failure(method: &Method) -> ProxyServeFuture {
        let status = StatusCode::BadGateway;

        let mut headers = Headers::new();

        headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Offline));

        Self::respond(method, status, headers, format!("{}", status))
    }

    fn body_fingerprint(body_string: &str) -> (String, ETag) {
        let body_hash = format!("{:x}", farmhash::fingerprint64(body_string.as_bytes()));
        let body_etag = ETag(EntityTag::new(false, body_hash.to_owned()));

        (body_hash, body_etag)
    }

    fn respond(
        method: &Method,
        status: StatusCode,
        headers: Headers,
        body_string: String,
    ) -> ProxyServeFuture {
        Box::new(future::ok(match method {
            &Method::Get | &Method::Post | &Method::Patch | &Method::Put => {
                Response::new()
                    .with_status(status)
                    .with_headers(headers)
                    .with_body(body_string)
            }
            _ => Response::new().with_status(status).with_headers(headers),
        }))
    }
}
<|endoftext|>


<commit_before>//! Iron's HTTP Request representation and associated methods.

use std::io::{self, Read};
use std::net::SocketAddr;
use std::fmt::{self, Debug};

use hyper::uri::RequestUri::{AbsoluteUri, AbsolutePath};
use hyper::net::NetworkStream;
use hyper::http::h1::HttpReader;
use hyper::version::HttpVersion;

use typemap::TypeMap;
use plugin::Extensible;
use method::Method;

pub use hyper::server::request::Request as HttpRequest;
use hyper::buffer;

pub use self::url::Url;

use {Protocol, Plugin, Headers, Set, headers};

mod url;

/// The `Request` given to all `Middleware`.
///
/// Stores all the properties of the client's request plus
/// an `TypeMap` for data communication between middleware.
pub struct Request<'a, 'b: 'a> {
    /// The requested URL.
    pub url: Url,

    /// The originating address of the request.
    pub remote_addr: SocketAddr,

    /// The local address of the request.
    pub local_addr: SocketAddr,

    /// The request headers.
    pub headers: Headers,

    /// The request body as a reader.
    pub body: Body<'a, 'b>,

    /// The request method.
    pub method: Method,

    /// Extensible storage for data passed between middleware.
    pub extensions: TypeMap
}

impl<'a, 'b> Debug for Request<'a, 'b> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "Request {{"));

        try!(writeln!(f, "    url: {:?}", self.url));
        try!(writeln!(f, "    method: {:?}", self.method));
        try!(writeln!(f, "    remote_addr: {:?}", self.remote_addr));
        try!(writeln!(f, "    local_addr: {:?}", self.local_addr));

        try!(write!(f, "}}"));
        Ok(())
    }
}

impl<'a, 'b> Request<'a, 'b> {
    /// Create a request from an HttpRequest.
    ///
    /// This constructor consumes the HttpRequest.
    pub fn from_http(req: HttpRequest<'a, 'b>, local_addr: SocketAddr, protocol: &Protocol)
                     -> Result<Request<'a, 'b>, String> {
        let (addr, method, headers, uri, version, reader) = req.deconstruct();

        let url = match uri {
            AbsoluteUri(ref url) => {
                match Url::from_generic_url(url.clone()) {
                    Ok(url) => url,
                    Err(e) => return Err(e)
                }
            },

            AbsolutePath(ref path) => {
                let url_string = match (version, headers.get::<headers::Host>()) {
                    (_, Some(ref host)) => {
                        // Attempt to prepend the Host header (mandatory in HTTP/1.1)
                        format!("{}://{}:{}{}", protocol.name(), host.hostname, local_addr.port(), path)
                    },
                    (v, None) if v < HttpVersion::Http11 => {
                        // Attempt to use the local address? (host header is not required in HTTP/1.0).
                        match local_addr {
                            SocketAddr::V4(addr4) => format!("{}://{}:{}{}", protocol.name(), addr4.ip(), local_addr.port(), path),
                            SocketAddr::V6(addr6) => format!("{}://[{}]:{}{}", protocol.name(), addr6.ip(), local_addr.port(), path),
                        }
                    },
                    (_, None) => {
                        return Err("No host specified in request".into())
                    }
                };

                match Url::parse(&url_string) {
                    Ok(url) => url,
                    Err(e) => return Err(format!("Couldn't parse requested URL: {}", e))
                }
            },
            _ => return Err("Unsupported request URI".into())
        };

        Ok(Request {
            url: url,
            remote_addr: addr,
            local_addr: local_addr,
            headers: headers,
            body: Body::new(reader),
            method: method,
            extensions: TypeMap::new()
        })
    }
}

/// The body of an Iron request,
pub struct Body<'a, 'b: 'a>(HttpReader<&'a mut buffer::BufReader<&'b mut NetworkStream>>);

impl<'a, 'b> Body<'a, 'b> {
    /// Create a new reader for use in an Iron request from a hyper HttpReader.
    pub fn new(reader: HttpReader<&'a mut buffer::BufReader<&'b mut NetworkStream>>) -> Body<'a, 'b> {
        Body(reader)
    }
}

impl<'a, 'b> Read for Body<'a, 'b> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

// Allow plugins to attach to requests.
impl<'a, 'b> Extensible for Request<'a, 'b> {
    fn extensions(&self) -> &TypeMap {
        &self.extensions
    }

    fn extensions_mut(&mut self) -> &mut TypeMap {
        &mut self.extensions
    }
}

impl<'a, 'b> Plugin for Request<'a, 'b> {}
impl<'a, 'b> Set for Request<'a, 'b> {}
<commit_msg>Don't mix up local address and Host header<commit_after>//! Iron's HTTP Request representation and associated methods.

use std::io::{self, Read};
use std::net::SocketAddr;
use std::fmt::{self, Debug};

use hyper::uri::RequestUri::{AbsoluteUri, AbsolutePath};
use hyper::net::NetworkStream;
use hyper::http::h1::HttpReader;
use hyper::version::HttpVersion;

use typemap::TypeMap;
use plugin::Extensible;
use method::Method;

pub use hyper::server::request::Request as HttpRequest;
use hyper::buffer;

pub use self::url::Url;

use {Protocol, Plugin, Headers, Set, headers};

mod url;

/// The `Request` given to all `Middleware`.
///
/// Stores all the properties of the client's request plus
/// an `TypeMap` for data communication between middleware.
pub struct Request<'a, 'b: 'a> {
    /// The requested URL.
    pub url: Url,

    /// The originating address of the request.
    pub remote_addr: SocketAddr,

    /// The local address of the request.
    pub local_addr: SocketAddr,

    /// The request headers.
    pub headers: Headers,

    /// The request body as a reader.
    pub body: Body<'a, 'b>,

    /// The request method.
    pub method: Method,

    /// Extensible storage for data passed between middleware.
    pub extensions: TypeMap
}

impl<'a, 'b> Debug for Request<'a, 'b> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "Request {{"));

        try!(writeln!(f, "    url: {:?}", self.url));
        try!(writeln!(f, "    method: {:?}", self.method));
        try!(writeln!(f, "    remote_addr: {:?}", self.remote_addr));
        try!(writeln!(f, "    local_addr: {:?}", self.local_addr));

        try!(write!(f, "}}"));
        Ok(())
    }
}

impl<'a, 'b> Request<'a, 'b> {
    /// Create a request from an HttpRequest.
    ///
    /// This constructor consumes the HttpRequest.
    pub fn from_http(req: HttpRequest<'a, 'b>, local_addr: SocketAddr, protocol: &Protocol)
                     -> Result<Request<'a, 'b>, String> {
        let (addr, method, headers, uri, version, reader) = req.deconstruct();

        let url = match uri {
            AbsoluteUri(ref url) => {
                match Url::from_generic_url(url.clone()) {
                    Ok(url) => url,
                    Err(e) => return Err(e)
                }
            },

            AbsolutePath(ref path) => {
                let url_string = match (version, headers.get::<headers::Host>()) {
                    (_, Some(ref host)) => {
                        // Attempt to prepend the Host header (mandatory in HTTP/1.1)
                        if let Some(port) = host.port {
                            format!("{}://{}:{}{}", protocol.name(), host.hostname, port, path)
                        } else {
                            format!("{}://{}{}", protocol.name(), host.hostname, path)
                        }
                    },
                    (v, None) if v < HttpVersion::Http11 => {
                        // Attempt to use the local address? (host header is not required in HTTP/1.0).
                        match local_addr {
                            SocketAddr::V4(addr4) => format!("{}://{}:{}{}", protocol.name(), addr4.ip(), local_addr.port(), path),
                            SocketAddr::V6(addr6) => format!("{}://[{}]:{}{}", protocol.name(), addr6.ip(), local_addr.port(), path),
                        }
                    },
                    (_, None) => {
                        return Err("No host specified in request".into())
                    }
                };

                match Url::parse(&url_string) {
                    Ok(url) => url,
                    Err(e) => return Err(format!("Couldn't parse requested URL: {}", e))
                }
            },
            _ => return Err("Unsupported request URI".into())
        };

        Ok(Request {
            url: url,
            remote_addr: addr,
            local_addr: local_addr,
            headers: headers,
            body: Body::new(reader),
            method: method,
            extensions: TypeMap::new()
        })
    }
}

/// The body of an Iron request,
pub struct Body<'a, 'b: 'a>(HttpReader<&'a mut buffer::BufReader<&'b mut NetworkStream>>);

impl<'a, 'b> Body<'a, 'b> {
    /// Create a new reader for use in an Iron request from a hyper HttpReader.
    pub fn new(reader: HttpReader<&'a mut buffer::BufReader<&'b mut NetworkStream>>) -> Body<'a, 'b> {
        Body(reader)
    }
}

impl<'a, 'b> Read for Body<'a, 'b> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

// Allow plugins to attach to requests.
impl<'a, 'b> Extensible for Request<'a, 'b> {
    fn extensions(&self) -> &TypeMap {
        &self.extensions
    }

    fn extensions_mut(&mut self) -> &mut TypeMap {
        &mut self.extensions
    }
}

impl<'a, 'b> Plugin for Request<'a, 'b> {}
impl<'a, 'b> Set for Request<'a, 'b> {}
<|endoftext|>


<commit_before>use byteorder::{BigEndian, ByteOrder};
use bytes::Bytes;
use futures::sync::{mpsc, BiLock};
use futures::{Async, Poll, Stream};
use std::collections::HashMap;

use util::SeqGenerator;

component! {
    ChannelManager : ChannelManagerInner {
        sequence: SeqGenerator<u16> = SeqGenerator::new(0),
        channels: HashMap<u16, mpsc::UnboundedSender<(u8, Bytes)>> = HashMap::new(),
    }
}

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

pub struct Channel {
    receiver: mpsc::UnboundedReceiver<(u8, Bytes)>,
    state: ChannelState,
}

pub struct ChannelHeaders(BiLock<Channel>);
pub struct ChannelData(BiLock<Channel>);

pub enum ChannelEvent {
    Header(u8, Vec<u8>),
    Data(Bytes),
}

#[derive(Clone)]
enum ChannelState {
    Header(Bytes),
    Data,
    Closed,
}

impl ChannelManager {
    pub fn allocate(&self) -> (u16, Channel) {
        let (tx, rx) = mpsc::unbounded();

        let seq = self.lock(|inner| {
            let seq = inner.sequence.get();
            inner.channels.insert(seq, tx);
            seq
        });

        let channel = Channel {
            receiver: rx,
            state: ChannelState::Header(Bytes::new()),
        };

        (seq, channel)
    }

    pub(crate) fn dispatch(&self, cmd: u8, mut data: Bytes) {
        use std::collections::hash_map::Entry;

        let id: u16 = BigEndian::read_u16(data.split_to(2).as_ref());

        trace!("Received data for channel {}: {} bytes.", id, data.len());

        self.lock(|inner| {
            if let Entry::Occupied(entry) = inner.channels.entry(id) {
                let _ = entry.get().unbounded_send((cmd, data));
            }
        });
    }
}

impl Channel {
    fn recv_packet(&mut self) -> Poll<Bytes, ChannelError> {
        let (cmd, packet) = match self.receiver.poll() {
            Ok(Async::Ready(t)) => t.expect("channel closed"),
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Err(()) => unreachable!(),
        };

        if cmd == 0xa {
            let code = BigEndian::read_u16(&packet.as_ref()[..2]);
            error!("channel error: {} {}", packet.len(), code);

            self.state = ChannelState::Closed;

            Err(ChannelError)
        } else {
            Ok(Async::Ready(packet))
        }
    }

    pub fn split(self) -> (ChannelHeaders, ChannelData) {
        let (headers, data) = BiLock::new(self);

        (ChannelHeaders(headers), ChannelData(data))
    }
}

impl Stream for Channel {
    type Item = ChannelEvent;
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            match self.state.clone() {
                ChannelState::Closed => panic!("Polling already terminated channel"),
                ChannelState::Header(mut data) => {
                    if data.len() == 0 {
                        data = try_ready!(self.recv_packet());
                    }

                    let length = BigEndian::read_u16(data.split_to(2).as_ref()) as usize;
                    if length == 0 {
                        assert_eq!(data.len(), 0);
                        self.state = ChannelState::Data;
                    } else {
                        let header_id = data.split_to(1).as_ref()[0];
                        let header_data = data.split_to(length - 1).as_ref().to_owned();

                        self.state = ChannelState::Header(data);

                        let event = ChannelEvent::Header(header_id, header_data);
                        return Ok(Async::Ready(Some(event)));
                    }
                }

                ChannelState::Data => {
                    let data = try_ready!(self.recv_packet());
                    if data.len() == 0 {
                        self.receiver.close();
                        self.state = ChannelState::Closed;
                        return Ok(Async::Ready(None));
                    } else {
                        let event = ChannelEvent::Data(data);
                        return Ok(Async::Ready(Some(event)));
                    }
                }
            }
        }
    }
}

impl Stream for ChannelData {
    type Item = Bytes;
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let mut channel = match self.0.poll_lock() {
            Async::Ready(c) => c,
            Async::NotReady => return Ok(Async::NotReady),
        };

        loop {
            match try_ready!(channel.poll()) {
                Some(ChannelEvent::Header(..)) => (),
                Some(ChannelEvent::Data(data)) => return Ok(Async::Ready(Some(data))),
                None => return Ok(Async::Ready(None)),
            }
        }
    }
}

impl Stream for ChannelHeaders {
    type Item = (u8, Vec<u8>);
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let mut channel = match self.0.poll_lock() {
            Async::Ready(c) => c,
            Async::NotReady => return Ok(Async::NotReady),
        };

        match try_ready!(channel.poll()) {
            Some(ChannelEvent::Header(id, data)) => Ok(Async::Ready(Some((id, data)))),
            Some(ChannelEvent::Data(..)) | None => Ok(Async::Ready(None)),
        }
    }
}
<commit_msg>Remove log message<commit_after>use byteorder::{BigEndian, ByteOrder};
use bytes::Bytes;
use futures::sync::{mpsc, BiLock};
use futures::{Async, Poll, Stream};
use std::collections::HashMap;

use util::SeqGenerator;

component! {
    ChannelManager : ChannelManagerInner {
        sequence: SeqGenerator<u16> = SeqGenerator::new(0),
        channels: HashMap<u16, mpsc::UnboundedSender<(u8, Bytes)>> = HashMap::new(),
    }
}

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

pub struct Channel {
    receiver: mpsc::UnboundedReceiver<(u8, Bytes)>,
    state: ChannelState,
}

pub struct ChannelHeaders(BiLock<Channel>);
pub struct ChannelData(BiLock<Channel>);

pub enum ChannelEvent {
    Header(u8, Vec<u8>),
    Data(Bytes),
}

#[derive(Clone)]
enum ChannelState {
    Header(Bytes),
    Data,
    Closed,
}

impl ChannelManager {
    pub fn allocate(&self) -> (u16, Channel) {
        let (tx, rx) = mpsc::unbounded();

        let seq = self.lock(|inner| {
            let seq = inner.sequence.get();
            inner.channels.insert(seq, tx);
            seq
        });

        let channel = Channel {
            receiver: rx,
            state: ChannelState::Header(Bytes::new()),
        };

        (seq, channel)
    }

    pub(crate) fn dispatch(&self, cmd: u8, mut data: Bytes) {
        use std::collections::hash_map::Entry;

        let id: u16 = BigEndian::read_u16(data.split_to(2).as_ref());

        self.lock(|inner| {
            if let Entry::Occupied(entry) = inner.channels.entry(id) {
                let _ = entry.get().unbounded_send((cmd, data));
            }
        });
    }
}

impl Channel {
    fn recv_packet(&mut self) -> Poll<Bytes, ChannelError> {
        let (cmd, packet) = match self.receiver.poll() {
            Ok(Async::Ready(t)) => t.expect("channel closed"),
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Err(()) => unreachable!(),
        };

        if cmd == 0xa {
            let code = BigEndian::read_u16(&packet.as_ref()[..2]);
            error!("channel error: {} {}", packet.len(), code);

            self.state = ChannelState::Closed;

            Err(ChannelError)
        } else {
            Ok(Async::Ready(packet))
        }
    }

    pub fn split(self) -> (ChannelHeaders, ChannelData) {
        let (headers, data) = BiLock::new(self);

        (ChannelHeaders(headers), ChannelData(data))
    }
}

impl Stream for Channel {
    type Item = ChannelEvent;
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            match self.state.clone() {
                ChannelState::Closed => panic!("Polling already terminated channel"),
                ChannelState::Header(mut data) => {
                    if data.len() == 0 {
                        data = try_ready!(self.recv_packet());
                    }

                    let length = BigEndian::read_u16(data.split_to(2).as_ref()) as usize;
                    if length == 0 {
                        assert_eq!(data.len(), 0);
                        self.state = ChannelState::Data;
                    } else {
                        let header_id = data.split_to(1).as_ref()[0];
                        let header_data = data.split_to(length - 1).as_ref().to_owned();

                        self.state = ChannelState::Header(data);

                        let event = ChannelEvent::Header(header_id, header_data);
                        return Ok(Async::Ready(Some(event)));
                    }
                }

                ChannelState::Data => {
                    let data = try_ready!(self.recv_packet());
                    if data.len() == 0 {
                        self.receiver.close();
                        self.state = ChannelState::Closed;
                        return Ok(Async::Ready(None));
                    } else {
                        let event = ChannelEvent::Data(data);
                        return Ok(Async::Ready(Some(event)));
                    }
                }
            }
        }
    }
}

impl Stream for ChannelData {
    type Item = Bytes;
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let mut channel = match self.0.poll_lock() {
            Async::Ready(c) => c,
            Async::NotReady => return Ok(Async::NotReady),
        };

        loop {
            match try_ready!(channel.poll()) {
                Some(ChannelEvent::Header(..)) => (),
                Some(ChannelEvent::Data(data)) => return Ok(Async::Ready(Some(data))),
                None => return Ok(Async::Ready(None)),
            }
        }
    }
}

impl Stream for ChannelHeaders {
    type Item = (u8, Vec<u8>);
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let mut channel = match self.0.poll_lock() {
            Async::Ready(c) => c,
            Async::NotReady => return Ok(Async::NotReady),
        };

        match try_ready!(channel.poll()) {
            Some(ChannelEvent::Header(id, data)) => Ok(Async::Ready(Some((id, data)))),
            Some(ChannelEvent::Data(..)) | None => Ok(Async::Ready(None)),
        }
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::io::BufReader;

use color::{ColorType};
use image::{DecodingResult, ImageDecoder, ImageResult, ImageError};

/// PPM decoder
pub struct PPMDecoder<R> {
    reader: BufReader<R>,
    width: u32,
    height: u32,
    maxwhite: u32,
}

impl<R: Read> PPMDecoder<R> {
    /// Create a new decoder that decodes from the stream ```r```
    pub fn new(r: R) -> ImageResult<PPMDecoder<R>> {
        let mut buf = BufReader::new(r);
        try!(PPMDecoder::read_next_string(&mut buf)); // Skip P6
        let width = try!(PPMDecoder::read_next_u32(&mut buf));
        let height = try!(PPMDecoder::read_next_u32(&mut buf));
        let maxwhite = try!(PPMDecoder::read_next_u32(&mut buf));
        Ok(PPMDecoder {
            reader: buf,
            width: width,
            height: height,
            maxwhite: maxwhite,
        })
    }

  fn read_next_string(reader: &mut BufReader<R>) -> ImageResult<String> {
      let mut bytes = Vec::new();
      loop {
          let mut buffer: [u8;1] = [0];
          try!(reader.read_exact(&mut buffer));
          match buffer[0] {
              b'\n' | b' ' | b'\r' => {
                  if bytes.len() > 0 {
                    break // We're done as we already have some content
                  }
              },
              _ => {
                  bytes.push(buffer[0]);
              },
          }
      }

      match String::from_utf8(bytes) {
          Ok(s) => Ok(s),
          Err(_) => Err(ImageError::FormatError("Couldn't read preamble".to_string())),
      }
  }

  fn read_next_u32(reader: &mut BufReader<R>) -> ImageResult<u32> {
      let s = try!(PPMDecoder::read_next_string(reader));
      match s.parse::<u32>() {
          Ok(v) => Ok(v),
          Err(_) => Err(ImageError::FormatError("Couldn't read preamble".to_string())),
      }
  }
}

impl<R: Read> ImageDecoder for PPMDecoder<R> {
    fn dimensions(&mut self) -> ImageResult<(u32, u32)> {
        Ok((self.width, self.height))
    }

    fn colortype(&mut self) -> ImageResult<ColorType> {
        match self.bytewidth() {
            1 => Ok(ColorType::RGB(8)),
            2 => Ok(ColorType::RGB(16)),
            _ => Err(ImageError::FormatError("Don't know how to decode PPM with more than 16 bits".to_string())),
        }
    }

    fn row_len(&mut self) -> ImageResult<usize> {
        Ok((self.width*3*self.bytewidth()) as usize)
    }

    fn read_scanline(&mut self, _buf: &mut [u8]) -> ImageResult<u32> {
        unimplemented!();
    }

    fn read_image(&mut self) -> ImageResult<DecodingResult> {
        let mut data = vec![0 as u8; (self.width*self.height*3*self.bytewidth()) as usize];
        match self.reader.read_exact(&mut data) {
            Ok(_) => {},
            Err(e) => return Err(ImageError::IoError(e)),
        };

        if self.bytewidth() == 1 {
            Ok(DecodingResult::U8(data))
        } else {
            let mut out = vec![0 as u16; (self.width*self.height*3) as usize];
            for (o, i) in out.chunks_mut(1).zip(data.chunks(2)) {
                o[0] = (i[0] as u16) << 8 | i[1] as u16;
            }
            Ok(DecodingResult::U16(out))
        }
    }
}

impl<R: Read> PPMDecoder<R> {
    fn bytewidth(&self) -> u32 {
        if self.maxwhite < 256 { 1 } else { 2 }
    }
}
<commit_msg>Use byteorder big-endian instead of hand-rolling<commit_after>use std::io::Read;
use std::io::BufReader;

use color::{ColorType};
use image::{DecodingResult, ImageDecoder, ImageResult, ImageError};
extern crate byteorder;
use self::byteorder::{BigEndian, ByteOrder};

/// PPM decoder
pub struct PPMDecoder<R> {
    reader: BufReader<R>,
    width: u32,
    height: u32,
    maxwhite: u32,
}

impl<R: Read> PPMDecoder<R> {
    /// Create a new decoder that decodes from the stream ```r```
    pub fn new(r: R) -> ImageResult<PPMDecoder<R>> {
        let mut buf = BufReader::new(r);
        try!(PPMDecoder::read_next_string(&mut buf)); // Skip P6
        let width = try!(PPMDecoder::read_next_u32(&mut buf));
        let height = try!(PPMDecoder::read_next_u32(&mut buf));
        let maxwhite = try!(PPMDecoder::read_next_u32(&mut buf));
        Ok(PPMDecoder {
            reader: buf,
            width: width,
            height: height,
            maxwhite: maxwhite,
        })
    }

  fn read_next_string(reader: &mut BufReader<R>) -> ImageResult<String> {
      let mut bytes = Vec::new();
      loop {
          let mut buffer: [u8;1] = [0];
          try!(reader.read_exact(&mut buffer));
          match buffer[0] {
              b'\n' | b' ' | b'\r' => {
                  if bytes.len() > 0 {
                    break // We're done as we already have some content
                  }
              },
              _ => {
                  bytes.push(buffer[0]);
              },
          }
      }

      match String::from_utf8(bytes) {
          Ok(s) => Ok(s),
          Err(_) => Err(ImageError::FormatError("Couldn't read preamble".to_string())),
      }
  }

  fn read_next_u32(reader: &mut BufReader<R>) -> ImageResult<u32> {
      let s = try!(PPMDecoder::read_next_string(reader));
      match s.parse::<u32>() {
          Ok(v) => Ok(v),
          Err(_) => Err(ImageError::FormatError("Couldn't read preamble".to_string())),
      }
  }
}

impl<R: Read> ImageDecoder for PPMDecoder<R> {
    fn dimensions(&mut self) -> ImageResult<(u32, u32)> {
        Ok((self.width, self.height))
    }

    fn colortype(&mut self) -> ImageResult<ColorType> {
        match self.bytewidth() {
            1 => Ok(ColorType::RGB(8)),
            2 => Ok(ColorType::RGB(16)),
            _ => Err(ImageError::FormatError("Don't know how to decode PPM with more than 16 bits".to_string())),
        }
    }

    fn row_len(&mut self) -> ImageResult<usize> {
        Ok((self.width*3*self.bytewidth()) as usize)
    }

    fn read_scanline(&mut self, _buf: &mut [u8]) -> ImageResult<u32> {
        unimplemented!();
    }

    fn read_image(&mut self) -> ImageResult<DecodingResult> {
        let mut data = vec![0 as u8; (self.width*self.height*3*self.bytewidth()) as usize];
        match self.reader.read_exact(&mut data) {
            Ok(_) => {},
            Err(e) => return Err(ImageError::IoError(e)),
        };

        if self.bytewidth() == 1 {
            Ok(DecodingResult::U8(data))
        } else {
            let mut out = vec![0 as u16; (self.width*self.height*3) as usize];
            for (o, i) in out.chunks_mut(1).zip(data.chunks(2)) {
                o[0] = BigEndian::read_u16(i);
            }
            Ok(DecodingResult::U16(out))
        }
    }
}

impl<R: Read> PPMDecoder<R> {
    fn bytewidth(&self) -> u32 {
        if self.maxwhite < 256 { 1 } else { 2 }
    }
}
<|endoftext|>


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

use device::dev;
use a = device::attrib;

pub type MaterialHandle = int;  //placeholder
pub type VertexCount = u16;
pub type ElementCount = u16;

/// Vertex attribute descriptor, goes into the vertex shader input
#[deriving(Clone, Show)]
pub struct Attribute {
    pub buffer: super::BufferHandle, // vertex buffer to contain the data
    pub elem_count: a::Count,   // number of elements per vertex
    pub elem_type: a::Type,     // type of a single element
    pub offset: a::Offset,      // offset in bytes to the first vertex
    pub stride: a::Stride,      // stride in bytes between consecutive vertices
    pub name: String,           // a name to match the shader input
}

#[deriving(Clone, Show)]
pub enum PolygonType {
    Point,
    Line,
    LineStrip,
    TriangleList,
    TriangleStrip,
    //Quad,
}

/// Mesh descriptor, as a collection of attributes
#[deriving(Clone, Show)]
pub struct Mesh {
    pub poly_type: PolygonType,
    pub num_vertices: VertexCount,
    pub attributes: Vec<Attribute>,
}

impl Mesh {
    pub fn new(nv: VertexCount) -> Mesh {
        Mesh {
            poly_type: TriangleList,
            num_vertices: nv,
            attributes: Vec::new(),
        }
    }

    pub fn embed(&mut self, mut builder: Builder) {
        builder.finalize();
        self.attributes.push_all(builder.attributes.as_slice());
    }
}

pub enum ComponentType {
    U8,
    U8n,
    U8f,
    I8,
    I8n,
    I8f,
    U16,
    U16n,
    U16f,
    I16,
    I16n,
    I16f,
    U32,
    U32n,
    U32f,
    I32,
    I32n,
    I32f,
    F16,
    F32,
    F64,
    F64d,
}

impl ComponentType {
    pub fn decode(&self) -> (u8, a::Type) {
        match *self {
            U8     => (1, a::Int(a::IntRaw,        a::U8,  a::Unsigned)),
            U8n    => (1, a::Int(a::IntNormalized, a::U8,  a::Unsigned)),
            U8f    => (1, a::Int(a::IntAsFloat,    a::U8,  a::Unsigned)),
            I8     => (1, a::Int(a::IntRaw,        a::U8,  a::Signed)),
            I8n    => (1, a::Int(a::IntNormalized, a::U8,  a::Signed)),
            I8f    => (1, a::Int(a::IntAsFloat,    a::U8,  a::Signed)),
            U16    => (2, a::Int(a::IntRaw,        a::U16, a::Unsigned)),
            U16n   => (2, a::Int(a::IntNormalized, a::U16, a::Unsigned)),
            U16f   => (2, a::Int(a::IntAsFloat,    a::U16, a::Unsigned)),
            I16    => (2, a::Int(a::IntRaw,        a::U16, a::Signed)),
            I16n   => (2, a::Int(a::IntNormalized, a::U16, a::Signed)),
            I16f   => (2, a::Int(a::IntAsFloat,    a::U16, a::Signed)),
            U32    => (4, a::Int(a::IntRaw,        a::U32, a::Unsigned)),
            U32n   => (4, a::Int(a::IntNormalized, a::U32, a::Unsigned)),
            U32f   => (4, a::Int(a::IntAsFloat,    a::U32, a::Unsigned)),
            I32    => (4, a::Int(a::IntRaw,        a::U32, a::Signed)),
            I32n   => (4, a::Int(a::IntNormalized, a::U32, a::Signed)),
            I32f   => (4, a::Int(a::IntAsFloat,    a::U32, a::Signed)),
            F16    => (2, a::Float(a::FloatDefault,   a::F16)),
            F32    => (4, a::Float(a::FloatDefault,   a::F32)),
            F64    => (8, a::Float(a::FloatDefault,   a::F64)),
            F64d   => (8, a::Float(a::FloatPrecision, a::F64)),
        }
    }
}

/// A helper class to populate Mesh attributes
pub struct Builder {
    buffer: super::BufferHandle,
    offset: a::Offset,
    attributes: Vec<Attribute>,
}

impl Builder {
    pub fn new(handle: super::BufferHandle) -> Builder {
        Builder {
            buffer: handle,
            offset: 0,
            attributes: Vec::new(),
        }
    }

    pub fn add(mut self, name: &str, count: a::Count, format: ComponentType) -> Builder {
        let (size, e_type) = format.decode();
        self.attributes.push(Attribute {
            buffer: self.buffer,
            elem_count: count,
            elem_type: e_type,
            offset: self.offset,
            stride: 0,
            name: name.to_string(),
        });
        self.offset += (count as a::Offset) * (size as a::Offset);
        self
    }

    fn finalize(&mut self) {
        for at in self.attributes.mut_iter() {
            at.stride = self.offset as a::Stride;
        }
    }

    pub fn complete(mut self, nv: VertexCount) -> Mesh {
        self.finalize();
        Mesh {
            poly_type: TriangleList,
            num_vertices: nv,
            attributes: self.attributes,
        }
    }
}

#[deriving(Clone, Show)]
pub enum Slice  {
    VertexSlice(VertexCount, VertexCount),
    IndexSlice(dev::Buffer, ElementCount, ElementCount),
}

/// Slice descriptor with an assigned material
#[deriving(Clone, Show)]
pub struct SubMesh {
    pub mesh: Mesh,
    pub material: MaterialHandle,
    pub slice: Slice,
}
<commit_msg>Follow Rust guidelines for naming and add documentation<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use device::dev;
use a = device::attrib;

pub type MaterialHandle = int;  //placeholder
pub type VertexCount = u16;
pub type ElementCount = u16;

/// Vertex attribute descriptor, goes into the vertex shader input
#[deriving(Clone, Show)]
pub struct Attribute {
    pub buffer: super::BufferHandle, // vertex buffer to contain the data
    pub elem_count: a::Count,   // number of elements per vertex
    pub elem_type: a::Type,     // type of a single element
    pub offset: a::Offset,      // offset in bytes to the first vertex
    pub stride: a::Stride,      // stride in bytes between consecutive vertices
    pub name: String,           // a name to match the shader input
}

#[deriving(Clone, Show)]
pub enum PolygonType {
    Point,
    Line,
    LineStrip,
    TriangleList,
    TriangleStrip,
    //Quad,
}

/// Mesh descriptor, as a collection of attributes
#[deriving(Clone, Show)]
pub struct Mesh {
    pub poly_type: PolygonType,
    pub num_vertices: VertexCount,
    pub attributes: Vec<Attribute>,
}

impl Mesh {
    pub fn new(nv: VertexCount) -> Mesh {
        Mesh {
            poly_type: TriangleList,
            num_vertices: nv,
            attributes: Vec::new(),
        }
    }

    pub fn embed(&mut self, mut builder: Builder) {
        builder.finalize();
        self.attributes.push_all(builder.attributes.as_slice());
    }
}

/// The numeric type of a vertex's components.
pub enum ComponentType {
    /// An 8-bit unsigned integer component.
    U8,
    /// An 8-bit unsigned integer component normalized to `[0, 1]`.
    U8N,
    /// An 8-bit unsigned integer component that is converted to a 32-bit float
    /// at runtime by the hardware.
    U8F,
    /// An 8-bit signed integer component.
    I8,
    /// An 8-bit signed integer component normalized to `[-1, 1]`.
    I8N,
    /// An 8-bit signed integer component that is converted to a 32-bit float at
    /// runtime by the hardware.
    I8F,
    /// A 16-bit unsigned integer component.
    U16,
    /// A 16-bit unsigned integer component normalized to `[-1, 1]`.
    U16N,
    /// A 16-bit unsigned integer component that is converted to a 32-bit float
    /// at runtime by the hardware.
    U16F,
    /// A 16-bit signed integer component.
    I16,
    /// A 16-bit signed integer component normalized to `[-1, 1]`.
    I16N,
    /// A 16-bit signed integer component that is converted to a 32-bit float at
    /// runtime by the hardware.
    I16F,
    /// A 32-bit unsigned integer component.
    U32,
    /// A 32-bit unsigned integer component normalized to `[-1, 1]`.
    U32N,
    /// A 32-bit unsigned integer component that is converted to a 32-bit float
    /// at runtime by the hardware.
    U32F,
    /// A 32-bit signed integer component.
    I32,
    /// A 32-bit signed integer component normalized to `[-1, 1]`.
    I32N,
    /// A 32-bit signed integer component that is converted to a 32-bit float at
    /// runtime by the hardware.
    I32F,
    /// A 16-bit (half precision) floating point component that is converted to
    /// a 32-bit float at runtime by the hardware.
    F16,
    /// A 32-bit (single precision) floating point component.
    F32,
    /// A 64-bit (double precision) floating point componentthat is converted to
    /// a 32-bit float at runtime by the hardware.
    F64,
    /// A 64-bit (double precision) floating point component.
    F64P,
}

impl ComponentType {
    pub fn decode(&self) -> (u8, a::Type) {
        match *self {
            U8     => (1, a::Int(a::IntRaw,        a::U8,  a::Unsigned)),
            U8N    => (1, a::Int(a::IntNormalized, a::U8,  a::Unsigned)),
            U8F    => (1, a::Int(a::IntAsFloat,    a::U8,  a::Unsigned)),
            I8     => (1, a::Int(a::IntRaw,        a::U8,  a::Signed)),
            I8N    => (1, a::Int(a::IntNormalized, a::U8,  a::Signed)),
            I8F    => (1, a::Int(a::IntAsFloat,    a::U8,  a::Signed)),
            U16    => (2, a::Int(a::IntRaw,        a::U16, a::Unsigned)),
            U16N   => (2, a::Int(a::IntNormalized, a::U16, a::Unsigned)),
            U16F   => (2, a::Int(a::IntAsFloat,    a::U16, a::Unsigned)),
            I16    => (2, a::Int(a::IntRaw,        a::U16, a::Signed)),
            I16N   => (2, a::Int(a::IntNormalized, a::U16, a::Signed)),
            I16F   => (2, a::Int(a::IntAsFloat,    a::U16, a::Signed)),
            U32    => (4, a::Int(a::IntRaw,        a::U32, a::Unsigned)),
            U32N   => (4, a::Int(a::IntNormalized, a::U32, a::Unsigned)),
            U32F   => (4, a::Int(a::IntAsFloat,    a::U32, a::Unsigned)),
            I32    => (4, a::Int(a::IntRaw,        a::U32, a::Signed)),
            I32N   => (4, a::Int(a::IntNormalized, a::U32, a::Signed)),
            I32F   => (4, a::Int(a::IntAsFloat,    a::U32, a::Signed)),
            F16    => (2, a::Float(a::FloatDefault,   a::F16)),
            F32    => (4, a::Float(a::FloatDefault,   a::F32)),
            F64    => (8, a::Float(a::FloatDefault,   a::F64)),
            F64P   => (8, a::Float(a::FloatPrecision, a::F64)),
        }
    }
}

/// A helper class to populate Mesh attributes
pub struct Builder {
    buffer: super::BufferHandle,
    offset: a::Offset,
    attributes: Vec<Attribute>,
}

impl Builder {
    pub fn new(handle: super::BufferHandle) -> Builder {
        Builder {
            buffer: handle,
            offset: 0,
            attributes: Vec::new(),
        }
    }

    pub fn add(mut self, name: &str, count: a::Count, format: ComponentType) -> Builder {
        let (size, e_type) = format.decode();
        self.attributes.push(Attribute {
            buffer: self.buffer,
            elem_count: count,
            elem_type: e_type,
            offset: self.offset,
            stride: 0,
            name: name.to_string(),
        });
        self.offset += (count as a::Offset) * (size as a::Offset);
        self
    }

    fn finalize(&mut self) {
        for at in self.attributes.mut_iter() {
            at.stride = self.offset as a::Stride;
        }
    }

    pub fn complete(mut self, nv: VertexCount) -> Mesh {
        self.finalize();
        Mesh {
            poly_type: TriangleList,
            num_vertices: nv,
            attributes: self.attributes,
        }
    }
}

#[deriving(Clone, Show)]
pub enum Slice  {
    VertexSlice(VertexCount, VertexCount),
    IndexSlice(dev::Buffer, ElementCount, ElementCount),
}

/// Slice descriptor with an assigned material
#[deriving(Clone, Show)]
pub struct SubMesh {
    pub mesh: Mesh,
    pub material: MaterialHandle,
    pub slice: Slice,
}
<|endoftext|>


<commit_before>use satyrs::cnf::CNF;

/**
 * DPLL Algorithm implementation
 * Start by cloning the cnf so we can modify the HashMap
 * Clone might be slow, consider a faster option
 */
#[allow(non_snake_case)]
pub fn DPLL( cnf : &CNF ) -> bool {
    let cnf_clone = cnf.clone();
    println!("{:?}",cnf_clone);
    true
}
<commit_msg>Not sure<commit_after>use satyrs::cnf::CNF;

/**
 * DPLL Algorithm implementation
 * Start by cloning the cnf so we can modify the HashMap
 * Clone might be slow, consider a faster option
 */
#[allow(non_snake_case)]
pub fn DPLL( cnf : &CNF ) -> bool {
    let cnf_clone = cnf.clone();
    // If consistent set of literals, return True
    // If contains an empty clause return False
    // For every unit-clause, unit-propogate
    // For ever pure literal, pure literal assign
    // Choose literal L for split
    // Return DPLL with L and -L
    println!("{:?}",cnf_clone);
    true
}
<|endoftext|>