From 4bfb324dd9f7c25f95a80ed0a520453ba33dab0e Mon Sep 17 00:00:00 2001
From: Alejandro Perea <alexpro820@gmail.com>
Date: Fri, 4 Mar 2022 12:08:50 +0100
Subject: [PATCH] Add preliminary documentation (#174)

* Warn on missing docs

* Add some documentation and fix examples

* More documentation

* More docs

* More docs

* Fix object colour docs

* Finish documenting

* Misc changes

* Address PR comment
---
 README.md                   | 29 +++++++++--------
 src/animation.rs            | 16 ++++++++--
 src/cache.rs                | 27 ++++++++++++++++
 src/error.rs                | 18 +++++++++--
 src/image.rs                |  4 +++
 src/layers/group.rs         | 11 ++++++-
 src/layers/image.rs         |  6 +++-
 src/layers/mod.rs           | 10 +++++-
 src/layers/object.rs        | 14 +++++++-
 src/layers/tile/finite.rs   |  8 ++++-
 src/layers/tile/infinite.rs | 17 ++++++++--
 src/layers/tile/mod.rs      | 11 ++++++-
 src/lib.rs                  |  3 ++
 src/map.rs                  |  6 ++++
 src/objects.rs              | 64 ++++++++++++++++++++++++++++++-------
 src/properties.rs           | 17 ++++++++--
 src/tile.rs                 |  2 ++
 src/tileset.rs              | 22 ++++++++++++-
 src/util.rs                 |  3 +-
 19 files changed, 246 insertions(+), 42 deletions(-)

diff --git a/README.md b/README.md
index 33eae93..05157f1 100644
--- a/README.md
+++ b/README.md
@@ -1,36 +1,39 @@
 # rs-tiled
+```toml
+tiled = "0.9.5"
+```
 
 [![Rust](https://github.com/mapeditor/rs-tiled/actions/workflows/rust.yml/badge.svg)](https://github.com/mapeditor/rs-tiled/actions/workflows/rust.yml)
 [![Crates.io](https://img.shields.io/crates/v/tiled.svg)](https://crates.io/crates/tiled)
 
-Read maps from the [Tiled Map Editor](http://www.mapeditor.org/) into rust for use in video games. It is game engine agnostic and pretty barebones at the moment. Documentation is available [on docs.rs](https://docs.rs/tiled/).
-
-Code contributions are welcome as are bug reports, documentation, suggestions and criticism.
-
-[There is a package on crates.io](https://crates.io/crates/tiled), to use simply add:
+A crate for reading TMX (map) and TSX (tileset) files from the [Tiled Map Editor](http://www.mapeditor.org/) into Rust.
+It provides a huge set of features as well as a strong wrapper over internal features such as GIDs.
 
-```
-tiled = "0.9.5"
-```
+Documentation is available [on docs.rs](https://docs.rs/tiled/).
 
-to the dependencies section of your Cargo.toml.
+Code contributions are welcome as are bug reports, documentation, suggestions and criticism.
 
 The minimum supported TMX version is 0.13.
 
 ### Example
 
 ```rust
-use tiled::Map;
+use tiled::{FilesystemResourceCache, Map};
 
 fn main() {
-    let map = Map::parse_file("assets/tiled_base64_zlib.tmx").unwrap();
+    let map = Map::parse_file(
+        "assets/tiled_base64_zlib.tmx",
+        &mut FilesystemResourceCache::new(),
+    )
+    .unwrap();
     println!("{:?}", map);
-    println!("{:?}", map.tileset_by_gid(22));
+    println!("{:?}", map.tilesets()[0].get_tile(0).unwrap().probability());
 }
+
 ```
 
 ### Licences
 
-assets/tilesheet.png by Buch (https://opengameart.org/content/sci-fi-interior-tiles)
+assets/tilesheet.png by [Buch](https://opengameart.org/content/sci-fi-interior-tiles)
 
 Licenced under MIT
diff --git a/src/animation.rs b/src/animation.rs
index 691b531..cb8d55e 100644
--- a/src/animation.rs
+++ b/src/animation.rs
@@ -1,10 +1,21 @@
+//! Structures related to tile animations.
+
 use xml::attribute::OwnedAttribute;
 
-use crate::{error::TiledError, util::{get_attrs, XmlEventResult, parse_tag}};
+use crate::{
+    error::TiledError,
+    util::{get_attrs, parse_tag, XmlEventResult},
+};
 
+/// A structure describing a [frame] of a [TMX tile animation].
+///
+/// [frame]: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tmx-frame
+/// [TMX tile animation]: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#animation
 #[derive(Debug, PartialEq, Clone, Copy)]
 pub struct Frame {
+    /// The local ID of a tile within the parent tileset.
     pub tile_id: u32,
+    /// How long (in milliseconds) this frame should be displayed before advancing to the next frame.
     pub duration: u32,
 }
 
@@ -26,7 +37,6 @@ impl Frame {
     }
 }
 
-
 pub(crate) fn parse_animation(
     parser: &mut impl Iterator<Item = XmlEventResult>,
 ) -> Result<Vec<Frame>, TiledError> {
@@ -38,4 +48,4 @@ pub(crate) fn parse_animation(
         },
     });
     Ok(animation)
-}
\ No newline at end of file
+}
diff --git a/src/cache.rs b/src/cache.rs
index a193a1a..5c4a330 100644
--- a/src/cache.rs
+++ b/src/cache.rs
@@ -6,11 +6,37 @@ use std::{
 
 use crate::Tileset;
 
+/// A reference type that is used to refer to a resource. For the owned variant, see [`ResourcePathBuf`].
 pub type ResourcePath = Path;
+/// An owned type that is used to refer to a resource. For the non-owned variant, see [`ResourcePath`].
 pub type ResourcePathBuf = PathBuf;
 
+/// A trait identifying a data type that holds resources (such as tilesets) and maps them to a
+/// [`ResourcePath`] to prevent loading them more than once.
 pub trait ResourceCache {
+    /// Obtains a tileset from the cache, if it exists.
+    /// 
+    /// # Example
+    /// ```
+    /// use std::fs::File;
+    /// use tiled::{FilesystemResourceCache, ResourceCache, Tileset};
+    /// # use tiled::TiledError;
+    /// # fn main() -> Result<(), TiledError> {
+    /// let mut cache = FilesystemResourceCache::new();
+    /// let path = "assets/tilesheet.tsx";
+    ///
+    /// assert!(cache.get_tileset(path).is_none());
+    /// cache.get_or_try_insert_tileset_with(path.to_owned().into(), || Tileset::parse_reader(File::open(path).unwrap(), path))?;
+    /// assert!(cache.get_tileset(path).is_some());
+    /// # Ok(())
+    /// # }
+    /// ```
     fn get_tileset(&self, path: impl AsRef<ResourcePath>) -> Option<Arc<Tileset>>;
+    
+    /// Returns the tileset mapped to `path` if it exists, otherwise calls `f` and, depending on its
+    /// result, it will:
+    /// - Insert the object into the cache, if the result was [`Ok`].
+    /// - Return the error and leave the cache intact, if the result was [`Err`].
     fn get_or_try_insert_tileset_with<F, E>(
         &mut self,
         path: ResourcePathBuf,
@@ -27,6 +53,7 @@ pub struct FilesystemResourceCache {
 }
 
 impl FilesystemResourceCache {
+    /// Creates an empty [`FilesystemResourceCache`].
     pub fn new() -> Self {
         Self {
             tilesets: HashMap::new(),
diff --git a/src/error.rs b/src/error.rs
index 3a4e834..1848dbf 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -10,30 +10,44 @@ pub enum TiledError {
     /// An error occured when decompressing using the
     /// [flate2](https://github.com/alexcrichton/flate2-rs) crate.
     DecompressingError(std::io::Error),
+    /// An error occured when decoding a base64 encoded dataset.
     Base64DecodingError(base64::DecodeError),
+    /// An error occured when parsing a XML file, such as a TMX or TSX file.
     XmlDecodingError(xml::reader::Error),
+    /// The XML stream ended before the document was fully parsed.
     PrematureEnd(String),
     /// The path given is invalid because it isn't contained in any folder.
     PathIsNotFile,
+    /// Could not open some file due to an I/O error.
     CouldNotOpenFile {
+        /// The path to the file that was unable to be opened.
         path: PathBuf,
+        /// The error that occured when trying to open the file.
         err: std::io::Error,
     },
     /// There was an invalid tile in the map parsed.
     InvalidTileFound,
     /// Unknown encoding or compression format or invalid combination of both (for tile layers)
     InvalidEncodingFormat {
+        /// The `encoding` attribute of the tile layer data, if any.
         encoding: Option<String>,
+        /// The `compression` attribute of the tile layer data, if any.
         compression: Option<String>,
     },
     /// There was an error parsing the value of a [`PropertyValue`].
     /// 
     /// [`PropertyValue`]: crate::PropertyValue
-    InvalidPropertyValue{description: String},
+    InvalidPropertyValue {
+        /// A description of the error that occured.
+        description: String
+    },
     /// Found an unknown property value type while parsing a [`PropertyValue`].
     /// 
     /// [`PropertyValue`]: crate::PropertyValue
-    UnknownPropertyType{name: String},
+    UnknownPropertyType {
+        /// The name of the property whose value type is unknown.
+        name: String
+    },
 }
 
 impl fmt::Display for TiledError {
diff --git a/src/image.rs b/src/image.rs
index 7399f38..c22b57a 100644
--- a/src/image.rs
+++ b/src/image.rs
@@ -4,6 +4,7 @@ use xml::attribute::OwnedAttribute;
 
 use crate::{error::TiledError, properties::Color, util::*};
 
+/// A reference to an image stored somewhere within the filesystem.
 #[derive(Debug, PartialEq, Eq, Clone)]
 pub struct Image {
     /// The filepath of the image.
@@ -15,8 +16,11 @@ pub struct Image {
     /// [source]: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#image
     // TODO: Embedded images
     pub source: PathBuf,
+    /// The width in pixels of the image.
     pub width: i32,
+    /// The height in pixels of the image.
     pub height: i32,
+    /// A color that should be interpreted as transparent (0 alpha), if any.
     pub transparent_colour: Option<Color>,
 }
 
diff --git a/src/layers/group.rs b/src/layers/group.rs
index f4d135d..0a4d8d2 100644
--- a/src/layers/group.rs
+++ b/src/layers/group.rs
@@ -78,12 +78,21 @@ impl GroupLayerData {
     }
 }
 
-map_wrapper!(GroupLayer => GroupLayerData);
+map_wrapper!(
+    #[doc = "A group layer, used to organize the layers of the map in a hierarchy."]
+    #[doc = "\nAlso see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#group)."]
+    #[doc = "## Note"]
+    #[doc = "In Tiled, the properties of the group layer recursively affect child layers.
+    Implementing this behavior is left up to the user of this library."]
+    GroupLayer => GroupLayerData
+);
 
 impl<'map> GroupLayer<'map> {
+    /// Returns an iterator over the layers present in this group in display order.
     pub fn layers(&self) -> GroupLayerIter {
         GroupLayerIter::new(self.map, self.data)
     }
+    /// Gets a specific layer from the group by index.
     pub fn get_layer(&self, index: usize) -> Option<Layer> {
         self.data
             .layers
diff --git a/src/layers/image.rs b/src/layers/image.rs
index e75a92b..d8c8ae8 100644
--- a/src/layers/image.rs
+++ b/src/layers/image.rs
@@ -35,7 +35,11 @@ impl ImageLayerData {
     }
 }
 
-map_wrapper!(ImageLayer => ImageLayerData);
+map_wrapper!(
+    #[doc = "A layer consisting of a single image."]
+    #[doc = "\nAlso see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#imagelayer)."]
+    ImageLayer => ImageLayerData
+);
 
 impl<'map> ImageLayer<'map> {
     /// Get a reference to the image layer's image.
diff --git a/src/layers/mod.rs b/src/layers/mod.rs
index b0b0069..56db87e 100644
--- a/src/layers/mod.rs
+++ b/src/layers/mod.rs
@@ -110,7 +110,10 @@ impl LayerData {
     }
 }
 
-map_wrapper!(Layer => LayerData);
+map_wrapper!(
+    #[doc = "A generic map layer, accessed via [`Map::layers()`]."]
+    Layer => LayerData
+);
 
 impl<'map> Layer<'map> {
     /// Get a reference to the layer's name.
@@ -180,11 +183,16 @@ impl<'map> Layer<'map> {
     }
 }
 
+/// Represents some kind of map layer.
 #[derive(Debug)]
 pub enum LayerType<'map> {
+    /// A tile layer; Also see [`TileLayer`].
     TileLayer(TileLayer<'map>),
+    /// An object layer (also called object group); Also see [`ObjectLayer`].
     ObjectLayer(ObjectLayer<'map>),
+    /// An image layer; Also see [`ImageLayer`].
     ImageLayer(ImageLayer<'map>),
+    /// A group layer; Also see [`GroupLayer`].
     GroupLayer(GroupLayer<'map>),
 }
 
diff --git a/src/layers/object.rs b/src/layers/object.rs
index c726595..500c7f6 100644
--- a/src/layers/object.rs
+++ b/src/layers/object.rs
@@ -11,7 +11,9 @@ use crate::{
 /// Raw data referring to a map object layer or tile collision data.
 #[derive(Debug, PartialEq, Clone)]
 pub struct ObjectLayerData {
+    /// The objects present in this layer.
     pub objects: Vec<ObjectData>,
+    /// The color used in the editor to display objects in this layer.
     pub colour: Option<Color>,
 }
 
@@ -48,9 +50,12 @@ impl ObjectLayerData {
     }
 }
 
-map_wrapper!(ObjectLayer => ObjectLayerData);
+map_wrapper!(
+    #[doc = "Also called an \"object group\". Used for storing [`Object`]s in a map."]
+    ObjectLayer => ObjectLayerData);
 
 impl<'map> ObjectLayer<'map> {
+    /// Obtains the object corresponding to the index given.
     pub fn get_object(&self, idx: usize) -> Option<Object<'map>> {
         self.data
             .objects
@@ -58,9 +63,16 @@ impl<'map> ObjectLayer<'map> {
             .map(|data| Object::new(self.map, data))
     }
 
+    /// Returns an iterator over the objects present in this layer, in the order they were declared
+    /// in in the TMX file.
     pub fn objects(&self) -> Objects<'map> {
         Objects::new(self.map, self.data)
     }
+
+    /// Get a reference to the object layer's colour.
+    pub fn colour(&self) -> Option<Color> {
+        self.data.colour
+    }
 }
 
 /// An iterator that iterates over all the objects in an object layer, obtained via [`ObjectLayer::objects`].
diff --git a/src/layers/tile/finite.rs b/src/layers/tile/finite.rs
index 2e2c0cc..e76eabe 100644
--- a/src/layers/tile/finite.rs
+++ b/src/layers/tile/finite.rs
@@ -60,9 +60,15 @@ impl FiniteTileLayerData {
     }
 }
 
-map_wrapper!(FiniteTileLayer => FiniteTileLayerData);
+map_wrapper!(
+    #[doc = "A [`TileLayer`](super::TileLayer) with a defined bound (width and height)."]
+    FiniteTileLayer => FiniteTileLayerData
+);
 
 impl<'map> FiniteTileLayer<'map> {
+    /// Obtains the tile present at the position given.
+    /// 
+    /// If the position given is invalid or the position is empty, this function will return [`None`].
     pub fn get_tile(&self, x: i32, y: i32) -> Option<LayerTile> {
         self.data
             .get_tile(x, y)
diff --git a/src/layers/tile/infinite.rs b/src/layers/tile/infinite.rs
index 96c8f67..f7d70fc 100644
--- a/src/layers/tile/infinite.rs
+++ b/src/layers/tile/infinite.rs
@@ -4,7 +4,7 @@ use xml::attribute::OwnedAttribute;
 
 use crate::{
     util::{floor_div, get_attrs, map_wrapper, parse_tag, XmlEventResult},
-    LayerTile, LayerTileData, MapTilesetGid,  TiledError,
+    LayerTile, LayerTileData, MapTilesetGid, TiledError,
 };
 
 use super::util::parse_data_line;
@@ -81,14 +81,21 @@ fn tile_to_chunk_pos(x: i32, y: i32) -> (i32, i32) {
     )
 }
 
+/// Part of an infinite tile layer.
 #[derive(Debug, PartialEq, Clone)]
 pub struct Chunk {
     tiles: Box<[Option<LayerTileData>; Self::TILE_COUNT]>,
 }
 
 impl Chunk {
+    /// Internal infinite layer chunk width. Do not rely on this value as it might change between
+    /// versions.
     pub const WIDTH: u32 = 16;
+    /// Internal infinite layer chunk height. Do not rely on this value as it might change between
+    /// versions.
     pub const HEIGHT: u32 = 16;
+    /// Internal infinite layer chunk tile count. Do not rely on this value as it might change
+    /// between versions.
     pub const TILE_COUNT: usize = Self::WIDTH as usize * Self::HEIGHT as usize;
 
     pub(crate) fn new() -> Self {
@@ -143,9 +150,15 @@ impl InternalChunk {
     }
 }
 
-map_wrapper!(InfiniteTileLayer => InfiniteTileLayerData);
+map_wrapper!(
+    #[doc = "A [`TileLayer`](super::TileLayer) with no bounds, internally stored using [`Chunk`]s."]
+    InfiniteTileLayer => InfiniteTileLayerData
+);
 
 impl<'map> InfiniteTileLayer<'map> {
+    /// Obtains the tile present at the position given.
+    ///
+    /// If the position is empty, this function will return [`None`].
     pub fn get_tile(&self, x: i32, y: i32) -> Option<LayerTile> {
         self.data
             .get_tile(x, y)
diff --git a/src/layers/tile/mod.rs b/src/layers/tile/mod.rs
index 5c3d27a..0257752 100644
--- a/src/layers/tile/mod.rs
+++ b/src/layers/tile/mod.rs
@@ -106,7 +106,10 @@ impl TileLayerData {
     }
 }
 
-map_wrapper!(LayerTile => LayerTileData);
+map_wrapper!(
+    #[doc = "An instance of a [`Tile`] present in a [`TileLayer`]."]
+    LayerTile => LayerTileData
+);
 
 impl<'map> LayerTile<'map> {
     /// Get a reference to the layer tile's referenced tile, if it exists.
@@ -155,9 +158,12 @@ impl<'map> LayerTile<'map> {
     }
 }
 
+/// A map layer containing tiles in some way. May be finite or infinite.
 #[derive(Debug)]
 pub enum TileLayer<'map> {
+    /// An finite tile layer; Also see [`FiniteTileLayer`].
     Finite(FiniteTileLayer<'map>),
+    /// An infinite tile layer; Also see [`InfiniteTileLayer`].
     Infinite(InfiniteTileLayer<'map>),
 }
 
@@ -169,6 +175,9 @@ impl<'map> TileLayer<'map> {
         }
     }
 
+    /// Obtains the tile present at the position given.
+    /// 
+    /// If the position given is invalid or the position is empty, this function will return [`None`].
     pub fn get_tile(&self, x: i32, y: i32) -> Option<LayerTile> {
         match self {
             TileLayer::Finite(finite) => finite.get_tile(x, y),
diff --git a/src/lib.rs b/src/lib.rs
index 0ec71af..3060086 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,6 @@
+#![doc = include_str!("../README.md")]
+#![deny(missing_docs)]
+#![deny(rustdoc::broken_intra_doc_links)]
 #![deny(unsafe_code)]
 #![deny(missing_copy_implementations)]
 #![deny(missing_debug_implementations)]
diff --git a/src/map.rs b/src/map.rs
index dcedbb2..96dc9f0 100644
--- a/src/map.rs
+++ b/src/map.rs
@@ -1,3 +1,5 @@
+//! Structures related to Tiled maps.
+
 use std::{collections::HashMap, fmt, fs::File, io::Read, path::Path, str::FromStr, sync::Arc};
 
 use xml::{attribute::OwnedAttribute, reader::XmlEvent, EventReader};
@@ -21,6 +23,7 @@ pub(crate) struct MapTilesetGid {
 pub struct Map {
     /// The TMX format version this map was saved to.
     pub version: String,
+    /// The way tiles are laid out in the map.
     pub orientation: Orientation,
     /// Width of the map, in tiles.
     pub width: u32,
@@ -38,6 +41,8 @@ pub struct Map {
     pub properties: Properties,
     /// The background color of this map, if any.
     pub background_color: Option<Color>,
+    /// Whether this map is infinite. An infinite map has no fixed size and can grow in all
+    /// directions. Its layer data is stored in chunks.
     pub infinite: bool,
 }
 
@@ -263,6 +268,7 @@ impl Map {
 
 /// Represents the way tiles are laid out in a map.
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
+#[allow(missing_docs)]
 pub enum Orientation {
     Orthogonal,
     Isometric,
diff --git a/src/objects.rs b/src/objects.rs
index 062270a..55c5a70 100644
--- a/src/objects.rs
+++ b/src/objects.rs
@@ -9,7 +9,11 @@ use crate::{
     LayerTile, LayerTileData, MapTilesetGid,
 };
 
+/// A structure describing an [`Object`]'s shape.
+///
+/// Also see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tmx-object).
 #[derive(Debug, PartialEq, Clone)]
+#[allow(missing_docs)]
 pub enum ObjectShape {
     Rect { width: f32, height: f32 },
     Ellipse { width: f32, height: f32 },
@@ -19,19 +23,40 @@ pub enum ObjectShape {
 }
 
 /// Raw data belonging to an object. Used internally and for tile collisions.
+///
+/// Also see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tmx-object).
 #[derive(Debug, PartialEq, Clone)]
 pub struct ObjectData {
+    /// ID of the object, which is unique per map since Tiled 0.11.
+    ///
+    /// On older versions this value is defaulted to 0.
     pub id: u32,
     tile: Option<LayerTileData>,
+    /// The name of the object, which is arbitrary and set by the user.
     pub name: String,
+    /// The type of the object, which is arbitrary and set by the user.
     pub obj_type: String,
+    /// The width of the object, if applicable. This refers to the attribute in `object`.
+    /// Since it is duplicate or irrelevant information in all cases, use the equivalent
+    /// member in [`ObjectShape`] instead.
+    #[deprecated(since = "0.10.0", note = "Use [`ObjectShape`] members instead")]
     pub width: f32,
+    /// The height of the object, if applicable. This refers to the attribute in `object`.
+    /// Since it is duplicate or irrelevant information in all cases, use the equivalent
+    /// member in [`ObjectShape`] instead.
+    #[deprecated(since = "0.10.0", note = "Use [`ObjectShape`] members instead")]
     pub height: f32,
+    /// The X coordinate of this object in pixels.
     pub x: f32,
+    /// The Y coordinate of this object in pixels.
     pub y: f32,
+    /// The clockwise rotation of this object around (x,y) in degrees.
     pub rotation: f32,
+    /// Whether the object is shown or hidden.
     pub visible: bool,
+    /// The object's shape.
     pub shape: ObjectShape,
+    /// The object's custom properties set by the user.
     pub properties: Properties,
 }
 
@@ -100,6 +125,7 @@ impl ObjectData {
 
         let shape = shape.unwrap_or(ObjectShape::Rect { width, height });
 
+        #[allow(deprecated)]
         Ok(ObjectData {
             id,
             tile,
@@ -168,10 +194,16 @@ impl ObjectData {
     }
 }
 
-map_wrapper!(Object => ObjectData);
+map_wrapper!(
+    #[doc = "Wrapper over an [`ObjectData`] that contains both a reference to the data as well as
+    to the map it is contained in."]
+    Object => ObjectData
+);
 
 impl<'map> Object<'map> {
-    /// Get the object's id.
+    /// ID of the object, which is unique per map since Tiled 0.11.
+    ///
+    /// On older versions this value is defaulted to 0.
     #[inline]
     pub fn id(&self) -> u32 {
         self.data.id
@@ -185,61 +217,69 @@ impl<'map> Object<'map> {
             .map(|tile| LayerTile::new(self.map, tile))
     }
 
-    /// Get a reference to the object's name.
+    /// The name of the object, which is arbitrary and set by the user.
     #[inline]
     pub fn name(&self) -> &str {
         self.data.name.as_ref()
     }
 
-    /// Get a reference to the object's type.
+    /// The type of the object, which is arbitrary and set by the user.
     #[inline]
     pub fn obj_type(&self) -> &str {
         self.data.obj_type.as_ref()
     }
 
-    /// Get the object's width.
+    /// The width of the object, if applicable. This refers to the attribute in `object`.
+    /// Since it is duplicate or irrelevant information in all cases, use the equivalent
+    /// member in [`ObjectShape`] instead.
+    #[deprecated(since = "0.10.0", note = "Use [`ObjectShape`] members instead")]
     #[inline]
     pub fn width(&self) -> f32 {
+        #[allow(deprecated)]
         self.data.width
     }
 
-    /// Get the object's height.
+    /// The height of the object, if applicable. This refers to the attribute in `object`.
+    /// Since it is duplicate or irrelevant information in all cases, use the equivalent
+    /// member in [`ObjectShape`] instead.
+    #[deprecated(since = "0.10.0", note = "Use [`ObjectShape`] members instead")]
     #[inline]
     pub fn height(&self) -> f32 {
+        #[allow(deprecated)]
         self.data.height
     }
 
-    /// Get the object's x.
+    /// The X coordinate of this object in pixels.
     #[inline]
     pub fn x(&self) -> f32 {
         self.data.x
     }
 
-    /// Get object's y.
+    /// The Y coordinate of this object in pixels.
     #[inline]
     pub fn y(&self) -> f32 {
         self.data.y
     }
 
-    /// Get a reference to the object's rotation.
+    /// The clockwise rotation of this object around (x,y) in degrees.
     #[inline]
     pub fn rotation(&self) -> f32 {
         self.data.rotation
     }
 
-    /// Whether the object should be visible or not.
+    /// Whether the object is shown or hidden.
     #[inline]
     pub fn visible(&self) -> bool {
         self.data.visible
     }
 
-    /// Get a reference to the object's shape.
+    /// The object's shape.
     #[inline]
     pub fn shape(&self) -> &ObjectShape {
         &self.data.shape
     }
 
-    /// Get a reference to the object's properties.
+    /// The object's custom properties set by the user.
     #[inline]
     pub fn properties(&self) -> &Properties {
         &self.data.properties
diff --git a/src/properties.rs b/src/properties.rs
index 0625c20..7fda017 100644
--- a/src/properties.rs
+++ b/src/properties.rs
@@ -7,7 +7,9 @@ use crate::{
     util::{get_attrs, parse_tag, XmlEventResult},
 };
 
+/// Represents a RGBA color with 8-bit depth on each channel.
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
+#[allow(missing_docs)]
 pub struct Color {
     pub alpha: u8,
     pub red: u8,
@@ -55,16 +57,26 @@ impl FromStr for Color {
     }
 }
 
+/// Represents a custom property's value.
+/// 
+/// Also read the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tmx-properties).
 #[derive(Debug, PartialEq, Clone)]
 pub enum PropertyValue {
+    /// A boolean value. Corresponds to the `bool` property type.
     BoolValue(bool),
+    /// A floating point value. Corresponds to the `float` property type.
     FloatValue(f32),
+    /// A signed integer value. Corresponds to the `int` property type.
     IntValue(i32),
+    /// A color value. Corresponds to the `color` property type.
     ColorValue(u32),
+    /// A string value. Corresponds to the `string` property type.
     StringValue(String),
-    /// Holds the path relative to the map or tileset
+    /// A filepath value. Corresponds to the `file` property type.
+    /// Holds the path relative to the map or tileset.
     FileValue(String),
-    /// Holds the id of a referenced object, or 0 if unset
+    /// An object ID value. Corresponds to the `object` property type.
+    /// Holds the id of a referenced object, or 0 if unset.
     ObjectValue(u32),
 }
 
@@ -111,6 +123,7 @@ impl PropertyValue {
     }
 }
 
+/// A custom property container.
 pub type Properties = HashMap<String, PropertyValue>;
 
 pub(crate) fn parse_properties(
diff --git a/src/tile.rs b/src/tile.rs
index 4ef80db..5563d64 100644
--- a/src/tile.rs
+++ b/src/tile.rs
@@ -12,6 +12,7 @@ use crate::{
     Tileset,
 };
 
+/// A tile ID, local to a tileset.
 pub type TileId = u32;
 
 #[derive(Debug, PartialEq, Clone, Default)]
@@ -24,6 +25,7 @@ pub(crate) struct TileData {
     probability: f32,
 }
 
+/// Points to a tile belonging to a tileset.
 #[derive(Debug)]
 pub struct Tile<'tileset> {
     pub(crate) tileset: &'tileset Tileset,
diff --git a/src/tileset.rs b/src/tileset.rs
index 8745a80..3c6a3ed 100644
--- a/src/tileset.rs
+++ b/src/tileset.rs
@@ -12,15 +12,35 @@ use crate::properties::{parse_properties, Properties};
 use crate::tile::TileData;
 use crate::{util::*, Gid, Tile};
 
-/// A tileset, usually the tilesheet image.
+/// A collection of tiles for usage in maps and template objects.
+/// 
+/// Also see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tileset).
 #[derive(Debug, PartialEq, Clone)]
 pub struct Tileset {
+    /// The name of the tileset, set by the user.
     pub name: String,
+    /// The (maximum) width in pixels of the tiles in this tileset. Irrelevant for [image collection]
+    /// tilesets.
+    /// 
+    /// [image collection]: Self::image
     pub tile_width: u32,
+    /// The (maximum) height in pixels of the tiles in this tileset. Irrelevant for [image collection]
+    /// tilesets.
+    /// 
+    /// [image collection]: Self::image
     pub tile_height: u32,
+    /// The spacing in pixels between the tiles in this tileset (applies to the tileset image).
+    /// Irrelevant for image collection tilesets.
     pub spacing: u32,
+    /// The margin around the tiles in this tileset (applies to the tileset image).
+    /// Irrelevant for image collection tilesets.
     pub margin: u32,
+    /// The number of tiles in this tileset. Note that tile IDs don't always have a connection with
+    /// the tile count, and as such there may be tiles with an ID bigger than the tile count.
     pub tilecount: u32,
+    /// The number of tile columns in the tileset. Editable for image collection tilesets, otherwise
+    /// calculated using [image](Self::image) width, [tile width](Self::tile_width),
+    /// [spacing](Self::spacing) and [margin](Self::margin).
     pub columns: u32,
 
     /// A tileset can either:
diff --git a/src/util.rs b/src/util.rs
index dadad0c..8ea2803 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -54,8 +54,9 @@ macro_rules! parse_tag {
 
 /// Creates a new type that wraps an internal data type over along with a map.
 macro_rules! map_wrapper {
-    ($name:ident => $data_ty:ty) => {
+    ($(#[$attrs:meta])* $name:ident => $data_ty:ty) => {
         #[derive(Clone, Copy, PartialEq, Debug)]
+        $(#[$attrs])*
         pub struct $name<'map> {
             pub(crate) map: &'map $crate::Map,
             pub(crate) data: &'map $data_ty,
-- 
GitLab