File: System\Formats\Nrbf\RectangularArrayRecord.cs
Web Access
Project: src\src\libraries\System.Formats.Nrbf\src\System.Formats.Nrbf.csproj (System.Formats.Nrbf)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection.Metadata;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Formats.Nrbf.Utils;
using System.Diagnostics;
using System.Runtime.Serialization;
 
namespace System.Formats.Nrbf;
 
internal sealed class RectangularArrayRecord : ArrayRecord
{
    private readonly Type _elementType;
    private readonly int[] _lengths;
    private readonly List<SerializationRecord> _records;
    private readonly AllowedRecordTypes _allowedRecordTypes;
    private readonly MemberTypeInfo _memberTypeInfo;
    private TypeName? _typeName;
 
    internal RectangularArrayRecord(Type elementType, ArrayInfo arrayInfo, MemberTypeInfo memberTypeInfo, int[] lengths) : base(arrayInfo)
    {
        _elementType = elementType;
        _lengths = lengths;
        _memberTypeInfo = memberTypeInfo;
        _records = new List<SerializationRecord>(Math.Min(4, arrayInfo.GetSZArrayLength()));
        _allowedRecordTypes = memberTypeInfo.GetNextAllowedRecordType(0).allowed;
 
        Debug.Assert(elementType == typeof(string) || elementType == typeof(SerializationRecord));
        Debug.Assert(!TypeName.GetElementType().IsArray, "Use JaggedArrayRecord instead.");
    }
 
    public override SerializationRecordType RecordType => SerializationRecordType.BinaryArray;
 
    public override ReadOnlySpan<int> Lengths => _lengths.AsSpan();
 
    public override TypeName TypeName
        => _typeName ??= _memberTypeInfo.GetArrayTypeName(ArrayInfo);
 
    [RequiresDynamicCode("May call Array.CreateInstance() and Type.MakeArrayType().")]
    private protected override Array Deserialize(Type arrayType, bool allowNulls)
    {
        bool storeStrings = _elementType == typeof(string);
 
        // We can not deserialize non-string types.
        // This method returns arrays of SerializationRecord for arrays of complex types.
        Array result =
#if NET9_0_OR_GREATER
            storeStrings
                ? Array.CreateInstanceFromArrayType(arrayType, _lengths)
                : Array.CreateInstance(_elementType, _lengths);
#else
            Array.CreateInstance(_elementType, _lengths);
#endif
 
        AllowedRecordTypes allowedRecordTypes = storeStrings ? AllowedRecordTypes.BinaryObjectString : AllowedRecordTypes.AnyObject;
        Populate(_records, result, _lengths, allowedRecordTypes, allowNulls);
 
        return result;
    }
 
    private protected override void AddValue(object value) => _records.Add((SerializationRecord)value);
 
    internal override (AllowedRecordTypes allowed, PrimitiveType primitiveType) GetAllowedRecordType()
        => (_allowedRecordTypes, default);
}