mirror of
https://github.com/janet-lang/janet
synced 2024-11-28 19:19:53 +00:00
Merge pull request #932 from ishehadeh/feature/int-to-bytes
Add int/to-bytes: Serialize int/[su]64 to a buffer
This commit is contained in:
commit
8045e29a52
@ -238,6 +238,61 @@ JANET_CORE_FN(cfun_to_number,
|
|||||||
janet_panicf("expected int/u64 or int/s64, got %q", argv[0]);
|
janet_panicf("expected int/u64 or int/s64, got %q", argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JANET_CORE_FN(cfun_to_bytes,
|
||||||
|
"(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, 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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int reverse = 0;
|
||||||
|
if (argc > 1 && !janet_checktype(argv[1], JANET_NIL)) {
|
||||||
|
JanetKeyword endianness_kw = janet_getkeyword(argv, 1);
|
||||||
|
if (!janet_cstrcmp(endianness_kw, "le")) {
|
||||||
|
#if JANET_BIG_ENDIAN
|
||||||
|
reverse = 1;
|
||||||
|
#endif
|
||||||
|
} else if (!janet_cstrcmp(endianness_kw, "be")) {
|
||||||
|
#if JANET_LITTLE_ENDIAN
|
||||||
|
reverse = 1;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
janet_panicf("int/to-bytes: expected endianness :le, :be or nil, got %v", argv[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Code to support polymorphic comparison.
|
* Code to support polymorphic comparison.
|
||||||
* int/u64 and int/s64 support a "compare" method that allows
|
* int/u64 and int/s64 support a "compare" method that allows
|
||||||
@ -546,6 +601,7 @@ void janet_lib_inttypes(JanetTable *env) {
|
|||||||
JANET_CORE_REG("int/s64", cfun_it_s64_new),
|
JANET_CORE_REG("int/s64", cfun_it_s64_new),
|
||||||
JANET_CORE_REG("int/u64", cfun_it_u64_new),
|
JANET_CORE_REG("int/u64", cfun_it_u64_new),
|
||||||
JANET_CORE_REG("int/to-number", cfun_to_number),
|
JANET_CORE_REG("int/to-number", cfun_to_number),
|
||||||
|
JANET_CORE_REG("int/to-bytes", cfun_to_bytes),
|
||||||
JANET_REG_END
|
JANET_REG_END
|
||||||
};
|
};
|
||||||
janet_core_cfuns_ext(env, NULL, it_cfuns);
|
janet_core_cfuns_ext(env, NULL, it_cfuns);
|
||||||
|
@ -91,6 +91,39 @@
|
|||||||
"trap INT64_MIN / -1"
|
"trap INT64_MIN / -1"
|
||||||
(:/ (int/s64 "-0x8000_0000_0000_0000") -1))
|
(:/ (int/s64 "-0x8000_0000_0000_0000") -1))
|
||||||
|
|
||||||
|
# int/s64 and int/u64 serialization
|
||||||
|
(assert (deep= (int/to-bytes (u64 0)) @"\x00\x00\x00\x00\x00\x00\x00\x00"))
|
||||||
|
|
||||||
|
(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 (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))
|
||||||
|
|
||||||
|
(assert-error
|
||||||
|
"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
|
# Dynamic bindings
|
||||||
(setdyn :a 10)
|
(setdyn :a 10)
|
||||||
(assert (= 40 (with-dyns [:a 25 :b 15] (+ (dyn :a) (dyn :b)))) "dyn usage 1")
|
(assert (= 40 (with-dyns [:a 25 :b 15] (+ (dyn :a) (dyn :b)))) "dyn usage 1")
|
||||||
|
Loading…
Reference in New Issue
Block a user