Skip to main content

pidgin_lang/
metrics.rs

1use serde::Serialize;
2
3use crate::ast::PgnPacket;
4
5#[derive(Debug, Serialize)]
6pub struct TokenReport {
7    pub char_count: usize,
8    pub estimated_tokens: usize,
9    pub line_count: usize,
10    pub field_count: usize,
11}
12
13pub fn estimate_tokens(text: &str) -> usize {
14    text.len().div_ceil(4)
15}
16
17pub fn measure_packet(packet: &PgnPacket) -> TokenReport {
18    let mut char_count = 0;
19    let mut line_count = 0;
20    let field_count = packet.fields.len();
21
22    // Header line
23    let header = format!("@{} {}", packet.directive.directive_name(), packet.run_id);
24    char_count += header.len();
25    line_count += 1;
26
27    // Field lines
28    for (name, value) in &packet.fields {
29        let line = match value {
30            crate::ast::FieldValue::Scalar(s) => format!("{}={}", name, s),
31            crate::ast::FieldValue::List(items) => format!("{}={}", name, items.join(",")),
32        };
33        char_count += line.len();
34        line_count += 1;
35    }
36
37    TokenReport {
38        char_count,
39        estimated_tokens: char_count.div_ceil(4),
40        line_count,
41        field_count,
42    }
43}
44
45#[derive(Debug, Serialize)]
46pub struct TokenSavingsReport {
47    pub pgn_tokens: usize,
48    pub verbose_tokens: usize,
49    pub savings_ratio: f32,
50    pub savings_pct_display: String,
51}
52
53pub fn compare_verbose(pgn_text: &str, verbose_text: &str) -> TokenSavingsReport {
54    let pgn_tokens = estimate_tokens(pgn_text);
55    let verbose_tokens = estimate_tokens(verbose_text);
56    let savings_ratio = if verbose_tokens > 0 {
57        1.0 - (pgn_tokens as f32 / verbose_tokens as f32)
58    } else {
59        0.0
60    };
61    let savings_pct = (savings_ratio * 100.0).round() as i32;
62
63    TokenSavingsReport {
64        pgn_tokens,
65        verbose_tokens,
66        savings_ratio,
67        savings_pct_display: format!("{}%", savings_pct),
68    }
69}