os_checker_types/
cache.rs

1use crate::prelude::*;
2use std::hash::Hash;
3
4// 由于我们想对每个检查出了结果时缓存,而不是在仓库所有检查完成时缓存,这里需要重复数据。
5// 减少数据重复,需要新定义一个结构,在缓存和 PackagesOutputs 上。
6#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct CacheRepoKeyCmd {
8    #[musli(with = musli::serde)]
9    pub pkg_name: XString,
10    pub checker: CacheChecker,
11    pub cmd: CacheCmd,
12}
13
14#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
15pub struct CacheRepoKey {
16    pub repo: CacheRepo,
17    pub cmd: CacheRepoKeyCmd,
18}
19
20impl CacheRepoKey {
21    pub fn user_repo(&self) -> [&str; 2] {
22        self.repo.user_repo()
23    }
24}
25
26redb_value!(@key CacheRepoKey, name: "OsCheckerCacheKey",
27    read_err: "Not a valid cache key.",
28    write_err: "Cache key can't be encoded to bytes."
29);
30
31#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
32pub struct CacheRepo {
33    #[musli(with = musli::serde)]
34    pub user: XString,
35    #[musli(with = musli::serde)]
36    pub repo: XString,
37    pub sha: String,
38    #[musli(with = musli::serde)]
39    pub branch: XString,
40}
41
42impl CacheRepo {
43    pub fn user_repo(&self) -> [&str; 2] {
44        [&self.user, &self.repo]
45    }
46}
47
48#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
49pub struct CacheChecker {
50    pub checker: crate::CheckerTool,
51    // If we don't care about the version, use None.
52    pub version: Option<String>,
53    pub sha: Option<String>,
54}
55
56#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)]
57pub struct CacheCmd {
58    pub cmd: String,
59    pub target: String,
60    /// FIXME: channel 转换回 RustToolchain 会丢失额外的信息
61    pub channel: String,
62    #[musli(with = musli::serde)]
63    pub env: IndexMap<String, String>,
64    // Below is not necessary, and currently not implemented.
65    #[musli(with = musli::serde)]
66    pub features: Vec<XString>,
67    /// rustcflags
68    #[musli(with = musli::serde)]
69    pub flags: Vec<XString>,
70}
71
72impl PartialOrd for CacheCmd {
73    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
74        Some(self.cmp(other))
75    }
76}
77impl Ord for CacheCmd {
78    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
79        let Self {
80            cmd,
81            target,
82            channel,
83            env,
84            features,
85            flags,
86        } = self;
87        let a = (cmd, target, channel, env.as_slice(), features, flags);
88        let Self {
89            cmd,
90            target,
91            channel,
92            env,
93            features,
94            flags,
95        } = other;
96        let b = (cmd, target, channel, env.as_slice(), features, flags);
97        a.cmp(&b)
98    }
99}
100impl Hash for CacheCmd {
101    fn hash<H>(&self, state: &mut H)
102    where
103        H: std::hash::Hasher,
104    {
105        let Self {
106            cmd,
107            target,
108            channel,
109            env,
110            features,
111            flags,
112        } = self;
113        let a = (cmd, target, channel, env.as_slice(), features, flags);
114        a.hash(state);
115    }
116}
117
118#[derive(Encode, Decode)]
119pub struct OutputData {
120    pub duration_ms: u64,
121    pub data: Vec<OutputDataInner>,
122}
123
124impl fmt::Debug for OutputData {
125    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126        f.debug_struct("OutputData")
127            .field("duration_ms", &self.duration_ms)
128            .field("data.len", &self.data.len())
129            .finish()
130    }
131}
132
133#[derive(Encode, Decode)]
134pub struct OutputDataInner {
135    #[musli(with = musli::serde)]
136    pub file: Utf8PathBuf,
137    pub kind: crate::Kind,
138    pub raw: String,
139}
140
141#[derive(Encode, Decode)]
142pub struct CacheValue {
143    pub unix_timestamp_milli: u64,
144    pub cmd: CacheRepoKeyCmd,
145    pub diagnostics: OutputData,
146}
147
148impl fmt::Debug for CacheValue {
149    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150        f.debug_struct("CacheValue")
151            .field(
152                "unix_timestamp_milli",
153                &super::parse_unix_timestamp_milli(self.unix_timestamp_milli),
154            )
155            .field("diagnostics.len", &self.diagnostics.data.len())
156            .finish()
157    }
158}
159
160redb_value!(CacheValue, name: "OsCheckerCacheValue",
161    read_err: "Not a valid cache value.",
162    write_err: "Cache value can't be encoded to bytes."
163);