Newer
Older
/// Loops through the attributes once and pulls out the ones we ask it to. It
/// will check that the required ones are there. This could have been done with
/// attrs.find but that would be inefficient.
///
/// This is probably a really terrible way to do this. It does cut down on lines
/// though which is nice.
macro_rules! get_attrs {
($attrs:expr, optionals: [$(($oName:pat, $oVar:ident, $oMethod:expr)),* $(,)*],
required: [$(($name:pat, $var:ident, $method:expr)),* $(,)*], $err:expr) => {
{
$(let mut $oVar = None;)*
$(let mut $var = None;)*
for attr in $attrs.iter() {
match attr.name.local_name.as_ref() {
$($oName => $oVar = $oMethod(attr.value.clone()),)*
$($name => $var = $method(attr.value.clone()),)*
_ => {}
}
}
if !(true $(&& $var.is_some())*) {
return Err($err);
}
(($($oVar),*), ($($var.unwrap()),*))
}
}
}
/// Goes through the children of the tag and will call the correct function for
macro_rules! parse_tag {
($parser:expr, $close_tag:expr, {$($open_tag:expr => $open_method:expr),* $(,)*}) => {
while let Some(next) = $parser.next() {
match next.map_err(TiledError::XmlDecodingError)? {
xml::reader::XmlEvent::StartElement {name, attributes, ..} => {
if false {}
$(else if name.local_name == $open_tag {
match $open_method(attributes) {
Ok(()) => {},
Err(e) => return Err(e)
};
})*
}
xml::reader::XmlEvent::EndElement {name, ..} => {
if name.local_name == $close_tag {
break;
}
}
xml::reader::XmlEvent::EndDocument => return Err(TiledError::PrematureEnd("Document ended before we expected.".to_string())),
_ => {}
}
}
}
}
/// Creates a new type that wraps an internal data type over along with a map.
macro_rules! map_wrapper {
($name:ident => $data_ty:ty) => {
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct $name<'map> {
pub(crate) map: &'map $crate::Map,
pub(crate) data: &'map $data_ty,
}
impl<'map> $name<'map> {
pub(crate) fn new(map: &'map $crate::Map, data: &'map $data_ty) -> Self {
Self { map, data }
}
/// Get the map this object is from.
pub fn map(&self) -> &'map $crate::Map {
self.map
}
}
};
}
pub(crate) use map_wrapper;
pub(crate) type XmlEventResult = xml::reader::Result<xml::reader::XmlEvent>;
/// Returns both the tileset and its index
pub(crate) fn get_tileset_for_gid(
tilesets: &[MapTilesetGid],
gid: Gid,
) -> Option<(usize, &MapTilesetGid)> {
tilesets
.iter()
.enumerate()
.rev()
.find(|(_idx, ts)| ts.first_gid <= gid)