struct Byte_Range {
  u64 start, len;
  u64 end() const { return start + len; }
};

// Used to store location information about stuff like checksums, page lists, etc
struct Range_Seq {
  Range_Seq *next;
  Byte_Range range;
};

struct Page_Info_Node {
  Page_Info_Node *next;

  Byte_Range range; // len includes checksum
  i32 n_elems; // negative = page has checksum
  u64 cluster_id;

  u64 checksum_size() const {
    return (n_elems < 0) * 8;
  }
};

static const Page_Info_Node invalid_pinfo {};

struct Page_Info_Group {
  Byte_Range range;
  Page_Info_Node *first;
};

struct Page_Info_Chunk {
  Page_Info_Chunk *next;
  Byte_Range range;
  u32 first_group;
};

struct Cluster_Group_Info {
  Byte_Range rng_page_list;
};

struct TFile_Data {
  u64 root_file_header_size;
  Byte_Range rng_root_file_obj;
  u16 root_version_major;
  u16 root_version_minor;
  u16 root_version_patch;
  u32 compression;
  Byte_Range rng_root_file_info;
  Byte_Range rng_root_file_free;
};

struct RNTuple_Data {
  struct {
    u16 epoch, major, minor, patch;
  } version;
  
  u64 rblob_header_size;
  Byte_Range rng_anchor;
  Byte_Range rng_anchor_key;
  Byte_Range rng_header;
  Byte_Range rng_footer;
  Byte_Range rng_tkeys_list;

  Page_Info_Node *pages;
  u64 n_pages;
  // total number of elements of all pages
  u64 n_elems;
  u64 tot_page_size;

  // TODO
  Range_Seq *checksums;
  u64        n_checksums;

  Cluster_Group_Info *cluster_groups;
  u64 n_cluster_groups;
  u64 tot_page_list_size;

  u64 n_clusters;

  Page_Info_Group *page_groups;
  u64 n_page_groups;

  // grouping of consecutive pages
  Page_Info_Chunk *page_chunks;
  u64 n_page_chunks;
};