Skip to main content

ruff_db/
file_revision.rs

1#[cfg(test)]
2use crate::system::file_time_now;
3
4/// A number representing the revision of a file.
5///
6/// Two revisions that don't compare equal signify that the file has been modified.
7/// Revisions aren't guaranteed to be monotonically increasing or in any specific order.
8///
9/// Possible revisions are:
10/// * The last modification time of the file.
11/// * The hash of the file's content.
12/// * The revision as it comes from an external system, for example the LSP.
13#[derive(Copy, Clone, Debug, Eq, PartialEq, Default, get_size2::GetSize)]
14pub struct FileRevision(u128);
15
16impl FileRevision {
17    pub fn new(value: u128) -> Self {
18        Self(value)
19    }
20
21    pub(crate) const fn zero() -> Self {
22        Self(0)
23    }
24
25    #[must_use]
26    pub(crate) fn as_u128(self) -> u128 {
27        self.0
28    }
29}
30
31impl From<u128> for FileRevision {
32    fn from(value: u128) -> Self {
33        FileRevision(value)
34    }
35}
36
37impl From<u64> for FileRevision {
38    fn from(value: u64) -> Self {
39        FileRevision(u128::from(value))
40    }
41}
42
43impl From<filetime::FileTime> for FileRevision {
44    fn from(value: filetime::FileTime) -> Self {
45        let seconds = value.seconds() as u128;
46        let seconds = seconds << 64;
47        let nanos = u128::from(value.nanoseconds());
48
49        FileRevision(seconds | nanos)
50    }
51}
52
53#[cfg(test)]
54mod tests {
55
56    use super::*;
57
58    #[test]
59    fn revision_from_file_time() {
60        let file_time = file_time_now();
61        let revision = FileRevision::from(file_time);
62
63        let revision = revision.as_u128();
64
65        let nano = revision & 0xFFFF_FFFF_FFFF_FFFF;
66        let seconds = revision >> 64;
67
68        assert_eq!(file_time.nanoseconds(), nano as u32);
69        assert_eq!(file_time.seconds(), seconds as i64);
70    }
71}