sq3_rs/file_header/
file_format_version_numbers.rs

1use std::fmt::Display;
2
3use sq3_derive::Name;
4use sq3_parser::TypeName;
5
6use crate::{field_parsing_error, result::SqliteResult, traits::ParseBytes};
7
8/// # File format version numbers (2 Bytes)
9///
10///  The file format write version and file format read version at offsets 18
11/// and 19 are intended to allow for enhancements of the file format in future
12/// versions of Sqlite. In current versions of Sqlite, both of these values
13/// are:
14///   - `1` for rollback journalling modes; and
15///   - `2` for WAL journalling mode.
16///
17///  If a version of Sqlite coded to the current file format specification
18/// encounters a database file where the read version is 1 or 2 but the write
19/// version is greater than 2, then the database file must be treated as
20/// read-only. If a database file with a read version greater than 2 is
21/// encountered, then that database cannot be read or written.
22#[derive(Debug, Default, Name)]
23pub struct FileFormatVersionNumbers {
24    /// File format write version. 1 for legacy; 2 for WAL.
25    write_version: FileFormatWriteVersion,
26    /// File format read version. 1 for legacy; 2 for WAL.
27    read_version: FileFormatReadVersion,
28}
29
30impl FileFormatVersionNumbers {
31    pub fn write_version(&self) -> &FileFormatWriteVersion {
32        &self.write_version
33    }
34
35    pub fn read_version(&self) -> &FileFormatReadVersion {
36        &self.read_version
37    }
38}
39
40impl ParseBytes for FileFormatVersionNumbers {
41    const LENGTH_BYTES: usize = 2;
42
43    fn parsing_handler(bytes: &[u8]) -> SqliteResult<Self> {
44        let write_version = FileFormatWriteVersion::parsing_handler(&[bytes[0]])?;
45        let read_version = FileFormatReadVersion::parsing_handler(&[bytes[1]])?;
46        Ok(Self {
47            write_version,
48            read_version,
49        })
50    }
51}
52
53#[derive(Debug, Default, Name)]
54pub enum FileFormatWriteVersion {
55    #[default]
56    Legacy,
57    /// Write-Ahead Log
58    ///
59    /// Reference: https://www.sqlite.org/wal.html
60    WAL,
61}
62
63impl From<&FileFormatWriteVersion> for u8 {
64    fn from(value: &FileFormatWriteVersion) -> Self {
65        match value {
66            FileFormatWriteVersion::Legacy => 1,
67            FileFormatWriteVersion::WAL => 2,
68        }
69    }
70}
71
72impl ParseBytes for FileFormatWriteVersion {
73    const LENGTH_BYTES: usize = 1;
74
75    fn parsing_handler(bytes: &[u8]) -> SqliteResult<Self> {
76        let one_byte = *bytes
77            .first()
78            .ok_or(field_parsing_error! {Self::NAME.into()})?;
79        match one_byte {
80            1 => Ok(Self::Legacy),
81            2 => Ok(Self::WAL),
82            _ => Err(field_parsing_error! {Self::NAME.into()}),
83        }
84    }
85}
86
87impl Display for FileFormatWriteVersion {
88    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
89        write!(f, "{}", u8::from(self))
90    }
91}
92
93#[derive(Debug, Default, Name)]
94pub enum FileFormatReadVersion {
95    #[default]
96    Legacy,
97    /// Write-Ahead Log
98    ///
99    /// Reference: https://www.sqlite.org/wal.html
100    WAL,
101}
102
103impl From<&FileFormatReadVersion> for u8 {
104    fn from(value: &FileFormatReadVersion) -> Self {
105        match value {
106            FileFormatReadVersion::Legacy => 1,
107            FileFormatReadVersion::WAL => 2,
108        }
109    }
110}
111
112impl ParseBytes for FileFormatReadVersion {
113    const LENGTH_BYTES: usize = 1;
114
115    fn parsing_handler(bytes: &[u8]) -> SqliteResult<Self> {
116        let one_byte = *bytes
117            .first()
118            .ok_or(field_parsing_error! {Self::NAME.into()})?;
119        match one_byte {
120            1 => Ok(Self::Legacy),
121            2 => Ok(Self::WAL),
122            _ => Err(field_parsing_error! {Self::NAME.into()}),
123        }
124    }
125}
126
127impl Display for FileFormatReadVersion {
128    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
129        write!(f, "{}", u8::from(self))
130    }
131}