feat(page): 实现Page结构的序列化与反序列化功能

新增DeSerializePage函数用于从字节数据中完整解析Page结构,
包括PageHead和Cells部分。同时实现Serialize方法将Page结构
序列化为字节数据。此外添加了GetCell、GetCellData和
WriteNewCell等辅助方法,便于操作Page中的Cell数据。
```
This commit is contained in:
kingecg 2025-11-10 22:42:38 +08:00
parent 96ba95f1be
commit 4add42dc21
1 changed files with 54 additions and 3 deletions

57
page.go
View File

@ -48,11 +48,17 @@ func DeSerializePageHead(data []byte) (*PageHead, error) {
FirstFreeOffset: FirstFreeOffset,
}, nil
}
// DeSerializePage 从字节数据中反序列化Page结构
// data: 包含页面数据的字节切片
// 返回值: 解析出的Page指针和可能的错误
func DeSerializePage(data []byte) (*Page, error) {
head, err := DeSerializePageHead(data[0:BlockFileHeaderSize])
if err != nil {
return nil, err
}
// 如果没有cell直接返回空的cells数组
if head.CellCount == 0 {
return &Page{
PageHead: head,
@ -60,8 +66,10 @@ func DeSerializePage(data []byte) (*Page, error) {
data: data,
}, nil
}
cells := make([]*Cell, head.CellCount)
// find cell offset array start
// 查找cell偏移数组的起始位置
cellPOffset := 0
for i := 17; i < BlockFilePageSize; i++ {
t := binary.LittleEndian.Uint32(data[i : i+4])
@ -74,26 +82,69 @@ func DeSerializePage(data []byte) (*Page, error) {
if cellPOffset == 0 {
return nil, errors.New("invalid page")
}
previousCellOffset := 0
currentFreeOffset := head.FirstFreeOffset
// 遍历所有cell解析每个cell的信息
for i := 0; i < head.CellCount; i++ {
cellOffset := binary.LittleEndian.Uint32(data[cellPOffset+i*4 : cellPOffset+i*4+4])
nextOffSet := binary.LittleEndian.Uint32(data[cellOffset : cellOffset+4])
cellSize := nextOffSet - cellOffset
cellSize := 0
// cell if from end to start
if i == 0 {
cellSize = BlockFilePageSize - int(cellOffset)
} else {
cellSize = int(cellOffset) - int(previousCellOffset)
}
cells[i] = &Cell{
IsFree: false,
NextFreeOffset: 0,
ActualSize: int(cellSize),
Start: Offset(cellOffset),
}
// 检查当前cell是否为空闲cell
if cellOffset == uint32(currentFreeOffset) {
cells[i].IsFree = true
cells[i].NextFreeOffset = Offset(binary.LittleEndian.Uint32(data[cellOffset+4 : cellOffset+8]))
currentFreeOffset = cells[i].NextFreeOffset
}
previousCellOffset = int(cellOffset)
}
return &Page{
PageHead: head,
Cells: cells,
data: data,
}, nil
}
func (p *Page) Serialize() []byte {
// 写入PageHead
binary.LittleEndian.PutUint64(p.data[0:8], uint64(p.PageId))
p.data[8] = byte(p.Type)
p.data[9] = byte(p.CellCount)
p.data[10] = byte(p.FirstFreeOffset)
// 写入Cell偏移数组
lastCellOffset := p.Cells[p.CellCount-1].Start
cellOffsets := make([]byte, p.CellCount*4)
for i, cell := range p.Cells {
binary.LittleEndian.PutUint32(cellOffsets[i*4:i*4+4], uint32(cell.Start))
}
copy(p.data[int(lastCellOffset)-len(cellOffsets):lastCellOffset], cellOffsets)
return p.data
}
func (p *Page) GetCell(index int) *Cell {
return p.Cells[index]
}
func (p *Page) GetCellData(cell *Cell) []byte {
return p.data[cell.Start : cell.Start+Offset(cell.ActualSize)]
}
func (p *Page) WriteNewCell(data []byte) (*Cell, error) {
}