|
| 1 | +use super::pattern::LEAGUE_FILE_MAGIC_BYTES; |
| 2 | + |
| 3 | +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
| 4 | +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] |
| 5 | +#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] |
| 6 | +/// The kind of league file (animation, mapgeo, bin, etc) |
| 7 | +pub enum LeagueFileKind { |
| 8 | + Animation, |
| 9 | + Jpeg, |
| 10 | + LightGrid, |
| 11 | + LuaObj, |
| 12 | + MapGeometry, |
| 13 | + Png, |
| 14 | + Preload, |
| 15 | + PropertyBin, |
| 16 | + PropertyBinOverride, |
| 17 | + RiotStringTable, |
| 18 | + SimpleSkin, |
| 19 | + Skeleton, |
| 20 | + StaticMeshAscii, |
| 21 | + StaticMeshBinary, |
| 22 | + Svg, |
| 23 | + Texture, |
| 24 | + TextureDds, |
| 25 | + Unknown, |
| 26 | + WorldGeometry, |
| 27 | + WwiseBank, |
| 28 | + WwisePackage, |
| 29 | +} |
| 30 | + |
| 31 | +impl LeagueFileKind { |
| 32 | + #[inline] |
| 33 | + #[must_use] |
| 34 | + /// The extension for this file type (anm, mapgeo, bin, etc) |
| 35 | + /// ``` |
| 36 | + /// # use league_toolkit::league_file::LeagueFileKind; |
| 37 | + /// assert_eq!(LeagueFileKind::Animation.extension(), Some("anm")); |
| 38 | + /// assert_eq!(LeagueFileKind::StaticMeshAscii.extension(), Some("sco")); |
| 39 | + /// assert_eq!(LeagueFileKind::Unknown.extension(), None); |
| 40 | + /// |
| 41 | + pub fn extension(&self) -> Option<&'static str> { |
| 42 | + Some(match self { |
| 43 | + Self::Unknown => return None, |
| 44 | + Self::Animation => "anm", |
| 45 | + Self::Jpeg => "jpg", |
| 46 | + Self::LightGrid => "lightgrid", |
| 47 | + Self::LuaObj => "luaobj", |
| 48 | + Self::MapGeometry => "mapgeo", |
| 49 | + Self::Png => "png", |
| 50 | + Self::Preload => "preload", |
| 51 | + Self::PropertyBin => "bin", |
| 52 | + Self::PropertyBinOverride => "bin", |
| 53 | + Self::RiotStringTable => "stringtable", |
| 54 | + Self::SimpleSkin => "skn", |
| 55 | + Self::Skeleton => "skl", |
| 56 | + Self::StaticMeshAscii => "sco", |
| 57 | + Self::StaticMeshBinary => "scb", |
| 58 | + Self::Texture => "tex", |
| 59 | + Self::TextureDds => "dds", |
| 60 | + Self::WorldGeometry => "wgeo", |
| 61 | + Self::WwiseBank => "bnk", |
| 62 | + Self::WwisePackage => "wpk", |
| 63 | + Self::Svg => "svg", |
| 64 | + }) |
| 65 | + } |
| 66 | + |
| 67 | + #[must_use] |
| 68 | + /// Infer the file type from the extension. Works with or without a preceding `'.'`. |
| 69 | + /// ``` |
| 70 | + /// # use league_toolkit::league_file::LeagueFileKind; |
| 71 | + /// # |
| 72 | + /// assert_eq!(LeagueFileKind::from_extension("png"), LeagueFileKind::Png); |
| 73 | + /// assert_eq!(LeagueFileKind::from_extension(".png"), LeagueFileKind::Png); |
| 74 | + /// ``` |
| 75 | + pub fn from_extension(extension: impl AsRef<str>) -> LeagueFileKind { |
| 76 | + let extension = extension.as_ref(); |
| 77 | + if extension.is_empty() { |
| 78 | + return LeagueFileKind::Unknown; |
| 79 | + } |
| 80 | + |
| 81 | + let extension = match extension.starts_with('.') { |
| 82 | + true => &extension[1..], |
| 83 | + false => extension, |
| 84 | + }; |
| 85 | + |
| 86 | + match extension { |
| 87 | + "anm" => Self::Animation, |
| 88 | + "bin" => Self::PropertyBin, |
| 89 | + "bnk" => Self::WwiseBank, |
| 90 | + "dds" => Self::TextureDds, |
| 91 | + "jpg" => Self::Jpeg, |
| 92 | + "luaobj" => Self::LuaObj, |
| 93 | + "mapgeo" => Self::MapGeometry, |
| 94 | + "png" => Self::Png, |
| 95 | + "preload" => Self::Preload, |
| 96 | + "scb" => Self::StaticMeshBinary, |
| 97 | + "sco" => Self::StaticMeshAscii, |
| 98 | + "skl" => Self::Skeleton, |
| 99 | + "skn" => Self::SimpleSkin, |
| 100 | + "stringtable" => Self::RiotStringTable, |
| 101 | + "svg" => Self::Svg, |
| 102 | + "tex" => Self::Texture, |
| 103 | + "wgeo" => Self::WorldGeometry, |
| 104 | + "wpk" => Self::WwisePackage, |
| 105 | + _ => Self::Unknown, |
| 106 | + } |
| 107 | + } |
| 108 | + |
| 109 | + /// Identify the type of league file from the magic at the start of the file. You must provide at |
| 110 | + /// least [`MAX_MAGIC_SIZE`] bytes of data to be able to detect all file types. |
| 111 | + /// |
| 112 | + /// # Examples |
| 113 | + /// ``` |
| 114 | + /// # use league_toolkit::league_file::*; |
| 115 | + /// # |
| 116 | + /// let data = b"r3d2skltblahblahblahblah"; |
| 117 | + /// let kind = LeagueFileKind::identify_from_bytes(data); |
| 118 | + /// assert_eq!(kind, LeagueFileKind::Skeleton); |
| 119 | + /// ``` |
| 120 | + /// |
| 121 | + /// |
| 122 | + /// ## Identifying from a reader |
| 123 | + /// ``` |
| 124 | + /// # use std::fs::File; |
| 125 | + /// # use std::io::{self, Cursor, Read}; |
| 126 | + /// # use league_toolkit::league_file::*; |
| 127 | + /// # |
| 128 | + /// let mut reader = Cursor::new([0x33, 0x22, 0x11, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]); |
| 129 | + /// let mut buffer = [0; MAX_MAGIC_SIZE]; |
| 130 | + /// reader.read(&mut buffer)?; |
| 131 | + /// |
| 132 | + /// let kind = LeagueFileKind::identify_from_bytes(&buffer); |
| 133 | + /// assert_eq!(kind, LeagueFileKind::SimpleSkin); |
| 134 | + /// # Ok::<(), io::Error>(()) |
| 135 | + /// ``` |
| 136 | + pub fn identify_from_bytes(data: &[u8]) -> LeagueFileKind { |
| 137 | + for magic_byte in LEAGUE_FILE_MAGIC_BYTES.iter() { |
| 138 | + if magic_byte.matches(data) { |
| 139 | + return magic_byte.kind; |
| 140 | + } |
| 141 | + } |
| 142 | + |
| 143 | + LeagueFileKind::Unknown |
| 144 | + } |
| 145 | +} |
0 commit comments