From c6aa299e98a96ed12ef352a4a3430f54d949e754754ad12ab09863d07a789358 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Thu, 7 Nov 2024 09:48:33 +0300 Subject: [PATCH] Bigints --- cyac/cmd/test-vector/test-vector.c | 36 ++++- cyac/lib/atoms.h | 98 +------------- cyac/lib/dec.c | 94 +++++++------ cyac/lib/dec.h | 6 +- cyac/lib/enc.c | 35 +++-- cyac/lib/err.c | 2 + cyac/lib/err.h | 1 + gyac/atomtype_string.go | 111 +--------------- gyac/cmd/test-vector-anys/main.go | 30 ++++- gyac/cmd/test-vector-manual/main.go | 33 +++-- gyac/dec.go | 109 ++++++++------- gyac/enc.go | 145 ++++---------------- gyac/itemtype_string.go | 21 +-- gyac/reflect.go | 5 + pyac/pyac.py | 54 ++++---- pyac/test-vector.py | 11 +- spec/encoding/cont.texi | 2 +- spec/encoding/index.texi | 16 +-- spec/encoding/int.texi | 62 ++++----- spec/encoding/table.texi | 198 ++++++++++++++-------------- tyac/test-vector.tcl | 3 + tyac/tyac.tcl | 33 +++-- 22 files changed, 437 insertions(+), 668 deletions(-) diff --git a/cyac/cmd/test-vector/test-vector.c b/cyac/cmd/test-vector/test-vector.c index b682604..f6a4d66 100644 --- a/cyac/cmd/test-vector/test-vector.c +++ b/cyac/cmd/test-vector/test-vector.c @@ -117,9 +117,25 @@ main(int argc, char **argv) // NOLINT(misc-unused-parameters) &Got, buf + Off, len - Off, - YACAtomIntNeg10, - (const unsigned char *)"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", - 10)); + YACAtomNint, + (const unsigned char *)"\x8A\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", + 11)); + adder(YACAtomRawEncode( + &Got, + buf + Off, + len - Off, + YACAtomNint, + (const unsigned char + *)"\x91\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + 18)); + adder(YACAtomRawEncode( + &Got, + buf + Off, + len - Off, + YACAtomNint, + (const unsigned char + *)"\xBE\x00\xA1\xE5\xA4\x61\x28\x03\x41\x85\x6D\x4A\xD9\x08\xA6\x9E\xA5\xF3\xCC\xC1\x0C\x78\x82\x14\x2B\xB7\xD8\x01\xCC\x38\x0F\x26\xB6\xB4\xD6\x96\x32\x02\x4E\xE5\x21\xF8\xCF\xAF\xB4\x43\xD4\x9A\x2A\x3D\x0C\xC7\x3B\xB4\x75\x7E\x88\x2F\x53\x96\xED\x30\x2B\x41\x82\x10\xD0\xD4\x9D\x71\xBE\x86\xCA\x69\x9C\xF5\xEE\x3B\xD6\xD5\x7E\xD6\x58\xE6\x93\x16\x22\x96\x44\xBA\x65\x0C\x92\xD7\xF0\xD4\xDB\x29\xC3\xAD\x1D\xFA\x99\x79\x16\x6F\x4C\x6E\x79\x56\x1A\x58\xF8\xE2\xC6\x3D\x08\xDF\x4E\x22\x46\xED\x1F\x64\xD2\xD6\x13\xA1\x9D\x8C\x9A\x68\x70\xE6\x18\x8E\x2F\x3A\xD4\x0C\x03\x8F\xDA\x30\x45\x2F\x8D\xDF\xCD\x21\x2A\x6A\x97\x4B\xC2\x5E\xC6\xA0\x56\x4C\x66\xA7\xD2\x87\x50\xFF\x9D\xB4\x58\xB7\x44\x41\xE4\x9E\xE5\xE8\x2D\xBF\x49\x74\xD6\x45\x67\x8E\x0A\xD0\x31\xF9\x7A\xAB\xA8\x55\x45\x1E\xEF\x17\xA8\x9B\x42\x82\x1E\x53\x08\x16\xDD\x57\x93\xA8\x3B\x7A\x82\xE8\xED\xE8\x1E\x7F\x33\x95\x69\x1F\x76\x17\x84\xF8\xBC\x62\x79\x61\xCD\x40\x84\x5E\xE9\x08\xA4\x0B\x9D\x1F\x01\x92\x7B\x38\xEB\x1A\x7D\x4E\xFD\x60\xDB\x09\x44\xF7\xEC\x1B\x83\x2B\x7E\x6E\xB1\x83\x3F\x9A\x35\x15\x76\xAD\x5D\xE5\x71\xFA\xE8\x86\x5D\xA7\x51\x4F\x06\xB0\xFB\xF3\x8C\x1F\x2A\x85\x38\xF5\xD3\x8B\x4E\x18\x00\x1C\xCB\xB9\xDD\xCB\x48\x85\x30\xF6\x08\x6D\x14\x74\x4D\x8B\x56\x72\x16\x6E\x48\xE9\xEF\x93\x77\x25\x75\xDB\x66\xB6\xF2\x57\xC6\xFF\xAD\x6E\x2C\x29\x15\x10\xC5\xED\x02\xE1\xA8\xB2\x4B\x44\xEC\x1E\x2A\x91\x68\x62\x38\xE8\xDE\xFD\x18\xC0\x19\x98\x63\x4A\x50\x76\xA6\xB7\xF8\x5F\xC8\x1A\x1D\x61\xA1\x5B\x2C\x52\x8D\xFA\x08\x2C\xE3\xE3\xE2\xCA\x64\x9A\xC0\x48\x17\xEC\x5C\x12\x3E\x0B\x76\x1A\xB1\x03\xF7\x80\xC0\x14\xF0\x21\xBB\xEB\x7E\xA3\xB8\x6E\x0C\xA1\xC8\x33\xE3\x8E\xF5\xC8\x97\xA6\xD7\xE1\xF4\xA2\x39\x8C\x49\x0B\x3D\x65\xE2\xF4\x5C\x7F\xAE\x40\x2D\x1D\xF1\x69\x8B\x6F\xDD\xB1\x85\x48\x16\x64\x87\x1C\x26\x64\xBF\xD1\x68\x6B\x2B\x33\x72\x78\x3F\x18\x56\xF6\x24\x7A\x3F\x84\x37\xA2\x81\x8F\x68\xB7\xC4\xEA\x13\xA5\xF5\x7B\x73\xC7\x28\x70\xB6\x84\x04\x5F\x14", + 481)); adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .ints.neg adder( @@ -136,9 +152,17 @@ main(int argc, char **argv) // NOLINT(misc-unused-parameters) &Got, buf + Off, len - Off, - YACAtomIntPos11, - (const unsigned char *)"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - 11)); + YACAtomPint, + (const unsigned char *)"\x8B\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + 12)); + adder(YACAtomRawEncode( + &Got, + buf + Off, + len - Off, + YACAtomPint, + (const unsigned char + *)"\x91\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + 18)); adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .ints.pos adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .ints diff --git a/cyac/lib/atoms.h b/cyac/lib/atoms.h index df8977d..bf3c255 100644 --- a/cyac/lib/atoms.h +++ b/cyac/lib/atoms.h @@ -10,6 +10,8 @@ enum YACAtomType { YACAtomList = 0x08, YACAtomMap = 0x09, YACAtomBlob = 0x0B, + YACAtomPint = 0x0C, + YACAtomNint = 0x0D, YACAtomFloat16 = 0x10, YACAtomFloat32 = 0x11, YACAtomFloat64 = 0x12, @@ -18,102 +20,6 @@ enum YACAtomType { YACAtomTAI64 = 0x18, YACAtomTAI64N = 0x19, YACAtomTAI64NA = 0x1A, - YACAtomIntPos1 = 0x20, - YACAtomIntPos2 = 0x21, - YACAtomIntPos3 = 0x22, - YACAtomIntPos4 = 0x23, - YACAtomIntPos5 = 0x24, - YACAtomIntPos6 = 0x25, - YACAtomIntPos7 = 0x26, - YACAtomIntPos8 = 0x27, - YACAtomIntPos9 = 0x28, - YACAtomIntPos10 = 0x29, - YACAtomIntPos11 = 0x2A, - YACAtomIntPos12 = 0x2B, - YACAtomIntPos13 = 0x2C, - YACAtomIntPos14 = 0x2D, - YACAtomIntPos15 = 0x2E, - YACAtomIntPos16 = 0x2F, - YACAtomIntNeg1 = 0x30, - YACAtomIntNeg2 = 0x31, - YACAtomIntNeg3 = 0x32, - YACAtomIntNeg4 = 0x33, - YACAtomIntNeg5 = 0x34, - YACAtomIntNeg6 = 0x35, - YACAtomIntNeg7 = 0x36, - YACAtomIntNeg8 = 0x37, - YACAtomIntNeg9 = 0x38, - YACAtomIntNeg10 = 0x39, - YACAtomIntNeg11 = 0x3A, - YACAtomIntNeg12 = 0x3B, - YACAtomIntNeg13 = 0x3C, - YACAtomIntNeg14 = 0x3D, - YACAtomIntNeg15 = 0x3E, - YACAtomIntNeg16 = 0x3F, - YACAtomInt0 = 0x40, - YACAtomInt1 = 0x41, - YACAtomInt2 = 0x42, - YACAtomInt3 = 0x43, - YACAtomInt4 = 0x44, - YACAtomInt5 = 0x45, - YACAtomInt6 = 0x46, - YACAtomInt7 = 0x47, - YACAtomInt8 = 0x48, - YACAtomInt9 = 0x49, - YACAtomInt10 = 0x4A, - YACAtomInt11 = 0x4B, - YACAtomInt12 = 0x4C, - YACAtomInt13 = 0x4D, - YACAtomInt14 = 0x4E, - YACAtomInt15 = 0x4F, - YACAtomInt16 = 0x50, - YACAtomInt17 = 0x51, - YACAtomInt18 = 0x52, - YACAtomInt19 = 0x53, - YACAtomInt20 = 0x54, - YACAtomInt21 = 0x55, - YACAtomInt22 = 0x56, - YACAtomInt23 = 0x57, - YACAtomInt24 = 0x58, - YACAtomInt25 = 0x59, - YACAtomInt26 = 0x5A, - YACAtomInt27 = 0x5B, - YACAtomInt28 = 0x5C, - YACAtomInt29 = 0x5D, - YACAtomInt30 = 0x5E, - YACAtomInt31 = 0x5F, - YACAtomIntN1 = 0x60, - YACAtomIntN2 = 0x61, - YACAtomIntN3 = 0x62, - YACAtomIntN4 = 0x63, - YACAtomIntN5 = 0x64, - YACAtomIntN6 = 0x65, - YACAtomIntN7 = 0x66, - YACAtomIntN8 = 0x67, - YACAtomIntN9 = 0x68, - YACAtomIntN10 = 0x69, - YACAtomIntN11 = 0x6A, - YACAtomIntN12 = 0x6B, - YACAtomIntN13 = 0x6C, - YACAtomIntN14 = 0x6D, - YACAtomIntN15 = 0x6E, - YACAtomIntN16 = 0x6F, - YACAtomIntN17 = 0x70, - YACAtomIntN18 = 0x71, - YACAtomIntN19 = 0x72, - YACAtomIntN20 = 0x73, - YACAtomIntN21 = 0x74, - YACAtomIntN22 = 0x75, - YACAtomIntN23 = 0x76, - YACAtomIntN24 = 0x77, - YACAtomIntN25 = 0x78, - YACAtomIntN26 = 0x79, - YACAtomIntN27 = 0x7A, - YACAtomIntN28 = 0x7B, - YACAtomIntN29 = 0x7C, - YACAtomIntN30 = 0x7D, - YACAtomIntN31 = 0x7E, - YACAtomIntN32 = 0x7F, YACAtomStrings = 0x80, YACAtomIsUTF8 = 0x40, diff --git a/cyac/lib/dec.c b/cyac/lib/dec.c index abd04ec..d9327a0 100644 --- a/cyac/lib/dec.c +++ b/cyac/lib/dec.c @@ -15,6 +15,7 @@ #include #include +#include #include "atoms.h" #include "dec.h" @@ -23,7 +24,7 @@ #include "utf8.h" enum YACErr -YACAtomDecode( +YACAtomDecode( // NOLINT(misc-no-recursion) size_t *got, struct YACAtom *atom, const unsigned char *buf, @@ -94,53 +95,6 @@ YACAtomDecode( return YACErrNo; } - if ((atom->tag >= YACAtomInt0) && (atom->tag < YACAtomInt0 + 32)) { - atom->typ = YACItemPint; - atom->v.pint = (uint64_t)(atom->tag - YACAtomInt0); - return YACErrNo; - } - if ((atom->tag >= YACAtomIntN1) && (atom->tag < YACAtomIntN1 + 32)) { - atom->typ = YACItemNint; - atom->v.nint = -1 - (int64_t)(atom->tag - YACAtomIntN1); - return YACErrNo; - } - switch (atom->tag & (uint8_t)0xF0) { - case YACAtomIntPos1: - case YACAtomIntNeg1: { - atom->typ = ((atom->tag & (uint8_t)YACAtomIntNeg1) == YACAtomIntNeg1) ? - YACItemNint : - YACItemPint; - const size_t l = (atom->tag & (uint8_t)0x0F) + 1; - (*got) += l; - if (len < (*got)) { - return YACErrNotEnough; - } - if (buf[1] == 0) { - return YACErrIntNonMinimal; - } - if (l > 8) { - atom->typ = YACItemRaw; - atom->v.str.len = l; - atom->v.str.ptr = buf + 1; - } else { - atom->v.pint = yacFromBE(buf + 1, l); - if ((atom->v.pint) < 32) { - return YACErrIntNonMinimal; - } - if (atom->typ == YACItemNint) { - if (atom->v.pint >= ((uint64_t)1 << (uint8_t)63)) { - atom->typ = YACItemRaw; - atom->v.str.len = l; - atom->v.str.ptr = buf + 1; - } else { - atom->v.nint = -1 - (int64_t)(atom->v.pint); - } - } - } - return YACErrNo; - } - } - switch (atom->tag) { case YACAtomEOC: atom->typ = YACItemEOC; @@ -183,6 +137,50 @@ YACAtomDecode( break; } + case YACAtomPint: + case YACAtomNint: { + atom->typ = (atom->tag == YACAtomPint) ? YACItemPint : YACItemNint; + size_t binGot = 0; + struct YACAtom bin; + memset(&bin, 0, sizeof(struct YACAtom)); + enum YACErr err = YACAtomDecode(&binGot, &bin, buf + 1, len - 1); + if (err != YACErrNo) { + return err; + } + (*got) += binGot; + if (bin.typ != YACItemBin) { + return YACErrIntNonBin; + } + if (bin.v.str.len == 0) { + if (atom->typ == YACItemPint) { + atom->v.pint = 0; + } else { + atom->v.nint = -1; + } + return YACErrNo; + } + if (bin.v.str.ptr[0] == 0) { + return YACErrIntNonMinimal; + } + if (bin.v.str.len > 8) { + atom->typ = YACItemRaw; + atom->v.str.len = binGot; + atom->v.str.ptr = buf + 1; + return YACErrNo; + } + atom->v.pint = yacFromBE(bin.v.str.ptr, bin.v.str.len); + if (atom->typ == YACItemNint) { + if (atom->v.pint >= ((uint64_t)1 << (uint8_t)63)) { + atom->typ = YACItemRaw; + atom->v.str.len = binGot; + atom->v.str.ptr = buf + 1; + } else { + atom->v.nint = -1 - (int64_t)(atom->v.pint); + } + } + return YACErrNo; + } + case YACAtomFloat16: case YACAtomFloat32: case YACAtomFloat64: diff --git a/cyac/lib/dec.h b/cyac/lib/dec.h index c06d8ab..c582ac7 100644 --- a/cyac/lib/dec.h +++ b/cyac/lib/dec.h @@ -73,9 +73,9 @@ enum YACItemType { // @code{.chunkLen} is the length of the chunk. @code{.chunks} is // the number of chunks, including the terminating binary string. // @item .v.str -// @code{.ptr} points to the start of the binary/UTF-8 string. -// @code{.len} is its length in bytes. TAI64 datetimes are stored as -// strings too. Raw values use it as a payload. +// @code{.ptr} points to the start of the binary/UTF-8/TAI64* +// string. @code{.len} is its length in bytes. +// Raw values use it as a payload. // @end table // @end deftp struct YACAtom { diff --git a/cyac/lib/enc.c b/cyac/lib/enc.c index 81df522..36cbbe2 100644 --- a/cyac/lib/enc.c +++ b/cyac/lib/enc.c @@ -74,31 +74,28 @@ YACAtomUUIDEncode( static bool yacAtomIntEncode(size_t *len, unsigned char *buf, const size_t cap, const uint64_t v) { - if (v < 32) { - (*len) = 1; - if (cap < 1) { - return false; - } - buf[0] = (unsigned char)v; - return true; + if (cap < 1) { + return false; + } + if (v == 0) { + const bool ok = + YACAtomBinEncode(len, buf + 1, cap - 1, (const unsigned char *)"", 0); + (*len)++; + return ok; } - size_t bits = 8; size_t l = 0; for (;;) { - if (v < ((uint64_t)1 << bits)) { + if (v < ((uint64_t)1 << ((l + 1) * 8))) { break; } l++; - bits += 8; } - if (cap < (1 + l)) { - return false; - } - buf[0] = (unsigned char)l; l++; - yacToBE(buf + 1, l, v); - (*len) = 1 + l; - return true; + unsigned char be[8] = {0}; + yacToBE(be, l, v); + const bool ok = YACAtomBinEncode(len, buf + 1, cap - 1, be, l); + (*len)++; + return ok; } bool @@ -106,7 +103,7 @@ YACAtomUintEncode(size_t *len, unsigned char *buf, const size_t cap, const uint6 { bool ok = yacAtomIntEncode(len, buf, cap, v); if (ok) { - buf[0] |= (unsigned char)((v < 32) ? YACAtomInt0 : YACAtomIntPos1); + buf[0] = YACAtomPint; } return ok; } @@ -120,7 +117,7 @@ YACAtomSintEncode(size_t *len, unsigned char *buf, const size_t cap, const int64 const uint64_t vp = (uint64_t)(-(v + 1)); bool ok = yacAtomIntEncode(len, buf, cap, vp); if (ok) { - buf[0] |= (unsigned char)((vp < 32) ? YACAtomIntN1 : YACAtomIntNeg1); + buf[0] = YACAtomNint; } return ok; } diff --git a/cyac/lib/err.c b/cyac/lib/err.c index 6f54748..8e199c5 100644 --- a/cyac/lib/err.c +++ b/cyac/lib/err.c @@ -16,6 +16,8 @@ YACErr2Str(const enum YACErr err) return "LenTooBig"; case YACErrBadUTF8: return "BadUTF8"; + case YACErrIntNonBin: + return "IntNonBin"; case YACErrIntNonMinimal: return "IntNonMinimal"; case YACErrBlobBadAtom: diff --git a/cyac/lib/err.h b/cyac/lib/err.h index 7ee9570..f3b8c28 100644 --- a/cyac/lib/err.h +++ b/cyac/lib/err.h @@ -48,6 +48,7 @@ enum YACErr { YACErrUnknownType, YACErrLenTooBig, YACErrBadUTF8, + YACErrIntNonBin, YACErrIntNonMinimal, YACErrBlobBadAtom, YACErrBlobBadTerm, diff --git a/gyac/atomtype_string.go b/gyac/atomtype_string.go index ebb5f94..dab86b4 100644 --- a/gyac/atomtype_string.go +++ b/gyac/atomtype_string.go @@ -16,6 +16,8 @@ func _() { _ = x[AtomList-8] _ = x[AtomMap-9] _ = x[AtomBlob-11] + _ = x[AtomPInt-12] + _ = x[AtomNInt-13] _ = x[AtomFloat16-16] _ = x[AtomFloat32-17] _ = x[AtomFloat64-18] @@ -24,119 +26,22 @@ func _() { _ = x[AtomTAI64-24] _ = x[AtomTAI64N-25] _ = x[AtomTAI64NA-26] - _ = x[AtomIntPos1-32] - _ = x[AtomIntPos2-33] - _ = x[AtomIntPos3-34] - _ = x[AtomIntPos4-35] - _ = x[AtomIntPos5-36] - _ = x[AtomIntPos6-37] - _ = x[AtomIntPos7-38] - _ = x[AtomIntPos8-39] - _ = x[AtomIntPos9-40] - _ = x[AtomIntPos10-41] - _ = x[AtomIntPos11-42] - _ = x[AtomIntPos12-43] - _ = x[AtomIntPos13-44] - _ = x[AtomIntPos14-45] - _ = x[AtomIntPos15-46] - _ = x[AtomIntPos16-47] - _ = x[AtomIntNeg1-48] - _ = x[AtomIntNeg2-49] - _ = x[AtomIntNeg3-50] - _ = x[AtomIntNeg4-51] - _ = x[AtomIntNeg5-52] - _ = x[AtomIntNeg6-53] - _ = x[AtomIntNeg7-54] - _ = x[AtomIntNeg8-55] - _ = x[AtomIntNeg9-56] - _ = x[AtomIntNeg10-57] - _ = x[AtomIntNeg11-58] - _ = x[AtomIntNeg12-59] - _ = x[AtomIntNeg13-60] - _ = x[AtomIntNeg14-61] - _ = x[AtomIntNeg15-62] - _ = x[AtomIntNeg16-63] - _ = x[AtomInt0-64] - _ = x[AtomInt1-65] - _ = x[AtomInt2-66] - _ = x[AtomInt3-67] - _ = x[AtomInt4-68] - _ = x[AtomInt5-69] - _ = x[AtomInt6-70] - _ = x[AtomInt7-71] - _ = x[AtomInt8-72] - _ = x[AtomInt9-73] - _ = x[AtomInt10-74] - _ = x[AtomInt11-75] - _ = x[AtomInt12-76] - _ = x[AtomInt13-77] - _ = x[AtomInt14-78] - _ = x[AtomInt15-79] - _ = x[AtomInt16-80] - _ = x[AtomInt17-81] - _ = x[AtomInt18-82] - _ = x[AtomInt19-83] - _ = x[AtomInt20-84] - _ = x[AtomInt21-85] - _ = x[AtomInt22-86] - _ = x[AtomInt23-87] - _ = x[AtomInt24-88] - _ = x[AtomInt25-89] - _ = x[AtomInt26-90] - _ = x[AtomInt27-91] - _ = x[AtomInt28-92] - _ = x[AtomInt29-93] - _ = x[AtomInt30-94] - _ = x[AtomInt31-95] - _ = x[AtomIntN1-96] - _ = x[AtomIntN2-97] - _ = x[AtomIntN3-98] - _ = x[AtomIntN4-99] - _ = x[AtomIntN5-100] - _ = x[AtomIntN6-101] - _ = x[AtomIntN7-102] - _ = x[AtomIntN8-103] - _ = x[AtomIntN9-104] - _ = x[AtomIntN10-105] - _ = x[AtomIntN11-106] - _ = x[AtomIntN12-107] - _ = x[AtomIntN13-108] - _ = x[AtomIntN14-109] - _ = x[AtomIntN15-110] - _ = x[AtomIntN16-111] - _ = x[AtomIntN17-112] - _ = x[AtomIntN18-113] - _ = x[AtomIntN19-114] - _ = x[AtomIntN20-115] - _ = x[AtomIntN21-116] - _ = x[AtomIntN22-117] - _ = x[AtomIntN23-118] - _ = x[AtomIntN24-119] - _ = x[AtomIntN25-120] - _ = x[AtomIntN26-121] - _ = x[AtomIntN27-122] - _ = x[AtomIntN28-123] - _ = x[AtomIntN29-124] - _ = x[AtomIntN30-125] - _ = x[AtomIntN31-126] - _ = x[AtomIntN32-127] } const ( _AtomType_name_0 = "AtomEOCAtomNILAtomFalseAtomTrueAtomUUID" _AtomType_name_1 = "AtomListAtomMap" - _AtomType_name_2 = "AtomBlob" + _AtomType_name_2 = "AtomBlobAtomPIntAtomNInt" _AtomType_name_3 = "AtomFloat16AtomFloat32AtomFloat64AtomFloat128AtomFloat256" _AtomType_name_4 = "AtomTAI64AtomTAI64NAtomTAI64NA" - _AtomType_name_5 = "AtomIntPos1AtomIntPos2AtomIntPos3AtomIntPos4AtomIntPos5AtomIntPos6AtomIntPos7AtomIntPos8AtomIntPos9AtomIntPos10AtomIntPos11AtomIntPos12AtomIntPos13AtomIntPos14AtomIntPos15AtomIntPos16AtomIntNeg1AtomIntNeg2AtomIntNeg3AtomIntNeg4AtomIntNeg5AtomIntNeg6AtomIntNeg7AtomIntNeg8AtomIntNeg9AtomIntNeg10AtomIntNeg11AtomIntNeg12AtomIntNeg13AtomIntNeg14AtomIntNeg15AtomIntNeg16AtomInt0AtomInt1AtomInt2AtomInt3AtomInt4AtomInt5AtomInt6AtomInt7AtomInt8AtomInt9AtomInt10AtomInt11AtomInt12AtomInt13AtomInt14AtomInt15AtomInt16AtomInt17AtomInt18AtomInt19AtomInt20AtomInt21AtomInt22AtomInt23AtomInt24AtomInt25AtomInt26AtomInt27AtomInt28AtomInt29AtomInt30AtomInt31AtomIntN1AtomIntN2AtomIntN3AtomIntN4AtomIntN5AtomIntN6AtomIntN7AtomIntN8AtomIntN9AtomIntN10AtomIntN11AtomIntN12AtomIntN13AtomIntN14AtomIntN15AtomIntN16AtomIntN17AtomIntN18AtomIntN19AtomIntN20AtomIntN21AtomIntN22AtomIntN23AtomIntN24AtomIntN25AtomIntN26AtomIntN27AtomIntN28AtomIntN29AtomIntN30AtomIntN31AtomIntN32" ) var ( _AtomType_index_0 = [...]uint8{0, 7, 14, 23, 31, 39} _AtomType_index_1 = [...]uint8{0, 8, 15} + _AtomType_index_2 = [...]uint8{0, 8, 16, 24} _AtomType_index_3 = [...]uint8{0, 11, 22, 33, 45, 57} _AtomType_index_4 = [...]uint8{0, 9, 19, 30} - _AtomType_index_5 = [...]uint16{0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 111, 123, 135, 147, 159, 171, 183, 194, 205, 216, 227, 238, 249, 260, 271, 282, 294, 306, 318, 330, 342, 354, 366, 374, 382, 390, 398, 406, 414, 422, 430, 438, 446, 455, 464, 473, 482, 491, 500, 509, 518, 527, 536, 545, 554, 563, 572, 581, 590, 599, 608, 617, 626, 635, 644, 653, 662, 671, 680, 689, 698, 707, 716, 725, 735, 745, 755, 765, 775, 785, 795, 805, 815, 825, 835, 845, 855, 865, 875, 885, 895, 905, 915, 925, 935, 945, 955} ) func (i AtomType) String() string { @@ -146,17 +51,15 @@ func (i AtomType) String() string { case 8 <= i && i <= 9: i -= 8 return _AtomType_name_1[_AtomType_index_1[i]:_AtomType_index_1[i+1]] - case i == 11: - return _AtomType_name_2 + case 11 <= i && i <= 13: + i -= 11 + return _AtomType_name_2[_AtomType_index_2[i]:_AtomType_index_2[i+1]] case 16 <= i && i <= 20: i -= 16 return _AtomType_name_3[_AtomType_index_3[i]:_AtomType_index_3[i+1]] case 24 <= i && i <= 26: i -= 24 return _AtomType_name_4[_AtomType_index_4[i]:_AtomType_index_4[i+1]] - case 32 <= i && i <= 127: - i -= 32 - return _AtomType_name_5[_AtomType_index_5[i]:_AtomType_index_5[i+1]] default: return "AtomType(" + strconv.FormatInt(int64(i), 10) + ")" } diff --git a/gyac/cmd/test-vector-anys/main.go b/gyac/cmd/test-vector-anys/main.go index 0dadf2b..1cc4e8c 100644 --- a/gyac/cmd/test-vector-anys/main.go +++ b/gyac/cmd/test-vector-anys/main.go @@ -4,13 +4,36 @@ import ( "bytes" "encoding/hex" "fmt" + "math/big" "time" "github.com/google/uuid" "go.cypherpunks.su/yac/gyac" ) +func mustHexDec(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} + func main() { + bigint80 := big.NewInt(0) + bigint80.SetBytes(mustHexDec("0100000000000000000000")) + bigintFF := big.NewInt(0) + bigintFF.SetBytes(mustHexDec("0100000000000000000000000000000000")) + bigintN80 := big.NewInt(0) + bigintN80.SetBytes(mustHexDec("0100000000000000000000")) + bigintN80 = bigintN80.Neg(bigintN80) + bigintNFF := big.NewInt(0) + bigintNFF.SetBytes(mustHexDec("0100000000000000000000000000000001")) + bigintNFF = bigintNFF.Neg(bigintNFF) + bigintN := big.NewInt(0) + bigintN.SetBytes(mustHexDec("e5a461280341856d4ad908a69ea5f3ccc10c7882142bb7d801cc380f26b6b4d69632024ee521f8cfafb443d49a2a3d0cc73bb4757e882f5396ed302b418210d0d49d71be86ca699cf5ee3bd6d57ed658e69316229644ba650c92d7f0d4db29c3ad1dfa9979166f4c6e79561a58f8e2c63d08df4e2246ed1f64d2d613a19d8c9a6870e6188e2f3ad40c038fda30452f8ddfcd212a6a974bc25ec6a0564c66a7d28750ff9db458b74441e49ee5e82dbf4974d645678e0ad031f97aaba855451eef17a89b42821e530816dd5793a83b7a82e8ede81e7f3395691f761784f8bc627961cd40845ee908a40b9d1f01927b38eb1a7d4efd60db0944f7ec1b832b7e6eb1833f9a351576ad5de571fae8865da7514f06b0fbf38c1f2a8538f5d38b4e18001ccbb9ddcb488530f6086d14744d8b5672166e48e9ef93772575db66b6f257c6ffad6e2c291510c5ed02e1a8b24b44ec1e2a91686238e8defd18c01998634a5076a6b7f85fc81a1d61a15b2c528dfa082ce3e3e2ca649ac04817ec5c123e0b761ab103f780c014f021bbeb7ea3b86e0ca1c833e38ef5c897a6d7e1f4a2398c490b3d65e2f45c7fae402d1df1698b6fddb185481664871c2664bfd1686b2b3372783f1856f6247a3f8437a2818f68b7c4ea13a5f57b73c72870b684045f15")) + bigintN = bigintN.Neg(bigintN) + data := map[string]any{ "ints": map[string]any{ "pos": []any{ @@ -21,7 +44,8 @@ func main() { uint64(123), uint64(1234), uint64(12345678), - &gyac.Raw{T: gyac.AtomIntPos11, V: []byte("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")}, + bigint80, + bigintFF, }, "neg": []any{ int64(-1), @@ -31,7 +55,9 @@ func main() { int64(-123), int64(-1234), int64(-12345678), - &gyac.Raw{T: gyac.AtomIntNeg10, V: []byte("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff")}, + bigintN80, + bigintNFF, + bigintN, }, }, "nil": nil, diff --git a/gyac/cmd/test-vector-manual/main.go b/gyac/cmd/test-vector-manual/main.go index 5f7b0f4..64fa841 100644 --- a/gyac/cmd/test-vector-manual/main.go +++ b/gyac/cmd/test-vector-manual/main.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/hex" "fmt" + "math/big" "time" "github.com/google/uuid" @@ -11,6 +12,14 @@ import ( "go.cypherpunks.su/yac/gyac" ) +func mustHexDec(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} + func main() { buf := make([]byte, 0, 68*1024) { @@ -88,10 +97,17 @@ func main() { buf = gyac.AtomIntEncode(buf, -123) buf = gyac.AtomIntEncode(buf, -1234) buf = gyac.AtomIntEncode(buf, -12345678) - buf = gyac.AtomRawEncode(buf, &gyac.Raw{ - T: gyac.AtomIntNeg10, - V: []byte("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"), - }) + + b := big.NewInt(0) + b.SetBytes(mustHexDec("0100000000000000000000")) + b = b.Neg(b) + buf = gyac.AtomBigIntEncode(buf, b) + b.SetBytes(mustHexDec("0100000000000000000000000000000001")) + b = b.Neg(b) + buf = gyac.AtomBigIntEncode(buf, b) + b.SetBytes(mustHexDec("e5a461280341856d4ad908a69ea5f3ccc10c7882142bb7d801cc380f26b6b4d69632024ee521f8cfafb443d49a2a3d0cc73bb4757e882f5396ed302b418210d0d49d71be86ca699cf5ee3bd6d57ed658e69316229644ba650c92d7f0d4db29c3ad1dfa9979166f4c6e79561a58f8e2c63d08df4e2246ed1f64d2d613a19d8c9a6870e6188e2f3ad40c038fda30452f8ddfcd212a6a974bc25ec6a0564c66a7d28750ff9db458b74441e49ee5e82dbf4974d645678e0ad031f97aaba855451eef17a89b42821e530816dd5793a83b7a82e8ede81e7f3395691f761784f8bc627961cd40845ee908a40b9d1f01927b38eb1a7d4efd60db0944f7ec1b832b7e6eb1833f9a351576ad5de571fae8865da7514f06b0fbf38c1f2a8538f5d38b4e18001ccbb9ddcb488530f6086d14744d8b5672166e48e9ef93772575db66b6f257c6ffad6e2c291510c5ed02e1a8b24b44ec1e2a91686238e8defd18c01998634a5076a6b7f85fc81a1d61a15b2c528dfa082ce3e3e2ca649ac04817ec5c123e0b761ab103f780c014f021bbeb7ea3b86e0ca1c833e38ef5c897a6d7e1f4a2398c490b3d65e2f45c7fae402d1df1698b6fddb185481664871c2664bfd1686b2b3372783f1856f6247a3f8437a2818f68b7c4ea13a5f57b73c72870b684045f15")) + b = b.Neg(b) + buf = gyac.AtomBigIntEncode(buf, b) buf = gyac.AtomEOCEncode(buf) } { @@ -104,10 +120,11 @@ func main() { buf = gyac.AtomUIntEncode(buf, 123) buf = gyac.AtomUIntEncode(buf, 1234) buf = gyac.AtomUIntEncode(buf, 12345678) - buf = gyac.AtomRawEncode(buf, &gyac.Raw{ - T: gyac.AtomIntPos11, - V: []byte("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), - }) + b := big.NewInt(0) + b.SetBytes(mustHexDec("0100000000000000000000")) + buf = gyac.AtomBigIntEncode(buf, b) + b.SetBytes(mustHexDec("0100000000000000000000000000000000")) + buf = gyac.AtomBigIntEncode(buf, b) buf = gyac.AtomEOCEncode(buf) } buf = gyac.AtomEOCEncode(buf) diff --git a/gyac/dec.go b/gyac/dec.go index 8609155..d9dc3e6 100644 --- a/gyac/dec.go +++ b/gyac/dec.go @@ -19,6 +19,7 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" "strings" "unicode/utf8" "unsafe" @@ -36,6 +37,7 @@ const ( ItemUUID ItemUInt ItemInt + ItemBigInt ItemList ItemMap ItemBlob @@ -138,55 +140,6 @@ func AtomDecode(buf []byte) (item *Item, off int, err error) { } return } - if AtomType(item.T) >= AtomInt0 && AtomType(item.T) < AtomInt0+32 { - item.V = uint64(item.T - byte(AtomInt0)) - item.T = byte(ItemUInt) - return - } - if AtomType(item.T) >= AtomIntN1 && AtomType(item.T) < AtomIntN1+32 { - item.V = -1 - int64(item.T-byte(AtomIntN1)) - item.T = byte(ItemInt) - return - } - switch item.T & 0xF0 { - case byte(AtomIntPos1), byte(AtomIntNeg1): - l := int((item.T & 0x0F) + 1) - if (item.T & byte(AtomIntNeg1)) == byte(AtomIntNeg1) { - item.T = byte(ItemInt) - } else { - item.T = byte(ItemUInt) - } - off += l - if len(buf) < off { - err = ErrNotEnough - return - } - if buf[1] == 0 { - err = ErrIntNonMinimal - return - } - if l > 8 { - item.T = byte(ItemRaw) - item.V = &Raw{T: AtomType(buf[0]), V: buf[1 : 1+l]} - return - } - v := FromBE(buf[1 : 1+l]) - if v < 32 { - err = ErrIntNonMinimal - return - } - if item.Typ() == ItemUInt { - item.V = v - } else { - if v >= (1 << 63) { - item.T = byte(ItemRaw) - item.V = &Raw{T: AtomType(buf[0]), V: buf[1 : 1+l]} - } else { - item.V = -1 - int64(v) - } - } - return - } switch AtomType(item.T) { case AtomEOC: item.T = byte(ItemEOC) @@ -226,6 +179,64 @@ func AtomDecode(buf []byte) (item *Item, off int, err error) { chunkLen++ item.V = chunkLen + case AtomPInt, AtomNInt: + if AtomType(item.T) == AtomPInt { + item.T = byte(ItemUInt) + } else { + item.T = byte(ItemInt) + } + var bin *Item + var binOff int + bin, binOff, err = AtomDecode(buf[1:]) + off += binOff + if err != nil { + return + } + if ItemType(bin.T) != ItemBin { + err = errors.New("wrong int value") + return + } + raw := bin.V.([]byte) + if len(raw) == 0 { + if item.Typ() == ItemUInt { + item.V = uint64(0) + } else { + item.V = int64(-1) + } + return + } + if raw[0] == 0 { + err = ErrIntNonMinimal + return + } + if len(raw) > 8 { + bi := big.NewInt(0) + bi = bi.SetBytes(raw) + if item.Typ() == ItemInt { + n1 := big.NewInt(-1) + bi = bi.Sub(n1, bi) + } + item.T = byte(ItemBigInt) + item.V = bi + return + } + v := FromBE(raw) + if item.Typ() == ItemUInt { + item.V = v + } else { + if v >= (1 << 63) { + bi := big.NewInt(0) + bi = bi.SetBytes(raw) + n1 := big.NewInt(-1) + bi = bi.Sub(n1, bi) + item.T = byte(ItemBigInt) + item.V = bi + } else { + item.V = -1 - int64(v) + } + } + return + case AtomFloat16, AtomFloat32, AtomFloat64, AtomFloat128, AtomFloat256: var l int switch AtomType(item.T) { diff --git a/gyac/enc.go b/gyac/enc.go index 05ffc13..38afc9c 100644 --- a/gyac/enc.go +++ b/gyac/enc.go @@ -16,11 +16,14 @@ package gyac import ( + "math/big" "sort" "github.com/google/uuid" ) +var BigIntZero = big.NewInt(0) + type AtomType byte //go:generate stringer -type=AtomType @@ -33,6 +36,8 @@ const ( AtomList AtomType = 0x08 AtomMap AtomType = 0x09 AtomBlob AtomType = 0x0B + AtomPInt AtomType = 0x0C + AtomNInt AtomType = 0x0D AtomFloat16 AtomType = 0x10 AtomFloat32 AtomType = 0x11 AtomFloat64 AtomType = 0x12 @@ -41,102 +46,6 @@ const ( AtomTAI64 AtomType = 0x18 AtomTAI64N AtomType = 0x19 AtomTAI64NA AtomType = 0x1A - AtomIntPos1 AtomType = 0x20 - AtomIntPos2 AtomType = 0x21 - AtomIntPos3 AtomType = 0x22 - AtomIntPos4 AtomType = 0x23 - AtomIntPos5 AtomType = 0x24 - AtomIntPos6 AtomType = 0x25 - AtomIntPos7 AtomType = 0x26 - AtomIntPos8 AtomType = 0x27 - AtomIntPos9 AtomType = 0x28 - AtomIntPos10 AtomType = 0x29 - AtomIntPos11 AtomType = 0x2A - AtomIntPos12 AtomType = 0x2B - AtomIntPos13 AtomType = 0x2C - AtomIntPos14 AtomType = 0x2D - AtomIntPos15 AtomType = 0x2E - AtomIntPos16 AtomType = 0x2F - AtomIntNeg1 AtomType = 0x30 - AtomIntNeg2 AtomType = 0x31 - AtomIntNeg3 AtomType = 0x32 - AtomIntNeg4 AtomType = 0x33 - AtomIntNeg5 AtomType = 0x34 - AtomIntNeg6 AtomType = 0x35 - AtomIntNeg7 AtomType = 0x36 - AtomIntNeg8 AtomType = 0x37 - AtomIntNeg9 AtomType = 0x38 - AtomIntNeg10 AtomType = 0x39 - AtomIntNeg11 AtomType = 0x3A - AtomIntNeg12 AtomType = 0x3B - AtomIntNeg13 AtomType = 0x3C - AtomIntNeg14 AtomType = 0x3D - AtomIntNeg15 AtomType = 0x3E - AtomIntNeg16 AtomType = 0x3F - AtomInt0 AtomType = 0x40 - AtomInt1 AtomType = 0x41 - AtomInt2 AtomType = 0x42 - AtomInt3 AtomType = 0x43 - AtomInt4 AtomType = 0x44 - AtomInt5 AtomType = 0x45 - AtomInt6 AtomType = 0x46 - AtomInt7 AtomType = 0x47 - AtomInt8 AtomType = 0x48 - AtomInt9 AtomType = 0x49 - AtomInt10 AtomType = 0x4A - AtomInt11 AtomType = 0x4B - AtomInt12 AtomType = 0x4C - AtomInt13 AtomType = 0x4D - AtomInt14 AtomType = 0x4E - AtomInt15 AtomType = 0x4F - AtomInt16 AtomType = 0x50 - AtomInt17 AtomType = 0x51 - AtomInt18 AtomType = 0x52 - AtomInt19 AtomType = 0x53 - AtomInt20 AtomType = 0x54 - AtomInt21 AtomType = 0x55 - AtomInt22 AtomType = 0x56 - AtomInt23 AtomType = 0x57 - AtomInt24 AtomType = 0x58 - AtomInt25 AtomType = 0x59 - AtomInt26 AtomType = 0x5A - AtomInt27 AtomType = 0x5B - AtomInt28 AtomType = 0x5C - AtomInt29 AtomType = 0x5D - AtomInt30 AtomType = 0x5E - AtomInt31 AtomType = 0x5F - AtomIntN1 AtomType = 0x60 - AtomIntN2 AtomType = 0x61 - AtomIntN3 AtomType = 0x62 - AtomIntN4 AtomType = 0x63 - AtomIntN5 AtomType = 0x64 - AtomIntN6 AtomType = 0x65 - AtomIntN7 AtomType = 0x66 - AtomIntN8 AtomType = 0x67 - AtomIntN9 AtomType = 0x68 - AtomIntN10 AtomType = 0x69 - AtomIntN11 AtomType = 0x6A - AtomIntN12 AtomType = 0x6B - AtomIntN13 AtomType = 0x6C - AtomIntN14 AtomType = 0x6D - AtomIntN15 AtomType = 0x6E - AtomIntN16 AtomType = 0x6F - AtomIntN17 AtomType = 0x70 - AtomIntN18 AtomType = 0x71 - AtomIntN19 AtomType = 0x72 - AtomIntN20 AtomType = 0x73 - AtomIntN21 AtomType = 0x74 - AtomIntN22 AtomType = 0x75 - AtomIntN23 AtomType = 0x76 - AtomIntN24 AtomType = 0x77 - AtomIntN25 AtomType = 0x78 - AtomIntN26 AtomType = 0x79 - AtomIntN27 AtomType = 0x7A - AtomIntN28 AtomType = 0x7B - AtomIntN29 AtomType = 0x7C - AtomIntN30 AtomType = 0x7D - AtomIntN31 AtomType = 0x7E - AtomIntN32 AtomType = 0x7F AtomStrings = 0x80 AtomIsUTF8 = 0x40 @@ -162,46 +71,42 @@ func AtomUUIDEncode(buf []byte, v uuid.UUID) []byte { } func atomUintEncode(v uint64) (buf []byte) { - if v < 32 { - return []byte{byte(v)} + if v == 0 { + return AtomBinEncode(nil, []byte{}) } - bits := 8 l := 0 for { - if v < (1 << bits) { + if v < (1 << ((l + 1) * 8)) { break } l++ - bits += 8 } - buf = make([]byte, 1+l+1) - buf[0] = byte(l) - ToBE(buf[1:], v) - return + buf = make([]byte, l+1) + ToBE(buf, v) + return AtomBinEncode(nil, buf) } func AtomUIntEncode(buf []byte, v uint64) []byte { - b := atomUintEncode(v) - if v < 32 { - b[0] |= byte(AtomInt0) - } else { - b[0] |= byte(AtomIntPos1) - } - return append(buf, b...) + return append(buf, append([]byte{byte(AtomPInt)}, atomUintEncode(v)...)...) } func AtomIntEncode(buf []byte, v int64) []byte { if v >= 0 { return AtomUIntEncode(buf, uint64(v)) } - vp := uint64(-(v + 1)) - b := atomUintEncode(vp) - if vp < 32 { - b[0] |= byte(AtomIntN1) - } else { - b[0] |= byte(AtomIntNeg1) + return append(buf, append([]byte{byte(AtomNInt)}, + atomUintEncode(uint64(-(v+1)))...)...) +} + +func AtomBigIntEncode(buf []byte, v *big.Int) []byte { + // TODO: fallback to U?IntEncode for small values + if v.Cmp(BigIntZero) >= 0 { + return append(buf, AtomBinEncode([]byte{byte(AtomPInt)}, v.Bytes())...) } - return append(buf, b...) + n1 := big.NewInt(-1) + v = v.Abs(v) + v = v.Add(v, n1) + return append(buf, AtomBinEncode([]byte{byte(AtomNInt)}, v.Bytes())...) } func AtomListEncode(buf []byte) []byte { @@ -284,6 +189,8 @@ func EncodeItem(buf []byte, item *Item) []byte { return AtomUIntEncode(buf, item.V.(uint64)) case ItemInt: return AtomIntEncode(buf, item.V.(int64)) + case ItemBigInt: + return AtomBigIntEncode(buf, item.V.(*big.Int)) case ItemList: buf = AtomListEncode(buf) for _, v := range item.V.([]*Item) { diff --git a/gyac/itemtype_string.go b/gyac/itemtype_string.go index 7016888..cd99d50 100644 --- a/gyac/itemtype_string.go +++ b/gyac/itemtype_string.go @@ -14,19 +14,20 @@ func _() { _ = x[ItemUUID-3] _ = x[ItemUInt-4] _ = x[ItemInt-5] - _ = x[ItemList-6] - _ = x[ItemMap-7] - _ = x[ItemBlob-8] - _ = x[ItemFloat-9] - _ = x[ItemTAI64-10] - _ = x[ItemBin-11] - _ = x[ItemStr-12] - _ = x[ItemRaw-13] + _ = x[ItemBigInt-6] + _ = x[ItemList-7] + _ = x[ItemMap-8] + _ = x[ItemBlob-9] + _ = x[ItemFloat-10] + _ = x[ItemTAI64-11] + _ = x[ItemBin-12] + _ = x[ItemStr-13] + _ = x[ItemRaw-14] } -const _ItemType_name = "ItemEOCItemNILItemBoolItemUUIDItemUIntItemIntItemListItemMapItemBlobItemFloatItemTAI64ItemBinItemStrItemRaw" +const _ItemType_name = "ItemEOCItemNILItemBoolItemUUIDItemUIntItemIntItemBigIntItemListItemMapItemBlobItemFloatItemTAI64ItemBinItemStrItemRaw" -var _ItemType_index = [...]uint8{0, 7, 14, 22, 30, 38, 45, 53, 60, 68, 77, 86, 93, 100, 107} +var _ItemType_index = [...]uint8{0, 7, 14, 22, 30, 38, 45, 55, 63, 70, 78, 87, 96, 103, 110, 117} func (i ItemType) String() string { if i >= ItemType(len(_ItemType_index)-1) { diff --git a/gyac/reflect.go b/gyac/reflect.go index 3d21c3f..8e99020 100644 --- a/gyac/reflect.go +++ b/gyac/reflect.go @@ -18,6 +18,7 @@ package gyac import ( "errors" "fmt" + "math/big" "reflect" "strings" "time" @@ -53,6 +54,8 @@ func (v *Item) ToGo() any { return ret case ItemBlob: return v.V.(*Blob) + case ItemBigInt: + return v.V.(*big.Int) case ItemFloat: panic("float is unsupported") case ItemTAI64: @@ -114,6 +117,8 @@ func ItemFromGo(v any) *Item { return &Item{T: byte(ItemTAI64), V: taiRaw} case *Raw: return &Item{T: byte(ItemRaw), V: v} + case *big.Int: + return &Item{T: byte(ItemBigInt), V: v} } switch reflect.TypeOf(v).Kind() { case reflect.Pointer: diff --git a/pyac/pyac.py b/pyac/pyac.py index 3be038c..0e909fa 100644 --- a/pyac/pyac.py +++ b/pyac/pyac.py @@ -136,12 +136,13 @@ class UUID: return self.v +from math import ceil + + class Int: - tags = tuple(v for v in range(0x20, 0x80)) - tagLenPositive = 0x20 - tagLenNegative = 0x30 - tagValPositive = 0x40 - tagValNegative = 0x60 + tagPositive = 0x0C + tagNegative = 0x0D + tags = (tagPositive, tagNegative) def __init__(self, v=0): if isinstance(v, Int): @@ -149,43 +150,32 @@ class Int: self.v = v def encode(self): - neg = False + tag = self.tagPositive v = self.v if v < 0: - neg = True + tag = self.tagNegative v = (-v) - 1 - if v < 32: - return ( - (self.tagValNegative if neg else self.tagValPositive) | v - ).to_bytes(1, "big") - tag = self.tagLenNegative if neg else self.tagLenPositive - for l, bits in enumerate(range(8, 128, 8)): - if v < (1<= klass.tagValPositive) and (data[0] < (klass.tagValPositive+32)): - v = data[0] - klass.tagValPositive - return klass(v), data[1:] - if (data[0] >= klass.tagValNegative) and (data[0] < (klass.tagValNegative+32)): - return klass(-1 - (data[0] - klass.tagValNegative)), data[1:] - if (data[0] & 0xF0) not in (klass.tagLenPositive, klass.tagLenNegative): + if data[0] not in klass.tags: raise WrongTag - neg = (data[0] & 0xF0) == klass.tagLenNegative - l = (data[0] & 0x0F) + 1 - data = data[1:] - if len(data) < l: - raise NotEnoughData(l) - v = int.from_bytes(data[:l], "big") - if v < 32: + neg = data[0] == klass.tagNegative + raw, data = Bin.decode(data[1:]) + raw = bytes(raw) + if raw == b"": + return (Int(-1) if neg else Int(0)), data + if raw[0] == 0: raise DecodeError("non-miminal encoding") + v = int.from_bytes(raw, "big") if neg: v = -1 - v - return klass(v), data[l:] + return klass(v), data def __repr__(self): return "INT(%d)" % self.v diff --git a/pyac/test-vector.py b/pyac/test-vector.py index beb8710..7fd79b0 100644 --- a/pyac/test-vector.py +++ b/pyac/test-vector.py @@ -3,8 +3,15 @@ from pyac import * data = { "ints": { - "pos": [0, 1, 31, 32, 123, 1234, 12345678, 1<<80], - "neg": [-1, -2, -32, -33, -123, -1234, -12345678, -1<<80], + "pos": [ + 0, 1, 31, 32, 123, 1234, 12345678, 1<<80, + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 1, + ], + "neg": [ + -1, -2, -32, -33, -123, -1234, -12345678, -1<<80, + -(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 2), + -123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789, + ], }, "floats": [Raw((Float.tags[1], b"\x01\x02\x03\x04"))], "nil": None, diff --git a/spec/encoding/cont.texi b/spec/encoding/cont.texi index c915bb4..5a53d3d 100644 --- a/spec/encoding/cont.texi +++ b/spec/encoding/cont.texi @@ -33,7 +33,7 @@ Example representations: @multitable @columnfractions .5 .5 @item LIST[] @tab @code{08 00} -@item LIST[INT(123) FALSE] @tab @code{08 207B 02 00} +@item LIST[INT(123) FALSE] @tab @code{08 0C817B 02 00} @item MAP[foo: LIST["bar"]] @tab @code{09 C3666F6F 08 C3626172 00 00} @item SET[sig, dh] @tab @code{09 C26468 01 C3736967 01 00} diff --git a/spec/encoding/index.texi b/spec/encoding/index.texi index 0dfd7f0..7c421c4 100644 --- a/spec/encoding/index.texi +++ b/spec/encoding/index.texi @@ -20,7 +20,9 @@ Possible values for the tag: @item 008 @tab 08 @tab @code{00001000} @tab 0 @tab @ref{Containers, LIST} @item 009 @tab 09 @tab @code{00001001} @tab 0 @tab @ref{Containers, MAP} @item 010 @tab 0A @tab @code{00001010} @tab -@item 011 @tab 0B @tab @code{00001011} @tab 8 @tab @ref{Blobs, BLOB} +@item 011 @tab 0B @tab @code{00001011} @tab 8+~ @tab @ref{Blobs, BLOB} +@item 012 @tab 0C @tab @code{00001100} @tab 1+~ @tab @ref{Integers, +INT} +@item 013 @tab 0D @tab @code{00001101} @tab 1+~ @tab @ref{Integers, -INT} @item [...] @item 016 @tab 10 @tab @code{00010000} @tab 2 @tab @ref{Floats, FLOAT16} @item 017 @tab 11 @tab @code{00010001} @tab 4 @tab @ref{Floats, FLOAT32} @@ -32,18 +34,6 @@ Possible values for the tag: @item 025 @tab 19 @tab @code{00011001} @tab 12 @tab @ref{TAI64, TAI64N} @item 026 @tab 1A @tab @code{00011010} @tab 16 @tab @ref{TAI64, TAI64NA} @item [...] -@item 032 @tab 20 @tab @code{0010LLLL} @tab 1 @tab @ref{Integers, +INT(len=1)} -@item [...] -@item 047 @tab 2F @tab @code{0010LLLL} @tab 16 @tab @ref{Integers, +INT(len=16)} -@item 048 @tab 30 @tab @code{0011LLLL} @tab 1 @tab @ref{Integers, -INT(len=1)} -@item [...] -@item 063 @tab 3F @tab @code{0011LLLL} @tab 16 @tab @ref{Integers, -INT(len=16)} -@item 064 @tab 40 @tab @code{010VVVVV} @tab 0 @tab @ref{Integers, INT=0} -@item [...] -@item 095 @tab 5F @tab @code{010VVVVV} @tab 0 @tab @ref{Integers, INT=31} -@item 096 @tab 60 @tab @code{011VVVVV} @tab 0 @tab @ref{Integers, INT=-1} -@item [...] -@item 127 @tab 7F @tab @code{011VVVVV} @tab 0 @tab @ref{Integers, INT=-32} @item 128 @tab 80 @tab @code{10LLLLLL} @tab 0 @tab @ref{Strings, BIN(len=0)} @item [...] @item 188 @tab BC @tab @code{10111100} @tab 60 @tab @ref{Strings, BIN(len=60)} diff --git a/spec/encoding/int.texi b/spec/encoding/int.texi index df31255..874efd6 100644 --- a/spec/encoding/int.texi +++ b/spec/encoding/int.texi @@ -2,51 +2,33 @@ @cindex INT @section Integers -Integers can be encoded in short or long form. Separate types are used -for positive and negative values. +Integers are encoded as ordinary binary string, that has prepended byte +indicating is it positive or negative integer. Negative integers store +their absolute value the same way as positive integers. After decoding, +their value is subtracted from -1. Negative value encoded as @code{0x02} +means @code{-1 - 0x02 => -3}. -Short form eats five bits of the tag -for positive values in @code{[0..32)} range, -and negative ones in @code{[-1..-32]} range. - -Long form is encoded as a big-endian number of varying length. -@code{*INT(len=1)..*INT(len=16)} types are for 8-, 16-, 24-, ..., -128-bit integer representations. - -Shortest possible form @strong{must} be used, that means no leading zero byte. -Short values (<32) @strong{must} be encoded in a short form. - -Negative integers store their absolute value the same way as positive -integers. After decoding, their value is subtracted from -1. Negative -value encoded as @code{0x02} means @code{-1 - 0x02 => -3}. - -Hint: both positive and negative long integer tag's value keeps the -length in the last 16 bits. So there is no need in dealing with every -tag's reserved value. You can check first 4 bits of the header to -determine is it positive or negative integer, and then treat remaining 4 -bits as a length (+1). +Shortest possible form @strong{must} be used, that means no leading zero +byte. 0 and -1 values are empty strings, so even they won't have leading +zero. Example representations: @multitable @columnfractions .5 .5 -@item 0 @tab @code{40} -@item 1 @tab @code{41} -@item 10 @tab @code{4A} -@item 31 @tab @code{5F} -@item 32 @tab @code{20 20} -@item 100 @tab @code{20 64} -@item 65536 @tab @code{22 01 00 00} -@item 1000000000000 @tab @code{24 E8 D4 A5 10 00} -@item 18446744073709551615 @tab @code{27 FF FF FF FF FF FF FF FF} -@item 18446744073709551616 @tab @code{28 01 00 00 00 00 00 00 00 00} -@item -18446744073709551616 @tab @code{37 FF FF FF FF FF FF FF FF} -@item -18446744073709551617 @tab @code{38 01 00 00 00 00 00 00 00 00} -@item -1 @tab @code{60} -@item -10 @tab @code{69} -@item -32 @tab @code{7F} -@item -33 @tab @code{30 20} -@item -100 @tab @code{30 63} -@item -65536 @tab @code{31 FF FF} +@item 0 @tab @code{0C 80} +@item 1 @tab @code{0C 81 01} +@item 10 @tab @code{0C 81 0A} +@item 100 @tab @code{0C 01 64} +@item 65536 @tab @code{0C 83 010000} +@item 1000000000000 @tab @code{0C 85 E8D4A51000} +@item 18446744073709551615 @tab @code{0C 88 FFFFFFFFFFFFFFFF} +@item 18446744073709551616 @tab @code{0C 89 010000000000000000} +@item -18446744073709551616 @tab @code{0D 88 FFFFFFFFFFFFFFFF} +@item -18446744073709551617 @tab @code{0D 89 010000000000000000} +@item -1 @tab @code{0D 80} +@item -10 @tab @code{0D 81 09} +@item -100 @tab @code{0D 81 63} +@item -65536 @tab @code{0D 82 FFFF} @end multitable diff --git a/spec/encoding/table.texi b/spec/encoding/table.texi index 6365a74..aedc196 100644 --- a/spec/encoding/table.texi +++ b/spec/encoding/table.texi @@ -15,9 +15,9 @@ @item 008 @tab 08 @tab @code{00001000} @tab 0 @tab @ref{Containers, LIST} @item 009 @tab 09 @tab @code{00001001} @tab 0 @tab @ref{Containers, MAP} @item 010 @tab 0A @tab @code{00001010} @tab 0 @tab -@item 011 @tab 0B @tab @code{00001011} @tab 8 @tab @ref{Blobs, BLOB} -@item 012 @tab 0C @tab @code{00001100} @tab 0 @tab -@item 013 @tab 0D @tab @code{00001101} @tab 0 @tab +@item 011 @tab 0B @tab @code{00001011} @tab 8+~ @tab @ref{Blobs, BLOB} +@item 012 @tab 0C @tab @code{00001100} @tab 1+~ @tab @ref{Integers, +INT} +@item 013 @tab 0D @tab @code{00001101} @tab 1+~ @tab @ref{Integers, -INT} @item 014 @tab 0E @tab @code{00001110} @tab 0 @tab @item 015 @tab 0F @tab @code{00001111} @tab 0 @tab @item 016 @tab 10 @tab @code{00010000} @tab 2 @tab @ref{Floats, FLOAT16} @@ -36,102 +36,102 @@ @item 029 @tab 1D @tab @code{00011101} @tab 0 @tab @item 030 @tab 1E @tab @code{00011110} @tab 0 @tab @item 031 @tab 1F @tab @code{00011111} @tab 0 @tab -@item 032 @tab 20 @tab @code{00100000} @tab 1 @tab @ref{Integers, +INT(len=1)} -@item 033 @tab 21 @tab @code{00100001} @tab 2 @tab @ref{Integers, +INT(len=2)} -@item 034 @tab 22 @tab @code{00100010} @tab 3 @tab @ref{Integers, +INT(len=3)} -@item 035 @tab 23 @tab @code{00100011} @tab 4 @tab @ref{Integers, +INT(len=4)} -@item 036 @tab 24 @tab @code{00100100} @tab 5 @tab @ref{Integers, +INT(len=5)} -@item 037 @tab 25 @tab @code{00100101} @tab 6 @tab @ref{Integers, +INT(len=6)} -@item 038 @tab 26 @tab @code{00100110} @tab 7 @tab @ref{Integers, +INT(len=7)} -@item 039 @tab 27 @tab @code{00100111} @tab 8 @tab @ref{Integers, +INT(len=8)} -@item 040 @tab 28 @tab @code{00101000} @tab 9 @tab @ref{Integers, +INT(len=9)} -@item 041 @tab 29 @tab @code{00101001} @tab 10 @tab @ref{Integers, +INT(len=10)} -@item 042 @tab 2A @tab @code{00101010} @tab 11 @tab @ref{Integers, +INT(len=11)} -@item 043 @tab 2B @tab @code{00101011} @tab 12 @tab @ref{Integers, +INT(len=12)} -@item 044 @tab 2C @tab @code{00101100} @tab 13 @tab @ref{Integers, +INT(len=13)} -@item 045 @tab 2D @tab @code{00101101} @tab 14 @tab @ref{Integers, +INT(len=14)} -@item 046 @tab 2E @tab @code{00101110} @tab 15 @tab @ref{Integers, +INT(len=15)} -@item 047 @tab 2F @tab @code{00101111} @tab 16 @tab @ref{Integers, +INT(len=16)} -@item 048 @tab 30 @tab @code{00110000} @tab 1 @tab @ref{Integers, -INT(len=1)} -@item 049 @tab 31 @tab @code{00110001} @tab 2 @tab @ref{Integers, -INT(len=2)} -@item 050 @tab 32 @tab @code{00110010} @tab 3 @tab @ref{Integers, -INT(len=3)} -@item 051 @tab 33 @tab @code{00110011} @tab 4 @tab @ref{Integers, -INT(len=4)} -@item 052 @tab 34 @tab @code{00110100} @tab 5 @tab @ref{Integers, -INT(len=5)} -@item 053 @tab 35 @tab @code{00110101} @tab 6 @tab @ref{Integers, -INT(len=6)} -@item 054 @tab 36 @tab @code{00110110} @tab 7 @tab @ref{Integers, -INT(len=7)} -@item 055 @tab 37 @tab @code{00110111} @tab 8 @tab @ref{Integers, -INT(len=8)} -@item 056 @tab 38 @tab @code{00111000} @tab 9 @tab @ref{Integers, -INT(len=9)} -@item 057 @tab 39 @tab @code{00111001} @tab 10 @tab @ref{Integers, -INT(len=10)} -@item 058 @tab 3A @tab @code{00111010} @tab 11 @tab @ref{Integers, -INT(len=11)} -@item 059 @tab 3B @tab @code{00111011} @tab 12 @tab @ref{Integers, -INT(len=12)} -@item 060 @tab 3C @tab @code{00111100} @tab 13 @tab @ref{Integers, -INT(len=13)} -@item 061 @tab 3D @tab @code{00111101} @tab 14 @tab @ref{Integers, -INT(len=14)} -@item 062 @tab 3E @tab @code{00111110} @tab 15 @tab @ref{Integers, -INT(len=15)} -@item 063 @tab 3F @tab @code{00111111} @tab 16 @tab @ref{Integers, -INT(len=16)} -@item 064 @tab 40 @tab @code{01000000} @tab 0 @tab @ref{Integers, INT=0} -@item 065 @tab 41 @tab @code{01000001} @tab 0 @tab @ref{Integers, INT=1} -@item 066 @tab 42 @tab @code{01000010} @tab 0 @tab @ref{Integers, INT=2} -@item 067 @tab 43 @tab @code{01000011} @tab 0 @tab @ref{Integers, INT=3} -@item 068 @tab 44 @tab @code{01000100} @tab 0 @tab @ref{Integers, INT=4} -@item 069 @tab 45 @tab @code{01000101} @tab 0 @tab @ref{Integers, INT=5} -@item 070 @tab 46 @tab @code{01000110} @tab 0 @tab @ref{Integers, INT=6} -@item 071 @tab 47 @tab @code{01000111} @tab 0 @tab @ref{Integers, INT=7} -@item 072 @tab 48 @tab @code{01001000} @tab 0 @tab @ref{Integers, INT=8} -@item 073 @tab 49 @tab @code{01001001} @tab 0 @tab @ref{Integers, INT=9} -@item 074 @tab 4A @tab @code{01001010} @tab 0 @tab @ref{Integers, INT=10} -@item 075 @tab 4B @tab @code{01001011} @tab 0 @tab @ref{Integers, INT=11} -@item 076 @tab 4C @tab @code{01001100} @tab 0 @tab @ref{Integers, INT=12} -@item 077 @tab 4D @tab @code{01001101} @tab 0 @tab @ref{Integers, INT=13} -@item 078 @tab 4E @tab @code{01001110} @tab 0 @tab @ref{Integers, INT=14} -@item 079 @tab 4F @tab @code{01001111} @tab 0 @tab @ref{Integers, INT=15} -@item 080 @tab 50 @tab @code{01010000} @tab 0 @tab @ref{Integers, INT=16} -@item 081 @tab 51 @tab @code{01010001} @tab 0 @tab @ref{Integers, INT=17} -@item 082 @tab 52 @tab @code{01010010} @tab 0 @tab @ref{Integers, INT=18} -@item 083 @tab 53 @tab @code{01010011} @tab 0 @tab @ref{Integers, INT=19} -@item 084 @tab 54 @tab @code{01010100} @tab 0 @tab @ref{Integers, INT=20} -@item 085 @tab 55 @tab @code{01010101} @tab 0 @tab @ref{Integers, INT=21} -@item 086 @tab 56 @tab @code{01010110} @tab 0 @tab @ref{Integers, INT=22} -@item 087 @tab 57 @tab @code{01010111} @tab 0 @tab @ref{Integers, INT=23} -@item 088 @tab 58 @tab @code{01011000} @tab 0 @tab @ref{Integers, INT=24} -@item 089 @tab 59 @tab @code{01011001} @tab 0 @tab @ref{Integers, INT=25} -@item 090 @tab 5A @tab @code{01011010} @tab 0 @tab @ref{Integers, INT=26} -@item 091 @tab 5B @tab @code{01011011} @tab 0 @tab @ref{Integers, INT=27} -@item 092 @tab 5C @tab @code{01011100} @tab 0 @tab @ref{Integers, INT=28} -@item 093 @tab 5D @tab @code{01011101} @tab 0 @tab @ref{Integers, INT=29} -@item 094 @tab 5E @tab @code{01011110} @tab 0 @tab @ref{Integers, INT=30} -@item 095 @tab 5F @tab @code{01011111} @tab 0 @tab @ref{Integers, INT=31} -@item 096 @tab 60 @tab @code{01100000} @tab 0 @tab @ref{Integers, INT=-1} -@item 097 @tab 61 @tab @code{01100001} @tab 0 @tab @ref{Integers, INT=-2} -@item 098 @tab 62 @tab @code{01100010} @tab 0 @tab @ref{Integers, INT=-3} -@item 099 @tab 63 @tab @code{01100011} @tab 0 @tab @ref{Integers, INT=-4} -@item 100 @tab 64 @tab @code{01100100} @tab 0 @tab @ref{Integers, INT=-5} -@item 101 @tab 65 @tab @code{01100101} @tab 0 @tab @ref{Integers, INT=-6} -@item 102 @tab 66 @tab @code{01100110} @tab 0 @tab @ref{Integers, INT=-7} -@item 103 @tab 67 @tab @code{01100111} @tab 0 @tab @ref{Integers, INT=-8} -@item 104 @tab 68 @tab @code{01101000} @tab 0 @tab @ref{Integers, INT=-9} -@item 105 @tab 69 @tab @code{01101001} @tab 0 @tab @ref{Integers, INT=-10} -@item 106 @tab 6A @tab @code{01101010} @tab 0 @tab @ref{Integers, INT=-11} -@item 107 @tab 6B @tab @code{01101011} @tab 0 @tab @ref{Integers, INT=-12} -@item 108 @tab 6C @tab @code{01101100} @tab 0 @tab @ref{Integers, INT=-13} -@item 109 @tab 6D @tab @code{01101101} @tab 0 @tab @ref{Integers, INT=-14} -@item 110 @tab 6E @tab @code{01101110} @tab 0 @tab @ref{Integers, INT=-15} -@item 111 @tab 6F @tab @code{01101111} @tab 0 @tab @ref{Integers, INT=-16} -@item 112 @tab 70 @tab @code{01110000} @tab 0 @tab @ref{Integers, INT=-17} -@item 113 @tab 71 @tab @code{01110001} @tab 0 @tab @ref{Integers, INT=-18} -@item 114 @tab 72 @tab @code{01110010} @tab 0 @tab @ref{Integers, INT=-19} -@item 115 @tab 73 @tab @code{01110011} @tab 0 @tab @ref{Integers, INT=-20} -@item 116 @tab 74 @tab @code{01110100} @tab 0 @tab @ref{Integers, INT=-21} -@item 117 @tab 75 @tab @code{01110101} @tab 0 @tab @ref{Integers, INT=-22} -@item 118 @tab 76 @tab @code{01110110} @tab 0 @tab @ref{Integers, INT=-23} -@item 119 @tab 77 @tab @code{01110111} @tab 0 @tab @ref{Integers, INT=-24} -@item 120 @tab 78 @tab @code{01111000} @tab 0 @tab @ref{Integers, INT=-25} -@item 121 @tab 79 @tab @code{01111001} @tab 0 @tab @ref{Integers, INT=-26} -@item 122 @tab 7A @tab @code{01111010} @tab 0 @tab @ref{Integers, INT=-27} -@item 123 @tab 7B @tab @code{01111011} @tab 0 @tab @ref{Integers, INT=-28} -@item 124 @tab 7C @tab @code{01111100} @tab 0 @tab @ref{Integers, INT=-29} -@item 125 @tab 7D @tab @code{01111101} @tab 0 @tab @ref{Integers, INT=-30} -@item 126 @tab 7E @tab @code{01111110} @tab 0 @tab @ref{Integers, INT=-31} -@item 127 @tab 7F @tab @code{01111111} @tab 0 @tab @ref{Integers, INT=-32} +@item 032 @tab 20 @tab @code{00100000} @tab 0 @tab +@item 033 @tab 21 @tab @code{00100001} @tab 0 @tab +@item 034 @tab 22 @tab @code{00100010} @tab 0 @tab +@item 035 @tab 23 @tab @code{00100011} @tab 0 @tab +@item 036 @tab 24 @tab @code{00100100} @tab 0 @tab +@item 037 @tab 25 @tab @code{00100101} @tab 0 @tab +@item 038 @tab 26 @tab @code{00100110} @tab 0 @tab +@item 039 @tab 27 @tab @code{00100111} @tab 0 @tab +@item 040 @tab 28 @tab @code{00101000} @tab 0 @tab +@item 041 @tab 29 @tab @code{00101001} @tab 0 @tab +@item 042 @tab 2A @tab @code{00101010} @tab 0 @tab +@item 043 @tab 2B @tab @code{00101011} @tab 0 @tab +@item 044 @tab 2C @tab @code{00101100} @tab 0 @tab +@item 045 @tab 2D @tab @code{00101101} @tab 0 @tab +@item 046 @tab 2E @tab @code{00101110} @tab 0 @tab +@item 047 @tab 2F @tab @code{00101111} @tab 0 @tab +@item 048 @tab 30 @tab @code{00110000} @tab 0 @tab +@item 049 @tab 31 @tab @code{00110001} @tab 0 @tab +@item 050 @tab 32 @tab @code{00110010} @tab 0 @tab +@item 051 @tab 33 @tab @code{00110011} @tab 0 @tab +@item 052 @tab 34 @tab @code{00110100} @tab 0 @tab +@item 053 @tab 35 @tab @code{00110101} @tab 0 @tab +@item 054 @tab 36 @tab @code{00110110} @tab 0 @tab +@item 055 @tab 37 @tab @code{00110111} @tab 0 @tab +@item 056 @tab 38 @tab @code{00111000} @tab 0 @tab +@item 057 @tab 39 @tab @code{00111001} @tab 0 @tab +@item 058 @tab 3A @tab @code{00111010} @tab 0 @tab +@item 059 @tab 3B @tab @code{00111011} @tab 0 @tab +@item 060 @tab 3C @tab @code{00111100} @tab 0 @tab +@item 061 @tab 3D @tab @code{00111101} @tab 0 @tab +@item 062 @tab 3E @tab @code{00111110} @tab 0 @tab +@item 063 @tab 3F @tab @code{00111111} @tab 0 @tab +@item 064 @tab 40 @tab @code{01000000} @tab 0 @tab +@item 065 @tab 41 @tab @code{01000001} @tab 0 @tab +@item 066 @tab 42 @tab @code{01000010} @tab 0 @tab +@item 067 @tab 43 @tab @code{01000011} @tab 0 @tab +@item 068 @tab 44 @tab @code{01000100} @tab 0 @tab +@item 069 @tab 45 @tab @code{01000101} @tab 0 @tab +@item 070 @tab 46 @tab @code{01000110} @tab 0 @tab +@item 071 @tab 47 @tab @code{01000111} @tab 0 @tab +@item 072 @tab 48 @tab @code{01001000} @tab 0 @tab +@item 073 @tab 49 @tab @code{01001001} @tab 0 @tab +@item 074 @tab 4A @tab @code{01001010} @tab 0 @tab +@item 075 @tab 4B @tab @code{01001011} @tab 0 @tab +@item 076 @tab 4C @tab @code{01001100} @tab 0 @tab +@item 077 @tab 4D @tab @code{01001101} @tab 0 @tab +@item 078 @tab 4E @tab @code{01001110} @tab 0 @tab +@item 079 @tab 4F @tab @code{01001111} @tab 0 @tab +@item 080 @tab 50 @tab @code{01010000} @tab 0 @tab +@item 081 @tab 51 @tab @code{01010001} @tab 0 @tab +@item 082 @tab 52 @tab @code{01010010} @tab 0 @tab +@item 083 @tab 53 @tab @code{01010011} @tab 0 @tab +@item 084 @tab 54 @tab @code{01010100} @tab 0 @tab +@item 085 @tab 55 @tab @code{01010101} @tab 0 @tab +@item 086 @tab 56 @tab @code{01010110} @tab 0 @tab +@item 087 @tab 57 @tab @code{01010111} @tab 0 @tab +@item 088 @tab 58 @tab @code{01011000} @tab 0 @tab +@item 089 @tab 59 @tab @code{01011001} @tab 0 @tab +@item 090 @tab 5A @tab @code{01011010} @tab 0 @tab +@item 091 @tab 5B @tab @code{01011011} @tab 0 @tab +@item 092 @tab 5C @tab @code{01011100} @tab 0 @tab +@item 093 @tab 5D @tab @code{01011101} @tab 0 @tab +@item 094 @tab 5E @tab @code{01011110} @tab 0 @tab +@item 095 @tab 5F @tab @code{01011111} @tab 0 @tab +@item 096 @tab 60 @tab @code{01100000} @tab 0 @tab +@item 097 @tab 61 @tab @code{01100001} @tab 0 @tab +@item 098 @tab 62 @tab @code{01100010} @tab 0 @tab +@item 099 @tab 63 @tab @code{01100011} @tab 0 @tab +@item 100 @tab 64 @tab @code{01100100} @tab 0 @tab +@item 101 @tab 65 @tab @code{01100101} @tab 0 @tab +@item 102 @tab 66 @tab @code{01100110} @tab 0 @tab +@item 103 @tab 67 @tab @code{01100111} @tab 0 @tab +@item 104 @tab 68 @tab @code{01101000} @tab 0 @tab +@item 105 @tab 69 @tab @code{01101001} @tab 0 @tab +@item 106 @tab 6A @tab @code{01101010} @tab 0 @tab +@item 107 @tab 6B @tab @code{01101011} @tab 0 @tab +@item 108 @tab 6C @tab @code{01101100} @tab 0 @tab +@item 109 @tab 6D @tab @code{01101101} @tab 0 @tab +@item 110 @tab 6E @tab @code{01101110} @tab 0 @tab +@item 111 @tab 6F @tab @code{01101111} @tab 0 @tab +@item 112 @tab 70 @tab @code{01110000} @tab 0 @tab +@item 113 @tab 71 @tab @code{01110001} @tab 0 @tab +@item 114 @tab 72 @tab @code{01110010} @tab 0 @tab +@item 115 @tab 73 @tab @code{01110011} @tab 0 @tab +@item 116 @tab 74 @tab @code{01110100} @tab 0 @tab +@item 117 @tab 75 @tab @code{01110101} @tab 0 @tab +@item 118 @tab 76 @tab @code{01110110} @tab 0 @tab +@item 119 @tab 77 @tab @code{01110111} @tab 0 @tab +@item 120 @tab 78 @tab @code{01111000} @tab 0 @tab +@item 121 @tab 79 @tab @code{01111001} @tab 0 @tab +@item 122 @tab 7A @tab @code{01111010} @tab 0 @tab +@item 123 @tab 7B @tab @code{01111011} @tab 0 @tab +@item 124 @tab 7C @tab @code{01111100} @tab 0 @tab +@item 125 @tab 7D @tab @code{01111101} @tab 0 @tab +@item 126 @tab 7E @tab @code{01111110} @tab 0 @tab +@item 127 @tab 7F @tab @code{01111111} @tab 0 @tab @item 128 @tab 80 @tab @code{10000000} @tab 0 @tab @ref{Strings, BIN(len=0)} @item 129 @tab 81 @tab @code{10000001} @tab 1 @tab @ref{Strings, BIN(len=1)} @item 130 @tab 82 @tab @code{10000010} @tab 2 @tab @ref{Strings, BIN(len=2)} diff --git a/tyac/test-vector.tcl b/tyac/test-vector.tcl index abecf2c..feb97dc 100644 --- a/tyac/test-vector.tcl +++ b/tyac/test-vector.tcl @@ -12,6 +12,7 @@ MAP { {INT 1234} {INT 12345678} {INT [expr {1 << 80}]} + {INT [expr 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 1]} }} neg {LIST { {INT -1} @@ -22,6 +23,8 @@ MAP { {INT -1234} {INT -12345678} {INT -[expr {1 << 80}]} + {INT [expr {-(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 2)}]} + {INT -123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789} }} }} floats {LIST { diff --git a/tyac/tyac.tcl b/tyac/tyac.tcl index ee0ae7a..311e46c 100644 --- a/tyac/tyac.tcl +++ b/tyac/tyac.tcl @@ -36,37 +36,36 @@ proc UUID {v} { add $v } -proc toBE {l v} { +proc toBEbin {l v} { + set a [list] for {set i 0} {$i < $l} {incr i} { set b [expr {($l - $i - 1) * 8}] - char [expr {($v & (0xFF << $b)) >> $b}] + lappend a [binary format c [expr {($v & (0xFF << $b)) >> $b}]] } + return $a +} + +proc toBE {l v} { + foreach c [toBEbin $l $v] { add $c } } proc INT {v} { - set neg 0 - if {$v < 0} { - set neg 1 + if {$v >= 0} { + char [expr 0x0C] + } { + char [expr 0x0D] set v [expr {- ($v + 1)}] } - if {$v < 32} { - if {$neg} { - char [expr {0x60 | $v}] - } { - char [expr {0x40 | $v}] - } + if {$v == 0} { + BIN "" return } - if {$neg} { set b [expr 0x30] } { set b [expr 0x20] } - set bits 8 set l 0 while {1} { - if {$v < [expr {1 << $bits}]} { break } + if {$v < [expr {1 << (($l+1)*8)}]} { break } incr l - incr bits 8 } - char [expr {$b | $l}] - toBE [expr {$l + 1}] $v + BIN [join [toBEbin [expr {$l + 1}] $v] ""] } proc _str {atom v} { -- 2.50.0