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