From 3cfbdfca83cc3a3ca32845460b6f224c6ce272e2 Mon Sep 17 00:00:00 2001
From: Danny McClanahan <1305167+cosmicexplorer@users.noreply.github.com>
Date: Wed, 12 Jul 2023 00:01:23 -0400
Subject: [PATCH] use num_enum to clean up the System type

---
 Cargo.toml   |  1 +
 src/read.rs  |  4 ++--
 src/types.rs | 29 ++++++++++++-----------------
 3 files changed, 15 insertions(+), 19 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index fbf4c7ae..719f3f78 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -30,6 +30,7 @@ constant_time_eq = { version = "0.3.0", optional = true }
 crc32fast = "1.4.0"
 flate2 = { version = "1.0.28", default-features = false, optional = true }
 hmac = { version = "0.12.1", optional = true, features = ["reset"] }
+num_enum = "0.6.1"
 pbkdf2 = { version = "0.12.2", optional = true }
 sha1 = { version = "0.10.6", optional = true }
 time = { workspace = true, optional = true, features = [
diff --git a/src/read.rs b/src/read.rs
index 0a39faef..e0615fca 100644
--- a/src/read.rs
+++ b/src/read.rs
@@ -812,7 +812,7 @@ fn central_header_to_zip_file_inner<R: Read>(
 
     // Construct the result
     let mut result = ZipFileData {
-        system: System::from_u8((version_made_by >> 8) as u8),
+        system: System::from((version_made_by >> 8) as u8),
         version_made_by: version_made_by as u8,
         encrypted,
         using_data_descriptor,
@@ -1178,7 +1178,7 @@ pub fn read_zipfile_from_stream<'a, R: Read>(reader: &'a mut R) -> ZipResult<Opt
     };
 
     let mut result = ZipFileData {
-        system: System::from_u8((version_made_by >> 8) as u8),
+        system: System::from((version_made_by >> 8) as u8),
         version_made_by: version_made_by as u8,
         encrypted,
         using_data_descriptor,
diff --git a/src/types.rs b/src/types.rs
index b4079f6c..7ac8a971 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -1,5 +1,6 @@
 //! Types that specify what is contained in a ZIP.
 use path::{Component, Path, PathBuf};
+use num_enum::{FromPrimitive, IntoPrimitive};
 use std::path;
 use std::sync::{Arc, OnceLock};
 
@@ -49,25 +50,15 @@ use crate::result::DateTimeRangeError;
 #[cfg(feature = "time")]
 use time::{error::ComponentRange, Date, Month, OffsetDateTime, PrimitiveDateTime, Time};
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)]
+#[repr(u8)]
 pub enum System {
     Dos = 0,
     Unix = 3,
+    #[num_enum(default)]
     Unknown,
 }
 
-impl System {
-    pub const fn from_u8(system: u8) -> System {
-        use self::System::*;
-
-        match system {
-            0 => Dos,
-            3 => Unix,
-            _ => Unknown,
-        }
-    }
-}
-
 /// Representation of a moment in time.
 ///
 /// Zip files use an old format from DOS to store timestamps,
@@ -512,10 +503,14 @@ mod test {
     #[test]
     fn system() {
         use super::System;
-        assert_eq!(System::Dos as u16, 0u16);
-        assert_eq!(System::Unix as u16, 3u16);
-        assert_eq!(System::from_u8(0), System::Dos);
-        assert_eq!(System::from_u8(3), System::Unix);
+        assert_eq!(u8::from(System::Dos), 0u8);
+        assert_eq!(System::Dos as u8, 0u8);
+        assert_eq!(System::Unix as u8, 3u8);
+        assert_eq!(u8::from(System::Unix), 3u8);
+        assert_eq!(System::from(0), System::Dos);
+        assert_eq!(System::from(3), System::Unix);
+        assert_eq!(u8::from(System::Unknown), 4u8);
+        assert_eq!(System::Unknown as u8, 4u8);
     }
 
     #[test]