spreadsheet_mcp/
utils.rs

1use chrono::{DateTime, SecondsFormat, Utc};
2use sha2::{Digest, Sha256};
3use std::fs::Metadata;
4use std::path::Path;
5use std::time::SystemTime;
6
7pub fn system_time_to_datetime(time: SystemTime) -> Option<DateTime<Utc>> {
8    Some(DateTime::<Utc>::from(time))
9}
10
11pub fn system_time_to_rfc3339(time: SystemTime) -> Option<DateTime<Utc>> {
12    system_time_to_datetime(time)
13}
14
15pub fn hash_path_metadata(path: &Path, metadata: &Metadata) -> String {
16    let mut hasher = Sha256::new();
17    hasher.update(path.to_string_lossy().as_bytes());
18    hasher.update(metadata.len().to_le_bytes());
19    if let Ok(modified) = metadata.modified()
20        && let Some(dt) = system_time_to_datetime(modified)
21    {
22        hasher.update(dt.to_rfc3339_opts(SecondsFormat::Micros, true).as_bytes());
23    }
24    format!("{:x}", hasher.finalize())
25}
26
27pub fn column_number_to_name(column: u32) -> String {
28    let mut column = column;
29    let mut name = String::new();
30    while column > 0 {
31        let rem = ((column - 1) % 26) as u8;
32        name.insert(0, (b'A' + rem) as char);
33        column = (column - 1) / 26;
34    }
35    name
36}
37
38pub fn cell_address(column: u32, row: u32) -> String {
39    format!("{}{}", column_number_to_name(column), row)
40}
41
42pub fn make_short_workbook_id(slug: &str, canonical_id: &str) -> String {
43    let mut slug_part: String = slug
44        .chars()
45        .filter(|c| c.is_ascii_alphanumeric())
46        .map(|c| c.to_ascii_lowercase())
47        .collect();
48    if slug_part.is_empty() {
49        slug_part = "wb".to_string();
50    }
51    if slug_part.len() > 12 {
52        slug_part.truncate(12);
53    }
54    let short_hash: String = canonical_id.chars().take(8).collect();
55    format!("{}-{}", slug_part, short_hash)
56}
57
58pub fn path_to_forward_slashes(path: &Path) -> String {
59    let raw = path.to_string_lossy();
60    if raw.contains('\\') {
61        raw.replace('\\', "/")
62    } else {
63        raw.into_owned()
64    }
65}