<commit_before>use std::collections::HashMap;
use std::{mem, time};
use std::sync::Arc;
use torrent::{Bitfield, Info, Peer};
use control::cio;

mod rarest;
mod sequential;

#[cfg(test)]
mod tests;

#[derive(Clone, Debug)]
pub struct Picker {
    /// Number of blocks per piece
    scale: u32,
    last_piece_scale: u32,
    last_piece: u32,
    /// Number of detected seeders
    seeders: u16,
    /// Set of pieces which have blocks waiting. These should be prioritized.
    downloading: HashMap<u32, Vec<Downloading>>,
    /// Bitfield of unpicked pieces, not in progress or
    /// completed yet. A set bit is picked, unset is unpicked.
    unpicked: Bitfield,
    /// The current picker in use
    picker: PickerKind,
    /// Piece priorities
    priorities: Vec<u8>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Block {
    pub index: u32,
    pub offset: u32,
}

/// Pickers act solely as piece picking algorithm.
/// They will select the optimal next piece for a peer,
/// and can be told when a piece is complete(or invalid).
#[derive(Clone, Debug)]
enum PickerKind {
    Rarest(rarest::Picker),
    Sequential(sequential::Picker),
}

/// A downloading block and the peers it has been
/// requested from.
#[derive(Clone, Debug)]
struct Downloading {
    offset: u32,
    completed: bool,
    requested: Vec<Request>,
}

/// A request to a peer and the time it was initiated.
#[derive(Clone, Debug)]
struct Request {
    peer: usize,
    requested_at: time::Instant,
}

const MAX_DUP_REQS: usize = 5;
const MAX_DL_Q: usize = 50;
const REQ_TIMEOUT: u64 = 15;

impl Picker {
    /// Creates a new picker, which will select over
    /// the given pieces. The algorithm used for selection
    /// will vary based on the current swarm state, but
    /// will default to rarest first.
    pub fn new(info: &Arc<Info>, pieces: &Bitfield, priorities: &[u8]) -> Picker {
        let scale = info.piece_len / 16_384;
        let picker = rarest::Picker::new(pieces);
        let last_piece = info.pieces().saturating_sub(1);
        let lpl = info.piece_len(last_piece);
        let last_piece_scale = if lpl % 16_384 == 0 {
            lpl / 16_384
        } else {
            lpl / 16_384 + 1
        };
        let downloading = if pieces.complete() {
            HashMap::with_capacity(0)
        } else {
            HashMap::with_capacity(info.pieces() as usize)
        };
        let mut picker = Picker {
            picker: PickerKind::Rarest(picker),
            scale,
            last_piece,
            last_piece_scale,
            seeders: 0,
            unpicked: pieces.clone(),
            downloading,
            priorities: vec![3; info.pieces() as usize],
        };
        picker.set_priorities(priorities, info);
        picker
    }

    /// Returns true if the current picker algorithm is sequential
    pub fn is_sequential(&self) -> bool {
        match self.picker {
            PickerKind::Sequential(_) => true,
            _ => false,
        }
    }

    pub fn tick(&mut self) {
        let mut expired = 0;
        for chunks in self.downloading.values_mut() {
            for chunk in chunks.iter_mut() {
                if !chunk.completed {
                    chunk.requested.retain(|req| {
                        let unexp = req.requested_at.elapsed().as_secs() < REQ_TIMEOUT;
                        if !unexp {
                            expired += 1;
                        }
                        unexp
                    })
                }
            }
        }
        if expired != 0 {
            debug!("Expired {} chunks!", expired);
        }
    }

    /// Attempts to select a block for a peer.
    pub fn pick<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        if let Some(b) = self.pick_expired(peer) {
            return Some(b);
        }
        if self.downloading.len() > MAX_DL_Q {
            if let Some(b) = self.pick_pri(peer) {
                return Some(b);
            }
        }

        let piece = match self.picker {
            PickerKind::Sequential(ref mut p) => p.pick(peer),
            PickerKind::Rarest(ref mut p) => p.pick(peer),
        };
        let res = piece
            .and_then(|p| self.pick_piece(p, peer.id()))
            .or_else(|| self.pick_downloading(peer));
        if res.is_none() && peer.pieces().complete() && !self.unpicked.complete() {
            debug_assert!(
                false,
                "Couldnt pick {:?} from a seeder for some reason!",
                piece
            );
        }
        res
    }

    /// Attempts to pick an expired block
    fn pick_expired<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        // TODO: Use some form of heuristic here to say "we expect to have
        // downloaded some pieces by X, hit the picker with a tick which checks
        // that, flags shit as invalid, and then does a double request
        None
    }

    /// Picks a block from a given piece for a peer
    fn pick_piece(&mut self, piece: u32, id: usize) -> Option<Block> {
        self.downloading.entry(piece).or_insert_with(|| vec![]);
        let dl = self.downloading.get_mut(&piece).unwrap();
        let offset = dl.len() as u32 * 16_384;
        dl.push(Downloading {
            offset,
            completed: false,
            requested: vec![Request::new(id)],
        });

        if dl.len() == self.scale as usize
            || (piece == self.last_piece && dl.len() == self.last_piece_scale as usize)
        {
            match self.picker {
                PickerKind::Sequential(ref mut p) => p.completed(piece),
                PickerKind::Rarest(ref mut p) => p.completed(piece),
            }
            self.unpicked.set_bit(u64::from(piece));
        }
        Some(Block {
            index: piece,
            offset,
        })
    }

    /// Attempts to pick the highest priority piece in the dl q
    fn pick_pri<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        let pri = &mut self.priorities;
        self.downloading
            .iter_mut()
            .max_by_key(|&(idx, _)| pri[*idx as usize])
            .and_then(|(idx, dl)| {
                dl.iter_mut()
                    .find(|r| {
                        !r.completed && r.requested.len() < MAX_DUP_REQS
                            && r.requested.iter().all(|req| req.peer != peer.id())
                    })
                    .map(|r| {
                        r.requested.push(Request::new(peer.id()));
                        Block::new(*idx, r.offset)
                    })
            })
    }

    /// Attempts to pick an already requested block
    fn pick_downloading<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        for (idx, dl) in &mut self.downloading {
            if peer.pieces().has_bit(u64::from(*idx)) {
                let r = dl.iter_mut()
                    .find(|r| {
                        !r.completed && r.requested.len() < MAX_DUP_REQS
                            && r.requested.iter().all(|req| req.peer != peer.id())
                    })
                    .map(|r| {
                        r.requested.push(Request::new(peer.id()));
                        Block::new(*idx, r.offset)
                    });
                if r.is_some() {
                    return r;
                }
            }
        }
        None
    }

    /// Marks a block as completed. Returns a result indicating if the block
    /// was actually requested, the success value containing a bool indicating
    /// if the block is complete, and a vector of peers from which the block
    /// was requested(for cancellation).
    pub fn completed(&mut self, b: Block) -> Result<(bool, Vec<usize>), ()> {
        // Find the block in our downloading blocks, mark as true,
        // and extract the current peer list for return.
        let res = self.downloading
            .get_mut(&b.index)
            .and_then(|dl| {
                dl.iter_mut()
                    .find(|r| r.offset == b.offset)
                    .map(|r| r.complete())
            })
            .map(|r| r.into_iter().map(|e| e.peer).collect());

        // If we've requested every single block for this piece and they're all complete, remove it
        // and report completion
        let scale = self.scale;
        let lp = self.last_piece;
        let lps = self.last_piece_scale;
        let complete = self.downloading
            .get_mut(&b.index)
            .map(|r| {
                (r.len() as u32 == scale || (b.index == lp && r.len() as u32 == lps))
                    && r.iter().all(|d| d.completed)
            })
            .unwrap_or(false);

        if complete {
            self.downloading.remove(&b.index);
        }

        res.map(|r| (complete, r)).ok_or(())
    }

    pub fn have_block(&mut self, b: Block) -> bool {
        self.downloading
            .get_mut(&b.index)
            .and_then(|dl| {
                dl.iter()
                    .find(|r| r.offset == b.offset)
                    .map(|r| r.completed)
            })
            .unwrap_or(false)
    }

    /// Invalidates a piece
    pub fn invalidate_piece(&mut self, idx: u32) {
        match self.picker {
            PickerKind::Sequential(ref mut p) => p.incomplete(idx),
            PickerKind::Rarest(ref mut p) => p.incomplete(idx),
        }
        self.unpicked.unset_bit(u64::from(idx));
        self.downloading.remove(&idx);
    }

    pub fn piece_available(&mut self, idx: u32) {
        if let PickerKind::Rarest(ref mut p) = self.picker {
            p.piece_available(idx);
        }
    }

    pub fn add_peer<T: cio::CIO>(&mut self, peer: &Peer<T>) {
        if peer.pieces().complete() {
            self.seeders += 1;
        } else {
            if let PickerKind::Rarest(ref mut p) = self.picker {
                p.add_peer(peer);
            }
        }
    }

    pub fn remove_peer<T: cio::CIO>(&mut self, peer: &Peer<T>) {
        // Have to consider situation where a peer became a seeder but joined as leecher.
        if peer.pieces().complete() && self.seeders > 0 {
            self.seeders -= 1;
        } else {
            if let PickerKind::Rarest(ref mut p) = self.picker {
                p.remove_peer(peer);
            }
        }

        for piece in self.downloading.values_mut() {
            for block in piece {
                block.requested.retain(|req| req.peer != peer.id())
            }
        }
    }

    /// Alters the picker to sequential/non sequential. If changing
    /// from sequential to non sequential, peer state will need to be loaded
    /// after this.
    pub fn change_picker(&mut self, sequential: bool, pieces: &Bitfield) {
        self.unpicked = pieces.clone();
        self.picker = if sequential {
            PickerKind::Sequential(sequential::Picker::new(&self.unpicked))
        } else {
            PickerKind::Rarest(rarest::Picker::new(&self.unpicked))
        };
        self.downloading.clear();
    }

    pub fn set_priorities(&mut self, pri: &[u8], info: &Arc<Info>) {
        self.unapply_priorities();
        self.priorities = generate_piece_pri(pri, info);
        self.apply_priorities();
    }

    pub fn apply_priorities(&mut self) {
        if self.is_sequential() {
            let mut pieces = [vec![], vec![], vec![], vec![], vec![], vec![]];
            for (piece, pri) in self.priorities.iter().enumerate() {
                pieces[*pri as usize].push(piece as u32);
            }
            self.picker = PickerKind::Sequential(sequential::Picker::new_pri(pieces));
        } else {
            for (piece, pri) in self.priorities.iter().enumerate() {
                if let PickerKind::Rarest(ref mut p) = self.picker {
                    for _ in 0..*pri {
                        p.piece_unavailable(piece as u32);
                    }
                }

                if *pri == 0 && !self.unpicked.has_bit(piece as u64) {
                    match self.picker {
                        PickerKind::Rarest(ref mut p) => p.completed(piece as u32),
                        _ => unreachable!(),
                    }
                }
            }
        }
    }

    pub fn unapply_priorities(&mut self) {
        if !self.is_sequential() {
            for (piece, pri) in self.priorities.iter().enumerate() {
                if let PickerKind::Rarest(ref mut p) = self.picker {
                    for _ in 0..*pri {
                        p.piece_available(piece as u32);
                    }
                }

                if *pri == 0 && !self.unpicked.has_bit(piece as u64) {
                    match self.picker {
                        PickerKind::Rarest(ref mut p) => p.incomplete(piece as u32),
                        _ => unreachable!(),
                    }
                }
            }
        }
    }
}

fn generate_piece_pri(pri: &[u8], info: &Arc<Info>) -> Vec<u8> {
    // Map piece -> priority
    let mut priorities = Vec::with_capacity(info.pieces() as usize);
    // If a piece is completely in a file, just assign that pri.
    // Otherwise mark it as the higher pri piece
    for p in 0..info.pieces() {
        let max = Info::piece_disk_locs(&info, p)
            .map(|loc| pri[loc.file])
            .max()
            .expect("Piece must have locations!");
        priorities.push(max);
    }
    priorities
}

#[cfg(test)]
impl Picker {
    pub fn new_rarest(info: &Info, pieces: &Bitfield) -> Picker {
        Picker::new(
            &Arc::new(info.clone()),
            pieces,
            &vec![3u8; info.files.len()],
        )
    }

    pub fn new_sequential(info: &Info, pieces: &Bitfield) -> Picker {
        let mut p = Picker::new(
            &Arc::new(info.clone()),
            pieces,
            &vec![3u8; info.files.len()],
        );
        p.change_picker(true);
        p
    }
}

impl Block {
    pub fn new(index: u32, offset: u32) -> Block {
        Block { index, offset }
    }
}

impl Request {
    fn new(peer: usize) -> Request {
        Request {
            peer,
            requested_at: time::Instant::now(),
        }
    }
}

impl Downloading {
    fn complete(&mut self) -> Vec<Request> {
        self.completed = true;
        mem::replace(&mut self.requested, Vec::with_capacity(0))
    }
}
<commit_msg>Fix picker tests<commit_after>use std::collections::HashMap;
use std::{mem, time};
use std::sync::Arc;
use torrent::{Bitfield, Info, Peer};
use control::cio;

mod rarest;
mod sequential;

#[cfg(test)]
mod tests;

#[derive(Clone, Debug)]
pub struct Picker {
    /// Number of blocks per piece
    scale: u32,
    last_piece_scale: u32,
    last_piece: u32,
    /// Number of detected seeders
    seeders: u16,
    /// Set of pieces which have blocks waiting. These should be prioritized.
    downloading: HashMap<u32, Vec<Downloading>>,
    /// Bitfield of unpicked pieces, not in progress or
    /// completed yet. A set bit is picked, unset is unpicked.
    unpicked: Bitfield,
    /// The current picker in use
    picker: PickerKind,
    /// Piece priorities
    priorities: Vec<u8>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Block {
    pub index: u32,
    pub offset: u32,
}

/// Pickers act solely as piece picking algorithm.
/// They will select the optimal next piece for a peer,
/// and can be told when a piece is complete(or invalid).
#[derive(Clone, Debug)]
enum PickerKind {
    Rarest(rarest::Picker),
    Sequential(sequential::Picker),
}

/// A downloading block and the peers it has been
/// requested from.
#[derive(Clone, Debug)]
struct Downloading {
    offset: u32,
    completed: bool,
    requested: Vec<Request>,
}

/// A request to a peer and the time it was initiated.
#[derive(Clone, Debug)]
struct Request {
    peer: usize,
    requested_at: time::Instant,
}

const MAX_DUP_REQS: usize = 5;
const MAX_DL_Q: usize = 50;
const REQ_TIMEOUT: u64 = 15;

impl Picker {
    /// Creates a new picker, which will select over
    /// the given pieces. The algorithm used for selection
    /// will vary based on the current swarm state, but
    /// will default to rarest first.
    pub fn new(info: &Arc<Info>, pieces: &Bitfield, priorities: &[u8]) -> Picker {
        let scale = info.piece_len / 16_384;
        let picker = rarest::Picker::new(pieces);
        let last_piece = info.pieces().saturating_sub(1);
        let lpl = info.piece_len(last_piece);
        let last_piece_scale = if lpl % 16_384 == 0 {
            lpl / 16_384
        } else {
            lpl / 16_384 + 1
        };
        let downloading = if pieces.complete() {
            HashMap::with_capacity(0)
        } else {
            HashMap::with_capacity(info.pieces() as usize)
        };
        let mut picker = Picker {
            picker: PickerKind::Rarest(picker),
            scale,
            last_piece,
            last_piece_scale,
            seeders: 0,
            unpicked: pieces.clone(),
            downloading,
            priorities: vec![3; info.pieces() as usize],
        };
        picker.set_priorities(priorities, info);
        picker
    }

    /// Returns true if the current picker algorithm is sequential
    pub fn is_sequential(&self) -> bool {
        match self.picker {
            PickerKind::Sequential(_) => true,
            _ => false,
        }
    }

    pub fn tick(&mut self) {
        let mut expired = 0;
        for chunks in self.downloading.values_mut() {
            for chunk in chunks.iter_mut() {
                if !chunk.completed {
                    chunk.requested.retain(|req| {
                        let unexp = req.requested_at.elapsed().as_secs() < REQ_TIMEOUT;
                        if !unexp {
                            expired += 1;
                        }
                        unexp
                    })
                }
            }
        }
        if expired != 0 {
            debug!("Expired {} chunks!", expired);
        }
    }

    /// Attempts to select a block for a peer.
    pub fn pick<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        if let Some(b) = self.pick_expired(peer) {
            return Some(b);
        }
        if self.downloading.len() > MAX_DL_Q {
            if let Some(b) = self.pick_pri(peer) {
                return Some(b);
            }
        }

        let piece = match self.picker {
            PickerKind::Sequential(ref mut p) => p.pick(peer),
            PickerKind::Rarest(ref mut p) => p.pick(peer),
        };
        let res = piece
            .and_then(|p| self.pick_piece(p, peer.id()))
            .or_else(|| self.pick_downloading(peer));
        if res.is_none() && peer.pieces().complete() && !self.unpicked.complete() {
            debug_assert!(
                false,
                "Couldnt pick {:?} from a seeder for some reason!",
                piece
            );
        }
        res
    }

    /// Attempts to pick an expired block
    fn pick_expired<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        // TODO: Use some form of heuristic here to say "we expect to have
        // downloaded some pieces by X, hit the picker with a tick which checks
        // that, flags shit as invalid, and then does a double request
        None
    }

    /// Picks a block from a given piece for a peer
    fn pick_piece(&mut self, piece: u32, id: usize) -> Option<Block> {
        self.downloading.entry(piece).or_insert_with(|| vec![]);
        let dl = self.downloading.get_mut(&piece).unwrap();
        let offset = dl.len() as u32 * 16_384;
        dl.push(Downloading {
            offset,
            completed: false,
            requested: vec![Request::new(id)],
        });

        if dl.len() == self.scale as usize
            || (piece == self.last_piece && dl.len() == self.last_piece_scale as usize)
        {
            match self.picker {
                PickerKind::Sequential(ref mut p) => p.completed(piece),
                PickerKind::Rarest(ref mut p) => p.completed(piece),
            }
            self.unpicked.set_bit(u64::from(piece));
        }
        Some(Block {
            index: piece,
            offset,
        })
    }

    /// Attempts to pick the highest priority piece in the dl q
    fn pick_pri<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        let pri = &mut self.priorities;
        self.downloading
            .iter_mut()
            .max_by_key(|&(idx, _)| pri[*idx as usize])
            .and_then(|(idx, dl)| {
                dl.iter_mut()
                    .find(|r| {
                        !r.completed && r.requested.len() < MAX_DUP_REQS
                            && r.requested.iter().all(|req| req.peer != peer.id())
                    })
                    .map(|r| {
                        r.requested.push(Request::new(peer.id()));
                        Block::new(*idx, r.offset)
                    })
            })
    }

    /// Attempts to pick an already requested block
    fn pick_downloading<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        for (idx, dl) in &mut self.downloading {
            if peer.pieces().has_bit(u64::from(*idx)) {
                let r = dl.iter_mut()
                    .find(|r| {
                        !r.completed && r.requested.len() < MAX_DUP_REQS
                            && r.requested.iter().all(|req| req.peer != peer.id())
                    })
                    .map(|r| {
                        r.requested.push(Request::new(peer.id()));
                        Block::new(*idx, r.offset)
                    });
                if r.is_some() {
                    return r;
                }
            }
        }
        None
    }

    /// Marks a block as completed. Returns a result indicating if the block
    /// was actually requested, the success value containing a bool indicating
    /// if the block is complete, and a vector of peers from which the block
    /// was requested(for cancellation).
    pub fn completed(&mut self, b: Block) -> Result<(bool, Vec<usize>), ()> {
        // Find the block in our downloading blocks, mark as true,
        // and extract the current peer list for return.
        let res = self.downloading
            .get_mut(&b.index)
            .and_then(|dl| {
                dl.iter_mut()
                    .find(|r| r.offset == b.offset)
                    .map(|r| r.complete())
            })
            .map(|r| r.into_iter().map(|e| e.peer).collect());

        // If we've requested every single block for this piece and they're all complete, remove it
        // and report completion
        let scale = self.scale;
        let lp = self.last_piece;
        let lps = self.last_piece_scale;
        let complete = self.downloading
            .get_mut(&b.index)
            .map(|r| {
                (r.len() as u32 == scale || (b.index == lp && r.len() as u32 == lps))
                    && r.iter().all(|d| d.completed)
            })
            .unwrap_or(false);

        if complete {
            self.downloading.remove(&b.index);
        }

        res.map(|r| (complete, r)).ok_or(())
    }

    pub fn have_block(&mut self, b: Block) -> bool {
        self.downloading
            .get_mut(&b.index)
            .and_then(|dl| {
                dl.iter()
                    .find(|r| r.offset == b.offset)
                    .map(|r| r.completed)
            })
            .unwrap_or(false)
    }

    /// Invalidates a piece
    pub fn invalidate_piece(&mut self, idx: u32) {
        match self.picker {
            PickerKind::Sequential(ref mut p) => p.incomplete(idx),
            PickerKind::Rarest(ref mut p) => p.incomplete(idx),
        }
        self.unpicked.unset_bit(u64::from(idx));
        self.downloading.remove(&idx);
    }

    pub fn piece_available(&mut self, idx: u32) {
        if let PickerKind::Rarest(ref mut p) = self.picker {
            p.piece_available(idx);
        }
    }

    pub fn add_peer<T: cio::CIO>(&mut self, peer: &Peer<T>) {
        if peer.pieces().complete() {
            self.seeders += 1;
        } else {
            if let PickerKind::Rarest(ref mut p) = self.picker {
                p.add_peer(peer);
            }
        }
    }

    pub fn remove_peer<T: cio::CIO>(&mut self, peer: &Peer<T>) {
        // Have to consider situation where a peer became a seeder but joined as leecher.
        if peer.pieces().complete() && self.seeders > 0 {
            self.seeders -= 1;
        } else {
            if let PickerKind::Rarest(ref mut p) = self.picker {
                p.remove_peer(peer);
            }
        }

        for piece in self.downloading.values_mut() {
            for block in piece {
                block.requested.retain(|req| req.peer != peer.id())
            }
        }
    }

    /// Alters the picker to sequential/non sequential. If changing
    /// from sequential to non sequential, peer state will need to be loaded
    /// after this.
    pub fn change_picker(&mut self, sequential: bool, pieces: &Bitfield) {
        self.unpicked = pieces.clone();
        self.picker = if sequential {
            PickerKind::Sequential(sequential::Picker::new(&self.unpicked))
        } else {
            PickerKind::Rarest(rarest::Picker::new(&self.unpicked))
        };
        self.downloading.clear();
    }

    pub fn set_priorities(&mut self, pri: &[u8], info: &Arc<Info>) {
        self.unapply_priorities();
        self.priorities = generate_piece_pri(pri, info);
        self.apply_priorities();
    }

    pub fn apply_priorities(&mut self) {
        if self.is_sequential() {
            let mut pieces = [vec![], vec![], vec![], vec![], vec![], vec![]];
            for (piece, pri) in self.priorities.iter().enumerate() {
                pieces[*pri as usize].push(piece as u32);
            }
            self.picker = PickerKind::Sequential(sequential::Picker::new_pri(pieces));
        } else {
            for (piece, pri) in self.priorities.iter().enumerate() {
                if let PickerKind::Rarest(ref mut p) = self.picker {
                    for _ in 0..*pri {
                        p.piece_unavailable(piece as u32);
                    }
                }

                if *pri == 0 && !self.unpicked.has_bit(piece as u64) {
                    match self.picker {
                        PickerKind::Rarest(ref mut p) => p.completed(piece as u32),
                        _ => unreachable!(),
                    }
                }
            }
        }
    }

    pub fn unapply_priorities(&mut self) {
        if !self.is_sequential() {
            for (piece, pri) in self.priorities.iter().enumerate() {
                if let PickerKind::Rarest(ref mut p) = self.picker {
                    for _ in 0..*pri {
                        p.piece_available(piece as u32);
                    }
                }

                if *pri == 0 && !self.unpicked.has_bit(piece as u64) {
                    match self.picker {
                        PickerKind::Rarest(ref mut p) => p.incomplete(piece as u32),
                        _ => unreachable!(),
                    }
                }
            }
        }
    }
}

fn generate_piece_pri(pri: &[u8], info: &Arc<Info>) -> Vec<u8> {
    // Map piece -> priority
    let mut priorities = Vec::with_capacity(info.pieces() as usize);
    // If a piece is completely in a file, just assign that pri.
    // Otherwise mark it as the higher pri piece
    for p in 0..info.pieces() {
        let max = Info::piece_disk_locs(&info, p)
            .map(|loc| pri[loc.file])
            .max()
            .expect("Piece must have locations!");
        priorities.push(max);
    }
    priorities
}

#[cfg(test)]
impl Picker {
    pub fn new_rarest(info: &Info, pieces: &Bitfield) -> Picker {
        Picker::new(
            &Arc::new(info.clone()),
            pieces,
            &vec![3u8; info.files.len()],
        )
    }

    pub fn new_sequential(info: &Info, pieces: &Bitfield) -> Picker {
        let mut p = Picker::new(
            &Arc::new(info.clone()),
            pieces,
            &vec![3u8; info.files.len()],
        );
        p.change_picker(true, pieces);
        p
    }
}

impl Block {
    pub fn new(index: u32, offset: u32) -> Block {
        Block { index, offset }
    }
}

impl Request {
    fn new(peer: usize) -> Request {
        Request {
            peer,
            requested_at: time::Instant::now(),
        }
    }
}

impl Downloading {
    fn complete(&mut self) -> Vec<Request> {
        self.completed = true;
        mem::replace(&mut self.requested, Vec::with_capacity(0))
    }
}
<|endoftext|>


<commit_before>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

//! `Universe` type definition and implementation.

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

use ::potentials::PairPotential;
use ::types::{Vector3D, Matrix3};

use super::Particle;
use super::UnitCell;
use super::interactions::Interactions;

/// The Universe type hold all the data about a system. This data contains:
///
///   - an unit cell, containing the system;
///   - a list of particles in the system;
///   - a list of interactions, associating particles kinds and potentials
///   - a hash map associating particles names and particles kinds.
pub struct Universe {
    /// Unit cell of the universe
    cell: UnitCell,
    /// List of particles in the system
    particles: Vec<Particle>,
    /// Particles kinds, associating particles names and indexes
    kinds: HashMap<String, usize>,
    /// Interactions is a hash map associating particles kinds and potentials
    interactions: Interactions,
}

impl Universe {
    /// Create a new empty Universe
    pub fn new() -> Universe {
        Universe{
            particles: Vec::new(),
            kinds: HashMap::new(),
            interactions: Interactions::new(),
            cell: UnitCell::new(),
        }
    }

    /// Create an empty universe with a specific UnitCell
    pub fn from_cell(cell: UnitCell) -> Universe {
        let mut universe = Universe::new();
        universe.set_cell(cell);
        return universe;
    }

    /// Get the universe unit cell
    pub fn cell<'a>(&'a self) -> &'a UnitCell {&self.cell}
    /// Set the universe unit cell
    pub fn set_cell(&mut self, cell: UnitCell) {self.cell = cell;}

    /// Insert a particle at the end of the internal list
    pub fn add_particle(&mut self, p: Particle) {
        let mut part = p;
        if part.kind() == usize::max_value() {
            // If no value have been precised, set one from the internal list
            // of particles kinds.
            let kind = self.get_kind(part.name());
            part.set_kind(kind);
        }
        self.particles.push(part);
    }
    /// Get the number of particles in this universe
    pub fn size(&self) -> usize {self.particles.len()}

    /// Get the list of pair interaction between the atom i and the atom j
    pub fn pairs<'a>(&'a self, i: usize, j: usize) -> &'a Vec<Box<PairPotential>> {
        let ikind = self.particles[i].kind();
        let jkind = self.particles[j].kind();
        &self.interactions.pairs[&(ikind, jkind)]
    }

    /// Add an interaction between the particles with names `names`
    pub fn add_pair_interaction<T>(&mut self, i: &str, j: &str, pot: T)
    where T: PairPotential + 'static {
        let ikind = self.get_kind(i);
        let jkind = self.get_kind(j);

        if !self.interactions.pairs.contains_key(&(ikind, jkind)) {
            self.interactions.pairs.insert((ikind, jkind), Vec::new());
        }
        let pairs = self.interactions.pairs.get_mut(&(ikind, jkind)).unwrap();
        pairs.push(Box::new(pot));
    }

    /// Get the distance between the particles at indexes `i` and `j`
    pub fn distance(&self, i: usize, j:usize) -> f64 {
        self.cell.distance(self.particles[i].position(), self.particles[j].position())
    }

    /// Wrap the vector i->j in the cell.
    pub fn wrap_vector(&self, i: usize, j:usize) -> Vector3D {
        let mut res = *self.particles[i].position() - *self.particles[j].position();
        self.cell.wrap_vector(&mut res);
        return res;
    }

    /// Get or create the usize kind index for the name `name` of a particle
    fn get_kind(&mut self, name: &str) -> usize {
        if self.kinds.contains_key(name) {
            self.kinds[name]
        } else {
            let index = self.kinds.len();
            self.kinds.insert(name.to_string(), index);
            return index;
        }
    }

    /// Get an iterator over the `Particle` in this universe
    pub fn iter(&self) -> slice::Iter<Particle> {
        self.particles.iter()
    }

    /// Get a mutable iterator over the `Particle` in this universe
    pub fn iter_mut(&mut self) -> slice::IterMut<Particle> {
        self.particles.iter_mut()
    }
}

/******************************************************************************/

use ::simulation::Compute;
use ::simulation::{PotentialEnergy, KineticEnergy, TotalEnergy};
use ::simulation::Temperature;
use ::simulation::Volume;
use ::simulation::{Virial, Stress, Pressure};

/// Functions to get pysical properties of an universe.
impl Universe {
    // TODO: This implementation recompute the properties each time. These can
    // be cached somehow.

    /// Get the kinetic energy of the system.
    pub fn kinetic_energy(&self) -> f64 {KineticEnergy.compute(self)}
    /// Get the potential energy of the system.
    pub fn potential_energy(&self) -> f64 {PotentialEnergy.compute(self)}
    /// Get the total energy of the system.
    pub fn total_energy(&self) -> f64 {TotalEnergy.compute(self)}
    /// Get the temperature of the system.
    pub fn temperature(&self) -> f64 {Temperature.compute(self)}

    /// Get the volume of the system.
    pub fn volume(&self) -> f64 {Volume.compute(self)}

    /// Get the tensorial virial of the system.
    pub fn virial(&self) -> Matrix3 {Virial.compute(self)}
    /// Get the pressure of the system, from the virial equation
    pub fn pressure(&self) -> f64 {Pressure.compute(self)}
    /// Get the stress tensor of the system, from the virial equation
    pub fn stress(&self) -> Matrix3 {Stress.compute(self)}
}

/******************************************************************************/
impl Index<usize> for Universe {
    type Output = Particle;
    #[inline]
    fn index<'a>(&'a self, index: usize) -> &'a Particle {
        &self.particles[index]
    }
}

impl IndexMut<usize> for Universe {
    #[inline]
    fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut Particle {
        &mut self.particles[index]
    }
}

#[cfg(test)]
mod tests {
    use ::universe::*;
    use ::types::*;
    use ::potentials::*;

    #[test]
    fn particles() {
        let mut universe = Universe::new();
        universe.add_particle(Particle::new("O"));
        universe.add_particle(Particle::new("H"));
        universe.add_particle(Particle::new("H"));

        assert_eq!(universe.size(), 3);
        assert_eq!(universe[0].name(), "O");
        assert_eq!(universe[1].name(), "H");
        assert_eq!(universe[2].name(), "H");
    }

    #[test]
    fn distances() {
        let mut universe = Universe::from_cell(UnitCell::cubic(5.0));
        universe.add_particle(Particle::new("O"));
        universe.add_particle(Particle::new("H"));

        universe[0].set_position(Vector3D::new(9.0, 0.0, 0.0));
        universe[1].set_position(Vector3D::new(0.0, 0.0, 0.0));
        assert_eq!(universe.distance(0, 1), 1.0);

        universe.set_cell(UnitCell::new());
        assert_eq!(universe.distance(0, 1), 9.0);
    }

    #[test]
    fn pairs() {
        let mut universe = Universe::new();
        universe.add_particle(Particle::new("He"));

        universe.add_pair_interaction("He", "He", LennardJones{sigma: 0.3, epsilon: 2.0});
        universe.add_pair_interaction("He", "He", Harmonic{k: 100.0, r0: 1.1});

        assert_eq!(universe.pairs(0, 0).len(), 2);
    }
}
<commit_msg>Add ability to read XYZ file for creating universes<commit_after>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

//! `Universe` type definition and implementation.

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

use std::io::prelude::*;
use std::io;
use std::fs::File;
use std::num;

use ::potentials::PairPotential;
use ::types::{Vector3D, Matrix3};

use super::Particle;
use super::UnitCell;
use super::interactions::Interactions;

/// The Universe type hold all the data about a system. This data contains:
///
///   - an unit cell, containing the system;
///   - a list of particles in the system;
///   - a list of interactions, associating particles kinds and potentials
///   - a hash map associating particles names and particles kinds.
pub struct Universe {
    /// Unit cell of the universe
    cell: UnitCell,
    /// List of particles in the system
    particles: Vec<Particle>,
    /// Particles kinds, associating particles names and indexes
    kinds: HashMap<String, usize>,
    /// Interactions is a hash map associating particles kinds and potentials
    interactions: Interactions,
}

/// Possible error causes where reading XYZ file
#[derive(Debug)]
pub enum ReadError {
    IoError(io::Error),
    ParseIntError(num::ParseIntError),
    ParseFloatError(num::ParseFloatError),
    XYZFormatError{err: &'static str}, // Badly formated file
}

impl From<num::ParseIntError> for ReadError {
    fn from(err: num::ParseIntError) -> ReadError {
        ReadError::ParseIntError(err)
    }
}

impl From<num::ParseFloatError> for ReadError {
    fn from(err: num::ParseFloatError) -> ReadError {
        ReadError::ParseFloatError(err)
    }
}

impl From<io::Error> for ReadError {
    fn from(err: io::Error) -> ReadError {
        ReadError::IoError(err)
    }
}

impl Universe {
    /// Create a new empty Universe
    pub fn new() -> Universe {
        Universe{
            particles: Vec::new(),
            kinds: HashMap::new(),
            interactions: Interactions::new(),
            cell: UnitCell::new(),
        }
    }

    /// Read an XYZ file and create an Universe from it.
    pub fn from_file(path: &str) -> Result<Universe, ReadError> {
        // TODO: use chemharp for implementation
        let mut file = try!(File::open(path));
        let mut content = String::new();
        try!(file.read_to_string(&mut content));
        let lines : Vec<&str> = content.lines_any().collect();
        let natoms = try!(lines[0].parse::<usize>());
        if lines.len() != natoms + 2 {
            return Err(ReadError::XYZFormatError{err: "Bad atom number in file."});
        }

        let mut universe = Universe::new();
        for line in lines[2..].iter() {
            let splited: Vec<&str> = line.split_whitespace().collect();
            if splited.len() < 4 {
                return Err(ReadError::XYZFormatError{err: "Line is too short."});
            }
            let mut part = Particle::new(splited[0]);
            let x = try!(splited[1].parse::<f64>());
            let y = try!(splited[2].parse::<f64>());
            let z = try!(splited[3].parse::<f64>());
            part.set_position(Vector3D::new(x, y, z));
            universe.add_particle(part);
        }
        return Ok(universe);
    }

    /// Create an empty universe with a specific UnitCell
    pub fn from_cell(cell: UnitCell) -> Universe {
        let mut universe = Universe::new();
        universe.set_cell(cell);
        return universe;
    }

    /// Get the universe unit cell
    pub fn cell<'a>(&'a self) -> &'a UnitCell {&self.cell}
    /// Set the universe unit cell
    pub fn set_cell(&mut self, cell: UnitCell) {self.cell = cell;}

    /// Insert a particle at the end of the internal list
    pub fn add_particle(&mut self, p: Particle) {
        let mut part = p;
        if part.kind() == usize::max_value() {
            // If no value have been precised, set one from the internal list
            // of particles kinds.
            let kind = self.get_kind(part.name());
            part.set_kind(kind);
        }
        self.particles.push(part);
    }
    /// Get the number of particles in this universe
    pub fn size(&self) -> usize {self.particles.len()}

    /// Get the list of pair interaction between the atom i and the atom j
    pub fn pairs<'a>(&'a self, i: usize, j: usize) -> &'a Vec<Box<PairPotential>> {
        let ikind = self.particles[i].kind();
        let jkind = self.particles[j].kind();
        &self.interactions.pairs[&(ikind, jkind)]
    }

    /// Add an interaction between the particles with names `names`
    pub fn add_pair_interaction<T>(&mut self, i: &str, j: &str, pot: T)
    where T: PairPotential + 'static {
        let ikind = self.get_kind(i);
        let jkind = self.get_kind(j);

        if !self.interactions.pairs.contains_key(&(ikind, jkind)) {
            self.interactions.pairs.insert((ikind, jkind), Vec::new());
        }
        let pairs = self.interactions.pairs.get_mut(&(ikind, jkind)).unwrap();
        pairs.push(Box::new(pot));
    }

    /// Get the distance between the particles at indexes `i` and `j`
    pub fn distance(&self, i: usize, j:usize) -> f64 {
        self.cell.distance(self.particles[i].position(), self.particles[j].position())
    }

    /// Wrap the vector i->j in the cell.
    pub fn wrap_vector(&self, i: usize, j:usize) -> Vector3D {
        let mut res = *self.particles[i].position() - *self.particles[j].position();
        self.cell.wrap_vector(&mut res);
        return res;
    }

    /// Get or create the usize kind index for the name `name` of a particle
    fn get_kind(&mut self, name: &str) -> usize {
        if self.kinds.contains_key(name) {
            self.kinds[name]
        } else {
            let index = self.kinds.len();
            self.kinds.insert(name.to_string(), index);
            return index;
        }
    }

    /// Get an iterator over the `Particle` in this universe
    pub fn iter(&self) -> slice::Iter<Particle> {
        self.particles.iter()
    }

    /// Get a mutable iterator over the `Particle` in this universe
    pub fn iter_mut(&mut self) -> slice::IterMut<Particle> {
        self.particles.iter_mut()
    }
}

/******************************************************************************/

use ::simulation::Compute;
use ::simulation::{PotentialEnergy, KineticEnergy, TotalEnergy};
use ::simulation::Temperature;
use ::simulation::Volume;
use ::simulation::{Virial, Stress, Pressure};

/// Functions to get pysical properties of an universe.
impl Universe {
    // TODO: This implementation recompute the properties each time. These can
    // be cached somehow.

    /// Get the kinetic energy of the system.
    pub fn kinetic_energy(&self) -> f64 {KineticEnergy.compute(self)}
    /// Get the potential energy of the system.
    pub fn potential_energy(&self) -> f64 {PotentialEnergy.compute(self)}
    /// Get the total energy of the system.
    pub fn total_energy(&self) -> f64 {TotalEnergy.compute(self)}
    /// Get the temperature of the system.
    pub fn temperature(&self) -> f64 {Temperature.compute(self)}

    /// Get the volume of the system.
    pub fn volume(&self) -> f64 {Volume.compute(self)}

    /// Get the tensorial virial of the system.
    pub fn virial(&self) -> Matrix3 {Virial.compute(self)}
    /// Get the pressure of the system, from the virial equation
    pub fn pressure(&self) -> f64 {Pressure.compute(self)}
    /// Get the stress tensor of the system, from the virial equation
    pub fn stress(&self) -> Matrix3 {Stress.compute(self)}
}

/******************************************************************************/
impl Index<usize> for Universe {
    type Output = Particle;
    #[inline]
    fn index<'a>(&'a self, index: usize) -> &'a Particle {
        &self.particles[index]
    }
}

impl IndexMut<usize> for Universe {
    #[inline]
    fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut Particle {
        &mut self.particles[index]
    }
}

#[cfg(test)]
mod tests {
    use ::universe::*;
    use ::types::*;
    use ::potentials::*;

    #[test]
    fn particles() {
        let mut universe = Universe::new();
        universe.add_particle(Particle::new("O"));
        universe.add_particle(Particle::new("H"));
        universe.add_particle(Particle::new("H"));

        assert_eq!(universe.size(), 3);
        assert_eq!(universe[0].name(), "O");
        assert_eq!(universe[1].name(), "H");
        assert_eq!(universe[2].name(), "H");
    }

    #[test]
    fn distances() {
        let mut universe = Universe::from_cell(UnitCell::cubic(5.0));
        universe.add_particle(Particle::new("O"));
        universe.add_particle(Particle::new("H"));

        universe[0].set_position(Vector3D::new(9.0, 0.0, 0.0));
        universe[1].set_position(Vector3D::new(0.0, 0.0, 0.0));
        assert_eq!(universe.distance(0, 1), 1.0);

        universe.set_cell(UnitCell::new());
        assert_eq!(universe.distance(0, 1), 9.0);
    }

    #[test]
    fn pairs() {
        let mut universe = Universe::new();
        universe.add_particle(Particle::new("He"));

        universe.add_pair_interaction("He", "He", LennardJones{sigma: 0.3, epsilon: 2.0});
        universe.add_pair_interaction("He", "He", Harmonic{k: 100.0, r0: 1.1});

        assert_eq!(universe.pairs(0, 0).len(), 2);
    }
}
<|endoftext|>


<commit_before>// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616

fn main() {}
<commit_msg>Remove no longer useful ui test<commit_after><|endoftext|>


<commit_before>#![feature(macro_rules)]
extern crate groupable;

use std::collections::{HashMap, TreeMap, VecMap, TrieMap};
use groupable::Groupable;

static XS : &'static [char] = ['h', 'b', 'i', 'y', '!', 'e'];

macro_rules! test_string (
    ($t:ty) => (
        {
            let map = XS.iter().enumerate()
                           .map(|(i, &c)| (i % 2, c))
                           .group::<$t>();

            assert_eq!(map[0].as_slice(), "hi!");
            assert_eq!(map[1].as_slice(), "bye");
        }
    )
)

macro_rules! test_char_vec (
    ($t:ty) => (
        {
            let map = XS.iter().enumerate()
                           .map(|(i, &c)| (i % 2, c))
                           .group::<$t>();

            assert_eq!(map[0].as_slice(), ['h', 'i', '!'].as_slice());
            assert_eq!(map[1].as_slice(), ['b', 'y', 'e'].as_slice());
        }
    )
)

#[test]
fn hashmap() {
    test_string!(HashMap<uint, String>)
    test_char_vec!(HashMap<uint, Vec<char>>)
}

#[test]
fn treemap() {
    test_string!(TreeMap<uint, String>)
    test_char_vec!(TreeMap<uint, Vec<char>>)
}

#[test]
fn smallintmap() {
    test_string!(VecMap<String>)
    test_char_vec!(VecMap<Vec<char>>)
}

#[test]
fn triemap() {
    test_string!(TrieMap<String>)
    test_char_vec!(TrieMap<Vec<char>>)
}
<commit_msg>[T,.. N] no longer coerces to &[T]<commit_after>#![feature(macro_rules)]
extern crate groupable;

use std::collections::{HashMap, TreeMap, VecMap, TrieMap};
use groupable::Groupable;

static XS : &'static [char] = &['h', 'b', 'i', 'y', '!', 'e'];

macro_rules! test_string (
    ($t:ty) => (
        {
            let map = XS.iter().enumerate()
                           .map(|(i, &c)| (i % 2, c))
                           .group::<$t>();

            assert_eq!(map[0].as_slice(), "hi!");
            assert_eq!(map[1].as_slice(), "bye");
        }
    )
)

macro_rules! test_char_vec (
    ($t:ty) => (
        {
            let map = XS.iter().enumerate()
                           .map(|(i, &c)| (i % 2, c))
                           .group::<$t>();

            assert_eq!(map[0].as_slice(), ['h', 'i', '!'].as_slice());
            assert_eq!(map[1].as_slice(), ['b', 'y', 'e'].as_slice());
        }
    )
)

#[test]
fn hashmap() {
    test_string!(HashMap<uint, String>)
    test_char_vec!(HashMap<uint, Vec<char>>)
}

#[test]
fn treemap() {
    test_string!(TreeMap<uint, String>)
    test_char_vec!(TreeMap<uint, Vec<char>>)
}

#[test]
fn smallintmap() {
    test_string!(VecMap<String>)
    test_char_vec!(VecMap<Vec<char>>)
}

#[test]
fn triemap() {
    test_string!(TrieMap<String>)
    test_char_vec!(TrieMap<Vec<char>>)
}
<|endoftext|>


<commit_before>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::env;
use common::Config;

/// Conversion table from triple OS name to Rust SYSNAME
const OS_TABLE: &'static [(&'static str, &'static str)] = &[
    ("android", "android"),
    ("bitrig", "bitrig"),
    ("cloudabi", "cloudabi"),
    ("darwin", "macos"),
    ("dragonfly", "dragonfly"),
    ("freebsd", "freebsd"),
    ("haiku", "haiku"),
    ("ios", "ios"),
    ("linux", "linux"),
    ("mingw32", "windows"),
    ("netbsd", "netbsd"),
    ("openbsd", "openbsd"),
    ("win32", "windows"),
    ("windows", "windows"),
    ("solaris", "solaris"),
    ("emscripten", "emscripten"),
];

const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
    ("aarch64", "aarch64"),
    ("amd64", "x86_64"),
    ("arm", "arm"),
    ("arm64", "aarch64"),
    ("hexagon", "hexagon"),
    ("i386", "x86"),
    ("i586", "x86"),
    ("i686", "x86"),
    ("mips", "mips"),
    ("msp430", "msp430"),
    ("powerpc", "powerpc"),
    ("s390x", "s390x"),
    ("sparc", "sparc"),
    ("x86_64", "x86_64"),
    ("xcore", "xcore"),
    ("asmjs", "asmjs"),
    ("wasm32", "wasm32"),
];

pub fn matches_os(triple: &str, name: &str) -> bool {
    // For the wasm32 bare target we ignore anything also ignored on emscripten
    // and then we also recognize `wasm32-bare` as the os for the target
    if triple == "wasm32-unknown-unknown" {
        return name == "emscripten" || name == "wasm32-bare"
    }
    for &(triple_os, os) in OS_TABLE {
        if triple.contains(triple_os) {
            return os == name;
        }
    }
    panic!("Cannot determine OS from triple");
}
pub fn get_arch(triple: &str) -> &'static str {
    for &(triple_arch, arch) in ARCH_TABLE {
        if triple.contains(triple_arch) {
            return arch;
        }
    }
    panic!("Cannot determine Architecture from triple");
}

pub fn get_env(triple: &str) -> Option<&str> {
    triple.split('-').nth(3)
}

pub fn get_pointer_width(triple: &str) -> &'static str {
    if (triple.contains("64") && !triple.ends_with("gnux32")) || triple.starts_with("s390x") {
        "64bit"
    } else {
        "32bit"
    }
}

pub fn make_new_path(path: &str) -> String {
    assert!(cfg!(windows));
    // Windows just uses PATH as the library search path, so we have to
    // maintain the current value while adding our own
    match env::var(lib_path_env_var()) {
        Ok(curr) => format!("{}{}{}", path, path_div(), curr),
        Err(..) => path.to_owned(),
    }
}

pub fn lib_path_env_var() -> &'static str {
    "PATH"
}
fn path_div() -> &'static str {
    ";"
}

pub fn logv(config: &Config, s: String) {
    debug!("{}", s);
    if config.verbose {
        println!("{}", s);
    }
}
<commit_msg>tools/compiletest: add mips64 to ARCH_LIST<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::env;
use common::Config;

/// Conversion table from triple OS name to Rust SYSNAME
const OS_TABLE: &'static [(&'static str, &'static str)] = &[
    ("android", "android"),
    ("bitrig", "bitrig"),
    ("cloudabi", "cloudabi"),
    ("darwin", "macos"),
    ("dragonfly", "dragonfly"),
    ("freebsd", "freebsd"),
    ("haiku", "haiku"),
    ("ios", "ios"),
    ("linux", "linux"),
    ("mingw32", "windows"),
    ("netbsd", "netbsd"),
    ("openbsd", "openbsd"),
    ("win32", "windows"),
    ("windows", "windows"),
    ("solaris", "solaris"),
    ("emscripten", "emscripten"),
];

const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
    ("aarch64", "aarch64"),
    ("amd64", "x86_64"),
    ("arm", "arm"),
    ("arm64", "aarch64"),
    ("hexagon", "hexagon"),
    ("i386", "x86"),
    ("i586", "x86"),
    ("i686", "x86"),
    ("mips64", "mips64"),
    ("mips", "mips"),
    ("msp430", "msp430"),
    ("powerpc", "powerpc"),
    ("s390x", "s390x"),
    ("sparc", "sparc"),
    ("x86_64", "x86_64"),
    ("xcore", "xcore"),
    ("asmjs", "asmjs"),
    ("wasm32", "wasm32"),
];

pub fn matches_os(triple: &str, name: &str) -> bool {
    // For the wasm32 bare target we ignore anything also ignored on emscripten
    // and then we also recognize `wasm32-bare` as the os for the target
    if triple == "wasm32-unknown-unknown" {
        return name == "emscripten" || name == "wasm32-bare"
    }
    for &(triple_os, os) in OS_TABLE {
        if triple.contains(triple_os) {
            return os == name;
        }
    }
    panic!("Cannot determine OS from triple");
}
pub fn get_arch(triple: &str) -> &'static str {
    for &(triple_arch, arch) in ARCH_TABLE {
        if triple.contains(triple_arch) {
            return arch;
        }
    }
    panic!("Cannot determine Architecture from triple");
}

pub fn get_env(triple: &str) -> Option<&str> {
    triple.split('-').nth(3)
}

pub fn get_pointer_width(triple: &str) -> &'static str {
    if (triple.contains("64") && !triple.ends_with("gnux32")) || triple.starts_with("s390x") {
        "64bit"
    } else {
        "32bit"
    }
}

pub fn make_new_path(path: &str) -> String {
    assert!(cfg!(windows));
    // Windows just uses PATH as the library search path, so we have to
    // maintain the current value while adding our own
    match env::var(lib_path_env_var()) {
        Ok(curr) => format!("{}{}{}", path, path_div(), curr),
        Err(..) => path.to_owned(),
    }
}

pub fn lib_path_env_var() -> &'static str {
    "PATH"
}
fn path_div() -> &'static str {
    ";"
}

pub fn logv(config: &Config, s: String) {
    debug!("{}", s);
    if config.verbose {
        println!("{}", s);
    }
}
<|endoftext|>


<commit_before>extern crate rustspec_assertions;
use self::rustspec_assertions::{expect, eq};

#[test]
fn eq_int_test() {
    expect(&2i).to(eq!(2i))
}

#[test]
#[should_fail]
fn eq_int_test_fail() {
    expect(&5i).to(eq!(4i));
}

#[test]
fn not_eq_int_test() {
    expect(&2i).not_to(eq!(4i));
}

#[test]
#[should_fail]
fn not_eq_int_test_fail() {
    expect(&5i).not_to(eq!(5i));
}

#[test]
fn eq_f64_test() {
    expect(&1f64).to(eq!(1f64));
}

<commit_msg>add silly test<commit_after>extern crate rustspec_assertions;
use self::rustspec_assertions::{expect, eq};

#[test]
fn eq_int_test() {
    expect(&2i).to(eq!(2i))
}

#[test]
#[should_fail]
fn eq_int_test_fail() {
    expect(&5i).to(eq!(4i));
}

#[test]
fn not_eq_int_test() {
    expect(&2i).not_to(eq!(4i));
}

#[test]
#[should_fail]
fn not_eq_int_test_fail() {
    expect(&5i).not_to(eq!(5i));
}

#[test]
fn eq_f64_test() {
    expect(&1f64).to(eq!(1f64));
}

#[test]
fn eq_uint_test() {
    expect(&1u).to(eq!(1u));
}

<|endoftext|>


<commit_before>//! Contains code for selecting features

#![deny(missing_docs)]
#![deny(warnings)]
#![deny(unused_extern_crates)]

use std::io;
use std::str::FromStr;

/// Define RustTarget struct definition, Default impl, and conversions
/// between RustTarget and String.
macro_rules! rust_target_def {
    ( $( $( #[$attr:meta] )* => $release:ident => $value:expr; )* ) => {
        /// Represents the version of the Rust language to target.
        ///
        /// To support a beta release, use the corresponding stable release.
        ///
        /// This enum will have more variants added as necessary.
        #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Hash)]
        #[allow(non_camel_case_types)]
        pub enum RustTarget {
            $(
                $(
                    #[$attr]
                )*
                $release,
            )*
        }

        impl Default for RustTarget {
            /// Gives the latest stable Rust version
            fn default() -> RustTarget {
                LATEST_STABLE_RUST
            }
        }

        impl FromStr for RustTarget {
            type Err = io::Error;

            /// Create a `RustTarget` from a string.
            ///
            /// * The stable/beta versions of Rust are of the form "1.0",
            /// "1.19", etc.
            /// * The nightly version should be specified with "nightly".
            fn from_str(s: &str) -> Result<Self, Self::Err> {
                match s.as_ref() {
                    $(
                        stringify!($value) => Ok(RustTarget::$release),
                    )*
                    _ => Err(
                        io::Error::new(
                            io::ErrorKind::InvalidInput,
                            concat!(
                                "Got an invalid rust target. Accepted values ",
                                "are of the form ",
                                "\"1.0\" or \"nightly\"."))),
                }
            }
        }

        impl From<RustTarget> for String {
            fn from(target: RustTarget) -> Self {
                match target {
                    $(
                        RustTarget::$release => stringify!($value),
                    )*
                }.into()
            }
        }
    }
}

/// Defines an array slice with all RustTarget values
macro_rules! rust_target_values_def {
    ( $( $( #[$attr:meta] )* => $release:ident => $value:expr; )* ) => {
        /// Strings of allowed `RustTarget` values
        pub static RUST_TARGET_STRINGS: &'static [&str] = &[
            $(
                stringify!($value),
            )*
        ];
    }
}

/// Defines macro which takes a macro
macro_rules! rust_target_base {
    ( $x_macro:ident ) => {
        $x_macro!(
            /// Rust stable 1.0
            => Stable_1_0 => 1.0;
            /// Rust stable 1.19
            => Stable_1_19 => 1.19;
            /// Rust stable 1.20
            => Stable_1_20 => 1.20;
            /// Rust stable 1.21
            => Stable_1_21 => 1.21;
            /// Rust stable 1.25
            => Stable_1_25 => 1.25;
            /// Nightly rust
            => Nightly => nightly;
        );
    }
}

rust_target_base!(rust_target_def);
rust_target_base!(rust_target_values_def);

/// Latest stable release of Rust
pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_21;

/// Create RustFeatures struct definition, new(), and a getter for each field
macro_rules! rust_feature_def {
    ( $( $( #[$attr:meta] )* => $feature:ident; )* ) => {
        /// Features supported by a rust target
        #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
        pub struct RustFeatures {
            $(
                $(
                    #[$attr]
                )*
                pub $feature: bool,
            )*
        }

        impl RustFeatures {
            /// Gives a RustFeatures struct with all features disabled
            fn new() -> Self {
                RustFeatures {
                    $(
                        $feature: false,
                    )*
                }
            }
        }
    }
}

rust_feature_def!(
    /// Untagged unions ([RFC 1444](https://github.com/rust-lang/rfcs/blob/master/text/1444-union.md))
    => untagged_union;
    /// `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
    => thiscall_abi;
    /// builtin impls for `Clone` ([PR](https://github.com/rust-lang/rust/pull/43690))
    => builtin_clone_impls;
    /// repr(align) https://github.com/rust-lang/rust/pull/47006
    => repr_align;
    /// associated constants https://github.com/rust-lang/rust/issues/29646
    => associated_const;
);

impl From<RustTarget> for RustFeatures {
    fn from(rust_target: RustTarget) -> Self {
        let mut features = RustFeatures::new();

        if rust_target >= RustTarget::Stable_1_19 {
            features.untagged_union = true;
        }

        if rust_target >= RustTarget::Stable_1_20 {
            features.associated_const = true;
        }

        if rust_target >= RustTarget::Stable_1_21 {
            features.builtin_clone_impls = true;
        }

        if rust_target >= RustTarget::Stable_1_25 {
            features.repr_align = true;
        }

        if rust_target >= RustTarget::Nightly {
            features.thiscall_abi = true;
        }

        features
    }
}

impl Default for RustFeatures {
    fn default() -> Self {
        let default_rust_target: RustTarget = Default::default();
        Self::from(default_rust_target)
    }
}

#[cfg(test)]
mod test {
#![allow(unused_imports)]
    use super::*;

    fn test_target(target_str: &str, target: RustTarget) {
        let target_string: String = target.into();
        assert_eq!(target_str, target_string);
        assert_eq!(target, RustTarget::from_str(target_str).unwrap());
    }

    #[test]
    fn str_to_target() {
        test_target("1.0", RustTarget::Stable_1_0);
        test_target("1.19", RustTarget::Stable_1_19);
        test_target("1.21", RustTarget::Stable_1_21);
        test_target("1.25", RustTarget::Stable_1_25);
        test_target("nightly", RustTarget::Nightly);
    }
}
<commit_msg>Track Rust target features with declaration macro<commit_after>//! Contains code for selecting features

#![deny(missing_docs)]
#![deny(warnings)]
#![deny(unused_extern_crates)]

use std::io;
use std::str::FromStr;

/// Define RustTarget struct definition, Default impl, and conversions
/// between RustTarget and String.
macro_rules! rust_target_def {
    ( $( $( #[$attr:meta] )* => $release:ident => $value:expr; )* ) => {
        /// Represents the version of the Rust language to target.
        ///
        /// To support a beta release, use the corresponding stable release.
        ///
        /// This enum will have more variants added as necessary.
        #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Hash)]
        #[allow(non_camel_case_types)]
        pub enum RustTarget {
            $(
                $(
                    #[$attr]
                )*
                $release,
            )*
        }

        impl Default for RustTarget {
            /// Gives the latest stable Rust version
            fn default() -> RustTarget {
                LATEST_STABLE_RUST
            }
        }

        impl FromStr for RustTarget {
            type Err = io::Error;

            /// Create a `RustTarget` from a string.
            ///
            /// * The stable/beta versions of Rust are of the form "1.0",
            /// "1.19", etc.
            /// * The nightly version should be specified with "nightly".
            fn from_str(s: &str) -> Result<Self, Self::Err> {
                match s.as_ref() {
                    $(
                        stringify!($value) => Ok(RustTarget::$release),
                    )*
                    _ => Err(
                        io::Error::new(
                            io::ErrorKind::InvalidInput,
                            concat!(
                                "Got an invalid rust target. Accepted values ",
                                "are of the form ",
                                "\"1.0\" or \"nightly\"."))),
                }
            }
        }

        impl From<RustTarget> for String {
            fn from(target: RustTarget) -> Self {
                match target {
                    $(
                        RustTarget::$release => stringify!($value),
                    )*
                }.into()
            }
        }
    }
}

/// Defines an array slice with all RustTarget values
macro_rules! rust_target_values_def {
    ( $( $( #[$attr:meta] )* => $release:ident => $value:expr; )* ) => {
        /// Strings of allowed `RustTarget` values
        pub static RUST_TARGET_STRINGS: &'static [&str] = &[
            $(
                stringify!($value),
            )*
        ];
    }
}

/// Defines macro which takes a macro
macro_rules! rust_target_base {
    ( $x_macro:ident ) => {
        $x_macro!(
            /// Rust stable 1.0
            => Stable_1_0 => 1.0;
            /// Rust stable 1.19
            => Stable_1_19 => 1.19;
            /// Rust stable 1.20
            => Stable_1_20 => 1.20;
            /// Rust stable 1.21
            => Stable_1_21 => 1.21;
            /// Rust stable 1.25
            => Stable_1_25 => 1.25;
            /// Nightly rust
            => Nightly => nightly;
        );
    }
}

rust_target_base!(rust_target_def);
rust_target_base!(rust_target_values_def);

/// Latest stable release of Rust
pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_21;

/// Create RustFeatures struct definition, new(), and a getter for each field
macro_rules! rust_feature_def {
    (
        $( $rust_target:ident {
            $( $( #[$attr:meta] )* => $feature:ident; )*
        } )*
    ) => {
        /// Features supported by a rust target
        #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
        pub struct RustFeatures {
            $( $(
                $(
                    #[$attr]
                )*
                pub $feature: bool,
            )* )*
        }

        impl RustFeatures {
            /// Gives a RustFeatures struct with all features disabled
            fn new() -> Self {
                RustFeatures {
                    $( $(
                        $feature: false,
                    )* )*
                }
            }
        }

        impl From<RustTarget> for RustFeatures {
            fn from(rust_target: RustTarget) -> Self {
                let mut features = RustFeatures::new();

                $(
                if rust_target >= RustTarget::$rust_target {
                    $(
                    features.$feature = true;
                    )*
                }
                )*

                features
            }
        }
    }
}

rust_feature_def!(
    Stable_1_19 {
        /// Untagged unions ([RFC 1444](https://github.com/rust-lang/rfcs/blob/master/text/1444-union.md))
        => untagged_union;
    }
    Stable_1_20 {
        /// associated constants ([PR](https://github.com/rust-lang/rust/pull/42809))
        => associated_const;
    }
    Stable_1_21 {
        /// builtin impls for `Clone` ([PR](https://github.com/rust-lang/rust/pull/43690))
        => builtin_clone_impls;
    }
    Stable_1_25 {
        /// repr(align) ([PR](https://github.com/rust-lang/rust/pull/47006))
        => repr_align;
    }
    Nightly {
        /// `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
        => thiscall_abi;
    }
);

impl Default for RustFeatures {
    fn default() -> Self {
        let default_rust_target: RustTarget = Default::default();
        Self::from(default_rust_target)
    }
}

#[cfg(test)]
mod test {
    #![allow(unused_imports)]
    use super::*;

    #[test]
    fn target_features() {
        let f_1_0 = RustFeatures::from(RustTarget::Stable_1_0);
        assert!(
            !f_1_0.untagged_union
                && !f_1_0.associated_const
                && !f_1_0.builtin_clone_impls
                && !f_1_0.repr_align
                && !f_1_0.thiscall_abi
        );
        let f_1_21 = RustFeatures::from(RustTarget::Stable_1_21);
        assert!(
            f_1_21.untagged_union
                && f_1_21.associated_const
                && f_1_21.builtin_clone_impls
                && !f_1_21.repr_align
                && !f_1_21.thiscall_abi
        );
        let f_nightly = RustFeatures::from(RustTarget::Nightly);
        assert!(
            f_nightly.untagged_union
                && f_nightly.associated_const
                && f_nightly.builtin_clone_impls
                && f_nightly.repr_align
                && f_nightly.thiscall_abi
        );
    }

    fn test_target(target_str: &str, target: RustTarget) {
        let target_string: String = target.into();
        assert_eq!(target_str, target_string);
        assert_eq!(target, RustTarget::from_str(target_str).unwrap());
    }

    #[test]
    fn str_to_target() {
        test_target("1.0", RustTarget::Stable_1_0);
        test_target("1.19", RustTarget::Stable_1_19);
        test_target("1.21", RustTarget::Stable_1_21);
        test_target("1.25", RustTarget::Stable_1_25);
        test_target("nightly", RustTarget::Nightly);
    }
}
<|endoftext|>


<commit_before>use itertools::Itertools;
use std::fmt::Debug;
use quickcheck::quickcheck;

struct Unspecialized<I>(I);
impl<I> Iterator for Unspecialized<I>
where
    I: Iterator,
{
    type Item = I::Item;

    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

fn check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F)
where
    V: Eq + Debug,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
    F: Fn(Box<dyn Iterator<Item = IterItem> + 'a>) -> V,
{
    assert_eq!(
        mapper(Box::new(Unspecialized(iterator.clone()))),
        mapper(Box::new(iterator.clone()))
    )
}

fn test_specializations<IterItem, Iter>(
    it: &Iter,
) where
    IterItem: Eq + Debug + Clone,
    Iter: Iterator<Item = IterItem> + Clone,
{
    check_specialized(it, |i| i.count());
    check_specialized(it, |i| i.last());
    check_specialized(it, |i| i.collect::<Vec<_>>());
    check_specialized(it, |i| {
        let mut parameters_from_fold = vec![];
        let fold_result = i.fold(vec![], |mut acc, v: IterItem| {
            parameters_from_fold.push((acc.clone(), v.clone()));
            acc.push(v);
            acc
        });
        (parameters_from_fold, fold_result)
    });
    check_specialized(it, |mut i| {
        let mut parameters_from_all = vec![];
        let first = i.next();
        let all_result = i.all(|x| {
            parameters_from_all.push(x.clone());
            Some(x)==first
        });
        (parameters_from_all, all_result)
    });
    let size = it.clone().count();
    for n in 0..size + 2 {
        check_specialized(it, |mut i| i.nth(n));
    }
    // size_hint is a bit harder to check
    let mut it_sh = it.clone();
    for n in 0..size + 2 {
        let len = it_sh.clone().count();
        let (min, max) = it_sh.size_hint();
        assert_eq!(size - n.min(size), len);
        assert!(min <= len);
        if let Some(max) = max {
            assert!(len <= max);
        }
        it_sh.next();
    }
}

fn put_back_test(test_vec: Vec<i32>) {
    {
        // Lexical lifetimes support
        let pb = itertools::put_back(test_vec.iter());
        test_specializations(&pb);
    }

    let mut pb = itertools::put_back(test_vec.into_iter());
    pb.put_back(1);
    test_specializations(&pb);
}

#[test]
fn put_back() {
    put_back_test(vec![7, 4, 1]);
}

quickcheck! {
    fn put_back_qc(test_vec: Vec<i32>) -> () {
        put_back_test(test_vec)
    }
}

fn merge_join_by_test(i1: Vec<usize>, i2: Vec<usize>) {
    let i1 = i1.into_iter();
    let i2 = i2.into_iter();
    let mjb = i1.clone().merge_join_by(i2.clone(), std::cmp::Ord::cmp);
    test_specializations(&mjb);

    // And the other way around
    let mjb = i2.merge_join_by(i1, std::cmp::Ord::cmp);
    test_specializations(&mjb);
}

#[test]
fn merge_join_by() {
    let i1 = vec![1, 3, 5, 7, 8, 9];
    let i2 = vec![0, 3, 4, 5];
    merge_join_by_test(i1, i2);
}

quickcheck! {
    fn merge_join_by_qc(i1: Vec<usize>, i2: Vec<usize>) -> () {
        merge_join_by_test(i1, i2)
    }
}
<commit_msg>Remove manual tests in favor of simpler quickcheck tests<commit_after>use itertools::Itertools;
use std::fmt::Debug;
use quickcheck::quickcheck;

struct Unspecialized<I>(I);
impl<I> Iterator for Unspecialized<I>
where
    I: Iterator,
{
    type Item = I::Item;

    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

fn check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F)
where
    V: Eq + Debug,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
    F: Fn(Box<dyn Iterator<Item = IterItem> + 'a>) -> V,
{
    assert_eq!(
        mapper(Box::new(Unspecialized(iterator.clone()))),
        mapper(Box::new(iterator.clone()))
    )
}

fn test_specializations<IterItem, Iter>(
    it: &Iter,
) where
    IterItem: Eq + Debug + Clone,
    Iter: Iterator<Item = IterItem> + Clone,
{
    check_specialized(it, |i| i.count());
    check_specialized(it, |i| i.last());
    check_specialized(it, |i| i.collect::<Vec<_>>());
    check_specialized(it, |i| {
        let mut parameters_from_fold = vec![];
        let fold_result = i.fold(vec![], |mut acc, v: IterItem| {
            parameters_from_fold.push((acc.clone(), v.clone()));
            acc.push(v);
            acc
        });
        (parameters_from_fold, fold_result)
    });
    check_specialized(it, |mut i| {
        let mut parameters_from_all = vec![];
        let first = i.next();
        let all_result = i.all(|x| {
            parameters_from_all.push(x.clone());
            Some(x)==first
        });
        (parameters_from_all, all_result)
    });
    let size = it.clone().count();
    for n in 0..size + 2 {
        check_specialized(it, |mut i| i.nth(n));
    }
    // size_hint is a bit harder to check
    let mut it_sh = it.clone();
    for n in 0..size + 2 {
        let len = it_sh.clone().count();
        let (min, max) = it_sh.size_hint();
        assert_eq!(size - n.min(size), len);
        assert!(min <= len);
        if let Some(max) = max {
            assert!(len <= max);
        }
        it_sh.next();
    }
}

fn put_back_test(test_vec: Vec<i32>) {
    {
        // Lexical lifetimes support
        let pb = itertools::put_back(test_vec.iter());
        test_specializations(&pb);
    }

    let mut pb = itertools::put_back(test_vec.into_iter());
    pb.put_back(1);
    test_specializations(&pb);
}

quickcheck! {
    fn put_back_qc(test_vec: Vec<i32>) -> () {
        put_back_test(test_vec)
    }
}

fn merge_join_by_test(i1: Vec<usize>, i2: Vec<usize>) {
    let i1 = i1.into_iter();
    let i2 = i2.into_iter();
    let mjb = i1.clone().merge_join_by(i2.clone(), std::cmp::Ord::cmp);
    test_specializations(&mjb);

    // And the other way around
    let mjb = i2.merge_join_by(i1, std::cmp::Ord::cmp);
    test_specializations(&mjb);
}

quickcheck! {
    fn merge_join_by_qc(i1: Vec<usize>, i2: Vec<usize>) -> () {
        merge_join_by_test(i1, i2)
    }
}
<|endoftext|>


<commit_before>//! Module used to construct fundamental parsers and combinators.

use ::{ParseResult, Input};

/// Private inner type containing the parse-state.
///
/// Only used to create fundamental parsers and combinators.
#[must_use]
#[derive(Debug, Eq, PartialEq)]
pub enum State<'a, I: 'a, T, E>
  where I: 'a,
        T: 'a,
        E: 'a {
    Data(&'a [I], T),
    Error(&'a [I], E),
    Incomplete(usize),
}

/// Trait for modifying `ParseResult`.
///
/// Only use this to create fundamental combinators.
pub trait ParseResultModify<'a> {
    type Input;
    type Data;
    type Error;

    /// Modifies the content of ParseResult, without changing its type.
    #[inline(always)]
    fn modify<F>(self, F) -> Self
      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>) -> ParseResult<'a, Self::Input, Self::Data, Self::Error>,
            <Self as ParseResultModify<'a>>::Input: 'a,
            <Self as ParseResultModify<'a>>::Data:  'a,
            <Self as ParseResultModify<'a>>::Error: 'a;

    /// Modifies the content of ParseResult, allowing types to change.
    // TODO: Is this needed?
    #[inline(always)]
    fn parse<I, T, E, F>(self, F) -> ParseResult<'a, I, T, E>
      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>) -> ParseResult<'a, I, T, E>,
            <Self as ParseResultModify<'a>>::Input: 'a,
            <Self as ParseResultModify<'a>>::Data:  'a,
            <Self as ParseResultModify<'a>>::Error: 'a;

    /// Consumes the `ParseResult` and reveals the inner state.
    #[inline(always)]
    fn internal(self) -> State<'a, Self::Input, Self::Data, Self::Error>;
}

impl<'a, I, T, E> ParseResultModify<'a> for ParseResult<'a, I, T, E> {
    type Input = I;
    type Data  = T;
    type Error = E;

    #[inline(always)]
    fn modify<F>(self, f: F) -> Self
      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>) -> ParseResult<'a, Self::Input, Self::Data, Self::Error>,
            <Self as ParseResultModify<'a>>::Input: 'a,
            <Self as ParseResultModify<'a>>::Data:  'a,
            <Self as ParseResultModify<'a>>::Error: 'a {
        f(self.0)
    }

    #[inline(always)]
    fn parse<N, Y, R, F>(self, f: F) -> ParseResult<'a, N, Y, R>
      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>) -> ParseResult<'a, N, Y, R>,
            <Self as ParseResultModify<'a>>::Input: 'a,
            <Self as ParseResultModify<'a>>::Data:  'a,
            <Self as ParseResultModify<'a>>::Error: 'a {
        f(self.0)
    }

    #[inline(always)]
    fn internal(self) -> State<'a, Self::Input, Self::Data, Self::Error> {
        self.0
    }
}

/// Trait for modifying `Input`.
///
/// Only use this to create fundamental parsers and combinators.
pub trait InputModify<'a> {
    type Type;

    /// Modifies the inner data without leaving the `Input` context.
    #[inline(always)]
    fn modify<F>(self, f: F) -> Self
      where F: FnOnce(&'a [Self::Type]) -> &'a [Self::Type],
            <Self as InputModify<'a>>::Type: 'a;

    /// Applies a parser operating directly on &[Type] to the input.
    #[inline(always)]
    fn parse<F, T, E>(self, f: F) -> ParseResult<'a, Self::Type, T, E>
      where F: FnOnce(&'a [Self::Type]) -> ParseResult<'a, Self::Type, T, E>,
            <Self as InputModify<'a>>::Type: 'a;
}

/// Creates a data-carrying value from an input slice and a data value.
#[inline(always)]
pub fn data<'a, I, T, E>(i: &'a [I], t: T) -> ParseResult<'a, I, T, E> {
    ParseResult(State::Data(i, t))
}

/// Creates an error value from an input slice and an error value.
#[inline(always)]
pub fn error<'a, I, T, E>(i: &'a [I], e: E) -> ParseResult<'a, I, T, E> {
    ParseResult(State::Error(i, e))
}

/// Notifies the combinator that a parser has reached the end of the currently supplied slice but
/// requires more data.
#[inline(always)]
pub fn incomplete<'a, I, T, E>(n: usize) -> ParseResult<'a, I, T, E> {
    ParseResult(State::Incomplete(n))
}

impl<'a, I> InputModify<'a> for Input<'a, I> {
    type Type = I;

    #[inline(always)]
    fn modify<F>(self, f: F) -> Self
      where F: FnOnce(&'a [Self::Type]) -> &'a [Self::Type] {
        Input(f(self.0))
    }

    #[inline(always)]
    fn parse<F, T, E>(self, f: F) -> ParseResult<'a, Self::Type, T, E>
      where F: FnOnce(&'a [Self::Type]) -> ParseResult<'a, Self::Type, T, E> {
        f(self.0)
    }
}

<commit_msg>Rustdoc<commit_after>//! Module used to construct fundamental parsers and combinators.
//!
//! # Internal
//!
//! Only used by fundamental parsers and combinators.

use ::{ParseResult, Input};

/// Internal inner type containing the parse-state.
///
/// # Internal
///
/// Only used by fundamental parsers and combinators.
#[must_use]
#[derive(Debug, Eq, PartialEq)]
pub enum State<'a, I: 'a, T, E>
  where I: 'a,
        T: 'a,
        E: 'a {
    Data(&'a [I], T),
    Error(&'a [I], E),
    Incomplete(usize),
}

/// Internal trait for modifying `ParseResult`.
///
/// # Internal
///
/// Only used by fundamental parsers and combinators.
pub trait ParseResultModify<'a> {
    type Input;
    type Data;
    type Error;

    /// Modifies the content of ParseResult, without changing its type.
    #[inline(always)]
    fn modify<F>(self, F) -> Self
      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>) -> ParseResult<'a, Self::Input, Self::Data, Self::Error>,
            <Self as ParseResultModify<'a>>::Input: 'a,
            <Self as ParseResultModify<'a>>::Data:  'a,
            <Self as ParseResultModify<'a>>::Error: 'a;

    /// Applies the function `f` to the inner `State`, allows modification of data and error types.
    #[inline(always)]
    fn parse<I, T, E, F>(self, F) -> ParseResult<'a, I, T, E>
      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>) -> ParseResult<'a, I, T, E>,
            <Self as ParseResultModify<'a>>::Input: 'a,
            <Self as ParseResultModify<'a>>::Data:  'a,
            <Self as ParseResultModify<'a>>::Error: 'a;

    /// Consumes the `ParseResult` and reveals the inner state.
    #[inline(always)]
    fn internal(self) -> State<'a, Self::Input, Self::Data, Self::Error>;
}

/// Implementation of internal trait used as a building block for combinators.
///
/// # Internal
///
/// Only used by fundamental parsers and combinators.
impl<'a, I, T, E> ParseResultModify<'a> for ParseResult<'a, I, T, E> {
    type Input = I;
    type Data  = T;
    type Error = E;

    /// Applies the function `f` to the inner `State` while preserving types.
    #[inline(always)]
    fn modify<F>(self, f: F) -> Self
      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>) -> ParseResult<'a, Self::Input, Self::Data, Self::Error>,
            <Self as ParseResultModify<'a>>::Input: 'a,
            <Self as ParseResultModify<'a>>::Data:  'a,
            <Self as ParseResultModify<'a>>::Error: 'a {
        f(self.0)
    }

    /// Applies the function `f` to the inner `State`, allows modification of data and error types.
    #[inline(always)]
    fn parse<N, Y, R, F>(self, f: F) -> ParseResult<'a, N, Y, R>
      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>) -> ParseResult<'a, N, Y, R>,
            <Self as ParseResultModify<'a>>::Input: 'a,
            <Self as ParseResultModify<'a>>::Data:  'a,
            <Self as ParseResultModify<'a>>::Error: 'a {
        f(self.0)
    }

    /// Consumes the `ParseResult` and reveals the inner state.
    #[inline(always)]
    fn internal(self) -> State<'a, Self::Input, Self::Data, Self::Error> {
        self.0
    }
}

/// Trait for modifying `Input`.
///
/// # Internal
///
/// Only used by fundamental parsers and combinators.
pub trait InputModify<'a> {
    type Type;

    /// Modifies the inner data without leaving the `Input` context.
    #[inline(always)]
    fn modify<F>(self, f: F) -> Self
      where F: FnOnce(&'a [Self::Type]) -> &'a [Self::Type],
            <Self as InputModify<'a>>::Type: 'a;

    /// Applies a parser operating directly on &[Type] to the input.
    #[inline(always)]
    fn parse<F, T, E>(self, f: F) -> ParseResult<'a, Self::Type, T, E>
      where F: FnOnce(&'a [Self::Type]) -> ParseResult<'a, Self::Type, T, E>,
            <Self as InputModify<'a>>::Type: 'a;
}

/// Implementation of internal trait used to build parsers and combinators.
///
/// # Internal
///
/// Only used by fundamental parsers and combinators.
impl<'a, I> InputModify<'a> for Input<'a, I> {
    type Type = I;

    /// Modifies the inner data without leaving the `Input` context.
    #[inline(always)]
    fn modify<F>(self, f: F) -> Self
      where F: FnOnce(&'a [Self::Type]) -> &'a [Self::Type] {
        Input(f(self.0))
    }

    /// Applies a parser operating directly on &[Type] to the input.
    #[inline(always)]
    fn parse<F, T, E>(self, f: F) -> ParseResult<'a, Self::Type, T, E>
      where F: FnOnce(&'a [Self::Type]) -> ParseResult<'a, Self::Type, T, E> {
        f(self.0)
    }
}

/// Creates a data-carrying value from an input slice and a data value.
///
/// # Internal
///
/// Only used by fundamental parsers and combinators.
#[inline(always)]
pub fn data<'a, I, T, E>(i: &'a [I], t: T) -> ParseResult<'a, I, T, E> {
    ParseResult(State::Data(i, t))
}

/// Creates an error value from an input slice and an error value.
///
/// # Internal
///
/// Only used by fundamental parsers and combinators.
#[inline(always)]
pub fn error<'a, I, T, E>(i: &'a [I], e: E) -> ParseResult<'a, I, T, E> {
    ParseResult(State::Error(i, e))
}

/// Notifies the combinator that a parser has reached the end of the currently supplied slice but
/// requires more data.
///
/// # Internal
///
/// Only used by fundamental parsers and combinators.
#[inline(always)]
pub fn incomplete<'a, I, T, E>(n: usize) -> ParseResult<'a, I, T, E> {
    ParseResult(State::Incomplete(n))
}
<|endoftext|>


<commit_before>
import util.option;
import util.some;
import util.none;

// FIXME: It would probably be more appealing to define this as
// type list[T] = rec(T hd, option[@list[T]] tl), but at the moment
// our recursion rules do not permit that.

tag list[T] {
    cons(T, @list[T]);
    nil;
}

fn foldl[T,U](&list[T] ls, U u, fn(&T t, U u) -> U f) -> U {
  alt(ls) {
    case (cons[T](?hd, ?tl)) {
      auto u_ = f(hd, u);
      // FIXME: should use 'be' here, not 'ret'. But parametric
      // tail calls currently don't work.
      ret foldl[T,U](*tl, u_, f);
    }
    case (nil[T]) {
      ret u;
    }
  }
}

fn find[T](&list[T] ls,
             (fn(&T) -> option[T]) f) -> option[T] {
  alt(ls) {
    case (cons[T](?hd, ?tl)) {
        alt (f(hd)) {
            case (none[T]) {
                // FIXME: should use 'be' here, not 'ret'. But parametric tail
                // calls currently don't work.
                ret find[T](*tl, f);
            }
            case (some[T](?res)) {
                ret some[T](res);
            }
        }
    }
    case (nil[T]) {
        ret none[T];
    }
  }
}

fn length[T](&list[T] ls) -> uint {
  fn count[T](&T t, uint u) -> uint {
    ret u + 1u;
  }
  ret foldl[T,uint](ls, 0u, bind count[T](_, _));
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Make list.find return an option of different type than the list element.<commit_after>
import util.option;
import util.some;
import util.none;

// FIXME: It would probably be more appealing to define this as
// type list[T] = rec(T hd, option[@list[T]] tl), but at the moment
// our recursion rules do not permit that.

tag list[T] {
    cons(T, @list[T]);
    nil;
}

fn foldl[T,U](&list[T] ls, U u, fn(&T t, U u) -> U f) -> U {
  alt(ls) {
    case (cons[T](?hd, ?tl)) {
      auto u_ = f(hd, u);
      // FIXME: should use 'be' here, not 'ret'. But parametric
      // tail calls currently don't work.
      ret foldl[T,U](*tl, u_, f);
    }
    case (nil[T]) {
      ret u;
    }
  }
}

fn find[T,U](&list[T] ls,
             (fn(&T) -> option[U]) f) -> option[U] {
  alt(ls) {
    case (cons[T](?hd, ?tl)) {
        alt (f(hd)) {
            case (none[U]) {
                // FIXME: should use 'be' here, not 'ret'. But parametric tail
                // calls currently don't work.
                ret find[T,U](*tl, f);
            }
            case (some[U](?res)) {
                ret some[U](res);
            }
        }
    }
    case (nil[T]) {
        ret none[U];
    }
  }
}

fn length[T](&list[T] ls) -> uint {
  fn count[T](&T t, uint u) -> uint {
    ret u + 1u;
  }
  ret foldl[T,uint](ls, 0u, bind count[T](_, _));
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


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

const MOD_PATH_SIZE: usize = 200;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Edge {
    Child,
}

pub struct GraphBuilder {
    graph: DiGraphMap<Mod, Edge>,
}

impl GraphBuilder {
    pub fn new() -> Self {
        Self {
            graph: DiGraphMap::new(),
        }
    }

    pub fn add_crate_root(&mut self, name: &str) {
        self.graph.add_node(Mod::new(name, Visibility::Public));
    }

    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, "::", name].concat(), visibility);
        self.graph.add_node(node);
        assert!(self.graph.add_edge(parent, node, Edge::Child).is_none());
    }

    pub fn build(self) -> Result<DiGraphMap<Mod, Edge>, GraphError> {
        Ok(self.graph)
    }

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

    // TODO: add_dep();
}

#[derive(Debug)]
pub enum GraphError {}

#[derive(Clone, Copy, Debug)]
pub struct Mod {
    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(),
            name_ridx: path.rfind("::").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_node_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)>>()
        );
    }

    // TODO: Add test where builder fails when non-existent parent node
}
<commit_msg>Panic with a better message when the module path is too long<commit_after>use arrayvec::ArrayString;
use petgraph::graphmap::DiGraphMap;
use std::cmp::{Ord, Ordering};
use std::hash::{Hash, Hasher};

const MOD_PATH_SIZE: usize = 200;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Edge {
    Child,
}

pub struct GraphBuilder {
    graph: DiGraphMap<Mod, Edge>,
}

impl GraphBuilder {
    pub fn new() -> Self {
        Self {
            graph: DiGraphMap::new(),
        }
    }

    pub fn add_crate_root(&mut self, name: &str) {
        self.graph.add_node(Mod::new(name, Visibility::Public));
    }

    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, "::", name].concat(), visibility);
        self.graph.add_node(node);
        assert!(self.graph.add_edge(parent, node, Edge::Child).is_none());
    }

    pub fn build(self) -> Result<DiGraphMap<Mod, Edge>, GraphError> {
        Ok(self.graph)
    }

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

    // TODO: add_dep();
}

#[derive(Debug)]
pub enum GraphError {}

#[derive(Clone, Copy, Debug)]
pub struct Mod {
    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("::").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);
    }

    // TODO: Add test where builder fails when non-existent parent node
}
<|endoftext|>