public RowsetHolder(ColumnInfo[] columnTypes, Memory <byte> storage, bool init) { System.Diagnostics.Debug.Assert(BitConverter.IsLittleEndian, "Rowset holder fixed assumes that we are running on little endian"); this.rowSize = GetRowSize(columnTypes); this.storage = storage; this.rowCount = 0; // bit for every row. // align on upper boundary. this.reservedPresenceBitmaskCount = (ushort)UtilStructures.IntCeil.CeilDiv(storage.Length, (rowSize * 8)); // TODO: In this implementation each value in tuple can't be bigger than 256 bytes. // Since this is only for fixed data this should be fine. this.reservedColumnTupleOffsetsCount = (ushort)(columnTypes.Length * sizeof(ushort)); if (init) { // set bitmask to 0. for (int i = 0; i < this.reservedPresenceBitmaskCount; i++) { this.storage.Span[i] = 0; } int pos = this.reservedPresenceBitmaskCount; this.storage.Span[pos] = 0; for (int i = 0; i < columnTypes.Length - 1; i++) { this.storage.Span[pos + 1] = (byte)(this.storage.Span[pos] + columnTypes[i].GetSize()); pos++; } } else { // Set row count. this.rowCount = BitArray.CountSet(storage.Span.Slice(0, this.reservedPresenceBitmaskCount)); } // Align so start is divisible by 4. // TODO: Need to measure perf. int dataStartUnAligned = this.reservedPresenceBitmaskCount + this.reservedColumnTupleOffsetsCount; this.dataStartPosition = (ushort)(((dataStartUnAligned + 4 - 1) / 4) * 4); maxRowCount = (ushort)((storage.Length - dataStartPosition) / rowSize); }