• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

me-viper / OpaDotNet.Compilation / 10266339656

06 Aug 2024 12:08PM UTC coverage: 89.2%. Remained the same
10266339656

push

github

me-viper
feat: Update dependencies

162 of 188 branches covered (86.17%)

Branch coverage included in aggregate %.

6 of 6 new or added lines in 3 files covered. (100.0%)

12 existing lines in 3 files now uncovered.

507 of 562 relevant lines covered (90.21%)

723.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.41
/src/OpaDotNet.Compilation.Interop/Interop.cs
1
using System.Runtime.InteropServices;
2
using System.Text;
3

4
using Microsoft.Extensions.Logging;
5
using Microsoft.Extensions.Logging.Abstractions;
6

7
using OpaDotNet.Compilation.Abstractions;
8

9
namespace OpaDotNet.Compilation.Interop;
10

11
internal static class Interop
12
{
13
    private const string Lib = "Opa.Interop";
14

15
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
16
    public struct OpaVersion
17
    {
18
        public string LibVersion;
19

20
        public string GoVersion;
21

22
        public string? Commit;
23

24
        public string Platform;
25
    }
26

27
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
28
    private struct OpaBytesBuildParams
29
    {
30
        public nint Bytes;
31

32
        public int BytesLen;
33

34
        public OpaBuildParams Params;
35
    }
36

37
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
38
    private struct OpaFsBuildParams
39
    {
40
        public string Source;
41

42
        public OpaBuildParams Params;
43
    }
44

45
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
46
    private struct OpaBuildParams
47
    {
48
        public string Target;
49

50
        public string? CapabilitiesJson;
51

52
        public string? CapabilitiesVersion;
53

54
        public int BundleMode;
55

56
        public nint Entrypoints;
57

58
        public int EntrypointsLen;
59

60
        public int Debug;
61

62
        public int OptimizationLevel;
63

64
        public int PruneUnused;
65

66
        public string? TempDir;
67

68
        public string? Revision;
69

70
        public nint Ignore;
71

72
        public int IgnoreLen;
73

74
        public int RegoVersion;
75

76
        public int FollowSymlinks;
77

78
        public int DisablePrintStatements;
79
    }
80

81
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
82
    private struct OpaBuildResult
83
    {
84
        public nint Result;
85

86
        public int ResultLen;
87

88
        public string? Errors;
89

90
        public string? Log;
91
    }
92

93
    [DllImport(Lib, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
94
    public static extern void OpaGetVersion(out nint version);
95

96
    [DllImport(Lib, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
97
    public static extern void OpaFreeVersion([In] nint version);
98

99
    [DllImport(Lib, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
100
    private static extern int OpaBuildFromFs(
101
        [In] ref OpaFsBuildParams buildParams,
102
        out nint result);
103

104
    [DllImport(Lib, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
105
    private static extern int OpaBuildFromBytes(
106
        [In] ref OpaBytesBuildParams buildParams,
107
        out nint result);
108

109
    [DllImport(Lib, CallingConvention = CallingConvention.Cdecl)]
110
    private static extern void OpaFree([In] nint buildResult);
111

112
    private static Stream Compile(
113
        Func<OpaBuildParams, (int, nint)> compile,
114
        CompilationParameters options,
115
        bool forceBundle,
116
        ILogger? logger)
117
    {
80✔
118
        ArgumentNullException.ThrowIfNull(compile);
80✔
119
        ArgumentNullException.ThrowIfNull(options);
80✔
120

121
        logger ??= NullLogger.Instance;
80!
122

123
        var pEntrypoints = nint.Zero;
80✔
124
        var entrypointsList = Array.Empty<nint>();
80✔
125

126
        var pIgnore = nint.Zero;
80✔
127
        var ignoreList = Array.Empty<nint>();
80✔
128

129
        try
130
        {
80✔
131
            string? caps = null;
80✔
132

133
            if (!string.IsNullOrWhiteSpace(options.CapabilitiesFilePath))
80✔
134
                caps = File.ReadAllText(options.CapabilitiesFilePath);
8✔
135
            else if (!options.CapabilitiesBytes.IsEmpty)
72✔
136
                caps = Encoding.UTF8.GetString(options.CapabilitiesBytes.Span);
4✔
137

138
            var buildParams = new OpaBuildParams
80!
139
            {
80✔
140
                CapabilitiesVersion = options.CapabilitiesVersion,
80✔
141
                CapabilitiesJson = caps,
80✔
142
                BundleMode = forceBundle || options.IsBundle ? 1 : 0,
80✔
143
                OptimizationLevel = 0,
80✔
144
                Target = "wasm",
80✔
145
                Debug = options.Debug ? 1 : 0,
80✔
146
                PruneUnused = options.PruneUnused ? 1 : 0,
80✔
147
                TempDir = string.IsNullOrWhiteSpace(options.OutputPath) ? null : Path.GetFullPath(options.OutputPath),
80✔
148
                RegoVersion = (int)options.RegoVersion,
80✔
149
                Revision = options.Revision,
80✔
150
                FollowSymlinks = options.FollowSymlinks ? 1 : 0,
80✔
151
                DisablePrintStatements = options.DisablePrintStatements ? 1 : 0,
80✔
152
            };
80✔
153

154
            if (options.Entrypoints != null)
80✔
155
            {
62✔
156
                var ep = options.Entrypoints.ToArray();
62✔
157
                pEntrypoints = Marshal.AllocCoTaskMem(ep.Length * nint.Size);
62✔
158
                entrypointsList = new nint[ep.Length];
62✔
159

160
                for (var i = 0; i < ep.Length; i++)
264✔
161
                    entrypointsList[i] = Marshal.StringToCoTaskMemAnsi(ep[i]);
70✔
162

163
                Marshal.Copy(entrypointsList, 0, pEntrypoints, ep.Length);
62✔
164

165
                buildParams.Entrypoints = pEntrypoints;
62✔
166
                buildParams.EntrypointsLen = ep.Length;
62✔
167
            }
62✔
168

169
            if (options.Ignore is { Count: > 0 })
80!
170
            {
8✔
171
                pIgnore = Marshal.AllocCoTaskMem(options.Ignore.Count * nint.Size);
8✔
172
                ignoreList = new nint[options.Ignore.Count];
8✔
173

174
                var i = 0;
8✔
175

176
                foreach (var ign in options.Ignore)
44✔
177
                    ignoreList[i++] = Marshal.StringToCoTaskMemAnsi(ign);
10✔
178

179
                Marshal.Copy(ignoreList, 0, pIgnore, options.Ignore.Count);
8✔
180

181
                buildParams.Ignore = pIgnore;
8✔
182
                buildParams.IgnoreLen = options.Ignore.Count;
8✔
183
            }
8✔
184

185
            var bundle = nint.Zero;
80✔
186

187
            try
188
            {
80✔
189
                (var result, bundle) = compile(buildParams);
80✔
190

191
                if (bundle == nint.Zero)
80!
UNCOV
192
                    throw new RegoCompilationException("Compilation failed");
×
193

194
                var resultBundle = Marshal.PtrToStructure<OpaBuildResult>(bundle);
80✔
195

196
                if (!string.IsNullOrWhiteSpace(resultBundle.Log))
80✔
197
                    logger.LogDebug("{BuildLog}", resultBundle.Log);
46✔
198

199
                if (!string.IsNullOrWhiteSpace(resultBundle.Errors))
80✔
200
                    throw new RegoCompilationException(resultBundle.Errors);
8✔
201

202
                if (result != 0)
72!
UNCOV
203
                    throw new RegoCompilationException($"Compilation error {result}");
×
204

205
                if (resultBundle.ResultLen == 0 || resultBundle.Result == nint.Zero)
72!
UNCOV
206
                    throw new RegoCompilationException("Bad result");
×
207

208
                var bundleBytes = new byte[resultBundle.ResultLen];
72✔
209
                Marshal.Copy(resultBundle.Result, bundleBytes, 0, resultBundle.ResultLen);
72✔
210

211
                return new MemoryStream(bundleBytes);
72✔
212
            }
213
            finally
214
            {
80✔
215
                if (bundle != nint.Zero)
80✔
216
                    OpaFree(bundle);
80✔
217
            }
80✔
218
        }
219
        finally
220
        {
80✔
221
            if (pEntrypoints != nint.Zero)
80✔
222
            {
62✔
223
                foreach (var p in entrypointsList)
326✔
224
                    Marshal.FreeCoTaskMem(p);
70✔
225

226
                Marshal.FreeCoTaskMem(pEntrypoints);
62✔
227
            }
62✔
228

229
            if (pIgnore != nint.Zero)
80✔
230
            {
8✔
231
                foreach (var p in ignoreList)
44✔
232
                    Marshal.FreeCoTaskMem(p);
10✔
233

234
                Marshal.FreeCoTaskMem(pIgnore);
8✔
235
            }
8✔
236
        }
80✔
237
    }
72✔
238

239
    public static Stream Compile(
240
        string source,
241
        CompilationParameters options,
242
        bool forceBundle,
243
        ILogger? logger)
244
    {
52✔
245
        ArgumentException.ThrowIfNullOrEmpty(source);
52✔
246
        ArgumentNullException.ThrowIfNull(options);
52✔
247

248
        static (int, nint) CompileFunc(string source, OpaBuildParams buildParams)
249
        {
52✔
250
            var fsBuildParams = new OpaFsBuildParams
52✔
251
            {
52✔
252
                Source = source,
52✔
253
                Params = buildParams,
52✔
254
            };
52✔
255

256
            var result = OpaBuildFromFs(ref fsBuildParams, out var bundle);
52✔
257
            return (result, bundle);
52✔
258
        }
52✔
259

260
        return Compile(p => CompileFunc(source, p), options, forceBundle, logger);
104✔
261
    }
48✔
262

263
    public static Stream Compile(
264
        Stream source,
265
        CompilationParameters options,
266
        bool forceBundle,
267
        ILogger? logger)
268
    {
28✔
269
        ArgumentNullException.ThrowIfNull(source);
28✔
270
        ArgumentNullException.ThrowIfNull(options);
28✔
271

272
        static (int, nint) CompileFunc(Stream source, OpaBuildParams buildParams)
273
        {
28✔
274
            var bytes = nint.Zero;
28✔
275

276
            try
277
            {
28✔
278
                var len = (int)source.Length;
28✔
279
                bytes = Marshal.AllocCoTaskMem(len);
28✔
280

281
                // It's possible to do this without unsafe code but it requires creating intermediate array
282
                // and extra copying. And not that this option would be safer.
283
                unsafe
284
                {
28✔
285
                    var b = new Span<byte>(bytes.ToPointer(), len);
28✔
286
                    _ = source.Read(b);
28✔
287
                }
28✔
288

289
                var bytesBuildParams = new OpaBytesBuildParams
28✔
290
                {
28✔
291
                    Bytes = bytes,
28✔
292
                    BytesLen = len,
28✔
293
                    Params = buildParams,
28✔
294
                };
28✔
295

296
                var result = OpaBuildFromBytes(ref bytesBuildParams, out var bundle);
28✔
297
                return (result, bundle);
28✔
298
            }
299
            finally
300
            {
28✔
301
                Marshal.FreeCoTaskMem(bytes);
28✔
302
            }
28✔
303
        }
28✔
304

305
        return Compile(p => CompileFunc(source, p), options, forceBundle, logger);
56✔
306
    }
24✔
307
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc