<commit_before>use std::{
    cmp::{min, Reverse},
    io,
    io::{Cursor, Write},
    ops::AddAssign,
};

use axum::{
    body,
    response::{IntoResponse, Response},
};
use bytes::{Buf, BufMut};
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr, SpaceSeparator, StringWithSeparator};
use shakmaty::{san::SanPlus, uci::Uci, ByColor, Chess, Color, Outcome};

use crate::{
    api::Limits,
    model::{
        read_uci, write_uci, GameId, GamePlayer, LaxDate, PreparedMove, PreparedResponse, Stats,
    },
    util::{sort_by_key_and_truncate, ByColorDef},
};

#[serde_as]
#[derive(Deserialize, Debug)]
pub struct MastersGameWithId {
    #[serde_as(as = "DisplayFromStr")]
    pub id: GameId,
    #[serde(flatten)]
    pub game: MastersGame,
}

#[serde_as]
#[derive(Serialize, Deserialize, Debug)]
pub struct MastersGame {
    pub event: String,
    pub site: String,
    #[serde_as(as = "DisplayFromStr")]
    pub date: LaxDate,
    pub round: String,
    #[serde(flatten, with = "ByColorDef")]
    pub players: ByColor<GamePlayer>,
    #[serde_as(as = "Option<DisplayFromStr>")]
    pub winner: Option<Color>,
    #[serde_as(as = "StringWithSeparator<SpaceSeparator, Uci>")]
    pub moves: Vec<Uci>,
}

impl MastersGame {
    fn outcome(&self) -> Outcome {
        Outcome::from_winner(self.winner)
    }

    fn write_pgn<W: Write>(&self, writer: &mut W) -> io::Result<()> {
        writeln!(writer, "[Event \"{}\"]", self.event)?;
        writeln!(writer, "[Site \"{}\"]", self.site)?;
        writeln!(writer, "[Date \"{}\"]", self.date)?;
        writeln!(writer, "[Round \"{}\"]", self.round)?;
        writeln!(writer, "[White \"{}\"]", self.players.white.name)?;
        writeln!(writer, "[Black \"{}\"]", self.players.black.name)?;
        writeln!(writer, "[Result \"{}\"]", self.outcome())?;
        writeln!(writer, "[WhiteElo \"{}\"]", self.players.white.rating)?;
        writeln!(writer, "[BlackElo \"{}\"]", self.players.black.rating)?;
        writeln!(writer)?;

        let mut pos = Chess::default();

        for (i, uci) in self.moves.iter().enumerate() {
            let m = uci
                .to_move(&pos)
                .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
            if i % 2 == 0 {
                if i > 0 {
                    write!(writer, " ")?;
                }
                write!(writer, "{}.", i / 2 + 1)?;
            }
            let san = SanPlus::from_move_and_play_unchecked(&mut pos, &m);
            write!(writer, " {}", san)?;
        }

        if !self.moves.is_empty() {
            write!(writer, " ")?;
        }
        writeln!(writer, "{}", self.outcome())
    }
}

impl IntoResponse for MastersGame {
    fn into_response(self) -> Response {
        let mut buf = Cursor::new(Vec::new());
        self.write_pgn(&mut buf).expect("write pgn");

        Response::builder()
            .header(axum::http::header::CONTENT_TYPE, "application/x-chess-pgn")
            .body(body::boxed(body::Full::from(buf.into_inner())))
            .unwrap()
    }
}

#[derive(Debug, Default)]
pub struct MastersGroup {
    pub stats: Stats,
    pub games: Vec<(u16, GameId)>,
}

impl AddAssign for MastersGroup {
    fn add_assign(&mut self, rhs: MastersGroup) {
        self.stats += rhs.stats;
        self.games.extend(rhs.games);
    }
}

#[derive(Default, Debug)]
pub struct MastersEntry {
    pub groups: FxHashMap<Uci, MastersGroup>,
}

impl MastersEntry {
    pub const SIZE_HINT: usize = 14;

    pub fn new_single(
        uci: Uci,
        id: GameId,
        outcome: Outcome,
        mover_rating: u16,
        opponent_rating: u16,
    ) -> MastersEntry {
        let mut groups = FxHashMap::with_capacity_and_hasher(1, Default::default());
        groups.insert(
            uci,
            MastersGroup {
                stats: Stats::new_single(outcome, mover_rating),
                games: vec![(mover_rating.saturating_add(opponent_rating), id)],
            },
        );
        MastersEntry { groups }
    }

    pub fn extend_from_reader<B: Buf>(&mut self, buf: &mut B) {
        while buf.has_remaining() {
            let uci = read_uci(buf);
            let group = self.groups.entry(uci).or_default();
            group.stats += Stats::read(buf);
            let num_games = usize::from(buf.get_u8());
            group
                .games
                .extend((0..num_games).map(|_| (buf.get_u16_le(), GameId::read(buf))));
        }
    }

    pub fn write<B: BufMut>(&self, buf: &mut B) {
        let mut top_games = Vec::new();
        for group in self.groups.values() {
            top_games.extend(&group.games);
        }
        sort_by_key_and_truncate(&mut top_games, 15, |(sort_key, _)| Reverse(*sort_key));

        for (uci, group) in &self.groups {
            write_uci(buf, uci);

            group.stats.write(buf);

            let num_games = if group.games.len() == 1 {
                1
            } else {
                group.games.iter().filter(|g| top_games.contains(g)).count()
            };
            buf.put_u8(num_games as u8);
            for (sort_key, id) in group
                .games
                .iter()
                .filter(|g| group.games.len() == 1 || top_games.contains(g))
            {
                buf.put_u16_le(*sort_key);
                id.write(buf);
            }
        }
    }

    fn total(&self) -> Stats {
        let mut sum = Stats::default();
        for group in self.groups.values() {
            sum += group.stats.clone();
        }
        sum
    }

    pub fn prepare(self, limits: &Limits) -> PreparedResponse {
        let total = self.total();

        let mut top_games = Vec::new();
        for (uci, group) in &self.groups {
            for (sort_key, game) in &group.games {
                top_games.push((*sort_key, uci.to_owned(), *game));
            }
        }
        sort_by_key_and_truncate(
            &mut top_games,
            min(limits.top_games, 15),
            |(sort_key, _, _)| Reverse(*sort_key),
        );

        let mut moves: Vec<PreparedMove> = self
            .groups
            .into_iter()
            .map(|(uci, group)| {
                let single_game = if group.stats.is_single() {
                    group.games.iter().map(|(_, id)| *id).next()
                } else {
                    None
                };
                PreparedMove {
                    uci,
                    average_rating: group.stats.average_rating(),
                    average_opponent_rating: None,
                    game: single_game,
                    stats: group.stats,
                }
            })
            .collect();
        sort_by_key_and_truncate(&mut moves, limits.moves.unwrap_or(12), |m| {
            Reverse(m.stats.total())
        });

        PreparedResponse {
            total,
            moves,
            top_games: top_games
                .into_iter()
                .map(|(_, uci, game)| (uci, game))
                .collect(),
            recent_games: Vec::new(),
        }
    }
}

#[cfg(test)]
mod tests {
    use shakmaty::Square;

    use super::*;

    #[test]
    fn test_masters_entry() {
        let uci = Uci::Normal {
            from: Square::E2,
            to: Square::E4,
            promotion: None,
        };
        let game = "aaaaaaaa".parse().unwrap();
        let a = MastersEntry::new_single(uci.clone(), game, Outcome::Draw, 1600, 1700);

        let mut buf = Vec::with_capacity(MastersEntry::SIZE_HINT);
        a.write(&mut buf);
        assert_eq!(
            buf.len(),
            MastersEntry::SIZE_HINT,
            "optimized for single entries"
        );

        let mut reader = &buf[..];
        let mut deserialized = MastersEntry::default();
        deserialized.extend_from_reader(&mut reader);

        let group = deserialized.groups.get(&uci).unwrap();
        assert_eq!(group.stats.draws, 1);
        assert_eq!(group.games[0], (1600 + 1700, game));
    }
}
<commit_msg>code golf extend loop<commit_after>use std::{
    cmp::{min, Reverse},
    io,
    io::{Cursor, Write},
    ops::AddAssign,
};

use axum::{
    body,
    response::{IntoResponse, Response},
};
use bytes::{Buf, BufMut};
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr, SpaceSeparator, StringWithSeparator};
use shakmaty::{san::SanPlus, uci::Uci, ByColor, Chess, Color, Outcome};

use crate::{
    api::Limits,
    model::{
        read_uci, write_uci, GameId, GamePlayer, LaxDate, PreparedMove, PreparedResponse, Stats,
    },
    util::{sort_by_key_and_truncate, ByColorDef},
};

#[serde_as]
#[derive(Deserialize, Debug)]
pub struct MastersGameWithId {
    #[serde_as(as = "DisplayFromStr")]
    pub id: GameId,
    #[serde(flatten)]
    pub game: MastersGame,
}

#[serde_as]
#[derive(Serialize, Deserialize, Debug)]
pub struct MastersGame {
    pub event: String,
    pub site: String,
    #[serde_as(as = "DisplayFromStr")]
    pub date: LaxDate,
    pub round: String,
    #[serde(flatten, with = "ByColorDef")]
    pub players: ByColor<GamePlayer>,
    #[serde_as(as = "Option<DisplayFromStr>")]
    pub winner: Option<Color>,
    #[serde_as(as = "StringWithSeparator<SpaceSeparator, Uci>")]
    pub moves: Vec<Uci>,
}

impl MastersGame {
    fn outcome(&self) -> Outcome {
        Outcome::from_winner(self.winner)
    }

    fn write_pgn<W: Write>(&self, writer: &mut W) -> io::Result<()> {
        writeln!(writer, "[Event \"{}\"]", self.event)?;
        writeln!(writer, "[Site \"{}\"]", self.site)?;
        writeln!(writer, "[Date \"{}\"]", self.date)?;
        writeln!(writer, "[Round \"{}\"]", self.round)?;
        writeln!(writer, "[White \"{}\"]", self.players.white.name)?;
        writeln!(writer, "[Black \"{}\"]", self.players.black.name)?;
        writeln!(writer, "[Result \"{}\"]", self.outcome())?;
        writeln!(writer, "[WhiteElo \"{}\"]", self.players.white.rating)?;
        writeln!(writer, "[BlackElo \"{}\"]", self.players.black.rating)?;
        writeln!(writer)?;

        let mut pos = Chess::default();

        for (i, uci) in self.moves.iter().enumerate() {
            let m = uci
                .to_move(&pos)
                .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
            if i % 2 == 0 {
                if i > 0 {
                    write!(writer, " ")?;
                }
                write!(writer, "{}.", i / 2 + 1)?;
            }
            let san = SanPlus::from_move_and_play_unchecked(&mut pos, &m);
            write!(writer, " {}", san)?;
        }

        if !self.moves.is_empty() {
            write!(writer, " ")?;
        }
        writeln!(writer, "{}", self.outcome())
    }
}

impl IntoResponse for MastersGame {
    fn into_response(self) -> Response {
        let mut buf = Cursor::new(Vec::new());
        self.write_pgn(&mut buf).expect("write pgn");

        Response::builder()
            .header(axum::http::header::CONTENT_TYPE, "application/x-chess-pgn")
            .body(body::boxed(body::Full::from(buf.into_inner())))
            .unwrap()
    }
}

#[derive(Debug, Default)]
pub struct MastersGroup {
    pub stats: Stats,
    pub games: Vec<(u16, GameId)>,
}

impl AddAssign for MastersGroup {
    fn add_assign(&mut self, rhs: MastersGroup) {
        self.stats += rhs.stats;
        self.games.extend(rhs.games);
    }
}

#[derive(Default, Debug)]
pub struct MastersEntry {
    pub groups: FxHashMap<Uci, MastersGroup>,
}

impl MastersEntry {
    pub const SIZE_HINT: usize = 14;

    pub fn new_single(
        uci: Uci,
        id: GameId,
        outcome: Outcome,
        mover_rating: u16,
        opponent_rating: u16,
    ) -> MastersEntry {
        let mut groups = FxHashMap::with_capacity_and_hasher(1, Default::default());
        groups.insert(
            uci,
            MastersGroup {
                stats: Stats::new_single(outcome, mover_rating),
                games: vec![(mover_rating.saturating_add(opponent_rating), id)],
            },
        );
        MastersEntry { groups }
    }

    pub fn extend_from_reader<B: Buf>(&mut self, buf: &mut B) {
        while buf.has_remaining() {
            let uci = read_uci(buf);
            let group = self.groups.entry(uci).or_default();
            group.stats += Stats::read(buf);
            let num_games = usize::from(buf.get_u8());
            group
                .games
                .extend((0..num_games).map(|_| (buf.get_u16_le(), GameId::read(buf))));
        }
    }

    pub fn write<B: BufMut>(&self, buf: &mut B) {
        let mut top_games = self
            .groups
            .values()
            .flat_map(|group| group.games.iter().copied())
            .collect();
        sort_by_key_and_truncate(&mut top_games, 15, |(sort_key, _)| Reverse(*sort_key));

        for (uci, group) in &self.groups {
            write_uci(buf, uci);

            group.stats.write(buf);

            let num_games = if group.games.len() == 1 {
                1
            } else {
                group.games.iter().filter(|g| top_games.contains(g)).count()
            };
            buf.put_u8(num_games as u8);
            for (sort_key, id) in group
                .games
                .iter()
                .filter(|g| group.games.len() == 1 || top_games.contains(g))
            {
                buf.put_u16_le(*sort_key);
                id.write(buf);
            }
        }
    }

    fn total(&self) -> Stats {
        let mut sum = Stats::default();
        for group in self.groups.values() {
            sum += group.stats.clone();
        }
        sum
    }

    pub fn prepare(self, limits: &Limits) -> PreparedResponse {
        let total = self.total();

        let mut top_games = Vec::new();
        for (uci, group) in &self.groups {
            for (sort_key, game) in &group.games {
                top_games.push((*sort_key, uci.to_owned(), *game));
            }
        }
        sort_by_key_and_truncate(
            &mut top_games,
            min(limits.top_games, 15),
            |(sort_key, _, _)| Reverse(*sort_key),
        );

        let mut moves: Vec<PreparedMove> = self
            .groups
            .into_iter()
            .map(|(uci, group)| {
                let single_game = if group.stats.is_single() {
                    group.games.iter().map(|(_, id)| *id).next()
                } else {
                    None
                };
                PreparedMove {
                    uci,
                    average_rating: group.stats.average_rating(),
                    average_opponent_rating: None,
                    game: single_game,
                    stats: group.stats,
                }
            })
            .collect();
        sort_by_key_and_truncate(&mut moves, limits.moves.unwrap_or(12), |m| {
            Reverse(m.stats.total())
        });

        PreparedResponse {
            total,
            moves,
            top_games: top_games
                .into_iter()
                .map(|(_, uci, game)| (uci, game))
                .collect(),
            recent_games: Vec::new(),
        }
    }
}

#[cfg(test)]
mod tests {
    use shakmaty::Square;

    use super::*;

    #[test]
    fn test_masters_entry() {
        let uci = Uci::Normal {
            from: Square::E2,
            to: Square::E4,
            promotion: None,
        };
        let game = "aaaaaaaa".parse().unwrap();
        let a = MastersEntry::new_single(uci.clone(), game, Outcome::Draw, 1600, 1700);

        let mut buf = Vec::with_capacity(MastersEntry::SIZE_HINT);
        a.write(&mut buf);
        assert_eq!(
            buf.len(),
            MastersEntry::SIZE_HINT,
            "optimized for single entries"
        );

        let mut reader = &buf[..];
        let mut deserialized = MastersEntry::default();
        deserialized.extend_from_reader(&mut reader);

        let group = deserialized.groups.get(&uci).unwrap();
        assert_eq!(group.stats.draws, 1);
        assert_eq!(group.games[0], (1600 + 1700, game));
    }
}
<|endoftext|>


<commit_before>#![allow(non_snake_case)]

use std::cmp;
use std::collections::HashMap;

use rgsl::randist::multinomial::multinomial_pdf;

use bio::stats::combinatorics::combinations;
use bio::stats::logprobs::{Prob, LogProb};
use bio::stats::logprobs;

struct Factory {
    N: u8,
    m: u8,
    p0: Prob,
    p1: Prob
}

impl Factory {

    /// Probability to make exactly i 1->0 and j 0->1 errors.
    fn xi(&self, i: u8, j: u8) -> Prob {
        self.p1.powi(i as i32) * self.p0.powi(j as i32) * (1.0 - self.p1).powi((self.m - i) as i32) * (1.0 - self.p0).powi((self.N - self.m - j) as i32)
    }

    /// Number of possibilities for i 1->0 and j 0->1 errors.
    fn psi(&self, i: u8, j: u8) -> f64 {
        combinations(self.m as u64, i as u64) * combinations((self.N - self.m)  as u64, j as u64)
    }

    /// Probability to see an exact readout given that we have a call.
    fn prob_call_exact(&self) -> Prob {
        self.xi(0, 0)
    }

    /// Probability to see a readout with one mismatch given that we have a call.
    fn prob_call_mismatch(&self) -> Prob {
        //(self.m as f64 * self.xi(1, 0) + (self.N - self.m) as f64 * self.xi(0, 1)) / self.N as f64
        (self.m as f64 * self.xi(1, 0) + (self.N - self.m) as f64 * self.xi(0, 1))
    }

    /// Probability to see an exact readout given that we have a miscall.
    fn prob_miscall_exact(&self) -> Prob {
        self.psi(2,2) * self.xi(2, 2)
    }

    /// Probability to see a readout with one mismatch given that we have a miscall.
    fn prob_miscall_mismatch(&self) -> Prob {
        self.psi(2, 1) * self.xi(2, 1) + self.psi(1, 2) * self.xi(1, 2) +
        self.psi(2, 3) * self.xi(2, 3) + self.psi(3, 2) * self.xi(3, 2)
    }

    /// Probability to completely miss a readout because of too many errors.
    fn prob_missed(&self) -> Prob {
        let mut p = 0.0;
        for k in 2..6 {
            for i in 0..cmp::min(self.m, k) + 1 {
                p += self.psi(i, k - i) * self.xi(i, k - i);
            }
        }
        p
    }
}

/// Readout probabilities.
pub struct Readout {
    prob_call_exact: Prob,
    prob_call_mismatch: Prob,
    prob_miscall_exact: LogProb,
    prob_miscall_mismatch: LogProb,
    prob_missed: Prob
}

impl Readout {
    pub fn new(N: u8, m: u8, p0: Prob, p1: Prob, dropout_rate: Prob) -> Self {
        let factory = Factory { N: N, m: m, p0: p0, p1: p1};
        Readout {
            prob_call_exact: factory.prob_call_exact(),
            prob_call_mismatch: factory.prob_call_mismatch(),
            prob_miscall_exact: factory.prob_miscall_exact().ln(),
            prob_miscall_mismatch: factory.prob_miscall_mismatch().ln(),
            prob_missed: factory.prob_missed()
        }
    }

    pub fn window(&self, count: u32, count_exact: u32) -> (u32, u32) {
        if count < 10 {
            (0, 20)
        }
        else {
            (count_exact, count + (count as f64 * self.prob_missed * 3.0) as u32)
        }
    }

    pub fn likelihood(&self, x: u32, count: u32, count_exact: u32) -> LogProb {
        let x = x;
        let count = count;
        let count_exact = count_exact;
        assert!(count >= count_exact);

        // TODO move to expression.rs and implement as dynamic programming over all x
        let mut summands = Vec::new();
        let probs = [self.prob_call_exact, self.prob_call_mismatch, self.prob_missed];
        for i in 0..(cmp::min(x, count) + 1) {
            let jmax = cmp::min(count_exact, i);
            let jmin = if count_exact + i > count { count_exact + i - count } else { 0 };
            for j in jmin..(jmax + 1) {
                let k = x - i;
                let p = multinomial_pdf(&probs, &[j, i - j, k]).ln() +
                        self.prob_miscall_exact *  (count_exact - j) as f64 +
                        self.prob_miscall_mismatch * (count - count_exact - (i - j)) as f64;
                summands.push(p);
            }
        }
        //println!("{:?}", summands);
        let likelihood = logprobs::log_prob_sum(&summands);
        assert!(!likelihood.is_nan());
        likelihood
    }
}

#[cfg(test)]
mod tests {
    #![allow(non_upper_case_globals)]

    use super::Factory;
    use nalgebra::ApproxEq;

    const factory: Factory = Factory { N: 16, m: 4, p0: 0.04, p1: 0.1 };

    #[test]
    fn test_prob_call_exact() {
        let p = factory.prob_call_exact();
        println!("{}", p);
        assert!(p.approx_eq(&0.4019988717840602));
    }

    #[test]
    fn test_prob_call_mismatch() {
        let p = factory.prob_call_mismatch();
        println!("{}", p);
        assert!(p.approx_eq(&0.3796656011293904));
    }

    #[test]
    fn test_prob_miscall_exact() {
        let p = factory.prob_miscall_exact();
        println!("{}", p);
        assert!(p.approx_eq(&0.003412027461130142));
    }

    #[test]
    fn test_prob_miscall_mismatch() {
        let p = factory.prob_miscall_mismatch();
        println!("{}", p);
        assert!(p.approx_eq(&0.03608764734772748));
    }

    #[test]
    fn test_prob_missed() {
        let p = factory.prob_missed();
        println!("{}", p);
        assert!(p.approx_eq(&0.21822058901379174));
    }

    #[test]
    fn test_xi() {
        let p = factory.xi(0, 0);
        assert!(p.approx_eq(&0.4019988717840602));
        let p = factory.xi(1, 0);
        assert!(p.approx_eq(&0.04466654130934002));
        let p = factory.xi(0, 1);
        assert!(p.approx_eq(&0.01674995299100251));
        let p = factory.xi(2, 2);
        assert!(p.approx_eq(&8.616230962449852e-06));
        let p = factory.xi(2, 1);
        assert!(p.approx_eq(&0.00020678954309879646));
        let p = factory.xi(1, 2);
        assert!(p.approx_eq(&7.754607866204867e-05));
    }
}
<commit_msg>Minor.<commit_after>#![allow(non_snake_case)]

use std::cmp;
use std::collections::HashMap;

use rgsl::randist::multinomial::multinomial_pdf;

use bio::stats::combinatorics::combinations;
use bio::stats::logprobs::{Prob, LogProb};
use bio::stats::logprobs;

struct Factory {
    N: u8,
    m: u8,
    p0: Prob,
    p1: Prob
}

impl Factory {

    /// Probability to make exactly i 1->0 and j 0->1 errors.
    fn xi(&self, i: u8, j: u8) -> Prob {
        self.p1.powi(i as i32) * self.p0.powi(j as i32) * (1.0 - self.p1).powi((self.m - i) as i32) * (1.0 - self.p0).powi((self.N - self.m - j) as i32)
    }

    /// Number of possibilities for i 1->0 and j 0->1 errors.
    fn psi(&self, i: u8, j: u8) -> f64 {
        combinations(self.m as u64, i as u64) * combinations((self.N - self.m)  as u64, j as u64)
    }

    /// Probability to see an exact readout given that we have a call.
    fn prob_call_exact(&self) -> Prob {
        self.xi(0, 0)
    }

    /// Probability to see a readout with one mismatch given that we have a call.
    fn prob_call_mismatch(&self) -> Prob {
        //(self.m as f64 * self.xi(1, 0) + (self.N - self.m) as f64 * self.xi(0, 1)) / self.N as f64
        (self.m as f64 * self.xi(1, 0) + (self.N - self.m) as f64 * self.xi(0, 1))
    }

    /// Probability to see an exact readout given that we have a miscall.
    fn prob_miscall_exact(&self) -> Prob {
        self.psi(2,2) * self.xi(2, 2)
    }

    /// Probability to see a readout with one mismatch given that we have a miscall.
    fn prob_miscall_mismatch(&self) -> Prob {
        self.psi(2, 1) * self.xi(2, 1) + self.psi(1, 2) * self.xi(1, 2) +
        self.psi(2, 3) * self.xi(2, 3) + self.psi(3, 2) * self.xi(3, 2)
    }

    /// Probability to completely miss a readout because of too many errors.
    fn prob_missed(&self) -> Prob {
        let mut p = 0.0;
        for k in 2..6 {
            for i in 0..cmp::min(self.m, k) + 1 {
                p += self.psi(i, k - i) * self.xi(i, k - i);
            }
        }
        p
    }
}

/// Readout probabilities.
pub struct Readout {
    prob_call_exact: Prob,
    prob_call_mismatch: Prob,
    prob_miscall_exact: LogProb,
    prob_miscall_mismatch: LogProb,
    prob_missed: Prob
}

impl Readout {
    pub fn new(N: u8, m: u8, p0: Prob, p1: Prob, dropout_rate: Prob) -> Self {
        let factory = Factory { N: N, m: m, p0: p0, p1: p1};
        Readout {
            prob_call_exact: factory.prob_call_exact(),
            prob_call_mismatch: factory.prob_call_mismatch(),
            prob_miscall_exact: factory.prob_miscall_exact().ln(),
            prob_miscall_mismatch: factory.prob_miscall_mismatch().ln(),
            prob_missed: factory.prob_missed()
        }
    }

    pub fn window(&self, count: u32, count_exact: u32) -> (u32, u32) {
        if count <= 10 {
            (0, 25)
        }
        else {
            (cmp::max(0, count as i32 - 10) as u32, count + (count as f64 * self.prob_missed * 4.0) as u32)
        }
    }

    pub fn likelihood(&self, x: u32, count: u32, count_exact: u32) -> LogProb {
        let x = x;
        let count = count;
        let count_exact = count_exact;
        assert!(count >= count_exact);

        // TODO move to expression.rs and implement as dynamic programming over all x
        let mut summands = Vec::new();
        let probs = [self.prob_call_exact, self.prob_call_mismatch, self.prob_missed];
        for i in 0..(cmp::min(x, count) + 1) {
            let jmax = cmp::min(count_exact, i);
            let jmin = if count_exact + i > count { count_exact + i - count } else { 0 };
            for j in jmin..(jmax + 1) {
                let k = x - i;
                let p = multinomial_pdf(&probs, &[j, i - j, k]).ln() +
                        self.prob_miscall_exact *  (count_exact - j) as f64 +
                        self.prob_miscall_mismatch * (count - count_exact - (i - j)) as f64;
                summands.push(p);
            }
        }
        //println!("{:?}", summands);
        let likelihood = logprobs::log_prob_sum(&summands);
        assert!(!likelihood.is_nan());
        likelihood
    }
}

#[cfg(test)]
mod tests {
    #![allow(non_upper_case_globals)]

    use super::Factory;
    use nalgebra::ApproxEq;

    const factory: Factory = Factory { N: 16, m: 4, p0: 0.04, p1: 0.1 };

    #[test]
    fn test_prob_call_exact() {
        let p = factory.prob_call_exact();
        println!("{}", p);
        assert!(p.approx_eq(&0.4019988717840602));
    }

    #[test]
    fn test_prob_call_mismatch() {
        let p = factory.prob_call_mismatch();
        println!("{}", p);
        assert!(p.approx_eq(&0.3796656011293904));
    }

    #[test]
    fn test_prob_miscall_exact() {
        let p = factory.prob_miscall_exact();
        println!("{}", p);
        assert!(p.approx_eq(&0.003412027461130142));
    }

    #[test]
    fn test_prob_miscall_mismatch() {
        let p = factory.prob_miscall_mismatch();
        println!("{}", p);
        assert!(p.approx_eq(&0.03608764734772748));
    }

    #[test]
    fn test_prob_missed() {
        let p = factory.prob_missed();
        println!("{}", p);
        assert!(p.approx_eq(&0.21822058901379174));
    }

    #[test]
    fn test_xi() {
        let p = factory.xi(0, 0);
        assert!(p.approx_eq(&0.4019988717840602));
        let p = factory.xi(1, 0);
        assert!(p.approx_eq(&0.04466654130934002));
        let p = factory.xi(0, 1);
        assert!(p.approx_eq(&0.01674995299100251));
        let p = factory.xi(2, 2);
        assert!(p.approx_eq(&8.616230962449852e-06));
        let p = factory.xi(2, 1);
        assert!(p.approx_eq(&0.00020678954309879646));
        let p = factory.xi(1, 2);
        assert!(p.approx_eq(&7.754607866204867e-05));
    }
}
<|endoftext|>


<commit_before><commit_msg>layout tweaks<commit_after><|endoftext|>


<commit_before>extern crate ggez;
extern crate rand;
extern crate sdl2;

use ggez::conf;
use ggez::event;
use ggez::{Context, GameResult};
use ggez::graphics;
use ggez::timer;
use std::time::Duration;

struct MainState {
    spritebatch: graphics::spritebatch::SpriteBatch,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let image = graphics::Image::new(ctx, "/tile.png").unwrap();
        let batch = graphics::spritebatch::SpriteBatch::new(image);
        let s = MainState {
            spritebatch: batch,
        };
        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context, _dt: Duration) -> GameResult<()> {

        if timer::get_ticks(ctx) % 100 == 0{

            println!("Delta frame time: {:?} ", _dt);
            println!("Average FPS: {}", timer::get_fps(ctx));
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx);

        for x in 0..50 {
            for y in 0..50 {
                let p = graphics::DrawParam {
                    dest: graphics::Point::new(x as f32 * 21.0 + 10.0, y as f32 * 20.0 + 10.0),
                    scale: graphics::Point::new(0.125, 0.125),
                    .. Default::default()
                };
                self.spritebatch.add(p);
            }
        }
        graphics::draw_ex(ctx, &self.spritebatch, Default::default())?;
        self.spritebatch.clear();

        graphics::present(ctx);
        Ok(())
    }
}

// Creating a gamestate depends on having an SDL context to load resources.
// Creating a context depends on loading a config file.
// Loading a config file depends on having FS (or we can just fake our way around it
// by creating an FS and then throwing it away; the costs are not huge.)
pub fn main() {
    let c = conf::Conf::new();
    println!("Starting with default config: {:#?}", c);
    let ctx = &mut Context::load_from_conf("imageview", "ggez", c).unwrap();
    let state = &mut MainState::new(ctx).unwrap();
    if let Err(e) = event::run(ctx, state) {
        println!("Error encountered: {}", e);
    } else {
        println!("Game exited cleanly.");
    }
}
<commit_msg>push stress test<commit_after>extern crate ggez;
extern crate rand;
extern crate sdl2;

use ggez::conf;
use ggez::event;
use ggez::{Context, GameResult};
use ggez::graphics;
use ggez::timer;
use std::time::Duration;

struct MainState {
    spritebatch: graphics::spritebatch::SpriteBatch,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let image = graphics::Image::new(ctx, "/tile.png").unwrap();
        let batch = graphics::spritebatch::SpriteBatch::new(image);
        let s = MainState {
            spritebatch: batch,
        };
        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context, _dt: Duration) -> GameResult<()> {

        if timer::get_ticks(ctx) % 100 == 0{

            println!("Delta frame time: {:?} ", _dt);
            println!("Average FPS: {}", timer::get_fps(ctx));
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx);

        for x in 0..100 {
            for y in 0..100 {
                let p = graphics::DrawParam {
                    dest: graphics::Point::new(x as f32 * 10.0 + 5.0, y as f32 * 10.0 + 5.0),
                    scale: graphics::Point::new(0.0625, 0.0625),
                    .. Default::default()
                };
                self.spritebatch.add(p);
            }
        }
        graphics::draw_ex(ctx, &self.spritebatch, Default::default())?;
        self.spritebatch.clear();

        graphics::present(ctx);
        Ok(())
    }
}

// Creating a gamestate depends on having an SDL context to load resources.
// Creating a context depends on loading a config file.
// Loading a config file depends on having FS (or we can just fake our way around it
// by creating an FS and then throwing it away; the costs are not huge.)
pub fn main() {
    let c = conf::Conf::new();
    println!("Starting with default config: {:#?}", c);
    let ctx = &mut Context::load_from_conf("imageview", "ggez", c).unwrap();
    let state = &mut MainState::new(ctx).unwrap();
    if let Err(e) = event::run(ctx, state) {
        println!("Error encountered: {}", e);
    } else {
        println!("Game exited cleanly.");
    }
}
<|endoftext|>


<commit_before>use uuid::Uuid;
use petgraph::graph::NodeIndex;

use super::super::{LayoutTree, Direction, TreeError};
use super::super::graph_tree::{GraphError, ShiftDirection};
use super::super::container::{Container, ContainerType, Handle, Layout};

pub enum ContainerMovementError {
    /// Attempted to move the node behind the UUID in the given direction,
    /// which would cause it to leave its siblings.
    MoveOutsideSiblings(Uuid, Direction),
    /// There was a tree error, generally should abort operation and pass this
    /// up back through the caller.
    InternalTreeError(TreeError)
}

impl LayoutTree {
    /// Returns the new parent of the active container if the move succeeds,
    /// Otherwise it signals what error occurred in the tree.
    pub fn move_recurse(&mut self, node_to_move: NodeIndex, move_ancestor: Option<NodeIndex>,
                           direction: Direction) -> Result<NodeIndex, TreeError> {
        match self.tree[node_to_move].get_type() {
            ContainerType::View | ContainerType::Container => { /* continue */ },
            _ => return Err(TreeError::UuidWrongType(self.tree[node_to_move].get_id(),
                                                     vec!(ContainerType::View,
                                                          ContainerType::Container)))
        }
        let parent_ix = try!(
            move_ancestor.and_then(|node| {
                self.tree.parent_of(node)
            }).or(self.tree.parent_of(node_to_move))
                .ok_or(TreeError::PetGraphError(GraphError::NoParent(node_to_move))));
        match self.tree[parent_ix] {
            Container::Container { layout, .. } =>  {
                match (layout, direction) {
                    (Layout::Horizontal, Direction::Left) |
                    (Layout::Horizontal, Direction::Right) |
                    (Layout::Vertical, Direction::Up) |
                    (Layout::Vertical, Direction::Down) => {
                        if let Some(ancestor_ix) = move_ancestor {
                            match self.move_between_ancestors(node_to_move, ancestor_ix, direction) {
                                Ok(new_parent_ix) => Ok(new_parent_ix),
                                Err(ContainerMovementError::InternalTreeError(err)) => {
                                    error!("Tree error moving between ancestors: {:?}", err);
                                    Err(err)
                                }
                                Err(ContainerMovementError::MoveOutsideSiblings(node, dir)) => {
                                    error!("Trying to move {:#?} in the {:?} direction somehow moved out of siblings",
                                           node, dir);
                                    panic!("Moving between ancestors failed in an unexpected way")
                                }
                            }
                        } else { /* Moving within current parent container */
                            match self.move_within_container(node_to_move, direction) {
                                Ok(new_parent_ix) => {
                                    Ok(new_parent_ix)
                                },
                                Err(ContainerMovementError::MoveOutsideSiblings(_,_)) => {
                                    self.move_recurse(node_to_move, Some(parent_ix), direction)
                                },
                                Err(ContainerMovementError::InternalTreeError(err)) => {
                                    Err(err)
                                }
                            }
                        }
                    },
                    _ => { self.move_recurse(node_to_move, Some(parent_ix), direction) }
                }
            },
            Container::Workspace { .. } => {
                Err(TreeError::InvalidOperationOnRootContainer(self.tree[node_to_move].get_id()))
            }
            _ => unreachable!()
        }
    }

    /// Attempt to move a container at the node index in the given direction.
    ///
    /// If the node would move outside of its current container by moving in that
    /// direction, then ContainerMovementError::MoveOutsideSiblings is returned.
    /// If the tree state is invalid, an appropriate wrapped up error is returned.
    ///
    /// If successful, the parent index of the node is returned.
    fn move_within_container(&mut self, node_ix: NodeIndex, direction: Direction)
                             -> Result<NodeIndex, ContainerMovementError> {
        let parent_ix = try!(self.tree.parent_of(node_ix)
                             .ok_or(ContainerMovementError::InternalTreeError(
                                 TreeError::PetGraphError(GraphError::NoParent(node_ix)))));
        let siblings_and_self = self.tree.children_of(parent_ix);
        let cur_index = try!(siblings_and_self.iter().position(|node| {
            *node == node_ix
        }).ok_or(ContainerMovementError::InternalTreeError(
            TreeError::NodeNotFound(self.tree[node_ix].get_id()))));
        let maybe_new_index = match direction {
            Direction::Right | Direction::Down => {
                cur_index.checked_add(1)
            }
            Direction::Left  | Direction::Up => {
                cur_index.checked_sub(1)
            }
        };
        if maybe_new_index.is_some() && maybe_new_index.unwrap() < siblings_and_self.len() {
            // There is a sibling to swap with
            let swap_index = maybe_new_index.unwrap();
            let swap_ix = siblings_and_self[swap_index];
            match self.tree[swap_ix] {
                Container::View { .. } => {
                    try!(self.tree.swap_node_order(node_ix, swap_ix)
                         .map_err(|err| ContainerMovementError::InternalTreeError(
                             TreeError::PetGraphError(err))))
                },
                Container::Container { .. } => {
                    try!(self.tree.move_into(node_ix, swap_ix)
                         .map_err(|err| ContainerMovementError::InternalTreeError(
                             TreeError::PetGraphError(err))));
                    if let Some(handle) = self.tree[node_ix].get_handle() {
                        match handle {
                            Handle::View(view) => self.normalize_view(view),
                            _ => unreachable!()
                        }
                    }
                },
                _ => return Err(ContainerMovementError::InternalTreeError(
                    TreeError::UuidWrongType(self.tree[swap_ix].get_id(),
                                             vec!(ContainerType::View, ContainerType::Container))))
            };
            Ok(self.tree.parent_of(node_ix)
               .expect("Moved container had no new parent"))
        } else {
            // Tried to move outside the limit
            Err(ContainerMovementError::MoveOutsideSiblings(self.tree[node_ix].get_id(), direction))
        }
    }

    /// Moves the node in the direction, outside to ancestor siblings.
    ///
    /// Returns the new parent of the node on success
    ///
    /// This should only be called by the recursive function.
    fn move_between_ancestors(&mut self,
                              node_to_move: NodeIndex,
                              move_ancestor: NodeIndex,
                              direction: Direction)
                                 -> Result<NodeIndex, ContainerMovementError> {
        let cur_parent_ix = try!(self.tree.parent_of(move_ancestor)
                                 .ok_or(ContainerMovementError::InternalTreeError(
                                     TreeError::PetGraphError(
                                         GraphError::NoParent(move_ancestor)))));
        let siblings_and_self = self.tree.children_of(cur_parent_ix);
        let cur_index = try!(siblings_and_self.iter().position(|node| {
            *node == move_ancestor
        }).ok_or(ContainerMovementError::InternalTreeError(
            TreeError::NodeNotFound(self.tree[move_ancestor].get_id()))));
        let next_ix = match direction {
            Direction::Right | Direction::Down => {
                let next_index = cur_index + 1;
                if next_index as usize >= siblings_and_self.len() {
                    return self.tree.add_to_end(node_to_move,
                                                siblings_and_self[siblings_and_self.len() - 1],
                                                ShiftDirection::Left)
                        .and_then(|_| self.tree.parent_of(node_to_move)
                             .ok_or(GraphError::NoParent(node_to_move)))
                        .map_err(|err| ContainerMovementError::InternalTreeError(
                            TreeError::PetGraphError(err)))
                } else {
                    siblings_and_self[next_index]
                }
            },
            Direction::Left | Direction::Up => {
                if let Some(next_index) = cur_index.checked_sub(1) {
                    siblings_and_self[next_index]
                } else {
                    return self.tree.add_to_end(node_to_move,
                                                siblings_and_self[0],
                                                ShiftDirection::Right)
                        .and_then(|_| self.tree.parent_of(node_to_move)
                                  .ok_or(GraphError::NoParent(node_to_move)))
                        .map_err(|err| ContainerMovementError::InternalTreeError(
                            TreeError::PetGraphError(err)))
                }
            }
        };
        // Replace ancestor location with the node we are moving,
        // shifts the others over
        let parent_ix = try!(match self.tree[next_ix] {
            Container::View { .. } => {
                match direction {
                    Direction::Right | Direction::Down => {
                        self.tree.place_node_at(node_to_move, next_ix, ShiftDirection::Left)
                    },
                    Direction::Left | Direction::Up => {
                        self.tree.place_node_at(node_to_move, next_ix, ShiftDirection::Right)
                    }
                }
            },
            Container::Container { .. } => {
                self.tree.move_into(node_to_move, next_ix)
            },
            _ => unreachable!()
        }.map_err(|err| ContainerMovementError::InternalTreeError(TreeError::PetGraphError(err))));
        match self.tree[node_to_move] {
            Container::View { handle, .. } => {
                self.normalize_view(handle);
                Ok(parent_ix)
            },
            _ => {
                Err(ContainerMovementError::InternalTreeError(
                    TreeError::UuidWrongType(self.tree[node_to_move].get_id(), vec!(ContainerType::View))))
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::super::tree::tests::basic_tree;
    use super::super::super::{Direction, Container, ContainerType, Layout};
    use rustwlc::*;

    #[test]
    fn test_basic_move() {
        let mut tree = basic_tree();
        tree.add_view(WlcView::root());
        let active_uuid = tree.get_active_container().unwrap().get_id();
        let active_parent = tree.tree.parent_of(tree.active_container.unwrap()).unwrap();
        let children = tree.tree.children_of(active_parent);
        assert_eq!(children[1], tree.active_container.unwrap());
        // These should do nothing, moving in wrong direction
        assert!(tree.move_container(active_uuid, Direction::Up).is_err());
        assert!(tree.move_container(active_uuid, Direction::Down).is_err());
        assert!(tree.move_container(active_uuid, Direction::Right).is_err());
        // test going left and right works
        assert!(tree.move_container(active_uuid, Direction::Left).is_ok());
        let children = tree.tree.children_of(active_parent);
        assert_eq!(children[0], tree.active_container.unwrap());
        assert!(tree.move_container(active_uuid, Direction::Right).is_ok());
        let children = tree.tree.children_of(active_parent);
        assert_eq!(children[1], tree.active_container.unwrap());
        // test going up and down works
        tree.toggle_active_horizontal();
        assert!(tree.move_container(active_uuid, Direction::Up).is_ok());
        let children = tree.tree.children_of(active_parent);
        assert_eq!(children[0], tree.active_container.unwrap());
        assert!(tree.move_container(active_uuid, Direction::Down).is_ok());
        let children = tree.tree.children_of(active_parent);
        assert_eq!(children[1], tree.active_container.unwrap());
    }

    #[test]
    fn test_move_into_sub_container_dif_layout() {
        let mut tree = basic_tree();
        tree.switch_to_workspace("2");
        let active_parent = tree.tree.parent_of(tree.active_container.unwrap()).unwrap();
        let children = tree.tree.children_of(active_parent);
        assert_eq!(Some(children[0]), tree.active_container);
        // make the first view have a vertical layout
        tree.toggle_active_layout(Layout::Vertical);
        tree.active_container = Some(children[1]);
        let active_parent = tree.tree.parent_of(tree.active_container.unwrap()).unwrap();
        let children = tree.tree.children_of(active_parent);
        let active_uuid = tree.get_active_container().unwrap().get_id();
        // make sure the first container is the sub container, second is the view
        assert_eq!(tree.tree[children[0]].get_type(), ContainerType::Container);
        assert_eq!(tree.tree[children[1]].get_type(), ContainerType::View);
        println!("Active is {:?}, tree: \n {:#?}", tree.tree[tree.active_container.unwrap()],tree);
        assert!(tree.move_container(active_uuid, Direction::Left).is_ok());
        let active_parent = tree.tree.parent_of(tree.active_container.unwrap()).unwrap();
        let children = tree.tree.children_of(active_parent);
        // we should all be in the same container now, in the vertical one
        println!("Active is {:?}, tree: \n {:#?}", tree.tree[tree.active_container.unwrap()],tree);
        assert_eq!(children.len(), 2);
        match tree.tree[active_parent] {
            Container::Container { ref layout, .. } => {
                assert_eq!(*layout, Layout::Vertical);
            }
            _ => panic!("Parent of active was not a vertical container")
        }
    }
}
<commit_msg>Added test for moving into same layout sub<commit_after>use uuid::Uuid;
use petgraph::graph::NodeIndex;

use super::super::{LayoutTree, Direction, TreeError};
use super::super::graph_tree::{GraphError, ShiftDirection};
use super::super::container::{Container, ContainerType, Handle, Layout};

pub enum ContainerMovementError {
    /// Attempted to move the node behind the UUID in the given direction,
    /// which would cause it to leave its siblings.
    MoveOutsideSiblings(Uuid, Direction),
    /// There was a tree error, generally should abort operation and pass this
    /// up back through the caller.
    InternalTreeError(TreeError)
}

impl LayoutTree {
    /// Returns the new parent of the active container if the move succeeds,
    /// Otherwise it signals what error occurred in the tree.
    pub fn move_recurse(&mut self, node_to_move: NodeIndex, move_ancestor: Option<NodeIndex>,
                           direction: Direction) -> Result<NodeIndex, TreeError> {
        match self.tree[node_to_move].get_type() {
            ContainerType::View | ContainerType::Container => { /* continue */ },
            _ => return Err(TreeError::UuidWrongType(self.tree[node_to_move].get_id(),
                                                     vec!(ContainerType::View,
                                                          ContainerType::Container)))
        }
        let parent_ix = try!(
            move_ancestor.and_then(|node| {
                self.tree.parent_of(node)
            }).or(self.tree.parent_of(node_to_move))
                .ok_or(TreeError::PetGraphError(GraphError::NoParent(node_to_move))));
        match self.tree[parent_ix] {
            Container::Container { layout, .. } =>  {
                match (layout, direction) {
                    (Layout::Horizontal, Direction::Left) |
                    (Layout::Horizontal, Direction::Right) |
                    (Layout::Vertical, Direction::Up) |
                    (Layout::Vertical, Direction::Down) => {
                        if let Some(ancestor_ix) = move_ancestor {
                            match self.move_between_ancestors(node_to_move, ancestor_ix, direction) {
                                Ok(new_parent_ix) => Ok(new_parent_ix),
                                Err(ContainerMovementError::InternalTreeError(err)) => {
                                    error!("Tree error moving between ancestors: {:?}", err);
                                    Err(err)
                                }
                                Err(ContainerMovementError::MoveOutsideSiblings(node, dir)) => {
                                    error!("Trying to move {:#?} in the {:?} direction somehow moved out of siblings",
                                           node, dir);
                                    panic!("Moving between ancestors failed in an unexpected way")
                                }
                            }
                        } else { /* Moving within current parent container */
                            match self.move_within_container(node_to_move, direction) {
                                Ok(new_parent_ix) => {
                                    Ok(new_parent_ix)
                                },
                                Err(ContainerMovementError::MoveOutsideSiblings(_,_)) => {
                                    self.move_recurse(node_to_move, Some(parent_ix), direction)
                                },
                                Err(ContainerMovementError::InternalTreeError(err)) => {
                                    Err(err)
                                }
                            }
                        }
                    },
                    _ => { self.move_recurse(node_to_move, Some(parent_ix), direction) }
                }
            },
            Container::Workspace { .. } => {
                Err(TreeError::InvalidOperationOnRootContainer(self.tree[node_to_move].get_id()))
            }
            _ => unreachable!()
        }
    }

    /// Attempt to move a container at the node index in the given direction.
    ///
    /// If the node would move outside of its current container by moving in that
    /// direction, then ContainerMovementError::MoveOutsideSiblings is returned.
    /// If the tree state is invalid, an appropriate wrapped up error is returned.
    ///
    /// If successful, the parent index of the node is returned.
    fn move_within_container(&mut self, node_ix: NodeIndex, direction: Direction)
                             -> Result<NodeIndex, ContainerMovementError> {
        let parent_ix = try!(self.tree.parent_of(node_ix)
                             .ok_or(ContainerMovementError::InternalTreeError(
                                 TreeError::PetGraphError(GraphError::NoParent(node_ix)))));
        let siblings_and_self = self.tree.children_of(parent_ix);
        let cur_index = try!(siblings_and_self.iter().position(|node| {
            *node == node_ix
        }).ok_or(ContainerMovementError::InternalTreeError(
            TreeError::NodeNotFound(self.tree[node_ix].get_id()))));
        let maybe_new_index = match direction {
            Direction::Right | Direction::Down => {
                cur_index.checked_add(1)
            }
            Direction::Left  | Direction::Up => {
                cur_index.checked_sub(1)
            }
        };
        if maybe_new_index.is_some() && maybe_new_index.unwrap() < siblings_and_self.len() {
            // There is a sibling to swap with
            let swap_index = maybe_new_index.unwrap();
            let swap_ix = siblings_and_self[swap_index];
            match self.tree[swap_ix] {
                Container::View { .. } => {
                    try!(self.tree.swap_node_order(node_ix, swap_ix)
                         .map_err(|err| ContainerMovementError::InternalTreeError(
                             TreeError::PetGraphError(err))))
                },
                Container::Container { .. } => {
                    try!(self.tree.move_into(node_ix, swap_ix)
                         .map_err(|err| ContainerMovementError::InternalTreeError(
                             TreeError::PetGraphError(err))));
                    if let Some(handle) = self.tree[node_ix].get_handle() {
                        match handle {
                            Handle::View(view) => self.normalize_view(view),
                            _ => unreachable!()
                        }
                    }
                },
                _ => return Err(ContainerMovementError::InternalTreeError(
                    TreeError::UuidWrongType(self.tree[swap_ix].get_id(),
                                             vec!(ContainerType::View, ContainerType::Container))))
            };
            Ok(self.tree.parent_of(node_ix)
               .expect("Moved container had no new parent"))
        } else {
            // Tried to move outside the limit
            Err(ContainerMovementError::MoveOutsideSiblings(self.tree[node_ix].get_id(), direction))
        }
    }

    /// Moves the node in the direction, outside to ancestor siblings.
    ///
    /// Returns the new parent of the node on success
    ///
    /// This should only be called by the recursive function.
    fn move_between_ancestors(&mut self,
                              node_to_move: NodeIndex,
                              move_ancestor: NodeIndex,
                              direction: Direction)
                                 -> Result<NodeIndex, ContainerMovementError> {
        let cur_parent_ix = try!(self.tree.parent_of(move_ancestor)
                                 .ok_or(ContainerMovementError::InternalTreeError(
                                     TreeError::PetGraphError(
                                         GraphError::NoParent(move_ancestor)))));
        let siblings_and_self = self.tree.children_of(cur_parent_ix);
        let cur_index = try!(siblings_and_self.iter().position(|node| {
            *node == move_ancestor
        }).ok_or(ContainerMovementError::InternalTreeError(
            TreeError::NodeNotFound(self.tree[move_ancestor].get_id()))));
        let next_ix = match direction {
            Direction::Right | Direction::Down => {
                let next_index = cur_index + 1;
                if next_index as usize >= siblings_and_self.len() {
                    return self.tree.add_to_end(node_to_move,
                                                siblings_and_self[siblings_and_self.len() - 1],
                                                ShiftDirection::Left)
                        .and_then(|_| self.tree.parent_of(node_to_move)
                             .ok_or(GraphError::NoParent(node_to_move)))
                        .map_err(|err| ContainerMovementError::InternalTreeError(
                            TreeError::PetGraphError(err)))
                } else {
                    siblings_and_self[next_index]
                }
            },
            Direction::Left | Direction::Up => {
                if let Some(next_index) = cur_index.checked_sub(1) {
                    siblings_and_self[next_index]
                } else {
                    return self.tree.add_to_end(node_to_move,
                                                siblings_and_self[0],
                                                ShiftDirection::Right)
                        .and_then(|_| self.tree.parent_of(node_to_move)
                                  .ok_or(GraphError::NoParent(node_to_move)))
                        .map_err(|err| ContainerMovementError::InternalTreeError(
                            TreeError::PetGraphError(err)))
                }
            }
        };
        // Replace ancestor location with the node we are moving,
        // shifts the others over
        let parent_ix = try!(match self.tree[next_ix] {
            Container::View { .. } => {
                match direction {
                    Direction::Right | Direction::Down => {
                        self.tree.place_node_at(node_to_move, next_ix, ShiftDirection::Left)
                    },
                    Direction::Left | Direction::Up => {
                        self.tree.place_node_at(node_to_move, next_ix, ShiftDirection::Right)
                    }
                }
            },
            Container::Container { .. } => {
                self.tree.move_into(node_to_move, next_ix)
            },
            _ => unreachable!()
        }.map_err(|err| ContainerMovementError::InternalTreeError(TreeError::PetGraphError(err))));
        match self.tree[node_to_move] {
            Container::View { handle, .. } => {
                self.normalize_view(handle);
                Ok(parent_ix)
            },
            _ => {
                Err(ContainerMovementError::InternalTreeError(
                    TreeError::UuidWrongType(self.tree[node_to_move].get_id(), vec!(ContainerType::View))))
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use uuid::Uuid;
    use super::super::tree::tests::basic_tree;
    use super::super::super::{Direction, Container, ContainerType, Layout};
    use rustwlc::*;

    #[test]
    fn test_basic_move() {
        let mut tree = basic_tree();
        tree.add_view(WlcView::root());
        let active_uuid = tree.get_active_container().unwrap().get_id();
        let active_parent = tree.tree.parent_of(tree.active_container.unwrap()).unwrap();
        let children = tree.tree.children_of(active_parent);
        assert_eq!(children[1], tree.active_container.unwrap());
        // These should do nothing, moving in wrong direction
        assert!(tree.move_container(active_uuid, Direction::Up).is_err());
        assert!(tree.move_container(active_uuid, Direction::Down).is_err());
        assert!(tree.move_container(active_uuid, Direction::Right).is_err());
        // test going left and right works
        assert!(tree.move_container(active_uuid, Direction::Left).is_ok());
        let children = tree.tree.children_of(active_parent);
        assert_eq!(children[0], tree.active_container.unwrap());
        assert!(tree.move_container(active_uuid, Direction::Right).is_ok());
        let children = tree.tree.children_of(active_parent);
        assert_eq!(children[1], tree.active_container.unwrap());
        // test going up and down works
        tree.toggle_active_horizontal();
        assert!(tree.move_container(active_uuid, Direction::Up).is_ok());
        let children = tree.tree.children_of(active_parent);
        assert_eq!(children[0], tree.active_container.unwrap());
        assert!(tree.move_container(active_uuid, Direction::Down).is_ok());
        let children = tree.tree.children_of(active_parent);
        assert_eq!(children[1], tree.active_container.unwrap());
    }

    #[test]
    fn test_move_into_sub_container_dif_layout() {
        let mut tree = basic_tree();
        tree.switch_to_workspace("2");
        let active_parent = tree.tree.parent_of(tree.active_container.unwrap()).unwrap();
        let children = tree.tree.children_of(active_parent);
        assert_eq!(Some(children[0]), tree.active_container);
        // make the first view have a vertical layout
        tree.toggle_active_layout(Layout::Vertical);
        tree.active_container = Some(children[1]);
        let active_parent = tree.tree.parent_of(tree.active_container.unwrap()).unwrap();
        let children = tree.tree.children_of(active_parent);
        let active_uuid = tree.get_active_container().unwrap().get_id();
        // make sure the first container is the sub container, second is the view
        assert_eq!(tree.tree[children[0]].get_type(), ContainerType::Container);
        assert_eq!(tree.tree[children[1]].get_type(), ContainerType::View);
        assert!(tree.move_container(active_uuid, Direction::Left).is_ok());
        let active_parent = tree.tree.parent_of(tree.active_container.unwrap()).unwrap();
        let children = tree.tree.children_of(active_parent);
        // we should all be in the same container now, in the vertical one
        assert_eq!(children.len(), 2);
        match tree.tree[active_parent] {
            Container::Container { ref layout, .. } => {
                assert_eq!(*layout, Layout::Vertical);
            }
            _ => panic!("Parent of active was not a vertical container")
        }
    }

    #[test]
    fn test_move_into_sub_container_same_layout() {
        let mut tree = basic_tree();
        tree.switch_to_workspace("2");
        let active_parent = tree.tree.parent_of(tree.active_container.unwrap()).unwrap();
        let children = tree.tree.children_of(active_parent);
        assert_eq!(Some(children[0]), tree.active_container);
        // make the first view have a vertical layout
        tree.toggle_active_layout(Layout::Horizontal);
        let horizontal_id = tree.tree[tree.tree.parent_of(tree.active_container.unwrap()).unwrap()].get_id();
        tree.active_container = Some(children[1]);
        let active_parent = tree.tree.parent_of(tree.active_container.unwrap()).unwrap();
        let children = tree.tree.children_of(active_parent);
        let active_uuid = tree.get_active_container().unwrap().get_id();
        // make sure the first container is the sub container, second is the view
        assert_eq!(tree.tree[children[0]].get_type(), ContainerType::Container);
        assert_eq!(tree.tree[children[1]].get_type(), ContainerType::View);
        assert!(tree.move_container(active_uuid, Direction::Left).is_ok());
        let active_parent = tree.tree.parent_of(tree.active_container.unwrap()).unwrap();
        let children = tree.tree.children_of(active_parent);
        // we should all be in the same container now, in the sub horizontal one
        assert_eq!(children.len(), 2);
        match tree.tree[active_parent] {
            Container::Container { ref layout, ref id, .. } => {
                assert_eq!(*layout, Layout::Horizontal);
                assert_eq!(*id, horizontal_id);
            }
            _ => panic!("Parent of active was not a vertical container")
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Only look at dir entries in use<commit_after><|endoftext|>


<commit_before>/* 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/. */

//! Borders, padding, and margins.

use std::num::Zero;
use geom::side_offsets::SideOffsets2D;
use gfx::geometry::Au;
use newcss::complete::CompleteStyle;
use newcss::units::{Em, Pt, Px};
use newcss::values::{CSSBorderWidth, CSSBorderWidthLength, CSSBorderWidthMedium};
use newcss::values::{CSSBorderWidthThick, CSSBorderWidthThin, CSSFontSize, CSSFontSizeLength};
use newcss::values::{CSSWidth, CSSWidthLength, CSSWidthPercentage, CSSWidthAuto};
use newcss::values::{CSSHeight, CSSHeightLength, CSSHeightPercentage, CSSHeightAuto};
use newcss::values::{CSSMargin, CSSMarginLength, CSSMarginPercentage, CSSMarginAuto};
use newcss::values::{CSSPadding, CSSPaddingLength, CSSPaddingPercentage};
/// Encapsulates the borders, padding, and margins, which we collectively call the "box model".
pub struct BoxModel {
    border: SideOffsets2D<Au>,
    padding: SideOffsets2D<Au>,
    margin: SideOffsets2D<Au>,
    /// The width of the content box.
    content_box_width: Au,
}

/// Useful helper data type when computing values for blocks and positioned elements.
pub enum MaybeAuto {
    Auto,
    Specified(Au),
}

impl MaybeAuto {
    pub fn from_margin(margin: CSSMargin, cb_width: Au, font_size: CSSFontSize) -> MaybeAuto {
        match margin {
            CSSMarginAuto => Auto,
            CSSMarginPercentage(percent) => Specified(cb_width.scale_by(percent/100.0)),
            CSSMarginLength(Px(v)) => Specified(Au::from_frac_px(v)),
            CSSMarginLength(Pt(v)) => Specified(Au::from_pt(v)),
            CSSMarginLength(Em(em)) => {
                match font_size {
                    CSSFontSizeLength(Px(v)) => Specified(Au::from_frac_px(em * v)),
                    CSSFontSizeLength(Pt(v)) => Specified(Au::from_pt(em * v)),
                    _ => fail!(~"expected non-relative font size"),
                }
            }
        }
    }

    pub fn from_width(width: CSSWidth, cb_width: Au, font_size: CSSFontSize) -> MaybeAuto {
        match width {
            CSSWidthAuto => Auto,
            CSSWidthPercentage(percent) => Specified(cb_width.scale_by(percent/100.0)),
            CSSWidthLength(Px(v)) => Specified(Au::from_frac_px(v)),
            CSSWidthLength(Pt(v)) => Specified(Au::from_pt(v)),
            CSSWidthLength(Em(em)) => {
                match font_size {
                    CSSFontSizeLength(Px(v)) => Specified(Au::from_frac_px(em * v)),
                    CSSFontSizeLength(Pt(v)) => Specified(Au::from_pt(em * v)),
                    _ => fail!(~"expected non-relative font size"),
                }
            }
        }
    }

    pub fn from_height(height: CSSHeight, cb_height: Au, font_size: CSSFontSize) -> MaybeAuto {
        match height {
            CSSHeightAuto => Auto,
            CSSHeightPercentage(percent) => Specified(cb_height.scale_by(percent/100.0)),
            CSSHeightLength(Px(v)) => Specified(Au::from_frac_px(v)),
            CSSHeightLength(Pt(v)) => Specified(Au::from_pt(v)),
            CSSHeightLength(Em(em)) => {
                match font_size {
                    CSSFontSizeLength(Px(v)) => Specified(Au::from_frac_px(em * v)),
                    CSSFontSizeLength(Pt(v)) => Specified(Au::from_pt(em * v)),
                    _ => fail!(~"expected non-relative font size"),
                }
            }

        }
    }

    pub fn specified_or_default(&self, default: Au) -> Au {
        match *self {
            Auto => default,
            Specified(value) => value,
        }
    }

    pub fn specified_or_zero(&self) -> Au {
        self.specified_or_default(Au(0))
    }
}

impl Zero for BoxModel {
    fn zero() -> BoxModel {
        BoxModel {
            border: Zero::zero(),
            padding: Zero::zero(),
            margin: Zero::zero(),
            content_box_width: Zero::zero(),
        }
    }

    fn is_zero(&self) -> bool {
        self.padding.is_zero() && self.border.is_zero() && self.margin.is_zero()
    }
}

impl BoxModel {
    /// Populates the box model parameters from the given computed style.
    pub fn compute_borders(&mut self, style: CompleteStyle) {
        // Compute the borders.
        self.border.top = self.compute_border_width(style.border_top_width(), style.font_size());
        self.border.right = self.compute_border_width(style.border_right_width(), style.font_size());
        self.border.bottom = self.compute_border_width(style.border_bottom_width(), style.font_size());
        self.border.left = self.compute_border_width(style.border_left_width(), style.font_size());
    }

    pub fn compute_padding(&mut self, style: CompleteStyle, cb_width: Au) {
        self.padding.top = self.compute_padding_length(style.padding_top(), cb_width, style.font_size());
        self.padding.right = self.compute_padding_length(style.padding_right(), cb_width, style.font_size());
        self.padding.bottom = self.compute_padding_length(style.padding_bottom(), cb_width, style.font_size());
        self.padding.left = self.compute_padding_length(style.padding_left(), cb_width, style.font_size());
    }

    pub fn noncontent_width(&self) -> Au {
        let left = self.margin.left + self.border.left + self.padding.left;
        let right = self.margin.right + self.border.right + self.padding.right;
        left + right
    }

    pub fn offset(&self) -> Au {
        self.margin.left + self.border.left + self.padding.left
    }

    /// Helper function to compute the border width in app units from the CSS border width.
    pub fn compute_border_width(&self, width: CSSBorderWidth, font_size: CSSFontSize) -> Au {
        match width {
            CSSBorderWidthLength(Px(v)) => Au::from_frac_px(v),
            CSSBorderWidthLength(Pt(v)) => Au::from_pt(v),
            CSSBorderWidthLength(Em(em)) => {
                match font_size {
                    CSSFontSizeLength(Px(v)) => Au::from_frac_px(em * v),
                    CSSFontSizeLength(Pt(v)) => Au::from_pt(em * v),
                    _ => fail!(~"expected non-relative font size"),
                }
            },
            CSSBorderWidthThin => Au::from_px(1),
            CSSBorderWidthMedium => Au::from_px(5),
            CSSBorderWidthThick => Au::from_px(10),
        }
    }

    pub fn compute_padding_length(&self, padding: CSSPadding, content_box_width: Au, font_size: CSSFontSize) -> Au {
        match padding {
            CSSPaddingLength(Px(v)) => Au::from_frac_px(v),
            CSSPaddingLength(Pt(v)) => Au::from_pt(v),
            CSSPaddingLength(Em(em)) => {
                match font_size {
                    CSSFontSizeLength(Px(v)) => Au::from_frac_px(em * v),
                    CSSFontSizeLength(Pt(v)) => Au::from_pt(em * v),
                    _ => fail!(~"expected non-relative font size"),
                }
            },
            CSSPaddingPercentage(p) => content_box_width.scale_by(p/100.0)
        }
    }
}
<commit_msg>Rename `cb_width` to `containing_width`.<commit_after>/* 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/. */

//! Borders, padding, and margins.

use std::num::Zero;
use geom::side_offsets::SideOffsets2D;
use gfx::geometry::Au;
use newcss::complete::CompleteStyle;
use newcss::units::{Em, Pt, Px};
use newcss::values::{CSSBorderWidth, CSSBorderWidthLength, CSSBorderWidthMedium};
use newcss::values::{CSSBorderWidthThick, CSSBorderWidthThin, CSSFontSize, CSSFontSizeLength};
use newcss::values::{CSSWidth, CSSWidthLength, CSSWidthPercentage, CSSWidthAuto};
use newcss::values::{CSSHeight, CSSHeightLength, CSSHeightPercentage, CSSHeightAuto};
use newcss::values::{CSSMargin, CSSMarginLength, CSSMarginPercentage, CSSMarginAuto};
use newcss::values::{CSSPadding, CSSPaddingLength, CSSPaddingPercentage};
/// Encapsulates the borders, padding, and margins, which we collectively call the "box model".
pub struct BoxModel {
    border: SideOffsets2D<Au>,
    padding: SideOffsets2D<Au>,
    margin: SideOffsets2D<Au>,
    /// The width of the content box.
    content_box_width: Au,
}

/// Useful helper data type when computing values for blocks and positioned elements.
pub enum MaybeAuto {
    Auto,
    Specified(Au),
}

impl MaybeAuto {
    pub fn from_margin(margin: CSSMargin, containing_width: Au, font_size: CSSFontSize) -> MaybeAuto {
        match margin {
            CSSMarginAuto => Auto,
            CSSMarginPercentage(percent) => Specified(containing_width.scale_by(percent/100.0)),
            CSSMarginLength(Px(v)) => Specified(Au::from_frac_px(v)),
            CSSMarginLength(Pt(v)) => Specified(Au::from_pt(v)),
            CSSMarginLength(Em(em)) => {
                match font_size {
                    CSSFontSizeLength(Px(v)) => Specified(Au::from_frac_px(em * v)),
                    CSSFontSizeLength(Pt(v)) => Specified(Au::from_pt(em * v)),
                    _ => fail!(~"expected non-relative font size"),
                }
            }
        }
    }

    pub fn from_width(width: CSSWidth, containing_width: Au, font_size: CSSFontSize) -> MaybeAuto {
        match width {
            CSSWidthAuto => Auto,
            CSSWidthPercentage(percent) => Specified(containing_width.scale_by(percent/100.0)),
            CSSWidthLength(Px(v)) => Specified(Au::from_frac_px(v)),
            CSSWidthLength(Pt(v)) => Specified(Au::from_pt(v)),
            CSSWidthLength(Em(em)) => {
                match font_size {
                    CSSFontSizeLength(Px(v)) => Specified(Au::from_frac_px(em * v)),
                    CSSFontSizeLength(Pt(v)) => Specified(Au::from_pt(em * v)),
                    _ => fail!(~"expected non-relative font size"),
                }
            }
        }
    }

    pub fn from_height(height: CSSHeight, cb_height: Au, font_size: CSSFontSize) -> MaybeAuto {
        match height {
            CSSHeightAuto => Auto,
            CSSHeightPercentage(percent) => Specified(cb_height.scale_by(percent/100.0)),
            CSSHeightLength(Px(v)) => Specified(Au::from_frac_px(v)),
            CSSHeightLength(Pt(v)) => Specified(Au::from_pt(v)),
            CSSHeightLength(Em(em)) => {
                match font_size {
                    CSSFontSizeLength(Px(v)) => Specified(Au::from_frac_px(em * v)),
                    CSSFontSizeLength(Pt(v)) => Specified(Au::from_pt(em * v)),
                    _ => fail!(~"expected non-relative font size"),
                }
            }

        }
    }

    pub fn specified_or_default(&self, default: Au) -> Au {
        match *self {
            Auto => default,
            Specified(value) => value,
        }
    }

    pub fn specified_or_zero(&self) -> Au {
        self.specified_or_default(Au(0))
    }
}

impl Zero for BoxModel {
    fn zero() -> BoxModel {
        BoxModel {
            border: Zero::zero(),
            padding: Zero::zero(),
            margin: Zero::zero(),
            content_box_width: Zero::zero(),
        }
    }

    fn is_zero(&self) -> bool {
        self.padding.is_zero() && self.border.is_zero() && self.margin.is_zero()
    }
}

impl BoxModel {
    /// Populates the box model parameters from the given computed style.
    pub fn compute_borders(&mut self, style: CompleteStyle) {
        // Compute the borders.
        self.border.top = self.compute_border_width(style.border_top_width(), style.font_size());
        self.border.right = self.compute_border_width(style.border_right_width(), style.font_size());
        self.border.bottom = self.compute_border_width(style.border_bottom_width(), style.font_size());
        self.border.left = self.compute_border_width(style.border_left_width(), style.font_size());
    }

    pub fn compute_padding(&mut self, style: CompleteStyle, containing_width: Au) {
        self.padding.top = self.compute_padding_length(style.padding_top(), containing_width, style.font_size());
        self.padding.right = self.compute_padding_length(style.padding_right(), containing_width, style.font_size());
        self.padding.bottom = self.compute_padding_length(style.padding_bottom(), containing_width, style.font_size());
        self.padding.left = self.compute_padding_length(style.padding_left(), containing_width, style.font_size());
    }

    pub fn noncontent_width(&self) -> Au {
        let left = self.margin.left + self.border.left + self.padding.left;
        let right = self.margin.right + self.border.right + self.padding.right;
        left + right
    }

    pub fn offset(&self) -> Au {
        self.margin.left + self.border.left + self.padding.left
    }

    /// Helper function to compute the border width in app units from the CSS border width.
    pub fn compute_border_width(&self, width: CSSBorderWidth, font_size: CSSFontSize) -> Au {
        match width {
            CSSBorderWidthLength(Px(v)) => Au::from_frac_px(v),
            CSSBorderWidthLength(Pt(v)) => Au::from_pt(v),
            CSSBorderWidthLength(Em(em)) => {
                match font_size {
                    CSSFontSizeLength(Px(v)) => Au::from_frac_px(em * v),
                    CSSFontSizeLength(Pt(v)) => Au::from_pt(em * v),
                    _ => fail!(~"expected non-relative font size"),
                }
            },
            CSSBorderWidthThin => Au::from_px(1),
            CSSBorderWidthMedium => Au::from_px(5),
            CSSBorderWidthThick => Au::from_px(10),
        }
    }

    pub fn compute_padding_length(&self, padding: CSSPadding, content_box_width: Au, font_size: CSSFontSize) -> Au {
        match padding {
            CSSPaddingLength(Px(v)) => Au::from_frac_px(v),
            CSSPaddingLength(Pt(v)) => Au::from_pt(v),
            CSSPaddingLength(Em(em)) => {
                match font_size {
                    CSSFontSizeLength(Px(v)) => Au::from_frac_px(em * v),
                    CSSFontSizeLength(Pt(v)) => Au::from_pt(em * v),
                    _ => fail!(~"expected non-relative font size"),
                }
            },
            CSSPaddingPercentage(p) => content_box_width.scale_by(p/100.0)
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 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.

#![deprecated = "use std::vec::CowVec"]

pub use self::MaybeOwnedVector::*;

use std::cmp::{Equiv, Ordering};
use std::default::Default;
use std::fmt;
use std::iter::FromIterator;
use std::path::BytesContainer;
use std::slice;

// Note 1: It is not clear whether the flexibility of providing both
// the `Growable` and `FixedLen` variants is sufficiently useful.
// Consider restricting to just a two variant enum.

// Note 2: Once Dynamically Sized Types (DST) lands, it might be
// reasonable to replace this with something like `enum MaybeOwned<'a,
// Sized? U>{ Owned(Box<U>), Borrowed(&'a U) }`; and then `U` could be
// instantiated with `[T]` or `str`, etc.  Of course, that would imply
// removing the `Growable` variant, which relates to note 1 above.
// Alternatively, we might add `MaybeOwned` for the general case but
// keep some form of `MaybeOwnedVector` to avoid unnecessary copying
// of the contents of `Vec<T>`, since we anticipate that to be a
// frequent way to dynamically construct a vector.

/// MaybeOwnedVector<'a,T> abstracts over `Vec<T>`, `&'a [T]`.
///
/// Some clients will have a pre-allocated vector ready to hand off in
/// a slice; others will want to create the set on the fly and hand
/// off ownership, via `Growable`.
pub enum MaybeOwnedVector<'a,T:'a> {
    Growable(Vec<T>),
    Borrowed(&'a [T]),
}

/// Trait for moving into a `MaybeOwnedVector`
pub trait IntoMaybeOwnedVector<'a,T> {
    /// Moves self into a `MaybeOwnedVector`
    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T>;
}

#[allow(deprecated)]
impl<'a,T:'a> IntoMaybeOwnedVector<'a,T> for Vec<T> {
    #[allow(deprecated)]
    #[inline]
    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Growable(self) }
}

#[allow(deprecated)]
impl<'a,T> IntoMaybeOwnedVector<'a,T> for &'a [T] {
    #[allow(deprecated)]
    #[inline]
    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Borrowed(self) }
}

impl<'a,T> MaybeOwnedVector<'a,T> {
    pub fn iter(&'a self) -> slice::Iter<'a,T> {
        match self {
            &Growable(ref v) => v.as_slice().iter(),
            &Borrowed(ref v) => v.iter(),
        }
    }

    pub fn len(&self) -> uint { self.as_slice().len() }

    #[allow(deprecated)]
    pub fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<'a, T: PartialEq> PartialEq for MaybeOwnedVector<'a, T> {
    fn eq(&self, other: &MaybeOwnedVector<T>) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl<'a, T: Eq> Eq for MaybeOwnedVector<'a, T> {}

impl<'a, T: PartialOrd> PartialOrd for MaybeOwnedVector<'a, T> {
    fn partial_cmp(&self, other: &MaybeOwnedVector<T>) -> Option<Ordering> {
        self.as_slice().partial_cmp(other.as_slice())
    }
}

impl<'a, T: Ord> Ord for MaybeOwnedVector<'a, T> {
    fn cmp(&self, other: &MaybeOwnedVector<T>) -> Ordering {
        self.as_slice().cmp(other.as_slice())
    }
}

#[allow(deprecated)]
impl<'a, T: PartialEq> Equiv<[T]> for MaybeOwnedVector<'a, T> {
    fn equiv(&self, other: &[T]) -> bool {
        self.as_slice() == other
    }
}

// The `Vector` trait is provided in the prelude and is implemented on
// both `&'a [T]` and `Vec<T>`, so it makes sense to try to support it
// seamlessly.  The other vector related traits from the prelude do
// not appear to be implemented on both `&'a [T]` and `Vec<T>`.  (It
// is possible that this is an oversight in some cases.)
//
// In any case, with `Vector` in place, the client can just use
// `as_slice` if they prefer that over `match`.

impl<'b,T> AsSlice<T> for MaybeOwnedVector<'b,T> {
    fn as_slice<'a>(&'a self) -> &'a [T] {
        match self {
            &Growable(ref v) => v.as_slice(),
            &Borrowed(ref v) => v.as_slice(),
        }
    }
}

impl<'a,T> FromIterator<T> for MaybeOwnedVector<'a,T> {
    #[allow(deprecated)]
    fn from_iter<I:Iterator<T>>(iterator: I) -> MaybeOwnedVector<'a,T> {
        // If we are building from scratch, might as well build the
        // most flexible variant.
        Growable(iterator.collect())
    }
}

impl<'a,T:fmt::Show> fmt::Show for MaybeOwnedVector<'a,T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

impl<'a, T: Clone> Clone for MaybeOwnedVector<'a, T> {
    #[allow(deprecated)]
    fn clone(&self) -> MaybeOwnedVector<'a, T> {
        match *self {
            Growable(ref v) => Growable(v.clone()),
            Borrowed(v) => Borrowed(v)
        }
    }
}

impl<'a, T> Default for MaybeOwnedVector<'a, T> {
    #[allow(deprecated)]
    fn default() -> MaybeOwnedVector<'a, T> {
        Growable(Vec::new())
    }
}

impl<'a> BytesContainer for MaybeOwnedVector<'a, u8> {
    fn container_as_bytes(&self) -> &[u8] {
        self.as_slice()
    }
}

impl<'a,T:Clone> MaybeOwnedVector<'a,T> {
    /// Convert `self` into a growable `Vec`, not making a copy if possible.
    pub fn into_vec(self) -> Vec<T> {
        match self {
            Growable(v) => v,
            Borrowed(v) => v.to_vec(),
        }
    }
}
<commit_msg>graphviz: fix fallout<commit_after>// Copyright 2014 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.

#![deprecated = "use std::vec::CowVec"]

pub use self::MaybeOwnedVector::*;

use std::cmp::{Equiv, Ordering};
use std::default::Default;
use std::fmt;
use std::iter::FromIterator;
use std::path::BytesContainer;
use std::slice;

// Note 1: It is not clear whether the flexibility of providing both
// the `Growable` and `FixedLen` variants is sufficiently useful.
// Consider restricting to just a two variant enum.

// Note 2: Once Dynamically Sized Types (DST) lands, it might be
// reasonable to replace this with something like `enum MaybeOwned<'a,
// Sized? U>{ Owned(Box<U>), Borrowed(&'a U) }`; and then `U` could be
// instantiated with `[T]` or `str`, etc.  Of course, that would imply
// removing the `Growable` variant, which relates to note 1 above.
// Alternatively, we might add `MaybeOwned` for the general case but
// keep some form of `MaybeOwnedVector` to avoid unnecessary copying
// of the contents of `Vec<T>`, since we anticipate that to be a
// frequent way to dynamically construct a vector.

/// MaybeOwnedVector<'a,T> abstracts over `Vec<T>`, `&'a [T]`.
///
/// Some clients will have a pre-allocated vector ready to hand off in
/// a slice; others will want to create the set on the fly and hand
/// off ownership, via `Growable`.
pub enum MaybeOwnedVector<'a,T:'a> {
    Growable(Vec<T>),
    Borrowed(&'a [T]),
}

/// Trait for moving into a `MaybeOwnedVector`
pub trait IntoMaybeOwnedVector<'a,T> {
    /// Moves self into a `MaybeOwnedVector`
    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T>;
}

#[allow(deprecated)]
impl<'a,T:'a> IntoMaybeOwnedVector<'a,T> for Vec<T> {
    #[allow(deprecated)]
    #[inline]
    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Growable(self) }
}

#[allow(deprecated)]
impl<'a,T> IntoMaybeOwnedVector<'a,T> for &'a [T] {
    #[allow(deprecated)]
    #[inline]
    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Borrowed(self) }
}

impl<'a,T> MaybeOwnedVector<'a,T> {
    pub fn iter(&'a self) -> slice::Iter<'a,T> {
        match self {
            &Growable(ref v) => v.as_slice().iter(),
            &Borrowed(ref v) => v.iter(),
        }
    }

    pub fn len(&self) -> uint { self.as_slice().len() }

    #[allow(deprecated)]
    pub fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<'a, T: PartialEq> PartialEq for MaybeOwnedVector<'a, T> {
    fn eq(&self, other: &MaybeOwnedVector<T>) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl<'a, T: Eq> Eq for MaybeOwnedVector<'a, T> {}

impl<'a, T: PartialOrd> PartialOrd for MaybeOwnedVector<'a, T> {
    fn partial_cmp(&self, other: &MaybeOwnedVector<T>) -> Option<Ordering> {
        self.as_slice().partial_cmp(other.as_slice())
    }
}

impl<'a, T: Ord> Ord for MaybeOwnedVector<'a, T> {
    fn cmp(&self, other: &MaybeOwnedVector<T>) -> Ordering {
        self.as_slice().cmp(other.as_slice())
    }
}

#[allow(deprecated)]
impl<'a, T: PartialEq> Equiv<[T]> for MaybeOwnedVector<'a, T> {
    fn equiv(&self, other: &[T]) -> bool {
        self.as_slice() == other
    }
}

// The `Vector` trait is provided in the prelude and is implemented on
// both `&'a [T]` and `Vec<T>`, so it makes sense to try to support it
// seamlessly.  The other vector related traits from the prelude do
// not appear to be implemented on both `&'a [T]` and `Vec<T>`.  (It
// is possible that this is an oversight in some cases.)
//
// In any case, with `Vector` in place, the client can just use
// `as_slice` if they prefer that over `match`.

impl<'b,T> AsSlice<T> for MaybeOwnedVector<'b,T> {
    fn as_slice<'a>(&'a self) -> &'a [T] {
        match self {
            &Growable(ref v) => v.as_slice(),
            &Borrowed(ref v) => v.as_slice(),
        }
    }
}

impl<'a,T> FromIterator<T> for MaybeOwnedVector<'a,T> {
    #[allow(deprecated)]
    fn from_iter<I:Iterator<Item=T>>(iterator: I) -> MaybeOwnedVector<'a,T> {
        // If we are building from scratch, might as well build the
        // most flexible variant.
        Growable(iterator.collect())
    }
}

impl<'a,T:fmt::Show> fmt::Show for MaybeOwnedVector<'a,T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

impl<'a, T: Clone> Clone for MaybeOwnedVector<'a, T> {
    #[allow(deprecated)]
    fn clone(&self) -> MaybeOwnedVector<'a, T> {
        match *self {
            Growable(ref v) => Growable(v.clone()),
            Borrowed(v) => Borrowed(v)
        }
    }
}

impl<'a, T> Default for MaybeOwnedVector<'a, T> {
    #[allow(deprecated)]
    fn default() -> MaybeOwnedVector<'a, T> {
        Growable(Vec::new())
    }
}

impl<'a> BytesContainer for MaybeOwnedVector<'a, u8> {
    fn container_as_bytes(&self) -> &[u8] {
        self.as_slice()
    }
}

impl<'a,T:Clone> MaybeOwnedVector<'a,T> {
    /// Convert `self` into a growable `Vec`, not making a copy if possible.
    pub fn into_vec(self) -> Vec<T> {
        match self {
            Growable(v) => v,
            Borrowed(v) => v.to_vec(),
        }
    }
}
<|endoftext|>


<commit_before>use std::io::fs;

fn main() {
    fs::rename(&Path::new("input.txt"), &Path::new("output.txt")).ok();
    fs::rename(&Path::new("docs"), &Path::new("mydocs")).ok();
    fs::rename(&Path::new("/input.txt"), &Path::new("/output.txt")).ok();
    fs::rename(&Path::new("/docs"), &Path::new("/mydocs")).ok();
}
<commit_msg>Use unwrap instead of ok<commit_after>use std::io::fs;

fn main() {
    fs::rename(&Path::new("input.txt"), &Path::new("output.txt")).unwrap();
    fs::rename(&Path::new("docs"), &Path::new("mydocs")).unwrap();
    fs::rename(&Path::new("/input.txt"), &Path::new("/output.txt")).unwrap();
    fs::rename(&Path::new("/docs"), &Path::new("/mydocs")).unwrap();
}
<|endoftext|>


<commit_before>extern crate term;
extern crate git2;
extern crate libc;

use prompt_buffer::PromptBuffer;

use std::io::{
    Acceptor,
    Command,
    File,
    fs,
    Listener,
    process,
    stdio,
    timer
};
use std::time::Duration;
use std::io::fs::PathExtensions;
use std::io::net::pipe::{
    UnixStream,
    UnixListener,
};
use std::os;

mod prompt_buffer;
mod git;
mod due_date;

fn get_prompt() -> PromptBuffer<'static> {
    let mut buf = PromptBuffer::new();
    buf.add_plugin(box due_date::DueDatePlugin::new());
    buf.add_plugin(box git::GitPlugin::new());

    buf
}

fn exe_changed() -> u64 {
    match os::self_exe_name() {
        Some(exe_path) => {
            match exe_path.stat() {
                Ok(s) => s.modified,
                _ => 0u64
            }
        },
        None => 0u64
    }
}

fn main() {
    let stdout_path = Path::new("/var/log/megaprompt/current.out");
    let stderr_path = Path::new("/var/log/megaprompt/current.err");
    let pid_path = Path::new("/var/log/megaprompt/current.pid");
    let socket_path = Path::new("/tmp/megaprompt-socket");

    let args = os::args();
    if args.len() > 1 { // Daemon process
        stdio::set_stdout(box File::create(&stdout_path));
        stdio::set_stderr(box File::create(&stderr_path));

        let last_modified = exe_changed();

        let mut p = get_prompt();

        if socket_path.exists() {
            fs::unlink(&socket_path).unwrap();
        }

        let stream = match UnixListener::bind(&socket_path) {
            Err(_) => panic!("Failed to bind to socket"),
            Ok(stream) => stream
        };

        for mut connection in stream.listen().incoming() {
            let c = &mut connection;

            let output = c.read_to_string().unwrap();
            p.set_path(Path::new(output));

            write!(c, "{}", p.to_string()).unwrap();

            if last_modified != exe_changed() {
                write!(c, "♻  ").unwrap();
                return;
            }
        }
    } else {
        let current_pid = match File::open(&pid_path) {
            Ok(mut file) => match file.read_to_string() {
                Ok(line) => match line.parse() {
                    Some(value) => value,
                    _ => -1
                },
                _ => -1
            },
            _ => -1
        };

        match process::Process::kill(current_pid, 0) {
            Err(_) => {
                // We need to start up the daemon again
                let child = Command::new(args.get(0).as_slice()[0])
                    .arg("daemon")
                    .detached().spawn().unwrap();

                let mut f = match File::create(&pid_path) {
                    Ok(f) => f,
                    Err(_) => panic!("Unable to open pid file")
                };

                write!(&mut f, "{}", child.id()).unwrap();

                println!("Spawned child {}", child.id());

                child.forget();

                timer::sleep(Duration::milliseconds(10));
            }
            _ => {}
        }

        let mut stream = match UnixStream::connect(&socket_path) {
            Err(_) => {
                println!("Can't connect");
                get_prompt().print();
                return;
            },
            Ok(stream) => stream
        };

        write!(&mut stream, "{}", os::make_absolute(&Path::new(".")).unwrap().display()).unwrap();
        stream.close_write().unwrap();
        println!("{}", stream.read_to_string().unwrap());
    }
}
<commit_msg>Clean up fetching of current pid<commit_after>extern crate term;
extern crate git2;
extern crate libc;

use prompt_buffer::PromptBuffer;

use std::io::{
    Acceptor,
    Command,
    File,
    fs,
    Listener,
    process,
    stdio,
    timer,
    IoError
};
use std::time::Duration;
use std::io::fs::PathExtensions;
use std::io::net::pipe::{
    UnixStream,
    UnixListener,
};
use std::os;

mod prompt_buffer;
mod git;
mod due_date;

fn get_prompt() -> PromptBuffer<'static> {
    let mut buf = PromptBuffer::new();
    buf.add_plugin(box due_date::DueDatePlugin::new());
    buf.add_plugin(box git::GitPlugin::new());

    buf
}

fn exe_changed() -> u64 {
    match os::self_exe_name() {
        Some(exe_path) => {
            match exe_path.stat() {
                Ok(s) => s.modified,
                _ => 0u64
            }
        },
        None => 0u64
    }
}

fn current_pid(pid_path: &Path) -> Result<i32, IoError> {
    let mut file = try!(File::open(pid_path));
    let contents = try!(file.read_to_string());

    match contents.parse() {
        Some(value) => Ok(value),
        None => Err(IoError::from_errno(libc::consts::os::posix88::ENOMSG as uint, true))
    }
}

fn main() {
    let stdout_path = Path::new("/var/log/megaprompt/current.out");
    let stderr_path = Path::new("/var/log/megaprompt/current.err");
    let pid_path = Path::new("/var/log/megaprompt/current.pid");
    let socket_path = Path::new("/tmp/megaprompt-socket");

    let args = os::args();
    if args.len() > 1 { // Daemon process
        stdio::set_stdout(box File::create(&stdout_path));
        stdio::set_stderr(box File::create(&stderr_path));

        let last_modified = exe_changed();

        let mut p = get_prompt();

        if socket_path.exists() {
            fs::unlink(&socket_path).unwrap();
        }

        let stream = match UnixListener::bind(&socket_path) {
            Err(_) => panic!("Failed to bind to socket"),
            Ok(stream) => stream
        };

        for mut connection in stream.listen().incoming() {
            let c = &mut connection;

            let output = c.read_to_string().unwrap();
            p.set_path(Path::new(output));

            write!(c, "{}", p.to_string()).unwrap();

            if last_modified != exe_changed() {
                write!(c, "♻  ").unwrap();
                return;
            }
        }
    } else {
        let current_pid = current_pid(&pid_path).ok().unwrap_or(-1);

        match process::Process::kill(current_pid, 0) {
            Err(_) => {
                // We need to start up the daemon again
                let child = Command::new(args.get(0).as_slice()[0])
                    .arg("daemon")
                    .detached().spawn().unwrap();

                let mut f = match File::create(&pid_path) {
                    Ok(f) => f,
                    Err(_) => panic!("Unable to open pid file")
                };

                write!(&mut f, "{}", child.id()).unwrap();

                println!("Spawned child {}", child.id());

                child.forget();

                timer::sleep(Duration::milliseconds(10));
            }
            _ => {}
        }

        let mut stream = match UnixStream::connect(&socket_path) {
            Err(_) => {
                println!("Can't connect");
                get_prompt().print();
                return;
            },
            Ok(stream) => stream
        };

        write!(&mut stream, "{}", os::make_absolute(&Path::new(".")).unwrap().display()).unwrap();
        stream.close_write().unwrap();
        println!("{}", stream.read_to_string().unwrap());
    }
}
<|endoftext|>