bindet 0.3.2

Fast file type detection
Documentation
//! Enumerates all file types that **bindet** is able to detect.
//!
//! Those enumerations are separated in two:
//!
//! - [FileType]
//! - [FileRootType]

impl From<FileType> for FileRootType {
    fn from(file_type: FileType) -> Self {
        file_type.root()
    }
}

#[cfg(feature = "nightly")]
macro_rules! file_types {
    ($($(#[$attr:meta])* $id:ident $(,$(#[$more_attr:meta])*$more:ident)* => $root:ident $(,$sub:ident)*;)*) => {
        /// All file types that **bindet** is able to detect, some of them are just different versions
        /// of the same format or very similar.
        ///
        /// **bindet** is able to do both, refined detection, which it tries to detect [FileType] precisely,
        /// and general detection, which it tries to do a weaker [FileType] detection
        /// (**note**: in its current state, it is only doing the precise detection).
        ///
        /// A more general categorization is enumerated by [FileRootType].
        ///
        /// # Supported file types
        #[doc = concat!($(concat!("\n - ", stringify!($id) $(,concat!("\n - ", stringify!($more)))*)),*)]
        #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
        #[non_exhaustive]
        pub enum FileType {
            $($(#[$attr])* $id $(,$(#[$more_attr])* $more)*),*
        }

        impl FileType {
            pub const fn variants() -> [FileType; ${count(id)} + ${count(more)}] {
                [
                    $(FileType::$id $(,FileType::$more)*),*
                ]
            }

            /// Gets the [FileRootType] of this [FileType]
            pub fn root(&self) -> FileRootType {
                match *self {
                    $(FileType::$id $(| FileType::$more)* => FileRootType::$root,)*
                }
            }

        }
    };
}

#[cfg(not(feature = "nightly"))]
macro_rules! file_types {
    ($($(#[$attr:meta])* $id:ident $(,$(#[$more_attr:meta])*$more:ident)* => $root:ident $(,$sub:ident)*;)*) => {
        /// All file types that **bindet** is able to detect, some of them are just different versions
        /// of the same format or very similar.
        ///
        /// **bindet** is able to do both, refined detection, which it tries to detect [FileType] precisely,
        /// and general detection, which it tries to do a weaker [FileType] detection
        /// (**note**: in its current state, it is only doing the precise detection).
        ///
        /// A more general categorization is enumerated by [FileRootType].
        ///
        /// # Supported file types
        #[doc = concat!($(concat!("\n - ", stringify!($id) $(,concat!("\n - ", stringify!($more)))*)),*)]
        #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
        #[non_exhaustive]
        pub enum FileType {
            $($(#[$attr])* $id $(,$(#[$more_attr])* $more)*),*
        }

        impl FileType {
            pub const fn variants() -> [FileType; count!($($id $(, $more)*),*)] {
                [
                    $(FileType::$id $(,FileType::$more)*),*
                ]
            }

            /// Gets the [FileRootType] of this [FileType]
            pub fn root(&self) -> FileRootType {
                match *self {
                    $(FileType::$id $(| FileType::$more)* => FileRootType::$root,)*
                }
            }

        }
    };
}

macro_rules! file_root_types {
    ($($(#[$attr:meta])* $id:ident,)*) => {
        /// Root file type which categorizes types in a generic way.
        ///
        /// For example, `Rar` and `Rar5` are both in the same `Rar` category, the same as
        /// `DosMzExecutable` and `DosZmExecutable`, which are in the `DosExecutable` category.
        ///
        /// This is useful when you are interested in knowing the type of a file, but does not need
        /// much precision.
        ///
        /// ## Performance note
        ///
        /// Root file types is also important for **bindet** performance characteristics,
        /// once a [file type][FileType] is detected, **bindet** will not try to detect another [file type][FileType]
        /// of the same [root category][FileRootType] unless another rule states that it can.
        ///
        /// Read more at [crate documentation][crate] to understand why **bindet** tries to detect
        /// more than one [file type][FileType].
        #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
        #[non_exhaustive]
        pub enum FileRootType {
            $($(#[$attr])* $id),*
        }
    };
}

#[cfg(not(feature = "nightly"))]
macro_rules! count {
    ($($tts:tt),*) => {<[()]>::len(&[$(count!(@tuple $tts)),*])};
    (@tuple $_t:tt) => { () };
}

file_types! {
    #[doc = "Zip file format, this includes: \n- jar\n- docx/xlsx/pptx\n- Apk\n- Aar\n- odt/ods/odp"]
    Zip => Zip;
    Rar5, Rar => Rar;
    #[doc = "Tar archive (only uncompressed).\n\n\
    Compressed tar archives are first archived using tar, then\
    \ncompressed, which means that in order to detect compressed tar\
    \nfiles we need to decompress them first, which is not viable\
    \nfor this library, and is not part of its goal."]
    Tar => Tar;
    Lzma => Lzma;
    Xz => Xz;
    Zst => Zst;
    Png => Png;
    Jpg => Jpg;
    _7z => _7z;
    #[doc = "Opus Ogg"]
    Opus => Ogg;
    #[doc = "Vorbis Ogg"]
    Vorbis => Ogg;
    Mp3 => Mp3;
    Webp => Webp;
    Flac => Flac;
    #[doc = "All Matroska media containers:\
    \n- mkv\
    \n- mka\
    \n- mks\
    \n- mk3d\
    \n- webm"]
    Matroska => Matroska;
    #[doc = "WebAssembly"]
    Wasm => Wasm;
    #[doc = "Java class"]
    Class => Class;
    #[doc = "Scala Tasty"]
    Tasty => Tasty;
    #[doc = "Mach-O (untested)"]
    Mach => Mach;
    #[doc = "Executable and Linkable Format\
    \n- `.so`\
    \n- `*nix executable`"]
    Elf => Elf;
    #[doc = "Waveform Audio File Format"]
    Wav => Wav;
    Avi => Avi;
    #[doc = "Audio Interchange File Format\
    \n- aiff\
    \n- aif\
    \n- aifc\
    \n- snd\
    \n- iff"]
    Aiff => Aiff;
    #[doc = "Tagged Image File Format\n\
    \n - Tiff\
    \n - Tif"]
    Tiff => Tiff;
    #[doc = "SQLite 3 Database"]
    Sqlite3 => Sqlite3;
    Ico => Ico;
    #[doc = "Dalvik (untested)"]
    Dalvik => Dalvik;
    #[doc = "PDF Document"]
    Pdf => Pdf;
    #[doc = "DOS MZ Executable\
    \n - `.exe`\
    \n - `.dll`"]
    DosMzExecutable,
    #[doc = "DOS MZ Executable\
    \n - `.exe`"]
    DosZmExecutable => DosExecutable;
    #[doc = "Gimp XCF"]
    Xcf => Xcf;
    #[doc = "Gif"]
    Gif => Gif;
    #[doc = "Bitmap"]
    Bmp => Bmp;
    #[doc = "Optical Disc Image"]
    Iso => Iso;
    Gpg,
    ArmoredGpg => Gpg;
    #[doc = "Adobe Small Web Format"]
    Swf, Swc => Flash;
}

file_root_types! {
    Zip,
    Rar,
    Tar,
    Lzma,
    Xz, // XZ and LZMA in the same category?? I don't really know because LZMA is really old
    Zst,
    Png,
    Jpg,
    _7z,
    Ogg,
    Mp3,
    Webp,
    Flac,
    Matroska,
    Wasm,
    Class,
    Tasty,
    Mach,
    Elf,
    Wav,
    Avi,
    Aiff,
    Tiff,
    Sqlite3,
    Ico,
    Dalvik,
    Pdf,
    DosExecutable,
    Xcf,
    Gif,
    Bmp,
    Iso,
    Gpg,
    Flash,
}