functionalscript 0.0.463 → 0.0.465

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.
@@ -19,10 +19,13 @@ jobs:
19
19
  runs-on: ${{ matrix.os }}
20
20
 
21
21
  steps:
22
- - uses: actions/checkout@v2
22
+ - uses: actions/checkout@v3
23
23
  - name: Use Node.js 19
24
24
  uses: actions/setup-node@v2
25
25
  with:
26
26
  node-version: 19
27
+ - uses: actions/setup-dotnet@v3
28
+ with:
29
+ dotnet-version: 7
27
30
  - run: npm ci
28
31
  - run: npm run comtest
package/Cargo.lock CHANGED
@@ -4,7 +4,7 @@ version = 3
4
4
 
5
5
  [[package]]
6
6
  name = "nanocom"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
 
9
9
  [[package]]
10
10
  name = "testrust"
package/com/cpp/com.hpp CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  #include <cstdint>
4
4
  #include <cstddef>
5
+ #include <atomic>
6
+ #include <iostream>
5
7
 
6
8
  #if defined(__aarch64__) || defined(__amd64__)
7
9
  #define COM_STDCALL
@@ -13,15 +15,62 @@
13
15
 
14
16
  namespace com
15
17
  {
18
+ constexpr uint64_t byteswap(uint64_t v)
19
+ {
20
+ v = v >> 8 & 0x00FF00FF00FF00FF |
21
+ v << 8 & 0xFF00FF00FF00FF00;
22
+ v = v >> 16 & 0x0000FFFF0000FFFF |
23
+ v << 16 & 0xFFFF0000FFFF0000;
24
+ return v >> 32 | v << 32;
25
+ }
26
+
16
27
  class GUID
17
28
  {
18
29
  public:
19
- uint64_t hi;
20
30
  uint64_t lo;
31
+ uint64_t hi;
32
+ constexpr GUID(uint64_t const lo, uint64_t const hi) noexcept
33
+ : lo(lo << 48 & 0xFFFF'0000'0000'0000 |
34
+ lo << 16 & 0x0000'FFFF'0000'0000 |
35
+ lo >> 32),
36
+ hi(byteswap(hi))
37
+ {
38
+ }
39
+ constexpr bool operator==(GUID const b) const noexcept
40
+ {
41
+ return lo == b.lo && hi == b.hi;
42
+ }
43
+ constexpr bool operator!=(GUID const b) const noexcept
44
+ {
45
+ return !(*this == b);
46
+ }
21
47
  };
22
48
 
49
+ inline void guid_part(std::ostream &os, uint64_t const v)
50
+ {
51
+ for (int i = 64; i > 0;)
52
+ {
53
+ i -= 4;
54
+ char const c = (v >> i) & 0xF;
55
+ char const x = c < 10 ? c + '0' : c + ('A' - 10);
56
+ os << x;
57
+ }
58
+ }
59
+
60
+ inline std::ostream &operator<<(std::ostream &os, GUID const &self)
61
+ {
62
+ guid_part(os, self.lo);
63
+ guid_part(os, self.hi);
64
+ return os;
65
+ }
66
+
23
67
  typedef uint32_t HRESULT;
68
+
69
+ static HRESULT const E_NOINTERFACE = 0x80004002;
70
+ static HRESULT const S_OK = 0;
71
+
24
72
  typedef uint32_t ULONG;
73
+
25
74
  typedef int32_t BOOL;
26
75
 
27
76
  class IUnknown
@@ -36,7 +85,7 @@ namespace com
36
85
  class ref
37
86
  {
38
87
  public:
39
- explicit ref(I &other) noexcept : p(other.p)
88
+ explicit ref(I &other) noexcept : p(other)
40
89
  {
41
90
  p.AddRef();
42
91
  }
@@ -47,7 +96,52 @@ namespace com
47
96
  {
48
97
  p.Release();
49
98
  }
99
+
50
100
  private:
51
101
  I &p;
52
102
  };
103
+
104
+ constexpr static GUID const iunknown_guid =
105
+ GUID(0x00000000'0000'0000, 0xC000'000000000046);
106
+
107
+ template <class I>
108
+ constexpr GUID interface_guid();
109
+
110
+ template <class T>
111
+ class implementation : public T
112
+ {
113
+ private:
114
+ HRESULT COM_STDCALL QueryInterface(GUID const &riid, IUnknown **const ppvObject) noexcept override
115
+ {
116
+ if (riid != iunknown_guid && riid != T::guid)
117
+ {
118
+ return E_NOINTERFACE;
119
+ }
120
+ add_ref();
121
+ *ppvObject = this;
122
+ return S_OK;
123
+ }
124
+
125
+ ULONG add_ref() noexcept
126
+ {
127
+ return counter.fetch_add(1);
128
+ }
129
+
130
+ ULONG COM_STDCALL AddRef() noexcept override
131
+ {
132
+ return add_ref() + 1;
133
+ }
134
+
135
+ ULONG COM_STDCALL Release() noexcept override
136
+ {
137
+ auto const c = counter.fetch_sub(1) - 1;
138
+ if (c == 0)
139
+ {
140
+ delete this;
141
+ }
142
+ return c;
143
+ }
144
+
145
+ std::atomic<ULONG> counter;
146
+ };
53
147
  }
@@ -5,7 +5,7 @@ const obj = require('../../types/object/module.f.cjs')
5
5
  const list = require('../../types/list/module.f.cjs')
6
6
  const { map, flatMap, flat } = list
7
7
  const { join } = require('../../types/string/module.f.cjs')
8
- const { entries } = Object
8
+ const { entries } = Object
9
9
 
10
10
  /** @type {(name: string) => (body: text.Block) => text.Block} */
11
11
  const struct = name => body => [`struct ${name}`, '{', body, '};']
@@ -70,12 +70,20 @@ const cpp = name => lib => {
70
70
  const mapMethod = map(method)
71
71
 
72
72
  /** @type {(i: types.Interface) => text.Block} */
73
- const defInterface = i => mapMethod(entries(i.interface))
73
+ const defInterface = ({ guid, interface: i }) => {
74
+ const g = guid.replaceAll('-', '');
75
+ const lo = g.substring(0, 16);
76
+ const hi = g.substring(16);
77
+ return flat([
78
+ [`constexpr static ::com::GUID const guid = ::com::GUID(0x${lo}, 0x${hi});`],
79
+ mapMethod(entries(i))
80
+ ])
81
+ }
74
82
 
75
83
  /** @type {(kv: obj.Entry<types.Definition>) => text.Block} */
76
84
  const def = ([name, d]) => d.interface === undefined
77
85
  ? struct(name)(defStruct(d))
78
- : struct(`${name}: ::com::IUnknown`)(defInterface(d))
86
+ : struct(`${name} : ::com::IUnknown`)(defInterface(d))
79
87
 
80
88
  /** @type {(kv: obj.Entry<types.Definition>) => text.Block} */
81
89
  const forward = ([name]) => [`struct ${name};`]
@@ -19,8 +19,9 @@ const f = () =>
19
19
  ' {\n' +
20
20
  ' ::com::ref<IMy> M;\n' +
21
21
  ' };\n' +
22
- ' struct IMy: ::com::IUnknown\n' +
22
+ ' struct IMy : ::com::IUnknown\n' +
23
23
  ' {\n' +
24
+ ' constexpr static ::com::GUID const guid = ::com::GUID(0xC66FB2702D8049AD, 0xBB6E88C1F90B805D);\n' +
24
25
  ' virtual Slice COM_STDCALL GetSlice() noexcept = 0;\n' +
25
26
  ' virtual void COM_STDCALL SetSlice(Slice slice) noexcept = 0;\n' +
26
27
  ' virtual ::com::BOOL* COM_STDCALL GetUnsafe() noexcept = 0;\n' +
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "nanocom"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  edition = "2021"
5
5
  description = "Nano-COM, extremly small subset of cross-platform COM"
6
6
  authors = ["NatFoam"]
@@ -3,7 +3,7 @@ use std::{
3
3
  sync::atomic::{AtomicU32, Ordering},
4
4
  };
5
5
 
6
- use crate::{hresult::HRESULT, iunknown::IUnknown, Class, Interface, Object, Ref, Vmt};
6
+ use crate::{guid::GuidEx, hresult::HRESULT, iunknown::IUnknown, Class, Object, Ref};
7
7
 
8
8
  #[repr(C)]
9
9
  pub struct CObject<T: Class> {
@@ -12,14 +12,6 @@ pub struct CObject<T: Class> {
12
12
  pub value: T,
13
13
  }
14
14
 
15
- const fn guid<I: Interface>() -> u128 {
16
- let x = <I>::GUID;
17
- (x >> 96) |
18
- ((x >> 48) & 0x00000_000_0000_0000_0000_FFFF_0000_0000) |
19
- ((x >> 16) & 0x0000_0000_0000_0000_FFFF_0000_0000_0000) |
20
- (((x as u64).swap_bytes() as u128) << 64)
21
- }
22
-
23
15
  impl<T: Class> CObject<T> {
24
16
  pub const IUNKNOWN: IUnknown<T::Interface> = IUnknown {
25
17
  QueryInterface: Self::QueryInterface,
@@ -38,7 +30,7 @@ impl<T: Class> CObject<T> {
38
30
  riid: &u128,
39
31
  ppv_object: &mut *const Object,
40
32
  ) -> HRESULT {
41
- let (p, r) = if *riid == guid::<()>() || *riid == guid::<T::Interface>() {
33
+ let (p, r) = if *riid == <()>::PLATFORM_GUID || *riid == T::Interface::PLATFORM_GUID {
42
34
  Self::AddRef(this);
43
35
  (this.to_iunknown() as *const Object, HRESULT::S_OK)
44
36
  } else {
@@ -1 +1,15 @@
1
+ use crate::Interface;
2
+
1
3
  pub type GUID = u128;
4
+
5
+ pub trait GuidEx: Interface {
6
+ const PLATFORM_GUID: GUID = {
7
+ let x = Self::GUID;
8
+ (x >> 96)
9
+ | ((x >> 48) & 0x00000_000_0000_0000_0000_FFFF_0000_0000)
10
+ | ((x >> 16) & 0x0000_0000_0000_0000_FFFF_0000_0000_0000)
11
+ | (((x as u64).swap_bytes() as u128) << 64)
12
+ };
13
+ }
14
+
15
+ impl<T: Interface> GuidEx for T {}
@@ -46,9 +46,9 @@ const flags = platform => {
46
46
  case 'win32':
47
47
  return []
48
48
  case 'linux':
49
- return ['-lstdc++']
49
+ return ['-lstdc++', '-fPIC']
50
50
  default:
51
- return ['-std=c++11', '-lc++']
51
+ return ['-std=c++17', '-lc++']
52
52
  }
53
53
  }
54
54
 
@@ -77,13 +77,17 @@ const cpp = ({dirname, platform}) => ({
77
77
  })
78
78
 
79
79
  /** @type {Func} */
80
- const cs = ({dirname}) => ({
80
+ const cs = ({dirname, platform}) => ({
81
81
  file: {
82
82
  name: `${dirname}/cs/_result.cs`,
83
83
  content: csContent,
84
84
  },
85
85
  line: [
86
- ['dotnet', 'run', '--project', `${dirname}/cs/cs.csproj`]],
86
+ platform === 'win32'
87
+ ? ['dotnet', 'run', '--project', `${dirname}/cs/cs.csproj`]
88
+ // .Net on Linux and Windows doesn't properly support COM object marshalling
89
+ : ['dotnet', 'build', `${dirname}/cs/cs.csproj`]
90
+ ],
87
91
  })
88
92
 
89
93
  /** @type {Func} */
@@ -13,6 +13,33 @@ extern "C" int c_get()
13
13
  return 43;
14
14
  }
15
15
 
16
- class Impl: My::IMy {
17
-
16
+ class Impl: public My::IMy
17
+ {
18
+ My::Slice COM_STDCALL GetSlice() noexcept override
19
+ {
20
+ }
21
+ void COM_STDCALL SetSlice(My::Slice slice) noexcept override
22
+ {
23
+ }
24
+ ::com::BOOL *COM_STDCALL GetUnsafe() noexcept override
25
+ {
26
+ }
27
+ void COM_STDCALL SetUnsafe(My::Slice *p, uint32_t size) noexcept override
28
+ {
29
+ }
30
+ ::com::BOOL COM_STDCALL Some(My::IMy &p) noexcept override
31
+ {
32
+ }
33
+ ::com::ref<My::IMy> COM_STDCALL GetIMy() noexcept override
34
+ {
35
+ }
36
+ void COM_STDCALL SetManagedStruct(My::ManagedStruct a) noexcept override
37
+ {
38
+ }
18
39
  };
40
+
41
+ DLL_EXPORT
42
+ extern "C" My::IMy* c_my_create()
43
+ {
44
+ return new ::com::implementation<Impl>();
45
+ }
@@ -10,10 +10,15 @@ static extern IMy rust_my_create();
10
10
  [DllImport("testc")]
11
11
  static extern int c_get();
12
12
 
13
+ [DllImport("testc")]
14
+ static extern IMy c_my_create();
15
+
13
16
  // See https://aka.ms/new-console-template for more information
14
17
  Console.WriteLine("Hello, World!");
15
18
  Console.WriteLine(get());
16
19
  Console.WriteLine(c_get());
17
20
 
18
- // var x = rust_my_create();
19
- // x.SetSlice(new Slice { Start = null, Size = (UIntPtr)44 });
21
+ var x = rust_my_create();
22
+ x.SetSlice(new Slice { Start = null, Size = (UIntPtr)44 });
23
+
24
+ var y = c_my_create();
@@ -46,9 +46,11 @@ impl _result::IMy::Ex for nanocom::CObject<My> {
46
46
  }
47
47
 
48
48
  #[no_mangle]
49
- pub extern "C" fn get() -> i32 { 42 }
49
+ pub extern "C" fn get() -> i32 {
50
+ 42
51
+ }
50
52
 
51
53
  #[no_mangle]
52
54
  pub extern "C" fn rust_my_create() -> IMy::Ref {
53
55
  My {}.to_cobject()
54
- }
56
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.463",
3
+ "version": "0.0.465",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "module.f.cjs",
6
6
  "scripts": {