1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use alloc::boxed::Box;

use layout::{collections::raw::RawBytes, layout, Decode, Encode, Fixed};

#[derive(Debug, Clone, Copy)]
pub enum FATEntry {
    Block(u64),
    Reserved,
    None,
}

impl FATEntry {
    pub fn unwrap(self) -> Option<u64> {
        match self {
            FATEntry::Block(b) => Some(b),
            FATEntry::None => None,
            FATEntry::Reserved => panic!("Attempted to unwrap reserved FAT entry"),
        }
    }
}

impl Fixed for FATEntry {
    fn size() -> u64 {
        u64::size()
    }
}

impl Encode for FATEntry {
    fn encode<W: layout::Write + layout::Seek + layout::IO>(
        &self,
        writer: &mut W,
    ) -> Result<(), W::Error> {
        match self {
            FATEntry::Block(b) => b.encode(writer),
            FATEntry::Reserved => (u64::max_value() - 1).encode(writer),
            FATEntry::None => u64::max_value().encode(writer),
        }
    }
}

impl Decode for FATEntry {
    fn decode<R: layout::Read + layout::Seek + layout::IO>(
        reader: &mut R,
    ) -> Result<Self, R::Error> {
        u64::decode(reader).map(|b| {
            if b == u64::max_value() {
                FATEntry::None
            } else if b == u64::max_value() - 1 {
                FATEntry::Reserved
            } else {
                FATEntry::Block(b)
            }
        })
    }
}

#[layout]
#[derive(Debug, Clone)]
pub struct Superblock {
    pub magic: u64,

    pub block_size: u32,
    pub block_count: u64,
}

#[layout]
#[derive(Debug)]
pub struct FileSystem {
    #[sublayout]
    pub super_block: Superblock,

    #[dynamic]
    pub fat: Box<[FATEntry]>,

    #[sublayout]
    pub super_block_cp: Superblock,

    #[dynamic]
    pub obj_lookup: Box<[FATEntry]>,

    #[sublayout]
    pub rest: RawBytes,
}

pub type ObjLookupBucket = Box<[ONode]>;

#[layout]
#[derive(Debug)]
pub struct ONode {
    pub object_id: u128,
    pub size: u64,

    pub first_block: u64,
    pub reserved: [u64; 4],
}