#![no_std]
#[cfg(feature = "diesel_sql")]
extern crate diesel;
#[macro_use]
#[cfg(feature = "std")]
extern crate std;
#[cfg(any(feature = "serialize", feature = "deserialize"))]
extern crate serde;
#[cfg(test)]
mod tests;
use core::fmt;
use core::hash::{Hash, Hasher};
#[cfg(feature = "ord")]
use core::cmp::Ordering;
#[cfg(feature = "diesel_sql")]
use std::io::Write;
#[cfg(feature = "std")]
use std::string::String;
#[cfg(feature = "serialize")]
use serde::Serializer;
#[cfg(feature = "deserialize")]
use serde::Deserializer;
pub struct Secret<T>(T);
#[cfg(feature = "std")]
impl Secret<String> {
#[inline]
pub fn as_str(&self) -> Secret<&str> {
Secret(self.0.as_str())
}
#[inline]
pub fn reveal_str(&self) -> &str {
self.0.as_str()
}
}
impl<T> Secret<T> {
#[inline]
pub fn new(val: T) -> Secret<T> {
Secret(val)
}
#[inline]
pub fn as_ref(&self) -> Secret<&T> {
Secret(&self.0)
}
#[inline]
pub fn as_mut(&mut self) -> Secret<&mut T> {
Secret(&mut self.0)
}
#[inline]
pub fn reveal(&self) -> &T {
&self.0
}
#[inline]
pub fn reveal_into(self) -> T {
self.0
}
#[inline]
pub fn map_revealed<V, F: FnOnce(T) -> V>(self, f: F) -> Secret<V> {
Secret(f(self.0))
}
}
impl<T> fmt::Debug for Secret<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "...")
}
}
impl<T: fmt::Display> fmt::Display for Secret<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "...")
}
}
impl<T: Clone> Clone for Secret<T> {
#[inline]
fn clone(&self) -> Self {
Secret(self.0.clone())
}
}
impl<T: PartialEq> PartialEq for Secret<T> {
#[inline]
fn eq(&self, other: &Secret<T>) -> bool {
self.0.eq(&other.0)
}
}
#[cfg(feature = "ord")]
impl<T: PartialOrd> PartialOrd for Secret<T> {
#[inline]
fn partial_cmp(&self, other: &Secret<T>) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
}
#[cfg(feature = "ord")]
impl<T: Ord> Ord for Secret<T> {
#[inline]
fn cmp(&self, other: &Secret<T>) -> Ordering {
self.0.cmp(&other.0)
}
}
impl<T: Hash> Hash for Secret<T> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl<T: Default> Default for Secret<T> {
#[inline]
fn default() -> Secret<T> {
Secret(T::default())
}
}
impl<T: Copy> Copy for Secret<T> {}
impl<T: Eq> Eq for Secret<T> {}
unsafe impl<T: Sync> Sync for Secret<T> {}
unsafe impl<T: Send> Send for Secret<T> {}
impl<T> From<T> for Secret<T> {
#[inline]
fn from(v: T) -> Secret<T> {
Secret(v)
}
}
#[cfg(feature = "serialize")]
impl<T: serde::Serialize> serde::Serialize for Secret<T> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}
#[cfg(feature = "deserialize")]
use serde::de::Error;
#[cfg(feature = "deserialize")]
impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for Secret<T> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
match T::deserialize(deserializer).map(Secret) {
Err(_) => Err(D::Error::custom(
"a confidential value could not be deserialized",
)),
Ok(v) => Ok(v),
}
}
}
#[cfg(all(feature = "diesel_sql", feature = "std"))]
impl<A, DB, T> diesel::types::ToSql<A, DB> for Secret<T>
where
T: diesel::types::ToSql<A, DB> + fmt::Debug,
DB: diesel::backend::Backend + diesel::types::HasSqlType<A>,
{
#[inline]
fn to_sql<W: Write>(
&self,
out: &mut diesel::serialize::Output<W, DB>,
) -> Result<diesel::types::IsNull, std::boxed::Box<dyn std::error::Error + Send + Sync>> {
self.0.to_sql(out)
}
}
#[cfg(all(feature = "diesel_sql", feature = "std"))]
impl<'a, E, T> diesel::expression::AsExpression<E> for &'a Secret<T>
where
T: diesel::expression::AsExpression<E>,
&'a T: diesel::expression::AsExpression<E>,
{
type Expression = <&'a T as diesel::expression::AsExpression<E>>::Expression;
#[inline]
fn as_expression(self) -> Self::Expression {
(&self.0).as_expression()
}
}
#[cfg(all(feature = "diesel_sql", feature = "std"))]
impl<T, ST, DB> diesel::query_source::Queryable<ST, DB> for Secret<T>
where
DB: diesel::backend::Backend + diesel::types::HasSqlType<ST>,
T: diesel::query_source::Queryable<ST, DB>,
{
type Row = T::Row;
#[inline]
fn build(row: Self::Row) -> Self {
Secret(T::build(row))
}
}