rigela_utils/
fs.rs

1/*
2 * Copyright (c) 2024. The RigelA open source project team and
3 * its contributors reserve all rights.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and limitations under the License.
12 */
13
14use std::{
15    fs::create_dir,
16    io::Error,
17    path::{Path, PathBuf},
18};
19use tokio::{
20    fs::{metadata, OpenOptions},
21    io::{AsyncReadExt, AsyncWriteExt},
22};
23use win_wrap::shell::{get_known_folder_path, FOLDERID_Profile, KF_FLAG_DEFAULT};
24
25pub const DIR_NAME: &str = ".rigela";
26
27/// 获取程序存储目录
28pub fn get_rigela_program_directory() -> PathBuf {
29    let home_path = get_known_folder_path(&FOLDERID_Profile, KF_FLAG_DEFAULT, None).unwrap();
30    let program_dir = Path::new(&home_path).join(DIR_NAME);
31
32    if !program_dir.exists() {
33        create_dir(&program_dir).expect("Can't create the root directory.");
34    }
35
36    program_dir
37}
38
39/**
40 获取文件已修改的时长(单位是秒),如果文件不存在或遇到其他错误则返回u64::MAX。
41 `path` 文件路径。
42 */
43pub async fn get_file_modified_duration(path: &PathBuf) -> u64 {
44    let Ok(attr) = metadata(&path).await else {
45        return u64::MAX;
46    };
47    let Ok(modified) = attr.modified() else {
48        return u64::MAX;
49    };
50    match modified.elapsed() {
51        Ok(d) => d.as_secs(),
52        Err(_) => u64::MAX,
53    }
54}
55
56/**
57 把数据完整写入到文件,这会冲洗现有文件,覆盖写入。
58 `path` 文件路径。
59 `data` 需要写入的数据。
60 */
61pub async fn write_file(path: &PathBuf, data: &[u8]) -> Result<(), Error> {
62    OpenOptions::new()
63        .create(true)
64        .write(true)
65        .truncate(true)
66        .open(&path)
67        .await?
68        .write_all(data)
69        .await
70}
71
72/**
73 异步读取文件
74 `path` 文件路径。
75 */
76pub async fn read_file(path: &PathBuf) -> Result<String, Error> {
77    let mut result = String::new();
78    OpenOptions::new()
79        .read(true)
80        .open(&path)
81        .await?
82        .read_to_string(&mut result)
83        .await?;
84    Ok(result)
85}