use std::{
    borrow::{Borrow, Cow},
    fmt,
    hash::{Hash, Hasher},
    iter,
    marker::PhantomData,
    ops::Deref,
    ptr, slice,
    str::FromStr,
};
use crate::{prelude::*, translate::*, BoolError, Type};
#[doc(alias = "GVariantType")]
pub struct VariantType {
    ptr: ptr::NonNull<ffi::GVariantType>,
    len: usize,
}
impl VariantType {
    pub fn new(type_string: &str) -> Result<VariantType, BoolError> {
        VariantTy::new(type_string).map(ToOwned::to_owned)
    }
    #[doc(alias = "g_variant_type_new_dict_entry")]
    pub fn new_dict_entry(key_type: &VariantTy, value_type: &VariantTy) -> VariantType {
        unsafe {
            from_glib_full(ffi::g_variant_type_new_dict_entry(
                key_type.to_glib_none().0,
                value_type.to_glib_none().0,
            ))
        }
    }
    #[doc(alias = "g_variant_type_new_array")]
    pub fn new_array(elem_type: &VariantTy) -> VariantType {
        unsafe { from_glib_full(ffi::g_variant_type_new_array(elem_type.to_glib_none().0)) }
    }
    #[doc(alias = "g_variant_type_new_maybe")]
    pub fn new_maybe(child_type: &VariantTy) -> VariantType {
        unsafe { from_glib_full(ffi::g_variant_type_new_maybe(child_type.to_glib_none().0)) }
    }
    #[doc(alias = "g_variant_type_new_tuple")]
    pub fn new_tuple(items: impl IntoIterator<Item = impl AsRef<VariantTy>>) -> VariantType {
        let mut builder = crate::GStringBuilder::new("(");
        for ty in items {
            builder.append(ty.as_ref().as_str());
        }
        builder.append_c(')');
        VariantType::from_string(builder.into_string()).unwrap()
    }
    pub fn from_string(type_string: impl Into<crate::GString>) -> Result<VariantType, BoolError> {
        let type_string = type_string.into();
        VariantTy::new(&type_string)?;
        let len = type_string.len();
        unsafe {
            let ptr = type_string.into_glib_ptr();
            Ok(VariantType {
                ptr: ptr::NonNull::new_unchecked(ptr as *mut ffi::GVariantType),
                len,
            })
        }
    }
}
unsafe impl Send for VariantType {}
unsafe impl Sync for VariantType {}
impl Drop for VariantType {
    #[inline]
    fn drop(&mut self) {
        unsafe { ffi::g_variant_type_free(self.ptr.as_ptr()) }
    }
}
impl AsRef<VariantTy> for VariantType {
    #[inline]
    fn as_ref(&self) -> &VariantTy {
        self
    }
}
impl Borrow<VariantTy> for VariantType {
    #[inline]
    fn borrow(&self) -> &VariantTy {
        self
    }
}
impl Clone for VariantType {
    #[inline]
    fn clone(&self) -> VariantType {
        unsafe {
            VariantType {
                ptr: ptr::NonNull::new_unchecked(ffi::g_variant_type_copy(self.ptr.as_ptr())),
                len: self.len,
            }
        }
    }
}
impl Deref for VariantType {
    type Target = VariantTy;
    #[allow(clippy::cast_slice_from_raw_parts)]
    #[inline]
    fn deref(&self) -> &VariantTy {
        unsafe {
            &*(slice::from_raw_parts(self.ptr.as_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.as_str())
    }
}
impl FromStr for VariantType {
    type Err = BoolError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Self::new(s)
    }
}
impl Hash for VariantType {
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        <VariantTy as Hash>::hash(self, state)
    }
}
impl<'a> From<VariantType> for Cow<'a, VariantTy> {
    #[inline]
    fn from(ty: VariantType) -> Cow<'a, VariantTy> {
        Cow::Owned(ty)
    }
}
#[doc(hidden)]
impl IntoGlibPtr<*mut ffi::GVariantType> for VariantType {
    #[inline]
    unsafe fn into_glib_ptr(self) -> *mut ffi::GVariantType {
        std::mem::ManuallyDrop::new(self).to_glib_none().0
    }
}
#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *const ffi::GVariantType> for VariantType {
    type Storage = PhantomData<&'a Self>;
    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GVariantType, Self> {
        Stash(self.ptr.as_ptr(), PhantomData)
    }
    #[inline]
    fn to_glib_full(&self) -> *const ffi::GVariantType {
        unsafe { ffi::g_variant_type_copy(self.ptr.as_ptr()) }
    }
}
#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *mut ffi::GVariantType> for VariantType {
    type Storage = PhantomData<&'a Self>;
    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::GVariantType, Self> {
        Stash(self.ptr.as_ptr(), PhantomData)
    }
    #[inline]
    fn to_glib_full(&self) -> *mut ffi::GVariantType {
        unsafe { ffi::g_variant_type_copy(self.ptr.as_ptr()) }
    }
}
#[doc(hidden)]
impl<'a> ToGlibPtrMut<'a, *mut ffi::GVariantType> for VariantType {
    type Storage = PhantomData<&'a mut Self>;
    #[inline]
    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::GVariantType, Self> {
        StashMut(self.ptr.as_ptr(), PhantomData)
    }
}
#[doc(hidden)]
impl FromGlibPtrNone<*const ffi::GVariantType> for VariantType {
    #[inline]
    unsafe fn from_glib_none(ptr: *const ffi::GVariantType) -> VariantType {
        VariantTy::from_ptr(ptr).to_owned()
    }
}
#[doc(hidden)]
impl FromGlibPtrFull<*const ffi::GVariantType> for VariantType {
    #[inline]
    unsafe fn from_glib_full(ptr: *const ffi::GVariantType) -> VariantType {
        VariantTy::from_ptr(ptr).to_owned()
    }
}
#[doc(hidden)]
impl FromGlibPtrFull<*mut ffi::GVariantType> for VariantType {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::GVariantType) -> VariantType {
        debug_assert!(!ptr.is_null());
        let len: usize = ffi::g_variant_type_get_string_length(ptr) as _;
        VariantType {
            ptr: ptr::NonNull::new_unchecked(ptr),
            len,
        }
    }
}
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct VariantTy {
    inner: str,
}
impl VariantTy {
    #[doc(alias = "G_VARIANT_TYPE_BOOLEAN")]
    pub const BOOLEAN: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BOOLEAN) };
    #[doc(alias = "G_VARIANT_TYPE_BYTE")]
    pub const BYTE: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE) };
    #[doc(alias = "G_VARIANT_TYPE_INT16")]
    pub const INT16: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT16) };
    #[doc(alias = "G_VARIANT_TYPE_UINT16")]
    pub const UINT16: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT16) };
    #[doc(alias = "G_VARIANT_TYPE_INT32")]
    pub const INT32: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT32) };
    #[doc(alias = "G_VARIANT_TYPE_UINT32")]
    pub const UINT32: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT32) };
    #[doc(alias = "G_VARIANT_TYPE_INT64")]
    pub const INT64: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT64) };
    #[doc(alias = "G_VARIANT_TYPE_UINT64")]
    pub const UINT64: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT64) };
    #[doc(alias = "G_VARIANT_TYPE_DOUBLE")]
    pub const DOUBLE: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DOUBLE) };
    #[doc(alias = "G_VARIANT_TYPE_STRING")]
    pub const STRING: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_STRING) };
    #[doc(alias = "G_VARIANT_TYPE_OBJECT_PATH")]
    pub const OBJECT_PATH: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_OBJECT_PATH) };
    #[doc(alias = "G_VARIANT_TYPE_SIGNATURE")]
    pub const SIGNATURE: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_SIGNATURE) };
    #[doc(alias = "G_VARIANT_TYPE_VARIANT")]
    pub const VARIANT: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_VARIANT) };
    #[doc(alias = "G_VARIANT_TYPE_HANDLE")]
    pub const HANDLE: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_HANDLE) };
    #[doc(alias = "G_VARIANT_TYPE_UNIT")]
    pub const UNIT: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UNIT) };
    #[doc(alias = "G_VARIANT_TYPE_ANY")]
    pub const ANY: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_ANY) };
    #[doc(alias = "G_VARIANT_TYPE_BASIC")]
    pub const BASIC: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BASIC) };
    #[doc(alias = "G_VARIANT_TYPE_MAYBE")]
    pub const MAYBE: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_MAYBE) };
    #[doc(alias = "G_VARIANT_TYPE_ARRAY")]
    pub const ARRAY: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_ARRAY) };
    #[doc(alias = "G_VARIANT_TYPE_TUPLE")]
    pub const TUPLE: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_TUPLE) };
    #[doc(alias = "G_VARIANT_TYPE_DICT_ENTRY")]
    pub const DICT_ENTRY: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DICT_ENTRY) };
    #[doc(alias = "G_VARIANT_TYPE_DICTIONARY")]
    pub const DICTIONARY: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DICTIONARY) };
    #[doc(alias = "G_VARIANT_TYPE_STRING_ARRAY")]
    pub const STRING_ARRAY: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_STRING_ARRAY) };
    #[doc(alias = "G_VARIANT_TYPE_OBJECT_PATH_ARRAY")]
    pub const OBJECT_PATH_ARRAY: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_OBJECT_PATH_ARRAY) };
    #[doc(alias = "G_VARIANT_TYPE_BYTE_STRING")]
    pub const BYTE_STRING: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE_STRING) };
    #[doc(alias = "G_VARIANT_TYPE_BYTE_STRING_ARRAY")]
    pub const BYTE_STRING_ARRAY: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE_STRING_ARRAY) };
    #[doc(alias = "G_VARIANT_TYPE_VARDICT")]
    pub const VARDICT: &'static VariantTy =
        unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_VARDICT) };
    pub fn new(type_string: &str) -> Result<&VariantTy, BoolError> {
        unsafe {
            let ptr = type_string.as_ptr();
            let limit = ptr.add(type_string.len());
            let mut end = ptr::null();
            let ok = from_glib(ffi::g_variant_type_string_scan(
                ptr as *const _,
                limit as *const _,
                &mut end,
            ));
            if ok && end as *const _ == limit {
                Ok(&*(type_string.as_bytes() as *const [u8] as *const VariantTy))
            } else {
                Err(bool_error!("Invalid type string: '{}'", type_string))
            }
        }
    }
    #[inline]
    pub const unsafe fn from_str_unchecked(type_string: &str) -> &VariantTy {
        std::mem::transmute::<&str, &VariantTy>(type_string)
    }
    #[doc(hidden)]
    #[allow(clippy::cast_slice_from_raw_parts)]
    #[inline]
    pub unsafe fn from_ptr<'a>(ptr: *const ffi::GVariantType) -> &'a VariantTy {
        debug_assert!(!ptr.is_null());
        let len: usize = ffi::g_variant_type_get_string_length(ptr) as _;
        debug_assert!(len > 0);
        &*(slice::from_raw_parts(ptr as *const u8, len) as *const [u8] as *const VariantTy)
    }
    #[doc(hidden)]
    #[inline]
    pub fn as_ptr(&self) -> *const ffi::GVariantType {
        self.inner.as_ptr() as *const _
    }
    #[inline]
    pub fn as_str(&self) -> &str {
        &self.inner
    }
    #[doc(alias = "g_variant_type_is_definite")]
    pub fn is_definite(&self) -> bool {
        unsafe { from_glib(ffi::g_variant_type_is_definite(self.to_glib_none().0)) }
    }
    #[doc(alias = "g_variant_type_is_container")]
    pub fn is_container(&self) -> bool {
        unsafe { from_glib(ffi::g_variant_type_is_container(self.to_glib_none().0)) }
    }
    #[doc(alias = "g_variant_type_is_basic")]
    pub fn is_basic(&self) -> bool {
        unsafe { from_glib(ffi::g_variant_type_is_basic(self.to_glib_none().0)) }
    }
    #[doc(alias = "g_variant_type_is_maybe")]
    pub fn is_maybe(&self) -> bool {
        unsafe { from_glib(ffi::g_variant_type_is_maybe(self.to_glib_none().0)) }
    }
    #[doc(alias = "g_variant_type_is_array")]
    pub fn is_array(&self) -> bool {
        unsafe { from_glib(ffi::g_variant_type_is_array(self.to_glib_none().0)) }
    }
    #[doc(alias = "g_variant_type_is_tuple")]
    pub fn is_tuple(&self) -> bool {
        unsafe { from_glib(ffi::g_variant_type_is_tuple(self.to_glib_none().0)) }
    }
    #[doc(alias = "g_variant_type_is_dict_entry")]
    pub fn is_dict_entry(&self) -> bool {
        unsafe { from_glib(ffi::g_variant_type_is_dict_entry(self.to_glib_none().0)) }
    }
    #[doc(alias = "g_variant_type_is_variant")]
    pub fn is_variant(&self) -> bool {
        unsafe { from_glib(ffi::g_variant_type_is_variant(self.to_glib_none().0)) }
    }
    #[doc(alias = "g_variant_type_is_subtype_of")]
    pub fn is_subtype_of(&self, supertype: &Self) -> bool {
        unsafe {
            from_glib(ffi::g_variant_type_is_subtype_of(
                self.to_glib_none().0,
                supertype.to_glib_none().0,
            ))
        }
    }
    #[doc(alias = "g_variant_type_element")]
    pub fn element(&self) -> &VariantTy {
        assert!(self.is_array() || self.is_maybe());
        unsafe {
            let element = ffi::g_variant_type_element(self.to_glib_none().0);
            Self::from_ptr(element)
        }
    }
    pub fn tuple_types(&self) -> VariantTyIterator {
        VariantTyIterator::new(self).expect("VariantTy does not represent a tuple")
    }
    #[doc(alias = "g_variant_type_first")]
    pub fn first(&self) -> Option<&VariantTy> {
        assert!(self.as_str().starts_with('(') || self.as_str().starts_with('{'));
        unsafe {
            let first = ffi::g_variant_type_first(self.to_glib_none().0);
            if first.is_null() {
                None
            } else {
                Some(Self::from_ptr(first))
            }
        }
    }
    #[doc(alias = "g_variant_type_next")]
    pub fn next(&self) -> Option<&VariantTy> {
        unsafe {
            let next = ffi::g_variant_type_next(self.to_glib_none().0);
            if next.is_null() {
                None
            } else {
                Some(Self::from_ptr(next))
            }
        }
    }
    #[doc(alias = "g_variant_type_n_items")]
    pub fn n_items(&self) -> usize {
        unsafe { ffi::g_variant_type_n_items(self.to_glib_none().0) }
    }
    #[doc(alias = "g_variant_type_key")]
    pub fn key(&self) -> &VariantTy {
        assert!(self.as_str().starts_with('{'));
        unsafe {
            let key = ffi::g_variant_type_key(self.to_glib_none().0);
            Self::from_ptr(key)
        }
    }
    #[doc(alias = "g_variant_type_value")]
    pub fn value(&self) -> &VariantTy {
        assert!(self.as_str().starts_with('{'));
        unsafe {
            let value = ffi::g_variant_type_value(self.to_glib_none().0);
            Self::from_ptr(value)
        }
    }
    pub(crate) fn as_array<'a>(&self) -> Cow<'a, VariantTy> {
        if self == VariantTy::STRING {
            Cow::Borrowed(VariantTy::STRING_ARRAY)
        } else if self == VariantTy::BYTE {
            Cow::Borrowed(VariantTy::BYTE_STRING)
        } else if self == VariantTy::BYTE_STRING {
            Cow::Borrowed(VariantTy::BYTE_STRING_ARRAY)
        } else if self == VariantTy::OBJECT_PATH {
            Cow::Borrowed(VariantTy::OBJECT_PATH_ARRAY)
        } else if self == VariantTy::DICT_ENTRY {
            Cow::Borrowed(VariantTy::DICTIONARY)
        } else {
            Cow::Owned(VariantType::new_array(self))
        }
    }
}
unsafe impl Sync for VariantTy {}
#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *const ffi::GVariantType> for VariantTy {
    type Storage = PhantomData<&'a Self>;
    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GVariantType, Self> {
        Stash(self.as_ptr(), PhantomData)
    }
}
impl fmt::Display for VariantTy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.as_str())
    }
}
impl<'a> From<&'a VariantTy> for Cow<'a, VariantTy> {
    #[inline]
    fn from(ty: &'a VariantTy) -> Cow<'a, VariantTy> {
        Cow::Borrowed(ty)
    }
}
impl AsRef<VariantTy> for VariantTy {
    #[inline]
    fn as_ref(&self) -> &Self {
        self
    }
}
impl ToOwned for VariantTy {
    type Owned = VariantType;
    #[inline]
    fn to_owned(&self) -> VariantType {
        unsafe {
            VariantType {
                ptr: ptr::NonNull::new_unchecked(ffi::g_variant_type_copy(self.as_ptr())),
                len: self.inner.len(),
            }
        }
    }
}
impl StaticType for VariantTy {
    #[inline]
    fn static_type() -> Type {
        unsafe { from_glib(ffi::g_variant_type_get_gtype()) }
    }
}
#[doc(hidden)]
unsafe impl<'a> crate::value::FromValue<'a> for &'a VariantTy {
    type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
    unsafe fn from_value(value: &'a crate::Value) -> Self {
        let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
        debug_assert!(!ptr.is_null());
        VariantTy::from_ptr(ptr as *const ffi::GVariantType)
    }
}
#[doc(hidden)]
impl crate::value::ToValue for VariantTy {
    fn to_value(&self) -> crate::Value {
        unsafe {
            let mut value = crate::Value::from_type_unchecked(VariantTy::static_type());
            gobject_ffi::g_value_set_boxed(
                value.to_glib_none_mut().0,
                self.to_glib_none().0 as *mut _,
            );
            value
        }
    }
    fn value_type(&self) -> crate::Type {
        VariantTy::static_type()
    }
}
#[doc(hidden)]
impl crate::value::ToValue for &VariantTy {
    fn to_value(&self) -> crate::Value {
        (*self).to_value()
    }
    #[inline]
    fn value_type(&self) -> crate::Type {
        VariantTy::static_type()
    }
}
#[doc(hidden)]
impl crate::value::ToValueOptional for &VariantTy {
    fn to_value_optional(s: Option<&Self>) -> crate::Value {
        let mut value = crate::Value::for_value_type::<VariantType>();
        unsafe {
            gobject_ffi::g_value_set_boxed(
                value.to_glib_none_mut().0,
                s.to_glib_none().0 as *mut _,
            );
        }
        value
    }
}
impl StaticType for VariantType {
    #[inline]
    fn static_type() -> Type {
        unsafe { from_glib(ffi::g_variant_type_get_gtype()) }
    }
}
#[doc(hidden)]
impl crate::value::ValueType for VariantType {
    type Type = VariantType;
}
#[doc(hidden)]
impl crate::value::ValueTypeOptional for VariantType {}
#[doc(hidden)]
unsafe impl<'a> crate::value::FromValue<'a> for VariantType {
    type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
    unsafe fn from_value(value: &'a crate::Value) -> Self {
        let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
        debug_assert!(!ptr.is_null());
        from_glib_none(ptr as *const ffi::GVariantType)
    }
}
#[doc(hidden)]
impl crate::value::ToValue for VariantType {
    fn to_value(&self) -> crate::Value {
        unsafe {
            let mut value = crate::Value::from_type_unchecked(VariantType::static_type());
            gobject_ffi::g_value_set_boxed(
                value.to_glib_none_mut().0,
                ToGlibPtr::<*mut _>::to_glib_none(&self).0 as *mut _,
            );
            value
        }
    }
    fn value_type(&self) -> crate::Type {
        VariantType::static_type()
    }
}
#[doc(hidden)]
impl From<VariantType> for crate::Value {
    fn from(t: VariantType) -> Self {
        unsafe {
            let mut value = crate::Value::from_type_unchecked(VariantType::static_type());
            gobject_ffi::g_value_take_boxed(
                value.to_glib_none_mut().0,
                IntoGlibPtr::<*mut _>::into_glib_ptr(t) as *mut _,
            );
            value
        }
    }
}
#[doc(hidden)]
impl crate::value::ToValueOptional for VariantType {
    fn to_value_optional(s: Option<&Self>) -> crate::Value {
        let mut value = crate::Value::for_value_type::<Self>();
        unsafe {
            gobject_ffi::g_value_set_boxed(
                value.to_glib_none_mut().0,
                ToGlibPtr::<*mut _>::to_glib_none(&s).0 as *mut _,
            );
        }
        value
    }
}
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) => {
        #[allow(clippy::extra_unused_lifetimes)]
        impl<'a, 'b> PartialEq<$rhs> for $lhs {
            #[inline]
            fn eq(&self, other: &$rhs) -> bool {
                <VariantTy as PartialEq>::eq(self, other)
            }
        }
        #[allow(clippy::extra_unused_lifetimes)]
        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) => {
        #[allow(clippy::redundant_slicing)]
        #[allow(clippy::extra_unused_lifetimes)]
        impl<'a, 'b> PartialEq<$rhs> for $lhs {
            #[inline]
            fn eq(&self, other: &$rhs) -> bool {
                self.as_str().eq(&other[..])
            }
        }
        #[allow(clippy::extra_unused_lifetimes)]
        impl<'a, 'b> PartialEq<$lhs> for $rhs {
            #[inline]
            fn eq(&self, other: &$lhs) -> bool {
                self[..].eq(other.as_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 {}
#[derive(Debug, Copy, Clone)]
pub struct VariantTyIterator<'a> {
    elem: Option<&'a VariantTy>,
}
impl<'a> VariantTyIterator<'a> {
    pub fn new(ty: &'a VariantTy) -> Result<Self, BoolError> {
        if (ty.is_tuple() && ty != VariantTy::TUPLE) || ty.is_dict_entry() {
            Ok(Self { elem: ty.first() })
        } else {
            Err(bool_error!(
                "Expected a definite tuple or dictionary entry type"
            ))
        }
    }
}
impl<'a> Iterator for VariantTyIterator<'a> {
    type Item = &'a VariantTy;
    #[doc(alias = "g_variant_type_next")]
    fn next(&mut self) -> Option<Self::Item> {
        let elem = self.elem?;
        self.elem = elem.next();
        Some(elem)
    }
}
impl<'a> iter::FusedIterator for VariantTyIterator<'a> {}
#[cfg(test)]
mod tests {
    use super::*;
    unsafe fn equal<T, U>(ptr1: *const T, ptr2: *const U) -> bool {
        from_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_ne!(ty1, ty2);
        assert_ne!(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);
        let ty3 = VariantTy::new("*").unwrap();
        let tyv2 = ty3.to_value();
        let ty4 = tyv2.get::<VariantType>().unwrap();
        assert_eq!(ty3, ty4);
        let ty5 = VariantTy::ANY;
        let tyv3 = ty5.to_value();
        let ty6 = tyv3.get::<VariantType>().unwrap();
        assert_eq!(ty5, ty6);
    }
    #[test]
    fn type_() {
        assert_eq!(VariantTy::static_type(), VariantType::static_type())
    }
    #[test]
    fn tuple_iter() {
        let ty = VariantTy::new("((iii)s)").unwrap();
        let types: Vec<_> = ty.tuple_types().map(|t| t.as_str()).collect();
        assert_eq!(&types, &["(iii)", "s"]);
    }
}