For example, let's say that for some reason macros were removed (this is very unlikely to happen, but as a thought experiment), then the symmetry between macro/fn definitions wouldn't be an argument anymore, and the question could be revisited.
Similar things have happened before: the optional type syntax changed from `int!` to the more mainstream `int?`. So why did I stick with `int!` for so long? Because initially it was called a "failable" and had different semantics. Revisiting this syntax after other changes to the syntax in 0.6.0, made it clear that `int?` was now fine to use.
So that's why I don't say never. But it would need for the situation to change in some way.
There is a C (single header-only) library[1] that determines CPU features at runtime (similar to that of what libsodium does), so I might try to use that with C3 and implement BLAKE2. That might be a good starting point, or perhaps even TOTP, my friend told me implementing TOTP might give me some insight into the language, but for that I will need base32 (I checked, it exists[2]) and SHA{1,256,512}-HMAC, which may not be available in C3, although there may be an OpenSSL binding already, or perhaps I could directly use OpenSSL from C3? The latter would be pretty cool if so.
Regarding the mentioned C library, it might not work, because it is header-only, and it generates the C functions using macros (see line 219). What do you think? Would this work from C3?
[1] https://zolk3ri.name/cgit/cpudetect/tree/cpudetect.h
[2] https://github.com/c3lang/c3c/blob/master/lib/std/encoding/b...
---
I checked base32.c3. I am comparing it to Odin's, which can be found at https://github.com/odin-lang/Odin/blob/master/core/encoding/.... Apparently they added a way to gracefully handle error cases. Is it possible to do so with the current C3 implementation?
Edit: I noticed "@require padding < 0xFF : "Invalid padding character"", and there is "encoding::INVALID_CHARACTER", so I presume we can handle some errors or invalid input gracefully. Although I prefer Odin's current implementation because you can handle specific errors, e.g. not just "invalid character", but invalid length (and others, see base32.odin for more). Any thoughts on this?
Additionally, what are the differences between
@require padding < 0xFF : "Invalid padding character"
and @return? encoding::INVALID_PADDING, encoding::INVALID_CHARACTER
exactly? If I want to handle invalid padding character, I would have to get rid of "@require"?Additionally, what if there are many more error cases? It would be a "long line" of available error cases? Could I use an enum of errors or something instead or something similar to https://github.com/odin-lang/Odin/blob/master/core/encoding/...?
BTW I like programming by contract, but I am not sure that all error cases that Odin has could have a "@require", and I am not sure if I would like to mix them either, because what if I have a program where I want to handle even "padding < 0xFF" specifically (in terms of base32.c3), or let's say, I don't want it to fail when "padding < 0xFF". Would I really need to implement my own base32 encoding in that case, then, or what?
---
Thank you for your time and help in advance!
macro String? encode2(Allocator allocator, char[] src, char padding = DEFAULT_PAD, Base32Alphabet* alphabet = &STANDARD)
{
if (padding >= 0xFF) return INVALID_PADDING?;
return encode(allocator, src, padding, alphabet);
}
Maybe a better place to ask these questions are on the Discord if you have an account: https://discord.gg/qN76R87The `@require` here is creating a contract. You can't give a padding that is 0xFF, that's a programming error. However, you might have data which is invalid – in that case the typical error is INVALID_CHARACTER. To pass in a too small buffer is a programming error since the output buffer must be calculated first, so that's why that is not an error either. This was a deliberate change to make the API tighter.
So it's quite possible to add an "INVALID_LENGTH" error, but that should only be there in case one does encryption / decryption where the length cannot be easily determined beforehand i.e. it's part of the unknown input which the function determines. But in the Base32 implementation this is not the case. Either use it with an allocator for it to allocate sufficient memory for the data, or calculate that the buffer you pass in is big enough (or run into asserts if it isn't)
BTW my last question still stands, however, that if there is a C library that is only a single header file that implements functions through macros, can it be used from C3? In C, for what I posted, you would need to first do "#define CPUDETECT_IMPL" and then include the header file. Could it be done from C3 somehow? As in, could this (or any) single-header library be used from C3?
And regarding the errors, can I have something like "Error" (in Odin), or an enum of errors? Sorry for this silly question, I realize I will have to read the source code of the libraries first.
Thank you for your help!
For that reason it's not an option for the standard library, but can certainly be useful for programs and libraries.
For faults, they are usually defined with `faultdef` which allows you to define one or more faults:
faultdef SOMETHING_WENT_SIDEWAYS, BIG_OOPS;
Then you use them as if they were constants: if (x > 0) return BIG_OOPS?;
If they are defined in another module, say "foo::bar::baz", then: if (x > 0) return baz::BIG_OOPS?;
Using path shortening "foo::bar::baz::BIG_OOPS" would also be valid, but is not necessary nor recommended.Is it possible to do something like:
faultdef {
FOO, // comment
BAR, // another comment
BAZ, // yadda
// Maybe this would work, too (for docgen if available)
QUX
}
or something like that?Does C3 have a way to generate documentation?