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

//! Wrapper around Gecko's CSS error reporting mechanism.

#![allow(unsafe_code)]

use cssparser::{CowRcStr, serialize_identifier, ToCss};
use cssparser::{SourceLocation, ParseError, ParseErrorKind, Token, BasicParseErrorKind};
use selectors::parser::SelectorParseErrorKind;
use std::ptr;
use style::error_reporting::{ParseErrorReporter, ContextualParseError};
use style::gecko_bindings::bindings::{Gecko_CreateCSSErrorReporter, Gecko_DestroyCSSErrorReporter};
use style::gecko_bindings::bindings::Gecko_ReportUnexpectedCSSError;
use style::gecko_bindings::structs::{Loader, ServoStyleSheet, nsIURI};
use style::gecko_bindings::structs::ErrorReporter as GeckoErrorReporter;
use style::gecko_bindings::structs::URLExtraData as RawUrlExtraData;
use style::gecko_bindings::sugar::refptr::RefPtr;
use style::stylesheets::UrlExtraData;
use style_traits::StyleParseErrorKind;

pub type ErrorKind<'i> = ParseErrorKind<'i, StyleParseErrorKind<'i>>;

/// Wrapper around an instance of Gecko's CSS error reporter.
pub struct ErrorReporter(*mut GeckoErrorReporter);

impl ErrorReporter {
    /// Create a new instance of the Gecko error reporter.
    pub fn new(sheet: *mut ServoStyleSheet,
               loader: *mut Loader,
               url: *mut RawUrlExtraData) -> ErrorReporter {
        unsafe {
            let url = RefPtr::from_ptr_ref(&url);
            ErrorReporter(Gecko_CreateCSSErrorReporter(sheet, loader, url.mBaseURI.raw::<nsIURI>()))
        }
    }
}

impl Drop for ErrorReporter {
    fn drop(&mut self) {
        unsafe {
            Gecko_DestroyCSSErrorReporter(self.0);
        }
    }
}

enum ErrorString<'a> {
    Snippet(CowRcStr<'a>),
    Ident(CowRcStr<'a>),
    UnexpectedToken(Token<'a>),
}

impl<'a> ErrorString<'a> {
    fn into_str(self) -> CowRcStr<'a> {
        match self {
            ErrorString::Snippet(s) => s,
            ErrorString::UnexpectedToken(t) => t.to_css_string().into(),
            ErrorString::Ident(i) => {
                let mut s = String::new();
                serialize_identifier(&i, &mut s).unwrap();
                s.into()
            }
        }
    }
}

enum Action {
    Nothing,
    Skip,
    Drop,
}

trait ErrorHelpers<'a> {
    fn error_data(self) -> (CowRcStr<'a>, ErrorKind<'a>);
    fn error_params(self) -> ErrorParams<'a>;
    fn to_gecko_message(&self) -> (Option<&'static [u8]>, &'static [u8], Action);
}

fn extract_error_param<'a>(err: ErrorKind<'a>) -> Option<ErrorString<'a>> {
    Some(match err {
        ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(t)) => {
            ErrorString::UnexpectedToken(t)
        }

        ParseErrorKind::Basic(BasicParseErrorKind::AtRuleInvalid(i)) |
        ParseErrorKind::Custom(StyleParseErrorKind::UnsupportedAtRule(i)) => {
            let mut s = String::from("@");
            serialize_identifier(&i, &mut s).unwrap();
            ErrorString::Snippet(s.into())
        }

        ParseErrorKind::Custom(StyleParseErrorKind::OtherInvalidValue(property)) => {
            ErrorString::Snippet(property)
        }

        ParseErrorKind::Custom(
            StyleParseErrorKind::SelectorError(
                SelectorParseErrorKind::UnexpectedIdent(ident)
            )
        ) => {
            ErrorString::Ident(ident)
        }

        ParseErrorKind::Custom(StyleParseErrorKind::UnknownProperty(property)) => {
            ErrorString::Ident(property)
        }

        ParseErrorKind::Custom(
            StyleParseErrorKind::UnexpectedTokenWithinNamespace(token)
        ) => {
            ErrorString::UnexpectedToken(token)
        }

        _ => return None,
    })
}

struct ErrorParams<'a> {
    prefix_param: Option<ErrorString<'a>>,
    main_param: Option<ErrorString<'a>>,
}

/// If an error parameter is present in the given error, return it. Additionally return
/// a second parameter if it exists, for use in the prefix for the eventual error message.
fn extract_error_params<'a>(err: ErrorKind<'a>) -> Option<ErrorParams<'a>> {
    let (main, prefix) = match err {
        ParseErrorKind::Custom(StyleParseErrorKind::InvalidColor(property, token)) |
        ParseErrorKind::Custom(StyleParseErrorKind::InvalidFilter(property, token)) => {
            (Some(ErrorString::Snippet(property.into())), Some(ErrorString::UnexpectedToken(token)))
        }

        ParseErrorKind::Custom(
            StyleParseErrorKind::MediaQueryExpectedFeatureName(ident)
        ) => {
            (Some(ErrorString::Ident(ident)), None)
        }

        ParseErrorKind::Custom(
            StyleParseErrorKind::ExpectedIdentifier(token)
        ) => {
            (Some(ErrorString::UnexpectedToken(token)), None)
        }

        ParseErrorKind::Custom(StyleParseErrorKind::SelectorError(err)) => match err {
            SelectorParseErrorKind::UnexpectedTokenInAttributeSelector(t) |
            SelectorParseErrorKind::BadValueInAttr(t) |
            SelectorParseErrorKind::ExpectedBarInAttr(t) |
            SelectorParseErrorKind::NoQualifiedNameInAttributeSelector(t) |
            SelectorParseErrorKind::InvalidQualNameInAttr(t) |
            SelectorParseErrorKind::ExplicitNamespaceUnexpectedToken(t) |
            SelectorParseErrorKind::PseudoElementExpectedIdent(t) |
            SelectorParseErrorKind::NoIdentForPseudo(t) |
            SelectorParseErrorKind::ClassNeedsIdent(t) |
            SelectorParseErrorKind::PseudoElementExpectedColon(t) => {
                (None, Some(ErrorString::UnexpectedToken(t)))
            }
            SelectorParseErrorKind::ExpectedNamespace(namespace) => {
                (None, Some(ErrorString::Ident(namespace)))
            }
            SelectorParseErrorKind::UnsupportedPseudoClassOrElement(p) => {
                (None, Some(ErrorString::Ident(p)))
            }
            SelectorParseErrorKind::EmptySelector |
            SelectorParseErrorKind::DanglingCombinator => {
                (None, None)
            }
            SelectorParseErrorKind::EmptyNegation => {
                (None, Some(ErrorString::Snippet(")".into())))
            }
            err => match extract_error_param(ParseErrorKind::Custom(StyleParseErrorKind::SelectorError(err))) {
                Some(e) => (Some(e), None),
                None => return None,
            }
        },
        err => match extract_error_param(err) {
            Some(e) => (Some(e), None),
            None => return None,
        }
    };
    Some(ErrorParams {
        main_param: main,
        prefix_param: prefix,
    })
}

impl<'a> ErrorHelpers<'a> for ContextualParseError<'a> {
    fn error_data(self) -> (CowRcStr<'a>, ErrorKind<'a>) {
        match self {
            ContextualParseError::UnsupportedPropertyDeclaration(s, err) |
            ContextualParseError::UnsupportedFontFaceDescriptor(s, err) |
            ContextualParseError::UnsupportedFontFeatureValuesDescriptor(s, err) |
            ContextualParseError::InvalidKeyframeRule(s, err) |
            ContextualParseError::InvalidFontFeatureValuesRule(s, err) |
            ContextualParseError::UnsupportedKeyframePropertyDeclaration(s, err) |
            ContextualParseError::InvalidRule(s, err) |
            ContextualParseError::UnsupportedRule(s, err) |
            ContextualParseError::UnsupportedViewportDescriptorDeclaration(s, err) |
            ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(s, err) |
            ContextualParseError::InvalidMediaRule(s, err) => {
                (s.into(), err.kind)
            }
            ContextualParseError::InvalidCounterStyleWithoutSymbols(s) |
            ContextualParseError::InvalidCounterStyleNotEnoughSymbols(s) => {
                (s.into(), ParseErrorKind::Custom(StyleParseErrorKind::UnspecifiedError.into()))
            }
            ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols |
            ContextualParseError::InvalidCounterStyleExtendsWithSymbols |
            ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols => {
                ("".into(), ParseErrorKind::Custom(StyleParseErrorKind::UnspecifiedError.into()))
            }
        }
    }

    fn error_params(self) -> ErrorParams<'a> {
        let (s, error) = self.error_data();
        extract_error_params(error).unwrap_or_else(|| ErrorParams {
            main_param: Some(ErrorString::Snippet(s)),
            prefix_param: None
        })
    }

    fn to_gecko_message(&self) -> (Option<&'static [u8]>, &'static [u8], Action) {
        let (msg, action): (&[u8], Action) = match *self {
            ContextualParseError::UnsupportedPropertyDeclaration(
                _, ParseError { kind: ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(_)), .. }
            ) |
            ContextualParseError::UnsupportedPropertyDeclaration(
                _, ParseError { kind: ParseErrorKind::Basic(BasicParseErrorKind::AtRuleInvalid(_)), .. }
            ) => {
                (b"PEParseDeclarationDeclExpected\0", Action::Skip)
            }
            ContextualParseError::UnsupportedPropertyDeclaration(
                _, ParseError { kind: ParseErrorKind::Custom(ref err), .. }
            ) => {
                match *err {
                    StyleParseErrorKind::InvalidColor(_, _) => {
                        return (Some(b"PEColorNotColor\0"),
                                b"PEValueParsingError\0", Action::Drop)
                    }
                    StyleParseErrorKind::InvalidFilter(_, _) => {
                        return (Some(b"PEExpectedNoneOrURLOrFilterFunction\0"),
                                b"PEValueParsingError\0", Action::Drop)
                    }
                    StyleParseErrorKind::OtherInvalidValue(_) => {
                        (b"PEValueParsingError\0", Action::Drop)
                    }
                    _ => (b"PEUnknownProperty\0", Action::Drop)
                }
            }
            ContextualParseError::UnsupportedPropertyDeclaration(..) =>
                (b"PEUnknownProperty\0", Action::Drop),
            ContextualParseError::UnsupportedFontFaceDescriptor(..) =>
                (b"PEUnknwnFontDesc\0", Action::Skip),
            ContextualParseError::InvalidKeyframeRule(..) =>
                (b"PEKeyframeBadName\0", Action::Nothing),
            ContextualParseError::UnsupportedKeyframePropertyDeclaration(..) =>
                (b"PEBadSelectorKeyframeRuleIgnored\0", Action::Nothing),
            ContextualParseError::InvalidRule(
                _, ParseError { kind: ParseErrorKind::Custom(
                    StyleParseErrorKind::UnexpectedTokenWithinNamespace(_)
                ), .. }
            ) => {
                (b"PEAtNSUnexpected\0", Action::Nothing)
            }
            ContextualParseError::InvalidRule(
                _, ParseError { kind: ParseErrorKind::Basic(BasicParseErrorKind::AtRuleInvalid(_)), .. }
            ) |
            ContextualParseError::InvalidRule(
                _, ParseError { kind: ParseErrorKind::Custom(
                    StyleParseErrorKind::UnsupportedAtRule(_)
                ), .. }
            ) => {
                (b"PEUnknownAtRule\0", Action::Nothing)
            }
            ContextualParseError::InvalidRule(_, ref err) => {
                let prefix = match err.kind {
                    ParseErrorKind::Custom(StyleParseErrorKind::SelectorError(ref err)) => match *err {
                        SelectorParseErrorKind::UnexpectedTokenInAttributeSelector(_) => {
                            Some(&b"PEAttSelUnexpected\0"[..])
                        }
                        SelectorParseErrorKind::ExpectedBarInAttr(_) => {
                            Some(&b"PEAttSelNoBar\0"[..])
                        }
                        SelectorParseErrorKind::BadValueInAttr(_) => {
                            Some(&b"PEAttSelBadValue\0"[..])
                        }
                        SelectorParseErrorKind::NoQualifiedNameInAttributeSelector(_) => {
                            Some(&b"PEAttributeNameOrNamespaceExpected\0"[..])
                        }
                        SelectorParseErrorKind::InvalidQualNameInAttr(_) => {
                            Some(&b"PEAttributeNameExpected\0"[..])
                        }
                        SelectorParseErrorKind::ExplicitNamespaceUnexpectedToken(_) => {
                            Some(&b"PETypeSelNotType\0"[..])
                        }
                        SelectorParseErrorKind::ExpectedNamespace(_) => {
                           Some(&b"PEUnknownNamespacePrefix\0"[..])
                        }
                        SelectorParseErrorKind::EmptySelector => {
                            Some(&b"PESelectorGroupNoSelector\0"[..])
                        }
                        SelectorParseErrorKind::DanglingCombinator => {
                            Some(&b"PESelectorGroupExtraCombinator\0"[..])
                        }
                        SelectorParseErrorKind::UnsupportedPseudoClassOrElement(_) => {
                            Some(&b"PEPseudoSelUnknown\0"[..])
                        }
                        SelectorParseErrorKind::PseudoElementExpectedColon(_) => {
                            Some(&b"PEPseudoSelEndOrUserActionPC\0"[..])
                        }
                        SelectorParseErrorKind::NoIdentForPseudo(_) => {
                            Some(&b"PEPseudoClassArgNotIdent\0"[..])
                        }
                        SelectorParseErrorKind::PseudoElementExpectedIdent(_) => {
                            Some(&b"PEPseudoSelBadName\0"[..])
                        }
                        SelectorParseErrorKind::ClassNeedsIdent(_) => {
                            Some(&b"PEClassSelNotIdent\0"[..])
                        }
                        SelectorParseErrorKind::EmptyNegation => {
                            Some(&b"PENegationBadArg\0"[..])
                        }
                        _ => None,
                    },
                    _ => None,
                };
                return (prefix, b"PEBadSelectorRSIgnored\0", Action::Nothing);
            }
            ContextualParseError::InvalidMediaRule(_, ref err) => {
                let err: &[u8] = match err.kind {
                    ParseErrorKind::Custom(StyleParseErrorKind::ExpectedIdentifier(..)) => {
                        b"PEGatherMediaNotIdent\0"
                    },
                    ParseErrorKind::Custom(StyleParseErrorKind::MediaQueryExpectedFeatureName(..)) => {
                        b"PEMQExpectedFeatureName\0"
                    },
                    ParseErrorKind::Custom(StyleParseErrorKind::MediaQueryExpectedFeatureValue) => {
                        b"PEMQExpectedFeatureValue\0"
                    },
                    ParseErrorKind::Custom(StyleParseErrorKind::RangedExpressionWithNoValue) => {
                        b"PEMQNoMinMaxWithoutValue\0"
                    },
                    _ => {
                        b"PEDeclDropped\0"
                    },
                };
                (err, Action::Nothing)
            }
            ContextualParseError::UnsupportedRule(..) =>
                (b"PEDeclDropped\0", Action::Nothing),
            ContextualParseError::UnsupportedViewportDescriptorDeclaration(..) |
            ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(..) |
            ContextualParseError::InvalidCounterStyleWithoutSymbols(..) |
            ContextualParseError::InvalidCounterStyleNotEnoughSymbols(..) |
            ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols |
            ContextualParseError::InvalidCounterStyleExtendsWithSymbols |
            ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols |
            ContextualParseError::UnsupportedFontFeatureValuesDescriptor(..) |
            ContextualParseError::InvalidFontFeatureValuesRule(..) =>
                (b"PEUnknownAtRule\0", Action::Skip),
        };
        (None, msg, action)
    }
}

impl ParseErrorReporter for ErrorReporter {
    fn report_error(&self,
                    _url: &UrlExtraData,
                    location: SourceLocation,
                    error: ContextualParseError) {
        let (pre, name, action) = error.to_gecko_message();
        let suffix = match action {
            Action::Nothing => ptr::null(),
            Action::Skip => b"PEDeclSkipped\0".as_ptr(),
            Action::Drop => b"PEDeclDropped\0".as_ptr(),
        };
        let params = error.error_params();
        let param = params.main_param;
        let pre_param = params.prefix_param;
        let param = param.map(|p| p.into_str());
        let pre_param = pre_param.map(|p| p.into_str());
        let param_ptr = param.as_ref().map_or(ptr::null(), |p| p.as_ptr());
        let pre_param_ptr = pre_param.as_ref().map_or(ptr::null(), |p| p.as_ptr());
        // The CSS source text is unused and will be removed in bug 1381188.
        let source = "";
        unsafe {
            Gecko_ReportUnexpectedCSSError(self.0,
                                           name.as_ptr() as *const _,
                                           param_ptr as *const _,
                                           param.as_ref().map_or(0, |p| p.len()) as u32,
                                           pre.map_or(ptr::null(), |p| p.as_ptr()) as *const _,
                                           pre_param_ptr as *const _,
                                           pre_param.as_ref().map_or(0, |p| p.len()) as u32,
                                           suffix as *const _,
                                           source.as_ptr() as *const _,
                                           source.len() as u32,
                                           location.line,
                                           location.column);
        }
    }
}
<commit_msg>geckolib: Fix typo in CSS parser error message name.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Wrapper around Gecko's CSS error reporting mechanism.

#![allow(unsafe_code)]

use cssparser::{CowRcStr, serialize_identifier, ToCss};
use cssparser::{SourceLocation, ParseError, ParseErrorKind, Token, BasicParseErrorKind};
use selectors::parser::SelectorParseErrorKind;
use std::ptr;
use style::error_reporting::{ParseErrorReporter, ContextualParseError};
use style::gecko_bindings::bindings::{Gecko_CreateCSSErrorReporter, Gecko_DestroyCSSErrorReporter};
use style::gecko_bindings::bindings::Gecko_ReportUnexpectedCSSError;
use style::gecko_bindings::structs::{Loader, ServoStyleSheet, nsIURI};
use style::gecko_bindings::structs::ErrorReporter as GeckoErrorReporter;
use style::gecko_bindings::structs::URLExtraData as RawUrlExtraData;
use style::gecko_bindings::sugar::refptr::RefPtr;
use style::stylesheets::UrlExtraData;
use style_traits::StyleParseErrorKind;

pub type ErrorKind<'i> = ParseErrorKind<'i, StyleParseErrorKind<'i>>;

/// Wrapper around an instance of Gecko's CSS error reporter.
pub struct ErrorReporter(*mut GeckoErrorReporter);

impl ErrorReporter {
    /// Create a new instance of the Gecko error reporter.
    pub fn new(sheet: *mut ServoStyleSheet,
               loader: *mut Loader,
               url: *mut RawUrlExtraData) -> ErrorReporter {
        unsafe {
            let url = RefPtr::from_ptr_ref(&url);
            ErrorReporter(Gecko_CreateCSSErrorReporter(sheet, loader, url.mBaseURI.raw::<nsIURI>()))
        }
    }
}

impl Drop for ErrorReporter {
    fn drop(&mut self) {
        unsafe {
            Gecko_DestroyCSSErrorReporter(self.0);
        }
    }
}

enum ErrorString<'a> {
    Snippet(CowRcStr<'a>),
    Ident(CowRcStr<'a>),
    UnexpectedToken(Token<'a>),
}

impl<'a> ErrorString<'a> {
    fn into_str(self) -> CowRcStr<'a> {
        match self {
            ErrorString::Snippet(s) => s,
            ErrorString::UnexpectedToken(t) => t.to_css_string().into(),
            ErrorString::Ident(i) => {
                let mut s = String::new();
                serialize_identifier(&i, &mut s).unwrap();
                s.into()
            }
        }
    }
}

enum Action {
    Nothing,
    Skip,
    Drop,
}

trait ErrorHelpers<'a> {
    fn error_data(self) -> (CowRcStr<'a>, ErrorKind<'a>);
    fn error_params(self) -> ErrorParams<'a>;
    fn to_gecko_message(&self) -> (Option<&'static [u8]>, &'static [u8], Action);
}

fn extract_error_param<'a>(err: ErrorKind<'a>) -> Option<ErrorString<'a>> {
    Some(match err {
        ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(t)) => {
            ErrorString::UnexpectedToken(t)
        }

        ParseErrorKind::Basic(BasicParseErrorKind::AtRuleInvalid(i)) |
        ParseErrorKind::Custom(StyleParseErrorKind::UnsupportedAtRule(i)) => {
            let mut s = String::from("@");
            serialize_identifier(&i, &mut s).unwrap();
            ErrorString::Snippet(s.into())
        }

        ParseErrorKind::Custom(StyleParseErrorKind::OtherInvalidValue(property)) => {
            ErrorString::Snippet(property)
        }

        ParseErrorKind::Custom(
            StyleParseErrorKind::SelectorError(
                SelectorParseErrorKind::UnexpectedIdent(ident)
            )
        ) => {
            ErrorString::Ident(ident)
        }

        ParseErrorKind::Custom(StyleParseErrorKind::UnknownProperty(property)) => {
            ErrorString::Ident(property)
        }

        ParseErrorKind::Custom(
            StyleParseErrorKind::UnexpectedTokenWithinNamespace(token)
        ) => {
            ErrorString::UnexpectedToken(token)
        }

        _ => return None,
    })
}

struct ErrorParams<'a> {
    prefix_param: Option<ErrorString<'a>>,
    main_param: Option<ErrorString<'a>>,
}

/// If an error parameter is present in the given error, return it. Additionally return
/// a second parameter if it exists, for use in the prefix for the eventual error message.
fn extract_error_params<'a>(err: ErrorKind<'a>) -> Option<ErrorParams<'a>> {
    let (main, prefix) = match err {
        ParseErrorKind::Custom(StyleParseErrorKind::InvalidColor(property, token)) |
        ParseErrorKind::Custom(StyleParseErrorKind::InvalidFilter(property, token)) => {
            (Some(ErrorString::Snippet(property.into())), Some(ErrorString::UnexpectedToken(token)))
        }

        ParseErrorKind::Custom(
            StyleParseErrorKind::MediaQueryExpectedFeatureName(ident)
        ) => {
            (Some(ErrorString::Ident(ident)), None)
        }

        ParseErrorKind::Custom(
            StyleParseErrorKind::ExpectedIdentifier(token)
        ) => {
            (Some(ErrorString::UnexpectedToken(token)), None)
        }

        ParseErrorKind::Custom(StyleParseErrorKind::SelectorError(err)) => match err {
            SelectorParseErrorKind::UnexpectedTokenInAttributeSelector(t) |
            SelectorParseErrorKind::BadValueInAttr(t) |
            SelectorParseErrorKind::ExpectedBarInAttr(t) |
            SelectorParseErrorKind::NoQualifiedNameInAttributeSelector(t) |
            SelectorParseErrorKind::InvalidQualNameInAttr(t) |
            SelectorParseErrorKind::ExplicitNamespaceUnexpectedToken(t) |
            SelectorParseErrorKind::PseudoElementExpectedIdent(t) |
            SelectorParseErrorKind::NoIdentForPseudo(t) |
            SelectorParseErrorKind::ClassNeedsIdent(t) |
            SelectorParseErrorKind::PseudoElementExpectedColon(t) => {
                (None, Some(ErrorString::UnexpectedToken(t)))
            }
            SelectorParseErrorKind::ExpectedNamespace(namespace) => {
                (None, Some(ErrorString::Ident(namespace)))
            }
            SelectorParseErrorKind::UnsupportedPseudoClassOrElement(p) => {
                (None, Some(ErrorString::Ident(p)))
            }
            SelectorParseErrorKind::EmptySelector |
            SelectorParseErrorKind::DanglingCombinator => {
                (None, None)
            }
            SelectorParseErrorKind::EmptyNegation => {
                (None, Some(ErrorString::Snippet(")".into())))
            }
            err => match extract_error_param(ParseErrorKind::Custom(StyleParseErrorKind::SelectorError(err))) {
                Some(e) => (Some(e), None),
                None => return None,
            }
        },
        err => match extract_error_param(err) {
            Some(e) => (Some(e), None),
            None => return None,
        }
    };
    Some(ErrorParams {
        main_param: main,
        prefix_param: prefix,
    })
}

impl<'a> ErrorHelpers<'a> for ContextualParseError<'a> {
    fn error_data(self) -> (CowRcStr<'a>, ErrorKind<'a>) {
        match self {
            ContextualParseError::UnsupportedPropertyDeclaration(s, err) |
            ContextualParseError::UnsupportedFontFaceDescriptor(s, err) |
            ContextualParseError::UnsupportedFontFeatureValuesDescriptor(s, err) |
            ContextualParseError::InvalidKeyframeRule(s, err) |
            ContextualParseError::InvalidFontFeatureValuesRule(s, err) |
            ContextualParseError::UnsupportedKeyframePropertyDeclaration(s, err) |
            ContextualParseError::InvalidRule(s, err) |
            ContextualParseError::UnsupportedRule(s, err) |
            ContextualParseError::UnsupportedViewportDescriptorDeclaration(s, err) |
            ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(s, err) |
            ContextualParseError::InvalidMediaRule(s, err) => {
                (s.into(), err.kind)
            }
            ContextualParseError::InvalidCounterStyleWithoutSymbols(s) |
            ContextualParseError::InvalidCounterStyleNotEnoughSymbols(s) => {
                (s.into(), ParseErrorKind::Custom(StyleParseErrorKind::UnspecifiedError.into()))
            }
            ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols |
            ContextualParseError::InvalidCounterStyleExtendsWithSymbols |
            ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols => {
                ("".into(), ParseErrorKind::Custom(StyleParseErrorKind::UnspecifiedError.into()))
            }
        }
    }

    fn error_params(self) -> ErrorParams<'a> {
        let (s, error) = self.error_data();
        extract_error_params(error).unwrap_or_else(|| ErrorParams {
            main_param: Some(ErrorString::Snippet(s)),
            prefix_param: None
        })
    }

    fn to_gecko_message(&self) -> (Option<&'static [u8]>, &'static [u8], Action) {
        let (msg, action): (&[u8], Action) = match *self {
            ContextualParseError::UnsupportedPropertyDeclaration(
                _, ParseError { kind: ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(_)), .. }
            ) |
            ContextualParseError::UnsupportedPropertyDeclaration(
                _, ParseError { kind: ParseErrorKind::Basic(BasicParseErrorKind::AtRuleInvalid(_)), .. }
            ) => {
                (b"PEParseDeclarationDeclExpected\0", Action::Skip)
            }
            ContextualParseError::UnsupportedPropertyDeclaration(
                _, ParseError { kind: ParseErrorKind::Custom(ref err), .. }
            ) => {
                match *err {
                    StyleParseErrorKind::InvalidColor(_, _) => {
                        return (Some(b"PEColorNotColor\0"),
                                b"PEValueParsingError\0", Action::Drop)
                    }
                    StyleParseErrorKind::InvalidFilter(_, _) => {
                        return (Some(b"PEExpectedNoneOrURLOrFilterFunction\0"),
                                b"PEValueParsingError\0", Action::Drop)
                    }
                    StyleParseErrorKind::OtherInvalidValue(_) => {
                        (b"PEValueParsingError\0", Action::Drop)
                    }
                    _ => (b"PEUnknownProperty\0", Action::Drop)
                }
            }
            ContextualParseError::UnsupportedPropertyDeclaration(..) =>
                (b"PEUnknownProperty\0", Action::Drop),
            ContextualParseError::UnsupportedFontFaceDescriptor(..) =>
                (b"PEUnknownFontDesc\0", Action::Skip),
            ContextualParseError::InvalidKeyframeRule(..) =>
                (b"PEKeyframeBadName\0", Action::Nothing),
            ContextualParseError::UnsupportedKeyframePropertyDeclaration(..) =>
                (b"PEBadSelectorKeyframeRuleIgnored\0", Action::Nothing),
            ContextualParseError::InvalidRule(
                _, ParseError { kind: ParseErrorKind::Custom(
                    StyleParseErrorKind::UnexpectedTokenWithinNamespace(_)
                ), .. }
            ) => {
                (b"PEAtNSUnexpected\0", Action::Nothing)
            }
            ContextualParseError::InvalidRule(
                _, ParseError { kind: ParseErrorKind::Basic(BasicParseErrorKind::AtRuleInvalid(_)), .. }
            ) |
            ContextualParseError::InvalidRule(
                _, ParseError { kind: ParseErrorKind::Custom(
                    StyleParseErrorKind::UnsupportedAtRule(_)
                ), .. }
            ) => {
                (b"PEUnknownAtRule\0", Action::Nothing)
            }
            ContextualParseError::InvalidRule(_, ref err) => {
                let prefix = match err.kind {
                    ParseErrorKind::Custom(StyleParseErrorKind::SelectorError(ref err)) => match *err {
                        SelectorParseErrorKind::UnexpectedTokenInAttributeSelector(_) => {
                            Some(&b"PEAttSelUnexpected\0"[..])
                        }
                        SelectorParseErrorKind::ExpectedBarInAttr(_) => {
                            Some(&b"PEAttSelNoBar\0"[..])
                        }
                        SelectorParseErrorKind::BadValueInAttr(_) => {
                            Some(&b"PEAttSelBadValue\0"[..])
                        }
                        SelectorParseErrorKind::NoQualifiedNameInAttributeSelector(_) => {
                            Some(&b"PEAttributeNameOrNamespaceExpected\0"[..])
                        }
                        SelectorParseErrorKind::InvalidQualNameInAttr(_) => {
                            Some(&b"PEAttributeNameExpected\0"[..])
                        }
                        SelectorParseErrorKind::ExplicitNamespaceUnexpectedToken(_) => {
                            Some(&b"PETypeSelNotType\0"[..])
                        }
                        SelectorParseErrorKind::ExpectedNamespace(_) => {
                           Some(&b"PEUnknownNamespacePrefix\0"[..])
                        }
                        SelectorParseErrorKind::EmptySelector => {
                            Some(&b"PESelectorGroupNoSelector\0"[..])
                        }
                        SelectorParseErrorKind::DanglingCombinator => {
                            Some(&b"PESelectorGroupExtraCombinator\0"[..])
                        }
                        SelectorParseErrorKind::UnsupportedPseudoClassOrElement(_) => {
                            Some(&b"PEPseudoSelUnknown\0"[..])
                        }
                        SelectorParseErrorKind::PseudoElementExpectedColon(_) => {
                            Some(&b"PEPseudoSelEndOrUserActionPC\0"[..])
                        }
                        SelectorParseErrorKind::NoIdentForPseudo(_) => {
                            Some(&b"PEPseudoClassArgNotIdent\0"[..])
                        }
                        SelectorParseErrorKind::PseudoElementExpectedIdent(_) => {
                            Some(&b"PEPseudoSelBadName\0"[..])
                        }
                        SelectorParseErrorKind::ClassNeedsIdent(_) => {
                            Some(&b"PEClassSelNotIdent\0"[..])
                        }
                        SelectorParseErrorKind::EmptyNegation => {
                            Some(&b"PENegationBadArg\0"[..])
                        }
                        _ => None,
                    },
                    _ => None,
                };
                return (prefix, b"PEBadSelectorRSIgnored\0", Action::Nothing);
            }
            ContextualParseError::InvalidMediaRule(_, ref err) => {
                let err: &[u8] = match err.kind {
                    ParseErrorKind::Custom(StyleParseErrorKind::ExpectedIdentifier(..)) => {
                        b"PEGatherMediaNotIdent\0"
                    },
                    ParseErrorKind::Custom(StyleParseErrorKind::MediaQueryExpectedFeatureName(..)) => {
                        b"PEMQExpectedFeatureName\0"
                    },
                    ParseErrorKind::Custom(StyleParseErrorKind::MediaQueryExpectedFeatureValue) => {
                        b"PEMQExpectedFeatureValue\0"
                    },
                    ParseErrorKind::Custom(StyleParseErrorKind::RangedExpressionWithNoValue) => {
                        b"PEMQNoMinMaxWithoutValue\0"
                    },
                    _ => {
                        b"PEDeclDropped\0"
                    },
                };
                (err, Action::Nothing)
            }
            ContextualParseError::UnsupportedRule(..) =>
                (b"PEDeclDropped\0", Action::Nothing),
            ContextualParseError::UnsupportedViewportDescriptorDeclaration(..) |
            ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(..) |
            ContextualParseError::InvalidCounterStyleWithoutSymbols(..) |
            ContextualParseError::InvalidCounterStyleNotEnoughSymbols(..) |
            ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols |
            ContextualParseError::InvalidCounterStyleExtendsWithSymbols |
            ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols |
            ContextualParseError::UnsupportedFontFeatureValuesDescriptor(..) |
            ContextualParseError::InvalidFontFeatureValuesRule(..) =>
                (b"PEUnknownAtRule\0", Action::Skip),
        };
        (None, msg, action)
    }
}

impl ParseErrorReporter for ErrorReporter {
    fn report_error(&self,
                    _url: &UrlExtraData,
                    location: SourceLocation,
                    error: ContextualParseError) {
        let (pre, name, action) = error.to_gecko_message();
        let suffix = match action {
            Action::Nothing => ptr::null(),
            Action::Skip => b"PEDeclSkipped\0".as_ptr(),
            Action::Drop => b"PEDeclDropped\0".as_ptr(),
        };
        let params = error.error_params();
        let param = params.main_param;
        let pre_param = params.prefix_param;
        let param = param.map(|p| p.into_str());
        let pre_param = pre_param.map(|p| p.into_str());
        let param_ptr = param.as_ref().map_or(ptr::null(), |p| p.as_ptr());
        let pre_param_ptr = pre_param.as_ref().map_or(ptr::null(), |p| p.as_ptr());
        // The CSS source text is unused and will be removed in bug 1381188.
        let source = "";
        unsafe {
            Gecko_ReportUnexpectedCSSError(self.0,
                                           name.as_ptr() as *const _,
                                           param_ptr as *const _,
                                           param.as_ref().map_or(0, |p| p.len()) as u32,
                                           pre.map_or(ptr::null(), |p| p.as_ptr()) as *const _,
                                           pre_param_ptr as *const _,
                                           pre_param.as_ref().map_or(0, |p| p.len()) as u32,
                                           suffix as *const _,
                                           source.as_ptr() as *const _,
                                           source.len() as u32,
                                           location.line,
                                           location.column);
        }
    }
}
<|endoftext|>


<commit_before>use libimagstore::store::EntryHeader;

use error::{LinkError, LinkErrorKind};
use link::{Link, Links};
use result::Result;

use toml::Value;
use toml::Table;

pub trait ExternalLinker {

    /// get the external link from the implementor object
    fn get_external_link(&self) -> Result<Option<Link>>;

    /// set the external link for the implementor object and return the current link from the entry,
    /// if any.
    fn set_external_link(&mut self, l: Link) -> Result<Option<Link>>;
}

impl ExternalLinker for EntryHeader {

    fn get_external_link(&self) -> Result<Option<Link>> {
        let uri = self.read("imag.content.uri");

        if uri.is_err() {
            let kind = LinkErrorKind::EntryHeaderReadError;
            let lerr = LinkError::new(kind, Some(Box::new(uri.err().unwrap())));
            return Err(lerr);
        }
        let uri = uri.unwrap();

        match uri {
            Some(Value::String(s)) => Ok(Some(Link::new(s))),
            _ => Err(LinkError::new(LinkErrorKind::ExistingLinkTypeWrong, None)),
        }
    }

    /// Set an external link in the header
    ///
    /// Return the previous set link if there was any
    fn set_external_link(&mut self, l: Link) -> Result<Option<Link>> {
        let old_link = self.set("imag.content.uri", Value::String(l.into()));

        if old_link.is_err() {
            let kind = LinkErrorKind::EntryHeaderWriteError;
            let lerr = LinkError::new(kind, Some(Box::new(old_link.err().unwrap())));
            return Err(lerr);
        }
        let old_link = old_link.unwrap();

        if old_link.is_none() {
            return Ok(None);
        }

        match old_link.unwrap() {
            Value::String(s) => Ok(Some(Link::new(s))),

            // We don't do anything in this case and be glad we corrected the type error with this set()
            _ => Ok(None),
        }
    }

}

<commit_msg>Implement ExternalLinker for Entry for convenience<commit_after>use libimagstore::store::Entry;
use libimagstore::store::EntryHeader;

use error::{LinkError, LinkErrorKind};
use link::{Link, Links};
use result::Result;

use toml::Value;
use toml::Table;

pub trait ExternalLinker {

    /// get the external link from the implementor object
    fn get_external_link(&self) -> Result<Option<Link>>;

    /// set the external link for the implementor object and return the current link from the entry,
    /// if any.
    fn set_external_link(&mut self, l: Link) -> Result<Option<Link>>;
}

impl ExternalLinker for EntryHeader {

    fn get_external_link(&self) -> Result<Option<Link>> {
        let uri = self.read("imag.content.uri");

        if uri.is_err() {
            let kind = LinkErrorKind::EntryHeaderReadError;
            let lerr = LinkError::new(kind, Some(Box::new(uri.err().unwrap())));
            return Err(lerr);
        }
        let uri = uri.unwrap();

        match uri {
            Some(Value::String(s)) => Ok(Some(Link::new(s))),
            _ => Err(LinkError::new(LinkErrorKind::ExistingLinkTypeWrong, None)),
        }
    }

    /// Set an external link in the header
    ///
    /// Return the previous set link if there was any
    fn set_external_link(&mut self, l: Link) -> Result<Option<Link>> {
        let old_link = self.set("imag.content.uri", Value::String(l.into()));

        if old_link.is_err() {
            let kind = LinkErrorKind::EntryHeaderWriteError;
            let lerr = LinkError::new(kind, Some(Box::new(old_link.err().unwrap())));
            return Err(lerr);
        }
        let old_link = old_link.unwrap();

        if old_link.is_none() {
            return Ok(None);
        }

        match old_link.unwrap() {
            Value::String(s) => Ok(Some(Link::new(s))),

            // We don't do anything in this case and be glad we corrected the type error with this set()
            _ => Ok(None),
        }
    }

}

impl ExternalLinker for Entry {

    fn get_external_link(&self) -> Result<Option<Link>> {
        self.get_header().get_external_link()
    }

    fn set_external_link(&mut self, l: Link) -> Result<Option<Link>> {
        self.get_header_mut().set_external_link(l)
    }

}
<|endoftext|>


<commit_before>//! Endpoints for event receipts.
<commit_msg>Implement receipt endpoints.<commit_after>//! Endpoints for event receipts.

/// [POST /_matrix/client/r0/rooms/{roomId}/receipt/{receiptType}/{eventId}](https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-receipt-receipttype-eventid)
pub mod create_receipt {
    use ruma_identifiers::{EventId, RoomId};

    use std::fmt::{Display, Error as FmtError, Formatter};

    /// Details about this API endpoint.
    pub struct Endpoint;

    /// This endpoint's path parameters.
    #[derive(Clone, Debug)]
    pub struct PathParams {
        /// The event ID to acknowledge up to.
        pub event_id: EventId,
        /// The type of receipt to send.
        pub receipt_type: ReceiptType,
        /// The room in which to send the event.
        pub room_id: RoomId,
    }

    /// The type of receipt.
    #[derive(Clone, Copy, Debug)]
    pub enum ReceiptType {
        /// m.read
        Read,
    }

    /// This API endpoint's response.
    #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
    pub struct Response;

    impl ::Endpoint for Endpoint {
        type BodyParams = ();
        type PathParams = PathParams;
        type QueryParams = ();
        type Response = Response;

        fn method() -> ::Method {
            ::Method::Post
        }

        fn request_path(params: Self::PathParams) -> String {
            format!(
                "/_matrix/client/r0/rooms/{}/receipt/{}/{}",
                params.room_id,
                params.receipt_type,
                params.event_id
            )
        }

        fn router_path() -> String {
            "/_matrix/client/r0/rooms/:room_id/receipt/:receipt_type/:event_id".to_string()
        }
    }

    impl Display for ReceiptType {
        fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
            match *self {
                ReceiptType::Read => write!(f, "m.read"),
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Support for build-in RNGs

#[derive(Debug)]
/// Used to obtain random numbers using x86_64's RDRAND opcode
pub struct RdRand(());

impl RdRand {
    /// Creates Some(RdRand) if RDRAND is supported, None otherwise
    #[cfg(target_arch = "x86_64")]
    pub fn new() -> Option<Self> {
        let cpuid = raw_cpuid::CpuId::new();
        let has_rdrand = match cpuid.get_feature_info() {
            Some(finfo) => finfo.has_rdrand(),
            None => false,
        };

        match has_rdrand {
            true => Some(RdRand(())),
            false => None,
        }
    }

    /// Uniformly sampled u64
    #[inline]
    #[cfg(target_arch = "x86_64")]
    pub fn get(&self) -> u64 {
        let res: u64;
        unsafe {
            asm!("rdrand %rax" : "={rax}"(res) ::: "volatile");
        }

        res
    }
}
<commit_msg>Handle failure of rdrand instruction (#59)<commit_after>//! Support for build-in RNGs

#[derive(Copy, Clone, Debug)]
/// Used to obtain random numbers using x86_64's RDRAND opcode
pub struct RdRand(());

#[cfg(target_arch = "x86_64")]
impl RdRand {
    /// Creates Some(RdRand) if RDRAND is supported, None otherwise
    pub fn new() -> Option<Self> {
        let cpuid = raw_cpuid::CpuId::new();
        let has_rdrand = match cpuid.get_feature_info() {
            Some(finfo) => finfo.has_rdrand(),
            None => false,
        };

        match has_rdrand {
            true => Some(RdRand(())),
            false => None,
        }
    }

    /// Uniformly sampled u64
    #[deprecated(note = "This method does not check for errors and will be removed in the next breaking release. Use get_u64() instead.")]
    #[inline]
    pub fn get(&self) -> u64 {
        let res: u64;
        unsafe {
            asm!("rdrand %rax" : "={rax}"(res) ::: "volatile");
        }

        res
    }
    /// Uniformly sampled u64.
    /// May fail in rare circumstances or heavy load.
    #[inline]
    pub fn get_u64(&self) -> Option<u64> {
        let res: u64;
        let ok: u8;
        unsafe {
            asm!("rdrand %rax; setc $1;"
                : "={rax}"(res) "=r"(ok)
                :: "flags" : "volatile");
        }
        match ok {
            1 => Some(res),
            _ => None
        }
    }
    /// Uniformly sampled u32.
    /// May fail in rare circumstances or heavy load.
    #[inline]
    pub fn get_u32(&self) -> Option<u32> {
        let res: u32;
        let ok: u8;
        unsafe {
            asm!("rdrand %eax; setc $1;"
                : "={eax}"(res) "=r"(ok)
                :: "flags" : "volatile");
        }
        match ok {
            1 => Some(res),
            _ => None
        }
    }
    /// Uniformly sampled u16.
    /// May fail in rare circumstances or heavy load.
    #[inline]
    pub fn get_u16(&self) -> Option<u16> {
        let res: u16;
        let ok: u8;
        unsafe {
            asm!("rdrand %ax; setc $1;"
                : "={ax}"(res) "=r"(ok)
                :: "flags" : "volatile");
        }
        match ok {
            1 => Some(res),
            _ => None
        }
    }
}<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::HashMap;
use std::{fs, thread};
use std::io::{Error, ErrorKind, Write};
use std::path::{Path, PathBuf};
use rustc_serialize;
use rustc_serialize::json;
use zmq;

use commands::{Command, CommandExecutor};
use commands::pool::PoolCommand;
use errors::pool::PoolError;
use utils::sequence::SequenceUtils;
use utils::environment::EnvironmentUtils;

pub struct PoolService {
    pools: RefCell<HashMap<i32, Pool>>,
}

struct Pool {
    name: String,
    id: i32,
    send_sock: zmq::Socket,
    worker: Option<thread::JoinHandle<()>>,
}

impl Pool {
    pub fn new(name: &str, cmd_id: i32) -> Result<Pool, PoolError> {
        let zmq_ctx = zmq::Context::new();
        let send_s = zmq_ctx.socket(zmq::SocketType::PAIR)?;
        let recv_s = zmq_ctx.socket(zmq::SocketType::PAIR)?;
        let zmq_ctx = zmq::Context::new();
        let recv_cmd_sock = zmq_ctx.socket(zmq::SocketType::PAIR)?;
        let send_cmd_sock = zmq_ctx.socket(zmq::SocketType::PAIR)?;
        let inproc_sock_name: String = format!("inproc://pool_{}", name);

        recv_cmd_sock.bind(inproc_sock_name.as_str())?;

        send_cmd_sock.connect(inproc_sock_name.as_str())?;
        let pool_id = SequenceUtils::get_next_id();

        Ok(Pool {
            name: name.to_string(),
            id: pool_id,
            send_sock: send_s,
            worker: Some(thread::spawn(move || {
                let mut socks_to_poll: [zmq::PollItem; 1] = [
                    recv_s.as_poll_item(zmq::POLLIN),
                ];
                CommandExecutor::instance().send(Command::Pool(
                    PoolCommand::OpenAck(cmd_id, Ok(pool_id)))); //TODO send only after catch-up?
                loop {
                    trace!("zmq poll loop >>");
                    let r = zmq::poll(&mut socks_to_poll, -1);
                    //FIXME implement
                    trace!("zmq poll loop << ret {:?}, at cmd sock {:?}", r, recv_s.recv_string(0));
                }
            })),
        })
    }
}

impl Drop for Pool {
    fn drop(&mut self) {
        loop {
            info!("inf loop");
        }
        let target = format!("pool{}", self.name);
        info!(target: target.as_str(), "Drop started");
        self.send_sock.send("exit".as_bytes(), 0);
        // Option worker type and this kludge is workaround for rust
        self.worker.take().unwrap().join().unwrap();
        info!(target: target.as_str(), "Drop finished");
    }
}

#[derive(RustcDecodable, RustcEncodable)]
struct PoolConfig {
    genesis_txn: String
}

impl PoolConfig {
    fn default(name: &str) -> PoolConfig {
        let mut txn = name.to_string();
        txn += ".txn";
        PoolConfig { genesis_txn: txn }
    }
}

impl PoolService {
    pub fn new() -> PoolService {
        PoolService {
            pools: RefCell::new(HashMap::new()),
        }
    }

    pub fn create(&self, name: &str, config: Option<&str>) -> Result<(), PoolError> {
        let mut path = EnvironmentUtils::pool_path(name);
        let pool_config: PoolConfig = match config {
            Some(config) => json::decode(config)?,
            None => PoolConfig::default(name)
        };

        if path.as_path().exists() {
            return Err(PoolError::NotCreated("Already created".to_string()));
        }

        fs::create_dir_all(path.as_path());

        path.push(name);
        path.set_extension("txn");
        fs::copy(&pool_config.genesis_txn, path.as_path())?;
        path.pop();

        path.push("config");
        path.set_extension("json");
        let mut f: fs::File = fs::File::create(path.as_path())?;
        f.write(json::encode(&pool_config)?.as_bytes())?;
        f.flush()?;

        // TODO probably create another one file pool.json with pool description,
        // but now there is no info to save (except name witch equal to directory)

        Ok(())
    }

    pub fn delete(&self, name: &str) -> Result<(), PoolError> {
        unimplemented!()
    }

    pub fn open(&self, name: &str, config: Option<&str>) -> Result<i32, PoolError> {
        for pool in self.pools.borrow().values() {
            if name.eq(pool.name.as_str()) {
                //TODO change error
                return Err(PoolError::InvalidHandle("Already opened".to_string()));
            }
        }

        let cmd_id: i32 = SequenceUtils::get_next_id();
        let new_pool = Pool::new(name, cmd_id)?;
        //FIXME process config: check None (use default), transfer to Pool instance

        self.pools.borrow_mut().insert(new_pool.id, new_pool);
        return Ok(cmd_id);
    }

    pub fn close(&self, handle: i32) -> Result<(), PoolError> {
        unimplemented!()
    }

    pub fn refresh(&self, handle: i32) -> Result<(), PoolError> {
        unimplemented!()
    }

    pub fn get_pool_name(&self, handle: i32) -> Result<String, PoolError> {
        self.pools.borrow().get(&handle).map_or(
            Err(PoolError::InvalidHandle("Doesn't exists".to_string())),
            |pool: &Pool| Ok(pool.name.clone()))
    }
}

#[cfg(test)]
mod mocks {
    use super::*;

    use std::cell::RefCell;

    pub struct PoolService {
        create_results: RefCell<Vec<Result<(), PoolError>>>,
        delete_results: RefCell<Vec<Result<(), PoolError>>>,
        open_results: RefCell<Vec<Result<i32, PoolError>>>,
        close_results: RefCell<Vec<Result<(), PoolError>>>,
        refresh_results: RefCell<Vec<Result<(), PoolError>>>
    }

    impl PoolService {
        pub fn new() -> PoolService {
            PoolService {
                create_results: RefCell::new(Vec::new()),
                delete_results: RefCell::new(Vec::new()),
                open_results: RefCell::new(Vec::new()),
                close_results: RefCell::new(Vec::new()),
                refresh_results: RefCell::new(Vec::new())
            }
        }

        pub fn create(&self, name: &str, config: &str) -> Result<(), PoolError> {
            //self.create_results.pop().unwrap()
            unimplemented!()
        }

        pub fn delete(&self, name: &str) -> Result<(), PoolError> {
            //self.delete_results.pop().unwrap()
            unimplemented!()
        }

        pub fn open(&self, name: &str, config: &str) -> Result<i32, PoolError> {
            //self.open_results.pop().unwrap()
            unimplemented!()
        }

        pub fn close(&self, handle: i32) -> Result<(), PoolError> {
            //self.close_results.pop().unwrap()
            unimplemented!()
        }

        pub fn refresh(&self, handle: i32) -> Result<(), PoolError> {
            //self.refresh_results.pop().unwrap()
            unimplemented!()
        }
    }
}

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

    #[test]
    fn pool_service_can_be_created() {
        let pool_service = PoolService::new();
        assert!(true, "No crashes on PoolService::new");
    }

    #[test]
    fn pool_service_can_be_dropped() {
        fn drop_test() {
            let pool_service = PoolService::new();
        }

        drop_test();
        assert!(true, "No crashes on PoolService::drop");
    }
}<commit_msg>Remove debug code from Pool.drop(), add TODO.<commit_after>use std::cell::RefCell;
use std::collections::HashMap;
use std::{fs, thread};
use std::io::{Error, ErrorKind, Write};
use std::path::{Path, PathBuf};
use rustc_serialize;
use rustc_serialize::json;
use zmq;

use commands::{Command, CommandExecutor};
use commands::pool::PoolCommand;
use errors::pool::PoolError;
use utils::sequence::SequenceUtils;
use utils::environment::EnvironmentUtils;

pub struct PoolService {
    pools: RefCell<HashMap<i32, Pool>>,
}

struct Pool {
    name: String,
    id: i32,
    send_sock: zmq::Socket,
    worker: Option<thread::JoinHandle<()>>,
}

impl Pool {
    pub fn new(name: &str, cmd_id: i32) -> Result<Pool, PoolError> {
        let zmq_ctx = zmq::Context::new();
        let send_s = zmq_ctx.socket(zmq::SocketType::PAIR)?;
        let recv_s = zmq_ctx.socket(zmq::SocketType::PAIR)?;
        let zmq_ctx = zmq::Context::new();
        let recv_cmd_sock = zmq_ctx.socket(zmq::SocketType::PAIR)?;
        let send_cmd_sock = zmq_ctx.socket(zmq::SocketType::PAIR)?;
        let inproc_sock_name: String = format!("inproc://pool_{}", name);

        recv_cmd_sock.bind(inproc_sock_name.as_str())?;

        send_cmd_sock.connect(inproc_sock_name.as_str())?;
        let pool_id = SequenceUtils::get_next_id();

        Ok(Pool {
            name: name.to_string(),
            id: pool_id,
            send_sock: send_s,
            worker: Some(thread::spawn(move || {
                let mut socks_to_poll: [zmq::PollItem; 1] = [
                    recv_s.as_poll_item(zmq::POLLIN),
                ];
                CommandExecutor::instance().send(Command::Pool(
                    PoolCommand::OpenAck(cmd_id, Ok(pool_id)))); //TODO send only after catch-up?
                loop {
                    trace!("zmq poll loop >>");
                    let r = zmq::poll(&mut socks_to_poll, -1);
                    //FIXME implement
                    trace!("zmq poll loop << ret {:?}, at cmd sock {:?}", r, recv_s.recv_string(0));
                }
            })),
        })
    }
}

impl Drop for Pool {
    fn drop(&mut self) {
        let target = format!("pool{}", self.name);
        info!(target: target.as_str(), "Drop started");
        self.send_sock.send("exit".as_bytes(), 0); //TODO
        // Option worker type and this kludge is workaround for rust
        self.worker.take().unwrap().join().unwrap();
        info!(target: target.as_str(), "Drop finished");
    }
}

#[derive(RustcDecodable, RustcEncodable)]
struct PoolConfig {
    genesis_txn: String
}

impl PoolConfig {
    fn default(name: &str) -> PoolConfig {
        let mut txn = name.to_string();
        txn += ".txn";
        PoolConfig { genesis_txn: txn }
    }
}

impl PoolService {
    pub fn new() -> PoolService {
        PoolService {
            pools: RefCell::new(HashMap::new()),
        }
    }

    pub fn create(&self, name: &str, config: Option<&str>) -> Result<(), PoolError> {
        let mut path = EnvironmentUtils::pool_path(name);
        let pool_config: PoolConfig = match config {
            Some(config) => json::decode(config)?,
            None => PoolConfig::default(name)
        };

        if path.as_path().exists() {
            return Err(PoolError::NotCreated("Already created".to_string()));
        }

        fs::create_dir_all(path.as_path());

        path.push(name);
        path.set_extension("txn");
        fs::copy(&pool_config.genesis_txn, path.as_path())?;
        path.pop();

        path.push("config");
        path.set_extension("json");
        let mut f: fs::File = fs::File::create(path.as_path())?;
        f.write(json::encode(&pool_config)?.as_bytes())?;
        f.flush()?;

        // TODO probably create another one file pool.json with pool description,
        // but now there is no info to save (except name witch equal to directory)

        Ok(())
    }

    pub fn delete(&self, name: &str) -> Result<(), PoolError> {
        unimplemented!()
    }

    pub fn open(&self, name: &str, config: Option<&str>) -> Result<i32, PoolError> {
        for pool in self.pools.borrow().values() {
            if name.eq(pool.name.as_str()) {
                //TODO change error
                return Err(PoolError::InvalidHandle("Already opened".to_string()));
            }
        }

        let cmd_id: i32 = SequenceUtils::get_next_id();
        let new_pool = Pool::new(name, cmd_id)?;
        //FIXME process config: check None (use default), transfer to Pool instance

        self.pools.borrow_mut().insert(new_pool.id, new_pool);
        return Ok(cmd_id);
    }

    pub fn close(&self, handle: i32) -> Result<(), PoolError> {
        unimplemented!()
    }

    pub fn refresh(&self, handle: i32) -> Result<(), PoolError> {
        unimplemented!()
    }

    pub fn get_pool_name(&self, handle: i32) -> Result<String, PoolError> {
        self.pools.borrow().get(&handle).map_or(
            Err(PoolError::InvalidHandle("Doesn't exists".to_string())),
            |pool: &Pool| Ok(pool.name.clone()))
    }
}

#[cfg(test)]
mod mocks {
    use super::*;

    use std::cell::RefCell;

    pub struct PoolService {
        create_results: RefCell<Vec<Result<(), PoolError>>>,
        delete_results: RefCell<Vec<Result<(), PoolError>>>,
        open_results: RefCell<Vec<Result<i32, PoolError>>>,
        close_results: RefCell<Vec<Result<(), PoolError>>>,
        refresh_results: RefCell<Vec<Result<(), PoolError>>>
    }

    impl PoolService {
        pub fn new() -> PoolService {
            PoolService {
                create_results: RefCell::new(Vec::new()),
                delete_results: RefCell::new(Vec::new()),
                open_results: RefCell::new(Vec::new()),
                close_results: RefCell::new(Vec::new()),
                refresh_results: RefCell::new(Vec::new())
            }
        }

        pub fn create(&self, name: &str, config: &str) -> Result<(), PoolError> {
            //self.create_results.pop().unwrap()
            unimplemented!()
        }

        pub fn delete(&self, name: &str) -> Result<(), PoolError> {
            //self.delete_results.pop().unwrap()
            unimplemented!()
        }

        pub fn open(&self, name: &str, config: &str) -> Result<i32, PoolError> {
            //self.open_results.pop().unwrap()
            unimplemented!()
        }

        pub fn close(&self, handle: i32) -> Result<(), PoolError> {
            //self.close_results.pop().unwrap()
            unimplemented!()
        }

        pub fn refresh(&self, handle: i32) -> Result<(), PoolError> {
            //self.refresh_results.pop().unwrap()
            unimplemented!()
        }
    }
}

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

    #[test]
    fn pool_service_can_be_created() {
        let pool_service = PoolService::new();
        assert!(true, "No crashes on PoolService::new");
    }

    #[test]
    fn pool_service_can_be_dropped() {
        fn drop_test() {
            let pool_service = PoolService::new();
        }

        drop_test();
        assert!(true, "No crashes on PoolService::drop");
    }
}<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.
use std::fmt::{Debug, Display, Formatter};
use regex::Error as RegexError;

/// An error type for failures that can occur during a session.
#[derive(Debug)]
pub enum Error {
    /// Action-specific failure.
    Action(Box<dyn std::error::Error>),
    /// Attempted to call an unknown or not implemented action.
    Dispatch(String),
    /// An error occurred when encoding bytes of a proto message.
    // TODO: Rename to just `Encode`.
    // TODO: Determine whether we need this error type or we should just panic.
    EncodeProtobuf(protobuf::ProtobufError),
    /// An error occurred when parsing a proto message.
    Parse(ParseError),
}

impl Error {

    /// Converts an arbitrary action-issued error to a session error.
    ///
    /// This function should be used to construct session errors from action
    /// specific error types and propagate them further in the session pipeline.
    pub fn action<E>(error: E) -> Error
    where
        E: std::error::Error + 'static
    {
        Error::Action(Box::new(error))
    }
}

impl Display for Error {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        use Error::*;

        match *self {
            Action(ref error) => {
                write!(fmt, "action error: {}", error)
            }
            Dispatch(ref name) if name.is_empty() => {
                write!(fmt, "missing action")
            }
            Dispatch(ref name) => {
                write!(fmt, "unknown action: {}", name)
            }
            EncodeProtobuf(ref error) => {
                write!(fmt, "failure during encoding proto message: {}", error)
            }
            Parse(ref error) => {
                write!(fmt, "malformed proto message: {}", error)
            }
        }
    }
}

impl std::error::Error for Error {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use Error::*;

        match *self {
            Action(ref error) => Some(error.as_ref()),
            Dispatch(_) => None,
            EncodeProtobuf(ref error) => Some(error),
            Parse(ref error) => Some(error),
        }
    }
}

impl From<protobuf::ProtobufError> for Error {

    fn from(error: protobuf::ProtobufError) -> Error {
        Error::EncodeProtobuf(error)
    }
}

impl From<ParseError> for Error {

    fn from(error: ParseError) -> Error {
        Error::Parse(error)
    }
}

/// An error type for failures that can occur when parsing proto messages.
#[derive(Debug)]
pub enum ParseError {
    /// An error occurred because the decoded proto message was malformed.
    Malformed(Box<dyn std::error::Error + Send + Sync>),
    // TODO: Rename to just `Decode`.
    /// An error occurred when decoding bytes of a proto message.
    DecodeProtobuf(protobuf::ProtobufError),
}

impl ParseError {

    /// Converts a detailed error indicating a malformed proto to `ParseError`.
    ///
    /// This is just a convenience function for lifting custom error types that
    /// contain more specific information to generic `ParseError`.
    pub fn malformed<E>(error: E) -> ParseError
    where
        E: Into<Box<dyn std::error::Error + Send + Sync>>,
    {
        ParseError::Malformed(error.into())
    }
}

impl Display for ParseError {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        use ParseError::*;

        match *self {
            Malformed(ref error) => {
                write!(fmt, "invalid proto message: {}", error)
            }
            DecodeProtobuf(ref error) => {
                write!(fmt, "failed to decode proto message: {}", error)
            }
        }
    }
}

impl std::error::Error for ParseError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use ParseError::*;

        match *self {
            Malformed(ref error) => Some(error.as_ref()),
            DecodeProtobuf(ref error) => Some(error),
        }
    }
}

impl From<protobuf::ProtobufError> for ParseError {

    fn from(error: protobuf::ProtobufError) -> ParseError {
        ParseError::DecodeProtobuf(error)
    }
}

/// An error type for situations where required proto field is missing.
#[derive(Debug)]
pub struct MissingFieldError {
    /// A name of the missing field.
    name: &'static str,
}

impl MissingFieldError {

    /// Creates a new error indicating that required field `name` is missing.
    pub fn new(name: &'static str) -> MissingFieldError {
        MissingFieldError {
            name: name,
        }
    }
}

impl Display for MissingFieldError {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        write!(fmt, "required field '{}' is missing", self.name)
    }
}

impl std::error::Error for MissingFieldError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl From<MissingFieldError> for ParseError {

    fn from(error: MissingFieldError) -> ParseError {
        ParseError::malformed(error)
    }
}

/// An error type for situations where a given proto value is not supported.
#[derive(Debug)]
pub struct UnsupportedValueError<T> {
    /// A name of the field the value belongs to.
    pub name: &'static str,
    /// A value that is not supported.
    pub value: T,
}

impl<T: Debug> Display for UnsupportedValueError<T> {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        write!(fmt, "unsupported value for '{}': {:?}", self.name, self.value)
    }
}

impl<T: Debug> std::error::Error for UnsupportedValueError<T> {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

/// An error type for situations where time micros cannot be converted
/// to `std::time::SystemTime`.
#[derive(Debug)]
pub struct TimeMicrosConversionError {
    /// Time micros value causing the conversion error.
    pub micros: u64,
}

impl Display for TimeMicrosConversionError {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        write!(fmt, "cannot convert micros to std::time::SystemTime: {}", self.micros)
    }
}

impl std::error::Error for TimeMicrosConversionError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl From<TimeMicrosConversionError> for ParseError {

    fn from(error: TimeMicrosConversionError) -> ParseError {
        ParseError::malformed(error)
    }
}

#[derive(Debug)]
pub struct RegexParseError {
    /// Raw data of the string which could not be converted to Regex.
    pub raw_data: Vec<u8>,
    /// Error message caught during the conversion.
    pub error: RegexError,
}

impl Display for RegexParseError {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        write!(fmt, "Regex parse error happened on parsing '{:?}'. \
                     Regex error: '{}'",
               self.raw_data,
               self.error.to_string())
    }
}

impl std::error::Error for RegexParseError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl From<RegexParseError> for ParseError {

    fn from(error: RegexParseError) -> ParseError {
        ParseError::malformed(error)
    }
}

/// An error type for situations where proto enum has a value for which
/// the definition is not known.
#[derive(Debug)]
pub struct UnknownEnumValueError {
    /// A name of the enum field having unknown enum value.
    pub name: &'static str,

    /// An enum value, which definition is not known.
    pub value: i32,
}

impl Display for UnknownEnumValueError {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        write!(fmt, "protobuf enum '{}' has unrecognised value: '{}'",
               self.name, self.value)
    }
}

impl std::error::Error for UnknownEnumValueError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl From<UnknownEnumValueError> for ParseError {

    fn from(error: UnknownEnumValueError) -> ParseError {
        ParseError::malformed(error)
    }
}
<commit_msg>Rename enum variants for `protobuf` errors.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.
use std::fmt::{Debug, Display, Formatter};
use regex::Error as RegexError;

/// An error type for failures that can occur during a session.
#[derive(Debug)]
pub enum Error {
    /// Action-specific failure.
    Action(Box<dyn std::error::Error>),
    /// Attempted to call an unknown or not implemented action.
    Dispatch(String),
    /// An error occurred when encoding bytes of a proto message.
    // TODO: Determine whether we need this error type or we should just panic.
    Encode(protobuf::ProtobufError),
    /// An error occurred when parsing a proto message.
    Parse(ParseError),
}

impl Error {

    /// Converts an arbitrary action-issued error to a session error.
    ///
    /// This function should be used to construct session errors from action
    /// specific error types and propagate them further in the session pipeline.
    pub fn action<E>(error: E) -> Error
    where
        E: std::error::Error + 'static
    {
        Error::Action(Box::new(error))
    }
}

impl Display for Error {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        use Error::*;

        match *self {
            Action(ref error) => {
                write!(fmt, "action error: {}", error)
            }
            Dispatch(ref name) if name.is_empty() => {
                write!(fmt, "missing action")
            }
            Dispatch(ref name) => {
                write!(fmt, "unknown action: {}", name)
            }
            Encode(ref error) => {
                write!(fmt, "failure during encoding proto message: {}", error)
            }
            Parse(ref error) => {
                write!(fmt, "malformed proto message: {}", error)
            }
        }
    }
}

impl std::error::Error for Error {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use Error::*;

        match *self {
            Action(ref error) => Some(error.as_ref()),
            Dispatch(_) => None,
            Encode(ref error) => Some(error),
            Parse(ref error) => Some(error),
        }
    }
}

impl From<protobuf::ProtobufError> for Error {

    fn from(error: protobuf::ProtobufError) -> Error {
        Error::Encode(error)
    }
}

impl From<ParseError> for Error {

    fn from(error: ParseError) -> Error {
        Error::Parse(error)
    }
}

/// An error type for failures that can occur when parsing proto messages.
#[derive(Debug)]
pub enum ParseError {
    /// An error occurred because the decoded proto message was malformed.
    Malformed(Box<dyn std::error::Error + Send + Sync>),
    /// An error occurred when decoding bytes of a proto message.
    Decode(protobuf::ProtobufError),
}

impl ParseError {

    /// Converts a detailed error indicating a malformed proto to `ParseError`.
    ///
    /// This is just a convenience function for lifting custom error types that
    /// contain more specific information to generic `ParseError`.
    pub fn malformed<E>(error: E) -> ParseError
    where
        E: Into<Box<dyn std::error::Error + Send + Sync>>,
    {
        ParseError::Malformed(error.into())
    }
}

impl Display for ParseError {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        use ParseError::*;

        match *self {
            Malformed(ref error) => {
                write!(fmt, "invalid proto message: {}", error)
            }
            Decode(ref error) => {
                write!(fmt, "failed to decode proto message: {}", error)
            }
        }
    }
}

impl std::error::Error for ParseError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use ParseError::*;

        match *self {
            Malformed(ref error) => Some(error.as_ref()),
            Decode(ref error) => Some(error),
        }
    }
}

impl From<protobuf::ProtobufError> for ParseError {

    fn from(error: protobuf::ProtobufError) -> ParseError {
        ParseError::Decode(error)
    }
}

/// An error type for situations where required proto field is missing.
#[derive(Debug)]
pub struct MissingFieldError {
    /// A name of the missing field.
    name: &'static str,
}

impl MissingFieldError {

    /// Creates a new error indicating that required field `name` is missing.
    pub fn new(name: &'static str) -> MissingFieldError {
        MissingFieldError {
            name: name,
        }
    }
}

impl Display for MissingFieldError {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        write!(fmt, "required field '{}' is missing", self.name)
    }
}

impl std::error::Error for MissingFieldError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl From<MissingFieldError> for ParseError {

    fn from(error: MissingFieldError) -> ParseError {
        ParseError::malformed(error)
    }
}

/// An error type for situations where a given proto value is not supported.
#[derive(Debug)]
pub struct UnsupportedValueError<T> {
    /// A name of the field the value belongs to.
    pub name: &'static str,
    /// A value that is not supported.
    pub value: T,
}

impl<T: Debug> Display for UnsupportedValueError<T> {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        write!(fmt, "unsupported value for '{}': {:?}", self.name, self.value)
    }
}

impl<T: Debug> std::error::Error for UnsupportedValueError<T> {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

/// An error type for situations where time micros cannot be converted
/// to `std::time::SystemTime`.
#[derive(Debug)]
pub struct TimeMicrosConversionError {
    /// Time micros value causing the conversion error.
    pub micros: u64,
}

impl Display for TimeMicrosConversionError {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        write!(fmt, "cannot convert micros to std::time::SystemTime: {}", self.micros)
    }
}

impl std::error::Error for TimeMicrosConversionError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl From<TimeMicrosConversionError> for ParseError {

    fn from(error: TimeMicrosConversionError) -> ParseError {
        ParseError::malformed(error)
    }
}

#[derive(Debug)]
pub struct RegexParseError {
    /// Raw data of the string which could not be converted to Regex.
    pub raw_data: Vec<u8>,
    /// Error message caught during the conversion.
    pub error: RegexError,
}

impl Display for RegexParseError {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        write!(fmt, "Regex parse error happened on parsing '{:?}'. \
                     Regex error: '{}'",
               self.raw_data,
               self.error.to_string())
    }
}

impl std::error::Error for RegexParseError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl From<RegexParseError> for ParseError {

    fn from(error: RegexParseError) -> ParseError {
        ParseError::malformed(error)
    }
}

/// An error type for situations where proto enum has a value for which
/// the definition is not known.
#[derive(Debug)]
pub struct UnknownEnumValueError {
    /// A name of the enum field having unknown enum value.
    pub name: &'static str,

    /// An enum value, which definition is not known.
    pub value: i32,
}

impl Display for UnknownEnumValueError {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        write!(fmt, "protobuf enum '{}' has unrecognised value: '{}'",
               self.name, self.value)
    }
}

impl std::error::Error for UnknownEnumValueError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl From<UnknownEnumValueError> for ParseError {

    fn from(error: UnknownEnumValueError) -> ParseError {
        ParseError::malformed(error)
    }
}
<|endoftext|>


<commit_before>// Using structs to represent 2D points
// and calculating the Euclidean distance between them

struct Point {
    x: f64,
    y: f64,
}

mod pointutils {
    pub fn euclidean(point_a: Point, point_b: Point) {
        0.0

    }

}

fn main() {
    let point_a: Point = Point { x: 0.3, y: 20.0 };
    let point_b: Point = Point { x: 4.0, y: -0.03 };

    let euclidean_distance = pointutils::euclidean(point_a, point_b);
    println!("Found distance: ", euclidean_distance);

}
<commit_msg>Encapsulate the struct and function in a mod<commit_after>// Using structs to represent 2D points
// and calculating the Euclidean distance between them

mod pointutils {

    pub struct Point {
        pub x: f64,
        pub y: f64,
    }

    pub fn euclidean(point_a: Point, point_b: Point) -> f64 {
        0.0

    }
}

fn main() {
    let point_a: pointutils::Point = pointutils::Point { x: 0.3, y: 20.0 };
    let point_b: pointutils::Point = pointutils::Point { x: 4.0, y: -0.03 };

    let euclidean_distance = pointutils::euclidean(point_a, point_b);
    // let euclidean_distance = euclidean(point_a, point_b);
    println!("Found distance: {}", euclidean_distance);

}
<|endoftext|>


<commit_before>//! The Rust Prelude.
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particularly traits, which are used in almost every single Rust
//! program.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: crate::io::prelude
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and re-exports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The
//!   marker traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//!   operations for both destructors and overloading `()`.
//! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly
//!   dropping a value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//!   [`to_owned`], the generic method for creating an owned type from a
//!   borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines
//!   [`clone`][`Clone::clone`], the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//!   comparison traits, which implement the comparison operators and are often
//!   seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//!   conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//!   [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//!   kinds.
//! * [`std::option`]::[`Option`]::{[`self`][`Option`], [`Some`], [`None`]}. A
//!   type which expresses the presence or absence of a value. This type is so
//!   commonly used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{[`self`][`Result`], [`Ok`], [`Err`]}. A type
//!   for functions that may succeed or fail. Like [`Option`], its variants are
//!   exported as well.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`], a growable, heap-allocated
//!   vector.
//!
//! [`mem::drop`]: crate::mem::drop
//! [`std::borrow`]: crate::borrow
//! [`std::boxed`]: crate::boxed
//! [`std::clone`]: crate::clone
//! [`std::cmp`]: crate::cmp
//! [`std::convert`]: crate::convert
//! [`std::default`]: crate::default
//! [`std::iter`]: crate::iter
//! [`std::marker`]: crate::marker
//! [`std::mem`]: crate::mem
//! [`std::ops`]: crate::ops
//! [`std::option`]: crate::option
//! [`std::prelude::v1`]: v1
//! [`std::result`]: crate::result
//! [`std::slice`]: crate::slice
//! [`std::string`]: crate::string
//! [`std::vec`]: crate::vec!
//! [`to_owned`]: crate::borrow::ToOwned::to_owned
//! [book-closures]: ../../book/ch13-01-closures.html
//! [book-dtor]: ../../book/ch15-03-drop.html
//! [book-enums]: ../../book/ch06-01-defining-an-enum.html
//! [book-iter]: ../../book/ch13-02-iterators.html

#![stable(feature = "rust1", since = "1.0.0")]

pub mod v1;
<commit_msg>Fix incorrect link in prelude<commit_after>//! The Rust Prelude.
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particularly traits, which are used in almost every single Rust
//! program.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: crate::io::prelude
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and re-exports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The
//!   marker traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//!   operations for both destructors and overloading `()`.
//! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly
//!   dropping a value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//!   [`to_owned`], the generic method for creating an owned type from a
//!   borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines
//!   [`clone`][`Clone::clone`], the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//!   comparison traits, which implement the comparison operators and are often
//!   seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//!   conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//!   [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//!   kinds.
//! * [`std::option`]::[`Option`]::{[`self`][`Option`], [`Some`], [`None`]}. A
//!   type which expresses the presence or absence of a value. This type is so
//!   commonly used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{[`self`][`Result`], [`Ok`], [`Err`]}. A type
//!   for functions that may succeed or fail. Like [`Option`], its variants are
//!   exported as well.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`], a growable, heap-allocated
//!   vector.
//!
//! [`mem::drop`]: crate::mem::drop
//! [`std::borrow`]: crate::borrow
//! [`std::boxed`]: crate::boxed
//! [`std::clone`]: crate::clone
//! [`std::cmp`]: crate::cmp
//! [`std::convert`]: crate::convert
//! [`std::default`]: crate::default
//! [`std::iter`]: crate::iter
//! [`std::marker`]: crate::marker
//! [`std::mem`]: crate::mem
//! [`std::ops`]: crate::ops
//! [`std::option`]: crate::option
//! [`std::prelude::v1`]: v1
//! [`std::result`]: crate::result
//! [`std::slice`]: crate::slice
//! [`std::string`]: crate::string
//! [`std::vec`]: mod@crate::vec
//! [`to_owned`]: crate::borrow::ToOwned::to_owned
//! [book-closures]: ../../book/ch13-01-closures.html
//! [book-dtor]: ../../book/ch15-03-drop.html
//! [book-enums]: ../../book/ch06-01-defining-an-enum.html
//! [book-iter]: ../../book/ch13-02-iterators.html

#![stable(feature = "rust1", since = "1.0.0")]

pub mod v1;
<|endoftext|>


<commit_before>//! Endpoints for managing room aliases.

use iron::{Chain, Handler, IronResult, Request, Response};
use iron::status::Status;
use router::Router;

use db::DB;
use error::APIError;
use middleware::{AccessTokenAuth, JsonRequest};
use modifier::SerializableResponse;
use room_alias::RoomAlias;

#[derive(Debug, Serialize)]
struct GetDirectoryRoomResponse {
    room_id: String,
    servers: Vec<String>,
}

/// The /directory/room/{roomAlias} endpoint when using the GET method.
pub struct GetDirectoryRoom;

impl GetDirectoryRoom {
    /// Create a `DirectoryRoom`.
    pub fn chain() -> Chain {
        Chain::new(GetDirectoryRoom)
    }
}

impl Handler for GetDirectoryRoom {
    fn handle(&self, request: &mut Request) -> IronResult<Response> {
        let params = request.extensions.get::<Router>().expect("Params object is missing").clone();

        let room_alias_name = params.find("room_alias").ok_or(APIError::not_found())?;

        let connection = DB::from_request(request)?;

        let room_alias = RoomAlias::find_by_alias(&connection, room_alias_name)?;

        let response = GetDirectoryRoomResponse {
            room_id: room_alias.room_id,
            servers: room_alias.servers,
        };

        Ok(Response::with((Status::Ok, SerializableResponse(response))))
    }
}

#[cfg(test)]
mod tests {
    use test::Test;
    use iron::status::Status;

    #[test]
    fn get_room_alias() {
        let test = Test::new();
        let access_token = test.create_access_token();

        let create_room_path = format!("/_matrix/client/r0/createRoom?access_token={}",
                                       access_token);
        let response = test.post(&create_room_path, r#"{"room_alias_name": "my_room"}"#);
        let room_id = response.json().find("room_id").unwrap().as_string();

        let get_room_alias_path = format!(
            "/_matrix/client/r0/directory/room/my_room?access_token={}", access_token
        );
        let response = test.get(&get_room_alias_path);

        assert_eq!(response.json().find("room_id").unwrap().as_string(), room_id);
        assert!(response.json().find("servers").unwrap().is_array());
    }

    #[test]
    fn get_unknown_room_alias() {
        let test = Test::new();
        let access_token = test.create_access_token();

        let create_room_path = format!("/_matrix/client/r0/createRoom?access_token={}",
                                       access_token);
        let _ = test.post(&create_room_path, r#"{"room_alias_name": "my_room"}"#);

        let get_room_alias_path = format!(
            "/_matrix/client/r0/directory/room/no_room?access_token={}", access_token
        );
        let response = test.get(&get_room_alias_path);

        assert_eq!(response.status, Status::NotFound);
        assert_eq!(
            response.json().find("errcode").unwrap().as_string().unwrap(),
            "M_NOT_FOUND"
        );
    }
}
<commit_msg>Add middleware to GetDirectoryRoom chain.<commit_after>//! Endpoints for managing room aliases.

use iron::{Chain, Handler, IronResult, Request, Response};
use iron::status::Status;
use router::Router;

use db::DB;
use error::APIError;
use middleware::AccessTokenAuth;
use modifier::SerializableResponse;
use room_alias::RoomAlias;

#[derive(Debug, Serialize)]
struct GetDirectoryRoomResponse {
    room_id: String,
    servers: Vec<String>,
}

/// The /directory/room/{roomAlias} endpoint when using the GET method.
pub struct GetDirectoryRoom;

impl GetDirectoryRoom {
    /// Create a `DirectoryRoom`.
    pub fn chain() -> Chain {
        let mut chain = Chain::new(GetDirectoryRoom);

        chain.link_before(AccessTokenAuth);

        chain
    }
}

impl Handler for GetDirectoryRoom {
    fn handle(&self, request: &mut Request) -> IronResult<Response> {
        let params = request.extensions.get::<Router>().expect("Params object is missing").clone();

        let room_alias_name = params.find("room_alias").ok_or(APIError::not_found())?;

        let connection = DB::from_request(request)?;

        let room_alias = RoomAlias::find_by_alias(&connection, room_alias_name)?;

        let response = GetDirectoryRoomResponse {
            room_id: room_alias.room_id,
            servers: room_alias.servers,
        };

        Ok(Response::with((Status::Ok, SerializableResponse(response))))
    }
}

#[cfg(test)]
mod tests {
    use test::Test;
    use iron::status::Status;

    #[test]
    fn get_room_alias() {
        let test = Test::new();
        let access_token = test.create_access_token();

        let create_room_path = format!("/_matrix/client/r0/createRoom?access_token={}",
                                       access_token);
        let response = test.post(&create_room_path, r#"{"room_alias_name": "my_room"}"#);
        let room_id = response.json().find("room_id").unwrap().as_string();

        let get_room_alias_path = format!(
            "/_matrix/client/r0/directory/room/my_room?access_token={}", access_token
        );
        let response = test.get(&get_room_alias_path);

        assert_eq!(response.json().find("room_id").unwrap().as_string(), room_id);
        assert!(response.json().find("servers").unwrap().is_array());
    }

    #[test]
    fn get_unknown_room_alias() {
        let test = Test::new();
        let access_token = test.create_access_token();

        let create_room_path = format!("/_matrix/client/r0/createRoom?access_token={}",
                                       access_token);
        let _ = test.post(&create_room_path, r#"{"room_alias_name": "my_room"}"#);

        let get_room_alias_path = format!(
            "/_matrix/client/r0/directory/room/no_room?access_token={}", access_token
        );
        let response = test.get(&get_room_alias_path);

        assert_eq!(response.status, Status::NotFound);
        assert_eq!(
            response.json().find("errcode").unwrap().as_string().unwrap(),
            "M_NOT_FOUND"
        );
    }
}
<|endoftext|>