First off, thanks for taking an interest in helping this crate expand! Contributions of any kind are very much welcome and appreciated, whether they're administrative or functional.
If you came here looking for one of the macros or functions in the SDK and couldn't find it, feel free to open an issue. If you know the inner workings, or if you can translate it to Rust, you're also welcome to just open a PR or both an issue and a closing PR. Just make sure to point to a reference for the function or macro or to point to a rough location where its Win32 SDK definition lives. If instead you ended up here looking to help with no idea what to do, take a look at the open issues and pick whatever you feel is feasible.
If you're here to open an issue, please try to link the matching documentation for the SDK implementation or point to someplace in the files it can be found. If you have absolutely no idea, a simple "I'm missing function/macro XYZ used for this magical task or workload" suffices. For anything else, try to see if an issue template exists.
Regardless of the type of contribution, if you want to get in touch you can do so through issues, on Discord (@rivenskaye), on Telegram (@RivenSkaye) or through Matrix (@rivenskaye:sakura.ci). I might at some point make a Discord guild and/or a group somewhere else if there's interest, but currently no such thing exists. Discord is generally the fastest way to get a response.
This crate is, first and foremost, meant to provide utilities and functions that are missing. That said, some things might be applicable to the types defined in windows-rs
as well. In these cases, allowing safe access by correctly handling the unsafe parts of windows-rs
can provide an ergonomics and usability benefit and as such, use of unsafe
is not disallowed. It is encouraged to prefer multiple unsafe
blocks or oneliners over marking a function unsafe as a whole for the same reasons. Any and all functions using unsafe
should be commented or documented with a brief description of why things are safe. These functions must also provide unit tests to ensure they work as intended. For other utilities, unit tests are only required for larger functions and interdependent ones, as small functions (such as the minwindef
oneliners) can usually be covered by simple doctest examples.
More elaborate testing for functions of all sizes might become required in the future, but there is currently no real reason for that.
When adding unsafe functions, please try to avoid SEH pitfalls. This crate does not (yet) have a mechanism to deal with this and the standard library only provides bare crash and unwind semantics for AMD64. We're hoping recent developments around expired patents will allow for easier x86 SEH recovery in compilers other than MSVC. For now, microSEH provides MSVC-only handling that uses a very minimal C wrapper. It seems at least LLVM offers support here and apparently GCC is also capable of emitting stuff for it these days. So who knows, maybe someone will PR in a contribution for microSEH that enables LLVM and GCC builds as well!
Not all headers include definitions that would also make for easy extension traits and methods. The minwindef.h
macros use a few layers of type aliases to just do bitops on the underlying integer values. As such, it makes sense to have an extension trait that allows you to just get the partial values straight from the integers. And considering bitops on constants can be solved at compile time, it even makes sense to offer these functions as const fn
s. This is obviously not always the case though, as some functions need things that aren't const
or require several values to do things. If a certain header only offers functionality that doesn't lend itself well to an extension trait on an existing type, then it makes no sense to include an ext
submodule. For those additions, a simple headername.rs
and its corresponding features and library exports are fine. If something does lend itself to extension traits, then it should be a directory with the header content exported and an ext
submodule that's only exported on the ext-impls
feature. Of course if it makes sense to split something over multiple files, there's no problem with using a directory instead.
The C++ header counterparts of most of what happens here are macros. Except when pre-processed the emitted result is usually relatively simple ops or compile time calculated constants. This means that for the ones implemented so far, an inlined const fn
would provide the exact same result while keeping readability. If something is more suited for implementation as a Rust macro, feel free to provide an implementation and give a brief explanation why. I'm comfortable reading and using macros, but for writing them I'd like to find someone more experienced to help implement them. It's simply a matter of not having enough experience to be certain of what I'm doing. If we find something that warrants a macro, maybe you are the one we want!