Skip to main content

shape_jit/ffi/call_method/
duration.rs

1// Heap allocation audit (PR-9 V8 Gap Closure):
2//   Category A (NaN-boxed returns): 1 site
3//     jit_box(HK_DURATION, ...) — to() unit conversion
4//   Category B (intermediate/consumed): 0 sites
5//   Category C (heap islands): 0 sites
6//!
7//! Duration method implementations for JIT
8
9use crate::context::JITDuration;
10use crate::nan_boxing::*;
11
12/// Call a method on a duration value
13#[inline(always)]
14pub fn call_duration_method(receiver_bits: u64, method_name: &str, args: &[u64]) -> u64 {
15    unsafe {
16        if !is_heap_kind(receiver_bits, HK_DURATION) {
17            return TAG_NULL;
18        }
19        let dur = jit_unbox::<JITDuration>(receiver_bits);
20
21        match method_name {
22            "to_seconds" | "toSeconds" | "as_seconds" => {
23                let seconds = match dur.unit {
24                    0 => dur.value,              // seconds
25                    1 => dur.value * 60.0,       // minutes
26                    2 => dur.value * 3600.0,     // hours
27                    3 => dur.value * 86400.0,    // days
28                    4 => dur.value * 604800.0,   // weeks
29                    5 => dur.value * 2592000.0,  // months (30 days)
30                    6 => dur.value * 31536000.0, // years (365 days)
31                    _ => dur.value,
32                };
33                box_number(seconds)
34            }
35            "to_minutes" | "toMinutes" | "as_minutes" => {
36                let minutes = match dur.unit {
37                    0 => dur.value / 60.0,
38                    1 => dur.value,
39                    2 => dur.value * 60.0,
40                    3 => dur.value * 1440.0,
41                    4 => dur.value * 10080.0,
42                    5 => dur.value * 43200.0,
43                    6 => dur.value * 525600.0,
44                    _ => dur.value,
45                };
46                box_number(minutes)
47            }
48            "to_hours" | "toHours" | "as_hours" => {
49                let hours = match dur.unit {
50                    0 => dur.value / 3600.0,
51                    1 => dur.value / 60.0,
52                    2 => dur.value,
53                    3 => dur.value * 24.0,
54                    4 => dur.value * 168.0,
55                    5 => dur.value * 720.0,
56                    6 => dur.value * 8760.0,
57                    _ => dur.value,
58                };
59                box_number(hours)
60            }
61            "to_days" | "toDays" | "as_days" => {
62                let days = match dur.unit {
63                    0 => dur.value / 86400.0,
64                    1 => dur.value / 1440.0,
65                    2 => dur.value / 24.0,
66                    3 => dur.value,
67                    4 => dur.value * 7.0,
68                    5 => dur.value * 30.0,
69                    6 => dur.value * 365.0,
70                    _ => dur.value,
71                };
72                box_number(days)
73            }
74            "value" => box_number(dur.value),
75            "unit" => box_number(dur.unit as f64),
76            "to" => {
77                // to("seconds"), to("minutes"), etc. - returns a new Duration in the target unit
78                if args.is_empty() {
79                    return TAG_NULL;
80                }
81                // Get target unit from first argument (should be a string)
82                let target_unit_str = if is_heap_kind(args[0], HK_STRING) {
83                    jit_unbox::<String>(args[0]).as_str()
84                } else {
85                    return TAG_NULL;
86                };
87
88                // Convert to seconds first (as intermediate)
89                let seconds = match dur.unit {
90                    0 => dur.value,              // seconds
91                    1 => dur.value * 60.0,       // minutes
92                    2 => dur.value * 3600.0,     // hours
93                    3 => dur.value * 86400.0,    // days
94                    4 => dur.value * 604800.0,   // weeks
95                    5 => dur.value * 2592000.0,  // months (30 days)
96                    6 => dur.value * 31536000.0, // years (365 days)
97                    _ => dur.value,
98                };
99
100                // Convert from seconds to target unit
101                let (new_value, new_unit) = match target_unit_str {
102                    "seconds" | "second" | "s" => (seconds, 0u8),
103                    "minutes" | "minute" | "m" => (seconds / 60.0, 1u8),
104                    "hours" | "hour" | "h" => (seconds / 3600.0, 2u8),
105                    "days" | "day" | "d" => (seconds / 86400.0, 3u8),
106                    "weeks" | "week" | "w" => (seconds / 604800.0, 4u8),
107                    "months" | "month" => (seconds / 2592000.0, 5u8),
108                    "years" | "year" | "y" => (seconds / 31536000.0, 6u8),
109                    _ => return TAG_NULL,
110                };
111
112                // Create a new JITDuration and return it
113                jit_box(
114                    HK_DURATION,
115                    JITDuration {
116                        value: new_value,
117                        unit: new_unit,
118                    },
119                )
120            }
121            _ => TAG_NULL,
122        }
123    }
124}