fjall_cli/types/
byte_encoding.rs1use errgonomic::{handle, handle_bool};
2use std::fs;
3use std::io;
4use std::path::PathBuf;
5use thiserror::Error;
6
7#[derive(clap::ValueEnum, Copy, Clone, Debug, Default, strum::Display)]
8#[clap(rename_all = "kebab")]
9#[strum(serialize_all = "kebab-case")]
10pub enum ByteEncoding {
11 Empty,
12 #[default]
13 String,
14 Hex,
15 Path,
16}
17
18impl ByteEncoding {
19 pub fn decode(&self, input: &str) -> Result<Vec<u8>, ByteEncodingDecodeError> {
20 use ByteEncoding::*;
21 use ByteEncodingDecodeError::*;
22 match self {
23 Empty => {
24 handle_bool!(input != "-", EmptyEncodingInvalid, input: input.to_owned());
25 Ok(Vec::new())
26 }
27 String => Ok(input.as_bytes().to_vec()),
28 Hex => Self::decode_hex(input),
29 Path => Self::decode_path(input),
30 }
31 }
32
33 pub fn decode_hex(input: &str) -> Result<Vec<u8>, ByteEncodingDecodeError> {
34 use ByteEncodingDecodeError::*;
35 let input = input.to_owned();
36 let bytes = handle!(hex::decode(&input), HexDecodeFailed, input);
37 Ok(bytes)
38 }
39
40 pub fn decode_path(input: &str) -> Result<Vec<u8>, ByteEncodingDecodeError> {
41 use ByteEncodingDecodeError::*;
42 let path = PathBuf::from(input);
43 let metadata = handle!(fs::metadata(&path), MetadataFailed, path);
44 handle_bool!(metadata.is_dir(), PathIsDirectory, path);
45 let bytes = handle!(fs::read(&path), ReadFailed, path);
46 Ok(bytes)
47 }
48}
49
50#[derive(Error, Debug)]
51pub enum ByteEncodingDecodeError {
52 #[error("empty encoding expects '-' but got '{input}'")]
53 EmptyEncodingInvalid { input: String },
54
55 #[error("failed to decode hex input '{input}'")]
56 HexDecodeFailed { source: hex::FromHexError, input: String },
57
58 #[error("failed to read metadata for path '{path}'")]
59 MetadataFailed { source: io::Error, path: PathBuf },
60
61 #[error("path '{path}' is a directory")]
62 PathIsDirectory { path: PathBuf },
63
64 #[error("failed to read bytes from path '{path}'")]
65 ReadFailed { source: io::Error, path: PathBuf },
66}