qubit_redact/facade/redacted_text.rs
1// =============================================================================
2// Copyright (c) 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Final text produced by one redaction operation.
9
10use std::borrow::Cow;
11use std::fmt;
12
13/// Final UTF-8 text produced by a redaction operation under its selected
14/// policy.
15///
16/// The value has crossed the runtime's plain-text presentation boundary. It is
17/// owned and can be rendered with [`std::fmt::Display`] without running another
18/// redaction pass. This guarantee is policy-relative: a disabled policy or an
19/// explicitly unredacted writer operation may deliberately preserve source
20/// content. Callers must not treat this type as proof that the text is
21/// confidential in every policy configuration. Any additional length
22/// restriction belongs to the caller's final logging or presentation sink.
23///
24/// # Examples
25///
26/// ```
27/// use qubit_redact::Redactor;
28///
29/// let output = Redactor::strict().redact_field("password", "raw-secret");
30/// assert_eq!(output.text().as_str(), "<redacted>");
31/// ```
32#[derive(Debug, Clone, PartialEq, Eq, Hash)]
33pub struct RedactedText(
34 /// Owned text that has already crossed the redaction safety boundary.
35 String,
36);
37
38impl RedactedText {
39 /// Creates final text from an already escaped representation.
40 #[must_use]
41 #[inline]
42 pub(crate) fn from_escaped(value: impl Into<Cow<'static, str>>) -> Self {
43 Self(value.into().into_owned())
44 }
45
46 /// Borrows the final redacted text.
47 #[must_use]
48 #[inline(always)]
49 pub fn as_str(&self) -> &str {
50 &self.0
51 }
52
53 /// Consumes the wrapper and returns its owned text.
54 #[must_use]
55 #[inline]
56 pub fn into_string(self) -> String {
57 self.0
58 }
59}
60
61impl AsRef<str> for RedactedText {
62 /// Borrows the safe text through the standard string-reference contract.
63 #[inline(always)]
64 fn as_ref(&self) -> &str {
65 self.as_str()
66 }
67}
68
69impl fmt::Display for RedactedText {
70 /// Writes only the finalized safe text to the destination formatter.
71 #[inline(always)]
72 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
73 formatter.write_str(self.as_str())
74 }
75}