// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms.
use std; use std::fmt; use std::marker::PhantomData; use std::mem; use std::mem::ManuallyDrop; use std::ops::{Deref, DerefMut}; use std::os::raw::c_void;
pubtrait CFIndexConvertible { /// Always use this method to construct a `CFIndex` value. It performs bounds checking to /// ensure the value is in range. fn to_CFIndex(self) -> CFIndex;
}
impl CFIndexConvertible for usize { #[inline] fn to_CFIndex(self) -> CFIndex { let max_CFIndex = CFIndex::max_value(); ifself > (max_CFIndex as usize) {
panic!("value out of range")
} selfas CFIndex
}
}
declare_TCFType! { /// Superclass of all Core Foundation objects.
CFType, CFTypeRef
}
impl CFType { /// Try to downcast the `CFType` to a subclass. Checking if the instance is the /// correct subclass happens at runtime and `None` is returned if it is not the correct type. /// Works similar to [`Box::downcast`] and [`CFPropertyList::downcast`]. /// /// # Examples /// /// ``` /// # use core_foundation::string::CFString; /// # use core_foundation::boolean::CFBoolean; /// # use core_foundation::base::{CFType, TCFType}; /// # /// // Create a string. /// let string: CFString = CFString::from_static_string("FooBar"); /// // Cast it up to a CFType. /// let cf_type: CFType = string.as_CFType(); /// // Cast it down again. /// assert_eq!(cf_type.downcast::<CFString>().unwrap().to_string(), "FooBar"); /// // Casting it to some other type will yield `None` /// assert!(cf_type.downcast::<CFBoolean>().is_none()); /// ``` /// /// ```compile_fail /// # use core_foundation::array::CFArray; /// # use core_foundation::base::TCFType; /// # use core_foundation::boolean::CFBoolean; /// # use core_foundation::string::CFString; /// # /// let boolean_array = CFArray::from_CFTypes(&[CFBoolean::true_value()]).into_CFType(); /// /// // This downcast is not allowed and causes compiler error, since it would cause undefined /// // behavior to access the elements of the array as a CFString: /// let invalid_string_array = boolean_array /// .downcast_into::<CFArray<CFString>>() /// .unwrap(); /// ``` /// /// [`Box::downcast`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast /// [`CFPropertyList::downcast`]: ../propertylist/struct.CFPropertyList.html#method.downcast #[inline] pubfn downcast<T: ConcreteCFType>(&self) -> Option<T> { ifself.instance_of::<T>() { unsafe { let reference = T::Ref::from_void_ptr(self.0);
Some(T::wrap_under_get_rule(reference))
}
} else {
None
}
}
/// Similar to [`downcast`], but consumes self and can thus avoid touching the retain count. /// /// [`downcast`]: #method.downcast #[inline] pubfn downcast_into<T: ConcreteCFType>(self) -> Option<T> { ifself.instance_of::<T>() { unsafe { let reference = T::Ref::from_void_ptr(self.0);
mem::forget(self);
Some(T::wrap_under_create_rule(reference))
}
} else {
None
}
}
}
/// All Core Foundation types implement this trait. The associated type `Ref` specifies the /// associated Core Foundation type: e.g. for `CFType` this is `CFTypeRef`; for `CFArray` this is /// `CFArrayRef`. /// /// Most structs that implement this trait will do so via the [`impl_TCFType`] macro. /// /// [`impl_TCFType`]: ../macro.impl_TCFType.html pubtrait TCFType { /// The reference type wrapped inside this type. typeRef: TCFTypeRef;
/// Returns the object as its concrete `TypeRef`. fn as_concrete_TypeRef(&self) -> Self::Ref;
/// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this /// when following Core Foundation's "Create Rule". The reference count is *not* bumped. unsafefn wrap_under_create_rule(obj: Self::Ref) -> Self;
/// Returns the type ID for this class. fn type_id() -> CFTypeID;
/// Returns the object as a wrapped `CFType`. The reference count is incremented by one. #[inline] fn as_CFType(&self) -> CFType { unsafe { TCFType::wrap_under_get_rule(self.as_CFTypeRef()) }
}
/// Returns the object as a wrapped `CFType`. Consumes self and avoids changing the reference /// count. #[inline] fn into_CFType(self) -> CFType where Self: Sized,
{ let reference = self.as_CFTypeRef();
mem::forget(self); unsafe { TCFType::wrap_under_create_rule(reference) }
}
/// Returns the object as a raw `CFTypeRef`. The reference count is not adjusted. fn as_CFTypeRef(&self) -> CFTypeRef;
/// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this /// when following Core Foundation's "Get Rule". The reference count *is* bumped. unsafefn wrap_under_get_rule(reference: Self::Ref) -> Self;
/// Returns the reference count of the object. It is unwise to do anything other than test /// whether the return value of this method is greater than zero. #[inline] fn retain_count(&self) -> CFIndex { unsafe { CFGetRetainCount(self.as_CFTypeRef()) }
}
/// Returns the type ID of this object. #[inline] fn type_of(&self) -> CFTypeID { unsafe { CFGetTypeID(self.as_CFTypeRef()) }
}
/// Writes a debugging version of this object on standard error. fn show(&self) { unsafe { CFShow(self.as_CFTypeRef()) }
}
/// Returns `true` if this value is an instance of another type. #[inline] fn instance_of<OtherCFType: TCFType>(&self) -> bool { self.type_of() == OtherCFType::type_id()
}
}
/// A trait describing how to convert from the stored `*mut c_void` to the desired `T` pubunsafetrait FromMutVoid { unsafefn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self> where Self: std::marker::Sized;
}
unsafeimpl FromMutVoid for u32 { unsafefn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self> {
ItemMutRef(ManuallyDrop::new(x as u32), PhantomData)
}
}
unsafeimpl<T: TCFType> FromMutVoid for T { unsafefn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self> {
ItemMutRef(
ManuallyDrop::new(TCFType::wrap_under_create_rule(T::Ref::from_void_ptr(x))),
PhantomData,
)
}
}
/// A trait describing how to convert from the stored `*const c_void` to the desired `T` pubunsafetrait FromVoid { unsafefn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> where Self: std::marker::Sized;
}
unsafeimpl FromVoid for u32 { unsafefn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> { // Functions like CGFontCopyTableTags treat the void*'s as u32's // so we convert by casting directly
ItemRef(ManuallyDrop::new(x as u32), PhantomData)
}
}
unsafeimpl<T: TCFType> FromVoid for T { unsafefn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> {
ItemRef(
ManuallyDrop::new(TCFType::wrap_under_create_rule(T::Ref::from_void_ptr(x))),
PhantomData,
)
}
}
/// A trait describing how to convert from the stored `*const c_void` to the desired `T` pubunsafetrait ToVoid<T> { fn to_void(&self) -> *const c_void;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.