<commit_before>use std::iter::Empty;
use std::ops::Range;
use std::sync::Arc;

use command_buffer::Submission;
use device::Device;
use format::FormatDesc;
use format::FormatTy;
use image::sys::Dimensions;
use image::sys::Layout;
use image::sys::UnsafeImage;
use image::sys::UnsafeImageView;
use image::sys::Usage;
use image::traits::AccessRange;
use image::traits::Image;
use image::traits::ImageContent;
use image::traits::ImageView;
use memory::DeviceMemory;
use sync::Sharing;

use OomError;

pub struct AttachmentImage<F> {
    image: UnsafeImage,
    view: UnsafeImageView,
    memory: DeviceMemory,
    format: F,

    // Layout to use when the image is used as a framebuffer attachment.
    // Should be either "depth-stencil optimal" or "color optimal".
    attachment_layout: Layout,
}

impl<F> AttachmentImage<F> {
    pub fn new(device: &Arc<Device>, dimensions: [u32; 2], format: F)
               -> Result<Arc<AttachmentImage<F>>, OomError>
        where F: FormatDesc
    {
        let is_depth = match format.format().ty() {
            FormatTy::Depth => true,
            FormatTy::DepthStencil => true,
            FormatTy::Compressed => panic!(),
            _ => false
        };

        let usage = Usage {
            transfer_source: true,
            sampled: true,
            color_attachment: !is_depth,
            depth_stencil_attachment: is_depth,
            input_attachment: true,
            .. Usage::none()
        };

        let (image, mem_reqs) = unsafe {
            try!(UnsafeImage::new(device, &usage, format.format(),
                                  Dimensions::Dim2d { width: dimensions[0], height: dimensions[1] },
                                  1, 1, Sharing::Exclusive::<Empty<u32>>, false, false))
        };

        let mem_ty = {
            let device_local = device.physical_device().memory_types()
                                     .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
                                     .filter(|t| t.is_device_local());
            let any = device.physical_device().memory_types()
                            .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0);
            device_local.chain(any).next().unwrap()
        };

        // note: alignment doesn't need to be checked because allocating memory is guaranteed to
        //       fulfill any alignment requirement

        let mem = try!(DeviceMemory::alloc(device, &mem_ty, mem_reqs.size));
        unsafe { try!(image.bind_memory(&mem, 0 .. mem_reqs.size)); }

        let view = unsafe {
            try!(UnsafeImageView::new(&image))
        };

        Ok(Arc::new(AttachmentImage {
            image: image,
            view: view,
            memory: mem,
            format: format,
            attachment_layout: if is_depth { Layout::DepthStencilAttachmentOptimal }
                               else { Layout::ColorAttachmentOptimal },
        }))
    }

    #[inline]
    pub fn dimensions(&self) -> Dimensions {
        self.image.dimensions()
    }
}

unsafe impl<F> Image for AttachmentImage<F> {
    #[inline]
    fn inner_image(&self) -> &UnsafeImage {
        &self.image
    }

    #[inline]
    fn blocks(&self, _: Range<u32>, _: Range<u32>) -> Vec<(u32, u32)> {
        vec![(0, 0)]
    }

    #[inline]
    fn initial_layout(&self, _: (u32, u32), _: Layout) -> Layout {
        self.attachment_layout
    }

    #[inline]
    fn final_layout(&self, _: (u32, u32), _: Layout) -> Layout {
        self.attachment_layout
    }

    fn needs_fence(&self, access: &mut Iterator<Item = AccessRange>) -> Option<bool> {
        Some(false)
    }

    unsafe fn gpu_access(&self, access: &mut Iterator<Item = AccessRange>,
                         submission: &Arc<Submission>) -> Vec<Arc<Submission>>
    {
        vec![]
    }
}

unsafe impl<P, F> ImageContent<P> for AttachmentImage<F> {
    #[inline]
    fn matches_format(&self) -> bool {
        true        // FIXME:
    }
}

unsafe impl<F: 'static> ImageView for AttachmentImage<F> {
    #[inline]
    fn parent(&self) -> &Image {
        self
    }

    #[inline]
    fn parent_arc(me: &Arc<Self>) -> Arc<Image> where Self: Sized {
        me.clone() as Arc<_>
    }

    #[inline]
    fn inner_view(&self) -> &UnsafeImageView {
        &self.view
    }

    #[inline]
    fn descriptor_set_storage_image_layout(&self, _: AccessRange) -> Layout {
        Layout::ColorAttachmentOptimal
    }

    #[inline]
    fn descriptor_set_combined_image_sampler_layout(&self, _: AccessRange) -> Layout {
        Layout::ColorAttachmentOptimal
    }

    #[inline]
    fn descriptor_set_sampled_image_layout(&self, _: AccessRange) -> Layout {
        Layout::ColorAttachmentOptimal
    }

    #[inline]
    fn descriptor_set_input_attachment_layout(&self, _: AccessRange) -> Layout {
        Layout::ColorAttachmentOptimal
    }

    #[inline]
    fn identity_swizzle(&self) -> bool {
        true
    }
}
<commit_msg>Use correct synchronization for AttachmentImage<commit_after>use std::mem;
use std::iter::Empty;
use std::ops::Range;
use std::sync::Arc;
use std::sync::Mutex;

use command_buffer::Submission;
use device::Device;
use format::FormatDesc;
use format::FormatTy;
use image::sys::Dimensions;
use image::sys::Layout;
use image::sys::UnsafeImage;
use image::sys::UnsafeImageView;
use image::sys::Usage;
use image::traits::AccessRange;
use image::traits::Image;
use image::traits::ImageContent;
use image::traits::ImageView;
use memory::DeviceMemory;
use sync::Sharing;

use OomError;

pub struct AttachmentImage<F> {
    image: UnsafeImage,
    view: UnsafeImageView,
    memory: DeviceMemory,
    format: F,

    // Layout to use when the image is used as a framebuffer attachment.
    // Should be either "depth-stencil optimal" or "color optimal".
    attachment_layout: Layout,

    latest_submission: Mutex<Option<Arc<Submission>>>,
}

impl<F> AttachmentImage<F> {
    pub fn new(device: &Arc<Device>, dimensions: [u32; 2], format: F)
               -> Result<Arc<AttachmentImage<F>>, OomError>
        where F: FormatDesc
    {
        let is_depth = match format.format().ty() {
            FormatTy::Depth => true,
            FormatTy::DepthStencil => true,
            FormatTy::Compressed => panic!(),
            _ => false
        };

        let usage = Usage {
            transfer_source: true,
            sampled: true,
            color_attachment: !is_depth,
            depth_stencil_attachment: is_depth,
            input_attachment: true,
            .. Usage::none()
        };

        let (image, mem_reqs) = unsafe {
            try!(UnsafeImage::new(device, &usage, format.format(),
                                  Dimensions::Dim2d { width: dimensions[0], height: dimensions[1] },
                                  1, 1, Sharing::Exclusive::<Empty<u32>>, false, false))
        };

        let mem_ty = {
            let device_local = device.physical_device().memory_types()
                                     .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
                                     .filter(|t| t.is_device_local());
            let any = device.physical_device().memory_types()
                            .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0);
            device_local.chain(any).next().unwrap()
        };

        // note: alignment doesn't need to be checked because allocating memory is guaranteed to
        //       fulfill any alignment requirement

        let mem = try!(DeviceMemory::alloc(device, &mem_ty, mem_reqs.size));
        unsafe { try!(image.bind_memory(&mem, 0 .. mem_reqs.size)); }

        let view = unsafe {
            try!(UnsafeImageView::new(&image))
        };

        Ok(Arc::new(AttachmentImage {
            image: image,
            view: view,
            memory: mem,
            format: format,
            attachment_layout: if is_depth { Layout::DepthStencilAttachmentOptimal }
                               else { Layout::ColorAttachmentOptimal },
            latest_submission: Mutex::new(None),
        }))
    }

    #[inline]
    pub fn dimensions(&self) -> Dimensions {
        self.image.dimensions()
    }
}

unsafe impl<F> Image for AttachmentImage<F> {
    #[inline]
    fn inner_image(&self) -> &UnsafeImage {
        &self.image
    }

    #[inline]
    fn blocks(&self, _: Range<u32>, _: Range<u32>) -> Vec<(u32, u32)> {
        vec![(0, 0)]
    }

    #[inline]
    fn initial_layout(&self, _: (u32, u32), _: Layout) -> Layout {
        self.attachment_layout
    }

    #[inline]
    fn final_layout(&self, _: (u32, u32), _: Layout) -> Layout {
        self.attachment_layout
    }

    fn needs_fence(&self, access: &mut Iterator<Item = AccessRange>) -> Option<bool> {
        Some(false)
    }

    unsafe fn gpu_access(&self, _: &mut Iterator<Item = AccessRange>,
                         submission: &Arc<Submission>) -> Vec<Arc<Submission>>
    {
        let mut latest_submission = self.latest_submission.lock().unwrap();

        let dependency = mem::replace(&mut *latest_submission, Some(submission.clone()));
        if let Some(dependency) = dependency {
            vec![dependency]
        } else {
            vec![]
        }
    }
}

unsafe impl<P, F> ImageContent<P> for AttachmentImage<F> {
    #[inline]
    fn matches_format(&self) -> bool {
        true        // FIXME:
    }
}

unsafe impl<F: 'static> ImageView for AttachmentImage<F> {
    #[inline]
    fn parent(&self) -> &Image {
        self
    }

    #[inline]
    fn parent_arc(me: &Arc<Self>) -> Arc<Image> where Self: Sized {
        me.clone() as Arc<_>
    }

    #[inline]
    fn inner_view(&self) -> &UnsafeImageView {
        &self.view
    }

    #[inline]
    fn descriptor_set_storage_image_layout(&self, _: AccessRange) -> Layout {
        Layout::ColorAttachmentOptimal
    }

    #[inline]
    fn descriptor_set_combined_image_sampler_layout(&self, _: AccessRange) -> Layout {
        Layout::ColorAttachmentOptimal
    }

    #[inline]
    fn descriptor_set_sampled_image_layout(&self, _: AccessRange) -> Layout {
        Layout::ColorAttachmentOptimal
    }

    #[inline]
    fn descriptor_set_input_attachment_layout(&self, _: AccessRange) -> Layout {
        Layout::ColorAttachmentOptimal
    }

    #[inline]
    fn identity_swizzle(&self) -> bool {
        true
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use crate::backend::Backend;
use crate::connection::Connection;
use crate::deserialize::QueryableByName;
use crate::query_builder::{AstPass, QueryFragment, QueryId};
use crate::query_dsl::{LoadQuery, RunQueryDsl};
use crate::result::QueryResult;
use crate::serialize::ToSql;
use crate::sql_types::HasSqlType;

#[derive(Debug, Clone)]
#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
/// The return value of `sql_query`.
///
/// Unlike most queries in Diesel, `SqlQuery` loads its data by column name,
/// rather than by index. This means that you cannot deserialize this query into
/// a tuple, and any structs used must implement `QueryableByName`.
///
/// See [`sql_query`](../fn.sql_query.html) for examples.
pub struct SqlQuery<Inner = ()> {
    inner: Inner,
    query: String,
}

impl<Inner> SqlQuery<Inner> {
    pub(crate) fn new(inner: Inner, query: String) -> Self {
        SqlQuery { inner, query }
    }

    /// Bind a value for use with this SQL query. The given query should have
    /// placeholders that vary based on the database type,
    /// like [SQLite Parameters](https://sqlite.org/lang_expr.html#varparam) or
    /// the [PostgreSQL PREPARE syntax](https://www.postgresql.org/docs/current/sql-prepare.html).
    ///
    /// # Safety
    ///
    /// This function should be used with care, as Diesel cannot validate that
    /// the value is of the right type nor can it validate that you have passed
    /// the correct number of parameters.
    ///
    /// # Example
    ///
    /// ```
    /// # #[macro_use] extern crate diesel;
    /// # include!("../doctest_setup.rs");
    /// #
    /// # use schema::users;
    /// #
    /// # #[derive(QueryableByName, Debug, PartialEq)]
    /// # #[table_name="users"]
    /// # struct User {
    /// #     id: i32,
    /// #     name: String,
    /// # }
    /// #
    /// # fn main() {
    /// #     use diesel::sql_query;
    /// #     use diesel::sql_types::{Integer, Text};
    /// #
    /// #     let connection = establish_connection();
    /// #     diesel::insert_into(users::table)
    /// #         .values(users::name.eq("Jim"))
    /// #         .execute(&connection).unwrap();
    /// # #[cfg(feature = "postgres")]
    /// # let users = sql_query("SELECT * FROM users WHERE id > $1 AND name != $2");
    /// # #[cfg(not(feature = "postgres"))]
    /// let users = sql_query("SELECT * FROM users WHERE id > ? AND name <> ?")
    /// # ;
    /// # let users = users
    ///     .bind::<Integer, _>(1)
    ///     .bind::<Text, _>("Tess")
    ///     .get_results(&connection);
    /// let expected_users = vec![
    ///     User { id: 3, name: "Jim".into() },
    /// ];
    /// assert_eq!(Ok(expected_users), users);
    /// # }
    /// ```
    pub fn bind<ST, Value>(self, value: Value) -> UncheckedBind<Self, Value, ST> {
        UncheckedBind::new(self, value)
    }

    /// Internally boxes future calls on `bind` and `sql` so that they don't
    /// change the type.
    ///
    /// This allows doing things you otherwise couldn't do, e.g. `bind`ing in a
    /// loop.
    pub fn into_boxed<'f, DB: Backend>(self) -> BoxedSqlQuery<'f, DB, Self> {
        BoxedSqlQuery::new(self)
    }

    /// Appends a piece of SQL code at the end.
    pub fn sql<T: AsRef<str>>(mut self, sql: T) -> Self {
        self.query += sql.as_ref();
        self
    }
}

impl<DB, Inner> QueryFragment<DB> for SqlQuery<Inner>
where
    DB: Backend,
    Inner: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.unsafe_to_cache_prepared();
        self.inner.walk_ast(out.reborrow())?;
        out.push_sql(&self.query);
        Ok(())
    }
}

impl<Inner> QueryId for SqlQuery<Inner> {
    type QueryId = ();

    const HAS_STATIC_QUERY_ID: bool = false;
}

impl<Inner, Conn, T> LoadQuery<Conn, T> for SqlQuery<Inner>
where
    Conn: Connection,
    T: QueryableByName<Conn::Backend>,
    Self: QueryFragment<Conn::Backend>,
{
    fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
        conn.query_by_name(&self)
    }
}

impl<Inner, Conn> RunQueryDsl<Conn> for SqlQuery<Inner> {}

#[derive(Debug, Clone, Copy)]
#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
pub struct UncheckedBind<Query, Value, ST> {
    query: Query,
    value: Value,
    _marker: PhantomData<ST>,
}

impl<Query, Value, ST> UncheckedBind<Query, Value, ST> {
    pub fn new(query: Query, value: Value) -> Self {
        UncheckedBind {
            query,
            value,
            _marker: PhantomData,
        }
    }

    pub fn bind<ST2, Value2>(self, value: Value2) -> UncheckedBind<Self, Value2, ST2> {
        UncheckedBind::new(self, value)
    }

    pub fn into_boxed<'f, DB: Backend>(self) -> BoxedSqlQuery<'f, DB, Self> {
        BoxedSqlQuery::new(self)
    }

    pub fn sql<T: Into<String>>(self, sql: T) -> SqlQuery<Self> {
        SqlQuery::new(self, sql.into())
    }
}

impl<Query, Value, ST> QueryId for UncheckedBind<Query, Value, ST>
where
    Query: QueryId,
    ST: QueryId,
{
    type QueryId = UncheckedBind<Query::QueryId, (), ST::QueryId>;

    const HAS_STATIC_QUERY_ID: bool = Query::HAS_STATIC_QUERY_ID && ST::HAS_STATIC_QUERY_ID;
}

impl<Query, Value, ST, DB> QueryFragment<DB> for UncheckedBind<Query, Value, ST>
where
    DB: Backend + HasSqlType<ST>,
    Query: QueryFragment<DB>,
    Value: ToSql<ST, DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        self.query.walk_ast(out.reborrow())?;
        out.push_bind_param_value_only(&self.value)?;
        Ok(())
    }
}

impl<Conn, Query, Value, ST, T> LoadQuery<Conn, T> for UncheckedBind<Query, Value, ST>
where
    Conn: Connection,
    T: QueryableByName<Conn::Backend>,
    Self: QueryFragment<Conn::Backend> + QueryId,
{
    fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
        conn.query_by_name(&self)
    }
}

impl<Conn, Query, Value, ST> RunQueryDsl<Conn> for UncheckedBind<Query, Value, ST> {}

#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
/// See [`SqlQuery::into_boxed`].
///
/// [`SqlQuery::into_boxed`]: ./struct.SqlQuery.html#method.into_boxed
#[allow(missing_debug_implementations)]
pub struct BoxedSqlQuery<'f, DB: Backend, Query> {
    query: Query,
    sql: String,
    binds: Vec<Box<dyn Fn(AstPass<DB>) -> QueryResult<()> + 'f>>,
}

impl<'f, DB: Backend, Query> BoxedSqlQuery<'f, DB, Query> {
    pub(crate) fn new(query: Query) -> Self {
        BoxedSqlQuery {
            query,
            sql: "".to_string(),
            binds: vec![],
        }
    }

    /// See [`SqlQuery::bind`].
    ///
    /// [`SqlQuery::bind`]: ./struct.SqlQuery.html#method.bind
    pub fn bind<BindSt, Value>(mut self, b: Value) -> Self
    where
        DB: HasSqlType<BindSt>,
        Value: ToSql<BindSt, DB> + 'f,
    {
        self.binds
            .push(Box::new(move |mut out| out.push_bind_param_value_only(&b)));
        self
    }

    /// See [`SqlQuery::sql`].
    ///
    /// [`SqlQuery::sql`]: ./struct.SqlQuery.html#method.sql
    pub fn sql<T: AsRef<str>>(mut self, sql: T) -> Self {
        self.sql += sql.as_ref();
        self
    }
}

impl<DB, Query> QueryFragment<DB> for BoxedSqlQuery<'_, DB, Query>
where
    DB: Backend,
    Query: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.unsafe_to_cache_prepared();
        self.query.walk_ast(out.reborrow())?;
        out.push_sql(&self.sql);

        for b in &self.binds {
            b(out.reborrow())?;
        }
        Ok(())
    }
}

impl<DB: Backend, Query> QueryId for BoxedSqlQuery<'_, DB, Query> {
    type QueryId = ();

    const HAS_STATIC_QUERY_ID: bool = false;
}

impl<Conn, T, Query> LoadQuery<Conn, T> for BoxedSqlQuery<'_, Conn::Backend, Query>
where
    Conn: Connection,
    T: QueryableByName<Conn::Backend>,
    Self: QueryFragment<Conn::Backend> + QueryId,
{
    fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
        conn.query_by_name(&self)
    }
}

impl<Conn: Connection, Query> RunQueryDsl<Conn> for BoxedSqlQuery<'_, Conn::Backend, Query> {}
<commit_msg>Mention MySQL<commit_after>use std::marker::PhantomData;

use crate::backend::Backend;
use crate::connection::Connection;
use crate::deserialize::QueryableByName;
use crate::query_builder::{AstPass, QueryFragment, QueryId};
use crate::query_dsl::{LoadQuery, RunQueryDsl};
use crate::result::QueryResult;
use crate::serialize::ToSql;
use crate::sql_types::HasSqlType;

#[derive(Debug, Clone)]
#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
/// The return value of `sql_query`.
///
/// Unlike most queries in Diesel, `SqlQuery` loads its data by column name,
/// rather than by index. This means that you cannot deserialize this query into
/// a tuple, and any structs used must implement `QueryableByName`.
///
/// See [`sql_query`](../fn.sql_query.html) for examples.
pub struct SqlQuery<Inner = ()> {
    inner: Inner,
    query: String,
}

impl<Inner> SqlQuery<Inner> {
    pub(crate) fn new(inner: Inner, query: String) -> Self {
        SqlQuery { inner, query }
    }

    /// Bind a value for use with this SQL query. The given query should have
    /// placeholders that vary based on the database type,
    /// like [SQLite Parameters](https://sqlite.org/lang_expr.html#varparam) syntax,
    /// the [PostgreSQL PREPARE syntax](https://www.postgresql.org/docs/current/sql-prepare.html),
    /// or [MySQL bind syntax](https://dev.mysql.com/doc/refman/8.0/en/mysql-stmt-bind-param.html).
    ///
    /// # Safety
    ///
    /// This function should be used with care, as Diesel cannot validate that
    /// the value is of the right type nor can it validate that you have passed
    /// the correct number of parameters.
    ///
    /// # Example
    ///
    /// ```
    /// # #[macro_use] extern crate diesel;
    /// # include!("../doctest_setup.rs");
    /// #
    /// # use schema::users;
    /// #
    /// # #[derive(QueryableByName, Debug, PartialEq)]
    /// # #[table_name="users"]
    /// # struct User {
    /// #     id: i32,
    /// #     name: String,
    /// # }
    /// #
    /// # fn main() {
    /// #     use diesel::sql_query;
    /// #     use diesel::sql_types::{Integer, Text};
    /// #
    /// #     let connection = establish_connection();
    /// #     diesel::insert_into(users::table)
    /// #         .values(users::name.eq("Jim"))
    /// #         .execute(&connection).unwrap();
    /// # #[cfg(feature = "postgres")]
    /// # let users = sql_query("SELECT * FROM users WHERE id > $1 AND name != $2");
    /// # #[cfg(not(feature = "postgres"))]
    /// let users = sql_query("SELECT * FROM users WHERE id > ? AND name <> ?")
    /// # ;
    /// # let users = users
    ///     .bind::<Integer, _>(1)
    ///     .bind::<Text, _>("Tess")
    ///     .get_results(&connection);
    /// let expected_users = vec![
    ///     User { id: 3, name: "Jim".into() },
    /// ];
    /// assert_eq!(Ok(expected_users), users);
    /// # }
    /// ```
    pub fn bind<ST, Value>(self, value: Value) -> UncheckedBind<Self, Value, ST> {
        UncheckedBind::new(self, value)
    }

    /// Internally boxes future calls on `bind` and `sql` so that they don't
    /// change the type.
    ///
    /// This allows doing things you otherwise couldn't do, e.g. `bind`ing in a
    /// loop.
    pub fn into_boxed<'f, DB: Backend>(self) -> BoxedSqlQuery<'f, DB, Self> {
        BoxedSqlQuery::new(self)
    }

    /// Appends a piece of SQL code at the end.
    pub fn sql<T: AsRef<str>>(mut self, sql: T) -> Self {
        self.query += sql.as_ref();
        self
    }
}

impl<DB, Inner> QueryFragment<DB> for SqlQuery<Inner>
where
    DB: Backend,
    Inner: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.unsafe_to_cache_prepared();
        self.inner.walk_ast(out.reborrow())?;
        out.push_sql(&self.query);
        Ok(())
    }
}

impl<Inner> QueryId for SqlQuery<Inner> {
    type QueryId = ();

    const HAS_STATIC_QUERY_ID: bool = false;
}

impl<Inner, Conn, T> LoadQuery<Conn, T> for SqlQuery<Inner>
where
    Conn: Connection,
    T: QueryableByName<Conn::Backend>,
    Self: QueryFragment<Conn::Backend>,
{
    fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
        conn.query_by_name(&self)
    }
}

impl<Inner, Conn> RunQueryDsl<Conn> for SqlQuery<Inner> {}

#[derive(Debug, Clone, Copy)]
#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
pub struct UncheckedBind<Query, Value, ST> {
    query: Query,
    value: Value,
    _marker: PhantomData<ST>,
}

impl<Query, Value, ST> UncheckedBind<Query, Value, ST> {
    pub fn new(query: Query, value: Value) -> Self {
        UncheckedBind {
            query,
            value,
            _marker: PhantomData,
        }
    }

    pub fn bind<ST2, Value2>(self, value: Value2) -> UncheckedBind<Self, Value2, ST2> {
        UncheckedBind::new(self, value)
    }

    pub fn into_boxed<'f, DB: Backend>(self) -> BoxedSqlQuery<'f, DB, Self> {
        BoxedSqlQuery::new(self)
    }

    pub fn sql<T: Into<String>>(self, sql: T) -> SqlQuery<Self> {
        SqlQuery::new(self, sql.into())
    }
}

impl<Query, Value, ST> QueryId for UncheckedBind<Query, Value, ST>
where
    Query: QueryId,
    ST: QueryId,
{
    type QueryId = UncheckedBind<Query::QueryId, (), ST::QueryId>;

    const HAS_STATIC_QUERY_ID: bool = Query::HAS_STATIC_QUERY_ID && ST::HAS_STATIC_QUERY_ID;
}

impl<Query, Value, ST, DB> QueryFragment<DB> for UncheckedBind<Query, Value, ST>
where
    DB: Backend + HasSqlType<ST>,
    Query: QueryFragment<DB>,
    Value: ToSql<ST, DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        self.query.walk_ast(out.reborrow())?;
        out.push_bind_param_value_only(&self.value)?;
        Ok(())
    }
}

impl<Conn, Query, Value, ST, T> LoadQuery<Conn, T> for UncheckedBind<Query, Value, ST>
where
    Conn: Connection,
    T: QueryableByName<Conn::Backend>,
    Self: QueryFragment<Conn::Backend> + QueryId,
{
    fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
        conn.query_by_name(&self)
    }
}

impl<Conn, Query, Value, ST> RunQueryDsl<Conn> for UncheckedBind<Query, Value, ST> {}

#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
/// See [`SqlQuery::into_boxed`].
///
/// [`SqlQuery::into_boxed`]: ./struct.SqlQuery.html#method.into_boxed
#[allow(missing_debug_implementations)]
pub struct BoxedSqlQuery<'f, DB: Backend, Query> {
    query: Query,
    sql: String,
    binds: Vec<Box<dyn Fn(AstPass<DB>) -> QueryResult<()> + 'f>>,
}

impl<'f, DB: Backend, Query> BoxedSqlQuery<'f, DB, Query> {
    pub(crate) fn new(query: Query) -> Self {
        BoxedSqlQuery {
            query,
            sql: "".to_string(),
            binds: vec![],
        }
    }

    /// See [`SqlQuery::bind`].
    ///
    /// [`SqlQuery::bind`]: ./struct.SqlQuery.html#method.bind
    pub fn bind<BindSt, Value>(mut self, b: Value) -> Self
    where
        DB: HasSqlType<BindSt>,
        Value: ToSql<BindSt, DB> + 'f,
    {
        self.binds
            .push(Box::new(move |mut out| out.push_bind_param_value_only(&b)));
        self
    }

    /// See [`SqlQuery::sql`].
    ///
    /// [`SqlQuery::sql`]: ./struct.SqlQuery.html#method.sql
    pub fn sql<T: AsRef<str>>(mut self, sql: T) -> Self {
        self.sql += sql.as_ref();
        self
    }
}

impl<DB, Query> QueryFragment<DB> for BoxedSqlQuery<'_, DB, Query>
where
    DB: Backend,
    Query: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.unsafe_to_cache_prepared();
        self.query.walk_ast(out.reborrow())?;
        out.push_sql(&self.sql);

        for b in &self.binds {
            b(out.reborrow())?;
        }
        Ok(())
    }
}

impl<DB: Backend, Query> QueryId for BoxedSqlQuery<'_, DB, Query> {
    type QueryId = ();

    const HAS_STATIC_QUERY_ID: bool = false;
}

impl<Conn, T, Query> LoadQuery<Conn, T> for BoxedSqlQuery<'_, Conn::Backend, Query>
where
    Conn: Connection,
    T: QueryableByName<Conn::Backend>,
    Self: QueryFragment<Conn::Backend> + QueryId,
{
    fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
        conn.query_by_name(&self)
    }
}

impl<Conn: Connection, Query> RunQueryDsl<Conn> for BoxedSqlQuery<'_, Conn::Backend, Query> {}
<|endoftext|>


<commit_before>use arch::init;

/// Interrupt handler function type.
pub type HandlerFunc = unsafe extern "C" fn();

#[derive(Debug, Clone)]
#[repr(C)]
pub struct ExceptionStackFrame {
    pub instruction_pointer: u64,
    pub code_segment: u64,
    pub cpu_flags: u64,
    pub stack_pointer: u64,
    pub stack_segment: u64,
}

#[derive(Debug, Clone)]
pub struct ExceptionInfo {
    pub instruction_pointer: u64,
    pub code_segment: u64,
    pub cpu_flags: u64,
    pub stack_pointer: u64,
    pub stack_segment: u64,
    pub error_code: Option<u64>,
    pub exception_code: u64
}

#[derive(Debug, Clone)]
pub struct Registers {
    pub rax: u64,
    pub rbx: u64,
    pub rcx: u64,
    pub rdx: u64,
    pub rbp: u64,
    pub rsi: u64,
    pub rdi: u64,
    pub r8: u64,
    pub r9: u64,
    pub r10: u64,
    pub r11: u64,
    pub r12: u64,
    pub r13: u64,
    pub r14: u64,
    pub r15: u64,
}

impl Default for Registers {
    fn default() -> Registers {
        Registers {
            rax: 0, rbx: 0, rcx: 0, rdx: 0, rbp: 0, rsi: 0, rdi: 0,
            r8: 0, r9: 0, r10: 0, r11: 0, r12: 0, r13: 0, r14: 0, r15: 0
        }
    }
}

macro_rules! save_registers {
    () => {
        asm!("push rax
              push rbx
              push rcx
              push rdx
              push rbp
              push rsi
              push rdi
              push r8
              push r9
              push r10
              push r11
              push r12
              push r13
              push r14
              push r15
              push rsp
        " :::: "intel", "volatile");
    }
}

macro_rules! restore_registers {
    () => {
        asm!("pop rsp
              pop r15
              pop r14
              pop r13
              pop r12
              pop r11
              pop r10
              pop r9
              pop r8
              pop rdi
              pop rsi
              pop rbp
              pop rdx
              pop rcx
              pop rbx
              pop rax
            " :::: "intel", "volatile");
    }
}

unsafe extern "C" fn set_kernel_stack(addr: u64) {
    init::set_kernel_stack(addr);
}

pub unsafe fn switch_to_raw(stack_vaddr: u64, code_start: u64, cpu_flags: u64, code_seg: u64, data_seg: u64) {
    asm!("call r15" :: "{rdi}"(stack_vaddr), "{rsi}"(code_start), "{rdx}"(cpu_flags), "{rcx}"(code_seg), "{r8}"(data_seg), "{r15}"(switch_to_raw_naked as unsafe extern "C" fn(u64, u64, u64, u64, u64)) :: "volatile", "intel");

    // WARNING: Everything below this before returning will not work.
}

#[no_mangle]
#[naked]
pub unsafe extern "C" fn switch_to_raw_naked(stack_vaddr: u64, code_start: u64, cpu_flags: u64, code_seg: u64, data_seg: u64) {
    save_registers!();

    asm!("mov rdi, rsp
          call $0" :: "i"(set_kernel_stack as unsafe extern "C" fn(u64)) : "rdi" : "volatile", "intel");

    asm!("push rax
          push rbx
          push r8
          push rcx
          push rdx
          push r9"
         :: "{rax}"(data_seg), "{rbx}"(stack_vaddr), "{rcx}"(code_seg), "{rdx}"(code_start), "{r8}"(cpu_flags),
         "{r9}"(CUR_REGISTERS.rbp)
         :: "volatile", "intel");

    asm!("pop rbp
          iretq" :: "{rax}"(CUR_REGISTERS.rax), "{rbx}"(CUR_REGISTERS.rbx), "{rcx}"(CUR_REGISTERS.rcx),
         "{rdx}"(CUR_REGISTERS.rdx), "{rsi}"(CUR_REGISTERS.rsi),
         "{rdi}"(CUR_REGISTERS.rdi), "{r8}"(CUR_REGISTERS.r8), "{r9}"(CUR_REGISTERS.r9),
         "{r10}"(CUR_REGISTERS.r10), "{r11}"(CUR_REGISTERS.r11), "{r12}"(CUR_REGISTERS.r12),
         "{r13}"(CUR_REGISTERS.r13), "{r14}"(CUR_REGISTERS.r14), "{r15}"(CUR_REGISTERS.r15)
         :: "volatile", "intel");
}

static mut CUR_EXCEPTION_STACK_FRAME: Option<ExceptionStackFrame> = None;
static mut CUR_EXCEPTION_ERROR_CODE: Option<u64> = None;
static mut CUR_EXCEPTION_CODE: Option<u64> = None;
static mut CUR_REGISTERS: Registers = Registers {
    rax: 0, rbx: 0, rcx: 0, rdx: 0, rbp: 0, rsi: 0, rdi: 0,
    r8: 0, r9: 0, r10: 0, r11: 0, r12: 0, r13: 0, r14: 0, r15: 0
};

pub unsafe fn set_cur_registers(registers: Registers) {
    CUR_REGISTERS = registers;
}

pub unsafe fn cur_registers() -> Registers {
    CUR_REGISTERS.clone()
}

pub unsafe extern "C" fn store_exception_stack(exception_raw: *const ExceptionStackFrame, exception_code: u64) {
    let exception = unsafe {&*exception_raw};
    CUR_EXCEPTION_STACK_FRAME = Some(exception.clone());
    CUR_EXCEPTION_ERROR_CODE = None;
    CUR_EXCEPTION_CODE = Some(exception_code);
}

pub unsafe extern "C" fn store_error_exception_stack(exception_raw: *const ExceptionStackFrame, error_code: u64, exception_code: u64) {
    let exception = unsafe {&*exception_raw};
    CUR_EXCEPTION_STACK_FRAME = Some(exception.clone());
    CUR_EXCEPTION_ERROR_CODE = Some(error_code);
    CUR_EXCEPTION_CODE = Some(exception_code);
}

#[inline(always)]
pub unsafe fn save_usermode_registers() {
    asm!("push rbp" :::: "volatile", "intel");

    asm!("" : "={rax}"(CUR_REGISTERS.rax), "={rbx}"(CUR_REGISTERS.rbx), "={rcx}"(CUR_REGISTERS.rcx),
         "={rdx}"(CUR_REGISTERS.rdx), "={rsi}"(CUR_REGISTERS.rsi),
         "={rdi}"(CUR_REGISTERS.rdi), "={r8}"(CUR_REGISTERS.r8), "={r9}"(CUR_REGISTERS.r9),
         "={r10}"(CUR_REGISTERS.r10), "={r11}"(CUR_REGISTERS.r11), "={r12}"(CUR_REGISTERS.r12),
         "={r13}"(CUR_REGISTERS.r13), "={r14}"(CUR_REGISTERS.r14), "={r15}"(CUR_REGISTERS.r15)
         ::: "volatile", "intel");

    asm!("pop r9" : "={r9}"(CUR_REGISTERS.rbp) ::: "volatile", "intel");
}

macro_rules! return_to_raw_fn {
    ($name: ident, $exception_code: expr) => (
        #[no_mangle]
        #[naked]
        unsafe extern "C" fn $name() {
            ::arch::interrupt::switch::save_usermode_registers();

            asm!("mov rdi, rsp
                  sub rsp, 8
                  call $0
                  add rsp, 48"
                 :: "i"(::arch::interrupt::switch::store_exception_stack as unsafe extern "C" fn(*const ::arch::interrupt::switch::ExceptionStackFrame, u64)), "{rsi}"($exception_code)
                 :: "volatile", "intel");

            restore_registers!();
        }
    )
}

macro_rules! return_error_to_raw_fn {
    ($name: ident, $exception_code: expr) => (
        #[no_mangle]
        #[naked]
        unsafe extern "C" fn $name() {
            ::arch::interrupt::switch::save_usermode_registers();

            asm!("pop rsi
                  mov rdi, rsp
                  sub rsp, 8
                  call $0
                  add rsp, 48"
                 :: "i"(::arch::interrupt::switch::store_error_exception_stack as unsafe extern "C" fn(*const ::arch::interrupt::switch::ExceptionStackFrame, u64)), "{rdx}"($exception_code)
                 :: "volatile", "intel");

            restore_registers!();
        }
    )
}

pub fn last_exception_return_value() -> Option<ExceptionInfo> {
    unsafe {
        CUR_EXCEPTION_STACK_FRAME.clone().map(|exp| {
            ExceptionInfo {
                instruction_pointer: exp.instruction_pointer,
                code_segment: exp.code_segment,
                cpu_flags: exp.cpu_flags,
                stack_pointer: exp.stack_pointer,
                stack_segment: exp.stack_segment,
                error_code: CUR_EXCEPTION_ERROR_CODE,
                exception_code: CUR_EXCEPTION_CODE.unwrap()
            }
        })
    }
}
<commit_msg>Fix rsp value in switch.rs due to Rust upgrade<commit_after>use arch::init;

/// Interrupt handler function type.
pub type HandlerFunc = unsafe extern "C" fn();

#[derive(Debug, Clone)]
#[repr(C)]
pub struct ExceptionStackFrame {
    pub instruction_pointer: u64,
    pub code_segment: u64,
    pub cpu_flags: u64,
    pub stack_pointer: u64,
    pub stack_segment: u64,
}

#[derive(Debug, Clone)]
pub struct ExceptionInfo {
    pub instruction_pointer: u64,
    pub code_segment: u64,
    pub cpu_flags: u64,
    pub stack_pointer: u64,
    pub stack_segment: u64,
    pub error_code: Option<u64>,
    pub exception_code: u64
}

#[derive(Debug, Clone)]
pub struct Registers {
    pub rax: u64,
    pub rbx: u64,
    pub rcx: u64,
    pub rdx: u64,
    pub rbp: u64,
    pub rsi: u64,
    pub rdi: u64,
    pub r8: u64,
    pub r9: u64,
    pub r10: u64,
    pub r11: u64,
    pub r12: u64,
    pub r13: u64,
    pub r14: u64,
    pub r15: u64,
}

impl Default for Registers {
    fn default() -> Registers {
        Registers {
            rax: 0, rbx: 0, rcx: 0, rdx: 0, rbp: 0, rsi: 0, rdi: 0,
            r8: 0, r9: 0, r10: 0, r11: 0, r12: 0, r13: 0, r14: 0, r15: 0
        }
    }
}

macro_rules! save_registers {
    () => {
        asm!("push rax
              push rbx
              push rcx
              push rdx
              push rbp
              push rsi
              push rdi
              push r8
              push r9
              push r10
              push r11
              push r12
              push r13
              push r14
              push r15
              push rsp
        " :::: "intel", "volatile");
    }
}

macro_rules! restore_registers {
    () => {
        asm!("pop rsp
              pop r15
              pop r14
              pop r13
              pop r12
              pop r11
              pop r10
              pop r9
              pop r8
              pop rdi
              pop rsi
              pop rbp
              pop rdx
              pop rcx
              pop rbx
              pop rax
            " :::: "intel", "volatile");
    }
}

unsafe extern "C" fn set_kernel_stack(addr: u64) {
    init::set_kernel_stack(addr);
}

pub unsafe fn switch_to_raw(stack_vaddr: u64, code_start: u64, cpu_flags: u64, code_seg: u64, data_seg: u64) {
    asm!("call r15" :: "{rdi}"(stack_vaddr), "{rsi}"(code_start), "{rdx}"(cpu_flags), "{rcx}"(code_seg), "{r8}"(data_seg), "{r15}"(switch_to_raw_naked as unsafe extern "C" fn(u64, u64, u64, u64, u64)) :: "volatile", "intel");

    // WARNING: Everything below this before returning will not work.
}

#[no_mangle]
#[naked]
pub unsafe extern "C" fn switch_to_raw_naked(stack_vaddr: u64, code_start: u64, cpu_flags: u64, code_seg: u64, data_seg: u64) {
    save_registers!();

    asm!("mov rdi, rsp
          call $0" :: "i"(set_kernel_stack as unsafe extern "C" fn(u64)) : "rdi" : "volatile", "intel");

    asm!("push rax
          push rbx
          push r8
          push rcx
          push rdx
          push r9"
         :: "{rax}"(data_seg), "{rbx}"(stack_vaddr), "{rcx}"(code_seg), "{rdx}"(code_start), "{r8}"(cpu_flags),
         "{r9}"(CUR_REGISTERS.rbp)
         :: "volatile", "intel");

    asm!("pop rbp
          iretq" :: "{rax}"(CUR_REGISTERS.rax), "{rbx}"(CUR_REGISTERS.rbx), "{rcx}"(CUR_REGISTERS.rcx),
         "{rdx}"(CUR_REGISTERS.rdx), "{rsi}"(CUR_REGISTERS.rsi),
         "{rdi}"(CUR_REGISTERS.rdi), "{r8}"(CUR_REGISTERS.r8), "{r9}"(CUR_REGISTERS.r9),
         "{r10}"(CUR_REGISTERS.r10), "{r11}"(CUR_REGISTERS.r11), "{r12}"(CUR_REGISTERS.r12),
         "{r13}"(CUR_REGISTERS.r13), "{r14}"(CUR_REGISTERS.r14), "{r15}"(CUR_REGISTERS.r15)
         :: "volatile", "intel");
}

static mut CUR_EXCEPTION_STACK_FRAME: Option<ExceptionStackFrame> = None;
static mut CUR_EXCEPTION_ERROR_CODE: Option<u64> = None;
static mut CUR_EXCEPTION_CODE: Option<u64> = None;
static mut CUR_REGISTERS: Registers = Registers {
    rax: 0, rbx: 0, rcx: 0, rdx: 0, rbp: 0, rsi: 0, rdi: 0,
    r8: 0, r9: 0, r10: 0, r11: 0, r12: 0, r13: 0, r14: 0, r15: 0
};

pub unsafe fn set_cur_registers(registers: Registers) {
    CUR_REGISTERS = registers;
}

pub unsafe fn cur_registers() -> Registers {
    CUR_REGISTERS.clone()
}

pub unsafe extern "C" fn store_exception_stack(exception_raw: *const ExceptionStackFrame, exception_code: u64) {
    let exception = unsafe {&*exception_raw};
    CUR_EXCEPTION_STACK_FRAME = Some(exception.clone());
    CUR_EXCEPTION_ERROR_CODE = None;
    CUR_EXCEPTION_CODE = Some(exception_code);
}

pub unsafe extern "C" fn store_error_exception_stack(exception_raw: *const ExceptionStackFrame, error_code: u64, exception_code: u64) {
    let exception = unsafe {&*exception_raw};
    CUR_EXCEPTION_STACK_FRAME = Some(exception.clone());
    CUR_EXCEPTION_ERROR_CODE = Some(error_code);
    CUR_EXCEPTION_CODE = Some(exception_code);
}

#[inline(always)]
pub unsafe fn save_usermode_registers() {
    asm!("push rbp" :::: "volatile", "intel");

    asm!("" : "={rax}"(CUR_REGISTERS.rax), "={rbx}"(CUR_REGISTERS.rbx), "={rcx}"(CUR_REGISTERS.rcx),
         "={rdx}"(CUR_REGISTERS.rdx), "={rsi}"(CUR_REGISTERS.rsi),
         "={rdi}"(CUR_REGISTERS.rdi), "={r8}"(CUR_REGISTERS.r8), "={r9}"(CUR_REGISTERS.r9),
         "={r10}"(CUR_REGISTERS.r10), "={r11}"(CUR_REGISTERS.r11), "={r12}"(CUR_REGISTERS.r12),
         "={r13}"(CUR_REGISTERS.r13), "={r14}"(CUR_REGISTERS.r14), "={r15}"(CUR_REGISTERS.r15)
         ::: "volatile", "intel");

    asm!("pop r9" : "={r9}"(CUR_REGISTERS.rbp) ::: "volatile", "intel");
}

macro_rules! return_to_raw_fn {
    ($name: ident, $exception_code: expr) => (
        #[no_mangle]
        #[naked]
        unsafe extern "C" fn $name() {
            ::arch::interrupt::switch::save_usermode_registers();

            asm!("mov rdi, rsp
                  sub rsp, 8
                  call $0
                  add rsp, 56"
                 :: "i"(::arch::interrupt::switch::store_exception_stack as unsafe extern "C" fn(*const ::arch::interrupt::switch::ExceptionStackFrame, u64)), "{rsi}"($exception_code)
                 :: "volatile", "intel");

            restore_registers!();
        }
    )
}

macro_rules! return_error_to_raw_fn {
    ($name: ident, $exception_code: expr) => (
        #[no_mangle]
        #[naked]
        unsafe extern "C" fn $name() {
            ::arch::interrupt::switch::save_usermode_registers();

            asm!("pop rsi
                  mov rdi, rsp
                  sub rsp, 8
                  call $0
                  add rsp, 56"
                 :: "i"(::arch::interrupt::switch::store_error_exception_stack as unsafe extern "C" fn(*const ::arch::interrupt::switch::ExceptionStackFrame, u64)), "{rdx}"($exception_code)
                 :: "volatile", "intel");

            restore_registers!();
        }
    )
}

pub fn last_exception_return_value() -> Option<ExceptionInfo> {
    unsafe {
        CUR_EXCEPTION_STACK_FRAME.clone().map(|exp| {
            ExceptionInfo {
                instruction_pointer: exp.instruction_pointer,
                code_segment: exp.code_segment,
                cpu_flags: exp.cpu_flags,
                stack_pointer: exp.stack_pointer,
                stack_segment: exp.stack_segment,
                error_code: CUR_EXCEPTION_ERROR_CODE,
                exception_code: CUR_EXCEPTION_CODE.unwrap()
            }
        })
    }
}
<|endoftext|>


<commit_before>#![deny(rust_2018_idioms)]

use cargo::{
    core::{
        package::PackageSet,
        registry::PackageRegistry,
        resolver::{self, Method},
        source::SourceMap,
        Dependency, Package, PackageId, Source, SourceId, TargetKind,
    },
    sources::RegistrySource,
    util::Config,
};
use itertools::Itertools;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::{
    collections::{BTreeMap, BTreeSet, HashSet},
    fs::File,
    io::{Read, Write},
};

/// The list of crates from crates.io
#[derive(Debug, Deserialize)]
struct TopCrates {
    crates: Vec<Crate>,
}

/// A single crate from crates.io
#[derive(Debug, Deserialize)]
struct OneCrate {
    #[serde(rename="crate")]
    krate: Crate,
}

/// The shared description of a crate
#[derive(Debug, Deserialize)]
struct Crate {
    #[serde(rename="id")]
    name: String,
}

/// A Cargo.toml file.
#[derive(Serialize)]
struct TomlManifest {
    package: TomlPackage,
    profile: Profiles,
    #[serde(serialize_with = "toml::ser::tables_last")]
    dependencies: BTreeMap<String, DependencySpec>,
}

/// Header of Cargo.toml file.
#[derive(Serialize)]
struct TomlPackage {
    name: String,
    version: String,
    authors: Vec<String>,
}

/// A mapping of a crates name to its identifier used in source code
#[derive(Debug, Serialize)]
struct CrateInformation {
    name: String,
    version: String,
    id: String,
}

/// Hand-curated changes to the crate list
#[derive(Debug, Deserialize)]
struct Modifications {
    #[serde(default)]
    blacklist: Vec<String>,
    #[serde(default)]
    additions: BTreeSet<String>,
}

/// A profile section in a Cargo.toml file
#[derive(Serialize)]
#[serde(rename_all="kebab-case")]
struct Profile {
    codegen_units: u32,
    incremental: bool,
}

/// Available profile types
#[derive(Serialize)]
struct Profiles {
    dev: Profile,
    release: Profile,
}

#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "kebab-case")]
struct DependencySpec {
    #[serde(skip_serializing_if = "String::is_empty")]
    package: String,
    #[serde(serialize_with = "exact_version")]
    version: String,
    #[serde(skip_serializing_if = "Vec::is_empty")]
    features: Vec<String>,
    #[serde(skip_serializing_if = "is_true")]
    default_features: bool,
}

fn exact_version<S>(version: &String, serializer: S) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    format!("={}", version).serialize(serializer)
}

fn is_true(b: &bool) -> bool {
    *b
}

impl Modifications {
    fn blacklisted(&self, name: &str) -> bool {
        self.blacklist.iter().any(|n| n == name)
    }
}

lazy_static! {
    static ref MODIFICATIONS: Modifications = {
        let mut f = File::open("crate-modifications.toml")
            .expect("unable to open crate modifications file");

        let mut d = Vec::new();
        f.read_to_end(&mut d)
            .expect("unable to read crate modifications file");

        toml::from_slice(&d)
            .expect("unable to parse crate modifications file")
    };
}

impl TopCrates {
    /// List top 100 crates by number of downloads on crates.io.
    fn download() -> TopCrates {
        let resp =
            reqwest::get("https://crates.io/api/v1/crates?page=1&per_page=100&sort=downloads")
            .expect("Could not fetch top crates");
        assert!(resp.status().is_success());

        serde_json::from_reader(resp).expect("Invalid JSON")
    }

    /// Add crates that have been hand-picked
    fn add_curated_crates(&mut self) {
        self.crates.extend({
            MODIFICATIONS
                .additions
                .iter()
                .cloned()
                .map(|name| Crate { name })
        });
    }
}

/// Finds the features specified by the custom metadata of `pkg`.
///
/// Our custom metadata format looks like:
///
///     [package.metadata.playground]
///     default-features = true
///     features = ["std", "extra-traits"]
///     all-features = false
///
/// All fields are optional.
fn playground_metadata_features(pkg: &Package) -> Option<(Vec<String>, bool)> {
    let custom_metadata = pkg.manifest().custom_metadata()?;
    let playground_metadata = custom_metadata.get("playground")?;

    #[derive(Deserialize)]
    #[serde(default, rename_all = "kebab-case")]
    struct Metadata {
        features: Vec<String>,
        default_features: bool,
        all_features: bool,
    }

    impl Default for Metadata {
        fn default() -> Self {
            Metadata {
                features: Vec::new(),
                default_features: true,
                all_features: false,
            }
        }
    }

    let metadata = match playground_metadata.clone().try_into::<Metadata>() {
        Ok(metadata) => metadata,
        Err(err) => {
            eprintln!(
                "Failed to parse custom metadata for {} {}: {}",
                pkg.name(), pkg.version(), err);
            return None;
        }
    };

    // If `all-features` is set then we ignore `features`.
    let summary = pkg.summary();
    let mut enabled_features: BTreeSet<String> = if metadata.all_features {
        summary.features().keys().map(ToString::to_string).collect()
    } else {
        metadata.features.into_iter().collect()
    };

    // If not opting out of default features, remove default features from the
    // explicit features list. This avoids ongoing spurious diffs in our
    // generated Cargo.toml as default features are added to a library.
    if metadata.default_features {
        if let Some(default_feature_names) = summary.features().get("default") {
            enabled_features.remove("default");
            for feature in default_feature_names {
                enabled_features.remove(&feature.to_string(summary));
            }
        }
    }

    if !enabled_features.is_empty() || !metadata.default_features {
        Some((
            enabled_features.into_iter().collect(),
            metadata.default_features,
        ))
    } else {
        None
    }
}

fn write_manifest(manifest: TomlManifest, path: &str) {
    let mut f = File::create(path).expect("Unable to create Cargo.toml");
    let content = toml::to_vec(&manifest).expect("Couldn't serialize TOML");
    f.write_all(&content).expect("Couldn't write Cargo.toml");
}

fn main() {
    // Setup to interact with cargo.
    let config = Config::default().expect("Unable to create default Cargo config");
    let _lock = config.acquire_package_cache_lock();
    let crates_io = SourceId::crates_io(&config).expect("Unable to create crates.io source ID");
    let mut source = RegistrySource::remote(crates_io, &HashSet::new(), &config);
    source.update().expect("Unable to update registry");

    let mut top = TopCrates::download();
    top.add_curated_crates();

    // Find the newest (non-prerelease, non-yanked) versions of all
    // the interesting crates.
    let mut summaries = Vec::new();
    for Crate { ref name } in top.crates {
        if MODIFICATIONS.blacklisted(name) {
            continue;
        }

        // Query the registry for a summary of this crate.
        // Usefully, this doesn't seem to include yanked versions
        let dep = Dependency::parse_no_deprecated(name, None, crates_io)
            .unwrap_or_else(|e| panic!("Unable to parse dependency for {}: {}", name, e));

        let matches = source.query_vec(&dep).unwrap_or_else(|e| {
            panic!("Unable to query registry for {}: {}", name, e);
        });

        // Find the newest non-prelease version
        let summary = matches.into_iter()
            .filter(|summary| !summary.version().is_prerelease())
            .max_by_key(|summary| summary.version().clone())
            .unwrap_or_else(|| panic!("Registry has no viable versions of {}", name));

        // Add a dependency on this crate.
        summaries.push((summary, Method::Required {
            dev_deps: false,
            features: Default::default(),
            uses_default_features: true,
            all_features: false,
        }));
    }

    // Resolve transitive dependencies.
    let mut registry = PackageRegistry::new(&config)
        .expect("Unable to create package registry");
    registry.lock_patches();
    let try_to_use = HashSet::new();
    let resolve = resolver::resolve(&summaries, &[], &mut registry, &try_to_use, None, true)
        .expect("Unable to resolve dependencies");

    // Get the package information for all dependencies.
    let package_ids: Vec<_> = resolve
        .iter()
        .filter(|pkg| !MODIFICATIONS.blacklisted(pkg.name().as_str()))
        .map(|pkg| {
            PackageId::new(&pkg.name(), pkg.version(), crates_io).unwrap_or_else(|e| {
                panic!(
                    "Unable to build PackageId for {} {}: {}",
                    pkg.name(),
                    pkg.version(),
                    e
                )
            })
        })
        .collect();

    let mut sources = SourceMap::new();
    sources.insert(Box::new(source));

    let package_set =
        PackageSet::new(&package_ids, sources, &config).expect("Unable to create a PackageSet");

    let mut packages = package_set
        .get_many(package_set.package_ids())
        .expect("Unable to download packages");

    // Sort all packages by name then version (descending), so that
    // when we group them we know we get all the same crates together
    // and the newest version first.
    packages.sort_by(|a, b| {
        a.name()
            .cmp(&b.name())
            .then(a.version().cmp(&b.version()).reverse())
    });

    let mut dependencies = BTreeMap::new();
    let mut infos = Vec::new();

    for (name, pkgs) in &packages.into_iter().group_by(|pkg| pkg.name()) {
        let mut first = true;

        for pkg in pkgs {
            let version = pkg.version();

            let crate_name = pkg
                .targets()
                .iter()
                .flat_map(|target| match target.kind() {
                    TargetKind::Lib(_) => Some(target.crate_name()),
                    _ => None,
                })
                .next()
                .unwrap_or_else(|| panic!("{} did not have a library", name));

            // We see the newest version first. Any subsequent
            // versions will have their version appended so that they
            // are uniquely named
            let exposed_name = if first {
                crate_name.clone()
            } else {
                format!(
                    "{}_{}_{}_{}",
                    crate_name, version.major, version.minor, version.patch
                )
            };

            let (features, default_features) =
                playground_metadata_features(&pkg).unwrap_or_else(|| (Vec::new(), true));

            dependencies.insert(
                exposed_name.clone(),
                DependencySpec {
                    package: name.to_string(),
                    version: version.to_string(),
                    features,
                    default_features,
                },
            );

            infos.push(CrateInformation {
                name: name.to_string(),
                version: version.to_string(),
                id: exposed_name,
            });

            first = false;
        }
    }

    // Construct playground's Cargo.toml.
    let manifest = TomlManifest {
        package: TomlPackage {
            name: "playground".to_owned(),
            version: "0.0.1".to_owned(),
            authors: vec!["The Rust Playground".to_owned()],
        },
        profile: Profiles {
            dev: Profile { codegen_units: 1, incremental: false },
            release: Profile { codegen_units: 1, incremental: false },
        },
        dependencies,
    };

    // Write manifest file.
    let cargo_toml = "../compiler/base/Cargo.toml";
    write_manifest(manifest, cargo_toml);
    println!("wrote {}", cargo_toml);

    let path = "../compiler/base/crate-information.json";
    let mut f = File::create(path)
        .unwrap_or_else(|e| panic!("Unable to create {}: {}", path, e));
    serde_json::to_writer_pretty(&mut f, &infos)
        .unwrap_or_else(|e| panic!("Unable to write {}: {}", path, e));
    println!("Wrote {}", path);
}
<commit_msg>Rustfmt the top-crates source<commit_after>#![deny(rust_2018_idioms)]

use cargo::{
    core::{
        package::PackageSet,
        registry::PackageRegistry,
        resolver::{self, Method},
        source::SourceMap,
        Dependency, Package, PackageId, Source, SourceId, TargetKind,
    },
    sources::RegistrySource,
    util::Config,
};
use itertools::Itertools;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::{
    collections::{BTreeMap, BTreeSet, HashSet},
    fs::File,
    io::{Read, Write},
};

/// The list of crates from crates.io
#[derive(Debug, Deserialize)]
struct TopCrates {
    crates: Vec<Crate>,
}

/// A single crate from crates.io
#[derive(Debug, Deserialize)]
struct OneCrate {
    #[serde(rename = "crate")]
    krate: Crate,
}

/// The shared description of a crate
#[derive(Debug, Deserialize)]
struct Crate {
    #[serde(rename = "id")]
    name: String,
}

/// A Cargo.toml file.
#[derive(Serialize)]
struct TomlManifest {
    package: TomlPackage,
    profile: Profiles,
    #[serde(serialize_with = "toml::ser::tables_last")]
    dependencies: BTreeMap<String, DependencySpec>,
}

/// Header of Cargo.toml file.
#[derive(Serialize)]
struct TomlPackage {
    name: String,
    version: String,
    authors: Vec<String>,
}

/// A mapping of a crates name to its identifier used in source code
#[derive(Debug, Serialize)]
struct CrateInformation {
    name: String,
    version: String,
    id: String,
}

/// Hand-curated changes to the crate list
#[derive(Debug, Deserialize)]
struct Modifications {
    #[serde(default)]
    blacklist: Vec<String>,
    #[serde(default)]
    additions: BTreeSet<String>,
}

/// A profile section in a Cargo.toml file
#[derive(Serialize)]
#[serde(rename_all = "kebab-case")]
struct Profile {
    codegen_units: u32,
    incremental: bool,
}

/// Available profile types
#[derive(Serialize)]
struct Profiles {
    dev: Profile,
    release: Profile,
}

#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "kebab-case")]
struct DependencySpec {
    #[serde(skip_serializing_if = "String::is_empty")]
    package: String,
    #[serde(serialize_with = "exact_version")]
    version: String,
    #[serde(skip_serializing_if = "Vec::is_empty")]
    features: Vec<String>,
    #[serde(skip_serializing_if = "is_true")]
    default_features: bool,
}

fn exact_version<S>(version: &String, serializer: S) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    format!("={}", version).serialize(serializer)
}

fn is_true(b: &bool) -> bool {
    *b
}

impl Modifications {
    fn blacklisted(&self, name: &str) -> bool {
        self.blacklist.iter().any(|n| n == name)
    }
}

lazy_static! {
    static ref MODIFICATIONS: Modifications = {
        let mut f = File::open("crate-modifications.toml")
            .expect("unable to open crate modifications file");

        let mut d = Vec::new();
        f.read_to_end(&mut d)
            .expect("unable to read crate modifications file");

        toml::from_slice(&d).expect("unable to parse crate modifications file")
    };
}

impl TopCrates {
    /// List top 100 crates by number of downloads on crates.io.
    fn download() -> TopCrates {
        let resp =
            reqwest::get("https://crates.io/api/v1/crates?page=1&per_page=100&sort=downloads")
                .expect("Could not fetch top crates");
        assert!(resp.status().is_success());

        serde_json::from_reader(resp).expect("Invalid JSON")
    }

    /// Add crates that have been hand-picked
    fn add_curated_crates(&mut self) {
        self.crates.extend({
            MODIFICATIONS
                .additions
                .iter()
                .cloned()
                .map(|name| Crate { name })
        });
    }
}

/// Finds the features specified by the custom metadata of `pkg`.
///
/// Our custom metadata format looks like:
///
///     [package.metadata.playground]
///     default-features = true
///     features = ["std", "extra-traits"]
///     all-features = false
///
/// All fields are optional.
fn playground_metadata_features(pkg: &Package) -> Option<(Vec<String>, bool)> {
    let custom_metadata = pkg.manifest().custom_metadata()?;
    let playground_metadata = custom_metadata.get("playground")?;

    #[derive(Deserialize)]
    #[serde(default, rename_all = "kebab-case")]
    struct Metadata {
        features: Vec<String>,
        default_features: bool,
        all_features: bool,
    }

    impl Default for Metadata {
        fn default() -> Self {
            Metadata {
                features: Vec::new(),
                default_features: true,
                all_features: false,
            }
        }
    }

    let metadata = match playground_metadata.clone().try_into::<Metadata>() {
        Ok(metadata) => metadata,
        Err(err) => {
            eprintln!(
                "Failed to parse custom metadata for {} {}: {}",
                pkg.name(),
                pkg.version(),
                err
            );
            return None;
        }
    };

    // If `all-features` is set then we ignore `features`.
    let summary = pkg.summary();
    let mut enabled_features: BTreeSet<String> = if metadata.all_features {
        summary.features().keys().map(ToString::to_string).collect()
    } else {
        metadata.features.into_iter().collect()
    };

    // If not opting out of default features, remove default features from the
    // explicit features list. This avoids ongoing spurious diffs in our
    // generated Cargo.toml as default features are added to a library.
    if metadata.default_features {
        if let Some(default_feature_names) = summary.features().get("default") {
            enabled_features.remove("default");
            for feature in default_feature_names {
                enabled_features.remove(&feature.to_string(summary));
            }
        }
    }

    if !enabled_features.is_empty() || !metadata.default_features {
        Some((
            enabled_features.into_iter().collect(),
            metadata.default_features,
        ))
    } else {
        None
    }
}

fn write_manifest(manifest: TomlManifest, path: &str) {
    let mut f = File::create(path).expect("Unable to create Cargo.toml");
    let content = toml::to_vec(&manifest).expect("Couldn't serialize TOML");
    f.write_all(&content).expect("Couldn't write Cargo.toml");
}

fn main() {
    // Setup to interact with cargo.
    let config = Config::default().expect("Unable to create default Cargo config");
    let _lock = config.acquire_package_cache_lock();
    let crates_io = SourceId::crates_io(&config).expect("Unable to create crates.io source ID");
    let mut source = RegistrySource::remote(crates_io, &HashSet::new(), &config);
    source.update().expect("Unable to update registry");

    let mut top = TopCrates::download();
    top.add_curated_crates();

    // Find the newest (non-prerelease, non-yanked) versions of all
    // the interesting crates.
    let mut summaries = Vec::new();
    for Crate { ref name } in top.crates {
        if MODIFICATIONS.blacklisted(name) {
            continue;
        }

        // Query the registry for a summary of this crate.
        // Usefully, this doesn't seem to include yanked versions
        let dep = Dependency::parse_no_deprecated(name, None, crates_io)
            .unwrap_or_else(|e| panic!("Unable to parse dependency for {}: {}", name, e));

        let matches = source.query_vec(&dep).unwrap_or_else(|e| {
            panic!("Unable to query registry for {}: {}", name, e);
        });

        // Find the newest non-prelease version
        let summary = matches
            .into_iter()
            .filter(|summary| !summary.version().is_prerelease())
            .max_by_key(|summary| summary.version().clone())
            .unwrap_or_else(|| panic!("Registry has no viable versions of {}", name));

        // Add a dependency on this crate.
        summaries.push((
            summary,
            Method::Required {
                dev_deps: false,
                features: Default::default(),
                uses_default_features: true,
                all_features: false,
            },
        ));
    }

    // Resolve transitive dependencies.
    let mut registry = PackageRegistry::new(&config).expect("Unable to create package registry");
    registry.lock_patches();
    let try_to_use = HashSet::new();
    let resolve = resolver::resolve(&summaries, &[], &mut registry, &try_to_use, None, true)
        .expect("Unable to resolve dependencies");

    // Get the package information for all dependencies.
    let package_ids: Vec<_> = resolve
        .iter()
        .filter(|pkg| !MODIFICATIONS.blacklisted(pkg.name().as_str()))
        .map(|pkg| {
            PackageId::new(&pkg.name(), pkg.version(), crates_io).unwrap_or_else(|e| {
                panic!(
                    "Unable to build PackageId for {} {}: {}",
                    pkg.name(),
                    pkg.version(),
                    e
                )
            })
        })
        .collect();

    let mut sources = SourceMap::new();
    sources.insert(Box::new(source));

    let package_set =
        PackageSet::new(&package_ids, sources, &config).expect("Unable to create a PackageSet");

    let mut packages = package_set
        .get_many(package_set.package_ids())
        .expect("Unable to download packages");

    // Sort all packages by name then version (descending), so that
    // when we group them we know we get all the same crates together
    // and the newest version first.
    packages.sort_by(|a, b| {
        a.name()
            .cmp(&b.name())
            .then(a.version().cmp(&b.version()).reverse())
    });

    let mut dependencies = BTreeMap::new();
    let mut infos = Vec::new();

    for (name, pkgs) in &packages.into_iter().group_by(|pkg| pkg.name()) {
        let mut first = true;

        for pkg in pkgs {
            let version = pkg.version();

            let crate_name = pkg
                .targets()
                .iter()
                .flat_map(|target| match target.kind() {
                    TargetKind::Lib(_) => Some(target.crate_name()),
                    _ => None,
                })
                .next()
                .unwrap_or_else(|| panic!("{} did not have a library", name));

            // We see the newest version first. Any subsequent
            // versions will have their version appended so that they
            // are uniquely named
            let exposed_name = if first {
                crate_name.clone()
            } else {
                format!(
                    "{}_{}_{}_{}",
                    crate_name, version.major, version.minor, version.patch
                )
            };

            let (features, default_features) =
                playground_metadata_features(&pkg).unwrap_or_else(|| (Vec::new(), true));

            dependencies.insert(
                exposed_name.clone(),
                DependencySpec {
                    package: name.to_string(),
                    version: version.to_string(),
                    features,
                    default_features,
                },
            );

            infos.push(CrateInformation {
                name: name.to_string(),
                version: version.to_string(),
                id: exposed_name,
            });

            first = false;
        }
    }

    // Construct playground's Cargo.toml.
    let manifest = TomlManifest {
        package: TomlPackage {
            name: "playground".to_owned(),
            version: "0.0.1".to_owned(),
            authors: vec!["The Rust Playground".to_owned()],
        },
        profile: Profiles {
            dev: Profile {
                codegen_units: 1,
                incremental: false,
            },
            release: Profile {
                codegen_units: 1,
                incremental: false,
            },
        },
        dependencies,
    };

    // Write manifest file.
    let cargo_toml = "../compiler/base/Cargo.toml";
    write_manifest(manifest, cargo_toml);
    println!("wrote {}", cargo_toml);

    let path = "../compiler/base/crate-information.json";
    let mut f = File::create(path).unwrap_or_else(|e| panic!("Unable to create {}: {}", path, e));
    serde_json::to_writer_pretty(&mut f, &infos)
        .unwrap_or_else(|e| panic!("Unable to write {}: {}", path, e));
    println!("Wrote {}", path);
}
<|endoftext|>


<commit_before>//! `bless` updates the reference files in the repo with changed output files
//! from the last test run.

use std::env;
use std::ffi::OsStr;
use std::fs;
use std::lazy::SyncLazy;
use std::path::PathBuf;
use walkdir::WalkDir;

use crate::clippy_project_root;

// NOTE: this is duplicated with tests/cargo/mod.rs What to do?
pub static CARGO_TARGET_DIR: SyncLazy<PathBuf> = SyncLazy::new(|| match env::var_os("CARGO_TARGET_DIR") {
    Some(v) => v.into(),
    None => env::current_dir().unwrap().join("target"),
});

pub fn bless() {
    let test_dirs = [
        clippy_project_root().join("tests").join("ui"),
        clippy_project_root().join("tests").join("ui-toml"),
        clippy_project_root().join("tests").join("ui-cargo"),
    ];
    for test_dir in &test_dirs {
        WalkDir::new(test_dir)
            .into_iter()
            .filter_map(Result::ok)
            .filter(|f| f.path().extension() == Some(OsStr::new("rs")))
            .for_each(|f| {
                update_reference_file(f.path().with_extension("stdout"));
                update_reference_file(f.path().with_extension("stderr"));
                update_reference_file(f.path().with_extension("fixed"));
            });
    }
}

fn update_reference_file(reference_file_path: PathBuf) {
    let test_output_path = build_dir().join(PathBuf::from(reference_file_path.file_name().unwrap()));
    let relative_reference_file_path = reference_file_path.strip_prefix(clippy_project_root()).unwrap();

    // If compiletest did not write any changes during the test run,
    // we don't have to update anything
    if !test_output_path.exists() {
        return;
    }

    let test_output_file = fs::read(&test_output_path).expect("Unable to read test output file");
    let reference_file = fs::read(&reference_file_path).expect("Unable to read reference file");

    if test_output_file != reference_file {
        // If a test run caused an output file to change, update the reference file
        println!("updating {}", &relative_reference_file_path.display());
        fs::copy(test_output_path, &reference_file_path).expect("Could not update reference file");

        if reference_file.is_empty() {
            // If we copied over an empty output file, we remove the now empty reference file
            println!("removing {}", &relative_reference_file_path.display());
            fs::remove_file(reference_file_path).expect("Could not remove reference file");
        }
    }
}

fn build_dir() -> PathBuf {
    let profile = format!("{}", env::var("PROFILE").unwrap_or("debug".to_string()));
    let mut path = PathBuf::new();
    path.push(CARGO_TARGET_DIR.clone());
    path.push(profile);
    path.push("test_build_base");
    path
}
<commit_msg>Feed the dog :dog2:<commit_after>//! `bless` updates the reference files in the repo with changed output files
//! from the last test run.

use std::env;
use std::ffi::OsStr;
use std::fs;
use std::lazy::SyncLazy;
use std::path::PathBuf;
use walkdir::WalkDir;

use crate::clippy_project_root;

// NOTE: this is duplicated with tests/cargo/mod.rs What to do?
pub static CARGO_TARGET_DIR: SyncLazy<PathBuf> = SyncLazy::new(|| match env::var_os("CARGO_TARGET_DIR") {
    Some(v) => v.into(),
    None => env::current_dir().unwrap().join("target"),
});

pub fn bless() {
    let test_dirs = [
        clippy_project_root().join("tests").join("ui"),
        clippy_project_root().join("tests").join("ui-toml"),
        clippy_project_root().join("tests").join("ui-cargo"),
    ];
    for test_dir in &test_dirs {
        WalkDir::new(test_dir)
            .into_iter()
            .filter_map(Result::ok)
            .filter(|f| f.path().extension() == Some(OsStr::new("rs")))
            .for_each(|f| {
                update_reference_file(f.path().with_extension("stdout"));
                update_reference_file(f.path().with_extension("stderr"));
                update_reference_file(f.path().with_extension("fixed"));
            });
    }
}

fn update_reference_file(reference_file_path: PathBuf) {
    let test_output_path = build_dir().join(PathBuf::from(reference_file_path.file_name().unwrap()));
    let relative_reference_file_path = reference_file_path.strip_prefix(clippy_project_root()).unwrap();

    // If compiletest did not write any changes during the test run,
    // we don't have to update anything
    if !test_output_path.exists() {
        return;
    }

    let test_output_file = fs::read(&test_output_path).expect("Unable to read test output file");
    let reference_file = fs::read(&reference_file_path).expect("Unable to read reference file");

    if test_output_file != reference_file {
        // If a test run caused an output file to change, update the reference file
        println!("updating {}", &relative_reference_file_path.display());
        fs::copy(test_output_path, &reference_file_path).expect("Could not update reference file");

        if reference_file.is_empty() {
            // If we copied over an empty output file, we remove the now empty reference file
            println!("removing {}", &relative_reference_file_path.display());
            fs::remove_file(reference_file_path).expect("Could not remove reference file");
        }
    }
}

fn build_dir() -> PathBuf {
    let profile = env::var("PROFILE").unwrap_or_else(|_| "debug".to_string());
    let mut path = PathBuf::new();
    path.push(CARGO_TARGET_DIR.clone());
    path.push(profile);
    path.push("test_build_base");
    path
}
<|endoftext|>


<commit_before>use async::engine::{self, EngineMessage};
use async::collections::atomic_array::AtomicArray;
use cell_extras::atomic_ref_cell::*;
use std::ptr;
use std::sync::Arc;
use math::*;
use polygon::anchor::AnchorId;

// HACK: This is a temporary upper bound on the number of nodes in a single row until we can
// better support dynamically allocating more space for a row.
const ROW_CAPACITY: usize = 1024;

/// A handle to a node in the scene graph.
pub struct Transform {
    inner: TransformInnerHandle,
}

impl Transform {
    pub fn new() -> Transform {
        engine::scene_graph(|scene_graph| Transform { inner: scene_graph.create_node() })
    }

    pub fn inner(&self) -> TransformInnerHandle {
        self.inner.clone()
    }

    pub fn set_position(&self, position: Point) {
        let mut data = self.inner.data_mut();
        data.position = position;
    }
}

impl Drop for Transform {
    fn drop(&mut self) {
        // TODO: Mark transform and all its children as destroyed in the manager.
        warn_once!("WARNING: Drop hasn't been implemented for Transform yet");
    }
}

unsafe impl Send for Transform {}

pub struct TransformGraph {
    row: AtomicArray<AtomicRefCell<TransformData>>,
}

impl TransformGraph {
    pub fn new() -> TransformGraph {
        TransformGraph {
            row: AtomicArray::new(ROW_CAPACITY),
        }
    }

    pub fn roots(&self) -> &[AtomicRefCell<TransformData>] {
        self.row.as_slice()
    }

    fn create_node(&self) -> TransformInnerHandle {
        // Create inner transform.
        let inner = Arc::new(TransformInner {
            data: AtomicRefCell::new(ptr::null_mut()),
            anchor: AtomicRefCell::new(None),
        });

        // Create transform data with pointer to inner.
        assert!(self.row.len() < ROW_CAPACITY, "Row 0 exceeded row capacity");
        self.row.push(AtomicRefCell::new(TransformData {
            inner: inner.clone(),

            position: Point::origin(),
            orientation: Quaternion::identity(),
            scale: Vector3::one(),
        }));

        // Hook up inner's pointer to data.
        {
            let mut data = inner.data.borrow_mut();
            *data = self.row.last().unwrap();
        }

        engine::send_message(EngineMessage::Anchor(inner.clone()));

        inner
    }
}

unsafe impl Send for TransformGraph {}
unsafe impl Sync for TransformGraph {}

#[derive(Debug)]
pub struct TransformInner {
    data: AtomicRefCell<*const AtomicRefCell<TransformData>>,
    anchor: AtomicRefCell<Option<AnchorId>>,
}

impl TransformInner {
    pub fn data(&self) -> AtomicRef<TransformData> {
        let data_ptr = self.data.borrow();
        let data = unsafe { &**data_ptr };
        data.borrow()
    }

    pub fn data_mut(&self) -> AtomicRefMut<TransformData> {
        let data_ptr = self.data.borrow();
        let data = unsafe { &**data_ptr };
        data.borrow_mut()
    }

    pub fn anchor(&self) -> Option<AnchorId> {
        self.anchor.borrow().clone()
    }
}

unsafe impl Send for TransformInner {}
unsafe impl Sync for TransformInner {}

impl TransformInner {
    pub fn set_anchor(&self, anchor: AnchorId) {
        let mut inner_anchor = self.anchor.borrow_mut();
        *inner_anchor = Some(anchor);
    }
}

pub type TransformInnerHandle = Arc<TransformInner>;

#[derive(Debug)]
pub struct TransformData {
    pub inner: TransformInnerHandle,

    pub position: Point,
    pub orientation: Quaternion,
    pub scale: Vector3,
}

impl TransformData {
    pub fn anchor(&self) -> Option<AnchorId> {
        *self.inner.anchor.borrow()
    }
}
<commit_msg>Flesh out async transform<commit_after>//! The transform component, used for positioning objects in the scene.
//!
//! TODO: Document the transform "component", especially how there's no parent/child setup.

use async::engine::{self, EngineMessage};
use async::collections::atomic_array::AtomicArray;
use cell_extras::atomic_ref_cell::*;
use std::fmt::{self, Debug, Formatter};
use std::ptr;
use std::sync::Arc;
use math::*;
use polygon::anchor::AnchorId;

// HACK: This is a temporary upper bound on the number of nodes in a single row until we can
// better support dynamically allocating more space for a row.
const ROW_CAPACITY: usize = 1024;

/// A handle to a node in the scene graph.
pub struct Transform {
    inner: TransformInnerHandle,
}

impl Transform {
    /// Creates a new transform in the scene.
    ///
    /// By default transforms start at the origin of the world with a scale of 1 and are oriented
    /// such that their "forward" is along global -z.
    pub fn new() -> Transform {
        engine::scene_graph(|scene_graph| Transform { inner: scene_graph.create_node() })
    }

    /// Gets the current position of the transform.
    pub fn position(&self) -> Point {
        let data = self.inner.data();
        data.position
    }

    /// Sets the current position of the transform the specified point.
    pub fn set_position(&mut self, position: Point) {
        let mut data = self.inner.data_mut();
        data.position = position;
    }

    /// Moves the transform by the specified offset.
    pub fn translate(&mut self, offset: Vector3) {
        let mut data = self.inner.data_mut();
        data.position += offset;
    }

    /// Gets the current orientation of the transform.
    pub fn orientation(&self) -> Quaternion {
        let data = self.inner.data();
        data.orientation
    }

    /// Sets the orientation of the transform.
    pub fn set_orientation(&mut self, orientation: Quaternion) {
        let mut data = self.inner.data_mut();
        data.orientation = orientation;
    }

    /// Rotates the transform by the specified offset.
    pub fn rotate(&mut self, offset: Quaternion) {
        let mut data = self.inner.data_mut();
        data.orientation *= offset;
    }

    /// Rotates the transform by the specified euler angles.
    ///
    /// TODO: Do the number represent clockwise or anitclockwise rotation around each axis? That
    /// might be determined by the math library, but it should be noted in the module docs.
    pub fn rotate_eulers(&mut self, x: f32, y: f32, z: f32) {
        self.rotate(Quaternion::from_eulers(x, y, z));
    }

    /// Gets the scale of the transform.
    pub fn scale(&self) -> Vector3 {
        let data = self.inner.data();
        data.scale
    }

    /// Sets the scale of the transform.
    pub fn set_scale(&mut self, scale: Vector3) {
        let mut data = self.inner.data_mut();
        data.scale = scale;
    }

    /// Gets the forward vector for the transform.
    ///
    /// The forward vector for the transform is the global forward (-z) as rotated by the
    /// transform's orientation.
    pub fn forward(&self) -> Vector3 {
        self.orientation() * Vector3::new(0.0, 0.0, -1.0)
    }

    pub fn right(&self) -> Vector3 {
        self.orientation() * Vector3::new(1.0, 0.0, 0.0)
    }

    // TODO: This shouldn't be public, it's only needed by engine internals.
    pub fn inner(&self) -> TransformInnerHandle {
        self.inner.clone()
    }
}

impl Drop for Transform {
    fn drop(&mut self) {
        // TODO: Mark transform and all its children as destroyed in the manager.
        warn_once!("WARNING: Drop hasn't been implemented for Transform yet");
    }
}

impl Debug for Transform {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        let data = self.inner.data();
        write!(
            formatter,
            "Transform {{ position: {:?}, orientation: {:?}, scale: {:?} }}",
            data.position,
            data.orientation,
            data.scale,
        )
    }
}

unsafe impl Send for Transform {}

pub struct TransformGraph {
    row: AtomicArray<AtomicRefCell<TransformData>>,
}

impl TransformGraph {
    pub fn new() -> TransformGraph {
        TransformGraph {
            row: AtomicArray::new(ROW_CAPACITY),
        }
    }

    pub fn roots(&self) -> &[AtomicRefCell<TransformData>] {
        self.row.as_slice()
    }

    fn create_node(&self) -> TransformInnerHandle {
        // Create inner transform.
        let inner = Arc::new(TransformInner {
            data: AtomicRefCell::new(ptr::null_mut()),
            anchor: AtomicRefCell::new(None),
        });

        // Create transform data with pointer to inner.
        assert!(self.row.len() < ROW_CAPACITY, "Row 0 exceeded row capacity");
        self.row.push(AtomicRefCell::new(TransformData {
            inner: inner.clone(),

            position: Point::origin(),
            orientation: Quaternion::identity(),
            scale: Vector3::one(),
        }));

        // Hook up inner's pointer to data.
        {
            let mut data = inner.data.borrow_mut();
            *data = self.row.last().unwrap();
        }

        engine::send_message(EngineMessage::Anchor(inner.clone()));

        inner
    }
}

unsafe impl Send for TransformGraph {}
unsafe impl Sync for TransformGraph {}

#[derive(Debug)]
pub struct TransformInner {
    data: AtomicRefCell<*const AtomicRefCell<TransformData>>,
    anchor: AtomicRefCell<Option<AnchorId>>,
}

impl TransformInner {
    pub fn data(&self) -> AtomicRef<TransformData> {
        let data_ptr = self.data.borrow();
        let data = unsafe { &**data_ptr };
        data.borrow()
    }

    pub fn data_mut(&self) -> AtomicRefMut<TransformData> {
        let data_ptr = self.data.borrow();
        let data = unsafe { &**data_ptr };
        data.borrow_mut()
    }

    pub fn anchor(&self) -> Option<AnchorId> {
        self.anchor.borrow().clone()
    }
}

unsafe impl Send for TransformInner {}
unsafe impl Sync for TransformInner {}

impl TransformInner {
    pub fn set_anchor(&self, anchor: AnchorId) {
        let mut inner_anchor = self.anchor.borrow_mut();
        *inner_anchor = Some(anchor);
    }
}

pub type TransformInnerHandle = Arc<TransformInner>;

#[derive(Debug)]
pub struct TransformData {
    pub inner: TransformInnerHandle,

    pub position: Point,
    pub orientation: Quaternion,
    pub scale: Vector3,
}

impl TransformData {
    pub fn anchor(&self) -> Option<AnchorId> {
        *self.inner.anchor.borrow()
    }
}
<|endoftext|>


<commit_before><commit_msg>A few comments<commit_after><|endoftext|>


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

use git2::{Repository, Signature};

use libimagerror::into::IntoError;
use libimagerror::trace::trace_error;

use vcs::git::result::Result;
use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::config::{author_name, author_mail, committer_name, committer_mail};

struct Person<'a> {
    pub name: &'a str,
    pub mail: &'a str,
}

impl<'a> Person<'a> {
    fn new(name: &'a str, mail: &'a str) -> Person<'a> {
        Person { name: name, mail: mail }
    }
}

struct Runtime<'a> {
    repository: Option<Repository>,
    author: Option<Person<'a>>,
    committer: Option<Person<'a>>,
}

impl<'a> Runtime<'a> {

    pub fn new(storepath: &PathBuf) -> Runtime<'a> {
        Runtime {
            repository: match Repository::open(storepath) {
                Ok(r) => Some(r),
                Err(e) => {
                    trace_error(&e);
                    None
                },
            },

            author: None,
            committer: None,
        }
    }

    pub fn configure(&mut self, config: &Value) -> Result<()> {
        author_name(cfg)
            .and_then(|n| author_email(cfg).map(|m| Person::new(n, m)))
            .and_then(|author| {
                committer_name(cfg)
                    .and_then(|n| committer_email(cfg).map(|m| (author, Person::new(n, m))))
            })
            .map(|(author, committer)| {
                self.author = Some(author);
                self.committer = Some(committer);
            })
    }

    pub fn new_committer_sig(&self) -> Option<Result<Signature>> {
        self.committer
            .as_ref()
            .map(|c| {
                Signature::now(c.name, c.mail)
                    .map_err(|e| GHEK::MkSignature.into_error_with_cause(Box::new(e)))
            })
    }

    pub fn repository(&self) -> Result<&Repository> {
        self.repository.as_ref().ok_or(GHEK::MkRepo.into_error())
    }

}

<commit_msg>Make Runtime pub<commit_after>use std::path::PathBuf;

use git2::{Repository, Signature};

use libimagerror::into::IntoError;
use libimagerror::trace::trace_error;

use vcs::git::result::Result;
use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::config::{author_name, author_mail, committer_name, committer_mail};

struct Person<'a> {
    pub name: &'a str,
    pub mail: &'a str,
}

impl<'a> Person<'a> {
    fn new(name: &'a str, mail: &'a str) -> Person<'a> {
        Person { name: name, mail: mail }
    }
}

pub struct Runtime<'a> {
    repository: Option<Repository>,
    author: Option<Person<'a>>,
    committer: Option<Person<'a>>,
}

impl<'a> Runtime<'a> {

    pub fn new(storepath: &PathBuf) -> Runtime<'a> {
        Runtime {
            repository: match Repository::open(storepath) {
                Ok(r) => Some(r),
                Err(e) => {
                    trace_error(&e);
                    None
                },
            },

            author: None,
            committer: None,
        }
    }

    pub fn configure(&mut self, config: &Value) -> Result<()> {
        author_name(cfg)
            .and_then(|n| author_email(cfg).map(|m| Person::new(n, m)))
            .and_then(|author| {
                committer_name(cfg)
                    .and_then(|n| committer_email(cfg).map(|m| (author, Person::new(n, m))))
            })
            .map(|(author, committer)| {
                self.author = Some(author);
                self.committer = Some(committer);
            })
    }

    pub fn new_committer_sig(&self) -> Option<Result<Signature>> {
        self.committer
            .as_ref()
            .map(|c| {
                Signature::now(c.name, c.mail)
                    .map_err(|e| GHEK::MkSignature.into_error_with_cause(Box::new(e)))
            })
    }

    pub fn repository(&self) -> Result<&Repository> {
        self.repository.as_ref().ok_or(GHEK::MkRepo.into_error())
    }

}

<|endoftext|>