sq3_rs/file_header/
database_text_encoding.rs

1use std::fmt::Display;
2
3use sq3_derive::Name;
4use sq3_parser::TypeName;
5
6use crate::{
7    field_parsing_error,
8    result::{SqliteError, SqliteResult},
9    traits::ParseBytes,
10};
11
12/// # Text encoding (4 Bytes)
13///
14///  The 4-byte big-endian integer at offset 56 determines the encoding used for
15/// all text strings stored in the database. A value of 1 means UTF-8. A value
16/// of 2 means UTF-16le. A value of 3 means UTF-16be. No other values are
17/// allowed. The sqlite3.h header file defines C-preprocessor macros
18/// SQLITE_UTF8 as 1, SQLITE_UTF16LE as 2, and SQLITE_UTF16BE as 3, to use in
19/// place of the numeric codes for the text encoding.
20#[derive(Debug, Default, Name)]
21pub enum DatabaseTextEncoding {
22    #[default]
23    Utf8,
24    Utf16Le,
25    Utf16Be,
26}
27
28impl From<&DatabaseTextEncoding> for u32 {
29    fn from(value: &DatabaseTextEncoding) -> Self {
30        match value {
31            DatabaseTextEncoding::Utf8 => 1,
32            DatabaseTextEncoding::Utf16Le => 2,
33            DatabaseTextEncoding::Utf16Be => 3,
34        }
35    }
36}
37
38impl TryFrom<u32> for DatabaseTextEncoding {
39    type Error = SqliteError;
40
41    fn try_from(value: u32) -> Result<Self, Self::Error> {
42        match value {
43            1 => Ok(Self::Utf8),
44            2 => Ok(Self::Utf16Le),
45            3 => Ok(Self::Utf16Be),
46            _ => Err(field_parsing_error! {Self::NAME.into()}),
47        }
48    }
49}
50
51impl Display for DatabaseTextEncoding {
52    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
53        let number = u32::from(self);
54        let name = match self {
55            DatabaseTextEncoding::Utf8 => "utf8",
56            DatabaseTextEncoding::Utf16Le => "utf16le",
57            DatabaseTextEncoding::Utf16Be => "utf16le",
58        };
59        write!(f, "{number} ({name})")
60    }
61}
62
63impl ParseBytes for DatabaseTextEncoding {
64    const LENGTH_BYTES: usize = 4;
65
66    fn parsing_handler(bytes: &[u8]) -> SqliteResult<Self> {
67        let buf: [u8; Self::LENGTH_BYTES] = bytes.try_into()?;
68
69        let value = u32::from_be_bytes(buf);
70
71        value.try_into()
72    }
73}