From 35280a05f360a6e5cc6d205c0d8fd904f2404ef4 Mon Sep 17 00:00:00 2001
From: Bryant Mairs <bryant@mai.rs>
Date: Fri, 22 Feb 2019 07:30:45 -0800
Subject: [PATCH] Add extra traits for fuchsia datatypes

---
 src/fuchsia/align.rs    |  73 +++++++++++-
 src/fuchsia/mod.rs      | 248 +++++++++++++++++++++++++++++++++++++++-
 src/fuchsia/no_align.rs |  82 ++++++++++++-
 src/fuchsia/x86_64.rs   |  43 ++++++-
 4 files changed, 433 insertions(+), 13 deletions(-)

diff --git a/src/fuchsia/align.rs b/src/fuchsia/align.rs
index 8d4040d0..bc972751 100644
--- a/src/fuchsia/align.rs
+++ b/src/fuchsia/align.rs
@@ -32,7 +32,6 @@ macro_rules! expand_align {
         }
 
         s_no_extra_traits! {
-            #[allow(missing_debug_implementations)]
             #[cfg_attr(all(target_pointer_width = "32",
                            any(target_arch = "arm",
                                target_arch = "x86_64")),
@@ -45,7 +44,6 @@ macro_rules! expand_align {
                 size: [u8; ::__SIZEOF_PTHREAD_MUTEX_T],
             }
 
-            #[allow(missing_debug_implementations)]
             #[cfg_attr(all(target_pointer_width = "32",
                            any(target_arch = "arm",
                                target_arch = "x86_64")),
@@ -58,7 +56,6 @@ macro_rules! expand_align {
                 size: [u8; ::__SIZEOF_PTHREAD_RWLOCK_T],
             }
 
-            #[allow(missing_debug_implementations)]
             #[cfg_attr(target_pointer_width = "32",
                        repr(align(4)))]
             #[cfg_attr(target_pointer_width = "64",
@@ -71,5 +68,75 @@ macro_rules! expand_align {
                 size: [u8; ::__SIZEOF_PTHREAD_COND_T],
             }
         }
+
+        cfg_if! {
+            if #[cfg(feature = "extra_traits")] {
+                impl PartialEq for pthread_cond_t {
+                    fn eq(&self, other: &pthread_cond_t) -> bool {
+                        self.size
+                            .iter()
+                            .zip(other.size.iter())
+                            .all(|(a,b)| a == b)
+                    }
+                }
+                impl Eq for pthread_cond_t {}
+                impl ::fmt::Debug for pthread_cond_t {
+                    fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                        f.debug_struct("pthread_cond_t")
+                            // FIXME: .field("size", &self.size)
+                            .finish()
+                    }
+                }
+                impl ::hash::Hash for pthread_cond_t {
+                    fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                        self.size.hash(state);
+                    }
+                }
+
+                impl PartialEq for pthread_mutex_t {
+                    fn eq(&self, other: &pthread_mutex_t) -> bool {
+                        self.size
+                            .iter()
+                            .zip(other.size.iter())
+                            .all(|(a,b)| a == b)
+                    }
+                }
+                impl Eq for pthread_mutex_t {}
+                impl ::fmt::Debug for pthread_mutex_t {
+                    fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                        f.debug_struct("pthread_mutex_t")
+                            // FIXME: .field("size", &self.size)
+                            .finish()
+                    }
+                }
+                impl ::hash::Hash for pthread_mutex_t {
+                    fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                        self.size.hash(state);
+                    }
+                }
+
+                impl PartialEq for pthread_rwlock_t {
+                    fn eq(&self, other: &pthread_rwlock_t) -> bool {
+                        self.size
+                            .iter()
+                            .zip(other.size.iter())
+                            .all(|(a,b)| a == b)
+                    }
+                }
+                impl Eq for pthread_rwlock_t {}
+                impl ::fmt::Debug for pthread_rwlock_t {
+                    fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                        f.debug_struct("pthread_rwlock_t")
+                            // FIXME: .field("size", &self.size)
+                            .finish()
+                    }
+                }
+                impl ::hash::Hash for pthread_rwlock_t {
+                    fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                        self.size.hash(state);
+                    }
+                }
+            }
+        }
     }
 }
diff --git a/src/fuchsia/mod.rs b/src/fuchsia/mod.rs
index cac0543b..76eb7f8f 100644
--- a/src/fuchsia/mod.rs
+++ b/src/fuchsia/mod.rs
@@ -922,7 +922,6 @@ s! {
 }
 
 s_no_extra_traits! {
-    #[allow(missing_debug_implementations)]
     pub struct sysinfo {
         pub uptime: ::c_ulong,
         pub loads: [::c_ulong; 3],
@@ -940,20 +939,17 @@ s_no_extra_traits! {
         pub __reserved: [::c_char; 256],
     }
 
-    #[allow(missing_debug_implementations)]
     pub struct sockaddr_un {
         pub sun_family: sa_family_t,
         pub sun_path: [::c_char; 108]
     }
 
-    #[allow(missing_debug_implementations)]
     pub struct sockaddr_storage {
         pub ss_family: sa_family_t,
         __ss_align: ::size_t,
         __ss_pad2: [u8; 128 - 2 * 8],
     }
 
-    #[allow(missing_debug_implementations)]
     pub struct utsname {
         pub sysname: [::c_char; 65],
         pub nodename: [::c_char; 65],
@@ -963,7 +959,6 @@ s_no_extra_traits! {
         pub domainname: [::c_char; 65]
     }
 
-    #[allow(missing_debug_implementations)]
     pub struct dirent {
         pub d_ino: ::ino_t,
         pub d_off: ::off_t,
@@ -972,7 +967,6 @@ s_no_extra_traits! {
         pub d_name: [::c_char; 256],
     }
 
-    #[allow(missing_debug_implementations)]
     pub struct dirent64 {
         pub d_ino: ::ino64_t,
         pub d_off: ::off64_t,
@@ -982,6 +976,248 @@ s_no_extra_traits! {
     }
 }
 
+
+cfg_if! {
+    if #[cfg(feature = "extra_traits")] {
+        impl PartialEq for sysinfo {
+            fn eq(&self, other: &sysinfo) -> bool {
+                self.uptime == other.uptime
+                    && self.loads == other.loads
+                    && self.totalram == other.totalram
+                    && self.freeram == other.freeram
+                    && self.sharedram == other.sharedram
+                    && self.bufferram == other.bufferram
+                    && self.totalswap == other.totalswap
+                    && self.freeswap == other.freeswap
+                    && self.procs == other.procs
+                    && self.pad == other.pad
+                    && self.totalhigh == other.totalhigh
+                    && self.freehigh == other.freehigh
+                    && self.mem_unit == other.mem_unit
+                    && self
+                        .__reserved
+                        .iter()
+                        .zip(other.__reserved.iter())
+                        .all(|(a,b)| a == b)
+            }
+        }
+        impl Eq for sysinfo {}
+        impl ::fmt::Debug for sysinfo {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("sysinfo")
+                    .field("uptime", &self.uptime)
+                    .field("loads", &self.loads)
+                    .field("totalram", &self.totalram)
+                    .field("freeram", &self.freeram)
+                    .field("sharedram", &self.sharedram)
+                    .field("bufferram", &self.bufferram)
+                    .field("totalswap", &self.totalswap)
+                    .field("freeswap", &self.freeswap)
+                    .field("procs", &self.procs)
+                    .field("pad", &self.pad)
+                    .field("totalhigh", &self.totalhigh)
+                    .field("freehigh", &self.freehigh)
+                    .field("mem_unit", &self.mem_unit)
+                    // FIXME: .field("__reserved", &self.__reserved)
+                    .finish()
+            }
+        }
+        impl ::hash::Hash for sysinfo {
+            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                self.uptime.hash(state);
+                self.loads.hash(state);
+                self.totalram.hash(state);
+                self.freeram.hash(state);
+                self.sharedram.hash(state);
+                self.bufferram.hash(state);
+                self.totalswap.hash(state);
+                self.freeswap.hash(state);
+                self.procs.hash(state);
+                self.pad.hash(state);
+                self.totalhigh.hash(state);
+                self.freehigh.hash(state);
+                self.mem_unit.hash(state);
+                self.__reserved.hash(state);
+            }
+        }
+
+        impl PartialEq for sockaddr_un {
+            fn eq(&self, other: &sockaddr_un) -> bool {
+                self.sun_family == other.sun_family
+                    && self
+                    .sun_path
+                    .iter()
+                    .zip(other.sun_path.iter())
+                    .all(|(a,b)| a == b)
+            }
+        }
+        impl Eq for sockaddr_un {}
+        impl ::fmt::Debug for sockaddr_un {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("sockaddr_un")
+                    .field("sun_family", &self.sun_family)
+                    // FIXME: .field("sun_path", &self.sun_path)
+                    .finish()
+            }
+        }
+        impl ::hash::Hash for sockaddr_un {
+            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                self.sun_family.hash(state);
+                self.sun_path.hash(state);
+            }
+        }
+
+        impl PartialEq for sockaddr_storage {
+            fn eq(&self, other: &sockaddr_storage) -> bool {
+                self.ss_family == other.ss_family
+                    && self.__ss_align == other.__ss_align
+                    && self
+                    .__ss_pad2
+                    .iter()
+                    .zip(other.__ss_pad2.iter())
+                    .all(|(a, b)| a == b)
+            }
+        }
+        impl Eq for sockaddr_storage {}
+        impl ::fmt::Debug for sockaddr_storage {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("sockaddr_storage")
+                    .field("ss_family", &self.ss_family)
+                    .field("__ss_align", &self.__ss_align)
+                    // FIXME: .field("__ss_pad2", &self.__ss_pad2)
+                    .finish()
+            }
+        }
+        impl ::hash::Hash for sockaddr_storage {
+            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                self.ss_family.hash(state);
+                self.__ss_align.hash(state);
+                self.__ss_pad2.hash(state);
+            }
+        }
+
+        impl PartialEq for utsname {
+            fn eq(&self, other: &utsname) -> bool {
+                self.sysname
+                    .iter()
+                    .zip(other.sysname.iter())
+                    .all(|(a,b)| a == b)
+                    && self
+                    .nodename
+                    .iter()
+                    .zip(other.nodename.iter())
+                    .all(|(a,b)| a == b)
+                    && self
+                    .release
+                    .iter()
+                    .zip(other.release.iter())
+                    .all(|(a,b)| a == b)
+                    && self
+                    .version
+                    .iter()
+                    .zip(other.version.iter())
+                    .all(|(a,b)| a == b)
+                    && self
+                    .machine
+                    .iter()
+                    .zip(other.machine.iter())
+                    .all(|(a,b)| a == b)
+            }
+        }
+        impl Eq for utsname {}
+        impl ::fmt::Debug for utsname {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("utsname")
+                    // FIXME: .field("sysname", &self.sysname)
+                    // FIXME: .field("nodename", &self.nodename)
+                    // FIXME: .field("release", &self.release)
+                    // FIXME: .field("version", &self.version)
+                    // FIXME: .field("machine", &self.machine)
+                    .finish()
+            }
+        }
+        impl ::hash::Hash for utsname {
+            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                self.sysname.hash(state);
+                self.nodename.hash(state);
+                self.release.hash(state);
+                self.version.hash(state);
+                self.machine.hash(state);
+            }
+        }
+
+        impl PartialEq for dirent {
+            fn eq(&self, other: &dirent) -> bool {
+                self.d_ino == other.d_ino
+                    && self.d_off == other.d_off
+                    && self.d_reclen == other.d_reclen
+                    && self.d_type == other.d_type
+                    && self
+                    .d_name
+                    .iter()
+                    .zip(other.d_name.iter())
+                    .all(|(a,b)| a == b)
+            }
+        }
+        impl Eq for dirent {}
+        impl ::fmt::Debug for dirent {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("dirent")
+                    .field("d_ino", &self.d_ino)
+                    .field("d_off", &self.d_off)
+                    .field("d_reclen", &self.d_reclen)
+                    .field("d_type", &self.d_type)
+                    // FIXME: .field("d_name", &self.d_name)
+                    .finish()
+            }
+        }
+        impl ::hash::Hash for dirent {
+            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                self.d_ino.hash(state);
+                self.d_off.hash(state);
+                self.d_reclen.hash(state);
+                self.d_type.hash(state);
+                self.d_name.hash(state);
+            }
+        }
+
+        impl PartialEq for dirent64 {
+            fn eq(&self, other: &dirent64) -> bool {
+                self.d_ino == other.d_ino
+                    && self.d_off == other.d_off
+                    && self.d_reclen == other.d_reclen
+                    && self.d_type == other.d_type
+                    && self
+                    .d_name
+                    .iter()
+                    .zip(other.d_name.iter())
+                    .all(|(a,b)| a == b)
+            }
+        }
+        impl Eq for dirent64 {}
+        impl ::fmt::Debug for dirent64 {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("dirent64")
+                    .field("d_ino", &self.d_ino)
+                    .field("d_off", &self.d_off)
+                    .field("d_reclen", &self.d_reclen)
+                    .field("d_type", &self.d_type)
+                    // FIXME: .field("d_name", &self.d_name)
+                    .finish()
+            }
+        }
+        impl ::hash::Hash for dirent64 {
+            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                self.d_ino.hash(state);
+                self.d_off.hash(state);
+                self.d_reclen.hash(state);
+                self.d_type.hash(state);
+                self.d_name.hash(state);
+            }
+        }
+    }
+}
+
 // PUB_CONST
 
 pub const INT_MIN: c_int = -2147483648;
diff --git a/src/fuchsia/no_align.rs b/src/fuchsia/no_align.rs
index 1b8db535..437da97e 100644
--- a/src/fuchsia/no_align.rs
+++ b/src/fuchsia/no_align.rs
@@ -21,7 +21,6 @@ macro_rules! expand_align {
         }
 
         s_no_extra_traits! {
-            #[allow(missing_debug_implementations)]
             pub struct pthread_mutex_t {
                 #[cfg(any(target_arch = "arm",
                           all(target_arch = "x86_64",
@@ -34,14 +33,12 @@ macro_rules! expand_align {
                 size: [u8; ::__SIZEOF_PTHREAD_MUTEX_T],
             }
 
-            #[allow(missing_debug_implementations)]
             pub struct pthread_rwlock_t {
                 __align: [::c_long; 0],
                 __align: [::c_longlong; 0],
                 size: [u8; ::__SIZEOF_PTHREAD_RWLOCK_T],
             }
 
-            #[allow(missing_debug_implementations)]
             pub struct pthread_cond_t {
                 __align: [*const ::c_void; 0],
                 #[cfg(not(target_env = "musl"))]
@@ -49,5 +46,84 @@ macro_rules! expand_align {
                 size: [u8; ::__SIZEOF_PTHREAD_COND_T],
             }
         }
+
+        cfg_if! {
+            if #[cfg(feature = "extra_traits")] {
+                impl PartialEq for pthread_cond_t {
+                    fn eq(&self, other: &pthread_cond_t) -> bool {
+                        // Ignore __align field
+                        self.size
+                            .iter()
+                            .zip(other.size.iter())
+                            .all(|(a,b)| a == b)
+                    }
+                }
+                impl Eq for pthread_cond_t {}
+                impl ::fmt::Debug for pthread_cond_t {
+                    fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                        f.debug_struct("pthread_cond_t")
+                            // Ignore __align field
+                            // FIXME: .field("size", &self.size)
+                            .finish()
+                    }
+                }
+                impl ::hash::Hash for pthread_cond_t {
+                    fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                        // Ignore __align field
+                        self.size.hash(state);
+                    }
+                }
+
+                impl PartialEq for pthread_mutex_t {
+                    fn eq(&self, other: &pthread_mutex_t) -> bool {
+                        // Ignore __align field
+                        self.size
+                            .iter()
+                            .zip(other.size.iter())
+                            .all(|(a,b)| a == b)
+                    }
+                }
+                impl Eq for pthread_mutex_t {}
+                impl ::fmt::Debug for pthread_mutex_t {
+                    fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                        f.debug_struct("pthread_mutex_t")
+                            // Ignore __align field
+                            // FIXME: .field("size", &self.size)
+                            .finish()
+                    }
+                }
+                impl ::hash::Hash for pthread_mutex_t {
+                    fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                        // Ignore __align field
+                        self.size.hash(state);
+                    }
+                }
+
+                impl PartialEq for pthread_rwlock_t {
+                    fn eq(&self, other: &pthread_rwlock_t) -> bool {
+                        // Ignore __align field
+                        self.size
+                            .iter()
+                            .zip(other.size.iter())
+                            .all(|(a,b)| a == b)
+                    }
+                }
+                impl Eq for pthread_rwlock_t {}
+                impl ::fmt::Debug for pthread_rwlock_t {
+                    fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                        f.debug_struct("pthread_rwlock_t")
+                            // Ignore __align field
+                            // FIXME: .field("size", &self.size)
+                            .finish()
+                    }
+                }
+                impl ::hash::Hash for pthread_rwlock_t {
+                    fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                        // Ignore __align field
+                        self.size.hash(state);
+                    }
+                }
+            }
+        }
     }
 }
diff --git a/src/fuchsia/x86_64.rs b/src/fuchsia/x86_64.rs
index 8c0dc55a..eb220998 100644
--- a/src/fuchsia/x86_64.rs
+++ b/src/fuchsia/x86_64.rs
@@ -65,7 +65,6 @@ s! {
 }
 
 s_no_extra_traits! {
-    #[allow(missing_debug_implementations)]
     pub struct ucontext_t {
         pub uc_flags: ::c_ulong,
         pub uc_link: *mut ucontext_t,
@@ -76,6 +75,48 @@ s_no_extra_traits! {
     }
 }
 
+cfg_if! {
+    if #[cfg(feature = "extra_traits")] {
+        impl PartialEq for ucontext_t {
+            fn eq(&self, other: &ucontext_t) -> bool {
+                self.uc_flags == other.uc_flags
+                    && self.uc_link == other.uc_link
+                    && self.uc_stack == other.uc_stack
+                    && self.uc_mcontext == other.uc_mcontext
+                    && self.uc_sigmask == other.uc_sigmask
+                    && self
+                    .__private
+                    .iter()
+                    .zip(other.__private.iter())
+                    .all(|(a,b)| a == b)
+            }
+        }
+        impl Eq for ucontext_t {}
+        impl ::fmt::Debug for ucontext_t {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("ucontext_t")
+                    .field("uc_flags", &self.uc_flags)
+                    .field("uc_link", &self.uc_link)
+                    .field("uc_stack", &self.uc_stack)
+                    .field("uc_mcontext", &self.uc_mcontext)
+                    .field("uc_sigmask", &self.uc_sigmask)
+                    // FIXME: .field("__private", &self.__private)
+                    .finish()
+            }
+        }
+        impl ::hash::Hash for ucontext_t {
+            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                self.uc_flags.hash(state);
+                self.uc_link.hash(state);
+                self.uc_stack.hash(state);
+                self.uc_mcontext.hash(state);
+                self.uc_sigmask.hash(state);
+                self.__private.hash(state);
+            }
+        }
+    }
+}
+
 // Syscall table
 
 pub const SYS_read: ::c_long = 0;
-- 
GitLab