There are a several options that set up callbacks that I did not wrap
in this first pass because I need to decide on whether or not it makes
sense to move the various thunks into a common location. There's one
that could be shared between the subscriptions and here due to having
the same signature, but I'm not sure there are any others that would
really benefit from cross-file sharing.
There is a case-sensitivity issue here. The Windows documentation calls
the library Ws2_32, but the mingw cross-compilation on Linux fails
unless it is called `ws3_32`. For some reason, both work on macOS. I
have not tried on Windows, but I assume this will probably work there
due to everything being extremely insensitive (case-wise) on Windows.
I think I am probably going to move unit tests to a separate
directory/file structure. This will allow me to add a bunch of utility
functions that don't get analyzed for the library compilation and also
avoid testing-only imports in the main modules.
The streaming API is not wrapped because we do not build nats.c with
the necessary libraries. The jetstream API is not wrapped because I am
extremely lazy and it's outside of the minimum viable scope at the
moment. It can happen after the other basic APIs have been wrapped.
I'm going to try out git-subrepo. The main reason for this is that
github's autogenerated tarballs do not include submodules. And
github's autogenerated tarballs are the easiest way to integrate into
the zig package manager. Since git-subrepo checks the files into the
tree directly, new tarballs should include this dependency code.
This is pretty much just the API surface that is used in the demo code
for now, with a couple of minor things I tacked on while getting a
feel for how I was going to go about it. Unfortunately, the diff is
too messy to show the improvement provided by the wrapped API, but I'm
pretty pleased with how it is turning out so far. In general, there
have been no major hiccups.
Most of the time working on this was spent noodling about how to create
the subscription callback thunk to provide type safety and pointer
nullability guarantees for the subscription zig API. I'm satisfied
with the solution in place now: it seems to have good default
ergonomics and very few downsides except that the callback function
must be known at compile time. An earlier iteration of this code
supported runtime function pointers but had a showstopping problem
with memory management. In order to store the runtime callback
pointer, the thunk would need to be allocated, but there was no way of
attaching our allocated memory to the c-library subscription object.
No attachment meant that there were a number of error scenarios where
the allocated thunk couldn't be freed correctly.
Ultimately, if the user needs to use runtime callback pointers they can
write a comptime known callback that calls a runtime known callback.
This way all of the object lifetime and ownership is in the user's
hands, which is really where it needs to belong anyway for this.
This builds a very basic version of the nats.c client (no TLS, no
streaming/jetstream/whatever, since those bring in complex
dependencies and I do not need them at the moment). Right now it
contains a simple test program that demonstrates the functionality
(cool!), but the plan is for the nats.zig to bind the API into a
nicer, zig-like shape and re-export it. Then this becomes a package.
The current function could become a test, though it's a bit complex
for a unit test (and requires connecting to an externally-running NATS
server in order to work).