<commit_before>extern crate fallible_iterator;
extern crate futures;
extern crate postgres_shared;
extern crate postgres_protocol;
extern crate tokio_core;
extern crate tokio_dns;
extern crate tokio_uds;

use fallible_iterator::FallibleIterator;
use futures::{Future, IntoFuture, BoxFuture, Stream, Sink, Poll, StartSend};
use futures::future::Either;
use postgres_protocol::authentication;
use postgres_protocol::message::{backend, frontend};
use postgres_protocol::message::backend::{ErrorResponseBody, ErrorFields};
use postgres_shared::RowData;
use std::collections::HashMap;
use std::fmt;
use std::io;
use tokio_core::reactor::Handle;

#[doc(inline)]
pub use postgres_shared::params;

use error::{ConnectError, Error, DbError};
use params::{ConnectParams, IntoConnectParams};
use stream::PostgresStream;

pub mod error;
mod stream;

#[cfg(test)]
mod test;

#[derive(Debug, Copy, Clone)]
pub struct CancelData {
    pub process_id: i32,
    pub secret_key: i32,
}

struct InnerConnection {
    stream: PostgresStream,
    parameters: HashMap<String, String>,
    cancel_data: CancelData,
}

impl InnerConnection {
    fn read(self) -> BoxFuture<(backend::Message<Vec<u8>>, InnerConnection), (io::Error, InnerConnection)> {
        self.into_future()
            .then(|r| {
                let (m, mut s) = match r {
                    Ok((m, s)) => (m, s),
                    Err((e, s)) => return Either::A(Err((e, s)).into_future()),
                };

                match m {
                    Some(backend::Message::ParameterStatus(body)) => {
                        let name = match body.name() {
                            Ok(name) => name.to_owned(),
                            Err(e) => return Either::A(Err((e, s)).into_future()),
                        };
                        let value = match body.value() {
                            Ok(value) => value.to_owned(),
                            Err(e) => return Either::A(Err((e, s)).into_future()),
                        };
                        s.parameters.insert(name, value);
                        Either::B(s.read())
                    }
                    Some(backend::Message::NoticeResponse(_)) => {
                        // TODO forward the error
                        Either::B(s.read())
                    }
                    Some(m) => Either::A(Ok((m, s)).into_future()),
                    None => Either::A(Err((eof(), s)).into_future()),
                }
            })
            .boxed()
    }
}

impl Stream for InnerConnection {
    type Item = backend::Message<Vec<u8>>;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<backend::Message<Vec<u8>>>, io::Error> {
        self.stream.poll()
    }
}

impl Sink for InnerConnection {
    type SinkItem = Vec<u8>;
    type SinkError = io::Error;

    fn start_send(&mut self, item: Vec<u8>) -> StartSend<Vec<u8>, io::Error> {
        self.stream.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), io::Error> {
        self.stream.poll_complete()
    }
}

pub struct Connection(InnerConnection);

// FIXME fill out
impl fmt::Debug for Connection {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Connection")
            .finish()
    }
}

impl Connection {
    pub fn connect<T>(params: T, handle: &Handle) -> BoxFuture<Connection, ConnectError>
        where T: IntoConnectParams
    {
        let params = match params.into_connect_params() {
            Ok(params) => params,
            Err(e) => return futures::failed(ConnectError::ConnectParams(e)).boxed(),
        };

        stream::connect(params.host(), params.port(), handle)
            .map_err(ConnectError::Io)
            .map(|s| {
                Connection(InnerConnection {
                    stream: s,
                    parameters: HashMap::new(),
                    cancel_data: CancelData {
                        process_id: 0,
                        secret_key: 0,
                    }
                })
            })
            .and_then(|s| s.startup(params))
            .and_then(|(s, params)| s.handle_auth(params))
            .and_then(|s| s.finish_startup())
            .boxed()
    }

    fn startup(self, params: ConnectParams) -> BoxFuture<(Connection, ConnectParams), ConnectError> {
        let mut buf = vec![];
        let result = {
            let options = [("client_encoding", "UTF8"), ("timezone", "GMT")];
            let options = options.iter().cloned();
            let options = options.chain(params.user().map(|u| ("user", u.name())));
            let options = options.chain(params.database().map(|d| ("database", d)));
            let options = options.chain(params.options().iter().map(|e| (&*e.0, &*e.1)));

            frontend::startup_message(options, &mut buf)
        };

        result
            .into_future()
            .and_then(move |()| self.0.send(buf))
            .and_then(|s| s.flush())
            .map_err(ConnectError::Io)
            .map(move |s| (Connection(s), params))
            .boxed()
    }

    fn handle_auth(self, params: ConnectParams) -> BoxFuture<Connection, ConnectError> {
        self.0.read()
            .map_err(|e| e.0.into())
            .and_then(move |(m, s)| {
                let response = match m {
                    backend::Message::AuthenticationOk => Ok(None),
                    backend::Message::AuthenticationCleartextPassword => {
                        match params.user().and_then(|u| u.password()) {
                            Some(pass) => {
                                let mut buf = vec![];
                                frontend::password_message(pass, &mut buf)
                                    .map(|()| Some(buf))
                                    .map_err(Into::into)
                            }
                            None => {
                                Err(ConnectError::ConnectParams(
                                    "password was required but not provided".into()))
                            }
                        }
                    }
                    backend::Message::AuthenticationMd5Password(body) => {
                        match params.user().and_then(|u| u.password().map(|p| (u.name(), p))) {
                            Some((user, pass)) => {
                                let pass = authentication::md5_hash(user.as_bytes(),
                                                                    pass.as_bytes(),
                                                                    body.salt());
                                let mut buf = vec![];
                                frontend::password_message(&pass, &mut buf)
                                    .map(|()| Some(buf))
                                    .map_err(Into::into)
                            }
                            None => {
                                Err(ConnectError::ConnectParams(
                                    "password was required but not provided".into()))
                            }
                        }
                    }
                    backend::Message::ErrorResponse(body) => Err(connect_err(&mut body.fields())),
                    _ => Err(bad_message()),
                };

                response.map(|m| (m, Connection(s)))
            })
            .and_then(|(m, s)| {
                match m {
                    Some(m) => Either::A(s.handle_auth_response(m)),
                    None => Either::B(Ok(s).into_future())
                }
            })
            .boxed()
    }

    fn handle_auth_response(self, message: Vec<u8>) -> BoxFuture<Connection, ConnectError> {
        self.0.send(message)
            .and_then(|s| s.flush())
            .and_then(|s| s.read().map_err(|e| e.0))
            .map_err(ConnectError::Io)
            .and_then(|(m, s)| {
                match m {
                    backend::Message::AuthenticationOk => Ok(Connection(s)),
                    backend::Message::ErrorResponse(body) => Err(connect_err(&mut body.fields())),
                    _ => Err(bad_message()),
                }
            })
            .boxed()
    }

    fn finish_startup(self) -> BoxFuture<Connection, ConnectError> {
        self.0.read()
            .map_err(|e| ConnectError::Io(e.0))
            .and_then(|(m, mut s)| {
                match m {
                    backend::Message::BackendKeyData(body) => {
                        s.cancel_data.process_id = body.process_id();
                        s.cancel_data.secret_key = body.secret_key();
                        Either::A(Connection(s).finish_startup())
                    }
                    backend::Message::ReadyForQuery(_) => Either::B(Ok(Connection(s)).into_future()),
                    backend::Message::ErrorResponse(body) => {
                        Either::B(Err(connect_err(&mut body.fields())).into_future())
                    }
                    _ => Either::B(Err(bad_message()).into_future()),
                }
            })
            .boxed()
    }

    fn simple_query(self, query: &str) -> BoxFuture<(Vec<RowData>, Connection), Error> {
        let mut buf = vec![];
        frontend::query(query, &mut buf)
            .map(|()| buf)
            .into_future()
            .and_then(move |buf| self.0.send(buf))
            .and_then(|s| s.flush())
            .map_err(Error::Io)
            .and_then(|s| Connection(s).simple_read_rows(vec![]))
            .boxed()
    }

    // This has its own read_rows since it will need to handle multiple query completions
    fn simple_read_rows(self, mut rows: Vec<RowData>) -> BoxFuture<(Vec<RowData>, Connection), Error> {
        self.0.read()
            .map_err(|e| Error::Io(e.0))
            .and_then(|(m, s)| {
                match m {
                    backend::Message::ReadyForQuery(_) => {
                        Ok((rows, Connection(s))).into_future().boxed()
                    }
                    backend::Message::DataRow(body) => {
                        match body.values().collect() {
                            Ok(row) => {
                                rows.push(row);
                                Connection(s).simple_read_rows(rows)
                            }
                            Err(e) => Err(Error::Io(e)).into_future().boxed(),
                        }
                    }
                    backend::Message::EmptyQueryResponse |
                    backend::Message::CommandComplete(_) |
                    backend::Message::RowDescription(_) => Connection(s).simple_read_rows(rows),
                    backend::Message::ErrorResponse(body) => Connection(s).ready_err(body),
                    _ => Err(bad_message()).into_future().boxed(),
                }
            })
            .boxed()
    }

    fn read_rows(self, mut rows: Vec<RowData>) -> BoxFuture<(Vec<RowData>, Connection), Error> {
        self.0.read()
            .map_err(|e| Error::Io(e.0))
            .and_then(|(m, s)| {
                match m {
                    backend::Message::EmptyQueryResponse |
                    backend::Message::CommandComplete(_) => Connection(s).ready(rows).boxed(),
                    backend::Message::DataRow(body) => {
                        match body.values().collect() {
                            Ok(row) => {
                                rows.push(row);
                                Connection(s).read_rows(rows)
                            }
                            Err(e) => Err(Error::Io(e)).into_future().boxed(),
                        }
                    }
                    backend::Message::ErrorResponse(body) => Connection(s).ready_err(body),
                    _ => Err(bad_message()).into_future().boxed(),
                }
            })
            .boxed()
    }

    fn ready<T>(self, t: T) -> BoxFuture<(T, Connection), Error>
        where T: 'static + Send
    {
        self.0.read()
            .map_err(|e| Error::Io(e.0))
            .and_then(|(m, s)| {
                match m {
                    backend::Message::ReadyForQuery(_) => Ok((t, Connection(s))),
                    _ => Err(bad_message())
                }
            })
            .boxed()
    }

    fn ready_err<T>(self, body: ErrorResponseBody<Vec<u8>>) -> BoxFuture<T, Error>
        where T: 'static + Send
    {
        DbError::new(&mut body.fields())
            .map_err(Error::Io)
            .into_future()
            .and_then(|e| self.ready(e))
            .and_then(|(e, s)| Err(Error::Db(Box::new(e), s)))
            .boxed()
    }

    pub fn batch_execute(self, query: &str) -> BoxFuture<Connection, Error> {
        self.simple_query(query).map(|r| r.1).boxed()
    }

    pub fn cancel_data(&self) -> CancelData {
        self.0.cancel_data
    }
}

fn connect_err(fields: &mut ErrorFields) -> ConnectError {
    match DbError::new(fields) {
        Ok(err) => ConnectError::Db(Box::new(err)),
        Err(err) => ConnectError::Io(err),
    }
}

fn err(fields: &mut ErrorFields, conn: Connection) -> Error {
    match DbError::new(fields) {
        Ok(err) => Error::Db(Box::new(err), conn),
        Err(err) => Error::Io(err),
    }
}

fn bad_message<T>() -> T
    where T: From<io::Error>
{
    io::Error::new(io::ErrorKind::InvalidInput, "unexpected message").into()
}

fn eof<T>() -> T
    where T: From<io::Error>
{
    io::Error::new(io::ErrorKind::UnexpectedEof, "unexpected EOF").into()
}
<commit_msg>Minor cleanup<commit_after>extern crate fallible_iterator;
extern crate futures;
extern crate postgres_shared;
extern crate postgres_protocol;
extern crate tokio_core;
extern crate tokio_dns;
extern crate tokio_uds;

use fallible_iterator::FallibleIterator;
use futures::{Future, IntoFuture, BoxFuture, Stream, Sink, Poll, StartSend};
use futures::future::Either;
use postgres_protocol::authentication;
use postgres_protocol::message::{backend, frontend};
use postgres_protocol::message::backend::{ErrorResponseBody, ErrorFields};
use postgres_shared::RowData;
use std::collections::HashMap;
use std::fmt;
use std::io;
use tokio_core::reactor::Handle;

#[doc(inline)]
pub use postgres_shared::params;

use error::{ConnectError, Error, DbError};
use params::{ConnectParams, IntoConnectParams};
use stream::PostgresStream;

pub mod error;
mod stream;

#[cfg(test)]
mod test;

#[derive(Debug, Copy, Clone)]
pub struct CancelData {
    pub process_id: i32,
    pub secret_key: i32,
}

struct InnerConnection {
    stream: PostgresStream,
    parameters: HashMap<String, String>,
    cancel_data: CancelData,
}

impl InnerConnection {
    fn read(self) -> BoxFuture<(backend::Message<Vec<u8>>, InnerConnection), (io::Error, InnerConnection)> {
        self.into_future()
            .then(|r| {
                let (m, mut s) = match r {
                    Ok((m, s)) => (m, s),
                    Err((e, s)) => return Either::A(Err((e, s)).into_future()),
                };

                match m {
                    Some(backend::Message::ParameterStatus(body)) => {
                        let name = match body.name() {
                            Ok(name) => name.to_owned(),
                            Err(e) => return Either::A(Err((e, s)).into_future()),
                        };
                        let value = match body.value() {
                            Ok(value) => value.to_owned(),
                            Err(e) => return Either::A(Err((e, s)).into_future()),
                        };
                        s.parameters.insert(name, value);
                        Either::B(s.read())
                    }
                    Some(backend::Message::NoticeResponse(_)) => {
                        // TODO forward the error
                        Either::B(s.read())
                    }
                    Some(m) => Either::A(Ok((m, s)).into_future()),
                    None => {
                        let err = io::Error::new(io::ErrorKind::UnexpectedEof, "unexpected EOF");
                        Either::A(Err((err, s)).into_future())
                    }
                }
            })
            .boxed()
    }
}

impl Stream for InnerConnection {
    type Item = backend::Message<Vec<u8>>;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<backend::Message<Vec<u8>>>, io::Error> {
        self.stream.poll()
    }
}

impl Sink for InnerConnection {
    type SinkItem = Vec<u8>;
    type SinkError = io::Error;

    fn start_send(&mut self, item: Vec<u8>) -> StartSend<Vec<u8>, io::Error> {
        self.stream.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), io::Error> {
        self.stream.poll_complete()
    }
}

pub struct Connection(InnerConnection);

// FIXME fill out
impl fmt::Debug for Connection {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Connection")
            .finish()
    }
}

impl Connection {
    pub fn connect<T>(params: T, handle: &Handle) -> BoxFuture<Connection, ConnectError>
        where T: IntoConnectParams
    {
        let params = match params.into_connect_params() {
            Ok(params) => params,
            Err(e) => return futures::failed(ConnectError::ConnectParams(e)).boxed(),
        };

        stream::connect(params.host(), params.port(), handle)
            .map_err(ConnectError::Io)
            .map(|s| {
                Connection(InnerConnection {
                    stream: s,
                    parameters: HashMap::new(),
                    cancel_data: CancelData {
                        process_id: 0,
                        secret_key: 0,
                    }
                })
            })
            .and_then(|s| s.startup(params))
            .and_then(|(s, params)| s.handle_auth(params))
            .and_then(|s| s.finish_startup())
            .boxed()
    }

    fn startup(self, params: ConnectParams) -> BoxFuture<(Connection, ConnectParams), ConnectError> {
        let mut buf = vec![];
        let result = {
            let options = [("client_encoding", "UTF8"), ("timezone", "GMT")];
            let options = options.iter().cloned();
            let options = options.chain(params.user().map(|u| ("user", u.name())));
            let options = options.chain(params.database().map(|d| ("database", d)));
            let options = options.chain(params.options().iter().map(|e| (&*e.0, &*e.1)));

            frontend::startup_message(options, &mut buf)
        };

        result
            .into_future()
            .and_then(move |()| self.0.send(buf))
            .and_then(|s| s.flush())
            .map_err(ConnectError::Io)
            .map(move |s| (Connection(s), params))
            .boxed()
    }

    fn handle_auth(self, params: ConnectParams) -> BoxFuture<Connection, ConnectError> {
        self.0.read()
            .map_err(|e| e.0.into())
            .and_then(move |(m, s)| {
                let response = match m {
                    backend::Message::AuthenticationOk => Ok(None),
                    backend::Message::AuthenticationCleartextPassword => {
                        match params.user().and_then(|u| u.password()) {
                            Some(pass) => {
                                let mut buf = vec![];
                                frontend::password_message(pass, &mut buf)
                                    .map(|()| Some(buf))
                                    .map_err(Into::into)
                            }
                            None => {
                                Err(ConnectError::ConnectParams(
                                    "password was required but not provided".into()))
                            }
                        }
                    }
                    backend::Message::AuthenticationMd5Password(body) => {
                        match params.user().and_then(|u| u.password().map(|p| (u.name(), p))) {
                            Some((user, pass)) => {
                                let pass = authentication::md5_hash(user.as_bytes(),
                                                                    pass.as_bytes(),
                                                                    body.salt());
                                let mut buf = vec![];
                                frontend::password_message(&pass, &mut buf)
                                    .map(|()| Some(buf))
                                    .map_err(Into::into)
                            }
                            None => {
                                Err(ConnectError::ConnectParams(
                                    "password was required but not provided".into()))
                            }
                        }
                    }
                    backend::Message::ErrorResponse(body) => Err(connect_err(&mut body.fields())),
                    _ => Err(bad_message()),
                };

                response.map(|m| (m, Connection(s)))
            })
            .and_then(|(m, s)| {
                match m {
                    Some(m) => Either::A(s.handle_auth_response(m)),
                    None => Either::B(Ok(s).into_future())
                }
            })
            .boxed()
    }

    fn handle_auth_response(self, message: Vec<u8>) -> BoxFuture<Connection, ConnectError> {
        self.0.send(message)
            .and_then(|s| s.flush())
            .and_then(|s| s.read().map_err(|e| e.0))
            .map_err(ConnectError::Io)
            .and_then(|(m, s)| {
                match m {
                    backend::Message::AuthenticationOk => Ok(Connection(s)),
                    backend::Message::ErrorResponse(body) => Err(connect_err(&mut body.fields())),
                    _ => Err(bad_message()),
                }
            })
            .boxed()
    }

    fn finish_startup(self) -> BoxFuture<Connection, ConnectError> {
        self.0.read()
            .map_err(|e| ConnectError::Io(e.0))
            .and_then(|(m, mut s)| {
                match m {
                    backend::Message::BackendKeyData(body) => {
                        s.cancel_data.process_id = body.process_id();
                        s.cancel_data.secret_key = body.secret_key();
                        Either::A(Connection(s).finish_startup())
                    }
                    backend::Message::ReadyForQuery(_) => Either::B(Ok(Connection(s)).into_future()),
                    backend::Message::ErrorResponse(body) => {
                        Either::B(Err(connect_err(&mut body.fields())).into_future())
                    }
                    _ => Either::B(Err(bad_message()).into_future()),
                }
            })
            .boxed()
    }

    fn simple_query(self, query: &str) -> BoxFuture<(Vec<RowData>, Connection), Error> {
        let mut buf = vec![];
        frontend::query(query, &mut buf)
            .map(|()| buf)
            .into_future()
            .and_then(move |buf| self.0.send(buf))
            .and_then(|s| s.flush())
            .map_err(Error::Io)
            .and_then(|s| Connection(s).simple_read_rows(vec![]))
            .boxed()
    }

    // This has its own read_rows since it will need to handle multiple query completions
    fn simple_read_rows(self, mut rows: Vec<RowData>) -> BoxFuture<(Vec<RowData>, Connection), Error> {
        self.0.read()
            .map_err(|e| Error::Io(e.0))
            .and_then(|(m, s)| {
                match m {
                    backend::Message::ReadyForQuery(_) => {
                        Ok((rows, Connection(s))).into_future().boxed()
                    }
                    backend::Message::DataRow(body) => {
                        match body.values().collect() {
                            Ok(row) => {
                                rows.push(row);
                                Connection(s).simple_read_rows(rows)
                            }
                            Err(e) => Err(Error::Io(e)).into_future().boxed(),
                        }
                    }
                    backend::Message::EmptyQueryResponse |
                    backend::Message::CommandComplete(_) |
                    backend::Message::RowDescription(_) => Connection(s).simple_read_rows(rows),
                    backend::Message::ErrorResponse(body) => Connection(s).ready_err(body),
                    _ => Err(bad_message()).into_future().boxed(),
                }
            })
            .boxed()
    }

    fn read_rows(self, mut rows: Vec<RowData>) -> BoxFuture<(Vec<RowData>, Connection), Error> {
        self.0.read()
            .map_err(|e| Error::Io(e.0))
            .and_then(|(m, s)| {
                match m {
                    backend::Message::EmptyQueryResponse |
                    backend::Message::CommandComplete(_) => Connection(s).ready(rows).boxed(),
                    backend::Message::DataRow(body) => {
                        match body.values().collect() {
                            Ok(row) => {
                                rows.push(row);
                                Connection(s).read_rows(rows)
                            }
                            Err(e) => Err(Error::Io(e)).into_future().boxed(),
                        }
                    }
                    backend::Message::ErrorResponse(body) => Connection(s).ready_err(body),
                    _ => Err(bad_message()).into_future().boxed(),
                }
            })
            .boxed()
    }

    fn ready<T>(self, t: T) -> BoxFuture<(T, Connection), Error>
        where T: 'static + Send
    {
        self.0.read()
            .map_err(|e| Error::Io(e.0))
            .and_then(|(m, s)| {
                match m {
                    backend::Message::ReadyForQuery(_) => Ok((t, Connection(s))),
                    _ => Err(bad_message())
                }
            })
            .boxed()
    }

    fn ready_err<T>(self, body: ErrorResponseBody<Vec<u8>>) -> BoxFuture<T, Error>
        where T: 'static + Send
    {
        DbError::new(&mut body.fields())
            .map_err(Error::Io)
            .into_future()
            .and_then(|e| self.ready(e))
            .and_then(|(e, s)| Err(Error::Db(Box::new(e), s)))
            .boxed()
    }

    pub fn batch_execute(self, query: &str) -> BoxFuture<Connection, Error> {
        self.simple_query(query).map(|r| r.1).boxed()
    }

    pub fn cancel_data(&self) -> CancelData {
        self.0.cancel_data
    }
}

fn connect_err(fields: &mut ErrorFields) -> ConnectError {
    match DbError::new(fields) {
        Ok(err) => ConnectError::Db(Box::new(err)),
        Err(err) => ConnectError::Io(err),
    }
}

fn bad_message<T>() -> T
    where T: From<io::Error>
{
    io::Error::new(io::ErrorKind::InvalidInput, "unexpected message").into()
}
<|endoftext|>


<commit_before>use std::cell::Cell;
use std::cmp::max;

use cairo::{self, ImageSurface, MatrixTrait};
use cssparser;
use markup5ever::local_name;
use nalgebra::Vector3;
use num_traits::identities::Zero;
use rayon::prelude::*;

use crate::drawing_ctx::DrawingCtx;
use crate::error::{AttributeResultExt, NodeError};
use crate::filters::{
    context::{FilterContext, FilterOutput, FilterResult},
    light::{
        bottom_left_normal,
        bottom_right_normal,
        bottom_row_normal,
        interior_normal,
        left_column_normal,
        light_source::LightSource,
        right_column_normal,
        top_left_normal,
        top_right_normal,
        top_row_normal,
        Normal,
    },
    Filter,
    FilterError,
    PrimitiveWithInput,
};
use crate::node::{CascadedValues, NodeResult, NodeTrait, NodeType, RsvgNode};
use crate::parsers;
use crate::property_bag::PropertyBag;
use crate::property_defs::ColorInterpolationFilters;
use crate::surface_utils::{
    shared_surface::{SharedImageSurface, SurfaceType},
    ImageSurfaceDataExt,
    Pixel,
};
use crate::util::clamp;

/// Properties specific to either diffuse or specular lighting.
enum Data {
    Diffuse {
        diffuse_constant: Cell<f64>,
    },
    Specular {
        specular_constant: Cell<f64>,
        specular_exponent: Cell<f64>,
    },
}

/// `Data` but without `Cell`s, needed for sharing between threads.
#[derive(Clone, Copy)]
enum RawData {
    Diffuse {
        diffuse_constant: f64,
    },
    Specular {
        specular_constant: f64,
        specular_exponent: f64,
    },
}

/// The `feDiffuseLighting` and `feSpecularLighting` filter primitives.
pub struct Lighting {
    base: PrimitiveWithInput,
    surface_scale: Cell<f64>,
    kernel_unit_length: Cell<Option<(f64, f64)>>,
    data: Data,
}

impl Lighting {
    /// Constructs a new diffuse `Lighting` with empty properties.
    #[inline]
    pub fn new_diffuse() -> Lighting {
        Lighting {
            data: Data::Diffuse {
                diffuse_constant: Cell::new(1.0),
            },
            ..Self::default()
        }
    }

    /// Constructs a new specular `Lighting` with empty properties.
    #[inline]
    pub fn new_specular() -> Lighting {
        Lighting {
            data: Data::Specular {
                specular_constant: Cell::new(1.0),
                specular_exponent: Cell::new(1.0),
            },
            ..Self::default()
        }
    }
}

impl NodeTrait for Lighting {
    impl_node_as_filter!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        for (attr, value) in pbag.iter() {
            match attr {
                local_name!("surfaceScale") => self.surface_scale.set(
                    parsers::number(value).attribute(attr)?,
                ),
                local_name!("kernelUnitLength") => self.kernel_unit_length.set(Some(
                    parsers::number_optional_number(value)
                        .attribute(attr.clone())
                        .and_then(|(x, y)| {
                            if x > 0.0 && y > 0.0 {
                                Ok((x, y))
                            } else {
                                Err(NodeError::value_error(
                                    attr,
                                    "kernelUnitLength can't be less or equal to zero",
                                ))
                            }
                        })?,
                )),
                _ => (),
            }
        }

        match self.data {
            Data::Diffuse {
                ref diffuse_constant,
            } => {
                for (attr, value) in pbag.iter() {
                    match attr {
                        local_name!("diffuseConstant") => diffuse_constant.set(
                            parsers::number(value)
                                .attribute(attr.clone())
                                .and_then(|x| {
                                    if x >= 0.0 {
                                        Ok(x)
                                    } else {
                                        Err(NodeError::value_error(
                                            attr,
                                            "diffuseConstant can't be negative",
                                        ))
                                    }
                                })?,
                        ),
                        _ => (),
                    }
                }
            }
            Data::Specular {
                ref specular_constant,
                ref specular_exponent,
            } => {
                for (attr, value) in pbag.iter() {
                    match attr {
                        local_name!("specularConstant") => specular_constant.set(
                            parsers::number(value)
                                .attribute(attr.clone())
                                .and_then(|x| {
                                    if x >= 0.0 {
                                        Ok(x)
                                    } else {
                                        Err(NodeError::value_error(
                                            attr,
                                            "specularConstant can't be negative",
                                        ))
                                    }
                                })?,
                        ),
                        local_name!("specularExponent") => specular_exponent.set(
                            parsers::number(value)
                                .attribute(attr.clone())
                                .and_then(|x| {
                                    if x >= 1.0 && x <= 128.0 {
                                        Ok(x)
                                    } else {
                                        Err(NodeError::value_error(
                                            attr,
                                            "specularExponent should be between 1.0 and 128.0",
                                        ))
                                    }
                                })?,
                        ),
                        _ => (),
                    }
                }
            }
        }

        Ok(())
    }
}

impl Filter for Lighting {
    fn render(
        &self,
        node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let mut bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .into_irect(draw_ctx);
        let original_bounds = bounds;

        let scale = self
            .kernel_unit_length
            .get()
            .map(|(dx, dy)| ctx.paffine().transform_distance(dx, dy));

        let surface_scale = self.surface_scale.get();

        let cascaded = CascadedValues::new_from_node(node);
        let values = cascaded.get();
        let lighting_color = match values.lighting_color.0 {
            cssparser::Color::CurrentColor => values.color.0,
            cssparser::Color::RGBA(rgba) => rgba,
        };

        let mut light_sources = node
            .children()
            .rev()
            .filter(|c| match c.borrow().get_type() {
                NodeType::DistantLight | NodeType::PointLight | NodeType::SpotLight => true,
                _ => false,
            });

        let light_source = light_sources.next();
        if light_source.is_none() || light_sources.next().is_some() {
            return Err(FilterError::InvalidLightSourceCount);
        }

        let light_source = light_source.unwrap();
        if light_source.borrow().is_in_error() {
            return Err(FilterError::ChildNodeInError);
        }

        let node_data = light_source.borrow();
        let light_source = node_data.get_impl::<LightSource>().transform(ctx);

        let mut input_surface = input.surface().clone();

        if let Some((ox, oy)) = scale {
            // Scale the input surface to match kernel_unit_length.
            let (new_surface, new_bounds) = input_surface.scale(bounds, 1.0 / ox, 1.0 / oy)?;

            input_surface = new_surface;
            bounds = new_bounds;
        }

        // Check if the surface is too small for normal computation. This case is unspecified;
        // WebKit doesn't render anything in this case.
        if bounds.x1 < bounds.x0 + 2 || bounds.y1 < bounds.y0 + 2 {
            return Err(FilterError::LightingInputTooSmall);
        }

        let (ox, oy) = scale.unwrap_or((1.0, 1.0));

        let mut output_surface = ImageSurface::create(
            cairo::Format::ARgb32,
            input_surface.width(),
            input_surface.height(),
        )?;

        let output_stride = output_surface.get_stride() as usize;
        {
            let mut output_data = output_surface.get_data().unwrap();
            let output_slice = &mut *output_data;
            let data = self.data.to_raw();

            let compute_output_pixel =
                |mut output_slice: &mut [u8], base_y, x, y, normal: Normal| {
                    let pixel = input_surface.get_pixel(x, y);

                    let scaled_x = f64::from(x) * ox;
                    let scaled_y = f64::from(y) * oy;
                    let z = f64::from(pixel.a) / 255.0 * surface_scale;
                    let light_vector = light_source.vector(scaled_x, scaled_y, z);
                    let light_color = light_source.color(lighting_color, light_vector);

                    let factor = match data {
                        RawData::Diffuse { diffuse_constant } => {
                            let k = if normal.normal.is_zero() {
                                // Common case of (0, 0, 1) normal.
                                light_vector.z
                            } else {
                                let mut n =
                                    normal.normal.map(|x| f64::from(x) * surface_scale / 255.);
                                n.component_mul_assign(&normal.factor);
                                let normal = Vector3::new(n.x, n.y, 1.0);

                                normal.dot(&light_vector) / normal.norm()
                            };

                            diffuse_constant * k
                        }
                        RawData::Specular {
                            specular_constant,
                            specular_exponent,
                        } => {
                            let h = light_vector + Vector3::new(0.0, 0.0, 1.0);
                            let h_norm = h.norm();
                            if h_norm == 0.0 {
                                0.0
                            } else {
                                let k = if normal.normal.is_zero() {
                                    // Common case of (0, 0, 1) normal.
                                    let n_dot_h = h.z / h_norm;
                                    if specular_exponent == 1.0 {
                                        n_dot_h
                                    } else {
                                        n_dot_h.powf(specular_exponent)
                                    }
                                } else {
                                    let mut n =
                                        normal.normal.map(|x| f64::from(x) * surface_scale / 255.);
                                    n.component_mul_assign(&normal.factor);
                                    let normal = Vector3::new(n.x, n.y, 1.0);

                                    let n_dot_h = normal.dot(&h) / normal.norm() / h_norm;
                                    if specular_exponent == 1.0 {
                                        n_dot_h
                                    } else {
                                        n_dot_h.powf(specular_exponent)
                                    }
                                };

                                specular_constant * k
                            }
                        }
                    };

                    let compute = |x| (clamp(factor * f64::from(x), 0.0, 255.0) + 0.5) as u8;

                    let mut output_pixel = Pixel {
                        r: compute(light_color.red),
                        g: compute(light_color.green),
                        b: compute(light_color.blue),
                        a: 255,
                    };

                    if let RawData::Specular { .. } = data {
                        output_pixel.a = max(max(output_pixel.r, output_pixel.g), output_pixel.b);
                    }

                    output_slice.set_pixel(output_stride, output_pixel, x, y - base_y);
                };

            // Top left.
            compute_output_pixel(
                output_slice,
                0,
                bounds.x0 as u32,
                bounds.y0 as u32,
                top_left_normal(&input_surface, bounds),
            );

            // Top right.
            compute_output_pixel(
                output_slice,
                0,
                bounds.x1 as u32 - 1,
                bounds.y0 as u32,
                top_right_normal(&input_surface, bounds),
            );

            // Bottom left.
            compute_output_pixel(
                output_slice,
                0,
                bounds.x0 as u32,
                bounds.y1 as u32 - 1,
                bottom_left_normal(&input_surface, bounds),
            );

            // Bottom right.
            compute_output_pixel(
                output_slice,
                0,
                bounds.x1 as u32 - 1,
                bounds.y1 as u32 - 1,
                bottom_right_normal(&input_surface, bounds),
            );

            if bounds.x1 - bounds.x0 >= 3 {
                // Top row.
                for x in bounds.x0 as u32 + 1..bounds.x1 as u32 - 1 {
                    compute_output_pixel(
                        output_slice,
                        0,
                        x,
                        bounds.y0 as u32,
                        top_row_normal(&input_surface, bounds, x),
                    );
                }

                // Bottom row.
                for x in bounds.x0 as u32 + 1..bounds.x1 as u32 - 1 {
                    compute_output_pixel(
                        output_slice,
                        0,
                        x,
                        bounds.y1 as u32 - 1,
                        bottom_row_normal(&input_surface, bounds, x),
                    );
                }
            }

            if bounds.y1 - bounds.y0 >= 3 {
                // Left column.
                for y in bounds.y0 as u32 + 1..bounds.y1 as u32 - 1 {
                    compute_output_pixel(
                        output_slice,
                        0,
                        bounds.x0 as u32,
                        y,
                        left_column_normal(&input_surface, bounds, y),
                    );
                }

                // Right column.
                for y in bounds.y0 as u32 + 1..bounds.y1 as u32 - 1 {
                    compute_output_pixel(
                        output_slice,
                        0,
                        bounds.x1 as u32 - 1,
                        y,
                        right_column_normal(&input_surface, bounds, y),
                    );
                }
            }

            if bounds.x1 - bounds.x0 >= 3 && bounds.y1 - bounds.y0 >= 3 {
                // Interior pixels.
                let first_row = bounds.y0 as u32 + 1;
                let one_past_last_row = bounds.y1 as u32 - 1;
                let first_pixel = (first_row as usize) * output_stride;
                let one_past_last_pixel = (one_past_last_row as usize) * output_stride;

                output_slice[first_pixel..one_past_last_pixel]
                    .par_chunks_mut(output_stride)
                    .zip(first_row..one_past_last_row)
                    .for_each(|(slice, y)| {
                        for x in bounds.x0 as u32 + 1..bounds.x1 as u32 - 1 {
                            compute_output_pixel(
                                slice,
                                y,
                                x,
                                y,
                                interior_normal(&input_surface, bounds, x, y),
                            );
                        }
                    });
            }
        }

        let cascaded = CascadedValues::new_from_node(node);
        let values = cascaded.get();
        // The generated color values are in the color space determined by
        // color-interpolation-filters.
        let surface_type =
            if values.color_interpolation_filters == ColorInterpolationFilters::LinearRgb {
                SurfaceType::LinearRgb
            } else {
                SurfaceType::SRgb
            };
        let mut output_surface = SharedImageSurface::new(output_surface, surface_type)?;

        if let Some((ox, oy)) = scale {
            // Scale the output surface back.
            output_surface = output_surface.scale_to(
                ctx.source_graphic().width(),
                ctx.source_graphic().height(),
                original_bounds,
                ox,
                oy,
            )?;

            bounds = original_bounds;
        }

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: output_surface,
                bounds,
            },
        })
    }

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

impl Data {
    #[inline]
    fn to_raw(&self) -> RawData {
        match self {
            Data::Diffuse { diffuse_constant } => RawData::Diffuse {
                diffuse_constant: diffuse_constant.get(),
            },
            Data::Specular {
                specular_constant,
                specular_exponent,
            } => RawData::Specular {
                specular_constant: specular_constant.get(),
                specular_exponent: specular_exponent.get(),
            },
        }
    }
}

impl Default for Lighting {
    #[inline]
    fn default() -> Self {
        Self {
            base: PrimitiveWithInput::new::<Self>(),
            surface_scale: Cell::new(1.0),
            kernel_unit_length: Cell::new(None),

            // The data field is unused in this case.
            data: Data::Diffuse {
                diffuse_constant: Cell::new(1.0),
            },
        }
    }
}
<commit_msg>filters/light/lighting: remove interior mutability<commit_after>use std::cmp::max;

use cairo::{self, ImageSurface, MatrixTrait};
use cssparser;
use markup5ever::local_name;
use nalgebra::Vector3;
use num_traits::identities::Zero;
use rayon::prelude::*;

use crate::drawing_ctx::DrawingCtx;
use crate::error::{AttributeResultExt, NodeError};
use crate::filters::{
    context::{FilterContext, FilterOutput, FilterResult},
    light::{
        bottom_left_normal,
        bottom_right_normal,
        bottom_row_normal,
        interior_normal,
        left_column_normal,
        light_source::LightSource,
        right_column_normal,
        top_left_normal,
        top_right_normal,
        top_row_normal,
        Normal,
    },
    Filter,
    FilterError,
    PrimitiveWithInput,
};
use crate::node::{CascadedValues, NodeResult, NodeTrait, NodeType, RsvgNode};
use crate::parsers;
use crate::property_bag::PropertyBag;
use crate::property_defs::ColorInterpolationFilters;
use crate::surface_utils::{
    shared_surface::{SharedImageSurface, SurfaceType},
    ImageSurfaceDataExt,
    Pixel,
};
use crate::util::clamp;

/// Properties specific to either diffuse or specular lighting.
#[derive(Clone, Copy)]
enum Data {
    Diffuse {
        diffuse_constant: f64,
    },
    Specular {
        specular_constant: f64,
        specular_exponent: f64,
    },
}

/// The `feDiffuseLighting` and `feSpecularLighting` filter primitives.
pub struct Lighting {
    base: PrimitiveWithInput,
    surface_scale: f64,
    kernel_unit_length: Option<(f64, f64)>,
    data: Data,
}

impl Lighting {
    /// Constructs a new diffuse `Lighting` with empty properties.
    #[inline]
    pub fn new_diffuse() -> Lighting {
        Lighting {
            data: Data::Diffuse {
                diffuse_constant: 1.0,
            },
            ..Self::default()
        }
    }

    /// Constructs a new specular `Lighting` with empty properties.
    #[inline]
    pub fn new_specular() -> Lighting {
        Lighting {
            data: Data::Specular {
                specular_constant: 1.0,
                specular_exponent: 1.0,
            },
            ..Self::default()
        }
    }
}

impl NodeTrait for Lighting {
    impl_node_as_filter!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        for (attr, value) in pbag.iter() {
            match attr {
                local_name!("surfaceScale") => {
                    self.surface_scale = parsers::number(value).attribute(attr)?
                }
                local_name!("kernelUnitLength") => {
                    self.kernel_unit_length = Some(
                        parsers::number_optional_number(value)
                            .attribute(attr.clone())
                            .and_then(|(x, y)| {
                                if x > 0.0 && y > 0.0 {
                                    Ok((x, y))
                                } else {
                                    Err(NodeError::value_error(
                                        attr,
                                        "kernelUnitLength can't be less or equal to zero",
                                    ))
                                }
                            })?,
                    )
                }
                _ => (),
            }
        }

        match self.data {
            Data::Diffuse {
                ref mut diffuse_constant,
            } => {
                for (attr, value) in pbag.iter() {
                    match attr {
                        local_name!("diffuseConstant") => {
                            *diffuse_constant = parsers::number(value)
                                .attribute(attr.clone())
                                .and_then(|x| {
                                    if x >= 0.0 {
                                        Ok(x)
                                    } else {
                                        Err(NodeError::value_error(
                                            attr,
                                            "diffuseConstant can't be negative",
                                        ))
                                    }
                                })?;
                        }
                        _ => (),
                    }
                }
            }
            Data::Specular {
                ref mut specular_constant,
                ref mut specular_exponent,
            } => {
                for (attr, value) in pbag.iter() {
                    match attr {
                        local_name!("specularConstant") => {
                            *specular_constant = parsers::number(value)
                                .attribute(attr.clone())
                                .and_then(|x| {
                                    if x >= 0.0 {
                                        Ok(x)
                                    } else {
                                        Err(NodeError::value_error(
                                            attr,
                                            "specularConstant can't be negative",
                                        ))
                                    }
                                })?;
                        }
                        local_name!("specularExponent") => {
                            *specular_exponent = parsers::number(value)
                                .attribute(attr.clone())
                                .and_then(|x| {
                                    if x >= 1.0 && x <= 128.0 {
                                        Ok(x)
                                    } else {
                                        Err(NodeError::value_error(
                                            attr,
                                            "specularExponent should be between 1.0 and 128.0",
                                        ))
                                    }
                                })?;
                        }
                        _ => (),
                    }
                }
            }
        }

        Ok(())
    }
}

impl Filter for Lighting {
    fn render(
        &self,
        node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let mut bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .into_irect(draw_ctx);
        let original_bounds = bounds;

        let scale = self
            .kernel_unit_length
            .map(|(dx, dy)| ctx.paffine().transform_distance(dx, dy));

        let cascaded = CascadedValues::new_from_node(node);
        let values = cascaded.get();
        let lighting_color = match values.lighting_color.0 {
            cssparser::Color::CurrentColor => values.color.0,
            cssparser::Color::RGBA(rgba) => rgba,
        };

        let mut light_sources = node
            .children()
            .rev()
            .filter(|c| match c.borrow().get_type() {
                NodeType::DistantLight | NodeType::PointLight | NodeType::SpotLight => true,
                _ => false,
            });

        let light_source = light_sources.next();
        if light_source.is_none() || light_sources.next().is_some() {
            return Err(FilterError::InvalidLightSourceCount);
        }

        let light_source = light_source.unwrap();
        if light_source.borrow().is_in_error() {
            return Err(FilterError::ChildNodeInError);
        }

        let node_data = light_source.borrow();
        let light_source = node_data.get_impl::<LightSource>().transform(ctx);

        let mut input_surface = input.surface().clone();

        if let Some((ox, oy)) = scale {
            // Scale the input surface to match kernel_unit_length.
            let (new_surface, new_bounds) = input_surface.scale(bounds, 1.0 / ox, 1.0 / oy)?;

            input_surface = new_surface;
            bounds = new_bounds;
        }

        // Check if the surface is too small for normal computation. This case is unspecified;
        // WebKit doesn't render anything in this case.
        if bounds.x1 < bounds.x0 + 2 || bounds.y1 < bounds.y0 + 2 {
            return Err(FilterError::LightingInputTooSmall);
        }

        let (ox, oy) = scale.unwrap_or((1.0, 1.0));

        let mut output_surface = ImageSurface::create(
            cairo::Format::ARgb32,
            input_surface.width(),
            input_surface.height(),
        )?;

        let output_stride = output_surface.get_stride() as usize;
        {
            let mut output_data = output_surface.get_data().unwrap();
            let output_slice = &mut *output_data;

            let compute_output_pixel =
                |mut output_slice: &mut [u8], base_y, x, y, normal: Normal| {
                    let pixel = input_surface.get_pixel(x, y);

                    let scaled_x = f64::from(x) * ox;
                    let scaled_y = f64::from(y) * oy;
                    let z = f64::from(pixel.a) / 255.0 * self.surface_scale;
                    let light_vector = light_source.vector(scaled_x, scaled_y, z);
                    let light_color = light_source.color(lighting_color, light_vector);

                    let factor = match self.data {
                        Data::Diffuse { diffuse_constant } => {
                            let k = if normal.normal.is_zero() {
                                // Common case of (0, 0, 1) normal.
                                light_vector.z
                            } else {
                                let mut n = normal
                                    .normal
                                    .map(|x| f64::from(x) * self.surface_scale / 255.);
                                n.component_mul_assign(&normal.factor);
                                let normal = Vector3::new(n.x, n.y, 1.0);

                                normal.dot(&light_vector) / normal.norm()
                            };

                            diffuse_constant * k
                        }
                        Data::Specular {
                            specular_constant,
                            specular_exponent,
                        } => {
                            let h = light_vector + Vector3::new(0.0, 0.0, 1.0);
                            let h_norm = h.norm();
                            if h_norm == 0.0 {
                                0.0
                            } else {
                                let k = if normal.normal.is_zero() {
                                    // Common case of (0, 0, 1) normal.
                                    let n_dot_h = h.z / h_norm;
                                    if specular_exponent == 1.0 {
                                        n_dot_h
                                    } else {
                                        n_dot_h.powf(specular_exponent)
                                    }
                                } else {
                                    let mut n = normal
                                        .normal
                                        .map(|x| f64::from(x) * self.surface_scale / 255.);
                                    n.component_mul_assign(&normal.factor);
                                    let normal = Vector3::new(n.x, n.y, 1.0);

                                    let n_dot_h = normal.dot(&h) / normal.norm() / h_norm;
                                    if specular_exponent == 1.0 {
                                        n_dot_h
                                    } else {
                                        n_dot_h.powf(specular_exponent)
                                    }
                                };

                                specular_constant * k
                            }
                        }
                    };

                    let compute = |x| (clamp(factor * f64::from(x), 0.0, 255.0) + 0.5) as u8;

                    let mut output_pixel = Pixel {
                        r: compute(light_color.red),
                        g: compute(light_color.green),
                        b: compute(light_color.blue),
                        a: 255,
                    };

                    if let Data::Specular { .. } = self.data {
                        output_pixel.a = max(max(output_pixel.r, output_pixel.g), output_pixel.b);
                    }

                    output_slice.set_pixel(output_stride, output_pixel, x, y - base_y);
                };

            // Top left.
            compute_output_pixel(
                output_slice,
                0,
                bounds.x0 as u32,
                bounds.y0 as u32,
                top_left_normal(&input_surface, bounds),
            );

            // Top right.
            compute_output_pixel(
                output_slice,
                0,
                bounds.x1 as u32 - 1,
                bounds.y0 as u32,
                top_right_normal(&input_surface, bounds),
            );

            // Bottom left.
            compute_output_pixel(
                output_slice,
                0,
                bounds.x0 as u32,
                bounds.y1 as u32 - 1,
                bottom_left_normal(&input_surface, bounds),
            );

            // Bottom right.
            compute_output_pixel(
                output_slice,
                0,
                bounds.x1 as u32 - 1,
                bounds.y1 as u32 - 1,
                bottom_right_normal(&input_surface, bounds),
            );

            if bounds.x1 - bounds.x0 >= 3 {
                // Top row.
                for x in bounds.x0 as u32 + 1..bounds.x1 as u32 - 1 {
                    compute_output_pixel(
                        output_slice,
                        0,
                        x,
                        bounds.y0 as u32,
                        top_row_normal(&input_surface, bounds, x),
                    );
                }

                // Bottom row.
                for x in bounds.x0 as u32 + 1..bounds.x1 as u32 - 1 {
                    compute_output_pixel(
                        output_slice,
                        0,
                        x,
                        bounds.y1 as u32 - 1,
                        bottom_row_normal(&input_surface, bounds, x),
                    );
                }
            }

            if bounds.y1 - bounds.y0 >= 3 {
                // Left column.
                for y in bounds.y0 as u32 + 1..bounds.y1 as u32 - 1 {
                    compute_output_pixel(
                        output_slice,
                        0,
                        bounds.x0 as u32,
                        y,
                        left_column_normal(&input_surface, bounds, y),
                    );
                }

                // Right column.
                for y in bounds.y0 as u32 + 1..bounds.y1 as u32 - 1 {
                    compute_output_pixel(
                        output_slice,
                        0,
                        bounds.x1 as u32 - 1,
                        y,
                        right_column_normal(&input_surface, bounds, y),
                    );
                }
            }

            if bounds.x1 - bounds.x0 >= 3 && bounds.y1 - bounds.y0 >= 3 {
                // Interior pixels.
                let first_row = bounds.y0 as u32 + 1;
                let one_past_last_row = bounds.y1 as u32 - 1;
                let first_pixel = (first_row as usize) * output_stride;
                let one_past_last_pixel = (one_past_last_row as usize) * output_stride;

                output_slice[first_pixel..one_past_last_pixel]
                    .par_chunks_mut(output_stride)
                    .zip(first_row..one_past_last_row)
                    .for_each(|(slice, y)| {
                        for x in bounds.x0 as u32 + 1..bounds.x1 as u32 - 1 {
                            compute_output_pixel(
                                slice,
                                y,
                                x,
                                y,
                                interior_normal(&input_surface, bounds, x, y),
                            );
                        }
                    });
            }
        }

        let cascaded = CascadedValues::new_from_node(node);
        let values = cascaded.get();
        // The generated color values are in the color space determined by
        // color-interpolation-filters.
        let surface_type =
            if values.color_interpolation_filters == ColorInterpolationFilters::LinearRgb {
                SurfaceType::LinearRgb
            } else {
                SurfaceType::SRgb
            };
        let mut output_surface = SharedImageSurface::new(output_surface, surface_type)?;

        if let Some((ox, oy)) = scale {
            // Scale the output surface back.
            output_surface = output_surface.scale_to(
                ctx.source_graphic().width(),
                ctx.source_graphic().height(),
                original_bounds,
                ox,
                oy,
            )?;

            bounds = original_bounds;
        }

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: output_surface,
                bounds,
            },
        })
    }

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

impl Default for Lighting {
    #[inline]
    fn default() -> Self {
        Self {
            base: PrimitiveWithInput::new::<Self>(),
            surface_scale: 1.0,
            kernel_unit_length: None,

            // The data field is unused in this case.
            data: Data::Diffuse {
                diffuse_constant: 1.0,
            },
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Read, Write};
use std::time::Duration;

/// A factory for creating a listener on a given address.
pub trait Transport {
    /// The type of listener that binds to the given address.
    type Listener: Listener;
    /// Return a listener on the given address, and a dialer to that address.
    fn bind(&self) -> io::Result<Self::Listener>;
}

/// Accepts incoming connections from dialers.
pub trait Listener: Send + 'static {
    /// The type of address being listened on.
    type Dialer: Dialer;
    /// The type of stream this listener accepts.
    type Stream: Stream;
    /// Accept an incoming stream.
    fn accept(&self) -> io::Result<Self::Stream>;
    /// Returns the local address being listened on.
    fn dialer(&self) -> io::Result<Self::Dialer>;
    /// Iterate over incoming connections.
    fn incoming(&self) -> Incoming<Self> {
        Incoming {
            listener: self,
        }
    }
}

/// A cloneable Reader/Writer.
pub trait Stream: Read + Write + Send + Sized + 'static {
    /// Clone that can fail.
    fn try_clone(&self) -> io::Result<Self>;
    /// Sets a read timeout.
    fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()>;
    /// Sets a write timeout.
    fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()>;
    /// Shuts down both ends of the stream.
    fn shutdown(&self) -> io::Result<()>;
}

/// A `Stream` factory.
pub trait Dialer {
    /// The type of `Stream` this can create.
    type Stream: Stream;
    /// The type of address being connected to.
    type Addr;
    /// Open a stream.
    fn dial(&self) -> io::Result<Self::Stream>;
    /// Return the address being dialed.
    fn addr(&self) -> &Self::Addr;
}

impl<P, D> Dialer for P
    where P: ::std::ops::Deref<Target=D>,
          D: Dialer + 'static
{
    type Stream = D::Stream;
    type Addr = D::Addr;
    fn dial(&self) -> io::Result<Self::Stream> {
        (**self).dial()
    }
    fn addr(&self) -> &Self::Addr {
        (**self).addr()
    }
}

/// Iterates over incoming connections.
pub struct Incoming<'a, L: Listener + ?Sized + 'a> {
    listener: &'a L,
}

impl<'a, L: Listener> Iterator for Incoming<'a, L> {
    type Item = io::Result<L::Stream>;

    fn next(&mut self) -> Option<Self::Item> {
        Some(self.listener.accept())
    }
}

/// Provides a TCP transport.
pub mod tcp;
/// Provides a unix socket transport.
pub mod unix;
<commit_msg>Better documentation for Stream.<commit_after>use std::io::{self, Read, Write};
use std::time::Duration;

/// A factory for creating a listener on a given address.
pub trait Transport {
    /// The type of listener that binds to the given address.
    type Listener: Listener;
    /// Return a listener on the given address, and a dialer to that address.
    fn bind(&self) -> io::Result<Self::Listener>;
}

/// Accepts incoming connections from dialers.
pub trait Listener: Send + 'static {
    /// The type of address being listened on.
    type Dialer: Dialer;
    /// The type of stream this listener accepts.
    type Stream: Stream;
    /// Accept an incoming stream.
    fn accept(&self) -> io::Result<Self::Stream>;
    /// Returns the local address being listened on.
    fn dialer(&self) -> io::Result<Self::Dialer>;
    /// Iterate over incoming connections.
    fn incoming(&self) -> Incoming<Self> {
        Incoming {
            listener: self,
        }
    }
}

/// A cloneable Reader/Writer.
pub trait Stream: Read + Write + Send + Sized + 'static {
    /// Creates a new independently owned handle to the underlying socket.
    ///
    /// The returned TcpStream should reference the same stream that this
    /// object references. Both handles should read and write the same
    /// stream of data, and options set on one stream should be propagated
    /// to the other stream.
    fn try_clone(&self) -> io::Result<Self>;
    /// Sets a read timeout.
    ///
    /// If the value specified is `None`, then read calls will block indefinitely.
    /// It is an error to pass the zero `Duration` to this method.
    fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()>;
    /// Sets a write timeout.
    ///
    /// If the value specified is `None`, then write calls will block indefinitely.
    /// It is an error to pass the zero `Duration` to this method.
    fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()>;
    /// Shuts down both ends of the stream.
    ///
    /// Implementations should cause all pending and future I/O on the specified
    /// portions to return immediately with an appropriate value.
    fn shutdown(&self) -> io::Result<()>;
}

/// A `Stream` factory.
pub trait Dialer {
    /// The type of `Stream` this can create.
    type Stream: Stream;
    /// The type of address being connected to.
    type Addr;
    /// Open a stream.
    fn dial(&self) -> io::Result<Self::Stream>;
    /// Return the address being dialed.
    fn addr(&self) -> &Self::Addr;
}

impl<P, D> Dialer for P
    where P: ::std::ops::Deref<Target=D>,
          D: Dialer + 'static
{
    type Stream = D::Stream;
    type Addr = D::Addr;
    fn dial(&self) -> io::Result<Self::Stream> {
        (**self).dial()
    }
    fn addr(&self) -> &Self::Addr {
        (**self).addr()
    }
}

/// Iterates over incoming connections.
pub struct Incoming<'a, L: Listener + ?Sized + 'a> {
    listener: &'a L,
}

impl<'a, L: Listener> Iterator for Incoming<'a, L> {
    type Item = io::Result<L::Stream>;

    fn next(&mut self) -> Option<Self::Item> {
        Some(self.listener.accept())
    }
}

/// Provides a TCP transport.
pub mod tcp;
/// Provides a unix socket transport.
pub mod unix;
<|endoftext|>


<commit_before>extern crate piston;
extern crate graphics;
extern crate sdl2_window;
extern crate gfx_device_gl;
extern crate gfx_graphics;

use std::path::Path;
use std::rc::Rc;
use std::cell::RefCell;
use piston::quack::Get;
use gfx_graphics::gfx::traits::*;
use gfx_graphics::{
    Gfx2d,
    Texture,
    gfx
};
use sdl2_window::{ Sdl2Window, OpenGL };

fn main() {
    use graphics::draw_state::BlendPreset;

    println!("Press A to change blending");

    let window = Sdl2Window::new(
        OpenGL::_3_2,
        piston::window::WindowSettings {
            title: "gfx_graphics: draw_state_test".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let mut device = gfx_device_gl::GlDevice::new(Sdl2Window::get_proc_address);
    let piston::window::Size(size) = window.get();
    let frame = gfx::Frame::new(size[0] as u16, size[1] as u16);
    let mut renderer = device.create_renderer();

    let rust_logo = Texture::from_path(&mut device,
        &Path::new("./assets/rust.png")).unwrap();
    let mut g2d = Gfx2d::new(&mut device);
    let mut blend = BlendPreset::Alpha;
    let window = Rc::new(RefCell::new(window));
    for e in piston::events(window) {
        use piston::event::*;
        use piston::input::*;

        if let Some(_) = e.render_args() {
            use graphics::*;

            g2d.draw(&mut renderer, &frame, |c, g| {
                let transform = c.transform.trans(100.0, 100.0);

                clear([0.8, 0.8, 0.8, 1.0], g);
                Rectangle::new([1.0, 0.0, 0.0, 1.0])
                    .draw([0.0, 0.0, 100.0, 100.0],
                          &c.draw_state,
                          c.transform,
                          g);

                let draw_state = c.draw_state.blend(blend);
                Rectangle::new([0.5, 1.0, 0.0, 0.3])
                    .draw([50.0, 50.0, 100.0, 100.0],
                          &draw_state,
                          c.transform,
                          g);
                Image::new().draw(&rust_logo, &c.draw_state, transform, g);
            });

            device.submit(renderer.as_buffer());
            renderer.reset();
        }

        if let Some(Button::Keyboard(Key::A)) = e.press_args() {
            blend = match blend {
                BlendPreset::Alpha => BlendPreset::Additive,
                BlendPreset::Additive => BlendPreset::Multiplicative,
                BlendPreset::Multiplicative => BlendPreset::Alpha,
            };
            println!("Changed blending to {:?}", blend);
        }

        if let Some(_) = e.after_render_args() {
            device.after_frame();
        }
    }
}
<commit_msg>Update to latest draw_state<commit_after>extern crate piston;
extern crate graphics;
extern crate sdl2_window;
extern crate gfx_device_gl;
extern crate gfx_graphics;

use std::path::Path;
use std::rc::Rc;
use std::cell::RefCell;
use piston::quack::Get;
use gfx_graphics::gfx::traits::*;
use gfx_graphics::{
    Gfx2d,
    Texture,
    gfx
};
use sdl2_window::{ Sdl2Window, OpenGL };

fn main() {
    use graphics::draw_state::BlendPreset;

    println!("Press A to change blending");

    let window = Sdl2Window::new(
        OpenGL::_3_2,
        piston::window::WindowSettings {
            title: "gfx_graphics: draw_state_test".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let mut device = gfx_device_gl::GlDevice::new(Sdl2Window::get_proc_address);
    let piston::window::Size(size) = window.get();
    let frame = gfx::Frame::new(size[0] as u16, size[1] as u16);
    let mut renderer = device.create_renderer();

    let rust_logo = Texture::from_path(&mut device,
        &Path::new("./assets/rust.png")).unwrap();
    let mut g2d = Gfx2d::new(&mut device);
    let mut blend = BlendPreset::Alpha;
    let window = Rc::new(RefCell::new(window));
    for e in piston::events(window) {
        use piston::event::*;
        use piston::input::*;

        if let Some(_) = e.render_args() {
            use graphics::*;

            g2d.draw(&mut renderer, &frame, |c, g| {
                let transform = c.transform.trans(100.0, 100.0);

                clear([0.8, 0.8, 0.8, 1.0], g);
                Rectangle::new([1.0, 0.0, 0.0, 1.0])
                    .draw([0.0, 0.0, 100.0, 100.0],
                          &c.draw_state,
                          c.transform,
                          g);

                let draw_state = c.draw_state.blend(blend);
                Rectangle::new([0.5, 1.0, 0.0, 0.3])
                    .draw([50.0, 50.0, 100.0, 100.0],
                          &draw_state,
                          c.transform,
                          g);
                Image::new().draw(&rust_logo, &c.draw_state, transform, g);
            });

            device.submit(renderer.as_buffer());
            renderer.reset();
        }

        if let Some(Button::Keyboard(Key::A)) = e.press_args() {
            blend = match blend {
                BlendPreset::Alpha => BlendPreset::Add,
                BlendPreset::Add => BlendPreset::Multiply,
                BlendPreset::Multiply => BlendPreset::Invert,
                BlendPreset::Invert => BlendPreset::Alpha,
            };
            println!("Changed blending to {:?}", blend);
        }

        if let Some(_) = e.after_render_args() {
            device.after_frame();
        }
    }
}
<|endoftext|>


<commit_before>use crate::schema::*;
use diesel::prelude::*;

#[test]
fn selecting_basic_data() {
    let connection = &mut connection();
    connection
        .execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
        .unwrap();

    let expected_data = vec![
        ("Sean".to_string(), None::<String>),
        ("Tess".to_string(), None::<String>),
    ];

    let user_alias = alias!(users as user_alias);

    let actual_data = user_alias
        .select((
            user_alias.field(users::name),
            user_alias.field(users::hair_color),
        ))
        .load(connection)
        .unwrap();

    assert_eq!(expected_data, actual_data);
}

#[test]
fn select_multiple_from_join() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();

    connection
        .execute(
            "INSERT INTO posts (id, user_id, title) VALUES
        (1, 1, 'Hello'),
        (2, 2, 'World')
    ",
        )
        .unwrap();

    alias!(users as user_alias: UserAlias);
    let post_alias = alias!(posts as post_alias);

    // Having two different aliases in one query works
    post_alias
        .select(post_alias.fields((posts::id, posts::user_id, posts::title, posts::body)))
        .filter(
            post_alias.field(posts::user_id).eq_any(
                user_alias.select(user_alias.field(users::id)).filter(
                    user_alias
                        .field(users::id)
                        .eq_any(users::table.select(users::id)),
                ),
            ),
        )
        .load::<(i32, i32, String, Option<String>)>(connection)
        .unwrap();

    // using a subquery with an alias seems to work
    post_alias
        .select(
            posts::table
                .select(posts::id)
                .filter(post_alias.field(posts::id).eq(posts::id))
                .single_value(),
        )
        .load::<Option<i32>>(connection)
        .unwrap();

    // Joining with explicit on clause works
    post_alias
        .left_join(users::table)
        .inner_join(
            user_alias.on(post_alias
                .field(posts::user_id)
                .eq(user_alias.field(users::id))),
        )
        .select((
            post_alias.field(posts::id),
            users::id.nullable(),
            user_alias.field(users::id),
        ))
        .load::<(i32, Option<i32>, i32)>(connection)
        .unwrap();

    // having the alias on the right side seems to work
    // joining the table with an alias twice, also works
    posts::table
        .inner_join(user_alias)
        .inner_join(users::table)
        .select((user_alias.field(users::name), users::name))
        .load::<(String, String)>(connection)
        .unwrap();

    // Joining alias to alias works
    post_alias
        .inner_join(user_alias)
        .select((user_alias.field(users::name), post_alias.field(posts::id)))
        .load::<(String, i32)>(connection)
        .unwrap();

    // using mutiple aliases for the same table works if they are declared in the same alias call
    let (user1_alias, user2_alias, _post_alias) =
        alias!(users as user1, users as user2, posts as post1,);

    posts::table
        .inner_join(user1_alias)
        .inner_join(user2_alias)
        .select(posts::id)
        .load::<i32>(connection)
        .unwrap();

    // its also possible to do a self join, multiple times
    // (that should work as long as all aliases are declared in the same alias! call)
    users::table
        .inner_join(user1_alias.on(users::id.eq(user1_alias.field(users::id))))
        .inner_join(
            user2_alias.on(user2_alias
                .field(users::id)
                .eq(user1_alias.field(users::id))),
        )
        .select((
            users::id,
            user1_alias.field(users::id),
            user2_alias.field(users::id),
        ))
        .load::<(i32, i32, i32)>(connection)
        .unwrap();
}

#[test]
fn find_and_first() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();
    let alias = alias!(users as users_alias);
    assert_eq!(
        alias
            .find(1)
            .select(alias.field(users::name))
            .first::<String>(connection),
        Ok("Sean".into()),
    )
}
<commit_msg>add boxed test<commit_after>use crate::schema::*;
use diesel::prelude::*;

#[test]
fn selecting_basic_data() {
    let connection = &mut connection();
    connection
        .execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
        .unwrap();

    let expected_data = vec![
        ("Sean".to_string(), None::<String>),
        ("Tess".to_string(), None::<String>),
    ];

    let user_alias = alias!(users as user_alias);

    let actual_data = user_alias
        .select((
            user_alias.field(users::name),
            user_alias.field(users::hair_color),
        ))
        .load(connection)
        .unwrap();

    assert_eq!(expected_data, actual_data);
}

#[test]
fn select_multiple_from_join() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();

    connection
        .execute(
            "INSERT INTO posts (id, user_id, title) VALUES
        (1, 1, 'Hello'),
        (2, 2, 'World')
    ",
        )
        .unwrap();

    alias!(users as user_alias: UserAlias);
    let post_alias = alias!(posts as post_alias);

    // Having two different aliases in one query works
    post_alias
        .select(post_alias.fields((posts::id, posts::user_id, posts::title, posts::body)))
        .filter(
            post_alias.field(posts::user_id).eq_any(
                user_alias.select(user_alias.field(users::id)).filter(
                    user_alias
                        .field(users::id)
                        .eq_any(users::table.select(users::id)),
                ),
            ),
        )
        .load::<(i32, i32, String, Option<String>)>(connection)
        .unwrap();

    // using a subquery with an alias seems to work
    post_alias
        .select(
            posts::table
                .select(posts::id)
                .filter(post_alias.field(posts::id).eq(posts::id))
                .single_value(),
        )
        .load::<Option<i32>>(connection)
        .unwrap();

    // Joining with explicit on clause works
    post_alias
        .left_join(users::table)
        .inner_join(
            user_alias.on(post_alias
                .field(posts::user_id)
                .eq(user_alias.field(users::id))),
        )
        .select((
            post_alias.field(posts::id),
            users::id.nullable(),
            user_alias.field(users::id),
        ))
        .load::<(i32, Option<i32>, i32)>(connection)
        .unwrap();

    // having the alias on the right side seems to work
    // joining the table with an alias twice, also works
    posts::table
        .inner_join(user_alias)
        .inner_join(users::table)
        .select((user_alias.field(users::name), users::name))
        .load::<(String, String)>(connection)
        .unwrap();

    // Joining alias to alias works
    post_alias
        .inner_join(user_alias)
        .select((user_alias.field(users::name), post_alias.field(posts::id)))
        .load::<(String, i32)>(connection)
        .unwrap();

    // using mutiple aliases for the same table works if they are declared in the same alias call
    let (user1_alias, user2_alias, _post_alias) =
        alias!(users as user1, users as user2, posts as post1,);

    posts::table
        .inner_join(user1_alias)
        .inner_join(user2_alias)
        .select(posts::id)
        .load::<i32>(connection)
        .unwrap();

    // its also possible to do a self join, multiple times
    // (that should work as long as all aliases are declared in the same alias! call)
    users::table
        .inner_join(user1_alias.on(users::id.eq(user1_alias.field(users::id))))
        .inner_join(
            user2_alias.on(user2_alias
                .field(users::id)
                .eq(user1_alias.field(users::id))),
        )
        .select((
            users::id,
            user1_alias.field(users::id),
            user2_alias.field(users::id),
        ))
        .load::<(i32, i32, i32)>(connection)
        .unwrap();
}

#[test]
fn find_and_first() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();
    let alias = alias!(users as users_alias);
    assert_eq!(
        alias
            .find(1)
            .select(alias.field(users::name))
            .first::<String>(connection),
        Ok("Sean".into()),
    )
}

#[test]
fn boxed() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();

    let (user1_alias, user2_alias, _post_alias) =
        alias!(users as user1, users as user2, posts as post1,);

    let q = posts::table
        .inner_join(user1_alias)
        .inner_join(user2_alias)
        .into_boxed();

    let res = q
        .select((posts::user_id, user1_alias.fields((users::id, users::id))))
        .load::<(i32, (i32, i32))>(connection)
        .unwrap();
    assert!(res.into_iter().all(|(a, (b, c))| a == b && a == c));
}
<|endoftext|>


<commit_before>//! This will build the proc macro in `imp`, and copy the resulting dylib artifact into the
//! `OUT_DIR`.
//!
//! `proc-macro-test` itself contains only a path to that artifact.

use std::{
    env, fs,
    path::{Path, PathBuf},
    process::Command,
};

use cargo_metadata::Message;

fn main() {
    let out_dir = env::var_os("OUT_DIR").unwrap();
    let out_dir = Path::new(&out_dir);

    let name = "proc-macro-test-impl";
    let version = "0.0.0";
    let target_dir = out_dir.join("target");
    let output = Command::new(toolchain::cargo())
        .current_dir("imp")
        .args(&["build", "-p", "proc-macro-test-impl", "--message-format", "json"])
        // Explicit override the target directory to avoid using the same one which the parent
        // cargo is using, or we'll deadlock.
        // This can happen when `CARGO_TARGET_DIR` is set or global config forces all cargo
        // instance to use the same target directory.
        .arg("--target-dir")
        .arg(&target_dir)
        .output()
        .unwrap();
    assert!(output.status.success());

    let mut artifact_path = None;
    for message in Message::parse_stream(output.stdout.as_slice()) {
        match message.unwrap() {
            Message::CompilerArtifact(artifact) => {
                if artifact.target.kind.contains(&"proc-macro".to_string()) {
                    let repr = format!("{} {}", name, version);
                    if artifact.package_id.repr.starts_with(&repr) {
                        artifact_path = Some(PathBuf::from(&artifact.filenames[0]));
                    }
                }
            }
            _ => (), // Unknown message
        }
    }

    // This file is under `target_dir` and is already under `OUT_DIR`.
    let artifact_path = artifact_path.expect("no dylib for proc-macro-test-impl found");

    let info_path = out_dir.join("proc_macro_test_location.txt");
    fs::write(info_path, artifact_path.to_str().unwrap()).unwrap();
}
<commit_msg>Auto merge of #12831 - fasterthanlime:proc-macro-test-in-tmp-dir, r=fasterthanlime<commit_after>//! This will build the proc macro in `imp`, and copy the resulting dylib artifact into the
//! `OUT_DIR`.
//!
//! `proc-macro-test` itself contains only a path to that artifact.

use std::{
    env, fs,
    path::{Path, PathBuf},
    process::Command,
};

use cargo_metadata::Message;

fn main() {
    println!("cargo:rerun-if-changed=imp");

    let out_dir = env::var_os("OUT_DIR").unwrap();
    let out_dir = Path::new(&out_dir);

    let name = "proc-macro-test-impl";
    let version = "0.0.0";

    let imp_dir = std::env::current_dir().unwrap().join("imp");

    let staging_dir = out_dir.join("proc-macro-test-imp-staging");
    // this'll error out if the staging dir didn't previously exist. using
    // `std::fs::exists` would suffer from TOCTOU so just do our best to
    // wipe it and ignore errors.
    let _ = std::fs::remove_dir_all(&staging_dir);

    println!("Creating {}", staging_dir.display());
    std::fs::create_dir_all(&staging_dir).unwrap();

    let src_dir = staging_dir.join("src");
    println!("Creating {}", src_dir.display());
    std::fs::create_dir_all(src_dir).unwrap();

    for item_els in [&["Cargo.toml"][..], &["src", "lib.rs"]] {
        let mut src = imp_dir.clone();
        let mut dst = staging_dir.clone();
        for el in item_els {
            src.push(el);
            dst.push(el);
        }
        println!("Copying {} to {}", src.display(), dst.display());
        std::fs::copy(src, dst).unwrap();
    }

    let target_dir = out_dir.join("target");
    let output = Command::new(toolchain::cargo())
        .current_dir(&staging_dir)
        .args(&["build", "-p", "proc-macro-test-impl", "--message-format", "json"])
        // Explicit override the target directory to avoid using the same one which the parent
        // cargo is using, or we'll deadlock.
        // This can happen when `CARGO_TARGET_DIR` is set or global config forces all cargo
        // instance to use the same target directory.
        .arg("--target-dir")
        .arg(&target_dir)
        .output()
        .unwrap();
    if !output.status.success() {
        println!("proc-macro-test-impl failed to build");
        println!("============ stdout ============");
        println!("{}", String::from_utf8_lossy(&output.stdout));
        println!("============ stderr ============");
        println!("{}", String::from_utf8_lossy(&output.stderr));
        panic!("proc-macro-test-impl failed to build");
    }

    let mut artifact_path = None;
    for message in Message::parse_stream(output.stdout.as_slice()) {
        match message.unwrap() {
            Message::CompilerArtifact(artifact) => {
                if artifact.target.kind.contains(&"proc-macro".to_string()) {
                    let repr = format!("{} {}", name, version);
                    if artifact.package_id.repr.starts_with(&repr) {
                        artifact_path = Some(PathBuf::from(&artifact.filenames[0]));
                    }
                }
            }
            _ => (), // Unknown message
        }
    }

    // This file is under `target_dir` and is already under `OUT_DIR`.
    let artifact_path = artifact_path.expect("no dylib for proc-macro-test-impl found");

    let info_path = out_dir.join("proc_macro_test_location.txt");
    fs::write(info_path, artifact_path.to_str().unwrap()).unwrap();
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

#![recursion_limit = "512"]
mod caps;
mod cargo_target_spec;
mod conv;
mod main_loop;
mod markdown;
pub mod req;
pub mod config;
mod world;

pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
pub use crate::{
    caps::server_capabilities,
    config::ServerConfig,
    main_loop::LspError,
    main_loop::{main_loop, show_message},
};
<commit_msg>No need to make config pub<commit_after>//! FIXME: write short doc here

#![recursion_limit = "512"]
mod caps;
mod cargo_target_spec;
mod conv;
mod main_loop;
mod markdown;
pub mod req;
mod config;
mod world;

pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
pub use crate::{
    caps::server_capabilities,
    config::ServerConfig,
    main_loop::LspError,
    main_loop::{main_loop, show_message},
};
<|endoftext|>


<commit_before>extern crate piston_window;

use std::thread;
use std::sync::mpsc::{self, TryRecvError};

use piston_window::*;

enum Shape {
    Line {
        from: (f64, f64),
        to: (f64, f64),
        thickness: f64,
    },
}

enum Response {
    Ok,
}

fn main() {
    let (tx_drawing, rx_drawing) = mpsc::channel();
    let (tx_main, rx_main) = mpsc::channel();

    thread::spawn(move || {
        let mut window: PistonWindow = WindowSettings::new(
            "Hello Piston!", [800, 600]
        ).exit_on_esc(true).build().unwrap();
        let mut shapes = vec![];

        while let Some(e) = window.next() {
            match rx_drawing.try_recv() {
                Ok(shape) => {
                    shapes.push(shape);
                    tx_main.send(Response::Ok).unwrap();
                },
                Err(TryRecvError::Empty) => {}, // Do nothing
                Err(TryRecvError::Disconnected) => break, // Quit
            }

            window.draw_2d(&e, |c, g| {
                clear([1.0; 4], g);

                for shape in &shapes {
                    match shape {
                        &Shape::Line {from, to, thickness} => {
                            line([0., 0., 0., 255.], thickness,
                                [from.0, from.1, to.0, to.1], c.transform, g);
                        },
                    }
                }
            });
        }
    });

    //TODO: Instead of unwrapping, we should quit since this means that the drawing
    //TODO: window has been closed (possibly due to an error on that thread)
    let draw = |shape: Shape| {
        tx_drawing.send(shape).unwrap();
        rx_main.recv().unwrap();
    };

    let center = (200., 200.);
    let radius = 100.;
    let thickness = 1.;
    let mut prev = (center.0 + radius, center.0);
    for i in 0..361 {
        let x = center.0 + radius * (i as f64).to_radians().cos();
        let y = center.1 + radius * (i as f64).to_radians().sin();
        draw(Shape::Line {
            from: (prev.0, prev.1),
            to: (x, y),
            thickness,
        });
        prev = (x, y);
    }
    draw(Shape::Line {
        from: (550., 150.),
        to: (350., 500.),
        thickness,
    });
    //handle.join().unwrap();
}
<commit_msg>Re-architected prototype to use a simple looking Canvas struct which automatically leaves the window open until it is closed by the user<commit_after>extern crate piston_window;

use canvas::{Canvas, Shape};

fn main() {
    let canvas = Canvas::new();

    let center = (200., 200.);
    let radius = 100.;
    let thickness = 1.;
    let mut prev = (center.0 + radius, center.0);
    for i in 0..361 {
        let x = center.0 + radius * (i as f64).to_radians().cos();
        let y = center.1 + radius * (i as f64).to_radians().sin();
        canvas.draw(Shape::Line {
            from: (prev.0, prev.1),
            to: (x, y),
            thickness,
        });
        prev = (x, y);
    }
    canvas.draw(Shape::Line {
        from: (550., 150.),
        to: (350., 500.),
        thickness,
    });
}

mod canvas {
    use std::thread;
    use std::process;
    use std::sync::mpsc::{self, TryRecvError};

    use piston_window::*;

    pub enum Shape {
        Line {
            from: (f64, f64),
            to: (f64, f64),
            thickness: f64,
        },
    }

    pub type Response = Result<(), ()>;

    pub struct Canvas {
        thread_handle: Option<thread::JoinHandle<()>>,
        transmitter: mpsc::Sender<Shape>,
        receiver: mpsc::Receiver<Response>,
    }

    impl Canvas {
        pub fn new() -> Canvas {
            let (tx_drawing, rx_drawing) = mpsc::channel();
            let (tx_main, rx_main) = mpsc::channel();

            let handle = thread::spawn(move || {
                let mut window: PistonWindow = WindowSettings::new(
                    "Turtle IDE", [800, 600]
                ).exit_on_esc(true).build().unwrap();
                let mut shapes = vec![];

                while let Some(e) = window.next() {
                    match rx_drawing.try_recv() {
                        Ok(shape) => {
                            shapes.push(shape);
                            tx_main.send(Ok(())).unwrap();
                        },
                        Err(TryRecvError::Empty) => {}, // Do nothing
                        Err(TryRecvError::Disconnected) => break, // Quit
                    }

                    window.draw_2d(&e, |c, g| {
                        clear([1.0; 4], g);

                        for shape in &shapes {
                            match shape {
                                &Shape::Line {from, to, thickness} => {
                                    line([0., 0., 0., 255.], thickness,
                                        [from.0, from.1, to.0, to.1], c.transform, g);
                                },
                            }
                        }
                    });
                }
            });

            Canvas {
                thread_handle: Some(handle),
                transmitter: tx_drawing,
                receiver: rx_main,
            }
        }

        pub fn draw(&self, shape: Shape) {
            let result = self.transmitter.send(shape).map_err(|_| ());
            let result = result.and_then(|_| {
                // Wait for the drawing animation to complete
                self.receiver.recv().map_err(|_| ())
            });
            match result {
                Ok(_) => {},
                Err(_) => {
                    // The connection has been closed so the window was closed
                    // or an error occurred on that thread
                    process::exit(0);
                },
            }
        }
    }

    impl Drop for Canvas {
        fn drop(&mut self) {
            if let Some(handle) = self.thread_handle.take() {
                handle.join().unwrap();
            }
        }
    }
}
<|endoftext|>