use std::error;
use std::fmt;
use std::str;
use Error;
use OomError;
use instance::loader::LoadingError;
macro_rules! extensions {
($sname:ident, $rawname:ident, $($ext:ident => $s:expr,)*) => (
#[derive(Copy, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
pub struct $sname {
$(
pub $ext: bool,
)*
pub _unbuildable: Unbuildable,
}
impl $sname {
#[inline]
pub fn none() -> $sname {
$sname {
$($ext: false,)*
_unbuildable: Unbuildable(())
}
}
#[inline]
pub fn union(&self, other: &$sname) -> $sname {
$sname {
$(
$ext: self.$ext || other.$ext,
)*
_unbuildable: Unbuildable(())
}
}
#[inline]
pub fn intersection(&self, other: &$sname) -> $sname {
$sname {
$(
$ext: self.$ext && other.$ext,
)*
_unbuildable: Unbuildable(())
}
}
#[inline]
pub fn difference(&self, other: &$sname) -> $sname {
$sname {
$(
$ext: self.$ext && !other.$ext,
)*
_unbuildable: Unbuildable(())
}
}
}
impl fmt::Debug for $sname {
#[allow(unused_assignments)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[")?;
let mut first = true;
$(
if self.$ext {
if !first { write!(f, ", ")? }
else { first = false; }
f.write_str(str::from_utf8($s).unwrap())?;
}
)*
write!(f, "]")
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct $rawname(HashSet<CString>);
impl $rawname {
pub fn new<I>(extensions: I) -> Self
where I: IntoIterator<Item=CString>
{
$rawname(extensions.into_iter().collect())
}
pub fn none() -> Self { $rawname(HashSet::new()) }
pub fn insert(&mut self, extension: CString) {
self.0.insert(extension);
}
pub fn intersection(&self, other: &Self) -> Self {
$rawname(self.0.intersection(&other.0).cloned().collect())
}
pub fn difference(&self, other: &Self) -> Self {
$rawname(self.0.difference(&other.0).cloned().collect())
}
pub fn union(&self, other: &Self) -> Self {
$rawname(self.0.union(&other.0).cloned().collect())
}
pub fn iter(&self) -> ::std::collections::hash_set::Iter<CString> { self.0.iter() }
}
impl fmt::Debug for $rawname {
#[allow(unused_assignments)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
impl FromIterator<CString> for $rawname {
fn from_iter<T>(iter: T) -> Self
where T: IntoIterator<Item = CString>
{
$rawname(iter.into_iter().collect())
}
}
impl<'a> From<&'a $sname> for $rawname {
fn from(x: &'a $sname) -> Self {
let mut data = HashSet::new();
$(if x.$ext { data.insert(CString::new(&$s[..]).unwrap()); })*
$rawname(data)
}
}
impl<'a> From<&'a $rawname> for $sname {
fn from(x: &'a $rawname) -> Self {
let mut extensions = $sname::none();
$(
if x.0.iter().any(|x| x.as_bytes() == &$s[..]) {
extensions.$ext = true;
}
)*
extensions
}
}
);
}
#[derive(Clone, Debug)]
pub enum SupportedExtensionsError {
LoadingError(LoadingError),
OomError(OomError),
}
impl error::Error for SupportedExtensionsError {
#[inline]
fn description(&self) -> &str {
match *self {
SupportedExtensionsError::LoadingError(_) => "failed to load the Vulkan shared library",
SupportedExtensionsError::OomError(_) => "not enough memory available",
}
}
#[inline]
fn cause(&self) -> Option<&dyn error::Error> {
match *self {
SupportedExtensionsError::LoadingError(ref err) => Some(err),
SupportedExtensionsError::OomError(ref err) => Some(err),
}
}
}
impl fmt::Display for SupportedExtensionsError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", error::Error::description(self))
}
}
impl From<OomError> for SupportedExtensionsError {
#[inline]
fn from(err: OomError) -> SupportedExtensionsError {
SupportedExtensionsError::OomError(err)
}
}
impl From<LoadingError> for SupportedExtensionsError {
#[inline]
fn from(err: LoadingError) -> SupportedExtensionsError {
SupportedExtensionsError::LoadingError(err)
}
}
impl From<Error> for SupportedExtensionsError {
#[inline]
fn from(err: Error) -> SupportedExtensionsError {
match err {
err @ Error::OutOfHostMemory => {
SupportedExtensionsError::OomError(OomError::from(err))
},
err @ Error::OutOfDeviceMemory => {
SupportedExtensionsError::OomError(OomError::from(err))
},
_ => panic!("unexpected error: {:?}", err),
}
}
}