Skip to content

Commit d12d76c

Browse files
committed
cleanup: remove most i64s from the wasm_bindings, safely cast to i32.
1 parent 2dad730 commit d12d76c

8 files changed

Lines changed: 77 additions & 68 deletions

File tree

crates/lox-space/src/time/wasm/deltas.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,26 @@ impl JsTimeDelta {
6060
///
6161
/// Raises:
6262
/// NonFiniteTimeDeltaError: If the delta is non-finite.
63-
pub fn seconds(&self) -> Result<i64, JsValue> {
64-
self.0.seconds().ok_or_else(|| {
63+
pub fn seconds(&self) -> Result<i32, JsValue> {
64+
self
65+
.0
66+
.seconds()
67+
.ok_or_else(|| {
6568
js_error_with_name(
6669
"NonFiniteTimeDeltaError",
6770
"cannot access seconds for non-finite time delta",
6871
)
6972
})
73+
.and_then(|seconds| {
74+
if seconds > i32::MAX as i64 || seconds < i32::MIN as i64 {
75+
Err(js_error_with_name(
76+
"OverflowError",
77+
"seconds component out of range for i32",
78+
))
79+
} else {
80+
Ok(seconds as i32)
81+
}
82+
})
7083
}
7184

7285
/// Return the subsecond (fractional second) component.
@@ -87,8 +100,8 @@ impl JsTimeDelta {
87100

88101
/// Create a TimeDelta from integer seconds.
89102
#[wasm_bindgen(js_name = "fromSeconds")]
90-
pub fn from_seconds(seconds: i64) -> Self {
91-
Self(TimeDelta::from_seconds(seconds))
103+
pub fn from_seconds(seconds: i32) -> Self {
104+
Self(TimeDelta::from_seconds(seconds as i64))
92105
}
93106

94107
/// Create a TimeDelta from minutes.
@@ -133,9 +146,9 @@ impl JsTimeDelta {
133146
///
134147
/// Examples:
135148
/// >>> deltas = lox.TimeDelta.range(0, 10, 2) # [0, 2, 4, 6, 8, 10]
136-
pub fn range(start: i64, end: i64, step: Option<i64>) -> Array {
137-
let step = TimeDelta::from_seconds(step.unwrap_or(1));
138-
let range = TimeDelta::range(start..=end).with_step(step);
149+
pub fn range(start: i32, end: i32, step: Option<i32>) -> Array {
150+
let step = TimeDelta::from_seconds(step.unwrap_or(1) as i64);
151+
let range = TimeDelta::range(start as i64..=end as i64).with_step(step);
139152
let arr = Array::new();
140153
for delta in range {
141154
arr.push(&JsValue::from(JsTimeDelta(delta)));

crates/lox-space/src/time/wasm/time.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl JsTime {
132132
#[wasm_bindgen(constructor)]
133133
pub fn new(
134134
scale: JsValue,
135-
year: i64,
135+
year: i32,
136136
month: u8,
137137
day: u8,
138138
hour: Option<u8>,
@@ -144,7 +144,7 @@ impl JsTime {
144144
let seconds = seconds.unwrap_or(0.0);
145145
let scale: JsTimeScale = scale.try_into()?;
146146
let time = Time::builder_with_scale(scale.inner())
147-
.with_ymd(year, month, day)
147+
.with_ymd(year as i64, month, day)
148148
.with_hms(hour, minute, seconds)
149149
.build()
150150
.map_err(JsTimeError)?;
@@ -218,15 +218,15 @@ impl JsTime {
218218
#[wasm_bindgen(js_name="fromDayOfYear")]
219219
pub fn from_day_of_year(
220220
scale: JsValue,
221-
year: i64,
221+
year: i32,
222222
day: u16,
223223
hour: Option<u8>,
224224
minute: Option<u8>,
225225
seconds: Option<f64>,
226226
) -> Result<JsTime, JsValue> {
227227
let scale: JsTimeScale = scale.try_into()?;
228228
let time = Time::builder_with_scale(scale.inner())
229-
.with_doy(year, day)
229+
.with_doy(year as i64, day)
230230
.with_hms(hour.unwrap_or(0), minute.unwrap_or(0), seconds.unwrap_or(0.0))
231231
.build()
232232
.map_err(JsTimeError)?;
@@ -419,8 +419,17 @@ impl JsTime {
419419
}
420420

421421
/// Return the year component.
422-
pub fn year(&self) -> i64 {
423-
self.0.year()
422+
pub fn year(&self) -> Result<i32, JsValue> {
423+
let year: i64 = self.0.year();
424+
425+
if year > i32::MAX as i64 || year < i32::MIN as i64 {
426+
Err(js_error_with_name(
427+
"OverflowError",
428+
"seconds component out of range for i32",
429+
))
430+
} else {
431+
Ok(year as i32)
432+
}
424433
}
425434

426435
/// Return the month component (1-12).

crates/lox-space/src/time/wasm/utc.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::time::time_of_day::CivilTime;
1212
use crate::time::utc::{Utc, UtcError};
1313
use crate::time::wasm::time::JsTime;
1414
use crate::time::wasm::time_scales::JsTimeScale;
15-
use crate::wasm::{js_error_with_name_from_string};
15+
use crate::wasm::{js_error_with_name, js_error_with_name_from_string};
1616

1717
pub struct JsUtcError(pub UtcError);
1818

@@ -49,15 +49,15 @@ pub struct JsUtc(Utc);
4949
impl JsUtc {
5050
#[wasm_bindgen(constructor)]
5151
pub fn new(
52-
year: i64,
52+
year: i32,
5353
month: u8,
5454
day: u8,
5555
hour: Option<u8>,
5656
minute: Option<u8>,
5757
seconds: Option<f64>,
5858
) -> Result<JsUtc, JsValue> {
5959
let utc = Utc::builder()
60-
.with_ymd(year, month, day)
60+
.with_ymd(year as i64, month, day)
6161
.with_hms(hour.unwrap_or(0), minute.unwrap_or(0), seconds.unwrap_or(0.0))
6262
.build()
6363
.map_err(JsUtcError)?;
@@ -117,8 +117,17 @@ impl JsUtc {
117117
}
118118

119119
/// Return the year component.
120-
pub fn year(&self) -> i64 {
121-
self.0.year()
120+
pub fn year(&self) -> Result<i32, JsValue> {
121+
let year: i64 = self.0.year();
122+
123+
if year > i32::MAX as i64 || year < i32::MIN as i64 {
124+
Err(js_error_with_name(
125+
"OverflowError",
126+
"seconds component out of range for i32",
127+
))
128+
} else {
129+
Ok(year as i32)
130+
}
122131
}
123132

124133
/// Return the month component (1-12).

crates/lox-space/tests/js/fixtures.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export function loadEstrack() {
8585
const origin = new lox.Origin('Earth');
8686
const loc = new lox.GroundLocation(origin, deg2rad(lon), deg2rad(lat), 0);
8787
const mask = lox.ElevationMask.fixed(0);
88-
return new lox.GroundStation(name, loc, mask); // adjust ctor if different
88+
return new lox.GroundStation(name, loc, mask);
8989
});
9090
}
9191

crates/lox-space/tests/js/test_frames.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const assertVecClose = (a, b, atol = 1e-6) => {
3737
describe("IAU frame transforms", () => {
3838
for (const frame of frames) {
3939
it(`converts J2000 -> ${frame}`, () => {
40-
const t = new Time("TDB", 2000n, 1, 1, 0, 0, 0);
40+
const t = new Time("TDB", 2000, 1, 1, 0, 0, 0);
4141
const r0 = [6068.27927, -1692.84394, -2516.61918];
4242
const v0 = [-0.660415582, 5.495938726, -5.303093233];
4343

crates/lox-space/tests/js/test_ground.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ describe('Ground observables', () => {
2222

2323
const position = [3359.927, -2398.072, 5153.0];
2424
const velocity = [5.0657, 5.485, -0.744];
25-
const time = new Time('TDB', 2012n, 7, 1, 0, 0, 0);
25+
const time = new Time('TDB', 2012, 7, 1, 0, 0, 0);
2626
const state = new State(time, position, velocity, new Origin('Earth'), new Frame('IAU_EARTH'));
2727

2828
const observables = location.observables(state);

crates/lox-space/tests/js/test_propagators.js

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,10 @@
22
//
33
// SPDX-License-Identifier: MPL-2.0
44

5-
import assert from "node:assert/strict";
65
import { describe, it } from "node:test";
7-
import { lox as binding, deg2rad } from './fixtures.js';
6+
import { lox as bindings, deg2rad, approxEqual, assertVecClose } from './fixtures.js';
87

9-
const { GroundLocation, GroundPropagator, Origin, SGP4, TimeDelta, UTC } =
10-
bindings;
11-
12-
const assertCloseRel = (actual, expected, rel = 1e-6) => {
13-
const diff = Math.abs(actual - expected);
14-
const tol = Math.abs(expected) * rel;
15-
assert.ok(
16-
diff <= tol,
17-
`actual=${actual}, expected=${expected}, |diff|=${diff} > tol=${tol}`
18-
);
19-
};
20-
21-
const assertVecClose = (actual, expected, atol = 1e-6) => {
22-
assert.equal(actual.length, expected.length);
23-
actual.forEach((v, idx) => {
24-
const diff = Math.abs(v - expected[idx]);
25-
assert.ok(
26-
diff <= atol,
27-
`mismatch at idx ${idx}: actual=${v}, expected=${expected[idx]}, |diff|=${diff} > atol=${atol}`
28-
);
29-
});
30-
};
8+
const { GroundLocation, GroundPropagator, Origin, SGP4, TimeDelta, UTC } = bindings;
319

3210
describe("propagators", () => {
3311
it("computes SGP4 orbital period", () => {
@@ -43,7 +21,7 @@ describe("propagators", () => {
4321
const actualPeriod = k1.orbitalPeriod().toDecimalSeconds();
4422
const expectedPeriod = 92.821 * 60;
4523

46-
assertCloseRel(actualPeriod, expectedPeriod, 1e-4);
24+
approxEqual(actualPeriod, expectedPeriod, 1e-4);
4725
});
4826

4927
it("propagates ground location state", () => {

crates/lox-space/tests/js/test_time.js

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('time', () => {
3333
});
3434

3535
it('handles time scale conversions and arithmetic', () => {
36-
const taiExp = new Time('TAI', 2000n, 1, 1);
36+
const taiExp = new Time('TAI', 2000, 1, 1);
3737
let taiAct = Time.fromISO('2000-01-01T00:00:00.000 TAI');
3838
assertTimeEqual(taiExp, taiAct);
3939

@@ -55,7 +55,7 @@ describe('time', () => {
5555
taiAct = taiExp.toScale('UT1', provider).toScale('TAI', provider);
5656
assertTimeClose(taiExp, taiAct);
5757

58-
const tai1 = new Time('TAI', 2000n, 1, 1, 0, 0, 0.5);
58+
const tai1 = new Time('TAI', 2000, 1, 1, 0, 0, 0.5);
5959
assert.ok(tai1.julianDate('jd', 'seconds') > taiExp.julianDate('jd', 'seconds'));
6060
const dt = new TimeDelta(0.5);
6161
assertTimeClose(taiExp.add(dt), tai1);
@@ -65,7 +65,7 @@ describe('time', () => {
6565
});
6666

6767
it('parses and converts UTC', () => {
68-
const utcExp = new UTC(2000n, 1, 1);
68+
const utcExp = new UTC(2000, 1, 1);
6969

7070
let utcAct = UTC.fromISO('2000-01-01T00:00:00.000');
7171
assertTimeEqual(utcExp, utcAct);
@@ -101,7 +101,7 @@ describe('time', () => {
101101
assert.equal(delta.toString(), '1.5 seconds'); // in case String calls toString
102102
assert.equal(delta.inspect ? delta.inspect() : delta.toString(), '1.5 seconds');
103103

104-
assert.equal(delta.seconds(), 1n);
104+
assert.equal(delta.seconds(), 1);
105105
assert.equal(delta.subsecond(), 0.5);
106106

107107
assert.equal(String(delta.add(delta)), '3 seconds');
@@ -115,7 +115,7 @@ describe('time', () => {
115115
});
116116

117117
it('constructs TimeDelta from various units', () => {
118-
let td = TimeDelta.fromSeconds(123n);
118+
let td = TimeDelta.fromSeconds(123);
119119
assert.equal(td.toDecimalSeconds(), 123);
120120

121121
td = TimeDelta.fromMinutes(2);
@@ -135,15 +135,15 @@ describe('time', () => {
135135
});
136136

137137
it('stringifies Time correctly', () => {
138-
const time = new Time('TAI', 2000n, 1, 1, 0, 0, 12.123456789123);
138+
const time = new Time('TAI', 2000, 1, 1, 0, 0, 12.123456789123);
139139
assert.equal(String(time), '2000-01-01T00:00:12.123 TAI');
140140
assert.equal(time.toString(), '2000-01-01T00:00:12.123 TAI');
141141
});
142142

143143
it('exposes Time accessors', () => {
144-
const time = new Time('TAI', 2000n, 1, 1, 0, 0, 12.123456789123);
144+
const time = new Time('TAI', 2000, 1, 1, 0, 0, 12.123456789123);
145145
assert.equal(time.scale().abbreviation(), 'TAI');
146-
assert.equal(time.year(), 2000n);
146+
assert.equal(time.year(), 2000);
147147
assert.equal(time.month(), 1);
148148
assert.equal(time.day(), 1);
149149
assert.equal(time.hour(), 0);
@@ -157,19 +157,19 @@ describe('time', () => {
157157
});
158158

159159
it('rejects invalid dates and hours', () => {
160-
assert.throws(() => new Time('TAI', 2000n, 13, 1), /invalid date/);
161-
assert.throws(() => new Time('TAI', 2000n, 12, 1, 24, 0, 0), /hour must be in the range/);
160+
assert.throws(() => new Time('TAI', 2000, 13, 1), /invalid date/);
161+
assert.throws(() => new Time('TAI', 2000, 12, 1, 24, 0, 0), /hour must be in the range/);
162162
});
163163

164164
it('disallows subtracting different time scales', () => {
165-
const t1 = new Time('TAI', 2000n, 1, 1, 0, 0, 1.0);
166-
const t0 = new Time('TT', 2000n, 1, 1, 0, 0, 1.0);
165+
const t1 = new Time('TAI', 2000, 1, 1, 0, 0, 1.0);
166+
const t0 = new Time('TT', 2000, 1, 1, 0, 0, 1.0);
167167
assert.throws(() => t1.subtractTime(t0), /cannot subtract.*different time scales/i);
168168
});
169169

170170
it('disallows isclose on different time scales', () => {
171-
const t0 = new Time('TAI', 2000n, 1, 1);
172-
const t1 = new Time('TT', 2000n, 1, 1);
171+
const t0 = new Time('TAI', 2000, 1, 1);
172+
const t1 = new Time('TT', 2000, 1, 1);
173173
assert.throws(() => t0.isClose(t1), /cannot compare.*different time scales/i);
174174
});
175175

@@ -199,27 +199,27 @@ describe('time', () => {
199199
});
200200

201201
it('rejects invalid epochs and units', () => {
202-
const time = new Time('TAI', 2000n, 1, 1);
202+
const time = new Time('TAI', 2000, 1, 1);
203203
assert.throws(() => time.julianDate('unknown', 'days'), /unknown epoch: unknown/);
204204
assert.throws(() => time.julianDate('jd', 'unknown'), /unknown unit: unknown/);
205205
});
206206

207207
it('converts to/from two-part Julian dates', () => {
208-
const expected = new Time('TAI', 2024n, 7, 11, 8, 2, 14.0);
208+
const expected = new Time('TAI', 2024, 7, 11, 8, 2, 14.0);
209209
const [jd1, jd2] = expected.twoPartJulianDate();
210210
const actual = Time.fromTwoPartJulianDate('TAI', jd1, jd2);
211211
assertTimeClose(expected, actual);
212212
});
213213

214214
it('converts from day-of-year', () => {
215-
const expected = new Time('TAI', 2024n, 12, 31);
216-
const actual = Time.fromDayOfYear('TAI', 2024n, 366);
215+
const expected = new Time('TAI', 2024, 12, 31);
216+
const actual = Time.fromDayOfYear('TAI', 2024, 366);
217217
assertTimeEqual(actual, expected);
218218
});
219219

220220
it('exposes UTC accessors', () => {
221-
const utc = new UTC(2000n, 1, 1, 12, 13, 14.123456789123);
222-
assert.equal(utc.year(), 2000n);
221+
const utc = new UTC(2000, 1, 1, 12, 13, 14.123456789123);
222+
assert.equal(utc.year(), 2000);
223223
assert.equal(utc.month(), 1);
224224
assert.equal(utc.day(), 1);
225225
assert.equal(utc.hour(), 12);
@@ -235,15 +235,15 @@ describe('time', () => {
235235
});
236236

237237
it('rejects invalid UTC inputs', () => {
238-
assert.throws(() => new UTC(2000n, 0, 1), /invalid date/);
238+
assert.throws(() => new UTC(2000, 0, 1), /invalid date/);
239239
assert.throws(() => UTC.fromISO('2000-01-01X00:00:00 UTC'), /invalid ISO/);
240240
});
241241

242242
it('handles EOP provider errors', () => {
243243
assert.throws(() => new EOPProvider('invalid_path'), EopParserError);
244244

245245
const provider = loadEOPProvider();
246-
const tai = new Time('TAI', 2100n, 1, 1);
246+
const tai = new Time('TAI', 2100, 1, 1);
247247
assert.throws(() => tai.toScaleWithProvider('UT1', provider), EopProviderError);
248248
});
249249
});

0 commit comments

Comments
 (0)