def type_to_string(f, map_types):
    """
    Convert type info to pretty names, based on numbers from from FieldDescriptorProto
    https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor.pb
    """
    if f.type in [1]:
        return "double"
    elif f.type in [2]:
        return "float"
    elif f.type in [3]:
        return "long"
    elif f.type in [4]:
        return "uint64"
    elif f.type in [5]:
        return "integer"
    elif f.type in [6]:
        return "fixed64"
    elif f.type in [7]:
        return "fixed32"
    elif f.type in [8]:
        return "boolean"
    elif f.type in [9]:
        return "string"
    # missing type 10 - Group
    elif f.type in [11, 14]:
        ref_name = f.ref_type
        if ref_name in map_types:
            ref_fields = map_types[ref_name]
            return {
                "type": "map",
                "key": " %s "% type_to_string(ref_fields["key"], map_types),
                "value": " %s "% type_to_string(ref_fields["value"], map_types)
            }
        else:
            kind = ":protobuf:message:`%s`" % simplify_name(f.ref_type)
            if f.label == 3: # LABEL_REPEATED
                return "list of " + kind
            else:
                return kind
    elif f.type in [12]:
        return "bytes"
    elif f.type in [13]:
        return "uint32"
    elif f.type in [15]:
        return "sfixed32"
    elif f.type in [16]:
        return "sfixed64"
    elif f.type in [17]:
        return "sint32"
    elif f.type in [18]:
        return "sint64"
    else:
        raise Exception, f.type
Convert type info to pretty names, based on numbers from from FieldDescriptorProto
    https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor.pb