<commit_before>use std::collections::HashSet;
use std::io::{Write, BufWriter};
use std::fs::File;
use std::path::{Path, PathBuf};

use ops::{Context, Unit};
use util::{CargoResult, internal};
use util::paths;
use ops::cargo_rustc::fingerprint;

fn render_filename<P: AsRef<Path>>(path: P, basedir: Option<&str>) -> CargoResult<String> {
    let path = path.as_ref();
    let relpath = match basedir {
        None => path,
        Some(base) => match path.strip_prefix(base) {
            Ok(relpath) => relpath,
            _ => path,
        }
    };
    relpath.to_str().ok_or_else(|| internal("path not utf-8")).map(|f| f.replace(" ", "\\ "))
}

fn add_deps_for_unit<'a, 'b>(
    deps: &mut HashSet<PathBuf>,
    context: &mut Context<'a, 'b>,
    unit: &Unit<'a>,
    visited: &mut HashSet<Unit<'a>>,
)
    -> CargoResult<()>
{
    if !visited.insert(*unit) {
        return Ok(());
    }

    // units representing the execution of a build script don't actually
    // generate a dep info file, so we just keep on going below
    if !unit.profile.run_custom_build {
        // Add dependencies from rustc dep-info output (stored in fingerprint directory)
        let dep_info_loc = fingerprint::dep_info_loc(context, unit);
        if let Some(paths) = fingerprint::parse_dep_info(unit.pkg, &dep_info_loc)? {
            for path in paths {
                deps.insert(path);
            }
        } else {
            debug!("can't find dep_info for {:?} {:?}",
                unit.pkg.package_id(), unit.profile);
            return Err(internal("dep_info missing"));
        }
    }

    // Add rerun-if-changed dependencies
    let key = (unit.pkg.package_id().clone(), unit.kind);
    if let Some(output) = context.build_state.outputs.lock().unwrap().get(&key) {
        for path in &output.rerun_if_changed {
            deps.insert(path.into());
        }
    }

    // Recursively traverse all transitive dependencies
    for dep_unit in &context.dep_targets(unit)? {
        let source_id = dep_unit.pkg.package_id().source_id();
        if source_id.is_path() {
            add_deps_for_unit(deps, context, dep_unit, visited)?;
        }
    }
    Ok(())
}

pub fn output_depinfo<'a, 'b>(context: &mut Context<'a, 'b>, unit: &Unit<'a>) -> CargoResult<()> {
    let mut deps = HashSet::new();
    let mut visited = HashSet::new();
    let success = add_deps_for_unit(&mut deps, context, unit, &mut visited).is_ok();
    let basedir_string;
    let basedir = match context.config.get_string("build.dep-info-basedir")? {
        Some(value) => {
            basedir_string = value.val;
            Some(basedir_string.as_str())
        }
        None => None,
    };
    for &(_, ref link_dst, _) in context.target_filenames(unit)?.iter() {
        if let Some(ref link_dst) = *link_dst {
            let output_path = link_dst.with_extension("d");
            if success {
                let mut outfile = BufWriter::new(File::create(output_path)?);
                let target_fn = render_filename(link_dst, basedir)?;
                write!(outfile, "{}:", target_fn)?;
                for dep in &deps {
                    write!(outfile, " {}", render_filename(dep, basedir)?)?;
                }
                writeln!(outfile, "")?;

            // dep-info generation failed, so delete output file. This will
            // usually cause the build system to always rerun the build
            // rule, which is correct if inefficient.
            } else if output_path.exists() {
                paths::remove_file(output_path)?;
            }
        }
    }
    Ok(())
}
<commit_msg>Use get_path() instead of get_string()<commit_after>use std::collections::HashSet;
use std::io::{Write, BufWriter};
use std::fs::File;
use std::path::{Path, PathBuf};

use ops::{Context, Unit};
use util::{CargoResult, internal};
use util::paths;
use ops::cargo_rustc::fingerprint;

fn render_filename<P: AsRef<Path>>(path: P, basedir: Option<&str>) -> CargoResult<String> {
    let path = path.as_ref();
    let relpath = match basedir {
        None => path,
        Some(base) => match path.strip_prefix(base) {
            Ok(relpath) => relpath,
            _ => path,
        }
    };
    relpath.to_str().ok_or_else(|| internal("path not utf-8")).map(|f| f.replace(" ", "\\ "))
}

fn add_deps_for_unit<'a, 'b>(
    deps: &mut HashSet<PathBuf>,
    context: &mut Context<'a, 'b>,
    unit: &Unit<'a>,
    visited: &mut HashSet<Unit<'a>>,
)
    -> CargoResult<()>
{
    if !visited.insert(*unit) {
        return Ok(());
    }

    // units representing the execution of a build script don't actually
    // generate a dep info file, so we just keep on going below
    if !unit.profile.run_custom_build {
        // Add dependencies from rustc dep-info output (stored in fingerprint directory)
        let dep_info_loc = fingerprint::dep_info_loc(context, unit);
        if let Some(paths) = fingerprint::parse_dep_info(unit.pkg, &dep_info_loc)? {
            for path in paths {
                deps.insert(path);
            }
        } else {
            debug!("can't find dep_info for {:?} {:?}",
                unit.pkg.package_id(), unit.profile);
            return Err(internal("dep_info missing"));
        }
    }

    // Add rerun-if-changed dependencies
    let key = (unit.pkg.package_id().clone(), unit.kind);
    if let Some(output) = context.build_state.outputs.lock().unwrap().get(&key) {
        for path in &output.rerun_if_changed {
            deps.insert(path.into());
        }
    }

    // Recursively traverse all transitive dependencies
    for dep_unit in &context.dep_targets(unit)? {
        let source_id = dep_unit.pkg.package_id().source_id();
        if source_id.is_path() {
            add_deps_for_unit(deps, context, dep_unit, visited)?;
        }
    }
    Ok(())
}

pub fn output_depinfo<'a, 'b>(context: &mut Context<'a, 'b>, unit: &Unit<'a>) -> CargoResult<()> {
    let mut deps = HashSet::new();
    let mut visited = HashSet::new();
    let success = add_deps_for_unit(&mut deps, context, unit, &mut visited).is_ok();
    let basedir_string;
    let basedir = match context.config.get_path("build.dep-info-basedir")? {
        Some(value) => {
            basedir_string = value.val.as_os_str().to_str().
              ok_or_else(|| internal("build.dep-info-basedir path not utf-8"))?.to_string();
            Some(basedir_string.as_str())
        }
        None => None,
    };
    for &(_, ref link_dst, _) in context.target_filenames(unit)?.iter() {
        if let Some(ref link_dst) = *link_dst {
            let output_path = link_dst.with_extension("d");
            if success {
                let mut outfile = BufWriter::new(File::create(output_path)?);
                let target_fn = render_filename(link_dst, basedir)?;
                write!(outfile, "{}:", target_fn)?;
                for dep in &deps {
                    write!(outfile, " {}", render_filename(dep, basedir)?)?;
                }
                writeln!(outfile, "")?;

            // dep-info generation failed, so delete output file. This will
            // usually cause the build system to always rerun the build
            // rule, which is correct if inefficient.
            } else if output_path.exists() {
                paths::remove_file(output_path)?;
            }
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::process::Command;

// represents an archive we download from crates.io
#[derive(Debug)]
struct KrateSource {
    version: String,
    name: String,
}

// represents the extracted sourcecode of a crate
#[derive(Debug)]
struct Krate {
    version: String,
    name: String,
    path: PathBuf,
}

impl KrateSource {
    fn new(name: &str, version: &str) -> Self {
        KrateSource {
            version: version.into(),
            name: name.into(),
        }
    }
    fn download_and_extract(&self) -> Krate {
        let extract_dir = PathBuf::from("target/crater/crates");

        // download
        let krate_download_dir = PathBuf::from("target/crater/downloads");

        let url = format!(
            "https://crates.io/api/v1/crates/{}/{}/download",
            self.name, self.version
        );
        println!("Downloading {}, {} / {}", self.name, self.version, url);
        let _ = std::fs::create_dir("target/crater/");

        let _ = std::fs::create_dir(&krate_download_dir);
        let _ = std::fs::create_dir(&extract_dir);

        let krate_name = format!("{}-{}.crate.tar.gz", &self.name, &self.version);
        let krate_file_path = krate_download_dir.join(krate_name);
        let mut krate_dest = std::fs::File::create(&krate_file_path).unwrap();
        let mut krate_req = ureq::get(&url).call().unwrap().into_reader();
        std::io::copy(&mut krate_req, &mut krate_dest).unwrap();
        // unzip the tarball
        let dl = std::fs::File::open(krate_file_path).unwrap();

        let ungz_tar = flate2::read::GzDecoder::new(dl);
        // extract the tar archive
        let mut archiv = tar::Archive::new(ungz_tar);
        let extract_path = extract_dir.join(format!("{}-{}/", self.name, self.version));
        archiv.unpack(&extract_path).expect("Failed to extract!");
        // extracted

        Krate {
            version: self.version.clone(),
            name: self.name.clone(),
            path: extract_path,
        }
    }
}

impl Krate {
    fn run_clippy_lints(&self) -> String {
        todo!();
    }
}

fn build_clippy() {
    Command::new("cargo")
        .arg("build")
        .output()
        .expect("Failed to build clippy!");
}

// the main fn
pub fn run() {
    let cargo_clippy_path: PathBuf = PathBuf::from("target/debug/cargo-clippy");
    let clippy_driver_path: PathBuf = PathBuf::from("target/debug/clippy-driver");

    // crates we want to check:
    let krates: Vec<KrateSource> = vec![KrateSource::new("cargo", "0.49.0"), KrateSource::new("regex", "1.4.2")];

    println!("Compiling clippy...");
    build_clippy();
    println!("Done compiling");

    // assert that clippy is found
    assert!(
        cargo_clippy_path.is_file(),
        "target/debug/cargo-clippy binary not found! {}",
        cargo_clippy_path.display()
    );
    assert!(
        clippy_driver_path.is_file(),
        "target/debug/clippy-driver binary not found! {}",
        clippy_driver_path.display()
    );

    // download and extract the crates, then run clippy on them and collect clippys warnings
    let _clippy_lint_results: Vec<String> = krates
        .into_iter()
        .map(|krate| krate.download_and_extract())
        .map(|krate| krate.run_clippy_lints())
        .collect::<Vec<String>>();
}
<commit_msg>clippy cargo dev: fix checking of crates<commit_after>use std::path::PathBuf;
use std::process::Command;

// represents an archive we download from crates.io
#[derive(Debug)]
struct KrateSource {
    version: String,
    name: String,
}

// represents the extracted sourcecode of a crate
#[derive(Debug)]
struct Krate {
    version: String,
    name: String,
    path: PathBuf,
}

impl KrateSource {
    fn new(name: &str, version: &str) -> Self {
        KrateSource {
            version: version.into(),
            name: name.into(),
        }
    }
    fn download_and_extract(&self) -> Krate {
        let extract_dir = PathBuf::from("target/crater/crates");

        // download
        let krate_download_dir = PathBuf::from("target/crater/downloads");

        let url = format!(
            "https://crates.io/api/v1/crates/{}/{}/download",
            self.name, self.version
        );
        println!("Downloading {}, {} / {}", self.name, self.version, url);
        let _ = std::fs::create_dir("target/crater/");

        let _ = std::fs::create_dir(&krate_download_dir);
        let _ = std::fs::create_dir(&extract_dir);

        let krate_name = format!("{}-{}.crate.tar.gz", &self.name, &self.version);
        let krate_file_path = krate_download_dir.join(krate_name);
        let mut krate_dest = std::fs::File::create(&krate_file_path).unwrap();
        let mut krate_req = ureq::get(&url).call().unwrap().into_reader();
        std::io::copy(&mut krate_req, &mut krate_dest).unwrap();
        // unzip the tarball
        let dl = std::fs::File::open(krate_file_path).unwrap();

        let ungz_tar = flate2::read::GzDecoder::new(dl);
        // extract the tar archive
        let mut archiv = tar::Archive::new(ungz_tar);
        let extract_path = extract_dir.clone();
        archiv.unpack(&extract_path).expect("Failed to extract!");
        // extracted
        dbg!(&extract_path);
        Krate {
            version: self.version.clone(),
            name: self.name.clone(),
            path: extract_dir.join(format!("{}-{}/", self.name, self.version))
        }
    }
}

impl Krate {
    fn run_clippy_lints(&self, cargo_clippy_path:  &PathBuf) -> String {
        let cargo_clippy_path = std::fs::canonicalize(cargo_clippy_path).unwrap();
        let project_root = &self.path;
        dbg!(&cargo_clippy_path);
        dbg!(&project_root);

        let output = std::process::Command::new(cargo_clippy_path).current_dir(project_root).output();
        dbg!(&output);
        let output = String::from_utf8_lossy(&output.unwrap().stderr).into_owned();
        dbg!(&output);
        output
    }
}

fn build_clippy() {
    Command::new("cargo")
        .arg("build")
        .output()
        .expect("Failed to build clippy!");
}

// the main fn
pub fn run() {
    let cargo_clippy_path: PathBuf = PathBuf::from("target/debug/cargo-clippy");
    let clippy_driver_path: PathBuf = PathBuf::from("target/debug/clippy-driver");

    // crates we want to check:
    let krates: Vec<KrateSource> = vec![KrateSource::new("regex", "1.4.2"), KrateSource::new("cargo", "0.49.0"), ];

    println!("Compiling clippy...");
    build_clippy();
    println!("Done compiling");

    // assert that clippy is found
    assert!(
        cargo_clippy_path.is_file(),
        "target/debug/cargo-clippy binary not found! {}",
        cargo_clippy_path.display()
    );
    assert!(
        clippy_driver_path.is_file(),
        "target/debug/clippy-driver binary not found! {}",
        clippy_driver_path.display()
     );

    // download and extract the crates, then run clippy on them and collect clippys warnings
    let _clippy_lint_results: Vec<String> = krates
        .into_iter()
        .map(|krate| krate.download_and_extract())
        .map(|krate| krate.run_clippy_lints(&cargo_clippy_path))
        .collect::<Vec<String>>();
}
<|endoftext|>


<commit_before>// Copyright (C) 2019 Guillaume Desmottes <guillaume.desmottes@collabora.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use cdg;
use cdg_renderer;
use glib;
use glib::subclass;
use glib::subclass::prelude::*;
use gst;
use gst::subclass::prelude::*;
use gst_video::prelude::VideoDecoderExtManual;
use gst_video::prelude::*;
use gst_video::subclass::prelude::*;
use gstreamer_video as gst_video;
use image::GenericImageView;
use std::sync::Mutex;

use crate::constants::{CDG_HEIGHT, CDG_WIDTH};

struct CdgDec {
    cdg_inter: Mutex<cdg_renderer::CdgInterpreter>,
    output_info: Mutex<Option<gst_video::VideoInfo>>,
}

lazy_static! {
    static ref CAT: gst::DebugCategory =
        gst::DebugCategory::new("cdgdec", gst::DebugColorFlags::empty(), Some("CDG decoder"),);
}

impl ObjectSubclass for CdgDec {
    const NAME: &'static str = "CdgDec";
    type ParentType = gst_video::VideoDecoder;
    type Instance = gst::subclass::ElementInstanceStruct<Self>;
    type Class = subclass::simple::ClassStruct<Self>;

    glib_object_subclass!();

    fn new() -> Self {
        Self {
            cdg_inter: Mutex::new(cdg_renderer::CdgInterpreter::new()),
            output_info: Mutex::new(None),
        }
    }

    fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
        klass.set_metadata(
            "CDG decoder",
            "Decoder/Video",
            "CDG decoder",
            "Guillaume Desmottes <guillaume.desmottes@collabora.com>",
        );

        let sink_caps = gst::Caps::new_simple("video/x-cdg", &[("parsed", &true)]);
        let sink_pad_template = gst::PadTemplate::new(
            "sink",
            gst::PadDirection::Sink,
            gst::PadPresence::Always,
            &sink_caps,
        )
        .unwrap();
        klass.add_pad_template(sink_pad_template);

        let src_caps = gst::Caps::new_simple(
            "video/x-raw",
            &[
                ("format", &gst_video::VideoFormat::Rgba.to_str()),
                ("width", &(CDG_WIDTH as i32)),
                ("height", &(CDG_HEIGHT as i32)),
                ("framerate", &gst::Fraction::new(0, 1)),
            ],
        );
        let src_pad_template = gst::PadTemplate::new(
            "src",
            gst::PadDirection::Src,
            gst::PadPresence::Always,
            &src_caps,
        )
        .unwrap();
        klass.add_pad_template(src_pad_template);
    }
}

impl ObjectImpl for CdgDec {
    glib_object_impl!();
}

impl ElementImpl for CdgDec {}

impl VideoDecoderImpl for CdgDec {
    fn start(&self, element: &gst_video::VideoDecoder) -> Result<(), gst::ErrorMessage> {
        let mut out_info = self.output_info.lock().unwrap();
        *out_info = None;

        self.parent_start(element)
    }

    fn handle_frame(
        &self,
        element: &gst_video::VideoDecoder,
        mut frame: gst_video::VideoCodecFrame,
    ) -> Result<gst::FlowSuccess, gst::FlowError> {
        {
            let mut out_info = self.output_info.lock().unwrap();
            if out_info.is_none() {
                let output_state = element.set_output_state(
                    gst_video::VideoFormat::Rgba,
                    CDG_WIDTH,
                    CDG_HEIGHT,
                    None,
                )?;

                element.negotiate(output_state)?;

                let out_state = element.get_output_state().unwrap();
                *out_info = Some(out_state.get_info());
            }
        }

        let cmd = {
            let input = frame.get_input_buffer().unwrap();
            let map = input.map_readable().map_err(|_| {
                gst_element_error!(
                    element,
                    gst::CoreError::Failed,
                    ["Failed to map input buffer readable"]
                );
                gst::FlowError::Error
            })?;
            let data = map.as_slice();

            cdg::decode_subchannel_cmd(&data)
        };

        let cmd = match cmd {
            Some(cmd) => cmd,
            None => {
                // Not a CDG command
                element.release_frame(frame);
                return Ok(gst::FlowSuccess::Ok);
            }
        };

        let mut cdg_inter = self.cdg_inter.lock().unwrap();
        cdg_inter.handle_cmd(cmd);

        element.allocate_output_frame(&mut frame, None)?;
        {
            let output = frame.get_output_buffer_mut().unwrap();
            let info = self.output_info.lock().unwrap();

            let mut out_frame =
                gst_video::VideoFrameRef::from_buffer_ref_writable(output, info.as_ref().unwrap())
                    .map_err(|_| {
                        gst_element_error!(
                            element,
                            gst::CoreError::Failed,
                            ["Failed to map output buffer writable"]
                        );
                        gst::FlowError::Error
                    })?;

            let out_stride = out_frame.plane_stride()[0] as usize;

            for (y, line) in out_frame
                .plane_data_mut(0)
                .unwrap()
                .chunks_exact_mut(out_stride)
                .take(CDG_HEIGHT as usize)
                .enumerate()
            {
                for (x, pixel) in line
                    .chunks_exact_mut(4)
                    .take(CDG_WIDTH as usize)
                    .enumerate()
                {
                    let p = cdg_inter.get_pixel(x as u32, y as u32);
                    pixel.copy_from_slice(&p.0);
                }
            }
        }

        gst_debug!(CAT, obj: element, "Finish frame pts={}", frame.get_pts());

        element.finish_frame(frame)
    }

    fn decide_allocation(
        &self,
        element: &gst_video::VideoDecoder,
        query: &mut gst::QueryRef,
    ) -> Result<(), gst::ErrorMessage> {
        if let gst::query::QueryView::Allocation(allocation) = query.view() {
            if allocation
                .find_allocation_meta::<gst_video::VideoMeta>()
                .is_some()
            {
                let pools = allocation.get_allocation_pools();
                if let Some((ref pool, _, _, _)) = pools.first() {
                    if let Some(pool) = pool {
                        let mut config = pool.get_config();
                        config.add_option(&gst_video::BUFFER_POOL_OPTION_VIDEO_META);
                        pool.set_config(config).map_err(|e| {
                            gst::gst_error_msg!(gst::CoreError::Negotiation, [&e.message])
                        })?;
                    }
                }
            }
        }

        self.parent_decide_allocation(element, query)
    }

    fn flush(&self, element: &gst_video::VideoDecoder) -> bool {
        gst_debug!(CAT, obj: element, "flushing, reset CDG interpreter");

        let mut cdg_inter = self.cdg_inter.lock().unwrap();
        cdg_inter.reset(false);
        true
    }
}

pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
    gst::Element::register(
        Some(plugin),
        "cdgdec",
        gst::Rank::Primary,
        CdgDec::get_type(),
    )
}
<commit_msg>cdgdec: reset the interpreter when stopping<commit_after>// Copyright (C) 2019 Guillaume Desmottes <guillaume.desmottes@collabora.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use cdg;
use cdg_renderer;
use glib;
use glib::subclass;
use glib::subclass::prelude::*;
use gst;
use gst::subclass::prelude::*;
use gst_video::prelude::VideoDecoderExtManual;
use gst_video::prelude::*;
use gst_video::subclass::prelude::*;
use gstreamer_video as gst_video;
use image::GenericImageView;
use std::sync::Mutex;

use crate::constants::{CDG_HEIGHT, CDG_WIDTH};

struct CdgDec {
    cdg_inter: Mutex<cdg_renderer::CdgInterpreter>,
    output_info: Mutex<Option<gst_video::VideoInfo>>,
}

lazy_static! {
    static ref CAT: gst::DebugCategory =
        gst::DebugCategory::new("cdgdec", gst::DebugColorFlags::empty(), Some("CDG decoder"),);
}

impl ObjectSubclass for CdgDec {
    const NAME: &'static str = "CdgDec";
    type ParentType = gst_video::VideoDecoder;
    type Instance = gst::subclass::ElementInstanceStruct<Self>;
    type Class = subclass::simple::ClassStruct<Self>;

    glib_object_subclass!();

    fn new() -> Self {
        Self {
            cdg_inter: Mutex::new(cdg_renderer::CdgInterpreter::new()),
            output_info: Mutex::new(None),
        }
    }

    fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
        klass.set_metadata(
            "CDG decoder",
            "Decoder/Video",
            "CDG decoder",
            "Guillaume Desmottes <guillaume.desmottes@collabora.com>",
        );

        let sink_caps = gst::Caps::new_simple("video/x-cdg", &[("parsed", &true)]);
        let sink_pad_template = gst::PadTemplate::new(
            "sink",
            gst::PadDirection::Sink,
            gst::PadPresence::Always,
            &sink_caps,
        )
        .unwrap();
        klass.add_pad_template(sink_pad_template);

        let src_caps = gst::Caps::new_simple(
            "video/x-raw",
            &[
                ("format", &gst_video::VideoFormat::Rgba.to_str()),
                ("width", &(CDG_WIDTH as i32)),
                ("height", &(CDG_HEIGHT as i32)),
                ("framerate", &gst::Fraction::new(0, 1)),
            ],
        );
        let src_pad_template = gst::PadTemplate::new(
            "src",
            gst::PadDirection::Src,
            gst::PadPresence::Always,
            &src_caps,
        )
        .unwrap();
        klass.add_pad_template(src_pad_template);
    }
}

impl ObjectImpl for CdgDec {
    glib_object_impl!();
}

impl ElementImpl for CdgDec {}

impl VideoDecoderImpl for CdgDec {
    fn start(&self, element: &gst_video::VideoDecoder) -> Result<(), gst::ErrorMessage> {
        let mut out_info = self.output_info.lock().unwrap();
        *out_info = None;

        self.parent_start(element)
    }

    fn stop(&self, element: &gst_video::VideoDecoder) -> Result<(), gst::ErrorMessage> {
        {
            let mut cdg_inter = self.cdg_inter.lock().unwrap();
            cdg_inter.reset(true);
        }
        self.parent_stop(element)
    }

    fn handle_frame(
        &self,
        element: &gst_video::VideoDecoder,
        mut frame: gst_video::VideoCodecFrame,
    ) -> Result<gst::FlowSuccess, gst::FlowError> {
        {
            let mut out_info = self.output_info.lock().unwrap();
            if out_info.is_none() {
                let output_state = element.set_output_state(
                    gst_video::VideoFormat::Rgba,
                    CDG_WIDTH,
                    CDG_HEIGHT,
                    None,
                )?;

                element.negotiate(output_state)?;

                let out_state = element.get_output_state().unwrap();
                *out_info = Some(out_state.get_info());
            }
        }

        let cmd = {
            let input = frame.get_input_buffer().unwrap();
            let map = input.map_readable().map_err(|_| {
                gst_element_error!(
                    element,
                    gst::CoreError::Failed,
                    ["Failed to map input buffer readable"]
                );
                gst::FlowError::Error
            })?;
            let data = map.as_slice();

            cdg::decode_subchannel_cmd(&data)
        };

        let cmd = match cmd {
            Some(cmd) => cmd,
            None => {
                // Not a CDG command
                element.release_frame(frame);
                return Ok(gst::FlowSuccess::Ok);
            }
        };

        let mut cdg_inter = self.cdg_inter.lock().unwrap();
        cdg_inter.handle_cmd(cmd);

        element.allocate_output_frame(&mut frame, None)?;
        {
            let output = frame.get_output_buffer_mut().unwrap();
            let info = self.output_info.lock().unwrap();

            let mut out_frame =
                gst_video::VideoFrameRef::from_buffer_ref_writable(output, info.as_ref().unwrap())
                    .map_err(|_| {
                        gst_element_error!(
                            element,
                            gst::CoreError::Failed,
                            ["Failed to map output buffer writable"]
                        );
                        gst::FlowError::Error
                    })?;

            let out_stride = out_frame.plane_stride()[0] as usize;

            for (y, line) in out_frame
                .plane_data_mut(0)
                .unwrap()
                .chunks_exact_mut(out_stride)
                .take(CDG_HEIGHT as usize)
                .enumerate()
            {
                for (x, pixel) in line
                    .chunks_exact_mut(4)
                    .take(CDG_WIDTH as usize)
                    .enumerate()
                {
                    let p = cdg_inter.get_pixel(x as u32, y as u32);
                    pixel.copy_from_slice(&p.0);
                }
            }
        }

        gst_debug!(CAT, obj: element, "Finish frame pts={}", frame.get_pts());

        element.finish_frame(frame)
    }

    fn decide_allocation(
        &self,
        element: &gst_video::VideoDecoder,
        query: &mut gst::QueryRef,
    ) -> Result<(), gst::ErrorMessage> {
        if let gst::query::QueryView::Allocation(allocation) = query.view() {
            if allocation
                .find_allocation_meta::<gst_video::VideoMeta>()
                .is_some()
            {
                let pools = allocation.get_allocation_pools();
                if let Some((ref pool, _, _, _)) = pools.first() {
                    if let Some(pool) = pool {
                        let mut config = pool.get_config();
                        config.add_option(&gst_video::BUFFER_POOL_OPTION_VIDEO_META);
                        pool.set_config(config).map_err(|e| {
                            gst::gst_error_msg!(gst::CoreError::Negotiation, [&e.message])
                        })?;
                    }
                }
            }
        }

        self.parent_decide_allocation(element, query)
    }

    fn flush(&self, element: &gst_video::VideoDecoder) -> bool {
        gst_debug!(CAT, obj: element, "flushing, reset CDG interpreter");

        let mut cdg_inter = self.cdg_inter.lock().unwrap();
        cdg_inter.reset(false);
        true
    }
}

pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
    gst::Element::register(
        Some(plugin),
        "cdgdec",
        gst::Rank::Primary,
        CdgDec::get_type(),
    )
}
<|endoftext|>


<commit_before>pub fn largest_number(nums: Vec<i32>) -> String {}

fn main() {}
<commit_msg>still a bit<commit_after>pub fn largest_number(nums: Vec<i32>) -> String {
    for n in nums {
        let this = n.to_string();
    }
}

fn main() {}
<|endoftext|>


<commit_before>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

mod alloc;
pub mod descriptor;
pub mod descriptor_reflection;
mod errno;
pub mod external_mapping;
pub mod scoped_event_macro;
mod tube;

#[cfg(unix)]
pub mod unix;

#[cfg(windows)]
pub mod windows;

pub use alloc::LayoutAllocation;
pub use errno::{errno_result, Error, Result};
pub use external_mapping::{Error as ExternalMappingError, Result as ExternalMappingResult, *};
pub use scoped_event_macro::*;
pub use tube::{Error as TubeError, RecvTube, Result as TubeResult, SendTube, Tube};

cfg_if::cfg_if! {
     if #[cfg(unix)] {
        mod event;
        mod ioctl;
        mod mmap;
        mod notifiers;
        mod shm;
        mod timer;
        mod wait_context;

        pub use unix as platform;

        pub use unix::net::*;
        pub use unix::ioctl::*;

        pub use event::{Event, EventReadResult, ScopedEvent};
        pub use crate::ioctl::{
            ioctl, ioctl_with_mut_ptr, ioctl_with_mut_ref, ioctl_with_ptr, ioctl_with_ref, ioctl_with_val,
        };
        pub use mmap::{
            MemoryMapping, MemoryMappingBuilder, MemoryMappingBuilderUnix, Unix as MemoryMappingUnix,
        };
        pub use notifiers::*;
        pub use shm::{SharedMemory, Unix as SharedMemoryUnix};
        pub use timer::{FakeTimer, Timer};
        pub use wait_context::{EventToken, EventType, TriggeredEvent, WaitContext};
     } else if #[cfg(windows)] {
        pub use windows as platform;
        pub use tube::{set_duplicate_handle_tube, set_alias_pid, DuplicateHandleTube};
     } else {
        compile_error!("Unsupported platform");
     }
}

pub use crate::descriptor::{
    AsRawDescriptor, Descriptor, FromRawDescriptor, IntoRawDescriptor, SafeDescriptor,
};
pub use platform::*;

/// Wraps an AsRawDescriptor in the simple Descriptor struct, which
/// has AsRawFd methods for interfacing with sys_util
pub fn wrap_descriptor(descriptor: &dyn AsRawDescriptor) -> Descriptor {
    Descriptor(descriptor.as_raw_descriptor())
}

/// Verifies that |raw_descriptor| is actually owned by this process and duplicates it
/// to ensure that we have a unique handle to it.
#[cfg(unix)]
pub fn validate_raw_descriptor(raw_descriptor: RawDescriptor) -> Result<RawDescriptor> {
    validate_raw_fd(raw_descriptor)
}

/// A trait similar to `AsRawDescriptor` but supports an arbitrary number of descriptors.
pub trait AsRawDescriptors {
    fn as_raw_descriptors(&self) -> Vec<RawDescriptor>;
}

impl<T> AsRawDescriptors for T
where
    T: AsRawDescriptor,
{
    fn as_raw_descriptors(&self) -> Vec<RawDescriptor> {
        vec![self.as_raw_descriptor()]
    }
}
<commit_msg>base: remove wrap_descriptor<commit_after>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

mod alloc;
pub mod descriptor;
pub mod descriptor_reflection;
mod errno;
pub mod external_mapping;
pub mod scoped_event_macro;
mod tube;

#[cfg(unix)]
pub mod unix;

#[cfg(windows)]
pub mod windows;

pub use alloc::LayoutAllocation;
pub use errno::{errno_result, Error, Result};
pub use external_mapping::{Error as ExternalMappingError, Result as ExternalMappingResult, *};
pub use scoped_event_macro::*;
pub use tube::{Error as TubeError, RecvTube, Result as TubeResult, SendTube, Tube};

cfg_if::cfg_if! {
     if #[cfg(unix)] {
        mod event;
        mod ioctl;
        mod mmap;
        mod notifiers;
        mod shm;
        mod timer;
        mod wait_context;

        pub use unix as platform;

        pub use unix::net::*;
        pub use unix::ioctl::*;

        pub use event::{Event, EventReadResult, ScopedEvent};
        pub use crate::ioctl::{
            ioctl, ioctl_with_mut_ptr, ioctl_with_mut_ref, ioctl_with_ptr, ioctl_with_ref, ioctl_with_val,
        };
        pub use mmap::{
            MemoryMapping, MemoryMappingBuilder, MemoryMappingBuilderUnix, Unix as MemoryMappingUnix,
        };
        pub use notifiers::*;
        pub use shm::{SharedMemory, Unix as SharedMemoryUnix};
        pub use timer::{FakeTimer, Timer};
        pub use wait_context::{EventToken, EventType, TriggeredEvent, WaitContext};
     } else if #[cfg(windows)] {
        pub use windows as platform;
        pub use tube::{set_duplicate_handle_tube, set_alias_pid, DuplicateHandleTube};
     } else {
        compile_error!("Unsupported platform");
     }
}

pub use crate::descriptor::{
    AsRawDescriptor, Descriptor, FromRawDescriptor, IntoRawDescriptor, SafeDescriptor,
};
pub use platform::*;

/// Verifies that |raw_descriptor| is actually owned by this process and duplicates it
/// to ensure that we have a unique handle to it.
#[cfg(unix)]
pub fn validate_raw_descriptor(raw_descriptor: RawDescriptor) -> Result<RawDescriptor> {
    validate_raw_fd(raw_descriptor)
}

/// A trait similar to `AsRawDescriptor` but supports an arbitrary number of descriptors.
pub trait AsRawDescriptors {
    fn as_raw_descriptors(&self) -> Vec<RawDescriptor>;
}

impl<T> AsRawDescriptors for T
where
    T: AsRawDescriptor,
{
    fn as_raw_descriptors(&self) -> Vec<RawDescriptor> {
        vec![self.as_raw_descriptor()]
    }
}
<|endoftext|>


<commit_before>// `impl Trait` is not required for this parser but we use to to show that it can be used to
// significantly simplify things
#![feature(conservative_impl_trait)]

#[macro_use]
extern crate bencher;

#[macro_use]
extern crate combine;

use std::collections::HashMap;
use std::io::Read;
use std::fs::File;
use std::path::Path;

use bencher::{black_box, Bencher};

use combine::stream::buffered::BufferedStream;
use combine::{Parser, Stream, StreamOnce};
use combine::error::{Consumed, ParseError};

use combine::parser::char::{char, digit, spaces, string};
use combine::parser::item::{any, satisfy, satisfy_map};
use combine::parser::sequence::between;
use combine::parser::repeat::{many, sep_by, many1};
use combine::parser::choice::{choice, optional};
use combine::parser::function::parser;

use combine::stream::IteratorStream;
use combine::stream::state::{SourcePosition, State};

#[derive(PartialEq, Debug)]
enum Value {
    Number(f64),
    String(String),
    Bool(bool),
    Null,
    Object(HashMap<String, Value>),
    Array(Vec<Value>),
}

fn lex<P>(p: P) -> impl Parser<Input = P::Input, Output = P::Output>
where
    P: Parser,
    P::Input: Stream<Item = char>,
    <P::Input as StreamOnce>::Error: ParseError<
        <P::Input as StreamOnce>::Item,
        <P::Input as StreamOnce>::Range,
        <P::Input as StreamOnce>::Position,
    >,
{
    p.skip(spaces())
}

fn integer<I>() -> impl Parser<Input = I, Output = i64>
where
    I: Stream<Item = char>,
    I::Error: ParseError<I::Item, I::Range, I::Position>,
{
    lex(many1(digit()))
        .map(|s: String| {
            let mut n = 0;
            for c in s.chars() {
                n = n * 10 + (c as i64 - '0' as i64);
            }
            n
        })
        .expected("integer")
}

fn number<I>() -> impl Parser<Input = I, Output = f64>
where
    I: Stream<Item = char>,
    I::Error: ParseError<I::Item, I::Range, I::Position>,
{
    let i = char('0').map(|_| 0.0).or(integer().map(|x| x as f64));
    let fractional = many(digit()).map(|digits: String| {
        let mut magnitude = 1.0;
        digits.chars().fold(0.0, |acc, d| {
            magnitude /= 10.0;
            match d.to_digit(10) {
                Some(d) => acc + (d as f64) * magnitude,
                None => panic!("Not a digit"),
            }
        })
    });

    let exp = satisfy(|c| c == 'e' || c == 'E').with(optional(char('-')).and(integer()));
    lex(optional(char('-'))
        .and(i)
        .map(|(sign, n)| if sign.is_some() { -n } else { n })
        .and(optional(char('.')).with(fractional))
        .map(|(x, y)| if x >= 0.0 { x + y } else { x - y })
        .and(optional(exp))
        .map(|(n, exp_option)| match exp_option {
            Some((sign, e)) => {
                let e = if sign.is_some() { -e } else { e };
                n * 10.0f64.powi(e as i32)
            }
            None => n,
        })).expected("number")
}

fn json_char<I>() -> impl Parser<Input = I, Output = char>
where
    I: Stream<Item = char>,
    I::Error: ParseError<I::Item, I::Range, I::Position>,
{
    parser(|input: &mut I| {
        let (c, consumed) = try!(any().parse_lazy(input).into());
        let mut back_slash_char = satisfy_map(|c| {
            Some(match c {
                '"' => '"',
                '\\' => '\\',
                '/' => '/',
                'b' => '\u{0008}',
                'f' => '\u{000c}',
                'n' => '\n',
                'r' => '\r',
                't' => '\t',
                _ => return None,
            })
        });
        match c {
            '\\' => consumed.combine(|_| back_slash_char.parse_stream(input)),
            '"' => Err(Consumed::Empty(I::Error::empty(input.position()).into())),
            _ => Ok((c, consumed)),
        }
    })
}

fn json_string<I>() -> impl Parser<Input = I, Output = String>
where
    I: Stream<Item = char>,
    I::Error: ParseError<I::Item, I::Range, I::Position>,
{
    between(char('"'), lex(char('"')), many(json_char())).expected("string")
}

fn object<I>() -> impl Parser<Input = I, Output = Value>
where
    I: Stream<Item = char>,
    I::Error: ParseError<I::Item, I::Range, I::Position>,
{
    let field = (json_string(), lex(char(':')), json_value()).map(|t| (t.0, t.2));
    let fields = sep_by(field, lex(char(',')));
    between(lex(char('{')), lex(char('}')), fields)
        .map(Value::Object)
        .expected("object")
}

#[inline(always)]
fn json_value<I>() -> impl Parser<Input = I, Output = Value>
where
    I: Stream<Item = char>,
    I::Error: ParseError<I::Item, I::Range, I::Position>,
{
    json_value_()
}

// We need to use `parser!` to break the recursive use of `value` to prevent the returned parser
// from containing itself
parser!{
    #[inline(always)]
    fn json_value_[I]()(I) -> Value
        where [ I: Stream<Item = char> ]
    {
        let array = between(
            lex(char('[')),
            lex(char(']')),
            sep_by(json_value(), lex(char(','))),
        ).map(Value::Array);

        choice((
            json_string().map(Value::String),
            object(),
            array,
            number().map(Value::Number),
            lex(string("false").map(|_| Value::Bool(false))),
            lex(string("true").map(|_| Value::Bool(true))),
            lex(string("null").map(|_| Value::Null)),
        ))
    }
}

#[test]
fn json_test() {
    use self::Value::*;
    let input = r#"{
    "array": [1, ""],
    "object": {},
    "number": 3.14,
    "small_number": 0.59,
    "int": -100,
    "exp": -1e2,
    "exp_neg": 23e-2,
    "true": true,
    "false"  : false,
    "null" : null
}"#;
    let result = json_value().easy_parse(input);
    let expected = Object(
        vec![
            ("array", Array(vec![Number(1.0), String("".to_string())])),
            ("object", Object(HashMap::new())),
            ("number", Number(3.14)),
            ("small_number", Number(0.59)),
            ("int", Number(-100.)),
            ("exp", Number(-1e2)),
            ("exp_neg", Number(23E-2)),
            ("true", Bool(true)),
            ("false", Bool(false)),
            ("null", Null),
        ].into_iter()
            .map(|(k, v)| (k.to_string(), v))
            .collect(),
    );
    match result {
        Ok(result) => assert_eq!(result, (expected, "")),
        Err(e) => {
            println!("{}", e);
            assert!(false);
        }
    }
}

fn test_data() -> String {
    let mut data = String::new();
    File::open(&Path::new(&"benches/data.json"))
        .and_then(|mut file| file.read_to_string(&mut data))
        .unwrap();
    data
}

fn bench_json(bencher: &mut Bencher) {
    let data = test_data();
    let mut parser = json_value();
    match parser.easy_parse(State::new(&data[..])) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => assert!(false),
        Err(err) => {
            println!("{}", err);
            assert!(false);
        }
    }
    bencher.iter(|| {
        let result = parser.easy_parse(State::new(&data[..]));
        black_box(result)
    });
}

fn bench_json_core_error(bencher: &mut Bencher) {
    let data = test_data();
    let mut parser = json_value();
    match parser.parse(State::new(&data[..])) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => assert!(false),
        Err(err) => {
            println!("{}", err);
            assert!(false);
        }
    }
    bencher.iter(|| {
        let result = parser.parse(State::new(&data[..]));
        black_box(result)
    });
}

fn bench_json_core_error_no_position(bencher: &mut Bencher) {
    let data = test_data();
    let mut parser = json_value();
    match parser.parse(&data[..]) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => assert!(false),
        Err(err) => {
            println!("{}", err);
            assert!(false);
        }
    }
    bencher.iter(|| {
        let result = parser.parse(&data[..]);
        black_box(result)
    });
}

fn bench_buffered_json(bencher: &mut Bencher) {
    let data = test_data();
    bencher.iter(|| {
        let buffer = BufferedStream::new(State::new(IteratorStream::new(data.chars())), 1);
        let mut parser = json_value();
        match parser.easy_parse(State::with_positioner(buffer, SourcePosition::default())) {
            Ok((Value::Array(v), _)) => {
                black_box(v);
            }
            Ok(_) => assert!(false),
            Err(err) => {
                println!("{}", err);
                assert!(false);
            }
        }
    });
}

benchmark_group!(
    json,
    bench_json,
    bench_json_core_error,
    bench_json_core_error_no_position,
    bench_buffered_json
);
benchmark_main!(json);
<commit_msg>Remove feature conservative_impl_trait from the json parser<commit_after>// `impl Trait` is not required for this parser but we use to to show that it can be used to
// significantly simplify things

#[macro_use]
extern crate bencher;

#[macro_use]
extern crate combine;

use std::collections::HashMap;
use std::io::Read;
use std::fs::File;
use std::path::Path;

use bencher::{black_box, Bencher};

use combine::stream::buffered::BufferedStream;
use combine::{Parser, Stream, StreamOnce};
use combine::error::{Consumed, ParseError};

use combine::parser::char::{char, digit, spaces, string};
use combine::parser::item::{any, satisfy, satisfy_map};
use combine::parser::sequence::between;
use combine::parser::repeat::{many, sep_by, many1};
use combine::parser::choice::{choice, optional};
use combine::parser::function::parser;

use combine::stream::IteratorStream;
use combine::stream::state::{SourcePosition, State};

#[derive(PartialEq, Debug)]
enum Value {
    Number(f64),
    String(String),
    Bool(bool),
    Null,
    Object(HashMap<String, Value>),
    Array(Vec<Value>),
}

fn lex<P>(p: P) -> impl Parser<Input = P::Input, Output = P::Output>
where
    P: Parser,
    P::Input: Stream<Item = char>,
    <P::Input as StreamOnce>::Error: ParseError<
        <P::Input as StreamOnce>::Item,
        <P::Input as StreamOnce>::Range,
        <P::Input as StreamOnce>::Position,
    >,
{
    p.skip(spaces())
}

fn integer<I>() -> impl Parser<Input = I, Output = i64>
where
    I: Stream<Item = char>,
    I::Error: ParseError<I::Item, I::Range, I::Position>,
{
    lex(many1(digit()))
        .map(|s: String| {
            let mut n = 0;
            for c in s.chars() {
                n = n * 10 + (c as i64 - '0' as i64);
            }
            n
        })
        .expected("integer")
}

fn number<I>() -> impl Parser<Input = I, Output = f64>
where
    I: Stream<Item = char>,
    I::Error: ParseError<I::Item, I::Range, I::Position>,
{
    let i = char('0').map(|_| 0.0).or(integer().map(|x| x as f64));
    let fractional = many(digit()).map(|digits: String| {
        let mut magnitude = 1.0;
        digits.chars().fold(0.0, |acc, d| {
            magnitude /= 10.0;
            match d.to_digit(10) {
                Some(d) => acc + (d as f64) * magnitude,
                None => panic!("Not a digit"),
            }
        })
    });

    let exp = satisfy(|c| c == 'e' || c == 'E').with(optional(char('-')).and(integer()));
    lex(optional(char('-'))
        .and(i)
        .map(|(sign, n)| if sign.is_some() { -n } else { n })
        .and(optional(char('.')).with(fractional))
        .map(|(x, y)| if x >= 0.0 { x + y } else { x - y })
        .and(optional(exp))
        .map(|(n, exp_option)| match exp_option {
            Some((sign, e)) => {
                let e = if sign.is_some() { -e } else { e };
                n * 10.0f64.powi(e as i32)
            }
            None => n,
        })).expected("number")
}

fn json_char<I>() -> impl Parser<Input = I, Output = char>
where
    I: Stream<Item = char>,
    I::Error: ParseError<I::Item, I::Range, I::Position>,
{
    parser(|input: &mut I| {
        let (c, consumed) = try!(any().parse_lazy(input).into());
        let mut back_slash_char = satisfy_map(|c| {
            Some(match c {
                '"' => '"',
                '\\' => '\\',
                '/' => '/',
                'b' => '\u{0008}',
                'f' => '\u{000c}',
                'n' => '\n',
                'r' => '\r',
                't' => '\t',
                _ => return None,
            })
        });
        match c {
            '\\' => consumed.combine(|_| back_slash_char.parse_stream(input)),
            '"' => Err(Consumed::Empty(I::Error::empty(input.position()).into())),
            _ => Ok((c, consumed)),
        }
    })
}

fn json_string<I>() -> impl Parser<Input = I, Output = String>
where
    I: Stream<Item = char>,
    I::Error: ParseError<I::Item, I::Range, I::Position>,
{
    between(char('"'), lex(char('"')), many(json_char())).expected("string")
}

fn object<I>() -> impl Parser<Input = I, Output = Value>
where
    I: Stream<Item = char>,
    I::Error: ParseError<I::Item, I::Range, I::Position>,
{
    let field = (json_string(), lex(char(':')), json_value()).map(|t| (t.0, t.2));
    let fields = sep_by(field, lex(char(',')));
    between(lex(char('{')), lex(char('}')), fields)
        .map(Value::Object)
        .expected("object")
}

#[inline(always)]
fn json_value<I>() -> impl Parser<Input = I, Output = Value>
where
    I: Stream<Item = char>,
    I::Error: ParseError<I::Item, I::Range, I::Position>,
{
    json_value_()
}

// We need to use `parser!` to break the recursive use of `value` to prevent the returned parser
// from containing itself
parser!{
    #[inline(always)]
    fn json_value_[I]()(I) -> Value
        where [ I: Stream<Item = char> ]
    {
        let array = between(
            lex(char('[')),
            lex(char(']')),
            sep_by(json_value(), lex(char(','))),
        ).map(Value::Array);

        choice((
            json_string().map(Value::String),
            object(),
            array,
            number().map(Value::Number),
            lex(string("false").map(|_| Value::Bool(false))),
            lex(string("true").map(|_| Value::Bool(true))),
            lex(string("null").map(|_| Value::Null)),
        ))
    }
}

#[test]
fn json_test() {
    use self::Value::*;
    let input = r#"{
    "array": [1, ""],
    "object": {},
    "number": 3.14,
    "small_number": 0.59,
    "int": -100,
    "exp": -1e2,
    "exp_neg": 23e-2,
    "true": true,
    "false"  : false,
    "null" : null
}"#;
    let result = json_value().easy_parse(input);
    let expected = Object(
        vec![
            ("array", Array(vec![Number(1.0), String("".to_string())])),
            ("object", Object(HashMap::new())),
            ("number", Number(3.14)),
            ("small_number", Number(0.59)),
            ("int", Number(-100.)),
            ("exp", Number(-1e2)),
            ("exp_neg", Number(23E-2)),
            ("true", Bool(true)),
            ("false", Bool(false)),
            ("null", Null),
        ].into_iter()
            .map(|(k, v)| (k.to_string(), v))
            .collect(),
    );
    match result {
        Ok(result) => assert_eq!(result, (expected, "")),
        Err(e) => {
            println!("{}", e);
            assert!(false);
        }
    }
}

fn test_data() -> String {
    let mut data = String::new();
    File::open(&Path::new(&"benches/data.json"))
        .and_then(|mut file| file.read_to_string(&mut data))
        .unwrap();
    data
}

fn bench_json(bencher: &mut Bencher) {
    let data = test_data();
    let mut parser = json_value();
    match parser.easy_parse(State::new(&data[..])) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => assert!(false),
        Err(err) => {
            println!("{}", err);
            assert!(false);
        }
    }
    bencher.iter(|| {
        let result = parser.easy_parse(State::new(&data[..]));
        black_box(result)
    });
}

fn bench_json_core_error(bencher: &mut Bencher) {
    let data = test_data();
    let mut parser = json_value();
    match parser.parse(State::new(&data[..])) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => assert!(false),
        Err(err) => {
            println!("{}", err);
            assert!(false);
        }
    }
    bencher.iter(|| {
        let result = parser.parse(State::new(&data[..]));
        black_box(result)
    });
}

fn bench_json_core_error_no_position(bencher: &mut Bencher) {
    let data = test_data();
    let mut parser = json_value();
    match parser.parse(&data[..]) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => assert!(false),
        Err(err) => {
            println!("{}", err);
            assert!(false);
        }
    }
    bencher.iter(|| {
        let result = parser.parse(&data[..]);
        black_box(result)
    });
}

fn bench_buffered_json(bencher: &mut Bencher) {
    let data = test_data();
    bencher.iter(|| {
        let buffer = BufferedStream::new(State::new(IteratorStream::new(data.chars())), 1);
        let mut parser = json_value();
        match parser.easy_parse(State::with_positioner(buffer, SourcePosition::default())) {
            Ok((Value::Array(v), _)) => {
                black_box(v);
            }
            Ok(_) => assert!(false),
            Err(err) => {
                println!("{}", err);
                assert!(false);
            }
        }
    });
}

benchmark_group!(
    json,
    bench_json,
    bench_json_core_error,
    bench_json_core_error_no_position,
    bench_buffered_json
);
benchmark_main!(json);
<|endoftext|>


<commit_before>fn main()
{
  println!("Hello, world!")
}
<commit_msg>Refactoring.<commit_after>fn test()
{
  println!("transliterator!")
}
<|endoftext|>


<commit_before>use std::rc::Rc;

use cairo::{self, ImageSurface, Status};
use gdk_pixbuf::Pixbuf;
use gio;
use glib::{self, IsA};
use libc;
use locale_config::{LanguageRange, Locale};

use crate::allowed_url::{AllowedUrl, Href};
use crate::c_api::{RsvgDimensionData, RsvgPositionData, SizeCallback};
use crate::dpi::Dpi;
use crate::drawing_ctx::{DrawingCtx, RsvgRectangle};
use crate::error::{DefsLookupErrorKind, LoadingError, RenderingError};
use crate::node::{CascadedValues, RsvgNode};
use crate::pixbuf_utils::{empty_pixbuf, pixbuf_from_surface};
use crate::structure::{IntrinsicDimensions, NodeSvg};
use crate::surface_utils::{shared_surface::SharedImageSurface, shared_surface::SurfaceType};
use crate::svg::Svg;
use crate::util::rsvg_g_warning;
use url::Url;

#[derive(Clone)]
pub struct LoadOptions {
    /// Base URL
    pub base_url: Option<Url>,

    /// Whether to turn off size limits in libxml2
    pub unlimited_size: bool,

    /// Whether to keep original (undecoded) image data to embed in Cairo PDF surfaces
    pub keep_image_data: bool,

    locale: Locale,
}

impl LoadOptions {
    pub fn new(base_url: Option<Url>) -> Self {
        LoadOptions {
            base_url,
            unlimited_size: false,
            keep_image_data: false,
            locale: locale_from_environment(),
        }
    }

    pub fn with_unlimited_size(mut self, unlimited: bool) -> Self {
        self.unlimited_size = unlimited;
        self
    }

    pub fn keep_image_data(mut self, keep: bool) -> Self {
        self.keep_image_data = keep;
        self
    }

    pub fn copy_with_base_url(&self, base_url: &AllowedUrl) -> Self {
        LoadOptions {
            base_url: Some((*base_url).clone()),
            unlimited_size: self.unlimited_size,
            keep_image_data: self.keep_image_data,
            locale: self.locale.clone(),
        }
    }

    pub fn locale(&self) -> &Locale {
        &self.locale
    }
}

pub struct Handle {
    svg: Rc<Svg>,
}

impl Handle {
    pub fn from_stream<S: IsA<gio::InputStream>>(
        load_options: &LoadOptions,
        stream: &S,
        cancellable: Option<&gio::Cancellable>,
    ) -> Result<Handle, LoadingError> {
        Ok(Handle {
            svg: Rc::new(Svg::load_from_stream(load_options, stream, cancellable)?),
        })
    }

    pub fn has_sub(&self, id: &str) -> Result<bool, RenderingError> {
        match self.lookup_node(id) {
            Ok(_) => Ok(true),

            Err(DefsLookupErrorKind::NotFound) => Ok(false),

            Err(e) => Err(RenderingError::InvalidId(e)),
        }
    }

    pub fn get_dimensions(
        &self,
        dpi: Dpi,
        size_callback: &SizeCallback,
        is_testing: bool,
    ) -> Result<RsvgDimensionData, RenderingError> {
        // This function is probably called from the cairo_render functions,
        // or is being erroneously called within the size_func.
        // To prevent an infinite loop we are saving the state, and
        // returning a meaningless size.
        if size_callback.get_in_loop() {
            return Ok(RsvgDimensionData {
                width: 1,
                height: 1,
                em: 1.0,
                ex: 1.0,
            });
        }

        size_callback.start_loop();

        let res = self.get_dimensions_sub(None, dpi, size_callback, is_testing);

        size_callback.end_loop();

        res
    }

    pub fn get_dimensions_no_error(
        &self,
        dpi: Dpi,
        size_callback: &SizeCallback,
        is_testing: bool,
    ) -> RsvgDimensionData {
        match self.get_dimensions(dpi, size_callback, is_testing) {
            Ok(dimensions) => dimensions,
            Err(_) => RsvgDimensionData::empty(),
        }
    }

    pub fn get_dimensions_sub(
        &self,
        id: Option<&str>,
        dpi: Dpi,
        size_callback: &SizeCallback,
        is_testing: bool,
    ) -> Result<RsvgDimensionData, RenderingError> {
        let (ink_r, _) = self.get_geometry_sub(id, dpi, is_testing)?;

        let (w, h) = size_callback.call(ink_r.width as libc::c_int, ink_r.height as libc::c_int);

        Ok(RsvgDimensionData {
            width: w,
            height: h,
            em: ink_r.width,
            ex: ink_r.height,
        })
    }

    pub fn get_position_sub(
        &self,
        id: Option<&str>,
        dpi: Dpi,
        size_callback: &SizeCallback,
        is_testing: bool,
    ) -> Result<RsvgPositionData, RenderingError> {
        if let None = id {
            return Ok(RsvgPositionData { x: 0, y: 0 });
        }

        let (ink_r, _) = self.get_geometry_sub(id, dpi, is_testing)?;

        let width = ink_r.width as libc::c_int;
        let height = ink_r.height as libc::c_int;

        size_callback.call(width, height);

        Ok(RsvgPositionData {
            x: ink_r.x as libc::c_int,
            y: ink_r.y as libc::c_int,
        })
    }

    /// Returns (ink_rect, logical_rect)
    fn get_node_geometry_with_viewport(
        &self,
        node: &RsvgNode,
        viewport: &cairo::Rectangle,
        dpi: Dpi,
        is_testing: bool,
    ) -> Result<(RsvgRectangle, RsvgRectangle), RenderingError> {
        let target = ImageSurface::create(cairo::Format::Rgb24, 1, 1)?;
        let cr = cairo::Context::new(&target);
        let mut draw_ctx = DrawingCtx::new(
            self.svg.clone(),
            Some(node),
            &cr,
            viewport,
            dpi,
            true,
            is_testing,
        );
        let root = self.svg.root();

        draw_ctx.draw_node_from_stack(&CascadedValues::new_from_node(&root), &root, false)?;

        let bbox = draw_ctx.get_bbox();

        let ink_rect = bbox
            .ink_rect
            .map(|r| RsvgRectangle::from(r))
            .unwrap_or_default();
        let logical_rect = bbox
            .rect
            .map(|r| RsvgRectangle::from(r))
            .unwrap_or_default();

        Ok((ink_rect, logical_rect))
    }

    /// Returns (ink_rect, logical_rect)
    fn get_geometry_sub(
        &self,
        id: Option<&str>,
        dpi: Dpi,
        is_testing: bool,
    ) -> Result<(RsvgRectangle, RsvgRectangle), RenderingError> {
        let node = self.get_node_or_root(id)?;

        let root = self.svg.root();
        let is_root = node == root;

        if is_root {
            let cascaded = CascadedValues::new_from_node(&node);
            let values = cascaded.get();

            if let Some((root_width, root_height)) =
                node.borrow().get_impl::<NodeSvg>().get_size(&values, dpi)
            {
                let ink_r = RsvgRectangle {
                    x: 0.0,
                    y: 0.0,
                    width: f64::from(root_width),
                    height: f64::from(root_height),
                };

                let logical_r = ink_r;

                return Ok((ink_r, logical_r));
            }
        }

        // This is just to start with an unknown viewport size
        let viewport = cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width: 1.0,
            height: 1.0,
        };

        self.get_node_geometry_with_viewport(&node, &viewport, dpi, is_testing)
    }

    fn get_node_or_root(&self, id: Option<&str>) -> Result<RsvgNode, RenderingError> {
        if let Some(id) = id {
            self.lookup_node(id).map_err(RenderingError::InvalidId)
        } else {
            Ok(self.svg.root())
        }
    }

    pub fn get_geometry_for_element(
        &self,
        id: Option<&str>,
        viewport: &cairo::Rectangle,
        dpi: Dpi,
        is_testing: bool,
    ) -> Result<(RsvgRectangle, RsvgRectangle), RenderingError> {
        let node = self.get_node_or_root(id)?;
        self.get_node_geometry_with_viewport(&node, viewport, dpi, is_testing)
    }

    fn lookup_node(&self, id: &str) -> Result<RsvgNode, DefsLookupErrorKind> {
        match Href::parse(&id).map_err(DefsLookupErrorKind::HrefError)? {
            Href::PlainUrl(_) => Err(DefsLookupErrorKind::CannotLookupExternalReferences),
            Href::WithFragment(fragment) => {
                if let Some(uri) = fragment.uri() {
                    // The public APIs to get geometries of individual elements, or to render
                    // them, should only allow referencing elements within the main handle's
                    // SVG file; that is, only plain "#foo" fragment IDs are allowed here.
                    // Otherwise, a calling program could request "another-file#foo" and cause
                    // another-file to be loaded, even if it is not part of the set of
                    // resources that the main SVG actually references.  In the future we may
                    // relax this requirement to allow lookups within that set, but not to
                    // other random files.

                    let msg = format!(
                        "the public API is not allowed to look up external references: {}#{}",
                        uri,
                        fragment.fragment()
                    );

                    rsvg_log!("{}", msg);

                    rsvg_g_warning(&msg);
                    return Err(DefsLookupErrorKind::CannotLookupExternalReferences);
                }

                match self.svg.lookup_node_by_id(fragment.fragment()) {
                    Some(n) => Ok(n),
                    None => Err(DefsLookupErrorKind::NotFound),
                }
            }
        }
    }

    pub fn render_cairo_sub(
        &self,
        cr: &cairo::Context,
        id: Option<&str>,
        dpi: Dpi,
        size_callback: &SizeCallback,
        is_testing: bool,
    ) -> Result<(), RenderingError> {
        check_cairo_context(cr)?;

        let dimensions = self.get_dimensions(dpi, size_callback, is_testing)?;
        if dimensions.width == 0 || dimensions.height == 0 {
            // nothing to render
            return Ok(());
        }

        let viewport = cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width: f64::from(dimensions.width),
            height: f64::from(dimensions.height),
        };

        self.render_element_to_viewport(cr, id, &viewport, dpi, is_testing)
    }

    pub fn render_element_to_viewport(
        &self,
        cr: &cairo::Context,
        id: Option<&str>,
        viewport: &cairo::Rectangle,
        dpi: Dpi,
        is_testing: bool,
    ) -> Result<(), RenderingError> {
        check_cairo_context(cr)?;

        let node = if let Some(id) = id {
            Some(self.lookup_node(id).map_err(RenderingError::InvalidId)?)
        } else {
            None
        };

        let root = self.svg.root();

        cr.save();
        let mut draw_ctx = DrawingCtx::new(
            self.svg.clone(),
            node.as_ref(),
            cr,
            viewport,
            dpi,
            false,
            is_testing,
        );
        let cascaded = CascadedValues::new_from_node(&root);
        let res = draw_ctx.draw_node_from_stack(&cascaded, &root, false);
        cr.restore();

        res
    }

    pub fn get_pixbuf_sub(
        &self,
        id: Option<&str>,
        dpi: Dpi,
        size_callback: &SizeCallback,
        is_testing: bool,
    ) -> Result<Pixbuf, RenderingError> {
        let dimensions = self.get_dimensions(dpi, size_callback, is_testing)?;

        if dimensions.width == 0 || dimensions.height == 0 {
            return empty_pixbuf();
        }

        let surface =
            ImageSurface::create(cairo::Format::ARgb32, dimensions.width, dimensions.height)?;

        {
            let cr = cairo::Context::new(&surface);
            self.render_cairo_sub(&cr, id, dpi, size_callback, is_testing)?;
        }

        let surface = SharedImageSurface::new(surface, SurfaceType::SRgb)?;

        pixbuf_from_surface(&surface)
    }

    pub fn get_intrinsic_dimensions(&self) -> IntrinsicDimensions {
        self.svg.get_intrinsic_dimensions()
    }
}

fn check_cairo_context(cr: &cairo::Context) -> Result<(), RenderingError> {
    let status = cr.status();
    if status == Status::Success {
        Ok(())
    } else {
        let msg = format!(
            "cannot render on a cairo_t with a failure status (status={:?})",
            status,
        );

        rsvg_g_warning(&msg);
        Err(RenderingError::Cairo(status))
    }
}

/// Gets the user's preferred locale from the environment and
/// translates it to a `Locale` with `LanguageRange` fallbacks.
///
/// The `Locale::current()` call only contemplates a single language,
/// but glib is smarter, and `g_get_langauge_names()` can provide
/// fallbacks, for example, when LC_MESSAGES="en_US.UTF-8:de" (USA
/// English and German).  This function converts the output of
/// `g_get_language_names()` into a `Locale` with appropriate
/// fallbacks.
fn locale_from_environment() -> Locale {
    let mut locale = Locale::invariant();

    for name in glib::get_language_names() {
        if let Ok(range) = LanguageRange::from_unix(&name) {
            locale.add(&range);
        }
    }

    locale
}
<commit_msg>Refactor match<commit_after>use std::rc::Rc;

use cairo::{self, ImageSurface, Status};
use gdk_pixbuf::Pixbuf;
use gio;
use glib::{self, IsA};
use libc;
use locale_config::{LanguageRange, Locale};

use crate::allowed_url::{AllowedUrl, Href};
use crate::c_api::{RsvgDimensionData, RsvgPositionData, SizeCallback};
use crate::dpi::Dpi;
use crate::drawing_ctx::{DrawingCtx, RsvgRectangle};
use crate::error::{DefsLookupErrorKind, LoadingError, RenderingError};
use crate::node::{CascadedValues, RsvgNode};
use crate::pixbuf_utils::{empty_pixbuf, pixbuf_from_surface};
use crate::structure::{IntrinsicDimensions, NodeSvg};
use crate::surface_utils::{shared_surface::SharedImageSurface, shared_surface::SurfaceType};
use crate::svg::Svg;
use crate::util::rsvg_g_warning;
use url::Url;

#[derive(Clone)]
pub struct LoadOptions {
    /// Base URL
    pub base_url: Option<Url>,

    /// Whether to turn off size limits in libxml2
    pub unlimited_size: bool,

    /// Whether to keep original (undecoded) image data to embed in Cairo PDF surfaces
    pub keep_image_data: bool,

    locale: Locale,
}

impl LoadOptions {
    pub fn new(base_url: Option<Url>) -> Self {
        LoadOptions {
            base_url,
            unlimited_size: false,
            keep_image_data: false,
            locale: locale_from_environment(),
        }
    }

    pub fn with_unlimited_size(mut self, unlimited: bool) -> Self {
        self.unlimited_size = unlimited;
        self
    }

    pub fn keep_image_data(mut self, keep: bool) -> Self {
        self.keep_image_data = keep;
        self
    }

    pub fn copy_with_base_url(&self, base_url: &AllowedUrl) -> Self {
        LoadOptions {
            base_url: Some((*base_url).clone()),
            unlimited_size: self.unlimited_size,
            keep_image_data: self.keep_image_data,
            locale: self.locale.clone(),
        }
    }

    pub fn locale(&self) -> &Locale {
        &self.locale
    }
}

pub struct Handle {
    svg: Rc<Svg>,
}

impl Handle {
    pub fn from_stream<S: IsA<gio::InputStream>>(
        load_options: &LoadOptions,
        stream: &S,
        cancellable: Option<&gio::Cancellable>,
    ) -> Result<Handle, LoadingError> {
        Ok(Handle {
            svg: Rc::new(Svg::load_from_stream(load_options, stream, cancellable)?),
        })
    }

    pub fn has_sub(&self, id: &str) -> Result<bool, RenderingError> {
        match self.lookup_node(id) {
            Ok(_) => Ok(true),

            Err(DefsLookupErrorKind::NotFound) => Ok(false),

            Err(e) => Err(RenderingError::InvalidId(e)),
        }
    }

    pub fn get_dimensions(
        &self,
        dpi: Dpi,
        size_callback: &SizeCallback,
        is_testing: bool,
    ) -> Result<RsvgDimensionData, RenderingError> {
        // This function is probably called from the cairo_render functions,
        // or is being erroneously called within the size_func.
        // To prevent an infinite loop we are saving the state, and
        // returning a meaningless size.
        if size_callback.get_in_loop() {
            return Ok(RsvgDimensionData {
                width: 1,
                height: 1,
                em: 1.0,
                ex: 1.0,
            });
        }

        size_callback.start_loop();

        let res = self.get_dimensions_sub(None, dpi, size_callback, is_testing);

        size_callback.end_loop();

        res
    }

    pub fn get_dimensions_no_error(
        &self,
        dpi: Dpi,
        size_callback: &SizeCallback,
        is_testing: bool,
    ) -> RsvgDimensionData {
        self.get_dimensions(dpi, size_callback, is_testing)
            .unwrap_or_else(|_| RsvgDimensionData::empty())
    }

    pub fn get_dimensions_sub(
        &self,
        id: Option<&str>,
        dpi: Dpi,
        size_callback: &SizeCallback,
        is_testing: bool,
    ) -> Result<RsvgDimensionData, RenderingError> {
        let (ink_r, _) = self.get_geometry_sub(id, dpi, is_testing)?;

        let (w, h) = size_callback.call(ink_r.width as libc::c_int, ink_r.height as libc::c_int);

        Ok(RsvgDimensionData {
            width: w,
            height: h,
            em: ink_r.width,
            ex: ink_r.height,
        })
    }

    pub fn get_position_sub(
        &self,
        id: Option<&str>,
        dpi: Dpi,
        size_callback: &SizeCallback,
        is_testing: bool,
    ) -> Result<RsvgPositionData, RenderingError> {
        if let None = id {
            return Ok(RsvgPositionData { x: 0, y: 0 });
        }

        let (ink_r, _) = self.get_geometry_sub(id, dpi, is_testing)?;

        let width = ink_r.width as libc::c_int;
        let height = ink_r.height as libc::c_int;

        size_callback.call(width, height);

        Ok(RsvgPositionData {
            x: ink_r.x as libc::c_int,
            y: ink_r.y as libc::c_int,
        })
    }

    /// Returns (ink_rect, logical_rect)
    fn get_node_geometry_with_viewport(
        &self,
        node: &RsvgNode,
        viewport: &cairo::Rectangle,
        dpi: Dpi,
        is_testing: bool,
    ) -> Result<(RsvgRectangle, RsvgRectangle), RenderingError> {
        let target = ImageSurface::create(cairo::Format::Rgb24, 1, 1)?;
        let cr = cairo::Context::new(&target);
        let mut draw_ctx = DrawingCtx::new(
            self.svg.clone(),
            Some(node),
            &cr,
            viewport,
            dpi,
            true,
            is_testing,
        );
        let root = self.svg.root();

        draw_ctx.draw_node_from_stack(&CascadedValues::new_from_node(&root), &root, false)?;

        let bbox = draw_ctx.get_bbox();

        let ink_rect = bbox
            .ink_rect
            .map(|r| RsvgRectangle::from(r))
            .unwrap_or_default();
        let logical_rect = bbox
            .rect
            .map(|r| RsvgRectangle::from(r))
            .unwrap_or_default();

        Ok((ink_rect, logical_rect))
    }

    /// Returns (ink_rect, logical_rect)
    fn get_geometry_sub(
        &self,
        id: Option<&str>,
        dpi: Dpi,
        is_testing: bool,
    ) -> Result<(RsvgRectangle, RsvgRectangle), RenderingError> {
        let node = self.get_node_or_root(id)?;

        let root = self.svg.root();
        let is_root = node == root;

        if is_root {
            let cascaded = CascadedValues::new_from_node(&node);
            let values = cascaded.get();

            if let Some((root_width, root_height)) =
                node.borrow().get_impl::<NodeSvg>().get_size(&values, dpi)
            {
                let ink_r = RsvgRectangle {
                    x: 0.0,
                    y: 0.0,
                    width: f64::from(root_width),
                    height: f64::from(root_height),
                };

                let logical_r = ink_r;

                return Ok((ink_r, logical_r));
            }
        }

        // This is just to start with an unknown viewport size
        let viewport = cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width: 1.0,
            height: 1.0,
        };

        self.get_node_geometry_with_viewport(&node, &viewport, dpi, is_testing)
    }

    fn get_node_or_root(&self, id: Option<&str>) -> Result<RsvgNode, RenderingError> {
        if let Some(id) = id {
            self.lookup_node(id).map_err(RenderingError::InvalidId)
        } else {
            Ok(self.svg.root())
        }
    }

    pub fn get_geometry_for_element(
        &self,
        id: Option<&str>,
        viewport: &cairo::Rectangle,
        dpi: Dpi,
        is_testing: bool,
    ) -> Result<(RsvgRectangle, RsvgRectangle), RenderingError> {
        let node = self.get_node_or_root(id)?;
        self.get_node_geometry_with_viewport(&node, viewport, dpi, is_testing)
    }

    fn lookup_node(&self, id: &str) -> Result<RsvgNode, DefsLookupErrorKind> {
        match Href::parse(&id).map_err(DefsLookupErrorKind::HrefError)? {
            Href::PlainUrl(_) => Err(DefsLookupErrorKind::CannotLookupExternalReferences),
            Href::WithFragment(fragment) => {
                if let Some(uri) = fragment.uri() {
                    // The public APIs to get geometries of individual elements, or to render
                    // them, should only allow referencing elements within the main handle's
                    // SVG file; that is, only plain "#foo" fragment IDs are allowed here.
                    // Otherwise, a calling program could request "another-file#foo" and cause
                    // another-file to be loaded, even if it is not part of the set of
                    // resources that the main SVG actually references.  In the future we may
                    // relax this requirement to allow lookups within that set, but not to
                    // other random files.

                    let msg = format!(
                        "the public API is not allowed to look up external references: {}#{}",
                        uri,
                        fragment.fragment()
                    );

                    rsvg_log!("{}", msg);

                    rsvg_g_warning(&msg);
                    return Err(DefsLookupErrorKind::CannotLookupExternalReferences);
                }

                match self.svg.lookup_node_by_id(fragment.fragment()) {
                    Some(n) => Ok(n),
                    None => Err(DefsLookupErrorKind::NotFound),
                }
            }
        }
    }

    pub fn render_cairo_sub(
        &self,
        cr: &cairo::Context,
        id: Option<&str>,
        dpi: Dpi,
        size_callback: &SizeCallback,
        is_testing: bool,
    ) -> Result<(), RenderingError> {
        check_cairo_context(cr)?;

        let dimensions = self.get_dimensions(dpi, size_callback, is_testing)?;
        if dimensions.width == 0 || dimensions.height == 0 {
            // nothing to render
            return Ok(());
        }

        let viewport = cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width: f64::from(dimensions.width),
            height: f64::from(dimensions.height),
        };

        self.render_element_to_viewport(cr, id, &viewport, dpi, is_testing)
    }

    pub fn render_element_to_viewport(
        &self,
        cr: &cairo::Context,
        id: Option<&str>,
        viewport: &cairo::Rectangle,
        dpi: Dpi,
        is_testing: bool,
    ) -> Result<(), RenderingError> {
        check_cairo_context(cr)?;

        let node = if let Some(id) = id {
            Some(self.lookup_node(id).map_err(RenderingError::InvalidId)?)
        } else {
            None
        };

        let root = self.svg.root();

        cr.save();
        let mut draw_ctx = DrawingCtx::new(
            self.svg.clone(),
            node.as_ref(),
            cr,
            viewport,
            dpi,
            false,
            is_testing,
        );
        let cascaded = CascadedValues::new_from_node(&root);
        let res = draw_ctx.draw_node_from_stack(&cascaded, &root, false);
        cr.restore();

        res
    }

    pub fn get_pixbuf_sub(
        &self,
        id: Option<&str>,
        dpi: Dpi,
        size_callback: &SizeCallback,
        is_testing: bool,
    ) -> Result<Pixbuf, RenderingError> {
        let dimensions = self.get_dimensions(dpi, size_callback, is_testing)?;

        if dimensions.width == 0 || dimensions.height == 0 {
            return empty_pixbuf();
        }

        let surface =
            ImageSurface::create(cairo::Format::ARgb32, dimensions.width, dimensions.height)?;

        {
            let cr = cairo::Context::new(&surface);
            self.render_cairo_sub(&cr, id, dpi, size_callback, is_testing)?;
        }

        let surface = SharedImageSurface::new(surface, SurfaceType::SRgb)?;

        pixbuf_from_surface(&surface)
    }

    pub fn get_intrinsic_dimensions(&self) -> IntrinsicDimensions {
        self.svg.get_intrinsic_dimensions()
    }
}

fn check_cairo_context(cr: &cairo::Context) -> Result<(), RenderingError> {
    let status = cr.status();
    if status == Status::Success {
        Ok(())
    } else {
        let msg = format!(
            "cannot render on a cairo_t with a failure status (status={:?})",
            status,
        );

        rsvg_g_warning(&msg);
        Err(RenderingError::Cairo(status))
    }
}

/// Gets the user's preferred locale from the environment and
/// translates it to a `Locale` with `LanguageRange` fallbacks.
///
/// The `Locale::current()` call only contemplates a single language,
/// but glib is smarter, and `g_get_langauge_names()` can provide
/// fallbacks, for example, when LC_MESSAGES="en_US.UTF-8:de" (USA
/// English and German).  This function converts the output of
/// `g_get_language_names()` into a `Locale` with appropriate
/// fallbacks.
fn locale_from_environment() -> Locale {
    let mut locale = Locale::invariant();

    for name in glib::get_language_names() {
        if let Ok(range) = LanguageRange::from_unix(&name) {
            locale.add(&range);
        }
    }

    locale
}
<|endoftext|>


<commit_before>#![allow(non_snake_case, non_upper_case_globals)]
// #![cfg_attr(test, feature(test))]
extern crate time;

use time::precise_time_s;
use std::mem;

///////////////////////////////////////////////////////////////////////////////
// 1. Calibration
///////////////////////////////////////////////////////////////////////////////
const aalpha:f64 = 0.33333333333;  // Elasticity of output w.r.t. capital
const bbeta:f64 = 0.95;           // Discount factor

// Productivity values
const vProductivity:[f64; 5] = [0.9792, 0.9896, 1.0000, 1.0106, 1.0212];

// Transition matrix
const mTransition:[[f64; 5]; 5] = [[0.9727, 0.0273, 0.0000, 0.0000, 0.0000],
                                   [0.0041, 0.9806, 0.0153, 0.0000, 0.0000],
                                   [0.0000, 0.0082, 0.9837, 0.0082, 0.0000],
                                   [0.0000, 0.0000, 0.0153, 0.9806, 0.0041],
                                   [0.0000, 0.0000, 0.0000, 0.0273, 0.9727]];

// Dimensions to generate the grid of capital
const nGridCapital: usize = 17820;
const nGridProductivity: usize = 5;

fn solve(print: bool) -> f64 {
  /////////////////////////////////////////////////////////////////////////////
  // 2. Steady State
  /////////////////////////////////////////////////////////////////////////////

    let capitalSteadyState: f64 = (aalpha * bbeta).powf(1_f64 / (1_f64 - aalpha));
    let outputSteadyState: f64 = capitalSteadyState.powf(aalpha);
    let consumptionSteadyState: f64 = outputSteadyState - capitalSteadyState;

    if print {
        println!("Output = {}, Capital = {}, Consumption = {}",
                 outputSteadyState,
                 capitalSteadyState,
                 consumptionSteadyState);
    }

    let mut vGridCapital = [0f64; nGridCapital];

    for (i, val) in vGridCapital.iter_mut().enumerate() {
        *val = 0.5 * capitalSteadyState + 0.00001 * (i as f64)
    }

    // 3. Required matrices and vectors
    let mut mValueFunction = vec![[0f64; nGridProductivity]; nGridCapital];
    let mut mPolicyFunction = mValueFunction.clone();
    let mut expectedValueFunction = mValueFunction.clone();

    // 4. We pre-build output for each point in the grid
    let mOutput : Vec<[f64; nGridProductivity]> = (0..nGridCapital).map(|nCapital| {
        let mut arr = [0.0; nGridProductivity];

        for (nProductivity, slot) in arr.iter_mut().enumerate() {
            *slot = vProductivity[nProductivity] * vGridCapital[nCapital].powf(aalpha)
        }

        arr
    }).collect();

  // 5. Main iteration
  // TODO: one could implement a macro for the multiple declarations
    let mut maxDifference = 10_f64;
    const tolerance: f64 = 0.0000001; // compiler warn: variable does not need to be mutable

    let mut iteration = 0;

    while maxDifference > tolerance {
        for (expected_values, value_fns) in expectedValueFunction.iter_mut()
                                                                 .zip(mValueFunction.iter()) {
            for (expected_value, transitions) in expected_values.iter_mut().zip(mTransition.iter()) {
                *expected_value = transitions.iter()
                                             .zip(value_fns.iter())
                                             .fold(0.0f64, |acc, (transition, value_fn)| {
                    acc + (transition * value_fn)
                });
            }
        }

        maxDifference = -100000.0;

        for nProductivity in 0..nGridProductivity {
            // We start from previous choice (monotonicity of policy function)
            let mut gridCapitalNextPeriod = 0;

            for (nCapital, ((policy, output), value_fn)) in mPolicyFunction.iter_mut()
                                                               .zip(mOutput.iter())
                                                               .zip(mValueFunction.iter_mut())
                                                               .enumerate() {
                let mut valueHighSoFar = -100000.0;
                let mut capitalChoice = vGridCapital[0];
                let mOutput_cache = &output[nProductivity];

                for nCapitalNextPeriod in gridCapitalNextPeriod..nGridCapital {
                    let consumption = mOutput_cache - &vGridCapital[nCapitalNextPeriod];
                    let valueProvisional = (1_f64 - bbeta) * (consumption.ln()) +
                                       bbeta *
                                       expectedValueFunction[nCapitalNextPeriod][nProductivity];

                    if valueProvisional > valueHighSoFar {
                        valueHighSoFar = valueProvisional;
                        capitalChoice = vGridCapital[nCapitalNextPeriod];
                        gridCapitalNextPeriod = nCapitalNextPeriod;
                    } else {
                        break; // We break when we have achieved the max
                    }
                }

                let old = mem::replace(&mut value_fn[nProductivity], valueHighSoFar);
                let diff = (old - valueHighSoFar).abs();
                if diff > maxDifference {
                    maxDifference = diff
                }

                policy[nProductivity] = capitalChoice;
            }
        }

        iteration += 1;
        if print && (iteration % 10 == 0 || iteration == 1) {
            println!("Iteration = {}, Sup Diff = {}", iteration, maxDifference);
        }
    }

    if print {
        println!("Iteration = {}, Sup Diff = {}", iteration, maxDifference);
    }

    mPolicyFunction[999][2]
}

fn main() {
    let sample = false;

    if sample {
        let mut samples = (0..5).map(|i| {
            let cpu0 = precise_time_s();
            let result = solve(false);
            let cpu1 = precise_time_s();

            assert_eq!(result, 0.1465491436956954);

            let diff = cpu1 - cpu0;
            println!("Sample #{}, Time: {}s", i + 1, diff);
            diff
        }).collect::<Vec<f64>>();

        samples.sort_by(|a, b| a.partial_cmp(b).unwrap());
        println!("\nMedian time is = {}", samples[2]);
    } else {
        let cpu0 = precise_time_s();
        let result = solve(true);
        let cpu1 = precise_time_s();

        println!("My check = {}\n", result);
        assert_eq!(result, 0.1465491436956954);
        println!("Elapsed time is = {}", cpu1 - cpu0);
    }
}

// FIXME: Can't use bench as the loop is too slow (takes 8mins to get samples)
// #[cfg(test)]
// mod test {
//     extern crate test;
//     use self::test::Bencher;
//     use super::solve;

//     #[bench]
//     fn bench(b: &mut Bencher) {
//         b.iter(|| {
//             // use `test::black_box` to prevent compiler optimizations from disregarding
//             // unused values
//             test::black_box(solve(false));
//         });
//     }
// }
<commit_msg>Invert data layout<commit_after>#![allow(non_snake_case, non_upper_case_globals)]
// #![cfg_attr(test, feature(test))]
extern crate time;

use time::precise_time_s;
use std::mem;

///////////////////////////////////////////////////////////////////////////////
// 1. Calibration
///////////////////////////////////////////////////////////////////////////////
const aalpha:f64 = 0.33333333333;  // Elasticity of output w.r.t. capital
const bbeta:f64 = 0.95;           // Discount factor

// Productivity values
const vProductivity:[f64; 5] = [0.9792, 0.9896, 1.0000, 1.0106, 1.0212];

// Transition matrix
const mTransition:[[f64; 5]; 5] = [[0.9727, 0.0273, 0.0000, 0.0000, 0.0000],
                                   [0.0041, 0.9806, 0.0153, 0.0000, 0.0000],
                                   [0.0000, 0.0082, 0.9837, 0.0082, 0.0000],
                                   [0.0000, 0.0000, 0.0153, 0.9806, 0.0041],
                                   [0.0000, 0.0000, 0.0000, 0.0273, 0.9727]];

// Dimensions to generate the grid of capital
const nGridCapital: usize = 17820;
const nGridProductivity: usize = 5;

fn solve(print: bool) -> f64 {
  /////////////////////////////////////////////////////////////////////////////
  // 2. Steady State
  /////////////////////////////////////////////////////////////////////////////

    let capitalSteadyState: f64 = (aalpha * bbeta).powf(1_f64 / (1_f64 - aalpha));
    let outputSteadyState: f64 = capitalSteadyState.powf(aalpha);
    let consumptionSteadyState: f64 = outputSteadyState - capitalSteadyState;

    if print {
        println!("Output = {}, Capital = {}, Consumption = {}",
                 outputSteadyState,
                 capitalSteadyState,
                 consumptionSteadyState);
    }

    let mut vGridCapital = [0f64; nGridCapital];

    for (i, val) in vGridCapital.iter_mut().enumerate() {
        *val = 0.5 * capitalSteadyState + 0.00001 * (i as f64)
    }

    // 3. Required matrices and vectors
    let mut mValueFunction: [Vec<f64>; nGridProductivity] = [
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
    ];

    let mut mPolicyFunction: [Vec<f64>; nGridProductivity] = [
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
    ];

    let mut expectedValueFunction: [Vec<f64>; nGridProductivity] = [
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
        vec![0f64; nGridCapital],
    ];

    // 4. We pre-build output for each point in the grid
    let mOutput : Vec<[f64; nGridProductivity]> = (0..nGridCapital).map(|nCapital| {
        let mut arr = [0.0; nGridProductivity];

        for (nProductivity, slot) in arr.iter_mut().enumerate() {
            *slot = vProductivity[nProductivity] * vGridCapital[nCapital].powf(aalpha)
        }

        arr
    }).collect();

  // 5. Main iteration
  // TODO: one could implement a macro for the multiple declarations
    let mut maxDifference = 10_f64;
    const tolerance: f64 = 0.0000001; // compiler warn: variable does not need to be mutable

    let mut iteration = 0;

    while maxDifference > tolerance {
        for (expected_values, transitions) in expectedValueFunction.iter_mut()
                                                                                .zip(mTransition.iter()) {
            for (idx, expected_value) in expected_values.iter_mut()
                                                        .enumerate() {
                *expected_value = transitions.iter()
                                             .zip(mValueFunction.iter())
                                             .fold(0.0f64, |acc, (transition, value_fns)| {
                    acc + (transition * value_fns[idx])
                });
            }
        }

        maxDifference = -100000.0;

        for (nProductivity, (policies, value_fns)) in mPolicyFunction.iter_mut()
                                                                     .zip(mValueFunction.iter_mut())
                                                                     .enumerate() {
            let expected_fn = &expectedValueFunction[nProductivity];

            // We start from previous choice (monotonicity of policy function)
            let mut gridCapitalNextPeriod = 0;

            for ((policy, output), value_fn) in policies.iter_mut()
                                                        .zip(mOutput.iter())
                                                        .zip(value_fns.iter_mut()) {
                let mut valueHighSoFar = -100000.0;
                let mut capitalChoice = vGridCapital[0];
                let mOutput_cache = &output[nProductivity];

                for nCapitalNextPeriod in gridCapitalNextPeriod..nGridCapital {
                    let consumption = mOutput_cache - &vGridCapital[nCapitalNextPeriod];
                    let valueProvisional = (1_f64 - bbeta) * (consumption.ln()) +
                                            bbeta *
                                            expected_fn[nCapitalNextPeriod];

                    if valueProvisional > valueHighSoFar {
                        valueHighSoFar = valueProvisional;
                        capitalChoice = vGridCapital[nCapitalNextPeriod];
                        gridCapitalNextPeriod = nCapitalNextPeriod;
                    } else {
                        break; // We break when we have achieved the max
                    }
                }

                let old = mem::replace(value_fn, valueHighSoFar);
                let diff = (old - valueHighSoFar).abs();
                if diff > maxDifference {
                    maxDifference = diff
                }

                *policy = capitalChoice;
            }
        }

        iteration += 1;
        if print && (iteration % 10 == 0 || iteration == 1) {
            println!("Iteration = {}, Sup Diff = {}", iteration, maxDifference);
        }
    }

    if print {
        println!("Iteration = {}, Sup Diff = {}", iteration, maxDifference);
    }

    mPolicyFunction[2][999]
}

fn main() {
    let sample = false;

    if sample {
        let mut samples = (0..5).map(|i| {
            let cpu0 = precise_time_s();
            let result = solve(false);
            let cpu1 = precise_time_s();

            assert_eq!(result, 0.1465491436956954);

            let diff = cpu1 - cpu0;
            println!("Sample #{}, Time: {}s", i + 1, diff);
            diff
        }).collect::<Vec<f64>>();

        samples.sort_by(|a, b| a.partial_cmp(b).unwrap());
        println!("\nMedian time is = {}", samples[2]);
    } else {
        let cpu0 = precise_time_s();
        let result = solve(true);
        let cpu1 = precise_time_s();

        println!("My check = {}\n", result);
        assert_eq!(result, 0.1465491436956954);
        println!("Elapsed time is = {}", cpu1 - cpu0);
    }
}

// FIXME: Can't use bench as the loop is too slow (takes 8mins to get samples)
// #[cfg(test)]
// mod test {
//     extern crate test;
//     use self::test::Bencher;
//     use super::solve;

//     #[bench]
//     fn bench(b: &mut Bencher) {
//         b.iter(|| {
//             // use `test::black_box` to prevent compiler optimizations from disregarding
//             // unused values
//             test::black_box(solve(false));
//         });
//     }
// }
<|endoftext|>


<commit_before>use crate::io::AsyncRead;
use futures_core::future::Future;
use futures_core::task::{self, Poll};
use std::io;
use std::marker::Unpin;
use std::mem::{self, PinMut};

/// A future which can be used to easily read exactly enough bytes to fill
/// a buffer.
///
/// Created by the [`read_exact`] function.
///
/// [`read_exact`]: fn.read_exact.html
#[derive(Debug)]
pub struct ReadExact<'a, R: ?Sized + 'a> {
    reader: &'a mut R,
    buf: &'a mut [u8],
}

impl<'a, R: ?Sized> Unpin for ReadExact<'a, R> {}

impl<'a, R: AsyncRead + ?Sized> ReadExact<'a, R> {
    pub(super) fn new(
        reader: &'a mut R,
        buf: &'a mut [u8]
    ) -> ReadExact<'a, R> {
        ReadExact { reader, buf }
    }
}

fn eof() -> io::Error {
    io::Error::new(io::ErrorKind::UnexpectedEof, "early eof")
}

impl<'a, R: AsyncRead + ?Sized> Future for ReadExact<'a, R> {
    type Output = io::Result<()>;

    fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
        let this = &mut *self;
        while !this.buf.is_empty() {
            let n = try_ready!(this.reader.poll_read(cx, this.buf));
            {
                let (rest, _) = mem::replace(&mut this.buf, &mut []).split_at_mut(n);
                this.buf = rest;
            }
            if n == 0 {
                return Poll::Ready(Err(eof()))
            }
        }
        Poll::Ready(Ok(()))
    }
}
<commit_msg>fix poll function in ReadExact<commit_after>use crate::io::AsyncRead;
use futures_core::future::Future;
use futures_core::task::{self, Poll};
use std::io;
use std::marker::Unpin;
use std::mem::{self, PinMut};

/// A future which can be used to easily read exactly enough bytes to fill
/// a buffer.
///
/// Created by the [`read_exact`] function.
///
/// [`read_exact`]: fn.read_exact.html
#[derive(Debug)]
pub struct ReadExact<'a, R: ?Sized + 'a> {
    reader: &'a mut R,
    buf: &'a mut [u8],
}

impl<'a, R: ?Sized> Unpin for ReadExact<'a, R> {}

impl<'a, R: AsyncRead + ?Sized> ReadExact<'a, R> {
    pub(super) fn new(
        reader: &'a mut R,
        buf: &'a mut [u8]
    ) -> ReadExact<'a, R> {
        ReadExact { reader, buf }
    }
}

fn eof() -> io::Error {
    io::Error::new(io::ErrorKind::UnexpectedEof, "early eof")
}

impl<'a, R: AsyncRead + ?Sized> Future for ReadExact<'a, R> {
    type Output = io::Result<()>;

    fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
        let this = &mut *self;
        while !this.buf.is_empty() {
            let n = try_ready!(this.reader.poll_read(cx, this.buf));
            {
                let (_, rest) = mem::replace(&mut this.buf, &mut []).split_at_mut(n);
                this.buf = rest;
            }
            if n == 0 {
                return Poll::Ready(Err(eof()))
            }
        }
        Poll::Ready(Ok(()))
    }
}
<|endoftext|>