func mruby2go(mrb *C.mrb_state, o C.mrb_value) interface{} { switch o.tt { case C.MRB_TT_TRUE: return true case C.MRB_TT_FALSE: return false case C.MRB_TT_FLOAT: return float32(C._mrb_float(o)) case C.MRB_TT_FIXNUM: return int32(C._mrb_fixnum(o)) case C.MRB_TT_ARRAY: { var list []interface{} for i := 0; i < int(C._RARRAY_LEN(o)); i++ { list = append(list, mruby2go(mrb, C.mrb_ary_ref(mrb, o, C.mrb_int(i)))) } return list } case C.MRB_TT_HASH: { hash := make(map[string]interface{}) keys := C.mrb_hash_keys(mrb, o) for i := 0; i < int(C._RARRAY_LEN(keys)); i++ { key := C.mrb_ary_ref(mrb, keys, C.mrb_int(i)) val := C.mrb_hash_get(mrb, o, key) hash[C.GoString(C.mrb_string_value_ptr(mrb, key))] = mruby2go(mrb, val) } return hash } case C.MRB_TT_STRING: return C.GoString(C.mrb_string_value_ptr(mrb, o)) } return nil }
// Converts mruby value to Go value. func (m *MRuby) goValue(v C.mrb_value) interface{} { switch v.tt { case C.MRB_TT_UNDEF: // for example, result of syntax error return nil case C.MRB_TT_TRUE: return true case C.MRB_TT_FALSE: if C._gomruby_is_nil(v) == 0 { return false } return nil case C.MRB_TT_FIXNUM: return int(C._gomruby_fixnum(v)) case C.MRB_TT_FLOAT: return float64(C._gomruby_float(v)) case C.MRB_TT_SYMBOL: cs := C.mrb_string_value_ptr(m.state, v) return Symbol(C.GoString(cs)) case C.MRB_TT_STRING: cs := C.mrb_string_value_ptr(m.state, v) return C.GoString(cs) case C.MRB_TT_ARRAY: l := int(C.mrb_ary_len(m.state, v)) res := make([]interface{}, l) for i := 0; i < l; i++ { res[i] = m.goValue(C.mrb_ary_ref(m.state, v, C.mrb_int(i))) } return res case C.MRB_TT_HASH: keys := C.mrb_hash_keys(m.state, v) l := int(C.mrb_ary_len(m.state, keys)) res := make(map[interface{}]interface{}, l) for i := 0; i < l; i++ { key := C.mrb_ary_ref(m.state, keys, C.mrb_int(i)) val := C.mrb_hash_get(m.state, v, key) res[m.goValue(key)] = m.goValue(val) } return res } panic(fmt.Errorf("gomruby bug: failed to convert mruby value %#v to Go value", v)) }