]> git.lizzy.rs Git - rust.git/blob - library/core/tests/hash/mod.rs
Rollup merge of #104194 - BoxyUwU:early_binder_docs, r=compiler-errors
[rust.git] / library / core / tests / hash / mod.rs
1 mod sip;
2
3 use std::default::Default;
4 use std::hash::{BuildHasher, Hash, Hasher};
5 use std::ptr;
6 use std::rc::Rc;
7
8 struct MyHasher {
9     hash: u64,
10 }
11
12 impl const Default for MyHasher {
13     fn default() -> MyHasher {
14         MyHasher { hash: 0 }
15     }
16 }
17
18 impl const Hasher for MyHasher {
19     fn write(&mut self, buf: &[u8]) {
20         // FIXME(const_trait_impl): change to for loop
21         let mut i = 0;
22         while i < buf.len() {
23             self.hash += buf[i] as u64;
24             i += 1;
25         }
26     }
27     fn write_str(&mut self, s: &str) {
28         self.write(s.as_bytes());
29         self.write_u8(0xFF);
30     }
31     fn finish(&self) -> u64 {
32         self.hash
33     }
34 }
35
36 #[test]
37 fn test_writer_hasher() {
38     const fn hash<T: ~const Hash>(t: &T) -> u64 {
39         let mut s = MyHasher { hash: 0 };
40         t.hash(&mut s);
41         s.finish()
42     }
43
44     const {
45         // FIXME(fee1-dead): assert_eq
46         assert!(hash(&()) == 0);
47         assert!(hash(&5_u8) == 5);
48         assert!(hash(&5_u16) == 5);
49         assert!(hash(&5_u32) == 5);
50
51         assert!(hash(&'a') == 97);
52
53         let s: &str = "a";
54         assert!(hash(&s) == 97 + 0xFF);
55     };
56
57     assert_eq!(hash(&()), 0);
58
59     assert_eq!(hash(&5_u8), 5);
60     assert_eq!(hash(&5_u16), 5);
61     assert_eq!(hash(&5_u32), 5);
62     assert_eq!(hash(&5_u64), 5);
63     assert_eq!(hash(&5_usize), 5);
64
65     assert_eq!(hash(&5_i8), 5);
66     assert_eq!(hash(&5_i16), 5);
67     assert_eq!(hash(&5_i32), 5);
68     assert_eq!(hash(&5_i64), 5);
69     assert_eq!(hash(&5_isize), 5);
70
71     assert_eq!(hash(&false), 0);
72     assert_eq!(hash(&true), 1);
73
74     assert_eq!(hash(&'a'), 97);
75
76     let s: &str = "a";
77     assert_eq!(hash(&s), 97 + 0xFF);
78     let s: Box<str> = String::from("a").into_boxed_str();
79     assert_eq!(hash(&s), 97 + 0xFF);
80     let s: Rc<&str> = Rc::new("a");
81     assert_eq!(hash(&s), 97 + 0xFF);
82     let cs: &[u8] = &[1, 2, 3];
83     assert_eq!(hash(&cs), 9);
84     let cs: Box<[u8]> = Box::new([1, 2, 3]);
85     assert_eq!(hash(&cs), 9);
86     let cs: Rc<[u8]> = Rc::new([1, 2, 3]);
87     assert_eq!(hash(&cs), 9);
88
89     let ptr = ptr::invalid::<i32>(5_usize);
90     assert_eq!(hash(&ptr), 5);
91
92     let ptr = ptr::invalid_mut::<i32>(5_usize);
93     assert_eq!(hash(&ptr), 5);
94
95     if cfg!(miri) {
96         // Miri cannot hash pointers
97         return;
98     }
99
100     let cs: &mut [u8] = &mut [1, 2, 3];
101     let ptr = cs.as_ptr();
102     let slice_ptr = cs as *const [u8];
103     assert_eq!(hash(&slice_ptr), hash(&ptr) + cs.len() as u64);
104
105     let slice_ptr = cs as *mut [u8];
106     assert_eq!(hash(&slice_ptr), hash(&ptr) + cs.len() as u64);
107 }
108
109 struct Custom {
110     hash: u64,
111 }
112 struct CustomHasher {
113     output: u64,
114 }
115
116 impl const Hasher for CustomHasher {
117     fn finish(&self) -> u64 {
118         self.output
119     }
120     fn write(&mut self, _: &[u8]) {
121         panic!()
122     }
123     fn write_u64(&mut self, data: u64) {
124         self.output = data;
125     }
126 }
127
128 impl const Default for CustomHasher {
129     fn default() -> CustomHasher {
130         CustomHasher { output: 0 }
131     }
132 }
133
134 impl const Hash for Custom {
135     fn hash<H: ~const Hasher>(&self, state: &mut H) {
136         state.write_u64(self.hash);
137     }
138 }
139
140 #[test]
141 fn test_custom_state() {
142     const fn hash<T: ~const Hash>(t: &T) -> u64 {
143         let mut c = CustomHasher { output: 0 };
144         t.hash(&mut c);
145         c.finish()
146     }
147
148     assert_eq!(hash(&Custom { hash: 5 }), 5);
149
150     const { assert!(hash(&Custom { hash: 6 }) == 6) };
151 }
152
153 // FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten.
154 // See https://github.com/kripken/emscripten-fastcomp/issues/169
155 #[cfg(not(target_os = "emscripten"))]
156 #[test]
157 fn test_indirect_hasher() {
158     let mut hasher = MyHasher { hash: 0 };
159     {
160         let mut indirect_hasher: &mut dyn Hasher = &mut hasher;
161         5u32.hash(&mut indirect_hasher);
162     }
163     assert_eq!(hasher.hash, 5);
164 }
165
166 #[test]
167 fn test_build_hasher_object_safe() {
168     use std::collections::hash_map::{DefaultHasher, RandomState};
169
170     let _: &dyn BuildHasher<Hasher = DefaultHasher> = &RandomState::new();
171 }
172
173 // just tests by whether or not this compiles
174 fn _build_hasher_default_impl_all_auto_traits<T>() {
175     use std::panic::{RefUnwindSafe, UnwindSafe};
176     fn all_auto_traits<T: Send + Sync + Unpin + UnwindSafe + RefUnwindSafe>() {}
177
178     all_auto_traits::<std::hash::BuildHasherDefault<T>>();
179 }