1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//! # Hash Macro Implementation
//!
//! The `Hash` macro generates a `hashCode()` method for computing numeric hash codes.
//! This is analogous to Rust's `Hash` trait and Java's `hashCode()` method, enabling
//! objects to be used as keys in hash-based collections.
//!
//! ## Generated Output
//!
//! | Type | Generated Code | Description |
//! |------|----------------|-------------|
//! | Class | `classNameHashCode(value)` + `static hashCode(value)` | Standalone function + static wrapper method |
//! | Enum | `enumNameHashCode(value: EnumName): number` | Standalone function hashing by enum value |
//! | Interface | `interfaceNameHashCode(value: InterfaceName): number` | Standalone function computing hash |
//! | Type Alias | `typeNameHashCode(value: TypeName): number` | Standalone function computing hash |
//!
//!
//! ## Hash Algorithm
//!
//! Uses the standard polynomial rolling hash algorithm:
//!
//! ```text
//! hash = 17 // Initial seed
//! for each field:
//! hash = (hash * 31 + fieldHash) | 0
//! ```
//!
//! The `| 0` (bitwise OR with zero) at the end of each step coerces the result
//! to a 32-bit signed integer, preventing floating-point drift from repeated
//! multiplication. This is equivalent to casting to `i32` in Rust and consistent
//! with Java's `Objects.hash()` implementation.
//!
//! ## Type-Specific Hashing
//!
//! | Type | Hash Strategy |
//! |------|---------------|
//! | `number` | Integer: direct value; Float: string hash of decimal |
//! | `bigint` | String hash of decimal representation |
//! | `string` | Character-by-character polynomial hash |
//! | `boolean` | 1231 for true, 1237 for false (Java convention) |
//! | `Date` | `getTime()` timestamp |
//! | Arrays | Element-by-element hash combination |
//! | `Map` | Entry-by-entry key+value hash |
//! | `Set` | Element-by-element hash |
//! | Objects | Calls `hashCode()` if available, else JSON string hash |
//!
//! ## Field-Level Options
//!
//! The `@hash` decorator supports:
//!
//! - `skip` - Exclude the field from hash calculation
//!
//! ## Example
//!
//! ```typescript
//! /** @derive(Hash) */
//! class User {
//! id: number;
//! name: string;
//!
//! /** @hash({ skip: true }) */
//! cachedScore: number;
//! }
//! ```
//!
//! Generated output:
//!
//! ```typescript
//! class User {
//! id: number;
//! name: string;
//!
//! cachedScore: number;
//!
//! static hashCode(value: User): number {
//! return userHashCode(value);
//! }
//! }
//!
//! export function userHashCode(value: User): number {
//! let hash = 17;
//! hash =
//! (hash * 31 +
//! (Number.isInteger(value.id)
//! ? value.id | 0
//! : value.id
//! .toString()
//! .split('')
//! .reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0))) |
//! 0;
//! hash =
//! (hash * 31 +
//! (value.name ?? '').split('').reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0)) |
//! 0;
//! return hash;
//! }
//! ```
//!
//! ## Hash Contract
//!
//! Objects that are equal (`PartialEq`) should produce the same hash code.
//! When using `@hash(skip)`, ensure the same fields are skipped in both
//! `Hash` and `PartialEq` to maintain this contract.
pub use *;
pub use generate_field_hash_for_interface;
pub use HashField;