faf_http_date/
lib.rs

1#![no_std]
2
3#[repr(C)]
4struct timespec {
5    pub tv_sec: i64,
6    pub tv_nsec: i64,
7}
8
9extern "C" {
10    fn clock_gettime(clk_id: i32, tp: *mut timespec) -> i32;
11}
12
13const CLOCK_REALTIME: i32 = 0;
14
15// Format: b"Date: Thu, 01 Jan 1970 00:00:00 GMT"
16#[inline]
17pub fn get_date_buff_with_key() -> [u8; 35] {
18    [
19        b'D', b'a', b't', b'e', b':', b' ', b' ', b' ', b' ', b',', b' ', b'0', b'0', b' ', b' ',
20        b' ', b' ', b' ', b'0', b'0', b'0', b'0', b' ', b'0', b'0', b':', b'0', b'0', b':', b'0',
21        b'0', b' ', b'G', b'M', b'T',
22    ]
23}
24
25// Format: b"Thu, 01 Jan 1970 00:00:00 GMT"
26#[inline]
27pub fn get_date_buff_no_key() -> [u8; 29] {
28    [
29        b' ', b' ', b' ', b',', b' ', b'0', b'0', b' ', b' ', b' ', b' ', b' ', b'0', b'0', b'0',
30        b'0', b' ', b'0', b'0', b':', b'0', b'0', b':', b'0', b'0', b' ', b'G', b'M', b'T',
31    ]
32}
33
34// Format: b"Date: Thu, 01 Jan 1970 00:00:00 GMT"
35#[inline]
36pub fn get_date_with_key(buf: &mut [u8; 35]) {
37    let mut ts: timespec = unsafe { core::mem::zeroed() };
38    unsafe { clock_gettime(CLOCK_REALTIME, &mut ts as *mut timespec) };
39
40    let secs_since_epoch = ts.tv_sec;
41
42    const LEAPOCH: i64 = 11017;
43    const DAYS_PER_400Y: i64 = 365 * 400 + 97;
44    const DAYS_PER_100Y: i64 = 365 * 100 + 24;
45    const DAYS_PER_4Y: i64 = 365 * 4 + 1;
46
47    let days = (secs_since_epoch / 86400) - LEAPOCH;
48    let secs_of_day = secs_since_epoch % 86400;
49
50    let mut qc_cycles = days / DAYS_PER_400Y;
51    let mut remdays = days % DAYS_PER_400Y;
52
53    if remdays < 0 {
54        remdays += DAYS_PER_400Y;
55        qc_cycles -= 1;
56    }
57
58    let mut c_cycles = remdays / DAYS_PER_100Y;
59    if c_cycles == 4 {
60        c_cycles -= 1;
61    }
62    remdays -= c_cycles * DAYS_PER_100Y;
63
64    let mut q_cycles = remdays / DAYS_PER_4Y;
65    if q_cycles == 25 {
66        q_cycles -= 1;
67    }
68    remdays -= q_cycles * DAYS_PER_4Y;
69
70    let mut remyears = remdays / 365;
71    if remyears == 4 {
72        remyears -= 1;
73    }
74    remdays -= remyears * 365;
75
76    let mut year = 2000 + remyears + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles;
77
78    let months = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29];
79    let mut mon = 0;
80    for mon_len in months.iter() {
81        mon += 1;
82        if remdays < *mon_len {
83            break;
84        }
85        remdays -= *mon_len;
86    }
87    let mday = remdays + 1;
88    let mon = if mon + 2 > 12 {
89        year += 1;
90        mon - 10
91    } else {
92        mon + 2
93    };
94
95    let mut wday = (3 + days) % 7;
96    if wday <= 0 {
97        wday += 7
98    };
99
100    let sec = (secs_of_day % 60) as u8;
101    let min = ((secs_of_day % 3600) / 60) as u8;
102    let hour = (secs_of_day / 3600) as u8;
103    let day = mday as u8;
104    let mon = mon as u8;
105    let year = year as u16;
106    let wday = wday as u8;
107
108    let wday = match wday {
109        1 => b"Mon",
110        2 => b"Tue",
111        3 => b"Wed",
112        4 => b"Thu",
113        5 => b"Fri",
114        6 => b"Sat",
115        7 => b"Sun",
116        _ => unsafe { core::hint::unreachable_unchecked() },
117    };
118    let mon = match mon {
119        1 => b"Jan",
120        2 => b"Feb",
121        3 => b"Mar",
122        4 => b"Apr",
123        5 => b"May",
124        6 => b"Jun",
125        7 => b"Jul",
126        8 => b"Aug",
127        9 => b"Sep",
128        10 => b"Oct",
129        11 => b"Nov",
130        12 => b"Dec",
131        _ => unsafe { core::hint::unreachable_unchecked() },
132    };
133
134    buf[6] = wday[0];
135    buf[7] = wday[1];
136    buf[8] = wday[2];
137    buf[11] = b'0' + (day / 10) as u8;
138    buf[12] = b'0' + (day % 10) as u8;
139    buf[14] = mon[0];
140    buf[15] = mon[1];
141    buf[16] = mon[2];
142    buf[18] = b'0' + (year / 1000) as u8;
143    buf[19] = b'0' + (year / 100 % 10) as u8;
144    buf[20] = b'0' + (year / 10 % 10) as u8;
145    buf[21] = b'0' + (year % 10) as u8;
146    buf[23] = b'0' + (hour / 10) as u8;
147    buf[24] = b'0' + (hour % 10) as u8;
148    buf[26] = b'0' + (min / 10) as u8;
149    buf[27] = b'0' + (min % 10) as u8;
150    buf[29] = b'0' + (sec / 10) as u8;
151    buf[30] = b'0' + (sec % 10) as u8;
152}
153
154// Format: b"Thu, 01 Jan 1970 00:00:00 GMT"
155#[inline]
156pub fn get_date_no_key(buf: &mut [u8; 29]) {
157    let mut ts: timespec = unsafe { core::mem::zeroed() };
158    unsafe { clock_gettime(CLOCK_REALTIME, &mut ts as *mut timespec) };
159
160    let secs_since_epoch = ts.tv_sec;
161
162    const LEAPOCH: i64 = 11017;
163    const DAYS_PER_400Y: i64 = 365 * 400 + 97;
164    const DAYS_PER_100Y: i64 = 365 * 100 + 24;
165    const DAYS_PER_4Y: i64 = 365 * 4 + 1;
166
167    let days = (secs_since_epoch / 86400) - LEAPOCH;
168    let secs_of_day = secs_since_epoch % 86400;
169
170    let mut qc_cycles = days / DAYS_PER_400Y;
171    let mut remdays = days % DAYS_PER_400Y;
172
173    if remdays < 0 {
174        remdays += DAYS_PER_400Y;
175        qc_cycles -= 1;
176    }
177
178    let mut c_cycles = remdays / DAYS_PER_100Y;
179    if c_cycles == 4 {
180        c_cycles -= 1;
181    }
182    remdays -= c_cycles * DAYS_PER_100Y;
183
184    let mut q_cycles = remdays / DAYS_PER_4Y;
185    if q_cycles == 25 {
186        q_cycles -= 1;
187    }
188    remdays -= q_cycles * DAYS_PER_4Y;
189
190    let mut remyears = remdays / 365;
191    if remyears == 4 {
192        remyears -= 1;
193    }
194    remdays -= remyears * 365;
195
196    let mut year = 2000 + remyears + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles;
197
198    let months = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29];
199    let mut mon = 0;
200    for mon_len in months.iter() {
201        mon += 1;
202        if remdays < *mon_len {
203            break;
204        }
205        remdays -= *mon_len;
206    }
207    let mday = remdays + 1;
208    let mon = if mon + 2 > 12 {
209        year += 1;
210        mon - 10
211    } else {
212        mon + 2
213    };
214
215    let mut wday = (3 + days) % 7;
216    if wday <= 0 {
217        wday += 7
218    };
219
220    let sec = (secs_of_day % 60) as u8;
221    let min = ((secs_of_day % 3600) / 60) as u8;
222    let hour = (secs_of_day / 3600) as u8;
223    let day = mday as u8;
224    let mon = mon as u8;
225    let year = year as u16;
226    let wday = wday as u8;
227
228    let wday = match wday {
229        1 => b"Mon",
230        2 => b"Tue",
231        3 => b"Wed",
232        4 => b"Thu",
233        5 => b"Fri",
234        6 => b"Sat",
235        7 => b"Sun",
236        _ => unsafe { core::hint::unreachable_unchecked() },
237    };
238    let mon = match mon {
239        1 => b"Jan",
240        2 => b"Feb",
241        3 => b"Mar",
242        4 => b"Apr",
243        5 => b"May",
244        6 => b"Jun",
245        7 => b"Jul",
246        8 => b"Aug",
247        9 => b"Sep",
248        10 => b"Oct",
249        11 => b"Nov",
250        12 => b"Dec",
251        _ => unsafe { core::hint::unreachable_unchecked() },
252    };
253
254    buf[0] = wday[0];
255    buf[1] = wday[1];
256    buf[2] = wday[2];
257    buf[5] = b'0' + (day / 10) as u8;
258    buf[6] = b'0' + (day % 10) as u8;
259    buf[8] = mon[0];
260    buf[9] = mon[1];
261    buf[10] = mon[2];
262    buf[12] = b'0' + (year / 1000) as u8;
263    buf[13] = b'0' + (year / 100 % 10) as u8;
264    buf[14] = b'0' + (year / 10 % 10) as u8;
265    buf[15] = b'0' + (year % 10) as u8;
266    buf[17] = b'0' + (hour / 10) as u8;
267    buf[18] = b'0' + (hour % 10) as u8;
268    buf[20] = b'0' + (min / 10) as u8;
269    buf[21] = b'0' + (min % 10) as u8;
270    buf[23] = b'0' + (sec / 10) as u8;
271    buf[24] = b'0' + (sec % 10) as u8;
272}
273
274// EXAMPLE USAGE
275// fn main() {
276//     let mut buf = get_date_buff_with_key();
277//     get_date_with_key(&mut buf);
278
279//     // Optional, convert to str
280//     let date_str = unsafe { std::str::from_utf8_unchecked(&buf[..]) };
281//     println!("{}", date_str);
282
283//     let mut buf = get_date_buff_no_key();
284//     get_date_no_key(&mut buf);
285
286//     // Optional, convert to str
287//     let date_str = unsafe { std::str::from_utf8_unchecked(&buf[..]) };
288//     println!("{}", date_str);
289// }