sqlite_rs/header/
schema_format.rs

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