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
use core::ops::Deref;

use crate::traits::{Name, ParseBytes};
use crate::{
  field_parsing_error, impl_name,
  result::{SQLiteError, SQLiteResult},
};

/// # 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, PartialEq, Eq)]
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_name! {PayloadFractions}

impl ParseBytes for PayloadFractions {
  const LENGTH_BYTES: usize = 3;

  fn parsing_handler(bytes: &[u8]) -> 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, PartialEq, Eq)]
pub struct MaximumEmbeddedPayloadFraction(u8);

impl Deref for MaximumEmbeddedPayloadFraction {
  type Target = u8;

  fn deref(&self) -> &Self::Target {
    &self.0
  }
}

impl_name! {MaximumEmbeddedPayloadFraction}

impl ParseBytes for MaximumEmbeddedPayloadFraction {
  const LENGTH_BYTES: usize = 1;

  fn parsing_handler(bytes: &[u8]) -> SQLiteResult<Self> {
    let maximum = *bytes.first().ok_or(field_parsing_error! {Self::NAME})?;
    if maximum == 64 {
      Ok(Self(maximum))
    } else {
      Err(SQLiteError::Custom(
        "MaximumEmbeddedPayloadFraction must be 64.",
      ))
    }
  }
}

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

impl Deref for MinimumEmbeddedPayloadFraction {
  type Target = u8;

  fn deref(&self) -> &Self::Target {
    &self.0
  }
}

impl_name! {MinimumEmbeddedPayloadFraction}

impl ParseBytes for MinimumEmbeddedPayloadFraction {
  const LENGTH_BYTES: usize = 1;

  fn parsing_handler(bytes: &[u8]) -> SQLiteResult<Self> {
    let minimum = *bytes.first().ok_or(field_parsing_error! {Self::NAME})?;
    if minimum == 32 {
      Ok(Self(minimum))
    } else {
      Err(SQLiteError::Custom(
        "MinimumEmbeddedPayloadFraction must be 32.",
      ))
    }
  }
}

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

impl Deref for LeafPayloadFraction {
  type Target = u8;

  fn deref(&self) -> &Self::Target {
    &self.0
  }
}

impl_name! {LeafPayloadFraction}

impl ParseBytes for LeafPayloadFraction {
  const LENGTH_BYTES: usize = 1;

  fn parsing_handler(bytes: &[u8]) -> SQLiteResult<Self> {
    let leaf = *bytes.first().ok_or(field_parsing_error! {Self::NAME})?;
    if leaf == 32 {
      Ok(Self(leaf))
    } else {
      Err(SQLiteError::Custom("LeafPayloadFraction must be 32."))
    }
  }
}