rosu-map 0.2.1

Library to de- and encode .osu files
Documentation
macro_rules! section_keys {
    (
        $( #[$meta:meta] )?
        pub enum $name:ident {
            $( $variant:ident, )*
        }
    ) => {
        $( #[$meta] )?
        #[derive(Copy, Clone, Debug, PartialEq, Eq)]
        pub enum $name {
            $( $variant, )*
        }

        impl $name {
            pub const fn as_str(&self) -> &'static str {
                match self {
                    $( $name::$variant => stringify!($variant), )*
                }
            }
        }

        impl std::str::FromStr for $name {
            type Err = $crate::section::UnknownKeyError;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                match s {
                    $( stringify!($variant) => Ok($name::$variant), )*
                    _ => Err($crate::section::UnknownKeyError),
                }
            }
        }

        impl std::fmt::Display for $name {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                f.write_str(self.as_str())
            }
        }
    };
}

macro_rules! thiserror {
	(
		#[error( $desc:tt )]
		$( #[ $error_attribute:meta ] )*
		$vis:vis struct $error_type_name:ident
			$( (
				$(
					$( #[ $tattr:ident ] )?
					$tt:ty
				),* $(,)?
			) )?;
	) => {
		$( #[ $error_attribute ] )*
		$vis struct $error_type_name $( ( $( $tt )* ))?;

		impl ::std::fmt::Display for $error_type_name {
			fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
				formatter.write_str($desc)
			}
		}

		impl ::std::error::Error for $error_type_name {
			fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
				thiserror!( @STRUCTSOURCE self, $( ( $( $tt ),* ) )? )
			}
		}
	};

	(
		$( #[ $error_attribute:meta ] )*
		$vis:vis struct $error_type_name:ident
			$( (
				$(
					$( #[ $tattr:ident ] )?
					$tt:ty
				),* $(,)?
			) )?;
	) => {
		compile_error!("`#[error(\"...\")]` must be the first attribute");
	};

	(
		@STRUCTSOURCE
		$self_:ident,
		(
			#[ $source_or_from:meta ]
			$t1:ty $( , $t_rest:ty )*
		)
	) => {
		Some(&self.0 as _)
    };

    (
		@STRUCTSOURCE
		$self_:ident,
		$( ( $( $tt:ty ),* ) )?
	) => {
		None
	};

	(
		$( #[$error_attribute:meta] )*
		$vis:vis enum $error_type_name:ident {
			$(
				#[error( $desc:tt )]
				$variant_name:ident
					$( {
						$(
							$( #[ $sattr:ident ] )?
							$sf:ident: $st:ty
						),* $(,)?
					} )?
					$( (
						$(
							$( #[ $tattr:ident ] )?
							$tt:ty
						),* $(,)?
					) )?
			),* $(,)?
		}
	) => {
		$( #[ $error_attribute ] )*
        $vis enum $error_type_name {
            $(
                $variant_name
					$( {
						$( $sf: $st ),*
					} )?
					$( (
						$( $tt ),*
					) )?
            ),*
		}

		impl ::std::fmt::Display for $error_type_name {
			fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
				#![allow(irrefutable_let_patterns)]

				$(
					thiserror!(
						@ENUMFMT
						self,
						formatter,
						$desc,
						$variant_name
						$( { $( $sf: $st ),* } )?
						$( ( $( $tt ),* ) )?
					);
				)*

				unreachable!()
			}
		}

		$(
			thiserror!(
				@ENUMFROM
				$error_type_name,
				$variant_name
				$( {
					$(
						$( #[ $sattr ] )?
						$sf: $st
					),*
				} )?
				$( (
					$(
						$( #[ $tattr ] )?
						$tt
					),*
				) )?
			);
		)*

		impl ::std::error::Error for $error_type_name {
			fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
				$(
					thiserror!(
						@ENUMSOURCE
						self,
						$variant_name
						$( { $( $sf: $st ),* } )?
						$( ( $( $tt ),* ) )?
					);
				)*

				None
			}
		}
	};

	( @ENUMFMT $self_:ident, $fmt:ident, $desc:literal, $variant_name:ident ) => {
        if let Self::$variant_name = $self_ {
			return $fmt.write_str($desc);
        }
    };

	( @ENUMFMT $self_:ident, $fmt:ident, $desc:literal, $variant_name:ident ( $t1:ty ) ) => {
        if let Self::$variant_name(a) = $self_ {
            return write!($fmt, concat!($desc, "{0:.0?}"), a);
        }
    };

    ( @ENUMFROM $e:ident, $variant_name:ident ( #[from] $t:ty ) ) => {
        impl From<$t> for $e {
            fn from(x: $t) -> $e {
                $e::$variant_name(x)
            }
        }
    };

    (
		@ENUMFROM
		$e:ident, $variant_name:ident
		$( ( $( $( #[source] )? $tt:ty ),* ) )?
		$( { $( $( #[source] )? $sf:ident: $st:ty ),* } )?
	) => {};

    (
		@ENUMSOURCE
		$self_:ident,
		$variant_name:ident (
			#[ $source_or_from:meta ]
			$t1:ty $( , $t_rest:ty )*
		)
	) => {
        if let Self::$variant_name(x, ..) = $self_ {
            return Some(x as _);
        }
    };

    (
		@ENUMSOURCE
		$self_:ident,
		$variant_name:ident
		$( ( $( $tt:ty ),* ) )?
		$( { $( $sf:ident: $st:ty ),* } )?
	) => {};
}