sq3_rs/file_header/
schema_format.rs

1use sq3_derive::Name;
2use sq3_parser::TypeName;
3
4use crate::{
5    field_parsing_error,
6    result::{SqliteError, SqliteResult},
7    traits::ParseBytes,
8};
9
10/// # Schema format number (4 Bytes)
11///
12///  The schema format number is a 4-byte big-endian integer at offset 44. The
13/// schema format number is similar to the file format read and write version
14/// numbers at offsets 18 and 19 except that the schema format number refers to
15/// the high-level SQL formatting rather than the low-level b-tree formatting.
16/// Four schema format numbers are currently defined:
17///
18/// - Format 1 is understood by all versions of Sqlite back to version 3.0.0
19///   (2004-06-18).
20///
21/// - Format 2 adds the ability of rows within the same table to have a varying
22///   number of columns, in order to support the ALTER TABLE ... ADD COLUMN
23///   functionality. Support for reading and writing format 2 was added in
24///   Sqlite version 3.1.3 on 2005-02-20.
25///
26/// - Format 3 adds the ability of extra columns added by
27///   ALTER TABLE ... ADD COLUMN to have non-NULL default values. This
28///   capability was added in Sqlite version 3.1.4 on 2005-03-11.
29///
30/// - Format 4 causes Sqlite to respect the DESC keyword on index declarations.
31///   (The DESC keyword is ignored in indexes for formats 1, 2, and 3.) Format 4
32///   also adds two new boolean record type values (serial types 8 and 9).
33///   Support for format 4 was added in Sqlite 3.3.0 on 2006-01-10.
34///
35///  New database files created by Sqlite use format 4 by default. The
36/// legacy_file_format pragma can be used to cause Sqlite to create new database
37/// files using format 1. The format version number can be made to default to 1
38/// instead of 4 by setting SQLITE_DEFAULT_FILE_FORMAT=1 at compile-time.
39#[derive(Debug, Default, Name, PartialEq, Eq)]
40pub enum SchemaFormat {
41    Format1,
42    Format2,
43    Format3,
44    #[default]
45    Format4,
46}
47
48impl TryFrom<u32> for SchemaFormat {
49    type Error = SqliteError;
50
51    fn try_from(value: u32) -> Result<Self, Self::Error> {
52        match value {
53            1 => Ok(Self::Format1),
54            2 => Ok(Self::Format2),
55            3 => Ok(Self::Format3),
56            4 => Ok(Self::Format4),
57            _ => Err(field_parsing_error! {Self::NAME.into()}),
58        }
59    }
60}
61
62impl From<&SchemaFormat> for u32 {
63    fn from(value: &SchemaFormat) -> Self {
64        match value {
65            SchemaFormat::Format1 => 1,
66            SchemaFormat::Format2 => 2,
67            SchemaFormat::Format3 => 3,
68            SchemaFormat::Format4 => 4,
69        }
70    }
71}
72
73impl ParseBytes for SchemaFormat {
74    const LENGTH_BYTES: usize = 4;
75
76    fn parsing_handler(bytes: &[u8]) -> SqliteResult<Self> {
77        let buf: [u8; Self::LENGTH_BYTES] = bytes.try_into()?;
78
79        let value = u32::from_be_bytes(buf);
80
81        value.try_into()
82    }
83}