<commit_before>// Copyright 2014 Johannes Köster, Christopher Schröder.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! FASTA format reading and writing.
//!
//! # Example
//!
//! ```
//! use std::io;
//! use bio::io::fasta;
//! let reader = fasta::Reader::new(io::stdin());
//! ```

use std::io;
use std::io::prelude::*;
use std::ascii::AsciiExt;
use std::collections;
use std::fs;
use std::path::Path;
use std::convert::AsRef;

use csv;

use utils::{TextSlice, Text};

/// A FASTA reader.
pub struct Reader<R: io::Read> {
    reader: io::BufReader<R>,
    line: String,
}

impl Reader<fs::File> {
    /// Read FASTA from given file path.
    pub fn from_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        fs::File::open(path).map(Reader::new)
    }
}

impl<R: io::Read> Reader<R> {
    /// Create a new Fasta reader given an instance of `io::Read`.
    pub fn new(reader: R) -> Self {
        Reader {
            reader: io::BufReader::new(reader),
            line: String::new(),
        }
    }

    /// Read next FASTA record into the given `Record`.
    pub fn read(&mut self, record: &mut Record) -> io::Result<()> {
        record.clear();
        if self.line.is_empty() {
            try!(self.reader.read_line(&mut self.line));
            if self.line.is_empty() {
                return Ok(());
            }
        }

        if !self.line.starts_with('>') {
            return Err(io::Error::new(io::ErrorKind::Other, "Expected > at record start."));
        }
        record.header.push_str(&self.line);
        loop {
            self.line.clear();
            try!(self.reader.read_line(&mut self.line));
            if self.line.is_empty() || self.line.starts_with('>') {
                break;
            }
            record.seq.push_str(&self.line.trim_right());
        }

        Ok(())
    }

    /// Return an iterator over the records of this FastQ file.
    pub fn records(self) -> Records<R> {
        Records { reader: self }
    }
}

/// A FASTA index as created by SAMtools (.fai).
pub struct Index {
    inner: collections::HashMap<String, IndexRecord>,
    seqs: Vec<String>,
}

impl Index {
    /// Open a FASTA index from a given `io::Read` instance.
    pub fn new<R: io::Read>(fai: R) -> csv::Result<Self> {
        let mut inner = collections::HashMap::new();
        let mut seqs = vec![];
        let mut fai_reader = csv::Reader::from_reader(fai).delimiter(b'\t').has_headers(false);
        for row in fai_reader.decode() {
            let (name, record): (String, IndexRecord) = try!(row);
            seqs.push(name.clone());
            inner.insert(name, record);
        }
        Ok(Index {
            inner: inner,
            seqs: seqs,
        })
    }

    /// Open a FASTA index from a given file path.
    pub fn from_file<P: AsRef<Path>>(path: &P) -> csv::Result<Self> {
        match fs::File::open(path) {
            Ok(fai) => Self::new(fai),
            Err(e) => Err(csv::Error::Io(e)),
        }
    }

    /// Open a FASTA index given the corresponding FASTA file path (e.g. for ref.fasta we expect ref.fasta.fai).
    pub fn with_fasta_file<P: AsRef<Path>>(fasta_path: &P) -> csv::Result<Self> {
        let mut ext = fasta_path.as_ref().extension().unwrap().to_str().unwrap().to_owned();
        ext.push_str(".fai");
        let fai_path = fasta_path.as_ref().with_extension(ext);

        Self::from_file(&fai_path)
    }

    /// Return a vector of sequences described in the index.
    pub fn sequences(&self) -> Vec<Sequence> {
        self.seqs
            .iter()
            .map(|name| {
                Sequence {
                    name: name.clone(),
                    len: self.inner.get(name).unwrap().len,
                }
            })
            .collect()
    }
}

/// A FASTA reader with an index as created by SAMtools (.fai).
pub struct IndexedReader<R: io::Read + io::Seek> {
    reader: io::BufReader<R>,
    pub index: Index,
}

impl IndexedReader<fs::File> {
    /// Read from a given file path. This assumes the index ref.fasta.fai to be present for FASTA ref.fasta.
    pub fn from_file<P: AsRef<Path>>(path: &P) -> csv::Result<Self> {
        let index = try!(Index::with_fasta_file(path));

        match fs::File::open(path) {
            Ok(fasta) => Ok(IndexedReader::with_index(fasta, index)),
            Err(e) => Err(csv::Error::Io(e)),
        }
    }
}

impl<R: io::Read + io::Seek> IndexedReader<R> {
    /// Read from a FASTA and its index, both given as `io::Read`. FASTA has to be `io::Seek` in addition.
    pub fn new<I: io::Read>(fasta: R, fai: I) -> csv::Result<Self> {
        let index = try!(Index::new(fai));
        Ok(IndexedReader {
            reader: io::BufReader::new(fasta),
            index: index,
        })
    }

    /// Read from a FASTA and its index, the first given as `io::Read`, the second given as index object.
    pub fn with_index(fasta: R, index: Index) -> Self {
        IndexedReader {
            reader: io::BufReader::new(fasta),
            index: index,
        }
    }

    /// For a given seqname, read the whole sequence into the given vector.
    pub fn read_all(&mut self, seqname: &str, seq: &mut Text) -> io::Result<()> {
        match self.index.inner.get(seqname) {
            Some(&idx) => self.read(seqname, 0, idx.len, seq),
            None => Err(io::Error::new(io::ErrorKind::Other, "Unknown sequence name.")),
        }
    }

    /// Read the given interval of the given seqname into the given vector (stop position is exclusive).
    pub fn read(&mut self,
                seqname: &str,
                start: u64,
                stop: u64,
                seq: &mut Text)
                -> io::Result<()> {
        match self.index.inner.get(seqname) {
            Some(idx) => {
                seq.clear();
                // derived from
                // http://www.allenyu.info/item/24-quickly-fetch-sequence-from-samtools-faidx-indexed-fasta-sequences.html
                let line = start / idx.line_bases * idx.line_bytes;
                let line_offset = start % idx.line_bases;
                let offset = idx.offset + line + line_offset;
                let lines = stop / idx.line_bases * idx.line_bytes - line;
                let line_stop = stop % idx.line_bases -
                                if lines == 0 {
                    line_offset
                } else {
                    0
                };

                try!(self.reader.seek(io::SeekFrom::Start(offset)));
                let mut buf = vec![0u8; idx.line_bases as usize];
                for _ in 0..lines {
                    // read full lines
                    try!(self.reader.read(&mut buf));
                    seq.extend_from_slice(&buf);
                }
                // read last line
                println!("linestop {}", line_stop);
                try!(self.reader.read(&mut buf[..line_stop as usize]));
                seq.extend_from_slice(&buf[..line_stop as usize]);
                Ok(())
            }
            None => Err(io::Error::new(io::ErrorKind::Other, "Unknown sequence name.")),
        }
    }
}

/// Record of a FASTA index.
#[derive(RustcDecodable, Debug, Copy, Clone)]
struct IndexRecord {
    len: u64,
    offset: u64,
    line_bases: u64,
    line_bytes: u64,
}

/// A sequence record returned by the FASTA index.
pub struct Sequence {
    pub name: String,
    pub len: u64,
}

/// A Fasta writer.
pub struct Writer<W: io::Write> {
    writer: io::BufWriter<W>,
}

impl Writer<fs::File> {
    /// Write to the given file path.
    pub fn to_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        fs::File::create(path).map(Writer::new)
    }
}

impl<W: io::Write> Writer<W> {
    /// Create a new Fasta writer.
    pub fn new(writer: W) -> Self {
        Writer { writer: io::BufWriter::new(writer) }
    }

    /// Directly write a Fasta record.
    pub fn write_record(&mut self, record: Record) -> io::Result<()> {
        self.write(record.id().unwrap_or(""), record.desc(), record.seq())
    }

    /// Write a Fasta record with given id, optional description and sequence.
    pub fn write(&mut self, id: &str, desc: Option<&str>, seq: TextSlice) -> io::Result<()> {
        try!(self.writer.write(b">"));
        try!(self.writer.write(id.as_bytes()));
        if desc.is_some() {
            try!(self.writer.write(b" "));
            try!(self.writer.write(desc.unwrap().as_bytes()));
        }
        try!(self.writer.write(b"\n"));
        try!(self.writer.write(seq));
        try!(self.writer.write(b"\n"));

        Ok(())
    }

    /// Flush the writer, ensuring that everything is written.
    pub fn flush(&mut self) -> io::Result<()> {
        self.writer.flush()
    }
}

/// A FASTA record.
pub struct Record {
    header: String,
    seq: String,
}

impl Record {
    /// Create a new instance.
    pub fn new() -> Self {
        Record {
            header: String::new(),
            seq: String::new(),
        }
    }

    /// Check if record is empty.
    pub fn is_empty(&self) -> bool {
        self.header.is_empty() && self.seq.is_empty()
    }

    /// Check validity of Fasta record.
    pub fn check(&self) -> Result<(), &str> {
        if self.id().is_none() {
            return Err("Expecting id for FastQ record.");
        }
        if !self.seq.is_ascii() {
            return Err("Non-ascii character found in sequence.");
        }

        Ok(())
    }

    /// Return the id of the record.
    pub fn id(&self) -> Option<&str> {
        self.header[1..].trim_right().splitn(2, ' ').next()
    }

    /// Return descriptions if present.
    pub fn desc(&self) -> Option<&str> {
        self.header[1..].trim_right().splitn(2, ' ').skip(1).next()
    }

    /// Return the sequence of the record.
    pub fn seq(&self) -> TextSlice {
        self.seq.as_bytes()
    }

    /// Clear the record.
    fn clear(&mut self) {
        self.header.clear();
        self.seq.clear();
    }
}

/// An iterator over the records of a Fasta file.
pub struct Records<R: io::Read> {
    reader: Reader<R>,
}

impl<R: io::Read> Iterator for Records<R> {
    type Item = io::Result<Record>;

    fn next(&mut self) -> Option<io::Result<Record>> {
        let mut record = Record::new();
        match self.reader.read(&mut record) {
            Ok(()) if record.is_empty() => None,
            Ok(()) => Some(Ok(record)),
            Err(err) => Some(Err(err)),
        }
    }
}

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

    const FASTA_FILE: &'static [u8] = b">id desc
ACCGTAGGCTGA
>id2
ATTGTTGTTTTA
";
    const FAI_FILE: &'static [u8] = b"id\t12\t9\t60\t61
";

    #[test]
    fn test_reader() {
        let reader = Reader::new(FASTA_FILE);
        let ids = [Some("id"), Some("id2")];
        let descs = [Some("desc"), None];
        let seqs: [&[u8]; 2] = [b"ACCGTAGGCTGA", b"ATTGTTGTTTTA"];

        for (i, r) in reader.records().enumerate() {
            let record = r.ok().expect("Error reading record");
            assert_eq!(record.check(), Ok(()));
            assert_eq!(record.id(), ids[i]);
            assert_eq!(record.desc(), descs[i]);
            assert_eq!(record.seq(), seqs[i]);
        }

        // let record = records.ok().nth(1).unwrap();
    }

    #[test]
    fn test_indexed_reader() {
        let mut reader = IndexedReader::new(io::Cursor::new(FASTA_FILE), FAI_FILE)
                             .ok()
                             .expect("Error reading index");
        let mut seq = Vec::new();
        reader.read("id", 1, 5, &mut seq).ok().expect("Error reading sequence.");
        assert_eq!(seq, b"CCGT");
    }

    #[test]
    fn test_writer() {
        let mut writer = Writer::new(Vec::new());
        writer.write("id", Some("desc"), b"ACCGTAGGCTGA").ok().expect("Expected successful write");
        writer.write("id2", None, b"ATTGTTGTTTTA").ok().expect("Expected successful write");
        writer.flush().ok().expect("Expected successful write");
        assert_eq!(writer.writer.get_ref(), &FASTA_FILE);
    }
}
<commit_msg>fix fasta::IndexedReader for multi-line reads and add unit tests<commit_after>// Copyright 2014 Johannes Köster, Christopher Schröder.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! FASTA format reading and writing.
//!
//! # Example
//!
//! ```
//! use std::io;
//! use bio::io::fasta;
//! let reader = fasta::Reader::new(io::stdin());
//! ```

use std::io;
use std::io::prelude::*;
use std::ascii::AsciiExt;
use std::collections;
use std::fs;
use std::path::Path;
use std::convert::AsRef;
use std::cmp::min;

use csv;

use utils::{TextSlice, Text};

/// A FASTA reader.
pub struct Reader<R: io::Read> {
    reader: io::BufReader<R>,
    line: String,
}

impl Reader<fs::File> {
    /// Read FASTA from given file path.
    pub fn from_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        fs::File::open(path).map(Reader::new)
    }
}

impl<R: io::Read> Reader<R> {
    /// Create a new Fasta reader given an instance of `io::Read`.
    pub fn new(reader: R) -> Self {
        Reader {
            reader: io::BufReader::new(reader),
            line: String::new(),
        }
    }

    /// Read next FASTA record into the given `Record`.
    pub fn read(&mut self, record: &mut Record) -> io::Result<()> {
        record.clear();
        if self.line.is_empty() {
            try!(self.reader.read_line(&mut self.line));
            if self.line.is_empty() {
                return Ok(());
            }
        }

        if !self.line.starts_with('>') {
            return Err(io::Error::new(io::ErrorKind::Other, "Expected > at record start."));
        }
        record.header.push_str(&self.line);
        loop {
            self.line.clear();
            try!(self.reader.read_line(&mut self.line));
            if self.line.is_empty() || self.line.starts_with('>') {
                break;
            }
            record.seq.push_str(&self.line.trim_right());
        }

        Ok(())
    }

    /// Return an iterator over the records of this FastQ file.
    pub fn records(self) -> Records<R> {
        Records { reader: self }
    }
}

/// A FASTA index as created by SAMtools (.fai).
pub struct Index {
    inner: collections::HashMap<String, IndexRecord>,
    seqs: Vec<String>,
}

impl Index {
    /// Open a FASTA index from a given `io::Read` instance.
    pub fn new<R: io::Read>(fai: R) -> csv::Result<Self> {
        let mut inner = collections::HashMap::new();
        let mut seqs = vec![];
        let mut fai_reader = csv::Reader::from_reader(fai).delimiter(b'\t').has_headers(false);
        for row in fai_reader.decode() {
            let (name, record): (String, IndexRecord) = try!(row);
            seqs.push(name.clone());
            inner.insert(name, record);
        }
        Ok(Index {
            inner: inner,
            seqs: seqs,
        })
    }

    /// Open a FASTA index from a given file path.
    pub fn from_file<P: AsRef<Path>>(path: &P) -> csv::Result<Self> {
        match fs::File::open(path) {
            Ok(fai) => Self::new(fai),
            Err(e) => Err(csv::Error::Io(e)),
        }
    }

    /// Open a FASTA index given the corresponding FASTA file path (e.g. for ref.fasta we expect ref.fasta.fai).
    pub fn with_fasta_file<P: AsRef<Path>>(fasta_path: &P) -> csv::Result<Self> {
        let mut ext = fasta_path.as_ref().extension().unwrap().to_str().unwrap().to_owned();
        ext.push_str(".fai");
        let fai_path = fasta_path.as_ref().with_extension(ext);

        Self::from_file(&fai_path)
    }

    /// Return a vector of sequences described in the index.
    pub fn sequences(&self) -> Vec<Sequence> {
        self.seqs
            .iter()
            .map(|name| {
                Sequence {
                    name: name.clone(),
                    len: self.inner.get(name).unwrap().len,
                }
            })
            .collect()
    }
}

/// A FASTA reader with an index as created by SAMtools (.fai).
pub struct IndexedReader<R: io::Read + io::Seek> {
    reader: io::BufReader<R>,
    pub index: Index,
}

impl IndexedReader<fs::File> {
    /// Read from a given file path. This assumes the index ref.fasta.fai to be present for FASTA ref.fasta.
    pub fn from_file<P: AsRef<Path>>(path: &P) -> csv::Result<Self> {
        let index = try!(Index::with_fasta_file(path));

        match fs::File::open(path) {
            Ok(fasta) => Ok(IndexedReader::with_index(fasta, index)),
            Err(e) => Err(csv::Error::Io(e)),
        }
    }
}

impl<R: io::Read + io::Seek> IndexedReader<R> {
    /// Read from a FASTA and its index, both given as `io::Read`. FASTA has to be `io::Seek` in addition.
    pub fn new<I: io::Read>(fasta: R, fai: I) -> csv::Result<Self> {
        let index = try!(Index::new(fai));
        Ok(IndexedReader {
            reader: io::BufReader::new(fasta),
            index: index,
        })
    }

    /// Read from a FASTA and its index, the first given as `io::Read`, the second given as index object.
    pub fn with_index(fasta: R, index: Index) -> Self {
        IndexedReader {
            reader: io::BufReader::new(fasta),
            index: index,
        }
    }

    /// For a given seqname, read the whole sequence into the given vector.
    pub fn read_all(&mut self, seqname: &str, seq: &mut Text) -> io::Result<()> {
        match self.index.inner.get(seqname) {
            Some(&idx) => self.read(seqname, 0, idx.len, seq),
            None => Err(io::Error::new(io::ErrorKind::Other, "Unknown sequence name.")),
        }
    }

    /// Read the given interval of the given seqname into the given vector (stop position is exclusive).
    pub fn read(&mut self,
                seqname: &str,
                start: u64,
                stop: u64,
                seq: &mut Text)
                -> io::Result<()> {
        match self.index.inner.get(seqname) {
            Some(idx) => {
                seq.clear();

                let length = stop - start as u64;
                let mut buf = vec![0u8; idx.line_bases as usize];

                loop {
                    let current_start = start + seq.len() as u64;
                    let line_start = current_start / idx.line_bases * idx.line_bytes;
                    let line_offset = current_start % idx.line_bases;
                    let offset = idx.offset + line_start + line_offset;
                    try!(self.reader.seek(io::SeekFrom::Start(offset)));

                    let left_to_read = length - seq.len() as u64;
                    let left_in_line = min(left_to_read, idx.line_bases - line_offset) as usize;

                    try!(self.reader.read(&mut buf[..left_in_line]));
                    seq.extend_from_slice(&buf[..left_in_line]);

                    if seq.len() as u64 == length
                    {
                        break;
                    }
                }

                Ok(())
            }
            None => Err(io::Error::new(io::ErrorKind::Other, "Unknown sequence name.")),
        }
    }
}

/// Record of a FASTA index.
#[derive(RustcDecodable, Debug, Copy, Clone)]
struct IndexRecord {
    len: u64,
    offset: u64,
    line_bases: u64,
    line_bytes: u64,
}

/// A sequence record returned by the FASTA index.
pub struct Sequence {
    pub name: String,
    pub len: u64,
}

/// A Fasta writer.
pub struct Writer<W: io::Write> {
    writer: io::BufWriter<W>,
}

impl Writer<fs::File> {
    /// Write to the given file path.
    pub fn to_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        fs::File::create(path).map(Writer::new)
    }
}

impl<W: io::Write> Writer<W> {
    /// Create a new Fasta writer.
    pub fn new(writer: W) -> Self {
        Writer { writer: io::BufWriter::new(writer) }
    }

    /// Directly write a Fasta record.
    pub fn write_record(&mut self, record: Record) -> io::Result<()> {
        self.write(record.id().unwrap_or(""), record.desc(), record.seq())
    }

    /// Write a Fasta record with given id, optional description and sequence.
    pub fn write(&mut self, id: &str, desc: Option<&str>, seq: TextSlice) -> io::Result<()> {
        try!(self.writer.write(b">"));
        try!(self.writer.write(id.as_bytes()));
        if desc.is_some() {
            try!(self.writer.write(b" "));
            try!(self.writer.write(desc.unwrap().as_bytes()));
        }
        try!(self.writer.write(b"\n"));
        try!(self.writer.write(seq));
        try!(self.writer.write(b"\n"));

        Ok(())
    }

    /// Flush the writer, ensuring that everything is written.
    pub fn flush(&mut self) -> io::Result<()> {
        self.writer.flush()
    }
}

/// A FASTA record.
pub struct Record {
    header: String,
    seq: String,
}

impl Record {
    /// Create a new instance.
    pub fn new() -> Self {
        Record {
            header: String::new(),
            seq: String::new(),
        }
    }

    /// Check if record is empty.
    pub fn is_empty(&self) -> bool {
        self.header.is_empty() && self.seq.is_empty()
    }

    /// Check validity of Fasta record.
    pub fn check(&self) -> Result<(), &str> {
        if self.id().is_none() {
            return Err("Expecting id for FastQ record.");
        }
        if !self.seq.is_ascii() {
            return Err("Non-ascii character found in sequence.");
        }

        Ok(())
    }

    /// Return the id of the record.
    pub fn id(&self) -> Option<&str> {
        self.header[1..].trim_right().splitn(2, ' ').next()
    }

    /// Return descriptions if present.
    pub fn desc(&self) -> Option<&str> {
        self.header[1..].trim_right().splitn(2, ' ').skip(1).next()
    }

    /// Return the sequence of the record.
    pub fn seq(&self) -> TextSlice {
        self.seq.as_bytes()
    }

    /// Clear the record.
    fn clear(&mut self) {
        self.header.clear();
        self.seq.clear();
    }
}

/// An iterator over the records of a Fasta file.
pub struct Records<R: io::Read> {
    reader: Reader<R>,
}

impl<R: io::Read> Iterator for Records<R> {
    type Item = io::Result<Record>;

    fn next(&mut self) -> Option<io::Result<Record>> {
        let mut record = Record::new();
        match self.reader.read(&mut record) {
            Ok(()) if record.is_empty() => None,
            Ok(()) => Some(Ok(record)),
            Err(err) => Some(Err(err)),
        }
    }
}

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

    const FASTA_FILE: &'static [u8] = b">id desc
ACCGTAGGCTGA
CCGTAGGCTGAA
CGTAGGCTGAAA
GTAGGCTGAAAA
CCCC
>id2
ATTGTTGTTTTA
ATTGTTGTTTTA
ATTGTTGTTTTA
GGGG
";
    const FAI_FILE: &'static [u8] = b"id\t52\t9\t12\t13
id2\t40\t71\t12\t13
";
    const WRITE_FASTA_FILE: &'static [u8] = b">id desc
ACCGTAGGCTGA
>id2
ATTGTTGTTTTA
";

    #[test]
    fn test_reader() {
        let reader = Reader::new(FASTA_FILE);
        let ids = [Some("id"), Some("id2")];
        let descs = [Some("desc"), None];
        let seqs: [&[u8]; 2] = [b"ACCGTAGGCTGACCGTAGGCTGAACGTAGGCTGAAAGTAGGCTGAAAACCCC",
                                b"ATTGTTGTTTTAATTGTTGTTTTAATTGTTGTTTTAGGGG"];

        for (i, r) in reader.records().enumerate() {
            let record = r.ok().expect("Error reading record");
            assert_eq!(record.check(), Ok(()));
            assert_eq!(record.id(), ids[i]);
            assert_eq!(record.desc(), descs[i]);
            assert_eq!(record.seq(), seqs[i]);
        }

        // let record = records.ok().nth(1).unwrap();
    }

    #[test]
    fn test_indexed_reader() {
        let mut reader = IndexedReader::new(io::Cursor::new(FASTA_FILE), FAI_FILE)
                             .ok()
                             .expect("Error reading index");
        let mut seq = Vec::new();

        // Test reading various substrings of the sequence
        reader.read("id", 1, 5, &mut seq).ok().expect("Error reading sequence.");
        assert_eq!(seq, b"CCGT");

        reader.read("id", 1, 31, &mut seq).ok().expect("Error reading sequence.");
        assert_eq!(seq, b"CCGTAGGCTGACCGTAGGCTGAACGTAGGC");

        reader.read("id", 13, 23, &mut seq).ok().expect("Error reading sequence.");
        assert_eq!(seq, b"CGTAGGCTGA");

        reader.read("id", 36, 52, &mut seq).ok().expect("Error reading sequence.");
        assert_eq!(seq, b"GTAGGCTGAAAACCCC");

        reader.read("id2", 12, 40, &mut seq).ok().expect("Error reading sequence.");
        assert_eq!(seq, b"ATTGTTGTTTTAATTGTTGTTTTAGGGG");
    }

    #[test]
    fn test_writer() {
        let mut writer = Writer::new(Vec::new());
        writer.write("id", Some("desc"), b"ACCGTAGGCTGA").ok().expect("Expected successful write");
        writer.write("id2", None, b"ATTGTTGTTTTA").ok().expect("Expected successful write");
        writer.flush().ok().expect("Expected successful write");
        assert_eq!(writer.writer.get_ref(), &WRITE_FASTA_FILE);
    }
}
<|endoftext|>


<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use refcount::{Refcount, Ref};
use types::FALSE;
use wrap;
use wrap::Wrapper;

use glib as ffi;
use gobject;

#[repr(C)]
pub struct MainContext {
    raw: ffi::GMainContext
}

unsafe impl Send for MainContext { }
unsafe impl Sync for MainContext { }
unsafe impl Wrapper for MainContext {
    type Raw = ffi::GMainContext;
}

impl MainContext {
    pub fn default() -> &'static MainContext {
        unsafe {
            wrap::from_raw(ffi::g_main_context_default())
        }
    }
}

impl Refcount for MainContext {

    unsafe fn inc_ref(&self) {
        ffi::g_main_context_ref(self.as_mut_ptr());
    }

    unsafe fn dec_ref(&self) {
        ffi::g_main_context_unref(self.as_mut_ptr());
    }
}

g_impl_boxed_type_for_ref!(MainContext, gobject::g_main_context_get_type);

#[repr(C)]
pub struct MainLoop {
    raw: ffi::GMainLoop
}

unsafe impl Send for MainLoop { }
unsafe impl Sync for MainLoop { }
unsafe impl Wrapper for MainLoop {
    type Raw = ffi::GMainLoop;
}

pub struct LoopRunner {
    mainloop: *mut ffi::GMainLoop,
}

impl LoopRunner {
    pub fn new() -> LoopRunner {
        unsafe {
            let ctx = ffi::g_main_context_new();
            let mainloop = ffi::g_main_loop_new(ctx, FALSE);
            ffi::g_main_context_unref(ctx);

            LoopRunner { mainloop: mainloop }
        }
    }

    pub fn run_after<F>(&self, setup: F) where F: FnOnce(Ref<MainLoop>) {
        unsafe {
            let ctx = ffi::g_main_loop_get_context(self.mainloop);
            ffi::g_main_context_push_thread_default(ctx);

            setup(Ref::new(wrap::from_raw(self.mainloop)));

            ffi::g_main_loop_run(self.mainloop);

            ffi::g_main_context_pop_thread_default(ctx);
        }
    }
}

impl Drop for LoopRunner {
    fn drop(&mut self) {
        unsafe {
            ffi::g_main_loop_unref(self.mainloop);
        }
    }
}

impl MainLoop {

    pub fn get_context(&self) -> &MainContext {
        unsafe {
            let ctx = ffi::g_main_loop_get_context(self.as_mut_ptr());
            wrap::from_raw(ctx)
        }
    }

    pub fn quit(&self) {
        unsafe {
            ffi::g_main_loop_quit(self.as_mut_ptr());
        }
    }
}

impl Refcount for MainLoop {

    unsafe fn inc_ref(&self) {
        ffi::g_main_loop_ref(self.as_mut_ptr());
    }

    unsafe fn dec_ref(&self) {
        ffi::g_main_loop_unref(self.as_mut_ptr());
    }
}

g_impl_boxed_type_for_ref!(MainLoop, gobject::g_main_loop_get_type);
<commit_msg>mainloop: Add infrastructure for source callbacks<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2014, 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use refcount::{Refcount, Ref};
use types::{FALSE, TRUE};
use types::{gboolean, gint, gpointer, guint};
use util::{box_free, box_from_pointer, box_into_pointer, into_destroy_notify};
use wrap;
use wrap::Wrapper;

use glib as ffi;
use gobject;
use std::convert;
use std::marker;
use std::mem;

pub const PRIORITY_DEFAULT      : gint = ffi::G_PRIORITY_DEFAULT;
pub const PRIORITY_DEFAULT_IDLE : gint = ffi::G_PRIORITY_DEFAULT_IDLE;
pub const PRIORITY_HIGH         : gint = ffi::G_PRIORITY_HIGH;
pub const PRIORITY_HIGH_IDLE    : gint = ffi::G_PRIORITY_HIGH_IDLE;
pub const PRIORITY_LOW          : gint = ffi::G_PRIORITY_LOW;

pub enum CallbackResult { Remove, Continue }
pub use self::CallbackResult::*;

pub struct RawCallback {
    func: ffi::GSourceFunc,
    data: gpointer,
    destroy: ffi::GDestroyNotify
}

impl Drop for RawCallback {
    fn drop(&mut self) {
        (self.destroy)(self.data);
    }
}

unsafe fn into_source_func(func: unsafe extern "C" fn(gpointer) -> gboolean)
                          -> ffi::GSourceFunc
{
    mem::transmute(func)
}

unsafe extern "C" fn source_func<F>(callback_data: gpointer) -> gboolean
    where F: FnMut() -> CallbackResult
{
    let mut callback: Box<F> = box_from_pointer(callback_data);
    let res = callback();
    mem::forget(callback);
    match res {
        Remove => FALSE,
        Continue => TRUE
    }
}

unsafe extern "C" fn source_once_func<F>(callback_data: gpointer) -> gboolean
    where F: FnOnce()
{
    let mut holder: Box<Option<F>> = box_from_pointer(callback_data);
    let callback = holder.take().expect("a callback closure expected");
    mem::forget(holder);
    callback();
    FALSE
}

pub struct SourceCallback(RawCallback);

impl Into<RawCallback> for SourceCallback {
    #[inline]
    fn into(self) -> RawCallback {
        self.0
    }
}

impl SourceCallback {
    pub fn new<F>(closure: F) -> Self
        where F: Send + 'static, F: FnMut() -> CallbackResult
    {
        let boxed_closure = Box::new(closure);
        SourceCallback(unsafe {
            RawCallback {
                func: into_source_func(source_func::<F>),
                data: box_into_pointer(boxed_closure),
                destroy: into_destroy_notify(box_free::<F>)
            }
        })
    }

    pub fn once<F>(closure: F) -> Self
        where F: Send + 'static, F: FnOnce()
    {
        let holder = Box::new(Some(closure));
        SourceCallback(unsafe {
            RawCallback {
                func: into_source_func(source_once_func::<F>),
                data: box_into_pointer(holder),
                destroy: into_destroy_notify(box_free::<Option<F>>)
            }
        })
    }
}

#[repr(C)]
pub struct MainContext {
    raw: ffi::GMainContext
}

unsafe impl Send for MainContext { }
unsafe impl Sync for MainContext { }
unsafe impl Wrapper for MainContext {
    type Raw = ffi::GMainContext;
}

impl MainContext {
    pub fn default() -> &'static MainContext {
        unsafe {
            wrap::from_raw(ffi::g_main_context_default())
        }
    }
}

impl Refcount for MainContext {

    unsafe fn inc_ref(&self) {
        ffi::g_main_context_ref(self.as_mut_ptr());
    }

    unsafe fn dec_ref(&self) {
        ffi::g_main_context_unref(self.as_mut_ptr());
    }
}

g_impl_boxed_type_for_ref!(MainContext, gobject::g_main_context_get_type);

#[repr(C)]
pub struct MainLoop {
    raw: ffi::GMainLoop
}

unsafe impl Send for MainLoop { }
unsafe impl Sync for MainLoop { }
unsafe impl Wrapper for MainLoop {
    type Raw = ffi::GMainLoop;
}

pub struct LoopRunner {
    mainloop: *mut ffi::GMainLoop,
}

impl LoopRunner {
    pub fn new() -> LoopRunner {
        unsafe {
            let ctx = ffi::g_main_context_new();
            let mainloop = ffi::g_main_loop_new(ctx, FALSE);
            ffi::g_main_context_unref(ctx);

            LoopRunner { mainloop: mainloop }
        }
    }

    pub fn run_after<F>(&self, setup: F) where F: FnOnce(Ref<MainLoop>) {
        unsafe {
            let ctx = ffi::g_main_loop_get_context(self.mainloop);
            ffi::g_main_context_push_thread_default(ctx);

            setup(Ref::new(wrap::from_raw(self.mainloop)));

            ffi::g_main_loop_run(self.mainloop);

            ffi::g_main_context_pop_thread_default(ctx);
        }
    }
}

impl Drop for LoopRunner {
    fn drop(&mut self) {
        unsafe {
            ffi::g_main_loop_unref(self.mainloop);
        }
    }
}

impl MainLoop {

    pub fn get_context(&self) -> &MainContext {
        unsafe {
            let ctx = ffi::g_main_loop_get_context(self.as_mut_ptr());
            wrap::from_raw(ctx)
        }
    }

    pub fn quit(&self) {
        unsafe {
            ffi::g_main_loop_quit(self.as_mut_ptr());
        }
    }
}

impl Refcount for MainLoop {

    unsafe fn inc_ref(&self) {
        ffi::g_main_loop_ref(self.as_mut_ptr());
    }

    unsafe fn dec_ref(&self) {
        ffi::g_main_loop_unref(self.as_mut_ptr());
    }
}

g_impl_boxed_type_for_ref!(MainLoop, gobject::g_main_loop_get_type);
<|endoftext|>


<commit_before>use error::*;
use result::*;

// TODO: GrpcResult
pub trait Marshaller<M> {
    fn write(&self, m: &M) -> GrpcResult<Vec<u8>>;
    fn read(&self, bytes: &[u8]) -> GrpcResult<M>;
}

pub struct MarshallerString;

impl Marshaller<String> for MarshallerString {
    fn write(&self, m: &String) -> GrpcResult<Vec<u8>> {
        Ok(m.as_bytes().to_vec())
    }

    fn read(&self, bytes: &[u8]) -> GrpcResult<String> {
        String::from_utf8(bytes.to_vec())
            .map_err(|_| GrpcError::Other("failed to parse utf-8"))
    }
}

pub struct MarshallerBytes;

impl Marshaller<Vec<u8>> for MarshallerBytes {
    fn write(&self, m: &Vec<u8>) -> GrpcResult<Vec<u8>> {
        Ok(m.clone())
    }

    fn read(&self, bytes: &[u8]) -> GrpcResult<Vec<u8>> {
        Ok(bytes.to_owned())
    }
}
<commit_msg>outdated todo<commit_after>use error::*;
use result::*;

pub trait Marshaller<M> {
    fn write(&self, m: &M) -> GrpcResult<Vec<u8>>;
    fn read(&self, bytes: &[u8]) -> GrpcResult<M>;
}

pub struct MarshallerString;

impl Marshaller<String> for MarshallerString {
    fn write(&self, m: &String) -> GrpcResult<Vec<u8>> {
        Ok(m.as_bytes().to_vec())
    }

    fn read(&self, bytes: &[u8]) -> GrpcResult<String> {
        String::from_utf8(bytes.to_vec())
            .map_err(|_| GrpcError::Other("failed to parse utf-8"))
    }
}

pub struct MarshallerBytes;

impl Marshaller<Vec<u8>> for MarshallerBytes {
    fn write(&self, m: &Vec<u8>) -> GrpcResult<Vec<u8>> {
        Ok(m.clone())
    }

    fn read(&self, bytes: &[u8]) -> GrpcResult<Vec<u8>> {
        Ok(bytes.to_owned())
    }
}
<|endoftext|>


<commit_before>/// Determines the minimum number of edits required to transform
/// the first string into the second, using a matrix-driven
/// version of the Levenshtein distance algorithm.
///
/// ```rust
/// let score = edit_distance("hound", "hounds"); // 1
/// ```
fn edit_distance(first: &str, second: &str) -> usize {
    // Initialize a matrix we'll use to track the
    // edit distances as we step through both strings.
    let width = first.chars().count()+1;
    let height = second.chars().count()+1;
    let mut distances: Vec<usize> = Vec::with_capacity(width*height);

    // We want to be able to index values immediately,
    // without having to push data (usizes default to zero).
    unsafe { distances.set_len(width*height); }

    // Initialize first row and column values, when we come
    // across them, which is the distance from nothing to
    // every zero-index substring of the other word.
    // e.g. ("" -> "hou", "" -> "houn", "" -> "hound")
    for row in (0..height) {
        distances[row*width] = row;
    }
    for column in (0..width) {
        distances[column] = column;
    }

    // We need to manage indices manually; strings don't have an
    // index + character iterator, since indexing UTF-8 strings
    // doesn't work beyond the ASCII set. We, however, need to track
    // each substring combination, so they're useful in this scenario.
    let mut row = 1;
    let mut column = 1;
    for row_char in second.chars() {
        for column_char in first.chars() {
            if column_char == row_char {
                // When the strings share a common character, there's
                // no additional cost; we carry forward the optimum edit
                // distance we calculated without having considered it.
                distances[row*width + column] = distances[(row-1)*width + (column-1)];
            } else {
                distances[row*width + column] = *[
                    // Cost of removing a character from the first word.
                    distances[(row-1)*width + column] + 1,

                    // Cost of adding a character to the first word.
                    distances[row*width + (column-1)] + 1,

                    // Cost of substituting the character for another.
                    distances[(row-1)*width + (column-1)] + 1
                ].iter().min().unwrap();
            }
            column += 1;
        }
        row += 1;
        column = 1;
    }

    // The optimal edit distance is always in the
    // lower-right corner of the distance matrix.
    return distances[width*height-1]
}

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

    #[test]
    fn edit_distance_is_correct_for_removing_a_character() {
        assert_eq!(edit_distance("hound", "hounds"), 1);
    }

    #[test]
    fn edit_distance_is_correct_for_adding_a_character() {
        assert_eq!(edit_distance("hounds", "hound"), 1);
    }

    #[test]
    fn edit_distance_is_correct_for_substitutions() {
        assert_eq!(edit_distance("hound", "mound"), 1);
    }
}
<commit_msg>Remove example code for private function.<commit_after>/// Determines the minimum number of edits required to transform
/// the first string into the second, using a matrix-driven
/// version of the Levenshtein distance algorithm.
///
fn edit_distance(first: &str, second: &str) -> usize {
    // Initialize a matrix we'll use to track the
    // edit distances as we step through both strings.
    let width = first.chars().count()+1;
    let height = second.chars().count()+1;
    let mut distances: Vec<usize> = Vec::with_capacity(width*height);

    // We want to be able to index values immediately,
    // without having to push data (usizes default to zero).
    unsafe { distances.set_len(width*height); }

    // Initialize first row and column values, when we come
    // across them, which is the distance from nothing to
    // every zero-index substring of the other word.
    // e.g. ("" -> "hou", "" -> "houn", "" -> "hound")
    for row in (0..height) {
        distances[row*width] = row;
    }
    for column in (0..width) {
        distances[column] = column;
    }

    // We need to manage indices manually; strings don't have an
    // index + character iterator, since indexing UTF-8 strings
    // doesn't work beyond the ASCII set. We, however, need to track
    // each substring combination, so they're useful in this scenario.
    let mut row = 1;
    let mut column = 1;
    for row_char in second.chars() {
        for column_char in first.chars() {
            if column_char == row_char {
                // When the strings share a common character, there's
                // no additional cost; we carry forward the optimum edit
                // distance we calculated without having considered it.
                distances[row*width + column] = distances[(row-1)*width + (column-1)];
            } else {
                distances[row*width + column] = *[
                    // Cost of removing a character from the first word.
                    distances[(row-1)*width + column] + 1,

                    // Cost of adding a character to the first word.
                    distances[row*width + (column-1)] + 1,

                    // Cost of substituting the character for another.
                    distances[(row-1)*width + (column-1)] + 1
                ].iter().min().unwrap();
            }
            column += 1;
        }
        row += 1;
        column = 1;
    }

    // The optimal edit distance is always in the
    // lower-right corner of the distance matrix.
    return distances[width*height-1]
}

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

    #[test]
    fn edit_distance_is_correct_for_removing_a_character() {
        assert_eq!(edit_distance("hound", "hounds"), 1);
    }

    #[test]
    fn edit_distance_is_correct_for_adding_a_character() {
        assert_eq!(edit_distance("hounds", "hound"), 1);
    }

    #[test]
    fn edit_distance_is_correct_for_substitutions() {
        assert_eq!(edit_distance("hound", "mound"), 1);
    }
}
<|endoftext|>


<commit_before>use arrayvec::ArrayString;
use petgraph::graphmap::DiGraphMap;
use std::cmp::{Ord, Ordering};
use std::hash::{Hash, Hasher};

/// Determines the maximum length of a module's path.
///
/// eg: `"my_crate::foo::bar::baz"`.
const MOD_PATH_SIZE: usize = 200;

const SELF_KEYWORD: &str = "self";

const SEP: &str = "::";

#[derive(Clone, Debug, PartialEq)]
pub struct Dependency {
    refers_to_all: bool,
    refers_to_mod: bool,
    referred_members: Vec<String>,
}

impl Dependency {
    pub fn module() -> Self {
        Self {
            refers_to_all: false,
            refers_to_mod: true,
            referred_members: vec![],
        }
    }

    pub fn all() -> Self {
        Self {
            refers_to_all: true,
            refers_to_mod: false,
            referred_members: vec![],
        }
    }

    pub fn members(mut members: Vec<String>) -> Self {
        let refers_to_mod: bool = members.contains(&String::from(SELF_KEYWORD));
        let referred_members: Vec<String> =
            members.drain(..).filter(|m| m != SELF_KEYWORD).collect();
        Self {
            refers_to_all: false,
            refers_to_mod,
            referred_members,
        }
    }
}

/// Represents an association between modules.
#[derive(Clone, Debug, PartialEq)]
pub enum Edge {
    Child,
    Dependency(Dependency),
}

/// Builds a graph, `DiGraphMap<Mod, Edge>` to be specific using domain
/// specific operations.
pub struct GraphBuilder {
    graph: DiGraphMap<Mod, Edge>,
    deferred_deps: Vec<(String, String, Dependency)>,
}

impl GraphBuilder {
    pub fn new() -> Self {
        Self {
            graph: DiGraphMap::new(),
            deferred_deps: vec![],
        }
    }

    /// Define a public module that has no parent.
    ///
    /// # Panics
    /// If `name` contains `"::"`.
    pub fn add_crate_root(&mut self, name: &str) {
        assert!(!name.contains(SEP));
        self.graph.add_node(Mod::new(name, Visibility::Public));
    }

    /// Define a sub-modules and associate it with its parent.
    ///
    /// # Panics
    /// - If the parent is not already defined.
    /// - If parent-child relationship for this pair is already defined.
    pub fn add_mod(&mut self, path: &str, name: &str, visibility: Visibility) {
        let parent: Mod = self.find_mod(path).unwrap();
        let node = Mod::new(&[path, SEP, name].concat(), visibility);
        self.graph.add_node(node);
        assert!(self.graph.add_edge(parent, node, Edge::Child).is_none());
        self.apply_deferred();
    }

    pub fn add_dep(&mut self, from: &str, to: &str, dependency: Dependency) {
        assert!(from != to, "Module cannot depend on itself");
        match (self.find_mod(from), self.find_mod(to)) {
            (Some(from), Some(to)) => {
                self.graph.add_edge(from, to, Edge::Dependency(dependency));
            }
            (None, _) => panic!("Trying to add dependency from an unknown module"),
            // Defer creating dependency link if
            // one of the nodes are not defined yet.
            (_, _) => self
                .deferred_deps
                .push((from.to_owned(), to.to_owned(), dependency)),
        };
    }

    /// Build the graph, consuming this builder, or return an error.
    pub fn build(mut self) -> Result<DiGraphMap<Mod, Edge>, GraphError> {
        if self.deferred_deps.is_empty() {
            Ok(self.graph)
        } else {
            let (from, to, _) = self.deferred_deps.remove(0);
            match self.find_mod(&from) {
                Some(_) => Err(GraphError::UnknownModule(to)),
                None => Err(GraphError::UnknownModule(from)),
            }
        }
    }

    fn apply_deferred(&mut self) {
        let deferred: Vec<(String, String, Dependency)> = self.deferred_deps.drain(..).collect();
        for (from, to, dep) in deferred {
            // We are only checking `to` because a dependent module
            // needs to be defined before the dependency is defined.
            if self.find_mod(&to).is_some() {
                self.add_dep(&from, &to, dep);
            } else {
                self.deferred_deps.push((from, to, dep));
            }
        }
    }

    fn find_mod(&self, path: &str) -> Option<Mod> {
        self.graph.nodes().find(|m| m.path() == path)
    }
}

#[derive(Debug, PartialEq)]
pub enum GraphError {
    UnknownModule(String),
}

/// Represents a node that is a module in the graph.
#[derive(Clone, Copy, Debug)]
pub struct Mod {
    /// Because this struct needs to be `Copy`, using `String` or `&str` was
    /// out of the question.  `ArrayString` provides a sized and owned string
    /// that is backed by a byte array.
    ///
    /// See also [MOD_PATH_SIZE]
    path: ArrayString<[u8; MOD_PATH_SIZE]>,
    name_ridx: usize,
    visibility: Visibility,
}

impl Mod {
    fn new(path: &str, visibility: Visibility) -> Self {
        Self {
            path: ArrayString::<[u8; MOD_PATH_SIZE]>::from(path)
                .unwrap_or_else(|_| panic!("Module path is too long")),
            name_ridx: path.rfind(SEP).unwrap_or(0),
            visibility,
        }
    }

    fn path(&self) -> &str {
        &self.path.as_str()
    }
}

impl Eq for Mod {}

impl Hash for Mod {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.path().hash(state);
    }
}

impl Ord for Mod {
    fn cmp(&self, other: &Mod) -> Ordering {
        self.path().cmp(&other.path())
    }
}

impl PartialEq for Mod {
    fn eq(&self, other: &Mod) -> bool {
        self.path() == other.path()
    }
}

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

#[derive(Clone, Copy, Debug)]
pub enum Visibility {
    Public,
    Private,
}

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

    #[test]
    fn new_builder_produces_an_empty_directed_graph() {
        let builder = GraphBuilder::new();
        let graph: DiGraphMap<Mod, Edge> = builder.build().unwrap();
        assert_eq!(0, graph.node_count());
        assert_eq!(0, graph.edge_count());
    }

    #[test]
    fn add_crate_root_adds_a_node() {
        let mut builder = GraphBuilder::new();
        builder.add_crate_root("crate-root");
        let graph: DiGraphMap<Mod, Edge> = builder.build().unwrap();
        assert_eq!(1, graph.node_count());
        assert_eq!(0, graph.edge_count());
        assert!(graph.contains_node(Mod::new("crate-root", Visibility::Public)));
    }

    #[test]
    fn add_mod_creates_an_association_with_parent() {
        let foo: Mod = Mod::new("foo", Visibility::Public);
        let bar: Mod = Mod::new("foo::bar", Visibility::Public);
        let baz: Mod = Mod::new("foo::bar::baz", Visibility::Private);
        let mut builder = GraphBuilder::new();
        builder.add_crate_root("foo");
        builder.add_mod("foo", "bar", Visibility::Public);
        builder.add_mod("foo::bar", "baz", Visibility::Private);
        let graph: DiGraphMap<Mod, Edge> = builder.build().unwrap();
        assert_eq!(3, graph.node_count());
        assert_eq!(2, graph.edge_count());
        assert!(graph.contains_node(foo));
        assert!(graph.contains_node(bar));
        assert!(graph.contains_node(baz));
        assert_eq!(
            vec![(foo, bar, &Edge::Child), (bar, baz, &Edge::Child)],
            graph.all_edges().collect::<Vec<(Mod, Mod, &Edge)>>()
        );
    }

    #[test]
    #[should_panic(expected = "Module path is too long")]
    fn add_mod_panics_if_path_is_longer_than_limit() {
        let name = "foo";
        let path = std::str::from_utf8([114; MOD_PATH_SIZE - 4].as_ref()).unwrap(); // 'r'
        let concatenated = format!("{}::{}", path, name);
        assert!(concatenated.len() > MOD_PATH_SIZE);
        let mut builder = GraphBuilder::new();
        builder.add_crate_root(path);
        builder.add_mod(path, name, Visibility::Public);
    }

    #[test]
    #[should_panic(expected = "Module cannot depend on itself")]
    fn adding_a_dependency_to_the_same_module_panics() {
        let mut builder = GraphBuilder::new();
        builder.add_crate_root("root");
        builder.add_mod("root", "sub", Visibility::Public);
        builder.add_dep("root::sub", "root::sub", Dependency::module());
    }

    #[test]
    fn adding_a_dependency_is_idempotent() {
        let mut builder = GraphBuilder::new();
        builder.add_crate_root("foo");
        builder.add_mod("foo", "bar", Visibility::Public);
        builder.add_mod("foo", "baz", Visibility::Private);
        builder.add_dep("foo::bar", "foo::baz", Dependency::module());
        builder.add_dep("foo::bar", "foo::baz", Dependency::module());
        let graph = builder.build().unwrap();
        assert_eq!(3, graph.edge_count());
    }

    #[test]
    fn add_dep_requires_both_modules_to_be_defined() {
        {
            let mut builder = GraphBuilder::new();
            builder.add_crate_root("foo");
            builder.add_mod("foo", "bar", Visibility::Public);
            builder.add_dep("foo::bar", "foo::baz", Dependency::module());
            assert_eq!(
                Some(GraphError::UnknownModule(String::from("foo::baz"))),
                builder.build().err()
            );
        }
        {
            let mut builder = GraphBuilder::new();
            builder.add_crate_root("foo");
            builder.add_mod("foo", "bar", Visibility::Private);
            builder.add_dep("foo::bar", "foo::baz", Dependency::module());
            builder.add_dep("foo::bar", "foo::fubar", Dependency::module());
            builder.add_mod("foo", "baz", Visibility::Private);
            assert_eq!(
                Some(GraphError::UnknownModule(String::from("foo::fubar"))),
                builder.build().err()
            );
        }
    }

    #[test]
    #[should_panic(expected = "Trying to add dependency from an unknown module")]
    fn dependency_from_unknown_module_panics() {
        {
            let mut builder = GraphBuilder::new();
            builder.add_crate_root("foo");
            builder.add_dep("foo::bar", "foo::baz", Dependency::module());
        }
    }

    #[test]
    fn dependency_can_be_added_before_dependent_module_is_added() {
        let mut builder = GraphBuilder::new();
        builder.add_crate_root("foo");
        builder.add_mod("foo", "bar", Visibility::Public);
        builder.add_dep("foo::bar", "foo::baz", Dependency::module());
        builder.add_mod("foo", "baz", Visibility::Public);
        assert_eq!(3, builder.build().unwrap().edge_count());
    }
}
<commit_msg>Rename graph::Mod as graph::Module<commit_after>use arrayvec::ArrayString;
use petgraph::graphmap::DiGraphMap;
use std::cmp::{Ord, Ordering};
use std::hash::{Hash, Hasher};

/// Determines the maximum length of a module's path.
///
/// eg: `"my_crate::foo::bar::baz"`.
const MOD_PATH_SIZE: usize = 200;

const SELF_KEYWORD: &str = "self";

const SEP: &str = "::";

#[derive(Clone, Debug, PartialEq)]
pub struct Dependency {
    refers_to_all: bool,
    refers_to_mod: bool,
    referred_members: Vec<String>,
}

impl Dependency {
    pub fn module() -> Self {
        Self {
            refers_to_all: false,
            refers_to_mod: true,
            referred_members: vec![],
        }
    }

    pub fn all() -> Self {
        Self {
            refers_to_all: true,
            refers_to_mod: false,
            referred_members: vec![],
        }
    }

    pub fn members(mut members: Vec<String>) -> Self {
        let refers_to_mod: bool = members.contains(&String::from(SELF_KEYWORD));
        let referred_members: Vec<String> =
            members.drain(..).filter(|m| m != SELF_KEYWORD).collect();
        Self {
            refers_to_all: false,
            refers_to_mod,
            referred_members,
        }
    }
}

/// Represents an association between modules.
#[derive(Clone, Debug, PartialEq)]
pub enum Edge {
    Child,
    Dependency(Dependency),
}

/// Builds a graph, `DiGraphMap<Mod, Edge>` to be specific using domain
/// specific operations.
pub struct GraphBuilder {
    graph: DiGraphMap<Module, Edge>,
    deferred_deps: Vec<(String, String, Dependency)>,
}

impl GraphBuilder {
    pub fn new() -> Self {
        Self {
            graph: DiGraphMap::new(),
            deferred_deps: vec![],
        }
    }

    /// Define a public module that has no parent.
    ///
    /// # Panics
    /// If `name` contains `"::"`.
    pub fn add_crate_root(&mut self, name: &str) {
        assert!(!name.contains(SEP));
        self.graph.add_node(Module::new(name, Visibility::Public));
    }

    /// Define a sub-modules and associate it with its parent.
    ///
    /// # Panics
    /// - If the parent is not already defined.
    /// - If parent-child relationship for this pair is already defined.
    pub fn add_mod(&mut self, path: &str, name: &str, visibility: Visibility) {
        let parent: Module = self.find_mod(path).unwrap();
        let node = Module::new(&[path, SEP, name].concat(), visibility);
        self.graph.add_node(node);
        assert!(self.graph.add_edge(parent, node, Edge::Child).is_none());
        self.apply_deferred();
    }

    pub fn add_dep(&mut self, from: &str, to: &str, dependency: Dependency) {
        assert!(from != to, "Module cannot depend on itself");
        match (self.find_mod(from), self.find_mod(to)) {
            (Some(from), Some(to)) => {
                self.graph.add_edge(from, to, Edge::Dependency(dependency));
            }
            (None, _) => panic!("Trying to add dependency from an unknown module"),
            // Defer creating dependency link if
            // one of the nodes are not defined yet.
            (_, _) => self
                .deferred_deps
                .push((from.to_owned(), to.to_owned(), dependency)),
        };
    }

    /// Build the graph, consuming this builder, or return an error.
    pub fn build(mut self) -> Result<DiGraphMap<Module, Edge>, GraphError> {
        if self.deferred_deps.is_empty() {
            Ok(self.graph)
        } else {
            let (from, to, _) = self.deferred_deps.remove(0);
            match self.find_mod(&from) {
                Some(_) => Err(GraphError::UnknownModule(to)),
                None => Err(GraphError::UnknownModule(from)),
            }
        }
    }

    fn apply_deferred(&mut self) {
        let deferred: Vec<(String, String, Dependency)> = self.deferred_deps.drain(..).collect();
        for (from, to, dep) in deferred {
            // We are only checking `to` because a dependent module
            // needs to be defined before the dependency is defined.
            if self.find_mod(&to).is_some() {
                self.add_dep(&from, &to, dep);
            } else {
                self.deferred_deps.push((from, to, dep));
            }
        }
    }

    fn find_mod(&self, path: &str) -> Option<Module> {
        self.graph.nodes().find(|m| m.path() == path)
    }
}

#[derive(Debug, PartialEq)]
pub enum GraphError {
    UnknownModule(String),
}

/// Represents a node that is a module in the graph.
#[derive(Clone, Copy, Debug)]
pub struct Module {
    /// Because this struct needs to be `Copy`, using `String` or `&str` was
    /// out of the question.  `ArrayString` provides a sized and owned string
    /// that is backed by a byte array.
    ///
    /// See also [MOD_PATH_SIZE]
    path: ArrayString<[u8; MOD_PATH_SIZE]>,
    name_ridx: usize,
    visibility: Visibility,
}

impl Module {
    fn new(path: &str, visibility: Visibility) -> Self {
        Self {
            path: ArrayString::<[u8; MOD_PATH_SIZE]>::from(path)
                .unwrap_or_else(|_| panic!("Module path is too long")),
            name_ridx: path.rfind(SEP).unwrap_or(0),
            visibility,
        }
    }

    fn path(&self) -> &str {
        &self.path.as_str()
    }
}

impl Eq for Module {}

impl Hash for Module {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.path().hash(state);
    }
}

impl Ord for Module {
    fn cmp(&self, other: &Self) -> Ordering {
        self.path().cmp(&other.path())
    }
}

impl PartialEq for Module {
    fn eq(&self, other: &Self) -> bool {
        self.path() == other.path()
    }
}

impl PartialOrd for Module {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[derive(Clone, Copy, Debug)]
pub enum Visibility {
    Public,
    Private,
}

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

    #[test]
    fn new_builder_produces_an_empty_directed_graph() {
        let builder = GraphBuilder::new();
        let graph: DiGraphMap<Module, Edge> = builder.build().unwrap();
        assert_eq!(0, graph.node_count());
        assert_eq!(0, graph.edge_count());
    }

    #[test]
    fn add_crate_root_adds_a_node() {
        let mut builder = GraphBuilder::new();
        builder.add_crate_root("crate-root");
        let graph: DiGraphMap<Module, Edge> = builder.build().unwrap();
        assert_eq!(1, graph.node_count());
        assert_eq!(0, graph.edge_count());
        assert!(graph.contains_node(Module::new("crate-root", Visibility::Public)));
    }

    #[test]
    fn add_mod_creates_an_association_with_parent() {
        let foo: Module = Module::new("foo", Visibility::Public);
        let bar: Module = Module::new("foo::bar", Visibility::Public);
        let baz: Module = Module::new("foo::bar::baz", Visibility::Private);
        let mut builder = GraphBuilder::new();
        builder.add_crate_root("foo");
        builder.add_mod("foo", "bar", Visibility::Public);
        builder.add_mod("foo::bar", "baz", Visibility::Private);
        let graph: DiGraphMap<Module, Edge> = builder.build().unwrap();
        assert_eq!(3, graph.node_count());
        assert_eq!(2, graph.edge_count());
        assert!(graph.contains_node(foo));
        assert!(graph.contains_node(bar));
        assert!(graph.contains_node(baz));
        assert_eq!(
            vec![(foo, bar, &Edge::Child), (bar, baz, &Edge::Child)],
            graph.all_edges().collect::<Vec<(Module, Module, &Edge)>>()
        );
    }

    #[test]
    #[should_panic(expected = "Module path is too long")]
    fn add_mod_panics_if_path_is_longer_than_limit() {
        let name = "foo";
        let path = std::str::from_utf8([114; MOD_PATH_SIZE - 4].as_ref()).unwrap(); // 'r'
        let concatenated = format!("{}::{}", path, name);
        assert!(concatenated.len() > MOD_PATH_SIZE);
        let mut builder = GraphBuilder::new();
        builder.add_crate_root(path);
        builder.add_mod(path, name, Visibility::Public);
    }

    #[test]
    #[should_panic(expected = "Module cannot depend on itself")]
    fn adding_a_dependency_to_the_same_module_panics() {
        let mut builder = GraphBuilder::new();
        builder.add_crate_root("root");
        builder.add_mod("root", "sub", Visibility::Public);
        builder.add_dep("root::sub", "root::sub", Dependency::module());
    }

    #[test]
    fn adding_a_dependency_is_idempotent() {
        let mut builder = GraphBuilder::new();
        builder.add_crate_root("foo");
        builder.add_mod("foo", "bar", Visibility::Public);
        builder.add_mod("foo", "baz", Visibility::Private);
        builder.add_dep("foo::bar", "foo::baz", Dependency::module());
        builder.add_dep("foo::bar", "foo::baz", Dependency::module());
        let graph = builder.build().unwrap();
        assert_eq!(3, graph.edge_count());
    }

    #[test]
    fn add_dep_requires_both_modules_to_be_defined() {
        {
            let mut builder = GraphBuilder::new();
            builder.add_crate_root("foo");
            builder.add_mod("foo", "bar", Visibility::Public);
            builder.add_dep("foo::bar", "foo::baz", Dependency::module());
            assert_eq!(
                Some(GraphError::UnknownModule(String::from("foo::baz"))),
                builder.build().err()
            );
        }
        {
            let mut builder = GraphBuilder::new();
            builder.add_crate_root("foo");
            builder.add_mod("foo", "bar", Visibility::Private);
            builder.add_dep("foo::bar", "foo::baz", Dependency::module());
            builder.add_dep("foo::bar", "foo::fubar", Dependency::module());
            builder.add_mod("foo", "baz", Visibility::Private);
            assert_eq!(
                Some(GraphError::UnknownModule(String::from("foo::fubar"))),
                builder.build().err()
            );
        }
    }

    #[test]
    #[should_panic(expected = "Trying to add dependency from an unknown module")]
    fn dependency_from_unknown_module_panics() {
        {
            let mut builder = GraphBuilder::new();
            builder.add_crate_root("foo");
            builder.add_dep("foo::bar", "foo::baz", Dependency::module());
        }
    }

    #[test]
    fn dependency_can_be_added_before_dependent_module_is_added() {
        let mut builder = GraphBuilder::new();
        builder.add_crate_root("foo");
        builder.add_mod("foo", "bar", Visibility::Public);
        builder.add_dep("foo::bar", "foo::baz", Dependency::module());
        builder.add_mod("foo", "baz", Visibility::Public);
        assert_eq!(3, builder.build().unwrap().edge_count());
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashMap};

use super::{lookups};
use super::{hand_rank};

use cards::card::{Card};
use cards::deck::{Deck};

use super::{HandRank};
use super::types::{InternalCardRepresentation};
use super::utils::{card_to_deck_number};

use holdem::{HandRankClass};

fn findit(key: usize) -> usize {
    let mut low = 0;
    let mut high = 4887;
    let mut mid;

    while low <= high {
        mid = (high+low) >> 1; // divide by two

        if key < lookups::PRODUCTS[mid] as usize {
            high = mid - 1;
        } else if key > lookups::PRODUCTS[mid] as usize {
            low = mid + 1;
        } else {
            return mid;
        }
    }

    panic!("No match found")
}

pub fn eval_5cards(cards: [&Card; 5]) -> HandRank {
    let c1 = card_to_deck_number(cards[0]);
    let c2 = card_to_deck_number(cards[1]);
    let c3 = card_to_deck_number(cards[2]);
    let c4 = card_to_deck_number(cards[3]);
    let c5 = card_to_deck_number(cards[4]);

    let q : usize = ((c1 | c2 | c3 | c4 | c5) as usize) >> 16;

    if (c1 & c2 & c3 & c4 & c5 & 0xf000) != 0 {
        return lookups::FLUSHES[q] as HandRank;
    }
    let s = lookups::UNIQUE_5[q] as HandRank;
    if s != 0 {
        return s;
    }

    let q =
        ((c1 & 0xff) * (c2 & 0xff) * (c3 & 0xff) * (c4 & 0xff) * (c5 & 0xff))
        as usize;
    let lookup = findit(q);
    lookups::VALUES[lookup] as HandRank
}

pub fn eval_7cards(cards: [&Card; 7]) -> HandRank {
    let mut tmp;
    let mut best = 9999;
    for ids in lookups::PERM_7.iter() {
        let subhand : [&Card; 5] = [
                cards[ids[0] as usize],
                cards[ids[1] as usize],
                cards[ids[2] as usize],
                cards[ids[3] as usize],
                cards[ids[4] as usize]
         ];

        tmp = eval_5cards(subhand);
        if tmp < best {
            best = tmp;
        }
    }

    best
}

#[test]
fn evaluate_all_possible_5_card_combinations() {
    let mut deck = Deck::new();
    let mut cards : Vec<Card> = Vec::new();

    // this could be made faster, by creating a function that works on raw-card-representations and translating
    // the deck cards into it
    for _ in 0..52 {
        let card = deck.draw();
        cards.push(card);
    }

    //let mut rank_class_count : HashMap<HandRankClass, usize> = HashMap::new();
    //let mut rank_count : HashMap<HandRank, bool> = HashMap::new();

    // 2,598,960 unique poker hands
    for i1 in 0..52 {
        for i2 in (i1+1)..52 {
            for i3 in (i2+1)..52 {
                for i4 in (i3+1)..52 {
                    for i5 in (i4+1)..52 {
                        let c1 = &cards[i1];
                        let c2 = &cards[i2];
                        let c3 = &cards[i3];
                        let c4 = &cards[i4];
                        let c5 = &cards[i5];

                        let rank = eval_5cards([c1, c2, c3, c4, c5]);
                        let rank_class = hand_rank(rank); //TODO: is this a move?

                        //rank_count.insert(rank, true);

                        //if !rank_class_count.contains_key(&rank_class) {
                        //    rank_class_count.insert(rank_class, 1);
                        //} else {
                        //    let cur_count = rank_class_count.get(rank_class);
                        //    rank_class_count.insert(rank_class, cur_count+1);
                        //}
                    }
                }
            }
        }
    }

    //assert_eq!(rank_class_count.get(HandRankClass::HighCard).unwrap(), 0);
    //assert_eq!(rank_class_count.get(HandRankClass::OnePair).unwrap(), 0);
    //assert_eq!(rank_class_count.get(HandRankClass::TwoPair).unwrap(), 0);
    //assert_eq!(rank_class_count.get(HandRankClass::ThreeOfAKind).unwrap(), 0);
    //assert_eq!(rank_class_count.get(HandRankClass::Straight).unwrap(), 0);
    //assert_eq!(rank_class_count.get(HandRankClass::Flush).unwrap(), 0);
    //assert_eq!(rank_class_count.get(HandRankClass::FullHouse).unwrap(), 0);
    //assert_eq!(rank_class_count.get(HandRankClass::FourOfAKind).unwrap(), 0);
    //assert_eq!(rank_class_count.get(HandRankClass::StraightFlush).unwrap(), 0);

    // there should be 7462 unique ranks, according to the hand_rank function
    //TODO: rank_count len == 7462
}
<commit_msg>A bit cleaner and uglier at the same time. But hey, test coverage!<commit_after>use super::{lookups};

use cards::card::{Card};

use super::{HandRank};
use super::utils::{card_to_deck_number};

fn findit(key: usize) -> usize {
    let mut low = 0;
    let mut high = 4887;
    let mut mid;

    while low <= high {
        mid = (high+low) >> 1; // divide by two

        if key < lookups::PRODUCTS[mid] as usize {
            high = mid - 1;
        } else if key > lookups::PRODUCTS[mid] as usize {
            low = mid + 1;
        } else {
            return mid;
        }
    }

    panic!("No match found")
}

pub fn eval_5cards(cards: [&Card; 5]) -> HandRank {
    let c1 = card_to_deck_number(cards[0]);
    let c2 = card_to_deck_number(cards[1]);
    let c3 = card_to_deck_number(cards[2]);
    let c4 = card_to_deck_number(cards[3]);
    let c5 = card_to_deck_number(cards[4]);

    let q : usize = ((c1 | c2 | c3 | c4 | c5) as usize) >> 16;

    if (c1 & c2 & c3 & c4 & c5 & 0xf000) != 0 {
        return lookups::FLUSHES[q] as HandRank;
    }
    let s = lookups::UNIQUE_5[q] as HandRank;
    if s != 0 {
        return s;
    }

    let q =
        ((c1 & 0xff) * (c2 & 0xff) * (c3 & 0xff) * (c4 & 0xff) * (c5 & 0xff))
        as usize;
    let lookup = findit(q);
    lookups::VALUES[lookup] as HandRank
}

pub fn eval_7cards(cards: [&Card; 7]) -> HandRank {
    let mut tmp;
    let mut best = 9999;
    for ids in lookups::PERM_7.iter() {
        let subhand : [&Card; 5] = [
                cards[ids[0] as usize],
                cards[ids[1] as usize],
                cards[ids[2] as usize],
                cards[ids[3] as usize],
                cards[ids[4] as usize]
         ];

        tmp = eval_5cards(subhand);
        if tmp < best {
            best = tmp;
        }
    }

    best
}

#[cfg(test)]
mod tests {
    use std::collections::{HashMap};

    use cards::deck::{Deck};
    use cards::card::{Card};
    use holdem::{HandRankClass};

    use super::super::{hand_rank}; //TODO this is kind of ugly
    use super::super::{HandRank};

    use super::{eval_5cards};

    // TODO: this is not really specific to this evaluation method. It could as well live in the library tests folder
    // the reason it is here, is due to the internal representation hackage which got ditched
    #[test]
    fn evaluate_all_possible_5_card_combinations() {
        let mut deck = Deck::new();
        let mut cards : Vec<Card> = Vec::new();

        // this could be made faster, by creating a function that works on raw-card-representations and translating
        // the deck cards into it
        for _ in 0..52 {
            let card = deck.draw();
            cards.push(card);
        }

        let mut rank_class_count : HashMap<HandRankClass, usize> = HashMap::new();
        let mut rank_count : HashMap<HandRank, bool> = HashMap::new();

        // 2,598,960 unique poker hands
        for i1 in 0..52 {
            for i2 in (i1+1)..52 {
                for i3 in (i2+1)..52 {
                    for i4 in (i3+1)..52 {
                        for i5 in (i4+1)..52 {
                            let c1 = &cards[i1];
                            let c2 = &cards[i2];
                            let c3 = &cards[i3];
                            let c4 = &cards[i4];
                            let c5 = &cards[i5];

                            let rank = eval_5cards([c1, c2, c3, c4, c5]);
                            let rank_class = hand_rank(rank); //TODO: is this a move?

                            // increment maps
                            rank_count.entry(rank).or_insert(true);

                            let count = rank_class_count.entry(rank_class).or_insert(0);
                            *count += 1;
                        }
                    }
                }
            }
        }

        // TODO: we might compare the numbers of expected combinations here or output them in a similar fashion
        //assert_eq!(*rank_class_count.get(&HandRankClass::HighCard).unwrap(), 1277);
        //assert_eq!(*rank_class_count.get(&HandRankClass::OnePair).unwrap(), 2860);
        //assert_eq!(*rank_class_count.get(&HandRankClass::TwoPair).unwrap(), 858);
        //assert_eq!(*rank_class_count.get(&HandRankClass::ThreeOfAKind).unwrap(), 858);
        //assert_eq!(*rank_class_count.get(&HandRankClass::Straight).unwrap(), 10);
        //assert_eq!(*rank_class_count.get(&HandRankClass::Flush).unwrap(), 1277);
        //assert_eq!(*rank_class_count.get(&HandRankClass::FullHouse).unwrap(), 156);
        //assert_eq!(*rank_class_count.get(&HandRankClass::FourOfAKind).unwrap(), 156);
        //assert_eq!(*rank_class_count.get(&HandRankClass::StraightFlush).unwrap(), 10);

        // there should be 7462 unique ranks, in accordance with the hand_rank function
        assert_eq!(rank_count.len(), 7462);
    }
}

<|endoftext|>


<commit_before>/*!
# Examples

```
let pos = Position::new(640, 480);

let mulpl = &pos * 2;
assert!(mulpl.x() == 640 * 2);
assert!(mulpl.y() == 480 * 2);

```

```
extern crate bwapi_sys;

let pos = Position::new(640, 480);
let walk_pos = WalkPosition::from(pos);
// or #![feature(type_ascription)]
//    let walk_pos = pos.into() : WalkPosition;
let sys_walk_pos: bwapi_sys::WalkPosition = walkpos.into();
```
*/

use bwapi_sys as sys;

use std::ops::Add;
use std::ops::Sub;
use std::ops::Mul;
use std::ops::Div;

pub trait Point {
    fn x(&self) -> isize;
    fn y(&self) -> isize;
    fn scale()  -> isize;

    /// The length of this point from (0,0)
    fn length(&self) -> f64 {
        let x = self.x().pow(2);
        let y = self.y().pow(2);
        ((x + y) as f64).sqrt()
    }
}

macro_rules! create_point_type {
    ($(#[$attr_struct:meta])* struct $name:ident $(#[$attr_scale:meta])* scale: $scale:expr) => {
        $(#[$attr_struct])*
        #[derive(Eq, PartialEq, Debug)]
        pub struct $name {
            x: isize,
            y: isize
        }
        impl $name {
            pub fn new(x: isize, y: isize) -> $name {
                Self { x, y }
            }
            /// The distance between this point and position.
            pub fn distance<'a>(&'a self, position: &'a Self) -> f64 {
                (self - position).length()
            }
        }
        impl Point for $name {
            fn x(&self) -> isize { self.x }
            fn y(&self) -> isize { self.y }
            $(#[$attr_scale])*
            fn scale()  -> isize { $scale }
        }
        impl From<sys::$name> for $name {
            fn from(sys_pos: sys::$name) -> $name {
                Self { x: sys_pos.x as isize, y: sys_pos.y as isize }
            }
        }
        impl From<$name> for sys::$name {
            fn from(pos: $name) -> sys::$name {
                Self { x: pos.x as i32, y: pos.y as i32 }
            }
        }
    };
}

create_point_type!(
    /// Indicates a position that is `1×1` pixel in size. This is the most precise position type.
    struct Position
    /// The scale of a [`Position`](#struct.Position). Each position corresponds to a 1x1 pixel area.
    scale: 1
);
create_point_type!(
    /// Indicates a position that is `8×8` pixels in size.
    struct WalkPosition
    /// The scale of a [`WalkPosition`](#struct.WalkPosition). Each walk position corresponds to an 8x8 pixel area.
    scale: 8
);
create_point_type!(
    /// Indicates a position that is `32×32` pixels in size.
    struct TilePosition
    /// The scale of a [`TilePosition`](#struct.TilePosition). Each tile position corresponds to a 32x32 pixel area.
    scale: 32
);

macro_rules! create_position_cast {
    ( $bigger:ty => $smaller:ty ) => {
        impl From<$bigger> for $smaller {
            fn from(pos: $bigger) -> $smaller {
                assert!(<$bigger>::scale() > <$smaller>::scale());
                let scale = <$bigger>::scale() / <$smaller>::scale();
                Self { x: pos.x() * scale, y: pos.y() * scale }
            }
        }
        impl From<$smaller> for $bigger {
            fn from(pos: $smaller) -> $bigger {
                assert!(<$bigger>::scale() > <$smaller>::scale());
                let scale = <$bigger>::scale() / <$smaller>::scale();
                Self { x: pos.x() / scale, y: pos.y() / scale }
            }
        }
    };
}

create_position_cast!(WalkPosition => Position);
create_position_cast!(TilePosition => Position);
create_position_cast!(TilePosition => WalkPosition);

macro_rules! create_point_ops {
    ( binary: $trait:ident method: $method:ident as $op:tt for $type:ty ) => {
        /// T op T
        impl $trait<$type> for $type {
            type Output = $type;
            fn $method(self, other: $type) -> $type {
                Self::Output { x: self.x $op other.x, y: self.y $op other.y }
            }
        }
        /// &T op T
        impl<'a> $trait<$type> for &'a $type {
            type Output = $type;
            fn $method(self, other: $type) -> $type {
                Self::Output { x: self.x $op other.x, y: self.y $op other.y }
            }
        }
        /// T op &T
        impl<'a> $trait<&'a $type> for $type {
            type Output = $type;
            fn $method(self, other: &'a $type) -> $type {
                Self::Output { x: self.x $op other.x, y: self.y $op other.y }
            }
        }
        /// &T op &T
        impl<'a, 'b> $trait<&'a $type> for &'b $type {
            type Output = $type;
            fn $method(self, other: &'a $type) -> $type {
                Self::Output { x: self.x $op other.x, y: self.y $op other.y }
            }
        }
    };
    ( scalar: $trait:ident method: $method:ident as $op:tt for $type:ty, $other:ty ) => {
        /// T op x
        impl $trait<$other> for $type {
            type Output = $type;
            fn $method(self, other: $other) -> $type {
                Self::Output { x: self.x $op other, y: self.y $op other }
            }
        }
        /// &T op x
        impl<'a> $trait<$other> for &'a $type {
            type Output = $type;
            fn $method(self, other: $other) -> $type {
                Self::Output { x: self.x $op other, y: self.y $op other }
            }
        }
        /// T op &x
        impl<'a> $trait<&'a $other> for $type {
            type Output = $type;
            fn $method(self, other: &'a $other) -> $type {
                Self::Output { x: self.x $op other, y: self.y $op other }
            }
        }
        /// &T op &x
        impl<'a, 'b> $trait<&'a $other> for &'b $type {
            type Output = $type;
            fn $method(self, other: &'a $other) -> $type {
                Self::Output { x: self.x $op other, y: self.y $op other }
            }
        }
    };
    ( $name:ty ) => {
        create_point_ops!(binary: Add method: add as + for $name );
        create_point_ops!(binary: Sub method: sub as - for $name );
        create_point_ops!(scalar: Mul method: mul as * for $name, isize);
        create_point_ops!(scalar: Div method: div as / for $name, isize);
    };
}

create_point_ops!(Position);
create_point_ops!(WalkPosition);
create_point_ops!(TilePosition);

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

    #[test]
    fn test_position_distance() {
        let p1 = Position::new(1, 2);
        let p2 = Position::new(1, 2);
        assert_approx_eq!(0.0, p2.distance(&p1));
    }

    #[test]
    fn position_add() {
        let p1 = Position::new(1, 5) + Position::new(2, 4);
        assert_eq!(p1, Position::new(3, 9));
        let p2 = &p1 + Position::new(1, 2);
        assert_eq!(p2, Position::new(4, 11));
        let p3 = p2 + &p1;
        assert_eq!(p3, Position::new(7, 20));
        let p4 = &p3 + &p1;
        assert_eq!(p4, Position::new(10, 29));
    }

    #[test]
    fn position_mul() {
        let p1 = Position::new(1, 2) * 3;
        assert_eq!(p1, Position::new(3, 6));
        let p2 = &p1 * 3;
        assert_eq!(p2, Position::new(9, 18));
        let p3 = p2 * &3;
        assert_eq!(p3, Position::new(27, 54));
        let p4 = &p3 * &2;
        assert_eq!(p4, Position::new(54, 108));
    }

    #[test]
    fn walkposition_from_position() {
        let p1 = Position::new(8, 16);
        let p2: WalkPosition = From::from(p1);
        assert_eq!(p2, WalkPosition::new(1, 2));

        let p3 = Position::new(8, 16);
        let p4: WalkPosition = p3.into();
        assert_eq!(p4, WalkPosition::new(1, 2));
    }

    #[test]
    fn position_from_walkposition() {
        let p1 = WalkPosition::new(1, 2);
        let p2: Position = From::from(p1);
        assert_eq!(p2, Position::new(8, 16));

        let p3 = WalkPosition::new(1, 2);
        let p4: Position = p3.into();
        assert_eq!(p4, Position::new(8, 16));
    }

    #[test]
    fn position_cast_sys() {
        let p1 = Position::new(32, 16);
        let sys_p1: sys::Position = From::from(p1);
        let p2: Position = sys_p1.into();
        let p3: WalkPosition = p2.into();
        assert_eq!(p3, WalkPosition::new(4, 2));
    }
}
<commit_msg>Fixes tests for Position<commit_after>/*!
# Examples

```
extern crate bwapi;
use bwapi::position::*;

let pos = Position::new(640, 480);

let mulpl = &pos * 2;
assert!(mulpl.x() == 640 * 2);
assert!(mulpl.y() == 480 * 2);

```

```
extern crate bwapi;
extern crate bwapi_sys;

use bwapi::position::*;

let pos = Position::new(640, 480);
let walk_pos = WalkPosition::from(pos);
// or #![feature(type_ascription)]
//    let walk_pos = pos.into() : WalkPosition;
let sys_walk_pos: bwapi_sys::WalkPosition = walk_pos.into();
```
*/

use bwapi_sys as sys;

use std::ops::Add;
use std::ops::Sub;
use std::ops::Mul;
use std::ops::Div;

pub trait Point {
    fn x(&self) -> isize;
    fn y(&self) -> isize;
    fn scale()  -> isize;

    /// The length of this point from (0,0)
    fn length(&self) -> f64 {
        let x = self.x().pow(2);
        let y = self.y().pow(2);
        ((x + y) as f64).sqrt()
    }
}

macro_rules! create_point_type {
    ($(#[$attr_struct:meta])* struct $name:ident $(#[$attr_scale:meta])* scale: $scale:expr) => {
        $(#[$attr_struct])*
        #[derive(Eq, PartialEq, Debug)]
        pub struct $name {
            x: isize,
            y: isize
        }
        impl $name {
            pub fn new(x: isize, y: isize) -> $name {
                Self { x, y }
            }
            /// The distance between this point and position.
            pub fn distance<'a>(&'a self, position: &'a Self) -> f64 {
                (self - position).length()
            }
        }
        impl Point for $name {
            fn x(&self) -> isize { self.x }
            fn y(&self) -> isize { self.y }
            $(#[$attr_scale])*
            fn scale()  -> isize { $scale }
        }
        impl From<sys::$name> for $name {
            fn from(sys_pos: sys::$name) -> $name {
                Self { x: sys_pos.x as isize, y: sys_pos.y as isize }
            }
        }
        impl From<$name> for sys::$name {
            fn from(pos: $name) -> sys::$name {
                Self { x: pos.x as i32, y: pos.y as i32 }
            }
        }
    };
}

create_point_type!(
    /// Indicates a position that is `1×1` pixel in size. This is the most precise position type.
    struct Position
    /// The scale of a [`Position`](#struct.Position). Each position corresponds to a 1x1 pixel area.
    scale: 1
);
create_point_type!(
    /// Indicates a position that is `8×8` pixels in size.
    struct WalkPosition
    /// The scale of a [`WalkPosition`](#struct.WalkPosition). Each walk position corresponds to an 8x8 pixel area.
    scale: 8
);
create_point_type!(
    /// Indicates a position that is `32×32` pixels in size.
    struct TilePosition
    /// The scale of a [`TilePosition`](#struct.TilePosition). Each tile position corresponds to a 32x32 pixel area.
    scale: 32
);

macro_rules! create_position_cast {
    ( $bigger:ty => $smaller:ty ) => {
        impl From<$bigger> for $smaller {
            fn from(pos: $bigger) -> $smaller {
                assert!(<$bigger>::scale() > <$smaller>::scale());
                let scale = <$bigger>::scale() / <$smaller>::scale();
                Self { x: pos.x() * scale, y: pos.y() * scale }
            }
        }
        impl From<$smaller> for $bigger {
            fn from(pos: $smaller) -> $bigger {
                assert!(<$bigger>::scale() > <$smaller>::scale());
                let scale = <$bigger>::scale() / <$smaller>::scale();
                Self { x: pos.x() / scale, y: pos.y() / scale }
            }
        }
    };
}

create_position_cast!(WalkPosition => Position);
create_position_cast!(TilePosition => Position);
create_position_cast!(TilePosition => WalkPosition);

macro_rules! create_point_ops {
    ( binary: $trait:ident method: $method:ident as $op:tt for $type:ty ) => {
        /// T op T
        impl $trait<$type> for $type {
            type Output = $type;
            fn $method(self, other: $type) -> $type {
                Self::Output { x: self.x $op other.x, y: self.y $op other.y }
            }
        }
        /// &T op T
        impl<'a> $trait<$type> for &'a $type {
            type Output = $type;
            fn $method(self, other: $type) -> $type {
                Self::Output { x: self.x $op other.x, y: self.y $op other.y }
            }
        }
        /// T op &T
        impl<'a> $trait<&'a $type> for $type {
            type Output = $type;
            fn $method(self, other: &'a $type) -> $type {
                Self::Output { x: self.x $op other.x, y: self.y $op other.y }
            }
        }
        /// &T op &T
        impl<'a, 'b> $trait<&'a $type> for &'b $type {
            type Output = $type;
            fn $method(self, other: &'a $type) -> $type {
                Self::Output { x: self.x $op other.x, y: self.y $op other.y }
            }
        }
    };
    ( scalar: $trait:ident method: $method:ident as $op:tt for $type:ty, $other:ty ) => {
        /// T op x
        impl $trait<$other> for $type {
            type Output = $type;
            fn $method(self, other: $other) -> $type {
                Self::Output { x: self.x $op other, y: self.y $op other }
            }
        }
        /// &T op x
        impl<'a> $trait<$other> for &'a $type {
            type Output = $type;
            fn $method(self, other: $other) -> $type {
                Self::Output { x: self.x $op other, y: self.y $op other }
            }
        }
        /// T op &x
        impl<'a> $trait<&'a $other> for $type {
            type Output = $type;
            fn $method(self, other: &'a $other) -> $type {
                Self::Output { x: self.x $op other, y: self.y $op other }
            }
        }
        /// &T op &x
        impl<'a, 'b> $trait<&'a $other> for &'b $type {
            type Output = $type;
            fn $method(self, other: &'a $other) -> $type {
                Self::Output { x: self.x $op other, y: self.y $op other }
            }
        }
    };
    ( $name:ty ) => {
        create_point_ops!(binary: Add method: add as + for $name );
        create_point_ops!(binary: Sub method: sub as - for $name );
        create_point_ops!(scalar: Mul method: mul as * for $name, isize);
        create_point_ops!(scalar: Div method: div as / for $name, isize);
    };
}

create_point_ops!(Position);
create_point_ops!(WalkPosition);
create_point_ops!(TilePosition);

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

    #[test]
    fn test_position_distance() {
        let p1 = Position::new(1, 2);
        let p2 = Position::new(1, 2);
        assert_approx_eq!(0.0, p2.distance(&p1));
    }

    #[test]
    fn position_add() {
        let p1 = Position::new(1, 5) + Position::new(2, 4);
        assert_eq!(p1, Position::new(3, 9));
        let p2 = &p1 + Position::new(1, 2);
        assert_eq!(p2, Position::new(4, 11));
        let p3 = p2 + &p1;
        assert_eq!(p3, Position::new(7, 20));
        let p4 = &p3 + &p1;
        assert_eq!(p4, Position::new(10, 29));
    }

    #[test]
    fn position_mul() {
        let p1 = Position::new(1, 2) * 3;
        assert_eq!(p1, Position::new(3, 6));
        let p2 = &p1 * 3;
        assert_eq!(p2, Position::new(9, 18));
        let p3 = p2 * &3;
        assert_eq!(p3, Position::new(27, 54));
        let p4 = &p3 * &2;
        assert_eq!(p4, Position::new(54, 108));
    }

    #[test]
    fn walkposition_from_position() {
        let p1 = Position::new(8, 16);
        let p2: WalkPosition = From::from(p1);
        assert_eq!(p2, WalkPosition::new(1, 2));

        let p3 = Position::new(8, 16);
        let p4: WalkPosition = p3.into();
        assert_eq!(p4, WalkPosition::new(1, 2));
    }

    #[test]
    fn position_from_walkposition() {
        let p1 = WalkPosition::new(1, 2);
        let p2: Position = From::from(p1);
        assert_eq!(p2, Position::new(8, 16));

        let p3 = WalkPosition::new(1, 2);
        let p4: Position = p3.into();
        assert_eq!(p4, Position::new(8, 16));
    }

    #[test]
    fn position_cast_sys() {
        let p1 = Position::new(32, 16);
        let sys_p1: sys::Position = From::from(p1);
        let p2: Position = sys_p1.into();
        let p3: WalkPosition = p2.into();
        assert_eq!(p3, WalkPosition::new(4, 2));
    }
}
<|endoftext|>


<commit_before>use search::Search;
use text::Text;

pub struct Renderer;

impl Renderer {
    pub fn render(&self, search: &Search) -> Vec<Text> {
        let mut result = Vec::new();
        result.push(Text::Normal(self.header(search)));

        let selection = search.selection.clone().unwrap_or("".to_string());

        for position in 0..(search.config.visible_limit - 1) {
            if position >= search.result.len() {
                result.push(Text::Blank);
                continue;
            }

            let choice = search.result[position].clone();

            if choice == selection {
                result.push(Text::Highlight(choice));
            } else {
                result.push(Text::Normal(choice))
            }
        }
        result
    }

    pub fn header(&self, search: &Search) -> String {
        format!("> {}", search.query)
    }
}

#[cfg(test)]
mod tests {
    use search::Search;
    use text::Text;
    use configuration::Configuration;
    use super::*;

    fn input() -> Vec<String> {
        vec!["one".to_string(), "two".to_string(), "three".to_string()]
    }

    #[test]
    fn it_renderes_selected_matches_with_a_highlight() {
        let input = input();
        let config = Configuration::from_inputs(&input, None, Some(3));
        let search = Search::blank(&config).down();
        let renderer = Renderer;

        let output = renderer.render(&search);

        assert_eq!(vec![Text::Normal("> ".to_string()),
                        Text::Normal("one".to_string()),
                        Text::Highlight("two".to_string())], output);
    }

    #[test]
    fn it_renders_a_missmatch() {
        let input = input();
        let config = Configuration::from_inputs(&input, None, Some(3));

        let search = Search::blank(&config).append_to_search("z");
        let renderer = Renderer;

        let output = renderer.render(&search);

        assert_eq!(vec![Text::Normal("> z".to_string()),
                        Text::Blank,
                        Text::Blank], output);
    }
}
<commit_msg>Print the current number of matches.<commit_after>use search::Search;
use text::Text;

pub struct Renderer;

impl Renderer {
    pub fn render(&self, search: &Search) -> Vec<Text> {
        let mut result = Vec::new();
        result.push(Text::Normal(self.header(search)));

        let selection = search.selection.clone().unwrap_or("".to_string());

        for position in 0..(search.config.visible_limit - 1) {
            if position >= search.result.len() {
                result.push(Text::Blank);
                continue;
            }

            let choice = search.result[position].clone();

            if choice == selection {
                result.push(Text::Highlight(choice));
            } else {
                result.push(Text::Normal(choice))
            }
        }
        result
    }

    pub fn header(&self, search: &Search) -> String {
        format!("{} > {}", search.result.len(), search.query)
    }
}

#[cfg(test)]
mod tests {
    use search::Search;
    use text::Text;
    use configuration::Configuration;
    use super::*;

    fn input() -> Vec<String> {
        vec!["one".to_string(), "two".to_string(), "three".to_string()]
    }

    #[test]
    fn it_renderes_selected_matches_with_a_highlight() {
        let input = input();
        let config = Configuration::from_inputs(&input, None, Some(3));
        let search = Search::blank(&config).down();
        let renderer = Renderer;

        let output = renderer.render(&search);

        assert_eq!(vec![Text::Normal("3 > ".to_string()),
                        Text::Normal("one".to_string()),
                        Text::Highlight("two".to_string())], output);
    }

    #[test]
    fn it_renders_a_missmatch() {
        let input = input();
        let config = Configuration::from_inputs(&input, None, Some(3));

        let search = Search::blank(&config).append_to_search("z");
        let renderer = Renderer;

        let output = renderer.render(&search);

        assert_eq!(vec![Text::Normal("0 > z".to_string()),
                        Text::Blank,
                        Text::Blank], output);
    }
}
<|endoftext|>