<commit_before>use proc_macro2::{Span, TokenStream};
use quote::{ToTokens, TokenStreamExt};
use syn;
use BuilderPattern;
use DEFAULT_STRUCT_NAME;

use crate::{BlockContents, DefaultExpression};

/// Initializer for the target struct fields, implementing `quote::ToTokens`.
///
/// Lives in the body of `BuildMethod`.
///
/// # Examples
///
/// Will expand to something like the following (depending on settings):
///
/// ```rust,ignore
/// # extern crate proc_macro2;
/// # #[macro_use]
/// # extern crate quote;
/// # extern crate syn;
/// # #[macro_use]
/// # extern crate derive_builder_core;
/// # use derive_builder_core::{DeprecationNotes, Initializer, BuilderPattern};
/// # fn main() {
/// #    let mut initializer = default_initializer!();
/// #    initializer.default_value = Some("42".parse().unwrap());
/// #    initializer.builder_pattern = BuilderPattern::Owned;
/// #
/// #    assert_eq!(quote!(#initializer).to_string(), quote!(
/// foo: match self.foo {
///     Some(value) => value,
///     None => { 42 },
/// },
/// #    ).to_string());
/// # }
/// ```
#[derive(Debug, Clone)]
pub struct Initializer<'a> {
    /// Name of the target field.
    pub field_ident: &'a syn::Ident,
    /// Whether the builder implements a setter for this field.
    pub field_enabled: bool,
    /// How the build method takes and returns `self` (e.g. mutably).
    pub builder_pattern: BuilderPattern,
    /// Default value for the target field.
    ///
    /// This takes precedence over a default struct identifier.
    pub default_value: Option<&'a DefaultExpression>,
    /// Whether the build_method defines a default struct.
    pub use_default_struct: bool,
    /// Span where the macro was told to use a preexisting error type, instead of creating one,
    /// to represent failures of the `build` method.
    ///
    /// An initializer can force early-return if a field has no set value and no default is
    /// defined. In these cases, it will convert from `derive_builder::UninitializedFieldError`
    /// into the return type of its enclosing `build` method. That conversion is guaranteed to
    /// work for generated error types, but if the caller specified an error type to use instead
    /// they may have forgotten the conversion from `UninitializedFieldError` into their specified
    /// error type.
    pub custom_error_type_span: Option<Span>,
    /// Method to use to to convert the builder's field to the target field
    ///
    /// For sub-builder fields, this will be `build` (or similar)
    pub conversion: FieldConversion<'a>,
}

impl<'a> ToTokens for Initializer<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let struct_field = &self.field_ident;
        let builder_field = struct_field;

        // This structure prevents accidental failure to add the trailing `,` due to incautious `return`
        let append_rhs = |tokens: &mut TokenStream| {
            if !self.field_enabled {
                let default = self.default();
                tokens.append_all(quote!(
                    #default
                ));
            } else {
                match &self.conversion {
                    FieldConversion::Block(conv) => {
                        conv.to_tokens(tokens);
                    }
                    FieldConversion::Move => tokens.append_all(quote!( self.#builder_field )),
                    FieldConversion::OptionOrDefault => {
                        let match_some = self.match_some();
                        let match_none = self.match_none();
                        tokens.append_all(quote!(
                            match self.#builder_field {
                                #match_some,
                                #match_none,
                            }
                        ));
                    }
                }
            }
        };

        tokens.append_all(quote!(#struct_field:));
        append_rhs(tokens);
        tokens.append_all(quote!(,));
    }
}

impl<'a> Initializer<'a> {
    /// To be used inside of `#struct_field: match self.#builder_field { ... }`
    fn match_some(&'a self) -> MatchSome {
        match self.builder_pattern {
            BuilderPattern::Owned => MatchSome::Move,
            BuilderPattern::Mutable | BuilderPattern::Immutable => MatchSome::Clone,
        }
    }

    /// To be used inside of `#struct_field: match self.#builder_field { ... }`
    fn match_none(&'a self) -> MatchNone<'a> {
        match self.default_value {
            Some(expr) => MatchNone::DefaultTo(expr),
            None => {
                if self.use_default_struct {
                    MatchNone::UseDefaultStructField(self.field_ident)
                } else {
                    MatchNone::ReturnError(
                        self.field_ident.to_string(),
                        self.custom_error_type_span,
                    )
                }
            }
        }
    }

    fn default(&'a self) -> TokenStream {
        match self.default_value {
            Some(ref expr) => quote!(#expr),
            None if self.use_default_struct => {
                let struct_ident = syn::Ident::new(DEFAULT_STRUCT_NAME, Span::call_site());
                let field_ident = self.field_ident;
                quote!(#struct_ident.#field_ident)
            }
            None => quote!(::derive_builder::export::core::default::Default::default()),
        }
    }
}

#[derive(Debug, Clone)]
pub enum FieldConversion<'a> {
    /// Usual conversion: unwrap the Option from the builder, or (hope to) use a default value
    OptionOrDefault,
    /// Custom conversion is a block contents expression
    Block(&'a BlockContents),
    /// Custom conversion is just to move the field from the builder
    Move,
}

/// To be used inside of `#struct_field: match self.#builder_field { ... }`
enum MatchNone<'a> {
    /// Inner value must be a valid Rust expression
    DefaultTo(&'a DefaultExpression),
    /// Inner value must be the field identifier
    ///
    /// The default struct must be in scope in the build_method.
    UseDefaultStructField(&'a syn::Ident),
    /// Inner value must be the field name
    ReturnError(String, Option<Span>),
}

impl<'a> ToTokens for MatchNone<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match *self {
            MatchNone::DefaultTo(expr) => tokens.append_all(quote!(
                None => #expr
            )),
            MatchNone::UseDefaultStructField(field_ident) => {
                let struct_ident = syn::Ident::new(DEFAULT_STRUCT_NAME, Span::call_site());
                tokens.append_all(quote!(
                    None => #struct_ident.#field_ident
                ))
            }
            MatchNone::ReturnError(ref field_name, ref span) => {
                let conv_span = span.unwrap_or_else(Span::call_site);
                let err_conv = quote_spanned!(conv_span => ::derive_builder::export::core::convert::Into::into(
                    ::derive_builder::UninitializedFieldError::from(#field_name)
                ));
                tokens.append_all(quote!(
                    None => return ::derive_builder::export::core::result::Result::Err(#err_conv)
                ));
            }
        }
    }
}

/// To be used inside of `#struct_field: match self.#builder_field { ... }`
enum MatchSome {
    Move,
    Clone,
}

impl<'a> ToTokens for MatchSome {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match *self {
            Self::Move => tokens.append_all(quote!(
                Some(value) => value
            )),
            Self::Clone => tokens.append_all(quote!(
                Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value)
            )),
        }
    }
}

/// Helper macro for unit tests. This is _only_ public in order to be accessible
/// from doc-tests too.
#[doc(hidden)]
#[macro_export]
macro_rules! default_initializer {
    () => {
        Initializer {
            field_ident: &syn::Ident::new("foo", ::proc_macro2::Span::call_site()),
            field_enabled: true,
            builder_pattern: BuilderPattern::Mutable,
            default_value: None,
            use_default_struct: false,
            conversion: FieldConversion::OptionOrDefault,
            custom_error_type_span: None,
        }
    };
}

#[cfg(test)]
mod tests {
    #[allow(unused_imports)]
    use super::*;

    #[test]
    fn immutable() {
        let mut initializer = default_initializer!();
        initializer.builder_pattern = BuilderPattern::Immutable;

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(
                foo: match self.foo {
                    Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
                    None => return ::derive_builder::export::core::result::Result::Err(::derive_builder::export::core::convert::Into::into(
                        ::derive_builder::UninitializedFieldError::from("foo")
                    )),
                },
            )
            .to_string()
        );
    }

    #[test]
    fn mutable() {
        let mut initializer = default_initializer!();
        initializer.builder_pattern = BuilderPattern::Mutable;

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(
                foo: match self.foo {
                    Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
                    None => return ::derive_builder::export::core::result::Result::Err(::derive_builder::export::core::convert::Into::into(
                        ::derive_builder::UninitializedFieldError::from("foo")
                    )),
                },
            )
            .to_string()
        );
    }

    #[test]
    fn owned() {
        let mut initializer = default_initializer!();
        initializer.builder_pattern = BuilderPattern::Owned;

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(
                foo: match self.foo {
                    Some(value) => value,
                    None => return ::derive_builder::export::core::result::Result::Err(::derive_builder::export::core::convert::Into::into(
                        ::derive_builder::UninitializedFieldError::from("foo")
                    )),
                },
            )
            .to_string()
        );
    }

    #[test]
    fn default_value() {
        let mut initializer = default_initializer!();
        let default_value = DefaultExpression::explicit::<syn::Expr>(parse_quote!(42));
        initializer.default_value = Some(&default_value);

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(
                foo: match self.foo {
                    Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
                    None => { 42 },
                },
            )
            .to_string()
        );
    }

    #[test]
    fn default_struct() {
        let mut initializer = default_initializer!();
        initializer.use_default_struct = true;

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(
                foo: match self.foo {
                    Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
                    None => __default.foo,
                },
            )
            .to_string()
        );
    }

    #[test]
    fn setter_disabled() {
        let mut initializer = default_initializer!();
        initializer.field_enabled = false;

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(foo: ::derive_builder::export::core::default::Default::default(),).to_string()
        );
    }

    #[test]
    fn no_std() {
        let initializer = default_initializer!();

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(
                foo: match self.foo {
                    Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
                    None => return ::derive_builder::export::core::result::Result::Err(::derive_builder::export::core::convert::Into::into(
                        ::derive_builder::UninitializedFieldError::from("foo")
                    )),
                },
            )
            .to_string()
        );
    }
}
<commit_msg>NFC: Remove unused lifetime<commit_after>use proc_macro2::{Span, TokenStream};
use quote::{ToTokens, TokenStreamExt};
use syn;
use BuilderPattern;
use DEFAULT_STRUCT_NAME;

use crate::{BlockContents, DefaultExpression};

/// Initializer for the target struct fields, implementing `quote::ToTokens`.
///
/// Lives in the body of `BuildMethod`.
///
/// # Examples
///
/// Will expand to something like the following (depending on settings):
///
/// ```rust,ignore
/// # extern crate proc_macro2;
/// # #[macro_use]
/// # extern crate quote;
/// # extern crate syn;
/// # #[macro_use]
/// # extern crate derive_builder_core;
/// # use derive_builder_core::{DeprecationNotes, Initializer, BuilderPattern};
/// # fn main() {
/// #    let mut initializer = default_initializer!();
/// #    initializer.default_value = Some("42".parse().unwrap());
/// #    initializer.builder_pattern = BuilderPattern::Owned;
/// #
/// #    assert_eq!(quote!(#initializer).to_string(), quote!(
/// foo: match self.foo {
///     Some(value) => value,
///     None => { 42 },
/// },
/// #    ).to_string());
/// # }
/// ```
#[derive(Debug, Clone)]
pub struct Initializer<'a> {
    /// Name of the target field.
    pub field_ident: &'a syn::Ident,
    /// Whether the builder implements a setter for this field.
    pub field_enabled: bool,
    /// How the build method takes and returns `self` (e.g. mutably).
    pub builder_pattern: BuilderPattern,
    /// Default value for the target field.
    ///
    /// This takes precedence over a default struct identifier.
    pub default_value: Option<&'a DefaultExpression>,
    /// Whether the build_method defines a default struct.
    pub use_default_struct: bool,
    /// Span where the macro was told to use a preexisting error type, instead of creating one,
    /// to represent failures of the `build` method.
    ///
    /// An initializer can force early-return if a field has no set value and no default is
    /// defined. In these cases, it will convert from `derive_builder::UninitializedFieldError`
    /// into the return type of its enclosing `build` method. That conversion is guaranteed to
    /// work for generated error types, but if the caller specified an error type to use instead
    /// they may have forgotten the conversion from `UninitializedFieldError` into their specified
    /// error type.
    pub custom_error_type_span: Option<Span>,
    /// Method to use to to convert the builder's field to the target field
    ///
    /// For sub-builder fields, this will be `build` (or similar)
    pub conversion: FieldConversion<'a>,
}

impl<'a> ToTokens for Initializer<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let struct_field = &self.field_ident;
        let builder_field = struct_field;

        // This structure prevents accidental failure to add the trailing `,` due to incautious `return`
        let append_rhs = |tokens: &mut TokenStream| {
            if !self.field_enabled {
                let default = self.default();
                tokens.append_all(quote!(
                    #default
                ));
            } else {
                match &self.conversion {
                    FieldConversion::Block(conv) => {
                        conv.to_tokens(tokens);
                    }
                    FieldConversion::Move => tokens.append_all(quote!( self.#builder_field )),
                    FieldConversion::OptionOrDefault => {
                        let match_some = self.match_some();
                        let match_none = self.match_none();
                        tokens.append_all(quote!(
                            match self.#builder_field {
                                #match_some,
                                #match_none,
                            }
                        ));
                    }
                }
            }
        };

        tokens.append_all(quote!(#struct_field:));
        append_rhs(tokens);
        tokens.append_all(quote!(,));
    }
}

impl<'a> Initializer<'a> {
    /// To be used inside of `#struct_field: match self.#builder_field { ... }`
    fn match_some(&'a self) -> MatchSome {
        match self.builder_pattern {
            BuilderPattern::Owned => MatchSome::Move,
            BuilderPattern::Mutable | BuilderPattern::Immutable => MatchSome::Clone,
        }
    }

    /// To be used inside of `#struct_field: match self.#builder_field { ... }`
    fn match_none(&'a self) -> MatchNone<'a> {
        match self.default_value {
            Some(expr) => MatchNone::DefaultTo(expr),
            None => {
                if self.use_default_struct {
                    MatchNone::UseDefaultStructField(self.field_ident)
                } else {
                    MatchNone::ReturnError(
                        self.field_ident.to_string(),
                        self.custom_error_type_span,
                    )
                }
            }
        }
    }

    fn default(&'a self) -> TokenStream {
        match self.default_value {
            Some(ref expr) => quote!(#expr),
            None if self.use_default_struct => {
                let struct_ident = syn::Ident::new(DEFAULT_STRUCT_NAME, Span::call_site());
                let field_ident = self.field_ident;
                quote!(#struct_ident.#field_ident)
            }
            None => quote!(::derive_builder::export::core::default::Default::default()),
        }
    }
}

#[derive(Debug, Clone)]
pub enum FieldConversion<'a> {
    /// Usual conversion: unwrap the Option from the builder, or (hope to) use a default value
    OptionOrDefault,
    /// Custom conversion is a block contents expression
    Block(&'a BlockContents),
    /// Custom conversion is just to move the field from the builder
    Move,
}

/// To be used inside of `#struct_field: match self.#builder_field { ... }`
enum MatchNone<'a> {
    /// Inner value must be a valid Rust expression
    DefaultTo(&'a DefaultExpression),
    /// Inner value must be the field identifier
    ///
    /// The default struct must be in scope in the build_method.
    UseDefaultStructField(&'a syn::Ident),
    /// Inner value must be the field name
    ReturnError(String, Option<Span>),
}

impl<'a> ToTokens for MatchNone<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match *self {
            MatchNone::DefaultTo(expr) => tokens.append_all(quote!(
                None => #expr
            )),
            MatchNone::UseDefaultStructField(field_ident) => {
                let struct_ident = syn::Ident::new(DEFAULT_STRUCT_NAME, Span::call_site());
                tokens.append_all(quote!(
                    None => #struct_ident.#field_ident
                ))
            }
            MatchNone::ReturnError(ref field_name, ref span) => {
                let conv_span = span.unwrap_or_else(Span::call_site);
                let err_conv = quote_spanned!(conv_span => ::derive_builder::export::core::convert::Into::into(
                    ::derive_builder::UninitializedFieldError::from(#field_name)
                ));
                tokens.append_all(quote!(
                    None => return ::derive_builder::export::core::result::Result::Err(#err_conv)
                ));
            }
        }
    }
}

/// To be used inside of `#struct_field: match self.#builder_field { ... }`
enum MatchSome {
    Move,
    Clone,
}

impl ToTokens for MatchSome {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match *self {
            Self::Move => tokens.append_all(quote!(
                Some(value) => value
            )),
            Self::Clone => tokens.append_all(quote!(
                Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value)
            )),
        }
    }
}

/// Helper macro for unit tests. This is _only_ public in order to be accessible
/// from doc-tests too.
#[doc(hidden)]
#[macro_export]
macro_rules! default_initializer {
    () => {
        Initializer {
            field_ident: &syn::Ident::new("foo", ::proc_macro2::Span::call_site()),
            field_enabled: true,
            builder_pattern: BuilderPattern::Mutable,
            default_value: None,
            use_default_struct: false,
            conversion: FieldConversion::OptionOrDefault,
            custom_error_type_span: None,
        }
    };
}

#[cfg(test)]
mod tests {
    #[allow(unused_imports)]
    use super::*;

    #[test]
    fn immutable() {
        let mut initializer = default_initializer!();
        initializer.builder_pattern = BuilderPattern::Immutable;

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(
                foo: match self.foo {
                    Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
                    None => return ::derive_builder::export::core::result::Result::Err(::derive_builder::export::core::convert::Into::into(
                        ::derive_builder::UninitializedFieldError::from("foo")
                    )),
                },
            )
            .to_string()
        );
    }

    #[test]
    fn mutable() {
        let mut initializer = default_initializer!();
        initializer.builder_pattern = BuilderPattern::Mutable;

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(
                foo: match self.foo {
                    Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
                    None => return ::derive_builder::export::core::result::Result::Err(::derive_builder::export::core::convert::Into::into(
                        ::derive_builder::UninitializedFieldError::from("foo")
                    )),
                },
            )
            .to_string()
        );
    }

    #[test]
    fn owned() {
        let mut initializer = default_initializer!();
        initializer.builder_pattern = BuilderPattern::Owned;

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(
                foo: match self.foo {
                    Some(value) => value,
                    None => return ::derive_builder::export::core::result::Result::Err(::derive_builder::export::core::convert::Into::into(
                        ::derive_builder::UninitializedFieldError::from("foo")
                    )),
                },
            )
            .to_string()
        );
    }

    #[test]
    fn default_value() {
        let mut initializer = default_initializer!();
        let default_value = DefaultExpression::explicit::<syn::Expr>(parse_quote!(42));
        initializer.default_value = Some(&default_value);

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(
                foo: match self.foo {
                    Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
                    None => { 42 },
                },
            )
            .to_string()
        );
    }

    #[test]
    fn default_struct() {
        let mut initializer = default_initializer!();
        initializer.use_default_struct = true;

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(
                foo: match self.foo {
                    Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
                    None => __default.foo,
                },
            )
            .to_string()
        );
    }

    #[test]
    fn setter_disabled() {
        let mut initializer = default_initializer!();
        initializer.field_enabled = false;

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(foo: ::derive_builder::export::core::default::Default::default(),).to_string()
        );
    }

    #[test]
    fn no_std() {
        let initializer = default_initializer!();

        assert_eq!(
            quote!(#initializer).to_string(),
            quote!(
                foo: match self.foo {
                    Some(ref value) => ::derive_builder::export::core::clone::Clone::clone(value),
                    None => return ::derive_builder::export::core::result::Result::Err(::derive_builder::export::core::convert::Into::into(
                        ::derive_builder::UninitializedFieldError::from("foo")
                    )),
                },
            )
            .to_string()
        );
    }
}
<|endoftext|>


<commit_before>use std::cast;
use std::libc;
use std::ptr;
use std::str;

// CU16String is a cursed version of `std::c_str::CString` for
// null-terminated utf-16 strings.

/// The representation of a C UTF-16 string.
pub struct CU16String {
    priv buf: *u16,
    priv owns_buffer_: bool,
}

// TODO: iter
impl CU16String {
    /// Create a CU16String from a pointer.
    pub unsafe fn new(buf: *u16, owns_buffer: bool) -> CU16String {
        CU16String { buf: buf, owns_buffer_: owns_buffer }
    }

    /// Unwraps the wrapped `*u16` from the `CU16String` wrapper.
    /// Any ownership of the buffer by the `CU16String` wrapper is forgotten.
    pub unsafe fn unwrap(self) -> *u16 {
        let mut c_u16_str = self;
        c_u16_str.owns_buffer_ = false;
        c_u16_str.buf
    }

    /// Calls a closure with a reference to the underlying `*u16`.
    ///
    /// # Failure
    ///
    /// Fails if the CU16String is null.
    pub fn with_ref<T>(&self, f: |*u16| -> T) -> T {
        if self.buf.is_null() { fail!("CU16String is null!"); }
        f(self.buf)
    }

    /// Calls a closure with a mutable reference to the underlying `*u16`.
    ///
    /// # Failure
    ///
    /// Fails if the CU16String is null.
    pub fn with_mut_ref<T>(&mut self, f: |*mut u16| -> T) -> T {
        if self.buf.is_null() { fail!("CU16String is null!"); }
        f(unsafe { cast::transmute_mut_unsafe(self.buf) })
    }

    /// Returns true if the CU16String is a null.
    pub fn is_null(&self) -> bool {
        self.buf.is_null()
    }

    /// Returns true if the CU16String is not null.
    pub fn is_not_null(&self) -> bool {
        self.buf.is_not_null()
    }

    /// Returns whether or not the `CU16String` owns the buffer.
    pub fn owns_buffer(&self) -> bool {
        self.owns_buffer_
    }
}

impl CU16String {
    /// Converts the CU16String into a `&[u8]` without copying.
    ///
    /// # Failure
    ///
    /// Fails if the CU16String is null.
    #[inline]
    pub fn as_u16_vec<'a>(&'a self) -> &'a [u16] {
        if self.buf.is_null() { fail!("CU16String is null!"); }
        unsafe {
            cast::transmute((self.buf, self.len() + 1))
        }
    }
}

impl ToStr for CU16String {
    #[inline]
    fn to_str(&self) -> ~str {
        if self.buf.is_null() {
        }
        str::from_utf16(self.as_u16_vec())
    }
}

impl Drop for CU16String {
    fn drop(&mut self) {
        if self.owns_buffer_ {
            unsafe {
                libc::free(self.buf as *libc::c_void)
            }
        }
    }
}

impl Container for CU16String {
    #[inline]
    fn len(&self) -> uint {
        unsafe {
            ptr::position(self.buf, |c| *c == 0)
        }
    }
}

/// Parses a C utf-16 "multistring".
/// See `std::c_str::from_c_multistring` for detailed explanation.
pub unsafe fn from_c_u16_multistring(buf: *u16, count: Option<uint>, f: |&CU16String|) -> uint {

    let mut curr_ptr: uint = buf as uint;
    let mut ctr = 0;
    let (limited_count, limit) = match count {
        Some(limit) => (true, limit),
        None => (false, 0)
    };
    while ((limited_count && ctr < limit) || !limited_count)
          && *(curr_ptr as *u16) != 0 as u16 {
        let cstr = CU16String::new(curr_ptr as *u16, false);
        f(&cstr);
        curr_ptr += (cstr.len() * 1 + 1) * 2;
        ctr += 1;
    }
    return ctr;
}

/// A generic trait for converting a value to a `CU16String`, like `ToCStr`.
pub trait ToCU16Str {
    fn with_c_u16_str<T>(&self, f: |*u16| -> T) -> T;
    fn with_c_u16_str_mut<T>(&mut self, f: |*mut u16| -> T) -> T;
}

impl<'a> ToCU16Str for &'a str {
    fn with_c_u16_str<T>(&self, f: |*u16| -> T) -> T {
        let mut t = self.to_utf16();
        // Null terminate before passing on.
        t.push(0u16);
        f(t.as_ptr())
    }

    fn with_c_u16_str_mut<T>(&mut self, f: |*mut u16| -> T) -> T {
        let mut t = self.to_utf16();
        t.push(0u16);
        f(t.as_mut_ptr())
    }
}

impl<S: Str> ToCU16Str for Option<S> {
    fn with_c_u16_str<T>(&self, f: |*u16| -> T) -> T {
        match self {
            &None => f(ptr::null()),
            &Some(ref s) => {
                s.as_slice().with_c_u16_str(f)
            },
        }
    }

    fn with_c_u16_str_mut<T>(&mut self, f: |*mut u16| -> T) -> T {
        match self {
            &None => f(ptr::mut_null()),
            &Some(ref s) => {
                s.as_slice().with_c_u16_str_mut(f)
            },
        }
    }
}

#[cfg(test)]
mod test {
    use super::CU16String;
    use super::from_c_u16_multistring;

    #[test]
    fn test_as_u16_vec() {
        let u16s: &[u16] = [
            0xac00, 0x20, 0xac00, 0x00,
        ];

        u16s.as_imm_buf(|buf, _len| {
            let cu = unsafe { CU16String::new(buf, false) };
            let v = cu.as_u16_vec();
            debug!("v: {:?}", v);
            assert_eq!(v, u16s);
        })
    }

    #[test]
    fn test_from_c_u16_multistring() {
        let test: &[u16] = [
            0xac00, 0x00,
            0xac00, 0xac00, 0x00,
            0xac00, 0xac00, 0xac00, 0x00,
            0xac00, 0xac00, 0xac00, 0xac02, 0x00,
            0x00,
        ];
        let compare = [
            "가",
            "가가",
            "가가가",
            "가가가갂",
        ];
        let mut i = 0;
        test.as_imm_buf(|buf, _len| {
            unsafe {
                from_c_u16_multistring(buf, None, |cu| {
                    let b = cu.to_str();
                    assert_eq!(b.char_len(), i + 1);
                    assert_eq!(b, compare[i].to_owned());
                    i += 1;
                })
            }
        });
        assert_eq!(i, 4);
    }
}
<commit_msg>wchar: Add .to_c_u16()<commit_after>use std::cast;
use std::libc;
use std::ptr;
use std::str;

// CU16String is a cursed version of `std::c_str::CString` for
// null-terminated utf-16 strings.

/// The representation of a C UTF-16 string.
pub struct CU16String {
    priv buf: *u16,
    priv owns_buffer_: bool,
}

// TODO: iter
impl CU16String {
    /// Create a CU16String from a pointer.
    pub unsafe fn new(buf: *u16, owns_buffer: bool) -> CU16String {
        CU16String { buf: buf, owns_buffer_: owns_buffer }
    }

    /// Unwraps the wrapped `*u16` from the `CU16String` wrapper.
    /// Any ownership of the buffer by the `CU16String` wrapper is forgotten.
    pub unsafe fn unwrap(self) -> *u16 {
        let mut c_u16_str = self;
        c_u16_str.owns_buffer_ = false;
        c_u16_str.buf
    }

    /// Calls a closure with a reference to the underlying `*u16`.
    ///
    /// # Failure
    ///
    /// Fails if the CU16String is null.
    pub fn with_ref<T>(&self, f: |*u16| -> T) -> T {
        if self.buf.is_null() { fail!("CU16String is null!"); }
        f(self.buf)
    }

    /// Calls a closure with a mutable reference to the underlying `*u16`.
    ///
    /// # Failure
    ///
    /// Fails if the CU16String is null.
    pub fn with_mut_ref<T>(&mut self, f: |*mut u16| -> T) -> T {
        if self.buf.is_null() { fail!("CU16String is null!"); }
        f(unsafe { cast::transmute_mut_unsafe(self.buf) })
    }

    /// Returns true if the CU16String is a null.
    pub fn is_null(&self) -> bool {
        self.buf.is_null()
    }

    /// Returns true if the CU16String is not null.
    pub fn is_not_null(&self) -> bool {
        self.buf.is_not_null()
    }

    /// Returns whether or not the `CU16String` owns the buffer.
    pub fn owns_buffer(&self) -> bool {
        self.owns_buffer_
    }
}

impl CU16String {
    /// Converts the CU16String into a `&[u8]` without copying.
    ///
    /// # Failure
    ///
    /// Fails if the CU16String is null.
    #[inline]
    pub fn as_u16_vec<'a>(&'a self) -> &'a [u16] {
        if self.buf.is_null() { fail!("CU16String is null!"); }
        unsafe {
            cast::transmute((self.buf, self.len() + 1))
        }
    }
}

impl ToStr for CU16String {
    #[inline]
    fn to_str(&self) -> ~str {
        if self.buf.is_null() {
        }
        str::from_utf16(self.as_u16_vec())
    }
}

impl Drop for CU16String {
    fn drop(&mut self) {
        if self.owns_buffer_ {
            unsafe {
                libc::free(self.buf as *libc::c_void)
            }
        }
    }
}

impl Container for CU16String {
    #[inline]
    fn len(&self) -> uint {
        unsafe {
            ptr::position(self.buf, |c| *c == 0)
        }
    }
}

/// Parses a C utf-16 "multistring".
/// See `std::c_str::from_c_multistring` for detailed explanation.
pub unsafe fn from_c_u16_multistring(buf: *u16, count: Option<uint>, f: |&CU16String|) -> uint {

    let mut curr_ptr: uint = buf as uint;
    let mut ctr = 0;
    let (limited_count, limit) = match count {
        Some(limit) => (true, limit),
        None => (false, 0)
    };
    while ((limited_count && ctr < limit) || !limited_count)
          && *(curr_ptr as *u16) != 0 as u16 {
        let cstr = CU16String::new(curr_ptr as *u16, false);
        f(&cstr);
        curr_ptr += (cstr.len() * 1 + 1) * 2;
        ctr += 1;
    }
    return ctr;
}

/// A generic trait for converting a value to a `CU16String`, like `ToCStr`.
pub trait ToCU16Str {
    fn to_c_u16(&self) -> ~[u16];

    fn with_c_u16_str<T>(&self, f: |*u16| -> T) -> T {
        let t = self.to_c_u16();
        f(t.as_ptr())
    }

    fn with_c_u16_str_mut<T>(&mut self, f: |*mut u16| -> T) -> T {
        let mut t = self.to_c_u16();
        f(t.as_mut_ptr())
    }
}

impl<'a> ToCU16Str for &'a str {
    fn to_c_u16(&self) -> ~[u16] {
        let mut t = self.to_utf16();
        t.push(0u16);
        t
    }
}

impl<S: Str> ToCU16Str for Option<S> {
    fn to_c_u16(&self) -> ~[u16] {
        match self {
            &None => ~[],
            &Some(ref s) => s.as_slice().to_c_u16(),
        }
    }

    fn with_c_u16_str<T>(&self, f: |*u16| -> T) -> T {
        match self {
            &None => f(ptr::null()),
            &Some(ref s) => {
                s.as_slice().with_c_u16_str(f)
            },
        }
    }

    fn with_c_u16_str_mut<T>(&mut self, f: |*mut u16| -> T) -> T {
        match self {
            &None => f(ptr::mut_null()),
            &Some(ref s) => {
                s.as_slice().with_c_u16_str_mut(f)
            },
        }
    }
}

#[cfg(test)]
mod test {
    use super::CU16String;
    use super::from_c_u16_multistring;

    #[test]
    fn test_as_u16_vec() {
        let u16s: &[u16] = [
            0xac00, 0x20, 0xac00, 0x00,
        ];

        let cu = unsafe { CU16String::new(u16s.as_ptr(), false) };
        let v = cu.as_u16_vec();
        assert_eq!(v, u16s);
    }

    #[test]
    fn test_from_c_u16_multistring() {
        let test: &[u16] = [
            0xac00, 0x00,
            0xac00, 0xac00, 0x00,
            0xac00, 0xac00, 0xac00, 0x00,
            0xac00, 0xac00, 0xac00, 0xac02, 0x00,
            0x00,
        ];
        let compare = [
            "가",
            "가가",
            "가가가",
            "가가가갂",
        ];
        let mut i = 0;
        let buf = test.as_ptr();
        unsafe {
            from_c_u16_multistring(buf, None, |cu| {
                let b = cu.to_str();
                assert_eq!(b.char_len(), i + 1);
                assert_eq!(b, compare[i].to_owned());
                i += 1;
            });
        }
        assert_eq!(i, 4);
    }
}
<|endoftext|>


<commit_before>use std::{
    hash::{Hash, Hasher},
    sync::Arc,
    cell::RefCell,
    fmt::Debug,
    any::Any,
};
use parking_lot::Mutex;
use libsyntax2::{File};
use im;
use {
    FileId,
    imp::{FileResolverImp},
};

#[derive(Debug)]
pub(crate) struct DbHost {
    db: Arc<Db>,
}

impl DbHost {
    pub(crate) fn new() -> DbHost {
        let db = Db {
            file_resolver: FileResolverImp::default(),
            files: im::HashMap::new(),
            cache: Mutex::new(Cache::new())
        };
        DbHost { db: Arc::new(db) }
    }
    pub(crate) fn change_file(&mut self, file_id: FileId, text: Option<String>) {
        let db = self.db_mut();
        match text {
            None => {
                db.files.remove(&file_id);
            }
            Some(text) => {
                db.files.insert(file_id, Arc::new(text));
            }
        }
    }
    pub(crate) fn set_file_resolver(&mut self, file_resolver: FileResolverImp) {
        let db = self.db_mut();
        db.file_resolver = file_resolver
    }
    pub(crate) fn query_ctx(&self) -> QueryCtx {
        QueryCtx {
            db: Arc::clone(&self.db),
            stack: RefCell::new(Vec::new()),
            trace: RefCell::new(Vec::new()),
        }
    }
    fn db_mut(&mut self) -> &mut Db {
        // NB: this "forks" the database
        let db = Arc::make_mut(&mut self.db);
        db.cache.get_mut().gen += 1;
        db
    }
}

type QueryInvocationId = (u32, u64);
type Gen = u64;
type OutputHash = u64;

fn id<Q: Query>(params: &Q::Params) -> QueryInvocationId {
    use std::collections::hash_map::DefaultHasher;
    let mut hasher = DefaultHasher::new();
    params.hash(&mut hasher);
    (Q::ID, hasher.finish())
}
fn output_hash<Q: Query>(output: &Q::Output) -> OutputHash {
    use std::collections::hash_map::DefaultHasher;
    let mut hasher = DefaultHasher::new();
    output.hash(&mut hasher);
    hasher.finish()
}

#[derive(Debug)]
pub(crate) struct Db {
    file_resolver: FileResolverImp,
    files: im::HashMap<FileId, Arc<String>>,
    cache: Mutex<Cache>,
}

impl Clone for Db {
    fn clone(&self) -> Db {
        Db {
            file_resolver: self.file_resolver.clone(),
            files: self.files.clone(),
            cache: Mutex::new(Cache::new()),
        }
    }
}

#[derive(Default, Debug)]
pub(crate) struct Cache {
    gen: Gen,
    green: im::HashMap<QueryInvocationId, (Gen, OutputHash)>,
    deps: im::HashMap<QueryInvocationId, Vec<(QueryInvocationId, OutputHash)>>,
    results: im::HashMap<QueryInvocationId, Arc<Any>>,
}

#[allow(type_alias_bounds)]
pub(crate) type QueryCache<Q: Query> = im::HashMap<
    <Q as Query>::Params,
    <Q as Query>::Output
>;

impl Cache {
    fn new() -> Cache {
        Default::default()
    }

    fn get_result<Q: Query>(&self, id: QueryInvocationId) -> Q::Output
    where
        Q::Output: Clone
    {
        let res = &self.results[&id];
        let res = res.downcast_ref::<Q::Output>().unwrap();
        res.clone()
    }
}

pub(crate) struct QueryCtx {
    db: Arc<Db>,
    stack: RefCell<Vec<(QueryInvocationId, Vec<(QueryInvocationId, OutputHash)>)>>,
    pub(crate) trace: RefCell<Vec<TraceEvent>>,
}

#[derive(Clone, Copy, Debug)]
pub(crate) struct TraceEvent {
    pub(crate) query_id: u32,
    pub(crate) kind: TraceEventKind
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum TraceEventKind {
    Start, Evaluating, Finish
}

impl QueryCtx {
    pub(crate) fn get<Q: Get>(&self, params: &Q::Params) -> Q::Output {
        let me = id::<Q>(params);
        self.trace(TraceEvent { query_id: Q::ID, kind: TraceEventKind::Start });
        let res = Q::get(self, params);
        self.trace(TraceEvent { query_id: Q::ID, kind: TraceEventKind::Finish });
        {
            let mut stack = self.stack.borrow_mut();
            if let Some((_, ref mut deps)) = stack.last_mut() {
                deps.push((me, output_hash::<Q>(&res)));
            }
        }

        res
    }
    fn trace(&self, event: TraceEvent) {
        self.trace.borrow_mut().push(event)
    }
}

pub(crate) trait Query {
    const ID: u32;
    type Params: Hash + Eq + Debug + Any + 'static;
    type Output: Hash + Debug + Any + 'static;
}

pub(crate) trait Get: Query {
    fn get(ctx: &QueryCtx, params: &Self::Params) -> Self::Output;
}

impl<Q: Eval> Get for Q
where
    Q::Params: Clone,
    Q::Output: Clone,
{
    fn get(ctx: &QueryCtx, params: &Self::Params) -> Self::Output {
        if let Some(res) = try_reuse::<Q>(ctx, params) {
            return res;
        }

        let me = id::<Q>(params);
        ctx.trace(TraceEvent { query_id: Q::ID, kind: TraceEventKind::Evaluating });
        ctx.stack.borrow_mut().push((me, Vec::new()));
        let res = Self::eval(ctx, params);
        let (also_me, deps) = ctx.stack.borrow_mut().pop().unwrap();
        assert_eq!(also_me, me);
        let mut cache = ctx.db.cache.lock();
        cache.deps.insert(me, deps);
        let gen = cache.gen;
        let output_hash = output_hash::<Q>(&res);
        let id = id::<Q>(params);
        cache.green.insert(id, (gen, output_hash));
        cache.results.insert(me, Arc::new(res.clone()));
        res
    }
}

fn try_reuse<Q: Eval>(ctx: &QueryCtx, params: &Q::Params) -> Option<Q::Output>
where
    Q::Params: Clone,
    Q::Output: Clone,
{
    let id = id::<Q>(params);
    let mut cache = ctx.db.cache.lock();
    let curr_gen = cache.gen;
    let old_hash = match *cache.green.get(&id)? {
        (gen, _) if gen == curr_gen => {
            return Some(cache.get_result::<Q>(id));
        }
        (_, hash) => hash,
    };
    let deps_are_fresh = cache.deps[&id]
        .iter()
        .all(|&(dep_id, dep_hash)| {
            match cache.green.get(&dep_id) {
                //TODO: store the value of parameters, and re-execute the query
                Some((gen, hash)) if gen == &curr_gen && hash == &dep_hash => true,
                _ => false,
            }
        });
    if !deps_are_fresh {
        return None;
    }
    cache.green.insert(id, (curr_gen, old_hash));
    Some(cache.get_result::<Q>(id))
}

pub(crate) trait Eval: Query
where
    Self::Params: Clone,
    Self::Output: Clone,
{
    fn eval(ctx: &QueryCtx, params: &Self::Params) -> Self::Output;
}

#[derive(Debug)]
pub(crate) struct DbFiles {
    db: Arc<Db>,
}

impl Hash for DbFiles {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        self.db.cache.lock().gen.hash(hasher)
    }
}

impl DbFiles {
    pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item=FileId> + 'a {
        self.db.files.keys().cloned()
    }
    pub(crate) fn file_resolver(&self) -> FileResolverImp {
        self.db.file_resolver.clone()
    }
}

pub(crate) enum Files {}
impl Query for Files {
    const ID: u32 = 1;
    type Params = ();
    type Output = DbFiles;
}
impl Get for Files {
    fn get(ctx: &QueryCtx, params: &()) -> DbFiles {
        let res = DbFiles { db: Arc::clone(&ctx.db) };
        let id = id::<Self>(params);
        let hash = output_hash::<Self>(&res);
        let mut cache = ctx.db.cache.lock();
        let gen = cache.gen;
        cache.green.insert(id, (gen, hash));
        res
    }
}

enum FileText {}
impl Query for FileText {
    const ID: u32 = 10;
    type Params = FileId;
    type Output = Arc<String>;
}
impl Get for FileText {
    fn get(ctx: &QueryCtx, file_id: &FileId) -> Arc<String> {
        let res = ctx.db.files[file_id].clone();
        let id = id::<Self>(file_id);
        let hash = output_hash::<Self>(&res);
        let mut cache = ctx.db.cache.lock();
        let gen = cache.gen;
        cache.green.insert(id, (gen, hash));
        res
    }
}

pub(crate) enum FileSyntax {}
impl Query for FileSyntax {
    const ID: u32 = 20;
    type Params = FileId;
    type Output = File;
}
impl Eval for FileSyntax {
    fn eval(ctx: &QueryCtx, file_id: &FileId) -> File {
        let text = ctx.get::<FileText>(file_id);
        File::parse(&text)
    }
}
<commit_msg>store params in the graph<commit_after>use std::{
    hash::{Hash, Hasher},
    sync::Arc,
    cell::RefCell,
    fmt::Debug,
    any::Any,
};
use parking_lot::Mutex;
use libsyntax2::{File};
use im;
use {
    FileId,
    imp::{FileResolverImp},
};

#[derive(Debug)]
pub(crate) struct DbHost {
    db: Arc<Db>,
}

impl DbHost {
    pub(crate) fn new() -> DbHost {
        let db = Db {
            file_resolver: FileResolverImp::default(),
            files: im::HashMap::new(),
            cache: Mutex::new(Cache::new())
        };
        DbHost { db: Arc::new(db) }
    }
    pub(crate) fn change_file(&mut self, file_id: FileId, text: Option<String>) {
        let db = self.db_mut();
        match text {
            None => {
                db.files.remove(&file_id);
            }
            Some(text) => {
                db.files.insert(file_id, Arc::new(text));
            }
        }
    }
    pub(crate) fn set_file_resolver(&mut self, file_resolver: FileResolverImp) {
        let db = self.db_mut();
        db.file_resolver = file_resolver
    }
    pub(crate) fn query_ctx(&self) -> QueryCtx {
        QueryCtx {
            db: Arc::clone(&self.db),
            stack: RefCell::new(Vec::new()),
            trace: RefCell::new(Vec::new()),
        }
    }
    fn db_mut(&mut self) -> &mut Db {
        // NB: this "forks" the database
        let db = Arc::make_mut(&mut self.db);
        db.cache.get_mut().gen += 1;
        db
    }
}

type QueryInvocationId = (u32, u64);
type Gen = u64;
type OutputHash = u64;

fn id<Q: Query>(params: &Q::Params) -> QueryInvocationId {
    use std::collections::hash_map::DefaultHasher;
    let mut hasher = DefaultHasher::new();
    params.hash(&mut hasher);
    (Q::ID, hasher.finish())
}
fn output_hash<Q: Query>(output: &Q::Output) -> OutputHash {
    use std::collections::hash_map::DefaultHasher;
    let mut hasher = DefaultHasher::new();
    output.hash(&mut hasher);
    hasher.finish()
}

#[derive(Debug)]
pub(crate) struct Db {
    file_resolver: FileResolverImp,
    files: im::HashMap<FileId, Arc<String>>,
    cache: Mutex<Cache>,
}

impl Clone for Db {
    fn clone(&self) -> Db {
        Db {
            file_resolver: self.file_resolver.clone(),
            files: self.files.clone(),
            cache: Mutex::new(Cache::new()),
        }
    }
}

type QueryDeps = Vec<(QueryInvocationId, Arc<Any>, OutputHash)>;

#[derive(Default, Debug)]
pub(crate) struct Cache {
    gen: Gen,
    green: im::HashMap<QueryInvocationId, (Gen, OutputHash)>,
    deps: im::HashMap<QueryInvocationId, QueryDeps>,
    results: im::HashMap<QueryInvocationId, Arc<Any>>,
}

#[allow(type_alias_bounds)]
pub(crate) type QueryCache<Q: Query> = im::HashMap<
    <Q as Query>::Params,
    <Q as Query>::Output
>;

impl Cache {
    fn new() -> Cache {
        Default::default()
    }

    fn get_result<Q: Query>(&self, id: QueryInvocationId) -> Q::Output
    where
        Q::Output: Clone
    {
        let res = &self.results[&id];
        let res = res.downcast_ref::<Q::Output>().unwrap();
        res.clone()
    }
}

pub(crate) struct QueryCtx {
    db: Arc<Db>,
    stack: RefCell<Vec<(QueryInvocationId, QueryDeps)>>,
    pub(crate) trace: RefCell<Vec<TraceEvent>>,
}

#[derive(Clone, Copy, Debug)]
pub(crate) struct TraceEvent {
    pub(crate) query_id: u32,
    pub(crate) kind: TraceEventKind
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum TraceEventKind {
    Start, Evaluating, Finish
}

impl QueryCtx {
    pub(crate) fn get<Q: Get>(&self, params: &Q::Params) -> Q::Output {
        let me = id::<Q>(params);
        self.trace(TraceEvent { query_id: Q::ID, kind: TraceEventKind::Start });
        let res = Q::get(self, params);
        self.trace(TraceEvent { query_id: Q::ID, kind: TraceEventKind::Finish });
        {
            let mut stack = self.stack.borrow_mut();
            if let Some((_, ref mut deps)) = stack.last_mut() {
                let params = Arc::new(params.clone());
                deps.push((me, params, output_hash::<Q>(&res)));
            }
        }

        res
    }
    fn trace(&self, event: TraceEvent) {
        self.trace.borrow_mut().push(event)
    }
}

pub(crate) trait Query {
    const ID: u32;
    type Params: Hash + Eq + Debug + Clone + Any + 'static;
    type Output: Hash + Debug + Any + 'static;
}

pub(crate) trait Get: Query {
    fn get(ctx: &QueryCtx, params: &Self::Params) -> Self::Output;
}

impl<Q: Eval> Get for Q
where
    Q::Params: Clone,
    Q::Output: Clone,
{
    fn get(ctx: &QueryCtx, params: &Self::Params) -> Self::Output {
        if let Some(res) = try_reuse::<Q>(ctx, params) {
            return res;
        }

        let me = id::<Q>(params);
        ctx.trace(TraceEvent { query_id: Q::ID, kind: TraceEventKind::Evaluating });
        ctx.stack.borrow_mut().push((me, Vec::new()));
        let res = Self::eval(ctx, params);
        let (also_me, deps) = ctx.stack.borrow_mut().pop().unwrap();
        assert_eq!(also_me, me);
        let mut cache = ctx.db.cache.lock();
        cache.deps.insert(me, deps);
        let gen = cache.gen;
        let output_hash = output_hash::<Q>(&res);
        let id = id::<Q>(params);
        cache.green.insert(id, (gen, output_hash));
        cache.results.insert(me, Arc::new(res.clone()));
        res
    }
}

fn try_reuse<Q: Eval>(ctx: &QueryCtx, params: &Q::Params) -> Option<Q::Output>
where
    Q::Params: Clone,
    Q::Output: Clone,
{
    let id = id::<Q>(params);
    let mut cache = ctx.db.cache.lock();
    let curr_gen = cache.gen;
    let old_hash = match *cache.green.get(&id)? {
        (gen, _) if gen == curr_gen => {
            return Some(cache.get_result::<Q>(id));
        }
        (_, hash) => hash,
    };
    let deps_are_fresh = cache.deps[&id]
        .iter()
        .all(|&(dep_id, _, dep_hash)| {
            match cache.green.get(&dep_id) {
                //TODO: store the value of parameters, and re-execute the query
                Some((gen, hash)) if gen == &curr_gen && hash == &dep_hash => true,
                _ => false,
            }
        });
    if !deps_are_fresh {
        return None;
    }
    cache.green.insert(id, (curr_gen, old_hash));
    Some(cache.get_result::<Q>(id))
}

pub(crate) trait Eval: Query
where
    Self::Params: Clone,
    Self::Output: Clone,
{
    fn eval(ctx: &QueryCtx, params: &Self::Params) -> Self::Output;
}

#[derive(Debug)]
pub(crate) struct DbFiles {
    db: Arc<Db>,
}

impl Hash for DbFiles {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        self.db.cache.lock().gen.hash(hasher)
    }
}

impl DbFiles {
    pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item=FileId> + 'a {
        self.db.files.keys().cloned()
    }
    pub(crate) fn file_resolver(&self) -> FileResolverImp {
        self.db.file_resolver.clone()
    }
}

pub(crate) enum Files {}
impl Query for Files {
    const ID: u32 = 1;
    type Params = ();
    type Output = DbFiles;
}
impl Get for Files {
    fn get(ctx: &QueryCtx, params: &()) -> DbFiles {
        let res = DbFiles { db: Arc::clone(&ctx.db) };
        let id = id::<Self>(params);
        let hash = output_hash::<Self>(&res);
        let mut cache = ctx.db.cache.lock();
        let gen = cache.gen;
        cache.green.insert(id, (gen, hash));
        res
    }
}

enum FileText {}
impl Query for FileText {
    const ID: u32 = 10;
    type Params = FileId;
    type Output = Arc<String>;
}
impl Get for FileText {
    fn get(ctx: &QueryCtx, file_id: &FileId) -> Arc<String> {
        let res = ctx.db.files[file_id].clone();
        let id = id::<Self>(file_id);
        let hash = output_hash::<Self>(&res);
        let mut cache = ctx.db.cache.lock();
        let gen = cache.gen;
        cache.green.insert(id, (gen, hash));
        res
    }
}

pub(crate) enum FileSyntax {}
impl Query for FileSyntax {
    const ID: u32 = 20;
    type Params = FileId;
    type Output = File;
}
impl Eval for FileSyntax {
    fn eval(ctx: &QueryCtx, file_id: &FileId) -> File {
        let text = ctx.get::<FileText>(file_id);
        File::parse(&text)
    }
}
<|endoftext|>


<commit_before>use tokens::*;
use symbols::*;
use symbols::symbol_table::*;
use support::*;
use plp::PLPWriter;

/// @return: (method_label, return_label)
pub fn get_method_labels(method_symbol: &Symbol) -> (String, String)
{
    let method_label = match method_symbol.location {
        SymbolLocation::Memory(ref address) => address.label_name.clone(),
        _ => { panic!("compile_method_body: Expected Memory address for method"); },
    };

    let mut return_label = method_label.clone();
    return_label.push_str("_return");

    (method_label, return_label)
}

/// @return (memory_label, memory_size)
pub fn get_static_allocation(method_symbol: &Symbol) -> (String, u16)
{
    match method_symbol.symbol_class {
            SymbolClass::Variable(_) => {
                    panic!("Expected Function found Variable");
                },
            SymbolClass::Function(_, _, ref label_name, var_count) => (label_name.clone(), var_count as u16),
            SymbolClass::Structure(ref subtype) => {
                    panic!("Expected Function found {}", subtype);
                }
        }
}

/// @return (memory_label, memory_size)
pub fn get_return_type_of(method_symbol: &Symbol) -> String
{
    match method_symbol.symbol_class
    {
        SymbolClass::Variable(_) => {
                panic!("Expected Function found Variable");
            },
        SymbolClass::Function(ref return_type, _, _, _) => return_type.clone(),
        SymbolClass::Structure(ref subtype) => {
                panic!("Expected Function found {}", subtype);
            }
    }
}
<commit_msg>Add printing support for method signatures<commit_after>use tokens::*;
use symbols::*;
use symbols::symbol_table::*;
use support::*;
use plp::PLPWriter;

/// @return: (method_label, return_label)
pub fn get_method_labels(method_symbol: &Symbol) -> (String, String)
{
    let method_label = match method_symbol.location {
        SymbolLocation::Memory(ref address) => address.label_name.clone(),
        _ => { panic!("compile_method_body: Expected Memory address for method"); },
    };

    let mut return_label = method_label.clone();
    return_label.push_str("_return");

    (method_label, return_label)
}

/// @return (memory_label, memory_size)
pub fn get_static_allocation(method_symbol: &Symbol) -> (String, u16)
{
    match method_symbol.symbol_class {
            SymbolClass::Variable(_) => {
                    panic!("Expected Function found Variable");
                },
            SymbolClass::Function(_, _, ref label_name, var_count) => (label_name.clone(), var_count as u16),
            SymbolClass::Structure(ref subtype) => {
                    panic!("Expected Function found {}", subtype);
                }
        }
}

/// @return (memory_label, memory_size)
pub fn get_return_type_of(method_symbol: &Symbol) -> String
{
    match method_symbol.symbol_class
    {
        SymbolClass::Variable(_) => {
                panic!("Expected Function found Variable");
            },
        SymbolClass::Function(ref return_type, _, _, _) => return_type.clone(),
        SymbolClass::Structure(ref subtype) => {
                panic!("Expected Function found {}", subtype);
            }
    }
}

/// @return ([arg1] [, arg2] {, arg3..})
pub fn get_arg_signature_of(method_symbol: &Symbol) -> String
{
    let types: &Vec<String> = match method_symbol.symbol_class
    {
        SymbolClass::Variable(_) => {
                panic!("Expected Function found Variable");
            },
        SymbolClass::Function(_, ref arg_types, _, _) => arg_types,
        SymbolClass::Structure(ref subtype) => {
                panic!("Expected Function found {}", subtype);
            }
    };

    let mut arg_signature = "(".to_string();
    // Handle first arg type
    if types.len() > 0
    {
        arg_signature.push_str(&*types[0]);
        for ref arg_type in types[1..].iter()
        {
            arg_signature.push_str(",");
            arg_signature.push_str(&*arg_type);
        }
    }
    arg_signature.push_str(")");

    arg_signature
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::fmt::{self, Display};
use temp;
use rustup_utils;
use rustup_utils::notify::{NotificationLevel};
use manifest::Component;
use dist::TargetTriple;
use errors::*;

#[derive(Debug)]
pub enum Notification<'a> {
    Utils(rustup_utils::Notification<'a>),
    Temp(temp::Notification<'a>),

    Extracting(&'a Path, &'a Path),
    ComponentAlreadyInstalled(&'a Component),
    CantReadUpdateHash(&'a Path),
    NoUpdateHash(&'a Path),
    ChecksumValid(&'a str),
    SignatureValid(&'a str),
    RollingBack,
    ExtensionNotInstalled(&'a Component),
    NonFatalError(&'a Error),
    MissingInstalledComponent(&'a str),
    DownloadingComponent(&'a str, &'a TargetTriple, Option<&'a TargetTriple>),
    InstallingComponent(&'a str, &'a TargetTriple, Option<&'a TargetTriple>),
    DownloadingManifest(&'a str),
    DownloadingLegacyManifest,
    ManifestChecksumFailedHack,
}

impl<'a> From<rustup_utils::Notification<'a>> for Notification<'a> {
    fn from(n: rustup_utils::Notification<'a>) -> Notification<'a> {
        Notification::Utils(n)
    }
}

impl<'a> From<temp::Notification<'a>> for Notification<'a> {
    fn from(n: temp::Notification<'a>) -> Notification<'a> {
        Notification::Temp(n)
    }
}

impl<'a> Notification<'a> {
    pub fn level(&self) -> NotificationLevel {
        use self::Notification::*;
        match *self {
            Temp(ref n) => n.level(),
            Utils(ref n) => n.level(),
            ChecksumValid(_) | NoUpdateHash(_) |
            DownloadingLegacyManifest  => NotificationLevel::Verbose,
            Extracting(_, _) | SignatureValid(_)  |
            DownloadingComponent(_, _, _) |
            InstallingComponent(_, _, _) |
            ComponentAlreadyInstalled(_)  |
            RollingBack | DownloadingManifest(_) => NotificationLevel::Info,
            CantReadUpdateHash(_) | ExtensionNotInstalled(_) |
            MissingInstalledComponent(_) |
            ManifestChecksumFailedHack => NotificationLevel::Warn,
            NonFatalError(_) => NotificationLevel::Error,
        }
    }
}

impl<'a> Display for Notification<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        use self::Notification::*;
        match *self {
            Temp(ref n) => n.fmt(f),
            Utils(ref n) => n.fmt(f),
            Extracting(_, _) => write!(f, "extracting..."),
            ComponentAlreadyInstalled(ref c) => {
                write!(f, "component {} is up to date", c.description())
            }
            CantReadUpdateHash(path) => {
                write!(f,
                       "can't read update hash file: '{}', can't skip update...",
                       path.display())
            }
            NoUpdateHash(path) => write!(f, "no update hash at: '{}'", path.display()),
            ChecksumValid(_) => write!(f, "checksum passed"),
            SignatureValid(_) => write!(f, "signature valid"),
            RollingBack => write!(f, "rolling back changes"),
            ExtensionNotInstalled(c) => {
                write!(f, "extension '{}' was not installed", c.name())
            }
            NonFatalError(e) => write!(f, "{}", e),
            MissingInstalledComponent(c) => write!(f, "during uninstall component {} was not found", c),
            DownloadingComponent(c, h, t) => {
                if Some(h) == t || t.is_none() {
                    write!(f, "downloading component '{}'", c)
                } else {
                    write!(f, "downloading component '{}' for '{}'", c, t.unwrap())
                }
            }
            InstallingComponent(c, h, t) => {
                if Some(h) == t || t.is_none() {
                    write!(f, "installing component '{}'", c)
                } else {
                    write!(f, "installing component '{}' for '{}'", c, t.unwrap())
                }
            }
            DownloadingManifest(t) => write!(f, "syncing channel updates for '{}'", t),
            DownloadingLegacyManifest => write!(f, "manifest not found. trying legacy manifest"),
            ManifestChecksumFailedHack => write!(f, "update not yet available, sorry! try again later"),
        }
    }
}

<commit_msg>Don't issue warnings about manifest checksum mismatches<commit_after>use std::path::Path;
use std::fmt::{self, Display};
use temp;
use rustup_utils;
use rustup_utils::notify::{NotificationLevel};
use manifest::Component;
use dist::TargetTriple;
use errors::*;

#[derive(Debug)]
pub enum Notification<'a> {
    Utils(rustup_utils::Notification<'a>),
    Temp(temp::Notification<'a>),

    Extracting(&'a Path, &'a Path),
    ComponentAlreadyInstalled(&'a Component),
    CantReadUpdateHash(&'a Path),
    NoUpdateHash(&'a Path),
    ChecksumValid(&'a str),
    SignatureValid(&'a str),
    RollingBack,
    ExtensionNotInstalled(&'a Component),
    NonFatalError(&'a Error),
    MissingInstalledComponent(&'a str),
    DownloadingComponent(&'a str, &'a TargetTriple, Option<&'a TargetTriple>),
    InstallingComponent(&'a str, &'a TargetTriple, Option<&'a TargetTriple>),
    DownloadingManifest(&'a str),
    DownloadingLegacyManifest,
    ManifestChecksumFailedHack,
}

impl<'a> From<rustup_utils::Notification<'a>> for Notification<'a> {
    fn from(n: rustup_utils::Notification<'a>) -> Notification<'a> {
        Notification::Utils(n)
    }
}

impl<'a> From<temp::Notification<'a>> for Notification<'a> {
    fn from(n: temp::Notification<'a>) -> Notification<'a> {
        Notification::Temp(n)
    }
}

impl<'a> Notification<'a> {
    pub fn level(&self) -> NotificationLevel {
        use self::Notification::*;
        match *self {
            Temp(ref n) => n.level(),
            Utils(ref n) => n.level(),
            ChecksumValid(_) | NoUpdateHash(_) |
            DownloadingLegacyManifest  => NotificationLevel::Verbose,
            Extracting(_, _) | SignatureValid(_)  |
            DownloadingComponent(_, _, _) |
            InstallingComponent(_, _, _) |
            ComponentAlreadyInstalled(_)  |
            ManifestChecksumFailedHack |
            RollingBack | DownloadingManifest(_) => NotificationLevel::Info,
            CantReadUpdateHash(_) | ExtensionNotInstalled(_) |
            MissingInstalledComponent(_) => NotificationLevel::Warn,
            NonFatalError(_) => NotificationLevel::Error,
        }
    }
}

impl<'a> Display for Notification<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        use self::Notification::*;
        match *self {
            Temp(ref n) => n.fmt(f),
            Utils(ref n) => n.fmt(f),
            Extracting(_, _) => write!(f, "extracting..."),
            ComponentAlreadyInstalled(ref c) => {
                write!(f, "component {} is up to date", c.description())
            }
            CantReadUpdateHash(path) => {
                write!(f,
                       "can't read update hash file: '{}', can't skip update...",
                       path.display())
            }
            NoUpdateHash(path) => write!(f, "no update hash at: '{}'", path.display()),
            ChecksumValid(_) => write!(f, "checksum passed"),
            SignatureValid(_) => write!(f, "signature valid"),
            RollingBack => write!(f, "rolling back changes"),
            ExtensionNotInstalled(c) => {
                write!(f, "extension '{}' was not installed", c.name())
            }
            NonFatalError(e) => write!(f, "{}", e),
            MissingInstalledComponent(c) => write!(f, "during uninstall component {} was not found", c),
            DownloadingComponent(c, h, t) => {
                if Some(h) == t || t.is_none() {
                    write!(f, "downloading component '{}'", c)
                } else {
                    write!(f, "downloading component '{}' for '{}'", c, t.unwrap())
                }
            }
            InstallingComponent(c, h, t) => {
                if Some(h) == t || t.is_none() {
                    write!(f, "installing component '{}'", c)
                } else {
                    write!(f, "installing component '{}' for '{}'", c, t.unwrap())
                }
            }
            DownloadingManifest(t) => write!(f, "syncing channel updates for '{}'", t),
            DownloadingLegacyManifest => write!(f, "manifest not found. trying legacy manifest"),
            ManifestChecksumFailedHack => write!(f, "update not yet available, sorry! try again later"),
        }
    }
}

<|endoftext|>


<commit_before>extern crate ruroonga_client;
extern crate json_flex;

use json_flex::Unwrap;

use ruroonga_client as groonga;

const GROONGA_SERVER: &'static str = "localhost:10041";

fn create_table() {
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("table_create");
    command.set_argument(vec![("name", "Sites"),
                              ("flags","TABLE_HASH_KEY"),("key_type","ShortText")]);
    let url = format!("http://{}{}", GROONGA_SERVER, command.encode());
    println!("load url: {}", url);
    let res = request.get(url);
    let result = request.receive(&mut res.unwrap()).unwrap();
    println!("result: {}", result);
}

fn create_column() {
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("column_create");
    command.set_argument(vec![("table", "Sites"),
                              ("name","title"),("type","ShortText")]);
    let url = format!("http://{}{}", GROONGA_SERVER, command.encode());
    println!("load url: {}", url);
    let res = request.get(url);
    let result = request.receive(&mut res.unwrap()).unwrap();
    println!("result: {}", result);
}

fn load() {
    let data = r#"
[
{"_key":"http://example.org/","title":"This is test record 1!"},
{"_key":"http://example.net/","title":"test record 2."},
{"_key":"http://example.com/","title":"test test record three."},
{"_key":"http://example.net/afr","title":"test record four."},
{"_key":"http://example.org/aba","title":"test test test record five."},
{"_key":"http://example.com/rab","title":"test test test test record six."},
{"_key":"http://example.net/atv","title":"test test test record seven."},
{"_key":"http://example.org/gat","title":"test test record eight."},
{"_key":"http://example.com/vdw","title":"test test record nine."},
]"#;
    let mut request = groonga::HTTPRequest::new();
    let mut load_command = groonga::CommandQuery::new("load");
    load_command.set_argument(vec![("table", "Sites")]);
    let load_url = format!("http://{}{}", GROONGA_SERVER, load_command.encode());
    println!("load url: {}", load_url);
    println!("load data: {}", data);
    let load_res = request.load(load_url, data.to_string());
    let load_result = request.receive(&mut load_res.unwrap()).unwrap();
    println!("result: {}", load_result);
}

#[derive(Clone, Debug)]
struct Result {
    id: i64,
    key: String,
    title: String
}

fn main() {
    create_table();
    create_column();
    load();
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("select");
    command.set_argument(vec![("table", "Sites")]);
    let url = format!("http://{}{}", GROONGA_SERVER, command.encode());
    println!("url: {}", url);
    let res = request.get(url);
    let result = request.receive(&mut res.unwrap()).unwrap();
    println!("result: {}", result);
    let mut decode = groonga::ResultParser::new(result);
    println!("status: {:?}", decode.status().unwrap());
    println!("start: {:?}", decode.start_time().unwrap());
    println!("elapsed: {:?}", decode.elapsed_time().unwrap());
    if decode.status().unwrap().clone() == 0 {
        println!("matched columns: {:?}", decode.matched_columns().unwrap());
        let decoded = groonga::Rows::new(decode.result());
        let decoded_vec = decoded.clone().columns().unwrap();
        println!("index access: {:?}", decoded_vec[2]);
        // Read got response
        let mut result_vec: Vec<Result> = Vec::new();
        println!("-- Display raw decoded json values --");
        // Skip reading result header
        for v in decoded_vec.iter().skip(2) {
            println!("{:?}", v);
            let raw = v.unwrap_vec();
            let elem = Result { id: raw[0].unwrap_i64().clone(),
                                key: raw[1].unwrap_string().clone(),
                                title: raw[2].unwrap_string().clone() };
            result_vec.push(elem.clone());
        }
        println!("-- Mapped to user-defined struct -- ");
        println!("{:?}", result_vec);
    } else {
        println!("Couldn't get success response.")
    }
}
<commit_msg>Use #into_row() in ResultParser type<commit_after>extern crate ruroonga_client;
extern crate json_flex;

use json_flex::Unwrap;

use ruroonga_client as groonga;

const GROONGA_SERVER: &'static str = "localhost:10041";

fn create_table() {
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("table_create");
    command.set_argument(vec![("name", "Sites"),
                              ("flags","TABLE_HASH_KEY"),("key_type","ShortText")]);
    let url = format!("http://{}{}", GROONGA_SERVER, command.encode());
    println!("load url: {}", url);
    let res = request.get(url);
    let result = request.receive(&mut res.unwrap()).unwrap();
    println!("result: {}", result);
}

fn create_column() {
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("column_create");
    command.set_argument(vec![("table", "Sites"),
                              ("name","title"),("type","ShortText")]);
    let url = format!("http://{}{}", GROONGA_SERVER, command.encode());
    println!("load url: {}", url);
    let res = request.get(url);
    let result = request.receive(&mut res.unwrap()).unwrap();
    println!("result: {}", result);
}

fn load() {
    let data = r#"
[
{"_key":"http://example.org/","title":"This is test record 1!"},
{"_key":"http://example.net/","title":"test record 2."},
{"_key":"http://example.com/","title":"test test record three."},
{"_key":"http://example.net/afr","title":"test record four."},
{"_key":"http://example.org/aba","title":"test test test record five."},
{"_key":"http://example.com/rab","title":"test test test test record six."},
{"_key":"http://example.net/atv","title":"test test test record seven."},
{"_key":"http://example.org/gat","title":"test test record eight."},
{"_key":"http://example.com/vdw","title":"test test record nine."},
]"#;
    let mut request = groonga::HTTPRequest::new();
    let mut load_command = groonga::CommandQuery::new("load");
    load_command.set_argument(vec![("table", "Sites")]);
    let load_url = format!("http://{}{}", GROONGA_SERVER, load_command.encode());
    println!("load url: {}", load_url);
    println!("load data: {}", data);
    let load_res = request.load(load_url, data.to_string());
    let load_result = request.receive(&mut load_res.unwrap()).unwrap();
    println!("result: {}", load_result);
}

#[derive(Clone, Debug)]
struct Result {
    id: i64,
    key: String,
    title: String
}

fn main() {
    create_table();
    create_column();
    load();
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("select");
    command.set_argument(vec![("table", "Sites")]);
    let url = format!("http://{}{}", GROONGA_SERVER, command.encode());
    println!("url: {}", url);
    let res = request.get(url);
    let result = request.receive(&mut res.unwrap()).unwrap();
    println!("result: {}", result);
    let mut decode = groonga::ResultParser::new(result);
    println!("status: {:?}", decode.status().unwrap());
    println!("start: {:?}", decode.start_time().unwrap());
    println!("elapsed: {:?}", decode.elapsed_time().unwrap());
    if decode.status().unwrap().clone() == 0 {
        println!("matched columns: {:?}", decode.matched_columns().unwrap());
        let decoded_vec = decode.into_row().columns().unwrap();
        println!("index access: {:?}", decoded_vec[2]);
        // Read got response
        let mut result_vec: Vec<Result> = Vec::new();
        println!("-- Display raw decoded json values --");
        // Skip reading result header
        for v in decoded_vec.iter().skip(2) {
            println!("{:?}", v);
            let raw = v.unwrap_vec();
            let elem = Result { id: raw[0].unwrap_i64().clone(),
                                key: raw[1].unwrap_string().clone(),
                                title: raw[2].unwrap_string().clone() };
            result_vec.push(elem.clone());
        }
        println!("-- Mapped to user-defined struct -- ");
        println!("{:?}", result_vec);
    } else {
        println!("Couldn't get success response.")
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#![feature(proc_macro)]

extern crate gtk;
#[macro_use]
extern crate mg;
extern crate mg_settings;
#[macro_use]
extern crate mg_settings_macros;

use std::rc::Rc;

use gtk::{ContainerExt, Entry, Label, WidgetExt};
use gtk::Orientation::Vertical;
use mg::ApplicationBuilder;

use AppCommand::*;
use AppSettingsVariant::*;
use SpecialCommand::*;

#[derive(Debug, Setting)]
pub enum CustomSetting {
    #[default]
    Choice,
    OtherChoice,
}

#[derive(Commands)]
enum AppCommand {
    #[completion(hidden)]
    Follow,
    Insert,
    Normal,
    #[help(text="Open the url")]
    Open(String),
    #[help(text="Quit the application")]
    Quit,
    #[help(text="Open the url in a new window")]
    WinOpen(String),
}

#[derive(Settings)]
pub struct AppSettings {
    boolean: bool,
    custom: CustomSetting,
    #[help(text="The window title")]
    title: String,
    title_len: i64,
    width: i64,
}

special_commands!(SpecialCommand {
    BackwardSearch('?', always),
    Search('/', always),
});

fn main() {
    gtk::init().unwrap();

    let app = ApplicationBuilder::new()
        .modes(hash! {
            "i" => "insert",
        })
        .settings(AppSettings::new())
        .build();
    app.use_dark_theme();
    let item = app.add_statusbar_item();
    item.set_text("Item");
    let item2 = app.add_statusbar_item();
    item2.set_text("Test");
    item.set_text("Rightmost");
    if let Err(error) = app.parse_config("examples/main.conf") {
        app.error(&error.to_string());
    }
    app.add_variable("url", || "http://duckduckgo.com/lite".to_string());
    app.set_window_title("First Mg Program");

    let vbox = gtk::Box::new(Vertical, 0);
    let label = Label::new(Some("Mg App"));
    vbox.add(&label);
    let label = Rc::new(label);
    let entry = Entry::new();
    vbox.add(&entry);
    app.set_view(&vbox);

    {
        let mg_app = app.clone();
        let label = label.clone();
        app.connect_setting_changed(move |setting| {
            match setting {
                Custom(setting) => label.set_text(&format!("custom setting is: {:?}", setting)),
                Title(title) => mg_app.set_window_title(&title),
                TitleLen(len) => mg_app.set_window_title(&format!("New title len: {}", len)),
                Boolean(_) | Width(_) => (),
            }
        });
    }

    {
        let mg_app = app.clone();
        let label = label.clone();
        app.connect_mode_changed(move |mode| {
            if mode != "normal" {
                let title = &mg_app.settings().title;
                label.set_text(&format!("Title was: {}", title));
                mg_app.set_setting(Title(mode.to_string()));
            }
        });
    }

    {
        let mg_app = app.clone();
        let label = label.clone();
        app.connect_command(move |command| {
            match command {
                Follow => (),
                Insert => mg_app.set_mode("insert"),
                Normal => mg_app.set_mode("normal"),
                Open(url) => label.set_text(&format!("Opening URL {}", url)),
                WinOpen(url) => label.set_text(&format!("Opening URL {} in new window", url)),
                Quit => gtk::main_quit(),
            }
        });
    }

    {
        app.connect_special_command(move |command| {
            match command {
                BackwardSearch(input) => println!("Searching backward for {}", input),
                Search(input) => println!("Searching for {}", input),
            }
        });
    }

    entry.grab_focus();

    gtk::main();
}
<commit_msg>Updated example to test corner case.<commit_after>/*
 * Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#![feature(proc_macro)]

extern crate gtk;
#[macro_use]
extern crate mg;
extern crate mg_settings;
#[macro_use]
extern crate mg_settings_macros;

use std::rc::Rc;

use gtk::{ContainerExt, Entry, Label, WidgetExt};
use gtk::Orientation::Vertical;
use mg::ApplicationBuilder;

use AppCommand::*;
use AppSettingsVariant::*;
use SpecialCommand::*;

#[derive(Debug, Setting)]
pub enum CustomSetting {
    #[default]
    Choice,
    OtherChoice,
}

#[derive(Commands)]
enum AppCommand {
    #[completion(hidden)]
    Follow,
    Insert,
    Normal,
    #[help(text="Open the url")]
    Open(String),
    #[help(text="Quit the application")]
    Quit,
    #[help(text="Open the url in a new window")]
    WinOpen(String),
}

#[derive(Settings)]
pub struct AppSettings {
    boolean: bool,
    custom_set: CustomSetting,
    #[help(text="The window title")]
    title: String,
    title_len: i64,
    width: i64,
}

special_commands!(SpecialCommand {
    BackwardSearch('?', always),
    Search('/', always),
});

fn main() {
    gtk::init().unwrap();

    let app = ApplicationBuilder::new()
        .modes(hash! {
            "i" => "insert",
        })
        .settings(AppSettings::new())
        .build();
    app.use_dark_theme();
    let item = app.add_statusbar_item();
    item.set_text("Item");
    let item2 = app.add_statusbar_item();
    item2.set_text("Test");
    item.set_text("Rightmost");
    if let Err(error) = app.parse_config("examples/main.conf") {
        app.error(&error.to_string());
    }
    app.add_variable("url", || "http://duckduckgo.com/lite".to_string());
    app.set_window_title("First Mg Program");

    let vbox = gtk::Box::new(Vertical, 0);
    let label = Label::new(Some("Mg App"));
    vbox.add(&label);
    let label = Rc::new(label);
    let entry = Entry::new();
    vbox.add(&entry);
    app.set_view(&vbox);

    {
        let mg_app = app.clone();
        let label = label.clone();
        app.connect_setting_changed(move |setting| {
            match setting {
                CustomSet(setting) => label.set_text(&format!("custom setting is: {:?}", setting)),
                Title(title) => mg_app.set_window_title(&title),
                TitleLen(len) => mg_app.set_window_title(&format!("New title len: {}", len)),
                Boolean(_) | Width(_) => (),
            }
        });
    }

    {
        let mg_app = app.clone();
        let label = label.clone();
        app.connect_mode_changed(move |mode| {
            if mode != "normal" {
                let title = &mg_app.settings().title;
                label.set_text(&format!("Title was: {}", title));
                mg_app.set_setting(Title(mode.to_string()));
            }
        });
    }

    {
        let mg_app = app.clone();
        let label = label.clone();
        app.connect_command(move |command| {
            match command {
                Follow => (),
                Insert => mg_app.set_mode("insert"),
                Normal => mg_app.set_mode("normal"),
                Open(url) => label.set_text(&format!("Opening URL {}", url)),
                WinOpen(url) => label.set_text(&format!("Opening URL {} in new window", url)),
                Quit => gtk::main_quit(),
            }
        });
    }

    {
        app.connect_special_command(move |command| {
            match command {
                BackwardSearch(input) => println!("Searching backward for {}", input),
                Search(input) => println!("Searching for {}", input),
            }
        });
    }

    entry.grab_focus();

    gtk::main();
}
<|endoftext|>


<commit_before>use std::fmt::{Write, Error as FmtError};

/// Simple pretty printer hand tailored for the output generated by the `quote`
/// crate for schema inference.
///
/// # Rules
///
/// 1. Seeing `{` increases indentation level
/// 2. Seeing `}` decreases indentation level
/// 3. Insert newline after `{`, `}`, `,`, and `;`
/// 4. Don't put spaces:
///   - between ident and `!`,
///   - between path segments and `::`
///   - after `(`, '<' and before `)`, `>`
///   - before `,`
pub fn format_schema(schema: &str) -> Result<String, FmtError> {
    let mut out = String::with_capacity(schema.len());
    let mut indent = String::new();
    let mut skip_space = false;
    let mut last_char = ' ';

    for c in schema.chars() {
        // The `quote!` macro inserts whitespaces at some strange location,
        // let's remove them!
        match c {
            '!' | '(' | ';' | ',' | '<' | ')' | '>' if last_char.is_whitespace() => {
                out.pop();
            },
            ':' if last_char.is_whitespace() => {
                // Unless we are at the beginning of a fully qualified path,
                // remove the whitespace.
                let char_before_whitespace = {
                    let mut chars = out.chars();
                    chars.next_back();
                    chars.next_back()
                };

                if char_before_whitespace != Some('>') {
                    out.pop();
                }
            },
            _=> { }
        }

        if skip_space && c.is_whitespace() && last_char != '>' {
            continue;
        }

        last_char = c;
        skip_space = false;

        // At this point, there is an empty line before `}`. We need to remove
        // the already inserted indent, because the new indent is smaller than
        // the old one.
        if c == '}' {
            while let Some(c) = out.pop() {
                if c == '\n' {
                    break;
                }
            }

            indent.pop();
            write!(out, "\n{}", indent)?;
        }

        write!(out, "{}", c)?;

        // We need to insert newlines in some places and adjust the indent.
        // Also, we need to remember if we could skip the next whitespace.
        match c {
            ';' | ',' | '}' => {
                skip_space = true;
                write!(out, "\n{}", indent)?;
            },
            '{' => {
                skip_space = true;
                indent += "\t";
                write!(out, "\n{}", indent)?;
            },
            ':' | '(' | '<' => skip_space = true,
            _=>{}
        }
    }

    Ok(out.replace("\t", "    "))
}

#[cfg(test)]
mod tests {
    use super::format_schema;

    fn run_test(input: &str, expected: &str){
        let actual = format_schema(input).unwrap();
        assert_eq!(expected, actual);
    }

    #[test]
    fn test_remove_whitespace_colon() {
        run_test(":: diesel :: types :: Text", "::diesel::types::Text");
    }

    #[test]
    fn test_format_nullable() {
        run_test("Nullable < :: diesel :: types :: Text >",
            "Nullable<::diesel::types::Text>");
    }

        #[test]
    fn test_format_nullable_multispace() {
        run_test("Nullable <  Integer >",
            "Nullable<Integer>");
    }

    #[test]
    fn test_newline_after_comma() {
        run_test(",", ",\n");
    }

    #[test]
    fn test_increase_indent() {
        run_test("{","{\n    ");
    }

    #[test]
    fn test_decrease_indent() {
        run_test("{abc,}","{\n    abc,\n}\n");
    }

    #[test]
    fn test_format_arrow() {
        run_test("created_at -> :: diesel :: types :: Timestamp",
            "created_at -> ::diesel::types::Timestamp");
    }

    #[test]
    fn test_format_full_line() {
        run_test("created_at -> :: diesel :: types :: Timestamp ,",
            "created_at -> ::diesel::types::Timestamp,\n");
    }

    #[test]
    fn test_format_include_line() {
        run_test("pub use self :: infer_locks :: * ;",
            "pub use self::infer_locks::*;\n");
    }

    #[test]
    fn test_format_generated_mod() {
        run_test("mod infer_users { table ! { users ( id ) { id -> :: diesel :: types :: Int4 , username -> :: diesel :: types :: Varchar , password -> :: diesel :: types :: Varchar , } } } pub use self :: infer_users :: * ;",
r"mod infer_users {
    table! {
        users(id) {
            id -> ::diesel::types::Int4,
            username -> ::diesel::types::Varchar,
            password -> ::diesel::types::Varchar,
        }
    }
}
pub use self::infer_users::*;
");
    }
}
<commit_msg>Rewrite pretty print tests to use macro<commit_after>use std::fmt::{Write, Error as FmtError};

/// Simple pretty printer hand tailored for the output generated by the `quote`
/// crate for schema inference.
///
/// # Rules
///
/// 1. Seeing `{` increases indentation level
/// 2. Seeing `}` decreases indentation level
/// 3. Insert newline after `{`, `}`, `,`, and `;`
/// 4. Don't put spaces:
///   - between ident and `!`,
///   - between path segments and `::`
///   - after `(`, '<' and before `)`, `>`
///   - before `,`
pub fn format_schema(schema: &str) -> Result<String, FmtError> {
    let mut out = String::with_capacity(schema.len());
    let mut indent = String::new();
    let mut skip_space = false;
    let mut last_char = ' ';

    for c in schema.chars() {
        // The `quote!` macro inserts whitespaces at some strange location,
        // let's remove them!
        match c {
            '!' | '(' | ';' | ',' | '<' | ')' | '>' if last_char.is_whitespace() => {
                out.pop();
            },
            ':' if last_char.is_whitespace() => {
                // Unless we are at the beginning of a fully qualified path,
                // remove the whitespace.
                let char_before_whitespace = {
                    let mut chars = out.chars();
                    chars.next_back();
                    chars.next_back()
                };

                if char_before_whitespace != Some('>') {
                    out.pop();
                }
            },
            _=> { }
        }

        if skip_space && c.is_whitespace() && last_char != '>' {
            continue;
        }

        last_char = c;
        skip_space = false;

        // At this point, there is an empty line before `}`. We need to remove
        // the already inserted indent, because the new indent is smaller than
        // the old one.
        if c == '}' {
            while let Some(c) = out.pop() {
                if c == '\n' {
                    break;
                }
            }

            indent.pop();
            write!(out, "\n{}", indent)?;
        }

        write!(out, "{}", c)?;

        // We need to insert newlines in some places and adjust the indent.
        // Also, we need to remember if we could skip the next whitespace.
        match c {
            ';' | ',' | '}' => {
                skip_space = true;
                write!(out, "\n{}", indent)?;
            },
            '{' => {
                skip_space = true;
                indent += "\t";
                write!(out, "\n{}", indent)?;
            },
            ':' | '(' | '<' => skip_space = true,
            _=>{}
        }
    }

    Ok(out.replace("\t", "    "))
}

#[cfg(test)]
mod tests {
    use super::format_schema;

    macro_rules! test_pretty_printing {
        ($($name: ident: $input: expr => $expected: expr);*) => {
            $(
                #[test]
                fn $name() {
                    let actual = format_schema($input).unwrap();
                    assert_eq!($expected, actual);
                }
            )*
        }
    }
    test_pretty_printing! {
        test_remove_whitespace_colon: ":: diesel :: types :: Text" =>
            "::diesel::types::Text";
        test_format_nullable: "Nullable < :: diesel :: types :: Text >" =>
            "Nullable<::diesel::types::Text>";
        test_format_nullable_multispace: "Nullable <  Integer >" => "Nullable<Integer>";
        test_newline_after_comma: "," => ",\n";
        test_increase_indent: "{" => "{\n    ";
        test_decrease_indent: "{abc,}" => "{\n    abc,\n}\n";
        test_format_arrow: "created_at -> :: diesel :: types :: Timestamp" =>
            "created_at -> ::diesel::types::Timestamp";
        test_format_full_line: "created_at -> :: diesel :: types :: Timestamp ," =>
            "created_at -> ::diesel::types::Timestamp,\n";
        test_format_include_line: "pub use self :: infer_locks :: * ;" =>
            "pub use self::infer_locks::*;\n";
        test_format_generated_mod: "mod infer_users { table ! { users ( id ) { id -> :: diesel :: types :: Int4 , username -> :: diesel :: types :: Varchar , password -> :: diesel :: types :: Varchar , } } } pub use self :: infer_users :: * ;" =>
r"mod infer_users {
    table! {
        users(id) {
            id -> ::diesel::types::Int4,
            username -> ::diesel::types::Varchar,
            password -> ::diesel::types::Varchar,
        }
    }
}
pub use self::infer_users::*;
"
    }
}
<|endoftext|>


<commit_before>use super::*;
use expect_test::expect;

#[test]
fn inner_item_smoke() {
    check_at(
        r#"
struct inner {}
fn outer() {
    $0
    fn inner() {}
}
"#,
        expect![[r#"
            block scope
            inner: v

            crate
            inner: t
            outer: v
        "#]],
    );
}

#[test]
fn use_from_crate() {
    check_at(
        r#"
struct Struct {}
fn outer() {
    fn Struct() {}
    use Struct as PlainStruct;
    use crate::Struct as CrateStruct;
    use self::Struct as SelfStruct;
    use super::Struct as SuperStruct;
    $0
}
"#,
        expect![[r#"
            block scope
            CrateStruct: t
            PlainStruct: t v
            SelfStruct: t
            Struct: v
            SuperStruct: _

            crate
            Struct: t
            outer: v
        "#]],
    );
}

#[test]
fn merge_namespaces() {
    check_at(
        r#"
struct name {}
fn outer() {
    fn name() {}

    use name as imported; // should import both `name`s

    $0
}
"#,
        expect![[r#"
            block scope
            imported: t v
            name: v

            crate
            name: t
            outer: v
        "#]],
    );
}

#[test]
fn nested_blocks() {
    check_at(
        r#"
fn outer() {
    struct inner1 {}
    fn inner() {
        use inner1;
        use outer;
        fn inner2() {}
        $0
    }
}
"#,
        expect![[r#"
            block scope
            inner1: t
            inner2: v
            outer: v

            block scope
            inner: v
            inner1: t

            crate
            outer: v
        "#]],
    );
}

#[test]
fn super_imports() {
    check_at(
        r#"
mod module {
    fn f() {
        use super::Struct;
        $0
    }
}

struct Struct {}
"#,
        expect![[r#"
            block scope
            Struct: t

            crate
            Struct: t
            module: t

            crate::module
            f: v
        "#]],
    );
}

#[test]
fn legacy_macro_items() {
    // Checks that legacy-scoped `macro_rules!` from parent namespaces are resolved and expanded
    // correctly.
    check_at(
        r#"
macro_rules! hit {
    () => {
        struct Hit {}
    }
}

fn f() {
    hit!();
    $0
}
"#,
        expect![[r#"
            block scope
            Hit: t

            crate
            f: v
        "#]],
    );
}

#[test]
fn macro_resolve() {
    check_at(
        r#"
//- /lib.rs crate:lib deps:core
use core::mark;

fn f() {
    fn nested() {
        mark::hit!(Hit);
        $0
    }
}
//- /core.rs crate:core
pub mod mark {
    #[macro_export]
    macro_rules! _hit {
        ($name:ident) => {
            struct $name {}
        }
    }

    pub use crate::_hit as hit;
}
"#,
        expect![[r#"
            block scope
            Hit: t

            block scope
            nested: v

            crate
            f: v
            mark: t
        "#]],
    );
}

#[test]
fn macro_resolve_legacy() {
    check_at(
        r#"
//- /lib.rs
mod module;

//- /module.rs
macro_rules! m {
    () => {
        struct Def {}
    };
}

fn f() {
    {
        m!();
        $0
    }
}
        "#,
        expect![[r#"
            block scope
            Def: t

            crate
            module: t

            crate::module
            f: v
        "#]],
    )
}
<commit_msg>Add another block def map test<commit_after>use super::*;
use expect_test::expect;

#[test]
fn inner_item_smoke() {
    check_at(
        r#"
struct inner {}
fn outer() {
    $0
    fn inner() {}
}
"#,
        expect![[r#"
            block scope
            inner: v

            crate
            inner: t
            outer: v
        "#]],
    );
}

#[test]
fn use_from_crate() {
    check_at(
        r#"
struct Struct {}
fn outer() {
    fn Struct() {}
    use Struct as PlainStruct;
    use crate::Struct as CrateStruct;
    use self::Struct as SelfStruct;
    use super::Struct as SuperStruct;
    $0
}
"#,
        expect![[r#"
            block scope
            CrateStruct: t
            PlainStruct: t v
            SelfStruct: t
            Struct: v
            SuperStruct: _

            crate
            Struct: t
            outer: v
        "#]],
    );
}

#[test]
fn merge_namespaces() {
    check_at(
        r#"
struct name {}
fn outer() {
    fn name() {}

    use name as imported; // should import both `name`s

    $0
}
"#,
        expect![[r#"
            block scope
            imported: t v
            name: v

            crate
            name: t
            outer: v
        "#]],
    );
}

#[test]
fn nested_blocks() {
    check_at(
        r#"
fn outer() {
    struct inner1 {}
    fn inner() {
        use inner1;
        use outer;
        fn inner2() {}
        $0
    }
}
"#,
        expect![[r#"
            block scope
            inner1: t
            inner2: v
            outer: v

            block scope
            inner: v
            inner1: t

            crate
            outer: v
        "#]],
    );
}

#[test]
fn super_imports() {
    check_at(
        r#"
mod module {
    fn f() {
        use super::Struct;
        $0
    }
}

struct Struct {}
"#,
        expect![[r#"
            block scope
            Struct: t

            crate
            Struct: t
            module: t

            crate::module
            f: v
        "#]],
    );
}

#[test]
fn legacy_macro_items() {
    // Checks that legacy-scoped `macro_rules!` from parent namespaces are resolved and expanded
    // correctly.
    check_at(
        r#"
macro_rules! hit {
    () => {
        struct Hit {}
    }
}

fn f() {
    hit!();
    $0
}
"#,
        expect![[r#"
            block scope
            Hit: t

            crate
            f: v
        "#]],
    );
}

#[test]
fn macro_resolve() {
    check_at(
        r#"
//- /lib.rs crate:lib deps:core
use core::mark;

fn f() {
    fn nested() {
        mark::hit!(Hit);
        $0
    }
}
//- /core.rs crate:core
pub mod mark {
    #[macro_export]
    macro_rules! _hit {
        ($name:ident) => {
            struct $name {}
        }
    }

    pub use crate::_hit as hit;
}
"#,
        expect![[r#"
            block scope
            Hit: t

            block scope
            nested: v

            crate
            f: v
            mark: t
        "#]],
    );
}

#[test]
fn macro_resolve_legacy() {
    check_at(
        r#"
//- /lib.rs
mod module;

//- /module.rs
macro_rules! m {
    () => {
        struct Def {}
    };
}

fn f() {
    {
        m!();
        $0
    }
}
        "#,
        expect![[r#"
            block scope
            Def: t

            crate
            module: t

            crate::module
            f: v
        "#]],
    )
}

#[test]
fn super_does_not_resolve_to_block_module() {
    check_at(
        r#"
fn main() {
    struct Struct {}
    mod module {
        use super::Struct;

        $0
    }
}
    "#,
        expect![[r#"
        block scope
        Struct: t
        module: t

        block scope::module
        Struct: _

        crate
        main: v
    "#]],
    );
}
<|endoftext|>