#![allow(unsafe_op_in_unsafe_fn)]
use core::ptr;
use libc::{CLOCK_MONOTONIC, clock_gettime, timespec};
use std::arch::asm;
const DIGITS2: &[u8; 200] = b"\
00\
01\
02\
03\
04\
05\
06\
07\
08\
09\
10\
11\
12\
13\
14\
15\
16\
17\
18\
19\
20\
21\
22\
23\
24\
25\
26\
27\
28\
29\
30\
31\
32\
33\
34\
35\
36\
37\
38\
39\
40\
41\
42\
43\
44\
45\
46\
47\
48\
49\
50\
51\
52\
53\
54\
55\
56\
57\
58\
59\
60\
61\
62\
63\
64\
65\
66\
67\
68\
69\
70\
71\
72\
73\
74\
75\
76\
77\
78\
79\
80\
81\
82\
83\
84\
85\
86\
87\
88\
89\
90\
91\
92\
93\
94\
95\
96\
97\
98\
99";
const WEEKDAYS: [[u8; 3]; 7] = [
*b"Sun", *b"Mon", *b"Tue", *b"Wed", *b"Thu", *b"Fri", *b"Sat",
];
const MONTHS: [[u8; 3]; 12] = [
*b"Jan", *b"Feb", *b"Mar", *b"Apr", *b"May", *b"Jun", *b"Jul", *b"Aug", *b"Sep", *b"Oct",
*b"Nov", *b"Dec",
];
#[inline(always)]
fn _nano_clock_rs(mut z: i64) -> (i32, u8, u8, u8, u8, u8, u8) {
const SECS_PER_DAY: i64 = 86_400;
let secs_of_day: u32 = (z % SECS_PER_DAY) as u32;
z /= SECS_PER_DAY;
let wday: u8 = ((z + 4) % 7) as u8;
z += 719_468;
let era: i64 = (z >= 0).then(|| z).unwrap_or(z - 146_096) / 146_097;
let doe: i64 = z - era * 146_097;
let yoe: i64 = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
let mut y: i64 = yoe + era * 400;
let doy: i64 = doe - (365 * yoe + yoe / 4 - yoe / 100);
let mp: i64 = (5 * doy + 2) / 153;
let d: u8 = (doy - (153 * mp + 2) / 5 + 1) as u8;
let m: i64 = (mp + 2) % 12 + 1;
y += mp / 10;
let (h, mnt, s): (u8, u8, u8) = (
(secs_of_day / 3600) as u8,
((secs_of_day / 60) % 60) as u8,
(secs_of_day % 60) as u8,
);
(y as i32, m as u8, d, h, mnt, s, wday)
}
#[repr(C)]
struct YMDHMSW {
y: i32,
m: u8,
d: u8,
h: u8,
n: u8,
s: u8,
w: u8,
}
#[inline(always)]
unsafe fn _nano_clock_asm(z: i64) -> (i32, u8, u8, u8, u8, u8, u8) {
let mut out = YMDHMSW {
y: 0,
m: 0,
d: 0,
h: 0,
n: 0,
s: 0,
w: 0,
};
let out_ptr: *mut YMDHMSW = &mut out as *mut _;
asm!(
"movabs rcx, 1749024623285053783", "mov rax, rsi",
"imul rcx",
"mov r9, rdx",
"mov r10, rdx",
"shr r10, 63",
"sar r9, 13",
"lea rax, [r9 + r10]",
"add rax, 719468", "movabs rcx, -62162121600", "cmp rsi, rcx",
"lea r8, [r9 + r10 + 573372]",
"cmovg r8, rax",
"lea rcx, [r9 + r10 + 4]", "movabs rdx, 5270498306774157605", "mov rax, rcx",
"imul rdx",
"mov rax, rdx",
"shr rax, 63",
"shr edx, 1",
"add edx, eax",
"lea eax, [rdx*8]", "sub edx, eax",
"add ecx, edx",
"mov cl, cl",
"add r9, r10",
"imul rax, r9, 86400",
"sub rsi, rax",
"movabs rdx, 4137408090565272301", "mov rax, r8",
"imul rdx",
"mov r8, rdx",
"mov rax, rdx",
"shr rax, 63",
"sar r8, 15",
"add r8, rax",
"imul rax, r8, -146097", "add r9, rax",
"add r9, 719468", "movabs r13, -3234497591006606311", "mov rax, r9",
"imul r13",
"mov r10, rdx",
"shr r10, 63",
"sar rdx, 8",
"add r10, rdx",
"movabs rdx, -1896998432287073591", "mov rax, r9",
"imul rdx",
"add r10, r9",
"lea r11, [rdx + r9]",
"mov rax, r11",
"shr rax, 63",
"sar r11, 15",
"add r11, rax",
"add r11, r10",
"movabs rdx, 1896998432287073591", "mov rax, r9",
"imul rdx",
"sub rdx, r9",
"mov r10, rdx",
"shr r10, 63",
"sar rdx, 17",
"add r10, rdx",
"add r10, r11",
"movabs rdx, 3234497591006606311",
"mov rax, r10",
"imul rdx",
"mov rax, rdx",
"shr rax, 63",
"sar rdx, 6",
"add rdx, rax",
"imul r11d, r8d, 400",
"add r11d, edx",
"imul r14, rdx, -365",
"mov rax, r10",
"imul r13",
"mov r8, rdx",
"mov rax, rdx",
"shr rax, 63",
"sar r8, 8",
"add r8, rax",
"movabs rdx, 2070078458244228039", "mov rax, r10",
"imul rdx",
"mov rax, rdx",
"shr rax, 63",
"sar rdx, 12",
"add rdx, rax",
"add r8, r9",
"add r8, rdx",
"add r8, r14",
"lea r10, [r8 + 4*r8 + 2]", "movabs rdx, 3858142551364089227",
"mov rax, r10",
"imul rdx",
"mov r9, rdx",
"lea r13, [r8 + 4*r8]",
"mov r14, rdx",
"shr r14, 63",
"sar r9, 5",
"lea rax, [r9 + r14]",
"imul rax, rax, 153", "add rax, 2",
"movabs rdx, -7378697629483820647",
"imul rdx", "mov rax, rdx",
"shr rax, 63",
"shr edx, 1",
"add edx, eax",
"add r8d, edx",
"inc r8b",
"add r9, r14",
"add r9, 2",
"movabs rdx, 3074457345618258603",
"mov rax, r9",
"imul rdx",
"mov rax, rdx",
"shr rax, 63",
"shr edx, 1",
"add edx, eax",
"shl edx, 2",
"lea eax, [rdx + 2*rdx]",
"sub r9d, eax", "movabs rdx, -6100687909344466089",
"mov rax, r10",
"imul rdx",
"lea rax, [rdx + r13]",
"add rax, 2",
"mov rdx, rax",
"shr rdx, 63",
"shr rax, 10",
"add eax, edx",
"add eax, r11d", "mov edx, esi", "mov r10d, 2443359173", "imul r10, rdx",
"shr r10, 43",
"mov r11d, 2290649225",
"imul r11, rdx",
"shr r11, 37",
"imul rdx, r11, 143165577",
"shr rdx, 33",
"imul edx, edx, 60",
"imul r13d, r11d, 60",
"sub r11d, edx",
"sub esi, r13d", "inc r9b", "mov dword ptr [rdi], eax", "mov byte ptr [rdi + 4], r9b", "mov byte ptr [rdi + 5], r8b", "mov byte ptr [rdi + 6], r10b", "mov byte ptr [rdi + 7], r11b", "mov byte ptr [rdi + 8], sil", "mov byte ptr [rdi + 9], cl", inlateout("rsi") z => _,
in("rdi") out_ptr,
out("rax") _, out("rcx") _, out("rdx") _,
out("r8") _, out("r9") _, out("r10") _, out("r11") _,
out("r12") _, out("r13") _, out("r14") _, out("r15") _,
options(nostack, preserves_flags)
);
(out.y, out.m, out.d, out.h, out.n, out.s, out.w)
}
#[inline(always)]
unsafe fn put2(dst: *mut u8, val: u8) {
ptr::copy_nonoverlapping(DIGITS2.as_ptr().add(val as usize * 2), dst, 2);
}
#[inline(always)]
pub fn nano_clock() -> (i32, u8, u8, u8, u8, u8, u8) {
let t: i64 = unsafe { timestamp() };
_nano_clock_rs(t)
}
#[inline(always)]
pub fn nano_clock_asm() -> (i32, u8, u8, u8, u8, u8, u8) {
let t: i64 = unsafe { timestamp() };
unsafe { _nano_clock_asm(t) }
}
#[inline(always)]
pub unsafe fn nano_http_date(buf: &mut [u8; 35], use_asm: bool) {
let (year, mon, mday, hh, mm, ss, wday): (i32, u8, u8, u8, u8, u8, u8) = match use_asm {
true => nano_clock_asm(), false => nano_clock(), };
unsafe {
ptr::copy_nonoverlapping(b"Date: ".as_ptr(), buf.as_mut_ptr(), 6); ptr::copy_nonoverlapping(WEEKDAYS[wday as usize].as_ptr(), buf.as_mut_ptr().add(6), 3);
*buf.get_unchecked_mut(9) = b','; *buf.get_unchecked_mut(10) = b' '; put2(buf.as_mut_ptr().add(11), mday);
*buf.get_unchecked_mut(13) = b' '; ptr::copy_nonoverlapping(
MONTHS[(mon - 1) as usize].as_ptr(),
buf.as_mut_ptr().add(14),
3,
);
*buf.get_unchecked_mut(17) = b' '; let y: u32 = year as u32;
put2(buf.as_mut_ptr().add(18), (y / 100) as u8); put2(buf.as_mut_ptr().add(20), (y % 100) as u8); *buf.get_unchecked_mut(22) = b' ';
put2(buf.as_mut_ptr().add(23), hh);
*buf.get_unchecked_mut(25) = b':';
put2(buf.as_mut_ptr().add(26), mm);
*buf.get_unchecked_mut(28) = b':';
put2(buf.as_mut_ptr().add(29), ss);
ptr::copy_nonoverlapping(b" GMT".as_ptr(), buf.as_mut_ptr().add(31), 4);
}
}
#[inline(always)]
pub unsafe fn timestamp() -> i64 {
libc::time(ptr::null_mut()) as i64
}
#[inline(always)]
pub unsafe fn nano_timestamp() -> i64 {
let mut ts: timespec = std::mem::zeroed();
clock_gettime(CLOCK_MONOTONIC, &mut ts);
ts.tv_sec as i64 * 1_000_000_000 + ts.tv_nsec as i64
}