java_utils/
object.rs

1use std::num::Wrapping;
2use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
3use std::ffi::OsStr;
4use std::hash::{BuildHasher, Hash};
5#[cfg(unix)]
6use std::os::unix::ffi::OsStrExt;
7#[cfg(windows)]
8use std::os::windows::ffi::OsStrExt;
9use std::path::Path;
10
11/// The `hashCode` function on all Java `Objects`
12pub trait HashCode {
13    /// Returns a Java hash code value for the object.
14    ///
15    /// This follows the principles of the `java.lang.Object.hashCode` method.
16    fn hash_code(&self) -> i32;
17}
18
19impl<T: HashCode> HashCode for &T {
20    fn hash_code(&self) -> i32 {
21        <T>::hash_code(self)
22    }
23}
24impl<T: HashCode> HashCode for &mut T {
25    fn hash_code(&self) -> i32 {
26        <T>::hash_code(self)
27    }
28}
29impl<T: HashCode> HashCode for Box<T> {
30    fn hash_code(&self) -> i32 {
31        <T>::hash_code(self)
32    }
33}
34impl<T> HashCode for *const T {
35    fn hash_code(&self) -> i32 {
36        (*self as usize).hash_code()
37    }
38}
39impl<T> HashCode for *mut T {
40    fn hash_code(&self) -> i32 {
41        (*self as usize).hash_code()
42    }
43}
44impl<Ret> HashCode for fn() -> Ret {
45    fn hash_code(&self) -> i32 {
46        (*self as usize).hash_code()
47    }
48}
49impl<Ret, A> HashCode for fn(A) -> Ret {
50    fn hash_code(&self) -> i32 {
51        (*self as usize).hash_code()
52    }
53}
54impl<Ret, A, B> HashCode for fn(A, B) -> Ret {
55    fn hash_code(&self) -> i32 {
56        (*self as usize).hash_code()
57    }
58}
59impl<Ret, A, B, C> HashCode for fn(A, B, C) -> Ret {
60    fn hash_code(&self) -> i32 {
61        (*self as usize).hash_code()
62    }
63}
64impl<Ret, A, B, C, D> HashCode for fn(A, B, C, D) -> Ret {
65    fn hash_code(&self) -> i32 {
66        (*self as usize).hash_code()
67    }
68}
69impl<Ret, A, B, C, D, E> HashCode for fn(A, B, C, D, E) -> Ret {
70    fn hash_code(&self) -> i32 {
71        (*self as usize).hash_code()
72    }
73}
74impl<Ret, A, B, C, D, E, F> HashCode for fn(A, B, C, D, E, F) -> Ret {
75    fn hash_code(&self) -> i32 {
76        (*self as usize).hash_code()
77    }
78}
79impl HashCode for () {
80    fn hash_code(&self) -> i32 {
81        0
82    }
83}
84impl<T: HashCode> HashCode for Option<&T> {
85    fn hash_code(&self) -> i32 {
86        self.map(|e| e.hash_code()).unwrap_or(0)
87    }
88}
89impl<T: HashCode, U: HashCode> HashCode for (T, U) {
90    fn hash_code(&self) -> i32 {
91        self.0.hash_code() ^ self.1.hash_code()
92    }
93}
94
95macro_rules! impl_for_iterable {
96    ($($type:ty:[ $( $i:tt: $($t:ident),*);+ ] )*) => (
97        $(
98            impl< $( $i: $($t+)* ),* > HashCode for $type {
99                fn hash_code(&self) -> i32 {
100                    self.iter()
101                        .fold(1, |hash_code, e| 31*hash_code + e.hash_code())
102                }
103            }
104        )*
105    );
106}
107
108impl_for_iterable!(&[T]:[T: HashCode]);
109
110// COLLECTIONS
111
112impl_for_iterable! {
113    Vec<T>:[T: HashCode]
114    VecDeque<T>:[T: HashCode]
115    LinkedList<T>:[T: HashCode]
116    HashMap<K, V, H>:[K: HashCode, Eq, Hash; V: HashCode; H: BuildHasher]
117    BTreeMap<K, V>:[K: HashCode, Eq; V: HashCode]
118    HashSet<T, H>:[T: HashCode, Eq, Hash; H: BuildHasher]
119    BTreeSet<T>:[T: HashCode]
120    BinaryHeap<T>:[T: HashCode, Ord]
121}
122// COLLECTIONS END
123
124mod wrapping_pow;
125use self::wrapping_pow::WrapPow;
126
127impl HashCode for str {
128    fn hash_code(&self) -> i32 {
129        let n = self.chars().count() as u32;
130        self.chars()
131            .enumerate()
132            .map(|(i, c)| (i as u32, c as i32))
133            .map(|(i, c)| Wrapping(c.wrapping_mul(31i32.wrap_pow(n - i - 1))))
134            .sum::<Wrapping<_>>().0
135    }
136}
137
138#[cfg(windows)]
139impl HashCode for OsStr {
140    fn hash_code(&self) -> i32 {
141        let n = self.encode_wide().count() as u32;
142        self.encode_wide()
143            .enumerate()
144            .map(|(i, c)| (i as u32, i32::from(c)))
145            .map(|(i, c)| Wrapping(c.wrapping_mul(31i32.wrap_pow(n - i - 1))))
146            .sum::<Wrapping<_>>().0
147    }
148}
149#[cfg(unix)]
150impl HashCode for OsStr {
151    fn hash_code(&self) -> i32 {
152        self.as_bytes().hash_code()
153    }
154}
155
156#[cfg(any(unix, windows))]
157impl HashCode for Path {
158    fn hash_code(&self) -> i32 {
159        self.as_os_str().hash_code()
160    }
161}
162
163macro_rules! impl_for_prim_signed {
164    ($($type:ty)*) => (
165        $(
166            impl HashCode for $type {
167                fn hash_code(&self) -> i32 {
168                    i32::from(*self)
169                }
170            }
171        )*
172    );
173}
174
175macro_rules! impl_for_prim_unsigned {
176    ($($u:ty, $i:ty)*) => (
177        $(
178            impl HashCode for $u {
179                fn hash_code(&self) -> i32 {
180                    (*self as $i).hash_code()
181                }
182            }
183        )*
184    );
185}
186
187impl_for_prim_signed! {
188    i8
189    i16
190    i32
191}
192
193impl_for_prim_unsigned! {
194    u8, i8
195    u16, i16
196    u32, i32
197    u64, i64
198}
199
200impl HashCode for bool {
201    fn hash_code(&self) -> i32 {
202        if *self {
203            1231
204        } else {
205            1237
206        }
207    }
208}
209
210impl HashCode for char {
211    fn hash_code(&self) -> i32 {
212        *self as i32
213    }
214}
215
216impl HashCode for f32 {
217    fn hash_code(&self) -> i32 {
218        self.to_bits() as i32
219    }
220}
221
222impl HashCode for f64 {
223    fn hash_code(&self) -> i32 {
224        self.to_bits().hash_code()
225    }
226}
227
228impl HashCode for i64 {
229    fn hash_code(&self) -> i32 {
230        (*self ^ (*self >> 32)) as i32
231    }
232}
233
234#[cfg(target_pointer_width = "64")]
235impl HashCode for isize {
236    fn hash_code(&self) -> i32 {
237        (*self as u64).hash_code()
238    }
239}
240#[cfg(target_pointer_width = "64")]
241impl HashCode for usize {
242    fn hash_code(&self) -> i32 {
243        (*self as u64).hash_code()
244    }
245}
246#[cfg(not(target_pointer_width = "64"))]
247impl HashCode for isize {
248    fn hash_code(&self) -> i32 {
249        *self as i32
250    }
251}
252#[cfg(not(target_pointer_width = "64"))]
253impl HashCode for usize {
254    fn hash_code(&self) -> i32 {
255        *self as i32
256    }
257}