Skip to content

Commit

Permalink
Fix some struct issues
Browse files Browse the repository at this point in the history
  • Loading branch information
slozier committed Nov 24, 2024
1 parent 6071a92 commit 4c537a4
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 33 deletions.
45 changes: 21 additions & 24 deletions Src/IronPython.Modules/_struct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -393,13 +393,13 @@ public void pack_into(CodeContext/*!*/ context, [NotNone] ByteArray/*!*/ buffer,
}

[Documentation("iteratively unpack the current format from the specified array.")]
public PythonUnpackIterator iter_unpack(CodeContext/*!*/ context, [BytesLike][NotNone] IList<byte>/*!*/ buffer, int offset = 0) {
return new PythonUnpackIterator(this, context, buffer, offset);
public PythonUnpackIterator iter_unpack(CodeContext/*!*/ context, [BytesLike][NotNone] IList<byte>/*!*/ buffer) {
return new PythonUnpackIterator(this, context, buffer);
}

[Documentation("iteratively unpack the current format from the specified array.")]
public PythonUnpackIterator iter_unpack(CodeContext/*!*/ context, [NotNone] ArrayModule.array/*!*/ buffer, int offset = 0) {
return new PythonUnpackIterator(this, context, buffer, offset);
public PythonUnpackIterator iter_unpack(CodeContext/*!*/ context, [NotNone] ArrayModule.array/*!*/ buffer) {
return new PythonUnpackIterator(this, context, buffer.ToByteArray());
}

[Documentation("gets the number of bytes that the serialized string will occupy or are required to deserialize the data")]
Expand Down Expand Up @@ -559,14 +559,19 @@ private static Struct CompileAndCache(CodeContext/*!*/ context, string/*!*/ fmt)
fLittleEndian = false;
fStandardized = true;
break;
case '\x00':
throw Error(context, "embedded null character");
default:
if (char.IsDigit(fmt[i])) {
count = 0;
while (char.IsDigit(fmt[i])) {
count = count * 10 + (fmt[i] - '0');
i++;
if (i >= fmt.Length) {
throw Error(context, "repeat count given without format specifier");
}
}
if (char.IsWhiteSpace(fmt[i])) Error(context, "white space not allowed between count and format");
if (char.IsWhiteSpace(fmt[i])) throw Error(context, "white space not allowed between count and format");
i--;
break;
}
Expand Down Expand Up @@ -633,33 +638,24 @@ public class PythonUnpackIterator : System.Collections.IEnumerator, System.Colle

private readonly CodeContext _context;
private readonly IList<byte> _buffer;
private readonly int _start_offset;
private readonly Struct _owner;

private PythonUnpackIterator() { }

internal PythonUnpackIterator(Struct/*!*/ owner, CodeContext/*!*/ context, IList<byte>/*!*/ buffer, int offset) {
internal PythonUnpackIterator(Struct/*!*/ owner, CodeContext/*!*/ context, IList<byte>/*!*/ buffer) {
_context = context;
_buffer = buffer;
_start_offset = offset;
_owner = owner;

Reset();
ValidateBufferLength();
}

internal PythonUnpackIterator(Struct/*!*/ owner, CodeContext/*!*/ context, ArrayModule.array/*!*/ buffer, int offset) {
_context = context;
_buffer = buffer.ToByteArray();
_start_offset = offset;
_owner = owner;

Reset();
ValidateBufferLength();
}

private void ValidateBufferLength() {
if (_buffer.Count - _start_offset < _owner.size) {
if (_owner.size == 0) {
throw Error(_context, "cannot iteratively unpack with a struct of length 0");
}
if (_buffer.Count % _owner.size != 0) {
throw Error(_context, $"iterative unpacking requires a buffer of a multiple of {_owner.size} bytes");
}
}
Expand Down Expand Up @@ -689,7 +685,7 @@ public bool MoveNext() {
[PythonHidden]
public void Reset() {
_iter_current = null;
_next_offset = _start_offset;
_next_offset = 0;
}
#endregion

Expand Down Expand Up @@ -869,13 +865,13 @@ public static void pack_into(CodeContext/*!*/ context, object fmt, [NotNone] Byt
}

[Documentation("Iteratively unpack the buffer, containing packed C structure data, according to\nfmt, starting at offset. Requires len(buffer[offset:]) >= calcsize(fmt).")]
public static PythonUnpackIterator/*!*/ iter_unpack(CodeContext/*!*/ context, object fmt, [BytesLike][NotNone] IList<byte>/*!*/ buffer, int offset = 0) {
return GetStructFromCache(context, fmt).iter_unpack(context, buffer, offset);
public static PythonUnpackIterator/*!*/ iter_unpack(CodeContext/*!*/ context, object fmt, [BytesLike][NotNone] IList<byte>/*!*/ buffer) {
return GetStructFromCache(context, fmt).iter_unpack(context, buffer);
}

[Documentation("Iteratively unpack the buffer, containing packed C structure data, according to\nfmt, starting at offset. Requires len(buffer[offset:]) >= calcsize(fmt).")]
public static PythonUnpackIterator/*!*/ iter_unpack(CodeContext/*!*/ context, object fmt, [NotNone] ArrayModule.array/*!*/ buffer, int offset = 0) {
return GetStructFromCache(context, fmt).iter_unpack(context, buffer, offset);
public static PythonUnpackIterator/*!*/ iter_unpack(CodeContext/*!*/ context, object fmt, [NotNone] ArrayModule.array/*!*/ buffer) {
return GetStructFromCache(context, fmt).iter_unpack(context, buffer);
}
#endregion

Expand Down Expand Up @@ -1361,6 +1357,7 @@ internal static Bytes CreateString(CodeContext/*!*/ context, ref int index, int

internal static Bytes CreatePascalString(CodeContext/*!*/ context, ref int index, int count, IList<byte> data) {
int realLen = (int)data[index++];
if (realLen > count) realLen = count;
using var res = new MemoryStream();
for (int i = 0; i < realLen; i++) {
res.WriteByte(data[index++]);
Expand Down
6 changes: 3 additions & 3 deletions Src/StdLib/Lib/test/test_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,13 +542,13 @@ def test_trailing_counter(self):

# format lists containing only count spec should result in an error
self.assertRaises(struct.error, struct.pack, '12345')
self.assertRaises(struct.error, struct.unpack, '12345', '')
self.assertRaises(struct.error, struct.unpack, '12345', b'')
self.assertRaises(struct.error, struct.pack_into, '12345', store, 0)
self.assertRaises(struct.error, struct.unpack_from, '12345', store, 0)

# Format lists with trailing count spec should result in an error
self.assertRaises(struct.error, struct.pack, 'c12345', 'x')
self.assertRaises(struct.error, struct.unpack, 'c12345', 'x')
self.assertRaises(struct.error, struct.unpack, 'c12345', b'x')
self.assertRaises(struct.error, struct.pack_into, 'c12345', store, 0,
'x')
self.assertRaises(struct.error, struct.unpack_from, 'c12345', store,
Expand All @@ -557,7 +557,7 @@ def test_trailing_counter(self):
# Mixed format tests
self.assertRaises(struct.error, struct.pack, '14s42', 'spam and eggs')
self.assertRaises(struct.error, struct.unpack, '14s42',
'spam and eggs')
b'spam and eggs')
self.assertRaises(struct.error, struct.pack_into, '14s42', store, 0,
'spam and eggs')
self.assertRaises(struct.error, struct.unpack_from, '14s42', store, 0)
Expand Down
10 changes: 4 additions & 6 deletions Tests/test_struct_stdlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@ def load_tests(loader, standard_tests, pattern):

if is_ironpython:
failing_tests = [
test.test_struct.StructTest('test_705836'), # TODO: figure out
test.test_struct.StructTest('test_bool'), # TODO: figure out
test.test_struct.StructTest('test_calcsize'), # TODO: figure out
test.test_struct.StructTest('test_count_overflow'), # TODO: figure out
test.test_struct.StructTest('test_trailing_counter'), # TODO: figure out
test.test_struct.UnpackIteratorTest('test_construct'), # TODO: figure out
test.test_struct.StructTest('test_705836'), # AssertionError: OverflowError not raised by pack
test.test_struct.StructTest('test_bool'), # struct.error: expected bool value got IronPython.NewTypes.System.Object_1$1
test.test_struct.StructTest('test_calcsize'), # AssertionError: 4 not greater than or equal to 8
test.test_struct.StructTest('test_count_overflow'), # AssertionError: error not raised by calcsize
]

return generate_suite(tests, failing_tests)
Expand Down

0 comments on commit 4c537a4

Please sign in to comment.