Exemplo n.º 1
0
        internal PEFieldSymbol(
            PEModuleSymbol moduleSymbol,
            PENamedTypeSymbol containingType,
            FieldHandle fieldDef)
        {
            Debug.Assert((object)moduleSymbol != null);
            Debug.Assert((object)containingType != null);
            Debug.Assert(!fieldDef.IsNil);

            this.handle = fieldDef;
            this.containingType = containingType;

            try
            {
                moduleSymbol.Module.GetFieldDefPropsOrThrow(fieldDef, out this.name, out this.flags);
            }
            catch (BadImageFormatException)
            {
                if ((object)this.name == null)
                {
                    this.name = String.Empty;
                }

                lazyUseSiteDiagnostic = new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this);
            }
        }
Exemplo n.º 2
0
 //
 // fieldHandle    - the "tkFieldDef" that identifies the field.
 // definingType   - the "tkTypeDef" that defined the field (this is where you get the metadata reader that created fieldHandle.)
 // contextType    - the type that supplies the type context (i.e. substitutions for generic parameters.) Though you
 //                  get your raw information from "definingType", you report "contextType" as your DeclaringType property.
 //
 //  For example:
 //
 //       typeof(Foo<>).GetTypeInfo().DeclaredMembers
 //
 //           The definingType and contextType are both Foo<>
 //
 //       typeof(Foo<int,String>).GetTypeInfo().DeclaredMembers
 //
 //          The definingType is "Foo<,>"
 //          The contextType is "Foo<int,String>"
 //
 //  We don't report any DeclaredMembers for arrays or generic parameters so those don't apply.
 //
 private RuntimeFieldInfo(FieldHandle fieldHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
 {
     _fieldHandle = fieldHandle;
     _definingTypeInfo = definingTypeInfo;
     _contextTypeInfo = contextTypeInfo;
     _reader = definingTypeInfo.Reader;
     _field = fieldHandle.GetField(_reader);
 }
Exemplo n.º 3
0
 /// <summary>
 /// Returns true if the field should be imported. Visibility
 /// and the value of <paramref name="importOptions"/> are considered
 /// </summary>
 public static bool ShouldImportField(this PEModule module, FieldHandle field, MetadataImportOptions importOptions)
 {
     try
     {
         var flags = module.GetFieldDefFlagsOrThrow(field);
         return ShouldImportField(flags, importOptions);
     }
     catch (BadImageFormatException)
     {
         return true;
     }
 }
Exemplo n.º 4
0
 internal override bool TryGetFieldHandle(Cci.IFieldDefinition def, out FieldHandle handle)
 {
     var other = this.mapToMetadata.MapDefinition(def) as PEFieldSymbol;
     if ((object)other != null)
     {
         handle = other.Handle;
         return true;
     }
     else
     {
         handle = default(FieldHandle);
         return false;
     }
 }
Exemplo n.º 5
0
 public abstract bool GetDefaultValueIfAny(MetadataReader reader, FieldHandle fieldHandle, Type declaredType, IEnumerable<CustomAttributeData> customAttributes, out Object defaultValue);
Exemplo n.º 6
0
 public abstract FieldAccessor TryGetFieldAccessor(RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle fieldTypeHandle, FieldHandle fieldHandle);
Exemplo n.º 7
0
 internal static RuntimeFieldInfo GetRuntimeFieldInfo(FieldHandle fieldHandle, NativeFormatRuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo, RuntimeTypeInfo reflectedType)
 {
     return(new NativeFormatRuntimeFieldInfo(fieldHandle, definingTypeInfo, contextTypeInfo, reflectedType).WithDebugName());
 }
Exemplo n.º 8
0
 public override void GetFieldDefProps(FieldHandle fieldDef, out string name, out FieldAttributes flags)
 {
     base.GetFieldDefProps(fieldDef, out name, out flags);
     ModifyFieldDefProps(fieldDef, name, ref flags);
 }
Exemplo n.º 9
0
 public override FieldAttributes GetFieldDefFlags(FieldHandle fieldDef)
 {
     string unused;
     FieldAttributes flags;
     GetFieldDefProps(fieldDef, out unused, out flags);
     return flags;
 }
Exemplo n.º 10
0
 public abstract bool TryGetFieldFromHandleAndType(RuntimeFieldHandle runtimeFieldHandle, RuntimeTypeHandle declaringTypeHandle, out FieldHandle fieldHandle);
Exemplo n.º 11
0
 internal abstract bool TryGetFieldHandle(Cci.IFieldDefinition def, out FieldHandle handle);
        public sealed override IEnumerable <CustomAttributeData> GetPsuedoCustomAttributes(MetadataReader reader, FieldHandle fieldHandle, TypeDefinitionHandle declaringTypeHandle)
        {
            TypeAttributes layoutKind = declaringTypeHandle.GetTypeDefinition(reader).Flags & TypeAttributes.LayoutMask;

            if (layoutKind == TypeAttributes.ExplicitLayout)
            {
                int offset = (int)(fieldHandle.GetField(reader).Offset);
                CustomAttributeTypedArgument offsetArgument = ExtensibleCustomAttributeData.CreateCustomAttributeTypedArgument(typeof(Int32), offset);
                yield return(ReflectionCoreExecution.ExecutionDomain.GetCustomAttributeData(typeof(FieldOffsetAttribute), new CustomAttributeTypedArgument[] { offsetArgument }, null));
            }
        }
        public sealed override bool GetDefaultValueIfAny(MetadataReader reader, FieldHandle fieldHandle, Type declaredType, IEnumerable <CustomAttributeData> customAttributes, out Object defaultValue)
        {
            Field field = fieldHandle.GetField(reader);

            return(DefaultValueParser.GetDefaultValueIfAny(DefaultValueParser.MemberType.Field, reader, field.DefaultValue, declaredType, customAttributes, out defaultValue));
        }
Exemplo n.º 14
0
 internal abstract bool TryGetFieldHandle(IFieldDefinition def, out FieldHandle handle);
Exemplo n.º 15
0
 public override string GetFieldDefName(FieldHandle fieldDef)
 {
     string name;
     FieldAttributes unused;
     GetFieldDefProps(fieldDef, out name, out unused);
     return name;
 }
        /// <summary>
        /// Try to look up field acccess info for given canon in metadata blobs for all available modules.
        /// </summary>
        /// <param name="metadataReader">Metadata reader for the declaring type</param>
        /// <param name="declaringTypeHandle">Declaring type for the method</param>
        /// <param name="fieldHandle">Field handle</param>
        /// <param name="canonFormKind">Canonical form to use</param>
        /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param>
        /// <returns>true when found, false otherwise</returns>
        private static bool TryGetFieldAccessMetadataFromFieldAccessMap(
            MetadataReader metadataReader,
            RuntimeTypeHandle declaringTypeHandle,
            FieldHandle fieldHandle,
            CanonicalFormKind canonFormKind,
            ref FieldAccessMetadata fieldAccessMetadata)
        {
            CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle, canonFormKind);
            TypeManagerHandle fieldHandleModule            = ModuleList.Instance.GetModuleForMetadataReader(metadataReader);
            bool              isDynamicType = RuntimeAugments.IsDynamicType(declaringTypeHandle);
            string            fieldName     = null;
            RuntimeTypeHandle declaringTypeHandleDefinition = Instance.GetTypeDefinition(declaringTypeHandle);

            foreach (NativeFormatModuleInfo mappingTableModule in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle)))
            {
                NativeReader fieldMapReader;
                if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.FieldAccessMap, out fieldMapReader))
                {
                    continue;
                }

                NativeParser    fieldMapParser = new NativeParser(fieldMapReader, 0);
                NativeHashtable fieldHashtable = new NativeHashtable(fieldMapParser);

                ExternalReferencesTable externalReferences = default(ExternalReferencesTable);
                if (!externalReferences.InitializeCommonFixupsTable(mappingTableModule))
                {
                    continue;
                }

                var lookup = fieldHashtable.Lookup(canonWrapper.LookupHashCode);

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    // Grammar of a hash table entry:
                    // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset

                    FieldTableFlags entryFlags = (FieldTableFlags)entryParser.GetUnsigned();

                    if ((canonFormKind == CanonicalFormKind.Universal) != ((entryFlags & FieldTableFlags.IsUniversalCanonicalEntry) != 0))
                    {
                        continue;
                    }

                    RuntimeTypeHandle entryDeclaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle) &&
                        !canonWrapper.IsCanonicallyEquivalent(entryDeclaringTypeHandle))
                    {
                        continue;
                    }

                    if ((entryFlags & FieldTableFlags.HasMetadataHandle) != 0)
                    {
                        Handle entryFieldHandle = (((int)HandleType.Field << 24) | (int)entryParser.GetUnsigned()).AsHandle();
                        if (!fieldHandle.Equals(entryFieldHandle))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (fieldName == null)
                        {
                            QTypeDefinition qTypeDefinition;

                            bool success = Instance.TryGetMetadataForNamedType(
                                declaringTypeHandleDefinition,
                                out qTypeDefinition);
                            Debug.Assert(success);

                            MetadataReader nativeFormatMetadataReader = qTypeDefinition.NativeFormatReader;

                            fieldName = nativeFormatMetadataReader.GetString(fieldHandle.GetField(nativeFormatMetadataReader).Name);
                        }

                        string entryFieldName = entryParser.GetString();

                        if (fieldName != entryFieldName)
                        {
                            continue;
                        }
                    }

                    int    cookieOrOffsetOrOrdinal = (int)entryParser.GetUnsigned();
                    int    fieldOffset;
                    IntPtr fieldAddressCookie = IntPtr.Zero;

                    if (canonFormKind == CanonicalFormKind.Universal)
                    {
                        if (!TypeLoaderEnvironment.Instance.TryGetFieldOffset(declaringTypeHandle, (uint)cookieOrOffsetOrOrdinal, out fieldOffset))
                        {
                            Debug.Assert(false);
                            return(false);
                        }
                    }
                    else
                    {
                        if ((entryFlags & FieldTableFlags.FieldOffsetEncodedDirectly) != 0)
                        {
                            fieldOffset = cookieOrOffsetOrOrdinal;
                        }
                        else
                        {
#if CORERT
                            fieldOffset        = 0;
                            fieldAddressCookie = externalReferences.GetFieldAddressFromIndex((uint)cookieOrOffsetOrOrdinal);

                            if ((entryFlags & FieldTableFlags.IsGcSection) != 0)
                            {
                                fieldOffset = (int)entryParser.GetUnsigned();
                            }
#else
                            fieldOffset = (int)externalReferences.GetRvaFromIndex((uint)cookieOrOffsetOrOrdinal);
#endif
                        }
                    }

                    if ((entryFlags & FieldTableFlags.StorageClass) == FieldTableFlags.ThreadStatic)
                    {
                        // TODO: CoreRT support

                        if (canonFormKind != CanonicalFormKind.Universal)
                        {
                            fieldAddressCookie = RvaToNonGenericStaticFieldAddress(mappingTableModule.Handle, fieldOffset);
                        }

                        if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle))
                        {
                            // In this case we didn't find an exact match, but we did find a canonically equivalent match
                            // We might be in the dynamic type case, or the canonically equivalent, but not the same case.

                            if (!RuntimeAugments.IsDynamicType(declaringTypeHandle))
                            {
                                int offsetToCreateCookieFor = fieldOffset;
                                // We're working with a statically generated type, but we didn't find an exact match in the tables
                                if (canonFormKind != CanonicalFormKind.Universal)
                                {
                                    offsetToCreateCookieFor = checked ((int)TypeLoaderEnvironment.GetThreadStaticTypeOffsetFromThreadStaticCookie(fieldAddressCookie));
                                }

                                fieldAddressCookie = TypeLoaderEnvironment.Instance.TryGetThreadStaticFieldOffsetCookieForTypeAndFieldOffset(declaringTypeHandle, checked ((uint)offsetToCreateCookieFor));
                            }
                        }
                    }

                    fieldAccessMetadata.MappingTableModule = mappingTableModule.Handle;
                    fieldAccessMetadata.Cookie             = fieldAddressCookie;
                    fieldAccessMetadata.Flags  = entryFlags;
                    fieldAccessMetadata.Offset = fieldOffset;
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 17
0
 public override void GetFieldDefProps(FieldHandle fieldDef, out string name, out FieldAttributes flags)
 {
     base.GetFieldDefProps(fieldDef, out name, out flags);
     ModifyFieldDefProps(fieldDef, name, ref flags);
 }
 public bool TryGetField(string name, out FieldHandle handle)
 {
     if (this.fieldDefs == null)
     {
         this.fieldDefs = GetFieldDefs(this.reader, this.typeHandle);
     }
     return this.fieldDefs.TryGetValue(name, out handle);
 }
Exemplo n.º 19
0
 public abstract FieldAccessor TryGetFieldAccessor(RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle fieldTypeHandle, FieldHandle fieldHandle);
Exemplo n.º 20
0
 public abstract bool GetDefaultValueIfAny(MetadataReader reader, FieldHandle fieldHandle, Type declaredType, IEnumerable <CustomAttributeData> customAttributes, out Object defaultValue);
Exemplo n.º 21
0
 public abstract IEnumerable<CustomAttributeData> GetPsuedoCustomAttributes(MetadataReader reader, FieldHandle fieldHandle, TypeDefinitionHandle declaringTypeHandle);
Exemplo n.º 22
0
 public abstract IEnumerable <CustomAttributeData> GetPseudoCustomAttributes(MetadataReader reader, FieldHandle fieldHandle, TypeDefinitionHandle declaringTypeHandle);
Exemplo n.º 23
0
        /// <summary>
        /// Try to look up field access info for given canon in metadata blobs for all available modules.
        /// </summary>
        /// <param name="metadataReader">Metadata reader for the declaring type</param>
        /// <param name="declaringTypeHandle">Declaring type for the method</param>
        /// <param name="fieldHandle">Field handle</param>
        /// <param name="canonFormKind">Canonical form to use</param>
        /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param>
        /// <returns>true when found, false otherwise</returns>
        private static unsafe bool TryGetFieldAccessMetadataFromFieldAccessMap(
            MetadataReader metadataReader,
            RuntimeTypeHandle declaringTypeHandle,
            FieldHandle fieldHandle,
            CanonicalFormKind canonFormKind,
            ref FieldAccessMetadata fieldAccessMetadata)
        {
            CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle, canonFormKind);
            string            fieldName = null;
            RuntimeTypeHandle declaringTypeHandleDefinition = TypeLoaderEnvironment.GetTypeDefinition(declaringTypeHandle);

            foreach (NativeFormatModuleInfo mappingTableModule in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle)))
            {
                NativeReader fieldMapReader;
                if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.FieldAccessMap, out fieldMapReader))
                {
                    continue;
                }

                NativeParser    fieldMapParser = new NativeParser(fieldMapReader, 0);
                NativeHashtable fieldHashtable = new NativeHashtable(fieldMapParser);

                ExternalReferencesTable externalReferences = default(ExternalReferencesTable);
                if (!externalReferences.InitializeCommonFixupsTable(mappingTableModule))
                {
                    continue;
                }

                var lookup = fieldHashtable.Lookup(canonWrapper.LookupHashCode);

                NativeParser entryParser;
                while (!(entryParser = lookup.GetNext()).IsNull)
                {
                    // Grammar of a hash table entry:
                    // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset

                    FieldTableFlags entryFlags = (FieldTableFlags)entryParser.GetUnsigned();

                    if ((canonFormKind == CanonicalFormKind.Universal) != ((entryFlags & FieldTableFlags.IsUniversalCanonicalEntry) != 0))
                    {
                        continue;
                    }

                    RuntimeTypeHandle entryDeclaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle) &&
                        !canonWrapper.IsCanonicallyEquivalent(entryDeclaringTypeHandle))
                    {
                        continue;
                    }

                    if ((entryFlags & FieldTableFlags.HasMetadataHandle) != 0)
                    {
                        Handle entryFieldHandle = (((int)HandleType.Field << 24) | (int)entryParser.GetUnsigned()).AsHandle();
                        if (!fieldHandle.Equals(entryFieldHandle))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (fieldName == null)
                        {
                            QTypeDefinition qTypeDefinition;

                            bool success = Instance.TryGetMetadataForNamedType(
                                declaringTypeHandleDefinition,
                                out qTypeDefinition);
                            Debug.Assert(success);

                            MetadataReader nativeFormatMetadataReader = qTypeDefinition.NativeFormatReader;

                            fieldName = nativeFormatMetadataReader.GetString(fieldHandle.GetField(nativeFormatMetadataReader).Name);
                        }

                        string entryFieldName = entryParser.GetString();

                        if (fieldName != entryFieldName)
                        {
                            continue;
                        }
                    }

                    int    fieldOffset;
                    IntPtr fieldAddressCookie = IntPtr.Zero;

                    if (canonFormKind == CanonicalFormKind.Universal)
                    {
                        if (!TypeLoaderEnvironment.Instance.TryGetFieldOffset(declaringTypeHandle, entryParser.GetUnsigned() /* field ordinal */, out fieldOffset))
                        {
                            Debug.Assert(false);
                            return(false);
                        }
                    }
                    else
                    {
                        if ((entryFlags & FieldTableFlags.FieldOffsetEncodedDirectly) != 0)
                        {
                            fieldOffset = (int)entryParser.GetUnsigned();
                        }
                        else
                        {
                            fieldOffset        = 0;
                            fieldAddressCookie = externalReferences.GetAddressFromIndex(entryParser.GetUnsigned());

                            FieldTableFlags storageClass = entryFlags & FieldTableFlags.StorageClass;
                            if (storageClass == FieldTableFlags.GCStatic || storageClass == FieldTableFlags.ThreadStatic)
                            {
                                fieldOffset = (int)entryParser.GetUnsigned();
                            }
                        }
                    }

                    fieldAccessMetadata.MappingTableModule = mappingTableModule.Handle;
                    fieldAccessMetadata.Cookie             = fieldAddressCookie;
                    fieldAccessMetadata.Flags  = entryFlags;
                    fieldAccessMetadata.Offset = fieldOffset;
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 24
0
 internal static RuntimeFieldInfo GetRuntimeFieldInfo(FieldHandle fieldHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
 {
     return(new RuntimeFieldInfo(fieldHandle, definingTypeInfo, contextTypeInfo).WithDebugName());
 }
Exemplo n.º 25
0
 /// <summary>
 ///
 /// </summary>
 /// <returns></returns>
 public override int GetHashCode()
 {
     return(FieldHandle.GetHashCode());
 }
Exemplo n.º 26
0
        /// <summary>
        /// The backing field of a WinRT enumeration type is not public although the backing fields
        /// of managed enumerations are. To allow managed languages to directly access this field,
        /// it is made public by the metadata adapter.
        /// </summary>
        private void ModifyFieldDefProps(FieldHandle fieldDef, string name, ref FieldAttributes flags)
        {
            if (name == "value__" && flags.HasFlag(FieldAttributes.RTSpecialName))
            {
                TypeHandle typeDef = FindContainingType(fieldDef);
                Debug.Assert(!typeDef.IsNil);

                MetadataToken extendsRef = GetTypeDefExtends(typeDef);
                if (extendsRef.HandleType == HandleType.TypeReference)
                {
                    string extendsName, extendsNamespace;
                    MetadataToken unused;
                    GetTypeRefProps(
                        (TypeReferenceHandle)extendsRef,
                        out extendsName,
                        out extendsNamespace,
                        out unused);
                    if (extendsName == "Enum" && extendsNamespace == "System")
                    {
                        flags = flags & ~FieldAttributes.Private;
                        flags |= FieldAttributes.Public;
                    }
                }
            }
        }
Exemplo n.º 27
0
 public abstract FieldAccessor TryGetFieldAccessor(MetadataReader reader, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle fieldTypeHandle, FieldHandle fieldHandle);
 private FieldInfo GetFieldInfo(RuntimeTypeHandle declaringTypeHandle, FieldHandle fieldHandle)
 {
     RuntimeType declaringType = ReflectionCoreNonPortable.GetTypeForRuntimeTypeHandle(declaringTypeHandle);
     RuntimeTypeInfo contextTypeInfo = declaringType.GetRuntimeTypeInfo();
     RuntimeNamedTypeInfo definingTypeInfo = contextTypeInfo.AnchoringTypeDefinitionForDeclaredMembers;
     MetadataReader reader = definingTypeInfo.Reader;
     return RuntimeFieldInfo.GetRuntimeFieldInfo(fieldHandle, definingTypeInfo, contextTypeInfo);
 }
Exemplo n.º 29
0
 public abstract bool TryGetFieldFromHandleAndType(RuntimeFieldHandle runtimeFieldHandle, RuntimeTypeHandle declaringTypeHandle, out FieldHandle fieldHandle);
 public sealed override IEnumerable<CustomAttributeData> GetPsuedoCustomAttributes(MetadataReader reader, FieldHandle fieldHandle, TypeDefinitionHandle declaringTypeHandle)
 {
     TypeAttributes layoutKind = declaringTypeHandle.GetTypeDefinition(reader).Flags & TypeAttributes.LayoutMask;
     if (layoutKind == TypeAttributes.ExplicitLayout)
     {
         int offset = (int)(fieldHandle.GetField(reader).Offset);
         CustomAttributeTypedArgument offsetArgument = ExtensibleCustomAttributeData.CreateCustomAttributeTypedArgument(typeof(Int32), offset);
         yield return ReflectionCoreExecution.ExecutionDomain.GetCustomAttributeData(typeof(FieldOffsetAttribute), new CustomAttributeTypedArgument[] { offsetArgument }, null);
     }
 }
 public sealed override bool GetDefaultValueIfAny(MetadataReader reader, FieldHandle fieldHandle, Type declaredType, IEnumerable<CustomAttributeData> customAttributes, out Object defaultValue)
 {
     Field field = fieldHandle.GetField(reader);
     return DefaultValueParser.GetDefaultValueIfAny(DefaultValueParser.MemberType.Field, reader, field.DefaultValue, declaredType, customAttributes, out defaultValue);
 }
        private MemberInfo GetOrAddFieldInfo(FieldHandle handle)
        {
            if (this.fields == null)
            {
                this.fields = new Dictionary<FieldHandle, MemberInfo>();
            }

            MemberInfo result = null;
            if (!fields.TryGetValue(handle, out result))
            {
                result = new MemberInfo(MemberKind.Field);
                var field = metadataReader.GetField(handle);
                result.Token = metadataReader.GetToken(handle);
                result.DeclaringTypeHandle = metadataReader.GetDeclaringType(handle);
                if (result.DeclaringTypeHandle.IsNil)
                {
                    throw null;
                }

                result.Handle = handle;
                fields[handle] = result;
            }

            return result;
        }