/// <summary> /// Recursively populates an array from PB binary data representation. /// </summary> private void PopulateArrayFromBinaryArray(NpgsqlBackendTypeInfo TypeInfo, byte[] backendData, Int32 fieldValueSize, Int32 TypeModifier, ref int dataOffset, int[] dimLengths, int[] dimLBounds, int dimOffset, Array dst, int[] dstOffsets) { int dimensionLBound = dimLBounds[dimOffset]; int end = dimensionLBound + dimLengths[dimOffset]; if (dimOffset < dimLengths.Length - 1) { // Drill down recursively until we hit a single dimension array. for (int i = dimensionLBound; i < end; i++) { dstOffsets[dimOffset] = i; PopulateArrayFromBinaryArray(TypeInfo, backendData, fieldValueSize, TypeModifier, ref dataOffset, dimLengths, dimLBounds, dimOffset + 1, dst, dstOffsets); } } else { // Populate a single dimension array. for (int i = dimensionLBound; i < end; i++) { // Sanity check. if (backendData.Length < dataOffset + 4) { throw new NpgsqlException("Out of backend data while reading binary array"); } int elementLength; // Each element consists of an int length identifier, followed by that many bytes of raw data. // Length -1 indicates a NULL value, and is naturally followed by no data. elementLength = PGUtil.ReadInt32(backendData, dataOffset); dataOffset += 4; if (elementLength == -1) { // This currently throws an exception on value types. dst.SetValue(DBNull.Value, dstOffsets); } else { // Sanity check. if (backendData.Length < dataOffset + elementLength) { throw new NpgsqlException("Out of backend data while reading binary array"); } byte[] elementBinary; // Get element data from backend data. elementBinary = PGUtil.ReadBytes(backendData, dataOffset, elementLength); object elementNative; elementNative = _elementConverter.ConvertBackendBinaryToNative(elementBinary, fieldValueSize, TypeModifier); dstOffsets[dimOffset] = i; dst.SetValue(elementNative, dstOffsets); dataOffset += elementLength; } } } }