private ThriftStructMetadata ExtractThriftStructMetadata(Type structType) { Guard.ArgumentNotNull(structType, nameof(structType)); var stack = this._stack.Value; if (stack.Contains(structType)) { string path = String.Join("->", stack.Union(new Type[] { structType }) .Select(t => t.Name)); throw new ThriftyException( $"Circular references must be qualified with '{nameof(ThriftFieldAttribute.Recursive)}' on a ThriftFieldAttribute in the cycle: {path}."); } else { stack.Push(structType); try { ThriftStructMetadataBuilder builder = new ThriftStructMetadataBuilder(this, structType); ThriftStructMetadata structMetadata = builder.Build(); return(structMetadata); } finally { Type top = stack.Pop(); if (!structType.Equals(top)) { throw new ThriftyException($"ThriftCatalog circularity detection stack is corrupt: expected {structType.FullName}, but got {top.FullName}"); } } } }
private ThriftType(ThriftType underlyingType, Type nullableType) { this.CSharpType = nullableType; this.UncoercedType = underlyingType; this.ProtocolType = underlyingType.ProtocolType; keyTypeReference = null; valueTypeReference = null; structMetadata = null; enumMetadata = underlyingType.enumMetadata; }
private ThriftType(ThriftStructMetadata structMetadata) { Guard.ArgumentNotNull(structMetadata, nameof(structMetadata)); this.ProtocolType = ThriftProtocolType.Struct; this.CSharpType = structMetadata.StructType; keyTypeReference = null; valueTypeReference = null; this.structMetadata = structMetadata; this.UncoercedType = null; }
private ThriftType(ThriftProtocolType protocolType, Type csharpType) { Guard.ArgumentNotNull(csharpType, "csharpType"); this.ProtocolType = protocolType; this.CSharpType = csharpType; keyTypeReference = null; valueTypeReference = null; structMetadata = null; this.UncoercedType = null; }
private ThriftType(ThriftEnumMetadata enumMetadata) { Guard.ArgumentNotNull(enumMetadata, "enumMetadata"); this.ProtocolType = ThriftProtocolType.Enum; this.CSharpType = enumMetadata.EnumType; keyTypeReference = null; valueTypeReference = null; structMetadata = null; this.enumMetadata = enumMetadata; this.UncoercedType = null; }
private ThriftType(ThriftProtocolType protocolType, Type javaType, IThriftTypeReference keyTypeReference, IThriftTypeReference valueTypeReference) { Guard.ArgumentNotNull(javaType, nameof(javaType)); Guard.ArgumentNotNull(valueTypeReference, nameof(valueTypeReference)); this.ProtocolType = protocolType; this.CSharpType = javaType; this.keyTypeReference = keyTypeReference; this.valueTypeReference = valueTypeReference; this.structMetadata = null; this.UncoercedType = null; }
public static ThriftType Struct(ThriftStructMetadata structMetadata) { return(new ThriftType(structMetadata)); }
// This should ONLY be called from buildThriftType() private ThriftType BuildThriftTypeInternal(Type csharpType) { ThriftType manualType = null; Type rawType = csharpType; if (_manualTypes.TryGetValue(csharpType, out manualType)) { return(manualType); } if (typeof(bool).Equals(rawType)) { return(ThriftType.Bool); } if (typeof(byte).Equals(rawType)) { return(ThriftType.Byte); } if (typeof(short).Equals(rawType)) { return(ThriftType.I16); } if (typeof(int).Equals(rawType)) { return(ThriftType.I32); } if (typeof(long).Equals(rawType)) { return(ThriftType.I64); } if (typeof(double).Equals(rawType)) { return(ThriftType.Double); } if (typeof(float).Equals(rawType)) { return(ThriftType.Float); } if (typeof(String).Equals(rawType)) { return(ThriftType.String); } if (typeof(Guid).Equals(rawType)) { return(ThriftType.Guid); } if (typeof(DateTime).Equals(rawType)) { return(ThriftType.DateTime); } if (typeof(Decimal).Equals(rawType)) { return(ThriftType.Decimal); } if (typeof(byte[]).Equals(rawType)) { // byte[] is encoded as BINARY and requires a coersion return(ThriftType.Binary); } if (rawType.GetTypeInfo().IsEnum) { return(ThriftType.Enum(new ThriftEnumMetadata(rawType))); } var dicType = rawType.GetInterfaces().Concat(new Type[] { rawType }).FirstOrDefault(t => t.GetTypeInfo().IsGenericType&& t.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(IDictionary <,>))); if (dicType != null) { var argTypes = dicType.GetTypeInfo().GetGenericArguments(); Type mapKeyType = argTypes[0]; Type mapValueType = argTypes[1]; return(ThriftType.Dictionary( GetMapKeyThriftTypeReference(mapKeyType), GetMapValueThriftTypeReference(mapValueType))); } if (rawType.IsArray) { var elementType = rawType.GetTypeInfo().GetElementType(); return(ThriftType.Array(GetCollectionElementThriftTypeReference(elementType))); } var setType = rawType.GetInterfaces().Concat(new Type[] { rawType }).FirstOrDefault(t => t.GetTypeInfo().IsGenericType&& t.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(ISet <>))); if (setType != null) { Type elementType = setType.GetTypeInfo().GetGenericArguments().First(); return(ThriftType.Set(GetCollectionElementThriftTypeReference(elementType))); } var listType = rawType.GetInterfaces().Concat(new Type[] { rawType }).FirstOrDefault(t => t.GetTypeInfo().IsGenericType&& t.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(IList <>))); if (listType != null) { Type elementType = listType.GetTypeInfo().GetGenericArguments().First(); return(ThriftType.List(GetCollectionElementThriftTypeReference(elementType))); } var arrayType = rawType.GetInterfaces().Concat(new Type[] { rawType }).FirstOrDefault(t => t.GetTypeInfo().IsGenericType&& t.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(IEnumerable <>))); if (arrayType != null) { Type elementType = arrayType.GetTypeInfo().GetGenericArguments().First(); return(ThriftType.Array(GetCollectionElementThriftTypeReference(elementType))); } // The void type is used by service methods and is encoded as an empty struct if (typeof(void).IsAssignableFrom(rawType) || typeof(Task).Equals(rawType)) { return(ThriftType.Void); } if (IsStructType(rawType)) { ThriftStructMetadata structMetadata = GetThriftStructMetadata(csharpType); // Unions are covered because a union looks like a struct with a single field. return(ThriftType.Struct(structMetadata)); } if (rawType.GetTypeInfo().IsGenericType&& rawType.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(Task <>))) { Type returnType = rawType.GetTypeInfo().GetGenericArguments().First(); // TODO: check that we aren't recursing through multiple futures // TODO: find a way to restrict this to return values only return(GetThriftType(returnType)); } // coerce the type if possible TypeCoercion coercion = null; if (_coercions.TryGetValue(csharpType, out coercion)) { return(coercion.ThriftType); } if (IsNullableEnum(rawType)) { coercion = _coercions.GetOrAdd(rawType, t => { ThriftEnumMetadata m = new ThriftEnumMetadata(t.GetTypeInfo().GetGenericArguments().First()); var tt = ThriftType.Enum(m, true); return(new TypeCoercion(tt)); }); return(coercion.ThriftType); } throw new ThriftyException($"Type can not be coerced to a Thrift type: {csharpType.FullName}"); }