<commit_before>/*
    Copyright 2017 Andrew Medworth <github@medworth.org.uk>

    This file is part of Dots-and-Boxes Engine.

    Dots-and-Boxes Engine is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Dots-and-Boxes Engine is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Dots-and-Boxes Engine.  If not, see <http://www.gnu.org/licenses/>.
*/
use game::{Position, Side};
use std::cmp;
use std::iter;

// A fragment extracted from a larger position.
pub struct PositionFragment {
    pub pos: Position,
    pub x_offset: usize,
    pub y_offset: usize,
}

// Depth-first search to find all coordinates which are part of the fragment including (x, y)
fn search(pos: &Position, x: usize, y: usize,
          visited: &mut Vec<Vec<bool>>, frag_coords: &mut Vec<(usize, usize)>) {
    visited[x][y] = true;
    frag_coords.push((x, y));
    for side in Side::all() {
        if pos.is_legal_move(x, y, side) {
            if let Some((next_x, next_y)) = pos.offset(x, y, side) {
                if !visited[next_x][next_y] {
                    search(pos, next_x, next_y, visited, frag_coords);
                }
            }
        }
    }
}

// Build a PositionFragment from a list of coordinates
fn make_fragment(pos: &Position, coords: &Vec<(usize, usize)>) -> PositionFragment {
    let (xl, xr, yt, yb) = coords.iter().fold(
        (coords[0].0, coords[0].0, coords[0].1, coords[0].1),
        |(xli, xri, yti, ybi), &(x, y)| (cmp::min(xli, x), cmp::max(xri, x), cmp::min(yti, y), cmp::max(ybi, y))
    );
    let mut frag_pos = Position::new_end_game(xr-xl+1, yb-yt+1);
    for &(x, y) in coords {
        let (frag_x, frag_y) = (x - xl, y - yt);
        for side in Side::all() {
            if pos.is_legal_move(x, y, side) && !frag_pos.is_legal_move(frag_x, frag_y, side) {
                frag_pos.undo_move(frag_x, frag_y, side);
            }
        }
    }
    PositionFragment{pos: frag_pos, x_offset: xl, y_offset: yt}
}

// Split a position into its independent fragments.
// If the position is fully connected, the result will consist of a single element
// representing the whole position.
pub fn split(pos: &Position) -> Vec<PositionFragment> {
    let mut visited: Vec<Vec<bool>> = Vec::with_capacity(pos.width());
    for _ in 0..pos.width() {
        visited.push(iter::repeat(false).take(pos.height()).collect());
    }
    let mut result = Vec::new();
    for x in 0..pos.width() {
        for y in 0..pos.height() {
            if !visited[x][y] && pos.valency(x, y) > 0 {
                let mut frag_coords = Vec::new();
                search(pos, x, y, &mut visited, &mut frag_coords);
                result.push(make_fragment(pos, &frag_coords));
            }
        }
    }
    result
}

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

    #[test]
    fn split_p50() {
        let pos = p50();
        let parts = split(&pos);
        assert_eq!(3, parts.len());

        let top_parts: Vec<&PositionFragment> = parts.iter().filter(|f| f.x_offset == 0 && f.y_offset == 0).collect();
        assert_eq!(1, top_parts.len());
        assert_eq!(true, top_parts[0].pos.eq(&p50_top()));

        let bl_parts: Vec<&PositionFragment> = parts.iter().filter(|f| f.x_offset == 0 && f.y_offset == 2).collect();
        assert_eq!(1, bl_parts.len());
        assert_eq!(true, bl_parts[0].pos.eq(&p50_bottomleft()));

        let br_parts: Vec<&PositionFragment> = parts.iter().filter(|f| f.x_offset == 3 && f.y_offset == 2).collect();
        assert_eq!(1, br_parts.len());
        assert_eq!(true, br_parts[0].pos.eq(&p50_bottomright()));
    }

    #[test]
    fn split_unsplittable() {
        let pos = Position::new_game(3, 3);
        let parts = split(&pos);
        assert_eq!(1, parts.len());
        let frag = &parts[0];
        assert_eq!(0, frag.x_offset);
        assert_eq!(0, frag.y_offset);
        assert_eq!(true, frag.pos.eq(&pos));
    }
}
<commit_msg>Rename make_fragment variables<commit_after>/*
    Copyright 2017 Andrew Medworth <github@medworth.org.uk>

    This file is part of Dots-and-Boxes Engine.

    Dots-and-Boxes Engine is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Dots-and-Boxes Engine is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Dots-and-Boxes Engine.  If not, see <http://www.gnu.org/licenses/>.
*/
use game::{Position, Side};
use std::cmp;
use std::iter;

// A fragment extracted from a larger position.
pub struct PositionFragment {
    pub pos: Position,
    pub x_offset: usize,
    pub y_offset: usize,
}

// Depth-first search to find all coordinates which are part of the fragment including (x, y)
fn search(pos: &Position, x: usize, y: usize,
          visited: &mut Vec<Vec<bool>>, frag_coords: &mut Vec<(usize, usize)>) {
    visited[x][y] = true;
    frag_coords.push((x, y));
    for side in Side::all() {
        if pos.is_legal_move(x, y, side) {
            if let Some((next_x, next_y)) = pos.offset(x, y, side) {
                if !visited[next_x][next_y] {
                    search(pos, next_x, next_y, visited, frag_coords);
                }
            }
        }
    }
}

// Build a PositionFragment from a list of coordinates
fn make_fragment(pos: &Position, coords: &Vec<(usize, usize)>) -> PositionFragment {
    let (x_left, x_right, y_top, y_bottom) = coords.iter().fold(
        (coords[0].0, coords[0].0, coords[0].1, coords[0].1),
        |(xl, xr, yt, yb), &(x, y)| (cmp::min(xl, x), cmp::max(xr, x), cmp::min(yt, y), cmp::max(yb, y))
    );
    let mut frag_pos = Position::new_end_game(x_right - x_left + 1, y_bottom - y_top + 1);
    for &(x, y) in coords {
        let (frag_x, frag_y) = (x - x_left, y - y_top);
        for side in Side::all() {
            if pos.is_legal_move(x, y, side) && !frag_pos.is_legal_move(frag_x, frag_y, side) {
                frag_pos.undo_move(frag_x, frag_y, side);
            }
        }
    }
    PositionFragment{pos: frag_pos, x_offset: x_left, y_offset: y_top}
}

// Split a position into its independent fragments.
// If the position is fully connected, the result will consist of a single element
// representing the whole position.
pub fn split(pos: &Position) -> Vec<PositionFragment> {
    let mut visited: Vec<Vec<bool>> = Vec::with_capacity(pos.width());
    for _ in 0..pos.width() {
        visited.push(iter::repeat(false).take(pos.height()).collect());
    }
    let mut result = Vec::new();
    for x in 0..pos.width() {
        for y in 0..pos.height() {
            if !visited[x][y] && pos.valency(x, y) > 0 {
                let mut frag_coords = Vec::new();
                search(pos, x, y, &mut visited, &mut frag_coords);
                result.push(make_fragment(pos, &frag_coords));
            }
        }
    }
    result
}

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

    #[test]
    fn split_p50() {
        let pos = p50();
        let parts = split(&pos);
        assert_eq!(3, parts.len());

        let top_parts: Vec<&PositionFragment> = parts.iter().filter(|f| f.x_offset == 0 && f.y_offset == 0).collect();
        assert_eq!(1, top_parts.len());
        assert_eq!(true, top_parts[0].pos.eq(&p50_top()));

        let bl_parts: Vec<&PositionFragment> = parts.iter().filter(|f| f.x_offset == 0 && f.y_offset == 2).collect();
        assert_eq!(1, bl_parts.len());
        assert_eq!(true, bl_parts[0].pos.eq(&p50_bottomleft()));

        let br_parts: Vec<&PositionFragment> = parts.iter().filter(|f| f.x_offset == 3 && f.y_offset == 2).collect();
        assert_eq!(1, br_parts.len());
        assert_eq!(true, br_parts[0].pos.eq(&p50_bottomright()));
    }

    #[test]
    fn split_unsplittable() {
        let pos = Position::new_game(3, 3);
        let parts = split(&pos);
        assert_eq!(1, parts.len());
        let frag = &parts[0];
        assert_eq!(0, frag.x_offset);
        assert_eq!(0, frag.y_offset);
        assert_eq!(true, frag.pos.eq(&pos));
    }
}
<|endoftext|>


<commit_before>use super::*;
use std::fs::File;
use std::path::Path;

pub struct VapoursynthWriter {
    opts: AvsOptions,
    audio_filename: Option<PathBuf>,
}

impl ScriptFormat for VapoursynthWriter {
    fn build_video_filter_string(&self, current_filename: &Path, is_preload: bool) -> String {
        let video_filter = self.get_video_filter_full_name(&current_filename);
        let timecodes_path = current_filename.with_extension("timecodes.txt");
        if self.opts.to_cfr && !timecodes_path.exists() {
            File::create(&timecodes_path).ok();
        }
        let mut filter_opts = String::new();
        if self.opts.to_cfr && is_preload {
            filter_opts.push_str(&format!(
                ", timecodes=\"{}\"",
                escape_python_string(timecodes_path.canonicalize().unwrap().to_str().unwrap()),
            ));
        }

        format!(
            "{}({}{})",
            video_filter,
            format!(
                "source='{}'",
                escape_python_string(current_filename.canonicalize().unwrap().to_str().unwrap())
            ),
            filter_opts
        )
    }

    fn build_vfr_string(&self, timecodes_path: &Path) -> String {
        format!(
            "core.vfrtocfr.VFRToCFR(\"{}\", 120000, 1001)",
            escape_python_string(timecodes_path.canonicalize().unwrap().to_str().unwrap())
        )
    }

    fn build_downsample_string(&self) -> Option<String> {
        Some("core.resize.Spline36(format = vs.YUV420P8)".to_string())
    }

    #[inline(always)]
    fn get_opts(&self) -> &AvsOptions {
        &self.opts
    }

    #[inline(always)]
    fn get_script_extension(&self) -> &'static str {
        "vpy"
    }

    fn build_audio_dub_string(&mut self, audio_filename: &Path) -> String {
        format!(
            "core.damb.Read(\'{}\')",
            escape_python_string(audio_filename.to_str().unwrap())
        )
    }

    fn build_subtitle_string(&self, subtitle_filename: &Path) -> String {
        format!(
            "core.sub.TextFile(\'{}\')",
            escape_python_string(subtitle_filename.to_str().unwrap())
        )
    }

    fn build_resize_string(&self, width: u32, height: u32) -> String {
        format!("core.resize.Spline36({}, {})", width, height)
    }

    fn build_trim_string(&self, breakpoint: BreakPoint) -> String {
        format!(
            "core.std.Trim({}, {})",
            breakpoint.start_frame, breakpoint.end_frame
        )
    }

    fn write_script_header(&self, script: &mut File) -> Result<(), String> {
        writeln!(script, "import vapoursynth as vs").map_err(|e| e.to_string())?;
        writeln!(script, "core = vs.get_core()").map_err(|e| e.to_string())?;
        writeln!(script).map_err(|e| e.to_string())?;
        Ok(())
    }

    fn write_segments(&self, segments: &[Vec<String>], script: &mut File) -> Result<(), String> {
        for (i, segment) in segments.iter().enumerate() {
            let video_label = format!("video{}", i + 1);
            for (j, mut filter) in segment.clone().into_iter().enumerate() {
                if j > 0 {
                    filter = if filter.contains("()") {
                        filter.replacen("()", &format!("({})", video_label), 1)
                    } else {
                        filter.replacen("(", &&format!("({}, ", video_label), 1)
                    };
                }
                writeln!(script, "{} = {}", video_label, filter).map_err(|e| e.to_string())?;
            }
            writeln!(script).map_err(|e| e.to_string())?;
        }
        writeln!(
            script,
            "video = {}",
            (0..segments.len())
                .map(|i| format!("video{}", i + 1))
                .collect::<Vec<String>>()
                .join(" + ")
        )
        .map_err(|e| e.to_string())?;
        writeln!(script).map_err(|e| e.to_string())?;
        if let Some(ref audio_filename) = self.audio_filename {
            writeln!(
                script,
                "core.damb.Write(video, \'{}\').set_output()",
                escape_python_string(audio_filename.with_extension("flac").to_str().unwrap())
            )
            .map_err(|e| e.to_string())?;
        } else {
            writeln!(script, "video.set_output()").map_err(|e| e.to_string())?;
        }

        Ok(())
    }
}

fn escape_python_string(input: &str) -> String {
    input.replace(r"\", r"\\").replace(r"'", r"\'")
}

impl VapoursynthWriter {
    pub fn new(
        mut opts: AvsOptions,
        apply_default_filters: bool,
        audio_filename: Option<PathBuf>,
    ) -> Self {
        let default_filters: &[String] = &["core.rgvs.RemoveGrain(1)".to_string()];
        if apply_default_filters {
            opts.filters.extend_from_slice(default_filters);
        }
        VapoursynthWriter {
            opts,
            audio_filename,
        }
    }

    fn determine_video_source_filter(&self, path: &Path) -> &'static str {
        match determine_input_type(path) {
            Some(InputTypes::DgIndex) => "core.d2v.Source",
            Some(InputTypes::DgAvc) => unimplemented!(),
            Some(_) => "core.lsmas.LWLibavSource",
            None => panic!("Invalid input type"),
        }
    }

    fn get_video_filter_full_name(&self, current_filename: &Path) -> &'static str {
        self.determine_video_source_filter(&current_filename)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs::File;
    use std::io::BufReader;
    use std::io::Read;
    use std::path::Path;

    fn read_file(path: &Path) -> String {
        let file = File::open(path).unwrap();
        let mut reader = BufReader::new(file);
        let mut output = String::new();
        reader.read_to_string(&mut output).unwrap();
        output.replace("\r\n", "\n")
    }

    #[test]
    fn create_script_vps_basic() {
        let in_file = Path::new("files/example.mkv");
        let out_file = Path::new("files/vps_basic.vpy");
        let expected = Path::new("files/vps_basic.vpy.expected");
        let opts = AvsOptions {
            filters: vec![],
            ass: false,
            ass_extract: None,
            audio: (false, None),
            resize: None,
            to_cfr: false,
            downsample: false,
        };
        let mut writer = VapoursynthWriter::new(opts, true);
        writer.create_script(in_file, out_file).unwrap();
        assert_eq!(&read_file(out_file), &read_file(expected));
    }

    #[test]
    fn create_script_vps_audio() {
        let in_file = Path::new("files/example.mkv");
        let out_file = Path::new("files/vps_audio.vpy");
        let expected = Path::new("files/vps_audio.vpy.expected");
        let opts = AvsOptions {
            filters: vec![],
            ass: false,
            ass_extract: None,
            audio: (true, None),
            resize: None,
            to_cfr: false,
            downsample: false,
        };
        let mut writer = VapoursynthWriter::new(opts, true);
        writer.create_script(in_file, out_file).unwrap();
        assert_eq!(&read_file(out_file), &read_file(expected));
    }

    #[test]
    fn create_script_vps_downsample() {
        let in_file = Path::new("files/example.mkv");
        let out_file = Path::new("files/vps_downsample.vpy");
        let expected = Path::new("files/vps_downsample.vpy.expected");
        let opts = AvsOptions {
            filters: vec![],
            ass: false,
            ass_extract: None,
            audio: (false, None),
            resize: None,
            to_cfr: false,
            downsample: true,
        };
        let mut writer = VapoursynthWriter::new(opts, true);
        writer.create_script(in_file, out_file).unwrap();
        assert_eq!(&read_file(out_file), &read_file(expected));
    }

    #[test]
    fn create_script_vps_cfr() {
        let in_file = Path::new("files/example.mkv");
        let out_file = Path::new("files/vps_cfr.vpy");
        let expected = Path::new("files/vps_cfr.vpy.expected");
        let opts = AvsOptions {
            filters: vec![],
            ass: false,
            ass_extract: None,
            audio: (false, None),
            resize: None,
            to_cfr: true,
            downsample: false,
        };
        let mut writer = VapoursynthWriter::new(opts, true);
        writer.create_script(in_file, out_file).unwrap();
        assert_eq!(&read_file(out_file), &read_file(expected));
    }

    #[test]
    fn create_script_vps_resize() {
        let in_file = Path::new("files/example.mkv");
        let out_file = Path::new("files/vps_resize.vpy");
        let expected = Path::new("files/vps_resize.vpy.expected");
        let opts = AvsOptions {
            filters: vec![],
            ass: false,
            ass_extract: None,
            audio: (false, None),
            resize: Some((640, 480)),
            to_cfr: false,
            downsample: false,
        };
        let mut writer = VapoursynthWriter::new(opts, true);
        writer.create_script(in_file, out_file).unwrap();
        assert_eq!(&read_file(out_file), &read_file(expected));
    }

    #[test]
    fn create_script_vps_ass() {
        let in_file = Path::new("files/example.mkv");
        let out_file = Path::new("files/vps_ass.vpy");
        let expected = Path::new("files/vps_ass.vpy.expected");
        let opts = AvsOptions {
            filters: vec![],
            ass: true,
            ass_extract: None,
            audio: (false, None),
            resize: None,
            to_cfr: false,
            downsample: false,
        };
        let mut writer = VapoursynthWriter::new(opts, true);
        writer.create_script(in_file, out_file).unwrap();
        assert_eq!(&read_file(out_file), &read_file(expected));
    }
}
<commit_msg>Revert "Prefer LWLibavSource from LSmash"<commit_after>use super::*;
use std::fs::File;
use std::path::Path;

pub struct VapoursynthWriter {
    opts: AvsOptions,
    audio_filename: Option<PathBuf>,
}

impl ScriptFormat for VapoursynthWriter {
    fn build_video_filter_string(&self, current_filename: &Path, is_preload: bool) -> String {
        let video_filter = self.get_video_filter_full_name(&current_filename);
        let timecodes_path = current_filename.with_extension("timecodes.txt");
        if self.opts.to_cfr && !timecodes_path.exists() {
            File::create(&timecodes_path).ok();
        }
        let mut filter_opts = String::new();
        if self.opts.to_cfr && is_preload {
            filter_opts.push_str(&format!(
                ", timecodes=\"{}\"",
                escape_python_string(timecodes_path.canonicalize().unwrap().to_str().unwrap()),
            ));
        }

        format!(
            "{}({}{})",
            video_filter,
            format!(
                "source='{}'",
                escape_python_string(current_filename.canonicalize().unwrap().to_str().unwrap())
            ),
            filter_opts
        )
    }

    fn build_vfr_string(&self, timecodes_path: &Path) -> String {
        format!(
            "core.vfrtocfr.VFRToCFR(\"{}\", 120000, 1001)",
            escape_python_string(timecodes_path.canonicalize().unwrap().to_str().unwrap())
        )
    }

    fn build_downsample_string(&self) -> Option<String> {
        Some("core.resize.Spline36(format = vs.YUV420P8)".to_string())
    }

    #[inline(always)]
    fn get_opts(&self) -> &AvsOptions {
        &self.opts
    }

    #[inline(always)]
    fn get_script_extension(&self) -> &'static str {
        "vpy"
    }

    fn build_audio_dub_string(&mut self, audio_filename: &Path) -> String {
        format!(
            "core.damb.Read(\'{}\')",
            escape_python_string(audio_filename.to_str().unwrap())
        )
    }

    fn build_subtitle_string(&self, subtitle_filename: &Path) -> String {
        format!(
            "core.sub.TextFile(\'{}\')",
            escape_python_string(subtitle_filename.to_str().unwrap())
        )
    }

    fn build_resize_string(&self, width: u32, height: u32) -> String {
        format!("core.resize.Spline36({}, {})", width, height)
    }

    fn build_trim_string(&self, breakpoint: BreakPoint) -> String {
        format!(
            "core.std.Trim({}, {})",
            breakpoint.start_frame, breakpoint.end_frame
        )
    }

    fn write_script_header(&self, script: &mut File) -> Result<(), String> {
        writeln!(script, "import vapoursynth as vs").map_err(|e| e.to_string())?;
        writeln!(script, "core = vs.get_core()").map_err(|e| e.to_string())?;
        writeln!(script).map_err(|e| e.to_string())?;
        Ok(())
    }

    fn write_segments(&self, segments: &[Vec<String>], script: &mut File) -> Result<(), String> {
        for (i, segment) in segments.iter().enumerate() {
            let video_label = format!("video{}", i + 1);
            for (j, mut filter) in segment.clone().into_iter().enumerate() {
                if j > 0 {
                    filter = if filter.contains("()") {
                        filter.replacen("()", &format!("({})", video_label), 1)
                    } else {
                        filter.replacen("(", &&format!("({}, ", video_label), 1)
                    };
                }
                writeln!(script, "{} = {}", video_label, filter).map_err(|e| e.to_string())?;
            }
            writeln!(script).map_err(|e| e.to_string())?;
        }
        writeln!(
            script,
            "video = {}",
            (0..segments.len())
                .map(|i| format!("video{}", i + 1))
                .collect::<Vec<String>>()
                .join(" + ")
        )
        .map_err(|e| e.to_string())?;
        writeln!(script).map_err(|e| e.to_string())?;
        if let Some(ref audio_filename) = self.audio_filename {
            writeln!(
                script,
                "core.damb.Write(video, \'{}\').set_output()",
                escape_python_string(audio_filename.with_extension("flac").to_str().unwrap())
            )
            .map_err(|e| e.to_string())?;
        } else {
            writeln!(script, "video.set_output()").map_err(|e| e.to_string())?;
        }

        Ok(())
    }
}

fn escape_python_string(input: &str) -> String {
    input.replace(r"\", r"\\").replace(r"'", r"\'")
}

impl VapoursynthWriter {
    pub fn new(
        mut opts: AvsOptions,
        apply_default_filters: bool,
        audio_filename: Option<PathBuf>,
    ) -> Self {
        let default_filters: &[String] = &["core.rgvs.RemoveGrain(1)".to_string()];
        if apply_default_filters {
            opts.filters.extend_from_slice(default_filters);
        }
        VapoursynthWriter {
            opts,
            audio_filename,
        }
    }

    fn determine_video_source_filter(&self, path: &Path) -> &'static str {
        match determine_input_type(path) {
            Some(InputTypes::DgIndex) => "core.d2v.Source",
            Some(InputTypes::DgAvc) => unimplemented!(),
            Some(_) => "core.ffms2.Source",
            None => panic!("Invalid input type"),
        }
    }

    fn get_video_filter_full_name(&self, current_filename: &Path) -> &'static str {
        self.determine_video_source_filter(&current_filename)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs::File;
    use std::io::BufReader;
    use std::io::Read;
    use std::path::Path;

    fn read_file(path: &Path) -> String {
        let file = File::open(path).unwrap();
        let mut reader = BufReader::new(file);
        let mut output = String::new();
        reader.read_to_string(&mut output).unwrap();
        output.replace("\r\n", "\n")
    }

    #[test]
    fn create_script_vps_basic() {
        let in_file = Path::new("files/example.mkv");
        let out_file = Path::new("files/vps_basic.vpy");
        let expected = Path::new("files/vps_basic.vpy.expected");
        let opts = AvsOptions {
            filters: vec![],
            ass: false,
            ass_extract: None,
            audio: (false, None),
            resize: None,
            to_cfr: false,
            downsample: false,
        };
        let mut writer = VapoursynthWriter::new(opts, true);
        writer.create_script(in_file, out_file).unwrap();
        assert_eq!(&read_file(out_file), &read_file(expected));
    }

    #[test]
    fn create_script_vps_audio() {
        let in_file = Path::new("files/example.mkv");
        let out_file = Path::new("files/vps_audio.vpy");
        let expected = Path::new("files/vps_audio.vpy.expected");
        let opts = AvsOptions {
            filters: vec![],
            ass: false,
            ass_extract: None,
            audio: (true, None),
            resize: None,
            to_cfr: false,
            downsample: false,
        };
        let mut writer = VapoursynthWriter::new(opts, true);
        writer.create_script(in_file, out_file).unwrap();
        assert_eq!(&read_file(out_file), &read_file(expected));
    }

    #[test]
    fn create_script_vps_downsample() {
        let in_file = Path::new("files/example.mkv");
        let out_file = Path::new("files/vps_downsample.vpy");
        let expected = Path::new("files/vps_downsample.vpy.expected");
        let opts = AvsOptions {
            filters: vec![],
            ass: false,
            ass_extract: None,
            audio: (false, None),
            resize: None,
            to_cfr: false,
            downsample: true,
        };
        let mut writer = VapoursynthWriter::new(opts, true);
        writer.create_script(in_file, out_file).unwrap();
        assert_eq!(&read_file(out_file), &read_file(expected));
    }

    #[test]
    fn create_script_vps_cfr() {
        let in_file = Path::new("files/example.mkv");
        let out_file = Path::new("files/vps_cfr.vpy");
        let expected = Path::new("files/vps_cfr.vpy.expected");
        let opts = AvsOptions {
            filters: vec![],
            ass: false,
            ass_extract: None,
            audio: (false, None),
            resize: None,
            to_cfr: true,
            downsample: false,
        };
        let mut writer = VapoursynthWriter::new(opts, true);
        writer.create_script(in_file, out_file).unwrap();
        assert_eq!(&read_file(out_file), &read_file(expected));
    }

    #[test]
    fn create_script_vps_resize() {
        let in_file = Path::new("files/example.mkv");
        let out_file = Path::new("files/vps_resize.vpy");
        let expected = Path::new("files/vps_resize.vpy.expected");
        let opts = AvsOptions {
            filters: vec![],
            ass: false,
            ass_extract: None,
            audio: (false, None),
            resize: Some((640, 480)),
            to_cfr: false,
            downsample: false,
        };
        let mut writer = VapoursynthWriter::new(opts, true);
        writer.create_script(in_file, out_file).unwrap();
        assert_eq!(&read_file(out_file), &read_file(expected));
    }

    #[test]
    fn create_script_vps_ass() {
        let in_file = Path::new("files/example.mkv");
        let out_file = Path::new("files/vps_ass.vpy");
        let expected = Path::new("files/vps_ass.vpy.expected");
        let opts = AvsOptions {
            filters: vec![],
            ass: true,
            ass_extract: None,
            audio: (false, None),
            resize: None,
            to_cfr: false,
            downsample: false,
        };
        let mut writer = VapoursynthWriter::new(opts, true);
        writer.create_script(in_file, out_file).unwrap();
        assert_eq!(&read_file(out_file), &read_file(expected));
    }
}
<|endoftext|>


<commit_before>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::libc::funcs::posix88;
use std::io::signal::{Listener, Interrupt};
use std::{io, run, os, str};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use std::io::fs::File;
use extra::getopts;

struct Shell {
    cmd_prompt: ~str,
    history: ~[~str],
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            history: ~[],
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        loop {
            print(self.cmd_prompt);
            io::stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let writeRedirect = cmd_line.find_str(" > ");
            let readRedirect = cmd_line.find_str(" < ");
            if(writeRedirect == None && readRedirect == None) {
            	let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");
            	self.history.push(cmd_line.clone());
            	match cmd_line.slice_from(cmd_line.len() - 2) {
            		" &"    => { self.run_background(program, cmd_line.slice(0, cmd_line.len() - 2));
            			continue; }
                	_	=> { }
            	}
            	match program {
			""           =>  { continue; }
			"exit"       =>  { return; }
			"cd"	     =>  { self.run_cd(cmd_line); }
			"history"    =>  { self.run_history(); }
			_            =>  { self.run_cmdline(cmd_line); }
            	}
            }
            else if (readRedirect == None) {
            	let cmd1 = cmd_line.slice(0, writeRedirect.unwrap());
            	let cmd2 = cmd_line.slice_from(writeRedirect.unwrap()+3);
            	let program = cmd1.splitn(' ', 1).nth(0).expect("no program");
            	let args : ~[&str] = if (cmd1.splitn(' ', 1).nth(1) != None) {cmd1.splitn(' ', 1).nth(1).unwrap().split(' ').collect()} else {~[]};
            	let mut argsOwned : ~[~str] = ~[];
            	for i in range (0, args.len()) {
            		argsOwned.push(args[i].to_owned());
            	}
		let newStdOut = File::create(&Path::new(cmd2));
            	match newStdOut {
            		Some(mut x) => {
            			let process = run::Process::new(program, argsOwned, run::ProcessOptions::new());
            			let output = process.unwrap().finish_with_output();
            			x.write(output.output);
            		}
            		None => { println("shouldnt be here");}
            	}
            }
            else if (writeRedirect == None) {
            	let cmd1 = cmd_line.slice(0, readRedirect.unwrap());
            	let cmd2 = cmd_line.slice_from(readRedirect.unwrap()+3);
            	let program = cmd1.splitn(' ', 1).nth(0).expect("no program");
            	let args : ~[&str] = if (cmd1.splitn(' ', 1).nth(1) != None) {cmd1.splitn(' ', 1).nth(1).unwrap().split(' ').collect()} else {~[]};
            	let mut argsOwned : ~[~str] = ~[];
            	for i in range (0, args.len()) {
            		argsOwned.push(args[i].to_owned());
            	}
           	let path = &Path::new(cmd2);
            	if (path.exists()) {
		let input = File::open(path);
            		match input {
            			Some(mut x) => {
            				let inputBytes = x.read_to_end();
            				let process = run::Process::new(program, argsOwned, run::ProcessOptions::new());
            				match(process) {
            					Some(mut toWrite) => {
            						toWrite.input().write(inputBytes);
            						let output = toWrite.finish_with_output();
            						print!("{:s}", str::from_utf8(output.output));
            					}
            					None => {}
        				}
            			}
            			None => { println!("gash: {:s}: No such file or directory", cmd2);}
            		}
            	}
                else {
           		println!("gash: {:s}: No such file or directory", cmd2);
           	}
            }
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 0 {
            let program: ~str = argv.remove(0);
            self.run_cmd(program, argv);
        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str]) {
        if self.cmd_exists(program) {
            run::process_status(program, argv);
        } else {
            println!("{:s}: command not found", program);
        }
    }

    fn run_cd(&mut self, program: &str) {
        let mut argv: ~[~str] =
            program.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

    	let mut programs : ~str = ~"";
            if argv.len() > 0 {
                programs = argv.remove(1);
            }
    	os::change_dir(&Path::new(programs.clone()));
    }

    fn run_history(&mut self) {
        for c in range(0, self.history.len()) {
            println!("{:s}", self.history[c]);
        }
    }

    fn run_background(&mut self, program: &str, cmd_line: &str) {
		let (portSelf, chanSelf): (Port<~Shell>, Chan<~Shell>) = Chan::new();
		let (portProg, chanProg): (Port<~str>, Chan<~str>) = Chan::new();
		let (portLine, chanLine): (Port<~str>, Chan<~str>) = Chan::new();

		let mut sendShell = ~(Shell::new("gash > "));
		sendShell.history = self.history.clone();
		chanSelf.send(sendShell);
		chanProg.send(program.to_owned());
		chanLine.send(cmd_line.to_owned());

		do spawn {
		let program : ~str = portProg.recv();
		let cmd_line : ~str = portLine.recv();
		let mut selfV : ~Shell = portSelf.recv();
                match program {
             	   ~""           =>  { }
              	  ~"exit"       =>  { }
		  ~"cd"	     =>  { selfV.run_cd(cmd_line); }
                  ~"history"    =>  { selfV.run_history(); }
                  _            =>  { selfV.run_cmdline(cmd_line); }
                }
            };
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    let mut listener = Listener::new();
    listener.register(Interrupt);

    let (portSelf, chanSelf): (Port<Listener>, Chan<Listener>) = Chan::new();
    chanSelf.send(listener);

    do spawn{
        loop {
            let listener = portSelf.recv();
            match listener.port.recv() {
                Interrupt => { println!("Got Interrupt'ed");
                                unsafe { posix88::signal::kill(std::libc::getpid() , std::libc::SIGINT); }
                            }
                _ => (),
            }
        }
    };

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<commit_msg>Fixed bug where cd wouldn't work with no parameter<commit_after>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::libc::funcs::posix88;
use std::io::signal::{Listener, Interrupt};
use std::{io, run, os, str};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use std::io::fs::File;
use extra::getopts;

struct Shell {
    cmd_prompt: ~str,
    history: ~[~str],
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            history: ~[],
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        loop {
            print(self.cmd_prompt);
            io::stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let writeRedirect = cmd_line.find_str(" > ");
            let readRedirect = cmd_line.find_str(" < ");
            if(writeRedirect == None && readRedirect == None) {
            	let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");
            	self.history.push(cmd_line.clone());
            	match cmd_line.slice_from(cmd_line.len() - 2) {
            		" &"    => { self.run_background(program, cmd_line.slice(0, cmd_line.len() - 2));
            			continue; }
                	_	=> { }
            	}
            	match program {
			""           =>  { continue; }
			"exit"       =>  { return; }
			"cd"	     =>  { self.run_cd(cmd_line); }
			"history"    =>  { self.run_history(); }
			_            =>  { self.run_cmdline(cmd_line); }
            	}
            }
            else if (readRedirect == None) {
            	let cmd1 = cmd_line.slice(0, writeRedirect.unwrap());
            	let cmd2 = cmd_line.slice_from(writeRedirect.unwrap()+3);
            	let program = cmd1.splitn(' ', 1).nth(0).expect("no program");
            	let args : ~[&str] = if (cmd1.splitn(' ', 1).nth(1) != None) {cmd1.splitn(' ', 1).nth(1).unwrap().split(' ').collect()} else {~[]};
            	let mut argsOwned : ~[~str] = ~[];
            	for i in range (0, args.len()) {
            		argsOwned.push(args[i].to_owned());
            	}
		let newStdOut = File::create(&Path::new(cmd2));
            	match newStdOut {
            		Some(mut x) => {
            			let process = run::Process::new(program, argsOwned, run::ProcessOptions::new());
            			let output = process.unwrap().finish_with_output();
            			x.write(output.output);
            		}
            		None => { println("shouldnt be here");}
            	}
            }
            else if (writeRedirect == None) {
            	let cmd1 = cmd_line.slice(0, readRedirect.unwrap());
            	let cmd2 = cmd_line.slice_from(readRedirect.unwrap()+3);
            	let program = cmd1.splitn(' ', 1).nth(0).expect("no program");
            	let args : ~[&str] = if (cmd1.splitn(' ', 1).nth(1) != None) {cmd1.splitn(' ', 1).nth(1).unwrap().split(' ').collect()} else {~[]};
            	let mut argsOwned : ~[~str] = ~[];
            	for i in range (0, args.len()) {
            		argsOwned.push(args[i].to_owned());
            	}
           	let path = &Path::new(cmd2);
            	if (path.exists()) {
		let input = File::open(path);
            		match input {
            			Some(mut x) => {
            				let inputBytes = x.read_to_end();
            				let process = run::Process::new(program, argsOwned, run::ProcessOptions::new());
            				match(process) {
            					Some(mut toWrite) => {
            						toWrite.input().write(inputBytes);
            						let output = toWrite.finish_with_output();
            						print!("{:s}", str::from_utf8(output.output));
            					}
            					None => {}
        				}
            			}
            			None => { println!("gash: {:s}: No such file or directory", cmd2);}
            		}
            	}
                else {
           		println!("gash: {:s}: No such file or directory", cmd2);
           	}
            }
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 0 {
            let program: ~str = argv.remove(0);
            self.run_cmd(program, argv);
        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str]) {
        if self.cmd_exists(program) {
            run::process_status(program, argv);
        } else {
            println!("{:s}: command not found", program);
        }
    }

    fn run_cd(&mut self, program: &str) {
        let mut argv: ~[~str] =
            program.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

    	let mut programs : ~str = ~"";
            if argv.len() > 1 {
                programs = argv.remove(1);
            }
    	os::change_dir(&Path::new(programs.clone()));
    }

    fn run_history(&mut self) {
        for c in range(0, self.history.len()) {
            println!("{:s}", self.history[c]);
        }
    }

    fn run_background(&mut self, program: &str, cmd_line: &str) {
		let (portSelf, chanSelf): (Port<~Shell>, Chan<~Shell>) = Chan::new();
		let (portProg, chanProg): (Port<~str>, Chan<~str>) = Chan::new();
		let (portLine, chanLine): (Port<~str>, Chan<~str>) = Chan::new();

		let mut sendShell = ~(Shell::new("gash > "));
		sendShell.history = self.history.clone();
		chanSelf.send(sendShell);
		chanProg.send(program.to_owned());
		chanLine.send(cmd_line.to_owned());

		do spawn {
		let program : ~str = portProg.recv();
		let cmd_line : ~str = portLine.recv();
		let mut selfV : ~Shell = portSelf.recv();
                match program {
             	   ~""           =>  { }
              	  ~"exit"       =>  { }
		  ~"cd"	     =>  { selfV.run_cd(cmd_line); }
                  ~"history"    =>  { selfV.run_history(); }
                  _            =>  { selfV.run_cmdline(cmd_line); }
                }
            };
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    let mut listener = Listener::new();
    listener.register(Interrupt);

    let (portSelf, chanSelf): (Port<Listener>, Chan<Listener>) = Chan::new();
    chanSelf.send(listener);

    do spawn{
        loop {
            let listener = portSelf.recv();
            match listener.port.recv() {
                Interrupt => { println!("Got Interrupt'ed");
                                unsafe { posix88::signal::kill(std::libc::getpid() , std::libc::SIGINT); }
                            }
                _ => (),
            }
        }
    };

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<|endoftext|>


<commit_before>//! checks for attributes

use crate::reexport::*;
use rustc::hir::*;
use rustc::lint::*;
use rustc::ty::{self, TyCtxt};
use semver::Version;
use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
use syntax::codemap::Span;
use crate::utils::{
    in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then,
    without_block_comments,
};

/// **What it does:** Checks for items annotated with `#[inline(always)]`,
/// unless the annotated function is empty or simply panics.
///
/// **Why is this bad?** While there are valid uses of this annotation (and once
/// you know when to use it, by all means `allow` this lint), it's a common
/// newbie-mistake to pepper one's code with it.
///
/// As a rule of thumb, before slapping `#[inline(always)]` on a function,
/// measure if that additional function call really affects your runtime profile
/// sufficiently to make up for the increase in compile time.
///
/// **Known problems:** False positives, big time. This lint is meant to be
/// deactivated by everyone doing serious performance work. This means having
/// done the measurement.
///
/// **Example:**
/// ```rust
/// #[inline(always)]
/// fn not_quite_hot_code(..) { ... }
/// ```
declare_clippy_lint! {
    pub INLINE_ALWAYS,
    pedantic,
    "use of `#[inline(always)]`"
}

/// **What it does:** Checks for `extern crate` and `use` items annotated with
/// lint attributes
///
/// **Why is this bad?** Lint attributes have no effect on crate imports. Most
/// likely a `!` was
/// forgotten
///
/// **Known problems:** Technically one might allow `unused_import` on a `use`
/// item,
/// but it's easier to remove the unused item.
///
/// **Example:**
/// ```rust
/// #[deny(dead_code)]
/// extern crate foo;
/// #[allow(unused_import)]
/// use foo::bar;
/// ```
declare_clippy_lint! {
    pub USELESS_ATTRIBUTE,
    correctness,
    "use of lint attributes on `extern crate` items"
}

/// **What it does:** Checks for `#[deprecated]` annotations with a `since`
/// field that is not a valid semantic version.
///
/// **Why is this bad?** For checking the version of the deprecation, it must be
/// a valid semver. Failing that, the contained information is useless.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// #[deprecated(since = "forever")]
/// fn something_else(..) { ... }
/// ```
declare_clippy_lint! {
    pub DEPRECATED_SEMVER,
    correctness,
    "use of `#[deprecated(since = \"x\")]` where x is not semver"
}

/// **What it does:** Checks for empty lines after outer attributes
///
/// **Why is this bad?**
/// Most likely the attribute was meant to be an inner attribute using a '!'.
/// If it was meant to be an outer attribute, then the following item
/// should not be separated by empty lines.
///
/// **Known problems:** Can cause false positives.
///
/// From the clippy side it's difficult to detect empty lines between an attributes and the
/// following item because empty lines and comments are not part of the AST. The parsing
/// currently works for basic cases but is not perfect.
///
/// **Example:**
/// ```rust
/// // Bad
/// #[inline(always)]
///
/// fn not_quite_good_code(..) { ... }
///
/// // Good (as inner attribute)
/// #![inline(always)]
///
/// fn this_is_fine(..) { ... }
///
/// // Good (as outer attribute)
/// #[inline(always)]
/// fn this_is_fine_too(..) { ... }
/// ```
declare_clippy_lint! {
    pub EMPTY_LINE_AFTER_OUTER_ATTR,
    nursery,
    "empty line after outer attribute"
}

#[derive(Copy, Clone)]
pub struct AttrPass;

impl LintPass for AttrPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(
            INLINE_ALWAYS,
            DEPRECATED_SEMVER,
            USELESS_ATTRIBUTE,
            EMPTY_LINE_AFTER_OUTER_ATTR
        )
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
    fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) {
        if let Some(ref items) = attr.meta_item_list() {
            if items.is_empty() || attr.name() != "deprecated" {
                return;
            }
            for item in items {
                if_chain! {
                    if let NestedMetaItemKind::MetaItem(ref mi) = item.node;
                    if let MetaItemKind::NameValue(ref lit) = mi.node;
                    if mi.name() == "since";
                    then {
                        check_semver(cx, item.span, lit);
                    }
                }
            }
        }
    }

    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
        if is_relevant_item(cx.tcx, item) {
            check_attrs(cx, item.span, item.name, &item.attrs)
        }
        match item.node {
            ItemExternCrate(_) | ItemUse(_, _) => {
                for attr in &item.attrs {
                    if let Some(ref lint_list) = attr.meta_item_list() {
                        match &*attr.name().as_str() {
                            "allow" | "warn" | "deny" | "forbid" => {
                                // whitelist `unused_imports` and `deprecated`
                                for lint in lint_list {
                                    if is_word(lint, "unused_imports") || is_word(lint, "deprecated") {
                                        if let ItemUse(_, _) = item.node {
                                            return;
                                        }
                                    }
                                }
                                let line_span = last_line_of_span(cx, attr.span);

                                if let Some(mut sugg) = snippet_opt(cx, line_span) {
                                    if sugg.contains("#[") {
                                        span_lint_and_then(
                                            cx,
                                            USELESS_ATTRIBUTE,
                                            line_span,
                                            "useless lint attribute",
                                            |db| {
                                                sugg = sugg.replacen("#[", "#![", 1);
                                                db.span_suggestion(line_span, "if you just forgot a `!`, use", sugg);
                                            },
                                        );
                                    }
                                }
                            },
                            _ => {},
                        }
                    }
                }
            },
            _ => {},
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
        if is_relevant_impl(cx.tcx, item) {
            check_attrs(cx, item.span, item.name, &item.attrs)
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
        if is_relevant_trait(cx.tcx, item) {
            check_attrs(cx, item.span, item.name, &item.attrs)
        }
    }
}

fn is_relevant_item(tcx: TyCtxt, item: &Item) -> bool {
    if let ItemFn(_, _, _, eid) = item.node {
        is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value)
    } else {
        true
    }
}

fn is_relevant_impl(tcx: TyCtxt, item: &ImplItem) -> bool {
    match item.node {
        ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value),
        _ => false,
    }
}

fn is_relevant_trait(tcx: TyCtxt, item: &TraitItem) -> bool {
    match item.node {
        TraitItemKind::Method(_, TraitMethod::Required(_)) => true,
        TraitItemKind::Method(_, TraitMethod::Provided(eid)) => {
            is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value)
        },
        _ => false,
    }
}

fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> bool {
    if let Some(stmt) = block.stmts.first() {
        match stmt.node {
            StmtDecl(_, _) => true,
            StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => is_relevant_expr(tcx, tables, expr),
        }
    } else {
        block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e))
    }
}

fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool {
    match expr.node {
        ExprBlock(ref block, _) => is_relevant_block(tcx, tables, block),
        ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e),
        ExprRet(None) | ExprBreak(_, None) => false,
        ExprCall(ref path_expr, _) => if let ExprPath(ref qpath) = path_expr.node {
            if let Some(fun_id) = opt_def_id(tables.qpath_def(qpath, path_expr.hir_id)) {
                !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC)
            } else {
                true
            }
        } else {
            true
        },
        _ => true,
    }
}

fn check_attrs(cx: &LateContext, span: Span, name: Name, attrs: &[Attribute]) {
    if in_macro(span) {
        return;
    }

    for attr in attrs {
        if attr.is_sugared_doc {
            return;
        }
        if attr.style == AttrStyle::Outer {
            if attr.tokens.is_empty() || !is_present_in_source(cx, attr.span) {
                return;
            }

            let begin_of_attr_to_item = Span::new(attr.span.lo(), span.lo(), span.ctxt());
            let end_of_attr_to_item = Span::new(attr.span.hi(), span.lo(), span.ctxt());

            if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) {
                let lines = snippet.split('\n').collect::<Vec<_>>();
                let lines = without_block_comments(lines);

                if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
                    span_lint(
                        cx,
                        EMPTY_LINE_AFTER_OUTER_ATTR,
                        begin_of_attr_to_item,
                        "Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute?"
                    );
                }
            }
        }

        if let Some(ref values) = attr.meta_item_list() {
            if values.len() != 1 || attr.name() != "inline" {
                continue;
            }
            if is_word(&values[0], "always") {
                span_lint(
                    cx,
                    INLINE_ALWAYS,
                    attr.span,
                    &format!(
                        "you have declared `#[inline(always)]` on `{}`. This is usually a bad idea",
                        name
                    ),
                );
            }
        }
    }
}

fn check_semver(cx: &LateContext, span: Span, lit: &Lit) {
    if let LitKind::Str(ref is, _) = lit.node {
        if Version::parse(&is.as_str()).is_ok() {
            return;
        }
    }
    span_lint(
        cx,
        DEPRECATED_SEMVER,
        span,
        "the since field must contain a semver-compliant version",
    );
}

fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool {
    if let NestedMetaItemKind::MetaItem(ref mi) = nmi.node {
        mi.is_word() && mi.name() == expected
    } else {
        false
    }
}

// If the snippet is empty, it's an attribute that was inserted during macro
// expansion and we want to ignore those, because they could come from external
// sources that the user has no control over.
// For some reason these attributes don't have any expansion info on them, so
// we have to check it this way until there is a better way.
fn is_present_in_source(cx: &LateContext, span: Span) -> bool {
    if let Some(snippet) = snippet_opt(cx, span) {
        if snippet.is_empty() {
            return false;
        }
    }
    true
}
<commit_msg>Format the code<commit_after>//! checks for attributes

use crate::reexport::*;
use crate::utils::{
    in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then,
    without_block_comments,
};
use rustc::hir::*;
use rustc::lint::*;
use rustc::ty::{self, TyCtxt};
use semver::Version;
use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
use syntax::codemap::Span;

/// **What it does:** Checks for items annotated with `#[inline(always)]`,
/// unless the annotated function is empty or simply panics.
///
/// **Why is this bad?** While there are valid uses of this annotation (and once
/// you know when to use it, by all means `allow` this lint), it's a common
/// newbie-mistake to pepper one's code with it.
///
/// As a rule of thumb, before slapping `#[inline(always)]` on a function,
/// measure if that additional function call really affects your runtime profile
/// sufficiently to make up for the increase in compile time.
///
/// **Known problems:** False positives, big time. This lint is meant to be
/// deactivated by everyone doing serious performance work. This means having
/// done the measurement.
///
/// **Example:**
/// ```rust
/// #[inline(always)]
/// fn not_quite_hot_code(..) { ... }
/// ```
declare_clippy_lint! {
    pub INLINE_ALWAYS,
    pedantic,
    "use of `#[inline(always)]`"
}

/// **What it does:** Checks for `extern crate` and `use` items annotated with
/// lint attributes
///
/// **Why is this bad?** Lint attributes have no effect on crate imports. Most
/// likely a `!` was
/// forgotten
///
/// **Known problems:** Technically one might allow `unused_import` on a `use`
/// item,
/// but it's easier to remove the unused item.
///
/// **Example:**
/// ```rust
/// #[deny(dead_code)]
/// extern crate foo;
/// #[allow(unused_import)]
/// use foo::bar;
/// ```
declare_clippy_lint! {
    pub USELESS_ATTRIBUTE,
    correctness,
    "use of lint attributes on `extern crate` items"
}

/// **What it does:** Checks for `#[deprecated]` annotations with a `since`
/// field that is not a valid semantic version.
///
/// **Why is this bad?** For checking the version of the deprecation, it must be
/// a valid semver. Failing that, the contained information is useless.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// #[deprecated(since = "forever")]
/// fn something_else(..) { ... }
/// ```
declare_clippy_lint! {
    pub DEPRECATED_SEMVER,
    correctness,
    "use of `#[deprecated(since = \"x\")]` where x is not semver"
}

/// **What it does:** Checks for empty lines after outer attributes
///
/// **Why is this bad?**
/// Most likely the attribute was meant to be an inner attribute using a '!'.
/// If it was meant to be an outer attribute, then the following item
/// should not be separated by empty lines.
///
/// **Known problems:** Can cause false positives.
///
/// From the clippy side it's difficult to detect empty lines between an attributes and the
/// following item because empty lines and comments are not part of the AST. The parsing
/// currently works for basic cases but is not perfect.
///
/// **Example:**
/// ```rust
/// // Bad
/// #[inline(always)]
///
/// fn not_quite_good_code(..) { ... }
///
/// // Good (as inner attribute)
/// #![inline(always)]
///
/// fn this_is_fine(..) { ... }
///
/// // Good (as outer attribute)
/// #[inline(always)]
/// fn this_is_fine_too(..) { ... }
/// ```
declare_clippy_lint! {
    pub EMPTY_LINE_AFTER_OUTER_ATTR,
    nursery,
    "empty line after outer attribute"
}

#[derive(Copy, Clone)]
pub struct AttrPass;

impl LintPass for AttrPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(
            INLINE_ALWAYS,
            DEPRECATED_SEMVER,
            USELESS_ATTRIBUTE,
            EMPTY_LINE_AFTER_OUTER_ATTR
        )
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
    fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) {
        if let Some(ref items) = attr.meta_item_list() {
            if items.is_empty() || attr.name() != "deprecated" {
                return;
            }
            for item in items {
                if_chain! {
                    if let NestedMetaItemKind::MetaItem(ref mi) = item.node;
                    if let MetaItemKind::NameValue(ref lit) = mi.node;
                    if mi.name() == "since";
                    then {
                        check_semver(cx, item.span, lit);
                    }
                }
            }
        }
    }

    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
        if is_relevant_item(cx.tcx, item) {
            check_attrs(cx, item.span, item.name, &item.attrs)
        }
        match item.node {
            ItemExternCrate(_) | ItemUse(_, _) => {
                for attr in &item.attrs {
                    if let Some(ref lint_list) = attr.meta_item_list() {
                        match &*attr.name().as_str() {
                            "allow" | "warn" | "deny" | "forbid" => {
                                // whitelist `unused_imports` and `deprecated`
                                for lint in lint_list {
                                    if is_word(lint, "unused_imports") || is_word(lint, "deprecated") {
                                        if let ItemUse(_, _) = item.node {
                                            return;
                                        }
                                    }
                                }
                                let line_span = last_line_of_span(cx, attr.span);

                                if let Some(mut sugg) = snippet_opt(cx, line_span) {
                                    if sugg.contains("#[") {
                                        span_lint_and_then(
                                            cx,
                                            USELESS_ATTRIBUTE,
                                            line_span,
                                            "useless lint attribute",
                                            |db| {
                                                sugg = sugg.replacen("#[", "#![", 1);
                                                db.span_suggestion(line_span, "if you just forgot a `!`, use", sugg);
                                            },
                                        );
                                    }
                                }
                            },
                            _ => {},
                        }
                    }
                }
            },
            _ => {},
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
        if is_relevant_impl(cx.tcx, item) {
            check_attrs(cx, item.span, item.name, &item.attrs)
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
        if is_relevant_trait(cx.tcx, item) {
            check_attrs(cx, item.span, item.name, &item.attrs)
        }
    }
}

fn is_relevant_item(tcx: TyCtxt, item: &Item) -> bool {
    if let ItemFn(_, _, _, eid) = item.node {
        is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value)
    } else {
        true
    }
}

fn is_relevant_impl(tcx: TyCtxt, item: &ImplItem) -> bool {
    match item.node {
        ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value),
        _ => false,
    }
}

fn is_relevant_trait(tcx: TyCtxt, item: &TraitItem) -> bool {
    match item.node {
        TraitItemKind::Method(_, TraitMethod::Required(_)) => true,
        TraitItemKind::Method(_, TraitMethod::Provided(eid)) => {
            is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value)
        },
        _ => false,
    }
}

fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> bool {
    if let Some(stmt) = block.stmts.first() {
        match stmt.node {
            StmtDecl(_, _) => true,
            StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => is_relevant_expr(tcx, tables, expr),
        }
    } else {
        block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e))
    }
}

fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool {
    match expr.node {
        ExprBlock(ref block, _) => is_relevant_block(tcx, tables, block),
        ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e),
        ExprRet(None) | ExprBreak(_, None) => false,
        ExprCall(ref path_expr, _) => if let ExprPath(ref qpath) = path_expr.node {
            if let Some(fun_id) = opt_def_id(tables.qpath_def(qpath, path_expr.hir_id)) {
                !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC)
            } else {
                true
            }
        } else {
            true
        },
        _ => true,
    }
}

fn check_attrs(cx: &LateContext, span: Span, name: Name, attrs: &[Attribute]) {
    if in_macro(span) {
        return;
    }

    for attr in attrs {
        if attr.is_sugared_doc {
            return;
        }
        if attr.style == AttrStyle::Outer {
            if attr.tokens.is_empty() || !is_present_in_source(cx, attr.span) {
                return;
            }

            let begin_of_attr_to_item = Span::new(attr.span.lo(), span.lo(), span.ctxt());
            let end_of_attr_to_item = Span::new(attr.span.hi(), span.lo(), span.ctxt());

            if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) {
                let lines = snippet.split('\n').collect::<Vec<_>>();
                let lines = without_block_comments(lines);

                if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
                    span_lint(
                        cx,
                        EMPTY_LINE_AFTER_OUTER_ATTR,
                        begin_of_attr_to_item,
                        "Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute?"
                    );
                }
            }
        }

        if let Some(ref values) = attr.meta_item_list() {
            if values.len() != 1 || attr.name() != "inline" {
                continue;
            }
            if is_word(&values[0], "always") {
                span_lint(
                    cx,
                    INLINE_ALWAYS,
                    attr.span,
                    &format!(
                        "you have declared `#[inline(always)]` on `{}`. This is usually a bad idea",
                        name
                    ),
                );
            }
        }
    }
}

fn check_semver(cx: &LateContext, span: Span, lit: &Lit) {
    if let LitKind::Str(ref is, _) = lit.node {
        if Version::parse(&is.as_str()).is_ok() {
            return;
        }
    }
    span_lint(
        cx,
        DEPRECATED_SEMVER,
        span,
        "the since field must contain a semver-compliant version",
    );
}

fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool {
    if let NestedMetaItemKind::MetaItem(ref mi) = nmi.node {
        mi.is_word() && mi.name() == expected
    } else {
        false
    }
}

// If the snippet is empty, it's an attribute that was inserted during macro
// expansion and we want to ignore those, because they could come from external
// sources that the user has no control over.
// For some reason these attributes don't have any expansion info on them, so
// we have to check it this way until there is a better way.
fn is_present_in_source(cx: &LateContext, span: Span) -> bool {
    if let Some(snippet) = snippet_opt(cx, span) {
        if snippet.is_empty() {
            return false;
        }
    }
    true
}
<|endoftext|>


<commit_before>#![feature(start, no_std)]
#![no_std]

extern crate uni;

#[start]
fn main(_: isize, _: *const *const u8) -> isize {
    loop {

    }
}
<commit_msg>examples: Hello now prints Hello World!<commit_after>#![feature(start, no_std)]
#![no_std]

#[macro_use]
extern crate uni;

#[start]
fn main(_: isize, _: *const *const u8) -> isize {
    println!("Hello World");

    0
}
<|endoftext|>


<commit_before>extern crate neli;

use std::error::Error;
use std::net::IpAddr;

use neli::consts::*;
use neli::err::NlError;
use neli::nl::Nlmsghdr;
use neli::rtnl::*;
use neli::socket::*;

fn parse_route_table(rtm: Nlmsghdr<Rtm, Rtmsg<Rta>>) {
    // This sample is only interested in the main table.
    if rtm.nl_payload.rtm_table == RtTable::Main {
        let mut src = None;
        let mut dst = None;
        let mut gateway = None;

        for attr in rtm.nl_payload.rtattrs.iter() {
            fn to_addr(b: &[u8]) -> Option<IpAddr> {
                use std::convert::TryFrom;
                if let Ok(tup) = <&[u8; 4]>::try_from(b) {
                    Some(IpAddr::from(*tup))
                } else if let Ok(tup) = <&[u8; 16]>::try_from(b) {
                    Some(IpAddr::from(*tup))
                } else {
                    None
                }
            }

            match attr.rta_type {
                Rta::Dst => dst = to_addr(&attr.rta_payload),
                Rta::Prefsrc => src = to_addr(&attr.rta_payload),
                Rta::Gateway => gateway = to_addr(&attr.rta_payload),
                _ => (),
            }
        }

        if let Some(dst) = dst {
            print!("{}/{} ", dst, rtm.nl_payload.rtm_dst_len);
        } else {
            print!("default ");
            if let Some(gateway) = gateway {
                print!("via {} ", gateway);
            }
        }

        if rtm.nl_payload.rtm_scope != RtScope::Universe {
            print!(
                " proto {:?}  scope {:?} ",
                rtm.nl_payload.rtm_protocol, rtm.nl_payload.rtm_scope
            )
        }
        if let Some(src) = src {
            print!(" src {} ", src);
        }
        println!();
    }
}

/// This sample is a simple imitation of the `ip route` command, to demonstrate interaction
/// with the rtnetlink subsystem.
fn main() -> Result<(), Box<dyn Error>> {
    let mut socket = NlSocket::connect(NlFamily::Route, None, None, true).unwrap();

    let rtmsg: Rtmsg<Rta> = Rtmsg {
        rtm_family: RtAddrFamily::Inet,
        rtm_dst_len: 0,
        rtm_src_len: 0,
        rtm_tos: 0,
        rtm_table: RtTable::Unspec,
        rtm_protocol: Rtprot::Unspec,
        rtm_scope: RtScope::Universe,
        rtm_type: Rtn::Unspec,
        rtm_flags: vec![],
        rtattrs: Rtattrs::empty(),
    };
    let nlhdr = {
        let len = None;
        let nl_type = Rtm::Getroute;
        let flags = vec![NlmF::Request, NlmF::Dump];
        let seq = None;
        let pid = None;
        let payload = rtmsg;
        Nlmsghdr::new(len, nl_type, flags, seq, pid, payload)
    };
    socket.send_nl(nlhdr).unwrap();

    // Provisionally deserialize as a Nlmsg first.
    let nl = socket.recv_nl::<Rtm, Rtmsg<Rta>>(None)?;
    let multi_msg = nl.nl_flags.contains(&NlmF::Multi);
    parse_route_table(nl);
    if multi_msg {
        while let Ok(nl) = socket.recv_nl::<u16, Rtmsg<Rta>>(None) {
            match Nlmsg::from(nl.nl_type) {
                Nlmsg::Done => return Ok(()),
                Nlmsg::Error => return Err(Box::new(NlError::new("rtnetlink error."))),
                _ => {
                    let rtm = Nlmsghdr {
                        nl_len: nl.nl_len,
                        nl_type: Rtm::from(nl.nl_type),
                        nl_flags: nl.nl_flags,
                        nl_seq: nl.nl_seq,
                        nl_pid: nl.nl_pid,
                        nl_payload: nl.nl_payload,
                    };

                    // Some other message type, so let's try to deserialize as a Rtm.
                    parse_route_table(rtm)
                }
            }
        }
    }
    Ok(())
}
<commit_msg>Fix example program<commit_after>extern crate neli;

use std::error::Error;
use std::net::IpAddr;

use neli::consts::*;
use neli::err::NlError;
use neli::nl::Nlmsghdr;
use neli::rtnl::*;
use neli::socket::*;

fn parse_route_table(rtm: Nlmsghdr<Rtm, Rtmsg>) {
    // This sample is only interested in the main table.
    if rtm.nl_payload.rtm_table == RtTable::Main {
        let mut src = None;
        let mut dst = None;
        let mut gateway = None;

        for attr in rtm.nl_payload.rtattrs.iter() {
            fn to_addr(b: &[u8]) -> Option<IpAddr> {
                use std::convert::TryFrom;
                if let Ok(tup) = <&[u8; 4]>::try_from(b) {
                    Some(IpAddr::from(*tup))
                } else if let Ok(tup) = <&[u8; 16]>::try_from(b) {
                    Some(IpAddr::from(*tup))
                } else {
                    None
                }
            }

            match attr.rta_type {
                Rta::Dst => dst = to_addr(&attr.rta_payload),
                Rta::Prefsrc => src = to_addr(&attr.rta_payload),
                Rta::Gateway => gateway = to_addr(&attr.rta_payload),
                _ => (),
            }
        }

        if let Some(dst) = dst {
            print!("{}/{} ", dst, rtm.nl_payload.rtm_dst_len);
        } else {
            print!("default ");
            if let Some(gateway) = gateway {
                print!("via {} ", gateway);
            }
        }

        if rtm.nl_payload.rtm_scope != RtScope::Universe {
            print!(
                " proto {:?}  scope {:?} ",
                rtm.nl_payload.rtm_protocol, rtm.nl_payload.rtm_scope
            )
        }
        if let Some(src) = src {
            print!(" src {} ", src);
        }
        println!();
    }
}

/// This sample is a simple imitation of the `ip route` command, to demonstrate interaction
/// with the rtnetlink subsystem.
fn main() -> Result<(), Box<dyn Error>> {
    let mut socket = NlSocket::connect(NlFamily::Route, None, None, true).unwrap();

    let rtmsg = Rtmsg {
        rtm_family: RtAddrFamily::Inet,
        rtm_dst_len: 0,
        rtm_src_len: 0,
        rtm_tos: 0,
        rtm_table: RtTable::Unspec,
        rtm_protocol: Rtprot::Unspec,
        rtm_scope: RtScope::Universe,
        rtm_type: Rtn::Unspec,
        rtm_flags: vec![],
        rtattrs: Rtattrs::empty(),
    };
    let nlhdr = {
        let len = None;
        let nl_type = Rtm::Getroute;
        let flags = vec![NlmF::Request, NlmF::Dump];
        let seq = None;
        let pid = None;
        let payload = rtmsg;
        Nlmsghdr::new(len, nl_type, flags, seq, pid, payload)
    };
    socket.send_nl(nlhdr).unwrap();

    // Provisionally deserialize as a Nlmsg first.
    let nl = socket.recv_nl::<Rtm, Rtmsg>(None)?;
    let multi_msg = nl.nl_flags.contains(&NlmF::Multi);
    parse_route_table(nl);
    if multi_msg {
        while let Ok(nl) = socket.recv_nl::<u16, Rtmsg>(None) {
            match Nlmsg::from(nl.nl_type) {
                Nlmsg::Done => return Ok(()),
                Nlmsg::Error => return Err(Box::new(NlError::new("rtnetlink error."))),
                _ => {
                    let rtm = Nlmsghdr {
                        nl_len: nl.nl_len,
                        nl_type: Rtm::from(nl.nl_type),
                        nl_flags: nl.nl_flags,
                        nl_seq: nl.nl_seq,
                        nl_pid: nl.nl_pid,
                        nl_payload: nl.nl_payload,
                    };

                    // Some other message type, so let's try to deserialize as a Rtm.
                    parse_route_table(rtm)
                }
            }
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use rustc_index::vec::Idx;

pub mod dominators;
pub mod implementation;
pub mod iterate;
mod reference;
pub mod scc;
pub mod vec_graph;

#[cfg(test)]
mod tests;

pub trait DirectedGraph {
    type Node: Idx;
}

pub trait WithNumNodes: DirectedGraph {
    fn num_nodes(&self) -> usize;
}

pub trait WithNumEdges: DirectedGraph {
    fn num_edges(&self) -> usize;
}

pub trait WithSuccessors: DirectedGraph
where
    Self: for<'graph> GraphSuccessors<'graph, Item = <Self as DirectedGraph>::Node>,
{
    fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter;

    fn depth_first_search(&self, from: Self::Node) -> iterate::DepthFirstSearch<'_, Self>
    where
        Self: WithNumNodes,
    {
        iterate::DepthFirstSearch::new(self, from)
    }
}

#[allow(unused_lifetimes)]
pub trait GraphSuccessors<'graph> {
    type Item;
    type Iter: Iterator<Item = Self::Item>;
}

pub trait WithPredecessors: DirectedGraph
where
    Self: for<'graph> GraphPredecessors<'graph, Item = <Self as DirectedGraph>::Node>,
{
    fn predecessors(&self, node: Self::Node) -> <Self as GraphPredecessors<'_>>::Iter;
}

#[allow(unused_lifetimes)]
pub trait GraphPredecessors<'graph> {
    type Item;
    type Iter: Iterator<Item = Self::Item>;
}

pub trait WithStartNode: DirectedGraph {
    fn start_node(&self) -> Self::Node;
}

pub trait ControlFlowGraph:
    DirectedGraph + WithStartNode + WithPredecessors + WithStartNode + WithSuccessors + WithNumNodes
{
    // convenient trait
}

impl<T> ControlFlowGraph for T where
    T: DirectedGraph
        + WithStartNode
        + WithPredecessors
        + WithStartNode
        + WithSuccessors
        + WithNumNodes
{
}

/// Returns `true` if the graph has a cycle that is reachable from the start node.
pub fn is_cyclic<G>(graph: &G) -> bool
where
    G: ?Sized + DirectedGraph + WithStartNode + WithSuccessors + WithNumNodes,
{
    iterate::TriColorDepthFirstSearch::new(graph)
        .run_from_start(&mut iterate::CycleDetector)
        .is_some()
}
<commit_msg>Rollup merge of #87880 - pierwill:graph-duplicate-trait-bound, r=LeSeulArtichaut<commit_after>use rustc_index::vec::Idx;

pub mod dominators;
pub mod implementation;
pub mod iterate;
mod reference;
pub mod scc;
pub mod vec_graph;

#[cfg(test)]
mod tests;

pub trait DirectedGraph {
    type Node: Idx;
}

pub trait WithNumNodes: DirectedGraph {
    fn num_nodes(&self) -> usize;
}

pub trait WithNumEdges: DirectedGraph {
    fn num_edges(&self) -> usize;
}

pub trait WithSuccessors: DirectedGraph
where
    Self: for<'graph> GraphSuccessors<'graph, Item = <Self as DirectedGraph>::Node>,
{
    fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter;

    fn depth_first_search(&self, from: Self::Node) -> iterate::DepthFirstSearch<'_, Self>
    where
        Self: WithNumNodes,
    {
        iterate::DepthFirstSearch::new(self, from)
    }
}

#[allow(unused_lifetimes)]
pub trait GraphSuccessors<'graph> {
    type Item;
    type Iter: Iterator<Item = Self::Item>;
}

pub trait WithPredecessors: DirectedGraph
where
    Self: for<'graph> GraphPredecessors<'graph, Item = <Self as DirectedGraph>::Node>,
{
    fn predecessors(&self, node: Self::Node) -> <Self as GraphPredecessors<'_>>::Iter;
}

#[allow(unused_lifetimes)]
pub trait GraphPredecessors<'graph> {
    type Item;
    type Iter: Iterator<Item = Self::Item>;
}

pub trait WithStartNode: DirectedGraph {
    fn start_node(&self) -> Self::Node;
}

pub trait ControlFlowGraph:
    DirectedGraph + WithStartNode + WithPredecessors + WithSuccessors + WithNumNodes
{
    // convenient trait
}

impl<T> ControlFlowGraph for T where
    T: DirectedGraph + WithStartNode + WithPredecessors + WithSuccessors + WithNumNodes
{
}

/// Returns `true` if the graph has a cycle that is reachable from the start node.
pub fn is_cyclic<G>(graph: &G) -> bool
where
    G: ?Sized + DirectedGraph + WithStartNode + WithSuccessors + WithNumNodes,
{
    iterate::TriColorDepthFirstSearch::new(graph)
        .run_from_start(&mut iterate::CycleDetector)
        .is_some()
}
<|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/. */

//! CSS handling for the computed value of
//! [`basic-shape`][basic-shape]s
//!
//! [basic-shape]: https://drafts.csswg.org/css-shapes/#typedef-basic-shape

use std::fmt;
use style_traits::ToCss;
use values::computed::LengthOrPercentage;
use values::generics::basic_shape::{BasicShape as GenericBasicShape};
use values::generics::basic_shape::{Circle as GenericCircle, ClippingShape as GenericClippingShape};
use values::generics::basic_shape::{Ellipse as GenericEllipse, FloatAreaShape as GenericFloatAreaShape};
use values::generics::basic_shape::{InsetRect as GenericInsetRect, ShapeRadius as GenericShapeRadius};

/// A specified clipping shape.
pub type ClippingShape = GenericClippingShape<BasicShape>;

/// A specified float area shape.
pub type FloatAreaShape = GenericFloatAreaShape<BasicShape>;

/// A computed basic shape.
pub type BasicShape = GenericBasicShape<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

/// The computed value of `inset()`
pub type InsetRect = GenericInsetRect<LengthOrPercentage>;

/// A computed circle.
pub type Circle = GenericCircle<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

/// A computed ellipse.
pub type Ellipse = GenericEllipse<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

/// The computed value of `ShapeRadius`
pub type ShapeRadius = GenericShapeRadius<LengthOrPercentage>;

impl ToCss for Circle {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str("circle(")?;
        self.radius.to_css(dest)?;
        dest.write_str(" at ")?;
        self.position.to_css(dest)
    }
}

impl ToCss for Ellipse {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str("ellipse(")?;
        if (self.semiaxis_x, self.semiaxis_y) != Default::default() {
            self.semiaxis_x.to_css(dest)?;
            dest.write_str(" ")?;
            self.semiaxis_y.to_css(dest)?;
            dest.write_str(" ")?;
        }
        dest.write_str("at ")?;
        self.position.to_css(dest)?;
        dest.write_str(")")
    }
}
<commit_msg>Fix serialisation of computed circle() shapes<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/. */

//! CSS handling for the computed value of
//! [`basic-shape`][basic-shape]s
//!
//! [basic-shape]: https://drafts.csswg.org/css-shapes/#typedef-basic-shape

use std::fmt;
use style_traits::ToCss;
use values::computed::LengthOrPercentage;
use values::generics::basic_shape::{BasicShape as GenericBasicShape};
use values::generics::basic_shape::{Circle as GenericCircle, ClippingShape as GenericClippingShape};
use values::generics::basic_shape::{Ellipse as GenericEllipse, FloatAreaShape as GenericFloatAreaShape};
use values::generics::basic_shape::{InsetRect as GenericInsetRect, ShapeRadius as GenericShapeRadius};

/// A specified clipping shape.
pub type ClippingShape = GenericClippingShape<BasicShape>;

/// A specified float area shape.
pub type FloatAreaShape = GenericFloatAreaShape<BasicShape>;

/// A computed basic shape.
pub type BasicShape = GenericBasicShape<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

/// The computed value of `inset()`
pub type InsetRect = GenericInsetRect<LengthOrPercentage>;

/// A computed circle.
pub type Circle = GenericCircle<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

/// A computed ellipse.
pub type Ellipse = GenericEllipse<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

/// The computed value of `ShapeRadius`
pub type ShapeRadius = GenericShapeRadius<LengthOrPercentage>;

impl ToCss for Circle {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str("circle(")?;
        self.radius.to_css(dest)?;
        dest.write_str(" at ")?;
        self.position.to_css(dest)?;
        dest.write_str(")")
    }
}

impl ToCss for Ellipse {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str("ellipse(")?;
        if (self.semiaxis_x, self.semiaxis_y) != Default::default() {
            self.semiaxis_x.to_css(dest)?;
            dest.write_str(" ")?;
            self.semiaxis_y.to_css(dest)?;
            dest.write_str(" ")?;
        }
        dest.write_str("at ")?;
        self.position.to_css(dest)?;
        dest.write_str(")")
    }
}
<|endoftext|>


<commit_before>use color::PuyoColor;
use field;
use field_bit::FieldBit;
use plain_field::PuyoPlainField;
use simd;
use simdext::*;
use std::mem;

#[derive(Clone, Copy)]
pub struct BitField {
    m: [FieldBit; 3],
}

impl BitField {
    pub fn new() -> BitField {
        BitField {
            m: [FieldBit::new_empty(),
                FieldBit::from_values(0xFFFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0xFFFF),
                FieldBit::new_empty(), ]
        }
    }

    pub fn from_plain_field(pf: PuyoPlainField) -> BitField {
        let mut bf = BitField::new();

        // TODO(mayah): We have better algorithm here.
        for x in 0 .. field::MAP_WIDTH {
            for y in 0 .. field::MAP_HEIGHT {
                bf.set_color(x, y, pf.color(x, y))
            }
        }

        bf
    }

    pub fn from_str(s: &str) -> BitField {
        BitField::from_plain_field(PuyoPlainField::from_str(s))
    }

    pub fn color(&self, x: usize, y: usize) -> PuyoColor {
        let b0: u8 = if self.m[0].get(x, y) { 1 } else { 0 };
        let b1: u8 = if self.m[1].get(x, y) { 2 } else { 0 };
        let b2: u8 = if self.m[2].get(x, y) { 4 } else { 0 };

        unsafe {
            mem::transmute(b0 | b1 | b2)
        }
    }

    pub fn is_color(&self, x: usize, y: usize, c: PuyoColor) -> bool {
        self.bits(c).get(x, y)
    }

    pub fn is_normal_color(&self, x: usize, y: usize) -> bool {
        self.m[2].get(x, y)
    }

    pub fn set_color(&mut self, x: usize, y: usize, c: PuyoColor) {
        let cc = c as u8;
        for i in 0 .. 3 {
            if (cc & (1 << i)) != 0 {
                self.m[i as usize].set(x, y);
            } else {
                self.m[i as usize].unset(x, y);
            }
        }
    }

    pub fn bits(&self, c: PuyoColor) -> FieldBit {
        let v = match c {
            PuyoColor::EMPTY => {  // 0
                (self.r(0) | self.r(1) | self.r(2)) ^ simd::u16x8::splat(0xFFFF)
            },
            PuyoColor::OJAMA => {  // 1
                mm_andnot_si128(self.r(2), mm_andnot_si128(self.r(1), self.r(0)))
            },
            PuyoColor::WALL => {   // 2
                mm_andnot_si128(self.r(2), mm_andnot_si128(self.r(0), self.r(1)))
            },
            PuyoColor::IRON => {   // 3
                mm_andnot_si128(self.r(2), mm_and_si128(self.r(0), self.r(1)))
            },
            PuyoColor::RED => {    // 4
                mm_andnot_si128(self.r(0), mm_andnot_si128(self.r(1), self.r(2)))
            },
            PuyoColor::BLUE => {   // 5
                mm_and_si128(self.r(0), mm_andnot_si128(self.r(1), self.r(2)))
            },
            PuyoColor::YELLOW => { // 6
                mm_andnot_si128(self.r(0), mm_and_si128(self.r(1), self.r(2)))
            },
            PuyoColor::GREEN => {  // 7
                mm_and_si128(self.r(0), mm_and_si128(self.r(1), self.r(2)))
            },
        };

        FieldBit::new(v)
    }

    fn r(&self, i: usize) -> simd::u16x8 {
        self.m[i].as_u16x8()
    }
}

#[cfg(test)]
mod tests {
    use super::BitField;
    use color;
    use color::PuyoColor;
    use field;

    #[test]
    fn test_initial() {
        let bf = BitField::new();
        for x in 0 .. 8 {
            for y in 0 .. 16 {
                if x == 0 || x == 7 || y == 0 || y == 15 {
                    assert_eq!(bf.color(x, y), PuyoColor::WALL);
                } else {
                    assert_eq!(bf.color(x, y), PuyoColor::EMPTY);
                }
            }
        }
    }

    #[test]
    fn test_from_str() {
        let bf = BitField::from_str(concat!(
            "RGBRGB",
            "RGBRGB",
            "RGBRGB"));

        assert_eq!(bf.color(1, 1), PuyoColor::RED);
        assert_eq!(bf.color(2, 1), PuyoColor::GREEN);
        assert_eq!(bf.color(3, 1), PuyoColor::BLUE);
        assert_eq!(bf.color(1, 3), PuyoColor::RED);
        assert_eq!(bf.color(2, 3), PuyoColor::GREEN);
        assert_eq!(bf.color(3, 3), PuyoColor::BLUE);
    }

    #[test]
    fn test_set_color() {
        let colors = [
            PuyoColor::EMPTY, PuyoColor::OJAMA, PuyoColor::WALL, PuyoColor::IRON,
            PuyoColor::RED, PuyoColor::BLUE, PuyoColor::YELLOW, PuyoColor::GREEN,
        ];
        let mut bf = BitField::new();

        for c in colors.iter() {
            bf.set_color(1, 1, *c);
            assert_eq!(*c, bf.color(1, 1));
        }
    }

    #[test]
    fn test_each_cell() {
        let bf = BitField::from_str(concat!(
            "&&&&&&",
            "OOOOOO",
            "YYYYYY",
            "BBBBBB",
            "GGGGGG",
            "RRRRRR"));

        for x in 0 .. field::MAP_WIDTH {
            for y in 0 .. field::MAP_HEIGHT {
                for c in color::color::ALL_PUYO_COLORS.iter() {
                    assert_eq!(bf.bits(*c).get(x, y), *c == bf.color(x, y));
                    assert_eq!(bf.is_color(x, y, *c), bf.is_color(x, y, *c));
                }

                assert_eq!(bf.is_normal_color(x, y), bf.is_normal_color(x, y));
            }
        }
    }
}
<commit_msg>Add BitField::count_connected_puyos().<commit_after>use color::PuyoColor;
use field;
use field_bit::FieldBit;
use plain_field::PuyoPlainField;
use simd;
use simdext::*;
use std::mem;

#[derive(Clone, Copy)]
pub struct BitField {
    m: [FieldBit; 3],
}

impl BitField {
    pub fn new() -> BitField {
        BitField {
            m: [FieldBit::new_empty(),
                FieldBit::from_values(0xFFFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0xFFFF),
                FieldBit::new_empty(), ]
        }
    }

    pub fn from_plain_field(pf: PuyoPlainField) -> BitField {
        let mut bf = BitField::new();

        // TODO(mayah): We have better algorithm here.
        for x in 0 .. field::MAP_WIDTH {
            for y in 0 .. field::MAP_HEIGHT {
                bf.set_color(x, y, pf.color(x, y))
            }
        }

        bf
    }

    pub fn from_str(s: &str) -> BitField {
        BitField::from_plain_field(PuyoPlainField::from_str(s))
    }

    pub fn color(&self, x: usize, y: usize) -> PuyoColor {
        let b0: u8 = if self.m[0].get(x, y) { 1 } else { 0 };
        let b1: u8 = if self.m[1].get(x, y) { 2 } else { 0 };
        let b2: u8 = if self.m[2].get(x, y) { 4 } else { 0 };

        unsafe {
            mem::transmute(b0 | b1 | b2)
        }
    }

    pub fn is_color(&self, x: usize, y: usize, c: PuyoColor) -> bool {
        self.bits(c).get(x, y)
    }

    pub fn is_normal_color(&self, x: usize, y: usize) -> bool {
        self.m[2].get(x, y)
    }

    pub fn set_color(&mut self, x: usize, y: usize, c: PuyoColor) {
        let cc = c as u8;
        for i in 0 .. 3 {
            if (cc & (1 << i)) != 0 {
                self.m[i as usize].set(x, y);
            } else {
                self.m[i as usize].unset(x, y);
            }
        }
    }

    pub fn count_connected_puyos(&self, x: usize, y: usize) -> usize {
        if y > field::HEIGHT {
            return 0
        }

        let c = self.color(x, y);
        let color_bits = self.bits(c).masked_field_12();
        FieldBit::from_onebit(x, y).expand(&color_bits).popcount()
    }

    pub fn bits(&self, c: PuyoColor) -> FieldBit {
        let v = match c {
            PuyoColor::EMPTY => {  // 0
                (self.r(0) | self.r(1) | self.r(2)) ^ simd::u16x8::splat(0xFFFF)
            },
            PuyoColor::OJAMA => {  // 1
                mm_andnot_si128(self.r(2), mm_andnot_si128(self.r(1), self.r(0)))
            },
            PuyoColor::WALL => {   // 2
                mm_andnot_si128(self.r(2), mm_andnot_si128(self.r(0), self.r(1)))
            },
            PuyoColor::IRON => {   // 3
                mm_andnot_si128(self.r(2), mm_and_si128(self.r(0), self.r(1)))
            },
            PuyoColor::RED => {    // 4
                mm_andnot_si128(self.r(0), mm_andnot_si128(self.r(1), self.r(2)))
            },
            PuyoColor::BLUE => {   // 5
                mm_and_si128(self.r(0), mm_andnot_si128(self.r(1), self.r(2)))
            },
            PuyoColor::YELLOW => { // 6
                mm_andnot_si128(self.r(0), mm_and_si128(self.r(1), self.r(2)))
            },
            PuyoColor::GREEN => {  // 7
                mm_and_si128(self.r(0), mm_and_si128(self.r(1), self.r(2)))
            },
        };

        FieldBit::new(v)
    }

    fn r(&self, i: usize) -> simd::u16x8 {
        self.m[i].as_u16x8()
    }
}

#[cfg(test)]
mod tests {
    use super::BitField;
    use color;
    use color::PuyoColor;
    use field;

    #[test]
    fn test_initial() {
        let bf = BitField::new();
        for x in 0 .. 8 {
            for y in 0 .. 16 {
                if x == 0 || x == 7 || y == 0 || y == 15 {
                    assert_eq!(bf.color(x, y), PuyoColor::WALL);
                } else {
                    assert_eq!(bf.color(x, y), PuyoColor::EMPTY);
                }
            }
        }
    }

    #[test]
    fn test_from_str() {
        let bf = BitField::from_str(concat!(
            "RGBRGB",
            "RGBRGB",
            "RGBRGB"));

        assert_eq!(bf.color(1, 1), PuyoColor::RED);
        assert_eq!(bf.color(2, 1), PuyoColor::GREEN);
        assert_eq!(bf.color(3, 1), PuyoColor::BLUE);
        assert_eq!(bf.color(1, 3), PuyoColor::RED);
        assert_eq!(bf.color(2, 3), PuyoColor::GREEN);
        assert_eq!(bf.color(3, 3), PuyoColor::BLUE);
    }

    #[test]
    fn test_set_color() {
        let colors = [
            PuyoColor::EMPTY, PuyoColor::OJAMA, PuyoColor::WALL, PuyoColor::IRON,
            PuyoColor::RED, PuyoColor::BLUE, PuyoColor::YELLOW, PuyoColor::GREEN,
        ];
        let mut bf = BitField::new();

        for c in colors.iter() {
            bf.set_color(1, 1, *c);
            assert_eq!(*c, bf.color(1, 1));
        }
    }

    #[test]
    fn test_each_cell() {
        let bf = BitField::from_str(concat!(
            "&&&&&&",
            "OOOOOO",
            "YYYYYY",
            "BBBBBB",
            "GGGGGG",
            "RRRRRR"));

        for x in 0 .. field::MAP_WIDTH {
            for y in 0 .. field::MAP_HEIGHT {
                for c in color::color::ALL_PUYO_COLORS.iter() {
                    assert_eq!(bf.bits(*c).get(x, y), *c == bf.color(x, y));
                    assert_eq!(bf.is_color(x, y, *c), bf.is_color(x, y, *c));
                }

                assert_eq!(bf.is_normal_color(x, y), bf.is_normal_color(x, y));
            }
        }
    }

    #[test]
    fn test_count_connected_puyos() {
        let bf = BitField::from_str(concat!(
            "RRRRRR",
            "BYBRRY",
            "RRRBBB"));

        assert_eq!(bf.count_connected_puyos(1, 1), 3);
        assert_eq!(bf.count_connected_puyos(4, 1), 3);
        assert_eq!(bf.count_connected_puyos(1, 2), 1);
        assert_eq!(bf.count_connected_puyos(3, 2), 1);
        assert_eq!(bf.count_connected_puyos(6, 2), 1);
        assert_eq!(bf.count_connected_puyos(4, 2), 8);
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]

#[warn(str_to_string)]
//~^WARNING: warning: lint str_to_string has been removed: using `str::to_string`
#[warn(string_to_string)]
//~^WARNING: warning: lint string_to_string has been removed: using `string::to_string`
#[warn(unstable_as_slice)]
//~^WARNING: warning: lint unstable_as_slice has been removed: `Vec::as_slice` has been stabilized
#[warn(unstable_as_mut_slice)]
//~^WARNING: warning: lint unstable_as_mut_slice has been removed: `Vec::as_mut_slice` has been stabilized
fn main() {}
<commit_msg>Remove redundant labels in tests<commit_after>#![feature(plugin)]
#![plugin(clippy)]

#[warn(str_to_string)]
//~^WARNING: lint str_to_string has been removed: using `str::to_string`
#[warn(string_to_string)]
//~^WARNING: lint string_to_string has been removed: using `string::to_string`
#[warn(unstable_as_slice)]
//~^WARNING: lint unstable_as_slice has been removed: `Vec::as_slice` has been stabilized
#[warn(unstable_as_mut_slice)]
//~^WARNING: lint unstable_as_mut_slice has been removed: `Vec::as_mut_slice` has been stabilized
fn main() {}
<|endoftext|>