Files
herolib/lib/vfs/vfs_db/decode.v
2025-03-24 06:44:39 +01:00

147 lines
3.5 KiB
V

module vfs_db
import freeflowuniverse.herolib.data.encoder
import freeflowuniverse.herolib.vfs
// decode_directory decodes a binary format back to Directory
pub fn decode_directory(data []u8) !Directory {
mut d := encoder.decoder_new(data)
version := d.get_u8()!
if version != 1 {
return error('Unsupported version ${version}')
}
type_byte := d.get_u8()!
if type_byte != u8(vfs.FileType.directory) {
return error('Invalid type byte for directory')
}
// Decode metadata
metadata := decode_metadata(mut d)!
// Decode parent_id
parent_id := d.get_u32()!
// Decode children IDs
children_count := int(d.get_u16()!)
mut children := []u32{cap: children_count}
for _ in 0 .. children_count {
children << d.get_u32()!
}
return Directory{
metadata: metadata
parent_id: parent_id
children: children
}
}
// decode_file decodes a binary format back to File (without the actual file data)
// returns file without data and the sequence of keys of chunks of data in data db
pub fn decode_file_metadata(data []u8) !File {
mut d := encoder.decoder_new(data)
version := d.get_u8()!
if version != 1 {
return error('Unsupported version ${version}')
}
type_byte := d.get_u8()!
if type_byte != u8(vfs.FileType.file) {
return error('Invalid type byte for file')
}
// Decode metadata
metadata := decode_metadata(mut d)!
// Decode parent_id
parent_id := d.get_u32()!
mut chunk_ids := []u32{}
if metadata.size == 0 {
blocksize := d.get_u16() or { return error('Failed to get block size ${err}') }
if blocksize != 0 {
return error('File data is empty, expected zero block size')
}
// means there was no data_db ids stored with file, so is empty file
} else {
// Decode data_db block ID's
// if data isn't empty, we expect a blocksize byte
// blocksize is max 2 bytes, so max 4gb entry size
blocksize := d.get_u16()!
for i in 0 .. blocksize {
chunk_ids << d.get_u32() or { return error('Failed to get block id ${err}') }
}
}
return File{
metadata: metadata
parent_id: parent_id
chunk_ids: chunk_ids
}
}
// decode_symlink decodes a binary format back to Symlink
pub fn decode_symlink(data []u8) !Symlink {
mut d := encoder.decoder_new(data)
version := d.get_u8()!
if version != 1 {
return error('Unsupported version ${version}')
}
type_byte := d.get_u8()!
if type_byte != u8(vfs.FileType.symlink) {
return error('Invalid type byte for symlink')
}
// Decode metadata
metadata := decode_metadata(mut d)!
// Decode parent_id
parent_id := d.get_u32()!
// Decode target path
target := d.get_string()!
return Symlink{
metadata: metadata
parent_id: parent_id
target: target
}
}
// decode_metadata decodes the common metadata structure
fn decode_metadata(mut d encoder.Decoder) !vfs.Metadata {
id := d.get_u32()!
name := d.get_string()!
file_type_byte := d.get_u8()!
size := d.get_u64()!
created_at := d.get_i64()!
modified_at := d.get_i64()!
accessed_at := d.get_i64()!
mode := d.get_u32()!
owner := d.get_string()!
group := d.get_string()!
return vfs.Metadata{
id: id
name: name
file_type: unsafe { vfs.FileType(file_type_byte) }
size: size
created_at: created_at
modified_at: modified_at
accessed_at: accessed_at
mode: mode
owner: owner
group: group
}
}
// decode_entry_type decodes the common metadata structure
fn decode_entry_type(data []u8) !vfs.FileType {
if data.len < 2 {
return error('Corrupt metadata bytes')
}
return unsafe { vfs.FileType(data[1]) }
}