<commit_before>use url;
use std::error::Error;
use std::fmt;
use r2d2;
cfg_if! {if #[cfg(feature = "with-postgres")]{
    use pg::PostgresError;
}}

cfg_if! {if #[cfg(feature = "with-sqlite")]{
    use sq::SqliteError;
}}

#[derive(Debug)]
pub enum ConnectError {
    NoSuchPoolConnection,
    ParseError(ParseError),
    UnsupportedDb(String),
    R2d2Error(r2d2::Error),
}

/// TODO: use error_chain i guess?
impl Error for ConnectError {
    fn description(&self) -> &str {
        "short desc"
    }
    fn cause(&self) -> Option<&Error> {
        None
    }
}

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

#[derive(Debug)]
pub enum ParseError {
    DbUrlParseError(url::ParseError),
}

#[derive(Debug)]
pub enum PlatformError {
    #[cfg(feature = "with-postgres")] PostgresError(PostgresError),
    #[cfg(feature = "with-sqlite")] SqliteError(SqliteError),
}

impl From<PostgresError> for PlatformError {
    fn from(e: PostgresError) -> Self {
        PlatformError::PostgresError(e)
    }
}

impl From<PostgresError> for DbError {
    fn from(e: PostgresError) -> Self {
        DbError::PlatformError(PlatformError::from(e))
    }
}

#[derive(Debug)]
pub enum DbError {
    DataError(DataError),
    PlatformError(PlatformError),
    ConvertError(ConvertError),
    ConnectError(ConnectError), //agnostic connection error
}

#[cfg(feature = "with-postgres")]
impl From<PlatformError> for DbError {
    fn from(e: PlatformError) -> Self {
        DbError::PlatformError(e)
    }
}

#[derive(Debug)]
pub enum ConvertError {
    UnknownDataType,
    UnsupportedDataType(String),
}

#[derive(Debug)]
pub enum DataError {
    ZeroRecordReturned,
    MoreThan1RecordReturned,
}
<commit_msg>feature specifics<commit_after>use url;
use std::error::Error;
use std::fmt;
use r2d2;
cfg_if! {if #[cfg(feature = "with-postgres")]{
    use pg::PostgresError;
}}

cfg_if! {if #[cfg(feature = "with-sqlite")]{
    use sq::SqliteError;
}}

#[derive(Debug)]
pub enum ConnectError {
    NoSuchPoolConnection,
    ParseError(ParseError),
    UnsupportedDb(String),
    R2d2Error(r2d2::Error),
}

/// TODO: use error_chain i guess?
impl Error for ConnectError {
    fn description(&self) -> &str {
        "short desc"
    }
    fn cause(&self) -> Option<&Error> {
        None
    }
}

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

#[derive(Debug)]
pub enum ParseError {
    DbUrlParseError(url::ParseError),
}

#[derive(Debug)]
pub enum PlatformError {
    #[cfg(feature = "with-postgres")] PostgresError(PostgresError),
    #[cfg(feature = "with-sqlite")] SqliteError(SqliteError),
}

#[cfg(feature = "with-postgres")]
impl From<PostgresError> for PlatformError {
    fn from(e: PostgresError) -> Self {
        PlatformError::PostgresError(e)
    }
}

#[cfg(feature = "with-postgres")]
impl From<PostgresError> for DbError {
    fn from(e: PostgresError) -> Self {
        DbError::PlatformError(PlatformError::from(e))
    }
}

#[derive(Debug)]
pub enum DbError {
    DataError(DataError),
    PlatformError(PlatformError),
    ConvertError(ConvertError),
    ConnectError(ConnectError), //agnostic connection error
}

#[cfg(feature = "with-postgres")]
impl From<PlatformError> for DbError {
    fn from(e: PlatformError) -> Self {
        DbError::PlatformError(e)
    }
}

#[derive(Debug)]
pub enum ConvertError {
    UnknownDataType,
    UnsupportedDataType(String),
}

#[derive(Debug)]
pub enum DataError {
    ZeroRecordReturned,
    MoreThan1RecordReturned,
}
<|endoftext|>


<commit_before>use proc_macro2::{Delimiter, Span};

use error::Result;
use parse::ParseBuffer;
#[cfg(any(feature = "full", feature = "derive"))]
use parse::ParseStream;
use private;
use token;

pub struct Parens<'a> {
    pub token: token::Paren,
    pub content: ParseBuffer<'a>,
}

pub struct Braces<'a> {
    pub token: token::Brace,
    pub content: ParseBuffer<'a>,
}

pub struct Brackets<'a> {
    pub token: token::Bracket,
    pub content: ParseBuffer<'a>,
}

#[cfg(any(feature = "full", feature = "derive"))]
pub struct Group<'a> {
    pub token: token::Group,
    pub content: ParseBuffer<'a>,
}

impl<'a> ParseBuffer<'a> {
    fn parse_delimited(&self, delimiter: Delimiter) -> Result<(Span, ParseBuffer<'a>)> {
        self.step(|cursor| {
            if let Some((content, span, rest)) = cursor.group(delimiter) {
                let unexpected = private::get_unexpected(self);
                let content =
                    private::new_parse_buffer(span, cursor.advance(content), unexpected);
                Ok(((span, content), rest))
            } else {
                let message = match delimiter {
                    Delimiter::Parenthesis => "expected parentheses",
                    Delimiter::Brace => "expected curly braces",
                    Delimiter::Bracket => "expected square brackets",
                    Delimiter::None => "expected invisible group",
                };
                Err(cursor.error(message))
            }
        })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_parens(&self) -> Result<Parens<'a>> {
        self.parse_delimited(Delimiter::Parenthesis)
            .map(|(span, content)| Parens {
                token: token::Paren(span),
                content: content,
            })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_braces(&self) -> Result<Braces<'a>> {
        self.parse_delimited(Delimiter::Brace)
            .map(|(span, content)| Braces {
                token: token::Brace(span),
                content: content,
            })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_brackets(&self) -> Result<Brackets<'a>> {
        self.parse_delimited(Delimiter::Bracket)
            .map(|(span, content)| Brackets {
                token: token::Bracket(span),
                content: content,
            })
    }
}

#[cfg(any(feature = "full", feature = "derive"))]
impl private {
    pub fn parse_group(input: ParseStream) -> Result<Group> {
        input.parse_delimited(Delimiter::None)
            .map(|(span, content)| Group {
                token: token::Group(span),
                content: content,
            })
    }
}

/// Parse a set of parentheses and expose their content to subsequent parsers.
///
/// ```rust
/// # #[macro_use]
/// # extern crate quote;
/// #
/// extern crate syn;
///
/// use syn::{parenthesized, token, Ident, Token, Type};
/// use syn::parse::{Parse, ParseStream, Result};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified tuple struct syntax like:
/// //
/// //     struct S(A, B);
/// struct TupleStruct {
///     struct_token: Token![struct],
///     ident: Ident,
///     paren_token: token::Paren,
///     fields: Punctuated<Type, Token![,]>,
///     semi_token: Token![;],
/// }
///
/// impl Parse for TupleStruct {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(TupleStruct {
///             struct_token: input.parse()?,
///             ident: input.parse()?,
///             paren_token: parenthesized!(content in input),
///             fields: content.parse_terminated(Type::parse)?,
///             semi_token: input.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         struct S(A, B);
/// #     };
/// #     syn::parse2::<TupleStruct>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! parenthesized {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_parens(&$cursor) {
            $crate::export::Ok(parens) => {
                $content = parens.content;
                parens.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}

/// Parse a set of curly braces and expose their content to subsequent parsers.
///
/// ```rust
/// # extern crate quote;
/// # use quote::quote;
/// #
/// extern crate syn;
///
/// use syn::{braced, token, Ident, Token, Type};
/// use syn::parse::{Parse, ParseStream, Result};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified struct syntax like:
/// //
/// //     struct S {
/// //         a: A,
/// //         b: B,
/// //     }
/// struct Struct {
///     struct_token: Token![struct],
///     ident: Ident,
///     brace_token: token::Brace,
///     fields: Punctuated<Field, Token![,]>,
/// }
///
/// struct Field {
///     name: Ident,
///     colon_token: Token![:],
///     ty: Type,
/// }
///
/// impl Parse for Struct {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(Struct {
///             struct_token: input.parse()?,
///             ident: input.parse()?,
///             brace_token: braced!(content in input),
///             fields: content.parse_terminated(Field::parse)?,
///         })
///     }
/// }
///
/// impl Parse for Field {
///     fn parse(input: ParseStream) -> Result<Self> {
///         Ok(Field {
///             name: input.parse()?,
///             colon_token: input.parse()?,
///             ty: input.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         struct S {
/// #             a: A,
/// #             b: B,
/// #         }
/// #     };
/// #     syn::parse2::<Struct>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! braced {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_braces(&$cursor) {
            $crate::export::Ok(braces) => {
                $content = braces.content;
                braces.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}

/// Parse a set of square brackets and expose their content to subsequent
/// parsers.
///
/// ```rust
/// # #[macro_use]
/// # extern crate quote;
/// #
/// extern crate proc_macro2;
/// extern crate syn;
///
/// use proc_macro2::TokenStream;
/// use syn::{bracketed, token, Token};
/// use syn::parse::{Parse, ParseStream, Result};
///
/// // Parse an outer attribute like:
/// //
/// //     #[repr(C, packed)]
/// struct OuterAttribute {
///     pound_token: Token![#],
///     bracket_token: token::Bracket,
///     content: TokenStream,
/// }
///
/// impl Parse for OuterAttribute {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(OuterAttribute {
///             pound_token: input.parse()?,
///             bracket_token: bracketed!(content in input),
///             content: content.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         #[repr(C, packed)]
/// #     };
/// #     syn::parse2::<OuterAttribute>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! bracketed {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_brackets(&$cursor) {
            $crate::export::Ok(brackets) => {
                $content = brackets.content;
                brackets.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}
<commit_msg>Add a heading to group macro examples<commit_after>use proc_macro2::{Delimiter, Span};

use error::Result;
use parse::ParseBuffer;
#[cfg(any(feature = "full", feature = "derive"))]
use parse::ParseStream;
use private;
use token;

pub struct Parens<'a> {
    pub token: token::Paren,
    pub content: ParseBuffer<'a>,
}

pub struct Braces<'a> {
    pub token: token::Brace,
    pub content: ParseBuffer<'a>,
}

pub struct Brackets<'a> {
    pub token: token::Bracket,
    pub content: ParseBuffer<'a>,
}

#[cfg(any(feature = "full", feature = "derive"))]
pub struct Group<'a> {
    pub token: token::Group,
    pub content: ParseBuffer<'a>,
}

impl<'a> ParseBuffer<'a> {
    fn parse_delimited(&self, delimiter: Delimiter) -> Result<(Span, ParseBuffer<'a>)> {
        self.step(|cursor| {
            if let Some((content, span, rest)) = cursor.group(delimiter) {
                let unexpected = private::get_unexpected(self);
                let content =
                    private::new_parse_buffer(span, cursor.advance(content), unexpected);
                Ok(((span, content), rest))
            } else {
                let message = match delimiter {
                    Delimiter::Parenthesis => "expected parentheses",
                    Delimiter::Brace => "expected curly braces",
                    Delimiter::Bracket => "expected square brackets",
                    Delimiter::None => "expected invisible group",
                };
                Err(cursor.error(message))
            }
        })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_parens(&self) -> Result<Parens<'a>> {
        self.parse_delimited(Delimiter::Parenthesis)
            .map(|(span, content)| Parens {
                token: token::Paren(span),
                content: content,
            })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_braces(&self) -> Result<Braces<'a>> {
        self.parse_delimited(Delimiter::Brace)
            .map(|(span, content)| Braces {
                token: token::Brace(span),
                content: content,
            })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_brackets(&self) -> Result<Brackets<'a>> {
        self.parse_delimited(Delimiter::Bracket)
            .map(|(span, content)| Brackets {
                token: token::Bracket(span),
                content: content,
            })
    }
}

#[cfg(any(feature = "full", feature = "derive"))]
impl private {
    pub fn parse_group(input: ParseStream) -> Result<Group> {
        input.parse_delimited(Delimiter::None)
            .map(|(span, content)| Group {
                token: token::Group(span),
                content: content,
            })
    }
}

/// Parse a set of parentheses and expose their content to subsequent parsers.
///
/// # Example
///
/// ```rust
/// # #[macro_use]
/// # extern crate quote;
/// #
/// extern crate syn;
///
/// use syn::{parenthesized, token, Ident, Token, Type};
/// use syn::parse::{Parse, ParseStream, Result};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified tuple struct syntax like:
/// //
/// //     struct S(A, B);
/// struct TupleStruct {
///     struct_token: Token![struct],
///     ident: Ident,
///     paren_token: token::Paren,
///     fields: Punctuated<Type, Token![,]>,
///     semi_token: Token![;],
/// }
///
/// impl Parse for TupleStruct {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(TupleStruct {
///             struct_token: input.parse()?,
///             ident: input.parse()?,
///             paren_token: parenthesized!(content in input),
///             fields: content.parse_terminated(Type::parse)?,
///             semi_token: input.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         struct S(A, B);
/// #     };
/// #     syn::parse2::<TupleStruct>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! parenthesized {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_parens(&$cursor) {
            $crate::export::Ok(parens) => {
                $content = parens.content;
                parens.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}

/// Parse a set of curly braces and expose their content to subsequent parsers.
///
/// # Example
///
/// ```rust
/// # extern crate quote;
/// # use quote::quote;
/// #
/// extern crate syn;
///
/// use syn::{braced, token, Ident, Token, Type};
/// use syn::parse::{Parse, ParseStream, Result};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified struct syntax like:
/// //
/// //     struct S {
/// //         a: A,
/// //         b: B,
/// //     }
/// struct Struct {
///     struct_token: Token![struct],
///     ident: Ident,
///     brace_token: token::Brace,
///     fields: Punctuated<Field, Token![,]>,
/// }
///
/// struct Field {
///     name: Ident,
///     colon_token: Token![:],
///     ty: Type,
/// }
///
/// impl Parse for Struct {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(Struct {
///             struct_token: input.parse()?,
///             ident: input.parse()?,
///             brace_token: braced!(content in input),
///             fields: content.parse_terminated(Field::parse)?,
///         })
///     }
/// }
///
/// impl Parse for Field {
///     fn parse(input: ParseStream) -> Result<Self> {
///         Ok(Field {
///             name: input.parse()?,
///             colon_token: input.parse()?,
///             ty: input.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         struct S {
/// #             a: A,
/// #             b: B,
/// #         }
/// #     };
/// #     syn::parse2::<Struct>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! braced {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_braces(&$cursor) {
            $crate::export::Ok(braces) => {
                $content = braces.content;
                braces.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}

/// Parse a set of square brackets and expose their content to subsequent
/// parsers.
///
/// # Example
///
/// ```rust
/// # #[macro_use]
/// # extern crate quote;
/// #
/// extern crate proc_macro2;
/// extern crate syn;
///
/// use proc_macro2::TokenStream;
/// use syn::{bracketed, token, Token};
/// use syn::parse::{Parse, ParseStream, Result};
///
/// // Parse an outer attribute like:
/// //
/// //     #[repr(C, packed)]
/// struct OuterAttribute {
///     pound_token: Token![#],
///     bracket_token: token::Bracket,
///     content: TokenStream,
/// }
///
/// impl Parse for OuterAttribute {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(OuterAttribute {
///             pound_token: input.parse()?,
///             bracket_token: bracketed!(content in input),
///             content: content.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         #[repr(C, packed)]
/// #     };
/// #     syn::parse2::<OuterAttribute>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! bracketed {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_brackets(&$cursor) {
            $crate::export::Ok(brackets) => {
                $content = brackets.content;
                brackets.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}
<|endoftext|>


<commit_before>//! User-input events and their effects.
//!
//! * Every user input the application receives is converted to an
//!   [`Event`](./enum.Event.html).
//! * Each event is then given to the root, and descends the view tree down to
//!   the view currently in focus, through the
//!   [`on_event`](../view/trait.View.html#method.on_event) method.
//!     * If the view consumes the event, it may return a callback to be
//!       executed.
//!     * Otherwise, it ignores the event, and the view parent can in turn
//!       choose to consume it or not.
//! * If no view consumes the event, the
//!   [global callback](../struct.Cursive.html#method.add_global_callback)
//!   table is checked.

use std::any::Any;
use std::cell::RefCell;
use std::ops::Deref;
use std::rc::Rc;
use vec::Vec2;
use Cursive;

/// Callback is a function that can be triggered by an event.
/// It has a mutable access to the cursive root.
#[derive(Clone)]
pub struct Callback(Rc<Box<Fn(&mut Cursive)>>);
// TODO: remove the Box when Box<T: Sized> -> Rc<T> is possible

/// A boxed callback that can be run on `&mut Any`.
pub type AnyCb<'a> = Box<FnMut(&mut Any) + 'a>;

impl Callback {
    /// Wraps the given function into a `Callback` object.
    pub fn from_fn<F>(f: F) -> Self
    where
        F: 'static + Fn(&mut Cursive),
    {
        Callback(Rc::new(Box::new(move |siv| {
            f(siv);
        })))
    }

    /// Wrap a `FnMut` into a `Callback` object.
    ///
    /// If this methods tries to call itself, nested calls will be no-ops.
    pub fn from_fn_mut<F>(f: F) -> Self
    where
        F: 'static + FnMut(&mut Cursive),
    {
        let cb = RefCell::new(f);

        Self::from_fn(move |s| {
            if let Ok(mut cb) = cb.try_borrow_mut() {
                (&mut *cb)(s);
            }
        })
    }

    /// Returns a dummy callback that doesn't run anything.
    pub fn dummy() -> Self {
        Callback::from_fn(|_| ())
    }
}

impl Deref for Callback {
    type Target = Box<Fn(&mut Cursive)>;
    fn deref<'a>(&'a self) -> &'a Box<Fn(&mut Cursive)> {
        &self.0
    }
}

impl From<Rc<Box<Fn(&mut Cursive)>>> for Callback {
    fn from(f: Rc<Box<Fn(&mut Cursive)>>) -> Self {
        Callback(f)
    }
}

impl From<Box<Fn(&mut Cursive) + Send>> for Callback {
    fn from(f: Box<Fn(&mut Cursive) + Send>) -> Self {
        Callback(Rc::new(f))
    }
}

impl From<Box<Fn(&mut Cursive)>> for Callback {
    fn from(f: Box<Fn(&mut Cursive)>) -> Self {
        Callback(Rc::new(f))
    }
}

/// Answer to an event notification.
/// The event can be consumed or ignored.
pub enum EventResult {
    /// The event was ignored. The parent can keep handling it.
    Ignored,
    /// The event was consumed. An optionnal callback to run is attached.
    Consumed(Option<Callback>), // TODO: make this a FnOnce?
}

impl EventResult {
    /// Convenient method to create `Consumed(Some(f))`
    pub fn with_cb<F>(f: F) -> Self
    where
        F: 'static + Fn(&mut Cursive),
    {
        EventResult::Consumed(Some(Callback::from_fn(f)))
    }

    /// Returns `true` if `self` is `EventResult::Consumed`.
    pub fn is_consumed(&self) -> bool {
        match *self {
            EventResult::Consumed(_) => true,
            _ => false,
        }
    }

    /// Returns `true` if `self` contains a callback.
    pub fn has_callback(&self) -> bool {
        match *self {
            EventResult::Consumed(Some(_)) => true,
            _ => false,
        }
    }

    /// Process this result if it is a callback.
    ///
    /// Does nothing otherwise.
    pub fn process(self, s: &mut Cursive) {
        if let EventResult::Consumed(Some(cb)) = self {
            cb(s);
        }
    }

    /// Returns `self` if it is not `EventResult::Ignored`, otherwise returns `f()`.
    pub fn or_else<F>(self, f: F) -> Self
    where
        F: FnOnce() -> EventResult,
    {
        match self {
            EventResult::Ignored => f(),
            other => other,
        }
    }
}

/// A non-character key on the keyboard
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum Key {
    /// Both Enter (or Return) and numpad Enter
    Enter,
    /// Tabulation key
    Tab,
    /// Backspace key
    Backspace,
    /// Escape key
    Esc,

    /// Left arrow
    Left,
    /// Right arrow
    Right,
    /// Up arrow
    Up,
    /// Down arrow
    Down,

    /// Insert key
    Ins,
    /// Delete key
    Del,
    /// Home key
    Home,
    /// End key
    End,
    /// Page Up key
    PageUp,
    /// Page Down key
    PageDown,

    /// Pause Break key
    PauseBreak,

    /// The 5 in the center of the keypad, when numlock is disabled.
    NumpadCenter,

    /// F0 key
    F0,
    /// F1 key
    F1,
    /// F2 key
    F2,
    /// F3 key
    F3,
    /// F4 key
    F4,
    /// F5 key
    F5,
    /// F6 key
    F6,
    /// F7 key
    F7,
    /// F8 key
    F8,
    /// F9 key
    F9,
    /// F10 key
    F10,
    /// F11 key
    F11,
    /// F12 key
    F12,
}

impl Key {
    /// Returns the function key corresponding to the given number
    ///
    /// 1 -> F1, etc...
    ///
    /// # Panics
    ///
    /// If `n == 0 || n > 12`
    pub fn from_f(n: u8) -> Key {
        match n {
            0 => Key::F0,
            1 => Key::F1,
            2 => Key::F2,
            3 => Key::F3,
            4 => Key::F4,
            5 => Key::F5,
            6 => Key::F6,
            7 => Key::F7,
            8 => Key::F8,
            9 => Key::F9,
            10 => Key::F10,
            11 => Key::F11,
            12 => Key::F12,
            _ => panic!("unknown function key: F{}", n),
        }
    }
}

/// One of the buttons present on the mouse
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum MouseButton {
    /// The left button, used for main actions.
    Left,
    /// Middle button, probably the wheel. Often pastes text in X11 on linux.
    Middle,
    /// The right button, for special actions.
    Right,

    /// Fourth button if the mouse supports it.
    Button4,
    /// Fifth button if the mouse supports it.
    Button5,

    // TODO: handle more buttons?
    #[doc(hidden)]
    Other,
}

/// Represents a possible event sent by the mouse.
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum MouseEvent {
    /// A button was pressed.
    Press(MouseButton),
    /// A button was released.
    Release(MouseButton),
    /// A button is being held.
    Hold(MouseButton),
    /// The wheel was moved up.
    WheelUp,
    /// The wheel was moved down.
    WheelDown,
}

impl MouseEvent {
    /// Returns the button used by this event, if any.
    ///
    /// Returns `None` if `self` is `WheelUp` or `WheelDown`.
    pub fn button(self) -> Option<MouseButton> {
        match self {
            MouseEvent::Press(btn)
            | MouseEvent::Release(btn)
            | MouseEvent::Hold(btn) => Some(btn),
            _ => None,
        }
    }

    /// Returns `true` if `self` is an event that can grab focus.
    ///
    /// This includes `Press`, `WheelUp` and `WheelDown`.
    pub fn grabs_focus(self) -> bool {
        match self {
            MouseEvent::Press(_)
            | MouseEvent::WheelUp
            | MouseEvent::WheelDown => true,
            _ => false,
        }
    }
}

/// Represents an event as seen by the application.
#[derive(PartialEq, Eq, Clone, Hash, Debug)]
pub enum Event {
    /// Event fired when the window is resized.
    WindowResize,

    /// Event fired regularly when a auto-refresh is set.
    Refresh,

    // TODO: have Char(modifier, char) and Key(modifier, key) enums?
    /// A character was entered (includes numbers, punctuation, ...).
    Char(char),
    /// A character was entered with the Ctrl key pressed.
    CtrlChar(char),
    /// A character was entered with the Alt key pressed.
    AltChar(char),

    /// A non-character key was pressed.
    Key(Key),
    /// A non-character key was pressed with the Shift key pressed.
    Shift(Key),
    /// A non-character key was pressed with the Alt key pressed.
    Alt(Key),
    /// A non-character key was pressed with the Shift and Alt keys pressed.
    AltShift(Key),
    /// A non-character key was pressed with the Ctrl key pressed.
    Ctrl(Key),
    /// A non-character key was pressed with the Ctrl and Shift keys pressed.
    CtrlShift(Key),
    /// A non-character key was pressed with the Ctrl and Alt keys pressed.
    CtrlAlt(Key),

    /// A mouse event was sent.
    Mouse {
        /// Position of the top-left corner of the view receiving this event.
        offset: Vec2,
        /// Position of the mouse when this event was fired.
        position: Vec2,
        /// The mouse event itself.
        event: MouseEvent,
    },

    // TODO: use a backend-dependent type for the unknown values?
    /// An unknown event was received.
    Unknown(Vec<u8>),

    // Maybe add a `Custom(Rc<Any>)` ?

    // Having a doc-hidden event prevents people from having exhaustive
    // matches, allowing us to add events in the future.
    #[doc(hidden)]
    /// The application is about to exit.
    Exit,
}

impl Event {
    /// Returns the position of the mouse, if `self` is a mouse event.
    pub fn mouse_position(&self) -> Option<Vec2> {
        if let Event::Mouse { position, .. } = *self {
            Some(position)
        } else {
            None
        }
    }

    /// Returns a mutable reference to the position of the mouse/
    ///
    /// Returns `None` if `self` is not a mouse event.
    pub fn mouse_position_mut(&mut self) -> Option<&mut Vec2> {
        if let Event::Mouse {
            ref mut position, ..
        } = *self
        {
            Some(position)
        } else {
            None
        }
    }

    /// Update `self` with the given offset.
    ///
    /// If `self` is a mouse event, adds `top_left` to its offset.
    /// Otherwise, do nothing.
    pub fn relativize<V>(&mut self, top_left: V)
    where
        V: Into<Vec2>,
    {
        if let Event::Mouse { ref mut offset, .. } = *self {
            *offset = *offset + top_left;
        }
    }

    /// Returns a cloned, relativized event.
    ///
    /// If `self` is a mouse event, adds `top_left` to its offset.
    /// Otherwise, returns a simple clone.
    pub fn relativized<V>(&self, top_left: V) -> Self
    where
        V: Into<Vec2>,
    {
        let mut result = self.clone();
        result.relativize(top_left);
        result
    }
}

impl From<char> for Event {
    fn from(c: char) -> Event {
        Event::Char(c)
    }
}

impl From<Key> for Event {
    fn from(k: Key) -> Event {
        Event::Key(k)
    }
}
<commit_msg>Add EventResult::and<commit_after>//! User-input events and their effects.
//!
//! * Every user input the application receives is converted to an
//!   [`Event`](./enum.Event.html).
//! * Each event is then given to the root, and descends the view tree down to
//!   the view currently in focus, through the
//!   [`on_event`](../view/trait.View.html#method.on_event) method.
//!     * If the view consumes the event, it may return a callback to be
//!       executed.
//!     * Otherwise, it ignores the event, and the view parent can in turn
//!       choose to consume it or not.
//! * If no view consumes the event, the
//!   [global callback](../struct.Cursive.html#method.add_global_callback)
//!   table is checked.

use std::any::Any;
use std::cell::RefCell;
use std::ops::Deref;
use std::rc::Rc;
use vec::Vec2;
use Cursive;

/// Callback is a function that can be triggered by an event.
/// It has a mutable access to the cursive root.
#[derive(Clone)]
pub struct Callback(Rc<Box<Fn(&mut Cursive)>>);
// TODO: remove the Box when Box<T: Sized> -> Rc<T> is possible

/// A boxed callback that can be run on `&mut Any`.
pub type AnyCb<'a> = Box<FnMut(&mut Any) + 'a>;

impl Callback {
    /// Wraps the given function into a `Callback` object.
    pub fn from_fn<F>(f: F) -> Self
    where
        F: 'static + Fn(&mut Cursive),
    {
        Callback(Rc::new(Box::new(move |siv| {
            f(siv);
        })))
    }

    /// Wrap a `FnMut` into a `Callback` object.
    ///
    /// If this methods tries to call itself, nested calls will be no-ops.
    pub fn from_fn_mut<F>(f: F) -> Self
    where
        F: 'static + FnMut(&mut Cursive),
    {
        let cb = RefCell::new(f);

        Self::from_fn(move |s| {
            if let Ok(mut cb) = cb.try_borrow_mut() {
                (&mut *cb)(s);
            }
        })
    }

    /// Returns a dummy callback that doesn't run anything.
    pub fn dummy() -> Self {
        Callback::from_fn(|_| ())
    }
}

impl Deref for Callback {
    type Target = Box<Fn(&mut Cursive)>;
    fn deref<'a>(&'a self) -> &'a Box<Fn(&mut Cursive)> {
        &self.0
    }
}

impl From<Rc<Box<Fn(&mut Cursive)>>> for Callback {
    fn from(f: Rc<Box<Fn(&mut Cursive)>>) -> Self {
        Callback(f)
    }
}

impl From<Box<Fn(&mut Cursive) + Send>> for Callback {
    fn from(f: Box<Fn(&mut Cursive) + Send>) -> Self {
        Callback(Rc::new(f))
    }
}

impl From<Box<Fn(&mut Cursive)>> for Callback {
    fn from(f: Box<Fn(&mut Cursive)>) -> Self {
        Callback(Rc::new(f))
    }
}

/// Answer to an event notification.
/// The event can be consumed or ignored.
pub enum EventResult {
    /// The event was ignored. The parent can keep handling it.
    Ignored,
    /// The event was consumed. An optionnal callback to run is attached.
    Consumed(Option<Callback>), // TODO: make this a FnOnce?
}

impl EventResult {
    /// Convenient method to create `Consumed(Some(f))`
    pub fn with_cb<F>(f: F) -> Self
    where
        F: 'static + Fn(&mut Cursive),
    {
        EventResult::Consumed(Some(Callback::from_fn(f)))
    }

    /// Returns `true` if `self` is `EventResult::Consumed`.
    pub fn is_consumed(&self) -> bool {
        match *self {
            EventResult::Consumed(_) => true,
            _ => false,
        }
    }

    /// Returns `true` if `self` contains a callback.
    pub fn has_callback(&self) -> bool {
        match *self {
            EventResult::Consumed(Some(_)) => true,
            _ => false,
        }
    }

    /// Process this result if it is a callback.
    ///
    /// Does nothing otherwise.
    pub fn process(self, s: &mut Cursive) {
        if let EventResult::Consumed(Some(cb)) = self {
            cb(s);
        }
    }

    /// Returns `self` if it is not `EventResult::Ignored`, otherwise returns `f()`.
    pub fn or_else<F>(self, f: F) -> Self
    where
        F: FnOnce() -> EventResult,
    {
        match self {
            EventResult::Ignored => f(),
            other => other,
        }
    }

    /// Returns an event result that combines `self` and `other`.
    pub fn and(self, other: Self) -> Self {
        match (self, other) {
            (EventResult::Ignored, result)
            | (result, EventResult::Ignored) => result,
            (EventResult::Consumed(None), EventResult::Consumed(cb))
            | (EventResult::Consumed(cb), EventResult::Consumed(None)) => {
                EventResult::Consumed(cb)
            }
            (
                EventResult::Consumed(Some(cb1)),
                EventResult::Consumed(Some(cb2)),
            ) => EventResult::with_cb(move |siv| {
                (cb1)(siv);
                (cb2)(siv);
            }),
        }
    }
}

/// A non-character key on the keyboard
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum Key {
    /// Both Enter (or Return) and numpad Enter
    Enter,
    /// Tabulation key
    Tab,
    /// Backspace key
    Backspace,
    /// Escape key
    Esc,

    /// Left arrow
    Left,
    /// Right arrow
    Right,
    /// Up arrow
    Up,
    /// Down arrow
    Down,

    /// Insert key
    Ins,
    /// Delete key
    Del,
    /// Home key
    Home,
    /// End key
    End,
    /// Page Up key
    PageUp,
    /// Page Down key
    PageDown,

    /// Pause Break key
    PauseBreak,

    /// The 5 in the center of the keypad, when numlock is disabled.
    NumpadCenter,

    /// F0 key
    F0,
    /// F1 key
    F1,
    /// F2 key
    F2,
    /// F3 key
    F3,
    /// F4 key
    F4,
    /// F5 key
    F5,
    /// F6 key
    F6,
    /// F7 key
    F7,
    /// F8 key
    F8,
    /// F9 key
    F9,
    /// F10 key
    F10,
    /// F11 key
    F11,
    /// F12 key
    F12,
}

impl Key {
    /// Returns the function key corresponding to the given number
    ///
    /// 1 -> F1, etc...
    ///
    /// # Panics
    ///
    /// If `n == 0 || n > 12`
    pub fn from_f(n: u8) -> Key {
        match n {
            0 => Key::F0,
            1 => Key::F1,
            2 => Key::F2,
            3 => Key::F3,
            4 => Key::F4,
            5 => Key::F5,
            6 => Key::F6,
            7 => Key::F7,
            8 => Key::F8,
            9 => Key::F9,
            10 => Key::F10,
            11 => Key::F11,
            12 => Key::F12,
            _ => panic!("unknown function key: F{}", n),
        }
    }
}

/// One of the buttons present on the mouse
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum MouseButton {
    /// The left button, used for main actions.
    Left,
    /// Middle button, probably the wheel. Often pastes text in X11 on linux.
    Middle,
    /// The right button, for special actions.
    Right,

    /// Fourth button if the mouse supports it.
    Button4,
    /// Fifth button if the mouse supports it.
    Button5,

    // TODO: handle more buttons?
    #[doc(hidden)]
    Other,
}

/// Represents a possible event sent by the mouse.
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum MouseEvent {
    /// A button was pressed.
    Press(MouseButton),
    /// A button was released.
    Release(MouseButton),
    /// A button is being held.
    Hold(MouseButton),
    /// The wheel was moved up.
    WheelUp,
    /// The wheel was moved down.
    WheelDown,
}

impl MouseEvent {
    /// Returns the button used by this event, if any.
    ///
    /// Returns `None` if `self` is `WheelUp` or `WheelDown`.
    pub fn button(self) -> Option<MouseButton> {
        match self {
            MouseEvent::Press(btn)
            | MouseEvent::Release(btn)
            | MouseEvent::Hold(btn) => Some(btn),
            _ => None,
        }
    }

    /// Returns `true` if `self` is an event that can grab focus.
    ///
    /// This includes `Press`, `WheelUp` and `WheelDown`.
    pub fn grabs_focus(self) -> bool {
        match self {
            MouseEvent::Press(_)
            | MouseEvent::WheelUp
            | MouseEvent::WheelDown => true,
            _ => false,
        }
    }
}

/// Represents an event as seen by the application.
#[derive(PartialEq, Eq, Clone, Hash, Debug)]
pub enum Event {
    /// Event fired when the window is resized.
    WindowResize,

    /// Event fired regularly when a auto-refresh is set.
    Refresh,

    // TODO: have Char(modifier, char) and Key(modifier, key) enums?
    /// A character was entered (includes numbers, punctuation, ...).
    Char(char),
    /// A character was entered with the Ctrl key pressed.
    CtrlChar(char),
    /// A character was entered with the Alt key pressed.
    AltChar(char),

    /// A non-character key was pressed.
    Key(Key),
    /// A non-character key was pressed with the Shift key pressed.
    Shift(Key),
    /// A non-character key was pressed with the Alt key pressed.
    Alt(Key),
    /// A non-character key was pressed with the Shift and Alt keys pressed.
    AltShift(Key),
    /// A non-character key was pressed with the Ctrl key pressed.
    Ctrl(Key),
    /// A non-character key was pressed with the Ctrl and Shift keys pressed.
    CtrlShift(Key),
    /// A non-character key was pressed with the Ctrl and Alt keys pressed.
    CtrlAlt(Key),

    /// A mouse event was sent.
    Mouse {
        /// Position of the top-left corner of the view receiving this event.
        offset: Vec2,
        /// Position of the mouse when this event was fired.
        position: Vec2,
        /// The mouse event itself.
        event: MouseEvent,
    },

    // TODO: use a backend-dependent type for the unknown values?
    /// An unknown event was received.
    Unknown(Vec<u8>),

    // Maybe add a `Custom(Rc<Any>)` ?

    // Having a doc-hidden event prevents people from having exhaustive
    // matches, allowing us to add events in the future.
    #[doc(hidden)]
    /// The application is about to exit.
    Exit,
}

impl Event {
    /// Returns the position of the mouse, if `self` is a mouse event.
    pub fn mouse_position(&self) -> Option<Vec2> {
        if let Event::Mouse { position, .. } = *self {
            Some(position)
        } else {
            None
        }
    }

    /// Returns a mutable reference to the position of the mouse/
    ///
    /// Returns `None` if `self` is not a mouse event.
    pub fn mouse_position_mut(&mut self) -> Option<&mut Vec2> {
        if let Event::Mouse {
            ref mut position, ..
        } = *self
        {
            Some(position)
        } else {
            None
        }
    }

    /// Update `self` with the given offset.
    ///
    /// If `self` is a mouse event, adds `top_left` to its offset.
    /// Otherwise, do nothing.
    pub fn relativize<V>(&mut self, top_left: V)
    where
        V: Into<Vec2>,
    {
        if let Event::Mouse { ref mut offset, .. } = *self {
            *offset = *offset + top_left;
        }
    }

    /// Returns a cloned, relativized event.
    ///
    /// If `self` is a mouse event, adds `top_left` to its offset.
    /// Otherwise, returns a simple clone.
    pub fn relativized<V>(&self, top_left: V) -> Self
    where
        V: Into<Vec2>,
    {
        let mut result = self.clone();
        result.relativize(top_left);
        result
    }
}

impl From<char> for Event {
    fn from(c: char) -> Event {
        Event::Char(c)
    }
}

impl From<Key> for Event {
    fn from(k: Key) -> Event {
        Event::Key(k)
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};

use proc_macro2::Term;
use unicode_xid::UnicodeXID;

use proc_macro2::Span;

/// A word of Rust code, which may be a keyword or legal variable name.
///
/// An identifier consists of at least one Unicode code point, the first of
/// which has the XID_Start property and the rest of which have the XID_Continue
/// property. An underscore may be used as the first character as long as it is
/// not the only character.
///
/// - The empty string is not an identifier. Use `Option<Ident>`.
/// - An underscore by itself is not an identifier. Use
///   `Token![_]` instead.
/// - A lifetime is not an identifier. Use `syn::Lifetime` instead.
///
/// An identifier constructed with `Ident::new` is permitted to be a Rust
/// keyword, though parsing one through its [`Synom`] implementation rejects
/// Rust keywords.
///
/// [`Synom`]: synom/trait.Synom.html
///
/// # Examples
///
/// A new ident can be created from a string using the `Ident::from` function.
/// Idents produced by `Ident::from` are set to resolve at the procedural macro
/// *def site* by default. A different span can be provided explicitly by using
/// `Ident::new`.
///
/// ```rust
/// extern crate syn;
/// extern crate proc_macro2;
///
/// use syn::Ident;
/// use proc_macro2::Span;
///
/// fn main() {
///     let def_ident = Ident::from("definitely");
///     let call_ident = Ident::new("calligraphy", Span::call_site());
///
///     println!("{} {}", def_ident, call_ident);
/// }
/// ```
///
/// An ident can be interpolated into a token stream using the `quote!` macro.
///
/// ```rust
/// #[macro_use]
/// extern crate quote;
///
/// extern crate syn;
/// use syn::Ident;
///
/// fn main() {
///     let ident = Ident::from("demo");
///
///     // Create a variable binding whose name is this ident.
///     let expanded = quote! { let #ident = 10; };
///
///     // Create a variable binding with a slightly different name.
///     let temp_ident = Ident::from(format!("new_{}", ident));
///     let expanded = quote! { let #temp_ident = 10; };
/// }
/// ```
///
/// A string representation of the ident is available through the `as_ref()` and
/// `to_string()` methods.
///
/// ```rust
/// # use syn::Ident;
/// # let ident = Ident::from("another_identifier");
/// #
/// // Examine the ident as a &str.
/// let ident_str = ident.as_ref();
/// if ident_str.len() > 60 {
///     println!("Very long identifier: {}", ident_str)
/// }
///
/// // Create a String from the ident.
/// let ident_string = ident.to_string();
/// give_away(ident_string);
///
/// fn give_away(s: String) { /* ... */ }
/// ```
#[derive(Copy, Clone, Debug)]
pub struct Ident {
    term: Term,
}

impl Ident {
    /// Creates an ident with the given string representation.
    ///
    /// # Panics
    ///
    /// Panics if the input string is neither a keyword nor a legal variable
    /// name.
    pub fn new(s: &str, span: Span) -> Self {
        if s.is_empty() {
            panic!("ident is not allowed to be empty; use Option<Ident>");
        }

        if s.starts_with('\'') {
            panic!("ident is not allowed to be a lifetime; use syn::Lifetime");
        }

        if s.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
            panic!("ident cannot be a number, use syn::Index instead");
        }

        fn xid_ok(s: &str) -> bool {
            let mut chars = s.chars();
            let first = chars.next().unwrap();
            if !(UnicodeXID::is_xid_start(first) || first == '_') {
                return false;
            }
            for ch in chars {
                if !UnicodeXID::is_xid_continue(ch) {
                    return false;
                }
            }
            true
        }

        if !xid_ok(s) {
            panic!("{:?} is not a valid ident", s);
        }

        Ident {
            term: Term::new(s, span),
        }
    }

    pub fn span(&self) -> Span {
        self.term.span()
    }

    pub fn set_span(&mut self, span: Span) {
        self.term.set_span(span);
    }
}

impl<'a> From<&'a str> for Ident {
    fn from(s: &str) -> Self {
        Ident::new(s, Span::call_site())
    }
}

impl From<Token![self]> for Ident {
    fn from(tok: Token![self]) -> Self {
        Ident::new("self", tok.0)
    }
}

impl From<Token![Self]> for Ident {
    fn from(tok: Token![Self]) -> Self {
        Ident::new("Self", tok.0)
    }
}

impl From<Token![super]> for Ident {
    fn from(tok: Token![super]) -> Self {
        Ident::new("super", tok.0)
    }
}

impl From<Token![crate]> for Ident {
    fn from(tok: Token![crate]) -> Self {
        Ident::new("crate", tok.0)
    }
}

impl<'a> From<Cow<'a, str>> for Ident {
    fn from(s: Cow<'a, str>) -> Self {
        Ident::new(&s, Span::call_site())
    }
}

impl From<String> for Ident {
    fn from(s: String) -> Self {
        Ident::new(&s, Span::call_site())
    }
}

impl AsRef<str> for Ident {
    fn as_ref(&self) -> &str {
        self.term.as_str()
    }
}

impl Display for Ident {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.term.as_str().fmt(formatter)
    }
}

impl<T: ?Sized> PartialEq<T> for Ident
where
    T: AsRef<str>,
{
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl Eq for Ident {}

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

impl Ord for Ident {
    fn cmp(&self, other: &Ident) -> Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl Hash for Ident {
    fn hash<H: Hasher>(&self, h: &mut H) {
        self.as_ref().hash(h);
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use buffer::Cursor;
    use parse_error;
    use synom::PResult;
    use synom::Synom;

    impl Synom for Ident {
        fn parse(input: Cursor) -> PResult<Self> {
            let (term, rest) = match input.term() {
                Some(term) => term,
                _ => return parse_error(),
            };
            if term.as_str().starts_with('\'') {
                return parse_error();
            }
            match term.as_str() {
                "_"
                // From https://doc.rust-lang.org/grammar.html#keywords
                | "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const"
                | "continue" | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final"
                | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match"
                | "mod" | "move" | "mut" | "offsetof" | "override" | "priv" | "proc" | "pub"
                | "pure" | "ref" | "return" | "Self" | "self" | "sizeof" | "static" | "struct"
                | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use"
                | "virtual" | "where" | "while" | "yield" => return parse_error(),
                _ => {}
            }

            Ok((Ident { term: term }, rest))
        }

        fn description() -> Option<&'static str> {
            Some("identifier")
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{ToTokens, Tokens};

    impl ToTokens for Ident {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(self.term);
        }
    }
}
<commit_msg>Introduce `parse_any` method for parsing identifiers containing rust keywords<commit_after>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};

use proc_macro2::Term;
use unicode_xid::UnicodeXID;

use proc_macro2::Span;

/// A word of Rust code, which may be a keyword or legal variable name.
///
/// An identifier consists of at least one Unicode code point, the first of
/// which has the XID_Start property and the rest of which have the XID_Continue
/// property. An underscore may be used as the first character as long as it is
/// not the only character.
///
/// - The empty string is not an identifier. Use `Option<Ident>`.
/// - An underscore by itself is not an identifier. Use
///   `Token![_]` instead.
/// - A lifetime is not an identifier. Use `syn::Lifetime` instead.
///
/// An identifier constructed with `Ident::new` is permitted to be a Rust
/// keyword, though parsing one through its [`Synom`] implementation rejects
/// Rust keywords.
///
/// [`Synom`]: synom/trait.Synom.html
///
/// # Examples
///
/// A new ident can be created from a string using the `Ident::from` function.
/// Idents produced by `Ident::from` are set to resolve at the procedural macro
/// *def site* by default. A different span can be provided explicitly by using
/// `Ident::new`.
///
/// ```rust
/// extern crate syn;
/// extern crate proc_macro2;
///
/// use syn::Ident;
/// use proc_macro2::Span;
///
/// fn main() {
///     let def_ident = Ident::from("definitely");
///     let call_ident = Ident::new("calligraphy", Span::call_site());
///
///     println!("{} {}", def_ident, call_ident);
/// }
/// ```
///
/// An ident can be interpolated into a token stream using the `quote!` macro.
///
/// ```rust
/// #[macro_use]
/// extern crate quote;
///
/// extern crate syn;
/// use syn::Ident;
///
/// fn main() {
///     let ident = Ident::from("demo");
///
///     // Create a variable binding whose name is this ident.
///     let expanded = quote! { let #ident = 10; };
///
///     // Create a variable binding with a slightly different name.
///     let temp_ident = Ident::from(format!("new_{}", ident));
///     let expanded = quote! { let #temp_ident = 10; };
/// }
/// ```
///
/// A string representation of the ident is available through the `as_ref()` and
/// `to_string()` methods.
///
/// ```rust
/// # use syn::Ident;
/// # let ident = Ident::from("another_identifier");
/// #
/// // Examine the ident as a &str.
/// let ident_str = ident.as_ref();
/// if ident_str.len() > 60 {
///     println!("Very long identifier: {}", ident_str)
/// }
///
/// // Create a String from the ident.
/// let ident_string = ident.to_string();
/// give_away(ident_string);
///
/// fn give_away(s: String) { /* ... */ }
/// ```
#[derive(Copy, Clone, Debug)]
pub struct Ident {
    term: Term,
}

impl Ident {
    /// Creates an ident with the given string representation.
    ///
    /// # Panics
    ///
    /// Panics if the input string is neither a keyword nor a legal variable
    /// name.
    pub fn new(s: &str, span: Span) -> Self {
        if s.is_empty() {
            panic!("ident is not allowed to be empty; use Option<Ident>");
        }

        if s.starts_with('\'') {
            panic!("ident is not allowed to be a lifetime; use syn::Lifetime");
        }

        if s.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
            panic!("ident cannot be a number, use syn::Index instead");
        }

        fn xid_ok(s: &str) -> bool {
            let mut chars = s.chars();
            let first = chars.next().unwrap();
            if !(UnicodeXID::is_xid_start(first) || first == '_') {
                return false;
            }
            for ch in chars {
                if !UnicodeXID::is_xid_continue(ch) {
                    return false;
                }
            }
            true
        }

        if !xid_ok(s) {
            panic!("{:?} is not a valid ident", s);
        }

        Ident {
            term: Term::new(s, span),
        }
    }

    pub fn span(&self) -> Span {
        self.term.span()
    }

    pub fn set_span(&mut self, span: Span) {
        self.term.set_span(span);
    }
}

impl<'a> From<&'a str> for Ident {
    fn from(s: &str) -> Self {
        Ident::new(s, Span::call_site())
    }
}

impl From<Token![self]> for Ident {
    fn from(tok: Token![self]) -> Self {
        Ident::new("self", tok.0)
    }
}

impl From<Token![Self]> for Ident {
    fn from(tok: Token![Self]) -> Self {
        Ident::new("Self", tok.0)
    }
}

impl From<Token![super]> for Ident {
    fn from(tok: Token![super]) -> Self {
        Ident::new("super", tok.0)
    }
}

impl From<Token![crate]> for Ident {
    fn from(tok: Token![crate]) -> Self {
        Ident::new("crate", tok.0)
    }
}

impl<'a> From<Cow<'a, str>> for Ident {
    fn from(s: Cow<'a, str>) -> Self {
        Ident::new(&s, Span::call_site())
    }
}

impl From<String> for Ident {
    fn from(s: String) -> Self {
        Ident::new(&s, Span::call_site())
    }
}

impl AsRef<str> for Ident {
    fn as_ref(&self) -> &str {
        self.term.as_str()
    }
}

impl Display for Ident {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.term.as_str().fmt(formatter)
    }
}

impl<T: ?Sized> PartialEq<T> for Ident
where
    T: AsRef<str>,
{
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl Eq for Ident {}

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

impl Ord for Ident {
    fn cmp(&self, other: &Ident) -> Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl Hash for Ident {
    fn hash<H: Hasher>(&self, h: &mut H) {
        self.as_ref().hash(h);
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use buffer::Cursor;
    use parse_error;
    use synom::PResult;
    use synom::Synom;

    impl Synom for Ident {
        fn parse(input: Cursor) -> PResult<Self> {
            let (term, rest) = match input.term() {
                Some(term) => term,
                _ => return parse_error(),
            };
            if term.as_str().starts_with('\'') {
                return parse_error();
            }
            match term.as_str() {
                "_"
                // From https://doc.rust-lang.org/grammar.html#keywords
                | "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const"
                | "continue" | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final"
                | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match"
                | "mod" | "move" | "mut" | "offsetof" | "override" | "priv" | "proc" | "pub"
                | "pure" | "ref" | "return" | "Self" | "self" | "sizeof" | "static" | "struct"
                | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use"
                | "virtual" | "where" | "while" | "yield" => return parse_error(),
                _ => {}
            }

            Ok((Ident { term: term }, rest))
        }

        fn description() -> Option<&'static str> {
            Some("identifier")
        }
    }

    impl Ident {
        /// Parses any identifier
        ///
        /// This is useful when parsing a DSL which allows Rust keywords as identifiers.
        pub fn parse_any(input: Cursor) -> PResult<Self> {
            let (term, rest) = match input.term() {
                Some(term) => term,
                _ => return parse_error(),
            };
            if term.as_str().starts_with('\'') {
                return parse_error();
            }

            Ok((Ident { term: term }, rest))
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{ToTokens, Tokens};

    impl ToTokens for Ident {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(self.term);
        }
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::address::SBAddress;
use super::block::SBBlock;
use super::compileunit::SBCompileUnit;
use super::expressionoptions::SBExpressionOptions;
use super::function::SBFunction;
use super::lineentry::SBLineEntry;
use super::lldb_addr_t;
use super::module::SBModule;
use super::stream::SBStream;
use super::symbol::SBSymbol;
use super::symbolcontext::SBSymbolContext;
use super::thread::SBThread;
use super::value::SBValue;
use super::valuelist::SBValueList;
use super::variablesoptions::SBVariablesOptions;
use std::ffi::{CStr, CString};
use std::fmt;
use sys;

/// One of the stack frames associated with a thread.
pub struct SBFrame {
    /// The underlying raw `SBFrameRef`.
    pub raw: sys::SBFrameRef,
}

impl SBFrame {
    /// Construct a new `SBFrame`.
    pub fn wrap(raw: sys::SBFrameRef) -> SBFrame {
        SBFrame { raw }
    }

    /// Construct a new `Some(SBFrame)` or `None`.
    pub fn maybe_wrap(raw: sys::SBFrameRef) -> Option<SBFrame> {
        if unsafe { sys::SBFrameIsValid(raw) != 0 } {
            Some(SBFrame { raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBFrame` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBFrameIsValid(self.raw) != 0 }
    }

    /// The zero-based stack frame index for this frame.
    ///
    /// This can be used to locate adjacent frames in the
    /// thread's stack frames.
    pub fn frame_id(&self) -> u32 {
        unsafe { sys::SBFrameGetFrameID(self.raw) }
    }

    /// Get the Canonical Frame Address for this stack frame.
    ///
    /// This is the DWARF standard's definition of a CFA, a
    /// stack address that remains constant throughout the
    /// lifetime of the function.
    pub fn cfa(&self) -> Option<lldb_addr_t> {
        let cfa = unsafe { sys::SBFrameGetCFA(self.raw) };
        if cfa != u64::max_value() {
            Some(cfa)
        } else {
            None
        }
    }

    /// The program counter (PC) as an unsigned integer.
    pub fn pc(&self) -> lldb_addr_t {
        unsafe { sys::SBFrameGetPC(self.raw) }
    }

    #[allow(missing_docs)]
    pub fn set_pc(&self, new_pc: lldb_addr_t) -> bool {
        unsafe { sys::SBFrameSetPC(self.raw, new_pc) != 0 }
    }

    /// The stack pointer address as an unsigned integer.
    pub fn sp(&self) -> lldb_addr_t {
        unsafe { sys::SBFrameGetSP(self.raw) }
    }

    /// The frame pointer address as an unsigned integer.
    pub fn fp(&self) -> lldb_addr_t {
        unsafe { sys::SBFrameGetFP(self.raw) }
    }

    /// The program counter (PC) as a section offset address (`SBAddress`).
    pub fn pc_address(&self) -> SBAddress {
        SBAddress::wrap(unsafe { sys::SBFrameGetPCAddress(self.raw) })
    }

    /// The symbol context for this frame's current pc value.
    ///
    /// The frame maintains this symbol context and adds information to
    /// it as needed. This helps avoid repeated lookups of the same
    /// information.
    ///
    /// * `resolve_scope`: Flags that specify what type of symbol context
    ///   is needed by the caller. These flags have constants starting
    ///   with `SYMBOL_CONTEXT_ITEM_`.
    pub fn symbol_context(&self, resolve_scope: u32) -> SBSymbolContext {
        SBSymbolContext::wrap(unsafe { sys::SBFrameGetSymbolContext(self.raw, resolve_scope) })
    }

    /// The `SBModule` for this stack frame.
    pub fn module(&self) -> SBModule {
        SBModule::wrap(unsafe { sys::SBFrameGetModule(self.raw) })
    }

    /// The `SBCompileUnit` for this stack frame.
    pub fn compile_unit(&self) -> SBCompileUnit {
        SBCompileUnit::wrap(unsafe { sys::SBFrameGetCompileUnit(self.raw) })
    }

    /// The `SBFunction` for this stack frame.
    pub fn function(&self) -> SBFunction {
        SBFunction::wrap(unsafe { sys::SBFrameGetFunction(self.raw) })
    }

    /// The `SBSymbol` for this stack frame.
    pub fn symbol(&self) -> SBSymbol {
        SBSymbol::wrap(unsafe { sys::SBFrameGetSymbol(self.raw) })
    }

    /// Get the deepest block that contains the frame PC.
    pub fn block(&self) -> SBBlock {
        SBBlock::wrap(unsafe { sys::SBFrameGetBlock(self.raw) })
    }

    /// Get the appropriate function name for this frame. Inlined functions in
    /// LLDB are represented by blocks that have inlined function information, so
    /// just looking at the `SBFunction` or `SBSymbol` for a frame isn't enough.
    /// This function will return the appropriate function, symbol or inlined
    /// function name for the frame.
    ///
    /// This function returns:
    ///
    /// * the name of the inlined function (if there is one)
    /// * the name of the concrete function (if there is one)
    /// * the name of the symbol (if there is one)
    /// * NULL
    ///
    /// See also `is_inlined`.
    pub fn function_name(&self) -> Option<&str> {
        unsafe {
            match CStr::from_ptr(sys::SBFrameGetFunctionName(self.raw)).to_str() {
                Ok(s) => Some(s),
                _ => None,
            }
        }
    }

    #[allow(missing_docs)]
    pub fn display_function_name(&self) -> Option<&str> {
        unsafe {
            match CStr::from_ptr(sys::SBFrameGetDisplayFunctionName(self.raw)).to_str() {
                Ok(s) => Some(s),
                _ => None,
            }
        }
    }

    /// Return `true` if this frame represents an inlined function.
    pub fn is_inlined(&self) -> bool {
        unsafe { sys::SBFrameIsInlined(self.raw) != 0 }
    }

    /// Evaluate an expression within the context of this frame.
    pub fn evaluate_expression(&self, expression: &str, options: &SBExpressionOptions) -> SBValue {
        let expression = CString::new(expression).unwrap();
        SBValue::wrap(unsafe {
            sys::SBFrameEvaluateExpression(self.raw, expression.as_ptr(), options.raw)
        })
    }

    /// Gets the lexical block that defines the stack frame. Another way to think
    /// of this is it will return the block that contains all of the variables
    /// for a stack frame. Inlined functions are represented as `SBBlock` objects
    /// that have inlined function information: the name of the inlined function,
    /// where it was called from. The block that is returned will be the first
    /// block at or above the block for the PC (`SBFrame::block()`) that defines
    /// the scope of the frame. When a function contains no inlined functions,
    /// this will be the top most lexical block that defines the function.
    /// When a function has inlined functions and the PC is currently
    /// in one of those inlined functions, this method will return the inlined
    /// block that defines this frame. If the PC isn't currently in an inlined
    /// function, the lexical block that defines the function is returned.
    pub fn frame_block(&self) -> SBBlock {
        SBBlock::wrap(unsafe { sys::SBFrameGetFrameBlock(self.raw) })
    }

    /// The line table entry (`SBLineEntry`) for this stack frame.
    pub fn line_entry(&self) -> Option<SBLineEntry> {
        SBLineEntry::maybe_wrap(unsafe { sys::SBFrameGetLineEntry(self.raw) })
    }

    /// The thread that is executing this stack frame.
    pub fn thread(&self) -> SBThread {
        SBThread::wrap(unsafe { sys::SBFrameGetThread(self.raw) })
    }

    /// The disassembly of this function, presented as a string.
    pub fn disassemble(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBFrameDisassemble(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The values for variables matching the specified options.
    pub fn variables(&self, options: &SBVariablesOptions) -> SBValueList {
        SBValueList::wrap(unsafe { sys::SBFrameGetVariables(self.raw, options.raw) })
    }

    /// The values for all variables in this stack frame.
    pub fn all_variables(&self) -> SBValueList {
        let options = SBVariablesOptions::new();
        options.set_include_arguments(true);
        options.set_include_locals(true);
        options.set_include_statics(true);
        options.set_in_scope_only(true);
        self.variables(&options)
    }

    /// The values for the argument variables in this stack frame.
    pub fn arguments(&self) -> SBValueList {
        let options = SBVariablesOptions::new();
        options.set_include_arguments(true);
        options.set_include_locals(false);
        options.set_include_statics(false);
        options.set_in_scope_only(false);
        self.variables(&options)
    }

    /// The values for the local variables in this stack frame.
    pub fn locals(&self) -> SBValueList {
        let options = SBVariablesOptions::new();
        options.set_include_arguments(false);
        options.set_include_locals(true);
        options.set_include_statics(false);
        options.set_in_scope_only(false);
        self.variables(&options)
    }

    /// The values for the static variables in this stack frame.
    pub fn statics(&self) -> SBValueList {
        let options = SBVariablesOptions::new();
        options.set_include_arguments(false);
        options.set_include_locals(false);
        options.set_include_statics(true);
        options.set_in_scope_only(false);
        self.variables(&options)
    }

    /// The values for the CPU registers for this stack frame.
    pub fn registers(&self) -> SBValueList {
        SBValueList::wrap(unsafe { sys::SBFrameGetRegisters(self.raw) })
    }

    /// The value for a particular register, if present.
    pub fn find_register(&self, name: &str) -> Option<SBValue> {
        let name = CString::new(name).unwrap();
        SBValue::maybe_wrap(unsafe { sys::SBFrameFindRegister(self.raw, name.as_ptr()) })
    }

    /// The parent frame that invoked this frame, if available.
    pub fn parent_frame(&self) -> Option<SBFrame> {
        let thread = self.thread();
        let parent_idx = self.frame_id() + 1;
        if parent_idx < unsafe { sys::SBThreadGetNumFrames(thread.raw) } {
            SBFrame::maybe_wrap(unsafe { sys::SBThreadGetFrameAtIndex(thread.raw, parent_idx) })
        } else {
            None
        }
    }
}

impl fmt::Debug for SBFrame {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBFrameGetDescription(self.raw, stream.raw) };
        write!(fmt, "SBFrame {{ {} }}", stream.data())
    }
}

impl Drop for SBFrame {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBFrame(self.raw) };
    }
}

#[cfg(feature = "graphql")]
graphql_object!(SBFrame: super::debugger::SBDebugger | &self | {
    field is_valid() -> bool {
        self.is_valid()
    }

    // TODO(bm): This should be u32
    field frame_id() -> i64 {
        self.frame_id() as i64
    }

    // TODO(bm) This should be u64
    field cfa() -> Option<i64> {
        self.cfa().map(|i| i as i64)
    }

    // TODO(bm) This should be u64
    field pc() -> i64 {
        self.pc() as i64
    }

    // TODO(bm) This should be u64
    field sp() -> i64 {
        self.sp() as i64
    }

    // TODO(bm) This should be u64
    field fp() -> i64 {
        self.fp() as i64
    }

    field pc_address() -> SBAddress {
        self.pc_address()
    }

    field module() -> SBModule {
        self.module()
    }

    field compile_unit() -> SBCompileUnit {
        self.compile_unit()
    }

    field function() -> SBFunction {
        self.function()
    }

    field symbol() -> SBSymbol {
        self.symbol()
    }

    field block() -> SBBlock {
        self.block()
    }

    field function_name() -> Option<&str> {
        self.function_name()
    }

    field display_function_name() -> Option<&str> {
        self.display_function_name()
    }

    field is_inlined() -> bool {
        self.is_inlined()
    }

    field frame_block() -> SBBlock {
        self.frame_block()
    }

    field line_entry() -> Option<SBLineEntry> {
        self.line_entry()
    }

    field thread() -> SBThread {
        self.thread()
    }
});
<commit_msg>Fix sigfault on lldb::SBFrame::function_name<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::address::SBAddress;
use super::block::SBBlock;
use super::compileunit::SBCompileUnit;
use super::expressionoptions::SBExpressionOptions;
use super::function::SBFunction;
use super::lineentry::SBLineEntry;
use super::lldb_addr_t;
use super::module::SBModule;
use super::stream::SBStream;
use super::symbol::SBSymbol;
use super::symbolcontext::SBSymbolContext;
use super::thread::SBThread;
use super::value::SBValue;
use super::valuelist::SBValueList;
use super::variablesoptions::SBVariablesOptions;
use std::ffi::{CStr, CString};
use std::fmt;
use sys;

/// One of the stack frames associated with a thread.
pub struct SBFrame {
    /// The underlying raw `SBFrameRef`.
    pub raw: sys::SBFrameRef,
}

impl SBFrame {
    /// Construct a new `SBFrame`.
    pub fn wrap(raw: sys::SBFrameRef) -> SBFrame {
        SBFrame { raw }
    }

    /// Construct a new `Some(SBFrame)` or `None`.
    pub fn maybe_wrap(raw: sys::SBFrameRef) -> Option<SBFrame> {
        if unsafe { sys::SBFrameIsValid(raw) != 0 } {
            Some(SBFrame { raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBFrame` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBFrameIsValid(self.raw) != 0 }
    }

    /// The zero-based stack frame index for this frame.
    ///
    /// This can be used to locate adjacent frames in the
    /// thread's stack frames.
    pub fn frame_id(&self) -> u32 {
        unsafe { sys::SBFrameGetFrameID(self.raw) }
    }

    /// Get the Canonical Frame Address for this stack frame.
    ///
    /// This is the DWARF standard's definition of a CFA, a
    /// stack address that remains constant throughout the
    /// lifetime of the function.
    pub fn cfa(&self) -> Option<lldb_addr_t> {
        let cfa = unsafe { sys::SBFrameGetCFA(self.raw) };
        if cfa != u64::max_value() {
            Some(cfa)
        } else {
            None
        }
    }

    /// The program counter (PC) as an unsigned integer.
    pub fn pc(&self) -> lldb_addr_t {
        unsafe { sys::SBFrameGetPC(self.raw) }
    }

    #[allow(missing_docs)]
    pub fn set_pc(&self, new_pc: lldb_addr_t) -> bool {
        unsafe { sys::SBFrameSetPC(self.raw, new_pc) != 0 }
    }

    /// The stack pointer address as an unsigned integer.
    pub fn sp(&self) -> lldb_addr_t {
        unsafe { sys::SBFrameGetSP(self.raw) }
    }

    /// The frame pointer address as an unsigned integer.
    pub fn fp(&self) -> lldb_addr_t {
        unsafe { sys::SBFrameGetFP(self.raw) }
    }

    /// The program counter (PC) as a section offset address (`SBAddress`).
    pub fn pc_address(&self) -> SBAddress {
        SBAddress::wrap(unsafe { sys::SBFrameGetPCAddress(self.raw) })
    }

    /// The symbol context for this frame's current pc value.
    ///
    /// The frame maintains this symbol context and adds information to
    /// it as needed. This helps avoid repeated lookups of the same
    /// information.
    ///
    /// * `resolve_scope`: Flags that specify what type of symbol context
    ///   is needed by the caller. These flags have constants starting
    ///   with `SYMBOL_CONTEXT_ITEM_`.
    pub fn symbol_context(&self, resolve_scope: u32) -> SBSymbolContext {
        SBSymbolContext::wrap(unsafe { sys::SBFrameGetSymbolContext(self.raw, resolve_scope) })
    }

    /// The `SBModule` for this stack frame.
    pub fn module(&self) -> SBModule {
        SBModule::wrap(unsafe { sys::SBFrameGetModule(self.raw) })
    }

    /// The `SBCompileUnit` for this stack frame.
    pub fn compile_unit(&self) -> SBCompileUnit {
        SBCompileUnit::wrap(unsafe { sys::SBFrameGetCompileUnit(self.raw) })
    }

    /// The `SBFunction` for this stack frame.
    pub fn function(&self) -> SBFunction {
        SBFunction::wrap(unsafe { sys::SBFrameGetFunction(self.raw) })
    }

    /// The `SBSymbol` for this stack frame.
    pub fn symbol(&self) -> SBSymbol {
        SBSymbol::wrap(unsafe { sys::SBFrameGetSymbol(self.raw) })
    }

    /// Get the deepest block that contains the frame PC.
    pub fn block(&self) -> SBBlock {
        SBBlock::wrap(unsafe { sys::SBFrameGetBlock(self.raw) })
    }

    /// Get the appropriate function name for this frame. Inlined functions in
    /// LLDB are represented by blocks that have inlined function information, so
    /// just looking at the `SBFunction` or `SBSymbol` for a frame isn't enough.
    /// This function will return the appropriate function, symbol or inlined
    /// function name for the frame.
    ///
    /// This function returns:
    ///
    /// * the name of the inlined function (if there is one)
    /// * the name of the concrete function (if there is one)
    /// * the name of the symbol (if there is one)
    /// * NULL
    ///
    /// See also `is_inlined`.
    pub fn function_name(&self) -> Option<&str> {
        unsafe {
            match CStr::from_ptr(sys::SBFrameGetFunctionName(self.raw).as_ref()?).to_str() {
                Ok(s) => Some(s),
                _ => None,
            }
        }
    }

    #[allow(missing_docs)]
    pub fn display_function_name(&self) -> Option<&str> {
        unsafe {
            match CStr::from_ptr(sys::SBFrameGetDisplayFunctionName(self.raw)).to_str() {
                Ok(s) => Some(s),
                _ => None,
            }
        }
    }

    /// Return `true` if this frame represents an inlined function.
    pub fn is_inlined(&self) -> bool {
        unsafe { sys::SBFrameIsInlined(self.raw) != 0 }
    }

    /// Evaluate an expression within the context of this frame.
    pub fn evaluate_expression(&self, expression: &str, options: &SBExpressionOptions) -> SBValue {
        let expression = CString::new(expression).unwrap();
        SBValue::wrap(unsafe {
            sys::SBFrameEvaluateExpression(self.raw, expression.as_ptr(), options.raw)
        })
    }

    /// Gets the lexical block that defines the stack frame. Another way to think
    /// of this is it will return the block that contains all of the variables
    /// for a stack frame. Inlined functions are represented as `SBBlock` objects
    /// that have inlined function information: the name of the inlined function,
    /// where it was called from. The block that is returned will be the first
    /// block at or above the block for the PC (`SBFrame::block()`) that defines
    /// the scope of the frame. When a function contains no inlined functions,
    /// this will be the top most lexical block that defines the function.
    /// When a function has inlined functions and the PC is currently
    /// in one of those inlined functions, this method will return the inlined
    /// block that defines this frame. If the PC isn't currently in an inlined
    /// function, the lexical block that defines the function is returned.
    pub fn frame_block(&self) -> SBBlock {
        SBBlock::wrap(unsafe { sys::SBFrameGetFrameBlock(self.raw) })
    }

    /// The line table entry (`SBLineEntry`) for this stack frame.
    pub fn line_entry(&self) -> Option<SBLineEntry> {
        SBLineEntry::maybe_wrap(unsafe { sys::SBFrameGetLineEntry(self.raw) })
    }

    /// The thread that is executing this stack frame.
    pub fn thread(&self) -> SBThread {
        SBThread::wrap(unsafe { sys::SBFrameGetThread(self.raw) })
    }

    /// The disassembly of this function, presented as a string.
    pub fn disassemble(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBFrameDisassemble(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The values for variables matching the specified options.
    pub fn variables(&self, options: &SBVariablesOptions) -> SBValueList {
        SBValueList::wrap(unsafe { sys::SBFrameGetVariables(self.raw, options.raw) })
    }

    /// The values for all variables in this stack frame.
    pub fn all_variables(&self) -> SBValueList {
        let options = SBVariablesOptions::new();
        options.set_include_arguments(true);
        options.set_include_locals(true);
        options.set_include_statics(true);
        options.set_in_scope_only(true);
        self.variables(&options)
    }

    /// The values for the argument variables in this stack frame.
    pub fn arguments(&self) -> SBValueList {
        let options = SBVariablesOptions::new();
        options.set_include_arguments(true);
        options.set_include_locals(false);
        options.set_include_statics(false);
        options.set_in_scope_only(false);
        self.variables(&options)
    }

    /// The values for the local variables in this stack frame.
    pub fn locals(&self) -> SBValueList {
        let options = SBVariablesOptions::new();
        options.set_include_arguments(false);
        options.set_include_locals(true);
        options.set_include_statics(false);
        options.set_in_scope_only(false);
        self.variables(&options)
    }

    /// The values for the static variables in this stack frame.
    pub fn statics(&self) -> SBValueList {
        let options = SBVariablesOptions::new();
        options.set_include_arguments(false);
        options.set_include_locals(false);
        options.set_include_statics(true);
        options.set_in_scope_only(false);
        self.variables(&options)
    }

    /// The values for the CPU registers for this stack frame.
    pub fn registers(&self) -> SBValueList {
        SBValueList::wrap(unsafe { sys::SBFrameGetRegisters(self.raw) })
    }

    /// The value for a particular register, if present.
    pub fn find_register(&self, name: &str) -> Option<SBValue> {
        let name = CString::new(name).unwrap();
        SBValue::maybe_wrap(unsafe { sys::SBFrameFindRegister(self.raw, name.as_ptr()) })
    }

    /// The parent frame that invoked this frame, if available.
    pub fn parent_frame(&self) -> Option<SBFrame> {
        let thread = self.thread();
        let parent_idx = self.frame_id() + 1;
        if parent_idx < unsafe { sys::SBThreadGetNumFrames(thread.raw) } {
            SBFrame::maybe_wrap(unsafe { sys::SBThreadGetFrameAtIndex(thread.raw, parent_idx) })
        } else {
            None
        }
    }
}

impl fmt::Debug for SBFrame {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBFrameGetDescription(self.raw, stream.raw) };
        write!(fmt, "SBFrame {{ {} }}", stream.data())
    }
}

impl Drop for SBFrame {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBFrame(self.raw) };
    }
}

#[cfg(feature = "graphql")]
graphql_object!(SBFrame: super::debugger::SBDebugger | &self | {
    field is_valid() -> bool {
        self.is_valid()
    }

    // TODO(bm): This should be u32
    field frame_id() -> i64 {
        self.frame_id() as i64
    }

    // TODO(bm) This should be u64
    field cfa() -> Option<i64> {
        self.cfa().map(|i| i as i64)
    }

    // TODO(bm) This should be u64
    field pc() -> i64 {
        self.pc() as i64
    }

    // TODO(bm) This should be u64
    field sp() -> i64 {
        self.sp() as i64
    }

    // TODO(bm) This should be u64
    field fp() -> i64 {
        self.fp() as i64
    }

    field pc_address() -> SBAddress {
        self.pc_address()
    }

    field module() -> SBModule {
        self.module()
    }

    field compile_unit() -> SBCompileUnit {
        self.compile_unit()
    }

    field function() -> SBFunction {
        self.function()
    }

    field symbol() -> SBSymbol {
        self.symbol()
    }

    field block() -> SBBlock {
        self.block()
    }

    field function_name() -> Option<&str> {
        self.function_name()
    }

    field display_function_name() -> Option<&str> {
        self.display_function_name()
    }

    field is_inlined() -> bool {
        self.is_inlined()
    }

    field frame_block() -> SBBlock {
        self.frame_block()
    }

    field line_entry() -> Option<SBLineEntry> {
        self.line_entry()
    }

    field thread() -> SBThread {
        self.thread()
    }
});
<|endoftext|>


<commit_before>use std::collections::hash_map::{HashMap, RandomState};
use std::error;
use std::fmt::{self, Debug, Formatter};
#[cfg(feature = "display")]
use std::fmt::Display;
use std::hash::{BuildHasher, Hash};
use std::marker::PhantomData;
use {Command, Error, Record};

/// A group of records.
pub struct Group<K: Hash + Eq, V, S = RandomState> {
    group: HashMap<K, V, S>,
    active: Option<K>,
    signals: Option<Box<FnMut(Option<&K>) + Send + Sync + 'static>>,
}

impl<K: Hash + Eq, V> Group<K, V, RandomState> {
    /// Returns a new group.
    #[inline]
    pub fn new() -> Group<K, V, RandomState> {
        Group {
            group: HashMap::new(),
            active: None,
            signals: None,
        }
    }
}

impl<'a, K: Hash + Eq, V, S: BuildHasher> Group<K, V, S> {
    /// Returns a builder for a group.
    #[inline]
    pub fn builder() -> GroupBuilder<K, V, S> {
        GroupBuilder {
            group: PhantomData,
            capacity: 0,
            signals: None,
        }
    }

    /// Reserves capacity for at least `additional` more items.
    ///
    /// # Panics
    /// Panics if the new capacity overflows usize.
    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        self.group.reserve(additional);
    }

    /// Returns the capacity of the group.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.group.capacity()
    }

    /// Returns the number of items in the group.
    #[inline]
    pub fn len(&self) -> usize {
        self.group.len()
    }

    /// Returns `true` if the group is empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.group.is_empty()
    }

    /// Sets how different signals should be handled when the state changes.
    #[inline]
    pub fn set_signals<F>(&mut self, f: F)
        where
            F: FnMut(Option<&K>) + Send + Sync + 'static,
    {
        self.signals = Some(Box::new(f));
    }

    /// Inserts an item into the group.
    #[inline]
    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
        self.group.insert(k, v)
    }

    /// Removes an item from the group.
    #[inline]
    pub fn remove(&mut self, k: &K) -> Option<V> {
        self.group.remove(k)
    }

    /// Gets a reference to the current active item in the group.
    #[inline]
    pub fn get(&self) -> Option<&V> {
        self.active.as_ref().and_then(|active| self.group.get(active))
    }

    /// Gets a mutable reference to the current active item in the group.
    #[inline]
    pub fn get_mut(&mut self) -> Option<&mut V> {
        let group = &mut self.group;
        self.active.as_ref().and_then(move |active| group.get_mut(active))
    }

    /// Sets the current active item in the group.
    ///
    /// Returns `None` if the item was successfully set, otherwise `k` is returned.
    #[inline]
    pub fn set(&mut self, k: K) -> Option<K> {
        if self.group.contains_key(&k) {
            if self.active.as_ref().map_or(false, |a| a != &k) {
                if let Some(ref mut f) = self.signals {
                    f(Some(&k))
                }
            }
            self.active = Some(k);
            None
        } else {
            Some(k)
        }
    }

    /// Unsets the current active item in the group.
    #[inline]
    pub fn unset(&mut self) {
        if self.active.is_some() {
            self.active = None;
            if let Some(ref mut f) = self.signals {
                f(None);
            }
        }
    }
}

impl<K: Hash + Eq, R, S: BuildHasher> Group<K, Record<R>, S> {
    /// Calls the [`set_saved`] method on the active record.
    ///
    /// [`set_saved`]: record/struct.Record.html#method.set_saved
    #[inline]
    pub fn set_saved(&mut self) {
        self.get_mut().map(|record| record.set_saved());
    }

    /// Calls the [`set_unsaved`] method on the active record.
    ///
    /// [`set_unsaved`]: record/struct.Record.html#method.set_unsaved
    #[inline]
    pub fn set_unsaved(&mut self) {
        self.get_mut().map(|record| record.set_unsaved());
    }

    /// Calls the [`is_saved`] method on the active record.
    ///
    /// [`is_saved`]: record/struct.Record.html#method.is_saved
    #[inline]
    pub fn is_saved(&self) -> bool {
        self.get().map_or(false, |record| record.is_saved())
    }

    /// Calls the [`apply`] method on the active record.
    ///
    /// [`apply`]: record/struct.Record.html#method.apply
    #[inline]
    pub fn apply<C>(&mut self, cmd: C) -> Option<Result<impl Iterator<Item=Box<Command<R> + 'static>>, Error<R>>>
        where
            C: Command<R> + 'static,
            R: 'static,
    {
        self.get_mut().map(move |record| record.apply(cmd))
    }

    /// Calls the [`undo`] method on the active record.
    ///
    /// [`undo`]: record/struct.Record.html#method.undo
    #[inline]
    pub fn undo(&mut self) -> Option<Result<(), Box<error::Error>>> {
        self.get_mut().and_then(|record| record.undo())
    }

    /// Calls the [`redo`] method on the active record.
    ///
    /// [`redo`]: record/struct.Record.html#method.redo
    #[inline]
    pub fn redo(&mut self) -> Option<Result<(), Box<error::Error>>> {
        self.get_mut().and_then(|record| record.redo())
    }

    /// Calls the [`to_undo_string`] method on the active record.
    ///
    /// [`to_undo_string`]: record/struct.Record.html#method.to_undo_string
    #[inline]
    #[cfg(feature = "display")]
    pub fn to_undo_string(&self) -> Option<String> {
        self.get().and_then(|record| record.to_undo_string())
    }

    /// Calls the [`to_redo_string`] method on the active record.
    ///
    /// [`to_redo_string`]: record/struct.Record.html#method.to_redo_string
    #[inline]
    #[cfg(feature = "display")]
    pub fn to_redo_string(&self) -> Option<String> {
        self.get().and_then(|record| record.to_redo_string())
    }

    /// Returns an iterator over the records.
    #[inline]
    pub fn records(&self) -> impl Iterator<Item=&Record<R>> {
        self.group.values()
    }
}

impl<K: Hash + Eq + Debug, V: Debug, S: BuildHasher> Debug for Group<K, V, S> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("Group")
            .field("group", &self.group)
            .field("active", &self.active)
            .finish()
    }
}

#[cfg(feature = "display")]
impl<K: Hash + Eq + Display, V: Display> Display for Group<K, V> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        for (key, item) in &self.group {
            if self.active.as_ref().map_or(false, |a| a == key) {
                writeln!(f, "* {}:\n{}", key, item)?;
            } else {
                writeln!(f, "  {}:\n{}", key, item)?;
            }
        }
        Ok(())
    }
}

impl<K: Hash + Eq, V> Default for Group<K, V, RandomState> {
    #[inline]
    fn default() -> Group<K, V, RandomState> {
        Group::new()
    }
}

/// Builder for a group.
pub struct GroupBuilder<K: Hash + Eq, V, S: BuildHasher> {
    group: PhantomData<(K, V, S)>,
    capacity: usize,
    signals: Option<Box<FnMut(Option<&K>) + Send + Sync + 'static>>,
}

impl<K: Hash + Eq, V> GroupBuilder<K, V, RandomState> {
    /// Creates the group.
    #[inline]
    pub fn build(self) -> Group<K, V, RandomState> {
        self.build_with_hasher(Default::default())
    }
}

impl<K: Hash + Eq, V, S: BuildHasher> GroupBuilder<K, V, S> {
    /// Sets the specified [capacity] for the group.
    ///
    /// [capacity]: https://doc.rust-lang.org/std/vec/struct.Vec.html#capacity-and-reallocation
    #[inline]
    pub fn capacity(mut self, capacity: usize) -> GroupBuilder<K, V, S> {
        self.capacity = capacity;
        self
    }

    /// Decides what should happen when the active stack changes.
    #[inline]
    pub fn signals<F>(mut self, f: F) -> GroupBuilder<K, V, S>
        where
            F: FnMut(Option<&K>) + Send + Sync + 'static
    {
        self.signals = Some(Box::new(f));
        self
    }

    /// Creates the group with the given hasher.
    #[inline]
    pub fn build_with_hasher(self, hasher: S) -> Group<K, V, S> {
        Group {
            group: HashMap::with_capacity_and_hasher(self.capacity, hasher),
            active: None,
            signals: self.signals,
        }
    }
}

impl<K: Hash + Eq, V, S: BuildHasher> Debug for GroupBuilder<K, V, S> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("GroupBuilder")
            .field("group", &self.group)
            .field("capacity", &self.capacity)
            .finish()
    }
}
<commit_msg>Add set_command method for Group<commit_after>use std::collections::hash_map::{HashMap, RandomState};
use std::error;
use std::fmt::{self, Debug, Formatter};
#[cfg(feature = "display")]
use std::fmt::Display;
use std::hash::{BuildHasher, Hash};
use std::marker::PhantomData;
use {Command, Error, Record};

/// A group of records.
pub struct Group<K: Hash + Eq, V, S = RandomState> {
    group: HashMap<K, V, S>,
    active: Option<K>,
    signals: Option<Box<FnMut(Option<&K>) + Send + Sync + 'static>>,
}

impl<K: Hash + Eq, V> Group<K, V, RandomState> {
    /// Returns a new group.
    #[inline]
    pub fn new() -> Group<K, V, RandomState> {
        Group {
            group: HashMap::new(),
            active: None,
            signals: None,
        }
    }
}

impl<'a, K: Hash + Eq, V, S: BuildHasher> Group<K, V, S> {
    /// Returns a builder for a group.
    #[inline]
    pub fn builder() -> GroupBuilder<K, V, S> {
        GroupBuilder {
            group: PhantomData,
            capacity: 0,
            signals: None,
        }
    }

    /// Reserves capacity for at least `additional` more items.
    ///
    /// # Panics
    /// Panics if the new capacity overflows usize.
    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        self.group.reserve(additional);
    }

    /// Returns the capacity of the group.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.group.capacity()
    }

    /// Returns the number of items in the group.
    #[inline]
    pub fn len(&self) -> usize {
        self.group.len()
    }

    /// Returns `true` if the group is empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.group.is_empty()
    }

    /// Sets how different signals should be handled when the state changes.
    #[inline]
    pub fn set_signals<F>(&mut self, f: F)
        where
            F: FnMut(Option<&K>) + Send + Sync + 'static,
    {
        self.signals = Some(Box::new(f));
    }

    /// Inserts an item into the group.
    #[inline]
    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
        self.group.insert(k, v)
    }

    /// Removes an item from the group.
    #[inline]
    pub fn remove(&mut self, k: &K) -> Option<V> {
        self.group.remove(k)
    }

    /// Gets a reference to the current active item in the group.
    #[inline]
    pub fn get(&self) -> Option<&V> {
        self.active.as_ref().and_then(|active| self.group.get(active))
    }

    /// Gets a mutable reference to the current active item in the group.
    #[inline]
    pub fn get_mut(&mut self) -> Option<&mut V> {
        let group = &mut self.group;
        self.active.as_ref().and_then(move |active| group.get_mut(active))
    }

    /// Sets the current active item in the group.
    ///
    /// Returns `None` if the item was successfully set, otherwise `k` is returned.
    #[inline]
    pub fn set(&mut self, k: K) -> Option<K> {
        if self.group.contains_key(&k) {
            if self.active.as_ref().map_or(false, |a| a != &k) {
                if let Some(ref mut f) = self.signals {
                    f(Some(&k))
                }
            }
            self.active = Some(k);
            None
        } else {
            Some(k)
        }
    }

    /// Unsets the current active item in the group.
    #[inline]
    pub fn unset(&mut self) {
        if self.active.is_some() {
            self.active = None;
            if let Some(ref mut f) = self.signals {
                f(None);
            }
        }
    }
}

impl<K: Hash + Eq, R, S: BuildHasher> Group<K, Record<R>, S> {
    /// Calls the [`set_saved`] method on the active record.
    ///
    /// [`set_saved`]: record/struct.Record.html#method.set_saved
    #[inline]
    pub fn set_saved(&mut self) {
        self.get_mut().map(|record| record.set_saved());
    }

    /// Calls the [`set_unsaved`] method on the active record.
    ///
    /// [`set_unsaved`]: record/struct.Record.html#method.set_unsaved
    #[inline]
    pub fn set_unsaved(&mut self) {
        self.get_mut().map(|record| record.set_unsaved());
    }

    /// Calls the [`is_saved`] method on the active record.
    ///
    /// [`is_saved`]: record/struct.Record.html#method.is_saved
    #[inline]
    pub fn is_saved(&self) -> bool {
        self.get().map_or(false, |record| record.is_saved())
    }

    /// Calls the [`apply`] method on the active record.
    ///
    /// [`apply`]: record/struct.Record.html#method.apply
    #[inline]
    pub fn apply<C>(&mut self, cmd: C) -> Option<Result<impl Iterator<Item=Box<Command<R> + 'static>>, Error<R>>>
        where
            C: Command<R> + 'static,
            R: 'static,
    {
        self.get_mut().map(move |record| record.apply(cmd))
    }

    /// Calls the [`undo`] method on the active record.
    ///
    /// [`undo`]: record/struct.Record.html#method.undo
    #[inline]
    pub fn undo(&mut self) -> Option<Result<(), Box<error::Error>>> {
        self.get_mut().and_then(|record| record.undo())
    }

    /// Calls the [`redo`] method on the active record.
    ///
    /// [`redo`]: record/struct.Record.html#method.redo
    #[inline]
    pub fn redo(&mut self) -> Option<Result<(), Box<error::Error>>> {
        self.get_mut().and_then(|record| record.redo())
    }

    /// Calls the [`set_command`] method on the active record.
    ///
    /// [`set_command`]: record/struct.Record.html#method.set_command
    #[inline]
    pub fn set_command(&mut self, index: usize) -> Option<Result<(), Box<error::Error>>> {
        self.get_mut().and_then(|record| record.set_command(index))
    }

    /// Calls the [`to_undo_string`] method on the active record.
    ///
    /// [`to_undo_string`]: record/struct.Record.html#method.to_undo_string
    #[inline]
    #[cfg(feature = "display")]
    pub fn to_undo_string(&self) -> Option<String> {
        self.get().and_then(|record| record.to_undo_string())
    }

    /// Calls the [`to_redo_string`] method on the active record.
    ///
    /// [`to_redo_string`]: record/struct.Record.html#method.to_redo_string
    #[inline]
    #[cfg(feature = "display")]
    pub fn to_redo_string(&self) -> Option<String> {
        self.get().and_then(|record| record.to_redo_string())
    }

    /// Returns an iterator over the records.
    #[inline]
    pub fn records(&self) -> impl Iterator<Item=&Record<R>> {
        self.group.values()
    }
}

impl<K: Hash + Eq + Debug, V: Debug, S: BuildHasher> Debug for Group<K, V, S> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("Group")
            .field("group", &self.group)
            .field("active", &self.active)
            .finish()
    }
}

#[cfg(feature = "display")]
impl<K: Hash + Eq + Display, V: Display> Display for Group<K, V> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        for (key, item) in &self.group {
            if self.active.as_ref().map_or(false, |a| a == key) {
                writeln!(f, "* {}:\n{}", key, item)?;
            } else {
                writeln!(f, "  {}:\n{}", key, item)?;
            }
        }
        Ok(())
    }
}

impl<K: Hash + Eq, V> Default for Group<K, V, RandomState> {
    #[inline]
    fn default() -> Group<K, V, RandomState> {
        Group::new()
    }
}

/// Builder for a group.
pub struct GroupBuilder<K: Hash + Eq, V, S: BuildHasher> {
    group: PhantomData<(K, V, S)>,
    capacity: usize,
    signals: Option<Box<FnMut(Option<&K>) + Send + Sync + 'static>>,
}

impl<K: Hash + Eq, V> GroupBuilder<K, V, RandomState> {
    /// Creates the group.
    #[inline]
    pub fn build(self) -> Group<K, V, RandomState> {
        self.build_with_hasher(Default::default())
    }
}

impl<K: Hash + Eq, V, S: BuildHasher> GroupBuilder<K, V, S> {
    /// Sets the specified [capacity] for the group.
    ///
    /// [capacity]: https://doc.rust-lang.org/std/vec/struct.Vec.html#capacity-and-reallocation
    #[inline]
    pub fn capacity(mut self, capacity: usize) -> GroupBuilder<K, V, S> {
        self.capacity = capacity;
        self
    }

    /// Decides what should happen when the active stack changes.
    #[inline]
    pub fn signals<F>(mut self, f: F) -> GroupBuilder<K, V, S>
        where
            F: FnMut(Option<&K>) + Send + Sync + 'static
    {
        self.signals = Some(Box::new(f));
        self
    }

    /// Creates the group with the given hasher.
    #[inline]
    pub fn build_with_hasher(self, hasher: S) -> Group<K, V, S> {
        Group {
            group: HashMap::with_capacity_and_hasher(self.capacity, hasher),
            active: None,
            signals: self.signals,
        }
    }
}

impl<K: Hash + Eq, V, S: BuildHasher> Debug for GroupBuilder<K, V, S> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("GroupBuilder")
            .field("group", &self.group)
            .field("capacity", &self.capacity)
            .finish()
    }
}
<|endoftext|>