229 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C#
		
	
	
		
		
			
		
	
	
			229 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C#
		
	
	
| 
								 | 
							
								using System;
							 | 
						|||
| 
								 | 
							
								using System.Reflection;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								namespace ProtoBuf
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								    /// <summary>
							 | 
						|||
| 
								 | 
							
								    /// Declares a member to be used in protocol-buffer serialization, using
							 | 
						|||
| 
								 | 
							
								    /// the given Tag. A DataFormat may be used to optimise the serialization
							 | 
						|||
| 
								 | 
							
								    /// format (for instance, using zigzag encoding for negative numbers, or 
							 | 
						|||
| 
								 | 
							
								    /// fixed-length encoding for large values.
							 | 
						|||
| 
								 | 
							
								    /// </summary>
							 | 
						|||
| 
								 | 
							
								    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field,
							 | 
						|||
| 
								 | 
							
								        AllowMultiple = false, Inherited = true)]
							 | 
						|||
| 
								 | 
							
								    public class ProtoMemberAttribute : Attribute
							 | 
						|||
| 
								 | 
							
								        , IComparable
							 | 
						|||
| 
								 | 
							
								        , IComparable<ProtoMemberAttribute>
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Compare with another ProtoMemberAttribute for sorting purposes
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public int CompareTo(object other) => CompareTo(other as ProtoMemberAttribute);
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Compare with another ProtoMemberAttribute for sorting purposes
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public int CompareTo(ProtoMemberAttribute other)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (other == null) return -1;
							 | 
						|||
| 
								 | 
							
								            if ((object)this == (object)other) return 0;
							 | 
						|||
| 
								 | 
							
								            int result = this.tag.CompareTo(other.tag);
							 | 
						|||
| 
								 | 
							
								            if (result == 0) result = string.CompareOrdinal(this.name, other.name);
							 | 
						|||
| 
								 | 
							
								            return result;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Creates a new ProtoMemberAttribute instance.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        /// <param name="tag">Specifies the unique tag used to identify this member within the type.</param>
							 | 
						|||
| 
								 | 
							
								        public ProtoMemberAttribute(int tag) : this(tag, false)
							 | 
						|||
| 
								 | 
							
								        { }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        internal ProtoMemberAttribute(int tag, bool forced)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (tag <= 0 && !forced) throw new ArgumentOutOfRangeException(nameof(tag));
							 | 
						|||
| 
								 | 
							
								            this.tag = tag;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#if !NO_RUNTIME
							 | 
						|||
| 
								 | 
							
								        internal MemberInfo Member, BackingMember;
							 | 
						|||
| 
								 | 
							
								        internal bool TagIsPinned;
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Gets or sets the original name defined in the .proto; not used
							 | 
						|||
| 
								 | 
							
								        /// during serialization.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public string Name { get { return name; } set { name = value; } }
							 | 
						|||
| 
								 | 
							
								        private string name;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Gets or sets the data-format to be used when encoding this value.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public DataFormat DataFormat { get { return dataFormat; } set { dataFormat = value; } }
							 | 
						|||
| 
								 | 
							
								        private DataFormat dataFormat;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Gets the unique tag used to identify this member within the type.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public int Tag { get { return tag; } }
							 | 
						|||
| 
								 | 
							
								        private int tag;
							 | 
						|||
| 
								 | 
							
								        internal void Rebase(int tag) { this.tag = tag; }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Gets or sets a value indicating whether this member is mandatory.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public bool IsRequired
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            get { return (options & MemberSerializationOptions.Required) == MemberSerializationOptions.Required; }
							 | 
						|||
| 
								 | 
							
								            set
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (value) options |= MemberSerializationOptions.Required;
							 | 
						|||
| 
								 | 
							
								                else options &= ~MemberSerializationOptions.Required;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Gets a value indicating whether this member is packed.
							 | 
						|||
| 
								 | 
							
								        /// This option only applies to list/array data of primitive types (int, double, etc).
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public bool IsPacked
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            get { return (options & MemberSerializationOptions.Packed) == MemberSerializationOptions.Packed; }
							 | 
						|||
| 
								 | 
							
								            set
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (value) options |= MemberSerializationOptions.Packed;
							 | 
						|||
| 
								 | 
							
								                else options &= ~MemberSerializationOptions.Packed;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Indicates whether this field should *repace* existing values (the default is false, meaning *append*).
							 | 
						|||
| 
								 | 
							
								        /// This option only applies to list/array data.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public bool OverwriteList
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            get { return (options & MemberSerializationOptions.OverwriteList) == MemberSerializationOptions.OverwriteList; }
							 | 
						|||
| 
								 | 
							
								            set
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (value) options |= MemberSerializationOptions.OverwriteList;
							 | 
						|||
| 
								 | 
							
								                else options &= ~MemberSerializationOptions.OverwriteList;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Enables full object-tracking/full-graph support.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public bool AsReference
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            get { return (options & MemberSerializationOptions.AsReference) == MemberSerializationOptions.AsReference; }
							 | 
						|||
| 
								 | 
							
								            set
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (value) options |= MemberSerializationOptions.AsReference;
							 | 
						|||
| 
								 | 
							
								                else options &= ~MemberSerializationOptions.AsReference;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                options |= MemberSerializationOptions.AsReferenceHasValue;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        internal bool AsReferenceHasValue
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            get { return (options & MemberSerializationOptions.AsReferenceHasValue) == MemberSerializationOptions.AsReferenceHasValue; }
							 | 
						|||
| 
								 | 
							
								            set
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (value) options |= MemberSerializationOptions.AsReferenceHasValue;
							 | 
						|||
| 
								 | 
							
								                else options &= ~MemberSerializationOptions.AsReferenceHasValue;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Embeds the type information into the stream, allowing usage with types not known in advance.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public bool DynamicType
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            get { return (options & MemberSerializationOptions.DynamicType) == MemberSerializationOptions.DynamicType; }
							 | 
						|||
| 
								 | 
							
								            set
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (value) options |= MemberSerializationOptions.DynamicType;
							 | 
						|||
| 
								 | 
							
								                else options &= ~MemberSerializationOptions.DynamicType;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Gets or sets a value indicating whether this member is packed (lists/arrays).
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public MemberSerializationOptions Options { get { return options; } set { options = value; } }
							 | 
						|||
| 
								 | 
							
								        private MemberSerializationOptions options;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    /// <summary>
							 | 
						|||
| 
								 | 
							
								    /// Additional (optional) settings that control serialization of members
							 | 
						|||
| 
								 | 
							
								    /// </summary>
							 | 
						|||
| 
								 | 
							
								    [Flags]
							 | 
						|||
| 
								 | 
							
								    public enum MemberSerializationOptions
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Default; no additional options
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        None = 0,
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Indicates that repeated elements should use packed (length-prefixed) encoding
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        Packed = 1,
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Indicates that the given item is required
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        Required = 2,
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Enables full object-tracking/full-graph support
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        AsReference = 4,
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Embeds the type information into the stream, allowing usage with types not known in advance
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        DynamicType = 8,
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Indicates whether this field should *repace* existing values (the default is false, meaning *append*).
							 | 
						|||
| 
								 | 
							
								        /// This option only applies to list/array data.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        OverwriteList = 16,
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Determines whether the types AsReferenceDefault value is used, or whether this member's AsReference should be used
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        AsReferenceHasValue = 32
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    /// <summary>
							 | 
						|||
| 
								 | 
							
								    /// Declares a member to be used in protocol-buffer serialization, using
							 | 
						|||
| 
								 | 
							
								    /// the given Tag and MemberName. This allows ProtoMemberAttribute usage
							 | 
						|||
| 
								 | 
							
								    /// even for partial classes where the individual members are not
							 | 
						|||
| 
								 | 
							
								    /// under direct control.
							 | 
						|||
| 
								 | 
							
								    /// A DataFormat may be used to optimise the serialization
							 | 
						|||
| 
								 | 
							
								    /// format (for instance, using zigzag encoding for negative numbers, or 
							 | 
						|||
| 
								 | 
							
								    /// fixed-length encoding for large values.
							 | 
						|||
| 
								 | 
							
								    /// </summary>
							 | 
						|||
| 
								 | 
							
								    [AttributeUsage(AttributeTargets.Class,
							 | 
						|||
| 
								 | 
							
								            AllowMultiple = true, Inherited = false)]
							 | 
						|||
| 
								 | 
							
								    public sealed class ProtoPartialMemberAttribute : ProtoMemberAttribute
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Creates a new ProtoMemberAttribute instance.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        /// <param name="tag">Specifies the unique tag used to identify this member within the type.</param>
							 | 
						|||
| 
								 | 
							
								        /// <param name="memberName">Specifies the member to be serialized.</param>
							 | 
						|||
| 
								 | 
							
								        public ProtoPartialMemberAttribute(int tag, string memberName)
							 | 
						|||
| 
								 | 
							
								            : base(tag)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								#if !NO_RUNTIME
							 | 
						|||
| 
								 | 
							
								            if (string.IsNullOrEmpty(memberName)) throw new ArgumentNullException(nameof(memberName));
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								            this.MemberName = memberName;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// The name of the member to be serialized.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public string MemberName { get; private set; }
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 |