<commit_before>use crate::context::ContextError;
use std::any::TypeId;
use std::backtrace::{Backtrace, BacktraceStatus};
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` functions a lot like `Box<dyn std::error::Error>`, with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`
/// - `Error` guarantees that a backtrace will exist, even if the error type
///   did not provide one
/// - `Error` is represented as a narrow pointer - exactly one word in size,
///   instead of two.
pub struct Error {
    inner: Box<ErrorImpl<()>>,
}

impl Error {
    /// Create a new error object from any error type.
    ///
    /// The error type must be threadsafe and `'static`, so that the `Error`
    /// will be as well.
    ///
    /// If the error type does not provide a backtrace, a backtrace will be
    /// created here to ensure that a backtrace exists.
    pub fn new<E>(error: E) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        Error::construct(error, TypeId::of::<E>())
    }

    #[doc(hidden)]
    pub fn new_adhoc<M>(message: M) -> Self
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::construct(MessageError(message), TypeId::of::<M>())
    }

    fn construct<E>(error: E, type_id: TypeId) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        let backtrace = match error.backtrace() {
            Some(_) => None,
            None => Some(Backtrace::capture()),
        };

        unsafe {
            let obj = mem::transmute::<&dyn StdError, TraitObject>(&error);
            let vtable = obj.vtable;
            let inner = Box::new(ErrorImpl {
                vtable,
                type_id,
                backtrace,
                error,
            });
            Error {
                inner: mem::transmute::<Box<ErrorImpl<E>>, Box<ErrorImpl<()>>>(inner),
            }
        }
    }

    /// Wrap the error value with additional context.
    pub fn context<C>(self, context: C) -> Self
    where
        C: Display + Send + Sync + 'static,
    {
        Error::from(ContextError {
            error: self,
            context,
        })
    }

    /// View this error object as the underlying error.
    pub fn as_dyn_error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        &**self
    }

    /// View this error object as the underlying error, mutably.
    pub fn as_dyn_error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        &mut **self
    }

    /// Get the backtrace for this Error.
    pub fn backtrace(&self) -> &Backtrace {
        // NB: this unwrap can only fail if the underlying error's backtrace
        // method is nondeterministic, which would only happen in maliciously
        // constructed code
        self.inner
            .backtrace
            .as_ref()
            .or_else(|| self.inner.error().backtrace())
            .expect("backtrace capture failed")
    }

    /// An iterator of the chain of source errors contained by this Error.
    ///
    /// This iterator will visit every error in the cause chain of this error
    /// object, beginning with the error that this error object was created
    /// from.
    pub fn chain(&self) -> Chain {
        Chain {
            next: Some(self.inner.error()),
        }
    }

    /// Returns `true` if `E` is the type wrapped by this error object.
    pub fn is<E>(&self) -> bool
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        TypeId::of::<E>() == self.inner.type_id
    }

    /// Attempt to downcast the error object to a concrete type.
    pub fn downcast<E>(self) -> Result<E, Self>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if let Some(error) = self.downcast_ref::<E>() {
            unsafe {
                let error = ptr::read(error);
                drop(ptr::read(&self.inner));
                mem::forget(self);
                Ok(error)
            }
        } else {
            Err(self)
        }
    }

    /// Downcast this error object by reference.
    pub fn downcast_ref<E>(&self) -> Option<&E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&*(self.inner.error() as *const dyn StdError as *const E)) }
        } else {
            None
        }
    }

    /// Downcast this error object by mutable reference.
    pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&mut *(self.inner.error_mut() as *mut dyn StdError as *mut E)) }
        } else {
            None
        }
    }
}

impl<E> From<E> for Error
where
    E: StdError + Send + Sync + 'static,
{
    fn from(error: E) -> Self {
        Error::new(error)
    }
}

impl Deref for Error {
    type Target = dyn StdError + Send + Sync + 'static;
    fn deref(&self) -> &Self::Target {
        self.inner.error()
    }
}

impl DerefMut for Error {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner.error_mut()
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.inner.error())?;

        let mut errors = self.chain().skip(1).enumerate();

        if let Some((n, error)) = errors.next() {
            writeln!(f, "\ncaused by:")?;
            writeln!(f, "\t{}: {}", n, error)?;
            for (n, error) in errors {
                writeln!(f, "\t{}: {}", n, error)?;
            }
        }

        let backtrace = self.backtrace();

        match backtrace.status() {
            BacktraceStatus::Captured => {
                writeln!(f, "\n{}", backtrace)?;
            }
            BacktraceStatus::Disabled => {
                writeln!(
                    f,
                    "\nbacktrace disabled; run with RUST_LIB_BACKTRACE=1 environment variable to display a backtrace"
                )?;
            }
            _ => {}
        }

        Ok(())
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.inner.error())
    }
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ptr::drop_in_place(self.inner.error_mut()) }
    }
}

// repr C to ensure that `E` remains in the final position
#[repr(C)]
struct ErrorImpl<E> {
    vtable: *const (),
    type_id: TypeId,
    backtrace: Option<Backtrace>,
    error: E,
}

// repr C to ensure that transmuting from trait objects is safe
#[repr(C)]
struct TraitObject {
    data: *const (),
    vtable: *const (),
}

#[repr(transparent)]
struct MessageError<M>(M);

impl<M> Debug for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl<M> Display for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}

impl ErrorImpl<()> {
    fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &self.error,
            vtable: self.vtable,
        };

        unsafe { mem::transmute::<TraitObject, &(dyn StdError + Send + Sync + 'static)>(object) }
    }

    fn error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &mut self.error,
            vtable: self.vtable,
        };

        unsafe {
            mem::transmute::<TraitObject, &mut (dyn StdError + Send + Sync + 'static)>(object)
        }
    }
}

/// Iterator of a chain of source errors.
pub struct Chain<'a> {
    next: Option<&'a (dyn StdError + 'static)>,
}

impl<'a> Iterator for Chain<'a> {
    type Item = &'a (dyn StdError + 'static);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.next.take()?;
        self.next = next.source();
        Some(next)
    }
}

#[cfg(test)]
mod repr_correctness {
    use super::*;
    use std::marker::Unpin;
    use std::mem;
    use std::sync::{Arc, Mutex};

    #[test]
    fn size_of_error() {
        assert_eq!(mem::size_of::<Error>(), mem::size_of::<usize>());
    }

    #[test]
    fn error_autotraits() {
        fn assert<E: Unpin + Send + Sync + 'static>() {}
        assert::<Error>();
    }

    #[test]
    fn destructors_work() {
        #[derive(Debug)]
        struct HasDrop(Box<Arc<Mutex<bool>>>);
        impl StdError for HasDrop {}
        impl Display for HasDrop {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "does something")
            }
        }
        impl Drop for HasDrop {
            fn drop(&mut self) {
                let mut has_dropped = self.0.lock().unwrap();
                assert!(!*has_dropped);
                *has_dropped = true;
            }
        }

        let has_dropped = Arc::new(Mutex::new(false));

        drop(Error::from(HasDrop(Box::new(has_dropped.clone()))));

        assert!(*has_dropped.lock().unwrap());
    }
}
<commit_msg>Replace Mutex<bool> with AtomicBool<commit_after>use crate::context::ContextError;
use std::any::TypeId;
use std::backtrace::{Backtrace, BacktraceStatus};
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` functions a lot like `Box<dyn std::error::Error>`, with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`
/// - `Error` guarantees that a backtrace will exist, even if the error type
///   did not provide one
/// - `Error` is represented as a narrow pointer - exactly one word in size,
///   instead of two.
pub struct Error {
    inner: Box<ErrorImpl<()>>,
}

impl Error {
    /// Create a new error object from any error type.
    ///
    /// The error type must be threadsafe and `'static`, so that the `Error`
    /// will be as well.
    ///
    /// If the error type does not provide a backtrace, a backtrace will be
    /// created here to ensure that a backtrace exists.
    pub fn new<E>(error: E) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        Error::construct(error, TypeId::of::<E>())
    }

    #[doc(hidden)]
    pub fn new_adhoc<M>(message: M) -> Self
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::construct(MessageError(message), TypeId::of::<M>())
    }

    fn construct<E>(error: E, type_id: TypeId) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        let backtrace = match error.backtrace() {
            Some(_) => None,
            None => Some(Backtrace::capture()),
        };

        unsafe {
            let obj = mem::transmute::<&dyn StdError, TraitObject>(&error);
            let vtable = obj.vtable;
            let inner = Box::new(ErrorImpl {
                vtable,
                type_id,
                backtrace,
                error,
            });
            Error {
                inner: mem::transmute::<Box<ErrorImpl<E>>, Box<ErrorImpl<()>>>(inner),
            }
        }
    }

    /// Wrap the error value with additional context.
    pub fn context<C>(self, context: C) -> Self
    where
        C: Display + Send + Sync + 'static,
    {
        Error::from(ContextError {
            error: self,
            context,
        })
    }

    /// View this error object as the underlying error.
    pub fn as_dyn_error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        &**self
    }

    /// View this error object as the underlying error, mutably.
    pub fn as_dyn_error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        &mut **self
    }

    /// Get the backtrace for this Error.
    pub fn backtrace(&self) -> &Backtrace {
        // NB: this unwrap can only fail if the underlying error's backtrace
        // method is nondeterministic, which would only happen in maliciously
        // constructed code
        self.inner
            .backtrace
            .as_ref()
            .or_else(|| self.inner.error().backtrace())
            .expect("backtrace capture failed")
    }

    /// An iterator of the chain of source errors contained by this Error.
    ///
    /// This iterator will visit every error in the cause chain of this error
    /// object, beginning with the error that this error object was created
    /// from.
    pub fn chain(&self) -> Chain {
        Chain {
            next: Some(self.inner.error()),
        }
    }

    /// Returns `true` if `E` is the type wrapped by this error object.
    pub fn is<E>(&self) -> bool
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        TypeId::of::<E>() == self.inner.type_id
    }

    /// Attempt to downcast the error object to a concrete type.
    pub fn downcast<E>(self) -> Result<E, Self>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if let Some(error) = self.downcast_ref::<E>() {
            unsafe {
                let error = ptr::read(error);
                drop(ptr::read(&self.inner));
                mem::forget(self);
                Ok(error)
            }
        } else {
            Err(self)
        }
    }

    /// Downcast this error object by reference.
    pub fn downcast_ref<E>(&self) -> Option<&E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&*(self.inner.error() as *const dyn StdError as *const E)) }
        } else {
            None
        }
    }

    /// Downcast this error object by mutable reference.
    pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&mut *(self.inner.error_mut() as *mut dyn StdError as *mut E)) }
        } else {
            None
        }
    }
}

impl<E> From<E> for Error
where
    E: StdError + Send + Sync + 'static,
{
    fn from(error: E) -> Self {
        Error::new(error)
    }
}

impl Deref for Error {
    type Target = dyn StdError + Send + Sync + 'static;
    fn deref(&self) -> &Self::Target {
        self.inner.error()
    }
}

impl DerefMut for Error {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner.error_mut()
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.inner.error())?;

        let mut errors = self.chain().skip(1).enumerate();

        if let Some((n, error)) = errors.next() {
            writeln!(f, "\ncaused by:")?;
            writeln!(f, "\t{}: {}", n, error)?;
            for (n, error) in errors {
                writeln!(f, "\t{}: {}", n, error)?;
            }
        }

        let backtrace = self.backtrace();

        match backtrace.status() {
            BacktraceStatus::Captured => {
                writeln!(f, "\n{}", backtrace)?;
            }
            BacktraceStatus::Disabled => {
                writeln!(
                    f,
                    "\nbacktrace disabled; run with RUST_LIB_BACKTRACE=1 environment variable to display a backtrace"
                )?;
            }
            _ => {}
        }

        Ok(())
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.inner.error())
    }
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ptr::drop_in_place(self.inner.error_mut()) }
    }
}

// repr C to ensure that `E` remains in the final position
#[repr(C)]
struct ErrorImpl<E> {
    vtable: *const (),
    type_id: TypeId,
    backtrace: Option<Backtrace>,
    error: E,
}

// repr C to ensure that transmuting from trait objects is safe
#[repr(C)]
struct TraitObject {
    data: *const (),
    vtable: *const (),
}

#[repr(transparent)]
struct MessageError<M>(M);

impl<M> Debug for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl<M> Display for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}

impl ErrorImpl<()> {
    fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &self.error,
            vtable: self.vtable,
        };

        unsafe { mem::transmute::<TraitObject, &(dyn StdError + Send + Sync + 'static)>(object) }
    }

    fn error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &mut self.error,
            vtable: self.vtable,
        };

        unsafe {
            mem::transmute::<TraitObject, &mut (dyn StdError + Send + Sync + 'static)>(object)
        }
    }
}

/// Iterator of a chain of source errors.
pub struct Chain<'a> {
    next: Option<&'a (dyn StdError + 'static)>,
}

impl<'a> Iterator for Chain<'a> {
    type Item = &'a (dyn StdError + 'static);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.next.take()?;
        self.next = next.source();
        Some(next)
    }
}

#[cfg(test)]
mod repr_correctness {
    use super::*;
    use std::marker::Unpin;
    use std::mem;
    use std::sync::atomic::AtomicBool;
    use std::sync::atomic::Ordering::SeqCst;
    use std::sync::Arc;

    #[test]
    fn size_of_error() {
        assert_eq!(mem::size_of::<Error>(), mem::size_of::<usize>());
    }

    #[test]
    fn error_autotraits() {
        fn assert<E: Unpin + Send + Sync + 'static>() {}
        assert::<Error>();
    }

    #[test]
    fn destructors_work() {
        #[derive(Debug)]
        struct HasDrop(Arc<AtomicBool>);
        impl StdError for HasDrop {}
        impl Display for HasDrop {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "does something")
            }
        }
        impl Drop for HasDrop {
            fn drop(&mut self) {
                let has_dropped = self.0.swap(true, SeqCst);
                assert!(!has_dropped);
            }
        }

        let has_dropped = Arc::new(AtomicBool::new(false));

        drop(Error::from(HasDrop(has_dropped.clone())));

        assert!(has_dropped.load(SeqCst));
    }
}
<|endoftext|>


<commit_before>use std;
use std::fmt::{self, Debug, Display};
use std::iter::FromIterator;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;

#[cfg(feature = "parsing")]
use crate::buffer::Cursor;
use crate::thread::ThreadBound;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// # Error reporting in proc macros
///
/// The correct way to report errors back to the compiler from a procedural
/// macro is by emitting an appropriately spanned invocation of
/// [`compile_error!`] in the generated code. This produces a better diagnostic
/// message than simply panicking the macro.
///
/// When parsing macro input, the [`parse_macro_input!`] macro handles the
/// conversion to `compile_error!` automatically.
///
/// ```
/// extern crate proc_macro;
///
/// use proc_macro::TokenStream;
/// use syn::{parse_macro_input, AttributeArgs, ItemFn};
///
/// # const IGNORE: &str = stringify! {
/// #[proc_macro_attribute]
/// # };
/// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream {
///     let args = parse_macro_input!(args as AttributeArgs);
///     let input = parse_macro_input!(input as ItemFn);
///
///     /* ... */
///     # TokenStream::new()
/// }
/// ```
///
/// For errors that arise later than the initial parsing stage, the
/// [`.to_compile_error()`] method can be used to perform an explicit conversion
/// to `compile_error!`.
///
/// [`.to_compile_error()`]: Error::to_compile_error
///
/// ```
/// # extern crate proc_macro;
/// #
/// # use proc_macro::TokenStream;
/// # use syn::{parse_macro_input, DeriveInput};
/// #
/// # const IGNORE: &str = stringify! {
/// #[proc_macro_derive(MyDerive)]
/// # };
/// pub fn my_derive(input: TokenStream) -> TokenStream {
///     let input = parse_macro_input!(input as DeriveInput);
///
///     // fn(DeriveInput) -> syn::Result<proc_macro2::TokenStream>
///     expand::my_derive(input)
///         .unwrap_or_else(|err| err.to_compile_error())
///         .into()
/// }
/// #
/// # mod expand {
/// #     use proc_macro2::TokenStream;
/// #     use syn::{DeriveInput, Result};
/// #
/// #     pub fn my_derive(input: DeriveInput) -> Result<TokenStream> {
/// #         unimplemented!()
/// #     }
/// # }
/// ```
pub struct Error {
    // Span is implemented as an index into a thread-local interner to keep the
    // size small. It is not safe to access from a different thread. We want
    // errors to be Send and Sync to play nicely with the Failure crate, so pin
    // the span we're given to its original thread and assume it is
    // Span::call_site if accessed from any other thread.
    start_span: ThreadBound<Span>,
    end_span: ThreadBound<Span>,
    message: String,
}

#[cfg(test)]
struct _Test
where
    Error: Send + Sync;

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: crate::parse::ParseBuffer::error
    ///
    /// # Example
    ///
    /// ```
    /// use syn::{Error, Ident, LitStr, Result, Token};
    /// use syn::parse::ParseStream;
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            start_span: ThreadBound::new(span),
            end_span: ThreadBound::new(span),
            message: message.to_string(),
        }
    }

    /// Creates an error with the specified message spanning the given syntax
    /// tree node.
    ///
    /// Unlike the `Error::new` constructor, this constructor takes an argument
    /// `tokens` which is a syntax tree node. This allows the resulting `Error`
    /// to attempt to span all tokens inside of `tokens`. While you would
    /// typically be able to use the `Spanned` trait with the above `Error::new`
    /// constructor, implementation limitations today mean that
    /// `Error::new_spanned` may provide a higher-quality error message on
    /// stable Rust.
    ///
    /// When in doubt it's recommended to stick to `Error::new` (or
    /// `ParseStream::error`)!
    #[cfg(feature = "printing")]
    pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
        let mut iter = tokens.into_token_stream().into_iter();
        let start = iter.next().map_or_else(Span::call_site, |t| t.span());
        let end = iter.last().map_or(start, |t| t.span());
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: message.to_string(),
        }
    }

    /// The source location of the error.
    ///
    /// Spans are not thread-safe so this function returns `Span::call_site()`
    /// if called from a different thread than the one on which the `Error` was
    /// originally created.
    pub fn span(&self) -> Span {
        let start = match self.start_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };
        let end = match self.end_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };
        start.join(end).unwrap_or(start)
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    pub fn to_compile_error(&self) -> TokenStream {
        let start = self
            .start_span
            .get()
            .cloned()
            .unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);

        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", start)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(start);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(end);
                        string
                    })])
                });
                group.set_span(end);
                group
            }),
        ])
    }
}

#[cfg(feature = "parsing")]
pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        let span = crate::buffer::open_span_of_group(cursor);
        Error::new(span, message)
    }
}

impl Debug for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_tuple("Error").field(&self.message).finish()
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.message)
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        let start = self
            .start_span
            .get()
            .cloned()
            .unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: self.message.clone(),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}
<commit_msg>Allow combining multiple errors into one<commit_after>use std;
use std::fmt::{self, Debug, Display};
use std::iter::FromIterator;
use std::slice;
use std::vec;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;

#[cfg(feature = "parsing")]
use crate::buffer::Cursor;
use crate::thread::ThreadBound;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// # Error reporting in proc macros
///
/// The correct way to report errors back to the compiler from a procedural
/// macro is by emitting an appropriately spanned invocation of
/// [`compile_error!`] in the generated code. This produces a better diagnostic
/// message than simply panicking the macro.
///
/// When parsing macro input, the [`parse_macro_input!`] macro handles the
/// conversion to `compile_error!` automatically.
///
/// ```
/// extern crate proc_macro;
///
/// use proc_macro::TokenStream;
/// use syn::{parse_macro_input, AttributeArgs, ItemFn};
///
/// # const IGNORE: &str = stringify! {
/// #[proc_macro_attribute]
/// # };
/// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream {
///     let args = parse_macro_input!(args as AttributeArgs);
///     let input = parse_macro_input!(input as ItemFn);
///
///     /* ... */
///     # TokenStream::new()
/// }
/// ```
///
/// For errors that arise later than the initial parsing stage, the
/// [`.to_compile_error()`] method can be used to perform an explicit conversion
/// to `compile_error!`.
///
/// [`.to_compile_error()`]: Error::to_compile_error
///
/// ```
/// # extern crate proc_macro;
/// #
/// # use proc_macro::TokenStream;
/// # use syn::{parse_macro_input, DeriveInput};
/// #
/// # const IGNORE: &str = stringify! {
/// #[proc_macro_derive(MyDerive)]
/// # };
/// pub fn my_derive(input: TokenStream) -> TokenStream {
///     let input = parse_macro_input!(input as DeriveInput);
///
///     // fn(DeriveInput) -> syn::Result<proc_macro2::TokenStream>
///     expand::my_derive(input)
///         .unwrap_or_else(|err| err.to_compile_error())
///         .into()
/// }
/// #
/// # mod expand {
/// #     use proc_macro2::TokenStream;
/// #     use syn::{DeriveInput, Result};
/// #
/// #     pub fn my_derive(input: DeriveInput) -> Result<TokenStream> {
/// #         unimplemented!()
/// #     }
/// # }
/// ```
#[derive(Clone)]
pub struct Error {
    messages: Vec<ErrorMessage>,
}

struct ErrorMessage {
    // Span is implemented as an index into a thread-local interner to keep the
    // size small. It is not safe to access from a different thread. We want
    // errors to be Send and Sync to play nicely with the Failure crate, so pin
    // the span we're given to its original thread and assume it is
    // Span::call_site if accessed from any other thread.
    start_span: ThreadBound<Span>,
    end_span: ThreadBound<Span>,
    message: String,
}

#[cfg(test)]
struct _Test
where
    Error: Send + Sync;

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: crate::parse::ParseBuffer::error
    ///
    /// # Example
    ///
    /// ```
    /// use syn::{Error, Ident, LitStr, Result, Token};
    /// use syn::parse::ParseStream;
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            messages: vec![ErrorMessage {
                start_span: ThreadBound::new(span),
                end_span: ThreadBound::new(span),
                message: message.to_string(),
            }],
        }
    }

    /// Creates an error with the specified message spanning the given syntax
    /// tree node.
    ///
    /// Unlike the `Error::new` constructor, this constructor takes an argument
    /// `tokens` which is a syntax tree node. This allows the resulting `Error`
    /// to attempt to span all tokens inside of `tokens`. While you would
    /// typically be able to use the `Spanned` trait with the above `Error::new`
    /// constructor, implementation limitations today mean that
    /// `Error::new_spanned` may provide a higher-quality error message on
    /// stable Rust.
    ///
    /// When in doubt it's recommended to stick to `Error::new` (or
    /// `ParseStream::error`)!
    #[cfg(feature = "printing")]
    pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
        let mut iter = tokens.into_token_stream().into_iter();
        let start = iter.next().map_or_else(Span::call_site, |t| t.span());
        let end = iter.last().map_or(start, |t| t.span());
        Error {
            messages: vec![ErrorMessage {
                start_span: ThreadBound::new(start),
                end_span: ThreadBound::new(end),
                message: message.to_string(),
            }],
        }
    }

    /// The source location of the error.
    ///
    /// Spans are not thread-safe so this function returns `Span::call_site()`
    /// if called from a different thread than the one on which the `Error` was
    /// originally created.
    pub fn span(&self) -> Span {
        let start = match self.messages[0].start_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };
        let end = match self.messages[0].end_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };
        start.join(end).unwrap_or(start)
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    pub fn to_compile_error(&self) -> TokenStream {
        self.messages
            .iter()
            .map(ErrorMessage::to_compile_error)
            .collect()
    }

    /// Add another error message to self such that when `to_compile_error()` is
    /// called, both errors will be emitted together.
    pub fn combine(&mut self, another: Error) {
        self.messages.extend(another.messages)
    }
}

impl ErrorMessage {
    fn to_compile_error(&self) -> TokenStream {
        let start = self
            .start_span
            .get()
            .cloned()
            .unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);

        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", start)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(start);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(end);
                        string
                    })])
                });
                group.set_span(end);
                group
            }),
        ])
    }
}

#[cfg(feature = "parsing")]
pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        let span = crate::buffer::open_span_of_group(cursor);
        Error::new(span, message)
    }
}

impl Debug for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        if self.messages.len() == 1 {
            formatter
                .debug_tuple("Error")
                .field(&self.messages[0])
                .finish()
        } else {
            formatter
                .debug_tuple("Error")
                .field(&self.messages)
                .finish()
        }
    }
}

impl Debug for ErrorMessage {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.message, formatter)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.messages[0].message)
    }
}

impl Clone for ErrorMessage {
    fn clone(&self) -> Self {
        let start = self
            .start_span
            .get()
            .cloned()
            .unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
        ErrorMessage {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: self.message.clone(),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}

impl IntoIterator for Error {
    type Item = Error;
    type IntoIter = IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter {
            messages: self.messages.into_iter(),
        }
    }
}

pub struct IntoIter {
    messages: vec::IntoIter<ErrorMessage>,
}

impl Iterator for IntoIter {
    type Item = Error;

    fn next(&mut self) -> Option<Self::Item> {
        Some(Error {
            messages: vec![self.messages.next()?],
        })
    }
}

impl<'a> IntoIterator for &'a Error {
    type Item = Error;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        Iter {
            messages: self.messages.iter(),
        }
    }
}

pub struct Iter<'a> {
    messages: slice::Iter<'a, ErrorMessage>,
}

impl<'a> Iterator for Iter<'a> {
    type Item = Error;

    fn next(&mut self) -> Option<Self::Item> {
        Some(Error {
            messages: vec![self.messages.next()?.clone()],
        })
    }
}
<|endoftext|>


<commit_before>use rustc::lint::Context;
use rustc::middle::const_eval::lookup_const_by_id;
use syntax::ast::*;
use syntax::ptr::P;

/// a Lit_-like enum to fold constant `Expr`s into
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum Constant {
    ConstantStr(&'static str, StrStyle),
    ConstantBinary(Rc<Vec<u8>>),
    ConstantByte(u8),
    ConstantChar(char),
    ConstantInt(u64, LitIntType),
    ConstantFloat(Cow<'static, str>, FloatTy),
    ConstantFloatUnsuffixed(Cow<'static, str>),
    ConstantBool(bool),
    ConstantVec(Vec<Constant>),
    ConstantTuple(Vec<Constant>),
}

/// simple constant folding
pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> {
    match e {
        &ExprParen(ref inner) => constant(cx, inner),
        &ExprPath(_, _) => fetch_path(cx, e),
        &ExprBlock(ref block) => constant_block(cx, inner),
        &ExprIf(ref cond, ref then, ref otherwise) =>
            match constant(cx, cond) {
                Some(ConstantBool(true)) => constant(cx, then),
                Some(ConstantBool(false)) => constant(cx, otherwise),
                _ => None,
            },
        &ExprLit(ref lit) => Some(lit_to_constant(lit)),
        &ExprVec(ref vec) => constant_vec(cx, vec),
        &ExprTup(ref tup) => constant_tup(cx, tup),
        &ExprUnary(op, ref operand) => constant(cx, operand).and_then(
            |o| match op {
                UnNot =>
                    if let ConstantBool(b) = o {
                        Some(ConstantBool(!b))
                    } else { None },
                UnNeg =>
                    match o {
                        &ConstantInt(value, ty) =>
                            Some(ConstantInt(value, match ty {
                                SignedIntLit(ity, sign) =>
                                    SignedIntLit(ity, neg_sign(sign)),
                                UnsuffixedIntLit(sign) =>
                                    UnsuffixedIntLit(neg_sign(sign)),
                                _ => { return None; },
                            })),
                        &LitFloat(ref is, ref ty) =>
                            Some(ConstantFloat(neg_float_str(is), ty)),
                        &LitFloatUnsuffixed(ref is) =>
                            Some(ConstantFloatUnsuffixed(neg_float_str(is))),
                        _ => None,
                    },
                UnUniq | UnDeref => o,
            }),
        //TODO: add other expressions
        _ => None,
    }
}

fn lit_to_constant(lit: &Lit_) -> Constant {
    match lit {
        &LitStr(ref is, style) => ConstantStr(&*is, style),
        &LitBinary(ref blob) => ConstantBinary(blob.clone()),
        &LitByte(b) => ConstantByte(b),
        &LitChar(c) => ConstantChar(c),
        &LitInt(value, ty) => ConstantInt(value, ty),
        &LitFloat(ref is, ty) => ConstantFloat(Cow::Borrowed(&*is), ty),
        &LitFloatUnsuffixed(InternedString) =>
            ConstantFloatUnsuffixed(Cow::Borrowed(&*is)),
        &LitBool(b) => ConstantBool(b),
    }
}

/// create `Some(ConstantVec(..))` of all constants, unless there is any
/// non-constant part
fn constant_vec(cx: &Context, vec: &[&Expr]) -> Option<Constant> {
    Vec<Constant> parts = Vec::new();
    for opt_part in vec {
        match constant(cx, opt_part) {
            Some(ref p) => parts.push(p),
            None => { return None; },
        }
    }
    Some(ConstantVec(parts))
}

fn constant_tup(cx, &Context, tup: &[&Expr]) -> Option<Constant> {
    Vec<Constant> parts = Vec::new();
    for opt_part in vec {
        match constant(cx, opt_part) {
            Some(ref p) => parts.push(p),
            None => { return None; },
        }
    }
    Some(ConstantTuple(parts))
}

/// lookup a possibly constant expression from a ExprPath
fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> {
    if let Some(&PathResolution { base_def: DefConst(id), ..}) =
            cx.tcx.def_map.borrow().get(&e.id) {
        lookup_const_by_id(cx.tcx, id, None).map(|l| constant(cx, l))
    } else { None }
}

/// A block can only yield a constant if it only has one constant expression
fn constant_block(cx: &Context, block: &Block) -> Option<Constant> {
    if block.stmts.is_empty() {
        block.expr.map(|b| constant(cx, b))
    } else { None }
}

fn neg_sign(s: Sign) -> Sign {
    match s:
        Sign::Plus => Sign::Minus,
        Sign::Minus => Sign::Plus,
    }
}

fn neg_float_str(s: &InternedString) -> Cow<'static, str> {
    if s.startsWith('-') {
        Cow::Borrowed(s[1..])
    } else {
        Cow::Owned(format!("-{}", &*s))
    }
}
<commit_msg>added follow flag<commit_after>use rustc::lint::Context;
use rustc::middle::const_eval::lookup_const_by_id;
use syntax::ast::*;
use syntax::ptr::P;

pub enum FloatWidth {
    Fw32,
    Fw64,
    FwAny
}

impl From<FloatTy> for FloatWidth {
    fn from(ty: FloatTy) -> FloatWidth {
        match ty {
            TyF32 => Fw32,
            TyF64 => Fw64,
        }
    }
}

/// a Lit_-like enum to fold constant `Expr`s into
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum Constant {
    /// a String "abc"
    ConstantStr(&'static str, StrStyle),
    /// a Binary String b"abc"
    ConstantBinary(Rc<Vec<u8>>),
    /// a single byte b'a'
    ConstantByte(u8),
    /// a single char 'a'
    ConstantChar(char),
    /// an integer
    ConstantInt(u64, LitIntType),
    /// a float with given type
    ConstantFloat(Cow<'static, str>, FloatWidth),
    /// true or false
    ConstantBool(bool),
    /// an array of constants
    ConstantVec(Vec<Constant>),
    /// also an array, but with only one constant, repeated N times
    ConstantRepeat(Constant, usize),
    /// a tuple of constants
    ConstantTuple(Vec<Constant>),
}

/// simple constant folding
pub fn constant(cx: &Context, e: &Expr, follow: bool) -> Option<Constant> {
    match e {
        &ExprParen(ref inner) => constant(cx, inner, follow),
        &ExprPath(_, _) => if follow { fetch_path(cx, e) } else { None },
        &ExprBlock(ref block) => constant_block(cx, inner, follow),
        &ExprIf(ref cond, ref then, ref otherwise) =>
            match constant(cx, cond) {
                Some(ConstantBool(true)) => constant(cx, then, follow),
                Some(ConstantBool(false)) => constant(cx, otherwise, follow),
                _ => None,
            },
        &ExprLit(ref lit) => Some(lit_to_constant(lit)),
        &ExprVec(ref vec) => constant_vec(cx, vec, follow),
        &ExprTup(ref tup) => constant_tup(cx, tup, follow),
        &ExprRepeat(ref value, ref number) =>
            constant_binop_apply(cx, value, number,|v, n| ConstantRepeat(v, n)),
        &ExprUnary(op, ref operand) => constant(cx, operand, follow).and_then(
            |o| match op {
                UnNot =>
                    if let ConstantBool(b) = o {
                        Some(ConstantBool(!b))
                    } else { None },
                UnNeg => constant_negate(o),
                UnUniq | UnDeref => o,
            }),
        &ExprBinary(op, ref left, ref right) =>
            constant_binop(cx, op, left, right, follow),
        //TODO: add other expressions
        _ => None,
    }
}

fn lit_to_constant(lit: &Lit_) -> Constant {
    match lit {
        &LitStr(ref is, style) => ConstantStr(&*is, style),
        &LitBinary(ref blob) => ConstantBinary(blob.clone()),
        &LitByte(b) => ConstantByte(b),
        &LitChar(c) => ConstantChar(c),
        &LitInt(value, ty) => ConstantInt(value, ty),
        &LitFloat(ref is, ty) => ConstantFloat(Cow::Borrowed(&*is), ty.into()),
        &LitFloatUnsuffixed(InternedString) =>
                ConstantFloat(Cow::Borrowed(&*is), FwAny),
        &LitBool(b) => ConstantBool(b),
    }
}

/// create `Some(ConstantVec(..))` of all constants, unless there is any
/// non-constant part
fn constant_vec(cx: &Context, vec: &[&Expr], follow: bool) -> Option<Constant> {
    parts = Vec::new();
    for opt_part in vec {
        match constant(cx, opt_part, follow) {
            Some(ref p) => parts.push(p),
            None => { return None; },
        }
    }
    Some(ConstantVec(parts))
}

fn constant_tup(cx: &Context, tup: &[&Expr], follow: bool) -> Option<Constant> {
    parts = Vec::new();
    for opt_part in vec {
        match constant(cx, opt_part, follow) {
            Some(ref p) => parts.push(p),
            None => { return None; },
        }
    }
    Some(ConstantTuple(parts))
}

/// lookup a possibly constant expression from a ExprPath
fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> {
    if let Some(&PathResolution { base_def: DefConst(id), ..}) =
            cx.tcx.def_map.borrow().get(&e.id) {
        lookup_const_by_id(cx.tcx, id, None).map(|l| constant(cx, l))
    } else { None }
}

/// A block can only yield a constant if it only has one constant expression
fn constant_block(cx: &Context, block: &Block, follow: bool) -> Option<Constant> {
    if block.stmts.is_empty() {
        block.expr.map(|b| constant(cx, b, follow))
    } else { None }
}

fn constant_negate(o: Constant) -> Option<Constant> {
    match o {
        &ConstantInt(value, ty) =>
            Some(ConstantInt(value, match ty {
                SignedIntLit(ity, sign) => SignedIntLit(ity, neg_sign(sign)),
                UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)),
                _ => { return None; },
            })),
        &LitFloat(ref is, ref ty) => Some(ConstantFloat(neg_float_str(is), ty)),
        _ => None,
    }
}

fn neg_sign(s: Sign) -> Sign {
    match s {
        Sign::Plus => Sign::Minus,
        Sign::Minus => Sign::Plus,
    }
}

fn neg_float_str(s: &InternedString) -> Cow<'static, str> {
    if s.startsWith('-') {
        Cow::Borrowed(s[1..])
    } else {
        Cow::Owned(format!("-{}", &*s))
    }
}

fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr,
        follow: bool) -> Option<Constant> {
    match op.node {
        //BiAdd,
        //BiSub,
        //BiMul,
        //BiDiv,
        //BiRem,
        BiAnd => constant_short_circuit(cx, left, right, false, follow),
        BiOr => constant_short_circuit(cx, left, right, true, follow),
        //BiBitXor,
        //BiBitAnd,
        //BiBitOr,
        //BiShl,
        //BiShr,
        //BiEq,
        //BiLt,
        //BiLe,
        //BiNe,
        //BiGe,
        //BiGt,
        _ => None,
    }
}

fn constant_binop_apply<F>(cx: &Context, left: &Expr, right: &Expr, op: F,
        follow: bool) -> Option<Constant>
where F: FnMut(Constant, Constant) -> Option<Constant> {
    constant(cx, left, follow).and_then(|l| constant(cx, right, follow)
        .and_then(|r| op(l, r)))
}

fn constant_short_circuit(cx: &Context, left: &Expr, right: &Expr, b: bool,
        follow: bool) -> Option<Constant> {
    if let ConstantBool(lbool) = constant(cx, left, follow) {
        if l == b {
            Some(ConstantBool(b))
        } else {
            if let ConstantBool(rbool) = constant(cx, right, follow) {
                Some(ConstantBool(rbool))
            } else { None }
        }
    } else { None }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;
use std::result;
use std::fmt;
use crypto::digest::Digest;
use crypto::sha2::Sha512;
use crypto::aes;
use crypto::blockmodes;
use crypto::symmetriccipher::SymmetricCipherError;
use crypto::buffer::{ReadBuffer, WriteBuffer, BufferResult, RefReadBuffer, RefWriteBuffer};

use patch_file::CryptFileMetadata;
use constants::{PATCH_SALT_ITG2, DECRYPT_MAGIC_ITG2};

pub fn derive_aes_key(metadata: &CryptFileMetadata,
                      output: &mut [u8; 24]) {
    let mut sh = Sha512::new();
    sh.input(&metadata.subkey);
    sh.input(&PATCH_SALT_ITG2);
    {
        let mut ws = [0u8; 64];
        sh.result(&mut ws);
        output.copy_from_slice(&ws[0..24]);
    }
}

pub fn verify_crypt_metadata(metadata: &CryptFileMetadata,
                             aes_key: &[u8; 24])
                            -> result::Result<bool, &'static str> {
    let mut decryptor = aes::ecb_decryptor(
            aes::KeySize::KeySize192,
            &aes_key[..],
            blockmodes::NoPadding);
    let mut dec_block = [0u8; 16];
    let mut verify_block = RefReadBuffer::new(&metadata.verify_block[..]);
    let mut dec_buf = RefWriteBuffer::new(&mut dec_block[..]);
    let res = decryptor.decrypt(&mut verify_block,
                                &mut dec_buf,
                                true)
        .map(|r: BufferResult| {
            r
        })
        .map_err(|ex: SymmetricCipherError| {
            "Decrypt error"
        })
        .and_then(|r: BufferResult| {
            let mut dreadbuf = dec_buf.take_read_buffer();
            let mut dmagic = dreadbuf.take_remaining();
            Ok(dmagic[0..2] == DECRYPT_MAGIC_ITG2[0..2])
        });
    res
}

pub fn decrypt_file<T: Read, U: Write>(metadata: &CryptFileMetadata,
                                       aes_key: &[u8; 24],
                                       src: &mut T,
                                       dst: &mut U)
                                      -> io::Result<u32> {
    Ok(metadata.file_size)
}
<commit_msg>fix a few build warnings<commit_after>use std::io;
use std::io::prelude::*;
use std::result;
use crypto::digest::Digest;
use crypto::sha2::Sha512;
use crypto::aes;
use crypto::blockmodes;
use crypto::symmetriccipher::SymmetricCipherError;
use crypto::buffer::{ReadBuffer, WriteBuffer, BufferResult, RefReadBuffer, RefWriteBuffer};

use patch_file::CryptFileMetadata;
use constants::{PATCH_SALT_ITG2, DECRYPT_MAGIC_ITG2};

pub fn derive_aes_key(metadata: &CryptFileMetadata,
                      output: &mut [u8; 24]) {
    let mut sh = Sha512::new();
    sh.input(&metadata.subkey);
    sh.input(&PATCH_SALT_ITG2);
    {
        let mut ws = [0u8; 64];
        sh.result(&mut ws);
        output.copy_from_slice(&ws[0..24]);
    }
}

pub fn verify_crypt_metadata(metadata: &CryptFileMetadata,
                             aes_key: &[u8; 24])
                            -> result::Result<bool, &'static str> {
    let mut decryptor = aes::ecb_decryptor(
            aes::KeySize::KeySize192,
            &aes_key[..],
            blockmodes::NoPadding);
    let mut dec_block = [0u8; 16];
    let mut verify_block = RefReadBuffer::new(&metadata.verify_block[..]);
    let mut dec_buf = RefWriteBuffer::new(&mut dec_block[..]);
    let res = decryptor.decrypt(&mut verify_block,
                                &mut dec_buf,
                                true)
        .map(|r: BufferResult| {
            r
        })
        .map_err(|_: SymmetricCipherError| {
            "Decrypt error"
        })
        .and_then(|_: BufferResult| {
            let mut dreadbuf = dec_buf.take_read_buffer();
            let dmagic = dreadbuf.take_remaining();
            Ok(dmagic[0..2] == DECRYPT_MAGIC_ITG2[0..2])
        });
    res
}

pub fn decrypt_file<T: Read, U: Write>(metadata: &CryptFileMetadata,
                                       aes_key: &[u8; 24],
                                       src: &mut T,
                                       dst: &mut U)
                                      -> io::Result<u32> {
    Ok(metadata.file_size)
}
<|endoftext|>


<commit_before>use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use geometry::CGPoint;
use event_source::{CGEventSource,CGEventSourceRef};

use libc;
use std::mem;
use std::ptr;

pub type CGKeyCode = libc::uint16_t;

/// Flags for events
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventFlags {
  // Device-independent modifier key bits.
  AlphaShift = 0x00010000,
  Shift = 0x00020000,
  Control = 0x00040000,
  Alternate = 0x00080000,
  Command = 0x00100000,

  // Special key identifiers.
  Help = 0x00400000,
  SecondaryFn = 0x00800000,

  // Identifies key events from numeric keypad area on extended keyboards.
  NumericPad = 0x00200000,

  // Indicates if mouse/pen movement events are not being coalesced
  NonCoalesced = 0x00000100,
}

/// Constants that specify the different types of input events.
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventType {
    Null = 1 << 0,

    // Mouse events.
    LeftMouseDown = 1 << 1,
    LeftMouseUp = 1 << 2,
    RightMouseDown = 1 << 3,
    RightMouseUp = 1 << 4,
    MouseMoved = 1 << 5,
    LeftMouseDragged = 1 << 6,
    RightMouseDragged = 1 << 7,

    // Keyboard events.
    KeyDown = 1 << 10,
    KeyUp = 1 << 11,
    FlagsChanged = 1 << 12,

    // Specialized control devices.
    ScrollWheel = 1 << 22,
    TabletPointer = 1 << 23,
    TabletProximity = 1 << 24,
    OtherMouseDown = 1 << 25,
    OtherMouseUp = 1 << 26,
    OtherMouseDragged = 1 << 27,

    // Out of band event types. These are delivered to the event tap callback
    // to notify it of unusual conditions that disable the event tap.
    TapDisabledByTimeout = 0xFFFFFFFE,
    TapDisabledByUserInput = 0xFFFFFFFF,
}

// Constants that specify buttons on a one, two, or three-button mouse.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGMouseButton {
    Left,
    Right,
    Center,
}

/// Possible tapping points for events.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventTapLocation {
    HID,
    Session,
    AnnotatedSession,
}

#[repr(C)]
pub struct __CGEvent;

pub type CGEventRef = *const __CGEvent;

pub struct CGEvent {
    obj: CGEventRef,
}

impl Clone for CGEvent {
    #[inline]
    fn clone(&self) -> CGEvent {
        unsafe {
            TCFType::wrap_under_get_rule(self.obj)
        }
    }
}

impl Drop for CGEvent {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.as_CFTypeRef();
            assert!(ptr != ptr::null());
            CFRelease(ptr);
        }
    }
}

impl TCFType<CGEventRef> for CGEvent {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGEventRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGEventRef) -> CGEvent {
        let reference: CGEventRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGEventRef) -> CGEvent {
        CGEvent {
            obj: obj,
        }
    }

    #[inline]
    fn type_id() -> CFTypeID {
        unsafe {
            CGEventGetTypeID()
        }
    }
}

impl CGEvent {
    pub fn new(source: CGEventSource) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreate(source.as_concrete_TypeRef());
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_keyboard_event(
        source: CGEventSource,
        keycode: CGKeyCode,
        keydown: bool
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateKeyboardEvent(source.as_concrete_TypeRef(), keycode, keydown);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_mouse_event(
        source: CGEventSource,
        mouse_type: CGEventType,
        mouse_cursor_position: CGPoint,
        mouse_button: CGMouseButton
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateMouseEvent(source.as_concrete_TypeRef(), mouse_type,
                mouse_cursor_position, mouse_button);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn post(&self, tap_location: CGEventTapLocation) {
        unsafe {
            CGEventPost(tap_location, self.as_concrete_TypeRef());
        }
    }

    pub fn location(&self) -> CGPoint {
        unsafe {
            CGEventGetLocation(self.as_concrete_TypeRef())
        }
    }

    #[cfg(feature = "elcapitan")]
    pub fn post_to_pid(&self, pid: libc::pid_t) {
        unsafe {
            CGEventPostToPid(pid, self.as_concrete_TypeRef());
        }
    }

    pub fn set_flags(&self, flags: CGEventFlags) {
        unsafe {
            CGEventSetFlags(self.as_concrete_TypeRef(), flags);
        }
    }

    pub fn get_flags(&self) -> CGEventFlags {
        unsafe {
            CGEventGetFlags(self.as_concrete_TypeRef())
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    /// Return the type identifier for the opaque type `CGEventRef'.
    fn CGEventGetTypeID() -> CFTypeID;

    /// Return a new event using the event source `source'. If `source' is NULL,
    /// the default source is used.
    fn CGEventCreate(source: CGEventSourceRef) -> CGEventRef;

    /// Return a new keyboard event.
    ///
    /// The event source may be taken from another event, or may be NULL. Based
    /// on the virtual key code values entered, the appropriate key down, key up,
    /// or flags changed events are generated.
    ///
    /// All keystrokes needed to generate a character must be entered, including
    /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z',
    /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT
    /// and 'z' key must be released:
    fn CGEventCreateKeyboardEvent(source: CGEventSourceRef, keycode: CGKeyCode,
        keydown: bool) -> CGEventRef;

    /// Return a new mouse event.
    ///
    /// The event source may be taken from another event, or may be NULL.
    /// `mouseType' should be one of the mouse event types. `mouseCursorPosition'
    /// should be the position of the mouse cursor in global coordinates.
    /// `mouseButton' should be the button that's changing state; `mouseButton'
    /// is ignored unless `mouseType' is one of `kCGEventOtherMouseDown',
    /// `kCGEventOtherMouseDragged', or `kCGEventOtherMouseUp'.
    ///
    /// The current implemementation of the event system supports a maximum of
    /// thirty-two buttons. Mouse button 0 is the primary button on the mouse.
    /// Mouse button 1 is the secondary mouse button (right). Mouse button 2 is
    /// the center button, and the remaining buttons are in USB device order.
    fn CGEventCreateMouseEvent(source: CGEventSourceRef, mouseType: CGEventType,
        mouseCursorPosition: CGPoint, mouseButton: CGMouseButton) -> CGEventRef;

    /// Post an event into the event stream at a specified location.
    ///
    /// This function posts the specified event immediately before any event taps
    /// instantiated for that location, and the event passes through any such
    /// taps.
    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    #[cfg(feature = "elcapitan")]
    /// Post an event to a specified process ID
    fn CGEventPostToPid(pid: libc::pid_t, event: CGEventRef);

    /// Set the event flags of an event.
    fn CGEventSetFlags(event: CGEventRef, flags: CGEventFlags);

    /// Return the event flags of an event.
    fn CGEventGetFlags(event: CGEventRef) -> CGEventFlags;

    /// Return the location of an event in global display coordinates.
    /// CGPointZero is returned if event is not a valid CGEventRef.
    fn CGEventGetLocation(event: CGEventRef) -> CGPoint;
}
<commit_msg>Auto merge of #71 - pythoneer:patch-1, r=jdm<commit_after>use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use geometry::CGPoint;
use event_source::{CGEventSource,CGEventSourceRef};

use libc;
use std::mem;
use std::ptr;

pub type CGKeyCode = libc::uint16_t;

/// Flags for events
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventFlags {
  // Device-independent modifier key bits.
  AlphaShift = 0x00010000,
  Shift = 0x00020000,
  Control = 0x00040000,
  Alternate = 0x00080000,
  Command = 0x00100000,

  // Special key identifiers.
  Help = 0x00400000,
  SecondaryFn = 0x00800000,

  // Identifies key events from numeric keypad area on extended keyboards.
  NumericPad = 0x00200000,

  // Indicates if mouse/pen movement events are not being coalesced
  NonCoalesced = 0x00000100,
}

/// Constants that specify the different types of input events.
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventType {
    Null = 0,

    // Mouse events.
    LeftMouseDown = 1,
    LeftMouseUp = 2,
    RightMouseDown = 3,
    RightMouseUp = 4,
    MouseMoved = 5,
    LeftMouseDragged = 6,
    RightMouseDragged = 7,

    // Keyboard events.
    KeyDown = 10,
    KeyUp = 11,
    FlagsChanged = 12,

    // Specialized control devices.
    ScrollWheel = 22,
    TabletPointer = 23,
    TabletProximity = 24,
    OtherMouseDown = 25,
    OtherMouseUp = 26,
    OtherMouseDragged = 27,

    // Out of band event types. These are delivered to the event tap callback
    // to notify it of unusual conditions that disable the event tap.
    TapDisabledByTimeout = 0xFFFFFFFE,
    TapDisabledByUserInput = 0xFFFFFFFF,
}

// Constants that specify buttons on a one, two, or three-button mouse.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGMouseButton {
    Left,
    Right,
    Center,
}

/// Possible tapping points for events.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventTapLocation {
    HID,
    Session,
    AnnotatedSession,
}

#[repr(C)]
pub struct __CGEvent;

pub type CGEventRef = *const __CGEvent;

pub struct CGEvent {
    obj: CGEventRef,
}

impl Clone for CGEvent {
    #[inline]
    fn clone(&self) -> CGEvent {
        unsafe {
            TCFType::wrap_under_get_rule(self.obj)
        }
    }
}

impl Drop for CGEvent {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.as_CFTypeRef();
            assert!(ptr != ptr::null());
            CFRelease(ptr);
        }
    }
}

impl TCFType<CGEventRef> for CGEvent {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGEventRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGEventRef) -> CGEvent {
        let reference: CGEventRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGEventRef) -> CGEvent {
        CGEvent {
            obj: obj,
        }
    }

    #[inline]
    fn type_id() -> CFTypeID {
        unsafe {
            CGEventGetTypeID()
        }
    }
}

impl CGEvent {
    pub fn new(source: CGEventSource) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreate(source.as_concrete_TypeRef());
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_keyboard_event(
        source: CGEventSource,
        keycode: CGKeyCode,
        keydown: bool
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateKeyboardEvent(source.as_concrete_TypeRef(), keycode, keydown);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_mouse_event(
        source: CGEventSource,
        mouse_type: CGEventType,
        mouse_cursor_position: CGPoint,
        mouse_button: CGMouseButton
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateMouseEvent(source.as_concrete_TypeRef(), mouse_type,
                mouse_cursor_position, mouse_button);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn post(&self, tap_location: CGEventTapLocation) {
        unsafe {
            CGEventPost(tap_location, self.as_concrete_TypeRef());
        }
    }

    pub fn location(&self) -> CGPoint {
        unsafe {
            CGEventGetLocation(self.as_concrete_TypeRef())
        }
    }

    #[cfg(feature = "elcapitan")]
    pub fn post_to_pid(&self, pid: libc::pid_t) {
        unsafe {
            CGEventPostToPid(pid, self.as_concrete_TypeRef());
        }
    }

    pub fn set_flags(&self, flags: CGEventFlags) {
        unsafe {
            CGEventSetFlags(self.as_concrete_TypeRef(), flags);
        }
    }

    pub fn get_flags(&self) -> CGEventFlags {
        unsafe {
            CGEventGetFlags(self.as_concrete_TypeRef())
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    /// Return the type identifier for the opaque type `CGEventRef'.
    fn CGEventGetTypeID() -> CFTypeID;

    /// Return a new event using the event source `source'. If `source' is NULL,
    /// the default source is used.
    fn CGEventCreate(source: CGEventSourceRef) -> CGEventRef;

    /// Return a new keyboard event.
    ///
    /// The event source may be taken from another event, or may be NULL. Based
    /// on the virtual key code values entered, the appropriate key down, key up,
    /// or flags changed events are generated.
    ///
    /// All keystrokes needed to generate a character must be entered, including
    /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z',
    /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT
    /// and 'z' key must be released:
    fn CGEventCreateKeyboardEvent(source: CGEventSourceRef, keycode: CGKeyCode,
        keydown: bool) -> CGEventRef;

    /// Return a new mouse event.
    ///
    /// The event source may be taken from another event, or may be NULL.
    /// `mouseType' should be one of the mouse event types. `mouseCursorPosition'
    /// should be the position of the mouse cursor in global coordinates.
    /// `mouseButton' should be the button that's changing state; `mouseButton'
    /// is ignored unless `mouseType' is one of `kCGEventOtherMouseDown',
    /// `kCGEventOtherMouseDragged', or `kCGEventOtherMouseUp'.
    ///
    /// The current implemementation of the event system supports a maximum of
    /// thirty-two buttons. Mouse button 0 is the primary button on the mouse.
    /// Mouse button 1 is the secondary mouse button (right). Mouse button 2 is
    /// the center button, and the remaining buttons are in USB device order.
    fn CGEventCreateMouseEvent(source: CGEventSourceRef, mouseType: CGEventType,
        mouseCursorPosition: CGPoint, mouseButton: CGMouseButton) -> CGEventRef;

    /// Post an event into the event stream at a specified location.
    ///
    /// This function posts the specified event immediately before any event taps
    /// instantiated for that location, and the event passes through any such
    /// taps.
    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    #[cfg(feature = "elcapitan")]
    /// Post an event to a specified process ID
    fn CGEventPostToPid(pid: libc::pid_t, event: CGEventRef);

    /// Set the event flags of an event.
    fn CGEventSetFlags(event: CGEventRef, flags: CGEventFlags);

    /// Return the event flags of an event.
    fn CGEventGetFlags(event: CGEventRef) -> CGEventFlags;

    /// Return the location of an event in global display coordinates.
    /// CGPointZero is returned if event is not a valid CGEventRef.
    fn CGEventGetLocation(event: CGEventRef) -> CGPoint;
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate image;

use std::collections::HashMap;
use rand::random;

use std::fs::File;
use std::path::Path;

/// Single map point
pub struct Field{
    state: u32,
}

impl Field{
    pub fn new(state: u32) -> Field{
        Field{
            state: state,
        }
    }
}

/// Whole map
pub struct Map{
    height: u32,
    width: u32,
    fields: HashMap<(u32,u32),Field>,
}

impl Map {
    pub fn new(x: u32, y: u32) -> Map{
        let mut map = Map{
            height: y,
            width: x,
            fields: HashMap::new(),
        };

        for i in 0..y {
            for j in 0..x{
                map.fields.insert((j,i),Field::new(0));
            }
        }
        map
    }

    /// Print map into stdout
    pub fn print(&self){
        for i in 0..self.height {
            for j in 0..self.width {
                let sym = if self.fields.get(&(j,i)).unwrap().state > 0
                    { '*' } else { ' ' };
                print!(" {}", sym);
            }
            println!("");
        }
    }

    pub fn export(&self){

        let mut imgbuf = image::ImageBuffer::new(self.width, self.height);

        for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
            let color = if self.fields.get(&(x,y)).unwrap().state > 0
            { 125 } else { 0 };

            *pixel = image::Luma([color as u8]);
        }

        let ref mut fout = File::create(&Path::new("out.png")).unwrap();

        image::ImageLuma8(imgbuf).save(fout, image::PNG);

    }

    /// Find neighbours for single map point
    fn calc_weight(&self, p: (u32,u32)) -> u32{
        let mut res = self.fields.get(&p).unwrap().state;

        // right cell
        if p.0 < self.width -1 {
            res += self.fields.get(&(p.0 + 1 , p.1)).unwrap().state;
        }
        // left cell
        if p.0 > 0 {
            res += self.fields.get(&(p.0 - 1, p.1)).unwrap().state;
        }
        // upper cell
        if p.1 > 0 {
            res += self.fields.get(&(p.0, p.1 - 1)).unwrap().state;
        }
        // down cell
        if p.1 < self.height -1 {
            res += self.fields.get(&(p.0, p.1 + 1)).unwrap().state;
        }
        res
    }

    /// Create neighbours map
    fn calc_neighbours(&self,pre_map :&mut HashMap<(u32,u32),u32>){
        for i in 0..self.height {
            for j in 0..self.width {
                let w = self.calc_weight((j,i));
                pre_map.insert((j,i),w);
            }
        }
    }

    /// Generate map
    pub fn generate(&mut self){

        // seed map
        for (_,field) in self.fields.iter_mut() {
            if random::<u32>() % 100 == 1 {
                field.state = 1;
            }
        }

        let mut neighbours = HashMap::<(u32,u32),u32>::new();

        for _ in 0..20 {
            self.calc_neighbours(&mut neighbours);

            for (p, field) in self.fields.iter_mut() {
                if field.state > 0 {
                    continue;
                }

                let weight = neighbours.get(&p).unwrap();
                let chance = random::<u32>() % 100;

                match *weight {
                    //0 => if chance < 1 { field.state = 1 },
                    1 => if chance < 10 { field.state = 1 },
                    2 => if chance < 35 { field.state = 1 },
                    3 => if chance < 45 { field.state = 1 },
                    4 => if chance < 80 { field.state = 1 },
                    _ => {},
                }
            }
        }
    }
}
<commit_msg>moved algo to separte func<commit_after>extern crate rand;
extern crate image;

use std::collections::HashMap;
use rand::random;

use std::fs::File;
use std::path::Path;

/// Single map point
pub struct Field{
    state: u32,
}

impl Field{
    pub fn new(state: u32) -> Field{
        Field{
            state: state,
        }
    }
}

/// Whole map
pub struct Map{
    height: u32,
    width: u32,
    fields: HashMap<(u32,u32),Field>,
}

pub struct Params{
    iterations: u32,
    chances: (u32,u32,u32,u32,u32),
}

impl Map {
    pub fn new(x: u32, y: u32) -> Map{
        let mut map = Map{
            height: y,
            width: x,
            fields: HashMap::new(),
        };

        for i in 0..y {
            for j in 0..x{
                map.fields.insert((j,i),Field::new(0));
            }
        }
        map
    }

    /// Print map into stdout
    pub fn print(&self){
        for i in 0..self.height {
            for j in 0..self.width {
                let sym = if self.fields.get(&(j,i)).unwrap().state > 0
                    { '*' } else { ' ' };
                print!(" {}", sym);
            }
            println!("");
        }
    }

    pub fn export(&self){

        let mut imgbuf = image::ImageBuffer::new(self.width, self.height);

        for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
            let color = if self.fields.get(&(x,y)).unwrap().state > 0
            { [0,125,0] } else { [0,0,125] };

            *pixel = image::Rgb(color);
        }

        let ref mut fout = File::create(&Path::new("out.png")).unwrap();

        image::ImageRgb8(imgbuf).save(fout, image::PNG);

    }

    /// Find neighbours for single map point
    fn calc_weight(&self, p: (u32,u32)) -> u32{
        let mut res = self.fields.get(&p).unwrap().state;

        // right cell
        if p.0 < self.width -1 {
            res += self.fields.get(&(p.0 + 1 , p.1)).unwrap().state;
        }
        // left cell
        if p.0 > 0 {
            res += self.fields.get(&(p.0 - 1, p.1)).unwrap().state;
        }
        // upper cell
        if p.1 > 0 {
            res += self.fields.get(&(p.0, p.1 - 1)).unwrap().state;
        }
        // down cell
        if p.1 < self.height -1 {
            res += self.fields.get(&(p.0, p.1 + 1)).unwrap().state;
        }
        res
    }

    /// Create neighbours map
    fn calc_neighbours(&self,pre_map: &mut HashMap<(u32,u32),u32>){
        for i in 0..self.height {
            for j in 0..self.width {
                let w = self.calc_weight((j,i));
                pre_map.insert((j,i),w);
            }
        }
    }

    fn algo(&mut self, params: Params){
        let mut neighbours = HashMap::<(u32,u32),u32>::new();

        for _ in 0..params.iterations {
            self.calc_neighbours(&mut neighbours);

            for (p, field) in self.fields.iter_mut() {
                if field.state > 0 {
                    continue;
                }

                let weight = neighbours.get(&p).unwrap();
                let chance = random::<u32>() % 100;

                match *weight {
                    0 => if chance < params.chances.0 { field.state = 1 },
                    1 => if chance < params.chances.1 { field.state = 1 },
                    2 => if chance < params.chances.2 { field.state = 1 },
                    3 => if chance < params.chances.3 { field.state = 1 },
                    4 => if chance < params.chances.4 { field.state = 1 },
                    _ => {},
                }
            }
        }
    }

    //TODO add target fill rate
    /// Generate map
    pub fn generate(&mut self){

        // seed map
        for (_,field) in self.fields.iter_mut() {
            if random::<u32>() % 100 == 1 {
                field.state = 1;
            }
        }

        self.algo(Params{iterations: 25, chances: (0,20,40,50,80)});

    }
}
<|endoftext|>


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

use conrod::Ui;
use graphics::Context;
use matrix;
use opengl_graphics::GlGraphics;
use opengl_graphics::glyph_cache::GlyphCache;
use piston::input;
use dl;

use super::graph_builder::{GraphAction, GraphBuilder};
use super::op::Operation;
use super::var_store::{VarStore, VarIndex};

pub struct Mouse {
    pub pos: [f64; 2],
    pub lmb: bool,
    pub rmb: bool,
}

impl Mouse {
    pub fn new() -> Self {
        Mouse {
            pos: [0.0; 2],
            lmb: false,
            rmb: false,
        }
    }
}

pub struct DeepLabUi {
    activation_blocks: [[Rc<Operation>; 2]; 2],
    graph: GraphBuilder,
    ctx: matrix::Context,

    place_op: Option<Rc<Operation>>,
    sel_var: Option<VarIndex>, // Selected variable
    mouse: Mouse,
}

impl DeepLabUi {
    pub fn new() -> DeepLabUi {
        let mat_mul = Rc::new(Operation::new("MatMul".to_string(), 2, 1,
            |ctx: &matrix::Context,
             graph: &mut dl::Graph,
             vars: &mut VarStore,
             _in: &[Option<VarIndex>],
             _out: &[VarIndex]| {
                let a = *_in[0].unwrap().get(&vars);
                let b = *_in[1].unwrap().get(&vars);
                let op = Box::new(dl::op::MatMul::new(&ctx, a.shape, b.shape));
                let node = graph.add_node(&ctx, op,
                                          vec![a.gpu.unwrap(), b.gpu.unwrap()],
                                          &[_out[0].get(vars).shape]);
                _out[0].get_mut(vars).gpu = Some(node.get(&graph).outputs[0]);
            }));
        let variable = Rc::new(Operation::new("Variable".to_string(), 0, 1,
            |ctx: &matrix::Context,
             graph: &mut dl::Graph,
             vars: &mut VarStore,
             _in: &[Option<VarIndex>],
             _out: &[VarIndex]| {
                 _out[0].get_mut(vars).gpu = Some(graph.add_variable(ctx, (1,1)));
            }));
        DeepLabUi {
            activation_blocks: [[mat_mul.clone(), mat_mul.clone()],
                                [variable.clone(), mat_mul.clone()]],
            graph: GraphBuilder::new(),
            ctx: matrix::Context::new(),

            place_op: None,
            sel_var: None,
            mouse: Mouse::new(),
        }
    }

    pub fn event(&mut self, event: &input::Event) {
        use piston::input::*;
        event.mouse_cursor(|x, y| {
            self.mouse.pos = [x, y];
        });
        event.press(|button| {
            //use piston::input::Button;
            match button {
                Button::Keyboard(key) => println!("Pressed keyboard key '{:?}'", key),
                Button::Mouse(button) => {
                    match button {
                        mouse::MouseButton::Left => {
                            self.mouse.lmb = true;
                        },
                        mouse::MouseButton::Right => {
                            self.mouse.rmb = true;
                            self.place_op = None;
                        },
                        _ => { },
                    }
                },
                _ => { },
            }
        });
        event.release(|button| {
            //use piston::input::Button;
            match button {
                Button::Keyboard(key) => println!("Released keyboard key '{:?}'", key),
                Button::Mouse(button) => {
                    match button {
                        mouse::MouseButton::Left => {
                            self.mouse.lmb = false;
                            if let Some(ref place_op) = self.place_op {
                                self.graph.add_node("asdf".to_string(), self.mouse.pos, place_op.clone());
                            }
                        },
                        mouse::MouseButton::Right => {
                            self.mouse.rmb = false;
                        }
                        _ => { },
                    }
                },
                _ => { },
            }
        });
        if let Some(graph_action) = self.graph.event(event, &self.mouse) {
            match graph_action {
                GraphAction::SelectNode(n) => { },
                GraphAction::SelectVariable(v) => { self.sel_var = Some(v); },
            }
        }
    }

    pub fn draw(&self, c: Context, gl: &mut GlGraphics) {
        self.graph.draw(&c, gl);
    }

    pub fn set_widgets<'a>(&mut self, ui: &mut Ui<GlyphCache<'a>>) {
        use conrod::{color, Button, Canvas, Colorable, Frameable, Labelable, Positionable, Sizeable, Slider, Tabs, Text, Widget, WidgetMatrix};

        // Construct our main `Canvas` tree.
        Canvas::new().flow_down(&[
            (UPPER, Canvas::new().flow_down(&[
                (TOOL_BAR, Canvas::new().color(color::rgb(0.7, 0.7, 0.7)).length(48.0)),
                (GRAPH_AREA, Canvas::new().color(color::rgb(1.0, 1.0, 0.8))),
            ])),
            (LOWER, Canvas::new().color(color::rgb(1.0, 0.8, 1.0)).scroll_kids_vertically().flow_right(&[
                (BLOCKS, Canvas::new().color(color::rgb(0.8, 1.0, 1.0)).pad_bottom(10.0)),
                (RELU_B, Canvas::new().color(color::rgb(0.8, 1.0, 0.8)).pad_bottom(10.0)),
                (VAR_MANIP, Canvas::new().color(color::rgb(0.8, 0.2, 0.8)).pad_bottom(10.0).pad_left(10.0)),
            ])),
        ]).set(MASTER, ui);

        /*Text::new("Fancy Neural Net").color(color::rgb(0.0, 0.0, 0.0))
                                     .font_size(48)
                                     .middle_of(GRAPH_AREA)
                                     .set(TITLE, ui);*/

        Button::new().rgb(0.3, 0.3, 0.8)
                     .label("Build Graph")
                     .middle_of(TOOL_BAR)
                     .react(|| {
                         self.graph.gpu_build(&self.ctx);
                     }).set(BUILD_BTN, ui);

        let footer_wh = ui.wh_of(BLOCKS).unwrap();
        WidgetMatrix::new(2, 2)
            .w_h(footer_wh[0], footer_wh[1])
            .mid_top_of(BLOCKS)
            .each_widget(|n, col, row| {
                let op: Rc<Operation> = {
                    let _row: &[Rc<Operation>; 2] = &self.activation_blocks[row];
                    let op: &Rc<Operation> = &_row[col];
                    op.clone()
                };
                Button::new()
                    .rgb(0.3, 0.8, 0.3)
                    .label(op.name.clone().as_ref())
                    .react(|| {
                        self.place_op = Some(op);
                    })
            }).set(ACTIVATION_BLOCK_MATRIX, ui);

        // Build the variable manipulator
        let var_val =
            if let Some(sel_var) = self.sel_var {
                *sel_var.get(&self.graph.vars).gpu.unwrap().get(&self.graph.graph).get(&self.ctx).get(0, 0)
            } else {
                0.5
            };
        Slider::new(var_val, 0.0, 1.0)
            .w_h(30.0, 150.0)
            .mid_left_of(VAR_MANIP)
            .rgb(0.5, 0.3, 0.6)
            .frame(1.0)
            .react(|val| {
                // TODO
            }).set(VAR_SLIDER, ui);
    }

    pub fn on_key_pressed(&mut self, key: input::Key) {
        match key {
            _ => { },
        }
    }

    pub fn on_key_released(&mut self, key: input::Key) {
        match key {
            _ => { },
        }
    }
}

widget_ids! {
    // Canvas IDs
    MASTER,
    TOOL_BAR,
    GRAPH_AREA,
    UPPER,
    LOWER,

    // Widget IDs
    BUILD_BTN,
    NODE,
    BLOCKS,
    ACTIVATION_BLOCK_MATRIX,
    RELU_B,
    TITLE,
    MATMUL,
    RELU,

    // Variable manipulator
    VAR_MANIP,
    VAR_SLIDER,
    VAR_MATRIX,
    VAR_TRAINABLE,
    VAR_DATASET,
}
<commit_msg>Store selected coordinate with selected variable<commit_after>use std::rc::Rc;

use conrod::Ui;
use graphics::Context;
use matrix;
use opengl_graphics::GlGraphics;
use opengl_graphics::glyph_cache::GlyphCache;
use piston::input;
use dl;

use super::graph_builder::{GraphAction, GraphBuilder};
use super::op::Operation;
use super::var_store::{VarStore, VarIndex};

pub struct Mouse {
    pub pos: [f64; 2],
    pub lmb: bool,
    pub rmb: bool,
}

impl Mouse {
    pub fn new() -> Self {
        Mouse {
            pos: [0.0; 2],
            lmb: false,
            rmb: false,
        }
    }
}

pub struct DeepLabUi {
    activation_blocks: [[Rc<Operation>; 2]; 2],
    graph: GraphBuilder,
    ctx: matrix::Context,

    place_op: Option<Rc<Operation>>,
    sel_var: Option<(VarIndex, Vec<usize>)>, // Selected variable
    mouse: Mouse,
}

impl DeepLabUi {
    pub fn new() -> DeepLabUi {
        let mat_mul = Rc::new(Operation::new("MatMul".to_string(), 2, 1,
            |ctx: &matrix::Context,
             graph: &mut dl::Graph,
             vars: &mut VarStore,
             _in: &[Option<VarIndex>],
             _out: &[VarIndex]| {
                let a = *_in[0].unwrap().get(&vars);
                let b = *_in[1].unwrap().get(&vars);
                let op = Box::new(dl::op::MatMul::new(&ctx, a.shape, b.shape));
                let node = graph.add_node(&ctx, op,
                                          vec![a.gpu.unwrap(), b.gpu.unwrap()],
                                          &[_out[0].get(vars).shape]);
                _out[0].get_mut(vars).gpu = Some(node.get(&graph).outputs[0]);
            }));
        let variable = Rc::new(Operation::new("Variable".to_string(), 0, 1,
            |ctx: &matrix::Context,
             graph: &mut dl::Graph,
             vars: &mut VarStore,
             _in: &[Option<VarIndex>],
             _out: &[VarIndex]| {
                 _out[0].get_mut(vars).gpu = Some(graph.add_variable(ctx, (1,1)));
            }));
        DeepLabUi {
            activation_blocks: [[mat_mul.clone(), mat_mul.clone()],
                                [variable.clone(), mat_mul.clone()]],
            graph: GraphBuilder::new(),
            ctx: matrix::Context::new(),

            place_op: None,
            sel_var: None,
            mouse: Mouse::new(),
        }
    }

    pub fn event(&mut self, event: &input::Event) {
        use piston::input::*;
        event.mouse_cursor(|x, y| {
            self.mouse.pos = [x, y];
        });
        event.press(|button| {
            //use piston::input::Button;
            match button {
                Button::Keyboard(key) => println!("Pressed keyboard key '{:?}'", key),
                Button::Mouse(button) => {
                    match button {
                        mouse::MouseButton::Left => {
                            self.mouse.lmb = true;
                        },
                        mouse::MouseButton::Right => {
                            self.mouse.rmb = true;
                            self.place_op = None;
                        },
                        _ => { },
                    }
                },
                _ => { },
            }
        });
        event.release(|button| {
            //use piston::input::Button;
            match button {
                Button::Keyboard(key) => println!("Released keyboard key '{:?}'", key),
                Button::Mouse(button) => {
                    match button {
                        mouse::MouseButton::Left => {
                            self.mouse.lmb = false;
                            if let Some(ref place_op) = self.place_op {
                                self.graph.add_node("asdf".to_string(), self.mouse.pos, place_op.clone());
                            }
                        },
                        mouse::MouseButton::Right => {
                            self.mouse.rmb = false;
                        }
                        _ => { },
                    }
                },
                _ => { },
            }
        });
        if let Some(graph_action) = self.graph.event(event, &self.mouse) {
            match graph_action {
                GraphAction::SelectNode(n) => { },
                GraphAction::SelectVariable(v) => { self.sel_var = Some((v, vec![0, 0])); },
            }
        }
    }

    pub fn draw(&self, c: Context, gl: &mut GlGraphics) {
        self.graph.draw(&c, gl);
    }

    pub fn set_widgets<'a>(&mut self, ui: &mut Ui<GlyphCache<'a>>) {
        use conrod::{color, Button, Canvas, Colorable, Frameable, Labelable, Positionable, Sizeable, Slider, Tabs, Text, Widget, WidgetMatrix};

        // Construct our main `Canvas` tree.
        Canvas::new().flow_down(&[
            (UPPER, Canvas::new().flow_down(&[
                (TOOL_BAR, Canvas::new().color(color::rgb(0.7, 0.7, 0.7)).length(48.0)),
                (GRAPH_AREA, Canvas::new().color(color::rgb(1.0, 1.0, 0.8))),
            ])),
            (LOWER, Canvas::new().color(color::rgb(1.0, 0.8, 1.0)).scroll_kids_vertically().flow_right(&[
                (BLOCKS, Canvas::new().color(color::rgb(0.8, 1.0, 1.0)).pad_bottom(10.0)),
                (RELU_B, Canvas::new().color(color::rgb(0.8, 1.0, 0.8)).pad_bottom(10.0)),
                (VAR_MANIP, Canvas::new().color(color::rgb(0.8, 0.2, 0.8)).pad_bottom(10.0).pad_left(10.0)),
            ])),
        ]).set(MASTER, ui);

        /*Text::new("Fancy Neural Net").color(color::rgb(0.0, 0.0, 0.0))
                                     .font_size(48)
                                     .middle_of(GRAPH_AREA)
                                     .set(TITLE, ui);*/

        Button::new().rgb(0.3, 0.3, 0.8)
                     .label("Build Graph")
                     .middle_of(TOOL_BAR)
                     .react(|| {
                         self.graph.gpu_build(&self.ctx);
                     }).set(BUILD_BTN, ui);

        let footer_wh = ui.wh_of(BLOCKS).unwrap();
        WidgetMatrix::new(2, 2)
            .w_h(footer_wh[0], footer_wh[1])
            .mid_top_of(BLOCKS)
            .each_widget(|n, col, row| {
                let op: Rc<Operation> = {
                    let _row: &[Rc<Operation>; 2] = &self.activation_blocks[row];
                    let op: &Rc<Operation> = &_row[col];
                    op.clone()
                };
                Button::new()
                    .rgb(0.3, 0.8, 0.3)
                    .label(op.name.clone().as_ref())
                    .react(|| {
                        self.place_op = Some(op);
                    })
            }).set(ACTIVATION_BLOCK_MATRIX, ui);

        // Build the variable manipulator
        if let Some((sel_var, ref coords)) = self.sel_var {
            let gpu_var = sel_var.get(&self.graph.vars).gpu.unwrap();
            let var_val = *gpu_var.get(&self.graph.graph).get(&self.ctx).get(coords[0], coords[1]);
            //let var_rows = gpu_var.get(&self.graph.graph).get(&self.ctx).rows();
            //let var_cols = gpu_var.get(&self.graph.graph).get(&self.ctx).columns();

            Slider::new(var_val, 0.0, 10.0)
                .w_h(30.0, 150.0)
                .mid_left_of(VAR_MANIP)
                .rgb(0.5, 0.3, 0.6)
                .frame(1.0)
                .react(|val| {
                    // TODO
                }).set(VAR_SLIDER, ui);

            /*WidgetMatrix::new(2, 2)
                .mid_top_of(VAR_MANIP)
                .each_widget(|n, col, row| {
                    let op: Rc<Operation> = {
                        let _row: &[Rc<Operation>; 2] = &self.activation_blocks[row];
                        let op: &Rc<Operation> = &_row[col];
                        op.clone()
                    };
                    Button::new()
                        .rgb(0.3, 0.8, 0.3)
                        .label(op.name.clone().as_ref())
                        .react(|| {
                            self.place_op = Some(op);
                        })
                }).set(ACTIVATION_BLOCK_MATRIX, ui);*/
        }
    }

    pub fn on_key_pressed(&mut self, key: input::Key) {
        match key {
            _ => { },
        }
    }

    pub fn on_key_released(&mut self, key: input::Key) {
        match key {
            _ => { },
        }
    }
}

widget_ids! {
    // Canvas IDs
    MASTER,
    TOOL_BAR,
    GRAPH_AREA,
    UPPER,
    LOWER,

    // Widget IDs
    BUILD_BTN,
    NODE,
    BLOCKS,
    ACTIVATION_BLOCK_MATRIX,
    RELU_B,
    TITLE,
    MATMUL,
    RELU,

    // Variable manipulator
    VAR_MANIP,
    VAR_SLIDER,
    VAR_MATRIX,
    VAR_TRAINABLE,
    VAR_DATASET,
}
<|endoftext|>


<commit_before>/// Error types

error_chain! {
    types {
        Error, ErrorKind, ResultExt, Result;
    }

    errors {
        QueryParsingError(query: String) {
            description("parsing the query failed")
            display("Parsing the query '{}' failed", query)
        }

        EmptyQueryError {
            description("the query is empty")
            display("The query on the TOML is empty")
        }

        EmptyIdentifier {
            description("Query an empty identifier: ''")
            display("The passed query has an empty identifier")
        }

        ArrayAccessWithoutIndex {
            description("trying to access array without index")
            display("The passed query tries to access an array but does not specify the index")
        }

        ArrayAccessWithInvalidIndex {
            description("trying to pass an invalid index")
            display("The passed query tries to access an array but does not specify a valid index")
        }
    }
}
<commit_msg>Add error type for resolver<commit_after>/// Error types

error_chain! {
    types {
        Error, ErrorKind, ResultExt, Result;
    }

    errors {

        // Errors for tokenizer

        QueryParsingError(query: String) {
            description("parsing the query failed")
            display("Parsing the query '{}' failed", query)
        }

        EmptyQueryError {
            description("the query is empty")
            display("The query on the TOML is empty")
        }

        EmptyIdentifier {
            description("Query an empty identifier: ''")
            display("The passed query has an empty identifier")
        }

        ArrayAccessWithoutIndex {
            description("trying to access array without index")
            display("The passed query tries to access an array but does not specify the index")
        }

        ArrayAccessWithInvalidIndex {
            description("trying to pass an invalid index")
            display("The passed query tries to access an array but does not specify a valid index")
        }

        // Errors for Resolver

        IdentifierNotFoundInDocument(ident: String) {
            description("Identifier missing in document")
            display("The identfier '{}' is not present in the document", ident)
        }

    }
}
<|endoftext|>