rrule-rust 0.0.1-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.yarnrc.yml ADDED
@@ -0,0 +1 @@
1
+ nodeLinker: node-modules
package/Cargo.toml ADDED
@@ -0,0 +1,21 @@
1
+ [package]
2
+ edition = "2021"
3
+ name = "rrule-rust"
4
+ version = "0.0.0"
5
+
6
+ [lib]
7
+ crate-type = ["cdylib"]
8
+
9
+ [dependencies]
10
+ chrono = "0.4.24"
11
+ # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
12
+ napi = { version = "2.11.1", default-features = false, features = ["napi4"] }
13
+ napi-derive = "2.11.0"
14
+ replace_with = "0.1.7"
15
+ rrule = { version = "0.10.0", features = ["exrule"] }
16
+
17
+ [build-dependencies]
18
+ napi-build = "2.0.1"
19
+
20
+ [profile.release]
21
+ lto = true
package/build.rs ADDED
@@ -0,0 +1,5 @@
1
+ extern crate napi_build;
2
+
3
+ fn main() {
4
+ napi_build::setup();
5
+ }
package/index.d.ts ADDED
@@ -0,0 +1,82 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /* auto-generated by NAPI-RS */
5
+
6
+ export const enum Frequency {
7
+ Yearly = 0,
8
+ Monthly = 1,
9
+ Weekly = 2,
10
+ Daily = 3,
11
+ Hourly = 4,
12
+ Minutely = 5,
13
+ Secondly = 6
14
+ }
15
+ export const enum Weekday {
16
+ Monday = 0,
17
+ Tuesday = 1,
18
+ Wednesday = 2,
19
+ Thursday = 3,
20
+ Friday = 4,
21
+ Saturday = 5,
22
+ Sunday = 6
23
+ }
24
+ export const enum Month {
25
+ January = 0,
26
+ February = 1,
27
+ March = 2,
28
+ April = 3,
29
+ May = 4,
30
+ June = 5,
31
+ July = 6,
32
+ August = 7,
33
+ September = 8,
34
+ October = 9,
35
+ November = 10,
36
+ December = 11
37
+ }
38
+ export type JsRRule = RRule
39
+ export class RRule {
40
+ constructor(frequency: Frequency)
41
+ get frequency(): Frequency
42
+ get interval(): number
43
+ get count(): number | null
44
+ get byWeekday(): Weekday[]
45
+ get byHour(): Array<number>
46
+ get byMinute(): Array<number>
47
+ get bySecond(): Array<number>
48
+ get byMonthday(): Array<number>
49
+ get bySetpos(): Array<number>
50
+ get byMonth(): Month[]
51
+ get byWeekno(): Array<number>
52
+ get byYearday(): Array<number>
53
+ get weekstart(): Weekday
54
+ get until(): number | null
55
+ toString(): string
56
+ setInterval(interval: number): this
57
+ setCount(count: number): this
58
+ setByWeekday(weekdays: Weekday[]): this
59
+ setByHour(hours: Array<number>): this
60
+ setByMinute(minutes: Array<number>): this
61
+ setBySecond(seconds: Array<number>): this
62
+ setByMonthday(days: Array<number>): this
63
+ setBySetpos(poses: Array<number>): this
64
+ setByMonth(months: Month[]): this
65
+ setByWeekno(weekNumbers: Array<number>): this
66
+ setByYearday(days: Array<number>): this
67
+ getWeekstart(day: Weekday): this
68
+ setUntil(timestamp: number): this
69
+ }
70
+ export type JsRRuleSet = RRuleSet
71
+ export class RRuleSet {
72
+ constructor(dtstart: number, tzid: string)
73
+ toString(): string
74
+ rrule(jsRrule: RRule): this
75
+ exrule(jsRrule: RRule): this
76
+ after(timestamp: number): this
77
+ before(timestamp: number): this
78
+ exdate(timestamp: number): this
79
+ getDtstart(): number
80
+ getTzid(): string
81
+ all(limit?: number | undefined | null): number[]
82
+ }
package/index.js ADDED
@@ -0,0 +1,255 @@
1
+ const { existsSync, readFileSync } = require('fs')
2
+ const { join } = require('path')
3
+
4
+ const { platform, arch } = process
5
+
6
+ let nativeBinding = null
7
+ let localFileExisted = false
8
+ let loadError = null
9
+
10
+ function isMusl() {
11
+ // For Node 10
12
+ if (!process.report || typeof process.report.getReport !== 'function') {
13
+ try {
14
+ const lddPath = require('child_process').execSync('which ldd').toString().trim();
15
+ return readFileSync(lddPath, 'utf8').includes('musl')
16
+ } catch (e) {
17
+ return true
18
+ }
19
+ } else {
20
+ const { glibcVersionRuntime } = process.report.getReport().header
21
+ return !glibcVersionRuntime
22
+ }
23
+ }
24
+
25
+ switch (platform) {
26
+ case 'android':
27
+ switch (arch) {
28
+ case 'arm64':
29
+ localFileExisted = existsSync(join(__dirname, 'rrule-rust.android-arm64.node'))
30
+ try {
31
+ if (localFileExisted) {
32
+ nativeBinding = require('./rrule-rust.android-arm64.node')
33
+ } else {
34
+ nativeBinding = require('rrule-rust-android-arm64')
35
+ }
36
+ } catch (e) {
37
+ loadError = e
38
+ }
39
+ break
40
+ case 'arm':
41
+ localFileExisted = existsSync(join(__dirname, 'rrule-rust.android-arm-eabi.node'))
42
+ try {
43
+ if (localFileExisted) {
44
+ nativeBinding = require('./rrule-rust.android-arm-eabi.node')
45
+ } else {
46
+ nativeBinding = require('rrule-rust-android-arm-eabi')
47
+ }
48
+ } catch (e) {
49
+ loadError = e
50
+ }
51
+ break
52
+ default:
53
+ throw new Error(`Unsupported architecture on Android ${arch}`)
54
+ }
55
+ break
56
+ case 'win32':
57
+ switch (arch) {
58
+ case 'x64':
59
+ localFileExisted = existsSync(
60
+ join(__dirname, 'rrule-rust.win32-x64-msvc.node')
61
+ )
62
+ try {
63
+ if (localFileExisted) {
64
+ nativeBinding = require('./rrule-rust.win32-x64-msvc.node')
65
+ } else {
66
+ nativeBinding = require('rrule-rust-win32-x64-msvc')
67
+ }
68
+ } catch (e) {
69
+ loadError = e
70
+ }
71
+ break
72
+ case 'ia32':
73
+ localFileExisted = existsSync(
74
+ join(__dirname, 'rrule-rust.win32-ia32-msvc.node')
75
+ )
76
+ try {
77
+ if (localFileExisted) {
78
+ nativeBinding = require('./rrule-rust.win32-ia32-msvc.node')
79
+ } else {
80
+ nativeBinding = require('rrule-rust-win32-ia32-msvc')
81
+ }
82
+ } catch (e) {
83
+ loadError = e
84
+ }
85
+ break
86
+ case 'arm64':
87
+ localFileExisted = existsSync(
88
+ join(__dirname, 'rrule-rust.win32-arm64-msvc.node')
89
+ )
90
+ try {
91
+ if (localFileExisted) {
92
+ nativeBinding = require('./rrule-rust.win32-arm64-msvc.node')
93
+ } else {
94
+ nativeBinding = require('rrule-rust-win32-arm64-msvc')
95
+ }
96
+ } catch (e) {
97
+ loadError = e
98
+ }
99
+ break
100
+ default:
101
+ throw new Error(`Unsupported architecture on Windows: ${arch}`)
102
+ }
103
+ break
104
+ case 'darwin':
105
+ localFileExisted = existsSync(join(__dirname, 'rrule-rust.darwin-universal.node'))
106
+ try {
107
+ if (localFileExisted) {
108
+ nativeBinding = require('./rrule-rust.darwin-universal.node')
109
+ } else {
110
+ nativeBinding = require('rrule-rust-darwin-universal')
111
+ }
112
+ break
113
+ } catch {}
114
+ switch (arch) {
115
+ case 'x64':
116
+ localFileExisted = existsSync(join(__dirname, 'rrule-rust.darwin-x64.node'))
117
+ try {
118
+ if (localFileExisted) {
119
+ nativeBinding = require('./rrule-rust.darwin-x64.node')
120
+ } else {
121
+ nativeBinding = require('rrule-rust-darwin-x64')
122
+ }
123
+ } catch (e) {
124
+ loadError = e
125
+ }
126
+ break
127
+ case 'arm64':
128
+ localFileExisted = existsSync(
129
+ join(__dirname, 'rrule-rust.darwin-arm64.node')
130
+ )
131
+ try {
132
+ if (localFileExisted) {
133
+ nativeBinding = require('./rrule-rust.darwin-arm64.node')
134
+ } else {
135
+ nativeBinding = require('rrule-rust-darwin-arm64')
136
+ }
137
+ } catch (e) {
138
+ loadError = e
139
+ }
140
+ break
141
+ default:
142
+ throw new Error(`Unsupported architecture on macOS: ${arch}`)
143
+ }
144
+ break
145
+ case 'freebsd':
146
+ if (arch !== 'x64') {
147
+ throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
148
+ }
149
+ localFileExisted = existsSync(join(__dirname, 'rrule-rust.freebsd-x64.node'))
150
+ try {
151
+ if (localFileExisted) {
152
+ nativeBinding = require('./rrule-rust.freebsd-x64.node')
153
+ } else {
154
+ nativeBinding = require('rrule-rust-freebsd-x64')
155
+ }
156
+ } catch (e) {
157
+ loadError = e
158
+ }
159
+ break
160
+ case 'linux':
161
+ switch (arch) {
162
+ case 'x64':
163
+ if (isMusl()) {
164
+ localFileExisted = existsSync(
165
+ join(__dirname, 'rrule-rust.linux-x64-musl.node')
166
+ )
167
+ try {
168
+ if (localFileExisted) {
169
+ nativeBinding = require('./rrule-rust.linux-x64-musl.node')
170
+ } else {
171
+ nativeBinding = require('rrule-rust-linux-x64-musl')
172
+ }
173
+ } catch (e) {
174
+ loadError = e
175
+ }
176
+ } else {
177
+ localFileExisted = existsSync(
178
+ join(__dirname, 'rrule-rust.linux-x64-gnu.node')
179
+ )
180
+ try {
181
+ if (localFileExisted) {
182
+ nativeBinding = require('./rrule-rust.linux-x64-gnu.node')
183
+ } else {
184
+ nativeBinding = require('rrule-rust-linux-x64-gnu')
185
+ }
186
+ } catch (e) {
187
+ loadError = e
188
+ }
189
+ }
190
+ break
191
+ case 'arm64':
192
+ if (isMusl()) {
193
+ localFileExisted = existsSync(
194
+ join(__dirname, 'rrule-rust.linux-arm64-musl.node')
195
+ )
196
+ try {
197
+ if (localFileExisted) {
198
+ nativeBinding = require('./rrule-rust.linux-arm64-musl.node')
199
+ } else {
200
+ nativeBinding = require('rrule-rust-linux-arm64-musl')
201
+ }
202
+ } catch (e) {
203
+ loadError = e
204
+ }
205
+ } else {
206
+ localFileExisted = existsSync(
207
+ join(__dirname, 'rrule-rust.linux-arm64-gnu.node')
208
+ )
209
+ try {
210
+ if (localFileExisted) {
211
+ nativeBinding = require('./rrule-rust.linux-arm64-gnu.node')
212
+ } else {
213
+ nativeBinding = require('rrule-rust-linux-arm64-gnu')
214
+ }
215
+ } catch (e) {
216
+ loadError = e
217
+ }
218
+ }
219
+ break
220
+ case 'arm':
221
+ localFileExisted = existsSync(
222
+ join(__dirname, 'rrule-rust.linux-arm-gnueabihf.node')
223
+ )
224
+ try {
225
+ if (localFileExisted) {
226
+ nativeBinding = require('./rrule-rust.linux-arm-gnueabihf.node')
227
+ } else {
228
+ nativeBinding = require('rrule-rust-linux-arm-gnueabihf')
229
+ }
230
+ } catch (e) {
231
+ loadError = e
232
+ }
233
+ break
234
+ default:
235
+ throw new Error(`Unsupported architecture on Linux: ${arch}`)
236
+ }
237
+ break
238
+ default:
239
+ throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
240
+ }
241
+
242
+ if (!nativeBinding) {
243
+ if (loadError) {
244
+ throw loadError
245
+ }
246
+ throw new Error(`Failed to load native binding`)
247
+ }
248
+
249
+ const { Frequency, Weekday, Month, RRule, RRuleSet } = nativeBinding
250
+
251
+ module.exports.Frequency = Frequency
252
+ module.exports.Weekday = Weekday
253
+ module.exports.Month = Month
254
+ module.exports.RRule = RRule
255
+ module.exports.RRuleSet = RRuleSet
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "rrule-rust",
3
+ "version": "0.0.1-1",
4
+ "main": "index.js",
5
+ "types": "index.d.ts",
6
+ "napi": {
7
+ "name": "rrule-rust",
8
+ "triples": {
9
+ "additional": [
10
+ "aarch64-apple-darwin",
11
+ "aarch64-linux-android",
12
+ "aarch64-unknown-linux-gnu",
13
+ "aarch64-unknown-linux-musl",
14
+ "aarch64-pc-windows-msvc",
15
+ "armv7-unknown-linux-gnueabihf",
16
+ "x86_64-unknown-linux-musl",
17
+ "x86_64-unknown-freebsd",
18
+ "i686-pc-windows-msvc",
19
+ "armv7-linux-androideabi",
20
+ "universal-apple-darwin"
21
+ ]
22
+ }
23
+ },
24
+ "license": "MIT",
25
+ "devDependencies": {
26
+ "@napi-rs/cli": "^2.14.8",
27
+ "ava": "^5.1.1"
28
+ },
29
+ "ava": {
30
+ "timeout": "3m"
31
+ },
32
+ "engines": {
33
+ "node": ">= 10"
34
+ },
35
+ "scripts": {
36
+ "artifacts": "napi artifacts",
37
+ "build": "napi build --platform --release",
38
+ "build:debug": "napi build --platform",
39
+ "prepublishOnly": "napi prepublish -t npm",
40
+ "test": "ava",
41
+ "universal": "napi universal",
42
+ "version": "napi version"
43
+ },
44
+ "optionalDependencies": {
45
+ "rrule-rust-win32-x64-msvc": "0.0.1-1",
46
+ "rrule-rust-darwin-x64": "0.0.1-1",
47
+ "rrule-rust-linux-x64-gnu": "0.0.1-1",
48
+ "rrule-rust-darwin-arm64": "0.0.1-1",
49
+ "rrule-rust-android-arm64": "0.0.1-1",
50
+ "rrule-rust-linux-arm64-gnu": "0.0.1-1",
51
+ "rrule-rust-linux-arm64-musl": "0.0.1-1",
52
+ "rrule-rust-win32-arm64-msvc": "0.0.1-1",
53
+ "rrule-rust-linux-arm-gnueabihf": "0.0.1-1",
54
+ "rrule-rust-linux-x64-musl": "0.0.1-1",
55
+ "rrule-rust-freebsd-x64": "0.0.1-1",
56
+ "rrule-rust-win32-ia32-msvc": "0.0.1-1",
57
+ "rrule-rust-android-arm-eabi": "0.0.1-1",
58
+ "rrule-rust-darwin-universal": "0.0.1-1"
59
+ }
60
+ }
package/src/lib.rs ADDED
@@ -0,0 +1,496 @@
1
+ #![deny(clippy::all)]
2
+
3
+ use chrono::{DateTime, Month, TimeZone, Weekday};
4
+ use napi::bindgen_prelude::*;
5
+ use replace_with::replace_with_or_abort;
6
+ use rrule::{Frequency, NWeekday, RRule, RRuleSet, Tz, Unvalidated};
7
+
8
+ #[macro_use]
9
+ extern crate napi_derive;
10
+
11
+ #[napi(js_name = "Frequency")]
12
+ pub enum JsFrequency {
13
+ Yearly,
14
+ Monthly,
15
+ Weekly,
16
+ Daily,
17
+ Hourly,
18
+ Minutely,
19
+ Secondly,
20
+ }
21
+
22
+ #[napi(js_name = "Weekday")]
23
+ pub enum JsWeekday {
24
+ Monday,
25
+ Tuesday,
26
+ Wednesday,
27
+ Thursday,
28
+ Friday,
29
+ Saturday,
30
+ Sunday,
31
+ }
32
+
33
+ #[napi(js_name = "Month")]
34
+ pub enum JsMonth {
35
+ January,
36
+ February,
37
+ March,
38
+ April,
39
+ May,
40
+ June,
41
+ July,
42
+ August,
43
+ September,
44
+ October,
45
+ November,
46
+ December,
47
+ }
48
+
49
+ #[napi(js_name = "RRule")]
50
+ pub struct JsRRule {
51
+ rrule: RRule<Unvalidated>,
52
+ }
53
+
54
+ #[napi]
55
+ impl JsRRule {
56
+ #[napi(constructor)]
57
+ pub fn new(frequency: JsFrequency) -> Self {
58
+ let rrule = RRule::new(map_js_frequency(frequency));
59
+
60
+ JsRRule { rrule }
61
+ }
62
+
63
+ #[napi(getter)]
64
+ pub fn frequency(&self) -> napi::Result<JsFrequency> {
65
+ Ok(map_rust_frequency(self.rrule.get_freq()))
66
+ }
67
+
68
+ #[napi(getter)]
69
+ pub fn interval(&self) -> napi::Result<u16> {
70
+ Ok(self.rrule.get_interval())
71
+ }
72
+
73
+ #[napi(getter)]
74
+ pub fn count(&self) -> napi::Result<Option<u32>> {
75
+ Ok(self.rrule.get_count())
76
+ }
77
+
78
+ #[napi(getter, ts_return_type = "Weekday[]")]
79
+ pub fn by_weekday(&self, env: Env) -> napi::Result<Array> {
80
+ let ndays = self.rrule.get_by_weekday();
81
+ let mut arr = env.create_array(0).unwrap();
82
+
83
+ for nday in ndays.iter() {
84
+ let day = match nday {
85
+ NWeekday::Every(day) => *day,
86
+ _ => panic!("Unsupported"),
87
+ };
88
+
89
+ arr.insert(map_rust_weekday(day)).unwrap();
90
+ }
91
+
92
+ Ok(arr)
93
+ }
94
+
95
+ #[napi(getter)]
96
+ pub fn by_hour(&self) -> napi::Result<Vec<u8>> {
97
+ Ok(self.rrule.get_by_hour().to_vec())
98
+ }
99
+
100
+ #[napi(getter)]
101
+ pub fn by_minute(&self) -> napi::Result<Vec<u8>> {
102
+ Ok(self.rrule.get_by_minute().to_vec())
103
+ }
104
+
105
+ #[napi(getter)]
106
+ pub fn by_second(&self) -> napi::Result<Vec<u8>> {
107
+ Ok(self.rrule.get_by_second().to_vec())
108
+ }
109
+
110
+ #[napi(getter)]
111
+ pub fn by_monthday(&self) -> napi::Result<Vec<i8>> {
112
+ Ok(self.rrule.get_by_month_day().to_vec())
113
+ }
114
+
115
+ #[napi(getter)]
116
+ pub fn by_setpos(&self) -> napi::Result<Vec<i32>> {
117
+ Ok(self.rrule.get_by_set_pos().to_vec())
118
+ }
119
+
120
+ #[napi(getter, ts_return_type = "Month[]")]
121
+ pub fn by_month(&self, env: Env) -> napi::Result<Array> {
122
+ let months = self.rrule.get_by_month();
123
+ let mut arr = env.create_array(0).unwrap();
124
+
125
+ for month in months.iter() {
126
+ arr.insert(map_rust_month(month)).unwrap();
127
+ }
128
+
129
+ Ok(arr)
130
+ }
131
+
132
+ #[napi(getter)]
133
+ pub fn by_weekno(&self) -> napi::Result<Vec<i8>> {
134
+ Ok(self.rrule.get_by_week_no().to_vec())
135
+ }
136
+
137
+ #[napi(getter)]
138
+ pub fn by_yearday(&self) -> napi::Result<Vec<i16>> {
139
+ Ok(self.rrule.get_by_year_day().to_vec())
140
+ }
141
+
142
+ #[napi(getter)]
143
+ pub fn weekstart(&self) -> napi::Result<JsWeekday> {
144
+ Ok(map_rust_weekday(self.rrule.get_week_start()))
145
+ }
146
+
147
+ #[napi(getter)]
148
+ pub fn until(&self) -> napi::Result<Option<i64>> {
149
+ Ok(match self.rrule.get_until() {
150
+ Some(until) => Some(until.timestamp_millis()),
151
+ None => None,
152
+ })
153
+ }
154
+
155
+ #[napi]
156
+ pub fn to_string(&self) -> napi::Result<String> {
157
+ Ok(self.rrule.to_string())
158
+ }
159
+
160
+ #[napi]
161
+ pub fn set_interval(&mut self, interval: u16) -> napi::Result<&Self> {
162
+ replace_with_or_abort(&mut self.rrule, |self_| self_.interval(interval));
163
+
164
+ Ok(self)
165
+ }
166
+
167
+ #[napi]
168
+ pub fn set_count(&mut self, count: u32) -> napi::Result<&Self> {
169
+ replace_with_or_abort(&mut self.rrule, |self_| self_.count(count));
170
+
171
+ Ok(self)
172
+ }
173
+
174
+ #[napi]
175
+ pub fn set_by_weekday(
176
+ &mut self,
177
+ #[napi(ts_arg_type = "Weekday[]")] weekdays: Array,
178
+ ) -> napi::Result<&Self> {
179
+ let mut vec: Vec<NWeekday> = Vec::new();
180
+
181
+ for i in 0..weekdays.len() {
182
+ let day: JsWeekday = weekdays.get(i).unwrap().unwrap();
183
+ let day = NWeekday::Every(map_js_weekday(day));
184
+
185
+ vec.push(day);
186
+ }
187
+
188
+ Ok(self)
189
+ }
190
+
191
+ #[napi]
192
+ pub fn set_by_hour(&mut self, hours: Vec<u8>) -> napi::Result<&Self> {
193
+ replace_with_or_abort(&mut self.rrule, |self_| self_.by_hour(hours));
194
+
195
+ Ok(self)
196
+ }
197
+
198
+ #[napi]
199
+ pub fn set_by_minute(&mut self, minutes: Vec<u8>) -> napi::Result<&Self> {
200
+ replace_with_or_abort(&mut self.rrule, |self_| self_.by_minute(minutes));
201
+
202
+ Ok(self)
203
+ }
204
+
205
+ #[napi]
206
+ pub fn set_by_second(&mut self, seconds: Vec<u8>) -> napi::Result<&Self> {
207
+ replace_with_or_abort(&mut self.rrule, |self_| self_.by_second(seconds));
208
+
209
+ Ok(self)
210
+ }
211
+
212
+ #[napi]
213
+ pub fn set_by_monthday(&mut self, days: Vec<i8>) -> napi::Result<&Self> {
214
+ replace_with_or_abort(&mut self.rrule, |self_| self_.by_month_day(days));
215
+
216
+ Ok(self)
217
+ }
218
+
219
+ #[napi]
220
+ pub fn set_by_setpos(&mut self, poses: Vec<i32>) -> napi::Result<&Self> {
221
+ replace_with_or_abort(&mut self.rrule, |self_| self_.by_set_pos(poses));
222
+
223
+ Ok(self)
224
+ }
225
+
226
+ #[napi]
227
+ pub fn set_by_month(
228
+ &mut self,
229
+ #[napi(ts_arg_type = "Month[]")] months: Array,
230
+ ) -> napi::Result<&Self> {
231
+ let mut vec: Vec<Month> = Vec::new();
232
+
233
+ for i in 0..months.len() {
234
+ let month: JsMonth = months.get(i).unwrap().unwrap();
235
+
236
+ vec.push(map_js_month(month));
237
+ }
238
+
239
+ Ok(self)
240
+ }
241
+
242
+ #[napi]
243
+ pub fn set_by_weekno(&mut self, week_numbers: Vec<i8>) -> napi::Result<&Self> {
244
+ replace_with_or_abort(&mut self.rrule, |self_| self_.by_week_no(week_numbers));
245
+
246
+ Ok(self)
247
+ }
248
+
249
+ #[napi]
250
+ pub fn set_by_yearday(&mut self, days: Vec<i16>) -> napi::Result<&Self> {
251
+ replace_with_or_abort(&mut self.rrule, |self_| self_.by_year_day(days));
252
+
253
+ Ok(self)
254
+ }
255
+
256
+ #[napi]
257
+ pub fn get_weekstart(&mut self, day: JsWeekday) -> napi::Result<&Self> {
258
+ replace_with_or_abort(&mut self.rrule, |self_| {
259
+ self_.week_start(map_js_weekday(day))
260
+ });
261
+
262
+ Ok(self)
263
+ }
264
+
265
+ #[napi]
266
+ pub fn set_until(&mut self, timestamp: i64) -> napi::Result<&Self> {
267
+ replace_with_or_abort(&mut self.rrule, |self_| {
268
+ self_.until(Tz::UTC.timestamp_millis_opt(timestamp).unwrap())
269
+ });
270
+
271
+ Ok(self)
272
+ }
273
+
274
+ pub fn validate(&self, dt_start: DateTime<Tz>) -> RRule {
275
+ self.rrule.clone().validate(dt_start).unwrap()
276
+ }
277
+ }
278
+
279
+ #[napi(js_name = "RRuleSet")]
280
+ pub struct JsRRuleSet {
281
+ tz: Tz,
282
+ rrule_set: RRuleSet,
283
+ }
284
+
285
+ #[napi]
286
+ impl JsRRuleSet {
287
+ #[napi(constructor)]
288
+ pub fn new(dtstart: i64, tzid: String) -> Self {
289
+ let tz = map_js_tz(&tzid);
290
+ let date = timestamp_to_date_with_tz(dtstart, &tz);
291
+ let rrule_set = RRuleSet::new(date);
292
+
293
+ JsRRuleSet { rrule_set, tz }
294
+ }
295
+
296
+ #[napi]
297
+ pub fn to_string(&self) -> napi::Result<String> {
298
+ Ok(self.rrule_set.to_string())
299
+ }
300
+
301
+ #[napi]
302
+ pub fn rrule(&mut self, js_rrule: &JsRRule) -> napi::Result<&Self> {
303
+ let dt_start = self.rrule_set.get_dt_start().clone();
304
+ let rrule = js_rrule.validate(dt_start);
305
+
306
+ replace_with_or_abort(&mut self.rrule_set, |self_| self_.rrule(rrule));
307
+
308
+ Ok(self)
309
+ }
310
+
311
+ #[napi]
312
+ pub fn exrule(&mut self, js_rrule: &JsRRule) -> napi::Result<&Self> {
313
+ let rrule = js_rrule.validate(*self.rrule_set.get_dt_start());
314
+
315
+ replace_with_or_abort(&mut self.rrule_set, |self_| self_.exrule(rrule));
316
+
317
+ Ok(self)
318
+ }
319
+
320
+ #[napi]
321
+ pub fn after(&mut self, timestamp: i64) -> napi::Result<&Self> {
322
+ replace_with_or_abort(&mut self.rrule_set, |self_| {
323
+ self_.after(timestamp_to_date_with_tz(timestamp, &self.tz))
324
+ });
325
+
326
+ Ok(self)
327
+ }
328
+
329
+ #[napi]
330
+ pub fn before(&mut self, timestamp: i64) -> napi::Result<&Self> {
331
+ replace_with_or_abort(&mut self.rrule_set, |self_| {
332
+ self_.before(timestamp_to_date_with_tz(timestamp, &self.tz))
333
+ });
334
+
335
+ Ok(self)
336
+ }
337
+
338
+ #[napi]
339
+ pub fn exdate(&mut self, timestamp: i64) -> napi::Result<&Self> {
340
+ replace_with_or_abort(&mut self.rrule_set, |self_| {
341
+ self_.exdate(timestamp_to_date_with_tz(timestamp, &self.tz))
342
+ });
343
+
344
+ Ok(self)
345
+ }
346
+
347
+ #[napi]
348
+ pub fn get_dtstart(&self) -> napi::Result<i64> {
349
+ Ok(self.rrule_set.get_dt_start().timestamp_millis())
350
+ }
351
+
352
+ #[napi]
353
+ pub fn get_tzid(&self) -> napi::Result<String> {
354
+ Ok(String::from(self.tz.name()))
355
+ }
356
+
357
+ /*#[napi(ts_return_type="RRule[]")]
358
+ pub fn get_rrules(&self, env: Env) -> napi::Result<Array> {
359
+ let mut arr = env.create_array(0).unwrap();
360
+ let rrules = self.rrule_set.get_rrule();
361
+
362
+ for rrule in rrules.iter() {
363
+ arr.insert(JsRRule {
364
+ freq: map_rust_frequency(rrule.get_freq())
365
+ }).unwrap();
366
+ }
367
+
368
+ Ok(arr)
369
+ }*/
370
+
371
+ #[napi(ts_return_type = "number[]")]
372
+ pub fn all(&self, env: Env, limit: Option<u32>) -> napi::Result<Array> {
373
+ let mut arr = env.create_array(0).unwrap();
374
+ let iter = self.rrule_set.into_iter();
375
+ let mut left = match limit {
376
+ Some(number) => number,
377
+ None => 0,
378
+ };
379
+
380
+ for date in iter {
381
+ if left > 0 {
382
+ left = left - 1;
383
+ } else if limit.is_some() {
384
+ break;
385
+ }
386
+
387
+ arr.insert(date.timestamp_millis()).unwrap();
388
+ }
389
+
390
+ Ok(arr)
391
+ }
392
+ }
393
+
394
+ fn map_rust_frequency(freq: Frequency) -> JsFrequency {
395
+ match freq {
396
+ Frequency::Daily => JsFrequency::Daily,
397
+ Frequency::Hourly => JsFrequency::Hourly,
398
+ Frequency::Minutely => JsFrequency::Minutely,
399
+ Frequency::Monthly => JsFrequency::Monthly,
400
+ Frequency::Secondly => JsFrequency::Secondly,
401
+ Frequency::Weekly => JsFrequency::Weekly,
402
+ Frequency::Yearly => JsFrequency::Yearly,
403
+ }
404
+ }
405
+
406
+ fn map_js_frequency(freq: JsFrequency) -> Frequency {
407
+ match freq {
408
+ JsFrequency::Daily => Frequency::Daily,
409
+ JsFrequency::Hourly => Frequency::Hourly,
410
+ JsFrequency::Minutely => Frequency::Minutely,
411
+ JsFrequency::Monthly => Frequency::Monthly,
412
+ JsFrequency::Secondly => Frequency::Secondly,
413
+ JsFrequency::Weekly => Frequency::Weekly,
414
+ JsFrequency::Yearly => Frequency::Yearly,
415
+ }
416
+ }
417
+
418
+ /*fn map_rust_rrule (rrule: RRule) -> JsRRule {
419
+ JsRRule {
420
+ freq: map_rust_frequency(rrule.get_freq()),
421
+ interval: Some(rrule.get_interval()),
422
+ count: rrule.get_count(),
423
+ by_weekday:
424
+ }
425
+ }*/
426
+
427
+ fn map_js_weekday(weekday: JsWeekday) -> Weekday {
428
+ match weekday {
429
+ JsWeekday::Monday => Weekday::Mon,
430
+ JsWeekday::Tuesday => Weekday::Tue,
431
+ JsWeekday::Wednesday => Weekday::Wed,
432
+ JsWeekday::Thursday => Weekday::Thu,
433
+ JsWeekday::Friday => Weekday::Fri,
434
+ JsWeekday::Saturday => Weekday::Sat,
435
+ JsWeekday::Sunday => Weekday::Sun,
436
+ }
437
+ }
438
+
439
+ fn map_rust_weekday(weekday: Weekday) -> JsWeekday {
440
+ match weekday {
441
+ Weekday::Mon => JsWeekday::Monday,
442
+ Weekday::Tue => JsWeekday::Tuesday,
443
+ Weekday::Wed => JsWeekday::Wednesday,
444
+ Weekday::Thu => JsWeekday::Thursday,
445
+ Weekday::Fri => JsWeekday::Friday,
446
+ Weekday::Sat => JsWeekday::Saturday,
447
+ Weekday::Sun => JsWeekday::Sunday,
448
+ }
449
+ }
450
+
451
+ fn map_js_month(month: JsMonth) -> Month {
452
+ match month {
453
+ JsMonth::January => Month::January,
454
+ JsMonth::February => Month::February,
455
+ JsMonth::March => Month::March,
456
+ JsMonth::April => Month::April,
457
+ JsMonth::May => Month::May,
458
+ JsMonth::June => Month::June,
459
+ JsMonth::July => Month::July,
460
+ JsMonth::August => Month::August,
461
+ JsMonth::September => Month::September,
462
+ JsMonth::October => Month::October,
463
+ JsMonth::November => Month::November,
464
+ JsMonth::December => Month::December,
465
+ }
466
+ }
467
+
468
+ fn map_rust_month(month: &u8) -> JsMonth {
469
+ match month {
470
+ 0 => JsMonth::January,
471
+ 1 => JsMonth::February,
472
+ 2 => JsMonth::March,
473
+ 3 => JsMonth::April,
474
+ 4 => JsMonth::May,
475
+ 5 => JsMonth::June,
476
+ 6 => JsMonth::July,
477
+ 7 => JsMonth::August,
478
+ 8 => JsMonth::September,
479
+ 9 => JsMonth::October,
480
+ 10 => JsMonth::November,
481
+ 11 => JsMonth::December,
482
+ _ => panic!("Unkown month index: {}", month),
483
+ }
484
+ }
485
+
486
+ fn map_js_tz(tz: &str) -> Tz {
487
+ let chrono_tz = tz.parse().unwrap();
488
+ Tz::Tz(chrono_tz)
489
+ }
490
+
491
+ fn timestamp_to_date_with_tz(timestamp: i64, tz: &Tz) -> DateTime<Tz> {
492
+ Tz::UTC
493
+ .timestamp_millis_opt(timestamp)
494
+ .unwrap()
495
+ .with_timezone(tz)
496
+ }