public emit()

in packages/jsii-pacmak/lib/targets/go/runtime/runtime-type-checking.ts [457:560]


      public emit(code: CodeMaker, scope: Package): void {
        const validTypes = new Array<string>();

        code.line(`switch ${expression}.(type) {`);
        for (const type of types) {
          const typeName = type.scopedReference(scope);
          validTypes.push(typeName);
          // Maps a type to the conversion instructions to the ${typeName} type
          const acceptableTypes = new Map<
            string,
            | ((code: CodeMaker, inVar: string, outVar: string) => void)
            | undefined
          >();
          acceptableTypes.set(typeName, undefined);
          switch (typeName) {
            case '*float64':
              // For numbers, we accept everything that implictly converts to float64 (pointer & not)
              acceptableTypes.set('float64', (code, inVar, outVar) =>
                code.line(`${outVar} := &${inVar}`),
              );
              const ALTERNATE_TYPES = [
                'int',
                'uint',
                'int8',
                'int16',
                'int32',
                'int64',
                'uint8',
                'uint16',
                'uint32',
                'uint64',
              ];
              for (const otherType of ALTERNATE_TYPES) {
                const varName = createHash('sha256')
                  .update(expression)
                  .digest('hex')
                  .slice(6);
                acceptableTypes.set(`*${otherType}`, (code) => {
                  code.openBlock(
                    `${varName} := func (v *${otherType}) *float64`,
                  );
                  code.openBlock('if v == nil {');
                  code.line('return nil');
                  code.closeBlock();
                  code.line(`val := float64(*v)`);
                  code.line(`return &val`);
                  code.closeBlock('()');
                });
                acceptableTypes.set(otherType, (code) => {
                  code.openBlock(
                    `${varName} := func (v ${otherType}) *float64`,
                  );
                  code.line(`val := float64(v)`);
                  code.line(`return &val`);
                  code.closeBlock('()');
                });
              }
              break;
            default:
              // Accept pointer and non-pointer versions of everything
              if (typeName.startsWith('*')) {
                const nonPointerType = typeName.slice(1);
                acceptableTypes.set(nonPointerType, (code, inVar, outVar) =>
                  code.line(`${outVar} := &${inVar}`),
                );
              }
          }
          for (const [acceptableType, conversion] of acceptableTypes) {
            code.indent(`case ${acceptableType}:`);
            const outVar = /^[a-z0-9_]+$/.test(expression) ? expression : `v`;
            const validation = Validation.forTypeMap(
              outVar,
              description,
              type.typeMap,
            );
            if (validation) {
              const inVar = conversion ? `${outVar}_` : outVar;
              code.line(`${inVar} := ${expression}.(${acceptableType})`);
              if (conversion) {
                conversion(code, inVar, outVar);
              }
              validation.emit(code, scope);
            } else {
              code.line('// ok');
            }
            code.unindent(false);
          }
        }
        code.indent('default:');
        if (hasInterface)
          code.openBlock(
            `if !${JSII_RT_ALIAS}.IsAnonymousProxy(${expression})`,
          );
        code.line(
          returnErrorf(
            `${description} must be one of the allowed types: ${validTypes.join(
              ', ',
            )}; received @{${expression}:#v} (a @{${expression}:T})`,
          ),
        );
        if (hasInterface) code.closeBlock();
        code.unindent('}');
      }
    }