summaryrefslogtreecommitdiff
path: root/legacy_data/src/data/local/cached_sheet.rs
blob: e67861b35858aeb0c75bb3956eb4e33e92b9bd04 (plain)
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
use std::{
    io::{Error, ErrorKind},
    path::PathBuf,
};

use cfg_file::config::ConfigFile;
use just_fmt::{fmt_path::fmt_path, snake_case};
use tokio::fs;

use crate::{
    constants::{
        CLIENT_FILE_CACHED_SHEET, CLIENT_PATH_CACHED_SHEET, CLIENT_SUFFIX_CACHED_SHEET_FILE,
        KEY_SHEET_NAME,
    },
    data::sheet::{SheetData, SheetName},
    env::current_local_path,
};

pub type CachedSheetPathBuf = PathBuf;

/// # Cached Sheet
/// The cached sheet is a read-only version cloned from the upstream repository to the local environment,
/// automatically generated during update operations,
/// which records the latest Sheet information stored locally to accelerate data access and reduce network requests.
pub struct CachedSheet;

impl CachedSheet {
    /// Read the cached sheet data.
    pub async fn cached_sheet_data(sheet_name: &SheetName) -> Result<SheetData, std::io::Error> {
        let sheet_name = snake_case!(sheet_name.clone());

        let Some(path) = Self::cached_sheet_path(sheet_name) else {
            return Err(Error::new(
                std::io::ErrorKind::NotFound,
                "Local workspace not found!",
            ));
        };
        let data = SheetData::read_from(path).await?;
        Ok(data)
    }

    /// Get the path to the cached sheet file.
    pub fn cached_sheet_path(sheet_name: SheetName) -> Option<PathBuf> {
        let current_workspace = current_local_path()?;
        Some(
            current_workspace
                .join(CLIENT_FILE_CACHED_SHEET.replace(KEY_SHEET_NAME, &sheet_name.to_string())),
        )
    }

    /// Get all cached sheet names
    pub async fn cached_sheet_names() -> Result<Vec<SheetName>, std::io::Error> {
        let mut dir = fs::read_dir(CLIENT_PATH_CACHED_SHEET).await?;
        let mut sheet_names = Vec::new();

        while let Some(entry) = dir.next_entry().await? {
            let path = entry.path();

            if path.is_file()
                && let Some(file_name) = path.file_name().and_then(|n| n.to_str())
                && file_name.ends_with(CLIENT_SUFFIX_CACHED_SHEET_FILE)
            {
                let name_without_ext = file_name
                    .trim_end_matches(CLIENT_SUFFIX_CACHED_SHEET_FILE)
                    .to_string();
                sheet_names.push(name_without_ext);
            }
        }

        Ok(sheet_names)
    }

    /// Get all cached sheet paths
    pub async fn cached_sheet_paths() -> Result<Vec<CachedSheetPathBuf>, std::io::Error> {
        let mut dir = fs::read_dir(CLIENT_PATH_CACHED_SHEET).await?;
        let mut sheet_paths = Vec::new();
        let Some(workspace_path) = current_local_path() else {
            return Err(Error::new(
                std::io::ErrorKind::NotFound,
                "Local workspace not found!",
            ));
        };

        while let Some(entry) = dir.next_entry().await? {
            let path = entry.path();

            if path.is_file()
                && let Some(file_name) = path.file_name().and_then(|n| n.to_str())
                && file_name.ends_with(CLIENT_SUFFIX_CACHED_SHEET_FILE)
            {
                sheet_paths
                    .push(fmt_path(workspace_path.join(path)).map_err(|e| {
                        std::io::Error::new(ErrorKind::InvalidInput, e.to_string())
                    })?);
            }
        }

        Ok(sheet_paths)
    }
}