Skip to content

Commit 1c52775

Browse files
author
houxulu
committed
function with struct
1 parent 0d30f07 commit 1c52775

File tree

3 files changed

+468
-1
lines changed

3 files changed

+468
-1
lines changed

vm/vm.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ var (
4949
errorType = reflect.ValueOf([]error{nil}).Index(0).Type()
5050
vmErrorType = reflect.TypeOf(&Error{})
5151
contextType = reflect.TypeOf((*context.Context)(nil)).Elem()
52+
mapIiType = reflect.TypeOf(map[interface{}]interface{}{})
5253

5354
nilValue = reflect.New(reflect.TypeOf((*interface{})(nil)).Elem()).Elem()
5455
trueValue = reflect.ValueOf(true)

vm/vmContainers_test.go

Lines changed: 372 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package vm
33
import (
44
"fmt"
55
"net/url"
6+
"os"
67
"reflect"
78
"testing"
89

@@ -1924,3 +1925,374 @@ make(struct {
19241925
}
19251926
runTests(t, tests, nil, &Options{Debug: true})
19261927
}
1928+
1929+
func TestFuncWithStructs(t *testing.T) {
1930+
os.Setenv("ANKO_DEBUG", "1")
1931+
tests := []Test{
1932+
{
1933+
Script: `v = {"A":1, "B":2, "C":3, "D":4, "E":5}; rv = FuncWithIntStruct(v); A = rv.A`,
1934+
Input: map[string]interface{}{
1935+
"FuncWithIntStruct": func(v struct {
1936+
A int8
1937+
B int16
1938+
C int32
1939+
D int64
1940+
E int
1941+
}) interface{} {
1942+
return v
1943+
},
1944+
},
1945+
RunOutput: int8(1),
1946+
Output: map[string]interface{}{
1947+
"rv": struct {
1948+
A int8
1949+
B int16
1950+
C int32
1951+
D int64
1952+
E int
1953+
}{
1954+
1, 2, 3, 4, 5,
1955+
},
1956+
},
1957+
},
1958+
{
1959+
Script: `v = {"A":3.14, "B":3.1415926}; rv = FuncWithFloatStruct(v); A = rv.A`,
1960+
Input: map[string]interface{}{
1961+
"FuncWithFloatStruct": func(v struct {
1962+
A float32
1963+
B float64
1964+
}) interface{} {
1965+
return v
1966+
},
1967+
},
1968+
RunOutput: float32(3.14),
1969+
Output: map[string]interface{}{
1970+
"rv": struct {
1971+
A float32
1972+
B float64
1973+
}{
1974+
3.14, 3.1415926,
1975+
},
1976+
},
1977+
},
1978+
{
1979+
Script: `v = {"A":true}; rv = FuncWithBoolStruct(v); A = rv.A`,
1980+
Input: map[string]interface{}{
1981+
"FuncWithBoolStruct": func(v struct {
1982+
A bool
1983+
B bool
1984+
}) interface{} {
1985+
return v
1986+
},
1987+
},
1988+
RunOutput: bool(true),
1989+
Output: map[string]interface{}{
1990+
"rv": struct {
1991+
A bool
1992+
B bool
1993+
}{
1994+
true, false,
1995+
},
1996+
},
1997+
},
1998+
{
1999+
Script: `v = {"A":"A"}; rv = FuncWithStringStruct(v); A = rv.A`,
2000+
Input: map[string]interface{}{
2001+
"FuncWithStringStruct": func(v struct {
2002+
A string
2003+
B string
2004+
}) interface{} {
2005+
return v
2006+
},
2007+
},
2008+
RunOutput: string("A"),
2009+
Output: map[string]interface{}{
2010+
"rv": struct {
2011+
A string
2012+
B string
2013+
}{
2014+
"A", "",
2015+
},
2016+
},
2017+
},
2018+
{
2019+
Script: `A = ["1","2","3"]; B = [1,2,3]; C = [true, false]; v = {"A":A, "B":B, "C":C}; rv = FuncWithSliceStruct(v); A = rv.A`,
2020+
Input: map[string]interface{}{
2021+
"FuncWithSliceStruct": func(v struct {
2022+
A []string
2023+
B []int
2024+
C []bool
2025+
}) interface{} {
2026+
return v
2027+
},
2028+
},
2029+
RunOutput: []string{"1", "2", "3"},
2030+
Output: map[string]interface{}{
2031+
"rv": struct {
2032+
A []string
2033+
B []int
2034+
C []bool
2035+
}{
2036+
A: []string{"1", "2", "3"},
2037+
B: []int{1, 2, 3},
2038+
C: []bool{true, false},
2039+
},
2040+
},
2041+
},
2042+
{
2043+
// map only suport key is interface or string, value can any type
2044+
Script: `A = {"M":"am", "N":1}; B = {"M":"bm", "N":2}; C = {"M":"cm", "N":"cn"}; D = {"M":1, "N":2}; v = {"A": A,"B": B,"C": C,"D": D}; rv = FuncWithMapStruct(v);AM = rv.A["M"]; AN = rv.A["N"]; BM = rv.B["M"]; BN = rv.B["N"]; CM = rv.C["M"]; CN = rv.C["N"]; DM = rv.D["M"]; DN = rv.D["N"];`,
2045+
Input: map[string]interface{}{
2046+
"FuncWithMapStruct": func(v struct {
2047+
A map[interface{}]interface{}
2048+
B map[string]interface{}
2049+
C map[string]string
2050+
D map[string]int
2051+
}) interface{} {
2052+
return v
2053+
},
2054+
},
2055+
RunOutput: 2,
2056+
Output: map[string]interface{}{
2057+
"AM": "am",
2058+
"AN": int64(1),
2059+
"BM": "bm",
2060+
"BN": int64(2),
2061+
"CM": "cm",
2062+
"CN": "cn",
2063+
"DM": 1,
2064+
"DN": 2,
2065+
},
2066+
},
2067+
{
2068+
Script: `d = ["1","2","3"]; e = {"M":"m", "N":1}; v = {"A": 1, "B": true, "C": "c", "D": d, "E":e}; rv = FuncWithCustomStruct(v); A=rv.A; B=rv.B; C=rv.C; D=rv.D; EM=rv.E["M"]; EN=rv.E["N"];`,
2069+
Input: map[string]interface{}{
2070+
"FuncWithCustomStruct": func(v struct {
2071+
A int
2072+
B bool
2073+
C string
2074+
D []string
2075+
E map[interface{}]interface{}
2076+
}) interface{} {
2077+
return v
2078+
},
2079+
},
2080+
RunOutput: int64(1),
2081+
Output: map[string]interface{}{
2082+
"A": int(1),
2083+
"B": true,
2084+
"C": "c",
2085+
"D": []string{"1", "2", "3"},
2086+
"EM": "m",
2087+
"EN": int64(1),
2088+
},
2089+
},
2090+
{
2091+
Script: `d = ["1","2","3"]; e = {"M":1,"N":2}; v = {"A": {"AA":1}, "B": {"BB":true}, "C": {"CC":"c"}, "D": {"DD":d}, "E":{"EE":e}}; rv = FuncWithNestedCustomStruct(v); A=rv.A.AA; B=rv.B.BB; C=rv.C.CC; D=rv.D.DD; EM=rv.E.EE["M"]; EN=rv.E.EE["N"];`,
2092+
Input: map[string]interface{}{
2093+
"FuncWithNestedCustomStruct": func(v struct {
2094+
A struct {
2095+
AA int
2096+
}
2097+
B struct {
2098+
BB bool
2099+
}
2100+
C struct {
2101+
CC string
2102+
}
2103+
D struct {
2104+
DD []string
2105+
}
2106+
E struct {
2107+
EE map[string]int
2108+
}
2109+
}) interface{} {
2110+
return v
2111+
},
2112+
},
2113+
RunOutput: int(2),
2114+
Output: map[string]interface{}{
2115+
"A": 1,
2116+
"B": true,
2117+
"C": "c",
2118+
"D": []string{"1", "2", "3"},
2119+
"EM": 1,
2120+
"EN": 2,
2121+
},
2122+
},
2123+
{
2124+
Script: `d = ["1","2","3"]; e = {"M":true, "N":false}; v = {"A": {"AA":1}, "B": {"BB":true}, "C": {"CC":"c"}, "D": {"DD":d}, "E":{"EE":e}}; rv = FuncWithPointerCustomStruct(v); A=rv.A.AA; B=rv.B.BB; C=rv.C.CC; D=rv.D.DD; EM=rv.E.EE["M"]; EN=rv.E.EE["N"];`,
2125+
Input: map[string]interface{}{
2126+
"FuncWithPointerCustomStruct": func(v *struct {
2127+
A *struct {
2128+
AA int
2129+
}
2130+
B *struct {
2131+
BB bool
2132+
}
2133+
C *struct {
2134+
CC string
2135+
}
2136+
D *struct {
2137+
DD []string
2138+
}
2139+
E *struct {
2140+
EE map[string]bool
2141+
}
2142+
}) interface{} {
2143+
return v
2144+
},
2145+
},
2146+
RunOutput: false,
2147+
Output: map[string]interface{}{
2148+
"A": 1,
2149+
"B": true,
2150+
"C": "c",
2151+
"D": []string{"1", "2", "3"},
2152+
"EM": true,
2153+
"EN": false,
2154+
},
2155+
},
2156+
{
2157+
Script: `a = [{"AA":"1"},{"AA":"2"}]; b = [{"BB":1},{"BB":2}]; v = {"A":a, "B":b}; rv = FuncWithSliceCustomStruct(v); A0 = rv.A[0].AA; A1 = rv.A[1].AA; B0 = rv.B[0].BB; B1 = rv.B[1].BB;`,
2158+
Input: map[string]interface{}{
2159+
"FuncWithSliceCustomStruct": func(v struct {
2160+
A []struct {
2161+
AA string
2162+
}
2163+
B []*struct {
2164+
BB int
2165+
}
2166+
}) interface{} {
2167+
return v
2168+
},
2169+
},
2170+
RunOutput: 2,
2171+
Output: map[string]interface{}{
2172+
"A0": "1",
2173+
"A1": "2",
2174+
"B0": 1,
2175+
"B1": 2,
2176+
},
2177+
},
2178+
{
2179+
Script: `a = {"M":{"AA":"1"}, 123:{"AA":"2"}}; b = {"M":{"BB":1},"N":{"BB":2}}; v = {"A":a, "B":b}; rv = FuncWithMapCustomStruct(v); AM = rv.A["M"].AA; AN = rv.A[123].AA; BM = rv.B["M"].BB; BN = rv.B["N"].BB;`,
2180+
Input: map[string]interface{}{
2181+
"FuncWithMapCustomStruct": func(v struct {
2182+
A map[interface{}]struct {
2183+
AA string
2184+
}
2185+
B map[string]*struct {
2186+
BB int
2187+
}
2188+
}) interface{} {
2189+
return v
2190+
},
2191+
},
2192+
RunOutput: 2,
2193+
Output: map[string]interface{}{
2194+
"AM": "1",
2195+
"AN": "2",
2196+
"BM": 1,
2197+
"BN": 2,
2198+
},
2199+
},
2200+
{
2201+
Script: `v = [{"A":"A", "B":1, "C":false}, {"A":"A1", "B":2, "C":true}]; rv = FuncWithStructSlice(v); A0 = rv[0].A; B0 = rv[0].B; C0 = rv[0].C; A1 = rv[1].A; B1 = rv[1].B; C1 = rv[1].C;`,
2202+
Input: map[string]interface{}{
2203+
"FuncWithStructSlice": func(v []struct {
2204+
A string
2205+
B int
2206+
C bool
2207+
}) interface{} {
2208+
return v
2209+
},
2210+
},
2211+
RunOutput: true,
2212+
Output: map[string]interface{}{
2213+
"A0": "A",
2214+
"B0": 1,
2215+
"C0": false,
2216+
"A1": "A1",
2217+
"B1": 2,
2218+
"C1": true,
2219+
},
2220+
},
2221+
{
2222+
Script: `v = {"M":{"A":"A", "B":1, "C":false}, "N":{"A":"A1", "B":2, "C":true}}; rv = FuncWithStructMap(v); MA = rv["M"].A; MB = rv["M"].B; MC = rv["M"].C; NA = rv["N"].A; NB = rv["N"].B; NC = rv["N"].C;`,
2223+
Input: map[string]interface{}{
2224+
"FuncWithStructMap": func(v map[string]struct {
2225+
A string
2226+
B int
2227+
C bool
2228+
}) interface{} {
2229+
return v
2230+
},
2231+
},
2232+
RunOutput: true,
2233+
Output: map[string]interface{}{
2234+
"MA": "A",
2235+
"MB": 1,
2236+
"MC": false,
2237+
"NA": "A1",
2238+
"NB": 2,
2239+
"NC": true,
2240+
},
2241+
},
2242+
}
2243+
runTests(t, tests, nil, &Options{Debug: true})
2244+
}
2245+
2246+
/* Benchmark test result
2247+
goos: linux
2248+
goarch: amd64
2249+
pkg: github.com/mattn/anko/vm
2250+
BenchmarkToStruct-16 199296 6095 ns/op 1672 B/op 43 allocs/op
2251+
*/
2252+
func BenchmarkToStruct(b *testing.B) {
2253+
rv := reflect.ValueOf(map[interface{}]interface{}{
2254+
"A": true,
2255+
"B": 1,
2256+
"C": 3.14,
2257+
"D": "d",
2258+
"E": []interface{}{"e1", "e2"},
2259+
"F": map[interface{}]interface{}{
2260+
"f1": "f1",
2261+
"f2": "f2",
2262+
},
2263+
"G": map[interface{}]interface{}{
2264+
"A": true,
2265+
"B": 1,
2266+
"C": 3.14,
2267+
"D": "d",
2268+
"E": []interface{}{"e1", "e2"},
2269+
"F": map[interface{}]interface{}{
2270+
"f1": "f1",
2271+
"f2": "f2",
2272+
},
2273+
},
2274+
})
2275+
rt := reflect.TypeOf(struct {
2276+
A bool
2277+
B int
2278+
C float32
2279+
D string
2280+
E []string
2281+
F map[string]string
2282+
G struct {
2283+
A bool
2284+
B int
2285+
C float32
2286+
D string
2287+
E []string
2288+
F map[string]string
2289+
}
2290+
}{})
2291+
2292+
for i := 0; i < b.N; i++ {
2293+
_, err := convertReflectValueToType(rv, rt)
2294+
if err != nil {
2295+
b.Errorf("BenchmarkConvertReflectValueToStruct %v", err)
2296+
}
2297+
}
2298+
}

0 commit comments

Comments
 (0)