ultimate_common/model/sensitive/
sensitive_string.rs1use core::{fmt, ops::Deref};
2
3use serde::{de::Visitor, Deserialize, Serialize};
4
5use crate::string;
6
7use super::{AsUnderlying, ToSensitive};
8
9#[derive(Clone)]
11pub struct SensitiveString {
12 underlying: String,
13 sensitive_len: usize,
14 c: char,
15}
16
17impl SensitiveString {
18 pub fn new(underlying: impl Into<String>, sensitive_len: usize, c: char) -> Self {
51 Self { underlying: underlying.into(), sensitive_len, c }
52 }
53
54 pub fn sensitive_len(&self) -> usize {
55 self.sensitive_len
56 }
57
58 pub fn c(&self) -> char {
59 self.c
60 }
61}
62
63impl fmt::Debug for SensitiveString {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 f.debug_tuple("SensitiveString").field(&self.to_sensitive()).finish()
66 }
67}
68
69impl fmt::Display for SensitiveString {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 f.write_str(&self.to_sensitive())
72 }
73}
74
75impl Deref for SensitiveString {
76 type Target = str;
77
78 fn deref(&self) -> &Self::Target {
79 &self.underlying
80 }
81}
82
83impl AsRef<str> for SensitiveString {
84 fn as_ref(&self) -> &str {
85 &self.underlying
86 }
87}
88
89impl ToSensitive for SensitiveString {
90 fn to_sensitive(&self) -> String {
91 let v = self.deref();
92 if v.len() < self.sensitive_len() {
93 return string::repeat_char(self.c(), v.len());
94 }
95
96 let sensitive_start = v.len() / 2 - self.sensitive_len() / 2;
97 let mut s = String::with_capacity(v.len());
98 s.push_str(&v[0..sensitive_start]);
99 for _ in 0..self.sensitive_len() {
100 s.push(self.c);
101 }
102 s.push_str(&v[(self.sensitive_len() + sensitive_start)..v.len()]);
103 s
104 }
105}
106
107impl AsUnderlying for SensitiveString {
108 fn as_underlying(&self) -> &str {
109 &self.underlying
110 }
111}
112
113impl Serialize for SensitiveString {
114 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
115 where
116 S: serde::Serializer,
117 {
118 serializer.serialize_str(&self.to_sensitive())
119 }
120}
121
122impl<'de> Deserialize<'de> for SensitiveString {
123 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
124 where
125 D: serde::Deserializer<'de>,
126 {
127 struct SensitiveStringVisitor;
128 impl<'de> Visitor<'de> for SensitiveStringVisitor {
129 type Value = SensitiveString;
130
131 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
132 formatter.write_str("Unsupport type, need string.")
133 }
134
135 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
136 where
137 E: serde::de::Error,
138 {
139 let sensitive_len = v.len() / 2;
140 Ok(SensitiveString::new(v, sensitive_len, '*'))
141 }
142
143 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
144 where
145 E: serde::de::Error,
146 {
147 let sensitive_len = v.len() / 2;
148 Ok(SensitiveString::new(v, sensitive_len, '*'))
149 }
150 }
151 deserializer.deserialize_string(SensitiveStringVisitor)
152 }
153}