1+ use super :: pattern:: LEAGUE_FILE_MAGIC_BYTES ;
2+
13#[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
24#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
35#[ cfg_attr( feature = "serde" , serde( rename_all = "snake_case" ) ) ]
@@ -29,9 +31,16 @@ pub enum LeagueFileKind {
2931impl LeagueFileKind {
3032 #[ inline]
3133 #[ must_use]
32- /// The extension for this file type (.anm, .mapgeo, .bin, etc)
33- pub fn extension ( & self ) -> & ' static str {
34- match self {
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 ,
3544 Self :: Animation => "anm" ,
3645 Self :: Jpeg => "jpg" ,
3746 Self :: LightGrid => "lightgrid" ,
@@ -48,16 +57,21 @@ impl LeagueFileKind {
4857 Self :: StaticMeshBinary => "scb" ,
4958 Self :: Texture => "tex" ,
5059 Self :: TextureDds => "dds" ,
51- Self :: Unknown => "" ,
5260 Self :: WorldGeometry => "wgeo" ,
5361 Self :: WwiseBank => "bnk" ,
5462 Self :: WwisePackage => "wpk" ,
5563 Self :: Svg => "svg" ,
56- }
64+ } )
5765 }
5866
5967 #[ must_use]
60- /// Infer the file type from the extension. Works with or without a preceding '.'.
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+ /// ```
6175 pub fn from_extension ( extension : impl AsRef < str > ) -> LeagueFileKind {
6276 let extension = extension. as_ref ( ) ;
6377 if extension. is_empty ( ) {
@@ -91,4 +105,41 @@ impl LeagueFileKind {
91105 _ => Self :: Unknown ,
92106 }
93107 }
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+ }
94145}
0 commit comments