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
use anyhow::bail;

use crate::result::SQLiteError;

///  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: MaximumEmbeddedPayloadFraction,
    minimum: MinimumEmbeddedPayloadFraction,
    leaf: LeafPayloadFraction,
}

impl<'a> TryFrom<&'a [u8]> for PayloadFractions {
    type Error = SQLiteError;

    fn try_from(payload: &'a [u8]) -> Result<Self, Self::Error> {
        const VALID_SIZE: usize = 3;

        if payload.len() != VALID_SIZE {
            bail!("Invalid size for PayloadFractions");
        }
        let maximum = MaximumEmbeddedPayloadFraction::try_from(payload[0])?;
        let minimum = MinimumEmbeddedPayloadFraction::try_from(payload[1])?;
        let leaf = LeafPayloadFraction::try_from(payload[2])?;
        Ok(Self {
            maximum,
            minimum,
            leaf,
        })
    }
}

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

impl TryFrom<u8> for MaximumEmbeddedPayloadFraction {
    type Error = SQLiteError;

    fn try_from(maximum: u8) -> Result<Self, Self::Error> {
        if maximum == 64 {
            Ok(Self(maximum))
        } else {
            bail!("Maximum embedded payload fraction. Must be 64.")
        }
    }
}

/// Minimum embedded payload fraction. Must be 32.
#[derive(Debug)]
pub struct MinimumEmbeddedPayloadFraction(u8);
impl TryFrom<u8> for MinimumEmbeddedPayloadFraction {
    type Error = SQLiteError;

    fn try_from(minimum: u8) -> Result<Self, Self::Error> {
        if minimum == 32 {
            Ok(Self(minimum))
        } else {
            bail!("Minimum embedded payload fraction. Must be 32.")
        }
    }
}

/// Leaf payload fraction. Must be 32.
#[derive(Debug)]
pub struct LeafPayloadFraction(u8);
impl TryFrom<u8> for LeafPayloadFraction {
    type Error = SQLiteError;

    fn try_from(leaf: u8) -> Result<Self, Self::Error> {
        if leaf == 32 {
            Ok(Self(leaf))
        } else {
            bail!("Leaf payload fraction. Must be 32.")
        }
    }
}