1 /* go-can-convert-interface.c -- can we convert to an interface? 2 3 Copyright 2009 The Go Authors. All rights reserved. 4 Use of this source code is governed by a BSD-style 5 license that can be found in the LICENSE file. */ 6 7 #include "runtime.h" 8 #include "go-assert.h" 9 #include "go-string.h" 10 #include "go-type.h" 11 #include "interface.h" 12 13 /* Return whether we can convert from the type in FROM_DESCRIPTOR to 14 the interface in TO_DESCRIPTOR. This is used for type 15 switches. */ 16 17 _Bool __go_can_convert_to_interface(const struct __go_type_descriptor * to_descriptor,const struct __go_type_descriptor * from_descriptor)18__go_can_convert_to_interface ( 19 const struct __go_type_descriptor *to_descriptor, 20 const struct __go_type_descriptor *from_descriptor) 21 { 22 const struct __go_interface_type *to_interface; 23 int to_method_count; 24 const struct __go_interface_method *to_method; 25 const struct __go_uncommon_type *from_uncommon; 26 int from_method_count; 27 const struct __go_method *from_method; 28 int i; 29 30 /* In a type switch FROM_DESCRIPTOR can be NULL. */ 31 if (from_descriptor == NULL) 32 return 0; 33 34 __go_assert ((to_descriptor->__code & GO_CODE_MASK) == GO_INTERFACE); 35 to_interface = (const struct __go_interface_type *) to_descriptor; 36 to_method_count = to_interface->__methods.__count; 37 to_method = ((const struct __go_interface_method *) 38 to_interface->__methods.__values); 39 40 from_uncommon = from_descriptor->__uncommon; 41 if (from_uncommon == NULL) 42 { 43 from_method_count = 0; 44 from_method = NULL; 45 } 46 else 47 { 48 from_method_count = from_uncommon->__methods.__count; 49 from_method = ((const struct __go_method *) 50 from_uncommon->__methods.__values); 51 } 52 53 for (i = 0; i < to_method_count; ++i) 54 { 55 while (from_method_count > 0 56 && (!__go_ptr_strings_equal (from_method->__name, 57 to_method->__name) 58 || !__go_ptr_strings_equal (from_method->__pkg_path, 59 to_method->__pkg_path))) 60 { 61 ++from_method; 62 --from_method_count; 63 } 64 65 if (from_method_count == 0) 66 return 0; 67 68 if (!__go_type_descriptors_equal (from_method->__mtype, 69 to_method->__type)) 70 return 0; 71 72 ++to_method; 73 ++from_method; 74 --from_method_count; 75 } 76 77 return 1; 78 } 79