From bd84017768f41210d3a6066f443d32596352157d Mon Sep 17 00:00:00 2001 From: Daniil Sedov Date: Fri, 23 Aug 2024 18:10:45 +0300 Subject: [PATCH] feat: implement `.toSlice()` struct method (#630) --- CHANGELOG.md | 1 + src/abi/struct.ts | 51 +++++++++++++++++-- .../__snapshots__/structs.spec.ts.snap | 6 +-- src/test/e2e-emulated/contracts/structs.tact | 6 ++- src/test/e2e-emulated/structs.spec.ts | 4 ++ 5 files changed, 61 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3af9f8815..04079f3ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The `exists` method for the `Map` type: PR [#581](https://github.com/tact-lang/tact/pull/581) - The `storeBit` method for `Builder` type and the `loadBit` method for `Slice` type: PR [#699](https://github.com/tact-lang/tact/pull/699) +- The `toSlice` method for structs and messages: PR [#630](https://github.com/tact-lang/tact/pull/630) ### Changed diff --git a/src/abi/struct.ts b/src/abi/struct.ts index a6dc4b4d2..48a24a135 100644 --- a/src/abi/struct.ts +++ b/src/abi/struct.ts @@ -16,14 +16,14 @@ export const StructFunctions: Map = new Map([ const arg = args[0]!; if (arg.kind !== "ref") { throwCompilationError( - "toCell() is implemented only a struct type", + `toCell() is not implemented for type '${arg.kind}'`, ref, ); } const tp = getType(ctx, arg.name); if (tp.kind !== "struct") { throwCompilationError( - "toCell() is implemented only a struct type", + `toCell() is not implemented for type '${arg.kind}'`, ref, ); } @@ -36,7 +36,7 @@ export const StructFunctions: Map = new Map([ const arg = args[0]!; if (arg.kind !== "ref") { throwCompilationError( - "toCell() is implemented only a struct type", + `toCell() is not implemented for type '${arg.kind}'`, ref, ); } @@ -103,6 +103,51 @@ export const StructFunctions: Map = new Map([ }, }, ], + [ + "toSlice", + { + name: "toSlice", + resolve: (ctx, args, ref) => { + if (args.length !== 1) { + throwCompilationError( + "toSlice() expects no arguments", + ref, + ); + } + const arg = args[0]!; + if (arg.kind !== "ref") { + throwCompilationError( + `toSlice() is not implemented for type '${arg.kind}'`, + ref, + ); + } + const tp = getType(ctx, arg.name); + if (tp.kind !== "struct") { + throwCompilationError( + `toSlice() is not implemented for type '${arg.kind}'`, + ref, + ); + } + return { kind: "ref", name: "Slice", optional: false }; + }, + generate: (ctx, args, resolved, ref) => { + if (resolved.length !== 1) { + throwCompilationError( + "toSlice() expects no arguments", + ref, + ); + } + const arg = args[0]!; + if (arg.kind !== "ref") { + throwCompilationError( + `toSlice() is not implemented for type '${arg.kind}'`, + ref, + ); + } + return `${ops.writerCell(arg.name, ctx)}(${resolved.map((v) => writeExpression(v, ctx)).join(", ")}).begin_parse()`; + }, + }, + ], [ "fromSlice", { diff --git a/src/test/e2e-emulated/__snapshots__/structs.spec.ts.snap b/src/test/e2e-emulated/__snapshots__/structs.spec.ts.snap index 0ec20b0c7..b781726f9 100644 --- a/src/test/e2e-emulated/__snapshots__/structs.spec.ts.snap +++ b/src/test/e2e-emulated/__snapshots__/structs.spec.ts.snap @@ -289,7 +289,7 @@ exports[`structs should implement structs correctly 13`] = ` "events": [ { "$type": "storage-charged", - "amount": "0.000000034", + "amount": "0.000000035", }, { "$type": "received", @@ -300,7 +300,7 @@ exports[`structs should implement structs correctly 13`] = ` }, "bounce": true, "from": "@treasure(treasure)", - "to": "kQA1LDdzadkUsxlM6-EvD2rMZ2-HuudKWuU-umho_Zw4Aoau", + "to": "kQCHYvnW92OPDk0lG_YI0DX9anWqZygSM4vJtR-ctm9picG2", "type": "internal", "value": "10", }, @@ -318,7 +318,7 @@ exports[`structs should implement structs correctly 13`] = ` "type": "cell", }, "bounce": false, - "from": "kQA1LDdzadkUsxlM6-EvD2rMZ2-HuudKWuU-umho_Zw4Aoau", + "from": "kQCHYvnW92OPDk0lG_YI0DX9anWqZygSM4vJtR-ctm9picG2", "to": "@treasure(treasure)", "type": "internal", "value": "9.988015", diff --git a/src/test/e2e-emulated/contracts/structs.tact b/src/test/e2e-emulated/contracts/structs.tact index eeefea5de..b54dd1d5d 100644 --- a/src/test/e2e-emulated/contracts/structs.tact +++ b/src/test/e2e-emulated/contracts/structs.tact @@ -260,10 +260,14 @@ contract StructsTester { self.t1.s.a == self.t2.s.a && self.t1.s.b == self.t2.s.b; } - get fun toCell1(s: MyStruct1): Cell { + get fun toCell1(s: MyStruct1): Cell { return s.toCell(); } + get fun toSlice1(s: MyStruct1): Slice { + return s.toSlice(); + } + get fun fromCell1(src: Cell): MyStruct1 { let s = MyStruct1.fromCell(src); return s; diff --git a/src/test/e2e-emulated/structs.spec.ts b/src/test/e2e-emulated/structs.spec.ts index c9e96784a..7d7fb6429 100644 --- a/src/test/e2e-emulated/structs.spec.ts +++ b/src/test/e2e-emulated/structs.spec.ts @@ -124,6 +124,10 @@ describe("structs", () => { c6.toString(), ); + expect((await contract.getToSlice1(s1)).toString()).toEqual( + c1.toString(), + ); + expect(await contract.getFromCell1(c1)).toMatchObject(s1); expect(await contract.getFromCell1(c2)).toMatchObject(s2); expect(await contract.getFromCell2(c3)).toMatchSnapshot();