summaryrefslogtreecommitdiff
path: root/src/solar.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/solar.rs')
-rw-r--r--src/solar.rs44
1 files changed, 23 insertions, 21 deletions
diff --git a/src/solar.rs b/src/solar.rs
index 4bff33a..1266a23 100644
--- a/src/solar.rs
+++ b/src/solar.rs
@@ -8,7 +8,7 @@ use num::cast;
use std::{
marker::Freeze,
mem::{transmute, MaybeUninit},
- ops::{Div, Rem},
+ ops::{Div, Index, IndexMut, Rem},
sync::LazyLock,
};
@@ -192,34 +192,40 @@ where
align(6 * g - 5 * z, 60, 0)
}
+// need to do this because
+// 1. unsafecell doesnt implement Sync
+// 2. mutating a slice directly will put it in .rodata for normal targets
+// where i test this on
struct Cell<T: ?Sized> {
val: T,
}
-impl<T: ?Sized> Cell<T> {
- pub fn get(&self) -> &mut T {
- unsafe { transmute(&self.val) }
- }
-}
+// SAFETY(lol): wasm isolates are single-core.
unsafe impl<T: ?Sized + Send> Sync for Cell<T> {}
// technically i dont need this because wasm mutable globals are enabled,
// and Freeze is only needed for targets with a separate .rodata
// i dont really care either way but this is how UnsafeCell does it
+//
// lang = "unsafe_cell" (apparently an extremely integral part of rust)
// does additional stuff but this is sufficient for the compiler to not
-// put it on .rodata for normal targets
+// put it in .rodata for normal targets
impl<T: ?Sized> !Freeze for Cell<T> {}
+impl<T: ?Sized + IndexMut<usize> + Index<usize>> Cell<T> {
+ pub fn get(&self, i: usize) -> &mut T::Output {
+ // SAFETY: see above
+ let a: &mut T = unsafe { transmute(&self.val) };
+ &mut a[i]
+ }
+}
fn stday(i: usize, y: usize) -> f64 {
const YEARS: usize = 200;
const ARRLEN: usize = YEARS * TERMS.len();
- static STDAYS: Cell<[f64; ARRLEN]> = Cell {
- val: [0.; ARRLEN],
- };
// rust doesnt have (*a)[n], | @ least ill have2 use a cr8 4 it
// also lazy_static doesnt work with mutables (im not using mutex)
- assert!((UNIT_YR..UNIT_YR + YEARS).contains(&y));
+ static STDAYS: Cell<[f64; ARRLEN]> = Cell { val: [0.; ARRLEN] };
let idx = y - UNIT_YR;
- let ret = &mut STDAYS.get()[idx * TERMS.len() + i];
+ assert!((0..YEARS).contains(&idx));
+ let ret = STDAYS.get(idx * TERMS.len() + i);
(if int(*ret) != 0 {
*ret
} else {
@@ -239,15 +245,10 @@ pub fn ganzhi(i: usize) -> &'static str {
'子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌',
'亥',
];
- let mut tmp: Vec<String> = Vec::with_capacity(60);
- (0..60).for_each(|i| {
- // looks so much worse than using format!()
- // cant be bothered to benchmark
- let mut s = gan[i % 10].to_string();
- s.push(zhi[i % 12]);
- tmp.push(s);
- });
- tmp
+ (0..60).fold(Vec::with_capacity(60), |mut v, i| {
+ v.push([gan[i % 10], zhi[i % 12]].iter().collect());
+ v
+ })
});
&GANZHIS[i]
}
@@ -271,6 +272,7 @@ pub fn solar(y: usize, m: usize, d: usize) -> SexagenaryDate {
let div = int(a.div(15.).floor());
let mut dz = align(div.div_ceil(2), 12, 9);
let mut termb = rem > 14.;
+ // SAFETY: guarded by termb
let mut term: usize = unsafe { MaybeUninit::uninit().assume_init() };
if termb {
term = align(div, 24, 18);