/**
   * Create a HeapPage from a set of bytes of data read from disk. The format of a HeapPage is a set
   * of header bytes indicating the slots of the page that are in use, some number of tuple slots.
   * Specifically, the number of tuples is equal to:
   *
   * <p>floor((BufferPool.PAGE_SIZE*8) / (tuple size * 8 + 1))
   *
   * <p>where tuple size is the size of tuples in this database table, which can be determined via
   * {@link Catalog#getTupleDesc}. The number of 8-bit header words is equal to:
   *
   * <p>ceiling(no. tuple slots / 8)
   *
   * <p>
   *
   * @see Database#getCatalog
   * @see Catalog#getTupleDesc
   * @see BufferPool#PAGE_SIZE
   */
  public HeapPage(HeapPageId id, byte[] data) throws IOException {
    this.pid = id;
    this.td = Database.getCatalog().getTupleDesc(id.getTableId());
    this.numSlots = getNumTuples();
    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));

    // allocate and read the header slots of this page
    header = new byte[getHeaderSize()];
    for (int i = 0; i < header.length; i++) header[i] = dis.readByte();

    try {
      // allocate and read the actual records of this page
      tuples = new Tuple[numSlots];
      for (int i = 0; i < tuples.length; i++) tuples[i] = readNextTuple(dis, i);
    } catch (NoSuchElementException e) {
      e.printStackTrace();
    }
    dis.close();

    setBeforeImage();
  }
  /**
   * Create a HeapPage from a set of bytes of data read from disk. The format of a HeapPage is a set
   * of 32-bit header words indicating the slots of the page that are in use, plus
   * (BufferPool.PAGE_SIZE/tuple size) tuple slots, where tuple size is the size of tuples in this
   * database table, which can be determined via {@link Catalog#getTupleDesc}.
   *
   * <p>The number of 32-bit header words is equal to:
   *
   * <p>(no. tuple slots / 32) + 1
   *
   * <p>
   *
   * @see Database#getCatalog
   * @see Catalog#getTupleDesc
   * @see BufferPool#PAGE_SIZE
   */
  public HeapPage(HeapPageId id, byte[] data) throws IOException {
    this.pid = id;
    this.td = Database.getCatalog().getTupleDesc(id.tableid());
    // this.numSlots = (BufferPool.PAGE_SIZE) / (td.getSize());
    this.numSlots = (BufferPool.PAGE_SIZE * 8) / ((td.getSize() * 8) + 1);
    // System.out.println(this.numSlots);
    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));

    // allocate and read the header slots of this page
    header = new Header(dis);

    try {
      // allocate and read the actual records of this page
      tuples = new Tuple[numSlots];
      for (int i = 0; i < numSlots; i++) {
        tuples[i] = readNextTuple(dis, i);
      }
    } catch (NoSuchElementException e) {
      // e.printStackTrace();
    }

    dis.close();
  }