shared/capabilities/
persistent_storage.rs

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
use serde::{Deserialize, Serialize};

use crux_core::capability::CapabilityContext;
use crux_core::capability::Operation;
use crux_core::Command;
use crux_macros::Capability;

use std::future::Future;

#[derive(Capability)]
pub struct PersistentStorage<Ev> {
    context: CapabilityContext<PersistentStorageOperation, Ev>,
}

/// Public API of the capability, called by App::update.
impl<Ev> PersistentStorage<Ev>
where
    Ev: 'static,
{
    pub fn new(context: CapabilityContext<PersistentStorageOperation, Ev>) -> Self {
        Self { context }
    }
}

pub type Data = String;
type Filename = String;
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
pub enum PersistentStorageOperation {
    Save(Filename, Data),
    AppendOrCreate(Filename, Data),
    Load(Filename),
}

impl Operation for PersistentStorageOperation {
    type Output = PersistentStorageOutput;
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub enum PersistentStorageOutput {
    FileData(String),
    SaveOk,
    AppendOk,
    Error,
    LoadErrorFileDoesntExist, // Failed to load as file doesn't exist
}

/// Instructs shell code to append to an existing file or create a new one if it doesn't exist
pub fn append_or_create_command<Effect, Event>(
    file_name: Filename,
    data: Data,
) -> crux_core::command::RequestBuilder<
    Effect,
    Event,
    impl Future<Output = <PersistentStorageOperation as Operation>::Output>,
>
where
    Effect: From<crate::Request<PersistentStorageOperation>> + Send + 'static,
    Event: Send + 'static,
{
    let request = PersistentStorageOperation::AppendOrCreate(file_name, data);
    Command::request_from_shell(request)
}

pub fn load<Effect, Event>(
    file_name: Filename,
) -> crux_core::command::RequestBuilder<
    Effect,
    Event,
    impl Future<Output = <PersistentStorageOperation as Operation>::Output>,
>
where
    Effect: From<crate::Request<PersistentStorageOperation>> + Send + 'static,
    Event: Send + 'static,
{
    let request = PersistentStorageOperation::Load(file_name);
    Command::request_from_shell(request)
}

pub fn save<Effect, Event>(
    file_name: Filename,
    data: Data,
) -> crux_core::command::RequestBuilder<
    Effect,
    Event,
    impl Future<Output = <PersistentStorageOperation as Operation>::Output>,
>
where
    Effect: From<crate::Request<PersistentStorageOperation>> + Send + 'static,
    Event: Send + 'static,
{
    let request = PersistentStorageOperation::Save(file_name, data);
    Command::request_from_shell(request)
}