diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-11-29 18:09:12 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-11-29 18:09:12 -0500 |
| commit | f66f8ad7119207b99f00ea2ea389550ee65db5b3 (patch) | |
| tree | 5b5a7c887b311e3de2f2cb293b1228598c5b9eb1 /stdlib/metamethods.c | |
| parent | 4b5e4cd1f21582f5e5fa682ab4e4bff252963468 (diff) | |
Add serialization and deserialization
Diffstat (limited to 'stdlib/metamethods.c')
| -rw-r--r-- | stdlib/metamethods.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/stdlib/metamethods.c b/stdlib/metamethods.c index 28d97730..2871a965 100644 --- a/stdlib/metamethods.c +++ b/stdlib/metamethods.c @@ -5,14 +5,17 @@ #include "arrays.h" #include "bools.h" +#include "bytes.h" #include "channels.h" #include "functiontype.h" +#include "integers.h" #include "metamethods.h" #include "optionals.h" #include "pointers.h" #include "siphash.h" #include "tables.h" #include "text.h" +#include "types.h" #include "util.h" PUREFUNC public uint64_t generic_hash(const void *obj, const TypeInfo_t *type) @@ -51,10 +54,72 @@ public Text_t generic_as_text(const void *obj, bool colorize, const TypeInfo_t * return type->metamethods.as_text(obj, colorize, type); } +public void _serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) +{ + if (type->metamethods.serialize) + return type->metamethods.serialize(obj, out, pointers, type); + + fwrite(obj, (size_t)type->size, 1, out); +} + +public Array_t generic_serialize(const void *x, const TypeInfo_t *type) +{ + char *buf = NULL; + size_t size = 0; + FILE *stream = open_memstream(&buf, &size); + Table_t pointers = {}; + _serialize(x, stream, &pointers, type); + fclose(stream); + Array_t bytes = { + .data=GC_MALLOC_ATOMIC(size), + .length=(int64_t)size, + .stride=1, + .atomic=1, + }; + memcpy(bytes.data, buf, size); + free(buf); + return bytes; +} + +public void _deserialize(FILE *input, void *outval, Array_t *pointers, const TypeInfo_t *type) +{ + if (type->metamethods.deserialize) { + type->metamethods.deserialize(input, outval, pointers, type); + return; + } + + fread(outval, (size_t)type->size, 1, input); +} + +public void generic_deserialize(Array_t bytes, void *outval, const TypeInfo_t *type) +{ + if (bytes.stride != 1) + Array$compact(&bytes, 1); + + FILE *input = fmemopen(bytes.data, (size_t)bytes.length, "r"); + Array_t pointers = {}; + _deserialize(input, outval, &pointers, type); + fclose(input); +} + public int generic_print(const void *obj, bool colorize, const TypeInfo_t *type) { Text_t text = generic_as_text(obj, colorize, type); return Text$print(stdout, text) + printf("\n"); } +__attribute__((noreturn)) +public void cannot_serialize(const void*, FILE*, Table_t*, const TypeInfo_t *type) +{ + Text_t typestr = generic_as_text(NULL, false, type); + fail("Values of type %k cannot be serialized or deserialized!", &typestr); +} + +__attribute__((noreturn)) +public void cannot_deserialize(FILE*, void*, Array_t*, const TypeInfo_t *type) +{ + Text_t typestr = generic_as_text(NULL, false, type); + fail("Values of type %k cannot be serialized or deserialized!", &typestr); +} + // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 |
