<commit_before>use crate::ast::{Enum, Field, Input, Struct, Variant};
use crate::attr::Attrs;
use syn::{Error, Member, Result};

pub(crate) const CHECKED: &str = "checked in validation";

impl Input<'_> {
    pub(crate) fn validate(&self) -> Result<()> {
        match self {
            Input::Struct(input) => input.validate(),
            Input::Enum(input) => input.validate(),
        }
    }
}

impl Struct<'_> {
    fn validate(&self) -> Result<()> {
        check_non_field_attrs(&self.attrs)?;
        check_field_attrs(&self.fields)?;
        for field in &self.fields {
            field.validate()?;
        }
        Ok(())
    }
}

impl Enum<'_> {
    fn validate(&self) -> Result<()> {
        check_non_field_attrs(&self.attrs)?;
        let has_display = self.has_display();
        for variant in &self.variants {
            variant.validate()?;
            if has_display && variant.attrs.display.is_none() {
                return Err(Error::new_spanned(
                    variant.original,
                    "missing #[error(\"...\")] display attribute",
                ));
            }
        }
        Ok(())
    }
}

impl Variant<'_> {
    fn validate(&self) -> Result<()> {
        check_non_field_attrs(&self.attrs)?;
        check_field_attrs(&self.fields)?;
        for field in &self.fields {
            field.validate()?;
        }
        Ok(())
    }
}

impl Field<'_> {
    fn validate(&self) -> Result<()> {
        if let Some(display) = &self.attrs.display {
            return Err(Error::new_spanned(
                display.original,
                "not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant",
            ));
        }
        Ok(())
    }
}

fn check_non_field_attrs(attrs: &Attrs) -> Result<()> {
    if let Some(from) = &attrs.from {
        return Err(Error::new_spanned(
            from,
            "not expected here; the #[from] attribute belongs on a specific field",
        ));
    }
    if let Some(source) = &attrs.source {
        return Err(Error::new_spanned(
            source,
            "not expected here; the #[source] attribute belongs on a specific field",
        ));
    }
    if let Some(backtrace) = &attrs.backtrace {
        return Err(Error::new_spanned(
            backtrace,
            "not expected here; the #[backtrace] attribute belongs on a specific field",
        ));
    }
    Ok(())
}

fn check_field_attrs(fields: &[Field]) -> Result<()> {
    let mut from_field = None;
    let mut source_field = None;
    let mut backtrace_field = None;
    for field in fields {
        if let Some(from) = field.attrs.from {
            if from_field.is_some() {
                return Err(Error::new_spanned(from, "duplicate #[from] attribute"));
            }
            from_field = Some(field);
        }
        if let Some(source) = field.attrs.source {
            if source_field.is_some() {
                return Err(Error::new_spanned(source, "duplicate #[source] attribute"));
            }
            source_field = Some(field);
        }
        if let Some(backtrace) = field.attrs.backtrace {
            if backtrace_field.is_some() {
                return Err(Error::new_spanned(
                    backtrace,
                    "duplicate #[backtrace] attribute",
                ));
            }
            backtrace_field = Some(field);
        }
    }
    if let (Some(from_field), Some(source_field)) = (from_field, source_field) {
        if !same_member(from_field, source_field) {
            return Err(Error::new_spanned(
                from_field.attrs.from,
                "#[from] is only supported on the source field, not any other field",
            ));
        }
    }
    Ok(())
}

fn same_member(one: &Field, two: &Field) -> bool {
    match (&one.member, &two.member) {
        (Member::Named(one), Member::Named(two)) => one == two,
        (Member::Unnamed(one), Member::Unnamed(two)) => one.index == two.index,
        _ => unreachable!(),
    }
}
<commit_msg>Detect multiple variants having same From type<commit_after>use crate::ast::{Enum, Field, Input, Struct, Variant};
use crate::attr::Attrs;
use quote::ToTokens;
use std::collections::BTreeSet as Set;
use syn::{Error, Member, Result};

pub(crate) const CHECKED: &str = "checked in validation";

impl Input<'_> {
    pub(crate) fn validate(&self) -> Result<()> {
        match self {
            Input::Struct(input) => input.validate(),
            Input::Enum(input) => input.validate(),
        }
    }
}

impl Struct<'_> {
    fn validate(&self) -> Result<()> {
        check_non_field_attrs(&self.attrs)?;
        check_field_attrs(&self.fields)?;
        for field in &self.fields {
            field.validate()?;
        }
        Ok(())
    }
}

impl Enum<'_> {
    fn validate(&self) -> Result<()> {
        check_non_field_attrs(&self.attrs)?;
        let has_display = self.has_display();
        for variant in &self.variants {
            variant.validate()?;
            if has_display && variant.attrs.display.is_none() {
                return Err(Error::new_spanned(
                    variant.original,
                    "missing #[error(\"...\")] display attribute",
                ));
            }
        }
        let mut from_types = Set::new();
        for variant in &self.variants {
            if let Some(from_field) = variant.from_field() {
                let repr = from_field.ty.to_token_stream().to_string();
                if !from_types.insert(repr) {
                    return Err(Error::new_spanned(
                        from_field.original,
                        "cannot derive From because another variant has the same source type",
                    ));
                }
            }
        }
        Ok(())
    }
}

impl Variant<'_> {
    fn validate(&self) -> Result<()> {
        check_non_field_attrs(&self.attrs)?;
        check_field_attrs(&self.fields)?;
        for field in &self.fields {
            field.validate()?;
        }
        Ok(())
    }
}

impl Field<'_> {
    fn validate(&self) -> Result<()> {
        if let Some(display) = &self.attrs.display {
            return Err(Error::new_spanned(
                display.original,
                "not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant",
            ));
        }
        Ok(())
    }
}

fn check_non_field_attrs(attrs: &Attrs) -> Result<()> {
    if let Some(from) = &attrs.from {
        return Err(Error::new_spanned(
            from,
            "not expected here; the #[from] attribute belongs on a specific field",
        ));
    }
    if let Some(source) = &attrs.source {
        return Err(Error::new_spanned(
            source,
            "not expected here; the #[source] attribute belongs on a specific field",
        ));
    }
    if let Some(backtrace) = &attrs.backtrace {
        return Err(Error::new_spanned(
            backtrace,
            "not expected here; the #[backtrace] attribute belongs on a specific field",
        ));
    }
    Ok(())
}

fn check_field_attrs(fields: &[Field]) -> Result<()> {
    let mut from_field = None;
    let mut source_field = None;
    let mut backtrace_field = None;
    for field in fields {
        if let Some(from) = field.attrs.from {
            if from_field.is_some() {
                return Err(Error::new_spanned(from, "duplicate #[from] attribute"));
            }
            from_field = Some(field);
        }
        if let Some(source) = field.attrs.source {
            if source_field.is_some() {
                return Err(Error::new_spanned(source, "duplicate #[source] attribute"));
            }
            source_field = Some(field);
        }
        if let Some(backtrace) = field.attrs.backtrace {
            if backtrace_field.is_some() {
                return Err(Error::new_spanned(
                    backtrace,
                    "duplicate #[backtrace] attribute",
                ));
            }
            backtrace_field = Some(field);
        }
    }
    if let (Some(from_field), Some(source_field)) = (from_field, source_field) {
        if !same_member(from_field, source_field) {
            return Err(Error::new_spanned(
                from_field.attrs.from,
                "#[from] is only supported on the source field, not any other field",
            ));
        }
    }
    Ok(())
}

fn same_member(one: &Field, two: &Field) -> bool {
    match (&one.member, &two.member) {
        (Member::Named(one), Member::Named(two)) => one == two,
        (Member::Unnamed(one), Member::Unnamed(two)) => one.index == two.index,
        _ => unreachable!(),
    }
}
<|endoftext|>


<commit_before>use super::{BatchInsert, InsertStatement};
use crate::connection::Connection;
use crate::insertable::InsertValues;
use crate::insertable::{CanInsertInSingleQuery, ColumnInsertValue, DefaultableColumnInsertValue};
use crate::prelude::*;
use crate::query_builder::{AstPass, QueryId, ValuesClause};
use crate::query_builder::{DebugQuery, QueryFragment};
use crate::query_dsl::methods::ExecuteDsl;
use crate::sqlite::Sqlite;
use crate::{QueryResult, Table};
use std::fmt::{self, Debug, Display};

pub trait DebugQueryHelper<ContainsDefaultableValue> {
    fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
    fn fmt_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
}

impl<'a, T, V, QId, Op, Ret, const STATIC_QUERY_ID: bool> DebugQueryHelper<Yes>
    for DebugQuery<
        'a,
        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op, Ret>,
        Sqlite,
    >
where
    V: QueryFragment<Sqlite>,
    T: Copy + QuerySource,
    Op: Copy,
    Ret: Copy,
    for<'b> InsertStatement<T, &'b ValuesClause<V, T>, Op, Ret>: QueryFragment<Sqlite>,
{
    fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut statements = vec![String::from("BEGIN")];
        for record in self.query.records.values.iter() {
            let stmt = InsertStatement::new(
                self.query.target,
                record,
                self.query.operator,
                self.query.returning,
            );
            statements.push(crate::debug_query(&stmt).to_string());
        }
        statements.push("COMMIT".into());

        f.debug_struct("Query")
            .field("sql", &statements)
            .field("binds", &[] as &[i32; 0])
            .finish()
    }

    fn fmt_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "BEGIN;")?;
        for record in self.query.records.values.iter() {
            let stmt = InsertStatement::new(
                self.query.target,
                record,
                self.query.operator,
                self.query.returning,
            );
            writeln!(f, "{}", crate::debug_query(&stmt))?;
        }
        writeln!(f, "COMMIT;")?;
        Ok(())
    }
}

impl<'a, T, V, QId, Op, const STATIC_QUERY_ID: bool> DebugQueryHelper<No>
    for DebugQuery<'a, InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op>, Sqlite>
where
    T: Copy + QuerySource,
    Op: Copy,
    DebugQuery<
        'a,
        InsertStatement<T, SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Op>,
        Sqlite,
    >: Debug + Display,
{
    fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let value = unsafe {
            // This cast is safe as `SqliteBatchInsertWrapper` is #[repr(transparent)]
            &*(self as *const DebugQuery<
                'a,
                InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op>,
                Sqlite,
            >
                as *const DebugQuery<
                    'a,
                    InsertStatement<T, SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Op>,
                    Sqlite,
                >)
        };
        <_ as Debug>::fmt(value, f)
    }

    fn fmt_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let value = unsafe {
            // This cast is safe as `SqliteBatchInsertWrapper` is #[repr(transparent)]
            &*(self as *const DebugQuery<
                'a,
                InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op>,
                Sqlite,
            >
                as *const DebugQuery<
                    'a,
                    InsertStatement<T, SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Op>,
                    Sqlite,
                >)
        };
        <_ as Display>::fmt(value, f)
    }
}

impl<'a, T, V, QId, Op, O, const STATIC_QUERY_ID: bool> Display
    for DebugQuery<
        'a,
        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
        Sqlite,
    >
where
    T: QuerySource,
    V: ContainsDefaultableValue<Out = O>,
    Self: DebugQueryHelper<O>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.fmt_display(f)
    }
}

impl<'a, T, V, QId, Op, O, const STATIC_QUERY_ID: bool> Debug
    for DebugQuery<
        'a,
        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
        Sqlite,
    >
where
    T: QuerySource,
    V: ContainsDefaultableValue<Out = O>,
    Self: DebugQueryHelper<O>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.fmt_debug(f)
    }
}

#[allow(missing_debug_implementations, missing_copy_implementations)]
pub struct Yes;

impl Default for Yes {
    fn default() -> Self {
        Yes
    }
}

#[allow(missing_debug_implementations, missing_copy_implementations)]
pub struct No;

impl Default for No {
    fn default() -> Self {
        No
    }
}

pub trait Any<Rhs> {
    type Out: Any<Yes> + Any<No>;
}

impl Any<No> for No {
    type Out = No;
}

impl Any<Yes> for No {
    type Out = Yes;
}

impl Any<No> for Yes {
    type Out = Yes;
}

impl Any<Yes> for Yes {
    type Out = Yes;
}

pub trait ContainsDefaultableValue {
    type Out: Any<Yes> + Any<No>;
}

impl<C, B> ContainsDefaultableValue for ColumnInsertValue<C, B> {
    type Out = No;
}

impl<I> ContainsDefaultableValue for DefaultableColumnInsertValue<I> {
    type Out = Yes;
}

impl<I, const SIZE: usize> ContainsDefaultableValue for [I; SIZE]
where
    I: ContainsDefaultableValue,
{
    type Out = I::Out;
}

impl<I, T> ContainsDefaultableValue for ValuesClause<I, T>
where
    I: ContainsDefaultableValue,
{
    type Out = I::Out;
}

impl<'a, T> ContainsDefaultableValue for &'a T
where
    T: ContainsDefaultableValue,
{
    type Out = T::Out;
}

impl<V, T, QId, C, Op, O, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
    for InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>
where
    T: QuerySource,
    C: Connection<Backend = Sqlite>,
    V: ContainsDefaultableValue<Out = O>,
    O: Default,
    (O, Self): ExecuteDsl<C, Sqlite>,
{
    fn execute(query: Self, conn: &mut C) -> QueryResult<usize> {
        <(O, Self) as ExecuteDsl<C, Sqlite>>::execute((O::default(), query), conn)
    }
}

impl<V, T, QId, C, Op, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
    for (
        Yes,
        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
    )
where
    C: Connection<Backend = Sqlite>,
    T: Table + Copy + QueryId + 'static,
    T::FromClause: QueryFragment<Sqlite>,
    Op: Copy + QueryId + QueryFragment<Sqlite>,
    V: InsertValues<T, Sqlite> + CanInsertInSingleQuery<Sqlite> + QueryId,
{
    fn execute((Yes, query): Self, conn: &mut C) -> QueryResult<usize> {
        conn.transaction(|conn| {
            let mut result = 0;
            for record in &query.records.values {
                let stmt =
                    InsertStatement::new(query.target, record, query.operator, query.returning);
                result += stmt.execute(conn)?;
            }
            Ok(result)
        })
    }
}

#[allow(missing_debug_implementations, missing_copy_implementations)]
#[repr(transparent)]
pub struct SqliteBatchInsertWrapper<V, T, QId, const STATIC_QUERY_ID: bool>(
    BatchInsert<V, T, QId, STATIC_QUERY_ID>,
);

impl<V, Tab, QId, const STATIC_QUERY_ID: bool> QueryFragment<Sqlite>
    for SqliteBatchInsertWrapper<Vec<ValuesClause<V, Tab>>, Tab, QId, STATIC_QUERY_ID>
where
    ValuesClause<V, Tab>: QueryFragment<Sqlite>,
    V: QueryFragment<Sqlite>,
{
    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Sqlite>) -> QueryResult<()> {
        if !STATIC_QUERY_ID {
            out.unsafe_to_cache_prepared();
        }

        let mut values = self.0.values.iter();
        if let Some(value) = values.next() {
            value.walk_ast(out.reborrow())?;
        }
        for value in values {
            out.push_sql(", (");
            value.values.walk_ast(out.reborrow())?;
            out.push_sql(")");
        }
        Ok(())
    }
}

#[allow(missing_copy_implementations, missing_debug_implementations)]
#[repr(transparent)]
pub struct SqliteCanInsertInSingleQueryHelper<T: ?Sized>(T);

impl<V, T, QId, const STATIC_QUERY_ID: bool> CanInsertInSingleQuery<Sqlite>
    for SqliteBatchInsertWrapper<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>
where
    // We constrain that here on an internal helper type
    // to make sure that this does not accidently leak
    // so that noone does really implement normal batch
    // insert for inserts with default values here
    SqliteCanInsertInSingleQueryHelper<V>: CanInsertInSingleQuery<Sqlite>,
{
    fn rows_to_insert(&self) -> Option<usize> {
        Some(self.0.values.len())
    }
}

impl<T> CanInsertInSingleQuery<Sqlite> for SqliteCanInsertInSingleQueryHelper<T>
where
    T: CanInsertInSingleQuery<Sqlite>,
{
    fn rows_to_insert(&self) -> Option<usize> {
        self.0.rows_to_insert()
    }
}

impl<V, T, QId, const STATIC_QUERY_ID: bool> QueryId
    for SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>
where
    BatchInsert<V, T, QId, STATIC_QUERY_ID>: QueryId,
{
    type QueryId = <BatchInsert<V, T, QId, STATIC_QUERY_ID> as QueryId>::QueryId;

    const HAS_STATIC_QUERY_ID: bool =
        <BatchInsert<V, T, QId, STATIC_QUERY_ID> as QueryId>::HAS_STATIC_QUERY_ID;
}

impl<V, T, QId, C, Op, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
    for (
        No,
        InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op>,
    )
where
    C: Connection<Backend = Sqlite>,
    T: Table + QueryId + 'static,
    T::FromClause: QueryFragment<Sqlite>,
    Op: QueryFragment<Sqlite> + QueryId,
    SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>:
        QueryFragment<Sqlite> + QueryId + CanInsertInSingleQuery<Sqlite>,
{
    fn execute((No, query): Self, conn: &mut C) -> QueryResult<usize> {
        let query = InsertStatement {
            records: SqliteBatchInsertWrapper(query.records),
            operator: query.operator,
            target: query.target,
            returning: query.returning,
            into_clause: query.into_clause,
        };
        query.execute(conn)
    }
}

macro_rules! tuple_impls {
        ($(
            $Tuple:tt {
                $(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)+
            }
        )+) => {
            $(
                impl_contains_defaultable_value!($($T,)*);
            )*
        }
    }

macro_rules! impl_contains_defaultable_value {
    ($T1: ident, $($T: ident,)+) => {
        impl<$T1, $($T,)*> ContainsDefaultableValue for ($T1, $($T,)*)
            where $T1: ContainsDefaultableValue,
                  ($($T,)*): ContainsDefaultableValue,
                  $T1::Out: Any<<($($T,)*) as ContainsDefaultableValue>::Out>
            {
                type Out = <$T1::Out as Any<<($($T,)*) as ContainsDefaultableValue>::Out>>::Out;
            }
    };
    ($T1: ident,) => {
        impl<$T1> ContainsDefaultableValue for ($T1,)
        where $T1: ContainsDefaultableValue,
        {
            type Out = <$T1 as ContainsDefaultableValue>::Out;
        }
    }
}

diesel_derives::__diesel_for_each_tuple!(tuple_impls);
<commit_msg>Partially revert 61351f779a3076bfa8b8cecdea19caa560fc95fc to fix build time regression on rust 1.56<commit_after>use super::{BatchInsert, InsertStatement};
use crate::connection::Connection;
use crate::insertable::InsertValues;
use crate::insertable::{CanInsertInSingleQuery, ColumnInsertValue, DefaultableColumnInsertValue};
use crate::prelude::*;
use crate::query_builder::{AstPass, QueryId, ValuesClause};
use crate::query_builder::{DebugQuery, QueryFragment};
use crate::query_dsl::methods::ExecuteDsl;
use crate::sqlite::Sqlite;
use crate::{QueryResult, Table};
use std::fmt::{self, Debug, Display};

pub trait DebugQueryHelper<ContainsDefaultableValue> {
    fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
    fn fmt_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
}

impl<'a, T, V, QId, Op, Ret, const STATIC_QUERY_ID: bool> DebugQueryHelper<Yes>
    for DebugQuery<
        'a,
        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op, Ret>,
        Sqlite,
    >
where
    V: QueryFragment<Sqlite>,
    T: Copy + QuerySource,
    Op: Copy,
    Ret: Copy,
    for<'b> InsertStatement<T, &'b ValuesClause<V, T>, Op, Ret>: QueryFragment<Sqlite>,
{
    fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut statements = vec![String::from("BEGIN")];
        for record in self.query.records.values.iter() {
            let stmt = InsertStatement::new(
                self.query.target,
                record,
                self.query.operator,
                self.query.returning,
            );
            statements.push(crate::debug_query(&stmt).to_string());
        }
        statements.push("COMMIT".into());

        f.debug_struct("Query")
            .field("sql", &statements)
            .field("binds", &[] as &[i32; 0])
            .finish()
    }

    fn fmt_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "BEGIN;")?;
        for record in self.query.records.values.iter() {
            let stmt = InsertStatement::new(
                self.query.target,
                record,
                self.query.operator,
                self.query.returning,
            );
            writeln!(f, "{}", crate::debug_query(&stmt))?;
        }
        writeln!(f, "COMMIT;")?;
        Ok(())
    }
}

impl<'a, T, V, QId, Op, const STATIC_QUERY_ID: bool> DebugQueryHelper<No>
    for DebugQuery<'a, InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op>, Sqlite>
where
    T: Copy + QuerySource,
    Op: Copy,
    DebugQuery<
        'a,
        InsertStatement<T, SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Op>,
        Sqlite,
    >: Debug + Display,
{
    fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let value = unsafe {
            // This cast is safe as `SqliteBatchInsertWrapper` is #[repr(transparent)]
            &*(self as *const DebugQuery<
                'a,
                InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op>,
                Sqlite,
            >
                as *const DebugQuery<
                    'a,
                    InsertStatement<T, SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Op>,
                    Sqlite,
                >)
        };
        <_ as Debug>::fmt(value, f)
    }

    fn fmt_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let value = unsafe {
            // This cast is safe as `SqliteBatchInsertWrapper` is #[repr(transparent)]
            &*(self as *const DebugQuery<
                'a,
                InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op>,
                Sqlite,
            >
                as *const DebugQuery<
                    'a,
                    InsertStatement<T, SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Op>,
                    Sqlite,
                >)
        };
        <_ as Display>::fmt(value, f)
    }
}

impl<'a, T, V, QId, Op, O, const STATIC_QUERY_ID: bool> Display
    for DebugQuery<
        'a,
        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
        Sqlite,
    >
where
    T: QuerySource,
    V: ContainsDefaultableValue<Out = O>,
    Self: DebugQueryHelper<O>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.fmt_display(f)
    }
}

impl<'a, T, V, QId, Op, O, const STATIC_QUERY_ID: bool> Debug
    for DebugQuery<
        'a,
        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
        Sqlite,
    >
where
    T: QuerySource,
    V: ContainsDefaultableValue<Out = O>,
    Self: DebugQueryHelper<O>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.fmt_debug(f)
    }
}

#[allow(missing_debug_implementations, missing_copy_implementations)]
pub struct Yes;

impl Default for Yes {
    fn default() -> Self {
        Yes
    }
}

#[allow(missing_debug_implementations, missing_copy_implementations)]
pub struct No;

impl Default for No {
    fn default() -> Self {
        No
    }
}

pub trait Any<Rhs> {
    type Out: Any<Yes> + Any<No>;
}

impl Any<No> for No {
    type Out = No;
}

impl Any<Yes> for No {
    type Out = Yes;
}

impl Any<No> for Yes {
    type Out = Yes;
}

impl Any<Yes> for Yes {
    type Out = Yes;
}

pub trait ContainsDefaultableValue {
    type Out: Any<Yes> + Any<No>;
}

impl<C, B> ContainsDefaultableValue for ColumnInsertValue<C, B> {
    type Out = No;
}

impl<I> ContainsDefaultableValue for DefaultableColumnInsertValue<I> {
    type Out = Yes;
}

impl<I, const SIZE: usize> ContainsDefaultableValue for [I; SIZE]
where
    I: ContainsDefaultableValue,
{
    type Out = I::Out;
}

impl<I, T> ContainsDefaultableValue for ValuesClause<I, T>
where
    I: ContainsDefaultableValue,
{
    type Out = I::Out;
}

impl<'a, T> ContainsDefaultableValue for &'a T
where
    T: ContainsDefaultableValue,
{
    type Out = T::Out;
}

impl<V, T, QId, C, Op, O, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
    for InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>
where
    T: QuerySource,
    C: Connection<Backend = Sqlite>,
    V: ContainsDefaultableValue<Out = O>,
    O: Default,
    (O, Self): ExecuteDsl<C, Sqlite>,
{
    fn execute(query: Self, conn: &mut C) -> QueryResult<usize> {
        <(O, Self) as ExecuteDsl<C, Sqlite>>::execute((O::default(), query), conn)
    }
}

impl<V, T, QId, C, Op, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
    for (
        Yes,
        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
    )
where
    C: Connection<Backend = Sqlite>,
    T: Table + Copy + QueryId + 'static,
    T::FromClause: QueryFragment<Sqlite>,
    Op: Copy + QueryId + QueryFragment<Sqlite>,
    V: InsertValues<T, Sqlite> + CanInsertInSingleQuery<Sqlite> + QueryId,
{
    fn execute((Yes, query): Self, conn: &mut C) -> QueryResult<usize> {
        conn.transaction(|conn| {
            let mut result = 0;
            for record in &query.records.values {
                let stmt =
                    InsertStatement::new(query.target, record, query.operator, query.returning);
                result += stmt.execute(conn)?;
            }
            Ok(result)
        })
    }
}

#[allow(missing_debug_implementations, missing_copy_implementations)]
#[repr(transparent)]
pub struct SqliteBatchInsertWrapper<V, T, QId, const STATIC_QUERY_ID: bool>(
    BatchInsert<V, T, QId, STATIC_QUERY_ID>,
);

impl<V, Tab, QId, const STATIC_QUERY_ID: bool> QueryFragment<Sqlite>
    for SqliteBatchInsertWrapper<Vec<ValuesClause<V, Tab>>, Tab, QId, STATIC_QUERY_ID>
where
    ValuesClause<V, Tab>: QueryFragment<Sqlite>,
    V: QueryFragment<Sqlite>,
{
    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Sqlite>) -> QueryResult<()> {
        if !STATIC_QUERY_ID {
            out.unsafe_to_cache_prepared();
        }

        let mut values = self.0.values.iter();
        if let Some(value) = values.next() {
            value.walk_ast(out.reborrow())?;
        }
        for value in values {
            out.push_sql(", (");
            value.values.walk_ast(out.reborrow())?;
            out.push_sql(")");
        }
        Ok(())
    }
}

#[allow(missing_copy_implementations, missing_debug_implementations)]
#[repr(transparent)]
pub struct SqliteCanInsertInSingleQueryHelper<T: ?Sized>(T);

impl<V, T, QId, const STATIC_QUERY_ID: bool> CanInsertInSingleQuery<Sqlite>
    for SqliteBatchInsertWrapper<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>
where
    // We constrain that here on an internal helper type
    // to make sure that this does not accidently leak
    // so that noone does really implement normal batch
    // insert for inserts with default values here
    SqliteCanInsertInSingleQueryHelper<V>: CanInsertInSingleQuery<Sqlite>,
{
    fn rows_to_insert(&self) -> Option<usize> {
        Some(self.0.values.len())
    }
}

impl<T> CanInsertInSingleQuery<Sqlite> for SqliteCanInsertInSingleQueryHelper<T>
where
    T: CanInsertInSingleQuery<Sqlite>,
{
    fn rows_to_insert(&self) -> Option<usize> {
        self.0.rows_to_insert()
    }
}

impl<V, T, QId, const STATIC_QUERY_ID: bool> QueryId
    for SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>
where
    BatchInsert<V, T, QId, STATIC_QUERY_ID>: QueryId,
{
    type QueryId = <BatchInsert<V, T, QId, STATIC_QUERY_ID> as QueryId>::QueryId;

    const HAS_STATIC_QUERY_ID: bool =
        <BatchInsert<V, T, QId, STATIC_QUERY_ID> as QueryId>::HAS_STATIC_QUERY_ID;
}

impl<V, T, QId, C, Op, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
    for (
        No,
        InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op>,
    )
where
    C: Connection<Backend = Sqlite>,
    T: Table + QueryId + 'static,
    T::FromClause: QueryFragment<Sqlite>,
    Op: QueryFragment<Sqlite> + QueryId,
    SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>:
        QueryFragment<Sqlite> + QueryId + CanInsertInSingleQuery<Sqlite>,
{
    fn execute((No, query): Self, conn: &mut C) -> QueryResult<usize> {
        let query = InsertStatement {
            records: SqliteBatchInsertWrapper(query.records),
            operator: query.operator,
            target: query.target,
            returning: query.returning,
            into_clause: query.into_clause,
        };
        query.execute(conn)
    }
}

macro_rules! tuple_impls {
        ($(
            $Tuple:tt {
                $(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)+
            }
        )+) => {
            $(
                impl_contains_defaultable_value!($($T,)*);
            )*
        }
    }

macro_rules! impl_contains_defaultable_value {
      (
        @build
        start_ts = [$($ST: ident,)*],
        ts = [$T1: ident,],
        bounds = [$($bounds: tt)*],
        out = [$($out: tt)*],
    )=> {
        impl<$($ST,)*> ContainsDefaultableValue for ($($ST,)*)
        where
            $($ST: ContainsDefaultableValue,)*
            $($bounds)*
            $T1::Out: Any<$($out)*>,
        {
            type Out = <$T1::Out as Any<$($out)*>>::Out;
        }

    };
    (
        @build
        start_ts = [$($ST: ident,)*],
        ts = [$T1: ident, $($T: ident,)+],
        bounds = [$($bounds: tt)*],
        out = [$($out: tt)*],
    )=> {
        impl_contains_defaultable_value! {
            @build
            start_ts = [$($ST,)*],
            ts = [$($T,)*],
            bounds = [$($bounds)* $T1::Out: Any<$($out)*>,],
            out = [<$T1::Out as Any<$($out)*>>::Out],
        }
    };
    ($T1: ident, $($T: ident,)+) => {
        impl_contains_defaultable_value! {
            @build
            start_ts = [$T1, $($T,)*],
            ts = [$($T,)*],
            bounds = [],
            out = [$T1::Out],
        }
    };
    ($T1: ident,) => {
        impl<$T1> ContainsDefaultableValue for ($T1,)
        where $T1: ContainsDefaultableValue,
        {
            type Out = <$T1 as ContainsDefaultableValue>::Out;
        }
    }
}

diesel_derives::__diesel_for_each_tuple!(tuple_impls);
<|endoftext|>


<commit_before>
<commit_msg>custom-set: Added template to the stub file<commit_after>use std::fmt::Debug;
use std::marker::PhantomData;

#[derive(Debug, PartialEq)]
pub struct CustomSet<T> {
    // This field is here to make the template compile and not to
    // complain about unused type parameter 'T'. Once you start
    // solving the exercise, delete this field and the 'std::marker::PhantomData'
    // import.
    phantom: PhantomData<T>,
}

impl<T: Debug> CustomSet<T> {
    pub fn new(input: &[T]) -> Self {
        unimplemented!(
            "From the given input '{:?}' construct a new CustomSet struct.",
            input
        );
    }

    pub fn contains(&self, element: &T) -> bool {
        unimplemented!(
            "Determine if the '{:?}' element is present in the CustomSet struct.",
            element
        );
    }

    pub fn add(&mut self, element: T) {
        unimplemented!("Add the '{:?}' element to the CustomSet struct.", element);
    }

    pub fn is_subset(&self, other: &Self) -> bool {
        unimplemented!(
            "Determine if the CustomSet struct is a subset of the other '{:?}' struct.",
            other
        );
    }

    pub fn is_empty(&self) -> bool {
        unimplemented!("Determine if the CustomSet struct is empty.");
    }

    pub fn is_disjoint(&self, other: &Self) -> bool {
        unimplemented!(
            "Determine if the CustomSet struct and the other struct '{:?}' are disjoint.",
            other
        );
    }

    pub fn intersection(&self, other: &Self) -> Self {
        unimplemented!("Construct a new CustomSet struct that is an intersection between current struct and the other struct '{:?}'.", other);
    }

    pub fn difference(&self, other: &Self) -> Self {
        unimplemented!("Construct a new CustomSet struct that is a difference between current struct and the other struct '{:?}'.", other);
    }

    pub fn union(&self, other: &Self) -> Self {
        unimplemented!("Construct a new CustomSet struct that is an union between current struct and the other struct '{:?}'.", other);
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::process;
use std::io::{self, Write};

fn main() {
   let args: Vec<String> = env::args().collect();
   if args.len() != 2 {
       try!(io::stderr().write(b"You must provide exactly one argument"));
       process::exit(1);
   }

   let position: u16 = args[1].parse::<u16>().unwrap();

   for i in 1..101 {
       if i == position {
           continue;
       }
       let suffix: &str;
       if i.to_string().ends_with("11") || i.to_string().ends_with("12") || i.to_string().ends_with("13") {
           suffix = "th";
       } else if i.to_string().ends_with("1") {
           suffix = "st";
       } else if i.to_string().ends_with("2") {
           suffix = "nd";
       } else if i.to_string().ends_with("3") {
           suffix = "rd";
       } else {
           suffix = "th";
       }

       println!("Position: {}{}", i, suffix);
   }
}
<commit_msg>Fix compile issue<commit_after>use std::env;
use std::process;
use std::io::{self, Write};

fn main() {
   let args: Vec<String> = env::args().collect();
   if args.len() != 2 {
       io::stderr().write(b"You must provide exactly one argument");
       process::exit(1);
   }

   let position: u16 = args[1].parse::<u16>().unwrap();

   for i in 1..101 {
       if i == position {
           continue;
       }
       let suffix: &str;
       if i.to_string().ends_with("11") || i.to_string().ends_with("12") || i.to_string().ends_with("13") {
           suffix = "th";
       } else if i.to_string().ends_with("1") {
           suffix = "st";
       } else if i.to_string().ends_with("2") {
           suffix = "nd";
       } else if i.to_string().ends_with("3") {
           suffix = "rd";
       } else {
           suffix = "th";
       }

       println!("Position: {}{}", i, suffix);
   }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// the json code is largely unfinished; allow these to silence a bunch of warnings
#![allow(unused_variables)]
#![allow(dead_code)]

use image::{ColorType, save_buffer};
use premultiply::unpremultiply;
use serde_json;
use std::borrow::BorrowMut;
use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::{fmt, fs};
use super::CURRENT_FRAME_NUMBER;
use time;
use webrender;
use webrender_traits::*;

enum CachedFont {
    Native(NativeFontHandle),
    Raw(Option<Vec<u8>>, u32, Option<PathBuf>),
}

struct CachedImage {
    width: u32,
    height: u32,
    stride: u32,
    format: ImageFormat,
    bytes: Option<Vec<u8>>,
    path: Option<PathBuf>,
}

pub struct JsonFrameWriter {
    frame_base: PathBuf,
    rsrc_base: PathBuf,
    rsrc_prefix: String,
    next_rsrc_num: u32,
    images: HashMap<ImageKey, CachedImage>,
    fonts: HashMap<FontKey, CachedFont>,

    last_frame_written: u32,

    dl_descriptor: Option<BuiltDisplayListDescriptor>,
    aux_descriptor: Option<AuxiliaryListsDescriptor>,
}

impl JsonFrameWriter {
    pub fn new(path: &Path) -> JsonFrameWriter {
        let mut rsrc_base = path.to_owned();
        rsrc_base.push("res");
        fs::create_dir_all(&rsrc_base).ok();

        let rsrc_prefix = format!("{}", time::get_time().sec);

        JsonFrameWriter {
            frame_base: path.to_owned(),
            rsrc_base: rsrc_base,
            rsrc_prefix: rsrc_prefix,
            next_rsrc_num: 1,
            images: HashMap::new(),
            fonts: HashMap::new(),

            dl_descriptor: None,
            aux_descriptor: None,

            last_frame_written: u32::max_value(),
        }
    }

    pub fn begin_write_display_list(&mut self,
                                    _: &Option<ColorF>,
                                    _: &Epoch,
                                    _: &PipelineId,
                                    _: &LayoutSize,
                                    display_list: &BuiltDisplayListDescriptor,
                                    auxiliary_lists: &AuxiliaryListsDescriptor)
    {
        unsafe {
            if CURRENT_FRAME_NUMBER == self.last_frame_written {
                return;
            }
            self.last_frame_written = CURRENT_FRAME_NUMBER;
        }

        self.dl_descriptor = Some(display_list.clone());
        self.aux_descriptor = Some(auxiliary_lists.clone());
    }

    pub fn finish_write_display_list(&mut self,
                                     frame: u32,
                                     data: &[u8])
    {
        let dl_desc = self.dl_descriptor.take().unwrap();
        let aux_desc = self.aux_descriptor.take().unwrap();

        assert_eq!(data.len(), dl_desc.size() + aux_desc.size() + 4);

        // there's a 4 byte epoch header that we skip
        let dl_data = data[4..dl_desc.size() + 4].to_vec();
        let aux_data = data[dl_desc.size() + 4..].to_vec();

        let dl = BuiltDisplayList::from_data(dl_data, dl_desc);
        let aux = AuxiliaryLists::from_data(aux_data, aux_desc);

        let mut frame_file_name = self.frame_base.clone();
        let current_shown_frame = unsafe { CURRENT_FRAME_NUMBER };
        frame_file_name.push(format!("frame-{}.json", current_shown_frame));

        let mut file = File::create(&frame_file_name).unwrap();

        let items: Vec<&DisplayItem> = dl.all_display_items().iter().collect();
        let s = serde_json::to_string_pretty(&items).unwrap();
        file.write_all(&s.into_bytes()).unwrap();
        file.write_all(b"\n").unwrap();
    }

    fn next_rsrc_paths(prefix: &str, counter: &mut u32, base_path: &Path, base: &str, ext: &str) -> (PathBuf, PathBuf) {
        let mut path_file = base_path.to_owned();
        let mut path = PathBuf::from("res");

        let fstr = format!("{}-{}-{}.{}", prefix, base, counter, ext);
        path_file.push(&fstr);
        path.push(&fstr);

        *counter += 1;

        (path_file, path)
    }

    fn path_for_image(&mut self, key: ImageKey) -> Option<PathBuf> {
        if let Some(ref mut data) = self.images.get_mut(&key) {
            if data.path.is_some() {
                return data.path.clone();
            }
        } else {
            return None;
        };

        // Remove the data to munge it
        let mut data = self.images.remove(&key).unwrap();
        let mut bytes = data.bytes.take().unwrap();
        let (path_file, path) = Self::next_rsrc_paths(&self.rsrc_prefix,
                                                      &mut self.next_rsrc_num,
                                                      &self.rsrc_base,
                                                      "img",
                                                      "png");

        let ok = match data.format {
            ImageFormat::RGB8 => {
                if data.stride == data.width * 3 {
                    save_buffer(&path_file, &bytes, data.width, data.height, ColorType::RGB(8)).unwrap();
                    true
                } else {
                    false
                }
            }
            ImageFormat::RGBA8 => {
                if data.stride == data.width * 4 {
                    unpremultiply(bytes.as_mut_slice());
                    save_buffer(&path_file, &bytes, data.width, data.height, ColorType::RGBA(8)).unwrap();
                    true
                } else {
                    false
                }
            }
            ImageFormat::A8 => {
                if data.stride == data.width {
                    save_buffer(&path_file, &bytes, data.width, data.height, ColorType::Gray(8)).unwrap();
                    true
                } else {
                    false
                }
            }
            _ => { false }
        };

        if !ok {
            println!("Failed to write image with format {:?}, dimensions {}x{}, stride {}",
                     data.format, data.width, data.height, data.stride);
            return None;
        }

        data.path = Some(path.clone());
        // put it back
        self.images.insert(key, data);
        Some(path)
    }
}

impl fmt::Debug for JsonFrameWriter {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "JsonFrameWriter")
    }
}

impl webrender::ApiRecordingReceiver for JsonFrameWriter {
    fn write_msg(&mut self, _: u32, msg: &ApiMsg) {
        match *msg {
            ApiMsg::SetRootPipeline(..) |
            ApiMsg::Scroll(..) |
            ApiMsg::TickScrollingBounce |
            ApiMsg::WebGLCommand(..) => {
            }

            ApiMsg::AddRawFont(ref key, ref bytes, index) => {
                self.fonts.insert(*key, CachedFont::Raw(Some(bytes.clone()), index, None));
            }

            ApiMsg::AddNativeFont(ref key, ref native_font_handle) => {
                self.fonts.insert(*key, CachedFont::Native(native_font_handle.clone()));
            }

            ApiMsg::AddImage(ref key, ref descriptor, ref data, _) => {
                let stride = descriptor.stride.unwrap_or(
                    descriptor.width * descriptor.format.bytes_per_pixel().unwrap()
                );
                let bytes = match *data {
                    ImageData::Raw(ref v) => { (**v).clone() }
                    ImageData::External(_) | ImageData::Blob(_) => { return; }
                };
                self.images.insert(*key, CachedImage {
                    width: descriptor.width,
                    height: descriptor.height,
                    stride: stride,
                    format: descriptor.format,
                    bytes: Some(bytes),
                    path: None,
                });
            }

            ApiMsg::UpdateImage(ref key, descriptor, ref img_data, _dirty_rect) => {
                if let Some(ref mut data) = self.images.get_mut(key) {
                    assert_eq!(data.width, descriptor.width);
                    assert_eq!(data.height, descriptor.height);
                    assert_eq!(data.format, descriptor.format);

                    if let ImageData::Raw(ref bytes) = *img_data {
                        *data.path.borrow_mut() = None;
                        *data.bytes.borrow_mut() = Some((**bytes).clone());
                    } else {
                        // Other existing image types only make sense within the gecko integration.
                        println!("Wrench only supports updating buffer images (ignoring update command).");
                    }
                }
            }

            ApiMsg::DeleteImage(ref key) => {
                self.images.remove(key);
            }

            ApiMsg::SetDisplayList(ref background_color,
                                    ref epoch,
                                    ref pipeline_id,
                                    ref viewport_size,
                                    ref display_list,
                                    ref auxiliary_lists,
                                    _preserve_frame_state) => {
                self.begin_write_display_list(background_color,
                                              epoch,
                                              pipeline_id,
                                              viewport_size,
                                              display_list,
                                              auxiliary_lists);
            }
            _ => {}
        }
    }

    fn write_payload(&mut self, frame: u32, data: &[u8]) {
        if self.dl_descriptor.is_some() {
            self.finish_write_display_list(frame, data);
        }
    }
}
<commit_msg>Auto merge of #1174 - Gankro:fix-json, r=kvark<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// the json code is largely unfinished; allow these to silence a bunch of warnings
#![allow(unused_variables)]
#![allow(dead_code)]

use image::{ColorType, save_buffer};
use premultiply::unpremultiply;
use serde_json;
use std::borrow::BorrowMut;
use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::{fmt, fs};
use super::CURRENT_FRAME_NUMBER;
use time;
use webrender;
use webrender_traits::*;
use webrender_traits::channel::Payload;

enum CachedFont {
    Native(NativeFontHandle),
    Raw(Option<Vec<u8>>, u32, Option<PathBuf>),
}

struct CachedImage {
    width: u32,
    height: u32,
    stride: u32,
    format: ImageFormat,
    bytes: Option<Vec<u8>>,
    path: Option<PathBuf>,
}

pub struct JsonFrameWriter {
    frame_base: PathBuf,
    rsrc_base: PathBuf,
    rsrc_prefix: String,
    next_rsrc_num: u32,
    images: HashMap<ImageKey, CachedImage>,
    fonts: HashMap<FontKey, CachedFont>,

    last_frame_written: u32,

    dl_descriptor: Option<BuiltDisplayListDescriptor>,
    aux_descriptor: Option<AuxiliaryListsDescriptor>,
}

impl JsonFrameWriter {
    pub fn new(path: &Path) -> JsonFrameWriter {
        let mut rsrc_base = path.to_owned();
        rsrc_base.push("res");
        fs::create_dir_all(&rsrc_base).ok();

        let rsrc_prefix = format!("{}", time::get_time().sec);

        JsonFrameWriter {
            frame_base: path.to_owned(),
            rsrc_base: rsrc_base,
            rsrc_prefix: rsrc_prefix,
            next_rsrc_num: 1,
            images: HashMap::new(),
            fonts: HashMap::new(),

            dl_descriptor: None,
            aux_descriptor: None,

            last_frame_written: u32::max_value(),
        }
    }

    pub fn begin_write_display_list(&mut self,
                                    _: &Option<ColorF>,
                                    _: &Epoch,
                                    _: &PipelineId,
                                    _: &LayoutSize,
                                    display_list: &BuiltDisplayListDescriptor,
                                    auxiliary_lists: &AuxiliaryListsDescriptor)
    {
        unsafe {
            if CURRENT_FRAME_NUMBER == self.last_frame_written {
                return;
            }
            self.last_frame_written = CURRENT_FRAME_NUMBER;
        }

        self.dl_descriptor = Some(display_list.clone());
        self.aux_descriptor = Some(auxiliary_lists.clone());
    }

    pub fn finish_write_display_list(&mut self,
                                     frame: u32,
                                     data: &[u8])
    {
        let payload = Payload::from_data(data);
        let dl_desc = self.dl_descriptor.take().unwrap();
        let aux_desc = self.aux_descriptor.take().unwrap();

        let dl = BuiltDisplayList::from_data(payload.display_list_data, dl_desc);
        let aux = AuxiliaryLists::from_data(payload.auxiliary_lists_data, aux_desc);

        let mut frame_file_name = self.frame_base.clone();
        let current_shown_frame = unsafe { CURRENT_FRAME_NUMBER };
        frame_file_name.push(format!("frame-{}.json", current_shown_frame));

        let mut file = File::create(&frame_file_name).unwrap();

        let items: Vec<&DisplayItem> = dl.all_display_items().iter().collect();
        let s = serde_json::to_string_pretty(&items).unwrap();
        file.write_all(&s.into_bytes()).unwrap();
        file.write_all(b"\n").unwrap();
    }

    fn next_rsrc_paths(prefix: &str, counter: &mut u32, base_path: &Path, base: &str, ext: &str) -> (PathBuf, PathBuf) {
        let mut path_file = base_path.to_owned();
        let mut path = PathBuf::from("res");

        let fstr = format!("{}-{}-{}.{}", prefix, base, counter, ext);
        path_file.push(&fstr);
        path.push(&fstr);

        *counter += 1;

        (path_file, path)
    }

    fn path_for_image(&mut self, key: ImageKey) -> Option<PathBuf> {
        if let Some(ref mut data) = self.images.get_mut(&key) {
            if data.path.is_some() {
                return data.path.clone();
            }
        } else {
            return None;
        };

        // Remove the data to munge it
        let mut data = self.images.remove(&key).unwrap();
        let mut bytes = data.bytes.take().unwrap();
        let (path_file, path) = Self::next_rsrc_paths(&self.rsrc_prefix,
                                                      &mut self.next_rsrc_num,
                                                      &self.rsrc_base,
                                                      "img",
                                                      "png");

        let ok = match data.format {
            ImageFormat::RGB8 => {
                if data.stride == data.width * 3 {
                    save_buffer(&path_file, &bytes, data.width, data.height, ColorType::RGB(8)).unwrap();
                    true
                } else {
                    false
                }
            }
            ImageFormat::RGBA8 => {
                if data.stride == data.width * 4 {
                    unpremultiply(bytes.as_mut_slice());
                    save_buffer(&path_file, &bytes, data.width, data.height, ColorType::RGBA(8)).unwrap();
                    true
                } else {
                    false
                }
            }
            ImageFormat::A8 => {
                if data.stride == data.width {
                    save_buffer(&path_file, &bytes, data.width, data.height, ColorType::Gray(8)).unwrap();
                    true
                } else {
                    false
                }
            }
            _ => { false }
        };

        if !ok {
            println!("Failed to write image with format {:?}, dimensions {}x{}, stride {}",
                     data.format, data.width, data.height, data.stride);
            return None;
        }

        data.path = Some(path.clone());
        // put it back
        self.images.insert(key, data);
        Some(path)
    }
}

impl fmt::Debug for JsonFrameWriter {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "JsonFrameWriter")
    }
}

impl webrender::ApiRecordingReceiver for JsonFrameWriter {
    fn write_msg(&mut self, _: u32, msg: &ApiMsg) {
        match *msg {
            ApiMsg::SetRootPipeline(..) |
            ApiMsg::Scroll(..) |
            ApiMsg::TickScrollingBounce |
            ApiMsg::WebGLCommand(..) => {
            }

            ApiMsg::AddRawFont(ref key, ref bytes, index) => {
                self.fonts.insert(*key, CachedFont::Raw(Some(bytes.clone()), index, None));
            }

            ApiMsg::AddNativeFont(ref key, ref native_font_handle) => {
                self.fonts.insert(*key, CachedFont::Native(native_font_handle.clone()));
            }

            ApiMsg::AddImage(ref key, ref descriptor, ref data, _) => {
                let stride = descriptor.stride.unwrap_or(
                    descriptor.width * descriptor.format.bytes_per_pixel().unwrap()
                );
                let bytes = match *data {
                    ImageData::Raw(ref v) => { (**v).clone() }
                    ImageData::External(_) | ImageData::Blob(_) => { return; }
                };
                self.images.insert(*key, CachedImage {
                    width: descriptor.width,
                    height: descriptor.height,
                    stride: stride,
                    format: descriptor.format,
                    bytes: Some(bytes),
                    path: None,
                });
            }

            ApiMsg::UpdateImage(ref key, descriptor, ref img_data, _dirty_rect) => {
                if let Some(ref mut data) = self.images.get_mut(key) {
                    assert_eq!(data.width, descriptor.width);
                    assert_eq!(data.height, descriptor.height);
                    assert_eq!(data.format, descriptor.format);

                    if let ImageData::Raw(ref bytes) = *img_data {
                        *data.path.borrow_mut() = None;
                        *data.bytes.borrow_mut() = Some((**bytes).clone());
                    } else {
                        // Other existing image types only make sense within the gecko integration.
                        println!("Wrench only supports updating buffer images (ignoring update command).");
                    }
                }
            }

            ApiMsg::DeleteImage(ref key) => {
                self.images.remove(key);
            }

            ApiMsg::SetDisplayList(ref background_color,
                                    ref epoch,
                                    ref pipeline_id,
                                    ref viewport_size,
                                    ref display_list,
                                    ref auxiliary_lists,
                                    _preserve_frame_state) => {
                self.begin_write_display_list(background_color,
                                              epoch,
                                              pipeline_id,
                                              viewport_size,
                                              display_list,
                                              auxiliary_lists);
            }
            _ => {}
        }
    }

    fn write_payload(&mut self, frame: u32, data: &[u8]) {
        if self.dl_descriptor.is_some() {
            self.finish_write_display_list(frame, data);
        }
    }
}
<|endoftext|>


<commit_before>//! Implementations of the default callbacks exposed by wlc.
//! These functions are the main entry points into Way Cooler from user action.
//! This is the default mode that Way Cooler is in at initilization
use rustwlc::*;
use rustwlc::input::{pointer, keyboard};
use rustwlc::render::{read_pixels, wlc_pixel_format};
use uuid::Uuid;

use super::{EVENT_BLOCKED, EVENT_PASS_THROUGH, LEFT_CLICK, RIGHT_CLICK};
use ::keys::{self, KeyPress, KeyEvent};
use ::layout::{lock_tree, try_lock_tree, try_lock_action, Action, ContainerType,
                    MovementError, TreeError, FocusError};
use ::layout::commands::set_performing_action;
use ::layout::MIN_SIZE;
use ::lua::{self, LuaQuery};

use ::render::screen_scrape::{read_screen_scrape_lock, scraped_pixels_lock,
                              sync_scrape};

use registry::{self};
use super::Mode;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Default;

#[allow(unused)]
impl Mode for Default {
    fn output_created(&mut self, output: WlcOutput) -> bool {
        if let Ok(mut tree) = try_lock_tree() {
            let result = tree.add_output(output).and_then(|_|{
                tree.switch_to_workspace(&"1")
                    .map(|_| tree.layout_active_of(ContainerType::Output))
            });
            match result {
                // If the output exists, we just couldn't add it to the tree because
                // it's already there. That's OK
                Ok(_) | Err(TreeError::OutputExists(_)) => true,
                _ => false
            }
        } else {
            false
        }
    }

    fn output_destroyed(&mut self, output: WlcOutput) {
         // TODO Redistribute workspaces of that output.
    }

    fn output_focused(&mut self, output: WlcOutput, focused: bool) {
         // TODO Ensure focused on right workspace
    }

    fn output_resolution(&mut self, output: WlcOutput,
                                    old_size_ptr: Size, new_size_ptr: Size) {
        // Update the resolution of the output and its children
        let scale = 1;
        output.set_resolution(new_size_ptr, scale);
        if let Ok(mut tree) = try_lock_tree() {
            tree.layout_active_of(ContainerType::Output)
                .expect("Could not layout active output");
        }
    }

    fn output_render_post(&mut self, output: WlcOutput) {
        let need_to_fetch = read_screen_scrape_lock();
        if *need_to_fetch {
            if WlcOutput::focused() != output {
                return
            }
            if let Ok(mut scraped_pixels) = scraped_pixels_lock() {
                let resolution = output.get_resolution()
                    .expect("Output had no resolution");
                let geo = Geometry {
                    origin: Point { x: 0, y: 0 },
                    size: resolution
                };
                let result = read_pixels(wlc_pixel_format::WLC_RGBA8888, geo).1;
                *scraped_pixels = result;
                sync_scrape();
            }
        }
    }

    fn view_created(&mut self, view: WlcView) -> bool {
        let lock = registry::clients_read();
        let client = lock.client(Uuid::nil()).unwrap();
        let handle = registry::ReadHandle::new(&client);
        let bar = handle.read("programs".into())
            .expect("programs category didn't exist")
            .get("x11_bar".into())
            .and_then(|data| data.as_string().map(str::to_string));
        // TODO Move this hack, probably could live somewhere else
        if let Some(bar_name) = bar {
            if view.get_title().as_str() == bar_name {
                view.set_mask(1);
                view.bring_to_front();
                if let Ok(mut tree) = try_lock_tree() {
                    for output in WlcOutput::list() {
                        tree.add_bar(view, output).unwrap_or_else(|_| {
                            warn!("Could not add bar {:#?} to output {:#?}", view, output);
                        });
                    }
                    return true;
                }
            }
        }
        // TODO Remove this hack
        if view.get_class().as_str() == "Background" {
            trace!("Setting background: {}", view.get_title());
            view.send_to_back();
            view.set_mask(1);
            let output = view.get_output();
            let resolution = output.get_resolution()
                .expect("Couldn't get output resolution");
            let fullscreen = Geometry {
                origin: Point { x: 0, y: 0 },
                size: resolution
            };
            view.set_geometry(ResizeEdge::empty(), fullscreen);
            if let Ok(mut tree) = lock_tree() {
                let output = tree.outputs()[0];
                return tree.add_background(view, output).map(|_| true)
                    .unwrap_or_else(|err| {
                        warn!("Could not add background due to {:?}", err);
                        true
                    })
            } else {
                warn!("Could not lock tree to place background");
            }
            return false
        }
        if let Ok(mut tree) = lock_tree() {
            let result = tree.add_view(view).and_then(|_| {
                view.set_state(VIEW_MAXIMIZED, true);
                match tree.set_active_view(view) {
                    // If blocked by fullscreen, we don't focus on purpose
                    Err(TreeError::Focus(FocusError::BlockedByFullscreen(_, _))) => Ok(()),
                    result => result
                }
            });
            if result.is_err() {
                warn!("Could not add {:?}. Reason: {:?}", view, result);
            }
            result.is_ok()
        } else {
            false
        }
    }

    fn view_destroyed(&mut self, view: WlcView) {
        match try_lock_tree() {
            Ok(mut tree) => {
                tree.remove_view(view).unwrap_or_else(|err| {
                    match err {
                        TreeError::ViewNotFound(_) => {},
                        _ => {
                            warn!("Error in view_destroyed: {:?}", err);
                        }
                    }});
            },
            Err(err) => warn!("Could not delete view {:?}, {:?}", view, err)
        }
    }

    fn view_focused(&mut self, current: WlcView, focused: bool) {
        current.set_state(VIEW_ACTIVATED, focused);
        if let Ok(mut tree) = try_lock_tree() {
            match tree.set_active_view(current) {
                Ok(_) => {},
                Err(err) => {
                    warn!("Could not set {:?} to be active view: {:?}", current, err);
                }
            }
        }
    }

    fn view_props_changed(&mut self, view: WlcView, prop: ViewPropertyType) {
        if prop.contains(PROPERTY_TITLE) {
            if let Ok(mut tree) = try_lock_tree() {
                match tree.update_title(view) {
                    Ok(_) => {},
                    Err(err) => {
                        warn!("Could not update title for view {:?} because {:#?}",
                            view, err);
                    }
                }
            }
        }
    }

    fn view_moved_to_output(&mut self, view: WlcView, o1: WlcOutput, o2: WlcOutput) {
        // TODO Ensure in correct workspace
    }

    fn view_request_state(&mut self, view: WlcView, state: ViewState, toggle: bool) {
        if state == VIEW_FULLSCREEN {
            if let Ok(mut tree) = try_lock_tree() {
                if let Ok(id) = tree.lookup_handle(view.into()) {
                    tree.set_fullscreen(id, toggle)
                        .expect("The ID was related to a non-view, somehow!");
                    match tree.container_in_active_workspace(id) {
                        Ok(true) => {
                            tree.layout_active_of(ContainerType::Workspace)
                                .unwrap_or_else(|err| {
                                    warn!("Could not layout active workspace \
                                           for view {:?}: {:?}",
                                            view, err)
                                });
                        },
                        Ok(false) => {},
                        Err(err) => warn!("Could not set {:?} fullscreen: {:?}",
                                           view, err)
                    }
                } else {
                    warn!("Could not find view {:?} in tree", view);
                }
            }
        }
    }

    fn view_request_move(&mut self, view: WlcView, _dest: Point) {
        if let Ok(mut tree) = try_lock_tree() {
            if let Err(err) = tree.set_active_view(view) {
                warn!("view_request_move error: {:?}", err);
            }
        }
    }

    fn view_request_resize(&mut self, view: WlcView, edge: ResizeEdge, point: Point) {
        if let Ok(mut tree) = try_lock_tree() {
            let in_action = try_lock_action()
                .map(|action| action.is_some())
                .unwrap_or(false);
            if in_action {
                if let Ok(id) = tree.lookup_handle(view.into()) {
                    if let Err(err) = tree.resize_container(id, edge, point) {
                        warn!("resize_container returned error: {:#?}",
                                err);
                    }
                }
            }
        }
    }

    fn on_keyboard_key(&mut self, _view: WlcView, _time: u32, mods: KeyboardModifiers,
                            key: u32, state: KeyState) -> bool {
        let empty_mods: KeyboardModifiers = KeyboardModifiers {
                mods: MOD_NONE,
                leds: KeyboardLed::empty()
        };
        let sym = keyboard::get_keysym_for_key(key, empty_mods);
        let press = KeyPress::new(mods.mods, sym);

        if state == KeyState::Pressed {
            if let Some(key) = keys::get(&press) {
                info!("[key] Found an action for {}, blocking event", press);
                let action = key.event;
                let passthrough = key.passthrough;
                match action {
                    KeyEvent::Command(func) => {
                        func();
                    },
                    KeyEvent::Lua => {
                        match lua::send(LuaQuery::HandleKey(press)) {
                            Ok(_) => {},
                            Err(err) => {
                                // We may want to wait for Lua's reply from
                                // keypresses; for example if the table is tampered
                                // with or Lua is restarted or Lua has an error.
                                // ATM Lua asynchronously logs this but in the future
                                // an error popup/etc is a good idea.
                                warn!("Error sending keypress: {:?}", err);
                            }
                        }
                    }
                }
                return !passthrough
            }
        }

        return EVENT_PASS_THROUGH
    }

    fn view_request_geometry(&mut self, view: WlcView, geometry: Geometry) {
        if geometry.size.w < MIN_SIZE.w || geometry.size.h < MIN_SIZE.h {
            warn!("Ignoring requested geometry {:#?}, which is below min {:#?}",
                  geometry, MIN_SIZE);
            return;
        }
        if let Ok(mut tree) = try_lock_tree() {
            match tree.update_floating_geometry(view, geometry) {
                Ok(()) | Err(TreeError::ViewNotFound(_)) => {},
                err => warn!("Could not find view {:#?} \
                              in order to update geometry w/ {:#?} \
                              because of {:#?}",
                             view, geometry, err)
            }
        }
    }

    fn on_pointer_button(&mut self, view: WlcView, _time: u32,
                            mods: KeyboardModifiers, button: u32,
                                state: ButtonState, point: Point) -> bool {
        if state == ButtonState::Pressed {
            let mouse_mod = keys::mouse_modifier();
            if button == LEFT_CLICK && !view.is_root() {
                if let Ok(mut tree) = try_lock_tree() {
                    tree.set_active_view(view).unwrap_or_else(|_| {
                        // still focus on view, even if not in tree.
                        view.focus();
                    });
                    if mods.mods.contains(mouse_mod) {
                        let action = Action {
                            view: view,
                            grab: point,
                            edges: ResizeEdge::empty()
                        };
                        set_performing_action(Some(action));
                    }
                }
            } else if button == RIGHT_CLICK && !view.is_root() {
                info!("User right clicked w/ mods \"{:?}\" on {:?}", mods, view);
                if let Ok(mut tree) = try_lock_tree() {
                    tree.set_active_view(view).ok();
                }
                if mods.mods.contains(mouse_mod) {
                    let action = Action {
                        view: view,
                        grab: point,
                        edges: ResizeEdge::empty()
                    };
                    set_performing_action(Some(action));
                    let geometry = view.get_geometry()
                        .expect("Could not get geometry of the view");
                    let halfw = geometry.origin.x + geometry.size.w as i32 / 2;
                    let halfh = geometry.origin.y + geometry.size.h as i32 / 2;

                    {
                        let mut action: Action = try_lock_action().ok().and_then(|guard| *guard)
                            .unwrap_or(Action {
                                view: view,
                                grab: point,
                                edges: ResizeEdge::empty()
                            });
                        let flag_x = if point.x < halfw {
                            RESIZE_LEFT
                        } else if point.x > halfw {
                            RESIZE_RIGHT
                        } else {
                            ResizeEdge::empty()
                        };

                        let flag_y = if point.y < halfh {
                            RESIZE_TOP
                        } else if point.y > halfh {
                            RESIZE_BOTTOM
                        } else {
                            ResizeEdge::empty()
                        };

                        action.edges = flag_x | flag_y;
                        set_performing_action(Some(action));
                    }
                    view.set_state(VIEW_RESIZING, true);
                    return EVENT_BLOCKED
                }
            }
        } else {
            if let Ok(lock) = try_lock_action() {
                match *lock {
                    Some(action) => {
                        let view = action.view;
                        if view.get_state().contains(VIEW_RESIZING) {
                            view.set_state(VIEW_RESIZING, false);
                        }
                    },
                    _ => {}
                }
            }
            set_performing_action(None);
        }
        EVENT_PASS_THROUGH
    }

    fn on_pointer_scroll(&mut self, _view: WlcView, _time: u32,
                            _mods_ptr: KeyboardModifiers, _axis: ScrollAxis,
                            _heights: [f64; 2]) -> bool {
        EVENT_PASS_THROUGH
    }

    fn on_pointer_motion(&mut self, view: WlcView, _time: u32, point: Point) -> bool {
        let mut result = EVENT_PASS_THROUGH;
        let mut maybe_action = None;
        {
            if let Ok(action_lock) = try_lock_action() {
                maybe_action = action_lock.clone();
            }
        }
        match maybe_action {
            None => result = EVENT_PASS_THROUGH,
            Some(action) => {
                if action.edges.bits() != 0 {
                    if let Ok(mut tree) = try_lock_tree() {
                        if let Ok(active_id) = tree.lookup_handle(view.into()) {
                            match tree.resize_container(active_id, action.edges, point) {
                                // Return early here to not set the pointer
                                Ok(_) => return EVENT_BLOCKED,
                                Err(err) => warn!("Could not resize: {:#?}", err)
                            }
                        }
                    }
                } else {
                    if let Ok(mut tree) = try_lock_tree() {
                        match tree.try_drag_active(point) {
                            Ok(_) => result = EVENT_BLOCKED,
                            Err(TreeError::PerformingAction(_)) |
                            Err(TreeError::Movement(MovementError::NotFloating(_))) =>
                                result = EVENT_PASS_THROUGH,
                            Err(err) => {
                                warn!("Unexpected drarg error: {:#?}", err);
                                result = EVENT_PASS_THROUGH
                            }
                        }
                    }
                }
            }
        }
        pointer::set_position(point);
        result
    }

    fn view_pre_render(&mut self, view: WlcView) {
        if let Ok(mut tree) = lock_tree() {
            tree.render_borders(view).unwrap_or_else(|err| {
                match err {
                    // TODO Only filter if background or bar
                    TreeError::ViewNotFound(_) => {},
                    err => warn!("Error while rendering borders: {:?}", err)
                }
            })
        }
    }
}
<commit_msg>Fixes #355<commit_after>//! Implementations of the default callbacks exposed by wlc.
//! These functions are the main entry points into Way Cooler from user action.
//! This is the default mode that Way Cooler is in at initilization
use rustwlc::*;
use rustwlc::input::{pointer, keyboard};
use rustwlc::render::{read_pixels, wlc_pixel_format};
use uuid::Uuid;

use super::{EVENT_BLOCKED, EVENT_PASS_THROUGH, LEFT_CLICK, RIGHT_CLICK};
use ::keys::{self, KeyPress, KeyEvent};
use ::layout::{lock_tree, try_lock_tree, try_lock_action, Action, ContainerType,
                    MovementError, TreeError, FocusError};
use ::layout::commands::set_performing_action;
use ::layout::MIN_SIZE;
use ::lua::{self, LuaQuery};

use ::render::screen_scrape::{read_screen_scrape_lock, scraped_pixels_lock,
                              sync_scrape};

use registry::{self};
use super::Mode;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Default;

#[allow(unused)]
impl Mode for Default {
    fn output_created(&mut self, output: WlcOutput) -> bool {
        if let Ok(mut tree) = try_lock_tree() {
            let result = tree.add_output(output).and_then(|_|{
                tree.switch_to_workspace(&"1")
                    .map(|_| tree.layout_active_of(ContainerType::Output))
            });
            match result {
                // If the output exists, we just couldn't add it to the tree because
                // it's already there. That's OK
                Ok(_) | Err(TreeError::OutputExists(_)) => true,
                _ => false
            }
        } else {
            false
        }
    }

    fn output_destroyed(&mut self, output: WlcOutput) {
         // TODO Redistribute workspaces of that output.
    }

    fn output_focused(&mut self, output: WlcOutput, focused: bool) {
         // TODO Ensure focused on right workspace
    }

    fn output_resolution(&mut self, output: WlcOutput,
                                    old_size_ptr: Size, new_size_ptr: Size) {
        // Update the resolution of the output and its children
        let scale = 1;
        output.set_resolution(new_size_ptr, scale);
        if let Ok(mut tree) = try_lock_tree() {
            tree.layout_active_of(ContainerType::Output)
                .expect("Could not layout active output");
        }
    }

    fn output_render_post(&mut self, output: WlcOutput) {
        let need_to_fetch = read_screen_scrape_lock();
        if *need_to_fetch {
            if WlcOutput::focused() != output {
                return
            }
            if let Ok(mut scraped_pixels) = scraped_pixels_lock() {
                let resolution = output.get_resolution()
                    .expect("Output had no resolution");
                let geo = Geometry {
                    origin: Point { x: 0, y: 0 },
                    size: resolution
                };
                let result = read_pixels(wlc_pixel_format::WLC_RGBA8888, geo).1;
                *scraped_pixels = result;
                sync_scrape();
            }
        }
    }

    fn view_created(&mut self, view: WlcView) -> bool {
        let lock = registry::clients_read();
        let client = lock.client(Uuid::nil()).unwrap();
        let handle = registry::ReadHandle::new(&client);
        let bar = handle.read("programs".into())
            .expect("programs category didn't exist")
            .get("x11_bar".into())
            .and_then(|data| data.as_string().map(str::to_string));
        // TODO Move this hack, probably could live somewhere else
        if let Some(bar_name) = bar {
            if view.get_title().as_str() == bar_name {
                view.set_mask(1);
                view.bring_to_front();
                if let Ok(mut tree) = try_lock_tree() {
                    for output in WlcOutput::list() {
                        tree.add_bar(view, output).unwrap_or_else(|_| {
                            warn!("Could not add bar {:#?} to output {:#?}", view, output);
                        });
                    }
                    return true;
                }
            }
        }
        // TODO Remove this hack
        if view.get_class().as_str() == "Background" {
            trace!("Setting background: {}", view.get_title());
            view.send_to_back();
            view.set_mask(1);
            let output = view.get_output();
            let resolution = output.get_resolution()
                .expect("Couldn't get output resolution");
            let fullscreen = Geometry {
                origin: Point { x: 0, y: 0 },
                size: resolution
            };
            view.set_geometry(ResizeEdge::empty(), fullscreen);
            if let Ok(mut tree) = lock_tree() {
                let output = tree.outputs()[0];
                return tree.add_background(view, output).map(|_| true)
                    .unwrap_or_else(|err| {
                        warn!("Could not add background due to {:?}", err);
                        true
                    })
            } else {
                warn!("Could not lock tree to place background");
            }
            return false
        }
        if let Ok(mut tree) = lock_tree() {
            let result = tree.add_view(view).and_then(|_| {
                view.set_state(VIEW_MAXIMIZED, true);
                match tree.set_active_view(view) {
                    // If blocked by fullscreen, we don't focus on purpose
                    Err(TreeError::Focus(FocusError::BlockedByFullscreen(_, _))) => Ok(()),
                    result => result
                }
            });
            if result.is_err() {
                warn!("Could not add {:?}. Reason: {:?}", view, result);
            }
            result.is_ok()
        } else {
            false
        }
    }

    fn view_destroyed(&mut self, view: WlcView) {
        match try_lock_tree() {
            Ok(mut tree) => {
                tree.remove_view(view).unwrap_or_else(|err| {
                    match err {
                        TreeError::ViewNotFound(_) => {},
                        _ => {
                            warn!("Error in view_destroyed: {:?}", err);
                        }
                    }});
            },
            Err(err) => warn!("Could not delete view {:?}, {:?}", view, err)
        }
    }

    fn view_focused(&mut self, current: WlcView, focused: bool) {
        current.set_state(VIEW_ACTIVATED, focused);
        if let Ok(mut tree) = try_lock_tree() {
            match tree.set_active_view(current) {
                Ok(_) => {},
                Err(err) => {
                    warn!("Could not set {:?} to be active view: {:?}", current, err);
                }
            }
        }
    }

    fn view_props_changed(&mut self, view: WlcView, prop: ViewPropertyType) {
        if prop.contains(PROPERTY_TITLE) {
            if let Ok(mut tree) = try_lock_tree() {
                match tree.update_title(view) {
                    Ok(_) => {},
                    Err(err) => {
                        warn!("Could not update title for view {:?} because {:#?}",
                            view, err);
                    }
                }
            }
        }
    }

    fn view_moved_to_output(&mut self, view: WlcView, o1: WlcOutput, o2: WlcOutput) {
        // TODO Ensure in correct workspace
    }

    fn view_request_state(&mut self, view: WlcView, state: ViewState, toggle: bool) {
        if state == VIEW_FULLSCREEN {
            if let Ok(mut tree) = try_lock_tree() {
                if let Ok(id) = tree.lookup_handle(view.into()) {
                    tree.set_fullscreen(id, toggle)
                        .expect("The ID was related to a non-view, somehow!");
                    match tree.container_in_active_workspace(id) {
                        Ok(true) => {
                            tree.layout_active_of(ContainerType::Workspace)
                                .unwrap_or_else(|err| {
                                    warn!("Could not layout active workspace \
                                           for view {:?}: {:?}",
                                            view, err)
                                });
                        },
                        Ok(false) => {},
                        Err(err) => warn!("Could not set {:?} fullscreen: {:?}",
                                           view, err)
                    }
                } else {
                    warn!("Could not find view {:?} in tree", view);
                }
            }
        }
    }

    fn view_request_move(&mut self, view: WlcView, _dest: Point) {
        if let Ok(mut tree) = try_lock_tree() {
            if let Err(err) = tree.set_active_view(view) {
                warn!("view_request_move error: {:?}", err);
            }
        }
    }

    fn view_request_resize(&mut self, view: WlcView, edge: ResizeEdge, point: Point) {
        if let Ok(mut tree) = try_lock_tree() {
            let in_action = try_lock_action()
                .map(|action| action.is_some())
                .unwrap_or(false);
            if in_action {
                if let Ok(id) = tree.lookup_handle(view.into()) {
                    if let Err(err) = tree.resize_container(id, edge, point) {
                        warn!("resize_container returned error: {:#?}",
                                err);
                    }
                }
            }
        }
    }

    fn on_keyboard_key(&mut self, _view: WlcView, _time: u32, mods: KeyboardModifiers,
                            key: u32, state: KeyState) -> bool {
        let empty_mods: KeyboardModifiers = KeyboardModifiers {
                mods: MOD_NONE,
                leds: KeyboardLed::empty()
        };
        let sym = keyboard::get_keysym_for_key(key, empty_mods);
        let press = KeyPress::new(mods.mods, sym);

        if state == KeyState::Pressed {
            if let Some(key) = keys::get(&press) {
                info!("[key] Found an action for {}, blocking event", press);
                let action = key.event;
                let passthrough = key.passthrough;
                match action {
                    KeyEvent::Command(func) => {
                        func();
                    },
                    KeyEvent::Lua => {
                        match lua::send(LuaQuery::HandleKey(press)) {
                            Ok(_) => {},
                            Err(err) => {
                                // We may want to wait for Lua's reply from
                                // keypresses; for example if the table is tampered
                                // with or Lua is restarted or Lua has an error.
                                // ATM Lua asynchronously logs this but in the future
                                // an error popup/etc is a good idea.
                                warn!("Error sending keypress: {:?}", err);
                            }
                        }
                    }
                }
                return !passthrough
            }
        }

        return EVENT_PASS_THROUGH
    }

    fn view_request_geometry(&mut self, view: WlcView, geometry: Geometry) {
        if geometry.size.w < MIN_SIZE.w && geometry.size.h < MIN_SIZE.h {
            warn!("Ignoring requested geometry {:#?}, which is below min {:#?}",
                  geometry, MIN_SIZE);
            return;
        }
        if let Ok(mut tree) = try_lock_tree() {
            match tree.update_floating_geometry(view, geometry) {
                Ok(()) | Err(TreeError::ViewNotFound(_)) => {},
                err => warn!("Could not find view {:#?} \
                              in order to update geometry w/ {:#?} \
                              because of {:#?}",
                             view, geometry, err)
            }
        }
    }

    fn on_pointer_button(&mut self, view: WlcView, _time: u32,
                            mods: KeyboardModifiers, button: u32,
                                state: ButtonState, point: Point) -> bool {
        if state == ButtonState::Pressed {
            let mouse_mod = keys::mouse_modifier();
            if button == LEFT_CLICK && !view.is_root() {
                if let Ok(mut tree) = try_lock_tree() {
                    tree.set_active_view(view).unwrap_or_else(|_| {
                        // still focus on view, even if not in tree.
                        view.focus();
                    });
                    if mods.mods.contains(mouse_mod) {
                        let action = Action {
                            view: view,
                            grab: point,
                            edges: ResizeEdge::empty()
                        };
                        set_performing_action(Some(action));
                    }
                }
            } else if button == RIGHT_CLICK && !view.is_root() {
                info!("User right clicked w/ mods \"{:?}\" on {:?}", mods, view);
                if let Ok(mut tree) = try_lock_tree() {
                    tree.set_active_view(view).ok();
                }
                if mods.mods.contains(mouse_mod) {
                    let action = Action {
                        view: view,
                        grab: point,
                        edges: ResizeEdge::empty()
                    };
                    set_performing_action(Some(action));
                    let geometry = view.get_geometry()
                        .expect("Could not get geometry of the view");
                    let halfw = geometry.origin.x + geometry.size.w as i32 / 2;
                    let halfh = geometry.origin.y + geometry.size.h as i32 / 2;

                    {
                        let mut action: Action = try_lock_action().ok().and_then(|guard| *guard)
                            .unwrap_or(Action {
                                view: view,
                                grab: point,
                                edges: ResizeEdge::empty()
                            });
                        let flag_x = if point.x < halfw {
                            RESIZE_LEFT
                        } else if point.x > halfw {
                            RESIZE_RIGHT
                        } else {
                            ResizeEdge::empty()
                        };

                        let flag_y = if point.y < halfh {
                            RESIZE_TOP
                        } else if point.y > halfh {
                            RESIZE_BOTTOM
                        } else {
                            ResizeEdge::empty()
                        };

                        action.edges = flag_x | flag_y;
                        set_performing_action(Some(action));
                    }
                    view.set_state(VIEW_RESIZING, true);
                    return EVENT_BLOCKED
                }
            }
        } else {
            if let Ok(lock) = try_lock_action() {
                match *lock {
                    Some(action) => {
                        let view = action.view;
                        if view.get_state().contains(VIEW_RESIZING) {
                            view.set_state(VIEW_RESIZING, false);
                        }
                    },
                    _ => {}
                }
            }
            set_performing_action(None);
        }
        EVENT_PASS_THROUGH
    }

    fn on_pointer_scroll(&mut self, _view: WlcView, _time: u32,
                            _mods_ptr: KeyboardModifiers, _axis: ScrollAxis,
                            _heights: [f64; 2]) -> bool {
        EVENT_PASS_THROUGH
    }

    fn on_pointer_motion(&mut self, view: WlcView, _time: u32, point: Point) -> bool {
        let mut result = EVENT_PASS_THROUGH;
        let mut maybe_action = None;
        {
            if let Ok(action_lock) = try_lock_action() {
                maybe_action = action_lock.clone();
            }
        }
        match maybe_action {
            None => result = EVENT_PASS_THROUGH,
            Some(action) => {
                if action.edges.bits() != 0 {
                    if let Ok(mut tree) = try_lock_tree() {
                        if let Ok(active_id) = tree.lookup_handle(view.into()) {
                            match tree.resize_container(active_id, action.edges, point) {
                                // Return early here to not set the pointer
                                Ok(_) => return EVENT_BLOCKED,
                                Err(err) => warn!("Could not resize: {:#?}", err)
                            }
                        }
                    }
                } else {
                    if let Ok(mut tree) = try_lock_tree() {
                        match tree.try_drag_active(point) {
                            Ok(_) => result = EVENT_BLOCKED,
                            Err(TreeError::PerformingAction(_)) |
                            Err(TreeError::Movement(MovementError::NotFloating(_))) =>
                                result = EVENT_PASS_THROUGH,
                            Err(err) => {
                                warn!("Unexpected drarg error: {:#?}", err);
                                result = EVENT_PASS_THROUGH
                            }
                        }
                    }
                }
            }
        }
        pointer::set_position(point);
        result
    }

    fn view_pre_render(&mut self, view: WlcView) {
        if let Ok(mut tree) = lock_tree() {
            tree.render_borders(view).unwrap_or_else(|err| {
                match err {
                    // TODO Only filter if background or bar
                    TreeError::ViewNotFound(_) => {},
                    err => warn!("Error while rendering borders: {:?}", err)
                }
            })
        }
    }
}
<|endoftext|>