001package net.gdface.codegen.thrift; 002 003import static com.google.common.base.Preconditions.*; 004 005import com.google.common.base.Supplier; 006import com.google.common.base.Suppliers; 007 008/** 009 * 定义thrift协议cxx类型 010 * @author guyadong 011 * 012 */ 013public class CxxTypeMeta { 014 015 enum ThriftProtocolType { 016 TYPE_VOID(true,false,false), 017 TYPE_STRING(true,false,false), 018 TYPE_BOOL(true,false,false), 019 TYPE_I8(true,false,true), 020 TYPE_I16(true,false,true), 021 TYPE_I32(true,false,true), 022 TYPE_I64(true,false,true), 023 TYPE_DOUBLE(true,false,true), 024 TYPE_BINARY(true,false,false), 025 TYPE_STRUCT(false,false,false), 026 TYPE_MAP(false,true,false), 027 TYPE_SET(false,true,false), 028 TYPE_LIST(false,true,false), 029 TYPE_ENUM(false,false,false); 030 public final boolean isBaseType,isContainer,isNumber; 031 private ThriftProtocolType(boolean isBaseType, boolean isContainer,boolean isNumber) { 032 this.isBaseType = isBaseType; 033 this.isContainer = isContainer; 034 this.isNumber = isNumber; 035 } 036 private Supplier<String> getTypeSupplier(CxxTypeMeta meta){ 037 switch(this){ 038 case TYPE_MAP: 039 return meta.mapSupplier; 040 case TYPE_SET: 041 return meta.setSupplier; 042 case TYPE_LIST: 043 return meta.listSupplier; 044 default: 045 return meta.type; 046 } 047 } 048 }; 049 public static final CxxTypeMeta BOOL = new CxxTypeMeta(ThriftProtocolType.TYPE_BOOL, "bool"); 050 public static final CxxTypeMeta BYTE = new CxxTypeMeta(ThriftProtocolType.TYPE_I8, "int8_t"); 051 public static final CxxTypeMeta DOUBLE = new CxxTypeMeta(ThriftProtocolType.TYPE_DOUBLE, "double"); 052 public static final CxxTypeMeta I16 = new CxxTypeMeta(ThriftProtocolType.TYPE_I16, "int16_t"); 053 public static final CxxTypeMeta I32 = new CxxTypeMeta(ThriftProtocolType.TYPE_I32, "int32_t"); 054 public static final CxxTypeMeta I64 = new CxxTypeMeta(ThriftProtocolType.TYPE_I64, "int64_t"); 055 public static final CxxTypeMeta STRING = new CxxTypeMeta(ThriftProtocolType.TYPE_STRING, "std::string"); 056 public static final CxxTypeMeta BINARY = new CxxTypeMeta(ThriftProtocolType.TYPE_BINARY, "std::string"); 057 public static final CxxTypeMeta VOID = new CxxTypeMeta(ThriftProtocolType.TYPE_VOID, "void"); 058 private Supplier<String> arraySupplier=new Supplier<String>(){ 059 @Override 060 public String get() { 061 StringBuilder sb = new StringBuilder(); 062 sb.append("std::vector<") 063 .append(valueType.getType()).append(">"); 064 return sb.toString(); 065 }}; 066 private Supplier<String> listSupplier=new Supplier<String>(){ 067 068 @Override 069 public String get() { 070 StringBuilder sb = new StringBuilder(); 071 sb.append("std::vector<") 072 .append(valueType.getType()).append(">"); 073 return sb.toString(); 074 }}; 075 private Supplier<String> setSupplier=new Supplier<String>(){ 076 077 @Override 078 public String get() { 079 StringBuilder sb = new StringBuilder(); 080 sb.append("std::set<") 081 .append(valueType.getType()).append(">"); 082 return sb.toString(); 083 }}; 084 private Supplier<String> mapSupplier = new Supplier<String>(){ 085 086 @Override 087 public String get() { 088 StringBuilder sb = new StringBuilder(); 089 sb.append("std::map<") 090 .append(keyType.getType()).append(",") 091 .append(valueType.getType()).append(">"); 092 return sb.toString(); 093 }}; 094 private final ThriftProtocolType protocolType; 095 private final CxxTypeMeta keyType; 096 private final CxxTypeMeta valueType; 097 private final Supplier<String> type; 098 private final boolean isArray; 099 private static class NameSupplier implements Supplier<String>{ 100 private String cxxType; 101 102 public NameSupplier(String cxxType) { 103 super(); 104 checkArgument(null !=cxxType, "cxxType is null"); 105 this.cxxType = cxxType; 106 } 107 108 @Override 109 public String get() { 110 return CxxHelper.getTypeName(cxxType); 111 } 112 } 113 static CxxTypeMeta struct(final String cxxType) 114 { 115 Supplier<String> supplier = new NameSupplier(cxxType); 116 return new CxxTypeMeta(ThriftProtocolType.TYPE_STRUCT,supplier); 117 } 118 119 static CxxTypeMeta enumType(final String cxxType) 120 { 121 Supplier<String> supplier = new NameSupplier(cxxType); 122 return new CxxTypeMeta(ThriftProtocolType.TYPE_ENUM,supplier); 123 } 124 125 static <K, V> CxxTypeMeta map(CxxTypeMeta keyType, CxxTypeMeta valueType) 126 { 127 if(null == valueType || null == valueType){ 128 return null; 129 } 130 131 return new CxxTypeMeta(ThriftProtocolType.TYPE_MAP, keyType, valueType, false); 132 } 133 static <E> CxxTypeMeta set(CxxTypeMeta valueType) 134 { 135 if(null == valueType){ 136 return null; 137 } 138 139 return new CxxTypeMeta(ThriftProtocolType.TYPE_SET, null, valueType, false); 140 } 141 142 static <E> CxxTypeMeta list(CxxTypeMeta valueType) 143 { 144 if(null == valueType){ 145 return null; 146 } 147 148 return new CxxTypeMeta(ThriftProtocolType.TYPE_LIST, null, valueType, false); 149 } 150 static CxxTypeMeta array(CxxTypeMeta valueType) 151 { 152 if(null == valueType){ 153 return null; 154 } 155 return new CxxTypeMeta(ThriftProtocolType.TYPE_LIST, null, valueType, true); 156 } 157 /** 158 * 容器类型构造方法<br> 159 * {@code isAray}为{@code true}且{@code valueType}为BYTE时,也允许{@code protocolType}为BINARY 160 * @param protocolType 161 * @param keyType 162 * @param valueType 163 * @param isArray 164 */ 165 private CxxTypeMeta(ThriftProtocolType protocolType, CxxTypeMeta keyType, CxxTypeMeta valueType, boolean isArray) 166 { 167 checkArgument(null !=protocolType, "protocolType is null"); 168 checkArgument(protocolType.equals(ThriftProtocolType.TYPE_BINARY) || protocolType.isContainer, "protocolType must be SET,MAP,LIST,BINARY"); 169 if(isArray){ 170 checkArgument(protocolType.equals(ThriftProtocolType.TYPE_LIST) || protocolType.equals(ThriftProtocolType.TYPE_BINARY),"protocolType must be LIST or BINARY,if isArray"); 171 if(protocolType.equals(ThriftProtocolType.TYPE_BINARY)){ 172 checkArgument(BYTE.equals(valueType),"valueType must be BYTE,if isArray is true and protocolType is TYPE_LIST"); 173 } 174 } 175 this.protocolType = protocolType; 176 this.isArray=isArray; 177 this.type = isArray? arraySupplier : protocolType.getTypeSupplier(this); 178 this.keyType = keyType; 179 this.valueType = checkNotNull(valueType,"valueType is null"); 180 } 181 /** 182 * 简单类型构造方法 183 * @param protocolType 184 * @param cxxType 185 */ 186 private CxxTypeMeta(ThriftProtocolType protocolType, String cxxType){ 187 this(protocolType,Suppliers.ofInstance(checkNotNull(cxxType, "cxxType is null"))); 188 } 189 /** 190 * 非容器类型构造方法 191 * @param protocolType 192 * @param cxxType 193 */ 194 private CxxTypeMeta(ThriftProtocolType protocolType, Supplier<String> cxxType){ 195 checkNotNull(protocolType, "protocolType is null"); 196 checkArgument(!protocolType.isContainer, "protocolType must not be SET,MAP,LIST"); 197 checkNotNull(cxxType, "cxxType is null"); 198 this.protocolType = protocolType; 199 this.isArray = false; 200 this.type = cxxType; 201 this.keyType = null; 202 this.valueType = null; 203 } 204 public String getType(){ 205 return type.get(); 206 } 207 public String getSampleType(){ 208 if(protocolType==ThriftProtocolType.TYPE_STRUCT || protocolType==ThriftProtocolType.TYPE_ENUM){ 209 return CxxHelper.simpleName(type.get()); 210 } 211 return type.get(); 212 } 213 public String getFullType(){ 214 if(type instanceof NameSupplier){ 215 return ((NameSupplier)type).cxxType; 216 }else{ 217 return type.get(); 218 } 219 } 220 public String getNamespace(){ 221 if(type instanceof NameSupplier){ 222 return CxxHelper.getCxxNamespace(((NameSupplier)type).cxxType); 223 }else{ 224 return CxxHelper.getCxxNamespace(type.get()); 225 } 226 } 227 public CxxTypeMeta getKeyType() { 228 return keyType; 229 } 230 public CxxTypeMeta getValueType() { 231 return valueType; 232 } 233 234 public ThriftProtocolType getProtocolType() { 235 return protocolType; 236 } 237 public boolean isBool(){ 238 return ThriftProtocolType.TYPE_BOOL.equals(getProtocolType()); 239 } 240 public boolean isVoid(){ 241 return ThriftProtocolType.TYPE_VOID.equals(getProtocolType()); 242 } 243 public boolean isString(){ 244 return ThriftProtocolType.TYPE_STRING.equals(getProtocolType()); 245 } 246 public boolean isBinary(){ 247 return ThriftProtocolType.TYPE_BINARY.equals(getProtocolType()); 248 } 249 public boolean isMap() { 250 return ThriftProtocolType.TYPE_MAP.equals(getProtocolType()); 251 } 252 public boolean isSet() { 253 return ThriftProtocolType.TYPE_SET.equals(getProtocolType()); 254 } 255 public boolean isList() { 256 return ThriftProtocolType.TYPE_LIST.equals(getProtocolType()); 257 } 258 public boolean isEnum() { 259 return ThriftProtocolType.TYPE_ENUM.equals(getProtocolType()); 260 } 261 public boolean isStruct() { 262 return ThriftProtocolType.TYPE_STRUCT.equals(getProtocolType()); 263 } 264 public boolean isContainer(){ 265 return this.getProtocolType().isContainer; 266 } 267 public boolean isBaseType(){ 268 return this.getProtocolType().isBaseType; 269 } 270 271 public boolean isNumber(){ 272 return getProtocolType().isNumber; 273 } 274 public boolean isArray() { 275 return isArray; 276 } 277 278 public boolean isByValue(){ 279 return isBool() || isNumber() || isEnum(); 280 } 281 public boolean isByReference(){ 282 return !isByValue() && !isVoid(); 283 } 284 public boolean isCanMove(){ 285 return isBinary() || isString() || isContainer() || isStruct(); 286 } 287 /** 288 * 类名转换,不含namespace 289 * @param name 290 * @return 291 */ 292 public CxxTypeMeta castName(String name){ 293 checkArgument(null !=name, "ns is null"); 294 checkArgument(isEnum() || isStruct(),"only ENUM or STRUCT can be cast namespace"); 295 return new CxxTypeMeta(protocolType,getNamespace() + "::" + name); 296 } 297 /** 298 * 类型转换 299 * @param cxxType 300 * @return 301 */ 302 public CxxTypeMeta cast(String cxxType){ 303 checkArgument(null !=cxxType, "cxxType is null"); 304 return new CxxTypeMeta(protocolType,cxxType); 305 } 306 /** 307 * 类型转换 308 * @param keyType 309 * @param valueType 310 * @param isArray 311 * @return 312 */ 313 public CxxTypeMeta cast(CxxTypeMeta keyType, CxxTypeMeta valueType, boolean isArray){ 314 return new CxxTypeMeta(protocolType,keyType,valueType,isArray); 315 } 316@Override 317 public String toString() { 318 StringBuilder builder = new StringBuilder(); 319 builder.append("CxxTypeMeta [protocolType="); 320 builder.append(protocolType); 321 builder.append(", type="); 322 builder.append(type.get()); 323 builder.append(", isArray="); 324 builder.append(isArray); 325 builder.append("]"); 326 return builder.toString(); 327 } 328 @Override 329 public int hashCode() { 330 final int prime = 31; 331 int result = 1; 332 result = prime * result + ((protocolType == null) ? 0 : protocolType.hashCode()); 333 result = prime * result + ((type == null) ? 0 : type.get().hashCode()); 334 return result; 335 } 336 @Override 337 public boolean equals(Object obj) { 338 if (this == obj) 339 return true; 340 if (obj == null) 341 return false; 342 if (getClass() != obj.getClass()) 343 return false; 344 CxxTypeMeta other = (CxxTypeMeta) obj; 345 if (protocolType != other.protocolType) 346 return false; 347 if (type == null) { 348 if (other.type != null) 349 return false; 350 } else if (!type.get().equals(other.type.get())) 351 return false; 352 return true; 353 } 354 355}