<commit_before>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use types::Type;
use types::StaticType;
use ffi as glib_ffi;
use translate::*;
use std::borrow::{Borrow, Cow, ToOwned};
use std::cmp::{PartialEq, Eq};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::slice;
use value::{Value, ToValue, SetValue, FromValueOptional};
use gobject_ffi;

/// Describes `Variant` types.
///
/// The `Variant` type system (based on the D-Bus one) describes types with
/// "type strings". `VariantType` is an owned immutable type string (you can
/// think of it as a `Box<str>` statically guaranteed to be a valid type
/// string), `&VariantTy` is a borrowed one (like `&str`).
pub struct VariantType {
    // GVariantType* essentially is a char*, that always is valid UTF-8 but
    // isn't NUL-terminated.
    ptr: *mut glib_ffi::GVariantType,
    // We query the length on creation assuming it's cheap (because type strings
    // are short) and likely to happen anyway.
    len: usize,
}

impl VariantType {
    /// Tries to create a `VariantType` from a string slice.
    ///
    /// Returns `Ok` if the string is a valid type string, `Err` otherwise.
    pub fn new(type_string: &str) -> Result<VariantType, ()> {
        VariantTy::new(type_string).map(ToOwned::to_owned)
    }
}

unsafe impl Send for VariantType { }
unsafe impl Sync for VariantType { }

impl Drop for VariantType {
    fn drop(&mut self) {
        unsafe { glib_ffi::g_variant_type_free(self.ptr) }
    }
}

impl Borrow<VariantTy> for VariantType {
    fn borrow(&self) -> &VariantTy {
        self
    }
}

impl Clone for VariantType {
    fn clone(&self) -> VariantType {
        unsafe {
            VariantType {
                ptr: glib_ffi::g_variant_type_copy(self.ptr),
                len: self.len,
            }
        }
    }
}

impl Deref for VariantType {
    type Target = VariantTy;
    fn deref(&self) -> &VariantTy {
        unsafe {
            &*(slice::from_raw_parts(self.ptr as *const u8, self.len) as *const [u8] as *const VariantTy)
        }
    }
}

impl fmt::Debug for VariantType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        <VariantTy as fmt::Debug>::fmt(self, f)
    }
}

impl fmt::Display for VariantType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.to_str())
    }
}

impl Hash for VariantType {
    fn hash<H: Hasher>(&self, state: &mut H) {
        <VariantTy as Hash>::hash(self, state)
    }
}

impl<'a> Into<Cow<'a, VariantTy>> for VariantType {
    fn into(self) -> Cow<'a, VariantTy> {
        Cow::Owned(self)
    }
}

#[doc(hidden)]
impl<'a> ToGlibPtrMut<'a, *mut glib_ffi::GVariantType> for VariantType {
    type Storage = &'a mut Self;

    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut glib_ffi::GVariantType, Self> {
        StashMut(self.ptr, self)
    }
}

#[doc(hidden)]
impl FromGlibPtrNone<*const glib_ffi::GVariantType> for VariantType {
    unsafe fn from_glib_none(ptr: *const glib_ffi::GVariantType) -> VariantType {
        VariantTy::from_ptr(ptr).to_owned()
    }
}

#[doc(hidden)]
impl FromGlibPtrFull<*const glib_ffi::GVariantType> for VariantType {
    unsafe fn from_glib_full(ptr: *const glib_ffi::GVariantType) -> VariantType {
        // Don't assume ownership of a const pointer.
        // A transfer: full annotation on a `const GVariantType*` is likely a bug.
        VariantTy::from_ptr(ptr).to_owned()
    }
}

/// Describes `Variant` types.
///
/// This is a borrowed counterpart of [`VariantType`](struct.VariantType.html).
/// Essentially it's a `str` statically guaranteed to be a valid type string.
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct VariantTy {
    inner: str,
}

impl VariantTy {
    /// Tries to create a `&VariantTy` from a string slice.
    ///
    /// Returns `Ok` if the string is a valid type string, `Err` otherwise.
    pub fn new(type_string: &str) -> Result<&VariantTy, ()> {
        let ptr = type_string.as_ptr();
        let limit = ptr as usize + type_string.len();
        let mut end = 0_usize;
        unsafe {
            let ok = from_glib(glib_ffi::g_variant_type_string_scan(ptr as *const _,
                limit as *const _, &mut end as *mut usize as *mut _));
            if ok && end == limit {
                Ok(&*(type_string.as_bytes() as *const [u8] as *const VariantTy))
            } else {
                Err(())
            }
        }
    }

    /// Converts a type string into `&VariantTy` without any checks.
    pub unsafe fn from_str_unchecked(type_string: &str) -> &VariantTy {
        &*(type_string as *const str as *const VariantTy)
    }

    /// Creates `&VariantTy` with a wildcard lifetime from a `GVariantType`
    /// pointer.
    #[doc(hidden)]
    pub unsafe fn from_ptr<'a>(ptr: *const glib_ffi::GVariantType) -> &'a VariantTy {
        let len = glib_ffi::g_variant_type_get_string_length(ptr) as usize;
        &*(slice::from_raw_parts(ptr as *const u8, len) as *const [u8] as *const VariantTy)
    }

    /// Returns a `GVariantType` pointer.
    #[doc(hidden)]
    pub fn as_ptr(&self) -> *const glib_ffi::GVariantType {
        self.inner.as_ptr() as *const _
    }

    /// Converts to a string slice.
    pub fn to_str(&self) -> &str {
        &self.inner
    }
}

unsafe impl Sync for VariantTy { }

#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *const glib_ffi::GVariantType> for VariantTy {
    type Storage = &'a Self;

    fn to_glib_none(&'a self) -> Stash<'a, *const glib_ffi::GVariantType, Self> {
        Stash(self.as_ptr(), self)
    }
}

impl fmt::Display for VariantTy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.to_str())
    }
}

impl<'a> Into<Cow<'a, VariantTy>> for &'a VariantTy {
    fn into(self) -> Cow<'a, VariantTy> {
        Cow::Borrowed(self)
    }
}

impl ToOwned for VariantTy {
    type Owned = VariantType;

    fn to_owned(&self) -> VariantType {
        unsafe {
            VariantType {
                ptr: glib_ffi::g_variant_type_copy(self.as_ptr()),
                len: self.inner.len(),
            }
        }
    }
}

impl StaticType for VariantTy {
    fn static_type() -> Type {
        unsafe { from_glib(glib_ffi::g_variant_type_get_gtype()) }
    }
}

impl SetValue for VariantTy {
    unsafe fn set_value(value: &mut Value, this: &Self) {
        gobject_ffi::g_value_set_boxed(value.to_glib_none_mut().0, this.to_glib_none().0 as glib_ffi::gpointer)
    }
}

impl StaticType for VariantType {
    fn static_type() -> Type {
        unsafe { from_glib(glib_ffi::g_variant_type_get_gtype()) }
    }
}

impl SetValue for VariantType {
    unsafe fn set_value(value: &mut Value, this: &Self) {
        gobject_ffi::g_value_set_boxed(value.to_glib_none_mut().0, this.to_glib_none().0 as glib_ffi::gpointer)
    }
}

impl<'a> FromValueOptional<'a> for VariantType {
    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
        Option::<VariantType>::from_glib_full(gobject_ffi::g_value_dup_boxed(value.to_glib_none().0) as *mut glib_ffi::GVariantType)
    }
}

impl PartialEq for VariantType {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        <VariantTy as PartialEq>::eq(self, other)
    }
}

macro_rules! impl_eq {
    ($lhs:ty, $rhs: ty) => {
        impl<'a, 'b> PartialEq<$rhs> for $lhs {
            #[inline]
            fn eq(&self, other: &$rhs) -> bool {
                <VariantTy as PartialEq>::eq(self, other)
            }
        }

        impl<'a, 'b> PartialEq<$lhs> for $rhs {
            #[inline]
            fn eq(&self, other: &$lhs) -> bool {
                <VariantTy as PartialEq>::eq(self, other)
            }
        }
    }
}

impl_eq!(VariantType, VariantTy);
impl_eq!(VariantType, &'a VariantTy);
impl_eq!(VariantType, Cow<'a, VariantTy>);
impl_eq!(&'a VariantTy, Cow<'b, VariantTy>);

macro_rules! impl_str_eq {
    ($lhs:ty, $rhs: ty) => {
        impl<'a, 'b> PartialEq<$rhs> for $lhs {
            #[inline]
            fn eq(&self, other: &$rhs) -> bool {
                self.to_str().eq(&other[..])
            }
        }

        impl<'a, 'b> PartialEq<$lhs> for $rhs {
            #[inline]
            fn eq(&self, other: &$lhs) -> bool {
                self[..].eq(other.to_str())
            }
        }
    }
}

impl_str_eq!(VariantTy, str);
impl_str_eq!(VariantTy, &'a str);
impl_str_eq!(&'a VariantTy, str);
impl_str_eq!(VariantTy, String);
impl_str_eq!(&'a VariantTy, String);
impl_str_eq!(VariantType, str);
impl_str_eq!(VariantType, &'a str);
impl_str_eq!(VariantType, String);

impl Eq for VariantType { }

#[cfg(test)]
mod tests {
    use ffi as glib_ffi;
    use translate::*;
    use super::*;

    unsafe fn equal<T, U>(ptr1: *const T, ptr2: *const U) -> bool {
        from_glib(glib_ffi::g_variant_type_equal(ptr1 as *const _, ptr2 as *const _))
    }

    #[test]
    fn new() {
        let ty = VariantTy::new("((iii)s)").unwrap();
        unsafe {
            assert!(equal(ty.as_ptr(), b"((iii)s)\0" as *const u8));
        }
    }

    #[test]
    fn new_empty() {
        assert!(VariantTy::new("").is_err());
    }

    #[test]
    fn new_with_nul() {
        assert!(VariantTy::new("((iii\0)s)").is_err());
    }

    #[test]
    fn new_too_short() {
        assert!(VariantTy::new("((iii").is_err());
    }

    #[test]
    fn new_too_long() {
        assert!(VariantTy::new("(iii)s").is_err());
    }

    #[test]
    fn eq() {
        let ty1 = VariantTy::new("((iii)s)").unwrap();
        let ty2 = VariantTy::new("((iii)s)").unwrap();
        assert_eq!(ty1, ty2);
        assert_eq!(ty1, "((iii)s)");
        unsafe {
            assert!(equal(ty1.as_ptr(), ty2.as_ptr()));
        }
    }

    #[test]
    fn ne() {
        let ty1 = VariantTy::new("((iii)s)").unwrap();
        let ty2 = VariantTy::new("((iii)o)").unwrap();
        assert!(ty1 != ty2);
        assert!(ty1 != "((iii)o)");
        unsafe {
            assert!(!equal(ty1.as_ptr(), ty2.as_ptr()));
        }
    }

    #[test]
    fn from_bytes() {
        unsafe {
            let ty = VariantTy::from_ptr(b"((iii)s)" as *const u8 as *const _);
            assert_eq!(ty, "((iii)s)");
            assert!(equal(ty.as_ptr(), "((iii)s)".as_ptr()));
        }
    }

    #[test]
    fn to_owned() {
        let ty1 = VariantTy::new("((iii)s)").unwrap();
        let ty2 = ty1.to_owned();
        assert_eq!(ty1, ty2);
        assert_eq!(ty2, "((iii)s)");
        unsafe {
            assert!(equal(ty1.as_ptr(), ty2.as_ptr()));
        }
    }

    #[test]
    fn value() {
        let ty1 = VariantType::new("*").unwrap();
        let tyv = ty1.to_value();
        let ty2 = tyv.get::<VariantType>().unwrap();
        assert_eq!(ty1, ty2);
    }

}
<commit_msg>add FromValue conversion for VariantTy<commit_after>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use types::Type;
use types::StaticType;
use ffi as glib_ffi;
use translate::*;
use std::borrow::{Borrow, Cow, ToOwned};
use std::cmp::{PartialEq, Eq};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::slice;
use value::{Value, ToValue, SetValue, FromValueOptional};
use gobject_ffi;

/// Describes `Variant` types.
///
/// The `Variant` type system (based on the D-Bus one) describes types with
/// "type strings". `VariantType` is an owned immutable type string (you can
/// think of it as a `Box<str>` statically guaranteed to be a valid type
/// string), `&VariantTy` is a borrowed one (like `&str`).
pub struct VariantType {
    // GVariantType* essentially is a char*, that always is valid UTF-8 but
    // isn't NUL-terminated.
    ptr: *mut glib_ffi::GVariantType,
    // We query the length on creation assuming it's cheap (because type strings
    // are short) and likely to happen anyway.
    len: usize,
}

impl VariantType {
    /// Tries to create a `VariantType` from a string slice.
    ///
    /// Returns `Ok` if the string is a valid type string, `Err` otherwise.
    pub fn new(type_string: &str) -> Result<VariantType, ()> {
        VariantTy::new(type_string).map(ToOwned::to_owned)
    }
}

unsafe impl Send for VariantType { }
unsafe impl Sync for VariantType { }

impl Drop for VariantType {
    fn drop(&mut self) {
        unsafe { glib_ffi::g_variant_type_free(self.ptr) }
    }
}

impl Borrow<VariantTy> for VariantType {
    fn borrow(&self) -> &VariantTy {
        self
    }
}

impl Clone for VariantType {
    fn clone(&self) -> VariantType {
        unsafe {
            VariantType {
                ptr: glib_ffi::g_variant_type_copy(self.ptr),
                len: self.len,
            }
        }
    }
}

impl Deref for VariantType {
    type Target = VariantTy;
    fn deref(&self) -> &VariantTy {
        unsafe {
            &*(slice::from_raw_parts(self.ptr as *const u8, self.len) as *const [u8] as *const VariantTy)
        }
    }
}

impl fmt::Debug for VariantType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        <VariantTy as fmt::Debug>::fmt(self, f)
    }
}

impl fmt::Display for VariantType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.to_str())
    }
}

impl Hash for VariantType {
    fn hash<H: Hasher>(&self, state: &mut H) {
        <VariantTy as Hash>::hash(self, state)
    }
}

impl<'a> Into<Cow<'a, VariantTy>> for VariantType {
    fn into(self) -> Cow<'a, VariantTy> {
        Cow::Owned(self)
    }
}

#[doc(hidden)]
impl<'a> ToGlibPtrMut<'a, *mut glib_ffi::GVariantType> for VariantType {
    type Storage = &'a mut Self;

    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut glib_ffi::GVariantType, Self> {
        StashMut(self.ptr, self)
    }
}

#[doc(hidden)]
impl FromGlibPtrNone<*const glib_ffi::GVariantType> for VariantType {
    unsafe fn from_glib_none(ptr: *const glib_ffi::GVariantType) -> VariantType {
        VariantTy::from_ptr(ptr).to_owned()
    }
}

#[doc(hidden)]
impl FromGlibPtrFull<*const glib_ffi::GVariantType> for VariantType {
    unsafe fn from_glib_full(ptr: *const glib_ffi::GVariantType) -> VariantType {
        // Don't assume ownership of a const pointer.
        // A transfer: full annotation on a `const GVariantType*` is likely a bug.
        VariantTy::from_ptr(ptr).to_owned()
    }
}

/// Describes `Variant` types.
///
/// This is a borrowed counterpart of [`VariantType`](struct.VariantType.html).
/// Essentially it's a `str` statically guaranteed to be a valid type string.
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct VariantTy {
    inner: str,
}

impl VariantTy {
    /// Tries to create a `&VariantTy` from a string slice.
    ///
    /// Returns `Ok` if the string is a valid type string, `Err` otherwise.
    pub fn new(type_string: &str) -> Result<&VariantTy, ()> {
        let ptr = type_string.as_ptr();
        let limit = ptr as usize + type_string.len();
        let mut end = 0_usize;
        unsafe {
            let ok = from_glib(glib_ffi::g_variant_type_string_scan(ptr as *const _,
                limit as *const _, &mut end as *mut usize as *mut _));
            if ok && end == limit {
                Ok(&*(type_string.as_bytes() as *const [u8] as *const VariantTy))
            } else {
                Err(())
            }
        }
    }

    /// Converts a type string into `&VariantTy` without any checks.
    pub unsafe fn from_str_unchecked(type_string: &str) -> &VariantTy {
        &*(type_string as *const str as *const VariantTy)
    }

    /// Creates `&VariantTy` with a wildcard lifetime from a `GVariantType`
    /// pointer.
    #[doc(hidden)]
    pub unsafe fn from_ptr<'a>(ptr: *const glib_ffi::GVariantType) -> &'a VariantTy {
        let len = glib_ffi::g_variant_type_get_string_length(ptr) as usize;
        &*(slice::from_raw_parts(ptr as *const u8, len) as *const [u8] as *const VariantTy)
    }

    /// Returns a `GVariantType` pointer.
    #[doc(hidden)]
    pub fn as_ptr(&self) -> *const glib_ffi::GVariantType {
        self.inner.as_ptr() as *const _
    }

    /// Converts to a string slice.
    pub fn to_str(&self) -> &str {
        &self.inner
    }
}

unsafe impl Sync for VariantTy { }

#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *const glib_ffi::GVariantType> for VariantTy {
    type Storage = &'a Self;

    fn to_glib_none(&'a self) -> Stash<'a, *const glib_ffi::GVariantType, Self> {
        Stash(self.as_ptr(), self)
    }
}

impl fmt::Display for VariantTy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.to_str())
    }
}

impl<'a> Into<Cow<'a, VariantTy>> for &'a VariantTy {
    fn into(self) -> Cow<'a, VariantTy> {
        Cow::Borrowed(self)
    }
}

impl ToOwned for VariantTy {
    type Owned = VariantType;

    fn to_owned(&self) -> VariantType {
        unsafe {
            VariantType {
                ptr: glib_ffi::g_variant_type_copy(self.as_ptr()),
                len: self.inner.len(),
            }
        }
    }
}

impl StaticType for VariantTy {
    fn static_type() -> Type {
        unsafe { from_glib(glib_ffi::g_variant_type_get_gtype()) }
    }
}

impl SetValue for VariantTy {
    unsafe fn set_value(value: &mut Value, this: &Self) {
        gobject_ffi::g_value_set_boxed(value.to_glib_none_mut().0, this.to_glib_none().0 as glib_ffi::gpointer)
    }
}

impl<'a> FromValueOptional<'a> for &'a VariantTy {
    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
        let cvty = gobject_ffi::g_value_dup_boxed(value.to_glib_none().0) as *mut glib_ffi::GVariantType;
        if cvty.is_null() {
            None
        } else {
            Some(VariantTy::from_ptr(cvty))
        }
    }
}

impl StaticType for VariantType {
    fn static_type() -> Type {
        unsafe { from_glib(glib_ffi::g_variant_type_get_gtype()) }
    }
}

impl SetValue for VariantType {
    unsafe fn set_value(value: &mut Value, this: &Self) {
        gobject_ffi::g_value_set_boxed(value.to_glib_none_mut().0, this.to_glib_none().0 as glib_ffi::gpointer)
    }
}

impl<'a> FromValueOptional<'a> for VariantType {
    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
        Option::<VariantType>::from_glib_full(gobject_ffi::g_value_dup_boxed(value.to_glib_none().0) as *mut glib_ffi::GVariantType)
    }
}

impl PartialEq for VariantType {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        <VariantTy as PartialEq>::eq(self, other)
    }
}

macro_rules! impl_eq {
    ($lhs:ty, $rhs: ty) => {
        impl<'a, 'b> PartialEq<$rhs> for $lhs {
            #[inline]
            fn eq(&self, other: &$rhs) -> bool {
                <VariantTy as PartialEq>::eq(self, other)
            }
        }

        impl<'a, 'b> PartialEq<$lhs> for $rhs {
            #[inline]
            fn eq(&self, other: &$lhs) -> bool {
                <VariantTy as PartialEq>::eq(self, other)
            }
        }
    }
}

impl_eq!(VariantType, VariantTy);
impl_eq!(VariantType, &'a VariantTy);
impl_eq!(VariantType, Cow<'a, VariantTy>);
impl_eq!(&'a VariantTy, Cow<'b, VariantTy>);

macro_rules! impl_str_eq {
    ($lhs:ty, $rhs: ty) => {
        impl<'a, 'b> PartialEq<$rhs> for $lhs {
            #[inline]
            fn eq(&self, other: &$rhs) -> bool {
                self.to_str().eq(&other[..])
            }
        }

        impl<'a, 'b> PartialEq<$lhs> for $rhs {
            #[inline]
            fn eq(&self, other: &$lhs) -> bool {
                self[..].eq(other.to_str())
            }
        }
    }
}

impl_str_eq!(VariantTy, str);
impl_str_eq!(VariantTy, &'a str);
impl_str_eq!(&'a VariantTy, str);
impl_str_eq!(VariantTy, String);
impl_str_eq!(&'a VariantTy, String);
impl_str_eq!(VariantType, str);
impl_str_eq!(VariantType, &'a str);
impl_str_eq!(VariantType, String);

impl Eq for VariantType { }

#[cfg(test)]
mod tests {
    use ffi as glib_ffi;
    use translate::*;
    use super::*;

    unsafe fn equal<T, U>(ptr1: *const T, ptr2: *const U) -> bool {
        from_glib(glib_ffi::g_variant_type_equal(ptr1 as *const _, ptr2 as *const _))
    }

    #[test]
    fn new() {
        let ty = VariantTy::new("((iii)s)").unwrap();
        unsafe {
            assert!(equal(ty.as_ptr(), b"((iii)s)\0" as *const u8));
        }
    }

    #[test]
    fn new_empty() {
        assert!(VariantTy::new("").is_err());
    }

    #[test]
    fn new_with_nul() {
        assert!(VariantTy::new("((iii\0)s)").is_err());
    }

    #[test]
    fn new_too_short() {
        assert!(VariantTy::new("((iii").is_err());
    }

    #[test]
    fn new_too_long() {
        assert!(VariantTy::new("(iii)s").is_err());
    }

    #[test]
    fn eq() {
        let ty1 = VariantTy::new("((iii)s)").unwrap();
        let ty2 = VariantTy::new("((iii)s)").unwrap();
        assert_eq!(ty1, ty2);
        assert_eq!(ty1, "((iii)s)");
        unsafe {
            assert!(equal(ty1.as_ptr(), ty2.as_ptr()));
        }
    }

    #[test]
    fn ne() {
        let ty1 = VariantTy::new("((iii)s)").unwrap();
        let ty2 = VariantTy::new("((iii)o)").unwrap();
        assert!(ty1 != ty2);
        assert!(ty1 != "((iii)o)");
        unsafe {
            assert!(!equal(ty1.as_ptr(), ty2.as_ptr()));
        }
    }

    #[test]
    fn from_bytes() {
        unsafe {
            let ty = VariantTy::from_ptr(b"((iii)s)" as *const u8 as *const _);
            assert_eq!(ty, "((iii)s)");
            assert!(equal(ty.as_ptr(), "((iii)s)".as_ptr()));
        }
    }

    #[test]
    fn to_owned() {
        let ty1 = VariantTy::new("((iii)s)").unwrap();
        let ty2 = ty1.to_owned();
        assert_eq!(ty1, ty2);
        assert_eq!(ty2, "((iii)s)");
        unsafe {
            assert!(equal(ty1.as_ptr(), ty2.as_ptr()));
        }
    }

    #[test]
    fn value() {
        let ty1 = VariantType::new("*").unwrap();
        let tyv = ty1.to_value();
        let ty2 = tyv.get::<VariantType>().unwrap();
        assert_eq!(ty1, ty2);
    }

}
<|endoftext|>


<commit_before>use failure::*;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use wabt::wat2wasm;

pub fn read_module<P: AsRef<Path>>(path: P) -> Result<Vec<u8>, Error> {
    let contents = read_to_u8s(path)?;
    let converted = if wasm_preamble(&contents) {
        contents
    } else {
        wat2wasm(contents)?
    };
    Ok(converted)
}

pub fn read_to_u8s<P: AsRef<Path>>(path: P) -> Result<Vec<u8>, Error> {
    let mut buf: Vec<u8> = Vec::new();
    let mut file = File::open(path)?;
    file.read_to_end(&mut buf)?;
    Ok(buf)
}

pub fn wasm_preamble(buf: &[u8]) -> bool {
    if buf.len() > 4 {
        buf[0..4] == [0, 97, 115, 109]
    } else {
        false
    }
}
<commit_msg>lucetc: do not print the error returned by wat2wasm (#207)<commit_after>use crate::error::LucetcErrorKind;
use failure::*;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use wabt::wat2wasm;

pub fn read_module<P: AsRef<Path>>(path: P) -> Result<Vec<u8>, Error> {
    let contents = read_to_u8s(path)?;
    let converted = if wasm_preamble(&contents) {
        contents
    } else {
        wat2wasm(contents).map_err(|_| {
            format_err!("Input is neither valid WASM nor WAT").context(LucetcErrorKind::Input)
        })?
    };
    Ok(converted)
}

pub fn read_to_u8s<P: AsRef<Path>>(path: P) -> Result<Vec<u8>, Error> {
    let mut buf: Vec<u8> = Vec::new();
    let mut file = File::open(path)?;
    file.read_to_end(&mut buf)?;
    Ok(buf)
}

pub fn wasm_preamble(buf: &[u8]) -> bool {
    if buf.len() > 4 {
        buf[0..4] == [0, 97, 115, 109]
    } else {
        false
    }
}
<|endoftext|>


<commit_before>//! Layout tree.
//!
//! The idea is to take the DOM tree and produce a layout tree with SVG concepts.

use std::rc::Rc;

use crate::aspect_ratio::AspectRatio;
use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::dasharray::Dasharray;
use crate::document::AcquiredNodes;
use crate::element::Element;
use crate::length::*;
use crate::node::*;
use crate::paint_server::{PaintSource, UserSpacePaintSource};
use crate::path_builder::Path;
use crate::properties::{
    ClipRule, ComputedValues, Direction, FillRule, Filter, FontFamily, FontStretch, FontStyle,
    FontVariant, FontWeight, MixBlendMode, Opacity, Overflow, PaintOrder, ShapeRendering,
    StrokeDasharray, StrokeLinecap, StrokeLinejoin, StrokeMiterlimit, TextDecoration,
    TextRendering, UnicodeBidi, XmlLang,
};
use crate::rect::Rect;
use crate::surface_utils::shared_surface::SharedImageSurface;
use crate::transform::Transform;
use crate::unit_interval::UnitInterval;

/// SVG Stacking context, an inner node in the layout tree.
///
/// https://www.w3.org/TR/SVG2/render.html#EstablishingStackingContex
///
/// This is not strictly speaking an SVG2 stacking context, but a
/// looser version of it.  For example. the SVG spec mentions that a
/// an element should establish a stacking context if the `filter`
/// property applies to the element and is not `none`.  In that case,
/// the element is rendered as an "isolated group" -
/// https://www.w3.org/TR/2015/CR-compositing-1-20150113/#csscompositingrules_SVG
///
/// Here we store all the parameters that may lead to the decision to actually
/// render an element as an isolated group.
pub struct StackingContext {
    pub element_name: String,
    pub transform: Transform,
    pub opacity: Opacity,
    pub filter: Filter,
    pub clip_in_user_space: Option<Node>,
    pub clip_in_object_space: Option<Node>,
    pub mask: Option<Node>,
    pub mix_blend_mode: MixBlendMode,

    /// Target from an <a> element
    pub link_target: Option<String>,
}

/// Stroke parameters in user-space coordinates.
pub struct Stroke {
    pub width: f64,
    pub miter_limit: StrokeMiterlimit,
    pub line_cap: StrokeLinecap,
    pub line_join: StrokeLinejoin,
    pub dash_offset: f64,
    pub dashes: Box<[f64]>,
}

/// Paths and basic shapes resolved to a path.
///
/// Note that `stroke_paint` and `fill_paint` are not in user-space coordinates;
/// they are just resolved to a `PaintSource`.  Turning them to a `UserSpacePaintSource`
/// involves knowing the bounding box of the path.
pub struct Shape {
    pub path: Rc<Path>,
    pub is_visible: bool,
    pub paint_order: PaintOrder,
    pub stroke: Stroke,
    pub stroke_paint: PaintSource,
    pub fill_paint: PaintSource,
    pub fill_rule: FillRule,
    pub clip_rule: ClipRule,
    pub shape_rendering: ShapeRendering,
    pub marker_start: Marker,
    pub marker_mid: Marker,
    pub marker_end: Marker,
}

pub struct Marker {
    pub node_ref: Option<Node>,
    pub context_stroke: PaintSource,
    pub context_fill: PaintSource,
}

/// Image in user-space coordinates.
pub struct Image {
    pub surface: SharedImageSurface,
    pub is_visible: bool,
    pub rect: Rect,
    pub aspect: AspectRatio,
    pub overflow: Overflow,
}

/// A single text span in user-space coordinates.
pub struct TextSpan {
    pub layout: pango::Layout,
    pub gravity: pango::Gravity,
    pub bbox: Option<BoundingBox>,
    pub is_visible: bool,
    pub x: f64,
    pub y: f64,
    pub paint_order: PaintOrder,
    pub stroke: Stroke,
    pub stroke_paint: UserSpacePaintSource,
    pub fill_paint: UserSpacePaintSource,
    pub text_rendering: TextRendering,
    pub link_target: Option<String>,
}

/// Fully laid-out text in user-space coordinates.
pub struct Text {
    pub spans: Vec<TextSpan>,
}

/// Font-related properties extracted from `ComputedValues`.
pub struct FontProperties {
    pub xml_lang: XmlLang,
    pub unicode_bidi: UnicodeBidi,
    pub direction: Direction,
    pub font_family: FontFamily,
    pub font_style: FontStyle,
    pub font_variant: FontVariant,
    pub font_weight: FontWeight,
    pub font_stretch: FontStretch,
    pub font_size: f64,
    pub letter_spacing: f64,
    pub text_decoration: TextDecoration,
}

impl StackingContext {
    pub fn new(
        acquired_nodes: &mut AcquiredNodes<'_>,
        element: &Element,
        transform: Transform,
        values: &ComputedValues,
    ) -> StackingContext {
        let element_name = format!("{}", element);

        let opacity;
        let filter;

        match *element {
            // "The opacity, filter and display properties do not apply to the mask element"
            // https://drafts.fxtf.org/css-masking-1/#MaskElement
            Element::Mask(_) => {
                opacity = Opacity(UnitInterval::clamp(1.0));
                filter = Filter::None;
            }

            _ => {
                opacity = values.opacity();
                filter = values.filter();
            }
        }

        let clip_path = values.clip_path();
        let clip_uri = clip_path.0.get();
        let (clip_in_user_space, clip_in_object_space) = clip_uri
            .and_then(|node_id| {
                acquired_nodes
                    .acquire(node_id)
                    .ok()
                    .filter(|a| is_element_of_type!(*a.get(), ClipPath))
            })
            .map(|acquired| {
                let clip_node = acquired.get().clone();

                let units = borrow_element_as!(clip_node, ClipPath).get_units();

                match units {
                    CoordUnits::UserSpaceOnUse => (Some(clip_node), None),
                    CoordUnits::ObjectBoundingBox => (None, Some(clip_node)),
                }
            })
            .unwrap_or((None, None));

        let mask = values.mask().0.get().and_then(|mask_id| {
            if let Ok(acquired) = acquired_nodes.acquire(mask_id) {
                let node = acquired.get();
                match *node.borrow_element() {
                    Element::Mask(_) => Some(node.clone()),

                    _ => {
                        rsvg_log!(
                            "element {} references \"{}\" which is not a mask",
                            element,
                            mask_id
                        );

                        None
                    }
                }
            } else {
                rsvg_log!(
                    "element {} references nonexistent mask \"{}\"",
                    element,
                    mask_id
                );

                None
            }
        });

        let mix_blend_mode = values.mix_blend_mode();

        StackingContext {
            element_name,
            transform,
            opacity,
            filter,
            clip_in_user_space,
            clip_in_object_space,
            mask,
            mix_blend_mode,
            link_target: None,
        }
    }

    pub fn new_with_link(
        acquired_nodes: &mut AcquiredNodes<'_>,
        element: &Element,
        transform: Transform,
        values: &ComputedValues,
        link_target: Option<String>,
    ) -> StackingContext {
        let mut ctx = Self::new(acquired_nodes, element, transform, values);
        ctx.link_target = link_target;
        ctx
    }
}

impl Stroke {
    pub fn new(values: &ComputedValues, params: &NormalizeParams) -> Stroke {
        let width = values.stroke_width().0.to_user(params);
        let miter_limit = values.stroke_miterlimit();
        let line_cap = values.stroke_line_cap();
        let line_join = values.stroke_line_join();
        let dash_offset = values.stroke_dashoffset().0.to_user(params);

        let dashes = match values.stroke_dasharray() {
            StrokeDasharray(Dasharray::None) => Box::new([]),
            StrokeDasharray(Dasharray::Array(dashes)) => dashes
                .iter()
                .map(|l| l.to_user(params))
                .collect::<Box<[f64]>>(),
        };

        Stroke {
            width,
            miter_limit,
            line_cap,
            line_join,
            dash_offset,
            dashes,
        }
    }
}

impl FontProperties {
    /// Collects font properties from a `ComputedValues`.
    ///
    /// The `writing-mode` property is passed separately, as it must come from the `<text>` element,
    /// not the `<tspan>` whose computed values are being passed.
    pub fn new(values: &ComputedValues, params: &NormalizeParams) -> FontProperties {
        FontProperties {
            xml_lang: values.xml_lang(),
            unicode_bidi: values.unicode_bidi(),
            direction: values.direction(),
            font_family: values.font_family(),
            font_style: values.font_style(),
            font_variant: values.font_variant(),
            font_weight: values.font_weight(),
            font_stretch: values.font_stretch(),
            font_size: values.font_size().to_user(params),
            letter_spacing: values.letter_spacing().to_user(params),
            text_decoration: values.text_decoration(),
        }
    }
}
<commit_msg>StackingContext: carry the value of the isolation property here<commit_after>//! Layout tree.
//!
//! The idea is to take the DOM tree and produce a layout tree with SVG concepts.

use std::rc::Rc;

use crate::aspect_ratio::AspectRatio;
use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::dasharray::Dasharray;
use crate::document::AcquiredNodes;
use crate::element::Element;
use crate::length::*;
use crate::node::*;
use crate::paint_server::{PaintSource, UserSpacePaintSource};
use crate::path_builder::Path;
use crate::properties::{
    ClipRule, ComputedValues, Direction, FillRule, Filter, FontFamily, FontStretch, FontStyle,
    FontVariant, FontWeight, Isolation, MixBlendMode, Opacity, Overflow, PaintOrder,
    ShapeRendering, StrokeDasharray, StrokeLinecap, StrokeLinejoin, StrokeMiterlimit,
    TextDecoration, TextRendering, UnicodeBidi, XmlLang,
};
use crate::rect::Rect;
use crate::surface_utils::shared_surface::SharedImageSurface;
use crate::transform::Transform;
use crate::unit_interval::UnitInterval;

/// SVG Stacking context, an inner node in the layout tree.
///
/// https://www.w3.org/TR/SVG2/render.html#EstablishingStackingContex
///
/// This is not strictly speaking an SVG2 stacking context, but a
/// looser version of it.  For example. the SVG spec mentions that a
/// an element should establish a stacking context if the `filter`
/// property applies to the element and is not `none`.  In that case,
/// the element is rendered as an "isolated group" -
/// https://www.w3.org/TR/2015/CR-compositing-1-20150113/#csscompositingrules_SVG
///
/// Here we store all the parameters that may lead to the decision to actually
/// render an element as an isolated group.
pub struct StackingContext {
    pub element_name: String,
    pub transform: Transform,
    pub opacity: Opacity,
    pub filter: Filter,
    pub clip_in_user_space: Option<Node>,
    pub clip_in_object_space: Option<Node>,
    pub mask: Option<Node>,
    pub mix_blend_mode: MixBlendMode,
    pub isolation: Isolation,

    /// Target from an <a> element
    pub link_target: Option<String>,
}

/// Stroke parameters in user-space coordinates.
pub struct Stroke {
    pub width: f64,
    pub miter_limit: StrokeMiterlimit,
    pub line_cap: StrokeLinecap,
    pub line_join: StrokeLinejoin,
    pub dash_offset: f64,
    pub dashes: Box<[f64]>,
}

/// Paths and basic shapes resolved to a path.
///
/// Note that `stroke_paint` and `fill_paint` are not in user-space coordinates;
/// they are just resolved to a `PaintSource`.  Turning them to a `UserSpacePaintSource`
/// involves knowing the bounding box of the path.
pub struct Shape {
    pub path: Rc<Path>,
    pub is_visible: bool,
    pub paint_order: PaintOrder,
    pub stroke: Stroke,
    pub stroke_paint: PaintSource,
    pub fill_paint: PaintSource,
    pub fill_rule: FillRule,
    pub clip_rule: ClipRule,
    pub shape_rendering: ShapeRendering,
    pub marker_start: Marker,
    pub marker_mid: Marker,
    pub marker_end: Marker,
}

pub struct Marker {
    pub node_ref: Option<Node>,
    pub context_stroke: PaintSource,
    pub context_fill: PaintSource,
}

/// Image in user-space coordinates.
pub struct Image {
    pub surface: SharedImageSurface,
    pub is_visible: bool,
    pub rect: Rect,
    pub aspect: AspectRatio,
    pub overflow: Overflow,
}

/// A single text span in user-space coordinates.
pub struct TextSpan {
    pub layout: pango::Layout,
    pub gravity: pango::Gravity,
    pub bbox: Option<BoundingBox>,
    pub is_visible: bool,
    pub x: f64,
    pub y: f64,
    pub paint_order: PaintOrder,
    pub stroke: Stroke,
    pub stroke_paint: UserSpacePaintSource,
    pub fill_paint: UserSpacePaintSource,
    pub text_rendering: TextRendering,
    pub link_target: Option<String>,
}

/// Fully laid-out text in user-space coordinates.
pub struct Text {
    pub spans: Vec<TextSpan>,
}

/// Font-related properties extracted from `ComputedValues`.
pub struct FontProperties {
    pub xml_lang: XmlLang,
    pub unicode_bidi: UnicodeBidi,
    pub direction: Direction,
    pub font_family: FontFamily,
    pub font_style: FontStyle,
    pub font_variant: FontVariant,
    pub font_weight: FontWeight,
    pub font_stretch: FontStretch,
    pub font_size: f64,
    pub letter_spacing: f64,
    pub text_decoration: TextDecoration,
}

impl StackingContext {
    pub fn new(
        acquired_nodes: &mut AcquiredNodes<'_>,
        element: &Element,
        transform: Transform,
        values: &ComputedValues,
    ) -> StackingContext {
        let element_name = format!("{}", element);

        let opacity;
        let filter;

        match *element {
            // "The opacity, filter and display properties do not apply to the mask element"
            // https://drafts.fxtf.org/css-masking-1/#MaskElement
            Element::Mask(_) => {
                opacity = Opacity(UnitInterval::clamp(1.0));
                filter = Filter::None;
            }

            _ => {
                opacity = values.opacity();
                filter = values.filter();
            }
        }

        let clip_path = values.clip_path();
        let clip_uri = clip_path.0.get();
        let (clip_in_user_space, clip_in_object_space) = clip_uri
            .and_then(|node_id| {
                acquired_nodes
                    .acquire(node_id)
                    .ok()
                    .filter(|a| is_element_of_type!(*a.get(), ClipPath))
            })
            .map(|acquired| {
                let clip_node = acquired.get().clone();

                let units = borrow_element_as!(clip_node, ClipPath).get_units();

                match units {
                    CoordUnits::UserSpaceOnUse => (Some(clip_node), None),
                    CoordUnits::ObjectBoundingBox => (None, Some(clip_node)),
                }
            })
            .unwrap_or((None, None));

        let mask = values.mask().0.get().and_then(|mask_id| {
            if let Ok(acquired) = acquired_nodes.acquire(mask_id) {
                let node = acquired.get();
                match *node.borrow_element() {
                    Element::Mask(_) => Some(node.clone()),

                    _ => {
                        rsvg_log!(
                            "element {} references \"{}\" which is not a mask",
                            element,
                            mask_id
                        );

                        None
                    }
                }
            } else {
                rsvg_log!(
                    "element {} references nonexistent mask \"{}\"",
                    element,
                    mask_id
                );

                None
            }
        });

        let mix_blend_mode = values.mix_blend_mode();
        let isolation = values.isolation();

        StackingContext {
            element_name,
            transform,
            opacity,
            filter,
            clip_in_user_space,
            clip_in_object_space,
            mask,
            mix_blend_mode,
            isolation,
            link_target: None,
        }
    }

    pub fn new_with_link(
        acquired_nodes: &mut AcquiredNodes<'_>,
        element: &Element,
        transform: Transform,
        values: &ComputedValues,
        link_target: Option<String>,
    ) -> StackingContext {
        let mut ctx = Self::new(acquired_nodes, element, transform, values);
        ctx.link_target = link_target;
        ctx
    }
}

impl Stroke {
    pub fn new(values: &ComputedValues, params: &NormalizeParams) -> Stroke {
        let width = values.stroke_width().0.to_user(params);
        let miter_limit = values.stroke_miterlimit();
        let line_cap = values.stroke_line_cap();
        let line_join = values.stroke_line_join();
        let dash_offset = values.stroke_dashoffset().0.to_user(params);

        let dashes = match values.stroke_dasharray() {
            StrokeDasharray(Dasharray::None) => Box::new([]),
            StrokeDasharray(Dasharray::Array(dashes)) => dashes
                .iter()
                .map(|l| l.to_user(params))
                .collect::<Box<[f64]>>(),
        };

        Stroke {
            width,
            miter_limit,
            line_cap,
            line_join,
            dash_offset,
            dashes,
        }
    }
}

impl FontProperties {
    /// Collects font properties from a `ComputedValues`.
    ///
    /// The `writing-mode` property is passed separately, as it must come from the `<text>` element,
    /// not the `<tspan>` whose computed values are being passed.
    pub fn new(values: &ComputedValues, params: &NormalizeParams) -> FontProperties {
        FontProperties {
            xml_lang: values.xml_lang(),
            unicode_bidi: values.unicode_bidi(),
            direction: values.direction(),
            font_family: values.font_family(),
            font_style: values.font_style(),
            font_variant: values.font_variant(),
            font_weight: values.font_weight(),
            font_stretch: values.font_stretch(),
            font_size: values.font_size().to_user(params),
            letter_spacing: values.letter_spacing().to_user(params),
            text_decoration: values.text_decoration(),
        }
    }
}
<|endoftext|>


<commit_before>use num::Num;
use div::sdiv;

#[inline(always)]
pub fn length_values_sq<T: Num>(x: T, y: T, z: T) -> T {
    x * x + y * y + z * z
}
#[test]
fn test_length_values_sq() {
    assert!(length_values_sq(1, 1, 1) == 3);
}

#[inline(always)]
pub fn length_values<T: Num>(x: T, y: T, z: T) -> T {
    let lsq = length_values_sq(x, y, z);
    if lsq == T::zero() {lsq} else {lsq.sqrt()}
}
#[test]
fn test_length_values() {
    assert!(length_values(1, 2, 2) == 3);
}

#[inline(always)]
pub fn inv_length_values<T: Num>(x: T, y: T, z: T) -> T {
    let lsq = length_values_sq(x, y, z);
    if lsq == T::zero() {lsq} else {T::one() / lsq.sqrt()}
}
#[test]
fn test_inv_length_values() {
    assert!(inv_length_values(1.0, 2.0, 2.0) == 1.0 / 3.0);
}

#[inline(always)]
pub fn dot<T: Num>(a: [T; 3], b: [T; 3]) -> T {
    a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
}
#[test]
fn test_dot() {
    assert!(dot([1, 1, 1], [1, 1, 1]) == 3);
}

#[inline(always)]
pub fn cross<T: Num>(out: &mut [T; 3], a: [T; 3], b: [T; 3]) -> &mut [T; 3] {
    out[0] = a[1] * b[2] - a[2] * b[1];
    out[1] = a[2] * b[0] - a[0] * b[2];
    out[2] = a[0] * b[1] - a[1] * b[0];
    out
}
#[test]
fn test_cross() {
    let mut v = [0, 0, 0];
    cross(&mut v, [1, 1, 1], [1, 1, 1]);
    assert!(v[0] == 0);
    assert!(v[1] == 0);
    assert!(v[2] == 0);
}

#[inline(always)]
pub fn length<T: Num>(out: [T; 3]) -> T {
    length_values(out[0], out[1], out[2])
}
#[test]
fn test_length() {
    assert!(length([1, 2, 2]) == 3);
}

#[inline(always)]
pub fn normalize<T: Num>(out: &mut [T; 3], a: [T; 3]) -> &mut [T; 3] {
    sdiv(out, a, length(a))
}
#[test]
fn test_normalize() {
    let mut v = [0, 0, 0];
    normalize(&mut v, [1, 1, 1]);
    assert!(v[0] == 1);
    assert!(v[1] == 1);
    assert!(v[2] == 1);
}
<commit_msg>updates<commit_after>use num::Num;
use div::sdiv;

#[inline(always)]
pub fn length_values_sq<T: Num>(x: T, y: T, z: T) -> T {
    x * x + y * y + z * z
}
#[test]
fn test_length_values_sq() {
    assert!(length_values_sq(1, 1, 1) == 3);
}

#[inline(always)]
pub fn length_values<T: Num>(x: T, y: T, z: T) -> T {
    let lsq = length_values_sq(x, y, z);
    if lsq == T::zero() {lsq} else {lsq.sqrt()}
}
#[test]
fn test_length_values() {
    assert!(length_values(1, 2, 2) == 3);
}

#[inline(always)]
pub fn inv_length_values<T: Num>(x: T, y: T, z: T) -> T {
    let lsq = length_values_sq(x, y, z);
    if lsq == T::zero() {lsq} else {T::one() / lsq.sqrt()}
}
#[test]
fn test_inv_length_values() {
    assert!(inv_length_values(1.0, 2.0, 2.0) == 1.0 / 3.0);
}

#[inline(always)]
pub fn dot<T: Num>(a: [T; 3], b: [T; 3]) -> T {
    a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
}
#[test]
fn test_dot() {
    assert!(dot([1, 1, 1], [1, 1, 1]) == 3);
}

#[inline(always)]
pub fn cross<T: Num>(out: &mut [T; 3], a: [T; 3], b: [T; 3]) -> &mut [T; 3] {
    out[0] = a[1] * b[2] - a[2] * b[1];
    out[1] = a[2] * b[0] - a[0] * b[2];
    out[2] = a[0] * b[1] - a[1] * b[0];
    out
}
#[test]
fn test_cross() {
    let mut v = [0, 0, 0];
    cross(&mut v, [1, 1, 1], [1, 1, 1]);
    assert!(v[0] == 0);
    assert!(v[1] == 0);
    assert!(v[2] == 0);
}

#[inline(always)]
pub fn length<T: Num>(out: [T; 3]) -> T {
    length_values(out[0], out[1], out[2])
}
#[test]
fn test_length() {
    assert!(length([1, 2, 2]) == 3);
}

#[inline(always)]
pub fn normalize<T: Num>(out: &mut [T; 3], a: [T; 3]) -> &mut [T; 3] {
    sdiv(out, a, length(a))
}
#[test]
fn test_normalize() {
    let mut v = [0, 0, 0];
    normalize(&mut v, [0, 0, 1]);
    assert!(v[0] == 0);
    assert!(v[1] == 0);
    assert!(v[2] == 1);
}
<|endoftext|>


<commit_before>use crate::{Result, Statement, ToSql};

mod sealed {
    /// This trait exists just to ensure that the only impls of `trait Params`
    /// that are allowed are ones in this crate.
    pub trait Sealed {}
}
use sealed::Sealed;

/// Trait used for [sets of parameter][params] passed into SQL
/// statements/queries.
///
/// [params]: https://www.sqlite.org/c3ref/bind_blob.html
///
/// Note: Currently, this trait can only be implemented inside this crate.
/// Additionally, it's methods (which are `doc(hidden)`) should currently not be
/// considered part of the stable API, although it's possible they will
/// stabilize in the future.
///
/// # Passing parameters to SQLite
///
/// Many functions in this library let you pass parameters to SQLite. Doing this
/// lets you avoid any risk of SQL injection, and is simpler than escaping
/// things manually. Aside from deprecated functions and a few helpers, this is
/// indicated by the function taking a generic argument that implements `Params`
/// (this trait).
///
/// ## Positional parameters
///
/// For cases where you want to pass a list of parameters where the number of
/// parameters is known at compile time, this can be done in one of the
/// following ways:
///
/// - Using the [`rusqlite::params!`](crate::params!) macro, e.g.
///   `thing.query(rusqlite::params![1, "foo", bar])`. This is mostly useful for
///   heterogeneous lists of parameters, or lists where the number of parameters
///   exceeds 32.
///
/// - For small heterogeneous lists of parameters, they can either be passed as:
///
///     - an array, as in `thing.query([1i32, 2, 3, 4])` or `thing.query(["foo",
///       "bar", "baz"])`.
///
///     - a reference to an array of references, as in `thing.query(&["foo",
///       "bar", "baz"])` or `thing.query(&[&1i32, &2, &3])`.
///
///         (Note: in this case we don't implement this for slices for coherence
///         reasons, so it really is only for the "reference to array" types —
///         hence why the number of parameters must be <= 32 or you need to
///         reach for `rusqlite::params!`)
///
///     Unfortunately, in the current design it's not possible to allow this for
///     references to arrays of non-references (e.g. `&[1i32, 2, 3]`). Code like
///     this should instead either use `params!`, an array literal, a `&[&dyn
///     ToSql]` or if none of those work, [`ParamsFromIter`].
///
/// - As a slice of `ToSql` trait object references, e.g. `&[&dyn ToSql]`. This
///   is mostly useful for passing parameter lists around as arguments without
///   having every function take a generic `P: Params`.
///
/// ### Example (positional)
///
/// ```rust,no_run
/// # use rusqlite::{Connection, Result, params};
/// fn update_rows(conn: &Connection) -> Result<()> {
///     let mut stmt = conn.prepare("INSERT INTO test (a, b) VALUES (?, ?)")?;
///
///     // Using `rusqlite::params!`:
///     stmt.execute(params![1i32, "blah"])?;
///
///     // array literal — non-references
///     stmt.execute([2i32, 3i32])?;
///
///     // array literal — references
///     stmt.execute(["foo", "bar"])?;
///
///     // Slice literal, references:
///     stmt.execute(&[&2i32, &3i32])?;
///
///     // Note: The types behind the references don't have to be `Sized`
///     stmt.execute(&["foo", "bar"])?;
///
///     // However, this doesn't work (see above):
///     // stmt.execute(&[1i32, 2i32])?;
///     Ok(())
/// }
/// ```
///
/// ## Named parameters
///
/// SQLite lets you name parameters using a number of conventions (":foo",
/// "@foo", "$foo"). You can pass named parameters in to SQLite using rusqlite
/// in a few ways:
///
/// - Using the [`rusqlite::named_params!`](crate::named_params!) macro, as in
///   `stmt.execute(named_params!{ ":name": "foo", ":age": 99 })`. Similar to
///   the `params` macro, this is most useful for heterogeneous lists of
///   parameters, or lists where the number of parameters exceeds 32.
///
/// - As a slice of `&[(&str, &dyn ToSql)]`. This is what essentially all of
///   these boil down to in the end, conceptually at least. In theory you can
///   pass this as `stmt.
///
/// - As array references, similar to the positional params. This looks like
///   `thing.query(&[(":foo", &1i32), (":bar", &2i32)])` or
///   `thing.query(&[(":foo", "abc"), (":bar", "def")])`.
///
/// Note: Unbound named parameters will be left to the value they previously
/// were bound with, falling back to `NULL` for parameters which have never been
/// bound.
///
/// ### Example (named)
///
/// ```rust,no_run
/// # use rusqlite::{Connection, Result, named_params};
/// fn insert(conn: &Connection) -> Result<()> {
///     let mut stmt = conn.prepare("INSERT INTO test (key, value) VALUES (:key, :value)")?;
///     // Using `rusqlite::params!`:
///     stmt.execute(named_params!{ ":key": "one", ":val": 2 })?;
///     // Alternatively:
///     stmt.execute(&[(":key", "three"), (":val", "four")])?;
///     // Or:
///     stmt.execute(&[(":key", &100), (":val", &200)])?;
///     Ok(())
/// }
/// ```
///
/// ## No parameters
///
/// You can just use an empty array literal for no params. The
/// `rusqlite::NO_PARAMS` constant which was so common in previous versions of
/// this library is no longer needed (and is now deprecated).
///
/// ### Example (no parameters)
///
/// ```rust,no_run
/// # use rusqlite::{Connection, Result, params};
/// fn delete_all_users(conn: &Connection) -> Result<()> {
///     // Just use an empty array (e.g. `[]`) for no params.
///     conn.execute("DELETE FROM users", [])?;
///     Ok(())
/// }
/// ```
///
/// ## Dynamic parameter list
///
/// If you have a number of parameters which is unknown at compile time (for
/// example, building a dynamic query at runtime), you have two choices:
///
/// - Use a `&[&dyn ToSql]`, which is nice if you have one otherwise might be
///   annoying.
/// - Use the [`ParamsFromIter`] type. This essentially lets you wrap an
///   iterator some `T: ToSql` with something that implements `Params`.
///
/// A lot of the considerations here are similar either way, so you should see
/// the [`ParamsFromIter`] documentation for more info / examples.
pub trait Params: Sealed {
    // XXX not public api, might not need to expose.
    //
    // Binds the parameters to the statement. It is unlikely calling this
    // explicitly will do what you want. Please use `Statement::query` or
    // similar directly.
    //
    // For now, just hide the function in the docs...
    #[doc(hidden)]
    fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()>;
}

// Explicitly impl for empty array. Critically, for `conn.execute([])` to be
// unambiguous, this must be the *only* implementation for an empty array. This
// avoids `NO_PARAMS` being a necessary part of the API.
impl Sealed for [&dyn ToSql; 0] {}
impl Params for [&dyn ToSql; 0] {
    #[inline]
    fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
        // Note: Can't just return `Ok(())` — `Statement::bind_parameters`
        // checks that the right number of params were passed too.
        // TODO: we should have tests for `Error::InvalidParameterCount`...
        stmt.bind_parameters(crate::params![])
    }
}

impl Sealed for &[&dyn ToSql] {}
impl Params for &[&dyn ToSql] {
    #[inline]
    fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
        stmt.bind_parameters(self)
    }
}

impl Sealed for &[(&str, &dyn ToSql)] {}
impl Params for &[(&str, &dyn ToSql)] {
    #[inline]
    fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
        stmt.bind_parameters_named(self)
    }
}

macro_rules! impl_for_array_ref {
    ($($N:literal)+) => {$(
        impl<T: ToSql + ?Sized> Sealed for &[&T; $N] {}
        impl<T: ToSql + ?Sized> Params for &[&T; $N] {
            fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
                stmt.bind_parameters(self)
            }
        }
        impl<T: ToSql + ?Sized> Sealed for &[(&str, &T); $N] {}
        impl<T: ToSql + ?Sized> Params for &[(&str, &T); $N] {
            fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
                stmt.bind_parameters_named(self)
            }
        }
        impl<T: ToSql> Sealed for [T; $N] {}
        impl<T: ToSql> Params for [T; $N] {
            fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
                stmt.bind_parameters(&self)
            }
        }
    )+};
}

// Following libstd/libcore's (old) lead, implement this for arrays up to `[_;
// 32]`. Note `[_; 0]` is intentionally omitted for coherence reasons, see the
// note above the impl of `[&dyn ToSql; 0]` for more information.
impl_for_array_ref!(
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
    18 19 20 21 22 23 24 25 26 27 29 30 31 32
);

/// Adapter type which allows any iterator over [`ToSql`] values to implement
/// [`Params`].
///
/// This struct is created by the [`params_from_iter`] function.
///
/// This can be useful if you have something like an `&[String]` (of unknown
/// length), and you want to use them with an API that wants something
/// implementing `Params`. This way, you can avoid having to allocate storage
/// for something like a `&[&dyn ToSql]`.
///
/// This essentially is only ever actually needed when dynamically generating
/// SQL — static SQL (by definition) has the number of parameters known
/// statically. As dynamically generating SQL is itself pretty advanced, this
/// API is itself for advanced use cases (See "Realistic use case" in the
/// examples).
///
/// # Example
///
/// ## Basic usage
///
/// ```rust,no_run
/// use rusqlite::{Connection, Result, params_from_iter};
/// use std::collections::BTreeSet;
///
/// fn query(conn: &Connection, ids: &BTreeSet<String>) -> Result<()> {
///     assert_eq!(ids.len(), 3, "Unrealistic sample code");
///
///     let mut stmt = conn.prepare("SELECT * FROM users WHERE id IN (?, ?, ?)")?;
///     let _rows = stmt.query(params_from_iter(ids.iter()))?;
///
///     // use _rows...
///     Ok(())
/// }
/// ```
///
/// ## Realistic use case
///
/// Here's how you'd use `ParamsFromIter` to call a function with no `_iter`
/// equivalent, e.g. [`Statement::exists`].
///
/// ```rust,no_run
/// use rusqlite::{Connection, Result};
///
/// pub fn any_active_users(conn: &Connection, usernames: &[String]) -> Result<bool> {
///     if usernames.is_empty() {
///         return Ok(false);
///     }
///
///     // Note: `repeat_vars` never returns anything attacker-controlled, so
///     // it's fine to use it in a dynamically-built SQL string.
///     let vars = repeat_vars(usernames.len());
///
///     let sql = format!(
///         // In practice this would probably be better as an `EXISTS` query.
///         "SELECT 1 FROM user WHERE is_active AND name IN ({}) LIMIT 1",
///         vars,
///     );
///     let mut stmt = conn.prepare(&sql)?;
///     stmt.exists(rusqlite::params_from_iter(usernames))
/// }
///
/// // Helper function to return a comma-separated sequence of `?`.
/// // - `repeat_vars(0) => panic!(...)`
/// // - `repeat_vars(1) => "?"`
/// // - `repeat_vars(2) => "?,?"`
/// // - `repeat_vars(3) => "?,?,?"`
/// // - ...
/// fn repeat_vars(count: usize) -> String {
///     assert_ne!(count, 0);
///     let mut s = "?,".repeat(count);
///     // Remove trailing comma
///     s.pop();
///     s
/// }
/// ```
///
/// That is fairly complex, and even so would need even more work to be fully
/// production-ready:
///
/// - production code should ensure `usernames` isn't so large that it will
///   surpass [`conn.limit(Limit::SQLITE_LIMIT_VARIABLE_NUMBER)`][limits]),
///   chunking if too large. (Note that the limits api requires rusqlite to have
///   the "limits" feature).
///
/// - `repeat_vars` can be implemented in a way that avoids needing to allocate
///   a String.
///
/// - Etc...
///
/// [limits]: crate::Connection::limit
///
/// This complexity reflects the fact that `ParamsFromIter` is mainly intended
/// for advanced use cases — most of the time you should know how many
/// parameters you have statically (and if you don't, you're either doing
/// something tricky, or should take a moment to think about the design).
#[derive(Clone, Debug)]
pub struct ParamsFromIter<I>(I);

/// Constructor function for a [`ParamsFromIter`]. See its documentation for
/// more.
#[inline]
pub fn params_from_iter<I>(iter: I) -> ParamsFromIter<I>
where
    I: IntoIterator,
    I::Item: ToSql,
{
    ParamsFromIter(iter)
}

impl<I> Sealed for ParamsFromIter<I>
where
    I: IntoIterator,
    I::Item: ToSql,
{
}

impl<I> Params for ParamsFromIter<I>
where
    I: IntoIterator,
    I::Item: ToSql,
{
    #[inline]
    fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
        stmt.bind_parameters(self.0)
    }
}
<commit_msg>Fix stale doc<commit_after>use crate::{Result, Statement, ToSql};

mod sealed {
    /// This trait exists just to ensure that the only impls of `trait Params`
    /// that are allowed are ones in this crate.
    pub trait Sealed {}
}
use sealed::Sealed;

/// Trait used for [sets of parameter][params] passed into SQL
/// statements/queries.
///
/// [params]: https://www.sqlite.org/c3ref/bind_blob.html
///
/// Note: Currently, this trait can only be implemented inside this crate.
/// Additionally, it's methods (which are `doc(hidden)`) should currently not be
/// considered part of the stable API, although it's possible they will
/// stabilize in the future.
///
/// # Passing parameters to SQLite
///
/// Many functions in this library let you pass parameters to SQLite. Doing this
/// lets you avoid any risk of SQL injection, and is simpler than escaping
/// things manually. Aside from deprecated functions and a few helpers, this is
/// indicated by the function taking a generic argument that implements `Params`
/// (this trait).
///
/// ## Positional parameters
///
/// For cases where you want to pass a list of parameters where the number of
/// parameters is known at compile time, this can be done in one of the
/// following ways:
///
/// - Using the [`rusqlite::params!`](crate::params!) macro, e.g.
///   `thing.query(rusqlite::params![1, "foo", bar])`. This is mostly useful for
///   heterogeneous lists of parameters, or lists where the number of parameters
///   exceeds 32.
///
/// - For small heterogeneous lists of parameters, they can either be passed as:
///
///     - an array, as in `thing.query([1i32, 2, 3, 4])` or `thing.query(["foo",
///       "bar", "baz"])`.
///
///     - a reference to an array of references, as in `thing.query(&["foo",
///       "bar", "baz"])` or `thing.query(&[&1i32, &2, &3])`.
///
///         (Note: in this case we don't implement this for slices for coherence
///         reasons, so it really is only for the "reference to array" types —
///         hence why the number of parameters must be <= 32 or you need to
///         reach for `rusqlite::params!`)
///
///     Unfortunately, in the current design it's not possible to allow this for
///     references to arrays of non-references (e.g. `&[1i32, 2, 3]`). Code like
///     this should instead either use `params!`, an array literal, a `&[&dyn
///     ToSql]` or if none of those work, [`ParamsFromIter`].
///
/// - As a slice of `ToSql` trait object references, e.g. `&[&dyn ToSql]`. This
///   is mostly useful for passing parameter lists around as arguments without
///   having every function take a generic `P: Params`.
///
/// ### Example (positional)
///
/// ```rust,no_run
/// # use rusqlite::{Connection, Result, params};
/// fn update_rows(conn: &Connection) -> Result<()> {
///     let mut stmt = conn.prepare("INSERT INTO test (a, b) VALUES (?, ?)")?;
///
///     // Using `rusqlite::params!`:
///     stmt.execute(params![1i32, "blah"])?;
///
///     // array literal — non-references
///     stmt.execute([2i32, 3i32])?;
///
///     // array literal — references
///     stmt.execute(["foo", "bar"])?;
///
///     // Slice literal, references:
///     stmt.execute(&[&2i32, &3i32])?;
///
///     // Note: The types behind the references don't have to be `Sized`
///     stmt.execute(&["foo", "bar"])?;
///
///     // However, this doesn't work (see above):
///     // stmt.execute(&[1i32, 2i32])?;
///     Ok(())
/// }
/// ```
///
/// ## Named parameters
///
/// SQLite lets you name parameters using a number of conventions (":foo",
/// "@foo", "$foo"). You can pass named parameters in to SQLite using rusqlite
/// in a few ways:
///
/// - Using the [`rusqlite::named_params!`](crate::named_params!) macro, as in
///   `stmt.execute(named_params!{ ":name": "foo", ":age": 99 })`. Similar to
///   the `params` macro, this is most useful for heterogeneous lists of
///   parameters, or lists where the number of parameters exceeds 32.
///
/// - As a slice of `&[(&str, &dyn ToSql)]`. This is what essentially all of
///   these boil down to in the end, conceptually at least. In theory you can
///   pass this as `stmt.
///
/// - As array references, similar to the positional params. This looks like
///   `thing.query(&[(":foo", &1i32), (":bar", &2i32)])` or
///   `thing.query(&[(":foo", "abc"), (":bar", "def")])`.
///
/// Note: Unbound named parameters will be left to the value they previously
/// were bound with, falling back to `NULL` for parameters which have never been
/// bound.
///
/// ### Example (named)
///
/// ```rust,no_run
/// # use rusqlite::{Connection, Result, named_params};
/// fn insert(conn: &Connection) -> Result<()> {
///     let mut stmt = conn.prepare("INSERT INTO test (key, value) VALUES (:key, :value)")?;
///     // Using `rusqlite::params!`:
///     stmt.execute(named_params!{ ":key": "one", ":val": 2 })?;
///     // Alternatively:
///     stmt.execute(&[(":key", "three"), (":val", "four")])?;
///     // Or:
///     stmt.execute(&[(":key", &100), (":val", &200)])?;
///     Ok(())
/// }
/// ```
///
/// ## No parameters
///
/// You can just use an empty array literal for no params. The
/// `rusqlite::NO_PARAMS` constant which was so common in previous versions of
/// this library is no longer needed (and is now deprecated).
///
/// ### Example (no parameters)
///
/// ```rust,no_run
/// # use rusqlite::{Connection, Result, params};
/// fn delete_all_users(conn: &Connection) -> Result<()> {
///     // Just use an empty array (e.g. `[]`) for no params.
///     conn.execute("DELETE FROM users", [])?;
///     Ok(())
/// }
/// ```
///
/// ## Dynamic parameter list
///
/// If you have a number of parameters which is unknown at compile time (for
/// example, building a dynamic query at runtime), you have two choices:
///
/// - Use a `&[&dyn ToSql]`, which is nice if you have one otherwise might be
///   annoying.
/// - Use the [`ParamsFromIter`] type. This essentially lets you wrap an
///   iterator some `T: ToSql` with something that implements `Params`.
///
/// A lot of the considerations here are similar either way, so you should see
/// the [`ParamsFromIter`] documentation for more info / examples.
pub trait Params: Sealed {
    // XXX not public api, might not need to expose.
    //
    // Binds the parameters to the statement. It is unlikely calling this
    // explicitly will do what you want. Please use `Statement::query` or
    // similar directly.
    //
    // For now, just hide the function in the docs...
    #[doc(hidden)]
    fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()>;
}

// Explicitly impl for empty array. Critically, for `conn.execute([])` to be
// unambiguous, this must be the *only* implementation for an empty array. This
// avoids `NO_PARAMS` being a necessary part of the API.
impl Sealed for [&dyn ToSql; 0] {}
impl Params for [&dyn ToSql; 0] {
    #[inline]
    fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
        // Note: Can't just return `Ok(())` — `Statement::bind_parameters`
        // checks that the right number of params were passed too.
        // TODO: we should have tests for `Error::InvalidParameterCount`...
        stmt.bind_parameters(crate::params![])
    }
}

impl Sealed for &[&dyn ToSql] {}
impl Params for &[&dyn ToSql] {
    #[inline]
    fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
        stmt.bind_parameters(self)
    }
}

impl Sealed for &[(&str, &dyn ToSql)] {}
impl Params for &[(&str, &dyn ToSql)] {
    #[inline]
    fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
        stmt.bind_parameters_named(self)
    }
}

macro_rules! impl_for_array_ref {
    ($($N:literal)+) => {$(
        impl<T: ToSql + ?Sized> Sealed for &[&T; $N] {}
        impl<T: ToSql + ?Sized> Params for &[&T; $N] {
            fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
                stmt.bind_parameters(self)
            }
        }
        impl<T: ToSql + ?Sized> Sealed for &[(&str, &T); $N] {}
        impl<T: ToSql + ?Sized> Params for &[(&str, &T); $N] {
            fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
                stmt.bind_parameters_named(self)
            }
        }
        impl<T: ToSql> Sealed for [T; $N] {}
        impl<T: ToSql> Params for [T; $N] {
            fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
                stmt.bind_parameters(&self)
            }
        }
    )+};
}

// Following libstd/libcore's (old) lead, implement this for arrays up to `[_;
// 32]`. Note `[_; 0]` is intentionally omitted for coherence reasons, see the
// note above the impl of `[&dyn ToSql; 0]` for more information.
impl_for_array_ref!(
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
    18 19 20 21 22 23 24 25 26 27 29 30 31 32
);

/// Adapter type which allows any iterator over [`ToSql`] values to implement
/// [`Params`].
///
/// This struct is created by the [`params_from_iter`] function.
///
/// This can be useful if you have something like an `&[String]` (of unknown
/// length), and you want to use them with an API that wants something
/// implementing `Params`. This way, you can avoid having to allocate storage
/// for something like a `&[&dyn ToSql]`.
///
/// This essentially is only ever actually needed when dynamically generating
/// SQL — static SQL (by definition) has the number of parameters known
/// statically. As dynamically generating SQL is itself pretty advanced, this
/// API is itself for advanced use cases (See "Realistic use case" in the
/// examples).
///
/// # Example
///
/// ## Basic usage
///
/// ```rust,no_run
/// use rusqlite::{Connection, Result, params_from_iter};
/// use std::collections::BTreeSet;
///
/// fn query(conn: &Connection, ids: &BTreeSet<String>) -> Result<()> {
///     assert_eq!(ids.len(), 3, "Unrealistic sample code");
///
///     let mut stmt = conn.prepare("SELECT * FROM users WHERE id IN (?, ?, ?)")?;
///     let _rows = stmt.query(params_from_iter(ids.iter()))?;
///
///     // use _rows...
///     Ok(())
/// }
/// ```
///
/// ## Realistic use case
///
/// Here's how you'd use `ParamsFromIter` to call [`Statement::exists`] with a
/// dynamic number of parameters.
///
/// ```rust,no_run
/// use rusqlite::{Connection, Result};
///
/// pub fn any_active_users(conn: &Connection, usernames: &[String]) -> Result<bool> {
///     if usernames.is_empty() {
///         return Ok(false);
///     }
///
///     // Note: `repeat_vars` never returns anything attacker-controlled, so
///     // it's fine to use it in a dynamically-built SQL string.
///     let vars = repeat_vars(usernames.len());
///
///     let sql = format!(
///         // In practice this would probably be better as an `EXISTS` query.
///         "SELECT 1 FROM user WHERE is_active AND name IN ({}) LIMIT 1",
///         vars,
///     );
///     let mut stmt = conn.prepare(&sql)?;
///     stmt.exists(rusqlite::params_from_iter(usernames))
/// }
///
/// // Helper function to return a comma-separated sequence of `?`.
/// // - `repeat_vars(0) => panic!(...)`
/// // - `repeat_vars(1) => "?"`
/// // - `repeat_vars(2) => "?,?"`
/// // - `repeat_vars(3) => "?,?,?"`
/// // - ...
/// fn repeat_vars(count: usize) -> String {
///     assert_ne!(count, 0);
///     let mut s = "?,".repeat(count);
///     // Remove trailing comma
///     s.pop();
///     s
/// }
/// ```
///
/// That is fairly complex, and even so would need even more work to be fully
/// production-ready:
///
/// - production code should ensure `usernames` isn't so large that it will
///   surpass [`conn.limit(Limit::SQLITE_LIMIT_VARIABLE_NUMBER)`][limits]),
///   chunking if too large. (Note that the limits api requires rusqlite to have
///   the "limits" feature).
///
/// - `repeat_vars` can be implemented in a way that avoids needing to allocate
///   a String.
///
/// - Etc...
///
/// [limits]: crate::Connection::limit
///
/// This complexity reflects the fact that `ParamsFromIter` is mainly intended
/// for advanced use cases — most of the time you should know how many
/// parameters you have statically (and if you don't, you're either doing
/// something tricky, or should take a moment to think about the design).
#[derive(Clone, Debug)]
pub struct ParamsFromIter<I>(I);

/// Constructor function for a [`ParamsFromIter`]. See its documentation for
/// more.
#[inline]
pub fn params_from_iter<I>(iter: I) -> ParamsFromIter<I>
where
    I: IntoIterator,
    I::Item: ToSql,
{
    ParamsFromIter(iter)
}

impl<I> Sealed for ParamsFromIter<I>
where
    I: IntoIterator,
    I::Item: ToSql,
{
}

impl<I> Params for ParamsFromIter<I>
where
    I: IntoIterator,
    I::Item: ToSql,
{
    #[inline]
    fn bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
        stmt.bind_parameters(self.0)
    }
}
<|endoftext|>


<commit_before>//! Functions for parsing a molecule or a chemical reaction.
//! Mostly based on the HTML parser from the robinson browser engine:
//! https://github.com/mbrubeck/robinson
//!
//! The parser works with the following grammar:
//! R = (R)eaction
//! S = one (S)ide of a reaction
//! M = (M)olecule
//! P = Combination of a (P)eriodic element and maybe a coefficient
//! E = Periodic (E)lement
//! C = (C)oefficient
//!
//! R --> S -> S
//! S --> M + S
//!    |  M
//! M --> PM
//!    |  P
//! P --> EC
//!    |  E
//! E --> <text>
//!    |  (M)
//! C --> <number>

use std::str::CharRange;
use elem::{PerElem, Molecule};
use error::{CTResult, CTSyntaxError};
use error::CTError::SyntaxError;

pub struct Parser {
    pos: usize,
    input: String,
}

impl Parser {
    pub fn new(input: &str) -> Parser {
        Parser { pos: 0, input: String::from_str(input) }
    }

    pub fn parse_reaction(&mut self) -> CTResult<(Vec<Molecule>, Vec<Molecule>)> {
        let lhs = try!(self.parse_side());
        self.consume_whitespace();

        // we do not care if some of the consumes are not called, since this is
        // an error anyway, and will abort the parsing
        if self.pos + 2 >= self.input.len() || self.consume_char() != '-' ||
                                               self.consume_char() != '>' {
            return Err(SyntaxError(CTSyntaxError {
                desc: "Missing arrow (->) in chemical reaction".to_string(),
                pos: self.pos - 2,
                len: 1,
            }));
        }
        self.consume_whitespace();

        let rhs = try!(self.parse_side());

        Ok((lhs, rhs))
    }

    pub fn parse_side(&mut self) -> CTResult<Vec<Molecule>> {
        let mut out = Vec::new();
        let molecule = try!(self.parse_molecule());
        out.push(molecule);
        self.consume_whitespace();

        if !self.eof() && self.peek_char() == '+' {
            self.consume_char();
            self.consume_whitespace();
            let rest = try!(self.parse_side());
            out.extend(rest.into_iter());
        }

        Ok(out)
    }

    pub fn parse_molecule(&mut self) -> CTResult<Molecule> {
        let mut out = Vec::new();
        let per = try!(self.parse_periodic());
        out.extend(per.into_iter());

        // TODO: Make this cleaner
        if !self.eof() && (self.peek_char().is_alphabetic() || self.peek_char() == '(') {
            let molecule = try!(self.parse_molecule());
            out.extend(molecule.into_iter());
        }

        Ok(out)
    }

    fn parse_periodic(&mut self) -> CTResult<Vec<PerElem>> {
        let mut elem = try!(self.parse_element());

        if !self.eof() && self.peek_char().is_numeric() {
            let coef = try!(self.parse_coefficient());
            for e in elem.iter_mut() {
                e.coef *= coef;
            }
        }

        Ok(elem)
    }

    fn parse_element(&mut self) -> CTResult<Vec<PerElem>> {
        if self.eof() {
            return Err(SyntaxError(CTSyntaxError {
                desc: "Found no periodic element".to_string(),
                pos: self.pos,
                len: 1,
            }));
        }
        let start_pos = self.pos;
        let first = self.consume_char();
        if first == '(' {
            let molecule = try!(self.parse_molecule());
            if self.eof() || self.consume_char() != ')' {
                Err(SyntaxError(CTSyntaxError {
                    desc: "Missing closing parentheses".to_string(),
                    pos: self.pos - 1,
                    len: 1,
                }))
            } else {
                Ok(molecule)
            }
        } else if first.is_uppercase() {
            let mut name = String::new();
            name.push(first);
            name.push_str(self.consume_while(|ch| ch.is_lowercase()).as_slice());
            let len = name.len();
            Ok(vec!(PerElem { name: name, coef: 1, pos: start_pos, len: len }))
        } else {
            Err(SyntaxError(CTSyntaxError {
                desc: "Missing uppercase letter at the beginning of the element".to_string(),
                pos: self.pos - 1,
                len: 1,
            }))
        }
    }

    fn parse_coefficient(&mut self) -> CTResult<u32> {
        let start_pos = self.pos;
        let num_str = self.consume_while(|ch| ch.is_numeric());
        if let Some(num) = num_str.parse::<u32>() {
            Ok(num)
        } else {
            Err(SyntaxError(CTSyntaxError {
                desc: "Could not parse coefficient".to_string(),
                pos: start_pos,
                len: num_str.len(),
            }))
        }
    }

    fn peek_char(&self) -> char {
        self.input.char_at(self.pos)
    }

    fn consume_char(&mut self) -> char {
        let CharRange { ch, next } = self.input.char_range_at(self.pos);
        self.pos = next;
        ch
    }

    fn consume_while<F>(&mut self, pred: F) -> String where F: Fn(char) -> bool {
        let mut out = String::new();
        while !self.eof() && pred(self.peek_char()) {
            out.push(self.consume_char());
        }
        out
    }

    fn consume_whitespace(&mut self) {
        self.consume_while(|ch| ch.is_whitespace());
    }

    fn eof(&mut self) -> bool {
        self.pos >= self.input.len()
    }
}

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

    macro_rules! check_raw_result(
        ($raw:expr, $expected:expr) => (
            if let Ok(result) = $raw {
                assert_eq!(result, $expected);
            } else {
                panic!($raw);
            }
        )
    );

    #[test]
    fn elems() {
        let mut parser = Parser::new("CHeH");
        let raw_result = parser.parse_molecule();
        let expected = vec!(PerElem { name: "C".to_string(), coef: 1, pos: 0, len: 1 },
                            PerElem { name: "He".to_string(), coef: 1, pos: 1, len: 2 },
                            PerElem { name: "H".to_string(), coef: 1, pos: 3, len: 1 });
        check_raw_result!(raw_result, expected);
    }

    #[test]
    fn coefs() {
        let mut parser = Parser::new("C23");
        let raw_result = parser.parse_molecule();
        let expected = vec!(PerElem { name: "C".to_string(), coef: 23, pos: 0, len: 1 });
        check_raw_result!(raw_result, expected);
    }

    #[test]
    fn parens() {
        let mut parser = Parser::new("(CH3)2");
        let raw_result = parser.parse_molecule();
        let expected = vec!(PerElem { name: "C".to_string(), coef: 2, pos: 1, len: 1 },
                            PerElem { name: "H".to_string(), coef: 6, pos: 2, len: 1 });
        check_raw_result!(raw_result, expected);
    }

    #[test]
    fn multiple_elems() {
        let mut parser = Parser::new("C + H");
        let raw_result = parser.parse_side();
        let expected = vec!(vec!(PerElem { name: "C".to_string(), coef: 1, pos: 0, len: 1 }),
                            vec!(PerElem { name: "H".to_string(), coef: 1, pos: 4, len: 1 }));
        check_raw_result!(raw_result, expected);
    }

    #[test]
    fn reaction() {
        let mut parser = Parser::new("C -> H");
        let raw_result = parser.parse_reaction();
        let expected = (vec!(vec!(PerElem { name: "C".to_string(), coef: 1, pos: 0, len: 1 })),
                        vec!(vec!(PerElem { name: "H".to_string(), coef: 1, pos: 5, len: 1 })));
        check_raw_result!(raw_result, expected);
    }

    #[test]
    fn empty() {
        let mut parser = Parser::new("");
        assert!(parser.parse_molecule().is_err());
        assert!(parser.parse_reaction().is_err());
    }

    #[test]
    fn no_uppercase() {
        let mut parser = Parser::new("c");
        assert!(parser.parse_molecule().is_err());
        assert!(parser.parse_reaction().is_err());
    }

    #[test]
    fn paren_error() {
        let mut parser = Parser::new("(C");
        assert!(parser.parse_molecule().is_err());
        assert!(parser.parse_reaction().is_err());
    }

    #[test]
    fn invald_num() {
        let mut parser = Parser::new("C999999999999999999999");
        assert!(parser.parse_molecule().is_err());
        assert!(parser.parse_reaction().is_err());
    }

    #[test]
    fn dangling_plus() {
        let mut parser = Parser::new("C + -> H");
        assert!(parser.parse_reaction().is_err());
    }
}<commit_msg>Use Vec::append instead of Vec::extend<commit_after>//! Functions for parsing a molecule or a chemical reaction.
//! Mostly based on the HTML parser from the robinson browser engine:
//! https://github.com/mbrubeck/robinson
//!
//! The parser works with the following grammar:
//! R = (R)eaction
//! S = one (S)ide of a reaction
//! M = (M)olecule
//! P = Combination of a (P)eriodic element and maybe a coefficient
//! E = Periodic (E)lement
//! C = (C)oefficient
//!
//! R --> S -> S
//! S --> M + S
//!    |  M
//! M --> PM
//!    |  P
//! P --> EC
//!    |  E
//! E --> <text>
//!    |  (M)
//! C --> <number>

use std::str::CharRange;
use elem::{PerElem, Molecule};
use error::{CTResult, CTSyntaxError};
use error::CTError::SyntaxError;

pub struct Parser {
    pos: usize,
    input: String,
}

impl Parser {
    pub fn new(input: &str) -> Parser {
        Parser { pos: 0, input: String::from_str(input) }
    }

    pub fn parse_reaction(&mut self) -> CTResult<(Vec<Molecule>, Vec<Molecule>)> {
        let lhs = try!(self.parse_side());
        self.consume_whitespace();

        // we do not care if some of the consumes are not called, since this is
        // an error anyway, and will abort the parsing
        if self.pos + 2 >= self.input.len() || self.consume_char() != '-' ||
                                               self.consume_char() != '>' {
            return Err(SyntaxError(CTSyntaxError {
                desc: "Missing arrow (->) in chemical reaction".to_string(),
                pos: self.pos - 2,
                len: 1,
            }));
        }
        self.consume_whitespace();

        let rhs = try!(self.parse_side());

        Ok((lhs, rhs))
    }

    pub fn parse_side(&mut self) -> CTResult<Vec<Molecule>> {
        let mut out = Vec::new();
        let molecule = try!(self.parse_molecule());
        out.push(molecule);
        self.consume_whitespace();

        if !self.eof() && self.peek_char() == '+' {
            self.consume_char();
            self.consume_whitespace();
            let mut rest = try!(self.parse_side());
            out.append(&mut rest);
        }

        Ok(out)
    }

    pub fn parse_molecule(&mut self) -> CTResult<Molecule> {
        let mut out = Vec::new();
        let mut per = try!(self.parse_periodic());
        out.append(&mut per);

        // TODO: Make this cleaner
        if !self.eof() && (self.peek_char().is_alphabetic() || self.peek_char() == '(') {
            let mut molecule = try!(self.parse_molecule());
            out.append(&mut molecule);
        }

        Ok(out)
    }

    fn parse_periodic(&mut self) -> CTResult<Vec<PerElem>> {
        let mut elem = try!(self.parse_element());

        if !self.eof() && self.peek_char().is_numeric() {
            let coef = try!(self.parse_coefficient());
            for e in elem.iter_mut() {
                e.coef *= coef;
            }
        }

        Ok(elem)
    }

    fn parse_element(&mut self) -> CTResult<Vec<PerElem>> {
        if self.eof() {
            return Err(SyntaxError(CTSyntaxError {
                desc: "Found no periodic element".to_string(),
                pos: self.pos,
                len: 1,
            }));
        }
        let start_pos = self.pos;
        let first = self.consume_char();
        if first == '(' {
            let molecule = try!(self.parse_molecule());
            if self.eof() || self.consume_char() != ')' {
                Err(SyntaxError(CTSyntaxError {
                    desc: "Missing closing parentheses".to_string(),
                    pos: self.pos - 1,
                    len: 1,
                }))
            } else {
                Ok(molecule)
            }
        } else if first.is_uppercase() {
            let mut name = String::new();
            name.push(first);
            name.push_str(self.consume_while(|ch| ch.is_lowercase()).as_slice());
            let len = name.len();
            Ok(vec!(PerElem { name: name, coef: 1, pos: start_pos, len: len }))
        } else {
            Err(SyntaxError(CTSyntaxError {
                desc: "Missing uppercase letter at the beginning of the element".to_string(),
                pos: self.pos - 1,
                len: 1,
            }))
        }
    }

    fn parse_coefficient(&mut self) -> CTResult<u32> {
        let start_pos = self.pos;
        let num_str = self.consume_while(|ch| ch.is_numeric());
        if let Some(num) = num_str.parse::<u32>() {
            Ok(num)
        } else {
            Err(SyntaxError(CTSyntaxError {
                desc: "Could not parse coefficient".to_string(),
                pos: start_pos,
                len: num_str.len(),
            }))
        }
    }

    fn peek_char(&self) -> char {
        self.input.char_at(self.pos)
    }

    fn consume_char(&mut self) -> char {
        let CharRange { ch, next } = self.input.char_range_at(self.pos);
        self.pos = next;
        ch
    }

    fn consume_while<F>(&mut self, pred: F) -> String where F: Fn(char) -> bool {
        let mut out = String::new();
        while !self.eof() && pred(self.peek_char()) {
            out.push(self.consume_char());
        }
        out
    }

    fn consume_whitespace(&mut self) {
        self.consume_while(|ch| ch.is_whitespace());
    }

    fn eof(&mut self) -> bool {
        self.pos >= self.input.len()
    }
}

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

    macro_rules! check_raw_result(
        ($raw:expr, $expected:expr) => (
            if let Ok(result) = $raw {
                assert_eq!(result, $expected);
            } else {
                panic!($raw);
            }
        )
    );

    #[test]
    fn elems() {
        let mut parser = Parser::new("CHeH");
        let raw_result = parser.parse_molecule();
        let expected = vec!(PerElem { name: "C".to_string(), coef: 1, pos: 0, len: 1 },
                            PerElem { name: "He".to_string(), coef: 1, pos: 1, len: 2 },
                            PerElem { name: "H".to_string(), coef: 1, pos: 3, len: 1 });
        check_raw_result!(raw_result, expected);
    }

    #[test]
    fn coefs() {
        let mut parser = Parser::new("C23");
        let raw_result = parser.parse_molecule();
        let expected = vec!(PerElem { name: "C".to_string(), coef: 23, pos: 0, len: 1 });
        check_raw_result!(raw_result, expected);
    }

    #[test]
    fn parens() {
        let mut parser = Parser::new("(CH3)2");
        let raw_result = parser.parse_molecule();
        let expected = vec!(PerElem { name: "C".to_string(), coef: 2, pos: 1, len: 1 },
                            PerElem { name: "H".to_string(), coef: 6, pos: 2, len: 1 });
        check_raw_result!(raw_result, expected);
    }

    #[test]
    fn multiple_elems() {
        let mut parser = Parser::new("C + H");
        let raw_result = parser.parse_side();
        let expected = vec!(vec!(PerElem { name: "C".to_string(), coef: 1, pos: 0, len: 1 }),
                            vec!(PerElem { name: "H".to_string(), coef: 1, pos: 4, len: 1 }));
        check_raw_result!(raw_result, expected);
    }

    #[test]
    fn reaction() {
        let mut parser = Parser::new("C -> H");
        let raw_result = parser.parse_reaction();
        let expected = (vec!(vec!(PerElem { name: "C".to_string(), coef: 1, pos: 0, len: 1 })),
                        vec!(vec!(PerElem { name: "H".to_string(), coef: 1, pos: 5, len: 1 })));
        check_raw_result!(raw_result, expected);
    }

    #[test]
    fn empty() {
        let mut parser = Parser::new("");
        assert!(parser.parse_molecule().is_err());
        assert!(parser.parse_reaction().is_err());
    }

    #[test]
    fn no_uppercase() {
        let mut parser = Parser::new("c");
        assert!(parser.parse_molecule().is_err());
        assert!(parser.parse_reaction().is_err());
    }

    #[test]
    fn paren_error() {
        let mut parser = Parser::new("(C");
        assert!(parser.parse_molecule().is_err());
        assert!(parser.parse_reaction().is_err());
    }

    #[test]
    fn invald_num() {
        let mut parser = Parser::new("C999999999999999999999");
        assert!(parser.parse_molecule().is_err());
        assert!(parser.parse_reaction().is_err());
    }

    #[test]
    fn dangling_plus() {
        let mut parser = Parser::new("C + -> H");
        assert!(parser.parse_reaction().is_err());
    }
}<|endoftext|>