1use serde::{Deserialize, Serialize};
19use std::fmt;
20use std::ops::{Add, AddAssign, Sub, SubAssign};
21
22#[derive(
24 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
25)]
26#[repr(transparent)]
27pub struct TokenCount(u32);
28
29impl TokenCount {
30 #[inline]
32 pub const fn new(count: u32) -> Self {
33 Self(count)
34 }
35
36 #[inline]
38 pub const fn zero() -> Self {
39 Self(0)
40 }
41
42 #[inline]
44 pub const fn get(self) -> u32 {
45 self.0
46 }
47
48 #[inline]
50 pub const fn is_zero(self) -> bool {
51 self.0 == 0
52 }
53
54 #[inline]
56 pub const fn saturating_sub(self, rhs: Self) -> Self {
57 Self(self.0.saturating_sub(rhs.0))
58 }
59
60 #[inline]
62 pub const fn saturating_add(self, rhs: Self) -> Self {
63 Self(self.0.saturating_add(rhs.0))
64 }
65
66 #[inline]
68 pub fn percentage_of(self, total: Self) -> f32 {
69 if total.0 == 0 {
70 0.0
71 } else {
72 (self.0 as f32 / total.0 as f32) * 100.0
73 }
74 }
75}
76
77impl Add for TokenCount {
78 type Output = Self;
79
80 #[inline]
81 fn add(self, rhs: Self) -> Self::Output {
82 Self(self.0 + rhs.0)
83 }
84}
85
86impl AddAssign for TokenCount {
87 #[inline]
88 fn add_assign(&mut self, rhs: Self) {
89 self.0 += rhs.0;
90 }
91}
92
93impl Sub for TokenCount {
94 type Output = Self;
95
96 #[inline]
97 fn sub(self, rhs: Self) -> Self::Output {
98 Self(self.0 - rhs.0)
99 }
100}
101
102impl SubAssign for TokenCount {
103 #[inline]
104 fn sub_assign(&mut self, rhs: Self) {
105 self.0 -= rhs.0;
106 }
107}
108
109impl From<u32> for TokenCount {
110 #[inline]
111 fn from(value: u32) -> Self {
112 Self(value)
113 }
114}
115
116impl From<TokenCount> for u32 {
117 #[inline]
118 fn from(value: TokenCount) -> Self {
119 value.0
120 }
121}
122
123impl fmt::Display for TokenCount {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 write!(f, "{} tokens", self.0)
126 }
127}
128
129impl std::iter::Sum for TokenCount {
130 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
131 iter.fold(Self::zero(), |acc, x| acc + x)
132 }
133}
134
135#[derive(
137 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
138)]
139#[repr(transparent)]
140pub struct LineNumber(u32);
141
142impl LineNumber {
143 #[inline]
145 pub const fn new(line: u32) -> Self {
146 Self(line)
147 }
148
149 #[inline]
151 pub const fn first() -> Self {
152 Self(1)
153 }
154
155 #[inline]
157 pub const fn get(self) -> u32 {
158 self.0
159 }
160
161 #[inline]
163 pub const fn is_valid(self) -> bool {
164 self.0 > 0
165 }
166
167 #[inline]
169 pub const fn to_zero_indexed(self) -> u32 {
170 self.0.saturating_sub(1)
171 }
172
173 #[inline]
175 pub const fn from_zero_indexed(offset: u32) -> Self {
176 Self(offset + 1)
177 }
178
179 #[inline]
181 pub const fn lines_to(self, end: Self) -> u32 {
182 if end.0 >= self.0 {
183 end.0 - self.0 + 1
184 } else {
185 1
186 }
187 }
188}
189
190impl From<u32> for LineNumber {
191 #[inline]
192 fn from(value: u32) -> Self {
193 Self(value)
194 }
195}
196
197impl From<LineNumber> for u32 {
198 #[inline]
199 fn from(value: LineNumber) -> Self {
200 value.0
201 }
202}
203
204impl fmt::Display for LineNumber {
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 write!(f, "L{}", self.0)
207 }
208}
209
210#[derive(
212 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
213)]
214#[repr(transparent)]
215pub struct ByteOffset(usize);
216
217impl ByteOffset {
218 #[inline]
220 pub const fn new(offset: usize) -> Self {
221 Self(offset)
222 }
223
224 #[inline]
226 pub const fn zero() -> Self {
227 Self(0)
228 }
229
230 #[inline]
232 pub const fn get(self) -> usize {
233 self.0
234 }
235}
236
237impl From<usize> for ByteOffset {
238 #[inline]
239 fn from(value: usize) -> Self {
240 Self(value)
241 }
242}
243
244impl From<ByteOffset> for usize {
245 #[inline]
246 fn from(value: ByteOffset) -> Self {
247 value.0
248 }
249}
250
251impl fmt::Display for ByteOffset {
252 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253 write!(f, "@{}", self.0)
254 }
255}
256
257#[derive(
259 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
260)]
261#[repr(transparent)]
262pub struct SymbolId(u32);
263
264impl SymbolId {
265 #[inline]
267 pub const fn new(id: u32) -> Self {
268 Self(id)
269 }
270
271 #[inline]
273 pub const fn unknown() -> Self {
274 Self(0)
275 }
276
277 #[inline]
279 pub const fn get(self) -> u32 {
280 self.0
281 }
282
283 #[inline]
285 pub const fn is_valid(self) -> bool {
286 self.0 > 0
287 }
288}
289
290impl From<u32> for SymbolId {
291 #[inline]
292 fn from(value: u32) -> Self {
293 Self(value)
294 }
295}
296
297impl From<SymbolId> for u32 {
298 #[inline]
299 fn from(value: SymbolId) -> Self {
300 value.0
301 }
302}
303
304impl fmt::Display for SymbolId {
305 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
306 write!(f, "#{}", self.0)
307 }
308}
309
310#[derive(
312 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
313)]
314#[repr(transparent)]
315pub struct FileSize(u64);
316
317impl FileSize {
318 #[inline]
320 pub const fn new(bytes: u64) -> Self {
321 Self(bytes)
322 }
323
324 #[inline]
326 pub const fn zero() -> Self {
327 Self(0)
328 }
329
330 #[inline]
332 pub const fn bytes(self) -> u64 {
333 self.0
334 }
335
336 #[inline]
338 pub const fn kilobytes(self) -> u64 {
339 self.0 / 1024
340 }
341
342 #[inline]
344 pub const fn megabytes(self) -> u64 {
345 self.0 / (1024 * 1024)
346 }
347
348 #[inline]
350 pub const fn exceeds(self, limit: Self) -> bool {
351 self.0 > limit.0
352 }
353}
354
355impl From<u64> for FileSize {
356 #[inline]
357 fn from(value: u64) -> Self {
358 Self(value)
359 }
360}
361
362impl From<FileSize> for u64 {
363 #[inline]
364 fn from(value: FileSize) -> Self {
365 value.0
366 }
367}
368
369impl fmt::Display for FileSize {
370 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
371 if self.0 >= 1024 * 1024 {
372 write!(f, "{:.1} MB", self.0 as f64 / (1024.0 * 1024.0))
373 } else if self.0 >= 1024 {
374 write!(f, "{:.1} KB", self.0 as f64 / 1024.0)
375 } else {
376 write!(f, "{} bytes", self.0)
377 }
378 }
379}
380
381#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
383#[repr(transparent)]
384pub struct ImportanceScore(f32);
385
386impl ImportanceScore {
387 #[inline]
389 pub fn new(score: f32) -> Self {
390 Self(score.clamp(0.0, 1.0))
391 }
392
393 #[inline]
395 pub const fn zero() -> Self {
396 Self(0.0)
397 }
398
399 #[inline]
401 pub const fn max() -> Self {
402 Self(1.0)
403 }
404
405 #[inline]
407 pub const fn default_score() -> Self {
408 Self(0.5)
409 }
410
411 #[inline]
413 pub const fn get(self) -> f32 {
414 self.0
415 }
416
417 #[inline]
419 pub fn is_high(self) -> bool {
420 self.0 > 0.7
421 }
422
423 #[inline]
425 pub fn is_low(self) -> bool {
426 self.0 < 0.3
427 }
428}
429
430impl From<f32> for ImportanceScore {
431 #[inline]
432 fn from(value: f32) -> Self {
433 Self::new(value)
434 }
435}
436
437impl From<ImportanceScore> for f32 {
438 #[inline]
439 fn from(value: ImportanceScore) -> Self {
440 value.0
441 }
442}
443
444impl fmt::Display for ImportanceScore {
445 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
446 write!(f, "{:.2}", self.0)
447 }
448}
449
450impl Eq for ImportanceScore {}
451
452impl PartialOrd for ImportanceScore {
453 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
454 Some(self.cmp(other))
455 }
456}
457
458impl Ord for ImportanceScore {
459 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
460 self.0
462 .partial_cmp(&other.0)
463 .unwrap_or(std::cmp::Ordering::Equal)
464 }
465}
466
467impl std::hash::Hash for ImportanceScore {
468 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
469 self.0.to_bits().hash(state);
470 }
471}
472
473#[cfg(test)]
474mod tests {
475 use super::*;
476 use std::collections::HashSet;
477
478 #[test]
483 fn test_token_count_operations() {
484 let a = TokenCount::new(100);
485 let b = TokenCount::new(50);
486
487 assert_eq!((a + b).get(), 150);
488 assert_eq!((a - b).get(), 50);
489 assert_eq!(a.saturating_sub(TokenCount::new(200)).get(), 0);
490 }
491
492 #[test]
493 fn test_token_count_percentage() {
494 let part = TokenCount::new(25);
495 let total = TokenCount::new(100);
496
497 assert!((part.percentage_of(total) - 25.0).abs() < 0.01);
498 assert_eq!(part.percentage_of(TokenCount::zero()), 0.0);
499 }
500
501 #[test]
502 fn test_token_count_sum() {
503 let counts = vec![TokenCount::new(10), TokenCount::new(20), TokenCount::new(30)];
504 let sum: TokenCount = counts.into_iter().sum();
505 assert_eq!(sum.get(), 60);
506 }
507
508 #[test]
509 fn test_token_count_zero() {
510 let zero = TokenCount::zero();
511 assert_eq!(zero.get(), 0);
512 assert!(zero.is_zero());
513 }
514
515 #[test]
516 fn test_token_count_is_zero() {
517 assert!(TokenCount::new(0).is_zero());
518 assert!(!TokenCount::new(1).is_zero());
519 assert!(!TokenCount::new(100).is_zero());
520 }
521
522 #[test]
523 fn test_token_count_saturating_add() {
524 let a = TokenCount::new(u32::MAX - 10);
525 let b = TokenCount::new(20);
526 let result = a.saturating_add(b);
527 assert_eq!(result.get(), u32::MAX);
528 }
529
530 #[test]
531 fn test_token_count_add_assign() {
532 let mut count = TokenCount::new(100);
533 count += TokenCount::new(50);
534 assert_eq!(count.get(), 150);
535 }
536
537 #[test]
538 fn test_token_count_sub_assign() {
539 let mut count = TokenCount::new(100);
540 count -= TokenCount::new(30);
541 assert_eq!(count.get(), 70);
542 }
543
544 #[test]
545 fn test_token_count_from_u32() {
546 let count: TokenCount = 42u32.into();
547 assert_eq!(count.get(), 42);
548 }
549
550 #[test]
551 fn test_token_count_into_u32() {
552 let count = TokenCount::new(42);
553 let value: u32 = count.into();
554 assert_eq!(value, 42);
555 }
556
557 #[test]
558 fn test_token_count_default() {
559 let count = TokenCount::default();
560 assert_eq!(count.get(), 0);
561 assert!(count.is_zero());
562 }
563
564 #[test]
565 fn test_token_count_clone_copy() {
566 let a = TokenCount::new(100);
567 let b = a; let c = a.clone(); assert_eq!(a.get(), b.get());
570 assert_eq!(a.get(), c.get());
571 }
572
573 #[test]
574 fn test_token_count_ord() {
575 let a = TokenCount::new(100);
576 let b = TokenCount::new(200);
577 assert!(a < b);
578 assert!(b > a);
579 assert_eq!(a.cmp(&a), std::cmp::Ordering::Equal);
580 }
581
582 #[test]
583 fn test_token_count_hash() {
584 let mut set = HashSet::new();
585 set.insert(TokenCount::new(100));
586 set.insert(TokenCount::new(200));
587 set.insert(TokenCount::new(100)); assert_eq!(set.len(), 2);
589 }
590
591 #[test]
592 fn test_token_count_debug() {
593 let count = TokenCount::new(42);
594 let debug_str = format!("{:?}", count);
595 assert!(debug_str.contains("42"));
596 }
597
598 #[test]
599 fn test_token_count_sum_empty() {
600 let counts: Vec<TokenCount> = vec![];
601 let sum: TokenCount = counts.into_iter().sum();
602 assert_eq!(sum.get(), 0);
603 }
604
605 #[test]
610 fn test_line_number_indexing() {
611 let line = LineNumber::new(10);
612
613 assert_eq!(line.to_zero_indexed(), 9);
614 assert_eq!(LineNumber::from_zero_indexed(9).get(), 10);
615 }
616
617 #[test]
618 fn test_line_number_range() {
619 let start = LineNumber::new(5);
620 let end = LineNumber::new(10);
621
622 assert_eq!(start.lines_to(end), 6);
623 assert_eq!(end.lines_to(start), 1); }
625
626 #[test]
627 fn test_line_number_first() {
628 let first = LineNumber::first();
629 assert_eq!(first.get(), 1);
630 }
631
632 #[test]
633 fn test_line_number_is_valid() {
634 assert!(!LineNumber::new(0).is_valid());
635 assert!(LineNumber::new(1).is_valid());
636 assert!(LineNumber::new(100).is_valid());
637 }
638
639 #[test]
640 fn test_line_number_to_zero_indexed_edge() {
641 assert_eq!(LineNumber::new(0).to_zero_indexed(), 0); assert_eq!(LineNumber::new(1).to_zero_indexed(), 0);
643 }
644
645 #[test]
646 fn test_line_number_from_zero_indexed() {
647 assert_eq!(LineNumber::from_zero_indexed(0).get(), 1);
648 assert_eq!(LineNumber::from_zero_indexed(99).get(), 100);
649 }
650
651 #[test]
652 fn test_line_number_from_u32() {
653 let line: LineNumber = 42u32.into();
654 assert_eq!(line.get(), 42);
655 }
656
657 #[test]
658 fn test_line_number_into_u32() {
659 let line = LineNumber::new(42);
660 let value: u32 = line.into();
661 assert_eq!(value, 42);
662 }
663
664 #[test]
665 fn test_line_number_default() {
666 let line = LineNumber::default();
667 assert_eq!(line.get(), 0);
668 }
669
670 #[test]
671 fn test_line_number_clone_copy() {
672 let a = LineNumber::new(10);
673 let b = a;
674 let c = a.clone();
675 assert_eq!(a.get(), b.get());
676 assert_eq!(a.get(), c.get());
677 }
678
679 #[test]
680 fn test_line_number_ord() {
681 let a = LineNumber::new(10);
682 let b = LineNumber::new(20);
683 assert!(a < b);
684 assert!(b > a);
685 }
686
687 #[test]
688 fn test_line_number_hash() {
689 let mut set = HashSet::new();
690 set.insert(LineNumber::new(10));
691 set.insert(LineNumber::new(20));
692 set.insert(LineNumber::new(10)); assert_eq!(set.len(), 2);
694 }
695
696 #[test]
697 fn test_line_number_debug() {
698 let line = LineNumber::new(42);
699 let debug_str = format!("{:?}", line);
700 assert!(debug_str.contains("42"));
701 }
702
703 #[test]
704 fn test_line_number_lines_to_same() {
705 let line = LineNumber::new(5);
706 assert_eq!(line.lines_to(line), 1);
707 }
708
709 #[test]
714 fn test_byte_offset() {
715 let offset = ByteOffset::new(1024);
716 assert_eq!(offset.get(), 1024);
717 assert_eq!(ByteOffset::zero().get(), 0);
718 }
719
720 #[test]
721 fn test_byte_offset_from_usize() {
722 let offset: ByteOffset = 1024usize.into();
723 assert_eq!(offset.get(), 1024);
724 }
725
726 #[test]
727 fn test_byte_offset_into_usize() {
728 let offset = ByteOffset::new(1024);
729 let value: usize = offset.into();
730 assert_eq!(value, 1024);
731 }
732
733 #[test]
734 fn test_byte_offset_default() {
735 let offset = ByteOffset::default();
736 assert_eq!(offset.get(), 0);
737 }
738
739 #[test]
740 fn test_byte_offset_clone_copy() {
741 let a = ByteOffset::new(1024);
742 let b = a;
743 let c = a.clone();
744 assert_eq!(a.get(), b.get());
745 assert_eq!(a.get(), c.get());
746 }
747
748 #[test]
749 fn test_byte_offset_ord() {
750 let a = ByteOffset::new(100);
751 let b = ByteOffset::new(200);
752 assert!(a < b);
753 assert!(b > a);
754 }
755
756 #[test]
757 fn test_byte_offset_hash() {
758 let mut set = HashSet::new();
759 set.insert(ByteOffset::new(100));
760 set.insert(ByteOffset::new(200));
761 set.insert(ByteOffset::new(100)); assert_eq!(set.len(), 2);
763 }
764
765 #[test]
766 fn test_byte_offset_debug() {
767 let offset = ByteOffset::new(1024);
768 let debug_str = format!("{:?}", offset);
769 assert!(debug_str.contains("1024"));
770 }
771
772 #[test]
773 fn test_byte_offset_display() {
774 let offset = ByteOffset::new(1024);
775 assert_eq!(offset.to_string(), "@1024");
776 }
777
778 #[test]
783 fn test_symbol_id_validity() {
784 assert!(!SymbolId::unknown().is_valid());
785 assert!(SymbolId::new(1).is_valid());
786 assert!(!SymbolId::new(0).is_valid());
787 }
788
789 #[test]
790 fn test_symbol_id_unknown() {
791 let unknown = SymbolId::unknown();
792 assert_eq!(unknown.get(), 0);
793 assert!(!unknown.is_valid());
794 }
795
796 #[test]
797 fn test_symbol_id_from_u32() {
798 let id: SymbolId = 42u32.into();
799 assert_eq!(id.get(), 42);
800 }
801
802 #[test]
803 fn test_symbol_id_into_u32() {
804 let id = SymbolId::new(42);
805 let value: u32 = id.into();
806 assert_eq!(value, 42);
807 }
808
809 #[test]
810 fn test_symbol_id_default() {
811 let id = SymbolId::default();
812 assert_eq!(id.get(), 0);
813 assert!(!id.is_valid());
814 }
815
816 #[test]
817 fn test_symbol_id_clone_copy() {
818 let a = SymbolId::new(42);
819 let b = a;
820 let c = a.clone();
821 assert_eq!(a.get(), b.get());
822 assert_eq!(a.get(), c.get());
823 }
824
825 #[test]
826 fn test_symbol_id_ord() {
827 let a = SymbolId::new(10);
828 let b = SymbolId::new(20);
829 assert!(a < b);
830 assert!(b > a);
831 }
832
833 #[test]
834 fn test_symbol_id_hash() {
835 let mut set = HashSet::new();
836 set.insert(SymbolId::new(10));
837 set.insert(SymbolId::new(20));
838 set.insert(SymbolId::new(10)); assert_eq!(set.len(), 2);
840 }
841
842 #[test]
843 fn test_symbol_id_debug() {
844 let id = SymbolId::new(42);
845 let debug_str = format!("{:?}", id);
846 assert!(debug_str.contains("42"));
847 }
848
849 #[test]
850 fn test_symbol_id_display() {
851 let id = SymbolId::new(42);
852 assert_eq!(id.to_string(), "#42");
853 }
854
855 #[test]
860 fn test_file_size_conversions() {
861 let size = FileSize::new(1024 * 1024 + 512 * 1024); assert_eq!(size.kilobytes(), 1536);
864 assert_eq!(size.megabytes(), 1);
865 }
866
867 #[test]
868 fn test_file_size_display() {
869 assert_eq!(FileSize::new(500).to_string(), "500 bytes");
870 assert_eq!(FileSize::new(2048).to_string(), "2.0 KB");
871 assert_eq!(FileSize::new(1024 * 1024).to_string(), "1.0 MB");
872 }
873
874 #[test]
875 fn test_file_size_zero() {
876 let zero = FileSize::zero();
877 assert_eq!(zero.bytes(), 0);
878 }
879
880 #[test]
881 fn test_file_size_bytes() {
882 let size = FileSize::new(12345);
883 assert_eq!(size.bytes(), 12345);
884 }
885
886 #[test]
887 fn test_file_size_exceeds() {
888 let size = FileSize::new(1000);
889 let limit = FileSize::new(500);
890 assert!(size.exceeds(limit));
891 assert!(!limit.exceeds(size));
892 assert!(!size.exceeds(size)); }
894
895 #[test]
896 fn test_file_size_from_u64() {
897 let size: FileSize = 1024u64.into();
898 assert_eq!(size.bytes(), 1024);
899 }
900
901 #[test]
902 fn test_file_size_into_u64() {
903 let size = FileSize::new(1024);
904 let value: u64 = size.into();
905 assert_eq!(value, 1024);
906 }
907
908 #[test]
909 fn test_file_size_default() {
910 let size = FileSize::default();
911 assert_eq!(size.bytes(), 0);
912 }
913
914 #[test]
915 fn test_file_size_clone_copy() {
916 let a = FileSize::new(1024);
917 let b = a;
918 let c = a.clone();
919 assert_eq!(a.bytes(), b.bytes());
920 assert_eq!(a.bytes(), c.bytes());
921 }
922
923 #[test]
924 fn test_file_size_ord() {
925 let a = FileSize::new(100);
926 let b = FileSize::new(200);
927 assert!(a < b);
928 assert!(b > a);
929 }
930
931 #[test]
932 fn test_file_size_hash() {
933 let mut set = HashSet::new();
934 set.insert(FileSize::new(100));
935 set.insert(FileSize::new(200));
936 set.insert(FileSize::new(100)); assert_eq!(set.len(), 2);
938 }
939
940 #[test]
941 fn test_file_size_debug() {
942 let size = FileSize::new(1024);
943 let debug_str = format!("{:?}", size);
944 assert!(debug_str.contains("1024"));
945 }
946
947 #[test]
948 fn test_file_size_display_edge_cases() {
949 assert_eq!(FileSize::new(1023).to_string(), "1023 bytes");
951 assert_eq!(FileSize::new(1024).to_string(), "1.0 KB");
953 let just_under_mb = 1024 * 1024 - 1;
955 assert!(FileSize::new(just_under_mb).to_string().contains("KB"));
956 }
957
958 #[test]
963 fn test_importance_score_clamping() {
964 assert_eq!(ImportanceScore::new(-0.5).get(), 0.0);
965 assert_eq!(ImportanceScore::new(1.5).get(), 1.0);
966 assert_eq!(ImportanceScore::new(0.5).get(), 0.5);
967 }
968
969 #[test]
970 fn test_importance_score_classification() {
971 assert!(ImportanceScore::new(0.8).is_high());
972 assert!(!ImportanceScore::new(0.5).is_high());
973 assert!(ImportanceScore::new(0.2).is_low());
974 assert!(!ImportanceScore::new(0.5).is_low());
975 }
976
977 #[test]
978 fn test_importance_score_zero() {
979 let zero = ImportanceScore::zero();
980 assert_eq!(zero.get(), 0.0);
981 assert!(zero.is_low());
982 }
983
984 #[test]
985 fn test_importance_score_max() {
986 let max = ImportanceScore::max();
987 assert_eq!(max.get(), 1.0);
988 assert!(max.is_high());
989 }
990
991 #[test]
992 fn test_importance_score_default_score() {
993 let default = ImportanceScore::default_score();
994 assert_eq!(default.get(), 0.5);
995 assert!(!default.is_high());
996 assert!(!default.is_low());
997 }
998
999 #[test]
1000 fn test_importance_score_from_f32() {
1001 let score: ImportanceScore = 0.75f32.into();
1002 assert_eq!(score.get(), 0.75);
1003 }
1004
1005 #[test]
1006 fn test_importance_score_from_f32_clamped() {
1007 let score: ImportanceScore = 2.0f32.into();
1008 assert_eq!(score.get(), 1.0);
1009 }
1010
1011 #[test]
1012 fn test_importance_score_into_f32() {
1013 let score = ImportanceScore::new(0.75);
1014 let value: f32 = score.into();
1015 assert_eq!(value, 0.75);
1016 }
1017
1018 #[test]
1019 fn test_importance_score_default() {
1020 let score = ImportanceScore::default();
1021 assert_eq!(score.get(), 0.0);
1022 }
1023
1024 #[test]
1025 fn test_importance_score_clone_copy() {
1026 let a = ImportanceScore::new(0.5);
1027 let b = a;
1028 let c = a.clone();
1029 assert_eq!(a.get(), b.get());
1030 assert_eq!(a.get(), c.get());
1031 }
1032
1033 #[test]
1034 fn test_importance_score_ord() {
1035 let a = ImportanceScore::new(0.3);
1036 let b = ImportanceScore::new(0.7);
1037 assert!(a < b);
1038 assert!(b > a);
1039 assert_eq!(a.cmp(&a), std::cmp::Ordering::Equal);
1040 }
1041
1042 #[test]
1043 fn test_importance_score_partial_ord() {
1044 let a = ImportanceScore::new(0.3);
1045 let b = ImportanceScore::new(0.7);
1046 assert!(a.partial_cmp(&b) == Some(std::cmp::Ordering::Less));
1047 assert!(b.partial_cmp(&a) == Some(std::cmp::Ordering::Greater));
1048 }
1049
1050 #[test]
1051 fn test_importance_score_eq() {
1052 let a = ImportanceScore::new(0.5);
1053 let b = ImportanceScore::new(0.5);
1054 let c = ImportanceScore::new(0.6);
1055 assert_eq!(a, b);
1056 assert_ne!(a, c);
1057 }
1058
1059 #[test]
1060 fn test_importance_score_hash() {
1061 let mut set = HashSet::new();
1062 set.insert(ImportanceScore::new(0.3));
1063 set.insert(ImportanceScore::new(0.7));
1064 set.insert(ImportanceScore::new(0.3)); assert_eq!(set.len(), 2);
1066 }
1067
1068 #[test]
1069 fn test_importance_score_debug() {
1070 let score = ImportanceScore::new(0.5);
1071 let debug_str = format!("{:?}", score);
1072 assert!(debug_str.contains("0.5"));
1073 }
1074
1075 #[test]
1076 fn test_importance_score_display() {
1077 let score = ImportanceScore::new(0.5);
1078 assert_eq!(score.to_string(), "0.50");
1079 }
1080
1081 #[test]
1082 fn test_importance_score_boundary_high() {
1083 assert!(!ImportanceScore::new(0.7).is_high()); assert!(ImportanceScore::new(0.71).is_high());
1086 }
1087
1088 #[test]
1089 fn test_importance_score_boundary_low() {
1090 assert!(!ImportanceScore::new(0.3).is_low()); assert!(ImportanceScore::new(0.29).is_low());
1093 }
1094
1095 #[test]
1100 fn test_display_formatting() {
1101 assert_eq!(TokenCount::new(100).to_string(), "100 tokens");
1102 assert_eq!(LineNumber::new(42).to_string(), "L42");
1103 assert_eq!(ByteOffset::new(1000).to_string(), "@1000");
1104 assert_eq!(SymbolId::new(5).to_string(), "#5");
1105 }
1106
1107 #[test]
1108 fn test_importance_score_display_precision() {
1109 assert_eq!(ImportanceScore::new(0.123).to_string(), "0.12");
1110 assert_eq!(ImportanceScore::new(0.999).to_string(), "1.00"); assert_eq!(ImportanceScore::zero().to_string(), "0.00");
1112 }
1113
1114 #[test]
1119 fn test_token_count_serde() {
1120 let count = TokenCount::new(100);
1121 let json = serde_json::to_string(&count).unwrap();
1122 let parsed: TokenCount = serde_json::from_str(&json).unwrap();
1123 assert_eq!(count, parsed);
1124 }
1125
1126 #[test]
1127 fn test_line_number_serde() {
1128 let line = LineNumber::new(42);
1129 let json = serde_json::to_string(&line).unwrap();
1130 let parsed: LineNumber = serde_json::from_str(&json).unwrap();
1131 assert_eq!(line, parsed);
1132 }
1133
1134 #[test]
1135 fn test_byte_offset_serde() {
1136 let offset = ByteOffset::new(1024);
1137 let json = serde_json::to_string(&offset).unwrap();
1138 let parsed: ByteOffset = serde_json::from_str(&json).unwrap();
1139 assert_eq!(offset, parsed);
1140 }
1141
1142 #[test]
1143 fn test_symbol_id_serde() {
1144 let id = SymbolId::new(42);
1145 let json = serde_json::to_string(&id).unwrap();
1146 let parsed: SymbolId = serde_json::from_str(&json).unwrap();
1147 assert_eq!(id, parsed);
1148 }
1149
1150 #[test]
1151 fn test_file_size_serde() {
1152 let size = FileSize::new(1024);
1153 let json = serde_json::to_string(&size).unwrap();
1154 let parsed: FileSize = serde_json::from_str(&json).unwrap();
1155 assert_eq!(size, parsed);
1156 }
1157
1158 #[test]
1159 fn test_importance_score_serde() {
1160 let score = ImportanceScore::new(0.75);
1161 let json = serde_json::to_string(&score).unwrap();
1162 let parsed: ImportanceScore = serde_json::from_str(&json).unwrap();
1163 assert_eq!(score, parsed);
1164 }
1165}