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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use crate::result::SQLiteError;
use alloc::format;
use super::ParseBytes;

/// # Payload Fractions (3 Bytes)
///  The maximum and minimum embedded payload fractions and the leaf payload
/// fraction values must be 64, 32, and 32. These values were originally
/// intended to be tunable parameters that could be used to modify the storage
/// format of the b-tree algorithm. However, that functionality is not
/// supported and there are no current plans to add support in the future.
/// Hence, these three bytes are fixed at the values specified.
#[derive(Debug)]
pub struct PayloadFractions {
  /// Maximum embedded payload fraction. Must be 64.
  maximum: MaximumEmbeddedPayloadFraction,
  /// Minimum embedded payload fraction. Must be 32.
  minimum: MinimumEmbeddedPayloadFraction,
  /// Leaf payload fraction. Must be 32.
  leaf: LeafPayloadFraction,
}

impl PayloadFractions {
  pub fn maximum(&self) -> &MaximumEmbeddedPayloadFraction {
    &self.maximum
  }

  pub fn minimum(&self) -> &MinimumEmbeddedPayloadFraction {
    &self.minimum
  }

  pub fn leaf(&self) -> &LeafPayloadFraction {
    &self.leaf
  }
}

impl ParseBytes<&[u8]> for PayloadFractions {
  fn struct_name() -> &'static str {
    "PayloadFractions"
  }

  fn bytes_length() -> usize {
    3
  }

  fn parsing_handler(bytes: &[u8]) -> crate::result::SQLiteResult<Self> {
    let maximum = MaximumEmbeddedPayloadFraction::parse_bytes(&[bytes[0]])?;
    let minimum = MinimumEmbeddedPayloadFraction::parse_bytes(&[bytes[1]])?;
    let leaf = LeafPayloadFraction::parse_bytes(&[bytes[2]])?;
    Ok(Self {
      maximum,
      minimum,
      leaf,
    })
  }
}

/// Maximum embedded payload fraction. Must be 64.
#[derive(Debug)]
pub struct MaximumEmbeddedPayloadFraction(u8);

impl MaximumEmbeddedPayloadFraction {
  pub fn get(&self) -> u8 {
    self.0
  }
}

impl ParseBytes<&[u8]> for MaximumEmbeddedPayloadFraction {
  fn struct_name() -> &'static str {
    "MaximumEmbeddedPayloadFraction"
  }

  fn bytes_length() -> usize {
    1
  }

  fn parsing_handler(bytes: &[u8]) -> crate::result::SQLiteResult<Self> {
    let maximum = *bytes.get(0).ok_or(SQLiteError::Custom(format!(
      "Impossible state on parsing {}",
      Self::struct_name()
    )))?;
    if maximum == 64 {
      Ok(Self(maximum))
    } else {
      return Err(SQLiteError::msg(
        "Maximum embedded payload fraction. Must be 64.",
      ));
    }
  }
}

/// Minimum embedded payload fraction. Must be 32.
#[derive(Debug)]
pub struct MinimumEmbeddedPayloadFraction(u8);

impl MinimumEmbeddedPayloadFraction {
  pub fn get(&self) -> u8 {
    self.0
  }
}

impl ParseBytes<&[u8]> for MinimumEmbeddedPayloadFraction {
  fn struct_name() -> &'static str {
    "MinimumEmbeddedPayloadFraction"
  }

  fn bytes_length() -> usize {
    1
  }

  fn parsing_handler(bytes: &[u8]) -> crate::result::SQLiteResult<Self> {
    let minimum = *bytes.get(0).ok_or(SQLiteError::Custom(format!(
      "Impossible state on parsing {}",
      Self::struct_name()
    )))?;
    if minimum == 32 {
      Ok(Self(minimum))
    } else {
      return Err(SQLiteError::msg(
        "Minimum embedded payload fraction. Must be 32.",
      ));
    }
  }
}

/// Leaf payload fraction. Must be 32.
#[derive(Debug)]
pub struct LeafPayloadFraction(u8);

impl LeafPayloadFraction {
  pub fn get(&self) -> u8 {
    self.0
  }
}

impl ParseBytes<&[u8]> for LeafPayloadFraction {
  fn struct_name() -> &'static str {
    "LeafPayloadFraction"
  }

  fn bytes_length() -> usize {
    1
  }

  fn parsing_handler(bytes: &[u8]) -> crate::result::SQLiteResult<Self> {
    let leaf = *bytes.get(0).ok_or(SQLiteError::Custom(format!(
      "Impossible state on parsing {}",
      Self::struct_name()
    )))?;
    if leaf == 32 {
      Ok(Self(leaf))
    } else {
      Err(SQLiteError::msg("Leaf payload fraction. Must be 32."))
    }
  }
}