1use crate::{Error, Result, SecretId, SecretPath, VaultId};
2use serde::{Deserialize, Serialize};
3use std::{fmt, str::FromStr};
4
5#[derive(
8 Default, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize,
9)]
10pub struct ExternalFileName(#[serde(with = "hex::serde")] [u8; 32]);
11
12impl fmt::Debug for ExternalFileName {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 f.debug_tuple("ExternalFileName")
15 .field(&hex::encode(self.0))
16 .finish()
17 }
18}
19
20impl From<ExternalFileName> for [u8; 32] {
21 fn from(value: ExternalFileName) -> Self {
22 value.0
23 }
24}
25
26impl AsRef<[u8]> for ExternalFileName {
27 fn as_ref(&self) -> &[u8] {
28 &self.0
29 }
30}
31
32impl From<[u8; 32]> for ExternalFileName {
33 fn from(value: [u8; 32]) -> Self {
34 Self(value)
35 }
36}
37
38impl TryFrom<&[u8]> for ExternalFileName {
39 type Error = Error;
40
41 fn try_from(value: &[u8]) -> Result<Self> {
42 let value: [u8; 32] = value.try_into()?;
43 Ok(value.into())
44 }
45}
46
47impl fmt::Display for ExternalFileName {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 write!(f, "{}", hex::encode(self.0))
50 }
51}
52
53impl FromStr for ExternalFileName {
54 type Err = Error;
55
56 fn from_str(s: &str) -> Result<Self> {
57 let buf: [u8; 32] = hex::decode(s)?.as_slice().try_into()?;
58 Ok(Self(buf))
59 }
60}
61
62#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
64pub struct ExternalFile(SecretPath, ExternalFileName);
65
66impl From<ExternalFile> for (SecretPath, ExternalFileName) {
67 fn from(value: ExternalFile) -> Self {
68 (value.0, value.1)
69 }
70}
71
72impl ExternalFile {
73 pub fn new(path: SecretPath, file_name: ExternalFileName) -> Self {
75 Self(path, file_name)
76 }
77
78 pub fn vault_id(&self) -> &VaultId {
80 &self.0 .0
81 }
82
83 pub fn secret_id(&self) -> &SecretId {
85 &self.0 .1
86 }
87
88 pub fn file_name(&self) -> &ExternalFileName {
90 &self.1
91 }
92}
93
94impl fmt::Display for ExternalFile {
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 write!(
97 f,
98 "{}/{}/{}",
99 self.vault_id(),
100 self.secret_id(),
101 self.file_name()
102 )
103 }
104}
105
106impl FromStr for ExternalFile {
107 type Err = Error;
108
109 fn from_str(s: &str) -> Result<Self> {
110 let mut parts = s.splitn(3, '/');
111 let vault_id = parts
112 .next()
113 .ok_or(Error::InvalidExternalFile(s.to_owned()))?;
114 let secret_id = parts
115 .next()
116 .ok_or(Error::InvalidExternalFile(s.to_owned()))?;
117 let file_name = parts
118 .next()
119 .ok_or(Error::InvalidExternalFile(s.to_owned()))?;
120 let vault_id: VaultId = vault_id.parse()?;
121 let secret_id: SecretId = secret_id.parse()?;
122 let file_name: ExternalFileName = file_name.parse()?;
123 Ok(Self(SecretPath(vault_id, secret_id), file_name))
124 }
125}