Skip to main content

fjall_cli/command/keyspace_command/
get_command.rs

1use crate::{ByteEncoding, ByteEncodingDecodeError, PrefixKind, Suffix};
2use errgonomic::{handle, handle_bool, handle_opt};
3use fjall::{Database, KeyspaceCreateOptions};
4use std::io;
5use std::io::Write;
6use std::process::ExitCode;
7use thiserror::Error;
8
9#[derive(clap::Parser, Clone, Debug)]
10pub struct GetCommand {
11    #[arg(value_name = "KEY")]
12    key: String,
13
14    #[arg(long, value_enum, default_value_t = ByteEncoding::String)]
15    key_encoding: ByteEncoding,
16
17    #[arg(long, value_enum)]
18    value_prefix: Option<PrefixKind>,
19
20    #[arg(long)]
21    value_suffix: Option<Suffix>,
22}
23
24impl GetCommand {
25    pub async fn run(self, db: &Database, keyspace: impl Into<String>) -> Result<ExitCode, GetCommandRunError> {
26        use GetCommandRunError::*;
27        let keyspace = keyspace.into();
28        let Self {
29            key,
30            key_encoding,
31            value_prefix,
32            value_suffix,
33        } = self;
34        let key_bytes = handle!(key_encoding.decode(&key), DecodeKeyBytesFailed, key, key_encoding);
35        handle_bool!(!db.keyspace_exists(&keyspace), KeyspaceNotFound, keyspace);
36        let keyspace_handle = handle!(db.keyspace(&keyspace, KeyspaceCreateOptions::default), KeyspaceFailed, keyspace);
37        let value_opt = handle!(keyspace_handle.get(&key_bytes), GetFailed, keyspace, key);
38        let value = handle_opt!(value_opt, KeyNotFound, keyspace, key);
39        let mut stdout = io::stdout().lock();
40        if let Some(prefix) = value_prefix {
41            let bytes = prefix.write(&value);
42            handle!(stdout.write_all(&bytes), WriteAllFailed);
43        }
44        handle!(stdout.write_all(value.as_ref()), WriteAllFailed);
45        if let Some(suffix) = value_suffix {
46            handle!(stdout.write_all(suffix.as_bytes()), WriteAllFailed);
47        }
48        Ok(ExitCode::SUCCESS)
49    }
50}
51
52#[derive(Error, Debug)]
53pub enum GetCommandRunError {
54    #[error("failed to decode key '{key}' with encoding '{key_encoding}'")]
55    DecodeKeyBytesFailed { source: ByteEncodingDecodeError, key: String, key_encoding: ByteEncoding },
56
57    #[error("keyspace '{keyspace}' not found")]
58    KeyspaceNotFound { keyspace: String },
59
60    #[error("failed to open keyspace '{keyspace}'")]
61    KeyspaceFailed { source: fjall::Error, keyspace: String },
62
63    #[error("failed to get key '{key}' from keyspace '{keyspace}'")]
64    GetFailed { source: fjall::Error, keyspace: String, key: String },
65
66    #[error("key '{key}' not found in keyspace '{keyspace}'")]
67    KeyNotFound { keyspace: String, key: String },
68
69    #[error("failed to write value to stdout")]
70    WriteAllFailed { source: io::Error },
71}