-
Notifications
You must be signed in to change notification settings - Fork 63
Support encoding indefinite containers #256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
b473365
to
b672722
Compare
How are the tests passing for you locally? |
b672722
to
088d68b
Compare
I'm getting all sorts of |
088d68b
to
597fc86
Compare
This message indicates that the C extension is unavailable. So likely it didn't compile successfully, or you didn't do it in the first place. How are you running the tests? |
I was just running |
Add the indefinite_containers parameter to the encoder functions. If the parameter is set to True, containers (maps and arrays) are encoded an indefinite containers.
597fc86
to
b8b0d89
Compare
WOOHOO! Passes the tests now :) |
That's odd. Try setting |
That |
From a cursory look, only minor code style issues remain. In Python code, I prefer a blank line after a control block if the code continues on the same level. In C code, I prefer a space between |
No problem with doing these changes, but wouldn't these styling issues be better resolved by a pre-commit formatter hook? |
If you can point me to a Ruff rule (or a rule in another linter) that can enforce these, I would be most grateful! |
Don't know about the Python part, but I am quite positive there is an option for the ifs in ClangFormat. There seems to be no autoformatting for the C code set up at the moment. |
Something occurred to me: couldn't we simply wrap indefinite containers to mark them to be encoded as such? |
You mean that you would need to use a specific class other than the |
Alright, I'll take that under advisement. Reviewing this is still on my to-do list, but I don't expect any trouble from that. |
static int | ||
encode_length(CBOREncoderObject *self, const uint8_t major_tag, | ||
const uint64_t length) | ||
encode_length_possibly_indefinite(CBOREncoderObject *self, const uint8_t major_tag, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain why you had to split this function into two parts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I wanted to reduce diff by keeping rest of the encode_length calls the same (not having to add the extra parameter everywhere)
- I felt that the bool parameter would be somewhat cryptic if there was not some addition to the function name, so I created
encode_length_possibly_indefinite
. Most of the use cases don't care about indefinite encoding, so it didn't make sense to drag this function there - so we have two now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took a better look at this, and it doesn't make a whole lot of sense. uint64_t
cannot possibly be -1 since it's unsigned. The actual value would then become a very large integer (18446744073709551615) instead, yes? While I doubt anyone will really try to actually encode such enormous structures, it does raise other questions, like if you felt this was an acceptable sentinel value, why then did you have to split encode_length()
instead of just using -1 as the sentinel for indefinite length? And why can't encode_length()
just directly look at self->indefinite_containers
and if it's true, ignore the length parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
encode_length cannot directly use indefinite_containers, because it is also used on other places outside of encoding array/map length.
Co-authored-by: Alex Grönholm <[email protected]>
Co-authored-by: Alex Grönholm <[email protected]>
|
||
// CBOREncoder.encode_length(self, major_tag, length) | ||
static PyObject * | ||
CBOREncoder_encode_length(CBOREncoderObject *self, PyObject *args) | ||
{ | ||
uint8_t major_tag; | ||
uint64_t length; | ||
uint64_t length = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, -1 becomes a very large integer.
I did this because I was too lazy to set up a custom structure for the uint64_or_none
that would be required for PyArg_ParseTuple
. It would be cleaner to have it distinct, yes. It is somewhat dirty, so I didn't want to bring this approach to other places.
Should I remake it?
Changes
indefinite_containers
parameter to the encoder functions. If the parameter is set to True, containers (maps and arrays) are encoded an indefinite containers.I am using this library to for unittesting a C++ CBOR generator, for which case I needed to generate structures with indefinite containers to be able to do 1:1 byte checks.