UNPKG

nitro-codegen

Version:

The code-generator for react-native-nitro-modules.

122 lines (106 loc) 3.72 kB
import type { FileWithReferencedTypes } from '../SourceFile.js' import { indent } from '../../utils.js' import { createFileMetadataString, isNotDuplicate } from '../helpers.js' import type { NamedType } from '../types/Type.js' import { includeHeader, includeNitroHeader } from './includeNitroHeader.js' import { NitroConfig } from '../../config/NitroConfig.js' export function createCppStruct( typename: string, properties: NamedType[] ): FileWithReferencedTypes { // Get C++ code for all struct members const cppStructProps = properties .map((p) => `${p.getCode('c++')} ${p.escapedName} SWIFT_PRIVATE;`) .join('\n') const cppConstructorParams = properties .map((p) => `${p.getCode('c++')} ${p.escapedName}`) .join(', ') const cppInitializerParams = properties .map((p) => `${p.escapedName}(${p.escapedName})`) .join(', ') // Get C++ code for converting each member from a jsi::Value const cppFromJsiParams = properties .map( (p) => `JSIConverter<${p.getCode('c++')}>::fromJSI(runtime, obj.getProperty(runtime, "${p.name}"))` ) .join(',\n') // Get C++ code for converting each member to a jsi::Value const cppToJsiCalls = properties .map( (p) => `obj.setProperty(runtime, "${p.name}", JSIConverter<${p.getCode('c++')}>::toJSI(runtime, arg.${p.escapedName}));` ) .join('\n') // Get C++ code for verifying if jsi::Value can be converted to type const cppCanConvertCalls = properties .map( (p) => `if (!JSIConverter<${p.getCode('c++')}>::canConvert(runtime, obj.getProperty(runtime, "${p.name}"))) return false;` ) .join('\n') // Get C++ includes for each extra-file we need to include const includedTypes = properties.flatMap((r) => r.getRequiredImports()) const cppForwardDeclarations = includedTypes .map((i) => i.forwardDeclaration) .filter((v) => v != null) .filter(isNotDuplicate) const cppExtraIncludes = includedTypes .map((i) => includeHeader(i)) .filter(isNotDuplicate) const cxxNamespace = NitroConfig.getCxxNamespace('c++') const cppCode = ` ${createFileMetadataString(`${typename}.hpp`)} #pragma once ${includeNitroHeader('JSIConverter.hpp')} ${includeNitroHeader('NitroDefines.hpp')} ${cppForwardDeclarations.join('\n')} ${cppExtraIncludes.join('\n')} namespace ${cxxNamespace} { /** * A struct which can be represented as a JavaScript object (${typename}). */ struct ${typename} { public: ${indent(cppStructProps, ' ')} public: ${typename}() = default; explicit ${typename}(${cppConstructorParams}): ${cppInitializerParams} {} }; } // namespace ${cxxNamespace} namespace margelo::nitro { using namespace ${cxxNamespace}; // C++ ${typename} <> JS ${typename} (object) template <> struct JSIConverter<${typename}> final { static inline ${typename} fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); return ${typename}( ${indent(cppFromJsiParams, ' ')} ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const ${typename}& arg) { jsi::Object obj(runtime); ${indent(cppToJsiCalls, ' ')} return obj; } static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { if (!value.isObject()) { return false; } jsi::Object obj = value.getObject(runtime); ${indent(cppCanConvertCalls, ' ')} return true; } }; } // namespace margelo::nitro ` return { content: cppCode, name: `${typename}.hpp`, subdirectory: [], language: 'c++', referencedTypes: properties, platform: 'shared', } }