<commit_before>//! Functions for corner point detection, also known as interest points.

use image::{
    GenericImage,
    Luma
};

use std::cmp;

/// A location and score for a detected corner.
/// The scores need not be comparable between different
/// corner detectors.
pub struct Corner {
    pub x: u32,
    pub y: u32,
    pub score: Option<f32>
}

impl Corner {
    pub fn new(x: u32, y: u32, score: Option<f32>) -> Corner {
        Corner {x: x, y: y, score: score}
    }
}

/// Finds corners using FAST-12 features. Given a point P, define
/// C_P to be the 16-pixel Bresenham circle of radius 3 centred at P.
/// We define a point P of intensity I to be a corner if at least
/// 12 contiguous pixels in C_P have an intensity strictly
/// greater than I + threshold or strictly less than I - threshold.
/// https://en.wikipedia.org/wiki/Features_from_accelerated_segment_test
pub fn corners_fast12<I>(image: &I, threshold: u8) -> Vec<Corner>
    where I: GenericImage<Pixel=Luma<u8>> + 'static {

    let (width, height) = image.dimensions();
    let mut corners = vec![];

    for y in 0..height {
        for x in 0..width {
            if is_corner_fast12(image, threshold, x, y) {
                corners.push(Corner::new(x,y, None));
            }
        }
    }

    corners
}

/// The score of a corner detected using the FAST12
/// detector is the largest threshold for which this
/// pixel is still a corner. We input the threshold at which
/// the corner was detected as a lower bound on the search.
/// Note that the corner check uses a strict inequality, so if
/// the smallest intensity difference between the center pixel
/// and a corner pixel is n then the corner will have a score of n - 1.
pub fn corner_score_fast12<I>(image: &I, threshold: u8, x: u32, y: u32)
        -> u8
    where I: GenericImage<Pixel=Luma<u8>> + 'static {

    let mut max = 255u8;
    let mut min = threshold;

    loop {
        if max == min {
            return max;
        }

        let mean = ((max as u16 + min as u16) / 2u16) as u8;
        let probe = if max == min + 1 { max } else { mean };

        if is_corner_fast12(image, probe, x, y) {
            min = probe;
        }
        else {
            max = probe - 1;
        }
    }
}

/// Checks if the given pixel is a corner.
fn is_corner_fast12<I>(image: &I, threshold: u8, x: u32, y: u32)
        -> bool
    where I: GenericImage<Pixel=Luma<u8>> + 'static {

    let (width, height) = image.dimensions();

    if x < 3 || y < 3 || x >= width - 3 || y >= height - 3 {
        return false;
    }

    let c = image.get_pixel(x, y)[0];
    let low_thresh: i16  = c as i16 - threshold as i16;
    let high_thresh: i16 = c as i16 + threshold as i16;

    // Circle pixels are labelled clockwise, starting at 0 directly above
    // the center, and finishing at 15, three pixels above and one to
    // the left of the center

    let p0 = image.get_pixel(x, y - 3)[0] as i16;
    let p8 = image.get_pixel(x, y + 3)[0] as i16;

    let mut above = p0 > high_thresh && p8 > high_thresh;
    let mut below = p0 < low_thresh  && p8 < low_thresh;

    if !above && !below {
        return false;
    }

    let p4  = image.get_pixel(x + 3, y)[0] as i16;
    let p12 = image.get_pixel(x - 3, y)[0] as i16;

    above = above && ((p4 > high_thresh) || (p12 > high_thresh));
    below = below && ((p4 < low_thresh)  || (p12 < low_thresh));

    if !above && !below {
        return false;
    }

    // TODO: Generate a list of pixel offsets once per image,
    // TODO: and use those offsets directly when reading pixels.
    // TODO: This is a little tricky as we can't always do it - we'd
    // TODO: need to distinguish between GenericImages and ImageBuffers.
    // TODO: We can also reduce the number of checks we do below.

    let mut pixels = [0i16; 16];

    pixels[0]  = p0;
    pixels[1]  = image.get_pixel(x + 1, y - 3)[0] as i16;
    pixels[2]  = image.get_pixel(x + 2, y - 2)[0] as i16;
    pixels[3]  = image.get_pixel(x + 3, y - 1)[0] as i16;
    pixels[4]  = p4;
    pixels[5]  = image.get_pixel(x + 3, y + 1)[0] as i16;
    pixels[6]  = image.get_pixel(x + 2, y + 2)[0] as i16;
    pixels[7]  = image.get_pixel(x + 1, y + 3)[0] as i16;
    pixels[8]  = p8;
    pixels[9]  = image.get_pixel(x - 1, y + 3)[0] as i16;
    pixels[10] = image.get_pixel(x - 2, y + 2)[0] as i16;
    pixels[11] = image.get_pixel(x - 3, y + 1)[0] as i16;
    pixels[12] = p12;
    pixels[13] = image.get_pixel(x - 3, y - 1)[0] as i16;
    pixels[14] = image.get_pixel(x - 2, y - 2)[0] as i16;
    pixels[15] = image.get_pixel(x - 1, y - 3)[0] as i16;

    if above {
        for i in 0..15 {
            let mut is_corner = true;
            let end   = i + 12;
            let upper = cmp::min(end, 16);
            let wrap  = if end > 16 { end - 16 } else { 0 };

            for j in i..upper {
                if pixels[j] <= high_thresh {
                    is_corner = false;
                    break;
                }
            }
            if is_corner {
                for j in 0..wrap {
                    if pixels[j] <= high_thresh {
                        is_corner = false;
                        break;
                    }
                }
            }
            if is_corner {
                return true;
            }
        }
    }
    else {
        for i in 0..15 {
            let mut is_corner = true;
            let end   = i + 12;
            let upper = cmp::min(end, 16);
            let wrap  = if end > 16 { end - 16 } else { 0 };

            for j in i..upper {
                if pixels[j] >= low_thresh {
                    is_corner = false;
                    break;
                }
            }
            if is_corner {
                for j in 0..wrap {
                    if pixels[j] >= low_thresh {
                        is_corner = false;
                        break;
                    }
                }
            }
            if is_corner {
                return true;
            }
        }
    }

    false
}

#[cfg(test)]
mod test {

    use super::{
        corner_score_fast12,
        is_corner_fast12
    };
    use image::{
        GrayImage,
        ImageBuffer
    };

    #[test]
    fn test_is_corner_fast12_12_contiguous_darker_pixels() {
        let image: GrayImage = ImageBuffer::from_raw(7, 7, vec![
            10, 10, 00, 00, 00, 10, 10,
            10, 00, 10, 10, 10, 00, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            10, 00, 10, 10, 10, 10, 10,
            10, 10, 00, 00, 00, 10, 10]).unwrap();

        assert_eq!(is_corner_fast12(&image, 8, 3, 3), true);
    }

    #[test]
    fn test_is_corner_fast12_12_contiguous_darker_pixels_large_threshold() {
        let image: GrayImage = ImageBuffer::from_raw(7, 7, vec![
            10, 10, 00, 00, 00, 10, 10,
            10, 00, 10, 10, 10, 00, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            10, 00, 10, 10, 10, 10, 10,
            10, 10, 00, 00, 00, 10, 10]).unwrap();

        assert_eq!(is_corner_fast12(&image, 15, 3, 3), false);
    }

    #[test]
    fn test_is_corner_fast12_12_contiguous_lighter_pixels() {
        let image: GrayImage = ImageBuffer::from_raw(7, 7, vec![
            00, 00, 10, 10, 10, 00, 00,
            00, 10, 00, 00, 00, 10, 00,
            10, 00, 00, 00, 00, 00, 00,
            10, 00, 00, 00, 00, 00, 00,
            10, 00, 00, 00, 00, 00, 00,
            00, 10, 00, 00, 00, 00, 00,
            00, 00, 10, 10, 10, 00, 00]).unwrap();

        assert_eq!(is_corner_fast12(&image, 8, 3, 3), true);
    }

    #[test]
    fn test_is_corner_fast12_12_noncontiguous() {
        let image: GrayImage = ImageBuffer::from_raw(7, 7, vec![
            10, 10, 00, 00, 00, 10, 10,
            10, 00, 10, 10, 10, 00, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            10, 10, 10, 10, 10, 10, 00,
            10, 00, 10, 10, 10, 10, 10,
            10, 10, 00, 00, 00, 10, 10]).unwrap();

        assert_eq!(is_corner_fast12(&image, 8, 3, 3), false);
    }

    #[test]
    fn test_is_corner_fast12_near_image_boundary() {
        let image: GrayImage = ImageBuffer::from_raw(7, 7, vec![
            10, 10, 00, 00, 00, 10, 10,
            10, 00, 10, 10, 10, 00, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            10, 00, 10, 10, 10, 10, 10,
            10, 10, 00, 00, 00, 10, 10]).unwrap();

        assert_eq!(is_corner_fast12(&image, 8, 1, 1), false);
    }

    #[test]
    fn test_corner_score_fast12() {
        let image: GrayImage = ImageBuffer::from_raw(7, 7, vec![
            10, 10, 00, 00, 00, 10, 10,
            10, 00, 10, 10, 10, 00, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            10, 00, 10, 10, 10, 10, 10,
            10, 10, 00, 00, 00, 10, 10]).unwrap();

        let score = corner_score_fast12(&image, 5, 3, 3);
        assert_eq!(score, 9);

        let score = corner_score_fast12(&image, 9, 3, 3);
        assert_eq!(score, 9);
    }
}
<commit_msg>Corners always have scores<commit_after>//! Functions for corner point detection, also known as interest points.

use image::{
    GenericImage,
    Luma
};

use std::cmp;

/// A location and score for a detected corner.
/// The scores need not be comparable between different
/// corner detectors.
#[derive(Copy,Clone)]
pub struct Corner {
    pub x: u32,
    pub y: u32,
    pub score: f32
}

impl Corner {
    pub fn new(x: u32, y: u32, score: f32) -> Corner {
        Corner {x: x, y: y, score: score}
    }
}

/// Finds corners using FAST-12 features. Given a point P, define
/// C_P to be the 16-pixel Bresenham circle of radius 3 centred at P.
/// We define a point P of intensity I to be a corner if at least
/// 12 contiguous pixels in C_P have an intensity strictly
/// greater than I + threshold or strictly less than I - threshold.
/// The score of a corner is the greatest threshold for which the given
/// pixel still qualifies as a corner.
/// https://en.wikipedia.org/wiki/Features_from_accelerated_segment_test
pub fn corners_fast12<I>(image: &I, threshold: u8) -> Vec<Corner>
    where I: GenericImage<Pixel=Luma<u8>> + 'static {

    let (width, height) = image.dimensions();
    let mut corners = vec![];

    for y in 0..height {
        for x in 0..width {
            if is_corner_fast12(image, threshold, x, y) {
                let score = corner_score_fast12(image, threshold, x, y);
                corners.push(Corner::new(x,y, score as f32));
            }
        }
    }

    corners
}

/// The score of a corner detected using the FAST12
/// detector is the largest threshold for which this
/// pixel is still a corner. We input the threshold at which
/// the corner was detected as a lower bound on the search.
/// Note that the corner check uses a strict inequality, so if
/// the smallest intensity difference between the center pixel
/// and a corner pixel is n then the corner will have a score of n - 1.
pub fn corner_score_fast12<I>(image: &I, threshold: u8, x: u32, y: u32)
        -> u8
    where I: GenericImage<Pixel=Luma<u8>> + 'static {

    let mut max = 255u8;
    let mut min = threshold;

    loop {
        if max == min {
            return max;
        }

        let mean = ((max as u16 + min as u16) / 2u16) as u8;
        let probe = if max == min + 1 { max } else { mean };

        if is_corner_fast12(image, probe, x, y) {
            min = probe;
        }
        else {
            max = probe - 1;
        }
    }
}

/// Checks if the given pixel is a corner.
fn is_corner_fast12<I>(image: &I, threshold: u8, x: u32, y: u32)
        -> bool
    where I: GenericImage<Pixel=Luma<u8>> + 'static {

    let (width, height) = image.dimensions();

    if x < 3 || y < 3 || x >= width - 3 || y >= height - 3 {
        return false;
    }

    let c = image.get_pixel(x, y)[0];
    let low_thresh: i16  = c as i16 - threshold as i16;
    let high_thresh: i16 = c as i16 + threshold as i16;

    // Circle pixels are labelled clockwise, starting at 0 directly above
    // the center, and finishing at 15, three pixels above and one to
    // the left of the center

    let p0 = image.get_pixel(x, y - 3)[0] as i16;
    let p8 = image.get_pixel(x, y + 3)[0] as i16;

    let mut above = p0 > high_thresh && p8 > high_thresh;
    let mut below = p0 < low_thresh  && p8 < low_thresh;

    if !above && !below {
        return false;
    }

    let p4  = image.get_pixel(x + 3, y)[0] as i16;
    let p12 = image.get_pixel(x - 3, y)[0] as i16;

    above = above && ((p4 > high_thresh) || (p12 > high_thresh));
    below = below && ((p4 < low_thresh)  || (p12 < low_thresh));

    if !above && !below {
        return false;
    }

    // TODO: Generate a list of pixel offsets once per image,
    // TODO: and use those offsets directly when reading pixels.
    // TODO: This is a little tricky as we can't always do it - we'd
    // TODO: need to distinguish between GenericImages and ImageBuffers.
    // TODO: We can also reduce the number of checks we do below.

    let mut pixels = [0i16; 16];

    pixels[0]  = p0;
    pixels[1]  = image.get_pixel(x + 1, y - 3)[0] as i16;
    pixels[2]  = image.get_pixel(x + 2, y - 2)[0] as i16;
    pixels[3]  = image.get_pixel(x + 3, y - 1)[0] as i16;
    pixels[4]  = p4;
    pixels[5]  = image.get_pixel(x + 3, y + 1)[0] as i16;
    pixels[6]  = image.get_pixel(x + 2, y + 2)[0] as i16;
    pixels[7]  = image.get_pixel(x + 1, y + 3)[0] as i16;
    pixels[8]  = p8;
    pixels[9]  = image.get_pixel(x - 1, y + 3)[0] as i16;
    pixels[10] = image.get_pixel(x - 2, y + 2)[0] as i16;
    pixels[11] = image.get_pixel(x - 3, y + 1)[0] as i16;
    pixels[12] = p12;
    pixels[13] = image.get_pixel(x - 3, y - 1)[0] as i16;
    pixels[14] = image.get_pixel(x - 2, y - 2)[0] as i16;
    pixels[15] = image.get_pixel(x - 1, y - 3)[0] as i16;

    if above {
        for i in 0..15 {
            let mut is_corner = true;
            let end   = i + 12;
            let upper = cmp::min(end, 16);
            let wrap  = if end > 16 { end - 16 } else { 0 };

            for j in i..upper {
                if pixels[j] <= high_thresh {
                    is_corner = false;
                    break;
                }
            }
            if is_corner {
                for j in 0..wrap {
                    if pixels[j] <= high_thresh {
                        is_corner = false;
                        break;
                    }
                }
            }
            if is_corner {
                return true;
            }
        }
    }
    else {
        for i in 0..15 {
            let mut is_corner = true;
            let end   = i + 12;
            let upper = cmp::min(end, 16);
            let wrap  = if end > 16 { end - 16 } else { 0 };

            for j in i..upper {
                if pixels[j] >= low_thresh {
                    is_corner = false;
                    break;
                }
            }
            if is_corner {
                for j in 0..wrap {
                    if pixels[j] >= low_thresh {
                        is_corner = false;
                        break;
                    }
                }
            }
            if is_corner {
                return true;
            }
        }
    }

    false
}

#[cfg(test)]
mod test {

    use super::{
        corner_score_fast12,
        is_corner_fast12
    };
    use image::{
        GrayImage,
        ImageBuffer
    };

    #[test]
    fn test_is_corner_fast12_12_contiguous_darker_pixels() {
        let image: GrayImage = ImageBuffer::from_raw(7, 7, vec![
            10, 10, 00, 00, 00, 10, 10,
            10, 00, 10, 10, 10, 00, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            10, 00, 10, 10, 10, 10, 10,
            10, 10, 00, 00, 00, 10, 10]).unwrap();

        assert_eq!(is_corner_fast12(&image, 8, 3, 3), true);
    }

    #[test]
    fn test_is_corner_fast12_12_contiguous_darker_pixels_large_threshold() {
        let image: GrayImage = ImageBuffer::from_raw(7, 7, vec![
            10, 10, 00, 00, 00, 10, 10,
            10, 00, 10, 10, 10, 00, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            10, 00, 10, 10, 10, 10, 10,
            10, 10, 00, 00, 00, 10, 10]).unwrap();

        assert_eq!(is_corner_fast12(&image, 15, 3, 3), false);
    }

    #[test]
    fn test_is_corner_fast12_12_contiguous_lighter_pixels() {
        let image: GrayImage = ImageBuffer::from_raw(7, 7, vec![
            00, 00, 10, 10, 10, 00, 00,
            00, 10, 00, 00, 00, 10, 00,
            10, 00, 00, 00, 00, 00, 00,
            10, 00, 00, 00, 00, 00, 00,
            10, 00, 00, 00, 00, 00, 00,
            00, 10, 00, 00, 00, 00, 00,
            00, 00, 10, 10, 10, 00, 00]).unwrap();

        assert_eq!(is_corner_fast12(&image, 8, 3, 3), true);
    }

    #[test]
    fn test_is_corner_fast12_12_noncontiguous() {
        let image: GrayImage = ImageBuffer::from_raw(7, 7, vec![
            10, 10, 00, 00, 00, 10, 10,
            10, 00, 10, 10, 10, 00, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            10, 10, 10, 10, 10, 10, 00,
            10, 00, 10, 10, 10, 10, 10,
            10, 10, 00, 00, 00, 10, 10]).unwrap();

        assert_eq!(is_corner_fast12(&image, 8, 3, 3), false);
    }

    #[test]
    fn test_is_corner_fast12_near_image_boundary() {
        let image: GrayImage = ImageBuffer::from_raw(7, 7, vec![
            10, 10, 00, 00, 00, 10, 10,
            10, 00, 10, 10, 10, 00, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            10, 00, 10, 10, 10, 10, 10,
            10, 10, 00, 00, 00, 10, 10]).unwrap();

        assert_eq!(is_corner_fast12(&image, 8, 1, 1), false);
    }

    #[test]
    fn test_corner_score_fast12() {
        let image: GrayImage = ImageBuffer::from_raw(7, 7, vec![
            10, 10, 00, 00, 00, 10, 10,
            10, 00, 10, 10, 10, 00, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            00, 10, 10, 10, 10, 10, 10,
            10, 00, 10, 10, 10, 10, 10,
            10, 10, 00, 00, 00, 10, 10]).unwrap();

        let score = corner_score_fast12(&image, 5, 3, 3);
        assert_eq!(score, 9);

        let score = corner_score_fast12(&image, 9, 3, 3);
        assert_eq!(score, 9);
    }
}
<|endoftext|>


<commit_before>use super::super::bus;
use super::cp0::CP0;
use super::instruction::Instruction;

use std::fmt;

const NUM_GPREG: usize = 32;
const NUM_FPREG: usize = 32;

const PIF_ROM_START: u64 = 0xffff_ffff_bfc0_0000;

pub struct Cpu {
    reg_gprs: [u64; NUM_GPREG],
    reg_fprs: [f64; NUM_FPREG],

    reg_pc: u64,

    reg_hi: u64,
    reg_lo: u64,

    reg_llbit: bool,

    reg_fcr0: u32,
    reg_fcr31: u32,

    cp0: CP0,

    bus: bus::Bus,
}

impl fmt::Debug for Cpu {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        const REGS_PER_LINE: usize = 2;
        const REG_NAMES: [&'static str; NUM_GPREG] =
            ["r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5",
             "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1",
             "gp", "sp", "s8", "ra"];

        try!(write!(f, "\nCPU General Purpose Registers:"));
        for reg_num in 0..NUM_GPREG {
            if (reg_num % REGS_PER_LINE) == 0 {
                try!(writeln!(f, ""));
            }
            try!(write!(f,
                        "{reg_name}/gpr{num:02}: {value:#018X} ",
                        num = reg_num,
                        reg_name = REG_NAMES[reg_num],
                        value = self.reg_gprs[reg_num]));
        }

        try!(write!(f, "\n\nCPU Floating Point Registers:"));
        for reg_num in 0..NUM_FPREG {
            if (reg_num % REGS_PER_LINE) == 0 {
                try!(writeln!(f, ""));
            }
            try!(write!(f,
                "fpr{num:02}: {value:21} ",
                num = reg_num,
                value = self.reg_fprs[reg_num],));
        }

        try!(writeln!(f, "\n\nCPU Special Registers:"));
        try!(writeln!(f,
                      "\
            reg_pc: {:#018X}\nreg_hi: {:#018X}\nreg_lo: \
                       {:#018X}\nreg_llbit: {}\nreg_fcr0:  {:#018X}\nreg_fcr31: {:#018X}\n",
                      self.reg_pc,
                      self.reg_hi,
                      self.reg_lo,
                      self.reg_llbit,
                      self.reg_fcr0,
                      self.reg_fcr31));

        try!(writeln!(f, "{:#?}", self.cp0));
        writeln!(f, "{:#?}", self.bus)
    }
}

impl Cpu {
    pub fn new(bus: bus::Bus) -> Cpu {
        Cpu {
            reg_gprs: [0; NUM_GPREG],
            reg_fprs: [0.0; NUM_FPREG],

            reg_pc: 0,

            reg_hi: 0,
            reg_lo: 0,

            reg_llbit: false,

            reg_fcr0: 0,
            reg_fcr31: 0,

            cp0: CP0::default(),

            bus: bus,
        }
    }

    pub fn power_on_reset(&mut self) {
        self.cp0.power_on_reset();

        self.reg_pc = PIF_ROM_START;
    }

    pub fn run(&mut self) {
        loop {
            self.run_instruction();
        }
    }

    pub fn run_instruction(&mut self) {
        let instruction = self.read_instruction(self.reg_pc);

        let opcode = instruction.get_opcode();
        let rs = instruction.get_bits(21, 5);
        let rt = instruction.get_bits(16, 5);
        let imval = instruction.get_immediate();

        match opcode {
            0b010000 => {
                // MTC0
                let rd = instruction.get_bits(11, 5);
                let data = self.read_gpr(rt as usize);
                self.cp0.write_reg(rd, data);
            }
            0b001101 => {
                // ORI
                let res = self.read_gpr(rs as usize) | (imval as u64);
                self.write_gpr(rt as usize, res);
            }
            0b001111 => {
                // LUI
                // assume 32 bit mode
                self.write_gpr(rt as usize, (((imval as u32) << 16) as i32) as u64);
            }
            0b100011 => {
                // LW
                let base = self.read_gpr(rs as usize);
                let vaddr = ((instruction.get_immediate() as i16) as u64) + base;
                if vaddr & 0b11 != 0 {
                    panic!("Address error exception");
                }
                panic!("Word {:#x}, base {:#x}, vaddr: {:#x}, imval: {:#x}",
                       instruction,
                       base,
                       vaddr,
                       imval);
                let word = self.read_word(vaddr);
                let mem = (word as i32) as u64;
                self.write_gpr(rt as usize, mem);

            }
            _ => {
                panic!("Unrecognised instruction {:#x}", instruction);
            }
        }

        self.reg_pc += 4;
    }

    fn read_word(&self, addr: u64) -> u32 {
        let paddr = vaddr_to_paddr(addr);
        self.bus.read_word(paddr as u32)
    }

    fn read_instruction(&self, addr: u64) -> Instruction {
        Instruction::new(self.read_word(addr))
    }

    fn write_gpr(&mut self, index: usize, value: u64) {
        if index != 0 {
            self.reg_gprs[index] = value;
        }
    }

    fn read_gpr(&self, index: usize) -> u64 {
        match index {
            0 => 0,
            _ => self.reg_gprs[index],
        }
    }
}

fn vaddr_to_paddr(vaddr: u64) -> u64 {
    let addr_bit_values = (vaddr >> 29) & 0b111;
    if addr_bit_values == 0b101 {
        // kseg1
        vaddr - 0xffff_ffff_a000_0000
    } else {
        panic!("Unrecognised virtual address {:#x}", vaddr);
    }
}
<commit_msg>Changed + to wrapping_add in Cpu LW command<commit_after>use super::super::bus;
use super::cp0::CP0;
use super::instruction::Instruction;

use std::fmt;

const NUM_GPREG: usize = 32;
const NUM_FPREG: usize = 32;

const PIF_ROM_START: u64 = 0xffff_ffff_bfc0_0000;

pub struct Cpu {
    reg_gprs: [u64; NUM_GPREG],
    reg_fprs: [f64; NUM_FPREG],

    reg_pc: u64,

    reg_hi: u64,
    reg_lo: u64,

    reg_llbit: bool,

    reg_fcr0: u32,
    reg_fcr31: u32,

    cp0: CP0,

    bus: bus::Bus,
}

impl fmt::Debug for Cpu {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        const REGS_PER_LINE: usize = 2;
        const REG_NAMES: [&'static str; NUM_GPREG] =
            ["r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5",
             "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1",
             "gp", "sp", "s8", "ra"];

        try!(write!(f, "\nCPU General Purpose Registers:"));
        for reg_num in 0..NUM_GPREG {
            if (reg_num % REGS_PER_LINE) == 0 {
                try!(writeln!(f, ""));
            }
            try!(write!(f,
                        "{reg_name}/gpr{num:02}: {value:#018X} ",
                        num = reg_num,
                        reg_name = REG_NAMES[reg_num],
                        value = self.reg_gprs[reg_num]));
        }

        try!(write!(f, "\n\nCPU Floating Point Registers:"));
        for reg_num in 0..NUM_FPREG {
            if (reg_num % REGS_PER_LINE) == 0 {
                try!(writeln!(f, ""));
            }
            try!(write!(f,
                "fpr{num:02}: {value:21} ",
                num = reg_num,
                value = self.reg_fprs[reg_num],));
        }

        try!(writeln!(f, "\n\nCPU Special Registers:"));
        try!(writeln!(f,
                      "\
            reg_pc: {:#018X}\nreg_hi: {:#018X}\nreg_lo: \
                       {:#018X}\nreg_llbit: {}\nreg_fcr0:  {:#018X}\nreg_fcr31: {:#018X}\n",
                      self.reg_pc,
                      self.reg_hi,
                      self.reg_lo,
                      self.reg_llbit,
                      self.reg_fcr0,
                      self.reg_fcr31));

        try!(writeln!(f, "{:#?}", self.cp0));
        writeln!(f, "{:#?}", self.bus)
    }
}

impl Cpu {
    pub fn new(bus: bus::Bus) -> Cpu {
        Cpu {
            reg_gprs: [0; NUM_GPREG],
            reg_fprs: [0.0; NUM_FPREG],

            reg_pc: 0,

            reg_hi: 0,
            reg_lo: 0,

            reg_llbit: false,

            reg_fcr0: 0,
            reg_fcr31: 0,

            cp0: CP0::default(),

            bus: bus,
        }
    }

    pub fn power_on_reset(&mut self) {
        self.cp0.power_on_reset();

        self.reg_pc = PIF_ROM_START;
    }

    pub fn run(&mut self) {
        loop {
            self.run_instruction();
        }
    }

    pub fn run_instruction(&mut self) {
        let instruction = self.read_instruction(self.reg_pc);

        let opcode = instruction.get_opcode();
        let rs = instruction.get_bits(21, 5);
        let rt = instruction.get_bits(16, 5);
        let imval = instruction.get_immediate();

        match opcode {
            0b010000 => {
                // MTC0
                let rd = instruction.get_bits(11, 5);
                let data = self.read_gpr(rt as usize);
                self.cp0.write_reg(rd, data);
            }
            0b001101 => {
                // ORI
                let res = self.read_gpr(rs as usize) | (imval as u64);
                self.write_gpr(rt as usize, res);
            }
            0b001111 => {
                // LUI
                // assume 32 bit mode
                self.write_gpr(rt as usize, (((imval as u32) << 16) as i32) as u64);
            }
            0b100011 => {
                // LW
                let base = self.read_gpr(rs as usize);
                let vaddr = base.wrapping_add((instruction.get_immediate() as i16) as u64);
                if vaddr & 0b11 != 0 {
                    panic!("Address error exception");
                }
                panic!("Word {:#x}, base {:#x}, vaddr: {:#x}, imval: {:#x}",
                       instruction,
                       base,
                       vaddr,
                       imval);
                let word = self.read_word(vaddr);
                let mem = (word as i32) as u64;
                self.write_gpr(rt as usize, mem);

            }
            _ => {
                panic!("Unrecognised instruction {:#x}", instruction);
            }
        }

        self.reg_pc += 4;
    }

    fn read_word(&self, addr: u64) -> u32 {
        let paddr = vaddr_to_paddr(addr);
        self.bus.read_word(paddr as u32)
    }

    fn read_instruction(&self, addr: u64) -> Instruction {
        Instruction::new(self.read_word(addr))
    }

    fn write_gpr(&mut self, index: usize, value: u64) {
        if index != 0 {
            self.reg_gprs[index] = value;
        }
    }

    fn read_gpr(&self, index: usize) -> u64 {
        match index {
            0 => 0,
            _ => self.reg_gprs[index],
        }
    }
}

fn vaddr_to_paddr(vaddr: u64) -> u64 {
    let addr_bit_values = (vaddr >> 29) & 0b111;
    if addr_bit_values == 0b101 {
        // kseg1
        vaddr - 0xffff_ffff_a000_0000
    } else {
        panic!("Unrecognised virtual address {:#x}", vaddr);
    }
}
<|endoftext|>


<commit_before>use socket::Socket;

pub struct Digital {
    socket: Socket,
}

impl Digital {
    pub fn new(socket: Socket) -> Self {
        Digital {
            socket: socket,
        }
    }

    pub fn set_direction(&mut self, pin: &str, direction: &str) {
        self.socket.send(format!("DIG:PIN:DIR {},{}", direction, pin));
    }

    pub fn set_state(&mut self, pin: &str, state: u8) {
        self.socket.send(format!("DIG:PIN {},{}", pin, state));
    }

    pub fn get_state(&mut self, pin: &str) -> u8 {
        self.socket.send(format!("DIG:PIN? {}", pin));

        self.socket.receive()
            .parse()
            .unwrap()
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_set_direction() {
        let (rx, mut digital) = create_digital();

        digital.set_direction("DIO0_N", "OUT");
        assert_eq!("DIG:PIN:DIR OUT,DIO0_N\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_state() {
        let (rx, mut digital) = create_digital();

        digital.set_state("DIO0_N", 1);
        assert_eq!("DIG:PIN DIO0_N,1\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_state() {
        let (_, mut digital) = create_digital();

        assert_eq!(digital.get_state("DIO0_N"), 1);
    }

    fn create_digital() -> (::std::sync::mpsc::Receiver<String>, ::digital::Digital) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(
            format!("{}", addr.ip()).as_str(),
            addr.port()
        );

        (rx, ::digital::Digital::new(socket))
    }
}
<commit_msg>[digital] Add digital::Direction enum<commit_after>use socket::Socket;

pub enum Direction {
    OUT,
    IN,
}

impl ::std::fmt::Display for Direction {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Direction::OUT => "OUT",
            &Direction::IN => "IN",
        };

        write!(f, "{}", display)
    }
}

pub struct Digital {
    socket: Socket,
}

impl Digital {
    pub fn new(socket: Socket) -> Self {
        Digital {
            socket: socket,
        }
    }

    pub fn set_direction(&mut self, pin: &str, direction: Direction) {
        self.socket.send(format!("DIG:PIN:DIR {},{}", direction, pin));
    }

    pub fn set_state(&mut self, pin: &str, state: u8) {
        self.socket.send(format!("DIG:PIN {},{}", pin, state));
    }

    pub fn get_state(&mut self, pin: &str) -> u8 {
        self.socket.send(format!("DIG:PIN? {}", pin));

        self.socket.receive()
            .parse()
            .unwrap()
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_set_direction_in() {
        let (rx, mut digital) = create_digital();

        digital.set_direction("DIO0_N", ::digital::Direction::IN);
        assert_eq!("DIG:PIN:DIR IN,DIO0_N\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_direction_out() {
        let (rx, mut digital) = create_digital();

        digital.set_direction("DIO0_N", ::digital::Direction::OUT);
        assert_eq!("DIG:PIN:DIR OUT,DIO0_N\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_state() {
        let (rx, mut digital) = create_digital();

        digital.set_state("DIO0_N", 1);
        assert_eq!("DIG:PIN DIO0_N,1\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_state() {
        let (_, mut digital) = create_digital();

        assert_eq!(digital.get_state("DIO0_N"), 1);
    }

    fn create_digital() -> (::std::sync::mpsc::Receiver<String>, ::digital::Digital) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(
            format!("{}", addr.ip()).as_str(),
            addr.port()
        );

        (rx, ::digital::Digital::new(socket))
    }
}
<|endoftext|>


<commit_before>#[cfg_attr(rustfmt, rustfmt_skip)]
const GRID: [[u32; 20]; 20] = [
    [08,02,22,97,38,15,00,40,00,75,04,05,07,78,52,12,50,77,91,08],
    [49,49,99,40,17,81,18,57,60,87,17,40,98,43,69,48,04,56,62,00],
    [81,49,31,73,55,79,14,29,93,71,40,67,53,88,30,03,49,13,36,65],
    [52,70,95,23,04,60,11,42,69,24,68,56,01,32,56,71,37,02,36,91],
    [22,31,16,71,51,67,63,89,41,92,36,54,22,40,40,28,66,33,13,80],
    [24,47,32,60,99,03,45,02,44,75,33,53,78,36,84,20,35,17,12,50],
    [32,98,81,28,64,23,67,10,26,38,40,67,59,54,70,66,18,38,64,70],
    [67,26,20,68,02,62,12,20,95,63,94,39,63,08,40,91,66,49,94,21],
    [24,55,58,05,66,73,99,26,97,17,78,78,96,83,14,88,34,89,63,72],
    [21,36,23,09,75,00,76,44,20,45,35,14,00,61,33,97,34,31,33,95],
    [78,17,53,28,22,75,31,67,15,94,03,80,04,62,16,14,09,53,56,92],
    [16,39,05,42,96,35,31,47,55,58,88,24,00,17,54,24,36,29,85,57],
    [86,56,00,48,35,71,89,07,05,44,44,37,44,60,21,58,51,54,17,58],
    [19,80,81,68,05,94,47,69,28,73,92,13,86,52,17,77,04,89,55,40],
    [04,52,08,83,97,35,99,16,07,97,57,32,16,26,26,79,33,27,98,66],
    [88,36,68,87,57,62,20,72,03,46,33,67,46,55,12,32,63,93,53,69],
    [04,42,16,73,38,25,39,11,24,94,72,18,08,46,29,32,40,62,76,36],
    [20,69,36,41,72,30,23,88,34,62,99,69,82,67,59,85,74,04,36,16],
    [20,73,35,29,78,31,90,01,74,31,49,71,48,86,81,16,23,57,05,54],
    [01,70,54,71,83,51,54,69,16,92,33,48,61,43,52,01,89,19,67,48]
];

pub fn main() {
    let product = |slice: &[u32]| slice.iter().fold(1, |prod, i| prod * i);
    let mut max = 0;
    for i in 0..20 {
        for j in 0..20 {
            if j < 17 {
                let p = product(&GRID[i][j..j + 4]);
                if p > max {
                    max = p
                }
            }
            if i < 17 {
                let p = product(&[GRID[i][j], GRID[i + 1][j], GRID[i + 2][j], GRID[i + 3][j]]);
                if p > max {
                    max = p
                }
            }
            if i < 17 && j < 17 {
                let p = product(&[GRID[i][j],
                                  GRID[i + 1][j + 1],
                                  GRID[i + 2][j + 2],
                                  GRID[i + 3][j + 3]]);
                if p > max {
                    max = p
                }
            }
            if i > 2 && j < 17 {
                let p = product(&[GRID[i][j],
                                  GRID[i - 1][j + 1],
                                  GRID[i - 2][j + 2],
                                  GRID[i - 3][j + 3]]);
                if p > max {
                    max = p
                }
            }
        }
    }
    println!("{}", max);
}
<commit_msg>silence clippy warning for leading zeroes<commit_after>#[cfg_attr(rustfmt, rustfmt_skip)]
#[allow(zero_prefixed_literal)]

const GRID: [[u32; 20]; 20] = [
    [08,02,22,97,38,15,00,40,00,75,04,05,07,78,52,12,50,77,91,08],
    [49,49,99,40,17,81,18,57,60,87,17,40,98,43,69,48,04,56,62,00],
    [81,49,31,73,55,79,14,29,93,71,40,67,53,88,30,03,49,13,36,65],
    [52,70,95,23,04,60,11,42,69,24,68,56,01,32,56,71,37,02,36,91],
    [22,31,16,71,51,67,63,89,41,92,36,54,22,40,40,28,66,33,13,80],
    [24,47,32,60,99,03,45,02,44,75,33,53,78,36,84,20,35,17,12,50],
    [32,98,81,28,64,23,67,10,26,38,40,67,59,54,70,66,18,38,64,70],
    [67,26,20,68,02,62,12,20,95,63,94,39,63,08,40,91,66,49,94,21],
    [24,55,58,05,66,73,99,26,97,17,78,78,96,83,14,88,34,89,63,72],
    [21,36,23,09,75,00,76,44,20,45,35,14,00,61,33,97,34,31,33,95],
    [78,17,53,28,22,75,31,67,15,94,03,80,04,62,16,14,09,53,56,92],
    [16,39,05,42,96,35,31,47,55,58,88,24,00,17,54,24,36,29,85,57],
    [86,56,00,48,35,71,89,07,05,44,44,37,44,60,21,58,51,54,17,58],
    [19,80,81,68,05,94,47,69,28,73,92,13,86,52,17,77,04,89,55,40],
    [04,52,08,83,97,35,99,16,07,97,57,32,16,26,26,79,33,27,98,66],
    [88,36,68,87,57,62,20,72,03,46,33,67,46,55,12,32,63,93,53,69],
    [04,42,16,73,38,25,39,11,24,94,72,18,08,46,29,32,40,62,76,36],
    [20,69,36,41,72,30,23,88,34,62,99,69,82,67,59,85,74,04,36,16],
    [20,73,35,29,78,31,90,01,74,31,49,71,48,86,81,16,23,57,05,54],
    [01,70,54,71,83,51,54,69,16,92,33,48,61,43,52,01,89,19,67,48]
];

pub fn main() {
    let product = |slice: &[u32]| slice.iter().fold(1, |prod, i| prod * i);
    let mut max = 0;
    for i in 0..20 {
        for j in 0..20 {
            if j < 17 {
                let p = product(&GRID[i][j..j + 4]);
                if p > max {
                    max = p
                }
            }
            if i < 17 {
                let p = product(&[GRID[i][j], GRID[i + 1][j], GRID[i + 2][j], GRID[i + 3][j]]);
                if p > max {
                    max = p
                }
            }
            if i < 17 && j < 17 {
                let p = product(&[GRID[i][j],
                                  GRID[i + 1][j + 1],
                                  GRID[i + 2][j + 2],
                                  GRID[i + 3][j + 3]]);
                if p > max {
                    max = p
                }
            }
            if i > 2 && j < 17 {
                let p = product(&[GRID[i][j],
                                  GRID[i - 1][j + 1],
                                  GRID[i - 2][j + 2],
                                  GRID[i - 3][j + 3]]);
                if p > max {
                    max = p
                }
            }
        }
    }
    println!("{}", max);
}
<|endoftext|>


<commit_before>use std::collections::HashSet;

const MAX: u32 = 10_000;

pub fn main() {
    let primes = (1..).filter(|&n| (2..(n as f32).sqrt() as u32 + 1).all(|i| n % i != 0));
    let isprime = |&n| (2..(n as f32).sqrt() as u32 + 1).all(|i| n % i != 0);
    let mut set = HashSet::<u32>::new();
    let doublesquares = (1..).map(|x| 2 * (x * x)).take(1500).collect::<Vec<u32>>();

    for p in primes.take_while(|&v| v < MAX) {
        for &s in doublesquares.iter() {
            set.insert(p + s);
        }
    }
    println!("{}",
             (1..MAX).filter(|x| x % 2 == 1 && !isprime(x) && !set.contains(&x)).nth(0).unwrap());
}
<commit_msg>use idomatic for loop<commit_after>use std::collections::HashSet;

const MAX: u32 = 10_000;

pub fn main() {
    let primes = (1..).filter(|&n| (2..(n as f32).sqrt() as u32 + 1).all(|i| n % i != 0));
    let isprime = |&n| (2..(n as f32).sqrt() as u32 + 1).all(|i| n % i != 0);
    let mut set = HashSet::<u32>::new();
    let doublesquares = (1..).map(|x| 2 * (x * x)).take(1500).collect::<Vec<u32>>();

    for p in primes.take_while(|&v| v < MAX) {
        for s in &doublesquares {
            set.insert(p + s);
        }
    }
    println!("{}",
             (1..MAX).filter(|x| x % 2 == 1 && !isprime(x) && !set.contains(&x)).nth(0).unwrap());
}
<|endoftext|>


<commit_before>#[allow(non_camel_case_types)]
pub mod bindgen;

#[cfg(test)]
mod bindgen_test {
    use super::bindgen as bg;
    use std::mem;

    #[test]
    fn ffi_call() {
        let mut cif: bg::ffi_cif = Default::default();
        let mut rc: i64 = 0;
        let mut args: Vec<*mut bg::ffi_type> =
            vec![ unsafe {&mut bg::ffi_type_sint64}
                , unsafe {&mut bg::ffi_type_sint64} ];
        let mut values: Vec<*mut i64> =
            vec![ &mut 5i64 as *mut i64
                , &mut 7i64 as *mut i64 ];

        unsafe {
            bg::ffi_prep_cif(&mut cif,
                             bg::FFI_DEFAULT_ABI,
                             2,
                             &mut bg::ffi_type_sint64,
                             args.as_mut_ptr());

            bg::ffi_call(&mut cif,
                         mem::transmute(add_it as usize),
                         mem::transmute(&mut rc),
                         mem::transmute(values.as_mut_ptr()));
        }

        assert_eq!(12, rc);
    }

    extern "C" fn add_it(n: i64, m: i64) -> i64 {
        return n + m;
    }
}
<commit_msg>wrapping of ffi_cif passes one test.<commit_after>#[allow(non_camel_case_types)]
pub mod bindgen;

#[derive(Debug)]
pub struct Cif(bindgen::ffi_cif);

#[derive(Debug)]
pub struct Arg(*mut ::std::os::raw::c_void);

#[derive(Copy, Clone, Debug)]
pub enum Type {
    Void,
    UInt8,
    SInt8,
    UInt16,
    SInt16,
    UInt32,
    SInt32,
    UInt64,
    SInt64,
    Float,
    Double,
    Pointer,
    LongDouble,
    ComplexFloat,
    ComplexDouble,
    ComplexLongDouble,
}

impl Type {
    fn as_ffi_type(self) -> *mut bindgen::ffi_type {
        unsafe {
            match self {
                Type::Void => &mut bindgen::ffi_type_void,
                Type::UInt8 => &mut bindgen::ffi_type_uint8,
                Type::SInt8 => &mut bindgen::ffi_type_sint8,
                Type::UInt16 => &mut bindgen::ffi_type_uint16,
                Type::SInt16 => &mut bindgen::ffi_type_sint16,
                Type::UInt32 => &mut bindgen::ffi_type_uint32,
                Type::SInt32 => &mut bindgen::ffi_type_sint32,
                Type::UInt64 => &mut bindgen::ffi_type_uint64,
                Type::SInt64 => &mut bindgen::ffi_type_sint64,
                Type::Float => &mut bindgen::ffi_type_float,
                Type::Double => &mut bindgen::ffi_type_double,
                Type::Pointer => &mut bindgen::ffi_type_pointer,
                Type::LongDouble => &mut bindgen::ffi_type_longdouble,
                Type::ComplexFloat => &mut bindgen::ffi_type_complex_float,
                Type::ComplexDouble => &mut bindgen::ffi_type_complex_double,
                Type::ComplexLongDouble =>
                    &mut bindgen::ffi_type_complex_double,
            }
        }
    }
}

pub fn arg<T>(r: &T) -> Arg {
    Arg(unsafe { ::std::mem::transmute(r as *const T) })
}

impl Cif {
    pub fn new(args: &[Type], result: Type) -> Self {
        let mut cif: bindgen::ffi_cif = Default::default();
        let mut real_args: Vec<_> =
            args.iter().map(|t| t.as_ffi_type()).collect();

        let result = unsafe {
            bindgen::ffi_prep_cif(&mut cif,
                                  bindgen::FFI_DEFAULT_ABI,
                                  args.len() as u32,
                                  result.as_ffi_type(),
                                  real_args.as_mut_ptr())
        };

        match result {
            bindgen::ffi_status::FFI_OK
                => (),
            bindgen::ffi_status::FFI_BAD_TYPEDEF
                => panic!("FFI_BAD_TYPEDEF"),
            bindgen::ffi_status::FFI_BAD_ABI
                => panic!("FFI_BAD_ABI"),
        }

        Cif(cif)
    }

    pub unsafe fn call<R>(&self, f: usize, values: &[Arg]) -> R {
        use std::mem;

        assert!(self.0.nargs as usize == values.len());

        let mut result: R = mem::zeroed();

        bindgen::ffi_call(
            mem::transmute(&self.0),
            mem::transmute(f),
            mem::transmute(&mut result),
            mem::transmute(values.as_ptr()));

        return result;
    }
}

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

    #[test]
    fn ffi_call() {
        let cif = Cif::new(&[Type::SInt64, Type::SInt64], Type::SInt64);

        let rc = unsafe {
            cif.call(add_it as usize, &[arg(&5i64), arg(&7i64)])
        };

        assert_eq!(12, rc);
    }

    extern "C" fn add_it(n: i64, m: i64) -> i64 {
        return n + m;
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::collections::vec_deque::IntoIter;
use {Command, Error, Record};

/// A [history tree] of commands.
///
/// [history tree]: https://www.emacswiki.org/emacs/UndoTree
#[derive(Debug, Default)]
pub struct History<R> {
    record: Record<R>,
    branch: Vec<IntoIter<Box<Command<R> + 'static>>>,
}

impl<R> History<R> {
    /// Returns a new history.
    #[inline]
    pub fn new(receiver: impl Into<R>) -> History<R> {
        History {
            record: Record::new(receiver),
            branch: Vec::new(),
        }
    }

    /// Pushes the command to the top of the history tree and executes its [`apply`] method.
    /// The command is merged with the previous top command if they have the same [`id`].
    ///
    /// # Errors
    /// If an error occur when executing [`apply`] the error is returned together with the command.
    ///
    /// [`apply`]: trait.Command.html#tymethod.apply
    /// [`id`]: trait.Command.html#method.id
    #[inline]
    pub fn apply(&mut self, _: impl Command<R> + 'static) -> Result<(), Error<R>>
    where
        R: 'static,
    {
        unimplemented!()
    }

    /// Calls the [`undo`] method for the active command and sets the previous one as the new active one.
    ///
    /// # Errors
    /// If an error occur when executing [`undo`] the error is returned together with the command.
    ///
    /// [`undo`]: trait.Command.html#tymethod.undo
    #[inline]
    pub fn undo(&mut self) -> Option<Result<(), Error<R>>> {
        unimplemented!()
    }

    /// Calls the [`redo`] method for the active command and sets the next one as the
    /// new active one.
    ///
    /// # Errors
    /// If an error occur when executing [`redo`] the error is returned together with the command.
    ///
    /// [`redo`]: trait.Command.html#method.redo
    #[inline]
    pub fn redo(&mut self) -> Option<Result<(), Error<R>>> {
        unimplemented!()
    }

    /// Returns a reference to the `receiver`.
    #[inline]
    pub fn as_receiver(&self) -> &R {
        &self.record.as_receiver()
    }

    /// Returns a mutable reference to the `receiver`.
    ///
    /// This method should **only** be used when doing changes that should not be able to be undone.
    #[inline]
    pub fn as_mut_receiver(&mut self) -> &mut R {
        self.record.as_mut_receiver()
    }

    /// Consumes the record, returning the `receiver`.
    #[inline]
    pub fn into_receiver(self) -> R {
        self.record.into_receiver()
    }
}

impl<R> AsRef<R> for History<R> {
    #[inline]
    fn as_ref(&self) -> &R {
        self.as_receiver()
    }
}

impl<R> AsMut<R> for History<R> {
    #[inline]
    fn as_mut(&mut self) -> &mut R {
        self.as_mut_receiver()
    }
}

impl<R> From<R> for History<R> {
    #[inline]
    fn from(receiver: R) -> Self {
        History::new(receiver)
    }
}
<commit_msg>Update documentation for History<commit_after>#![allow(dead_code)]

use std::collections::vec_deque::IntoIter;
use {Command, Error, Record};

/// A history of commands.
#[derive(Debug, Default)]
pub struct History<R> {
    record: Record<R>,
    branch: Vec<IntoIter<Box<Command<R> + 'static>>>,
}

impl<R> History<R> {
    /// Returns a new history.
    #[inline]
    pub fn new(_: impl Into<R>) -> History<R> {
        unimplemented!()
    }

    /// Pushes the command to the top of the history and executes its [`apply`] method.
    /// The command is merged with the previous top command if they have the same [`id`].
    ///
    /// # Errors
    /// If an error occur when executing [`apply`] the error is returned together with the command.
    ///
    /// [`apply`]: trait.Command.html#tymethod.apply
    /// [`id`]: trait.Command.html#method.id
    #[inline]
    pub fn apply(&mut self, _: impl Command<R> + 'static) -> Result<(), Error<R>>
    where
        R: 'static,
    {
        unimplemented!()
    }

    /// Calls the [`undo`] method for the active command and sets the previous one as the new active one.
    ///
    /// # Errors
    /// If an error occur when executing [`undo`] the error is returned together with the command.
    ///
    /// [`undo`]: trait.Command.html#tymethod.undo
    #[inline]
    pub fn undo(&mut self) -> Option<Result<(), Error<R>>> {
        unimplemented!()
    }

    /// Calls the [`redo`] method for the active command and sets the next one as the
    /// new active one.
    ///
    /// # Errors
    /// If an error occur when executing [`redo`] the error is returned together with the command.
    ///
    /// [`redo`]: trait.Command.html#method.redo
    #[inline]
    pub fn redo(&mut self) -> Option<Result<(), Error<R>>> {
        unimplemented!()
    }
}

impl<R> From<R> for History<R> {
    #[inline]
    fn from(receiver: R) -> Self {
        History::new(receiver)
    }
}
<|endoftext|>


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

use std::cmp::Ordering;

use config::lists::*;
use syntax::ast;
use syntax::codemap::{BytePos, Span};

use codemap::SpanUtils;
use config::IndentStyle;
use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator};
use rewrite::{Rewrite, RewriteContext};
use shape::Shape;
use types::{rewrite_path, PathContext};
use utils::{format_visibility, mk_sp};
use visitor::FmtVisitor;

/// Returns a name imported by a `use` declaration. e.g. returns `Ordering`
/// for `std::cmp::Ordering` and `self` for `std::cmp::self`.
pub fn path_to_imported_ident(path: &ast::Path) -> ast::Ident {
    path.segments.last().unwrap().identifier
}

pub fn same_rename(opt_ident: &Option<ast::Ident>, path: &ast::Path) -> bool {
    opt_ident.map_or(true, |ident| path_to_imported_ident(path) == ident)
}

fn rewrite_prefix(path: &ast::Path, context: &RewriteContext, shape: Shape) -> Option<String> {
    if path.segments.len() > 1 && path_to_imported_ident(path).to_string() == "self" {
        let path = &ast::Path {
            span: path.span,
            segments: path.segments[..path.segments.len() - 1].to_owned(),
        };
        rewrite_path(context, PathContext::Import, None, path, shape)
    } else {
        rewrite_path(context, PathContext::Import, None, path, shape)
    }
}

impl Rewrite for ast::UseTree {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        match self.kind {
            ast::UseTreeKind::Nested(ref items) => {
                rewrite_nested_use_tree(shape, &self.prefix, items, self.span, context)
            }
            ast::UseTreeKind::Glob => {
                let prefix_shape = shape.sub_width(3)?;

                if !self.prefix.segments.is_empty() {
                    let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)?;
                    Some(format!("{}::*", path_str))
                } else {
                    Some("*".to_owned())
                }
            }
            ast::UseTreeKind::Simple(opt_ident) => {
                if same_rename(&opt_ident, &self.prefix) {
                    rewrite_prefix(&self.prefix, context, shape)
                        .or_else(|| Some(context.snippet(self.prefix.span).to_owned()))
                } else {
                    let ident_str = opt_ident?.to_string();
                    // 4 = " as ".len()
                    let prefix_shape = shape.sub_width(ident_str.len() + 4)?;
                    let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)
                        .unwrap_or_else(|| context.snippet(self.prefix.span).to_owned());
                    Some(format!("{} as {}", path_str, ident_str))
                }
            }
        }
    }
}

fn is_unused_import(tree: &ast::UseTree, attrs: &[ast::Attribute]) -> bool {
    attrs.is_empty() && is_unused_import_inner(tree)
}

fn is_unused_import_inner(tree: &ast::UseTree) -> bool {
    match tree.kind {
        ast::UseTreeKind::Nested(ref items) => match items.len() {
            0 => true,
            1 => is_unused_import_inner(&items[0].0),
            _ => false,
        },
        _ => false,
    }
}

// Rewrite `use foo;` WITHOUT attributes.
pub fn rewrite_import(
    context: &RewriteContext,
    vis: &ast::Visibility,
    tree: &ast::UseTree,
    attrs: &[ast::Attribute],
    shape: Shape,
) -> Option<String> {
    let vis = format_visibility(vis);
    // 4 = `use `, 1 = `;`
    let rw = shape
        .offset_left(vis.len() + 4)
        .and_then(|shape| shape.sub_width(1))
        .and_then(|shape| {
            // If we have an empty nested group with no attributes, we erase it
            if is_unused_import(tree, attrs) {
                Some("".to_owned())
            } else {
                tree.rewrite(context, shape)
            }
        });
    match rw {
        Some(ref s) if !s.is_empty() => Some(format!("{}use {};", vis, s)),
        _ => rw,
    }
}

impl<'a> FmtVisitor<'a> {
    pub fn format_import(&mut self, item: &ast::Item, tree: &ast::UseTree) {
        let span = item.span;
        let shape = self.shape();
        let rw = rewrite_import(&self.get_context(), &item.vis, tree, &item.attrs, shape);
        match rw {
            Some(ref s) if s.is_empty() => {
                // Format up to last newline
                let prev_span = mk_sp(self.last_pos, source!(self, span).lo());
                let trimmed_snippet = self.snippet(prev_span).trim_right();
                let span_end = self.last_pos + BytePos(trimmed_snippet.len() as u32);
                self.format_missing(span_end);
                // We have an excessive newline from the removed import.
                if self.buffer.ends_with('\n') {
                    self.buffer.pop();
                    self.line_number -= 1;
                }
                self.last_pos = source!(self, span).hi();
            }
            Some(ref s) => {
                self.format_missing_with_indent(source!(self, span).lo());
                self.push_str(s);
                self.last_pos = source!(self, span).hi();
            }
            None => {
                self.format_missing_with_indent(source!(self, span).lo());
                self.format_missing(source!(self, span).hi());
            }
        }
    }
}

fn rewrite_nested_use_tree_single(
    context: &RewriteContext,
    path_str: &str,
    tree: &ast::UseTree,
    shape: Shape,
) -> Option<String> {
    match tree.kind {
        ast::UseTreeKind::Simple(opt_rename) => {
            let mut item_str = rewrite_prefix(&tree.prefix, context, shape)?;
            if item_str == "self" {
                item_str = "".to_owned();
            }

            let path_item_str = if path_str.is_empty() {
                if item_str.is_empty() {
                    "self".to_owned()
                } else {
                    item_str
                }
            } else if item_str.is_empty() {
                path_str.to_owned()
            } else {
                format!("{}::{}", path_str, item_str)
            };

            Some(if same_rename(&opt_rename, &tree.prefix) {
                path_item_str
            } else {
                format!("{} as {}", path_item_str, opt_rename?)
            })
        }
        ast::UseTreeKind::Glob | ast::UseTreeKind::Nested(..) => {
            // 2 = "::"
            let nested_shape = shape.offset_left(path_str.len() + 2)?;
            tree.rewrite(context, nested_shape)
                .map(|item| format!("{}::{}", path_str, item))
        }
    }
}

#[derive(Eq, PartialEq)]
enum ImportItem<'a> {
    // `self` or `self as a`
    SelfImport(&'a str),
    // name_one, name_two, ...
    SnakeCase(&'a str),
    // NameOne, NameTwo, ...
    CamelCase(&'a str),
    // NAME_ONE, NAME_TWO, ...
    AllCaps(&'a str),
    // Failed to format the import item
    Invalid,
}

impl<'a> ImportItem<'a> {
    fn from_str(s: &str) -> ImportItem {
        if s == "self" || s.starts_with("self as") {
            ImportItem::SelfImport(s)
        } else if s.chars().all(|c| c.is_lowercase() || c == '_' || c == ' ') {
            ImportItem::SnakeCase(s)
        } else if s.chars().all(|c| c.is_uppercase() || c == '_' || c == ' ') {
            ImportItem::AllCaps(s)
        } else {
            ImportItem::CamelCase(s)
        }
    }

    fn from_opt_str(s: Option<&String>) -> ImportItem {
        s.map_or(ImportItem::Invalid, |s| ImportItem::from_str(s))
    }

    fn to_str(&self) -> Option<&str> {
        match *self {
            ImportItem::SelfImport(s)
            | ImportItem::SnakeCase(s)
            | ImportItem::CamelCase(s)
            | ImportItem::AllCaps(s) => Some(s),
            ImportItem::Invalid => None,
        }
    }

    fn to_u32(&self) -> u32 {
        match *self {
            ImportItem::SelfImport(..) => 0,
            ImportItem::SnakeCase(..) => 1,
            ImportItem::CamelCase(..) => 2,
            ImportItem::AllCaps(..) => 3,
            ImportItem::Invalid => 4,
        }
    }
}

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

impl<'a> Ord for ImportItem<'a> {
    fn cmp(&self, other: &ImportItem<'a>) -> Ordering {
        let res = self.to_u32().cmp(&other.to_u32());
        if res != Ordering::Equal {
            return res;
        }
        self.to_str().map_or(Ordering::Greater, |self_str| {
            other
                .to_str()
                .map_or(Ordering::Less, |other_str| self_str.cmp(other_str))
        })
    }
}

// Pretty prints a multi-item import.
// If the path list is empty, it leaves the braces empty.
fn rewrite_nested_use_tree(
    shape: Shape,
    path: &ast::Path,
    trees: &[(ast::UseTree, ast::NodeId)],
    span: Span,
    context: &RewriteContext,
) -> Option<String> {
    // Returns a different option to distinguish `::foo` and `foo`
    let path_str = rewrite_path(context, PathContext::Import, None, path, shape)?;

    match trees.len() {
        0 => {
            let shape = shape.offset_left(path_str.len() + 3)?;
            return rewrite_path(context, PathContext::Import, None, path, shape)
                .map(|path_str| format!("{}::{{}}", path_str));
        }
        1 => {
            return rewrite_nested_use_tree_single(context, &path_str, &trees[0].0, shape);
        }
        _ => (),
    }

    let path_str = if path_str.is_empty() {
        path_str
    } else {
        format!("{}::", path_str)
    };

    // 2 = "{}"
    let remaining_width = shape.width.checked_sub(path_str.len() + 2).unwrap_or(0);
    let nested_indent = match context.config.imports_indent() {
        IndentStyle::Block => shape.indent.block_indent(context.config),
        // 1 = `{`
        IndentStyle::Visual => shape.visual_indent(path_str.len() + 1).indent,
    };

    let nested_shape = match context.config.imports_indent() {
        IndentStyle::Block => Shape::indented(nested_indent, context.config).sub_width(1)?,
        IndentStyle::Visual => Shape::legacy(remaining_width, nested_indent),
    };

    let mut items = {
        // Dummy value, see explanation below.
        let mut items = vec![ListItem::from_str("")];
        let iter = itemize_list(
            context.snippet_provider,
            trees.iter().map(|tree| &tree.0),
            "}",
            ",",
            |tree| tree.span.lo(),
            |tree| tree.span.hi(),
            |tree| tree.rewrite(context, nested_shape),
            context.snippet_provider.span_after(span, "{"),
            span.hi(),
            false,
        );
        items.extend(iter);
        items
    };

    // We prefixed the item list with a dummy value so that we can
    // potentially move "self" to the front of the vector without touching
    // the rest of the items.
    let has_self = move_self_to_front(&mut items);
    let first_index = if has_self { 0 } else { 1 };

    if context.config.reorder_imported_names() {
        items[1..].sort_by(|a, b| {
            let a = ImportItem::from_opt_str(a.item.as_ref());
            let b = ImportItem::from_opt_str(b.item.as_ref());
            a.cmp(&b)
        });
    }

    let tactic = definitive_tactic(
        &items[first_index..],
        context.config.imports_layout(),
        Separator::Comma,
        remaining_width,
    );

    let ends_with_newline = context.config.imports_indent() == IndentStyle::Block
        && tactic != DefinitiveListTactic::Horizontal;

    let fmt = ListFormatting {
        tactic,
        separator: ",",
        trailing_separator: if ends_with_newline {
            context.config.trailing_comma()
        } else {
            SeparatorTactic::Never
        },
        separator_place: SeparatorPlace::Back,
        shape: nested_shape,
        ends_with_newline,
        preserve_newline: true,
        config: context.config,
    };
    let list_str = write_list(&items[first_index..], &fmt)?;

    let result = if list_str.contains('\n') && context.config.imports_indent() == IndentStyle::Block
    {
        format!(
            "{}{{\n{}{}\n{}}}",
            path_str,
            nested_shape.indent.to_string(context.config),
            list_str,
            shape.indent.to_string(context.config)
        )
    } else {
        format!("{}{{{}}}", path_str, list_str)
    };
    Some(result)
}

// Returns true when self item was found.
fn move_self_to_front(items: &mut Vec<ListItem>) -> bool {
    match items
        .iter()
        .position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self"))
    {
        Some(pos) => {
            items[0] = items.remove(pos);
            true
        }
        None => false,
    }
}
<commit_msg>Put imports list on the next line if it exceeds max width<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp::Ordering;

use config::lists::*;
use syntax::ast;
use syntax::codemap::{BytePos, Span};

use codemap::SpanUtils;
use config::IndentStyle;
use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator};
use rewrite::{Rewrite, RewriteContext};
use shape::Shape;
use types::{rewrite_path, PathContext};
use utils::{format_visibility, mk_sp};
use visitor::FmtVisitor;

/// Returns a name imported by a `use` declaration. e.g. returns `Ordering`
/// for `std::cmp::Ordering` and `self` for `std::cmp::self`.
pub fn path_to_imported_ident(path: &ast::Path) -> ast::Ident {
    path.segments.last().unwrap().identifier
}

pub fn same_rename(opt_ident: &Option<ast::Ident>, path: &ast::Path) -> bool {
    opt_ident.map_or(true, |ident| path_to_imported_ident(path) == ident)
}

fn rewrite_prefix(path: &ast::Path, context: &RewriteContext, shape: Shape) -> Option<String> {
    if path.segments.len() > 1 && path_to_imported_ident(path).to_string() == "self" {
        let path = &ast::Path {
            span: path.span,
            segments: path.segments[..path.segments.len() - 1].to_owned(),
        };
        rewrite_path(context, PathContext::Import, None, path, shape)
    } else {
        rewrite_path(context, PathContext::Import, None, path, shape)
    }
}

impl Rewrite for ast::UseTree {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        match self.kind {
            ast::UseTreeKind::Nested(ref items) => {
                rewrite_nested_use_tree(shape, &self.prefix, items, self.span, context)
            }
            ast::UseTreeKind::Glob => {
                let prefix_shape = shape.sub_width(3)?;

                if !self.prefix.segments.is_empty() {
                    let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)?;
                    Some(format!("{}::*", path_str))
                } else {
                    Some("*".to_owned())
                }
            }
            ast::UseTreeKind::Simple(opt_ident) => {
                if same_rename(&opt_ident, &self.prefix) {
                    rewrite_prefix(&self.prefix, context, shape)
                        .or_else(|| Some(context.snippet(self.prefix.span).to_owned()))
                } else {
                    let ident_str = opt_ident?.to_string();
                    // 4 = " as ".len()
                    let prefix_shape = shape.sub_width(ident_str.len() + 4)?;
                    let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)
                        .unwrap_or_else(|| context.snippet(self.prefix.span).to_owned());
                    Some(format!("{} as {}", path_str, ident_str))
                }
            }
        }
    }
}

fn is_unused_import(tree: &ast::UseTree, attrs: &[ast::Attribute]) -> bool {
    attrs.is_empty() && is_unused_import_inner(tree)
}

fn is_unused_import_inner(tree: &ast::UseTree) -> bool {
    match tree.kind {
        ast::UseTreeKind::Nested(ref items) => match items.len() {
            0 => true,
            1 => is_unused_import_inner(&items[0].0),
            _ => false,
        },
        _ => false,
    }
}

// Rewrite `use foo;` WITHOUT attributes.
pub fn rewrite_import(
    context: &RewriteContext,
    vis: &ast::Visibility,
    tree: &ast::UseTree,
    attrs: &[ast::Attribute],
    shape: Shape,
) -> Option<String> {
    let vis = format_visibility(vis);
    // 4 = `use `, 1 = `;`
    let rw = shape
        .offset_left(vis.len() + 4)
        .and_then(|shape| shape.sub_width(1))
        .and_then(|shape| {
            // If we have an empty nested group with no attributes, we erase it
            if is_unused_import(tree, attrs) {
                Some("".to_owned())
            } else {
                tree.rewrite(context, shape)
            }
        });
    match rw {
        Some(ref s) if !s.is_empty() => Some(format!("{}use {};", vis, s)),
        _ => rw,
    }
}

impl<'a> FmtVisitor<'a> {
    pub fn format_import(&mut self, item: &ast::Item, tree: &ast::UseTree) {
        let span = item.span;
        let shape = self.shape();
        let rw = rewrite_import(&self.get_context(), &item.vis, tree, &item.attrs, shape);
        match rw {
            Some(ref s) if s.is_empty() => {
                // Format up to last newline
                let prev_span = mk_sp(self.last_pos, source!(self, span).lo());
                let trimmed_snippet = self.snippet(prev_span).trim_right();
                let span_end = self.last_pos + BytePos(trimmed_snippet.len() as u32);
                self.format_missing(span_end);
                // We have an excessive newline from the removed import.
                if self.buffer.ends_with('\n') {
                    self.buffer.pop();
                    self.line_number -= 1;
                }
                self.last_pos = source!(self, span).hi();
            }
            Some(ref s) => {
                self.format_missing_with_indent(source!(self, span).lo());
                self.push_str(s);
                self.last_pos = source!(self, span).hi();
            }
            None => {
                self.format_missing_with_indent(source!(self, span).lo());
                self.format_missing(source!(self, span).hi());
            }
        }
    }
}

fn rewrite_nested_use_tree_single(
    context: &RewriteContext,
    path_str: &str,
    tree: &ast::UseTree,
    shape: Shape,
) -> Option<String> {
    match tree.kind {
        ast::UseTreeKind::Simple(opt_rename) => {
            let mut item_str = rewrite_prefix(&tree.prefix, context, shape)?;
            if item_str == "self" {
                item_str = "".to_owned();
            }

            let path_item_str = if path_str.is_empty() {
                if item_str.is_empty() {
                    "self".to_owned()
                } else {
                    item_str
                }
            } else if item_str.is_empty() {
                path_str.to_owned()
            } else {
                format!("{}::{}", path_str, item_str)
            };

            Some(if same_rename(&opt_rename, &tree.prefix) {
                path_item_str
            } else {
                format!("{} as {}", path_item_str, opt_rename?)
            })
        }
        ast::UseTreeKind::Glob | ast::UseTreeKind::Nested(..) => {
            // 2 = "::"
            let nested_shape = shape.offset_left(path_str.len() + 2)?;
            tree.rewrite(context, nested_shape)
                .map(|item| format!("{}::{}", path_str, item))
        }
    }
}

#[derive(Eq, PartialEq)]
enum ImportItem<'a> {
    // `self` or `self as a`
    SelfImport(&'a str),
    // name_one, name_two, ...
    SnakeCase(&'a str),
    // NameOne, NameTwo, ...
    CamelCase(&'a str),
    // NAME_ONE, NAME_TWO, ...
    AllCaps(&'a str),
    // Failed to format the import item
    Invalid,
}

impl<'a> ImportItem<'a> {
    fn from_str(s: &str) -> ImportItem {
        if s == "self" || s.starts_with("self as") {
            ImportItem::SelfImport(s)
        } else if s.chars().all(|c| c.is_lowercase() || c == '_' || c == ' ') {
            ImportItem::SnakeCase(s)
        } else if s.chars().all(|c| c.is_uppercase() || c == '_' || c == ' ') {
            ImportItem::AllCaps(s)
        } else {
            ImportItem::CamelCase(s)
        }
    }

    fn from_opt_str(s: Option<&String>) -> ImportItem {
        s.map_or(ImportItem::Invalid, |s| ImportItem::from_str(s))
    }

    fn to_str(&self) -> Option<&str> {
        match *self {
            ImportItem::SelfImport(s)
            | ImportItem::SnakeCase(s)
            | ImportItem::CamelCase(s)
            | ImportItem::AllCaps(s) => Some(s),
            ImportItem::Invalid => None,
        }
    }

    fn to_u32(&self) -> u32 {
        match *self {
            ImportItem::SelfImport(..) => 0,
            ImportItem::SnakeCase(..) => 1,
            ImportItem::CamelCase(..) => 2,
            ImportItem::AllCaps(..) => 3,
            ImportItem::Invalid => 4,
        }
    }
}

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

impl<'a> Ord for ImportItem<'a> {
    fn cmp(&self, other: &ImportItem<'a>) -> Ordering {
        let res = self.to_u32().cmp(&other.to_u32());
        if res != Ordering::Equal {
            return res;
        }
        self.to_str().map_or(Ordering::Greater, |self_str| {
            other
                .to_str()
                .map_or(Ordering::Less, |other_str| self_str.cmp(other_str))
        })
    }
}

// Pretty prints a multi-item import.
// If the path list is empty, it leaves the braces empty.
fn rewrite_nested_use_tree(
    shape: Shape,
    path: &ast::Path,
    trees: &[(ast::UseTree, ast::NodeId)],
    span: Span,
    context: &RewriteContext,
) -> Option<String> {
    // Returns a different option to distinguish `::foo` and `foo`
    let path_str = rewrite_path(context, PathContext::Import, None, path, shape)?;

    match trees.len() {
        0 => {
            let shape = shape.offset_left(path_str.len() + 3)?;
            return rewrite_path(context, PathContext::Import, None, path, shape)
                .map(|path_str| format!("{}::{{}}", path_str));
        }
        1 => {
            return rewrite_nested_use_tree_single(context, &path_str, &trees[0].0, shape);
        }
        _ => (),
    }

    let path_str = if path_str.is_empty() {
        path_str
    } else {
        format!("{}::", path_str)
    };

    // 2 = "{}"
    let remaining_width = shape.width.checked_sub(path_str.len() + 2).unwrap_or(0);
    let nested_indent = match context.config.imports_indent() {
        IndentStyle::Block => shape.indent.block_indent(context.config),
        // 1 = `{`
        IndentStyle::Visual => shape.visual_indent(path_str.len() + 1).indent,
    };

    let nested_shape = match context.config.imports_indent() {
        IndentStyle::Block => Shape::indented(nested_indent, context.config).sub_width(1)?,
        IndentStyle::Visual => Shape::legacy(remaining_width, nested_indent),
    };

    let mut items = {
        // Dummy value, see explanation below.
        let mut items = vec![ListItem::from_str("")];
        let iter = itemize_list(
            context.snippet_provider,
            trees.iter().map(|tree| &tree.0),
            "}",
            ",",
            |tree| tree.span.lo(),
            |tree| tree.span.hi(),
            |tree| tree.rewrite(context, nested_shape),
            context.snippet_provider.span_after(span, "{"),
            span.hi(),
            false,
        );
        items.extend(iter);
        items
    };

    // We prefixed the item list with a dummy value so that we can
    // potentially move "self" to the front of the vector without touching
    // the rest of the items.
    let has_self = move_self_to_front(&mut items);
    let first_index = if has_self { 0 } else { 1 };

    if context.config.reorder_imported_names() {
        items[1..].sort_by(|a, b| {
            let a = ImportItem::from_opt_str(a.item.as_ref());
            let b = ImportItem::from_opt_str(b.item.as_ref());
            a.cmp(&b)
        });
    }

    let tactic = definitive_tactic(
        &items[first_index..],
        context.config.imports_layout(),
        Separator::Comma,
        remaining_width,
    );

    let ends_with_newline = context.config.imports_indent() == IndentStyle::Block
        && tactic != DefinitiveListTactic::Horizontal;

    let fmt = ListFormatting {
        tactic,
        separator: ",",
        trailing_separator: if ends_with_newline {
            context.config.trailing_comma()
        } else {
            SeparatorTactic::Never
        },
        separator_place: SeparatorPlace::Back,
        shape: nested_shape,
        ends_with_newline,
        preserve_newline: true,
        config: context.config,
    };
    let list_str = write_list(&items[first_index..], &fmt)?;

    let result = if (list_str.contains('\n') || list_str.len() > remaining_width)
        && context.config.imports_indent() == IndentStyle::Block
    {
        format!(
            "{}{{\n{}{}\n{}}}",
            path_str,
            nested_shape.indent.to_string(context.config),
            list_str,
            shape.indent.to_string(context.config)
        )
    } else {
        format!("{}{{{}}}", path_str, list_str)
    };
    Some(result)
}

// Returns true when self item was found.
fn move_self_to_front(items: &mut Vec<ListItem>) -> bool {
    match items
        .iter()
        .position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self"))
    {
        Some(pos) => {
            items[0] = items.remove(pos);
            true
        }
        None => false,
    }
}
<|endoftext|>


<commit_before>

pub fn is_leap_year(year: i32) -> bool
{
    if year%4 == 0 {
        if year%100 == 0 && year%400 == 0
        {
            true
        }
        else if year%100 == 0
            {
                false
            }
            else
            {
                true
            }
        }
        else
        {
            false
        }

}
<commit_msg>Exercism: leap<commit_after>

pub fn is_leap_year(year: i32) -> bool
{
    if year%4 == 0{
        if year%100 == 0 && year%400 == 0{
            true}
        else if year%100 == 0{
            false}
        else{
            true}
        }
    else{
        false}
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::fmt;
use std::mem;
use std::path::Path;
use std::ptr;

use shared_library;
use vk;

lazy_static! {
    static ref VK_LIB: Result<shared_library::dynamic_library::DynamicLibrary, LoadingError> = {
        #[cfg(windows)] fn get_path() -> &'static Path { Path::new("vulkan-1.dll") }
        #[cfg(unix)] fn get_path() -> &'static Path { Path::new("libvulkan.so") }
        let path = get_path();
        shared_library::dynamic_library::DynamicLibrary::open(Some(path))
                                    .map_err(|err| LoadingError::LibraryLoadFailure(err))
    };

    static ref VK_STATIC: Result<vk::Static, LoadingError> = {
        match *VK_LIB {
            Ok(ref lib) => {
                let mut err = None;
                let result = vk::Static::load(|name| unsafe {
                    let name = name.to_str().unwrap();
                    match lib.symbol(name) {
                        Ok(s) => s,
                        Err(_) => {     // TODO: return error?
                            err = Some(LoadingError::MissingEntryPoint(name.to_owned()));
                            ptr::null()
                        }
                    }
                });

                if let Some(err) = err {
                    Err(err)
                } else {
                    Ok(result)
                }
            },
            Err(ref err) => Err(err.clone()),
        }
    };

    static ref VK_ENTRY: Result<vk::EntryPoints, LoadingError> = {
        match *VK_STATIC {
            Ok(ref lib) => {
                // At this point we assume that if one of the functions fails to load, it is an
                // implementation bug and not a real-life situation that could be handled by
                // an error.
                Ok(vk::EntryPoints::load(|name| unsafe {
                    mem::transmute(lib.GetInstanceProcAddr(0, name.as_ptr()))
                }))
            },
            Err(ref err) => Err(err.clone()),
        }
    };
}

/// Returns the collection of static functions from the Vulkan loader, or an error if failed to
/// open the loader.
pub fn static_functions() -> Result<&'static vk::Static, LoadingError> {
    VK_STATIC.as_ref().map_err(|err| err.clone())
}

/// Returns the collection of Vulkan entry points from the Vulkan loader, or an error if failed to
/// open the loader.
pub fn entry_points() -> Result<&'static vk::EntryPoints, LoadingError> {
    VK_ENTRY.as_ref().map_err(|err| err.clone())
}

/// Error that can happen when loading the Vulkan loader.
#[derive(Debug, Clone)]
pub enum LoadingError {
    /// Failed to load the Vulkan shared library.
    LibraryLoadFailure(String),         // TODO: meh for error type, but this needs changes in shared_library

    /// One of the entry points required to be supported by the Vulkan implementation is missing.
    MissingEntryPoint(String),
}

impl error::Error for LoadingError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            LoadingError::LibraryLoadFailure(_) => {
                "failed to load the Vulkan shared library"
            },
            LoadingError::MissingEntryPoint(_) => {
                "one of the entry points required to be supported by the Vulkan implementation \
                 is missing"
            },
        }
    }

    /*#[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            LoadingError::LibraryLoadFailure(ref err) => Some(err),
            _ => None
        }
    }*/
}

impl fmt::Display for LoadingError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}
<commit_msg>Change vulkan library name on unix<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::fmt;
use std::mem;
use std::path::Path;
use std::ptr;

use shared_library;
use vk;

lazy_static! {
    static ref VK_LIB: Result<shared_library::dynamic_library::DynamicLibrary, LoadingError> = {
        #[cfg(windows)] fn get_path() -> &'static Path { Path::new("vulkan-1.dll") }
        #[cfg(unix)] fn get_path() -> &'static Path { Path::new("libvulkan.so.1") }
        let path = get_path();
        shared_library::dynamic_library::DynamicLibrary::open(Some(path))
                                    .map_err(|err| LoadingError::LibraryLoadFailure(err))
    };

    static ref VK_STATIC: Result<vk::Static, LoadingError> = {
        match *VK_LIB {
            Ok(ref lib) => {
                let mut err = None;
                let result = vk::Static::load(|name| unsafe {
                    let name = name.to_str().unwrap();
                    match lib.symbol(name) {
                        Ok(s) => s,
                        Err(_) => {     // TODO: return error?
                            err = Some(LoadingError::MissingEntryPoint(name.to_owned()));
                            ptr::null()
                        }
                    }
                });

                if let Some(err) = err {
                    Err(err)
                } else {
                    Ok(result)
                }
            },
            Err(ref err) => Err(err.clone()),
        }
    };

    static ref VK_ENTRY: Result<vk::EntryPoints, LoadingError> = {
        match *VK_STATIC {
            Ok(ref lib) => {
                // At this point we assume that if one of the functions fails to load, it is an
                // implementation bug and not a real-life situation that could be handled by
                // an error.
                Ok(vk::EntryPoints::load(|name| unsafe {
                    mem::transmute(lib.GetInstanceProcAddr(0, name.as_ptr()))
                }))
            },
            Err(ref err) => Err(err.clone()),
        }
    };
}

/// Returns the collection of static functions from the Vulkan loader, or an error if failed to
/// open the loader.
pub fn static_functions() -> Result<&'static vk::Static, LoadingError> {
    VK_STATIC.as_ref().map_err(|err| err.clone())
}

/// Returns the collection of Vulkan entry points from the Vulkan loader, or an error if failed to
/// open the loader.
pub fn entry_points() -> Result<&'static vk::EntryPoints, LoadingError> {
    VK_ENTRY.as_ref().map_err(|err| err.clone())
}

/// Error that can happen when loading the Vulkan loader.
#[derive(Debug, Clone)]
pub enum LoadingError {
    /// Failed to load the Vulkan shared library.
    LibraryLoadFailure(String),         // TODO: meh for error type, but this needs changes in shared_library

    /// One of the entry points required to be supported by the Vulkan implementation is missing.
    MissingEntryPoint(String),
}

impl error::Error for LoadingError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            LoadingError::LibraryLoadFailure(_) => {
                "failed to load the Vulkan shared library"
            },
            LoadingError::MissingEntryPoint(_) => {
                "one of the entry points required to be supported by the Vulkan implementation \
                 is missing"
            },
        }
    }

    /*#[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            LoadingError::LibraryLoadFailure(ref err) => Some(err),
            _ => None
        }
    }*/
}

impl fmt::Display for LoadingError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}
<|endoftext|>