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;