File: System\Runtime\Serialization\Schema\SchemaImportHelper.cs
Web Access
Project: src\src\libraries\System.Runtime.Serialization.Schema\src\System.Runtime.Serialization.Schema.csproj (System.Runtime.Serialization.Schema)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization.DataContracts;
using System.Xml;
 
namespace System.Runtime.Serialization
{
    internal enum DataContractType
    {
        ClassDataContract,
        CollectionDataContract,
        EnumDataContract,
        PrimitiveDataContract,
        XmlDataContract,
        Unknown = -1
    }
 
    internal static class DataContractExtensions
    {
        internal static DataContractType GetContractType(this DataContract dataContract) => dataContract.ContractType switch
        {
            "ClassDataContract" => DataContractType.ClassDataContract,
            "CollectionDataContract" => DataContractType.CollectionDataContract,
            "EnumDataContract" => DataContractType.EnumDataContract,
            "PrimitiveDataContract" => DataContractType.PrimitiveDataContract,
            "XmlDataContract" => DataContractType.XmlDataContract,
            _ => DataContractType.Unknown
        };
 
        internal static bool Is(this DataContract dataContract, DataContractType dcType)
        {
            return (dataContract.GetContractType() == dcType);
        }
 
        internal static DataContract? As(this DataContract dataContract, DataContractType dcType)
        {
            if (dataContract.GetContractType() == dcType)
                return dataContract;
            return null;
        }
 
        [RequiresUnreferencedCode(ImportGlobals.SerializerTrimmerWarning)]
        internal static bool IsItemTypeNullable(this DataContract collectionDataContract)
        {
            if (collectionDataContract.GetContractType() == DataContractType.CollectionDataContract)
            {
                // ItemContract - aka BaseContract - is never null for CollectionDataContract
                return SchemaImportHelper.IsTypeNullable(collectionDataContract.BaseContract!.UnderlyingType);
            }
 
            return false;
        }
    }
 
    internal static class SchemaImportHelper
    {
        internal static bool IsTypeNullable(Type type)
        {
            return !type.IsValueType ||
                    (type.IsGenericType &&
                    type.GetGenericTypeDefinition() == typeof(Nullable<>));
        }
 
        internal static string GetCollectionNamespace(string elementNs)
        {
            return IsBuiltInNamespace(elementNs) ? ImportGlobals.CollectionsNamespace : elementNs;
        }
 
        internal static string GetDataContractNamespaceFromUri(string uriString)
        {
            return uriString.StartsWith(ImportGlobals.DataContractXsdBaseNamespace, StringComparison.Ordinal) ? uriString.Substring(ImportGlobals.DataContractXsdBaseNamespace.Length) : uriString;
        }
 
        internal static string GetDefaultXmlNamespace(string? clrNs)
        {
            return new Uri(ImportGlobals.DataContractXsdBaseNamespaceUri, clrNs ?? string.Empty).AbsoluteUri;
        }
 
        internal static bool IsBuiltInNamespace(string ns)
        {
            return (ns == ImportGlobals.SchemaNamespace || ns == ImportGlobals.SerializationNamespace);
        }
 
        // This should match the behavior of DataContract.EncodeLocalName
        internal static string EncodeLocalName(string localName)
        {
            if (IsAsciiLocalName(localName))
                return localName;
 
            if (IsValidNCName(localName))
                return localName;
 
            return XmlConvert.EncodeLocalName(localName);
        }
 
        private static bool IsAsciiLocalName(string localName)
        {
            if (localName.Length == 0)
                return false;
            if (!char.IsAsciiLetter(localName[0]))
                return false;
            for (int i = 1; i < localName.Length; i++)
            {
                char ch = localName[i];
                if (!char.IsAsciiLetterOrDigit(ch))
                    return false;
            }
            return true;
        }
 
        private static bool IsValidNCName(string name)
        {
            try
            {
                XmlConvert.VerifyNCName(name);
                return true;
            }
            catch (XmlException)
            {
                return false;
            }
        }
    }
}