Skip to content

Commit 96c1c5a

Browse files
committed
Use rusts internal hash algorithm.
1 parent 58b905f commit 96c1c5a

File tree

4 files changed

+39
-22
lines changed

4 files changed

+39
-22
lines changed

vm/src/obj/objbytes.rs

+12
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@ use super::super::pyobject::{
55
use super::super::vm::VirtualMachine;
66
use super::objint;
77
use super::objtype;
8+
use num_bigint::ToBigInt;
89
use num_traits::ToPrimitive;
910
use std::cell::Ref;
11+
use std::hash::{Hash, Hasher};
1012
use std::ops::Deref;
1113
// Binary data support
1214

1315
// Fill bytes class methods:
1416
pub fn init(context: &PyContext) {
1517
let ref bytes_type = context.bytes_type;
1618
bytes_type.set_attr("__eq__", context.new_rustfunc(bytes_eq));
19+
bytes_type.set_attr("__hash__", context.new_rustfunc(bytes_hash));
1720
bytes_type.set_attr("__new__", context.new_rustfunc(bytes_new));
1821
bytes_type.set_attr("__repr__", context.new_rustfunc(bytes_repr));
1922
}
@@ -64,6 +67,15 @@ fn bytes_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
6467
Ok(vm.ctx.new_bool(result))
6568
}
6669

70+
fn bytes_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
71+
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.bytes_type()))]);
72+
let data = get_value(zelf);
73+
let mut hasher = std::collections::hash_map::DefaultHasher::new();
74+
data.hash(&mut hasher);
75+
let hash = hasher.finish();
76+
Ok(vm.ctx.new_int(hash.to_bigint().unwrap()))
77+
}
78+
6779
pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<u8>> + 'a {
6880
Ref::map(obj.borrow(), |py_obj| {
6981
if let PyObjectKind::Bytes { ref value } = py_obj.kind {

vm/src/obj/objint.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ use super::objstr;
88
use super::objtype;
99
use num_bigint::{BigInt, ToBigInt};
1010
use num_traits::{Pow, Signed, ToPrimitive, Zero};
11+
use std::hash::{Hash, Hasher};
1112

1213
// This proxy allows for easy switching between types.
13-
// TODO: maybe this is a good idea:
14-
// type IntType = BigInt;
14+
type IntType = BigInt;
1515

1616
fn int_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
1717
arg_check!(vm, args, required = [(int, Some(vm.ctx.int_type()))]);
@@ -47,7 +47,7 @@ pub fn to_int(
4747
vm: &mut VirtualMachine,
4848
obj: &PyObjectRef,
4949
base: u32,
50-
) -> Result<BigInt, PyObjectRef> {
50+
) -> Result<IntType, PyObjectRef> {
5151
let val = if objtype::isinstance(obj, &vm.ctx.int_type()) {
5252
get_value(obj)
5353
} else if objtype::isinstance(obj, &vm.ctx.float_type()) {
@@ -75,7 +75,7 @@ pub fn to_int(
7575
}
7676

7777
// Retrieve inner int value:
78-
pub fn get_value(obj: &PyObjectRef) -> BigInt {
78+
pub fn get_value(obj: &PyObjectRef) -> IntType {
7979
if let PyObjectKind::Integer { value } = &obj.borrow().kind {
8080
value.clone()
8181
} else {
@@ -171,9 +171,11 @@ fn int_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
171171

172172
fn int_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
173173
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.int_type()))]);
174-
175-
// TODO: how to hash int?
176-
Ok(zelf.clone())
174+
let value = BigInt::from_pyobj(zelf);
175+
let mut hasher = std::collections::hash_map::DefaultHasher::new();
176+
value.hash(&mut hasher);
177+
let hash = hasher.finish();
178+
Ok(vm.ctx.new_int(hash.to_bigint().unwrap()))
177179
}
178180

179181
fn int_abs(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

vm/src/obj/objstr.rs

+11
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use super::objsequence::PySliceableSequence;
77
use super::objtype;
88
use num_bigint::ToBigInt;
99
use num_traits::ToPrimitive;
10+
use std::hash::{Hash, Hasher};
1011

1112
pub fn init(context: &PyContext) {
1213
let ref str_type = context.str_type;
@@ -15,6 +16,7 @@ pub fn init(context: &PyContext) {
1516
str_type.set_attr("__contains__", context.new_rustfunc(str_contains));
1617
str_type.set_attr("__getitem__", context.new_rustfunc(str_getitem));
1718
str_type.set_attr("__gt__", context.new_rustfunc(str_gt));
19+
str_type.set_attr("__hash__", context.new_rustfunc(str_hash));
1820
str_type.set_attr("__len__", context.new_rustfunc(str_len));
1921
str_type.set_attr("__mul__", context.new_rustfunc(str_mul));
2022
str_type.set_attr("__new__", context.new_rustfunc(str_new));
@@ -124,6 +126,15 @@ fn str_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
124126
}
125127
}
126128

129+
fn str_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
130+
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.str_type()))]);
131+
let value = get_value(zelf);
132+
let mut hasher = std::collections::hash_map::DefaultHasher::new();
133+
value.hash(&mut hasher);
134+
let hash = hasher.finish();
135+
Ok(vm.ctx.new_int(hash.to_bigint().unwrap()))
136+
}
137+
127138
fn str_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
128139
arg_check!(vm, args, required = [(s, Some(vm.ctx.str_type()))]);
129140
let sv = get_value(s);

vm/src/obj/objtuple.rs

+7-15
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use super::objsequence::{get_elements, get_item, seq_equal};
99
use super::objstr;
1010
use super::objtype;
1111
use num_bigint::ToBigInt;
12-
use num_traits::ToPrimitive;
12+
use std::hash::{Hash, Hasher};
1313

1414
fn tuple_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
1515
arg_check!(
@@ -30,22 +30,14 @@ fn tuple_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
3030

3131
fn tuple_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
3232
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.tuple_type()))]);
33-
34-
let mut x: usize = 0x345678;
3533
let elements = get_elements(zelf);
36-
let len: usize = elements.len();
37-
let mut mult = 0xf4243;
38-
39-
for elem in elements.iter() {
40-
let y: usize = objint::get_value(&vm.call_method(elem, "__hash__", vec![])?)
41-
.to_usize()
42-
.unwrap();
43-
x = (x ^ y) * mult;
44-
mult = mult + 82520 + len * 2;
34+
let mut hasher = std::collections::hash_map::DefaultHasher::new();
35+
for element in elements.iter() {
36+
let element_hash = objint::get_value(&vm.call_method(element, "__hash__", vec![])?);
37+
element_hash.hash(&mut hasher);
4538
}
46-
x += 97531;
47-
48-
Ok(vm.ctx.new_int(x.to_bigint().unwrap()))
39+
let hash = hasher.finish();
40+
Ok(vm.ctx.new_int(hash.to_bigint().unwrap()))
4941
}
5042

5143
fn tuple_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

0 commit comments

Comments
 (0)