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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! VADER sentiment scoring with exact output parity against Python
//! [vaderSentiment] 3.3.2.
//!
//! VADER (Valence Aware Dictionary and sEntiment Reasoner) is the rule-based
//! sentiment model of Hutto & Gilbert (ICWSM-14). This crate reimplements
//! that package's whole rule set over that package's own data files,
//! vendored byte-identical from the 3.3.2 sdist: lexicon scoring, booster
//! and dampener modifiers with the casing increment, negation with the
//! "least" special case, contrastive "but" reweighting, exclamation and
//! question mark emphasis, the special-case idioms, emoji translation, and
//! the alpha-15 normalization to compound. For every input, all four scores
//! equal what the Python package returns at its published precision: three
//! decimals for the proportions, four for the compound. The frozen oracle
//! vectors in `tests/vectors/frozen.tsv` replay on every `cargo test`, and a
//! release-time differential corpus against the pinned package holds that
//! parity with zero tolerated divergence. Casing is pinned with the rest:
//! `str.isupper()` and `str.lower()` answer from tables vendored out of
//! CPython 3.14.6 with Unicode data 16.0.0, checked across every codepoint,
//! so the scores hold still when the Rust standard library adopts a newer
//! Unicode version than the reference interpreter's.
//!
//! ```
//! use vader_parity::SentimentIntensityAnalyzer;
//!
//! let analyzer = SentimentIntensityAnalyzer::new();
//! let scores = analyzer.polarity_scores("VADER is smart, handsome, and funny.");
//! assert_eq!(scores.neg, 0.0);
//! assert_eq!(scores.neu, 0.254);
//! assert_eq!(scores.pos, 0.746);
//! assert_eq!(scores.compound, 0.8316);
//! ```
//!
//! # Scoring many texts
//!
//! [`SentimentIntensityAnalyzer::new`] parses the vendored lexicons, about
//! 11,000 data lines, once. Build one analyzer and score many texts. Each
//! call is a bounded linear pass, and the example below is the crate's own
//! regression tripwire for that claim.
//!
//! ```
//! use vader_parity::SentimentIntensityAnalyzer;
//!
//! let analyzer = SentimentIntensityAnalyzer::new();
//! let started = std::time::Instant::now();
//! for _ in 0..10_000 {
//! analyzer.polarity_scores("Today only kinda sux! But I'll get by, lol");
//! }
//! assert!(started.elapsed() < std::time::Duration::from_secs(30));
//! ```
//!
//! # Scope
//!
//! The reference is English-only and so is its lexicon. This crate is the
//! scoring engine only, pinned to reference version 3.3.2, `std`-only, with
//! zero runtime dependencies. Sentence splitting, custom lexicons, and other
//! reference versions are out of scope.
//!
//! # Attribution
//!
//! The VADER algorithm design, the sentiment lexicon, and the emoji lexicon
//! are the MIT-licensed work of C.J. Hutto and E.E. Gilbert. The vendored
//! files in `data/` ship with the authors' license text and their recorded
//! sha256 digests, and the Rust implementation and its tests are this
//! crate's. If you use VADER, cite: Hutto, C.J. & Gilbert, E.E. (2014).
//! VADER: A Parsimonious Rule-based Model for Sentiment Analysis of Social
//! Media Text. Eighth International Conference on Weblogs and Social Media
//! (ICWSM-14). Ann Arbor, MI.
//!
//! [vaderSentiment]: https://pypi.org/project/vaderSentiment/3.3.2/
/// The four scores for one text. Field values match Python vaderSentiment
/// 3.3.2, at that package's published precision.
///
/// The proportions describe how the text's tokens split across the three
/// categories and sum to 1 up to rounding residue. The compound is the
/// normalized, weighted composite in [-1, 1], the single number most callers
/// read (its sign is the sentiment label). `tests/properties.rs` holds the
/// distribution invariant, and the frozen vectors pin all four fields.
/// The analyzer, holding the loaded lexicons.
///
/// Construction parses the vendored VADER 3.3.2 data once, and scoring
/// reuses the parsed tables. Two analyzers are interchangeable: same input,
/// same bits, which `tests/properties.rs` asserts.