mirror of
https://github.com/janet-lang/janet
synced 2025-01-12 16:40:27 +00:00
int/to-bytes: return a buffer instead of a tuple
Buffers make more sense for this function because one of their primary use cases is working with bytes. The tuple implementation was an array of floats, which is less performant and ergonomic for common operations. (i.e: bit manipulation) Buffers also have the advantage they are mutable, meaning the user can write ints to an existing buffer.
This commit is contained in:
parent
6aea7c7f70
commit
bbb3e16fd1
@ -239,13 +239,15 @@ JANET_CORE_FN(cfun_to_number,
|
||||
}
|
||||
|
||||
JANET_CORE_FN(cfun_to_bytes,
|
||||
"(int/to-bytes value &opt endianness)",
|
||||
"Convert an `int/s64` or `int/u64` into an 8-element tuple of bytes.\n"
|
||||
"the endianness paramater indicates the byte order:\n"
|
||||
"(int/to-bytes value &opt endianness buffer)",
|
||||
"Write the bytes of an `int/s64` or `int/u64` into a buffer.\n"
|
||||
"The `buffer` parameter specifies an existing buffer to write to, if unset a new buffer will be created.\n"
|
||||
"Returns the modified buffer.\n"
|
||||
"The `endianness` paramater indicates the byte order:\n"
|
||||
"- `nil` (unset): system byte order\n"
|
||||
"- `:le`: little-endian, least significant byte first\n"
|
||||
"- `:be`: big-endian, most significant byte first\n") {
|
||||
janet_arity(argc, 1, 2);
|
||||
janet_arity(argc, 1, 3);
|
||||
if (janet_is_int(argv[0]) == JANET_INT_NONE) {
|
||||
janet_panicf("int/to-bytes: expected an int/s64 or int/u64, got %q", argv[0]);
|
||||
}
|
||||
@ -266,13 +268,29 @@ JANET_CORE_FN(cfun_to_bytes,
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *bytes = janet_unwrap_abstract(argv[0]);
|
||||
Janet *bytes_tuple = janet_tuple_begin(8);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
bytes_tuple[i] = janet_wrap_integer(bytes[reverse ? 7 - i : i]);
|
||||
JanetBuffer *buffer = NULL;
|
||||
if (argc > 2 && !janet_checktype(argv[2], JANET_NIL)) {
|
||||
if (!janet_checktype(argv[2], JANET_BUFFER)) {
|
||||
janet_panicf("int/to-bytes: expected buffer or nil, got %q", argv[2]);
|
||||
}
|
||||
|
||||
buffer = janet_unwrap_buffer(argv[2]);
|
||||
janet_buffer_extra(buffer, 8);
|
||||
} else {
|
||||
buffer = janet_buffer(8);
|
||||
}
|
||||
|
||||
return janet_wrap_tuple(janet_tuple_end(bytes_tuple));
|
||||
uint8_t *bytes = janet_unwrap_abstract(argv[0]);
|
||||
if (reverse) {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
buffer->data[buffer->count + 7 - i] = bytes[i];
|
||||
}
|
||||
} else {
|
||||
memcpy(buffer->data + buffer->count, bytes, 8);
|
||||
}
|
||||
buffer->count += 8;
|
||||
|
||||
return janet_wrap_buffer(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -92,17 +92,25 @@
|
||||
(:/ (int/s64 "-0x8000_0000_0000_0000") -1))
|
||||
|
||||
# int/s64 and int/u64 serialization
|
||||
(assert (= (int/to-bytes (u64 0)) [0 0 0 0 0 0 0 0]))
|
||||
(assert (deep= (int/to-bytes (u64 0)) @"\x00\x00\x00\x00\x00\x00\x00\x00"))
|
||||
|
||||
(assert (= (int/to-bytes (i64 1) :le) [1 0 0 0 0 0 0 0]))
|
||||
(assert (= (int/to-bytes (i64 1) :be) [0 0 0 0 0 0 0 1]))
|
||||
(assert (= (int/to-bytes (i64 -1)) [0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF]))
|
||||
(assert (= (int/to-bytes (i64 -5) :be) [0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF (- 0xFF 4)]))
|
||||
(assert (deep= (int/to-bytes (i64 1) :le) @"\x01\x00\x00\x00\x00\x00\x00\x00"))
|
||||
(assert (deep= (int/to-bytes (i64 1) :be) @"\x00\x00\x00\x00\x00\x00\x00\x01"))
|
||||
(assert (deep= (int/to-bytes (i64 -1)) @"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"))
|
||||
(assert (deep= (int/to-bytes (i64 -5) :be) @"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFB"))
|
||||
|
||||
(assert (= (int/to-bytes (u64 1) :le) [1 0 0 0 0 0 0 0]))
|
||||
(assert (= (int/to-bytes (u64 1) :be) [0 0 0 0 0 0 0 1]))
|
||||
(assert (= (int/to-bytes (u64 300) :be) [0 0 0 0 0 0 0x01 0x2C]))
|
||||
(assert (deep= (int/to-bytes (u64 1) :le) @"\x01\x00\x00\x00\x00\x00\x00\x00"))
|
||||
(assert (deep= (int/to-bytes (u64 1) :be) @"\x00\x00\x00\x00\x00\x00\x00\x01"))
|
||||
(assert (deep= (int/to-bytes (u64 300) :be) @"\x00\x00\x00\x00\x00\x00\x01\x2C"))
|
||||
|
||||
# int/s64 int/u64 to existing buffer
|
||||
(let [buf1 @""
|
||||
buf2 @"abcd"]
|
||||
(assert (deep= (int/to-bytes (i64 1) :le buf1) @"\x01\x00\x00\x00\x00\x00\x00\x00"))
|
||||
(assert (deep= buf1 @"\x01\x00\x00\x00\x00\x00\x00\x00"))
|
||||
(assert (deep= (int/to-bytes (u64 300) :be buf2) @"abcd\x00\x00\x00\x00\x00\x00\x01\x2C")))
|
||||
|
||||
# int/s64 and int/u64 paramater type checking
|
||||
(assert-error
|
||||
"bad value passed to int/to-bytes"
|
||||
(int/to-bytes 1))
|
||||
@ -111,6 +119,10 @@
|
||||
"invalid endianness passed to int/to-bytes"
|
||||
(int/to-bytes (u64 0) :little))
|
||||
|
||||
(assert-error
|
||||
"invalid buffer passed to int/to-bytes"
|
||||
(int/to-bytes (u64 0) :little :buffer))
|
||||
|
||||
|
||||
# Dynamic bindings
|
||||
(setdyn :a 10)
|
||||
|
Loading…
Reference in New Issue
Block a user