Coverage Report

Created: 2025-12-20 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/moxcms-0.7.11/src/dat.rs
Line
Count
Source
1
/*
2
 * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved.
3
 * //
4
 * // Redistribution and use in source and binary forms, with or without modification,
5
 * // are permitted provided that the following conditions are met:
6
 * //
7
 * // 1.  Redistributions of source code must retain the above copyright notice, this
8
 * // list of conditions and the following disclaimer.
9
 * //
10
 * // 2.  Redistributions in binary form must reproduce the above copyright notice,
11
 * // this list of conditions and the following disclaimer in the documentation
12
 * // and/or other materials provided with the distribution.
13
 * //
14
 * // 3.  Neither the name of the copyright holder nor the names of its
15
 * // contributors may be used to endorse or promote products derived from
16
 * // this software without specific prior written permission.
17
 * //
18
 * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
 * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
 * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
 * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
 * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
 * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
 * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29
use crate::CmsError;
30
use crate::writer::write_u16_be;
31
use std::time::{SystemTime, UNIX_EPOCH};
32
33
#[repr(C)]
34
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Default)]
35
pub struct ColorDateTime {
36
    pub year: u16,
37
    pub month: u16,
38
    pub day_of_the_month: u16,
39
    pub hours: u16,
40
    pub minutes: u16,
41
    pub seconds: u16,
42
}
43
44
0
fn is_leap(year: i32) -> bool {
45
0
    (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
46
0
}
47
48
0
fn days_in_month(year: i32, month: i32) -> i32 {
49
0
    match month {
50
0
        1 => 31,
51
        2 => {
52
0
            if is_leap(year) {
53
0
                29
54
            } else {
55
0
                28
56
            }
57
        }
58
0
        3 => 31,
59
0
        4 => 30,
60
0
        5 => 31,
61
0
        6 => 30,
62
0
        7 => 31,
63
0
        8 => 31,
64
0
        9 => 30,
65
0
        10 => 31,
66
0
        11 => 30,
67
0
        12 => 31,
68
0
        _ => unreachable!("Unknown month"),
69
    }
70
0
}
71
72
impl ColorDateTime {
73
    /// Parses slice for date time
74
0
    pub fn new_from_slice(slice: &[u8]) -> Result<ColorDateTime, CmsError> {
75
0
        if slice.len() != 12 {
76
0
            return Err(CmsError::InvalidProfile);
77
0
        }
78
0
        let year = u16::from_be_bytes([slice[0], slice[1]]);
79
0
        let month = u16::from_be_bytes([slice[2], slice[3]]);
80
0
        let day_of_the_month = u16::from_be_bytes([slice[4], slice[5]]);
81
0
        let hours = u16::from_be_bytes([slice[6], slice[7]]);
82
0
        let minutes = u16::from_be_bytes([slice[8], slice[9]]);
83
0
        let seconds = u16::from_be_bytes([slice[10], slice[11]]);
84
0
        Ok(ColorDateTime {
85
0
            year,
86
0
            month,
87
0
            day_of_the_month,
88
0
            hours,
89
0
            minutes,
90
0
            seconds,
91
0
        })
92
0
    }
93
94
    /// Creates a new `ColorDateTime` from the current system time (UTC)
95
0
    pub fn now() -> Self {
96
0
        let now = match SystemTime::now().duration_since(UNIX_EPOCH) {
97
0
            Ok(v) => v,
98
0
            Err(_) => return Self::default(),
99
        };
100
0
        let mut days = (now.as_secs() / 86_400) as i64;
101
0
        let secs_of_day = (now.as_secs() % 86_400) as i64;
102
103
0
        let mut year = 1970;
104
        loop {
105
0
            let year_days = if is_leap(year) { 366 } else { 365 };
106
0
            if days >= year_days {
107
0
                days -= year_days;
108
0
                year += 1;
109
0
            } else {
110
0
                break;
111
            }
112
        }
113
114
0
        let mut month = 1;
115
        loop {
116
0
            let mdays = days_in_month(year, month);
117
0
            if days >= mdays as i64 {
118
0
                days -= mdays as i64;
119
0
                month += 1;
120
0
            } else {
121
0
                break;
122
            }
123
        }
124
0
        let day = days + 1; // days from zero based to 1 base
125
126
0
        let hour = secs_of_day / 3600;
127
0
        let min = (secs_of_day % 3600) / 60;
128
0
        let sec = secs_of_day % 60;
129
0
        Self {
130
0
            year: year as u16,
131
0
            month: month as u16,
132
0
            day_of_the_month: day as u16,
133
0
            hours: hour as u16,
134
0
            minutes: min as u16,
135
0
            seconds: sec as u16,
136
0
        }
137
0
    }
138
139
    #[inline]
140
0
    pub(crate) fn encode(&self, into: &mut Vec<u8>) {
141
0
        let year = self.year;
142
0
        let month = self.month;
143
0
        let day_of_the_month = self.day_of_the_month;
144
0
        let hours = self.hours;
145
0
        let minutes = self.minutes;
146
0
        let seconds = self.seconds;
147
0
        write_u16_be(into, year);
148
0
        write_u16_be(into, month);
149
0
        write_u16_be(into, day_of_the_month);
150
0
        write_u16_be(into, hours);
151
0
        write_u16_be(into, minutes);
152
0
        write_u16_be(into, seconds);
153
0
    }
154
}