codex_helper_core/
usage_format.rs1use crate::usage::UsageMetrics;
2
3pub fn tokens_short(value: i64) -> String {
4 let value = value.max(0) as f64;
5 if value >= 1_000_000_000.0 {
6 format!("{:.1}b", value / 1_000_000_000.0)
7 } else if value >= 1_000_000.0 {
8 format!("{:.1}m", value / 1_000_000.0)
9 } else if value >= 1_000.0 {
10 format!("{:.1}k", value / 1_000.0)
11 } else {
12 format!("{value:.0}")
13 }
14}
15
16pub fn tokens_per_second(value: Option<f64>) -> String {
17 value
18 .filter(|value| value.is_finite() && *value > 0.0)
19 .map(|value| format!("{value:.1}"))
20 .unwrap_or_else(|| "-".to_string())
21}
22
23pub fn usage_line_with_labels(
24 usage: &UsageMetrics,
25 usage_label: &str,
26 cache_label: &str,
27) -> String {
28 let mut line = format!(
29 "{usage_label}: {}/{}/{}/{}",
30 tokens_short(usage.input_tokens),
31 tokens_short(usage.output_tokens),
32 tokens_short(usage.reasoning_output_tokens_total()),
33 tokens_short(usage.total_tokens)
34 );
35 if usage.has_cache_tokens() {
36 line.push_str(&format!(
37 " {cache_label}: {}/{}",
38 tokens_short(usage.cache_read_tokens_total()),
39 tokens_short(usage.cache_creation_tokens_total())
40 ));
41 }
42 line
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn tokens_short_scales_counts() {
51 assert_eq!(tokens_short(-1), "0");
52 assert_eq!(tokens_short(999), "999");
53 assert_eq!(tokens_short(1_500), "1.5k");
54 assert_eq!(tokens_short(1_500_000), "1.5m");
55 assert_eq!(tokens_short(1_500_000_000), "1.5b");
56 }
57
58 #[test]
59 fn tokens_per_second_formats_positive_finite_values() {
60 assert_eq!(tokens_per_second(None), "-");
61 assert_eq!(tokens_per_second(Some(0.0)), "-");
62 assert_eq!(tokens_per_second(Some(f64::INFINITY)), "-");
63 assert_eq!(tokens_per_second(Some(12.34)), "12.3");
64 }
65
66 #[test]
67 fn usage_line_with_labels_includes_cache_when_present() {
68 let usage = UsageMetrics {
69 input_tokens: 1_000,
70 output_tokens: 20,
71 reasoning_output_tokens: 3,
72 total_tokens: 1_023,
73 cached_input_tokens: 10,
74 cache_creation_input_tokens: 5,
75 ..UsageMetrics::default()
76 };
77
78 assert_eq!(
79 usage_line_with_labels(&usage, "tok in/out/rsn/ttl", "cache read/create"),
80 "tok in/out/rsn/ttl: 1.0k/20/3/1.0k cache read/create: 10/5"
81 );
82 }
83}