<commit_before>use std::mem;
use std::kinds::marker;

/// The implementation of this splay tree is largely based on the c code at:
///     ftp://ftp.cs.cmu.edu/usr/ftp/usr/sleator/splaying/top-down-splay.c
/// This version of splaying is a top-down splay operation.
#[deriving(Clone)]
pub struct SplayMap<K, V> {
    root: Option<Box<Node<K, V>>>,
    size: uint,
    marker: marker::NoSync, // lookups mutate the tree
}

#[deriving(Clone)]
struct Node<K, V> {
    key: K,
    value: V,
    left: Option<Box<Node<K, V>>>,
    right: Option<Box<Node<K, V>>>,
}

/// Performs a top-down splay operation on a tree rooted at `node`. This will
/// modify the pointer to contain the new root of the tree once the splay
/// operation is done. When finished, if `key` is in the tree, it will be at the
/// root. Otherwise the closest key to the specified key will be at the root.
fn splay<K: Ord, V>(key: &K, node: &mut Box<Node<K, V>>) {
    let mut newleft = None;
    let mut newright = None;

    // Eplicitly grab a new scope so the loans on newleft/newright are
    // terminated before we move out of them.
    {
        // Yes, these are backwards, that's intentional.
        let mut l = &mut newright;
        let mut r = &mut newleft;

        loop {
            match key.cmp(&node.key) {
                // Found it, yay!
                Equal => { break }

                Less => {
                    let mut left = match node.pop_left() {
                        Some(left) => left, None => break
                    };
                    // rotate this node right if necessary
                    if key.cmp(&left.key) == Less {
                        // A bit odd, but avoids drop glue
                        mem::swap(&mut node.left, &mut left.right);
                        mem::swap(&mut left, node);
                        let none = mem::replace(&mut node.right, Some(left));
                        match mem::replace(&mut node.left, none) {
                            Some(l) => { left = l; }
                            None    => { break }
                        }
                    }

                    *r = Some(mem::replace(node, left));
                    let tmp = r;
                    r = &mut tmp.as_mut().unwrap().left;
                }

                // If you look closely, you may have seen some similar code
                // before
                Greater => {
                    match node.pop_right() {
                        None => { break }
                        // rotate left if necessary
                        Some(mut right) => {
                            if key.cmp(&right.key) == Greater {
                                mem::swap(&mut node.right, &mut right.left);
                                mem::swap(&mut right, node);
                                let none = mem::replace(&mut node.left,
                                                         Some(right));
                                match mem::replace(&mut node.right, none) {
                                    Some(r) => { right = r; }
                                    None    => { break }
                                }
                            }
                            *l = Some(mem::replace(node, right));
                            let tmp = l;
                            l = &mut tmp.as_mut().unwrap().right;
                        }
                    }
                }
            }
        }

        mem::swap(l, &mut node.left);
        mem::swap(r, &mut node.right);
    }

    node.left = newright;
    node.right = newleft;
}

impl<K: Ord, V> SplayMap<K, V> {
    pub fn new() -> SplayMap<K, V> {
        SplayMap{ root: None, size: 0, marker: marker::NoSync }
    }

    /// Similar to `find`, but panics if the key is not present in the map
    pub fn get(&self, k: &K) -> &V {
        match self.find(k) {
            Some(v) => v,
            None => panic!("key not present in SplayMap"),
        }
    }

    /// Similar to `find_mut`, but panics if the key is not present in the map
    pub fn get_mut(&mut self, k: &K) -> &mut V {
        match self.find_mut(k) {
            Some(v) => v,
            None => panic!("key not present in SplayMap"),
        }
    }

    /// Moves all values out of this map, transferring ownership to the given
    /// iterator.
    pub fn into_iter(&mut self) -> IntoIter<K, V> {
        IntoIter { cur: self.root.take(), remaining: self.size }
    }

    pub fn len(&self) -> uint { self.size }
    pub fn is_empty(&self) -> bool { self.len() == 0 }

    /// Clears the tree in O(1) extra space (including the stack). This is
    /// necessary to prevent stack exhaustion with extremely large trees.
    pub fn clear(&mut self) {
        let mut iter = IntoIter { cur: self.root.take(),
                                      remaining: self.size };
        for _ in iter {
            // ignore, drop the values (and the node)
        }
        self.size = 0;
    }

    /// Return true if the map contains a value for the specified key
    pub fn contains_key(&self, key: &K) -> bool {
        self.find(key).is_some()
    }

    /// Return a reference to the value corresponding to the key
    pub fn find(&self, key: &K) -> Option<&V> {
        // Splay trees are self-modifying, so they can't exactly operate with
        // the immutable self given by the Map interface for this method. It can
        // be guaranteed, however, that the callers of this method are not
        // modifying the tree, they may just be rotating it. Each node is a
        // pointer on the heap, so we know that none of the pointers inside
        // these nodes (the value returned from this function) will be moving.
        //
        // With this in mind, we can unsafely use a mutable version of this tree
        // to invoke the splay operation and return a pointer to the inside of
        // one of the nodes (the pointer won't be deallocated or moved).
        //
        // However I'm not entirely sure whether this works with iteration or
        // not. Arbitrary lookups can occur during iteration, and during
        // iteration there's some form of "stack" remembering the nodes that
        // need to get visited. I don't believe that it's safe to allow lookups
        // while the tree is being iterated. Right now there are no iterators
        // exposed on this splay tree implementation, and more thought would be
        // required if there were.
        unsafe {
            let this = mem::transmute::<&_, &mut SplayMap<K, V>>(self);
            this.find_mut(key).map(|x| &*x)
        }
    }

    /// Return a mutable reference to the value corresponding to the key
    pub fn find_mut(&mut self, key: &K) -> Option<&mut V> {
        match self.root {
            None => { return None; }
            Some(ref mut root) => {
                splay(key, root);
                if *key == root.key {
                    return Some(&mut root.value);
                }
                return None;
            }
        }
    }

    /// Insert a key-value pair into the map. An existing value for a
    /// key is replaced by the new value. Return true if the key did
    /// not already exist in the map.
    pub fn insert(&mut self, key: K, value: V) -> bool {
        self.swap(key, value).is_none()
    }

    /// Insert a key-value pair from the map. If the key already had a value
    /// present in the map, that value is returned. Otherwise None is returned.
    pub fn swap(&mut self, key: K, value: V) -> Option<V> {
        match self.root {
            None => self.root = Some(Node::new(key, value, None, None)),
            Some(ref mut root) => {
                splay(&key, root);

                match key.cmp(&root.key) {
                    Equal => {
                        let old = mem::replace(&mut root.value, value);
                        return Some(old);
                    }
                    /* TODO: would unsafety help perf here? */
                    Less => {
                        let left = root.pop_left();
                        let new = Node::new(key, value, left, None);
                        let prev = mem::replace(root, new);
                        root.right = Some(prev);
                    }
                    Greater => {
                        let right = root.pop_right();
                        let new = Node::new(key, value, None, right);
                        let prev = mem::replace(root, new);
                        root.left = Some(prev);
                    }
                }
            }
        }
        self.size += 1;
        return None;
    }

    /// Remove a key-value pair from the map. Return true if the key
    /// was present in the map, otherwise false.
    pub fn remove(&mut self, key: &K) -> bool {
        self.pop(key).is_some()
    }

    /// Removes a key from the map, returning the value at the key if the key
    /// was previously in the map.
    pub fn pop(&mut self, key: &K) -> Option<V> {
        match self.root {
            None => { return None; }
            Some(ref mut root) => {
                splay(key, root);
                if *key != root.key { return None }
            }
        }

        // TODO: Extra storage of None isn't necessary
        let (value, left, right) = match self.root.take().unwrap() {
            box Node {left, right, value, ..} => (value, left, right)
        };

        match left {
            None => self.root = right,
            Some(node) => {
                let mut node = node;
                splay(key, &mut node);
                node.right = right;
                self.root = Some(node);
            }
        }

        self.size -= 1;
        return Some(value);
    }
}

impl<K, V> Node<K, V> {
    fn new(k: K, v: V,
           l: Option<Box<Node<K, V>>>,
           r: Option<Box<Node<K, V>>>) -> Box<Node<K, V>> {
        box Node{ key: k, value: v, left: l, right: r }
    }

    #[inline(always)]
    fn pop_left(&mut self) -> Option<Box<Node<K, V>>> {
        mem::replace(&mut self.left, None)
    }

    #[inline(always)]
    fn pop_right(&mut self) -> Option<Box<Node<K, V>>> {
        mem::replace(&mut self.right, None)
    }
}

pub struct IntoIter<K, V> {
    cur: Option<Box<Node<K, V>>>,
    remaining: uint,
}

impl<K, V> Iterator<(K, V)> for IntoIter<K, V> {
    fn next(&mut self) -> Option<(K, V)> {
        match self.cur.take() {
            None => None,
            Some(cur) => {
                let mut cur = cur;
                loop {
                    match cur.pop_left() {
                        Some(node) => {
                            let mut node = node;
                            cur.left = node.pop_right();
                            node.right = Some(cur);
                            cur = node;
                        }

                        None => {
                            self.cur = cur.pop_right();
                            // left and right fields are both None
                            let node = *cur;
                            let Node { key, value, .. } = node;
                            self.remaining -= 1;
                            return Some((key, value));
                        }
                    }
                }
            }
        }
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        (self.remaining, Some(self.remaining))
    }
}

impl<K, V> DoubleEndedIterator<(K, V)> for IntoIter<K, V> {
    // Pretty much the same as the above code, but with left replaced with right
    // and vice-versa.
    fn next_back(&mut self) -> Option<(K, V)> {
        match self.cur.take() {
            None => None,
            Some(cur) => {
                let mut cur = cur;
                loop {
                    match cur.pop_right() {
                        Some(node) => {
                            let mut node = node;
                            cur.right = node.pop_left();
                            node.left = Some(cur);
                            cur = node;
                        }

                        None => {
                            self.cur = cur.pop_left();
                            // left and right fields are both None
                            let node = *cur;
                            let Node { key, value, .. } = node;
                            self.remaining -= 1;
                            return Some((key, value));
                        }
                    }
                }
            }
        }
    }
}

#[unsafe_destructor]
impl<K: Ord, V> Drop for SplayMap<K, V> {
    fn drop(&mut self) {
        // Be sure to not recurse too deep on destruction
        self.clear();
    }
}
<commit_msg>Less indentation<commit_after>use std::mem;
use std::kinds::marker;

/// The implementation of this splay tree is largely based on the c code at:
///     ftp://ftp.cs.cmu.edu/usr/ftp/usr/sleator/splaying/top-down-splay.c
/// This version of splaying is a top-down splay operation.
#[deriving(Clone)]
pub struct SplayMap<K, V> {
    root: Option<Box<Node<K, V>>>,
    size: uint,
    marker: marker::NoSync, // lookups mutate the tree
}

#[deriving(Clone)]
struct Node<K, V> {
    key: K,
    value: V,
    left: Option<Box<Node<K, V>>>,
    right: Option<Box<Node<K, V>>>,
}

/// Performs a top-down splay operation on a tree rooted at `node`. This will
/// modify the pointer to contain the new root of the tree once the splay
/// operation is done. When finished, if `key` is in the tree, it will be at the
/// root. Otherwise the closest key to the specified key will be at the root.
fn splay<K: Ord, V>(key: &K, node: &mut Box<Node<K, V>>) {
    let mut newleft = None;
    let mut newright = None;

    // Eplicitly grab a new scope so the loans on newleft/newright are
    // terminated before we move out of them.
    {
        // Yes, these are backwards, that's intentional.
        let mut l = &mut newright;
        let mut r = &mut newleft;

        loop {
            match key.cmp(&node.key) {
                // Found it, yay!
                Equal => { break }

                Less => {
                    let mut left = match node.pop_left() {
                        Some(left) => left, None => break
                    };
                    // rotate this node right if necessary
                    if key.cmp(&left.key) == Less {
                        // A bit odd, but avoids drop glue
                        mem::swap(&mut node.left, &mut left.right);
                        mem::swap(&mut left, node);
                        let none = mem::replace(&mut node.right, Some(left));
                        match mem::replace(&mut node.left, none) {
                            Some(l) => { left = l; }
                            None    => { break }
                        }
                    }

                    *r = Some(mem::replace(node, left));
                    let tmp = r;
                    r = &mut tmp.as_mut().unwrap().left;
                }

                // If you look closely, you may have seen some similar code
                // before
                Greater => {
                    match node.pop_right() {
                        None => { break }
                        // rotate left if necessary
                        Some(mut right) => {
                            if key.cmp(&right.key) == Greater {
                                mem::swap(&mut node.right, &mut right.left);
                                mem::swap(&mut right, node);
                                let none = mem::replace(&mut node.left,
                                                         Some(right));
                                match mem::replace(&mut node.right, none) {
                                    Some(r) => { right = r; }
                                    None    => { break }
                                }
                            }
                            *l = Some(mem::replace(node, right));
                            let tmp = l;
                            l = &mut tmp.as_mut().unwrap().right;
                        }
                    }
                }
            }
        }

        mem::swap(l, &mut node.left);
        mem::swap(r, &mut node.right);
    }

    node.left = newright;
    node.right = newleft;
}

impl<K: Ord, V> SplayMap<K, V> {
    pub fn new() -> SplayMap<K, V> {
        SplayMap{ root: None, size: 0, marker: marker::NoSync }
    }

    /// Similar to `find`, but panics if the key is not present in the map
    pub fn get(&self, k: &K) -> &V {
        match self.find(k) {
            Some(v) => v,
            None => panic!("key not present in SplayMap"),
        }
    }

    /// Similar to `find_mut`, but panics if the key is not present in the map
    pub fn get_mut(&mut self, k: &K) -> &mut V {
        match self.find_mut(k) {
            Some(v) => v,
            None => panic!("key not present in SplayMap"),
        }
    }

    /// Moves all values out of this map, transferring ownership to the given
    /// iterator.
    pub fn into_iter(&mut self) -> IntoIter<K, V> {
        IntoIter { cur: self.root.take(), remaining: self.size }
    }

    pub fn len(&self) -> uint { self.size }
    pub fn is_empty(&self) -> bool { self.len() == 0 }

    /// Clears the tree in O(1) extra space (including the stack). This is
    /// necessary to prevent stack exhaustion with extremely large trees.
    pub fn clear(&mut self) {
        let mut iter = IntoIter { cur: self.root.take(),
                                      remaining: self.size };
        for _ in iter {
            // ignore, drop the values (and the node)
        }
        self.size = 0;
    }

    /// Return true if the map contains a value for the specified key
    pub fn contains_key(&self, key: &K) -> bool {
        self.find(key).is_some()
    }

    /// Return a reference to the value corresponding to the key
    pub fn find(&self, key: &K) -> Option<&V> {
        // Splay trees are self-modifying, so they can't exactly operate with
        // the immutable self given by the Map interface for this method. It can
        // be guaranteed, however, that the callers of this method are not
        // modifying the tree, they may just be rotating it. Each node is a
        // pointer on the heap, so we know that none of the pointers inside
        // these nodes (the value returned from this function) will be moving.
        //
        // With this in mind, we can unsafely use a mutable version of this tree
        // to invoke the splay operation and return a pointer to the inside of
        // one of the nodes (the pointer won't be deallocated or moved).
        //
        // However I'm not entirely sure whether this works with iteration or
        // not. Arbitrary lookups can occur during iteration, and during
        // iteration there's some form of "stack" remembering the nodes that
        // need to get visited. I don't believe that it's safe to allow lookups
        // while the tree is being iterated. Right now there are no iterators
        // exposed on this splay tree implementation, and more thought would be
        // required if there were.
        unsafe {
            let this = mem::transmute::<&_, &mut SplayMap<K, V>>(self);
            this.find_mut(key).map(|x| &*x)
        }
    }

    /// Return a mutable reference to the value corresponding to the key
    pub fn find_mut(&mut self, key: &K) -> Option<&mut V> {
        match self.root {
            None => { return None; }
            Some(ref mut root) => {
                splay(key, root);
                if *key == root.key {
                    return Some(&mut root.value);
                }
                return None;
            }
        }
    }

    /// Insert a key-value pair into the map. An existing value for a
    /// key is replaced by the new value. Return true if the key did
    /// not already exist in the map.
    pub fn insert(&mut self, key: K, value: V) -> bool {
        self.swap(key, value).is_none()
    }

    /// Insert a key-value pair from the map. If the key already had a value
    /// present in the map, that value is returned. Otherwise None is returned.
    pub fn swap(&mut self, key: K, value: V) -> Option<V> {
        match self.root {
            None => self.root = Some(Node::new(key, value, None, None)),
            Some(ref mut root) => {
                splay(&key, root);

                match key.cmp(&root.key) {
                    Equal => {
                        let old = mem::replace(&mut root.value, value);
                        return Some(old);
                    }
                    /* TODO: would unsafety help perf here? */
                    Less => {
                        let left = root.pop_left();
                        let new = Node::new(key, value, left, None);
                        let prev = mem::replace(root, new);
                        root.right = Some(prev);
                    }
                    Greater => {
                        let right = root.pop_right();
                        let new = Node::new(key, value, None, right);
                        let prev = mem::replace(root, new);
                        root.left = Some(prev);
                    }
                }
            }
        }
        self.size += 1;
        return None;
    }

    /// Remove a key-value pair from the map. Return true if the key
    /// was present in the map, otherwise false.
    pub fn remove(&mut self, key: &K) -> bool {
        self.pop(key).is_some()
    }

    /// Removes a key from the map, returning the value at the key if the key
    /// was previously in the map.
    pub fn pop(&mut self, key: &K) -> Option<V> {
        match self.root {
            None => { return None; }
            Some(ref mut root) => {
                splay(key, root);
                if *key != root.key { return None }
            }
        }

        // TODO: Extra storage of None isn't necessary
        let (value, left, right) = match self.root.take().unwrap() {
            box Node {left, right, value, ..} => (value, left, right)
        };

        match left {
            None => self.root = right,
            Some(node) => {
                let mut node = node;
                splay(key, &mut node);
                node.right = right;
                self.root = Some(node);
            }
        }

        self.size -= 1;
        return Some(value);
    }
}

impl<K, V> Node<K, V> {
    fn new(k: K, v: V,
           l: Option<Box<Node<K, V>>>,
           r: Option<Box<Node<K, V>>>) -> Box<Node<K, V>> {
        box Node{ key: k, value: v, left: l, right: r }
    }

    #[inline(always)]
    fn pop_left(&mut self) -> Option<Box<Node<K, V>>> {
        mem::replace(&mut self.left, None)
    }

    #[inline(always)]
    fn pop_right(&mut self) -> Option<Box<Node<K, V>>> {
        mem::replace(&mut self.right, None)
    }
}

pub struct IntoIter<K, V> {
    cur: Option<Box<Node<K, V>>>,
    remaining: uint,
}

impl<K, V> Iterator<(K, V)> for IntoIter<K, V> {
    fn next(&mut self) -> Option<(K, V)> {
        let mut cur = match self.cur.take() {
            Some(cur) => cur,
            None => return None,
        };
        loop {
            match cur.pop_left() {
                Some(node) => {
                    let mut node = node;
                    cur.left = node.pop_right();
                    node.right = Some(cur);
                    cur = node;
                }

                None => {
                    self.cur = cur.pop_right();
                    // left and right fields are both None
                    let node = *cur;
                    let Node { key, value, .. } = node;
                    self.remaining -= 1;
                    return Some((key, value));
                }
            }
        }
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        (self.remaining, Some(self.remaining))
    }
}

impl<K, V> DoubleEndedIterator<(K, V)> for IntoIter<K, V> {
    // Pretty much the same as the above code, but with left replaced with right
    // and vice-versa.
    fn next_back(&mut self) -> Option<(K, V)> {
        let mut cur = match self.cur.take() {
            Some(cur) => cur,
            None => return None,
        };
        loop {
            match cur.pop_right() {
                Some(node) => {
                    let mut node = node;
                    cur.right = node.pop_left();
                    node.left = Some(cur);
                    cur = node;
                }

                None => {
                    self.cur = cur.pop_left();
                    // left and right fields are both None
                    let node = *cur;
                    let Node { key, value, .. } = node;
                    self.remaining -= 1;
                    return Some((key, value));
                }
            }
        }
    }
}

#[unsafe_destructor]
impl<K: Ord, V> Drop for SplayMap<K, V> {
    fn drop(&mut self) {
        // Be sure to not recurse too deep on destruction
        self.clear();
    }
}
<|endoftext|>


<commit_before>//! Raw un-exported bindings to miniz for encoding/decoding

use std::io;
use std::mem;
use std::io::IoResult;
use libc;

use {CompressionLevel, NoCompression};
use ffi;

pub struct EncoderWriter<W> {
    pub inner: Option<W>,
    stream: Stream,
    buf: Vec<u8>,
}

pub struct EncoderReader<R> {
    pub inner: R,
    stream: Stream,
    buf: Vec<u8>,
    pos: uint,
}

pub struct DecoderReader<R> {
    pub inner: R,
    stream: Stream,
    pos: uint,
    pub buf: Vec<u8>,
}

pub struct DecoderWriter<W> {
    pub inner: Option<W>,
    stream: Stream,
    buf: Vec<u8>,
}

enum Flavor { Deflate, Inflate }

struct Stream(ffi::mz_stream, Flavor);

impl<W: Writer> EncoderWriter<W> {
    pub fn new(w: W, level: CompressionLevel, raw: bool,
               buf: Vec<u8>) -> EncoderWriter<W> {
        EncoderWriter {
            inner: Some(w),
            stream: Stream::new(Deflate, raw, level),
            buf: buf,
        }
    }

    pub fn do_finish(&mut self) -> IoResult<()> {
        try!(self.stream.write([], ffi::MZ_FINISH, &mut self.buf,
                               self.inner.as_mut().unwrap(), ffi::mz_deflate));
        try!(self.inner.as_mut().unwrap().write(self.buf.as_slice()));
        self.buf.truncate(0);
        Ok(())
    }
}

impl<W: Writer> Writer for EncoderWriter<W> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.stream.write(buf, ffi::MZ_NO_FLUSH, &mut self.buf,
                          self.inner.as_mut().unwrap(), ffi::mz_deflate)
    }

    fn flush(&mut self) -> IoResult<()> {
        let inner = self.inner.as_mut().unwrap();
        try!(self.stream.write([], ffi::MZ_SYNC_FLUSH, &mut self.buf, inner,
                               ffi::mz_deflate));
        inner.flush()
    }
}

#[unsafe_destructor]
impl<W: Writer> Drop for EncoderWriter<W> {
    fn drop(&mut self) {
        match self.inner {
            Some(..) => { let _ = self.do_finish(); }
            None => {}
        }
    }
}

impl<R: Reader> EncoderReader<R> {
    pub fn new(w: R, level: CompressionLevel, raw: bool,
               buf: Vec<u8>) -> EncoderReader<R> {
        EncoderReader {
            inner: w,
            stream: Stream::new(Deflate, raw, level),
            buf: buf,
            pos: 0,
        }
    }
}

impl<R: Reader> Reader for EncoderReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.stream.read(buf, &mut self.buf, &mut self.pos,
                         &mut self.inner, ffi::mz_deflate)
    }
}

impl<R: Reader> DecoderReader<R> {
    pub fn new(r: R, raw: bool, buf: Vec<u8>) -> DecoderReader<R> {
        DecoderReader {
            inner: r,
            stream: Stream::new(Inflate, raw, NoCompression),
            pos: 0,
            buf: buf,
        }
    }
}

impl<R: Reader> Reader for DecoderReader<R> {
    fn read(&mut self, into: &mut [u8]) -> IoResult<uint> {
        self.stream.read(into, &mut self.buf, &mut self.pos,
                         &mut self.inner, ffi::mz_inflate)
    }
}

impl<W: Writer> DecoderWriter<W> {
    pub fn new(w: W, raw: bool, buf: Vec<u8>) -> DecoderWriter<W> {
        DecoderWriter {
            inner: Some(w),
            stream: Stream::new(Inflate, raw, NoCompression),
            buf: buf,
        }
    }

    pub fn do_finish(&mut self) -> IoResult<()> {
        try!(self.stream.write([], ffi::MZ_FINISH, &mut self.buf,
                               self.inner.as_mut().unwrap(), ffi::mz_inflate));
        try!(self.inner.as_mut().unwrap().write(self.buf.as_slice()));
        self.buf.truncate(0);
        Ok(())
    }
}

impl<W: Writer> Writer for DecoderWriter<W> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.stream.write(buf, ffi::MZ_NO_FLUSH, &mut self.buf,
                          self.inner.as_mut().unwrap(), ffi::mz_inflate)
    }

    fn flush(&mut self) -> IoResult<()> {
        let inner = self.inner.as_mut().unwrap();
        try!(self.stream.write([], ffi::MZ_SYNC_FLUSH, &mut self.buf, inner,
                               ffi::mz_inflate));
        inner.flush()
    }
}

impl Stream {
    fn new(kind: Flavor, raw: bool, level: CompressionLevel) -> Stream {
        let mut state: ffi::mz_stream = unsafe { mem::zeroed() };
        let ret = match kind {
            Deflate => unsafe {
                ffi::mz_deflateInit2(&mut state,
                                     level as libc::c_int,
                                     ffi::MZ_DEFLATED,
                                     if raw {
                                         -ffi::MZ_DEFAULT_WINDOW_BITS
                                     } else {
                                         ffi::MZ_DEFAULT_WINDOW_BITS
                                     },
                                     9,
                                     ffi::MZ_DEFAULT_STRATEGY)
            },
            Inflate => unsafe {
                ffi::mz_inflateInit2(&mut state,
                                     if raw {
                                         -ffi::MZ_DEFAULT_WINDOW_BITS
                                     } else {
                                         ffi::MZ_DEFAULT_WINDOW_BITS
                                     })
            }
        };
        assert_eq!(ret, 0);
        Stream(state, kind)
    }

    fn read<R: Reader>(&mut self, into: &mut [u8], buf: &mut Vec<u8>,
                       pos: &mut uint, reader: &mut R,
                       f: unsafe extern fn(*mut ffi::mz_stream,
                                           libc::c_int) -> libc::c_int)
                       -> IoResult<uint> {

        let cap = buf.capacity();
        let mut read = 0;
        let mut eof = false;
        while read < into.len() {
            if *pos == buf.len() {
                buf.truncate(0);
                match reader.push(cap, buf) {
                    Ok(..) => {}
                    Err(ref e) if e.kind == io::EndOfFile => eof = true,
                    Err(e) => return Err(e),
                }
                *pos = 0;
            }

            self.next_in = buf.slice_from(*pos).as_ptr();
            self.avail_in = (buf.len() - *pos) as libc::c_uint;
            self.next_out = into.slice_from_mut(read).as_mut_ptr();
            self.avail_out = (into.len() - read) as libc::c_uint;

            let before_out = self.total_out;
            let before_in = self.total_in;

            let flush = if eof {ffi::MZ_FINISH} else {ffi::MZ_NO_FLUSH};
            let ret = unsafe { f(&mut **self, flush) };
            read += (self.total_out - before_out) as uint;
            *pos += (self.total_in - before_in) as uint;

            match ret {
                ffi::MZ_OK => {}
                ffi::MZ_STREAM_END if read > 0 => break,
                ffi::MZ_STREAM_END => {
                    return Err(io::standard_error(io::EndOfFile))
                }
                ffi::MZ_BUF_ERROR => break,
                ffi::MZ_DATA_ERROR => {
                    return Err(io::standard_error(io::InvalidInput))
                }
                n => fail!("unexpected return {}", n),
            }
        }

        Ok(read)
    }

    fn write<W: Writer>(&mut self, mut buf: &[u8], flush: libc::c_int,
                        into: &mut Vec<u8>, writer: &mut W,
                        f: unsafe extern fn(*mut ffi::mz_stream,
                                            libc::c_int) -> libc::c_int)
                        -> IoResult<()> {
        let cap = into.capacity();
        while buf.len() > 0 || flush == ffi::MZ_FINISH {
            self.next_in = buf.as_ptr();
            self.avail_in = buf.len() as libc::c_uint;
            let cur_len = into.len();
            self.next_out = into.slice_from_mut(cur_len).as_mut_ptr();
            self.avail_out = (cap - cur_len) as libc::c_uint;

            let before_out = self.total_out;
            let before_in = self.total_in;

            let ret = unsafe {
                let ret = f(&mut **self, flush);
                into.set_len(cur_len + (self.total_out - before_out) as uint);
                ret
            };
            buf = buf.slice_from((self.total_in - before_in) as uint);

            if cap - cur_len == 0 || ret == ffi::MZ_BUF_ERROR {
                try!(writer.write(into.as_slice()));
                into.truncate(0);
            }
            match ret {
                ffi::MZ_OK => {},
                ffi::MZ_STREAM_END => return Ok(()),
                ffi::MZ_BUF_ERROR => {}
                n => fail!("unexpected return {}", n),
            }
        }

        Ok(())
    }
}

impl Deref<ffi::mz_stream> for Stream {
    fn deref<'a>(&'a self) -> &'a ffi::mz_stream {
        let Stream(ref inner, _) = *self; inner
    }
}

impl DerefMut<ffi::mz_stream> for Stream {
    fn deref_mut<'a>(&'a mut self) -> &'a mut ffi::mz_stream {
        let Stream(ref mut inner, _) = *self; inner
    }
}

impl Drop for Stream {
    fn drop(&mut self) {
        unsafe {
            match *self {
                Stream(ref mut s, Deflate) => ffi::mz_deflateEnd(s),
                Stream(ref mut s, Inflate) => ffi::mz_inflateEnd(s),
            };
        }
    }
}
<commit_msg>fail -> panic<commit_after>//! Raw un-exported bindings to miniz for encoding/decoding

use std::io;
use std::mem;
use std::io::IoResult;
use libc;

use {CompressionLevel, NoCompression};
use ffi;

pub struct EncoderWriter<W> {
    pub inner: Option<W>,
    stream: Stream,
    buf: Vec<u8>,
}

pub struct EncoderReader<R> {
    pub inner: R,
    stream: Stream,
    buf: Vec<u8>,
    pos: uint,
}

pub struct DecoderReader<R> {
    pub inner: R,
    stream: Stream,
    pos: uint,
    pub buf: Vec<u8>,
}

pub struct DecoderWriter<W> {
    pub inner: Option<W>,
    stream: Stream,
    buf: Vec<u8>,
}

enum Flavor { Deflate, Inflate }

struct Stream(ffi::mz_stream, Flavor);

impl<W: Writer> EncoderWriter<W> {
    pub fn new(w: W, level: CompressionLevel, raw: bool,
               buf: Vec<u8>) -> EncoderWriter<W> {
        EncoderWriter {
            inner: Some(w),
            stream: Stream::new(Deflate, raw, level),
            buf: buf,
        }
    }

    pub fn do_finish(&mut self) -> IoResult<()> {
        try!(self.stream.write([], ffi::MZ_FINISH, &mut self.buf,
                               self.inner.as_mut().unwrap(), ffi::mz_deflate));
        try!(self.inner.as_mut().unwrap().write(self.buf.as_slice()));
        self.buf.truncate(0);
        Ok(())
    }
}

impl<W: Writer> Writer for EncoderWriter<W> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.stream.write(buf, ffi::MZ_NO_FLUSH, &mut self.buf,
                          self.inner.as_mut().unwrap(), ffi::mz_deflate)
    }

    fn flush(&mut self) -> IoResult<()> {
        let inner = self.inner.as_mut().unwrap();
        try!(self.stream.write([], ffi::MZ_SYNC_FLUSH, &mut self.buf, inner,
                               ffi::mz_deflate));
        inner.flush()
    }
}

#[unsafe_destructor]
impl<W: Writer> Drop for EncoderWriter<W> {
    fn drop(&mut self) {
        match self.inner {
            Some(..) => { let _ = self.do_finish(); }
            None => {}
        }
    }
}

impl<R: Reader> EncoderReader<R> {
    pub fn new(w: R, level: CompressionLevel, raw: bool,
               buf: Vec<u8>) -> EncoderReader<R> {
        EncoderReader {
            inner: w,
            stream: Stream::new(Deflate, raw, level),
            buf: buf,
            pos: 0,
        }
    }
}

impl<R: Reader> Reader for EncoderReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.stream.read(buf, &mut self.buf, &mut self.pos,
                         &mut self.inner, ffi::mz_deflate)
    }
}

impl<R: Reader> DecoderReader<R> {
    pub fn new(r: R, raw: bool, buf: Vec<u8>) -> DecoderReader<R> {
        DecoderReader {
            inner: r,
            stream: Stream::new(Inflate, raw, NoCompression),
            pos: 0,
            buf: buf,
        }
    }
}

impl<R: Reader> Reader for DecoderReader<R> {
    fn read(&mut self, into: &mut [u8]) -> IoResult<uint> {
        self.stream.read(into, &mut self.buf, &mut self.pos,
                         &mut self.inner, ffi::mz_inflate)
    }
}

impl<W: Writer> DecoderWriter<W> {
    pub fn new(w: W, raw: bool, buf: Vec<u8>) -> DecoderWriter<W> {
        DecoderWriter {
            inner: Some(w),
            stream: Stream::new(Inflate, raw, NoCompression),
            buf: buf,
        }
    }

    pub fn do_finish(&mut self) -> IoResult<()> {
        try!(self.stream.write([], ffi::MZ_FINISH, &mut self.buf,
                               self.inner.as_mut().unwrap(), ffi::mz_inflate));
        try!(self.inner.as_mut().unwrap().write(self.buf.as_slice()));
        self.buf.truncate(0);
        Ok(())
    }
}

impl<W: Writer> Writer for DecoderWriter<W> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.stream.write(buf, ffi::MZ_NO_FLUSH, &mut self.buf,
                          self.inner.as_mut().unwrap(), ffi::mz_inflate)
    }

    fn flush(&mut self) -> IoResult<()> {
        let inner = self.inner.as_mut().unwrap();
        try!(self.stream.write([], ffi::MZ_SYNC_FLUSH, &mut self.buf, inner,
                               ffi::mz_inflate));
        inner.flush()
    }
}

impl Stream {
    fn new(kind: Flavor, raw: bool, level: CompressionLevel) -> Stream {
        let mut state: ffi::mz_stream = unsafe { mem::zeroed() };
        let ret = match kind {
            Deflate => unsafe {
                ffi::mz_deflateInit2(&mut state,
                                     level as libc::c_int,
                                     ffi::MZ_DEFLATED,
                                     if raw {
                                         -ffi::MZ_DEFAULT_WINDOW_BITS
                                     } else {
                                         ffi::MZ_DEFAULT_WINDOW_BITS
                                     },
                                     9,
                                     ffi::MZ_DEFAULT_STRATEGY)
            },
            Inflate => unsafe {
                ffi::mz_inflateInit2(&mut state,
                                     if raw {
                                         -ffi::MZ_DEFAULT_WINDOW_BITS
                                     } else {
                                         ffi::MZ_DEFAULT_WINDOW_BITS
                                     })
            }
        };
        assert_eq!(ret, 0);
        Stream(state, kind)
    }

    fn read<R: Reader>(&mut self, into: &mut [u8], buf: &mut Vec<u8>,
                       pos: &mut uint, reader: &mut R,
                       f: unsafe extern fn(*mut ffi::mz_stream,
                                           libc::c_int) -> libc::c_int)
                       -> IoResult<uint> {

        let cap = buf.capacity();
        let mut read = 0;
        let mut eof = false;
        while read < into.len() {
            if *pos == buf.len() {
                buf.truncate(0);
                match reader.push(cap, buf) {
                    Ok(..) => {}
                    Err(ref e) if e.kind == io::EndOfFile => eof = true,
                    Err(e) => return Err(e),
                }
                *pos = 0;
            }

            self.next_in = buf.slice_from(*pos).as_ptr();
            self.avail_in = (buf.len() - *pos) as libc::c_uint;
            self.next_out = into.slice_from_mut(read).as_mut_ptr();
            self.avail_out = (into.len() - read) as libc::c_uint;

            let before_out = self.total_out;
            let before_in = self.total_in;

            let flush = if eof {ffi::MZ_FINISH} else {ffi::MZ_NO_FLUSH};
            let ret = unsafe { f(&mut **self, flush) };
            read += (self.total_out - before_out) as uint;
            *pos += (self.total_in - before_in) as uint;

            match ret {
                ffi::MZ_OK => {}
                ffi::MZ_STREAM_END if read > 0 => break,
                ffi::MZ_STREAM_END => {
                    return Err(io::standard_error(io::EndOfFile))
                }
                ffi::MZ_BUF_ERROR => break,
                ffi::MZ_DATA_ERROR => {
                    return Err(io::standard_error(io::InvalidInput))
                }
                n => panic!("unexpected return {}", n),
            }
        }

        Ok(read)
    }

    fn write<W: Writer>(&mut self, mut buf: &[u8], flush: libc::c_int,
                        into: &mut Vec<u8>, writer: &mut W,
                        f: unsafe extern fn(*mut ffi::mz_stream,
                                            libc::c_int) -> libc::c_int)
                        -> IoResult<()> {
        let cap = into.capacity();
        while buf.len() > 0 || flush == ffi::MZ_FINISH {
            self.next_in = buf.as_ptr();
            self.avail_in = buf.len() as libc::c_uint;
            let cur_len = into.len();
            self.next_out = into.slice_from_mut(cur_len).as_mut_ptr();
            self.avail_out = (cap - cur_len) as libc::c_uint;

            let before_out = self.total_out;
            let before_in = self.total_in;

            let ret = unsafe {
                let ret = f(&mut **self, flush);
                into.set_len(cur_len + (self.total_out - before_out) as uint);
                ret
            };
            buf = buf.slice_from((self.total_in - before_in) as uint);

            if cap - cur_len == 0 || ret == ffi::MZ_BUF_ERROR {
                try!(writer.write(into.as_slice()));
                into.truncate(0);
            }
            match ret {
                ffi::MZ_OK => {},
                ffi::MZ_STREAM_END => return Ok(()),
                ffi::MZ_BUF_ERROR => {}
                n => panic!("unexpected return {}", n),
            }
        }

        Ok(())
    }
}

impl Deref<ffi::mz_stream> for Stream {
    fn deref<'a>(&'a self) -> &'a ffi::mz_stream {
        let Stream(ref inner, _) = *self; inner
    }
}

impl DerefMut<ffi::mz_stream> for Stream {
    fn deref_mut<'a>(&'a mut self) -> &'a mut ffi::mz_stream {
        let Stream(ref mut inner, _) = *self; inner
    }
}

impl Drop for Stream {
    fn drop(&mut self) {
        unsafe {
            match *self {
                Stream(ref mut s, Deflate) => ffi::mz_deflateEnd(s),
                Stream(ref mut s, Inflate) => ffi::mz_inflateEnd(s),
            };
        }
    }
}
<|endoftext|>


<commit_before>extern crate proxer;
extern crate pretty_env_logger;

use proxer::Client;
use proxer::Endpoint;
use proxer::PageableEndpoint;
use proxer::Pager;
use proxer::parameter;
use std::error::Error;
use std::ops::Add;

fn main()
{
	pretty_env_logger::init().unwrap();

	get_comments();
}

fn get_fullentry()
{
	let prxr = Client::with_env_key("PROXER_API_KEY").unwrap();

	let req = prxr.api()
		.info()
		.get_fullentry(parameter::InfoGetFullEntry { id: 53 });

	let res = prxr.execute(req);

	eprintln!("{:#?}", res);
}

fn get_comments()
{
	let prxr = Client::with_env_key("PROXER_API_KEY").unwrap();

	let req = prxr.api()
		.info()
		.get_comments(
			parameter::InfoGetComments {
				id: 53,
				p: None,
				limit: Some(100),
				sort: None,
			}
		);

	let pager = req.pager(prxr);

	let mut counter = 0;

	for comment in pager {
		counter = counter.add(1);
		let comment = comment.unwrap();

		println!("{:5}: {}", counter, comment.username);
	}
}
<commit_msg>update functions<commit_after>extern crate proxer;
extern crate pretty_env_logger;

use proxer::Client;
use proxer::Endpoint;
use proxer::PageableEndpoint;
use proxer::Pager;
use proxer::parameter;
use std::error::Error;
use std::ops::Add;

fn main()
{
	pretty_env_logger::init().unwrap();

	get_comments();
	get_fullentry();
}

fn get_fullentry()
{
	let prxr = Client::with_env_key("PROXER_API_KEY").unwrap();

	let req = prxr.api()
		.info()
		.get_fullentry(parameter::InfoGetFullEntry { id: 53 });

	let res = prxr.execute(req);

	eprintln!("{:#?}", res);
}

fn get_comments()
{
	let prxr = Client::with_env_key("PROXER_API_KEY").unwrap();

	let req = prxr.api()
		.info()
		.get_comments(
			parameter::InfoGetComments {
				id: 53,
				p: None,
				limit: Some(100),
				sort: None,
			}
		);

	let pager = req.pager(prxr);

	let mut counter = 0;

	for comment in pager {
		counter = counter.add(1);
		let comment = comment.unwrap();

		println!("{:5}: {}", counter, comment.username);
	}
}
<|endoftext|>


<commit_before>use std::process;
use std::sync::mpsc::{self, TryRecvError};

use piston_window::{
    PistonWindow,
    G2d,
    context,
    clear,
    line,
    polygon,
};

use turtle_window::ReadOnly;
use extensions::ConvertScreenCoordinates;
use state::{Path, Polygon, Pen, TurtleState};
use event::from_piston_event;
use {Point, Event, Color, color};

pub enum DrawingCommand {
    /// When a path is finished being animated, it needs to be persisted in the renderer
    /// so it can be redrawn every frame
    StorePath(Path),
    /// Begins filling with the current fill color from the next path onwards. If temporary_path is
    /// set, it is included in the fill shape. Any paths sent via StorePath will be added to the
    /// filled shape.
    /// This command should be passed the fill color that was set at the time when this command
    /// was issued. We cannot simply poll that from the state when this command is handled because
    /// that may be well after the fill color has changed.
    BeginFill(Color),
    /// Send EndFill to finish the filled shape.
    EndFill,
    /// Clears the image completely
    ///
    /// Panics if temporary_path is not None
    Clear,
}

#[derive(Debug)]
pub enum Drawing {
    Path(Path),
    Polygon(Polygon),
}

pub struct Renderer {
    drawings: Vec<Drawing>,
    /// Polygon that is currently in the process of being filled
    /// Removed when EndFill is sent
    fill_polygon: Option<(Vec<Path>, Polygon)>,
}

impl Renderer {
    pub fn new() -> Renderer {
        Self {
            drawings: Vec::new(),
            fill_polygon: None,
        }
    }

    pub fn run(
        &mut self,
        window: &mut PistonWindow,
        drawing_rx: mpsc::Receiver<DrawingCommand>,
        events_tx: mpsc::Sender<Event>,
        state: ReadOnly,
    ) {
        let mut center = [0.0, 0.0];

        'renderloop:
        while let Some(e) = window.next() {
            if let Some(event) = from_piston_event(&e, |pt| pt.to_local_coords(center)) {
                match events_tx.send(event) {
                    Ok(_) => {},
                    // Quit
                    Err(_) => break,
                }
            }

            loop {
                match drawing_rx.try_recv() {
                    Ok(cmd) => self.handle_drawing_command(cmd),
                    Err(TryRecvError::Empty) => break, // Do nothing
                    Err(TryRecvError::Disconnected) => break 'renderloop, // Quit
                }
            }

            window.draw_2d(&e, |c, g| {
                let background = state.drawing().background;
                clear(background.into(), g);

                let view = c.get_view_size();
                let width = view[0] as f64;
                let height = view[1] as f64;
                center = [width * 0.5, height * 0.5];

                for drawing in &self.drawings {
                    match *drawing {
                        Drawing::Path(ref path) => self.render_path(c, g, center, path),
                        Drawing::Polygon(ref poly) => self.render_polygon(c, g, center, poly),
                    }
                }

                if let Some(&(ref border, ref poly)) = self.fill_polygon.as_ref() {
                    self.render_polygon(c, g, center, poly);
                    for path in border {
                        if path.pen.enabled {
                            self.render_path(c, g, center, path);
                        }
                    }
                }
                //TODO: Render the temporary_path as part of the polygon when fill_polygon.is_some()

                if let Some(ref path) = *state.temporary_path() {
                    if path.pen.enabled {
                        self.render_path(c, g, center, path);
                    }
                }

                self.render_shell(c, g, center, &state);
            });
        }

        // Quit immediately when the window is closed
        process::exit(0);
    }

    /// Handles a drawing command sent from the main thread
    fn handle_drawing_command(&mut self, command: DrawingCommand) {
        //NOTE: Do not pass the ReadOnly state to this function. By the time a DrawingCommand is
        // handled, that state may be completely out of date
        use self::DrawingCommand::*;
        match command {
            StorePath(path) => {
                if self.fill_polygon.is_some() {
                    let &mut (ref mut border, ref mut poly) = self.fill_polygon.as_mut().unwrap();
                    border.push(path.clone());

                    let Path {start, end, ..} = path;
                    if poly.vertices.last().map_or(true, |&v| v != path.start) {
                        poly.vertices.push(start);
                    }
                    poly.vertices.push(end);
                }
                else if path.pen.enabled {
                    self.drawings.push(Drawing::Path(path));
                }
            },
            BeginFill(fill_color) => {
                // Calling begin_fill multiple times is okay, it just won't do anything until
                // end_fill is called
                self.fill_polygon = self.fill_polygon.take().or_else(|| Some((Vec::new(), Polygon {
                    vertices: Vec::new(),
                    fill_color: fill_color,
                })));
            },
            // Calling end_fill multiple times is not a problem
            EndFill => if let Some((border, poly)) = self.fill_polygon.take() {
                // Always add the border over the filled polygon so the border is drawn on top
                self.drawings.push(Drawing::Polygon(poly));
                self.drawings.extend(border.into_iter().filter_map(|p| if p.pen.enabled {
                    Some(Drawing::Path(p))
                } else { None }));
            },
            Clear => {
                self.drawings.clear();
                // Because clear doesn't actually shorten the capacity of the vector
                // We don't want to leak memory by leaving this Vec at whatever its size was before
                self.drawings.shrink_to_fit();
                self.fill_polygon.take();
            }
        }
    }

    /// Render a path assuming that its pen is enabled
    fn render_path(&self, c: context::Context, g: &mut G2d, center: Point, path: &Path) {
        let &Path {start, end, ref pen} = path;
        let &Pen {thickness, color, enabled} = pen;
        debug_assert!(enabled, "bug: attempt to render path when pen was not enabled");

        let start = start.to_screen_coords(center);
        let end = end.to_screen_coords(center);

        line(color.into(), thickness,
            [start[0], start[1], end[0], end[1]],
            c.transform, g);
    }

    /// Render a polygon
    fn render_polygon(&self, c: context::Context, g: &mut G2d, center: Point, poly: &Polygon) {
        let verts = poly.vertices.iter().map(|p| p.to_screen_coords(center)).collect::<Vec<_>>();
        polygon(poly.fill_color.into(), &verts, c.transform, g);
    }

    /// Draw the turtle's shell
    fn render_shell(&self, c: context::Context, g: &mut G2d, center: Point, state: &ReadOnly) {
        // Calculate all the points on the shell by rotating the shell shape by the turtle's
        // heading and moving it to the turtle's position
        let TurtleState {position, heading, visible, ..} = *state.turtle();
        if !visible {
            return;
        }

        let cos = heading.cos();
        let sin = heading.sin();
        let turtle_x = position[0];
        let turtle_y = position[1];
        let shell: Vec<_> = [
            [0., 15.],
            [10., 0.],
            [0., -15.],
        ].into_iter().map(|pt| {
            // Rotate each point by the heading and add the current turtle position
            let x = cos * pt[0] - sin * pt[1] + turtle_x;
            let y = sin * pt[0] + cos * pt[1] + turtle_y;
            [x, y].to_screen_coords(center)
        }).collect();

        // Draw the turtle shell with its background first, then its border
        polygon(color::WHITE.into(), &shell, c.transform, g);
        for i in 0..shell.len() {
            let start = shell[i];
            let end = shell[(i + 1) % shell.len()];

            line(color::BLACK.into(), 1.,
            [start[0], start[1], end[0], end[1]],
            c.transform, g);
        }
    }
}
<commit_msg>Refactored render_polygon to use the temporary_path (Fixes #5)<commit_after>use std::process;
use std::sync::mpsc::{self, TryRecvError};

use piston_window::{
    PistonWindow,
    G2d,
    context,
    clear,
    line,
    polygon,
};

use turtle_window::ReadOnly;
use extensions::ConvertScreenCoordinates;
use state::{Path, Polygon, Pen, TurtleState};
use event::from_piston_event;
use {Point, Event, Color, color};

pub enum DrawingCommand {
    /// When a path is finished being animated, it needs to be persisted in the renderer
    /// so it can be redrawn every frame
    StorePath(Path),
    /// Begins filling with the current fill color from the next path onwards. If temporary_path is
    /// set, it is included in the fill shape. Any paths sent via StorePath will be added to the
    /// filled shape.
    /// This command should be passed the fill color that was set at the time when this command
    /// was issued. We cannot simply poll that from the state when this command is handled because
    /// that may be well after the fill color has changed.
    BeginFill(Color),
    /// Send EndFill to finish the filled shape.
    EndFill,
    /// Clears the image completely
    ///
    /// Panics if temporary_path is not None
    Clear,
}

#[derive(Debug)]
pub enum Drawing {
    Path(Path),
    Polygon(Polygon),
}

pub struct Renderer {
    drawings: Vec<Drawing>,
    /// Polygon that is currently in the process of being filled
    /// Removed when EndFill is sent
    fill_polygon: Option<(Vec<Path>, Polygon)>,
}

impl Renderer {
    pub fn new() -> Renderer {
        Self {
            drawings: Vec::new(),
            fill_polygon: None,
        }
    }

    pub fn run(
        &mut self,
        window: &mut PistonWindow,
        drawing_rx: mpsc::Receiver<DrawingCommand>,
        events_tx: mpsc::Sender<Event>,
        state: ReadOnly,
    ) {
        let mut center = [0.0, 0.0];

        'renderloop:
        while let Some(e) = window.next() {
            if let Some(event) = from_piston_event(&e, |pt| pt.to_local_coords(center)) {
                match events_tx.send(event) {
                    Ok(_) => {},
                    // Quit
                    Err(_) => break,
                }
            }

            loop {
                match drawing_rx.try_recv() {
                    Ok(cmd) => self.handle_drawing_command(cmd),
                    Err(TryRecvError::Empty) => break, // Do nothing
                    Err(TryRecvError::Disconnected) => break 'renderloop, // Quit
                }
            }

            window.draw_2d(&e, |c, g| {
                let background = state.drawing().background;
                clear(background.into(), g);

                let view = c.get_view_size();
                let width = view[0] as f64;
                let height = view[1] as f64;
                center = [width * 0.5, height * 0.5];

                for drawing in &self.drawings {
                    match *drawing {
                        Drawing::Path(ref path) => self.render_path(c, g, center, path),
                        Drawing::Polygon(ref poly) => self.render_polygon(c, g, center, poly, None),
                    }
                }

                if let Some(&(ref border, ref poly)) = self.fill_polygon.as_ref() {
                    self.render_polygon(c, g, center, poly, state.temporary_path().as_ref());
                    for path in border {
                        if path.pen.enabled {
                            self.render_path(c, g, center, path);
                        }
                    }
                }
                //TODO: Render the temporary_path as part of the polygon when fill_polygon.is_some()

                if let Some(ref path) = *state.temporary_path() {
                    if path.pen.enabled {
                        self.render_path(c, g, center, path);
                    }
                }

                self.render_shell(c, g, center, &state);
            });
        }

        // Quit immediately when the window is closed
        process::exit(0);
    }

    /// Handles a drawing command sent from the main thread
    fn handle_drawing_command(&mut self, command: DrawingCommand) {
        //NOTE: Do not pass the ReadOnly state to this function. By the time a DrawingCommand is
        // handled, that state may be completely out of date
        use self::DrawingCommand::*;
        match command {
            StorePath(path) => {
                if self.fill_polygon.is_some() {
                    let &mut (ref mut border, ref mut poly) = self.fill_polygon.as_mut().unwrap();
                    border.push(path.clone());

                    let Path {start, end, ..} = path;
                    if poly.vertices.last().map_or(true, |&v| v != start) {
                        poly.vertices.push(start);
                    }
                    poly.vertices.push(end);
                }
                else if path.pen.enabled {
                    self.drawings.push(Drawing::Path(path));
                }
            },
            BeginFill(fill_color) => {
                // Calling begin_fill multiple times is okay, it just won't do anything until
                // end_fill is called
                self.fill_polygon = self.fill_polygon.take().or_else(|| Some((Vec::new(), Polygon {
                    vertices: Vec::new(),
                    fill_color: fill_color,
                })));
            },
            // Calling end_fill multiple times is not a problem
            EndFill => if let Some((border, poly)) = self.fill_polygon.take() {
                // Always add the border over the filled polygon so the border is drawn on top
                self.drawings.push(Drawing::Polygon(poly));
                self.drawings.extend(border.into_iter().filter_map(|p| if p.pen.enabled {
                    Some(Drawing::Path(p))
                } else { None }));
            },
            Clear => {
                self.drawings.clear();
                // Because clear doesn't actually shorten the capacity of the vector
                // We don't want to leak memory by leaving this Vec at whatever its size was before
                self.drawings.shrink_to_fit();
                self.fill_polygon.take();
            }
        }
    }

    /// Render a path assuming that its pen is enabled
    fn render_path(&self, c: context::Context, g: &mut G2d, center: Point, path: &Path) {
        let &Path {start, end, ref pen} = path;
        let &Pen {thickness, color, enabled} = pen;
        debug_assert!(enabled, "bug: attempt to render path when pen was not enabled");

        let start = start.to_screen_coords(center);
        let end = end.to_screen_coords(center);

        line(color.into(), thickness,
            [start[0], start[1], end[0], end[1]],
            c.transform, g);
    }

    /// Render a polygon with an optional extra edge
    fn render_polygon(&self, c: context::Context, g: &mut G2d, center: Point, poly: &Polygon,
        extra_edge: Option<&Path>
    ) {
        let extra = if let Some(&Path {start, end, ..}) = extra_edge {
            if poly.vertices.last().map_or(true, |&v| v != start) {
                vec![start, end]
            }
            else {
                vec![end]
            }
        }
        else {
            Vec::new()
        };

        let verts = poly.vertices.iter()
            .chain(extra.iter())
            .map(|p| p.to_screen_coords(center))
            .collect::<Vec<_>>();
        polygon(poly.fill_color.into(), &verts, c.transform, g);
    }

    /// Draw the turtle's shell
    fn render_shell(&self, c: context::Context, g: &mut G2d, center: Point, state: &ReadOnly) {
        // Calculate all the points on the shell by rotating the shell shape by the turtle's
        // heading and moving it to the turtle's position
        let TurtleState {position, heading, visible, ..} = *state.turtle();
        if !visible {
            return;
        }

        let cos = heading.cos();
        let sin = heading.sin();
        let turtle_x = position[0];
        let turtle_y = position[1];
        let shell: Vec<_> = [
            [0., 15.],
            [10., 0.],
            [0., -15.],
        ].into_iter().map(|pt| {
            // Rotate each point by the heading and add the current turtle position
            let x = cos * pt[0] - sin * pt[1] + turtle_x;
            let y = sin * pt[0] + cos * pt[1] + turtle_y;
            [x, y].to_screen_coords(center)
        }).collect();

        // Draw the turtle shell with its background first, then its border
        polygon(color::WHITE.into(), &shell, c.transform, g);
        for i in 0..shell.len() {
            let start = shell[i];
            let end = shell[(i + 1) % shell.len()];

            line(color::BLACK.into(), 1.,
            [start[0], start[1], end[0], end[1]],
            c.transform, g);
        }
    }
}
<|endoftext|>


<commit_before>//! Users interface

use {Future, Github};

use hyper::client::connect::Connect;

/// User information
#[derive(Debug, Deserialize)]
pub struct User {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    // type (keyword)
    pub site_admin: bool,
}

/// Information about current authenticated user
#[derive(Debug, Deserialize)]
pub struct AuthenticatedUser {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    // type (keyword)
    pub site_admin: bool,

    // extend over `User`:
    pub name: String,
    pub company: Option<String>,
    pub blog: String,
    pub location: String,
    pub email: String,
    pub hireable: Option<bool>,
    pub bio: String,
    pub public_repos: u64,
    pub public_gists: u64,
    pub followers: u64,
    pub following: u64,
    pub created_at: String, // TODO: change to `DateTime`?
    pub updated_at: String, // TODO: change to `DateTime`?
}

/// Query user information
pub struct Users<C>
where
    C: Clone + Connect + 'static,
{
    github: Github<C>,
}

impl<C: Clone + Connect + 'static> Users<C> {
    pub fn new(github: Github<C>) -> Self {
        Users { github }
    }

    /// Information about current authenticated user
    pub fn authenticated(&self) -> Future<AuthenticatedUser> {
        self.github.get("/user")
    }

    pub fn get<U>(&self, username: U) -> Future<User>
    where
        U: Into<String>,
    {
        self.github
            .get(&format!("/users/{username}", username = username.into()))
    }
}
<commit_msg>Make nullable AuthenticatedUser fields optional<commit_after>//! Users interface

use {Future, Github};

use hyper::client::connect::Connect;

/// User information
#[derive(Debug, Deserialize)]
pub struct User {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    // type (keyword)
    pub site_admin: bool,
}

/// Information about current authenticated user
#[derive(Debug, Deserialize)]
pub struct AuthenticatedUser {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    // type (keyword)
    pub site_admin: bool,

    // extend over `User`:
    pub name: Option<String>,
    pub company: Option<String>,
    pub blog: String,
    pub location: Option<String>,
    pub email: Option<String>,
    pub hireable: Option<bool>,
    pub bio: Option<String>,
    pub public_repos: u64,
    pub public_gists: u64,
    pub followers: u64,
    pub following: u64,
    pub created_at: String, // TODO: change to `DateTime`?
    pub updated_at: String, // TODO: change to `DateTime`?
}

/// Query user information
pub struct Users<C>
where
    C: Clone + Connect + 'static,
{
    github: Github<C>,
}

impl<C: Clone + Connect + 'static> Users<C> {
    pub fn new(github: Github<C>) -> Self {
        Users { github }
    }

    /// Information about current authenticated user
    pub fn authenticated(&self) -> Future<AuthenticatedUser> {
        self.github.get("/user")
    }

    pub fn get<U>(&self, username: U) -> Future<User>
    where
        U: Into<String>,
    {
        self.github
            .get(&format!("/users/{username}", username = username.into()))
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix a typo in tokio_reactor::PollEvented (#250)<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2018 Chef Software Inc. and/or applicable contributors
//
// 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.

extern crate habitat_pkg_export_docker as export_docker;

use std::io::Write;

use export_docker::Result;

pub struct Values {
    values: Vec<ValuesEntry>,
}

impl Values {
    pub fn new() -> Self {
        Values { values: Vec::new() }
    }

    pub fn add_entry(&mut self, variable: &str, value: &str) {
        self.values.push(ValuesEntry {
            variable: variable.to_owned(),
            value: value.to_owned(),
        });
    }

    pub fn generate(&self, write: &mut Write) -> Result<()> {
        let mut out = "".to_owned();
        for entry in &self.values {
            out = out + &format!("{}: \"{}\"\n", entry.variable, entry.value);
        }

        write.write(out.as_bytes())?;

        Ok(())
    }
}

struct ValuesEntry {
    variable: String,
    value: String,
}
<commit_msg>pkg-export-helm: Use QuoteHelper to generate values<commit_after>// Copyright (c) 2018 Chef Software Inc. and/or applicable contributors
//
// 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.

extern crate habitat_pkg_export_docker as export_docker;

use std::io::Write;

use export_docker::Result;
use export_k8s::QuoteHelper;

pub struct Values {
    values: Vec<ValuesEntry>,
}

impl Values {
    pub fn new() -> Self {
        Values { values: Vec::new() }
    }

    pub fn add_entry(&mut self, variable: &str, value: &str) {
        self.values.push(ValuesEntry {
            variable: variable.to_owned(),
            value: value.to_owned(),
        });
    }

    pub fn generate(&self, write: &mut Write) -> Result<()> {
        let mut out = "".to_owned();
        for entry in &self.values {
            out = out + &format!(
                "{}: {}\n",
                entry.variable,
                QuoteHelper::escape(&entry.value)
            );
        }

        write.write(out.as_bytes())?;

        Ok(())
    }
}

struct ValuesEntry {
    variable: String,
    value: String,
}
<|endoftext|>


<commit_before>use boxdraw;

use SimpleSearch;

// EXERCISE 1: Can you make an undraw implementation that can handle
// the case below?

#[test]
fn three_by_three() {
    boxdraw::check_undraw(".............\n\
                           ..+--+--+--+.\n\
                           ..|aa|bb|cc|.\n\
                           ..|aa|bb|cc|.\n\
                           ..+--+--+--+.\n\
                           ..|dd|ee|ff|.\n\
                           ..|dd|ee|ff|.\n\
                           ..+--+--+--+.\n\
                           ..|gg|hh|ii|.\n\
                           ..|gg|hh|ii|.\n\
                           ..+--+--+--+.\n\
                           .............\n\
                          ",
                          &SimpleSearch).unwrap();

}

// EXERCISE 2: One might think that once you generate a working
// Script, there's no further way to improve upon it. However,
// consider a case like this:
//
//
//                  ....................
//                  ......+------+......
//                  ......|bbbbbb|......
//                  ......|bbbbbb|......
//                  .+----|bbbbbb|----+.
//                  .|aaaa|bbbbbb|aaaa|.
//                  .|aaaa|bbbbbb|aaaa|.
//                  .+----|bbbbbb|----+.
//                  ......|bbbbbb|......
//                  ......+------+......
//                  ....................
//
// There are two "obvious" relatively short scripts that generate the
// above picture: one that draws two 'a' rectangles and then the
// single 'b' rectangle (thus requiring three commands in the script).
//
//  ....................       ....................
//  ....................       ......+------+......
//  ....................       ......|bbbbbb|......
//  ....................       ......|bbbbbb|......
//  .+----+......+----+.       ......|bbbbbb|......
//  .|aaaa|......|aaaa|. then  ......|bbbbbb|......
//  .|aaaa|......|aaaa|.       ......|bbbbbb|......
//  .+----+......+----+.       ......|bbbbbb|......
//  ....................       ......|bbbbbb|......
//  ....................       ......+------+......
//  ....................       ....................
//
//
// But there is also this approach, which requires only two commands:
//
//  ....................       ....................
//  ....................       ......+------+......
//  ....................       ......|bbbbbb|......
//  ....................       ......|bbbbbb|......
//  .+----------------+.       ......|bbbbbb|......
//  .|aaaaaaaaaaaaaaaa|. then  ......|bbbbbb|......
//  .|aaaaaaaaaaaaaaaa|.       ......|bbbbbb|......
//  .+----------------+.       ......|bbbbbb|......
//  ....................       ......|bbbbbb|......
//  ....................       ......+------+......
//  ....................       ....................
//
// The undraw strategy of the code above will tend to generate the
// three-command script. What ideas do you have to try to make it
// generate "optimal" scripts (where "optimal" here means "minimal
// number of commands."

// EXERCISE 3: Up until now, we have assumed that all boxes are at
// least width and height >= 2.  So for example `narrow_lines()` above
// shows boxes of width == 2, so narrow that they have no interior.
//
// BUT: The boxdraw-rs library supports boxes of width or height == 1
// as well, and it has *very* different behavior for them. Find out
// what that behavior is (perhaps by looking at the tests in the
// boxdraw library).
//
// Consider what a box with both width and height equal to 1 would
// look like. What implications does this have? For example, what kind
// of pictures can you make with *just* boxes width and height 1?
//
// Try to solve the undraw problem even for such cases.
//
// Note 1: to do this, you may want to start from scratch; or maybe
// some of the code here could be of use.
//
// Note 2: You may want to play around first with approaches that are
// not anywhere close to optimal.

// EXERCISE 4: Like exercise 2 above: Again, solve the generalized
// undraw problem (that is, including boxes of width and/or height 1),
// but this time, try to generate relatively small scripts.
//
// Note that you can make short scripts that first draw large boxes
// (which will then have borders) and then write over the borders with
// boxes of width or height 1, like so:
//
//  ....................       ....................   ....................
//  ....................       ....................   ....................
//  ....................       ....................   ....................
//  ....................       ....................   ....................
//  .+----------------+.       .aaaaaaaaaaaaaaaaaa.   .a................a.
//  .|aaaaaaaaaaaaaaaa|. then  .................... ; .a................a.
//  .|aaaaaaaaaaaaaaaa|.       ....................   .a................a.
//  .+----------------+.       .aaaaaaaaaaaaaaaaaa.   .a................a.
//  ....................       ....................   ....................
//  ....................       ....................   ....................
//  ....................       ....................   ....................
//
// and this generates a picture with a borderless box:
//
//  ....................
//  ....................
//  ....................
//  ....................
//  .aaaaaaaaaaaaaaaaaa.
//  .aaaaaaaaaaaaaaaaaa.
//  .aaaaaaaaaaaaaaaaaa.
//  .aaaaaaaaaaaaaaaaaa.
//  ....................
//  ....................
//  ....................
<commit_msg>Fix a misplaced reference post file refactoring.<commit_after>use boxdraw;

use SimpleSearch;

// EXERCISE 1: Can you make an undraw implementation that can handle
// the case below?

#[test]
fn three_by_three() {
    boxdraw::check_undraw(".............\n\
                           ..+--+--+--+.\n\
                           ..|aa|bb|cc|.\n\
                           ..|aa|bb|cc|.\n\
                           ..+--+--+--+.\n\
                           ..|dd|ee|ff|.\n\
                           ..|dd|ee|ff|.\n\
                           ..+--+--+--+.\n\
                           ..|gg|hh|ii|.\n\
                           ..|gg|hh|ii|.\n\
                           ..+--+--+--+.\n\
                           .............\n\
                          ",
                          &SimpleSearch).unwrap();

}

// EXERCISE 2: One might think that once you generate a working
// Script, there's no further way to improve upon it. However,
// consider a case like this:
//
//
//                  ....................
//                  ......+------+......
//                  ......|bbbbbb|......
//                  ......|bbbbbb|......
//                  .+----|bbbbbb|----+.
//                  .|aaaa|bbbbbb|aaaa|.
//                  .|aaaa|bbbbbb|aaaa|.
//                  .+----|bbbbbb|----+.
//                  ......|bbbbbb|......
//                  ......+------+......
//                  ....................
//
// There are two "obvious" relatively short scripts that generate the
// above picture: one that draws two 'a' rectangles and then the
// single 'b' rectangle (thus requiring three commands in the script).
//
//  ....................       ....................
//  ....................       ......+------+......
//  ....................       ......|bbbbbb|......
//  ....................       ......|bbbbbb|......
//  .+----+......+----+.       ......|bbbbbb|......
//  .|aaaa|......|aaaa|. then  ......|bbbbbb|......
//  .|aaaa|......|aaaa|.       ......|bbbbbb|......
//  .+----+......+----+.       ......|bbbbbb|......
//  ....................       ......|bbbbbb|......
//  ....................       ......+------+......
//  ....................       ....................
//
//
// But there is also this approach, which requires only two commands:
//
//  ....................       ....................
//  ....................       ......+------+......
//  ....................       ......|bbbbbb|......
//  ....................       ......|bbbbbb|......
//  .+----------------+.       ......|bbbbbb|......
//  .|aaaaaaaaaaaaaaaa|. then  ......|bbbbbb|......
//  .|aaaaaaaaaaaaaaaa|.       ......|bbbbbb|......
//  .+----------------+.       ......|bbbbbb|......
//  ....................       ......|bbbbbb|......
//  ....................       ......+------+......
//  ....................       ....................
//
// The undraw strategy of the code above will tend to generate the
// three-command script. What ideas do you have to try to make it
// generate "optimal" scripts (where "optimal" here means "minimal
// number of commands."

// EXERCISE 3: Up until now, we have assumed that all boxes are at
// least width and height >= 2.  So for example `test::narrow_lines()`
// shows boxes of width == 2, so narrow that they have no interior.
//
// BUT: The boxdraw-rs library supports boxes of width or height == 1
// as well, and it has *very* different behavior for them. Find out
// what that behavior is (perhaps by looking at the tests in the
// boxdraw library).
//
// Consider what a box with both width and height equal to 1 would
// look like. What implications does this have? For example, what kind
// of pictures can you make with *just* boxes width and height 1?
//
// Try to solve the undraw problem even for such cases.
//
// Note 1: to do this, you may want to start from scratch; or maybe
// some of the code here could be of use.
//
// Note 2: You may want to play around first with approaches that are
// not anywhere close to optimal.

// EXERCISE 4: Like exercise 2 above: Again, solve the generalized
// undraw problem (that is, including boxes of width and/or height 1),
// but this time, try to generate relatively small scripts.
//
// Note that you can make short scripts that first draw large boxes
// (which will then have borders) and then write over the borders with
// boxes of width or height 1, like so:
//
//  ....................       ....................   ....................
//  ....................       ....................   ....................
//  ....................       ....................   ....................
//  ....................       ....................   ....................
//  .+----------------+.       .aaaaaaaaaaaaaaaaaa.   .a................a.
//  .|aaaaaaaaaaaaaaaa|. then  .................... ; .a................a.
//  .|aaaaaaaaaaaaaaaa|.       ....................   .a................a.
//  .+----------------+.       .aaaaaaaaaaaaaaaaaa.   .a................a.
//  ....................       ....................   ....................
//  ....................       ....................   ....................
//  ....................       ....................   ....................
//
// and this generates a picture with a borderless box:
//
//  ....................
//  ....................
//  ....................
//  ....................
//  .aaaaaaaaaaaaaaaaaa.
//  .aaaaaaaaaaaaaaaaaa.
//  .aaaaaaaaaaaaaaaaaa.
//  .aaaaaaaaaaaaaaaaaa.
//  ....................
//  ....................
//  ....................
<|endoftext|>


<commit_before>// Copyright 2020 Manuel Landesfeind, Evotec International GmbH
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//!
//! Module for working with faidx-indexed FASTA files.
//!

use std::ffi;
use std::path::Path;
use url::Url;

use crate::htslib;

pub mod errors;
pub use errors::{Error, Result};

fn path_as_bytes<'a, P: 'a + AsRef<Path>>(path: P, must_exist: bool) -> Result<Vec<u8>> {
    if path.as_ref().exists() || !must_exist {
        Ok(path
            .as_ref()
            .to_str()
            .ok_or(Error::NonUnicodePath)?
            .as_bytes()
            .to_owned())
    } else {
        Err(Error::FileNotFound {
            path: path.as_ref().to_owned(),
        })
    }
}
/// A Fasta reader.
#[derive(Debug)]
pub struct Reader {
    inner: *mut htslib::faidx_t,
}

impl Reader {
    /// Create a new Reader from a path.
    ///
    /// # Arguments
    ///
    /// * `path` - the path to open.
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
        Self::new(&path_as_bytes(path, true)?)
    }

    /// Create a new Reader from an URL.
    ///
    /// # Arguments
    ///
    /// * `url` - the url to open
    pub fn from_url(url: &Url) -> Result<Self, Error> {
        Self::new(url.as_str().as_bytes())
    }

    /// Internal function to create a Reader from some sort of path (could be file path but also URL).
    /// The path or URL will be handled by the c-implementation transparently.
    ///
    /// # Arguments
    ///
    /// * `path` - the path or URL to open
    fn new(path: &[u8]) -> Result<Self, Error> {
        let cpath = ffi::CString::new(path).unwrap();
        let inner = unsafe { htslib::fai_load(cpath.as_ptr()) };
        Ok(Self { inner })
    }

    /// Fetch the sequence as a byte array.
    ///
    /// # Arguments
    ///
    /// * `name` - the name of the template sequence (e.g., "chr1")
    /// * `begin` - the offset within the template sequence (starting with 0)
    /// * `end` - the end position to return (if smaller than `begin`, the behavior is undefined).
    pub fn fetch_seq<N: AsRef<str>>(&self, name: N, begin: usize, end: usize) -> Result<&[u8]> {
        if begin > i64::MAX as usize {
            return Err(Error::PositionTooLarge);
        }
        if end > i64::MAX as usize {
            return Err(Error::PositionTooLarge);
        }
        let cname = ffi::CString::new(name.as_ref().as_bytes()).unwrap();
        let len_out: i64 = 0;
        let cseq = unsafe {
            let ptr = htslib::faidx_fetch_seq64(
                self.inner,                          //*const faidx_t,
                cname.as_ptr(),                      // c_name
                begin as htslib::hts_pos_t,          // p_beg_i
                end as htslib::hts_pos_t,            // p_end_i
                &mut (len_out as htslib::hts_pos_t), //len
            );
            ffi::CStr::from_ptr(ptr)
        };

        Ok(cseq.to_bytes())
    }

    /// Fetches the sequence and returns it as string.
    ///
    /// # Arguments
    ///
    /// * `name` - the name of the template sequence (e.g., "chr1")
    /// * `begin` - the offset within the template sequence (starting with 0)
    /// * `end` - the end position to return (if smaller than `begin`, the behavior is undefined).
    pub fn fetch_seq_string<N: AsRef<str>>(
        &self,
        name: N,
        begin: usize,
        end: usize,
    ) -> Result<String> {
        let bytes = self.fetch_seq(name, begin, end)?;
        Ok(std::str::from_utf8(bytes).unwrap().to_owned())
    }
}

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

    fn open_reader() -> Reader {
        Reader::from_path(format!("{}/test/test_cram.fa", env!("CARGO_MANIFEST_DIR")))
            .ok()
            .unwrap()
    }
    #[test]
    fn faidx_open() {
        open_reader();
    }

    #[test]
    fn faidx_read_chr_first_base() {
        let r = open_reader();

        let bseq = r.fetch_seq("chr1", 0, 0).unwrap();
        assert_eq!(bseq.len(), 1);
        assert_eq!(bseq, b"G");

        let seq = r.fetch_seq_string("chr1", 0, 0).unwrap();
        assert_eq!(seq.len(), 1);
        assert_eq!(seq, "G");
    }

    #[test]
    fn faidx_read_chr_start() {
        let r = open_reader();

        let bseq = r.fetch_seq("chr1", 0, 9).unwrap();
        assert_eq!(bseq.len(), 10);
        assert_eq!(bseq, b"GGGCACAGCC");

        let seq = r.fetch_seq_string("chr1", 0, 9).unwrap();
        assert_eq!(seq.len(), 10);
        assert_eq!(seq, "GGGCACAGCC");
    }

    #[test]
    fn faidx_read_chr_between() {
        let r = open_reader();

        let bseq = r.fetch_seq("chr1", 4, 14).unwrap();
        assert_eq!(bseq.len(), 11);
        assert_eq!(bseq, b"ACAGCCTCACC");

        let seq = r.fetch_seq_string("chr1", 4, 14).unwrap();
        assert_eq!(seq.len(), 11);
        assert_eq!(seq, "ACAGCCTCACC");
    }

    #[test]
    fn faidx_read_chr_end() {
        let r = open_reader();

        let bseq = r.fetch_seq("chr1", 110, 120).unwrap();
        assert_eq!(bseq.len(), 10);
        assert_eq!(bseq, b"CCCCTCCGTG");

        let seq = r.fetch_seq_string("chr1", 110, 120).unwrap();
        assert_eq!(seq.len(), 10);
        assert_eq!(seq, "CCCCTCCGTG");
    }

    #[test]
    fn faidx_read_twice_string() {
        let r = open_reader();
        let seq = r.fetch_seq_string("chr1", 110, 120).unwrap();
        assert_eq!(seq.len(), 10);
        assert_eq!(seq, "CCCCTCCGTG");

        let seq = r.fetch_seq_string("chr1", 5, 9).unwrap();
        assert_eq!(seq.len(), 5);
        assert_eq!(seq, "CAGCC");
    }

    #[test]
    fn faidx_read_twice_bytes() {
        let r = open_reader();
        let seq = r.fetch_seq("chr1", 110, 120).unwrap();
        assert_eq!(seq.len(), 10);
        assert_eq!(seq, b"CCCCTCCGTG");

        let seq = r.fetch_seq("chr1", 5, 9).unwrap();
        assert_eq!(seq.len(), 5);
        assert_eq!(seq, b"CAGCC");
    }

    #[test]
    fn faidx_position_too_large() {
        let r = open_reader();
        let position_too_large = i64::MAX as usize;
        let res = r.fetch_seq("chr1", position_too_large, position_too_large + 1);
        assert_eq!(res, Err(Error::PositionTooLarge));
    }
}
<commit_msg>Explicitly reference std::i64::MAX to allow compilation in older versions of Rust (#266)<commit_after>// Copyright 2020 Manuel Landesfeind, Evotec International GmbH
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//!
//! Module for working with faidx-indexed FASTA files.
//!

use std::ffi;
use std::path::Path;
use url::Url;

use crate::htslib;

pub mod errors;
pub use errors::{Error, Result};

fn path_as_bytes<'a, P: 'a + AsRef<Path>>(path: P, must_exist: bool) -> Result<Vec<u8>> {
    if path.as_ref().exists() || !must_exist {
        Ok(path
            .as_ref()
            .to_str()
            .ok_or(Error::NonUnicodePath)?
            .as_bytes()
            .to_owned())
    } else {
        Err(Error::FileNotFound {
            path: path.as_ref().to_owned(),
        })
    }
}
/// A Fasta reader.
#[derive(Debug)]
pub struct Reader {
    inner: *mut htslib::faidx_t,
}

impl Reader {
    /// Create a new Reader from a path.
    ///
    /// # Arguments
    ///
    /// * `path` - the path to open.
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
        Self::new(&path_as_bytes(path, true)?)
    }

    /// Create a new Reader from an URL.
    ///
    /// # Arguments
    ///
    /// * `url` - the url to open
    pub fn from_url(url: &Url) -> Result<Self, Error> {
        Self::new(url.as_str().as_bytes())
    }

    /// Internal function to create a Reader from some sort of path (could be file path but also URL).
    /// The path or URL will be handled by the c-implementation transparently.
    ///
    /// # Arguments
    ///
    /// * `path` - the path or URL to open
    fn new(path: &[u8]) -> Result<Self, Error> {
        let cpath = ffi::CString::new(path).unwrap();
        let inner = unsafe { htslib::fai_load(cpath.as_ptr()) };
        Ok(Self { inner })
    }

    /// Fetch the sequence as a byte array.
    ///
    /// # Arguments
    ///
    /// * `name` - the name of the template sequence (e.g., "chr1")
    /// * `begin` - the offset within the template sequence (starting with 0)
    /// * `end` - the end position to return (if smaller than `begin`, the behavior is undefined).
    pub fn fetch_seq<N: AsRef<str>>(&self, name: N, begin: usize, end: usize) -> Result<&[u8]> {
        if begin > std::i64::MAX as usize {
            return Err(Error::PositionTooLarge);
        }
        if end > std::i64::MAX as usize {
            return Err(Error::PositionTooLarge);
        }
        let cname = ffi::CString::new(name.as_ref().as_bytes()).unwrap();
        let len_out: i64 = 0;
        let cseq = unsafe {
            let ptr = htslib::faidx_fetch_seq64(
                self.inner,                          //*const faidx_t,
                cname.as_ptr(),                      // c_name
                begin as htslib::hts_pos_t,          // p_beg_i
                end as htslib::hts_pos_t,            // p_end_i
                &mut (len_out as htslib::hts_pos_t), //len
            );
            ffi::CStr::from_ptr(ptr)
        };

        Ok(cseq.to_bytes())
    }

    /// Fetches the sequence and returns it as string.
    ///
    /// # Arguments
    ///
    /// * `name` - the name of the template sequence (e.g., "chr1")
    /// * `begin` - the offset within the template sequence (starting with 0)
    /// * `end` - the end position to return (if smaller than `begin`, the behavior is undefined).
    pub fn fetch_seq_string<N: AsRef<str>>(
        &self,
        name: N,
        begin: usize,
        end: usize,
    ) -> Result<String> {
        let bytes = self.fetch_seq(name, begin, end)?;
        Ok(std::str::from_utf8(bytes).unwrap().to_owned())
    }
}

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

    fn open_reader() -> Reader {
        Reader::from_path(format!("{}/test/test_cram.fa", env!("CARGO_MANIFEST_DIR")))
            .ok()
            .unwrap()
    }
    #[test]
    fn faidx_open() {
        open_reader();
    }

    #[test]
    fn faidx_read_chr_first_base() {
        let r = open_reader();

        let bseq = r.fetch_seq("chr1", 0, 0).unwrap();
        assert_eq!(bseq.len(), 1);
        assert_eq!(bseq, b"G");

        let seq = r.fetch_seq_string("chr1", 0, 0).unwrap();
        assert_eq!(seq.len(), 1);
        assert_eq!(seq, "G");
    }

    #[test]
    fn faidx_read_chr_start() {
        let r = open_reader();

        let bseq = r.fetch_seq("chr1", 0, 9).unwrap();
        assert_eq!(bseq.len(), 10);
        assert_eq!(bseq, b"GGGCACAGCC");

        let seq = r.fetch_seq_string("chr1", 0, 9).unwrap();
        assert_eq!(seq.len(), 10);
        assert_eq!(seq, "GGGCACAGCC");
    }

    #[test]
    fn faidx_read_chr_between() {
        let r = open_reader();

        let bseq = r.fetch_seq("chr1", 4, 14).unwrap();
        assert_eq!(bseq.len(), 11);
        assert_eq!(bseq, b"ACAGCCTCACC");

        let seq = r.fetch_seq_string("chr1", 4, 14).unwrap();
        assert_eq!(seq.len(), 11);
        assert_eq!(seq, "ACAGCCTCACC");
    }

    #[test]
    fn faidx_read_chr_end() {
        let r = open_reader();

        let bseq = r.fetch_seq("chr1", 110, 120).unwrap();
        assert_eq!(bseq.len(), 10);
        assert_eq!(bseq, b"CCCCTCCGTG");

        let seq = r.fetch_seq_string("chr1", 110, 120).unwrap();
        assert_eq!(seq.len(), 10);
        assert_eq!(seq, "CCCCTCCGTG");
    }

    #[test]
    fn faidx_read_twice_string() {
        let r = open_reader();
        let seq = r.fetch_seq_string("chr1", 110, 120).unwrap();
        assert_eq!(seq.len(), 10);
        assert_eq!(seq, "CCCCTCCGTG");

        let seq = r.fetch_seq_string("chr1", 5, 9).unwrap();
        assert_eq!(seq.len(), 5);
        assert_eq!(seq, "CAGCC");
    }

    #[test]
    fn faidx_read_twice_bytes() {
        let r = open_reader();
        let seq = r.fetch_seq("chr1", 110, 120).unwrap();
        assert_eq!(seq.len(), 10);
        assert_eq!(seq, b"CCCCTCCGTG");

        let seq = r.fetch_seq("chr1", 5, 9).unwrap();
        assert_eq!(seq.len(), 5);
        assert_eq!(seq, b"CAGCC");
    }

    #[test]
    fn faidx_position_too_large() {
        let r = open_reader();
        let position_too_large = i64::MAX as usize;
        let res = r.fetch_seq("chr1", position_too_large, position_too_large + 1);
        assert_eq!(res, Err(Error::PositionTooLarge));
    }
}
<|endoftext|>