public void SetSettings(MemberLevelSettingsValue value, int level) { var s = GetSettingsCopy(level); s.Basic = value; SetSettings(s, level); }
public void SetLegacyFormat(ref MemberLevelSettingsValue level, MemberInfo member, RuntimeTypeModel model) { Type type = Helpers.GetMemberType(member); ValueFormat legacyFormat = ValueSerializerBuilder.GetDefaultLegacyFormat(type, model); switch (Helpers.GetTypeCode(type)) { // these can't be registered and don't have AsReferenceDefault // explicitely set their asReference = false case ProtoTypeCode.String: case ProtoTypeCode.ByteArray: case ProtoTypeCode.Type: case ProtoTypeCode.Uri: level.Format = legacyFormat; break; default: if (!RuntimeTypeModel.CheckTypeCanBeAdded(model, type)) { // for primitive types - explicitly level.Format = legacyFormat; } break; } }
static RuntimeTypeModel CreateDefaultRefModel(bool aFirst, bool comp) { ProtoCompatibilitySettingsValue fullComp = ProtoCompatibilitySettingsValue.FullCompatibility; fullComp.SuppressValueEnhancedFormat = false; var model = TypeModel.Create(false, comp ? fullComp : ProtoCompatibilitySettingsValue.Incompatible); if (comp) { model.SkipForcedLateReference = true; } // otherwise will not be compatible model.SkipForcedAdvancedVersioning = true; if (aFirst) { model.Add(typeof(A_WithDefaultRef), true); model.Add(typeof(B_WithDefaultRef), true); } else { model.Add(typeof(B_WithDefaultRef), true); model.Add(typeof(A_WithDefaultRef), true); } ValueMember f = model[typeof(B_WithDefaultRef)][2]; MemberLevelSettingsValue s = f.GetSettingsCopy(0); Assert.That(s.Format, Is.EqualTo(ValueFormat.NotSpecified)); s.Format = ValueFormat.Compact; f.SetSettings(s); model.AutoCompile = false; return(model); }
static void ResetCollectionSettings(ref MemberLevelSettingsValue level0) { level0.Collection.ItemType = null; level0.Collection.PackedWireTypeForRead = null; level0.Collection.Format = CollectionFormat.NotSpecified; level0.Collection.ConcreteType = null; level0.Collection.ArrayLengthReadLimit = null; }
/// <summary> /// These settings are only applicable for collection types when they are serialized not as a member (root or LateReference) /// </summary> public void SetNestedSettingsWhenRoot(MemberLevelSettingsValue value, int level) { if (level == 0) { throw new ArgumentOutOfRangeException(nameof(level), "Zero level settings should be specified through DefaultX properties on MetaType"); } ThrowIfFrozen(); Helpers.MemoryBarrier(); _rootNestedVs.SetSettings(value, level); }
internal MetaType(RuntimeTypeModel model, Type type, MethodInfo factory) { this._factory = factory; if (model == null) { throw new ArgumentNullException(nameof(model)); } if (type == null) { throw new ArgumentNullException(nameof(type)); } this._model = model; IProtoSerializer coreSerializer = model.TryGetBasicTypeSerializer(type); if (coreSerializer != null) { throw InbuiltType(type); } this.Type = type; #if WINRT this._typeInfo = type.GetTypeInfo(); #endif MemberInfo[] members; _tupleCtor = ResolveTupleConstructor(Type, out members); if (_tupleCtor != null) { foreach (MemberInfo memberInfo in members) { var level = new MemberLevelSettingsValue(); var vs = new ValueSerializationSettings(); vs.SetSettings(new ValueSerializationSettings.LevelValue(level) { IsNotAssignable = true }, 0); vs.DefaultLevel = new ValueSerializationSettings.LevelValue(level.MakeDefaultNestedLevel()); var main = new MemberMainSettingsValue() { Name = memberInfo.Name }; var vm = new ValueMember(main, vs, memberInfo, Type, model, canHaveDefaultValue: false, isAccessHandledOutside: true); AddTupleField(vm); } } }
public void SetSettings(MemberLevelSettingsValue value, int level = 0) { ThrowIfFrozen(); Helpers.MemoryBarrier(); _vsByClient.SetSettings(value, level); }
ValueSerializationSettings.LevelValue CompleteLevel(ValueSerializationSettings vs, int levelNr, out object defaultValue) { var lv = vs.GetSettingsCopy(levelNr); var level = lv.Basic; // do not use lv.Basic, it's overwritten at the end of this method var originalLevel = level; if (levelNr == 0) { //#if WINRT if (vs.DefaultValue != null && _model.MapType(vs.DefaultValue.GetType()) != level.EffectiveType) //#else // if (defaultValue != null && !memberType.IsInstanceOfType(defaultValue)) //#endif { vs.DefaultValue = ParseDefaultValue(level.EffectiveType, vs.DefaultValue); } defaultValue = vs.DefaultValue; } else { defaultValue = null; } int idx = _model.FindOrAddAuto(level.EffectiveType, false, true, false); MetaType effectiveMetaType = null; if (idx >= 0) { effectiveMetaType = _model[idx]; var typeSettings = effectiveMetaType.GetFinalSettingsCopy(); level = MemberLevelSettingsValue.Merge(typeSettings.Member, level); } MemberDefaultsMode defaultsMode = level.DefaultsMode.GetValueOrDefault(); if (level.Format == ValueFormat.NotSpecified && defaultsMode == MemberDefaultsMode.Legacy) { level.Format = GetDefaultLegacyFormat(level.EffectiveType, _model); } if (level.Format == ValueFormat.LateReference) { if (vs.MaxSpecifiedNestedLevel > levelNr) { throw new ProtoException("LateReference member levels can't have nested levels"); } var defaultSettings = effectiveMetaType?.GetFinalSettingsCopy().Member ?? new MemberLevelSettingsValue().GetInitializedToValueOrDefault(); if (level.ContentBinaryFormatHint.GetValueOrDefault() != defaultSettings.ContentBinaryFormatHint.GetValueOrDefault() || level.WriteAsDynamicType.GetValueOrDefault() != defaultSettings.WriteAsDynamicType.GetValueOrDefault() || level.Collection.Append.GetValueOrDefault() != defaultSettings.Collection.Append.GetValueOrDefault() || level.Collection.PackedWireTypeForRead != defaultSettings.Collection.PackedWireTypeForRead) { throw new ProtoException("LateReference member levels can't override default member settings specified on MetaType"); } } Type newCollectionConcreteType = null; Type newItemType = null; if (!effectiveMetaType?.GetFinalSettingsCopy().IgnoreListHandling ?? true) { MetaType.ResolveListTypes(_model, level.EffectiveType, ref newItemType, ref newCollectionConcreteType); } // tuples depend on collection if (defaultsMode == MemberDefaultsMode.LegacyTuple && level.Format == ValueFormat.NotSpecified && newItemType != null) { level.Format = ValueFormat.Compact; } EnsureCorrectFormatSpecified(_model, ref level.Format, level.EffectiveType, ref level.WriteAsDynamicType, true); #region Collections { if (effectiveMetaType?.GetFinalSettingsCopy().IgnoreListHandling ?? false) { ResetCollectionSettings(ref level); } else { // defaults for ItemType and others were already merged from type settings if (level.Collection.ItemType != null) { if (level.Format == ValueFormat.LateReference) { Type defaultItemType = (effectiveMetaType?.GetFinalSettingsCopy().Member.Collection.ItemType ?? newItemType); if (level.Collection.ItemType != defaultItemType) { throw new ProtoException("LateReference member settings level should have default collection item type (" + defaultItemType + ")"); } } } else { level.Collection.ItemType = newItemType; } if (level.Collection.ItemType == null) { ResetCollectionSettings(ref level); } else { // should not override with default because: what if specified something like List<string> for IList? if (level.Collection.ConcreteType != null) { if (!Helpers.IsAssignableFrom(level.EffectiveType, level.Collection.ConcreteType)) { throw new ProtoException( "Specified CollectionConcreteType " + level.Collection.ConcreteType.Name + " is not assignable to " + level.EffectiveType); } if (level.Format == ValueFormat.LateReference) { Type defaultConcreteType = (effectiveMetaType?.GetFinalSettingsCopy().Member.Collection.ConcreteType ?? newCollectionConcreteType); if (level.Collection.ConcreteType != defaultConcreteType) { throw new ProtoException("LateReference member settings level should have default collection concrete type (" + defaultConcreteType + ")"); } } } else { level.Collection.ConcreteType = newCollectionConcreteType; } if (!level.Collection.Append.GetValueOrDefault() && lv.IsNotAssignable) { if (level.Collection.Append == null) { level.Collection.Append = true; } else { throw new ProtoException("The property is not writable but AppendCollection was set to false"); } } if (!CanPack(level.Collection.ItemType, level.ContentBinaryFormatHint)) { if (level.Collection.PackedWireTypeForRead != null && level.Collection.PackedWireTypeForRead != WireType.None) { throw new ProtoException("PackedWireTypeForRead " + level.Collection.PackedWireTypeForRead + " specified but type can't be packed"); } level.Collection.PackedWireTypeForRead = WireType.None; } if (level.Collection.Format == CollectionFormat.NotSpecified) { level.Collection.Format = !_model.ProtoCompatibility.SuppressCollectionEnhancedFormat ? CollectionFormat.Enhanced : CollectionFormat.Protobuf; } else if (level.Collection.Format == CollectionFormat.Enhanced && _model.ProtoCompatibility.SuppressCollectionEnhancedFormat) { level.Collection.Format = CollectionFormat.Protobuf; } } } if (!level.EffectiveType.IsArray) { if (level.Collection.ArrayLengthReadLimit != null) { throw new ProtoException("ArrayLengthReadLimit specified for non-array"); } } else if (level.Collection.ArrayLengthReadLimit == null) { level.Collection.ArrayLengthReadLimit = TypeModel.DefaultArrayLengthReadLimit; } else if (level.Collection.ArrayLengthReadLimit <= 0) { throw new ProtoException("ArrayLengthReadLimit should be greater than zero or not specified"); } } #endregion lv.Basic = level.GetInitializedToValueOrDefault(); vs.SetSettings(lv, levelNr); originalLevel.GetHashCode(); return(lv); }
static void ThrowIfHasMoreLevels(ValueSerializationSettings settings, int currentLevelNr, MemberLevelSettingsValue currentLevel, string description) { if (settings.MaxSpecifiedNestedLevel > currentLevelNr) { throw new ProtoException( "Found unused specified nested level settings, maximum possible nested level is " + currentLevelNr + "-" + currentLevel.EffectiveType.Name + description); } }
public bool CanBePackedCollection(MemberLevelSettingsValue level) { return(level.Collection.IsCollection && CanPack(level.Collection.ItemType, level.ContentBinaryFormatHint) && level.Collection.Format == CollectionFormat.Protobuf); }
public MemberHandlerResult TryRead(AttributeMap attribute, MemberState s, MemberInfo member, RuntimeTypeModel model) { if (s.Input.IsEnumValueMember) { return(MemberHandlerResult.NotFound); } var main = s.MainValue; try { MemberLevelSettingsValue level = s.SerializationSettings.GetSettingsCopy(0).Basic; level.DefaultsMode = MemberDefaultsMode.Legacy; if (main.Tag <= 0) { attribute.TryGetNotDefault("Tag", ref main.Tag); } if (string.IsNullOrEmpty(main.Name)) { attribute.TryGetNotEmpty("Name", ref main.Name); } if (!main.IsRequiredInSchema) { attribute.TryGetNotDefault("IsRequired", ref main.IsRequiredInSchema); } var type = Helpers.GetMemberType(member); BinaryDataFormat dataFormat = 0; attribute.TryGetNotDefault("DataFormat", ref dataFormat); level.ContentBinaryFormatHint = dataFormat; bool isPacked = false; attribute.TryGetNotDefault("IsPacked", ref isPacked); level.Collection.Format = isPacked ? CollectionFormat.Protobuf : (model.ProtoCompatibility.SuppressCollectionEnhancedFormat ? CollectionFormat.ProtobufNotPacked : CollectionFormat.NotSpecified ); bool overwriteList = false; attribute.TryGetNotDefault("OverwriteList", ref overwriteList); level.Collection.Append = !overwriteList; if (!level.WriteAsDynamicType.GetValueOrDefault()) { attribute.TryGetNotDefault("DynamicType", ref level.WriteAsDynamicType); } bool dynamicType = level.WriteAsDynamicType.GetValueOrDefault(); bool asRefHasValue = false; bool notAsReference = false; #if !FEAT_IKVM // IKVM can't access AsReferenceHasValue, but conveniently, AsReference will only be returned if set via ctor or property attribute.TryGetNotDefault("AsReferenceHasValue", ref asRefHasValue, publicOnly: false); if (asRefHasValue) #endif { bool value = false; asRefHasValue = attribute.TryGetNotDefault("AsReference", ref value); if (asRefHasValue) // if AsReference = true - use defaults { notAsReference = !value; } } if (!asRefHasValue) { if (level.Format == ValueFormat.NotSpecified) { SetLegacyFormat(ref level, member, model); } } else { level.Format = notAsReference ? ValueSerializerBuilder.GetDefaultLegacyFormat(type, model) : ValueFormat.Reference; } s.TagIsPinned = main.Tag > 0; var dl = s.SerializationSettings.DefaultLevel.GetValueOrDefault(new ValueSerializationSettings.LevelValue(level.MakeDefaultNestedLevelForLegacyMember())); if (isPacked) { dl.Basic.Format = ValueFormat.Compact; } if (dynamicType) { // apply dynamic type to items Type itemType = null; Type defaultType = null; MetaType.ResolveListTypes(model, Helpers.GetMemberType(s.Member), ref itemType, ref defaultType); if (itemType != null) { dl.Basic.WriteAsDynamicType = true; dl.Basic.Format = ValueFormat.Reference; if (level.Format == ValueFormat.Compact || level.Format == ValueFormat.MinimalEnhancement) { level.WriteAsDynamicType = false; } } } s.SerializationSettings.DefaultLevel = dl; s.SerializationSettings.SetSettings(level, 0); return(s.TagIsPinned ? MemberHandlerResult.Done : MemberHandlerResult.Partial); // note minAcceptFieldNumber only applies to non-proto } finally { s.MainValue = main; } }
internal void WriteSchema(System.Text.StringBuilder builder, int indent, ref bool requiresBclImport) { Serializer.GetHashCode(); if (_surrogate != null) { return; // nothing to write } ValueMember[] fieldsArr = new ValueMember[_fields.Count]; _fields.CopyTo(fieldsArr, 0); Array.Sort(fieldsArr, ValueMember.Comparer.Default); if (IsList) { string itemTypeName = _model.GetSchemaTypeName(TypeModel.GetListItemType(_model, Type), BinaryDataFormat.Default, false, false, ref requiresBclImport); NewLine(builder, indent).Append("message ").Append(GetSchemaTypeName()).Append(" {"); NewLine(builder, indent + 1).Append("repeated ").Append(itemTypeName).Append(" items = 1;"); NewLine(builder, indent).Append('}'); } else if (_settingsValueFinal.IsAutoTuple) { // key-value-pair etc MemberInfo[] mapping; if (ResolveTupleConstructor(Type, out mapping) != null) { NewLine(builder, indent).Append("message ").Append(GetSchemaTypeName()).Append(" {"); for (int i = 0; i < mapping.Length; i++) { Type effectiveType; if (mapping[i] is PropertyInfo) { effectiveType = ((PropertyInfo)mapping[i]).PropertyType; } else if (mapping[i] is FieldInfo) { effectiveType = ((FieldInfo)mapping[i]).FieldType; } else { throw new NotSupportedException("Unknown member type: " + mapping[i].GetType().Name); } NewLine(builder, indent + 1) .Append("optional ") .Append(_model.GetSchemaTypeName(effectiveType, BinaryDataFormat.Default, false, false, ref requiresBclImport).Replace('.', '_')) .Append(' ').Append(mapping[i].Name).Append(" = ").Append(i + 1).Append(';'); } NewLine(builder, indent).Append('}'); } } else if (Helpers.IsEnum(Type)) { NewLine(builder, indent).Append("enum ").Append(GetSchemaTypeName()).Append(" {"); if (_settingsValueFinal.EnumPassthru.GetValueOrDefault()) { if (Type #if WINRT .GetTypeInfo() #endif .IsDefined(_model.MapType(typeof(FlagsAttribute)), false)) { NewLine(builder, indent + 1).Append("// this is a composite/flags enumeration"); } else { NewLine(builder, indent + 1).Append("// this enumeration will be passed as a raw value"); } foreach (FieldInfo field in #if WINRT Type.GetRuntimeFields() #else Type.GetFields() #endif ) { if (field.IsStatic && field.IsLiteral) { object enumVal; #if WINRT || PORTABLE || CF || FX11 enumVal = field.GetValue(null); #else enumVal = field.GetRawConstantValue(); #endif NewLine(builder, indent + 1).Append(field.Name).Append(" = ").Append(enumVal).Append(";"); } } } else { foreach (ValueMember member in fieldsArr) { NewLine(builder, indent + 1).Append(member.Name).Append(" = ").Append(member.FieldNumber).Append(';'); } } NewLine(builder, indent).Append('}'); } else { NewLine(builder, indent).Append("message ").Append(GetSchemaTypeName()).Append(" {"); foreach (ValueMember member in fieldsArr) { member.Serializer.GetHashCode(); MemberLevelSettingsValue s = member.GetFinalSettingsCopy(0); string ordinality = s.Collection.IsCollection ? "repeated" : member.IsRequired ? "required" : "optional"; NewLine(builder, indent + 1).Append(ordinality).Append(' '); if (s.ContentBinaryFormatHint.GetValueOrDefault() == BinaryDataFormat.Group) { builder.Append("group "); } string schemaTypeName = member.GetSchemaTypeName(true, ref requiresBclImport); builder.Append(schemaTypeName).Append(" ") .Append(member.Name).Append(" = ").Append(member.FieldNumber); object defaultValue = member.GetFinalDefaultValue(); if (defaultValue != null && member.IsRequired == false) { if (defaultValue is string) { builder.Append(" [default = \"").Append(defaultValue).Append("\"]"); } else if (defaultValue is bool) { // need to be lower case (issue 304) builder.Append((bool)defaultValue ? " [default = true]" : " [default = false]"); } else { builder.Append(" [default = ").Append(defaultValue).Append(']'); } } if (s.Collection.IsCollection && s.Collection.Format == CollectionFormat.Protobuf && ListDecorator.CanPack(HelpersInternal.GetWireType(Helpers.GetTypeCode(member.MemberType), s.ContentBinaryFormatHint.GetValueOrDefault()))) { builder.Append(" [packed=true]"); } builder.Append(';'); if (schemaTypeName == "bcl.NetObjectProxy" && (s.Format == ValueFormat.Reference || s.Format == ValueFormat.LateReference) && !s.WriteAsDynamicType.GetValueOrDefault()) // we know what it is; tell the user { builder.Append(" // reference-tracked ").Append(member.GetSchemaTypeName(false, ref requiresBclImport)); } } if (_subTypes != null && _subTypes.Count != 0) { NewLine(builder, indent + 1).Append("// the following represent sub-types; at most 1 should have a value"); SubType[] subTypeArr = new SubType[_subTypes.Count]; _subTypes.CopyTo(subTypeArr, 0); Array.Sort(subTypeArr, SubType.Comparer.Default); foreach (SubType subType in subTypeArr) { string subTypeName = subType.DerivedType.GetSchemaTypeName(); NewLine(builder, indent + 1).Append("optional ").Append(subTypeName) .Append(" ").Append(subTypeName).Append(" = ").Append(subType.FieldNumber).Append(';'); } } NewLine(builder, indent).Append('}'); } }
internal void FinalizeSettingsValue() { if (_settingsValueFinalSet) { return; } int opaqueToken = 0; try { _model.TakeLock(ref opaqueToken); if (_settingsValueFinalSet) { return; } _settingsValueFinal = _settingsValueByClient; ThrowIfInvalidSettings(_settingsValueFinal); FinalizingOwnSettings?.Invoke(this, new FinalizingOwnSettingsArgs(this)); ThrowIfInvalidSettings(_settingsValueFinal); MemberLevelSettingsValue m = _settingsValueFinal.Member; if (_settingsValueFinal.EnumPassthru == null && Helpers.IsEnum(Type)) { #if WINRT _settingsValueFinal.EnumPassthru = _typeInfo.IsDefined(typeof(FlagsAttribute), false); #else _settingsValueFinal.EnumPassthru = Type.IsDefined(_model.MapType(typeof(FlagsAttribute)), false); #endif } if (_settingsValueFinal.IgnoreListHandling) { m.Collection.ItemType = null; m.Collection.Format = CollectionFormat.NotSpecified; m.Collection.PackedWireTypeForRead = null; } else if (m.Collection.ItemType == null) { m.Collection.ItemType = Type.IsArray ? Type.GetElementType() : TypeModel.GetListItemType(_model, Type); } m.Collection.ConcreteType = _settingsValueFinal.ConstructType; if (_settingsValueFinal.PrefixLength == null && !IsSimpleValue) { _settingsValueFinal.PrefixLength = true; } _settingsValueFinal.Member = m; Helpers.MemoryBarrier(); _settingsValueFinalSet = true; IsFrozen = true; } finally { _model.ReleaseLock(opaqueToken); } }
public ValueSerializationSettings(IEnumerable <MemberLevelSettingsValue?> levels, MemberLevelSettingsValue defaultLevel) { _levels = new List <LevelValue?>(levels.Select(x => x != null ? new LevelValue(x.Value) : (LevelValue?)null) ?? new LevelValue?[0]); DefaultLevel = new LevelValue(defaultLevel); }
public LevelValue(MemberLevelSettingsValue basic) : this() { Basic = basic; }