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

use std::collections::HashMap;
use webrender_traits::{FontKey, FontRenderMode, GlyphDimensions};
use webrender_traits::{GlyphKey, GlyphOptions};
use gamma_lut::{GammaLut, Color as ColorLut};

use dwrote;

lazy_static! {
    static ref DEFAULT_FONT_DESCRIPTOR: dwrote::FontDescriptor = dwrote::FontDescriptor {
        family_name: "Arial".to_owned(),
        weight: dwrote::FontWeight::Regular,
        stretch: dwrote::FontStretch::Normal,
        style: dwrote::FontStyle::Normal,
    };
}

pub struct FontContext {
    fonts: HashMap<FontKey, dwrote::FontFace>,
    gamma_lut: GammaLut,
    gdi_gamma_lut: GammaLut,
}

pub struct RasterizedGlyph {
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

fn dwrite_texture_type(render_mode: FontRenderMode) ->
                       dwrote::DWRITE_TEXTURE_TYPE {
    match render_mode {
        FontRenderMode::Mono => dwrote::DWRITE_TEXTURE_ALIASED_1x1 ,
        FontRenderMode::Alpha |
        FontRenderMode::Subpixel => dwrote::DWRITE_TEXTURE_CLEARTYPE_3x1,
    }
}

fn dwrite_measure_mode(render_mode: FontRenderMode, options: Option<GlyphOptions>) ->
                       dwrote::DWRITE_MEASURING_MODE {
    if let Some(GlyphOptions{ force_gdi_rendering: true, .. }) = options {
        return dwrote::DWRITE_MEASURING_MODE_GDI_CLASSIC;
    }

    match render_mode {
        FontRenderMode::Mono => dwrote::DWRITE_MEASURING_MODE_GDI_NATURAL,
        FontRenderMode::Alpha |
        FontRenderMode::Subpixel => dwrote::DWRITE_MEASURING_MODE_NATURAL,
    }
}

fn dwrite_render_mode(font_face: &dwrote::FontFace,
                      render_mode: FontRenderMode,
                      em_size: f32,
                      measure_mode: dwrote::DWRITE_MEASURING_MODE,
                      options: Option<GlyphOptions>) ->
                      dwrote::DWRITE_RENDERING_MODE {
    if let Some(GlyphOptions{ force_gdi_rendering: true, .. }) = options {
        return dwrote::DWRITE_RENDERING_MODE_GDI_CLASSIC;
    }

    let dwrite_render_mode = match render_mode {
        FontRenderMode::Mono => dwrote::DWRITE_RENDERING_MODE_ALIASED,
        FontRenderMode::Alpha |
        FontRenderMode::Subpixel => {
            font_face.get_recommended_rendering_mode_default_params(em_size,
                                                                    1.0,
                                                                    measure_mode)
        },
    };

    if dwrite_render_mode  == dwrote::DWRITE_RENDERING_MODE_OUTLINE {
        // Outline mode is not supported
        return dwrote::DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
    }

    dwrite_render_mode
}

fn get_glyph_dimensions_with_analysis(analysis: dwrote::GlyphRunAnalysis,
                                      texture_type: dwrote::DWRITE_TEXTURE_TYPE)
                                      -> Option<GlyphDimensions> {
    let bounds = analysis.get_alpha_texture_bounds(texture_type);

    let width = (bounds.right - bounds.left) as u32;
    let height = (bounds.bottom - bounds.top) as u32;

    // Alpha texture bounds can sometimes return an empty rect
    // Such as for spaces
    if width == 0 || height == 0 {
        return None
    }

    Some(GlyphDimensions {
        left: bounds.left,
        top: -bounds.top,
        width: width,
        height: height,
    })
}

impl FontContext {
    pub fn new() -> FontContext {
        // These are the default values we use in Gecko.
        // We use a gamma value of 2.3 for gdi fonts
        // TODO: Fetch this data from Gecko itself.
        let contrast = 1.0;
        let gamma = 1.8;
        let gdi_gamma = 2.3;
        FontContext {
            fonts: HashMap::new(),
            gamma_lut: GammaLut::new(contrast, gamma, gamma),
            gdi_gamma_lut: GammaLut::new(contrast, gdi_gamma, gdi_gamma),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, data: &[u8]) {
        if self.fonts.contains_key(font_key) {
            return
        }

        if let Some(font_file) = dwrote::FontFile::new_from_data(data) {
            let face = font_file.create_face(0, dwrote::DWRITE_FONT_SIMULATIONS_NONE);
            self.fonts.insert((*font_key).clone(), face);
        } else {
            // XXX add_raw_font needs to have a way to return an error
            debug!("DWrite WR failed to load font from data, using Arial instead");
            self.add_native_font(font_key, DEFAULT_FONT_DESCRIPTOR.clone());
        }
    }

    pub fn add_native_font(&mut self, font_key: &FontKey, font_handle: dwrote::FontDescriptor) {
        if self.fonts.contains_key(font_key) {
            return
        }

        let system_fc = dwrote::FontCollection::system();
        let font = system_fc.get_font_from_descriptor(&font_handle).unwrap();
        let face = font.create_font_face();
        self.fonts.insert((*font_key).clone(), face);
    }

    // Assumes RGB format from dwrite, which is 3 bytes per pixel as dwrite
    // doesn't output an alpha value via GlyphRunAnalysis::CreateAlphaTexture
    #[allow(dead_code)]
    fn print_glyph_data(&self, data: &Vec<u8>, width: usize, height: usize) {
        // Rust doesn't have step_by support on stable :(
        for i in 0..height {
            let current_height = i * width * 3;

            for pixel in data[current_height .. current_height + (width * 3)].chunks(3) {
                let r = pixel[0];
                let g = pixel[1];
                let b = pixel[2];
                print!("({}, {}, {}) ", r, g, b, );
            }
            println!("");
        }
    }

    fn create_glyph_analysis(&self, key: &GlyphKey,
                            render_mode: FontRenderMode,
                            options: Option<GlyphOptions>) ->
                            dwrote::GlyphRunAnalysis {
        let face = self.fonts.get(&key.font_key).unwrap();
        let glyph = key.index as u16;
        let advance = 0.0f32;
        let offset = dwrote::GlyphOffset { advanceOffset: 0.0, ascenderOffset: 0.0 };

        let glyph_run = dwrote::DWRITE_GLYPH_RUN {
            fontFace: unsafe { face.as_ptr() },
            fontEmSize: key.size.to_f32_px(), // size in DIPs (1/96", same as CSS pixels)
            glyphCount: 1,
            glyphIndices: &glyph,
            glyphAdvances: &advance,
            glyphOffsets: &offset,
            isSideways: 0,
            bidiLevel: 0,
        };

        let dwrite_measure_mode = dwrite_measure_mode(render_mode, options);
        let dwrite_render_mode = dwrite_render_mode(face,
                                                    render_mode,
                                                    key.size.to_f32_px(),
                                                    dwrite_measure_mode,
                                                    options);

        let (x_offset, y_offset) = key.subpixel_point.to_f64();
        let transform = Some(
                        dwrote::DWRITE_MATRIX { m11: 1.0, m12: 0.0, m21: 0.0, m22: 1.0,
                                                dx: x_offset as f32, dy: y_offset as f32 }
                        );

        dwrote::GlyphRunAnalysis::create(&glyph_run, 1.0, transform,
                                         dwrite_render_mode,
                                         dwrite_measure_mode,
                                         0.0, 0.0)
    }

    // TODO: Pipe GlyphOptions into glyph_dimensions too
    pub fn get_glyph_dimensions(&self,
                                key: &GlyphKey)
                                -> Option<GlyphDimensions> {
        // Probably have to default to something else here.
        let render_mode = FontRenderMode::Subpixel;
        let analysis = self.create_glyph_analysis(key, render_mode, None);

        let texture_type = dwrite_texture_type(render_mode);
        get_glyph_dimensions_with_analysis(analysis, texture_type)
    }

    // DWRITE gives us values in RGB. WR doesn't really touch it after. Note, CG returns in BGR
    // TODO: Decide whether all fonts should return RGB or BGR
    fn convert_to_rgba(&self, pixels: &Vec<u8>, render_mode: FontRenderMode) -> Vec<u8> {
        match render_mode {
            FontRenderMode::Mono => {
                let mut rgba_pixels: Vec<u8> = vec![0; pixels.len() * 4];
                for i in 0..pixels.len() {
                    rgba_pixels[i*4+0] = pixels[i];
                    rgba_pixels[i*4+1] = pixels[i];
                    rgba_pixels[i*4+2] = pixels[i];
                    rgba_pixels[i*4+3] = pixels[i];
                }
                rgba_pixels
            }
            FontRenderMode::Alpha => {
                let length = pixels.len() / 3;
                let mut rgba_pixels: Vec<u8> = vec![0; length * 4];
                for i in 0..length {
                    // TODO(vlad): we likely need to do something smarter
                    // This is what skia does
                    let alpha = ((pixels[i*3+0] as u32 +
                                pixels[i*3+1] as u32 +
                                pixels[i*3+2] as u32)
                                / 3) as u8;

                    rgba_pixels[i*4+0] = alpha;
                    rgba_pixels[i*4+1] = alpha;
                    rgba_pixels[i*4+2] = alpha;
                    rgba_pixels[i*4+3] = alpha;
                }
                rgba_pixels
            }
            FontRenderMode::Subpixel => {
                let length = pixels.len() / 3;
                let mut rgba_pixels: Vec<u8> = vec![0; length * 4];
                for i in 0..length {
                    rgba_pixels[i*4+0] = pixels[i*3+0];
                    rgba_pixels[i*4+1] = pixels[i*3+1];
                    rgba_pixels[i*4+2] = pixels[i*3+2];
                    rgba_pixels[i*4+3] = 0xff;
                }
                rgba_pixels
            }
        }
    }

    pub fn rasterize_glyph(&mut self,
                           key: &GlyphKey,
                           render_mode: FontRenderMode,
                           glyph_options: Option<GlyphOptions>)
                           -> Option<RasterizedGlyph> {
        let analysis = self.create_glyph_analysis(key,
                                                  render_mode,
                                                  glyph_options);
        let texture_type = dwrite_texture_type(render_mode);

        let bounds = analysis.get_alpha_texture_bounds(texture_type);
        let width = (bounds.right - bounds.left) as usize;
        let height = (bounds.bottom - bounds.top) as usize;

        // We should not get here since glyph_dimensions would return
        // None for empty glyphs.
        assert!(width > 0 && height > 0);

        let mut pixels = analysis.create_alpha_texture(texture_type, bounds);

        let lut_correction = match glyph_options {
            Some(option) => {
                if option.force_gdi_rendering {
                    &self.gdi_gamma_lut
                } else {
                    &self.gamma_lut
                }
            },
            None => &self.gamma_lut
        };

        lut_correction.preblend_rgb(&mut pixels, width, height,
                                    ColorLut::new(key.color.r,
                                                  key.color.g,
                                                  key.color.b,
                                                  key.color.a));

        let rgba_pixels = self.convert_to_rgba(&mut pixels, render_mode);

        Some(RasterizedGlyph {
            width: width as u32,
            height: height as u32,
            bytes: rgba_pixels,
        })
    }
}
<commit_msg>Only gamma correct for non-mono windows fonts<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/. */

use std::collections::HashMap;
use webrender_traits::{FontKey, FontRenderMode, GlyphDimensions};
use webrender_traits::{GlyphKey, GlyphOptions};
use gamma_lut::{GammaLut, Color as ColorLut};

use dwrote;

lazy_static! {
    static ref DEFAULT_FONT_DESCRIPTOR: dwrote::FontDescriptor = dwrote::FontDescriptor {
        family_name: "Arial".to_owned(),
        weight: dwrote::FontWeight::Regular,
        stretch: dwrote::FontStretch::Normal,
        style: dwrote::FontStyle::Normal,
    };
}

pub struct FontContext {
    fonts: HashMap<FontKey, dwrote::FontFace>,
    gamma_lut: GammaLut,
    gdi_gamma_lut: GammaLut,
}

pub struct RasterizedGlyph {
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

fn dwrite_texture_type(render_mode: FontRenderMode) ->
                       dwrote::DWRITE_TEXTURE_TYPE {
    match render_mode {
        FontRenderMode::Mono => dwrote::DWRITE_TEXTURE_ALIASED_1x1 ,
        FontRenderMode::Alpha |
        FontRenderMode::Subpixel => dwrote::DWRITE_TEXTURE_CLEARTYPE_3x1,
    }
}

fn dwrite_measure_mode(render_mode: FontRenderMode, options: Option<GlyphOptions>) ->
                       dwrote::DWRITE_MEASURING_MODE {
    if let Some(GlyphOptions{ force_gdi_rendering: true, .. }) = options {
        return dwrote::DWRITE_MEASURING_MODE_GDI_CLASSIC;
    }

    match render_mode {
        FontRenderMode::Mono => dwrote::DWRITE_MEASURING_MODE_GDI_NATURAL,
        FontRenderMode::Alpha |
        FontRenderMode::Subpixel => dwrote::DWRITE_MEASURING_MODE_NATURAL,
    }
}

fn dwrite_render_mode(font_face: &dwrote::FontFace,
                      render_mode: FontRenderMode,
                      em_size: f32,
                      measure_mode: dwrote::DWRITE_MEASURING_MODE,
                      options: Option<GlyphOptions>) ->
                      dwrote::DWRITE_RENDERING_MODE {
    if let Some(GlyphOptions{ force_gdi_rendering: true, .. }) = options {
        return dwrote::DWRITE_RENDERING_MODE_GDI_CLASSIC;
    }

    let dwrite_render_mode = match render_mode {
        FontRenderMode::Mono => dwrote::DWRITE_RENDERING_MODE_ALIASED,
        FontRenderMode::Alpha |
        FontRenderMode::Subpixel => {
            font_face.get_recommended_rendering_mode_default_params(em_size,
                                                                    1.0,
                                                                    measure_mode)
        },
    };

    if dwrite_render_mode  == dwrote::DWRITE_RENDERING_MODE_OUTLINE {
        // Outline mode is not supported
        return dwrote::DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
    }

    dwrite_render_mode
}

fn get_glyph_dimensions_with_analysis(analysis: dwrote::GlyphRunAnalysis,
                                      texture_type: dwrote::DWRITE_TEXTURE_TYPE)
                                      -> Option<GlyphDimensions> {
    let bounds = analysis.get_alpha_texture_bounds(texture_type);

    let width = (bounds.right - bounds.left) as u32;
    let height = (bounds.bottom - bounds.top) as u32;

    // Alpha texture bounds can sometimes return an empty rect
    // Such as for spaces
    if width == 0 || height == 0 {
        return None
    }

    Some(GlyphDimensions {
        left: bounds.left,
        top: -bounds.top,
        width: width,
        height: height,
    })
}

impl FontContext {
    pub fn new() -> FontContext {
        // These are the default values we use in Gecko.
        // We use a gamma value of 2.3 for gdi fonts
        // TODO: Fetch this data from Gecko itself.
        let contrast = 1.0;
        let gamma = 1.8;
        let gdi_gamma = 2.3;
        FontContext {
            fonts: HashMap::new(),
            gamma_lut: GammaLut::new(contrast, gamma, gamma),
            gdi_gamma_lut: GammaLut::new(contrast, gdi_gamma, gdi_gamma),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, data: &[u8]) {
        if self.fonts.contains_key(font_key) {
            return
        }

        if let Some(font_file) = dwrote::FontFile::new_from_data(data) {
            let face = font_file.create_face(0, dwrote::DWRITE_FONT_SIMULATIONS_NONE);
            self.fonts.insert((*font_key).clone(), face);
        } else {
            // XXX add_raw_font needs to have a way to return an error
            debug!("DWrite WR failed to load font from data, using Arial instead");
            self.add_native_font(font_key, DEFAULT_FONT_DESCRIPTOR.clone());
        }
    }

    pub fn add_native_font(&mut self, font_key: &FontKey, font_handle: dwrote::FontDescriptor) {
        if self.fonts.contains_key(font_key) {
            return
        }

        let system_fc = dwrote::FontCollection::system();
        let font = system_fc.get_font_from_descriptor(&font_handle).unwrap();
        let face = font.create_font_face();
        self.fonts.insert((*font_key).clone(), face);
    }

    // Assumes RGB format from dwrite, which is 3 bytes per pixel as dwrite
    // doesn't output an alpha value via GlyphRunAnalysis::CreateAlphaTexture
    #[allow(dead_code)]
    fn print_glyph_data(&self, data: &Vec<u8>, width: usize, height: usize) {
        // Rust doesn't have step_by support on stable :(
        for i in 0..height {
            let current_height = i * width * 3;

            for pixel in data[current_height .. current_height + (width * 3)].chunks(3) {
                let r = pixel[0];
                let g = pixel[1];
                let b = pixel[2];
                print!("({}, {}, {}) ", r, g, b, );
            }
            println!("");
        }
    }

    fn create_glyph_analysis(&self, key: &GlyphKey,
                            render_mode: FontRenderMode,
                            options: Option<GlyphOptions>) ->
                            dwrote::GlyphRunAnalysis {
        let face = self.fonts.get(&key.font_key).unwrap();
        let glyph = key.index as u16;
        let advance = 0.0f32;
        let offset = dwrote::GlyphOffset { advanceOffset: 0.0, ascenderOffset: 0.0 };

        let glyph_run = dwrote::DWRITE_GLYPH_RUN {
            fontFace: unsafe { face.as_ptr() },
            fontEmSize: key.size.to_f32_px(), // size in DIPs (1/96", same as CSS pixels)
            glyphCount: 1,
            glyphIndices: &glyph,
            glyphAdvances: &advance,
            glyphOffsets: &offset,
            isSideways: 0,
            bidiLevel: 0,
        };

        let dwrite_measure_mode = dwrite_measure_mode(render_mode, options);
        let dwrite_render_mode = dwrite_render_mode(face,
                                                    render_mode,
                                                    key.size.to_f32_px(),
                                                    dwrite_measure_mode,
                                                    options);

        let (x_offset, y_offset) = key.subpixel_point.to_f64();
        let transform = Some(
                        dwrote::DWRITE_MATRIX { m11: 1.0, m12: 0.0, m21: 0.0, m22: 1.0,
                                                dx: x_offset as f32, dy: y_offset as f32 }
                        );

        dwrote::GlyphRunAnalysis::create(&glyph_run, 1.0, transform,
                                         dwrite_render_mode,
                                         dwrite_measure_mode,
                                         0.0, 0.0)
    }

    // TODO: Pipe GlyphOptions into glyph_dimensions too
    pub fn get_glyph_dimensions(&self,
                                key: &GlyphKey)
                                -> Option<GlyphDimensions> {
        // Probably have to default to something else here.
        let render_mode = FontRenderMode::Subpixel;
        let analysis = self.create_glyph_analysis(key, render_mode, None);

        let texture_type = dwrite_texture_type(render_mode);
        get_glyph_dimensions_with_analysis(analysis, texture_type)
    }

    // DWRITE gives us values in RGB. WR doesn't really touch it after. Note, CG returns in BGR
    // TODO: Decide whether all fonts should return RGB or BGR
    fn convert_to_rgba(&self, pixels: &Vec<u8>, render_mode: FontRenderMode) -> Vec<u8> {
        match render_mode {
            FontRenderMode::Mono => {
                let mut rgba_pixels: Vec<u8> = vec![0; pixels.len() * 4];
                for i in 0..pixels.len() {
                    rgba_pixels[i*4+0] = pixels[i];
                    rgba_pixels[i*4+1] = pixels[i];
                    rgba_pixels[i*4+2] = pixels[i];
                    rgba_pixels[i*4+3] = pixels[i];
                }
                rgba_pixels
            }
            FontRenderMode::Alpha => {
                let length = pixels.len() / 3;
                let mut rgba_pixels: Vec<u8> = vec![0; length * 4];
                for i in 0..length {
                    // Only take the G channel, as its closest to D2D
                    let alpha = pixels[i*3 + 1] as u8;
                    rgba_pixels[i*4+0] = alpha;
                    rgba_pixels[i*4+1] = alpha;
                    rgba_pixels[i*4+2] = alpha;
                    rgba_pixels[i*4+3] = alpha;
                }
                rgba_pixels
            }
            FontRenderMode::Subpixel => {
                let length = pixels.len() / 3;
                let mut rgba_pixels: Vec<u8> = vec![0; length * 4];
                for i in 0..length {
                    rgba_pixels[i*4+0] = pixels[i*3+0];
                    rgba_pixels[i*4+1] = pixels[i*3+1];
                    rgba_pixels[i*4+2] = pixels[i*3+2];
                    rgba_pixels[i*4+3] = 0xff;
                }
                rgba_pixels
            }
        }
    }

    pub fn rasterize_glyph(&mut self,
                           key: &GlyphKey,
                           render_mode: FontRenderMode,
                           glyph_options: Option<GlyphOptions>)
                           -> Option<RasterizedGlyph> {
        let analysis = self.create_glyph_analysis(key,
                                                  render_mode,
                                                  glyph_options);
        let texture_type = dwrite_texture_type(render_mode);

        let bounds = analysis.get_alpha_texture_bounds(texture_type);
        let width = (bounds.right - bounds.left) as usize;
        let height = (bounds.bottom - bounds.top) as usize;

        // We should not get here since glyph_dimensions would return
        // None for empty glyphs.
        assert!(width > 0 && height > 0);

        let mut pixels = analysis.create_alpha_texture(texture_type, bounds);

        if render_mode != FontRenderMode::Mono {
            let lut_correction = match glyph_options {
                Some(option) => {
                    if option.force_gdi_rendering {
                        &self.gdi_gamma_lut
                    } else {
                        &self.gamma_lut
                    }
                },
                None => &self.gamma_lut
            };

            lut_correction.preblend_rgb(&mut pixels, width, height,
                                        ColorLut::new(key.color.r,
                                                      key.color.g,
                                                      key.color.b,
                                                      key.color.a));
        }

        let rgba_pixels = self.convert_to_rgba(&mut pixels, render_mode);

        Some(RasterizedGlyph {
            width: width as u32,
            height: height as u32,
            bytes: rgba_pixels,
        })
    }
}
<|endoftext|>


<commit_before>extern crate log;

use self::log::{LogLevelFilter, Log, LogMetadata, LogRecord};

const MAX_LOG_LEVEL: LogLevelFilter = LogLevelFilter::Debug;

struct Logger;

impl Log for Logger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= MAX_LOG_LEVEL
    }

    fn log(&self, record: &LogRecord) {
        println!("{}: {}", record.level(), record.args());
    }
}

static LOGGER: Logger = Logger;

pub fn init() {
    let _ = unsafe {
        log::set_logger_raw(|max_lvl| {
            max_lvl.set(MAX_LOG_LEVEL);
            &LOGGER
        })
    };
}
<commit_msg>Disable logging in fuzzer<commit_after>extern crate log;

use self::log::{LogLevelFilter, Log, LogMetadata, LogRecord};

const MAX_LOG_LEVEL: LogLevelFilter = LogLevelFilter::Off;

struct Logger;

impl Log for Logger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= MAX_LOG_LEVEL
    }

    fn log(&self, record: &LogRecord) {
        println!("{}: {}", record.level(), record.args());
    }
}

static LOGGER: Logger = Logger;

pub fn init() {
    let _ = unsafe {
        log::set_logger_raw(|max_lvl| {
            max_lvl.set(MAX_LOG_LEVEL);
            &LOGGER
        })
    };
}
<|endoftext|>


<commit_before>use crate::paths::TargetDir;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str;

pub(crate) fn target_dir(out_dir: &Path) -> TargetDir {
    (|| {
        let cargo = option_env!("CARGO").unwrap_or("cargo");
        let output = Command::new(cargo)
            .current_dir(out_dir)
            .arg("metadata")
            .arg("--no-deps")
            .arg("--format-version=1")
            .output()
            .ok()?;

        // Cargo only outputs utf8 encoded JSON.
        let mut metadata = str::from_utf8(&output.stdout).ok()?;

        let key_pattern = "\"target_directory\":";
        let key_index = metadata.rfind(key_pattern)?;
        metadata = &metadata[key_index + key_pattern.len()..];
        let open_quote_index = metadata.find('"')?;
        metadata = &metadata[open_quote_index + 1..];
        let close_quote_index = metadata.find('"')?;
        let string = &metadata[..close_quote_index];
        let target_directory = string.replace("\\\\", "\\");
        Some(TargetDir::Path(PathBuf::from(target_directory)))
    })()
    .unwrap_or(TargetDir::Unknown)
}
<commit_msg>Unindent target dir cargo logic<commit_after>use crate::paths::TargetDir;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str;

pub(crate) fn target_dir(out_dir: &Path) -> TargetDir {
    try_target_dir(out_dir).map_or(TargetDir::Unknown, TargetDir::Path)
}

fn try_target_dir(out_dir: &Path) -> Option<PathBuf> {
    let cargo = option_env!("CARGO").unwrap_or("cargo");
    let output = Command::new(cargo)
        .current_dir(out_dir)
        .arg("metadata")
        .arg("--no-deps")
        .arg("--format-version=1")
        .output()
        .ok()?;

    // Cargo only outputs utf8 encoded JSON.
    let mut metadata = str::from_utf8(&output.stdout).ok()?;

    let key_pattern = "\"target_directory\":";
    let key_index = metadata.rfind(key_pattern)?;
    metadata = &metadata[key_index + key_pattern.len()..];
    let open_quote_index = metadata.find('"')?;
    metadata = &metadata[open_quote_index + 1..];
    let close_quote_index = metadata.find('"')?;
    let string = &metadata[..close_quote_index];
    let target_directory = string.replace("\\\\", "\\");
    Some(PathBuf::from(target_directory))
}
<|endoftext|>


<commit_before>#![unstable(reason = "not public", issue = "none", feature = "fd")]

use crate::cmp;
use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read};
use crate::mem;
use crate::sys::cvt;
use crate::sys_common::AsInner;

use libc::{c_int, c_void};

#[derive(Debug)]
pub struct FileDesc {
    fd: c_int,
}

// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`,
// with the man page quoting that if the count of bytes to read is
// greater than `SSIZE_MAX` the result is "unspecified".
//
// On macOS, however, apparently the 64-bit libc is either buggy or
// intentionally showing odd behavior by rejecting any read with a size
// larger than or equal to INT_MAX. To handle both of these the read
// size is capped on both platforms.
#[cfg(target_os = "macos")]
const READ_LIMIT: usize = c_int::MAX as usize - 1;
#[cfg(not(target_os = "macos"))]
const READ_LIMIT: usize = libc::ssize_t::MAX as usize;

impl FileDesc {
    pub fn new(fd: c_int) -> FileDesc {
        FileDesc { fd }
    }

    pub fn raw(&self) -> c_int {
        self.fd
    }

    /// Extracts the actual file descriptor without closing it.
    pub fn into_raw(self) -> c_int {
        let fd = self.fd;
        mem::forget(self);
        fd
    }

    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT))
        })?;
        Ok(ret as usize)
    }

    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::readv(
                self.fd,
                bufs.as_ptr() as *const libc::iovec,
                cmp::min(bufs.len(), c_int::MAX as usize) as c_int,
            )
        })?;
        Ok(ret as usize)
    }

    #[inline]
    pub fn is_read_vectored(&self) -> bool {
        true
    }

    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
        let mut me = self;
        (&mut me).read_to_end(buf)
    }

    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
        #[cfg(target_os = "android")]
        use super::android::cvt_pread64;

        #[cfg(not(target_os = "android"))]
        unsafe fn cvt_pread64(
            fd: c_int,
            buf: *mut c_void,
            count: usize,
            offset: i64,
        ) -> io::Result<isize> {
            #[cfg(not(target_os = "linux"))]
            use libc::pread as pread64;
            #[cfg(target_os = "linux")]
            use libc::pread64;
            cvt(pread64(fd, buf, count, offset))
        }

        unsafe {
            cvt_pread64(
                self.fd,
                buf.as_mut_ptr() as *mut c_void,
                cmp::min(buf.len(), READ_LIMIT),
                offset as i64,
            )
            .map(|n| n as usize)
        }
    }

    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT))
        })?;
        Ok(ret as usize)
    }

    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::writev(
                self.fd,
                bufs.as_ptr() as *const libc::iovec,
                cmp::min(bufs.len(), c_int::MAX as usize) as c_int,
            )
        })?;
        Ok(ret as usize)
    }

    #[inline]
    pub fn is_write_vectored(&self) -> bool {
        true
    }

    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
        #[cfg(target_os = "android")]
        use super::android::cvt_pwrite64;

        #[cfg(not(target_os = "android"))]
        unsafe fn cvt_pwrite64(
            fd: c_int,
            buf: *const c_void,
            count: usize,
            offset: i64,
        ) -> io::Result<isize> {
            #[cfg(not(target_os = "linux"))]
            use libc::pwrite as pwrite64;
            #[cfg(target_os = "linux")]
            use libc::pwrite64;
            cvt(pwrite64(fd, buf, count, offset))
        }

        unsafe {
            cvt_pwrite64(
                self.fd,
                buf.as_ptr() as *const c_void,
                cmp::min(buf.len(), READ_LIMIT),
                offset as i64,
            )
            .map(|n| n as usize)
        }
    }

    #[cfg(target_os = "linux")]
    pub fn get_cloexec(&self) -> io::Result<bool> {
        unsafe { Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
    }

    #[cfg(not(any(
        target_env = "newlib",
        target_os = "solaris",
        target_os = "illumos",
        target_os = "emscripten",
        target_os = "fuchsia",
        target_os = "l4re",
        target_os = "linux",
        target_os = "haiku",
        target_os = "redox"
    )))]
    pub fn set_cloexec(&self) -> io::Result<()> {
        unsafe {
            cvt(libc::ioctl(self.fd, libc::FIOCLEX))?;
            Ok(())
        }
    }
    #[cfg(any(
        target_env = "newlib",
        target_os = "solaris",
        target_os = "illumos",
        target_os = "emscripten",
        target_os = "fuchsia",
        target_os = "l4re",
        target_os = "linux",
        target_os = "haiku",
        target_os = "redox"
    ))]
    pub fn set_cloexec(&self) -> io::Result<()> {
        unsafe {
            let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?;
            let new = previous | libc::FD_CLOEXEC;
            if new != previous {
                cvt(libc::fcntl(self.fd, libc::F_SETFD, new))?;
            }
            Ok(())
        }
    }

    #[cfg(target_os = "linux")]
    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
        unsafe {
            let v = nonblocking as c_int;
            cvt(libc::ioctl(self.fd, libc::FIONBIO, &v))?;
            Ok(())
        }
    }

    #[cfg(not(target_os = "linux"))]
    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
        unsafe {
            let previous = cvt(libc::fcntl(self.fd, libc::F_GETFL))?;
            let new = if nonblocking {
                previous | libc::O_NONBLOCK
            } else {
                previous & !libc::O_NONBLOCK
            };
            if new != previous {
                cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?;
            }
            Ok(())
        }
    }

    pub fn duplicate(&self) -> io::Result<FileDesc> {
        // We want to atomically duplicate this file descriptor and set the
        // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
        // is a POSIX flag that was added to Linux in 2.6.24.
        let fd = cvt(unsafe { libc::fcntl(self.raw(), libc::F_DUPFD_CLOEXEC, 0) })?;
        Ok(FileDesc::new(fd))
    }
}

impl<'a> Read for &'a FileDesc {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (**self).read(buf)
    }

    #[inline]
    unsafe fn initializer(&self) -> Initializer {
        Initializer::nop()
    }
}

impl AsInner<c_int> for FileDesc {
    fn as_inner(&self) -> &c_int {
        &self.fd
    }
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        // Note that errors are ignored when closing a file descriptor. The
        // reason for this is that if an error occurs we don't actually know if
        // the file descriptor was closed or not, and if we retried (for
        // something like EINTR), we might close another valid file descriptor
        // opened after we closed ours.
        let _ = unsafe { libc::close(self.fd) };
    }
}
<commit_msg>Auto merge of #75005 - adamreichold:limit-vector-count, r=Amanieu<commit_after>#![unstable(reason = "not public", issue = "none", feature = "fd")]

use crate::cmp;
use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read};
use crate::mem;
#[cfg(not(any(target_os = "redox", target_env = "newlib")))]
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::cvt;
use crate::sys_common::AsInner;

use libc::{c_int, c_void};

#[derive(Debug)]
pub struct FileDesc {
    fd: c_int,
}

// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`,
// with the man page quoting that if the count of bytes to read is
// greater than `SSIZE_MAX` the result is "unspecified".
//
// On macOS, however, apparently the 64-bit libc is either buggy or
// intentionally showing odd behavior by rejecting any read with a size
// larger than or equal to INT_MAX. To handle both of these the read
// size is capped on both platforms.
#[cfg(target_os = "macos")]
const READ_LIMIT: usize = c_int::MAX as usize - 1;
#[cfg(not(target_os = "macos"))]
const READ_LIMIT: usize = libc::ssize_t::MAX as usize;

#[cfg(not(any(target_os = "redox", target_env = "newlib")))]
fn max_iov() -> usize {
    static LIM: AtomicUsize = AtomicUsize::new(0);

    let mut lim = LIM.load(Ordering::Relaxed);
    if lim == 0 {
        let ret = unsafe { libc::sysconf(libc::_SC_IOV_MAX) };

        // 16 is the minimum value required by POSIX.
        lim = if ret > 0 { ret as usize } else { 16 };
        LIM.store(lim, Ordering::Relaxed);
    }

    lim
}

#[cfg(any(target_os = "redox", target_env = "newlib"))]
fn max_iov() -> usize {
    16 // The minimum value required by POSIX.
}

impl FileDesc {
    pub fn new(fd: c_int) -> FileDesc {
        FileDesc { fd }
    }

    pub fn raw(&self) -> c_int {
        self.fd
    }

    /// Extracts the actual file descriptor without closing it.
    pub fn into_raw(self) -> c_int {
        let fd = self.fd;
        mem::forget(self);
        fd
    }

    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT))
        })?;
        Ok(ret as usize)
    }

    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::readv(
                self.fd,
                bufs.as_ptr() as *const libc::iovec,
                cmp::min(bufs.len(), max_iov()) as c_int,
            )
        })?;
        Ok(ret as usize)
    }

    #[inline]
    pub fn is_read_vectored(&self) -> bool {
        true
    }

    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
        let mut me = self;
        (&mut me).read_to_end(buf)
    }

    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
        #[cfg(target_os = "android")]
        use super::android::cvt_pread64;

        #[cfg(not(target_os = "android"))]
        unsafe fn cvt_pread64(
            fd: c_int,
            buf: *mut c_void,
            count: usize,
            offset: i64,
        ) -> io::Result<isize> {
            #[cfg(not(target_os = "linux"))]
            use libc::pread as pread64;
            #[cfg(target_os = "linux")]
            use libc::pread64;
            cvt(pread64(fd, buf, count, offset))
        }

        unsafe {
            cvt_pread64(
                self.fd,
                buf.as_mut_ptr() as *mut c_void,
                cmp::min(buf.len(), READ_LIMIT),
                offset as i64,
            )
            .map(|n| n as usize)
        }
    }

    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT))
        })?;
        Ok(ret as usize)
    }

    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::writev(
                self.fd,
                bufs.as_ptr() as *const libc::iovec,
                cmp::min(bufs.len(), max_iov()) as c_int,
            )
        })?;
        Ok(ret as usize)
    }

    #[inline]
    pub fn is_write_vectored(&self) -> bool {
        true
    }

    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
        #[cfg(target_os = "android")]
        use super::android::cvt_pwrite64;

        #[cfg(not(target_os = "android"))]
        unsafe fn cvt_pwrite64(
            fd: c_int,
            buf: *const c_void,
            count: usize,
            offset: i64,
        ) -> io::Result<isize> {
            #[cfg(not(target_os = "linux"))]
            use libc::pwrite as pwrite64;
            #[cfg(target_os = "linux")]
            use libc::pwrite64;
            cvt(pwrite64(fd, buf, count, offset))
        }

        unsafe {
            cvt_pwrite64(
                self.fd,
                buf.as_ptr() as *const c_void,
                cmp::min(buf.len(), READ_LIMIT),
                offset as i64,
            )
            .map(|n| n as usize)
        }
    }

    #[cfg(target_os = "linux")]
    pub fn get_cloexec(&self) -> io::Result<bool> {
        unsafe { Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
    }

    #[cfg(not(any(
        target_env = "newlib",
        target_os = "solaris",
        target_os = "illumos",
        target_os = "emscripten",
        target_os = "fuchsia",
        target_os = "l4re",
        target_os = "linux",
        target_os = "haiku",
        target_os = "redox"
    )))]
    pub fn set_cloexec(&self) -> io::Result<()> {
        unsafe {
            cvt(libc::ioctl(self.fd, libc::FIOCLEX))?;
            Ok(())
        }
    }
    #[cfg(any(
        target_env = "newlib",
        target_os = "solaris",
        target_os = "illumos",
        target_os = "emscripten",
        target_os = "fuchsia",
        target_os = "l4re",
        target_os = "linux",
        target_os = "haiku",
        target_os = "redox"
    ))]
    pub fn set_cloexec(&self) -> io::Result<()> {
        unsafe {
            let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?;
            let new = previous | libc::FD_CLOEXEC;
            if new != previous {
                cvt(libc::fcntl(self.fd, libc::F_SETFD, new))?;
            }
            Ok(())
        }
    }

    #[cfg(target_os = "linux")]
    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
        unsafe {
            let v = nonblocking as c_int;
            cvt(libc::ioctl(self.fd, libc::FIONBIO, &v))?;
            Ok(())
        }
    }

    #[cfg(not(target_os = "linux"))]
    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
        unsafe {
            let previous = cvt(libc::fcntl(self.fd, libc::F_GETFL))?;
            let new = if nonblocking {
                previous | libc::O_NONBLOCK
            } else {
                previous & !libc::O_NONBLOCK
            };
            if new != previous {
                cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?;
            }
            Ok(())
        }
    }

    pub fn duplicate(&self) -> io::Result<FileDesc> {
        // We want to atomically duplicate this file descriptor and set the
        // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
        // is a POSIX flag that was added to Linux in 2.6.24.
        let fd = cvt(unsafe { libc::fcntl(self.raw(), libc::F_DUPFD_CLOEXEC, 0) })?;
        Ok(FileDesc::new(fd))
    }
}

impl<'a> Read for &'a FileDesc {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (**self).read(buf)
    }

    #[inline]
    unsafe fn initializer(&self) -> Initializer {
        Initializer::nop()
    }
}

impl AsInner<c_int> for FileDesc {
    fn as_inner(&self) -> &c_int {
        &self.fd
    }
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        // Note that errors are ignored when closing a file descriptor. The
        // reason for this is that if an error occurs we don't actually know if
        // the file descriptor was closed or not, and if we retried (for
        // something like EINTR), we might close another valid file descriptor
        // opened after we closed ours.
        let _ = unsafe { libc::close(self.fd) };
    }
}

#[cfg(test)]
mod tests {
    use super::{FileDesc, IoSlice};

    #[test]
    fn limit_vector_count() {
        let stdout = FileDesc { fd: 1 };
        let bufs = (0..1500).map(|_| IoSlice::new(&[])).collect::<Vec<_>>();

        assert!(stdout.write_vectored(&bufs).is_ok());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use enums;
use parse;

use is_builtin;
use name_from_id;
use location_decoration;
use type_from_id;
use format_from_id;

pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> (String, String) {
    let (execution, ep_name, interface) = match instruction {
        &parse::Instruction::EntryPoint { ref execution, id, ref name, ref interface } => {
            (execution, name, interface)
        },
        _ => unreachable!()
    };

    let capitalized_ep_name: String = ep_name.chars().take(1).flat_map(|c| c.to_uppercase())
                                             .chain(ep_name.chars().skip(1)).collect();

    let interface_structs = write_interface_structs(doc, &capitalized_ep_name, interface);

    let (ty, f_call) = match *execution {
        enums::ExecutionModel::ExecutionModelVertex => {
            let t = format!("::vulkano::pipeline::shader::VertexShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name);
            let f = format!("vertex_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ vertex: true, .. ShaderStages::none() }}))", capitalized_ep_name);
            (t, f)
        },

        enums::ExecutionModel::ExecutionModelTessellationControl => {
            let t = format!("::vulkano::pipeline::shader::TessControlShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name);
            let f = format!("tess_control_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ tessellation_control: true, .. ShaderStages::none() }}))", capitalized_ep_name);
            (t, f)
        },

        enums::ExecutionModel::ExecutionModelTessellationEvaluation => {
            let t = format!("::vulkano::pipeline::shader::TessEvaluationShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name);
            let f = format!("tess_evaluation_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ tessellation_evaluation: true, .. ShaderStages::none() }}))", capitalized_ep_name);
            (t, f)
        },

        enums::ExecutionModel::ExecutionModelGeometry => {
            let t = format!("::vulkano::pipeline::shader::GeometryShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name);
            let f = format!("geometry_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ geometry: true, .. ShaderStages::none() }}))", capitalized_ep_name);
            (t, f)
        },

        enums::ExecutionModel::ExecutionModelFragment => {
            let t = format!("::vulkano::pipeline::shader::FragmentShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name);
            let f = format!("fragment_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ fragment: true, .. ShaderStages::none() }}))", capitalized_ep_name);
            (t, f)
        },

        enums::ExecutionModel::ExecutionModelGLCompute => {
            (format!("::vulkano::pipeline::shader::ComputeShaderEntryPoint<(), Layout>"),
             format!("compute_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), Layout(ShaderStages {{ compute: true, .. ShaderStages::none() }}))"))
        },

        enums::ExecutionModel::ExecutionModelKernel => panic!("Kernels are not supported"),
    };

    let entry_point = format!(r#"
    /// Returns a logical struct describing the entry point named `{ep_name}`.
    #[inline]
    pub fn {ep_name}_entry_point(&self) -> {ty} {{
        unsafe {{
            #[allow(dead_code)]
            static NAME: [u8; {ep_name_lenp1}] = [{encoded_ep_name}, 0];     // "{ep_name}"
            self.shader.{f_call}
        }}
    }}
            "#, ep_name = ep_name, ep_name_lenp1 = ep_name.chars().count() + 1, ty = ty,
                encoded_ep_name = ep_name.chars().map(|c| (c as u32).to_string())
                                         .collect::<Vec<String>>().join(", "),
                f_call = f_call);

    (interface_structs, entry_point)
}

fn write_interface_structs(doc: &parse::Spirv, capitalized_ep_name: &str, interface: &[u32])
                           -> String
{
    let mut input_elements = Vec::new();
    let mut output_elements = Vec::new();

    // Filling `input_elements` and `output_elements`.
    for interface in interface.iter() {
        for i in doc.instructions.iter() {
            match i {
                &parse::Instruction::Variable { result_type_id, result_id, ref storage_class, .. }
                                              if &result_id == interface =>
                {
                    if is_builtin(doc, result_id) {
                        continue;
                    }

                    if is_builtin(doc, result_type_id) {
                        continue;
                    }

                    let to_write = match storage_class {
                        &enums::StorageClass::StorageClassInput => &mut input_elements,
                        &enums::StorageClass::StorageClassOutput => &mut output_elements,
                        _ => continue
                    };

                    let name = name_from_id(doc, result_id);
                    if name == "__unnamed" { continue; }        // FIXME: hack

                    let loc = match location_decoration(doc, result_id) {
                        Some(l) => l,
                        None => panic!("Attribute `{}` (id {}) is missing a location", name, result_id)
                    };

                    to_write.push((loc, name, format_from_id(doc, result_type_id)));
                },
                _ => ()
            }
        }
    }

    write_interface_struct(&format!("{}Input", capitalized_ep_name), &input_elements) +
        &write_interface_struct(&format!("{}Output", capitalized_ep_name), &output_elements)
}

fn write_interface_struct(struct_name: &str, attributes: &[(u32, String, (String, usize))]) -> String {
    // Checking for overlapping elements.
    for (offset, &(loc, ref name, (_, loc_len))) in attributes.iter().enumerate() {
        for &(loc2, ref name2, (_, loc_len2)) in attributes.iter().skip(offset + 1) {
            if loc == loc2 || (loc < loc2 && loc + loc_len as u32 > loc2) ||
               (loc2 < loc && loc2 + loc_len2 as u32 > loc)
            {
                panic!("The locations of attributes `{}` and `{}` overlap",
                       name, name2);
            }
        }
    }

    let body = attributes.iter().enumerate().map(|(num, &(loc, ref name, (ref ty, num_locs)))| {
        assert!(num_locs >= 1);

        format!("if self.num == {} {{
            self.num += 1;

            return Some(::vulkano::pipeline::shader::ShaderInterfaceDefEntry {{
                location: {} .. {},
                format: ::vulkano::format::Format::{},
                name: Some(::std::borrow::Cow::Borrowed(\"{}\"))
            }});
        }}", num, loc, loc as usize + num_locs, ty, name)
    }).collect::<Vec<_>>().join("");

    format!("
        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
        pub struct {name};

        unsafe impl ::vulkano::pipeline::shader::ShaderInterfaceDef for {name} {{
            type Iter = {name}Iter;
            fn elements(&self) -> {name}Iter {{
                {name}Iter {{ num: 0 }}
            }}
        }}

        #[derive(Debug, Copy, Clone)]
        pub struct {name}Iter {{ num: u16 }}
        impl Iterator for {name}Iter {{
            type Item = ::vulkano::pipeline::shader::ShaderInterfaceDefEntry;

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

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {{
                let len = ({len} - self.num) as usize;
                (len, Some(len))
            }}
        }}

        impl ExactSizeIterator for {name}Iter {{}}
    ", name = struct_name, body = body, len = attributes.len())
}
<commit_msg>Add a better diagnostic when attrib locations overlap<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use enums;
use parse;

use is_builtin;
use name_from_id;
use location_decoration;
use type_from_id;
use format_from_id;

pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> (String, String) {
    let (execution, ep_name, interface) = match instruction {
        &parse::Instruction::EntryPoint { ref execution, id, ref name, ref interface } => {
            (execution, name, interface)
        },
        _ => unreachable!()
    };

    let capitalized_ep_name: String = ep_name.chars().take(1).flat_map(|c| c.to_uppercase())
                                             .chain(ep_name.chars().skip(1)).collect();

    let interface_structs = write_interface_structs(doc, &capitalized_ep_name, interface);

    let (ty, f_call) = match *execution {
        enums::ExecutionModel::ExecutionModelVertex => {
            let t = format!("::vulkano::pipeline::shader::VertexShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name);
            let f = format!("vertex_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ vertex: true, .. ShaderStages::none() }}))", capitalized_ep_name);
            (t, f)
        },

        enums::ExecutionModel::ExecutionModelTessellationControl => {
            let t = format!("::vulkano::pipeline::shader::TessControlShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name);
            let f = format!("tess_control_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ tessellation_control: true, .. ShaderStages::none() }}))", capitalized_ep_name);
            (t, f)
        },

        enums::ExecutionModel::ExecutionModelTessellationEvaluation => {
            let t = format!("::vulkano::pipeline::shader::TessEvaluationShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name);
            let f = format!("tess_evaluation_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ tessellation_evaluation: true, .. ShaderStages::none() }}))", capitalized_ep_name);
            (t, f)
        },

        enums::ExecutionModel::ExecutionModelGeometry => {
            let t = format!("::vulkano::pipeline::shader::GeometryShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name);
            let f = format!("geometry_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ geometry: true, .. ShaderStages::none() }}))", capitalized_ep_name);
            (t, f)
        },

        enums::ExecutionModel::ExecutionModelFragment => {
            let t = format!("::vulkano::pipeline::shader::FragmentShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name);
            let f = format!("fragment_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ fragment: true, .. ShaderStages::none() }}))", capitalized_ep_name);
            (t, f)
        },

        enums::ExecutionModel::ExecutionModelGLCompute => {
            (format!("::vulkano::pipeline::shader::ComputeShaderEntryPoint<(), Layout>"),
             format!("compute_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), Layout(ShaderStages {{ compute: true, .. ShaderStages::none() }}))"))
        },

        enums::ExecutionModel::ExecutionModelKernel => panic!("Kernels are not supported"),
    };

    let entry_point = format!(r#"
    /// Returns a logical struct describing the entry point named `{ep_name}`.
    #[inline]
    pub fn {ep_name}_entry_point(&self) -> {ty} {{
        unsafe {{
            #[allow(dead_code)]
            static NAME: [u8; {ep_name_lenp1}] = [{encoded_ep_name}, 0];     // "{ep_name}"
            self.shader.{f_call}
        }}
    }}
            "#, ep_name = ep_name, ep_name_lenp1 = ep_name.chars().count() + 1, ty = ty,
                encoded_ep_name = ep_name.chars().map(|c| (c as u32).to_string())
                                         .collect::<Vec<String>>().join(", "),
                f_call = f_call);

    (interface_structs, entry_point)
}

fn write_interface_structs(doc: &parse::Spirv, capitalized_ep_name: &str, interface: &[u32])
                           -> String
{
    let mut input_elements = Vec::new();
    let mut output_elements = Vec::new();

    // Filling `input_elements` and `output_elements`.
    for interface in interface.iter() {
        for i in doc.instructions.iter() {
            match i {
                &parse::Instruction::Variable { result_type_id, result_id, ref storage_class, .. }
                                              if &result_id == interface =>
                {
                    if is_builtin(doc, result_id) {
                        continue;
                    }

                    if is_builtin(doc, result_type_id) {
                        continue;
                    }

                    let to_write = match storage_class {
                        &enums::StorageClass::StorageClassInput => &mut input_elements,
                        &enums::StorageClass::StorageClassOutput => &mut output_elements,
                        _ => continue
                    };

                    let name = name_from_id(doc, result_id);
                    if name == "__unnamed" { continue; }        // FIXME: hack

                    let loc = match location_decoration(doc, result_id) {
                        Some(l) => l,
                        None => panic!("Attribute `{}` (id {}) is missing a location", name, result_id)
                    };

                    to_write.push((loc, name, format_from_id(doc, result_type_id)));
                },
                _ => ()
            }
        }
    }

    write_interface_struct(&format!("{}Input", capitalized_ep_name), &input_elements) +
        &write_interface_struct(&format!("{}Output", capitalized_ep_name), &output_elements)
}

fn write_interface_struct(struct_name: &str, attributes: &[(u32, String, (String, usize))]) -> String {
    // Checking for overlapping elements.
    for (offset, &(loc, ref name, (_, loc_len))) in attributes.iter().enumerate() {
        for &(loc2, ref name2, (_, loc_len2)) in attributes.iter().skip(offset + 1) {
            if loc == loc2 || (loc < loc2 && loc + loc_len as u32 > loc2) ||
               (loc2 < loc && loc2 + loc_len2 as u32 > loc)
            {
                panic!("The locations of attributes `{}` (start={}, size={}) \
                        and `{}` (start={}, size={}) overlap",
                        name, loc, loc_len, name2, loc2, loc_len2);
            }
        }
    }

    let body = attributes.iter().enumerate().map(|(num, &(loc, ref name, (ref ty, num_locs)))| {
        assert!(num_locs >= 1);

        format!("if self.num == {} {{
            self.num += 1;

            return Some(::vulkano::pipeline::shader::ShaderInterfaceDefEntry {{
                location: {} .. {},
                format: ::vulkano::format::Format::{},
                name: Some(::std::borrow::Cow::Borrowed(\"{}\"))
            }});
        }}", num, loc, loc as usize + num_locs, ty, name)
    }).collect::<Vec<_>>().join("");

    format!("
        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
        pub struct {name};

        unsafe impl ::vulkano::pipeline::shader::ShaderInterfaceDef for {name} {{
            type Iter = {name}Iter;
            fn elements(&self) -> {name}Iter {{
                {name}Iter {{ num: 0 }}
            }}
        }}

        #[derive(Debug, Copy, Clone)]
        pub struct {name}Iter {{ num: u16 }}
        impl Iterator for {name}Iter {{
            type Item = ::vulkano::pipeline::shader::ShaderInterfaceDefEntry;

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

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {{
                let len = ({len} - self.num) as usize;
                (len, Some(len))
            }}
        }}

        impl ExactSizeIterator for {name}Iter {{}}
    ", name = struct_name, body = body, len = attributes.len())
}
<|endoftext|>


<commit_before>use crate::utils::paths;
use crate::utils::{
    is_expn_of, is_type_diagnostic_item, last_path_segment, match_def_path, match_function_call, snippet, snippet_opt,
    span_lint_and_then,
};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, MatchSource, PatKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::sym;

declare_clippy_lint! {
    /// **What it does:** Checks for the use of `format!("string literal with no
    /// argument")` and `format!("{}", foo)` where `foo` is a string.
    ///
    /// **Why is this bad?** There is no point of doing that. `format!("foo")` can
    /// be replaced by `"foo".to_owned()` if you really need a `String`. The even
    /// worse `&format!("foo")` is often encountered in the wild. `format!("{}",
    /// foo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()`
    /// if `foo: &str`.
    ///
    /// **Known problems:** None.
    ///
    /// **Examples:**
    /// ```rust
    ///
    /// // Bad
    /// # let foo = "foo";
    /// format!("{}", foo);
    ///
    /// // Good
    /// format!("foo");
    /// ```
    pub USELESS_FORMAT,
    complexity,
    "useless use of `format!`"
}

declare_lint_pass!(UselessFormat => [USELESS_FORMAT]);

impl<'tcx> LateLintPass<'tcx> for UselessFormat {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        let span = match is_expn_of(expr.span, "format") {
            Some(s) if !s.from_expansion() => s,
            _ => return,
        };

        // Operate on the only argument of `alloc::fmt::format`.
        if let Some(sugg) = on_new_v1(cx, expr) {
            span_useless_format(cx, span, "consider using `.to_string()`", sugg);
        } else if let Some(sugg) = on_new_v1_fmt(cx, expr) {
            span_useless_format(cx, span, "consider using `.to_string()`", sugg);
        }
    }
}

fn span_useless_format<T: LintContext>(cx: &T, span: Span, help: &str, mut sugg: String) {
    let to_replace = span.source_callsite();

    // The callsite span contains the statement semicolon for some reason.
    let snippet = snippet(cx, to_replace, "..");
    if snippet.ends_with(';') {
        sugg.push(';');
    }

    span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |diag| {
        diag.span_suggestion(
            to_replace,
            help,
            sugg,
            Applicability::MachineApplicable, // snippet
        );
    });
}

fn on_argumentv1_new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) -> Option<String> {
    if_chain! {
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref format_args) = expr.kind;
        if let ExprKind::Array(ref elems) = arms[0].body.kind;
        if elems.len() == 1;
        if let Some(args) = match_function_call(cx, &elems[0], &paths::FMT_ARGUMENTV1_NEW);
        // matches `core::fmt::Display::fmt`
        if args.len() == 2;
        if let ExprKind::Path(ref qpath) = args[1].kind;
        if let Some(did) = cx.qpath_res(qpath, args[1].hir_id).opt_def_id();
        if match_def_path(cx, did, &paths::DISPLAY_FMT_METHOD);
        // check `(arg0,)` in match block
        if let PatKind::Tuple(ref pats, None) = arms[0].pat.kind;
        if pats.len() == 1;
        then {
            let ty = cx.typeck_results().pat_ty(&pats[0]).peel_refs();
            if *ty.kind() != rustc_middle::ty::Str && !is_type_diagnostic_item(cx, ty, sym::string_type) {
                return None;
            }
            if let ExprKind::Lit(ref lit) = format_args.kind {
                if let LitKind::Str(ref s, _) = lit.node {
                    return Some(format!("{:?}.to_string()", s.as_str()));
                }
            } else {
                let snip = snippet(cx, format_args.span, "<arg>");
                if let ExprKind::MethodCall(ref path, _, _, _) = format_args.kind {
                    if path.ident.name == sym!(to_string) {
                        return Some(format!("{}", snip));
                    }
                } else if let ExprKind::Binary(..) = format_args.kind {
                    return Some(format!("{}", snip));
                }
                return Some(format!("{}.to_string()", snip));
            }
        }
    }
    None
}

fn on_new_v1<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<String> {
    if_chain! {
        if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1);
        if args.len() == 2;
        // Argument 1 in `new_v1()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arr) = args[0].kind;
        if let ExprKind::Array(ref pieces) = arr.kind;
        if pieces.len() == 1;
        if let ExprKind::Lit(ref lit) = pieces[0].kind;
        if let LitKind::Str(ref s, _) = lit.node;
        // Argument 2 in `new_v1()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg1) = args[1].kind;
        if let ExprKind::Match(ref matchee, ref arms, MatchSource::Normal) = arg1.kind;
        if arms.len() == 1;
        if let ExprKind::Tup(ref tup) = matchee.kind;
        then {
            // `format!("foo")` expansion contains `match () { () => [], }`
            if tup.is_empty() {
                if let Some(s_src) = snippet_opt(cx, lit.span) {
                    // Simulate macro expansion, converting {{ and }} to { and }.
                    let s_expand = s_src.replace("{{", "{").replace("}}", "}");
                    return Some(format!("{}.to_string()", s_expand))
                }
            } else if s.as_str().is_empty() {
                return on_argumentv1_new(cx, &tup[0], arms);
            }
        }
    }
    None
}

fn on_new_v1_fmt<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<String> {
    if_chain! {
        if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1_FORMATTED);
        if args.len() == 3;
        if check_unformatted(&args[2]);
        // Argument 1 in `new_v1_formatted()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arr) = args[0].kind;
        if let ExprKind::Array(ref pieces) = arr.kind;
        if pieces.len() == 1;
        if let ExprKind::Lit(ref lit) = pieces[0].kind;
        if let LitKind::Str(..) = lit.node;
        // Argument 2 in `new_v1_formatted()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg1) = args[1].kind;
        if let ExprKind::Match(ref matchee, ref arms, MatchSource::Normal) = arg1.kind;
        if arms.len() == 1;
        if let ExprKind::Tup(ref tup) = matchee.kind;
        then {
            return on_argumentv1_new(cx, &tup[0], arms);
        }
    }
    None
}

/// Checks if the expression matches
/// ```rust,ignore
/// &[_ {
///    format: _ {
///         width: _::Implied,
///         precision: _::Implied,
///         ...
///    },
///    ...,
/// }]
/// ```
fn check_unformatted(expr: &Expr<'_>) -> bool {
    if_chain! {
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) = expr.kind;
        if let ExprKind::Array(ref exprs) = expr.kind;
        if exprs.len() == 1;
        // struct `core::fmt::rt::v1::Argument`
        if let ExprKind::Struct(_, ref fields, _) = exprs[0].kind;
        if let Some(format_field) = fields.iter().find(|f| f.ident.name == sym::format);
        // struct `core::fmt::rt::v1::FormatSpec`
        if let ExprKind::Struct(_, ref fields, _) = format_field.expr.kind;
        if let Some(precision_field) = fields.iter().find(|f| f.ident.name == sym::precision);
        if let ExprKind::Path(ref precision_path) = precision_field.expr.kind;
        if last_path_segment(precision_path).ident.name == sym::Implied;
        if let Some(width_field) = fields.iter().find(|f| f.ident.name == sym::width);
        if let ExprKind::Path(ref width_qpath) = width_field.expr.kind;
        if last_path_segment(width_qpath).ident.name == sym::Implied;
        then {
            return true;
        }
    }

    false
}
<commit_msg>Auto merge of #6854 - mgacek8:6844_fix_doc_for_useless_format_lint, r=phansch<commit_after>use crate::utils::paths;
use crate::utils::{
    is_expn_of, is_type_diagnostic_item, last_path_segment, match_def_path, match_function_call, snippet, snippet_opt,
    span_lint_and_then,
};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, MatchSource, PatKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::sym;

declare_clippy_lint! {
    /// **What it does:** Checks for the use of `format!("string literal with no
    /// argument")` and `format!("{}", foo)` where `foo` is a string.
    ///
    /// **Why is this bad?** There is no point of doing that. `format!("foo")` can
    /// be replaced by `"foo".to_owned()` if you really need a `String`. The even
    /// worse `&format!("foo")` is often encountered in the wild. `format!("{}",
    /// foo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()`
    /// if `foo: &str`.
    ///
    /// **Known problems:** None.
    ///
    /// **Examples:**
    /// ```rust
    ///
    /// // Bad
    /// let foo = "foo";
    /// format!("{}", foo);
    ///
    /// // Good
    /// foo.to_owned();
    /// ```
    pub USELESS_FORMAT,
    complexity,
    "useless use of `format!`"
}

declare_lint_pass!(UselessFormat => [USELESS_FORMAT]);

impl<'tcx> LateLintPass<'tcx> for UselessFormat {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        let span = match is_expn_of(expr.span, "format") {
            Some(s) if !s.from_expansion() => s,
            _ => return,
        };

        // Operate on the only argument of `alloc::fmt::format`.
        if let Some(sugg) = on_new_v1(cx, expr) {
            span_useless_format(cx, span, "consider using `.to_string()`", sugg);
        } else if let Some(sugg) = on_new_v1_fmt(cx, expr) {
            span_useless_format(cx, span, "consider using `.to_string()`", sugg);
        }
    }
}

fn span_useless_format<T: LintContext>(cx: &T, span: Span, help: &str, mut sugg: String) {
    let to_replace = span.source_callsite();

    // The callsite span contains the statement semicolon for some reason.
    let snippet = snippet(cx, to_replace, "..");
    if snippet.ends_with(';') {
        sugg.push(';');
    }

    span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |diag| {
        diag.span_suggestion(
            to_replace,
            help,
            sugg,
            Applicability::MachineApplicable, // snippet
        );
    });
}

fn on_argumentv1_new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) -> Option<String> {
    if_chain! {
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref format_args) = expr.kind;
        if let ExprKind::Array(ref elems) = arms[0].body.kind;
        if elems.len() == 1;
        if let Some(args) = match_function_call(cx, &elems[0], &paths::FMT_ARGUMENTV1_NEW);
        // matches `core::fmt::Display::fmt`
        if args.len() == 2;
        if let ExprKind::Path(ref qpath) = args[1].kind;
        if let Some(did) = cx.qpath_res(qpath, args[1].hir_id).opt_def_id();
        if match_def_path(cx, did, &paths::DISPLAY_FMT_METHOD);
        // check `(arg0,)` in match block
        if let PatKind::Tuple(ref pats, None) = arms[0].pat.kind;
        if pats.len() == 1;
        then {
            let ty = cx.typeck_results().pat_ty(&pats[0]).peel_refs();
            if *ty.kind() != rustc_middle::ty::Str && !is_type_diagnostic_item(cx, ty, sym::string_type) {
                return None;
            }
            if let ExprKind::Lit(ref lit) = format_args.kind {
                if let LitKind::Str(ref s, _) = lit.node {
                    return Some(format!("{:?}.to_string()", s.as_str()));
                }
            } else {
                let snip = snippet(cx, format_args.span, "<arg>");
                if let ExprKind::MethodCall(ref path, _, _, _) = format_args.kind {
                    if path.ident.name == sym!(to_string) {
                        return Some(format!("{}", snip));
                    }
                } else if let ExprKind::Binary(..) = format_args.kind {
                    return Some(format!("{}", snip));
                }
                return Some(format!("{}.to_string()", snip));
            }
        }
    }
    None
}

fn on_new_v1<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<String> {
    if_chain! {
        if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1);
        if args.len() == 2;
        // Argument 1 in `new_v1()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arr) = args[0].kind;
        if let ExprKind::Array(ref pieces) = arr.kind;
        if pieces.len() == 1;
        if let ExprKind::Lit(ref lit) = pieces[0].kind;
        if let LitKind::Str(ref s, _) = lit.node;
        // Argument 2 in `new_v1()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg1) = args[1].kind;
        if let ExprKind::Match(ref matchee, ref arms, MatchSource::Normal) = arg1.kind;
        if arms.len() == 1;
        if let ExprKind::Tup(ref tup) = matchee.kind;
        then {
            // `format!("foo")` expansion contains `match () { () => [], }`
            if tup.is_empty() {
                if let Some(s_src) = snippet_opt(cx, lit.span) {
                    // Simulate macro expansion, converting {{ and }} to { and }.
                    let s_expand = s_src.replace("{{", "{").replace("}}", "}");
                    return Some(format!("{}.to_string()", s_expand))
                }
            } else if s.as_str().is_empty() {
                return on_argumentv1_new(cx, &tup[0], arms);
            }
        }
    }
    None
}

fn on_new_v1_fmt<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<String> {
    if_chain! {
        if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1_FORMATTED);
        if args.len() == 3;
        if check_unformatted(&args[2]);
        // Argument 1 in `new_v1_formatted()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arr) = args[0].kind;
        if let ExprKind::Array(ref pieces) = arr.kind;
        if pieces.len() == 1;
        if let ExprKind::Lit(ref lit) = pieces[0].kind;
        if let LitKind::Str(..) = lit.node;
        // Argument 2 in `new_v1_formatted()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg1) = args[1].kind;
        if let ExprKind::Match(ref matchee, ref arms, MatchSource::Normal) = arg1.kind;
        if arms.len() == 1;
        if let ExprKind::Tup(ref tup) = matchee.kind;
        then {
            return on_argumentv1_new(cx, &tup[0], arms);
        }
    }
    None
}

/// Checks if the expression matches
/// ```rust,ignore
/// &[_ {
///    format: _ {
///         width: _::Implied,
///         precision: _::Implied,
///         ...
///    },
///    ...,
/// }]
/// ```
fn check_unformatted(expr: &Expr<'_>) -> bool {
    if_chain! {
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) = expr.kind;
        if let ExprKind::Array(ref exprs) = expr.kind;
        if exprs.len() == 1;
        // struct `core::fmt::rt::v1::Argument`
        if let ExprKind::Struct(_, ref fields, _) = exprs[0].kind;
        if let Some(format_field) = fields.iter().find(|f| f.ident.name == sym::format);
        // struct `core::fmt::rt::v1::FormatSpec`
        if let ExprKind::Struct(_, ref fields, _) = format_field.expr.kind;
        if let Some(precision_field) = fields.iter().find(|f| f.ident.name == sym::precision);
        if let ExprKind::Path(ref precision_path) = precision_field.expr.kind;
        if last_path_segment(precision_path).ident.name == sym::Implied;
        if let Some(width_field) = fields.iter().find(|f| f.ident.name == sym::width);
        if let ExprKind::Path(ref width_qpath) = width_field.expr.kind;
        if last_path_segment(width_qpath).ident.name == sym::Implied;
        then {
            return true;
        }
    }

    false
}
<|endoftext|>


<commit_before>use common::*;
use std::vec;

/// Column major dense matrix type.
pub struct DenseMatrix {
  num_rows: uint,
  num_cols: uint,
  data: ~[R]
}

impl DenseMatrix {

  pub fn from_fn(num_rows: uint, num_cols: uint, f: &fn(row:uint, col:uint) -> R) -> DenseMatrix {
    DenseMatrix {
      num_rows: num_rows,
      num_cols: num_cols,
      data: vec::from_fn(num_rows * num_cols, |i| {
        let c = i / num_rows;
        let r = i % num_rows;
        f(r,c)
      })
    }
  }

  pub fn from_elem(num_rows: uint, num_cols: uint, elem: R) -> DenseMatrix {
    DenseMatrix {
      num_rows: num_rows,
      num_cols: num_cols,
      data: vec::from_elem(num_rows * num_cols, elem)
    }
  }

  pub fn upper_triangular_from_fn(num_rows: uint, num_cols: uint, f: &fn(row:uint, col:uint) -> R) -> DenseMatrix {
    let mut data = vec::from_elem(num_rows * num_cols, 0 as R);
    for c in range(0, num_cols) {
      for r in range(0, c) {
        let f_val = f(r,c);
        data[c * num_rows + r] = f_val;
      }
      data[c * num_cols + c] = f(c,c);
    }
    DenseMatrix {
      num_rows: num_rows,
      num_cols: num_cols,
      data: data
    }
  }

  #[inline]
  pub fn get(&self, r: uint, c: uint) -> R {
    self.data[c * self.num_rows + r]
  }

  #[inline]
  pub fn set(&mut self, r: uint, c: uint, value: R) {
    self.data[c * self.num_rows + r] = value;
  }

  pub fn col_maj_data_copy(&self) -> ~[R] {
    self.data.clone()
  }

/*
  #[inline]
  pub fn copy_data_into(&self, buf: &mut [R]) -> () {
    use std::vec::MutableCloneableVector;
    let ncopied = buf.copy_from(self.data);
    assert!(ncopied == self.data.len());
  }
*/
}

#[test]
fn test_constr_from_fn() {
  let m = DenseMatrix::from_fn(3,3, |r,c| {
    1000. * r as R + c as R
  });
  assert_eq!(m.data, ~[0.,1000.,2000.,1.,1001.,2001.,2.,1002.,2002.]);
}

fn test_constr_from_elem() {
  let m = DenseMatrix::from_elem(3,3, 10.);
  assert_eq!(m.data, ~[10.,10.,10.,10.,10.,10.,10.,10.,10.]);
}

#[test]
fn test_constr_upper_triangular_from_fn() {
  let m = DenseMatrix::upper_triangular_from_fn(3,3, |r,c| {
    1000. * r as R + c as R
  });
  assert_eq!(m.data, ~[0.,0.,0.,1.,1001.,0.,2.,1002.,2002.]);
}

#[test]
fn test_get() {
  let m = DenseMatrix::from_fn(3,3, |r,c| {
    1000. * r as R + c as R
  });
  assert_eq!(m.get(0,0), 0.);
  assert_eq!(m.get(0,1), 1.);
  assert_eq!(m.get(0,2), 2.);
  assert_eq!(m.get(1,0), 1000.);
  assert_eq!(m.get(1,1), 1001.);
  assert_eq!(m.get(1,2), 1002.);
  assert_eq!(m.get(2,0), 2000.);
  assert_eq!(m.get(2,1), 2001.);
  assert_eq!(m.get(2,2), 2002.);
}

#[test]
fn test_set() {
  let mut m = DenseMatrix::from_fn(3,3, |r,c| {
    1000. * r as R + c as R
  });
  assert_eq!(m.get(2,1), 2001.);
  m.set(2,1, 2001.5);
  assert_eq!(m.get(2,1), 2001.5);
}

<commit_msg>Remove unused fn.<commit_after>use common::*;
use std::vec;

/// Column major dense matrix type.
pub struct DenseMatrix {
  num_rows: uint,
  num_cols: uint,
  data: ~[R]
}

impl DenseMatrix {

  pub fn from_fn(num_rows: uint, num_cols: uint, f: &fn(row:uint, col:uint) -> R) -> DenseMatrix {
    DenseMatrix {
      num_rows: num_rows,
      num_cols: num_cols,
      data: vec::from_fn(num_rows * num_cols, |i| {
        let c = i / num_rows;
        let r = i % num_rows;
        f(r,c)
      })
    }
  }

  pub fn from_elem(num_rows: uint, num_cols: uint, elem: R) -> DenseMatrix {
    DenseMatrix {
      num_rows: num_rows,
      num_cols: num_cols,
      data: vec::from_elem(num_rows * num_cols, elem)
    }
  }

  pub fn upper_triangular_from_fn(num_rows: uint, num_cols: uint, f: &fn(row:uint, col:uint) -> R) -> DenseMatrix {
    let mut data = vec::from_elem(num_rows * num_cols, 0 as R);
    for c in range(0, num_cols) {
      for r in range(0, c) {
        let f_val = f(r,c);
        data[c * num_rows + r] = f_val;
      }
      data[c * num_cols + c] = f(c,c);
    }
    DenseMatrix {
      num_rows: num_rows,
      num_cols: num_cols,
      data: data
    }
  }

  #[inline]
  pub fn get(&self, r: uint, c: uint) -> R {
    self.data[c * self.num_rows + r]
  }

  #[inline]
  pub fn set(&mut self, r: uint, c: uint, value: R) {
    self.data[c * self.num_rows + r] = value;
  }

  pub fn col_maj_data_copy(&self) -> ~[R] {
    self.data.clone()
  }

}

#[test]
fn test_constr_from_fn() {
  let m = DenseMatrix::from_fn(3,3, |r,c| {
    1000. * r as R + c as R
  });
  assert_eq!(m.data, ~[0.,1000.,2000.,1.,1001.,2001.,2.,1002.,2002.]);
}

fn test_constr_from_elem() {
  let m = DenseMatrix::from_elem(3,3, 10.);
  assert_eq!(m.data, ~[10.,10.,10.,10.,10.,10.,10.,10.,10.]);
}

#[test]
fn test_constr_upper_triangular_from_fn() {
  let m = DenseMatrix::upper_triangular_from_fn(3,3, |r,c| {
    1000. * r as R + c as R
  });
  assert_eq!(m.data, ~[0.,0.,0.,1.,1001.,0.,2.,1002.,2002.]);
}

#[test]
fn test_get() {
  let m = DenseMatrix::from_fn(3,3, |r,c| {
    1000. * r as R + c as R
  });
  assert_eq!(m.get(0,0), 0.);
  assert_eq!(m.get(0,1), 1.);
  assert_eq!(m.get(0,2), 2.);
  assert_eq!(m.get(1,0), 1000.);
  assert_eq!(m.get(1,1), 1001.);
  assert_eq!(m.get(1,2), 1002.);
  assert_eq!(m.get(2,0), 2000.);
  assert_eq!(m.get(2,1), 2001.);
  assert_eq!(m.get(2,2), 2002.);
}

#[test]
fn test_set() {
  let mut m = DenseMatrix::from_fn(3,3, |r,c| {
    1000. * r as R + c as R
  });
  assert_eq!(m.get(2,1), 2001.);
  m.set(2,1, 2001.5);
  assert_eq!(m.get(2,1), 2001.5);
}

<|endoftext|>


<commit_before>//! A blinky example for Tessel

// This enables the system allocator in your script.
// This is required to run Rust binaries on Tessel.
#![feature(alloc_system)]
extern crate alloc_system;

// Import the tessel library
extern crate tessel;
// Import the Tessel API
use tessel::Tessel;
// Import sleep from the standard lib
use std::thread::sleep;
// Import durations from the standard lib
use std::time::Duration;

fn main() {
    // Create a new Tessel
    let mut tessel = Tessel::new();

    // Turn on one of the LEDs
    tessel.led[2].on().unwrap();

    println!("I'm blinking! (Press CTRL + C to stop)");

    // Loop forever
    loop {
        // Toggle each LED
        tessel.led[2].toggle().unwrap();
        tessel.led[3].toggle().unwrap();
        // Re-execute the loop after sleeping for 100ms
        sleep(Duration::from_millis(100));
    }
}
<commit_msg>Removes allocator req from rust init.<commit_after>//! A blinky example for Tessel

// Import the tessel library
extern crate tessel;
// Import the Tessel API
use tessel::Tessel;
// Import sleep from the standard lib
use std::thread::sleep;
// Import durations from the standard lib
use std::time::Duration;

fn main() {
    // Create a new Tessel
    let mut tessel = Tessel::new();

    // Turn on one of the LEDs
    tessel.led[2].on().unwrap();

    println!("I'm blinking! (Press CTRL + C to stop)");

    // Loop forever
    loop {
        // Toggle each LED
        tessel.led[2].toggle().unwrap();
        tessel.led[3].toggle().unwrap();
        // Re-execute the loop after sleeping for 100ms
        sleep(Duration::from_millis(100));
    }
}
<|endoftext|>


<commit_before>use gsgdt::GraphvizSettings;
use rustc_graphviz as dot;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use std::fmt::Debug;
use std::io::{self, Write};

use super::generic_graph::mir_fn_to_generic_graph;
use super::pretty::dump_mir_def_ids;

/// Write a graphviz DOT graph of a list of MIRs.
pub fn write_mir_graphviz<W>(tcx: TyCtxt<'_>, single: Option<DefId>, w: &mut W) -> io::Result<()>
where
    W: Write,
{
    let def_ids = dump_mir_def_ids(tcx, single);

    let use_subgraphs = def_ids.len() > 1;
    if use_subgraphs {
        writeln!(w, "digraph __crate__ {{")?;
    }

    for def_id in def_ids {
        let body = &tcx.optimized_mir(def_id);
        write_mir_fn_graphviz(tcx, body, use_subgraphs, w)?;
    }

    if use_subgraphs {
        writeln!(w, "}}")?;
    }

    Ok(())
}

/// Write a graphviz DOT graph of the MIR.
pub fn write_mir_fn_graphviz<'tcx, W>(
    tcx: TyCtxt<'tcx>,
    body: &Body<'_>,
    subgraph: bool,
    w: &mut W,
) -> io::Result<()>
where
    W: Write,
{
    // Global graph properties
    let font = format!(r#"fontname="{}""#, tcx.sess.opts.debugging_opts.graphviz_font);
    let mut graph_attrs = vec![&font[..]];
    let mut content_attrs = vec![&font[..]];

    let dark_mode = tcx.sess.opts.debugging_opts.graphviz_dark_mode;
    if dark_mode {
        graph_attrs.push(r#"bgcolor="black""#);
        graph_attrs.push(r#"fontcolor="white""#);
        content_attrs.push(r#"color="white""#);
        content_attrs.push(r#"fontcolor="white""#);
    }

    // Graph label
    let label = get_graph_label(tcx, body);
    let g = mir_fn_to_generic_graph(tcx, body, subgraph);
    let settings = GraphvizSettings {
        graph_attrs: Some(graph_attrs.join(" ")),
        node_attrs: Some(content_attrs.join(" ")),
        edge_attrs: Some(content_attrs.join(" ")),
        graph_label: Some(label),
    };
    g.to_dot(w, &settings)
}

/// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
/// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
/// all the variables and temporaries.
fn get_graph_label<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> String {
    let def_id = body.source.def_id();
    let mut label: Vec<String> = Vec::new();

    label.push(format!("fn {}(", dot::escape_html(&tcx.def_path_str(def_id))));

    // fn argument types.
    for (i, arg) in body.args_iter().enumerate() {
        if i > 0 {
            label.push(", ".to_owned());
        }
        label.push(format!("{:?}: {}", Place::from(arg), escape(&body.local_decls[arg].ty)));
    }

    label.push(format!(") -> {}", escape(&body.return_ty())));
    label.push(r#"
"#.to_owned());

    for local in body.vars_and_temps_iter() {
        let decl = &body.local_decls[local];

        label.push("let ".to_owned());
        if decl.mutability == Mutability::Mut {
            label.push("mut ".to_owned());
        }

        label.push(format!(r#"{:?}: {};
"#, Place::from(local), escape(&decl.ty)));
    }

    for var_debug_info in &body.var_debug_info {
        label.push(format!(
            r#"debug {} => {};
"#,
            var_debug_info.name,
            escape(&var_debug_info.place)
        ));
    }
    label.join("")
}

fn escape<T: Debug>(t: &T) -> String {
    dot::escape_html(&format!("{:?}", t))
}
<commit_msg>write to a String instead to reduce churn<commit_after>use gsgdt::GraphvizSettings;
use rustc_graphviz as dot;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use std::fmt::Debug;
use std::io::{self, Write};

use super::generic_graph::mir_fn_to_generic_graph;
use super::pretty::dump_mir_def_ids;

/// Write a graphviz DOT graph of a list of MIRs.
pub fn write_mir_graphviz<W>(tcx: TyCtxt<'_>, single: Option<DefId>, w: &mut W) -> io::Result<()>
where
    W: Write,
{
    let def_ids = dump_mir_def_ids(tcx, single);

    let use_subgraphs = def_ids.len() > 1;
    if use_subgraphs {
        writeln!(w, "digraph __crate__ {{")?;
    }

    for def_id in def_ids {
        let body = &tcx.optimized_mir(def_id);
        write_mir_fn_graphviz(tcx, body, use_subgraphs, w)?;
    }

    if use_subgraphs {
        writeln!(w, "}}")?;
    }

    Ok(())
}

/// Write a graphviz DOT graph of the MIR.
pub fn write_mir_fn_graphviz<'tcx, W>(
    tcx: TyCtxt<'tcx>,
    body: &Body<'_>,
    subgraph: bool,
    w: &mut W,
) -> io::Result<()>
where
    W: Write,
{
    // Global graph properties
    let font = format!(r#"fontname="{}""#, tcx.sess.opts.debugging_opts.graphviz_font);
    let mut graph_attrs = vec![&font[..]];
    let mut content_attrs = vec![&font[..]];

    let dark_mode = tcx.sess.opts.debugging_opts.graphviz_dark_mode;
    if dark_mode {
        graph_attrs.push(r#"bgcolor="black""#);
        graph_attrs.push(r#"fontcolor="white""#);
        content_attrs.push(r#"color="white""#);
        content_attrs.push(r#"fontcolor="white""#);
    }

    // Graph label
    let mut label = String::from("");
    // FIXME: remove this unwrap
    write_graph_label(tcx, body, &mut label).unwrap();
    let g = mir_fn_to_generic_graph(tcx, body, subgraph);
    let settings = GraphvizSettings {
        graph_attrs: Some(graph_attrs.join(" ")),
        node_attrs: Some(content_attrs.join(" ")),
        edge_attrs: Some(content_attrs.join(" ")),
        graph_label: Some(label),
    };
    g.to_dot(w, &settings)
}

/// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
/// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
/// all the variables and temporaries.
fn write_graph_label<'tcx, W: std::fmt::Write>(
    tcx: TyCtxt<'tcx>,
    body: &Body<'_>,
    w: &mut W,
) -> std::fmt::Result {
    let def_id = body.source.def_id();

    write!(w, "fn {}(", dot::escape_html(&tcx.def_path_str(def_id)))?;

    // fn argument types.
    for (i, arg) in body.args_iter().enumerate() {
        if i > 0 {
            write!(w, ", ")?;
        }
        write!(w, "{:?}: {}", Place::from(arg), escape(&body.local_decls[arg].ty))?;
    }

    write!(w, ") -> {}", escape(&body.return_ty()))?;
    write!(w, r#"
"#)?;

    for local in body.vars_and_temps_iter() {
        let decl = &body.local_decls[local];

        write!(w, "let ")?;
        if decl.mutability == Mutability::Mut {
            write!(w, "mut ")?;
        }

        write!(w, r#"{:?}: {};
"#, Place::from(local), escape(&decl.ty))?;
    }

    for var_debug_info in &body.var_debug_info {
        write!(
            w,
            r#"debug {} => {};
"#,
            var_debug_info.name,
            escape(&var_debug_info.place)
        )?;
    }

    Ok(())
}

fn escape<T: Debug>(t: &T) -> String {
    dot::escape_html(&format!("{:?}", t))
}
<|endoftext|>


<commit_before>extern crate euler;

#[macro_use] extern crate indoc;

use euler::inputs;
use euler::solutions;

fn main() {
  println!("{}",
    solutions::largest_product_in_a_series(13, inputs::INPUT_8).unwrap());
}
<commit_msg>unused import<commit_after>extern crate euler;

use euler::inputs;
use euler::solutions;

fn main() {
  println!("{}",
    solutions::largest_product_in_a_series(13, inputs::INPUT_8).unwrap());
}
<|endoftext|>