public override InvocationExpressionSyntax Create()
        {
            //Default to ASCII if no encoding specified
            EncodingType encodingType = EncodingType.ASCII;

            //Overriding default behavior.
            bool hasSaneDefaults = Member.ContainingType.HasAttributeExact <WireSaneDefaultsAttribute>(true);

            if (Member.HasAttributeExact <EncodingAttribute>())
            {
                encodingType = EncodingAttribute.Parse(Member.GetAttributeExact <EncodingAttribute>().ConstructorArguments.First().ToCSharpString());
            }

            if (Member.HasAttributeExact <KnownSizeAttribute>() && Member.HasAttributeExact <SendSizeAttribute>() && !hasSaneDefaults)
            {
                throw new InvalidOperationException($"Emit failed for Member: {ActualType} in Type: {Member.ContainingType.Name}. Cannot use Attributes: {nameof(SendSizeAttribute)} and {nameof(KnownSizeAttribute)} together.");
            }

            if (IsSendSizeString() && !Member.HasAttributeExact <DontTerminateAttribute>())
            {
                PrimitiveSizeType sendSize = SendSizeAttribute.Parse(Member.GetAttributeExact <SendSizeAttribute>().ConstructorArguments.First().ToCSharpString());
                var generator = new RawLengthPrefixedStringTypeSerializationGenerator(ActualType, Member, Mode, encodingType, sendSize);
                return(generator.Create());
            }
            else if (IsSendSizeString() || (hasSaneDefaults && !IsKnownSizeString()))             //SANE DEFAULT
            {
                //Dont Terminate attribute FOUND!
                PrimitiveSizeType sendSize = PrimitiveSizeType.Int32;                 //SANE DEFAULT size 65,000

                if (Member.HasAttributeExact <SendSizeAttribute>())
                {
                    sendSize = SendSizeAttribute.Parse(Member.GetAttributeExact <SendSizeAttribute>().ConstructorArguments.First().ToCSharpString());
                }

                var generator = new RawDontTerminateLengthPrefixedStringTypeSerializationGenerator(ActualType, Member, Mode, encodingType, sendSize);
                return(generator.Create());
            }
            else if (IsKnownSizeString())
            {
                int size = KnownSizeAttribute.Parse(Member.GetAttributeExact <KnownSizeAttribute>().ConstructorArguments.First().ToCSharpString());

                var generator = new RawKnownSizeStringTypeSerializerGenerator(ActualType, Member, Mode, encodingType, size, !Member.HasAttributeExact <DontTerminateAttribute>());
                return(generator.Create());
            }
            else
            {
                //If it's not knownsize or sendsize then let's emit the default!
                var generator = new RawDefaultStringTypeSerializerGenerator(ActualType, Member, Mode, encodingType, !Member.HasAttributeExact <DontTerminateAttribute>());
                return(generator.Create());
            }
        }
Example #2
0
        /// <inheritdoc />
        public ContextualSerializerLookupKey Create([NotNull] ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            //We must inspect the metadata to build the key
            if (!context.HasContextualMemberMetadata())
            {
                GetKeyFromStorage(ContextTypeFlags.None, context.TargetType);
            }

            //Build the relevant flags
            ContextTypeFlags flags = ContextTypeFlags.None;

            if (context.HasMemberAttribute <ReadToEndAttribute>())
            {
                flags |= ContextTypeFlags.ReadToEnd;
            }

            if (context.HasMemberAttribute <ReverseDataAttribute>())
            {
                flags |= ContextTypeFlags.Reverse;
            }

            if (context.HasMemberAttribute <EnumStringAttribute>())
            {
                flags |= ContextTypeFlags.EnumString;
            }

            //Check for no terminate too
            if (context.HasMemberAttribute <DontTerminateAttribute>())
            {
                flags |= ContextTypeFlags.DontTerminate;
            }

            if (context.HasMemberAttribute <CompressAttribute>())
            {
                flags |= ContextTypeFlags.Compressed;
            }

            //Encoding requires multiple flags to be set.
            //We can't rely on the context key since it may be used for size
            if (context.HasMemberAttribute <EncodingAttribute>())
            {
                flags |= ContextTypeFlags.Encoding;
                EncodingAttribute attri = context.GetMemberAttribute <EncodingAttribute>();
                switch (attri.DesiredEncodingType)
                {
                case EncodingType.ASCII:
                    flags |= ContextTypeFlags.ASCII;
                    break;

                case EncodingType.UTF16:
                    flags |= ContextTypeFlags.UTF16;
                    break;

                case EncodingType.UTF32:
                    flags |= ContextTypeFlags.UTF32;
                    break;

                case EncodingType.UTF8:
                    flags |= ContextTypeFlags.UTF8;
                    break;
                }
            }

            if (context.HasMemberAttribute <SendSizeAttribute>())
            {
                return(new ContextualSerializerLookupKey(flags | ContextTypeFlags.SendSize, new SendSizeContextKey(context.GetMemberAttribute <SendSizeAttribute>().TypeOfSize, context.GetMemberAttribute <SendSizeAttribute>().AddedSize), context.TargetType));
            }

            if (context.HasMemberAttribute <KnownSizeAttribute>())
            {
                return(new ContextualSerializerLookupKey(flags | ContextTypeFlags.FixedSize, new SizeContextKey(context.GetMemberAttribute <KnownSizeAttribute>().KnownSize), context.TargetType));
            }

            //If we're here then we have flags that weren't mutually exclusive
            return(GetKeyFromStorage(flags, context.TargetType));
        }