greentic_operator/
secret_value.rs1use std::{borrow::Cow, fmt};
2
3#[derive(Clone)]
4pub struct SecretValue<'a> {
5 inner: Cow<'a, [u8]>,
6}
7
8impl<'a> SecretValue<'a> {
9 pub fn new(value: &'a [u8]) -> Self {
10 Self {
11 inner: Cow::Borrowed(value),
12 }
13 }
14
15 pub fn owned(value: Vec<u8>) -> SecretValue<'static> {
16 SecretValue {
17 inner: Cow::Owned(value),
18 }
19 }
20
21 pub fn as_bytes(&self) -> &[u8] {
22 &self.inner
23 }
24
25 pub fn len(&self) -> usize {
26 self.inner.len()
27 }
28
29 pub fn is_empty(&self) -> bool {
30 self.inner.is_empty()
31 }
32}
33
34impl<'a> From<&'a [u8]> for SecretValue<'a> {
35 fn from(value: &'a [u8]) -> Self {
36 Self::new(value)
37 }
38}
39
40impl From<Vec<u8>> for SecretValue<'static> {
41 fn from(value: Vec<u8>) -> Self {
42 Self::owned(value)
43 }
44}
45
46impl fmt::Display for SecretValue<'_> {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 f.write_str("[REDACTED]")
49 }
50}
51
52impl fmt::Debug for SecretValue<'_> {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 f.write_str("[REDACTED]")
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::SecretValue;
61
62 #[test]
63 fn debug_and_display_are_redacted() {
64 let value = SecretValue::new(b"super-secret");
65 assert_eq!(format!("{value}"), "[REDACTED]");
66 assert_eq!(format!("{value:?}"), "[REDACTED]");
67 }
68}