Skip to content

Commit a985b45

Browse files
committed
objint: Implement int.from_bytes() class method and .to_bytes() method.
These two are apprerently the most concise and efficient way to convert int to/from bytes in Python. The alternatives are struct and array modules, but methods using them are more verbose in Python code and less efficient in memory/cycles.
1 parent 3aa8ee7 commit a985b45

3 files changed

Lines changed: 46 additions & 0 deletions

File tree

py/objint.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,11 +261,49 @@ mp_obj_t mp_obj_int_binary_op_extra_cases(int op, mp_obj_t lhs_in, mp_obj_t rhs_
261261
return MP_OBJ_NULL;
262262
}
263263

264+
STATIC mp_obj_t int_from_bytes(uint n_args, const mp_obj_t *args) {
265+
buffer_info_t bufinfo;
266+
mp_get_buffer_raise(args[0], &bufinfo);
267+
268+
assert(bufinfo.len >= sizeof(machine_int_t));
269+
// TODO: Support long ints
270+
// TODO: Support byteorder param
271+
// TODO: Support signed param
272+
return mp_obj_new_int_from_uint(*(machine_uint_t*)bufinfo.buf);
273+
}
274+
275+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_obj, 1, 3, int_from_bytes);
276+
277+
STATIC mp_obj_t int_to_bytes(uint n_args, const mp_obj_t *args) {
278+
machine_int_t val = mp_obj_int_get_checked(args[0]);
279+
280+
uint len = MP_OBJ_SMALL_INT_VALUE(args[1]);
281+
byte *data;
282+
283+
// TODO: Support long ints
284+
// TODO: Support byteorder param
285+
// TODO: Support signed param
286+
mp_obj_t o = mp_obj_str_builder_start(&mp_type_bytes, len, &data);
287+
memset(data, 0, len);
288+
memcpy(data, &val, len < sizeof(machine_int_t) ? len : sizeof(machine_int_t));
289+
return mp_obj_str_builder_end(o);
290+
}
291+
292+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_to_bytes_obj, 2, 4, int_to_bytes);
293+
294+
STATIC const mp_map_elem_t int_locals_dict_table[] = {
295+
{ MP_OBJ_NEW_QSTR(MP_QSTR_from_bytes), (mp_obj_t)&int_from_bytes_obj },
296+
{ MP_OBJ_NEW_QSTR(MP_QSTR_to_bytes), (mp_obj_t)&int_to_bytes_obj },
297+
};
298+
299+
STATIC MP_DEFINE_CONST_DICT(int_locals_dict, int_locals_dict_table);
300+
264301
const mp_obj_type_t mp_type_int = {
265302
{ &mp_type_type },
266303
.name = MP_QSTR_int,
267304
.print = mp_obj_int_print,
268305
.make_new = mp_obj_int_make_new,
269306
.unary_op = mp_obj_int_unary_op,
270307
.binary_op = mp_obj_int_binary_op,
308+
.locals_dict = (mp_obj_t)&int_locals_dict,
271309
};

py/qstrdefs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ Q(eval)
9696
Q(exec)
9797
Q(filter)
9898
Q(float)
99+
Q(from_bytes)
99100
Q(getattr)
100101
Q(globals)
101102
Q(hash)
@@ -127,6 +128,7 @@ Q(sum)
127128
Q(super)
128129
Q(str)
129130
Q(sys)
131+
Q(to_bytes)
130132
Q(tuple)
131133
Q(type)
132134
Q(value)

tests/basics/int-bytes.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
print((10).to_bytes(1, "little"))
2+
print((111111).to_bytes(4, "little"))
3+
print((100).to_bytes(10, "little"))
4+
print(int.from_bytes(b"\x00\x01\0\0\0\0\0\0", "little"))
5+
print(int.from_bytes(b"\x01\0\0\0\0\0\0\0", "little"))
6+
print(int.from_bytes(b"\x00\x01\0\0\0\0\0\0", "little"))

0 commit comments

Comments
 (0)