<commit_before>extern crate num_complex;

use std::cmp::Ordering;
use std::collections::BTreeMap;
use std::collections::btree_map;

use self::num_complex::{Complex32, Complex64};

use signal::Signal;

use render::render_spec::RenderSpec;

/// Any angular frequencies within this distance from eachother will be
/// considered equal, and the difference is attributed to float rounding.
const FREQ_DELTA : f32 = 0.00001f32;
/// Any waves with amplitude less than this delta are considered safe to drop
const AMP_DELTA : f32 = 0.000000001f32;
const AMP_DELTA_SQR : f32 = AMP_DELTA*AMP_DELTA;
/// Provides a type that compares equal if to frequencies are nearly
/// indistinguishable.
/// The threshold for "indistinguishable" is not whether or not they are
/// audibly different, but rather, could both frequencies feasibly be obtained
/// from the same calculation by reordering the mathematical operations?
#[derive(Debug)]
struct ApproxFreq (f32);

/// Takes a series of Partials and turns them into a PCM/audio signal.
//#[derive(Debug)]
pub struct PartialRenderer {
    // Note: at 44100 Hz, u32 can cover 1.12 days of audio
    // u64 = 12,000,000 years
    frame_idx : u64,
    inv_sample_rate : f64,
    /// Maps the angular frequency of a wave to its amplitude coefficient.
    partials : BTreeMap<ApproxFreq, Complex32>,
}

impl PartialRenderer {
    /// Creates a new renderer according to the provided `spec`
    pub fn new(spec: RenderSpec) -> PartialRenderer {
        PartialRenderer {
            partials: BTreeMap::new(),
            frame_idx: 0,
            inv_sample_rate: 1.0f64/(spec.sample_rate() as f64)
        }
    }
    pub fn feed(&mut self, signal : Signal) {
        // If there's already an entry for a frequency very close to ours,
        // then add our coefficient into that entry. Otherwise, create a new
        // entry. In either case, delete the entry if the amplitude of the wave
        // is less than some threshold.
        //
        // Deleting the entry means that calling feed(p) followed by feed(-p)
        // will always work to remove p from the table.
        match self.partials.entry(ApproxFreq(signal.ang_freq())) {
            btree_map::Entry::Vacant(entry) => {
                let new_val = signal.phaser_coeff();
                if new_val.norm_sqr() >= AMP_DELTA_SQR {
                    entry.insert(new_val);
                }
            },
            btree_map::Entry::Occupied(entry_) => {
                let mut entry = entry_;
                let new_val = entry.get() + signal.phaser_coeff();
                if new_val.norm_sqr() >= AMP_DELTA_SQR {
                    entry.insert(new_val);
                } else {
                    entry.remove();
                }
            }
        };
    }
    /// Obtain the next sample
    pub fn step(&mut self) -> f32 {
        let seconds = self.frame_idx as f64 * self.inv_sample_rate;
        self.frame_idx += 1;

        // Signal is described by sum: coeff*exp(i*freq*seconds)
        // we only care about the real portion of the signal
        // exp(i*w) = cos(w) + i*sin(w)
        // Therefore signal = sum: coeff*Complex32(cos(w), sin(w)).re
        self.partials.iter().fold(0.0f32, |accum, (freq, coeff)| {
            //let (res_sin, res_cos) = f64::sin_cos(seconds*freq.0 as f64);
            //accum + (coeff*PhaserCoeff::new_f32(res_cos as f32, res_sin as f32)).re().value()
            let phased = Complex64::from_polar(&1.0, &(seconds*freq.0 as f64));
            let phased = Complex32::new(phased.re as f32, phased.im as f32);
            accum + (coeff*phased).re
        })
    }
}

impl PartialEq for ApproxFreq {
    /// Returns true if the frequencies are within +/- FREQ_DELTA from eeachother
    /// In order to make NAN's considered equal, we check for the inverse and negate it.
    fn eq(&self, other: &ApproxFreq) -> bool {
        !(self.0 > other.0 + FREQ_DELTA
            || other.0 > self.0 + FREQ_DELTA
        )
    }
}

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

impl Ord for ApproxFreq {
    fn cmp(&self, other: &ApproxFreq) -> Ordering {
        if self.eq(other) {
            Ordering::Equal
        } else if self.0 < other.0 {
            Ordering::Less
        } else {
            Ordering::Greater
        }
    }
}

impl Eq for ApproxFreq {}
<commit_msg>Reference renderer respects signal start time<commit_after>extern crate num_complex;

use std::cmp::Ordering;
use std::collections::{BTreeMap, btree_map, BinaryHeap};

use self::num_complex::{Complex32, Complex64};
use render::render_spec::RenderSpec;
use signal::Signal;

/// Any angular frequencies within this distance from eachother will be
/// considered equal, and the difference is attributed to float rounding.
const FREQ_DELTA : f32 = 0.00001f32;
/// Any waves with amplitude less than this delta are considered safe to drop
const AMP_DELTA : f32 = 0.000000001f32;
const AMP_DELTA_SQR : f32 = AMP_DELTA*AMP_DELTA;
/// Provides a type that compares equal if to frequencies are nearly
/// indistinguishable.
/// The threshold for "indistinguishable" is not whether or not they are
/// audibly different, but rather, could both frequencies feasibly be obtained
/// from the same calculation by reordering the mathematical operations?
#[derive(Debug)]
struct ApproxFreq (f32);

/// Takes a series of Partials and turns them into a PCM/audio signal.
//#[derive(Debug)]
pub struct PartialRenderer {
    // Note: at 44100 Hz, u32 can cover 1.12 days of audio
    // u64 = 12,000,000 years
    frame_idx : u64,
    inv_sample_rate : f64,
    /// Maps the angular frequency of a wave to its amplitude coefficient.
    partials : BTreeMap<ApproxFreq, Complex32>,
    /// For partials that are starting soon, but not yet:
    queued: BinaryHeap<Signal>,
}

impl PartialRenderer {
    /// Creates a new renderer according to the provided `spec`
    pub fn new(spec: RenderSpec) -> PartialRenderer {
        PartialRenderer {
            frame_idx: 0,
            inv_sample_rate: 1.0f64/(spec.sample_rate() as f64),
            partials: BTreeMap::new(),
            queued: BinaryHeap::new(),
        }
    }
    /// add the signal into the queue, and begin rendering it once the frame
    /// reaches/exceeds the signal's start time.
    pub fn feed(&mut self, signal : Signal) {
        self.queued.push(signal);
    }
    fn feed_now(&mut self, signal : Signal) {
        // If there's already an entry for a frequency very close to ours,
        // then add our coefficient into that entry. Otherwise, create a new
        // entry. In either case, delete the entry if the amplitude of the wave
        // is less than some threshold.
        //
        // Deleting the entry means that calling feed(p) followed by feed(-p)
        // will always work to remove p from the table.
        match self.partials.entry(ApproxFreq(signal.ang_freq())) {
            btree_map::Entry::Vacant(entry) => {
                let new_val = signal.phaser_coeff();
                if new_val.norm_sqr() >= AMP_DELTA_SQR {
                    entry.insert(new_val);
                }
            },
            btree_map::Entry::Occupied(entry_) => {
                let mut entry = entry_;
                let new_val = entry.get() + signal.phaser_coeff();
                if new_val.norm_sqr() >= AMP_DELTA_SQR {
                    entry.insert(new_val);
                } else {
                    entry.remove();
                }
            }
        };
    }
    /// Obtain the next sample
    pub fn step(&mut self) -> f32 {
        let seconds = self.frame_idx as f64 * self.inv_sample_rate;
        self.frame_idx += 1;

        // Check for queued signals that should start this frame
        while self.queued.peek().map_or(false, |s| s.start() as f64 <= seconds) {
            let sig = self.queued.pop().unwrap();
            self.feed_now(sig);
        }

        // Signal is described by sum: coeff*exp(i*freq*seconds)
        // we only care about the real portion of the signal
        // exp(i*w) = cos(w) + i*sin(w)
        // Therefore signal = sum: coeff*Complex32(cos(w), sin(w)).re
        self.partials.iter().fold(0.0f32, |accum, (freq, coeff)| {
            //let (res_sin, res_cos) = f64::sin_cos(seconds*freq.0 as f64);
            //accum + (coeff*PhaserCoeff::new_f32(res_cos as f32, res_sin as f32)).re().value()
            let phased = Complex64::from_polar(&1.0, &(seconds*freq.0 as f64));
            let phased = Complex32::new(phased.re as f32, phased.im as f32);
            accum + (coeff*phased).re
        })
    }
}

impl PartialEq for ApproxFreq {
    /// Returns true if the frequencies are within +/- FREQ_DELTA from eeachother
    /// In order to make NAN's considered equal, we check for the inverse and negate it.
    fn eq(&self, other: &ApproxFreq) -> bool {
        !(self.0 > other.0 + FREQ_DELTA
            || other.0 > self.0 + FREQ_DELTA
        )
    }
}

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

impl Ord for ApproxFreq {
    fn cmp(&self, other: &ApproxFreq) -> Ordering {
        if self.eq(other) {
            Ordering::Equal
        } else if self.0 < other.0 {
            Ordering::Less
        } else {
            Ordering::Greater
        }
    }
}

impl Eq for ApproxFreq {}

// In order to have signals sorted in the BinaryHeap queue, we need
// to implement an ordering that places the partial starting soonest as
// having maximum priority
impl PartialEq for Signal {
    fn eq(&self, other: &Signal) -> bool {
        return self.start() == other.start()
    }
}
impl Eq for Signal {}
impl PartialOrd for Signal {
    fn partial_cmp(&self, other: &Signal) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl Ord for Signal {
    fn cmp(&self, other: &Signal) -> Ordering {
        if self.eq(other) {
            Ordering::Equal
        } else if self.start() < other.start() {
            // HIGHER priority
            Ordering::Greater
        } else {
            Ordering::Less
        }
    }
}
<|endoftext|>


<commit_before>use crate::migrations::migration_directory_from_given_path;
use migrations_internals::{migration_paths_in_directory, version_from_path};
use quote::quote;
use std::error::Error;
use std::fs::DirEntry;
use std::path::Path;

pub fn expand(path: String) -> proc_macro2::TokenStream {
    dbg!(&path);
    let migrations_path_opt = if path.is_empty() {
        None
    } else {
        Some(path.replace("\"", ""))
    };
    let migrations_expr =
        migration_directory_from_given_path(migrations_path_opt.as_ref().map(String::as_str))
            .and_then(|path| migration_literals_from_path(&path));
    let migrations_expr = match migrations_expr {
        Ok(v) => v,
        Err(e) => panic!("Error reading migrations: {}", e),
    };

    quote! {
        #[allow(dead_code)]
        mod embedded_migrations {
            extern crate diesel;
            extern crate diesel_migrations;

            use self::diesel_migrations::*;
            use self::diesel::connection::SimpleConnection;
            use std::io;

            const ALL_MIGRATIONS: &[&Migration] = &[#(#migrations_expr),*];

            struct EmbeddedMigration {
                version: &'static str,
                up_sql: &'static str,
            }

            impl Migration for EmbeddedMigration {
                fn version(&self) -> &str {
                    self.version
                }

                fn run(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
                    conn.batch_execute(self.up_sql).map_err(Into::into)
                }

                fn revert(&self, _conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
                    unreachable!()
                }
            }

            pub fn run<C: MigrationConnection>(conn: &C) -> Result<(), RunMigrationsError> {
                run_with_output(conn, &mut io::sink())
            }

            pub fn run_with_output<C: MigrationConnection>(
                conn: &C,
                out: &mut io::Write,
            ) -> Result<(), RunMigrationsError> {
                run_migrations(conn, ALL_MIGRATIONS.iter().map(|v| *v), out)
            }
        }
    }
}

fn migration_literals_from_path(
    path: &Path,
) -> Result<Vec<proc_macro2::TokenStream>, Box<dyn Error>> {
    let mut migrations = migration_paths_in_directory(path)?;

    migrations.sort_by_key(DirEntry::path);

    migrations
        .into_iter()
        .map(|e| migration_literal_from_path(&e.path()))
        .collect()
}

fn migration_literal_from_path(path: &Path) -> Result<proc_macro2::TokenStream, Box<dyn Error>> {
    let version = version_from_path(path)?;
    let sql_file = path.join("up.sql");
    let sql_file_path = sql_file.to_str();

    Ok(quote!(&EmbeddedMigration {
        version: #version,
        up_sql: include_str!(#sql_file_path),
    }))
}
<commit_msg>Remove `dbg!` statement<commit_after>use crate::migrations::migration_directory_from_given_path;
use migrations_internals::{migration_paths_in_directory, version_from_path};
use quote::quote;
use std::error::Error;
use std::fs::DirEntry;
use std::path::Path;

pub fn expand(path: String) -> proc_macro2::TokenStream {
    let migrations_path_opt = if path.is_empty() {
        None
    } else {
        Some(path.replace("\"", ""))
    };
    let migrations_expr =
        migration_directory_from_given_path(migrations_path_opt.as_ref().map(String::as_str))
            .and_then(|path| migration_literals_from_path(&path));
    let migrations_expr = match migrations_expr {
        Ok(v) => v,
        Err(e) => panic!("Error reading migrations: {}", e),
    };

    quote! {
        #[allow(dead_code)]
        mod embedded_migrations {
            extern crate diesel;
            extern crate diesel_migrations;

            use self::diesel_migrations::*;
            use self::diesel::connection::SimpleConnection;
            use std::io;

            const ALL_MIGRATIONS: &[&Migration] = &[#(#migrations_expr),*];

            struct EmbeddedMigration {
                version: &'static str,
                up_sql: &'static str,
            }

            impl Migration for EmbeddedMigration {
                fn version(&self) -> &str {
                    self.version
                }

                fn run(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
                    conn.batch_execute(self.up_sql).map_err(Into::into)
                }

                fn revert(&self, _conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
                    unreachable!()
                }
            }

            pub fn run<C: MigrationConnection>(conn: &C) -> Result<(), RunMigrationsError> {
                run_with_output(conn, &mut io::sink())
            }

            pub fn run_with_output<C: MigrationConnection>(
                conn: &C,
                out: &mut io::Write,
            ) -> Result<(), RunMigrationsError> {
                run_migrations(conn, ALL_MIGRATIONS.iter().map(|v| *v), out)
            }
        }
    }
}

fn migration_literals_from_path(
    path: &Path,
) -> Result<Vec<proc_macro2::TokenStream>, Box<dyn Error>> {
    let mut migrations = migration_paths_in_directory(path)?;

    migrations.sort_by_key(DirEntry::path);

    migrations
        .into_iter()
        .map(|e| migration_literal_from_path(&e.path()))
        .collect()
}

fn migration_literal_from_path(path: &Path) -> Result<proc_macro2::TokenStream, Box<dyn Error>> {
    let version = version_from_path(path)?;
    let sql_file = path.join("up.sql");
    let sql_file_path = sql_file.to_str();

    Ok(quote!(&EmbeddedMigration {
        version: #version,
        up_sql: include_str!(#sql_file_path),
    }))
}
<|endoftext|>


<commit_before>use qt_charts::{qt_core::QString, qt_widgets::QApplication, QChart};

#[test]
fn chart1() {
    QApplication::init(|_| unsafe {
        let mut chart = QChart::new_0a();
        chart.set_title(&QString::from_std_str("test"));
        let title = chart.title().to_std_string();
        assert_eq!(&title, "test");
        0
    })
}
<commit_msg>fix warning in q_chart test<commit_after>use qt_charts::{qt_core::QString, qt_widgets::QApplication, QChart};

#[test]
fn chart1() {
    QApplication::init(|_| unsafe {
        let chart = QChart::new_0a();
        chart.set_title(&QString::from_std_str("test"));
        let title = chart.title().to_std_string();
        assert_eq!(&title, "test");
        0
    })
}
<|endoftext|>


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

trait MyTrait {
    const C: bool;
    //~^ associated constants are experimental
    //~| add #![feature(associated_consts)] to the crate attributes to enable
}

struct Foo;

impl Foo {
    const C: bool = true;
    //~^ associated constants are experimental
    //~| add #![feature(associated_consts)] to the crate attributes to enable
}
<commit_msg>Rollup merge of #25503 - brson:betafix, r=cmr<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

trait MyTrait {
    const C: bool;
    //~^ associated constants are experimental
}

struct Foo;

impl Foo {
    const C: bool = true;
    //~^ associated constants are experimental
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use db::migration::Migrator;

use error::SrvResult;

pub fn migrate(migrator: &mut Migrator) -> SrvResult<()> {
    migrator.migrate(
        "originsrv",
        r#"CREATE SEQUENCE IF NOT EXISTS origin_integration_id_seq;"#,
    )?;
    migrator.migrate(
        "originsrv",
        r#"CREATE TABLE IF NOT EXISTS origin_integrations (
                        id bigint PRIMARY KEY DEFAULT next_id_v1('origin_integration_id_seq'),
                        origin text,
                        integration text,
                        name text,
                        body text,
                        created_at timestamptz DEFAULT now(),
                        updated_at timestamptz,
                        UNIQUE (origin, name)
                        )"#,
    )?;
    migrator.migrate(
        "originsrv",
        r#"CREATE OR REPLACE FUNCTION insert_origin_integration_v1 (
                        in_origin text,
                        in_integration text,
                        in_name text,
                        in_body text
                 ) RETURNS SETOF origin_integrations AS $$
                        INSERT INTO origin_integrations(
                                      origin,
                                      integration,
                                      name,
                                      body)
                        VALUES (
                            in_origin,
                            in_integration,
                            in_name,
                            in_body)
                        RETURNING *
                 $$ LANGUAGE SQL VOLATILE"#,
    )?;
    migrator.migrate(
        "originsrv",
        r#"CREATE OR REPLACE FUNCTION get_origin_integrations_v1 (
                        in_origin text,
                        in_integration text
                 ) RETURNS SETOF origin_integrations AS $$
                        SELECT * FROM origin_integrations
                        WHERE origin = in_origin AND integration = in_integration
                    $$ LANGUAGE SQL STABLE"#,
    )?;
    migrator.migrate(
        "originsrv",
        r#"CREATE OR REPLACE FUNCTION delete_origin_integration_v1 (
                        in_origin text,
                        in_integration text,
                        in_name text
                 ) RETURNS void AS $$
                        DELETE FROM origin_integrations
                        WHERE origin = in_origin AND integration = in_integration AND name = in_name
                    $$ LANGUAGE SQL VOLATILE"#,
    )?;
    migrator.migrate(
        "originsrv",
        r#"CREATE OR REPLACE FUNCTION get_origin_integrations_for_origin_v1 (
                        in_origin text
                 ) RETURNS SETOF origin_integrations AS $$
                        SELECT * FROM origin_integrations
                        WHERE origin = in_origin
                        ORDER BY integration, name
                    $$ LANGUAGE SQL STABLE"#,
    )?;
    Ok(())
}
<commit_msg>Make origin/integration/name unique instead of origin/name<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use db::migration::Migrator;

use error::SrvResult;

pub fn migrate(migrator: &mut Migrator) -> SrvResult<()> {
    migrator.migrate(
        "originsrv",
        r#"CREATE SEQUENCE IF NOT EXISTS origin_integration_id_seq;"#,
    )?;
    migrator.migrate(
        "originsrv",
        r#"CREATE TABLE IF NOT EXISTS origin_integrations (
                        id bigint PRIMARY KEY DEFAULT next_id_v1('origin_integration_id_seq'),
                        origin text,
                        integration text,
                        name text,
                        body text,
                        created_at timestamptz DEFAULT now(),
                        updated_at timestamptz,
                        UNIQUE (origin, name)
                        )"#,
    )?;
    migrator.migrate(
        "originsrv",
        r#"CREATE OR REPLACE FUNCTION insert_origin_integration_v1 (
                        in_origin text,
                        in_integration text,
                        in_name text,
                        in_body text
                 ) RETURNS SETOF origin_integrations AS $$
                        INSERT INTO origin_integrations(
                                      origin,
                                      integration,
                                      name,
                                      body)
                        VALUES (
                            in_origin,
                            in_integration,
                            in_name,
                            in_body)
                        RETURNING *
                 $$ LANGUAGE SQL VOLATILE"#,
    )?;
    migrator.migrate(
        "originsrv",
        r#"CREATE OR REPLACE FUNCTION get_origin_integrations_v1 (
                        in_origin text,
                        in_integration text
                 ) RETURNS SETOF origin_integrations AS $$
                        SELECT * FROM origin_integrations
                        WHERE origin = in_origin AND integration = in_integration
                    $$ LANGUAGE SQL STABLE"#,
    )?;
    migrator.migrate(
        "originsrv",
        r#"CREATE OR REPLACE FUNCTION delete_origin_integration_v1 (
                        in_origin text,
                        in_integration text,
                        in_name text
                 ) RETURNS void AS $$
                        DELETE FROM origin_integrations
                        WHERE origin = in_origin AND integration = in_integration AND name = in_name
                    $$ LANGUAGE SQL VOLATILE"#,
    )?;
    migrator.migrate(
        "originsrv",
        r#"CREATE OR REPLACE FUNCTION get_origin_integrations_for_origin_v1 (
                        in_origin text
                 ) RETURNS SETOF origin_integrations AS $$
                        SELECT * FROM origin_integrations
                        WHERE origin = in_origin
                        ORDER BY integration, name
                    $$ LANGUAGE SQL STABLE"#,
    )?;
    migrator.migrate(
        "originsrv",
        r#"ALTER TABLE IF EXISTS origin_integrations DROP CONSTRAINT IF EXISTS origin_integrations_origin_name_key"#,
    )?;
    migrator.migrate(
        "originsrv",
        r#"ALTER TABLE IF EXISTS origin_integrations ADD CONSTRAINT origin_integrations_origin_integration_name_key UNIQUE(origin, integration, name)"#,
    )?;
    Ok(())
}
<|endoftext|>


<commit_before>//! Uninteresting example that produces all the weak symbols that `f3` exposes

#![no_main]
#![no_std]

extern crate f3;

#[export_name = "main"]
pub extern "C" fn main() -> ! {
    panic!()
}
<commit_msg>drop the _all-the-weak-symbols "example"<commit_after><|endoftext|>


<commit_before>// Make sure that the mono-item collector does not crash when trying to
// instantiate a default impl for DecodeUtf16<<u8 as A>::Item>
// See https://github.com/rust-lang/rust/issues/58375
// compile-flags:-C link-dead-code

#![crate_type = "rlib"]

pub struct DecodeUtf16<I>(I);

pub trait Arbitrary {
    fn arbitrary() {}
}

pub trait A {
    type Item;
}

impl A for u8 {
    type Item = char;
}

impl Arbitrary for DecodeUtf16<<u8 as A>::Item>  {
}<commit_msg>Add missing trailing newline<commit_after>// Make sure that the mono-item collector does not crash when trying to
// instantiate a default impl for DecodeUtf16<<u8 as A>::Item>
// See https://github.com/rust-lang/rust/issues/58375
// compile-flags:-C link-dead-code

#![crate_type = "rlib"]

pub struct DecodeUtf16<I>(I);

pub trait Arbitrary {
    fn arbitrary() {}
}

pub trait A {
    type Item;
}

impl A for u8 {
    type Item = char;
}

impl Arbitrary for DecodeUtf16<<u8 as A>::Item>  {
}
<|endoftext|>


<commit_before>pub struct LineIterator<'a> {
    data: &'a str,
    line_number: usize,
    line_start: usize,
    line_end: usize
}

impl<'a> LineIterator<'a> {
    pub fn new<'b>(data: &'b str) -> LineIterator<'b> {
        LineIterator{
            data: data,
            line_number: 0,
            line_start: 0,
            line_end: 0,
        }
    }

    pub fn done(&self) -> bool {
        self.line_end == self.data.len()
    }
}

impl<'a> Iterator for LineIterator<'a> {
    type Item = (usize, &'a str);

    fn next(&mut self) -> Option<Self::Item> {
        if self.done() {
            return None
        }

        // Move the range beyond its previous position.
        self.line_start = self.line_end;

        // Find the next line range.
        for c in self.data[self.line_start..].chars() {
            // Extend the current line range to include this char.
            self.line_end += c.len_utf8();

            if c == '\n' {
                break;
            }
        }
        self.line_number += 1;

        Some((
            self.line_number-1,
            &self.data[
                self.line_start..self.line_end
            ]
        ))
    }
}

#[cfg(test)]
mod tests {
    use super::LineIterator;

    #[test]
    fn next_includes_trailing_newlines() {
        let mut lines = LineIterator::new("line\nanother line\n");
        assert_eq!(Some((0, "line\n")), lines.next());
        assert_eq!(Some((1, "another line\n")), lines.next());
    }

    #[test]
    fn next_stops_at_end_of_data() {
        let mut lines = LineIterator::new("line\nanother line\n");
        lines.next();
        lines.next();
        assert_eq!(None, lines.next());
    }
}
<commit_msg>Fix line iterator edge cases<commit_after>pub struct LineIterator<'a> {
    data: &'a str,
    line_number: usize,
    line_start: usize,
    line_end: usize,
    done: bool
}

impl<'a> LineIterator<'a> {
    pub fn new<'b>(data: &'b str) -> LineIterator<'b> {
        LineIterator{
            data: data,
            line_number: 0,
            line_start: 0,
            line_end: 0,
            done: false
        }
    }

    fn out_of_data(&self) -> bool {
        self.line_end == self.data.len()
    }
}

impl<'a> Iterator for LineIterator<'a> {
    type Item = (usize, &'a str);

    fn next(&mut self) -> Option<Self::Item> {
        if self.done {
            return None
        }

        // Move the range beyond its previous position.
        self.line_start = self.line_end;

        // We track trailing newlines because, if the buffer ends immediately
        // after one, we want to return one last line on the next iteration.
        let mut trailing_newline = false;

        // Find the next line range.
        for c in self.data[self.line_start..].chars() {
            // Extend the current line range to include this char.
            self.line_end += c.len_utf8();

            if c == '\n' {
                trailing_newline = true;
                break;
            }
        }

        let line = Some((
            self.line_number,
            &self.data[
                self.line_start..self.line_end
            ]
        ));

        // Flag the iterator as done as soon as we've exhausted its data,
        // and have given one last line for data with a trailing newline.
        if self.out_of_data() && !trailing_newline {
            self.done = true;
        } else {
            self.line_number += 1;
        }

        line
    }
}

#[cfg(test)]
mod tests {
    use super::LineIterator;

    #[test]
    fn next_produces_a_value_for_empty_data() {
        let mut lines = LineIterator::new("");
        assert_eq!(Some((0, "")), lines.next());
    }

    #[test]
    fn next_includes_trailing_newlines() {
        let mut lines = LineIterator::new("line\nanother line\n");
        assert_eq!(Some((0, "line\n")), lines.next());
        assert_eq!(Some((1, "another line\n")), lines.next());
        assert_eq!(Some((2, "")), lines.next());
    }

    #[test]
    fn next_stops_at_end_of_data() {
        let mut lines = LineIterator::new("line\nanother line");
        lines.next();
        lines.next();
        assert_eq!(None, lines.next());
    }
}
<|endoftext|>


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

//! Crate for displaying simple surfaces and GPU buffers over wayland.

extern crate data_model;
extern crate sys_util;

#[path = "dwl.rs"]
mod dwl;

use dwl::*;

use crate::{DisplayT, EventDevice, GpuDisplayError, GpuDisplayFramebuffer};

use std::cell::Cell;
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::os::unix::io::{AsRawFd, RawFd};
use std::path::Path;
use std::ptr::{null, null_mut};

use data_model::VolatileMemory;
use sys_util::{round_up_to_page_size, MemoryMapping, SharedMemory};

const BUFFER_COUNT: usize = 2;
const BYTES_PER_PIXEL: u32 = 4;

struct DwlContext(*mut dwl_context);
impl Drop for DwlContext {
    fn drop(&mut self) {
        if !self.0.is_null() {
            // Safe given that we checked the pointer for non-null and it should always be of the
            // correct type.
            unsafe {
                dwl_context_destroy(&mut self.0);
            }
        }
    }
}

struct DwlDmabuf(*mut dwl_dmabuf);
impl Drop for DwlDmabuf {
    fn drop(&mut self) {
        if !self.0.is_null() {
            // Safe given that we checked the pointer for non-null and it should always be of the
            // correct type.
            unsafe {
                dwl_dmabuf_destroy(&mut self.0);
            }
        }
    }
}

struct DwlSurface(*mut dwl_surface);
impl Drop for DwlSurface {
    fn drop(&mut self) {
        if !self.0.is_null() {
            // Safe given that we checked the pointer for non-null and it should always be of the
            // correct type.
            unsafe {
                dwl_surface_destroy(&mut self.0);
            }
        }
    }
}

struct Surface {
    surface: DwlSurface,
    row_size: u32,
    buffer_size: usize,
    buffer_index: Cell<usize>,
    buffer_mem: MemoryMapping,
}

impl Surface {
    fn surface(&self) -> *mut dwl_surface {
        self.surface.0
    }
}

/// A connection to the compositor and associated collection of state.
///
/// The user of `GpuDisplay` can use `AsRawFd` to poll on the compositor connection's file
/// descriptor. When the connection is readable, `dispatch_events` can be called to process it.
pub struct DisplayWl {
    ctx: DwlContext,
    dmabufs: HashMap<u32, DwlDmabuf>,
    dmabuf_next_id: u32,
    surfaces: HashMap<u32, Surface>,
    surface_next_id: u32,
}

impl DisplayWl {
    /// Opens a fresh connection to the compositor.
    pub fn new(wayland_path: Option<&Path>) -> Result<DisplayWl, GpuDisplayError> {
        // The dwl_context_new call should always be safe to call, and we check its result.
        let ctx = DwlContext(unsafe { dwl_context_new() });
        if ctx.0.is_null() {
            return Err(GpuDisplayError::Allocate);
        }

        // The dwl_context_setup call is always safe to call given that the supplied context is
        // valid. and we check its result.
        let cstr_path = match wayland_path.map(|p| p.as_os_str().to_str()) {
            Some(Some(s)) => match CString::new(s) {
                Ok(cstr) => Some(cstr),
                Err(_) => return Err(GpuDisplayError::InvalidPath),
            },
            Some(None) => return Err(GpuDisplayError::InvalidPath),
            None => None,
        };
        // This grabs a pointer to cstr_path without moving the CString into the .map closure
        // accidentally, which triggeres a really hard to catch use after free in
        // dwl_context_setup.
        let cstr_path_ptr = cstr_path
            .as_ref()
            .map(|s: &CString| CStr::as_ptr(s))
            .unwrap_or(null());
        let setup_success = unsafe { dwl_context_setup(ctx.0, cstr_path_ptr) };
        if !setup_success {
            return Err(GpuDisplayError::Connect);
        }

        Ok(DisplayWl {
            ctx,
            dmabufs: Default::default(),
            dmabuf_next_id: 0,
            surfaces: Default::default(),
            surface_next_id: 0,
        })
    }

    fn ctx(&self) -> *mut dwl_context {
        self.ctx.0
    }

    fn get_surface(&self, surface_id: u32) -> Option<&Surface> {
        self.surfaces.get(&surface_id)
    }
}

impl DisplayT for DisplayWl {
    fn import_dmabuf(
        &mut self,
        fd: RawFd,
        offset: u32,
        stride: u32,
        modifiers: u64,
        width: u32,
        height: u32,
        fourcc: u32,
    ) -> Result<u32, GpuDisplayError> {
        // Safe given that the context pointer is valid. Any other invalid parameters would be
        // rejected by dwl_context_dmabuf_new safely. We check that the resulting dmabuf is valid
        // before filing it away.
        let dmabuf = DwlDmabuf(unsafe {
            dwl_context_dmabuf_new(
                self.ctx(),
                fd,
                offset,
                stride,
                modifiers,
                width,
                height,
                fourcc,
            )
        });
        if dmabuf.0.is_null() {
            return Err(GpuDisplayError::FailedImport);
        }

        let next_id = self.dmabuf_next_id;
        self.dmabufs.insert(next_id, dmabuf);
        self.dmabuf_next_id += 1;
        Ok(next_id)
    }

    fn release_import(&mut self, import_id: u32) {
        self.dmabufs.remove(&import_id);
    }

    fn dispatch_events(&mut self) {
        // Safe given that the context pointer is valid.
        unsafe {
            dwl_context_dispatch(self.ctx());
        }
    }

    fn create_surface(
        &mut self,
        parent_surface_id: Option<u32>,
        width: u32,
        height: u32,
    ) -> Result<u32, GpuDisplayError> {
        let parent_ptr = match parent_surface_id {
            Some(id) => match self.get_surface(id).map(|p| p.surface()) {
                Some(ptr) => ptr,
                None => return Err(GpuDisplayError::InvalidSurfaceId),
            },
            None => null_mut(),
        };
        let row_size = width * BYTES_PER_PIXEL;
        let fb_size = row_size * height;
        let buffer_size = round_up_to_page_size(fb_size as usize * BUFFER_COUNT);
        let mut buffer_shm =
            SharedMemory::named("GpuDisplaySurface").map_err(GpuDisplayError::CreateShm)?;
        buffer_shm
            .set_size(buffer_size as u64)
            .map_err(GpuDisplayError::SetSize)?;
        let buffer_mem = MemoryMapping::from_fd(&buffer_shm, buffer_size).unwrap();

        // Safe because only a valid context, parent pointer (if not  None), and buffer FD are used.
        // The returned surface is checked for validity before being filed away.
        let surface = DwlSurface(unsafe {
            dwl_context_surface_new(
                self.ctx(),
                parent_ptr,
                buffer_shm.as_raw_fd(),
                buffer_size,
                fb_size as usize,
                width,
                height,
                row_size,
            )
        });

        if surface.0.is_null() {
            return Err(GpuDisplayError::CreateSurface);
        }

        let next_id = self.surface_next_id;
        self.surfaces.insert(
            next_id,
            Surface {
                surface,
                row_size,
                buffer_size: fb_size as usize,
                buffer_index: Cell::new(0),
                buffer_mem,
            },
        );

        self.surface_next_id += 1;
        Ok(next_id)
    }

    fn release_surface(&mut self, surface_id: u32) {
        self.surfaces.remove(&surface_id);
    }

    fn framebuffer(&mut self, surface_id: u32) -> Option<GpuDisplayFramebuffer> {
        let surface = self.get_surface(surface_id)?;
        let buffer_index = (surface.buffer_index.get() + 1) % BUFFER_COUNT;
        let framebuffer = surface
            .buffer_mem
            .get_slice(buffer_index * surface.buffer_size, surface.buffer_size)
            .ok()?;
        Some(GpuDisplayFramebuffer::new(
            framebuffer,
            surface.row_size,
            BYTES_PER_PIXEL,
        ))
    }

    fn commit(&mut self, surface_id: u32) {
        match self.get_surface(surface_id) {
            Some(surface) => {
                // Safe because only a valid surface is used.
                unsafe {
                    dwl_surface_commit(surface.surface());
                }
            }
            None => debug_assert!(false, "invalid surface_id {}", surface_id),
        }
    }

    fn next_buffer_in_use(&self, surface_id: u32) -> bool {
        match self.get_surface(surface_id) {
            Some(surface) => {
                let next_buffer_index = (surface.buffer_index.get() + 1) % BUFFER_COUNT;
                // Safe because only a valid surface and buffer index is used.
                unsafe { dwl_surface_buffer_in_use(surface.surface(), next_buffer_index) }
            }
            None => {
                debug_assert!(false, "invalid surface_id {}", surface_id);
                false
            }
        }
    }

    fn flip(&mut self, surface_id: u32) {
        match self.get_surface(surface_id) {
            Some(surface) => {
                surface
                    .buffer_index
                    .set((surface.buffer_index.get() + 1) % BUFFER_COUNT);
                // Safe because only a valid surface and buffer index is used.
                unsafe {
                    dwl_surface_flip(surface.surface(), surface.buffer_index.get());
                }
            }
            None => debug_assert!(false, "invalid surface_id {}", surface_id),
        }
    }

    fn flip_to(&mut self, surface_id: u32, import_id: u32) {
        match self.get_surface(surface_id) {
            Some(surface) => {
                match self.dmabufs.get(&import_id) {
                    // Safe because only a valid surface and dmabuf is used.
                    Some(dmabuf) => unsafe { dwl_surface_flip_to(surface.surface(), dmabuf.0) },
                    None => debug_assert!(false, "invalid import_id {}", import_id),
                }
            }
            None => debug_assert!(false, "invalid surface_id {}", surface_id),
        }
    }

    fn close_requested(&self, surface_id: u32) -> bool {
        match self.get_surface(surface_id) {
            Some(surface) =>
            // Safe because only a valid surface is used.
            unsafe { dwl_surface_close_requested(surface.surface()) }
            None => false,
        }
    }

    fn set_position(&mut self, surface_id: u32, x: u32, y: u32) {
        match self.get_surface(surface_id) {
            Some(surface) => {
                // Safe because only a valid surface is used.
                unsafe {
                    dwl_surface_set_position(surface.surface(), x, y);
                }
            }
            None => debug_assert!(false, "invalid surface_id {}", surface_id),
        }
    }

    fn import_event_device(&mut self, _event_device: EventDevice) -> Result<u32, GpuDisplayError> {
        Err(GpuDisplayError::Unsupported)
    }
    fn release_event_device(&mut self, _event_device_id: u32) {
        // unsupported
    }
    fn attach_event_device(&mut self, _surface_id: u32, _event_device_id: u32) {
        // unsupported
    }
}

impl AsRawFd for DisplayWl {
    fn as_raw_fd(&self) -> RawFd {
        // Safe given that the context pointer is valid.
        unsafe { dwl_context_fd(self.ctx.0) }
    }
}
<commit_msg>Bump display_wl buffer count to 3<commit_after>// Copyright 2019 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.

//! Crate for displaying simple surfaces and GPU buffers over wayland.

extern crate data_model;
extern crate sys_util;

#[path = "dwl.rs"]
mod dwl;

use dwl::*;

use crate::{DisplayT, EventDevice, GpuDisplayError, GpuDisplayFramebuffer};

use std::cell::Cell;
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::os::unix::io::{AsRawFd, RawFd};
use std::path::Path;
use std::ptr::{null, null_mut};

use data_model::VolatileMemory;
use sys_util::{round_up_to_page_size, MemoryMapping, SharedMemory};

const BUFFER_COUNT: usize = 3;
const BYTES_PER_PIXEL: u32 = 4;

struct DwlContext(*mut dwl_context);
impl Drop for DwlContext {
    fn drop(&mut self) {
        if !self.0.is_null() {
            // Safe given that we checked the pointer for non-null and it should always be of the
            // correct type.
            unsafe {
                dwl_context_destroy(&mut self.0);
            }
        }
    }
}

struct DwlDmabuf(*mut dwl_dmabuf);
impl Drop for DwlDmabuf {
    fn drop(&mut self) {
        if !self.0.is_null() {
            // Safe given that we checked the pointer for non-null and it should always be of the
            // correct type.
            unsafe {
                dwl_dmabuf_destroy(&mut self.0);
            }
        }
    }
}

struct DwlSurface(*mut dwl_surface);
impl Drop for DwlSurface {
    fn drop(&mut self) {
        if !self.0.is_null() {
            // Safe given that we checked the pointer for non-null and it should always be of the
            // correct type.
            unsafe {
                dwl_surface_destroy(&mut self.0);
            }
        }
    }
}

struct Surface {
    surface: DwlSurface,
    row_size: u32,
    buffer_size: usize,
    buffer_index: Cell<usize>,
    buffer_mem: MemoryMapping,
}

impl Surface {
    fn surface(&self) -> *mut dwl_surface {
        self.surface.0
    }
}

/// A connection to the compositor and associated collection of state.
///
/// The user of `GpuDisplay` can use `AsRawFd` to poll on the compositor connection's file
/// descriptor. When the connection is readable, `dispatch_events` can be called to process it.
pub struct DisplayWl {
    ctx: DwlContext,
    dmabufs: HashMap<u32, DwlDmabuf>,
    dmabuf_next_id: u32,
    surfaces: HashMap<u32, Surface>,
    surface_next_id: u32,
}

impl DisplayWl {
    /// Opens a fresh connection to the compositor.
    pub fn new(wayland_path: Option<&Path>) -> Result<DisplayWl, GpuDisplayError> {
        // The dwl_context_new call should always be safe to call, and we check its result.
        let ctx = DwlContext(unsafe { dwl_context_new() });
        if ctx.0.is_null() {
            return Err(GpuDisplayError::Allocate);
        }

        // The dwl_context_setup call is always safe to call given that the supplied context is
        // valid. and we check its result.
        let cstr_path = match wayland_path.map(|p| p.as_os_str().to_str()) {
            Some(Some(s)) => match CString::new(s) {
                Ok(cstr) => Some(cstr),
                Err(_) => return Err(GpuDisplayError::InvalidPath),
            },
            Some(None) => return Err(GpuDisplayError::InvalidPath),
            None => None,
        };
        // This grabs a pointer to cstr_path without moving the CString into the .map closure
        // accidentally, which triggeres a really hard to catch use after free in
        // dwl_context_setup.
        let cstr_path_ptr = cstr_path
            .as_ref()
            .map(|s: &CString| CStr::as_ptr(s))
            .unwrap_or(null());
        let setup_success = unsafe { dwl_context_setup(ctx.0, cstr_path_ptr) };
        if !setup_success {
            return Err(GpuDisplayError::Connect);
        }

        Ok(DisplayWl {
            ctx,
            dmabufs: Default::default(),
            dmabuf_next_id: 0,
            surfaces: Default::default(),
            surface_next_id: 0,
        })
    }

    fn ctx(&self) -> *mut dwl_context {
        self.ctx.0
    }

    fn get_surface(&self, surface_id: u32) -> Option<&Surface> {
        self.surfaces.get(&surface_id)
    }
}

impl DisplayT for DisplayWl {
    fn import_dmabuf(
        &mut self,
        fd: RawFd,
        offset: u32,
        stride: u32,
        modifiers: u64,
        width: u32,
        height: u32,
        fourcc: u32,
    ) -> Result<u32, GpuDisplayError> {
        // Safe given that the context pointer is valid. Any other invalid parameters would be
        // rejected by dwl_context_dmabuf_new safely. We check that the resulting dmabuf is valid
        // before filing it away.
        let dmabuf = DwlDmabuf(unsafe {
            dwl_context_dmabuf_new(
                self.ctx(),
                fd,
                offset,
                stride,
                modifiers,
                width,
                height,
                fourcc,
            )
        });
        if dmabuf.0.is_null() {
            return Err(GpuDisplayError::FailedImport);
        }

        let next_id = self.dmabuf_next_id;
        self.dmabufs.insert(next_id, dmabuf);
        self.dmabuf_next_id += 1;
        Ok(next_id)
    }

    fn release_import(&mut self, import_id: u32) {
        self.dmabufs.remove(&import_id);
    }

    fn dispatch_events(&mut self) {
        // Safe given that the context pointer is valid.
        unsafe {
            dwl_context_dispatch(self.ctx());
        }
    }

    fn create_surface(
        &mut self,
        parent_surface_id: Option<u32>,
        width: u32,
        height: u32,
    ) -> Result<u32, GpuDisplayError> {
        let parent_ptr = match parent_surface_id {
            Some(id) => match self.get_surface(id).map(|p| p.surface()) {
                Some(ptr) => ptr,
                None => return Err(GpuDisplayError::InvalidSurfaceId),
            },
            None => null_mut(),
        };
        let row_size = width * BYTES_PER_PIXEL;
        let fb_size = row_size * height;
        let buffer_size = round_up_to_page_size(fb_size as usize * BUFFER_COUNT);
        let mut buffer_shm =
            SharedMemory::named("GpuDisplaySurface").map_err(GpuDisplayError::CreateShm)?;
        buffer_shm
            .set_size(buffer_size as u64)
            .map_err(GpuDisplayError::SetSize)?;
        let buffer_mem = MemoryMapping::from_fd(&buffer_shm, buffer_size).unwrap();

        // Safe because only a valid context, parent pointer (if not  None), and buffer FD are used.
        // The returned surface is checked for validity before being filed away.
        let surface = DwlSurface(unsafe {
            dwl_context_surface_new(
                self.ctx(),
                parent_ptr,
                buffer_shm.as_raw_fd(),
                buffer_size,
                fb_size as usize,
                width,
                height,
                row_size,
            )
        });

        if surface.0.is_null() {
            return Err(GpuDisplayError::CreateSurface);
        }

        let next_id = self.surface_next_id;
        self.surfaces.insert(
            next_id,
            Surface {
                surface,
                row_size,
                buffer_size: fb_size as usize,
                buffer_index: Cell::new(0),
                buffer_mem,
            },
        );

        self.surface_next_id += 1;
        Ok(next_id)
    }

    fn release_surface(&mut self, surface_id: u32) {
        self.surfaces.remove(&surface_id);
    }

    fn framebuffer(&mut self, surface_id: u32) -> Option<GpuDisplayFramebuffer> {
        let surface = self.get_surface(surface_id)?;
        let buffer_index = (surface.buffer_index.get() + 1) % BUFFER_COUNT;
        let framebuffer = surface
            .buffer_mem
            .get_slice(buffer_index * surface.buffer_size, surface.buffer_size)
            .ok()?;
        Some(GpuDisplayFramebuffer::new(
            framebuffer,
            surface.row_size,
            BYTES_PER_PIXEL,
        ))
    }

    fn commit(&mut self, surface_id: u32) {
        match self.get_surface(surface_id) {
            Some(surface) => {
                // Safe because only a valid surface is used.
                unsafe {
                    dwl_surface_commit(surface.surface());
                }
            }
            None => debug_assert!(false, "invalid surface_id {}", surface_id),
        }
    }

    fn next_buffer_in_use(&self, surface_id: u32) -> bool {
        match self.get_surface(surface_id) {
            Some(surface) => {
                let next_buffer_index = (surface.buffer_index.get() + 1) % BUFFER_COUNT;
                // Safe because only a valid surface and buffer index is used.
                unsafe { dwl_surface_buffer_in_use(surface.surface(), next_buffer_index) }
            }
            None => {
                debug_assert!(false, "invalid surface_id {}", surface_id);
                false
            }
        }
    }

    fn flip(&mut self, surface_id: u32) {
        match self.get_surface(surface_id) {
            Some(surface) => {
                surface
                    .buffer_index
                    .set((surface.buffer_index.get() + 1) % BUFFER_COUNT);
                // Safe because only a valid surface and buffer index is used.
                unsafe {
                    dwl_surface_flip(surface.surface(), surface.buffer_index.get());
                }
            }
            None => debug_assert!(false, "invalid surface_id {}", surface_id),
        }
    }

    fn flip_to(&mut self, surface_id: u32, import_id: u32) {
        match self.get_surface(surface_id) {
            Some(surface) => {
                match self.dmabufs.get(&import_id) {
                    // Safe because only a valid surface and dmabuf is used.
                    Some(dmabuf) => unsafe { dwl_surface_flip_to(surface.surface(), dmabuf.0) },
                    None => debug_assert!(false, "invalid import_id {}", import_id),
                }
            }
            None => debug_assert!(false, "invalid surface_id {}", surface_id),
        }
    }

    fn close_requested(&self, surface_id: u32) -> bool {
        match self.get_surface(surface_id) {
            Some(surface) =>
            // Safe because only a valid surface is used.
            unsafe { dwl_surface_close_requested(surface.surface()) }
            None => false,
        }
    }

    fn set_position(&mut self, surface_id: u32, x: u32, y: u32) {
        match self.get_surface(surface_id) {
            Some(surface) => {
                // Safe because only a valid surface is used.
                unsafe {
                    dwl_surface_set_position(surface.surface(), x, y);
                }
            }
            None => debug_assert!(false, "invalid surface_id {}", surface_id),
        }
    }

    fn import_event_device(&mut self, _event_device: EventDevice) -> Result<u32, GpuDisplayError> {
        Err(GpuDisplayError::Unsupported)
    }
    fn release_event_device(&mut self, _event_device_id: u32) {
        // unsupported
    }
    fn attach_event_device(&mut self, _surface_id: u32, _event_device_id: u32) {
        // unsupported
    }
}

impl AsRawFd for DisplayWl {
    fn as_raw_fd(&self) -> RawFd {
        // Safe given that the context pointer is valid.
        unsafe { dwl_context_fd(self.ctx.0) }
    }
}
<|endoftext|>


<commit_before>use crate::interface::{Compiler, Result};
use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt};

use rustc_incremental::DepGraphFuture;
use rustc_data_structures::sync::Lrc;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc::session::config::{OutputFilenames, OutputType};
use rustc::util::common::{time, ErrorReported};
use rustc::hir;
use rustc::lint;
use rustc::session::Session;
use rustc::lint::LintStore;
use rustc::hir::def_id::LOCAL_CRATE;
use rustc::ty::steal::Steal;
use rustc::ty::ResolverOutputs;
use rustc::dep_graph::DepGraph;
use std::cell::{Ref, RefMut, RefCell};
use std::rc::Rc;
use std::any::Any;
use std::mem;
use syntax::{self, ast};

/// Represent the result of a query.
/// This result can be stolen with the `take` method and returned with the `give` method.
pub struct Query<T> {
    result: RefCell<Option<Result<T>>>,
}

impl<T> Query<T> {
    fn compute<F: FnOnce() -> Result<T>>(&self, f: F) -> Result<&Query<T>> {
        let mut result = self.result.borrow_mut();
        if result.is_none() {
            *result = Some(f());
        }
        result.as_ref().unwrap().as_ref().map(|_| self).map_err(|err| *err)
    }

    /// Takes ownership of the query result. Further attempts to take or peek the query
    /// result will panic unless it is returned by calling the `give` method.
    pub fn take(&self) -> T {
        self.result
            .borrow_mut()
            .take()
            .expect("missing query result")
            .unwrap()
    }

    /// Borrows the query result using the RefCell. Panics if the result is stolen.
    pub fn peek(&self) -> Ref<'_, T> {
        Ref::map(self.result.borrow(), |r| {
            r.as_ref().unwrap().as_ref().expect("missing query result")
        })
    }

    /// Mutably borrows the query result using the RefCell. Panics if the result is stolen.
    pub fn peek_mut(&self) -> RefMut<'_, T> {
        RefMut::map(self.result.borrow_mut(), |r| {
            r.as_mut().unwrap().as_mut().expect("missing query result")
        })
    }
}

impl<T> Default for Query<T> {
    fn default() -> Self {
        Query {
            result: RefCell::new(None),
        }
    }
}

pub struct Queries<'comp> {
    compiler: &'comp Compiler,

    dep_graph_future: Query<Option<DepGraphFuture>>,
    parse: Query<ast::Crate>,
    crate_name: Query<String>,
    register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
    expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
    dep_graph: Query<DepGraph>,
    lower_to_hir: Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>,
    prepare_outputs: Query<OutputFilenames>,
    global_ctxt: Query<BoxedGlobalCtxt>,
    ongoing_codegen: Query<Box<dyn Any>>,
}

impl<'comp> Queries<'comp> {
    pub fn new(compiler: &'comp Compiler) -> Queries<'comp> {
        Queries {
            compiler,
            dep_graph_future: Default::default(),
            parse: Default::default(),
            crate_name: Default::default(),
            register_plugins: Default::default(),
            expansion: Default::default(),
            dep_graph: Default::default(),
            lower_to_hir: Default::default(),
            prepare_outputs: Default::default(),
            global_ctxt: Default::default(),
            ongoing_codegen: Default::default(),
        }
    }

    fn session(&self) -> &Lrc<Session> {
        &self.compiler.sess
    }
    fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> {
        &self.compiler.codegen_backend()
    }

    pub fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
        self.dep_graph_future.compute(|| {
            Ok(if self.session().opts.build_dep_graph() {
                Some(rustc_incremental::load_dep_graph(self.session()))
            } else {
                None
            })
        })
    }

    pub fn parse(&self) -> Result<&Query<ast::Crate>> {
        self.parse.compute(|| {
            passes::parse(self.session(), &self.compiler.input).map_err(
                |mut parse_error| {
                    parse_error.emit();
                    ErrorReported
                },
            )
        })
    }

    pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> {
        self.register_plugins.compute(|| {
            let crate_name = self.crate_name()?.peek().clone();
            let krate = self.parse()?.take();

            let empty: &(dyn Fn(&Session, &mut lint::LintStore) + Sync + Send) = &|_, _| {};
            let result = passes::register_plugins(
                self.session(),
                &*self.codegen_backend().metadata_loader(),
                self.compiler.register_lints
                    .as_ref()
                    .map(|p| &**p)
                    .unwrap_or_else(|| empty),
                krate,
                &crate_name,
            );

            // Compute the dependency graph (in the background). We want to do
            // this as early as possible, to give the DepGraph maximum time to
            // load before dep_graph() is called, but it also can't happen
            // until after rustc_incremental::prepare_session_directory() is
            // called, which happens within passes::register_plugins().
            self.dep_graph_future().ok();

            result
        })
    }

    pub fn crate_name(&self) -> Result<&Query<String>> {
        self.crate_name.compute(|| {
            Ok(match self.compiler.crate_name {
                Some(ref crate_name) => crate_name.clone(),
                None => {
                    let parse_result = self.parse()?;
                    let krate = parse_result.peek();
                    rustc_codegen_utils::link::find_crate_name(
                        Some(self.session()),
                        &krate.attrs,
                        &self.compiler.input
                    )
                }
            })
        })
    }

    pub fn expansion(
        &self
    ) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> {
        self.expansion.compute(|| {
            let crate_name = self.crate_name()?.peek().clone();
            let (krate, lint_store) = self.register_plugins()?.take();
            passes::configure_and_expand(
                self.session().clone(),
                lint_store.clone(),
                self.codegen_backend().metadata_loader(),
                krate,
                &crate_name,
            ).map(|(krate, resolver)| {
                (krate, Steal::new(Rc::new(RefCell::new(resolver))), lint_store)
            })
        })
    }

    pub fn dep_graph(&self) -> Result<&Query<DepGraph>> {
        self.dep_graph.compute(|| {
            Ok(match self.dep_graph_future()?.take() {
                None => DepGraph::new_disabled(),
                Some(future) => {
                    let (prev_graph, prev_work_products) =
                        time(self.session(), "blocked while dep-graph loading finishes", || {
                            future.open().unwrap_or_else(|e| rustc_incremental::LoadResult::Error {
                                message: format!("could not decode incremental cache: {:?}", e),
                            }).open(self.session())
                        });
                    DepGraph::new(prev_graph, prev_work_products)
                }
            })
        })
    }

    pub fn lower_to_hir(
        &self,
    ) -> Result<&Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>> {
        self.lower_to_hir.compute(|| {
            let expansion_result = self.expansion()?;
            let peeked = expansion_result.peek();
            let krate = &peeked.0;
            let resolver = peeked.1.steal();
            let lint_store = &peeked.2;
            let hir = Steal::new(resolver.borrow_mut().access(|resolver| {
                passes::lower_to_hir(
                    self.session(),
                    lint_store,
                    resolver,
                    &*self.dep_graph()?.peek(),
                    &krate
                )
            })?);
            Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver))))
        })
    }

    pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
        self.prepare_outputs.compute(|| {
            let expansion_result = self.expansion()?;
            let (krate, boxed_resolver, _) = &*expansion_result.peek();
            let crate_name = self.crate_name()?;
            let crate_name = crate_name.peek();
            passes::prepare_outputs(
                self.session(), self.compiler, &krate, &boxed_resolver, &crate_name
            )
        })
    }

    pub fn global_ctxt(&self) -> Result<&Query<BoxedGlobalCtxt>> {
        self.global_ctxt.compute(|| {
            let crate_name = self.crate_name()?.peek().clone();
            let outputs = self.prepare_outputs()?.peek().clone();
            let lint_store = self.expansion()?.peek().2.clone();
            let hir = self.lower_to_hir()?;
            let hir = hir.peek();
            let (hir_forest, resolver_outputs) = &*hir;
            Ok(passes::create_global_ctxt(
                self.compiler,
                lint_store,
                hir_forest.steal(),
                resolver_outputs.steal(),
                outputs,
                &crate_name))
        })
    }

    pub fn ongoing_codegen(&self) -> Result<&Query<Box<dyn Any>>> {
        self.ongoing_codegen.compute(|| {
            let outputs = self.prepare_outputs()?;
            self.global_ctxt()?.peek_mut().enter(|tcx| {
                tcx.analysis(LOCAL_CRATE).ok();

                // Don't do code generation if there were any errors
                self.session().compile_status()?;

                Ok(passes::start_codegen(
                    &***self.codegen_backend(),
                    tcx,
                    &*outputs.peek()
                ))
            })
        })
    }

    pub fn linker(&self) -> Result<Linker> {
        let dep_graph = self.dep_graph()?;
        let prepare_outputs = self.prepare_outputs()?;
        let ongoing_codegen = self.ongoing_codegen()?;

        let sess = self.session().clone();
        let codegen_backend = self.codegen_backend().clone();

        Ok(Linker {
            sess,
            dep_graph: dep_graph.peek().clone(),
            prepare_outputs: prepare_outputs.take(),
            ongoing_codegen: ongoing_codegen.take(),
            codegen_backend,
        })
    }
}

pub struct Linker {
    sess: Lrc<Session>,
    dep_graph: DepGraph,
    prepare_outputs: OutputFilenames,
    ongoing_codegen: Box<dyn Any>,
    codegen_backend: Lrc<Box<dyn CodegenBackend>>,
}

impl Linker {
    pub fn link(self) -> Result<()> {
        self.codegen_backend.join_codegen_and_link(
            self.ongoing_codegen,
            &self.sess,
            &self.dep_graph,
            &self.prepare_outputs,
        ).map_err(|_| ErrorReported)
    }
}

impl Compiler {
    pub fn enter<'c, F, T>(&'c self, f: F) -> T
        where F: for<'q> FnOnce(&'q Queries<'c>) -> T
    {
        let queries = Queries::new(&self);
        f(&queries)
    }

    // This method is different to all the other methods in `Compiler` because
    // it lacks a `Queries` entry. It's also not currently used. It does serve
    // as an example of how `Compiler` can be used, with additional steps added
    // between some passes. And see `rustc_driver::run_compiler` for a more
    // complex example.
    pub fn compile(&self) -> Result<()> {
        let linker = self.enter(|queries| {
            queries.prepare_outputs()?;

            if self.session().opts.output_types.contains_key(&OutputType::DepInfo)
                && self.session().opts.output_types.len() == 1
            {
                return Ok(None)
            }

            queries.global_ctxt()?;

            // Drop AST after creating GlobalCtxt to free memory.
            mem::drop(queries.expansion()?.take());

            queries.ongoing_codegen()?;

            // Drop GlobalCtxt after starting codegen to free memory.
            mem::drop(queries.global_ctxt()?.take());

            let linker = queries.linker()?;
            Ok(Some(linker))
        })?;

        if let Some(linker) = linker {
            linker.link()?
        }

        Ok(())
    }
}
<commit_msg>Superfluous lifetime.<commit_after>use crate::interface::{Compiler, Result};
use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt};

use rustc_incremental::DepGraphFuture;
use rustc_data_structures::sync::Lrc;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc::session::config::{OutputFilenames, OutputType};
use rustc::util::common::{time, ErrorReported};
use rustc::hir;
use rustc::lint;
use rustc::session::Session;
use rustc::lint::LintStore;
use rustc::hir::def_id::LOCAL_CRATE;
use rustc::ty::steal::Steal;
use rustc::ty::ResolverOutputs;
use rustc::dep_graph::DepGraph;
use std::cell::{Ref, RefMut, RefCell};
use std::rc::Rc;
use std::any::Any;
use std::mem;
use syntax::{self, ast};

/// Represent the result of a query.
/// This result can be stolen with the `take` method and returned with the `give` method.
pub struct Query<T> {
    result: RefCell<Option<Result<T>>>,
}

impl<T> Query<T> {
    fn compute<F: FnOnce() -> Result<T>>(&self, f: F) -> Result<&Query<T>> {
        let mut result = self.result.borrow_mut();
        if result.is_none() {
            *result = Some(f());
        }
        result.as_ref().unwrap().as_ref().map(|_| self).map_err(|err| *err)
    }

    /// Takes ownership of the query result. Further attempts to take or peek the query
    /// result will panic unless it is returned by calling the `give` method.
    pub fn take(&self) -> T {
        self.result
            .borrow_mut()
            .take()
            .expect("missing query result")
            .unwrap()
    }

    /// Borrows the query result using the RefCell. Panics if the result is stolen.
    pub fn peek(&self) -> Ref<'_, T> {
        Ref::map(self.result.borrow(), |r| {
            r.as_ref().unwrap().as_ref().expect("missing query result")
        })
    }

    /// Mutably borrows the query result using the RefCell. Panics if the result is stolen.
    pub fn peek_mut(&self) -> RefMut<'_, T> {
        RefMut::map(self.result.borrow_mut(), |r| {
            r.as_mut().unwrap().as_mut().expect("missing query result")
        })
    }
}

impl<T> Default for Query<T> {
    fn default() -> Self {
        Query {
            result: RefCell::new(None),
        }
    }
}

pub struct Queries<'comp> {
    compiler: &'comp Compiler,

    dep_graph_future: Query<Option<DepGraphFuture>>,
    parse: Query<ast::Crate>,
    crate_name: Query<String>,
    register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
    expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
    dep_graph: Query<DepGraph>,
    lower_to_hir: Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>,
    prepare_outputs: Query<OutputFilenames>,
    global_ctxt: Query<BoxedGlobalCtxt>,
    ongoing_codegen: Query<Box<dyn Any>>,
}

impl<'comp> Queries<'comp> {
    pub fn new(compiler: &'comp Compiler) -> Queries<'comp> {
        Queries {
            compiler,
            dep_graph_future: Default::default(),
            parse: Default::default(),
            crate_name: Default::default(),
            register_plugins: Default::default(),
            expansion: Default::default(),
            dep_graph: Default::default(),
            lower_to_hir: Default::default(),
            prepare_outputs: Default::default(),
            global_ctxt: Default::default(),
            ongoing_codegen: Default::default(),
        }
    }

    fn session(&self) -> &Lrc<Session> {
        &self.compiler.sess
    }
    fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> {
        &self.compiler.codegen_backend()
    }

    pub fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
        self.dep_graph_future.compute(|| {
            Ok(if self.session().opts.build_dep_graph() {
                Some(rustc_incremental::load_dep_graph(self.session()))
            } else {
                None
            })
        })
    }

    pub fn parse(&self) -> Result<&Query<ast::Crate>> {
        self.parse.compute(|| {
            passes::parse(self.session(), &self.compiler.input).map_err(
                |mut parse_error| {
                    parse_error.emit();
                    ErrorReported
                },
            )
        })
    }

    pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> {
        self.register_plugins.compute(|| {
            let crate_name = self.crate_name()?.peek().clone();
            let krate = self.parse()?.take();

            let empty: &(dyn Fn(&Session, &mut lint::LintStore) + Sync + Send) = &|_, _| {};
            let result = passes::register_plugins(
                self.session(),
                &*self.codegen_backend().metadata_loader(),
                self.compiler.register_lints
                    .as_ref()
                    .map(|p| &**p)
                    .unwrap_or_else(|| empty),
                krate,
                &crate_name,
            );

            // Compute the dependency graph (in the background). We want to do
            // this as early as possible, to give the DepGraph maximum time to
            // load before dep_graph() is called, but it also can't happen
            // until after rustc_incremental::prepare_session_directory() is
            // called, which happens within passes::register_plugins().
            self.dep_graph_future().ok();

            result
        })
    }

    pub fn crate_name(&self) -> Result<&Query<String>> {
        self.crate_name.compute(|| {
            Ok(match self.compiler.crate_name {
                Some(ref crate_name) => crate_name.clone(),
                None => {
                    let parse_result = self.parse()?;
                    let krate = parse_result.peek();
                    rustc_codegen_utils::link::find_crate_name(
                        Some(self.session()),
                        &krate.attrs,
                        &self.compiler.input
                    )
                }
            })
        })
    }

    pub fn expansion(
        &self
    ) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> {
        self.expansion.compute(|| {
            let crate_name = self.crate_name()?.peek().clone();
            let (krate, lint_store) = self.register_plugins()?.take();
            passes::configure_and_expand(
                self.session().clone(),
                lint_store.clone(),
                self.codegen_backend().metadata_loader(),
                krate,
                &crate_name,
            ).map(|(krate, resolver)| {
                (krate, Steal::new(Rc::new(RefCell::new(resolver))), lint_store)
            })
        })
    }

    pub fn dep_graph(&self) -> Result<&Query<DepGraph>> {
        self.dep_graph.compute(|| {
            Ok(match self.dep_graph_future()?.take() {
                None => DepGraph::new_disabled(),
                Some(future) => {
                    let (prev_graph, prev_work_products) =
                        time(self.session(), "blocked while dep-graph loading finishes", || {
                            future.open().unwrap_or_else(|e| rustc_incremental::LoadResult::Error {
                                message: format!("could not decode incremental cache: {:?}", e),
                            }).open(self.session())
                        });
                    DepGraph::new(prev_graph, prev_work_products)
                }
            })
        })
    }

    pub fn lower_to_hir(
        &self,
    ) -> Result<&Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>> {
        self.lower_to_hir.compute(|| {
            let expansion_result = self.expansion()?;
            let peeked = expansion_result.peek();
            let krate = &peeked.0;
            let resolver = peeked.1.steal();
            let lint_store = &peeked.2;
            let hir = Steal::new(resolver.borrow_mut().access(|resolver| {
                passes::lower_to_hir(
                    self.session(),
                    lint_store,
                    resolver,
                    &*self.dep_graph()?.peek(),
                    &krate
                )
            })?);
            Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver))))
        })
    }

    pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
        self.prepare_outputs.compute(|| {
            let expansion_result = self.expansion()?;
            let (krate, boxed_resolver, _) = &*expansion_result.peek();
            let crate_name = self.crate_name()?;
            let crate_name = crate_name.peek();
            passes::prepare_outputs(
                self.session(), self.compiler, &krate, &boxed_resolver, &crate_name
            )
        })
    }

    pub fn global_ctxt(&self) -> Result<&Query<BoxedGlobalCtxt>> {
        self.global_ctxt.compute(|| {
            let crate_name = self.crate_name()?.peek().clone();
            let outputs = self.prepare_outputs()?.peek().clone();
            let lint_store = self.expansion()?.peek().2.clone();
            let hir = self.lower_to_hir()?;
            let hir = hir.peek();
            let (hir_forest, resolver_outputs) = &*hir;
            Ok(passes::create_global_ctxt(
                self.compiler,
                lint_store,
                hir_forest.steal(),
                resolver_outputs.steal(),
                outputs,
                &crate_name))
        })
    }

    pub fn ongoing_codegen(&self) -> Result<&Query<Box<dyn Any>>> {
        self.ongoing_codegen.compute(|| {
            let outputs = self.prepare_outputs()?;
            self.global_ctxt()?.peek_mut().enter(|tcx| {
                tcx.analysis(LOCAL_CRATE).ok();

                // Don't do code generation if there were any errors
                self.session().compile_status()?;

                Ok(passes::start_codegen(
                    &***self.codegen_backend(),
                    tcx,
                    &*outputs.peek()
                ))
            })
        })
    }

    pub fn linker(&self) -> Result<Linker> {
        let dep_graph = self.dep_graph()?;
        let prepare_outputs = self.prepare_outputs()?;
        let ongoing_codegen = self.ongoing_codegen()?;

        let sess = self.session().clone();
        let codegen_backend = self.codegen_backend().clone();

        Ok(Linker {
            sess,
            dep_graph: dep_graph.peek().clone(),
            prepare_outputs: prepare_outputs.take(),
            ongoing_codegen: ongoing_codegen.take(),
            codegen_backend,
        })
    }
}

pub struct Linker {
    sess: Lrc<Session>,
    dep_graph: DepGraph,
    prepare_outputs: OutputFilenames,
    ongoing_codegen: Box<dyn Any>,
    codegen_backend: Lrc<Box<dyn CodegenBackend>>,
}

impl Linker {
    pub fn link(self) -> Result<()> {
        self.codegen_backend.join_codegen_and_link(
            self.ongoing_codegen,
            &self.sess,
            &self.dep_graph,
            &self.prepare_outputs,
        ).map_err(|_| ErrorReported)
    }
}

impl Compiler {
    pub fn enter<F, T>(&self, f: F) -> T
        where F: for<'q> FnOnce(&'q Queries<'_>) -> T
    {
        let queries = Queries::new(&self);
        f(&queries)
    }

    // This method is different to all the other methods in `Compiler` because
    // it lacks a `Queries` entry. It's also not currently used. It does serve
    // as an example of how `Compiler` can be used, with additional steps added
    // between some passes. And see `rustc_driver::run_compiler` for a more
    // complex example.
    pub fn compile(&self) -> Result<()> {
        let linker = self.enter(|queries| {
            queries.prepare_outputs()?;

            if self.session().opts.output_types.contains_key(&OutputType::DepInfo)
                && self.session().opts.output_types.len() == 1
            {
                return Ok(None)
            }

            queries.global_ctxt()?;

            // Drop AST after creating GlobalCtxt to free memory.
            mem::drop(queries.expansion()?.take());

            queries.ongoing_codegen()?;

            // Drop GlobalCtxt after starting codegen to free memory.
            mem::drop(queries.global_ctxt()?.take());

            let linker = queries.linker()?;
            Ok(Some(linker))
        })?;

        if let Some(linker) = linker {
            linker.link()?
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Completes environment variables defined by Cargo (https://doc.rust-lang.org/cargo/reference/environment-variables.html)
use ide_db::syntax_helpers::node_ext::get_outer_macro_name;
use syntax::ast::{self, IsString};

use crate::{CompletionItem, CompletionItemKind};

use super::Completions;
const CARGO_DEFINED_VARS: &[(&str, &str)] = &[
("CARGO","Path to the cargo binary performing the build"),
("CARGO_MANIFEST_DIR","The directory containing the manifest of your package"),
("CARGO_PKG_VERSION","The full version of your package"),
("CARGO_PKG_VERSION_MAJOR","The major version of your package"),
("CARGO_PKG_VERSION_MINOR","The minor version of your package"),
("CARGO_PKG_VERSION_PATCH","The patch version of your package"),
("CARGO_PKG_VERSION_PRE","The pre-release version of your package"),
("CARGO_PKG_AUTHORS","Colon separated list of authors from the manifest of your package"),
("CARGO_PKG_NAME","The name of your package"),
("CARGO_PKG_DESCRIPTION","The description from the manifest of your package"),
("CARGO_PKG_HOMEPAGE","The home page from the manifest of your package"),
("CARGO_PKG_REPOSITORY","The repository from the manifest of your package"),
("CARGO_PKG_LICENSE","The license from the manifest of your package"),
("CARGO_PKG_LICENSE_FILE","The license file from the manifest of your package"),
("CARGO_PKG_RUST_VERSION","The Rust version from the manifest of your package. Note that this is the minimum Rust version supported by the package, not the current Rust version"),
("CARGO_CRATE_NAME","The name of the crate that is currently being compiled"),
("CARGO_BIN_NAME","The name of the binary that is currently being compiled (if it is a binary). This name does not include any file extension, such as .exe"),
("CARGO_PRIMARY_PACKAGE","This environment variable will be set if the package being built is primary. Primary packages are the ones the user selected on the command-line, either with -p flags or the defaults based on the current directory and the default workspace members. This environment variable will not be set when building dependencies. This is only set when compiling the package (not when running binaries or tests)"),
("CARGO_TARGET_TMPDIR","Only set when building integration test or benchmark code. This is a path to a directory inside the target directory where integration tests or benchmarks are free to put any data needed by the tests/benches. Cargo initially creates this directory but doesn't manage its content in any way, this is the responsibility of the test code")
];

pub(crate) fn complete_cargo_env_vars(acc: &mut Completions, expanded: &ast::String) -> Option<()> {
    guard_env_macro(expanded)?;
    let range = expanded.text_range_between_quotes()?;

    CARGO_DEFINED_VARS.iter().for_each(|(var, detail)| {
        let mut item = CompletionItem::new(CompletionItemKind::Keyword, range, var);
        item.detail(*detail);
        item.add_to(acc);
    });

    Some(())
}

fn guard_env_macro(string: &ast::String) -> Option<()> {
    let name = get_outer_macro_name(string)?;
    if !matches!(name.text().as_str(), "env" | "option_env") {
        return None;
    }

    Some(())
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_edit, completion_list};

    fn check(macro_name: &str) {
        check_edit(
            "CARGO_BIN_NAME",
            &format!(
                r#"
            fn main() {{
                let foo = {}!("CAR$0");
            }}
        "#,
                macro_name
            ),
            &format!(
                r#"
            fn main() {{
                let foo = {}!("CARGO_BIN_NAME");
            }}
        "#,
                macro_name
            ),
        );
    }
    #[test]
    fn completes_env_variable_in_env() {
        check("env")
    }

    #[test]
    fn completes_env_variable_in_option_env() {
        check("option_env");
    }

    #[test]
    fn doesnt_complete_in_random_strings() {
        let fixture = r#"
            fn main() {
                let foo = "CA$0";
            }
        "#;

        let completions = completion_list(fixture);
        assert!(completions.is_empty(), "Completions weren't empty: {}", completions);
    }

    #[test]
    fn doesnt_complete_in_random_macro() {
        let fixture = r#"
            macro_rules! bar {
                ($($arg:tt)*) => { 0 }
            }

            fn main() {
                let foo = bar!("CA$0");

            }
        "#;

        let completions = completion_list(fixture);
        assert!(completions.is_empty(), "Completions weren't empty: {}", completions);
    }
}
<commit_msg>Restrict auto-completion for only built-in macros<commit_after>//! Completes environment variables defined by Cargo (https://doc.rust-lang.org/cargo/reference/environment-variables.html)
use hir::Semantics;
use ide_db::{syntax_helpers::node_ext::get_outer_macro, RootDatabase};
use syntax::ast::{self, IsString};

use crate::{context::CompletionContext, CompletionItem, CompletionItemKind};

use super::Completions;
const CARGO_DEFINED_VARS: &[(&str, &str)] = &[
("CARGO","Path to the cargo binary performing the build"),
("CARGO_MANIFEST_DIR","The directory containing the manifest of your package"),
("CARGO_PKG_VERSION","The full version of your package"),
("CARGO_PKG_VERSION_MAJOR","The major version of your package"),
("CARGO_PKG_VERSION_MINOR","The minor version of your package"),
("CARGO_PKG_VERSION_PATCH","The patch version of your package"),
("CARGO_PKG_VERSION_PRE","The pre-release version of your package"),
("CARGO_PKG_AUTHORS","Colon separated list of authors from the manifest of your package"),
("CARGO_PKG_NAME","The name of your package"),
("CARGO_PKG_DESCRIPTION","The description from the manifest of your package"),
("CARGO_PKG_HOMEPAGE","The home page from the manifest of your package"),
("CARGO_PKG_REPOSITORY","The repository from the manifest of your package"),
("CARGO_PKG_LICENSE","The license from the manifest of your package"),
("CARGO_PKG_LICENSE_FILE","The license file from the manifest of your package"),
("CARGO_PKG_RUST_VERSION","The Rust version from the manifest of your package. Note that this is the minimum Rust version supported by the package, not the current Rust version"),
("CARGO_CRATE_NAME","The name of the crate that is currently being compiled"),
("CARGO_BIN_NAME","The name of the binary that is currently being compiled (if it is a binary). This name does not include any file extension, such as .exe"),
("CARGO_PRIMARY_PACKAGE","This environment variable will be set if the package being built is primary. Primary packages are the ones the user selected on the command-line, either with -p flags or the defaults based on the current directory and the default workspace members. This environment variable will not be set when building dependencies. This is only set when compiling the package (not when running binaries or tests)"),
("CARGO_TARGET_TMPDIR","Only set when building integration test or benchmark code. This is a path to a directory inside the target directory where integration tests or benchmarks are free to put any data needed by the tests/benches. Cargo initially creates this directory but doesn't manage its content in any way, this is the responsibility of the test code")
];

pub(crate) fn complete_cargo_env_vars(
    acc: &mut Completions,
    ctx: &CompletionContext<'_>,
    expanded: &ast::String,
) -> Option<()> {
    guard_env_macro(expanded, &ctx.sema, &ctx.db)?;
    let range = expanded.text_range_between_quotes()?;

    CARGO_DEFINED_VARS.iter().for_each(|(var, detail)| {
        let mut item = CompletionItem::new(CompletionItemKind::Keyword, range, var);
        item.detail(*detail);
        item.add_to(acc);
    });

    Some(())
}

fn guard_env_macro(
    string: &ast::String,
    semantics: &Semantics<'_, RootDatabase>,
    db: &RootDatabase,
) -> Option<()> {
    let call = get_outer_macro(string)?;
    let name = call.path()?.segment()?.name_ref()?;
    let makro = semantics.resolve_macro_call(&call)?;

    match name.text().as_str() {
        "env" | "option_env" if makro.kind(db) == hir::MacroKind::BuiltIn => Some(()),
        _ => None,
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_edit, completion_list};

    fn check(macro_name: &str) {
        check_edit(
            "CARGO_BIN_NAME",
            &format!(
                r#"
            #[rustc_builtin_macro]
            macro_rules! {} {{
                ($var:literal) => {{ 0 }}
            }}

            fn main() {{
                let foo = {}!("CAR$0");
            }}
        "#,
                macro_name, macro_name
            ),
            &format!(
                r#"
            #[rustc_builtin_macro]
            macro_rules! {} {{
                ($var:literal) => {{ 0 }}
            }}

            fn main() {{
                let foo = {}!("CARGO_BIN_NAME");
            }}
        "#,
                macro_name, macro_name
            ),
        );
    }
    #[test]
    fn completes_env_variable_in_env() {
        check("env")
    }

    #[test]
    fn completes_env_variable_in_option_env() {
        check("option_env");
    }

    #[test]
    fn doesnt_complete_in_random_strings() {
        let fixture = r#"
            fn main() {
                let foo = "CA$0";
            }
        "#;

        let completions = completion_list(fixture);
        assert!(completions.is_empty(), "Completions weren't empty: {}", completions);
    }

    #[test]
    fn doesnt_complete_in_random_macro() {
        let fixture = r#"
            macro_rules! bar {
                ($($arg:tt)*) => { 0 }
            }

            fn main() {
                let foo = bar!("CA$0");

            }
        "#;

        let completions = completion_list(fixture);
        assert!(completions.is_empty(), "Completions weren't empty: {}", completions);
    }

    #[test]
    fn doesnt_complete_for_shadowed_macro() {
        let fixture = r#"
            macro_rules! env {
                ($var:literal) => { 0 }
            }

            fn main() {
                let foo = env!("CA$0");
            }
        "#;

        let completions = completion_list(fixture);
        assert!(completions.is_empty(), "Completions weren't empty: {}", completions)
    }
}
<|endoftext|>