| 820 | } |
| 821 | |
| 822 | std::string ABIFunctions::abiEncodingFunctionStruct( |
| 823 | StructType const& _from, |
| 824 | StructType const& _to, |
| 825 | EncodingOptions const& _options |
| 826 | ) |
| 827 | { |
| 828 | std::string functionName = |
| 829 | "abi_encode_" + |
| 830 | _from.identifier() + |
| 831 | "_to_" + |
| 832 | _to.identifier() + |
| 833 | _options.toFunctionNameSuffix(); |
| 834 | |
| 835 | solAssert(&_from.structDefinition() == &_to.structDefinition(), ""); |
| 836 | |
| 837 | return createFunction(functionName, [&]() { |
| 838 | bool dynamic = _to.isDynamicallyEncoded(); |
| 839 | Whiskers templ(R"( |
| 840 | // <readableTypeNameFrom> -> <readableTypeNameTo> |
| 841 | function <functionName>(value, pos) <return> { |
| 842 | let tail := add(pos, <headSize>) |
| 843 | <init> |
| 844 | <#members> |
| 845 | { |
| 846 | // <memberName> |
| 847 | <preprocess> |
| 848 | let <memberValues> := <retrieveValue> |
| 849 | <encode> |
| 850 | } |
| 851 | </members> |
| 852 | <assignEnd> |
| 853 | } |
| 854 | )"); |
| 855 | templ("functionName", functionName); |
| 856 | templ("readableTypeNameFrom", _from.toString(true)); |
| 857 | templ("readableTypeNameTo", _to.toString(true)); |
| 858 | templ("return", dynamic ? " -> end " : ""); |
| 859 | if (dynamic && _options.dynamicInplace) |
| 860 | templ("assignEnd", "end := pos"); |
| 861 | else if (dynamic && !_options.dynamicInplace) |
| 862 | templ("assignEnd", "end := tail"); |
| 863 | else |
| 864 | templ("assignEnd", ""); |
| 865 | // to avoid multiple loads from the same slot for subsequent members |
| 866 | templ("init", _from.dataStoredIn(DataLocation::Storage) ? "let slotValue := 0" : ""); |
| 867 | u256 previousSlotOffset(-1); |
| 868 | u256 encodingOffset = 0; |
| 869 | std::vector<std::map<std::string, std::string>> members; |
| 870 | for (auto const& member: _to.members(nullptr)) |
| 871 | { |
| 872 | solAssert(member.type, ""); |
| 873 | solAssert(!member.type->containsNestedMapping(), ""); |
| 874 | Type const* memberTypeTo = member.type->fullEncodingType(_options.encodeAsLibraryTypes, true, false); |
| 875 | solUnimplementedAssert(memberTypeTo, "Encoding type \"" + member.type->toString() + "\" not yet implemented."); |
| 876 | auto memberTypeFrom = _from.memberType(member.name); |
| 877 | solAssert(memberTypeFrom, ""); |
| 878 | bool dynamicMember = memberTypeTo->isDynamicallyEncoded(); |
| 879 | if (dynamicMember) |
nothing calls this directly
no test coverage detected