robt/
vlog.rs

1use mkit::{
2    self,
3    cbor::{FromCbor, IntoCbor},
4    db, Cborize,
5};
6
7use std::{convert::TryFrom, io};
8
9use crate::{util, Error, Result};
10
11const VALUE_VER1: u32 = 0x0001;
12const DELTA_VER1: u32 = 0x0001;
13
14#[derive(Clone, Debug, Eq, PartialEq, Cborize)]
15pub enum Value<V> {
16    N { value: db::Value<V> },
17    R { fpos: u64, length: u64 },
18}
19
20impl<V> Value<V> {
21    const ID: u32 = VALUE_VER1;
22}
23
24impl<V> From<db::Value<V>> for Value<V> {
25    fn from(value: db::Value<V>) -> Value<V> {
26        Value::N { value }
27    }
28}
29
30impl<V> From<Value<V>> for db::Value<V> {
31    fn from(value: Value<V>) -> db::Value<V> {
32        match value {
33            Value::N { value } => value,
34            Value::R { .. } => unreachable!(),
35        }
36    }
37}
38
39impl<V> Value<V> {
40    pub fn into_reference(self, fpos: u64) -> Result<(Self, Vec<u8>)>
41    where
42        V: IntoCbor,
43    {
44        match self {
45            Value::N { value } => {
46                let data = util::into_cbor_bytes(value)?;
47                let length = err_at!(FailConvert, u64::try_from(data.len()))?;
48                Ok((Value::R { fpos, length }, data))
49            }
50            val @ Value::R { .. } => Ok((val, vec![])),
51        }
52    }
53
54    #[allow(unused_imports)]
55    pub fn into_native<F>(self, f: &mut F) -> Result<Self>
56    where
57        F: io::Seek + io::Read,
58        V: FromCbor,
59    {
60        match self {
61            Value::N { .. } => Ok(self),
62            Value::R { fpos, length } => {
63                let seek = io::SeekFrom::Start(fpos);
64                let block = read_file!(f, seek, length, "reading value from vlog")?;
65                let value = util::from_cbor_bytes(&block)?.0;
66                Ok(Value::N { value })
67            }
68        }
69    }
70}
71
72#[derive(Clone, Debug, Eq, PartialEq, Cborize)]
73pub enum Delta<D> {
74    N { delta: db::Delta<D> },
75    R { fpos: u64, length: u64 },
76}
77
78impl<D> Delta<D> {
79    const ID: u32 = DELTA_VER1;
80}
81
82impl<D> From<db::Delta<D>> for Delta<D> {
83    fn from(delta: db::Delta<D>) -> Delta<D> {
84        Delta::N { delta }
85    }
86}
87
88impl<D> From<Delta<D>> for db::Delta<D> {
89    fn from(delta: Delta<D>) -> db::Delta<D> {
90        match delta {
91            Delta::N { delta } => delta,
92            Delta::R { .. } => unreachable!(),
93        }
94    }
95}
96
97impl<D> Delta<D> {
98    pub fn into_reference(self, fpos: u64) -> Result<(Self, Vec<u8>)>
99    where
100        D: IntoCbor,
101    {
102        match self {
103            Delta::N { delta } => {
104                let data = util::into_cbor_bytes(delta)?;
105                let length = err_at!(FailConvert, u64::try_from(data.len()))?;
106                Ok((Delta::R { fpos, length }, data))
107            }
108            val @ Delta::R { .. } => Ok((val, vec![])),
109        }
110    }
111
112    #[allow(unused_imports)]
113    pub fn into_native<F>(self, f: &mut F) -> Result<Self>
114    where
115        F: io::Seek + io::Read,
116        D: FromCbor,
117    {
118        match self {
119            Delta::N { .. } => Ok(self),
120            Delta::R { fpos, length } => {
121                let seek = io::SeekFrom::Start(fpos);
122                let block = read_file!(f, seek, length, "reading delta from vlog")?;
123                let delta = util::from_cbor_bytes(&block)?.0;
124                Ok(Delta::N { delta })
125            }
126        }
127    }
128}
129
130#[cfg(test)]
131#[path = "vlog_test.rs"]
132mod vlog_test;