diff --git a/packages/schema/bind/src/bindings/assemblyscript/functions.ts b/packages/schema/bind/src/bindings/assemblyscript/functions.ts index 12f8adfbd3..44c34685a7 100644 --- a/packages/schema/bind/src/bindings/assemblyscript/functions.ts +++ b/packages/schema/bind/src/bindings/assemblyscript/functions.ts @@ -1,5 +1,5 @@ -import { isBaseType, isKeyword } from "./types"; import { MustacheFn } from "../types"; +import { isBaseType, isKeyword } from "./types"; // check if any of the keywords match the property name; // if there's a match, insert `_` at the beginning of the property name. @@ -67,13 +67,29 @@ export const toWasmInit: MustacheFn = () => { } if (type.startsWith("Map<")) { - const openBracketIdx = type.indexOf("<"); - const closeBracketIdx = type.lastIndexOf(">"); - const [key, value] = type - .substring(openBracketIdx + 1, closeBracketIdx) - .split(",") - .map((x) => toWasm()(x.trim(), render)); - return `new Map<${key}, ${value}>()`; + const firstOpenBracketIdx = type.indexOf("<"); + const lastCloseBracketIdx = type.lastIndexOf(">"); + if (firstOpenBracketIdx === -1 || lastCloseBracketIdx === -1) { + throw new Error(`Invalid Map: ${type}`); + } + + const keyValTypes = type.substring( + firstOpenBracketIdx + 1, + lastCloseBracketIdx + ); + + const firstCommaIdx = keyValTypes.indexOf(","); + if (firstCommaIdx === -1) { + throw new Error(`Invalid Map: ${type}`); + } + + const keyType = keyValTypes.substring(0, firstCommaIdx).trim(); + const valType = keyValTypes.substring(firstCommaIdx + 1).trim(); + + const wasmKeyType = toWasm()(keyType, (str) => str); + const wasmValType = toWasm()(valType, (str) => str); + + return `new Map<${wasmKeyType}, ${wasmValType}>()`; } switch (type) { @@ -198,23 +214,27 @@ const toWasmMap = (type: string, optional: boolean): string => { const firstOpenBracketIdx = type.indexOf("<"); const lastCloseBracketIdx = type.lastIndexOf(">"); - if (!(firstOpenBracketIdx !== -1 && lastCloseBracketIdx !== -1)) { + if (firstOpenBracketIdx === -1 || lastCloseBracketIdx === -1) { throw new Error(`Invalid Map: ${type}`); } - const keyValTypes = type - .substring(firstOpenBracketIdx + 1, lastCloseBracketIdx) - .split(",") - .map((x) => x.trim()); + const keyValTypes = type.substring( + firstOpenBracketIdx + 1, + lastCloseBracketIdx + ); - if (keyValTypes.length !== 2 || !keyValTypes[0] || !keyValTypes[1]) { + const firstCommaIdx = keyValTypes.indexOf(","); + if (firstCommaIdx === -1) { throw new Error(`Invalid Map: ${type}`); } - const keyType = toWasm()(keyValTypes[0], (str) => str); - const valType = toWasm()(keyValTypes[1], (str) => str); + const keyType = keyValTypes.substring(0, firstCommaIdx).trim(); + const valType = keyValTypes.substring(firstCommaIdx + 1).trim(); + + const wasmKeyType = toWasm()(keyType, (str) => str); + const wasmValType = toWasm()(valType, (str) => str); - return applyOptional(`Map<${keyType}, ${valType}>`, optional, false); + return applyOptional(`Map<${wasmKeyType}, ${wasmValType}>`, optional, false); }; const applyOptional = ( diff --git a/packages/schema/bind/src/bindings/rust/functions.ts b/packages/schema/bind/src/bindings/rust/functions.ts index 67605e8445..1bf2dc995e 100644 --- a/packages/schema/bind/src/bindings/rust/functions.ts +++ b/packages/schema/bind/src/bindings/rust/functions.ts @@ -154,13 +154,30 @@ export const toWasmInit: MustacheFn = () => { } if (type.startsWith("Map<")) { - const openBracketIdx = type.indexOf("<"); - const closeBracketIdx = type.lastIndexOf(">"); - const [key, value] = type - .substring(openBracketIdx + 1, closeBracketIdx) - .split(",") - .map((x) => toWasm()(x.trim(), render)); - return optionalModifier(`Map::<${key}, ${value}>::new()`); + const firstOpenBracketIdx = type.indexOf("<"); + const lastCloseBracketIdx = type.lastIndexOf(">"); + + if (firstOpenBracketIdx === -1 || lastCloseBracketIdx === -1) { + throw new Error(`Invalid Map: ${type}`); + } + + const keyValTypes = type.substring( + firstOpenBracketIdx + 1, + lastCloseBracketIdx + ); + + const firstCommaIdx = keyValTypes.indexOf(","); + if (firstCommaIdx === -1) { + throw new Error(`Invalid Map: ${type}`); + } + + const keyType = keyValTypes.substring(0, firstCommaIdx).trim(); + const valType = keyValTypes.substring(firstCommaIdx + 1).trim(); + + const wasmKeyType = toWasm()(keyType, (str) => str); + const wasmValType = toWasm()(valType, (str) => str); + + return optionalModifier(`Map::<${wasmKeyType}, ${wasmValType}>::new()`); } switch (type) { @@ -302,23 +319,27 @@ const toWasmMap = (type: string, optional: boolean): string => { const firstOpenBracketIdx = type.indexOf("<"); const lastCloseBracketIdx = type.lastIndexOf(">"); - if (!(firstOpenBracketIdx !== -1 && lastCloseBracketIdx !== -1)) { + if (firstOpenBracketIdx === -1 || lastCloseBracketIdx === -1) { throw new Error(`Invalid Map: ${type}`); } - const keyValTypes = type - .substring(firstOpenBracketIdx + 1, lastCloseBracketIdx) - .split(",") - .map((x) => x.trim()); + const keyValTypes = type.substring( + firstOpenBracketIdx + 1, + lastCloseBracketIdx + ); - if (keyValTypes.length !== 2 || !keyValTypes[0] || !keyValTypes[1]) { + const firstCommaIdx = keyValTypes.indexOf(","); + if (firstCommaIdx === -1) { throw new Error(`Invalid Map: ${type}`); } - const keyType = toWasm()(keyValTypes[0], (str) => str); - const valType = toWasm()(keyValTypes[1], (str) => str); + const keyType = keyValTypes.substring(0, firstCommaIdx).trim(); + const valType = keyValTypes.substring(firstCommaIdx + 1).trim(); + + const wasmKeyType = toWasm()(keyType, (str) => str); + const wasmValType = toWasm()(valType, (str) => str); - return applyOptional(`Map<${keyType}, ${valType}>`, optional); + return applyOptional(`Map<${wasmKeyType}, ${wasmValType}>`, optional); }; const applyOptional = (type: string, optional: boolean): string => { diff --git a/packages/schema/bind/src/bindings/typescript/functions.ts b/packages/schema/bind/src/bindings/typescript/functions.ts index e38b0ce3d6..1c47e7f24a 100644 --- a/packages/schema/bind/src/bindings/typescript/functions.ts +++ b/packages/schema/bind/src/bindings/typescript/functions.ts @@ -109,13 +109,17 @@ const toTypescriptMap = (type: string, optional: boolean): string => { const openAngleBracketIdx = type.indexOf("<"); const closeAngleBracketIdx = type.lastIndexOf(">"); - const [keyType, valtype] = type - .substring(openAngleBracketIdx + 1, closeAngleBracketIdx) - .split(",") - .map((x) => x.trim()); + const keyValTypes = type.substring( + openAngleBracketIdx + 1, + closeAngleBracketIdx + ); + + const firstCommaIdx = keyValTypes.indexOf(","); + const keyType = keyValTypes.substring(0, firstCommaIdx).trim(); + const valType = keyValTypes.substring(firstCommaIdx + 1).trim(); const tsKeyType = _toTypescript(keyType, (str) => str); - const tsValType = _toTypescript(valtype, (str) => str, true); + const tsValType = _toTypescript(valType, (str) => str, true); return applyOptional(`Map<${tsKeyType}, ${tsValType}>`, optional); }; diff --git a/packages/test-cases/cases/bind/sanity/input/schema.graphql b/packages/test-cases/cases/bind/sanity/input/schema.graphql index c91cdb1dab..298c8fd244 100644 --- a/packages/test-cases/cases/bind/sanity/input/schema.graphql +++ b/packages/test-cases/cases/bind/sanity/input/schema.graphql @@ -56,6 +56,7 @@ type Module @imports( optEnumArray: [CustomEnum] map: Map! @annotate(type: "Map!") mapOfArr: Map! @annotate(type: "Map!") + mapOfMap: Map! @annotate(type: "Map!>!") mapOfObj: Map! @annotate(type: "Map!") mapOfArrOfObj: Map! @annotate(type: "Map!") ): Int! diff --git a/packages/test-cases/cases/bind/sanity/output/plugin-ts/module.ts b/packages/test-cases/cases/bind/sanity/output/plugin-ts/module.ts index 6aae6c7543..d5f83d6b66 100644 --- a/packages/test-cases/cases/bind/sanity/output/plugin-ts/module.ts +++ b/packages/test-cases/cases/bind/sanity/output/plugin-ts/module.ts @@ -18,6 +18,7 @@ export interface Args_moduleMethod extends Record { optEnumArray?: Array | null; map: Map; mapOfArr: Map>; + mapOfMap: Map>; mapOfObj: Map; mapOfArrOfObj: Map>; } diff --git a/packages/test-cases/cases/bind/sanity/output/plugin-ts/wrap.info.ts b/packages/test-cases/cases/bind/sanity/output/plugin-ts/wrap.info.ts index 3ef889121d..aa4c46cec8 100644 --- a/packages/test-cases/cases/bind/sanity/output/plugin-ts/wrap.info.ts +++ b/packages/test-cases/cases/bind/sanity/output/plugin-ts/wrap.info.ts @@ -779,6 +779,72 @@ export const manifest: WrapManifest = { "required": true, "type": "Map" }, + { + "kind": 34, + "map": { + "key": { + "kind": 4, + "name": "mapOfMap", + "required": true, + "type": "String" + }, + "kind": 262146, + "map": { + "key": { + "kind": 4, + "name": "mapOfMap", + "required": true, + "type": "String" + }, + "kind": 262146, + "name": "mapOfMap", + "required": true, + "scalar": { + "kind": 4, + "name": "mapOfMap", + "required": true, + "type": "Int" + }, + "type": "Map", + "value": { + "kind": 4, + "name": "mapOfMap", + "required": true, + "type": "Int" + } + }, + "name": "mapOfMap", + "required": true, + "type": "Map>", + "value": { + "key": { + "kind": 4, + "name": "mapOfMap", + "required": true, + "type": "String" + }, + "kind": 262146, + "name": "mapOfMap", + "required": true, + "scalar": { + "kind": 4, + "name": "mapOfMap", + "required": true, + "type": "Int" + }, + "type": "Map", + "value": { + "kind": 4, + "name": "mapOfMap", + "required": true, + "type": "Int" + } + } + }, + "name": "mapOfMap", + "required": true, + "type": "Map>" + }, { "kind": 34, "map": { diff --git a/packages/test-cases/cases/bind/sanity/output/wasm-as/Module/serialization.ts b/packages/test-cases/cases/bind/sanity/output/wasm-as/Module/serialization.ts index c3f3a0d5db..4fe8792357 100644 --- a/packages/test-cases/cases/bind/sanity/output/wasm-as/Module/serialization.ts +++ b/packages/test-cases/cases/bind/sanity/output/wasm-as/Module/serialization.ts @@ -21,6 +21,7 @@ export class Args_moduleMethod { optEnumArray: Array> | null; map: Map; mapOfArr: Map>; + mapOfMap: Map>; mapOfObj: Map; mapOfArrOfObj: Map>; } @@ -43,6 +44,8 @@ export function deserializemoduleMethodArgs(argsBuf: ArrayBuffer): Args_moduleMe let _mapSet: bool = false; let _mapOfArr: Map> = new Map>(); let _mapOfArrSet: bool = false; + let _mapOfMap: Map> = new Map>(); + let _mapOfMapSet: bool = false; let _mapOfObj: Map = new Map(); let _mapOfObjSet: bool = false; let _mapOfArrOfObj: Map> = new Map>(); @@ -156,6 +159,20 @@ export function deserializemoduleMethodArgs(argsBuf: ArrayBuffer): Args_moduleMe _mapOfArrSet = true; reader.context().pop(); } + else if (field == "mapOfMap") { + reader.context().push(field, "Map>", "type found, reading property"); + _mapOfMap = reader.readExtGenericMap((reader: Read): string => { + return reader.readString(); + }, (reader: Read): Map => { + return reader.readExtGenericMap((reader: Read): string => { + return reader.readString(); + }, (reader: Read): i32 => { + return reader.readInt32(); + }); + }); + _mapOfMapSet = true; + reader.context().pop(); + } else if (field == "mapOfObj") { reader.context().push(field, "Map", "type found, reading property"); _mapOfObj = reader.readExtGenericMap((reader: Read): string => { @@ -198,6 +215,9 @@ export function deserializemoduleMethodArgs(argsBuf: ArrayBuffer): Args_moduleMe if (!_mapOfArrSet) { throw new Error(reader.context().printWithContext("Missing required argument: 'mapOfArr: Map'")); } + if (!_mapOfMapSet) { + throw new Error(reader.context().printWithContext("Missing required argument: 'mapOfMap: Map>'")); + } if (!_mapOfObjSet) { throw new Error(reader.context().printWithContext("Missing required argument: 'mapOfObj: Map'")); } @@ -214,6 +234,7 @@ export function deserializemoduleMethodArgs(argsBuf: ArrayBuffer): Args_moduleMe optEnumArray: _optEnumArray, map: _map, mapOfArr: _mapOfArr, + mapOfMap: _mapOfMap, mapOfObj: _mapOfObj, mapOfArrOfObj: _mapOfArrOfObj }; diff --git a/packages/test-cases/cases/bind/sanity/output/wasm-as/Module/wrapped.ts b/packages/test-cases/cases/bind/sanity/output/wasm-as/Module/wrapped.ts index 6eb47467e1..9de3884c85 100644 --- a/packages/test-cases/cases/bind/sanity/output/wasm-as/Module/wrapped.ts +++ b/packages/test-cases/cases/bind/sanity/output/wasm-as/Module/wrapped.ts @@ -30,6 +30,7 @@ export function moduleMethodWrapped(argsBuf: ArrayBuffer, env_size: u32): ArrayB optEnumArray: args.optEnumArray, map: args.map, mapOfArr: args.mapOfArr, + mapOfMap: args.mapOfMap, mapOfObj: args.mapOfObj, mapOfArrOfObj: args.mapOfArrOfObj } diff --git a/packages/test-cases/cases/bind/sanity/output/wasm-rs/module/serialization.rs b/packages/test-cases/cases/bind/sanity/output/wasm-rs/module/serialization.rs index 73884c9578..678a6ae880 100644 --- a/packages/test-cases/cases/bind/sanity/output/wasm-rs/module/serialization.rs +++ b/packages/test-cases/cases/bind/sanity/output/wasm-rs/module/serialization.rs @@ -32,6 +32,7 @@ pub struct ArgsModuleMethod { pub opt_enum_array: Option>>, pub map: Map, pub map_of_arr: Map>, + pub map_of_map: Map>, pub map_of_obj: Map, pub map_of_arr_of_obj: Map>, } @@ -56,6 +57,8 @@ pub fn deserialize_module_method_args(args: &[u8]) -> Result> = Map::>::new(); let mut _map_of_arr_set = false; + let mut _map_of_map: Map> = Map::>::new(); + let mut _map_of_map_set = false; let mut _map_of_obj: Map = Map::::new(); let mut _map_of_obj_set = false; let mut _map_of_arr_of_obj: Map> = Map::>::new(); @@ -161,6 +164,20 @@ pub fn deserialize_module_method_args(args: &[u8]) -> Result { + reader.context().push(&field, "Map>", "type found, reading argument"); + _map_of_map = reader.read_ext_generic_map(|reader| { + reader.read_string() + }, |reader| { + reader.read_ext_generic_map(|reader| { + reader.read_string() + }, |reader| { + reader.read_i32() + }) + })?; + _map_of_map_set = true; + reader.context().pop(); + } "mapOfObj" => { reader.context().push(&field, "Map", "type found, reading argument"); _map_of_obj = reader.read_ext_generic_map(|reader| { @@ -203,6 +220,9 @@ pub fn deserialize_module_method_args(args: &[u8]) -> Result.".to_string())); } + if !_map_of_map_set { + return Err(DecodeError::MissingField("mapOfMap: Map>.".to_string())); + } if !_map_of_obj_set { return Err(DecodeError::MissingField("mapOfObj: Map.".to_string())); } @@ -219,6 +239,7 @@ pub fn deserialize_module_method_args(args: &[u8]) -> Result Vec { opt_enum_array: args.opt_enum_array, map: args.map, map_of_arr: args.map_of_arr, + map_of_map: args.map_of_map, map_of_obj: args.map_of_obj, map_of_arr_of_obj: args.map_of_arr_of_obj, });