functionalscript 0.0.409 → 0.0.412
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/Cargo.lock +14 -0
- package/Cargo.toml +5 -0
- package/com/rust/module.f.cjs +10 -0
- package/com/rust/nanocom/Cargo.lock +7 -0
- package/com/rust/nanocom/Cargo.toml +10 -0
- package/com/rust/nanocom/README.md +3 -0
- package/com/rust/nanocom/rstest/Cargo.lock +14 -0
- package/com/rust/nanocom/rstest/Cargo.toml +9 -0
- package/com/rust/nanocom/rstest/src/lib.rs +109 -0
- package/com/rust/nanocom/src/class.rs +14 -0
- package/com/rust/nanocom/src/cobject.rs +76 -0
- package/com/rust/nanocom/src/guid.rs +1 -0
- package/com/rust/nanocom/src/hresult.rs +7 -0
- package/com/rust/nanocom/src/interface.rs +5 -0
- package/com/rust/nanocom/src/iunknown.rs +7 -0
- package/com/rust/nanocom/src/iunknownvmt.rs +13 -0
- package/com/rust/nanocom/src/lib.rs +15 -0
- package/com/rust/nanocom/src/object.rs +34 -0
- package/com/rust/nanocom/src/ref.rs +53 -0
- package/com/rust/nanocom/src/vmt.rs +7 -0
- package/com/rust/test.f.cjs +11 -0
- package/doc/fa.md +8 -2
- package/doc/vm.md +0 -21
- package/html/module.f.cjs +1 -3
- package/json/module.f.cjs +9 -7
- package/package.json +1 -1
- package/test.f.cjs +1 -0
package/Cargo.lock
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 3
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "nanocom"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
|
|
9
|
+
[[package]]
|
|
10
|
+
name = "rstest"
|
|
11
|
+
version = "0.1.0"
|
|
12
|
+
dependencies = [
|
|
13
|
+
"nanocom",
|
|
14
|
+
]
|
package/Cargo.toml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const types = require('../types/module.f.cjs')
|
|
2
|
+
const text = require('../../text/module.f.cjs')
|
|
3
|
+
|
|
4
|
+
/** @type {(name: string) => (library: types.Library) => text.Block} */
|
|
5
|
+
const rust = name => library => []
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
/** @readonly */
|
|
9
|
+
rust,
|
|
10
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#[cfg(test)]
|
|
2
|
+
mod test {
|
|
3
|
+
// interface definition:
|
|
4
|
+
|
|
5
|
+
mod library {
|
|
6
|
+
use nanocom::{CObject, Class, Interface, Object, Ref, GUID};
|
|
7
|
+
|
|
8
|
+
#[allow(non_snake_case)]
|
|
9
|
+
#[repr(C)]
|
|
10
|
+
pub struct IMy {
|
|
11
|
+
pub A: unsafe extern "stdcall" fn(this: &Object<IMy>) -> Ref<IMy>,
|
|
12
|
+
pub B: unsafe extern "stdcall" fn(this: &Object<IMy>) -> u32,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
impl Interface for IMy {
|
|
16
|
+
const GUID: GUID = 0x01234567_89AB_CDEF_0123_456789ABCDEF;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#[allow(non_snake_case)]
|
|
20
|
+
pub trait IMyEx {
|
|
21
|
+
fn A(&self) -> Ref<IMy>;
|
|
22
|
+
fn B(&self) -> u32;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
#[allow(non_snake_case)]
|
|
26
|
+
impl IMyEx for Object<IMy> {
|
|
27
|
+
fn A(&self) -> Ref<IMy> {
|
|
28
|
+
unsafe { (self.interface().A)(self) }
|
|
29
|
+
}
|
|
30
|
+
fn B(&self) -> u32 {
|
|
31
|
+
unsafe { (self.interface().B)(self) }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
pub trait IMyVmt: Class<Interface = IMy>
|
|
36
|
+
where
|
|
37
|
+
CObject<Self>: IMyEx,
|
|
38
|
+
{
|
|
39
|
+
const INTERFACE: IMy = IMy {
|
|
40
|
+
A: Self::A,
|
|
41
|
+
B: Self::B,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
impl<T: Class<Interface = IMy>> IMyVmt for T where CObject<T>: IMyEx {}
|
|
46
|
+
|
|
47
|
+
#[allow(non_snake_case)]
|
|
48
|
+
trait IMyVmtFn: Class<Interface = IMy>
|
|
49
|
+
where
|
|
50
|
+
CObject<Self>: IMyEx,
|
|
51
|
+
{
|
|
52
|
+
extern "stdcall" fn A(this: &Object<IMy>) -> Ref<IMy> {
|
|
53
|
+
unsafe { Self::to_cobject(this) }.A()
|
|
54
|
+
}
|
|
55
|
+
extern "stdcall" fn B(this: &Object<IMy>) -> u32 {
|
|
56
|
+
unsafe { Self::to_cobject(this) }.B()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
impl<T: Class<Interface = IMy>> IMyVmtFn for T where CObject<T>: IMyEx {}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// interface implementation
|
|
64
|
+
mod x {
|
|
65
|
+
use nanocom::{CObject, Class, Ref, Vmt};
|
|
66
|
+
|
|
67
|
+
use super::library::{IMy, IMyEx, IMyVmt};
|
|
68
|
+
|
|
69
|
+
pub struct X(pub u32);
|
|
70
|
+
|
|
71
|
+
impl Class for X {
|
|
72
|
+
type Interface = IMy;
|
|
73
|
+
fn static_vmt() -> &'static Vmt<Self::Interface> {
|
|
74
|
+
static V: Vmt<IMy> = Vmt {
|
|
75
|
+
iunknown: X::IUNKNOWN,
|
|
76
|
+
interface: X::INTERFACE,
|
|
77
|
+
};
|
|
78
|
+
&V
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#[allow(non_snake_case)]
|
|
83
|
+
impl IMyEx for CObject<X> {
|
|
84
|
+
fn A(&self) -> Ref<IMy> {
|
|
85
|
+
self.to_interface().into()
|
|
86
|
+
}
|
|
87
|
+
fn B(&self) -> u32 {
|
|
88
|
+
self.value.0
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
mod using {
|
|
94
|
+
use nanocom::Class;
|
|
95
|
+
|
|
96
|
+
use crate::test::{library::IMyEx, x::X};
|
|
97
|
+
|
|
98
|
+
#[test]
|
|
99
|
+
fn test() {
|
|
100
|
+
let a = X(42).cobject_new();
|
|
101
|
+
let a1 = a.A();
|
|
102
|
+
assert_eq!(a, a1);
|
|
103
|
+
assert_eq!(a.B(), 42);
|
|
104
|
+
let b = X(43).cobject_new();
|
|
105
|
+
assert_ne!(a, b);
|
|
106
|
+
assert_eq!(b.B(), 43);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
use crate::{iunknownvmt::IUnknownVmt, CObject, Interface, Object, Ref, Vmt};
|
|
2
|
+
|
|
3
|
+
pub trait Class: Sized {
|
|
4
|
+
type Interface: Interface;
|
|
5
|
+
fn static_vmt() -> &'static Vmt<Self::Interface>;
|
|
6
|
+
const IUNKNOWN: IUnknownVmt<Self::Interface> = CObject::<Self>::IUNKNOWN;
|
|
7
|
+
fn cobject_new(self) -> Ref<Self::Interface> {
|
|
8
|
+
CObject::new(self)
|
|
9
|
+
}
|
|
10
|
+
unsafe fn to_cobject(this: &Object<Self::Interface>) -> &CObject<Self> {
|
|
11
|
+
let p = this as *const Object<Self::Interface> as *const CObject<Self>;
|
|
12
|
+
&*p
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
use std::{
|
|
2
|
+
ptr::null,
|
|
3
|
+
sync::atomic::{AtomicU32, Ordering},
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
use crate::{
|
|
7
|
+
hresult::HRESULT, iunknown::IUnknown, iunknownvmt::IUnknownVmt, Class, Interface, Object, Ref,
|
|
8
|
+
Vmt,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
#[repr(C)]
|
|
12
|
+
pub struct CObject<T: Class> {
|
|
13
|
+
vmt: &'static Vmt<T::Interface>,
|
|
14
|
+
counter: AtomicU32,
|
|
15
|
+
pub value: T,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
impl<T: Class> CObject<T> {
|
|
19
|
+
pub fn new(value: T) -> Ref<T::Interface> {
|
|
20
|
+
let c = CObject {
|
|
21
|
+
vmt: T::static_vmt(),
|
|
22
|
+
counter: Default::default(),
|
|
23
|
+
value,
|
|
24
|
+
};
|
|
25
|
+
let p = Box::into_raw(Box::new(c));
|
|
26
|
+
unsafe { &*p }.to_interface().into()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
pub fn to_interface(&self) -> &Object<T::Interface> {
|
|
30
|
+
let p = self as *const Self as *const Object<T::Interface>;
|
|
31
|
+
unsafe { &*p }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
pub const IUNKNOWN: IUnknownVmt<T::Interface> = IUnknownVmt {
|
|
35
|
+
QueryInterface: Self::QueryInterface,
|
|
36
|
+
AddRef: Self::AddRef,
|
|
37
|
+
Release: Self::Release,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
#[allow(non_snake_case)]
|
|
41
|
+
extern "stdcall" fn QueryInterface(
|
|
42
|
+
this: &Object<T::Interface>,
|
|
43
|
+
riid: &u128,
|
|
44
|
+
ppv_object: &mut *const Object<IUnknown>,
|
|
45
|
+
) -> HRESULT {
|
|
46
|
+
let (p, r) = if *riid == IUnknown::GUID || *riid == T::Interface::GUID {
|
|
47
|
+
Self::AddRef(this);
|
|
48
|
+
(this.to_iunknown() as *const Object<IUnknown>, HRESULT::S_OK)
|
|
49
|
+
} else {
|
|
50
|
+
(null(), HRESULT::E_NOINTERFACE)
|
|
51
|
+
};
|
|
52
|
+
*ppv_object = p;
|
|
53
|
+
r
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#[allow(non_snake_case)]
|
|
57
|
+
extern "stdcall" fn AddRef(this: &Object<T::Interface>) -> u32 {
|
|
58
|
+
unsafe { T::to_cobject(this) }
|
|
59
|
+
.counter
|
|
60
|
+
.fetch_add(1, Ordering::Relaxed)
|
|
61
|
+
+ 1
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
#[allow(non_snake_case)]
|
|
65
|
+
extern "stdcall" fn Release(this: &Object<T::Interface>) -> u32 {
|
|
66
|
+
let t = unsafe { T::to_cobject(this) };
|
|
67
|
+
match t.counter.fetch_sub(1, Ordering::Relaxed) {
|
|
68
|
+
1 => {
|
|
69
|
+
let m = t as *const CObject<T> as *mut CObject<T>;
|
|
70
|
+
unsafe { Box::from_raw(m) };
|
|
71
|
+
0
|
|
72
|
+
}
|
|
73
|
+
x => x - 1,
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pub type GUID = u128;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
use crate::{hresult::HRESULT, iunknown::IUnknown, Object, GUID};
|
|
2
|
+
|
|
3
|
+
#[allow(non_snake_case)]
|
|
4
|
+
#[repr(C)]
|
|
5
|
+
pub struct IUnknownVmt<I: 'static> {
|
|
6
|
+
pub QueryInterface: unsafe extern "stdcall" fn(
|
|
7
|
+
this: &Object<I>,
|
|
8
|
+
riid: &GUID,
|
|
9
|
+
ppv_object: &mut *const Object<IUnknown>,
|
|
10
|
+
) -> HRESULT,
|
|
11
|
+
pub AddRef: unsafe extern "stdcall" fn(this: &Object<I>) -> u32,
|
|
12
|
+
pub Release: unsafe extern "stdcall" fn(this: &Object<I>) -> u32,
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
mod class;
|
|
2
|
+
mod cobject;
|
|
3
|
+
mod guid;
|
|
4
|
+
mod hresult;
|
|
5
|
+
mod interface;
|
|
6
|
+
mod iunknown;
|
|
7
|
+
mod iunknownvmt;
|
|
8
|
+
mod object;
|
|
9
|
+
mod r#ref;
|
|
10
|
+
mod vmt;
|
|
11
|
+
|
|
12
|
+
pub use crate::{
|
|
13
|
+
class::Class, cobject::CObject, guid::GUID, interface::Interface, object::Object, r#ref::Ref,
|
|
14
|
+
vmt::Vmt,
|
|
15
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
use crate::{
|
|
2
|
+
hresult::HRESULT, interface::Interface, iunknown::IUnknown, iunknownvmt::IUnknownVmt,
|
|
3
|
+
r#ref::Ref, vmt::Vmt,
|
|
4
|
+
};
|
|
5
|
+
use std::ptr::null;
|
|
6
|
+
|
|
7
|
+
#[repr(C)]
|
|
8
|
+
pub struct Object<I: 'static>(&'static Vmt<I>);
|
|
9
|
+
|
|
10
|
+
impl<I> Object<I> {
|
|
11
|
+
pub unsafe fn iunknown(&self) -> &'static IUnknownVmt<I> {
|
|
12
|
+
&self.0.iunknown
|
|
13
|
+
}
|
|
14
|
+
pub unsafe fn interface(&self) -> &'static I {
|
|
15
|
+
&self.0.interface
|
|
16
|
+
}
|
|
17
|
+
pub fn to_iunknown(&self) -> &Object<IUnknown> {
|
|
18
|
+
let p = self as *const Object<I> as *const Object<IUnknown>;
|
|
19
|
+
unsafe { &*p }
|
|
20
|
+
}
|
|
21
|
+
pub fn query_interface<J: Interface>(&self) -> Result<Ref<J>, HRESULT> {
|
|
22
|
+
let mut p = null();
|
|
23
|
+
match unsafe { (self.0.iunknown.QueryInterface)(self, &J::GUID, &mut p) } {
|
|
24
|
+
HRESULT::S_OK => {
|
|
25
|
+
let r = p as *const Object<J>;
|
|
26
|
+
Ok(unsafe { Ref::from_raw(r) })
|
|
27
|
+
}
|
|
28
|
+
e => Err(e),
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
pub fn query_iunknown(&self) -> Ref<IUnknown> {
|
|
32
|
+
self.query_interface().unwrap()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
use std::{cmp::Eq, fmt::Debug, ops::Deref};
|
|
2
|
+
|
|
3
|
+
use crate::object::Object;
|
|
4
|
+
|
|
5
|
+
#[repr(transparent)]
|
|
6
|
+
pub struct Ref<I: 'static>(*const Object<I>);
|
|
7
|
+
|
|
8
|
+
impl<I: 'static> Ref<I> {
|
|
9
|
+
pub unsafe fn from_raw(p: *const Object<I>) -> Ref<I> {
|
|
10
|
+
Ref(p)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
impl<I> Deref for Ref<I> {
|
|
15
|
+
type Target = Object<I>;
|
|
16
|
+
fn deref(&self) -> &Self::Target {
|
|
17
|
+
let p = self.0;
|
|
18
|
+
unsafe { &*p }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
impl<I> Drop for Ref<I> {
|
|
23
|
+
fn drop(&mut self) {
|
|
24
|
+
unsafe { (self.iunknown().Release)(self) };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
impl<I> Clone for Ref<I> {
|
|
29
|
+
fn clone(&self) -> Self {
|
|
30
|
+
self.deref().into()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
impl<I> From<&Object<I>> for Ref<I> {
|
|
35
|
+
fn from(this: &Object<I>) -> Self {
|
|
36
|
+
unsafe { (this.iunknown().AddRef)(this) };
|
|
37
|
+
Self(this)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
impl<I> Debug for Ref<I> {
|
|
42
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
43
|
+
f.debug_tuple("Ref").field(&self.0).finish()
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
impl<I> PartialEq for Ref<I> {
|
|
48
|
+
fn eq(&self, other: &Self) -> bool {
|
|
49
|
+
self.0 == other.0
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
impl<I> Eq for Ref<I> {}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const { rust } = require('./module.f.cjs')
|
|
2
|
+
const { flat } = require('../../text/module.f.cjs')
|
|
3
|
+
const { join } = require('../../types/string/module.f.cjs')
|
|
4
|
+
const library = require('../types/test.f.cjs')
|
|
5
|
+
|
|
6
|
+
{
|
|
7
|
+
const r = join('\n')(flat(' ')(rust('My')(library)))
|
|
8
|
+
if (r !== '') { throw r }
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports = {}
|
package/doc/fa.md
CHANGED
|
@@ -129,11 +129,17 @@ const i5 = [
|
|
|
129
129
|
id, id, id, _,
|
|
130
130
|
_, _, _, id]
|
|
131
131
|
|
|
132
|
-
const
|
|
132
|
+
const i7 = [
|
|
133
133
|
id, id, id, id,
|
|
134
134
|
id, id, id, id,
|
|
135
135
|
id, id, id, _,
|
|
136
136
|
_, _, _, _]
|
|
137
|
+
|
|
138
|
+
const id = [
|
|
139
|
+
_, _, i2, i3,
|
|
140
|
+
i4, i5, i4, i7,
|
|
141
|
+
_, _, _, _,
|
|
142
|
+
_, _, _, _]
|
|
137
143
|
```
|
|
138
144
|
|
|
139
145
|
```js
|
|
@@ -155,4 +161,4 @@ const i = [
|
|
|
155
161
|
// 5
|
|
156
162
|
1111_1111_1110_0000,
|
|
157
163
|
]
|
|
158
|
-
```
|
|
164
|
+
```
|
package/doc/vm.md
CHANGED
|
@@ -68,27 +68,6 @@ Least used letters in English: Q, J, Z and X.
|
|
|
68
68
|
|
|
69
69
|
Starts with `0xFFF`
|
|
70
70
|
|
|
71
|
-
- `50`:
|
|
72
|
-
- `48`: stringUInt48 (0..281_474_976_710_655)
|
|
73
|
-
- `48`: 8 x 6 string
|
|
74
|
-
- `48`: `42` 7 x 6 string
|
|
75
|
-
- `48`: 6 x 8 string
|
|
76
|
-
- `50`:
|
|
77
|
-
- `48`: `45` 5 x 9 string
|
|
78
|
-
- `48`: 4 x 12 string
|
|
79
|
-
- `48`: 3 x 16 string
|
|
80
|
-
- `48`: `32`: 2 x 16 string
|
|
81
|
-
- `50`:
|
|
82
|
-
- `48`: `16`: 1 x 16 string
|
|
83
|
-
- `48`: `0`: ""
|
|
84
|
-
- `48`: false
|
|
85
|
-
- `48`: true
|
|
86
|
-
- `50`:
|
|
87
|
-
- `48`: ptr
|
|
88
|
-
- `48`: bigInt48 (140_737_488_355_328..140_737_488_355_327)
|
|
89
|
-
- `48`: undefined
|
|
90
|
-
- `48`: `-inf`
|
|
91
|
-
|
|
92
71
|
| | | |type |
|
|
93
72
|
|------|--|-------------|-----------|
|
|
94
73
|
|`1111`|48|stringUInt48 |`string` |
|
package/html/module.f.cjs
CHANGED
|
@@ -3,9 +3,7 @@ const { map, flatMap, flat, concat: listConcat } = list
|
|
|
3
3
|
const { concat: stringConcat } = require('../types/string/module.f.cjs')
|
|
4
4
|
const object = require('../types/object/module.f.cjs')
|
|
5
5
|
const { compose } = require('../types/function/module.f.cjs')
|
|
6
|
-
const
|
|
7
|
-
const { stringToList } = encoding
|
|
8
|
-
|
|
6
|
+
const { stringToList } = require('../text/utf16/module.f.cjs')
|
|
9
7
|
const { fromCharCode } = String
|
|
10
8
|
const { entries } = Object
|
|
11
9
|
|
package/json/module.f.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const list = require('../types/list/module.f.cjs')
|
|
2
|
-
const { next, flat, reduce
|
|
2
|
+
const { next, flat, reduce, map, empty } = list
|
|
3
3
|
const { concat } = require('../types/string/module.f.cjs')
|
|
4
4
|
const object = require('../types/object/module.f.cjs')
|
|
5
5
|
const { at } = object
|
|
6
6
|
const operator = require('../types/function/operator/module.f.cjs')
|
|
7
|
-
const { compose } = require('../types/function/module.f.cjs')
|
|
7
|
+
const { compose, fn } = require('../types/function/module.f.cjs')
|
|
8
8
|
const { entries } = Object
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -54,7 +54,7 @@ const comma = [',']
|
|
|
54
54
|
const joinOp = b => prior => flat([prior, comma, b])
|
|
55
55
|
|
|
56
56
|
/** @type {(input: list.List<list.List<string>>) => list.List<string>} */
|
|
57
|
-
const join =
|
|
57
|
+
const join = reduce(joinOp)(empty)
|
|
58
58
|
|
|
59
59
|
/** @type {(open: string) => (close: string) => (input: list.List<list.List<string>>) => list.List<string>} */
|
|
60
60
|
const wrap = open => close => {
|
|
@@ -83,7 +83,11 @@ const serialize = sort => {
|
|
|
83
83
|
])
|
|
84
84
|
const mapPropertySerialize = map(propertySerialize)
|
|
85
85
|
/** @type {(object: Object) => list.List<string>} */
|
|
86
|
-
const objectSerialize =
|
|
86
|
+
const objectSerialize = fn(entries)
|
|
87
|
+
.then(sort)
|
|
88
|
+
.then(mapPropertySerialize)
|
|
89
|
+
.then(objectWrap)
|
|
90
|
+
.result
|
|
87
91
|
/** @type {(value: Unknown) => list.List<string>} */
|
|
88
92
|
const f = value => {
|
|
89
93
|
switch (typeof value) {
|
|
@@ -97,9 +101,7 @@ const serialize = sort => {
|
|
|
97
101
|
}
|
|
98
102
|
}
|
|
99
103
|
}
|
|
100
|
-
const
|
|
101
|
-
/** @type {(input: Array) => list.List<string>} */
|
|
102
|
-
const arraySerialize = compose(mapF)(arrayWrap)
|
|
104
|
+
const arraySerialize = compose(map(f))(arrayWrap)
|
|
103
105
|
return f
|
|
104
106
|
}
|
|
105
107
|
|
package/package.json
CHANGED
package/test.f.cjs
CHANGED