spatial-db/storage/unity_file.go

94 lines
1.8 KiB
Go
Raw Normal View History

2023-12-11 01:33:39 -08:00
package storage
import (
"bytes"
"encoding/json"
"os"
"git.nicholasnovak.io/nnovak/spatial-db/world"
)
// A `UnityFile` is a collection of chunks, stored as a single file on disk
//
// This is done because with worlds that span millions of chunks, the speed to
// access individual files slows down
type UnityFile struct {
fd *os.File
fileSize int
// metadata maps the position of a chunk to its start index within the file
metadata map[world.ChunkPos]int
}
func CreateUnityFile(fileName string) (UnityFile, error) {
var u UnityFile
f, err := os.Create(fileName)
if err != nil {
return u, err
}
u.fd = f
u.metadata = make(map[world.ChunkPos]int)
return u, nil
}
func (u UnityFile) Size() int {
return u.fileSize
}
func (u *UnityFile) WriteChunk(data world.ChunkData) error {
var encoded bytes.Buffer
// Encode the chunk first
if err := json.NewEncoder(&encoded).Encode(data); err != nil {
return err
}
encodedSize := encoded.Len()
// Go to the end of the file
u.fd.Seek(0, u.fileSize)
// Write the encoded contents to the file
if _, err := u.fd.Write(encoded.Bytes()); err != nil {
return err
}
// Update the metadata with the new file
u.metadata[data.Pos] = u.fileSize
u.fileSize += encodedSize
return nil
}
func (u UnityFile) WriteMetadataFile(fileName string) error {
fd, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return err
}
defer fd.Close()
if err := json.NewEncoder(fd).Encode(&u.metadata); err != nil {
return err
}
return nil
}
func (u *UnityFile) ReadMetadataFile(fileName string) error {
fd, err := os.Open(fileName)
if err != nil {
return err
}
if err := json.NewDecoder(fd).Decode(&u.metadata); err != nil {
return err
}
return nil
}
func (u UnityFile) ReadChunk() world.ChunkData {
return world.ChunkData{}
}