Example #1
0
        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}");
                    }
                }
            }
        }
Example #2
0
        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;
        }
Example #3
0
        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;
        }
Example #4
0
        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;
        }
Example #5
0
        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;
        }
Example #6
0
        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;
        }
Example #7
0
 public static ThriftType Struct(ThriftStructMetadata structMetadata)
 {
     return(new ThriftType(structMetadata));
 }
Example #8
0
        // 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}");
        }