Refactor struct module#2084
Conversation
| )) | ||
| } | ||
| } | ||
| Err(obj) => PyBytesLike::try_from_object(vm, obj).map(PyAsciiBytesLike::Buffer), |
There was a problem hiding this comment.
You'd probably want to check that the bytes is all ascii as well
Edit: hmm, although CPython doesn't actually care if there's non-ascii bytes in a bytestring, for both binascii and struct
There was a problem hiding this comment.
We don't need to check if it's ascii, as all usages error if they encounter any characters that they don't recognise including bytes out of the ascii range. That also means we could get away with not checking the string is ascii as the bytes are the utf-8 encoding of it, so any bytes less than 128 match the ascii characters, and any bytes that are 128 and above are a part of an non-ascii character.
| impl TryFromObject for SerializedData { | ||
| fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> { | ||
| match_class!(match obj { | ||
| b @ PyBytes => Ok(SerializedData::Bytes(b)), | ||
| b @ PyByteArray => Ok(SerializedData::Buffer(b)), | ||
| a @ PyString => { | ||
| if a.as_str().is_ascii() { | ||
| Ok(SerializedData::Ascii(a)) | ||
| } else { | ||
| Err(vm.new_value_error( | ||
| "string argument should contain only ASCII characters".to_owned(), | ||
| )) | ||
| } | ||
| } | ||
| obj => Err(vm.new_type_error(format!( | ||
| "argument should be bytes, buffer or ASCII string, not '{}'", | ||
| obj.class().name, | ||
| ))), | ||
| }) | ||
| } | ||
| } |
There was a problem hiding this comment.
Maybe keep this? binascii does allow a bytearray, while struct doesn't:
>>> binascii.a2b_hex(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: argument should be bytes, buffer or ASCII string, not 'int'
>>> struct.Struct(bytearray())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Struct() argument 1 must be a str or bytes object, not bytearrayThere was a problem hiding this comment.
PyAsciiBytesLike aligns with what binascii accept more than this e.g. the following is allowed: binascii.a2b_base64(array.array('B', b'1111')). I'm also not sure if struct.Struct(bytearray()) should be disallowed or not. there is a comment about allowing it: https://github.com/python/cpython/blob/67acf74c4eaf64a860cc1bcda6efe6e9cb01f89b/Modules/_struct.c#L1466
There was a problem hiding this comment.
CPython source code looks like to saying it is not an intention.
https://github.com/python/cpython/blob/v3.10.0/Modules/_struct.c#L1478
| b'n' | b'N' | b'P' => std::mem::size_of::<usize>(), | ||
| c => { | ||
| panic!("Unsupported format code {:?}", c); | ||
| panic!("Unsupported format code {:?}", c as char); |
There was a problem hiding this comment.
How about throw an exception (like ValueError) instead of panic?
422b05f to
bf0c712
Compare
|
|
bf0c712 to
6070af3
Compare
This accepts either an string with only ascii characters or any bytes like object.