[SQLite] #SZ4 Stuck trying to read the table leaf cells

I’m stuck on Stage and #SZ4. I am using Rust to go through this challenge. The problem I am facing is about how to extract the table names from the cells. From what I understand, in order to get the location of the cells, we first need to parse the cell pointer array that follows the page header. Since we have already extracted the num cells, we can simply do some thing as follows to extract the offsets:

let count = page_header.num_cells;
let mut cell_offset:[u8; 2] = [0; 2];
let mut offsets:Vec<Offset> = Vec::new();
for _ in 0 .. count {
    reader.read_exact(&mut cell_offset)?;
    let offset: Offset = ByteOffset(cell_offset).into();
    println!("found offset: {}", offset.0);
    offsets.push(offset);
} 

I got the following offsets:

found offset: 3983
found offset: 3901
found offset: 3779
Logs from your program will appear here!
database page size: 4096
Number of tables: 3

Reading the specification, it seems like I will now need to read the cells at the three offsets to get the table names. Now the problem is that the offsets are from the start of the page_header, since I am making a read_exact call to read the byte arrays, I am essentially going though the stream without the ability to rewind to the start of the page_header in order to jump to the table leaf cells. Maybe this is due my limited intuitions around byte arithmetic but it will be great to get some pointers on how I can read the leaf cells.

And here’s a snippet of my code that outlines how I am reading the bytes:

impl DB {
  pub fn from_reader(mut reader: impl Read) -> Result<Self, Error> {
        let mut headers = [0; 100];
        reader.read_exact(&mut headers)?;
        let header: Header = ByteHeaders(headers).into();

        let mut page_headers = [0; 8];
        reader.read_exact(&mut page_headers)?;
        let page_header: PageHeader =  BytePageHeaders(page_headers).into();
        
        let count = page_header.num_cells;
        let mut cell_offset:[u8; 2] = [0; 2];
        let mut offsets:Vec<Offset> = Vec::new();
        for _ in 0 .. count {
            reader.read_exact(&mut cell_offset)?;
            let offset: Offset = ByteOffset(cell_offset).into();
            println!("found offset: {}", offset.0);
            offsets.push(offset);
        }

        Ok(DB {
            header,
            page_header,
        })
    }
}

Hello, you can try Cursor in the std lib, it allows seek forward and backward using seek and seek_relative. More exactly, I’m using `Cursor<&'_ [u8]>`.

1 Like

Hey @scorpion-917, another thing you could try is to read the entire page (4K bytes) into a Vec<u8> and work with it directly.

Closing this thread due to inactivity. If you still need assistance, feel free to reopen or start a new discussion!

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.