Skip to content

Commit 7b8b309

Browse files
committed
Clean up code and improve docs
I decided the `impl TryFrom<Vec<u8>>` was too cheesy and instead just called that method `SecretString::from_utf8`, with different variants for `from_utf8_box` or `from_utf8_box_len`.
1 parent 9c5e1a0 commit 7b8b309

File tree

1 file changed

+33
-24
lines changed

1 file changed

+33
-24
lines changed

secrecy/src/lib.rs

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
extern crate alloc;
3838

39-
use alloc::string::FromUtf8Error as _FromUtf8Error;
39+
use alloc::string;
4040
use alloc::{boxed::Box, string::String, vec::Vec};
4141
use core::convert::Infallible;
4242
use core::mem::take;
@@ -133,21 +133,19 @@ impl<S: Zeroize + Clone> SecretBox<S> {
133133
}
134134
}
135135

136-
/// Error return from [`SecretString::from_utf8`] or [`SecretString::from_utf8_len`].
136+
/// A possible error value when creating a [`SecretString`] from a UTF-8 byte vector.
137137
///
138-
/// This is like [`FromUtf8Error`] except it zeroizes its buffer on [`Drop`].
139-
///
140-
/// [`FromUtf8Error`]: _FromUtf8Error
138+
/// This is like [`string::FromUtf8Error`] except it zeroizes its buffer on [`Drop`].
141139
pub struct FromUtf8Error {
142-
inner: Option<_FromUtf8Error>,
140+
inner: Option<string::FromUtf8Error>,
143141
}
144142

145143
impl FromUtf8Error {
146-
fn new(inner: _FromUtf8Error) -> Self {
144+
fn new(inner: string::FromUtf8Error) -> Self {
147145
FromUtf8Error { inner: Some(inner) }
148146
}
149147

150-
/// See [`utf8_error`][_FromUtf8Error::utf8_error].
148+
/// See [`string::FromUtf8Error::utf8_error`].
151149
pub fn utf8_error(&self) -> Utf8Error {
152150
// Panic safety: `take` is only called on moves.
153151
let Some(err) = &self.inner else {
@@ -156,7 +154,7 @@ impl FromUtf8Error {
156154
err.utf8_error()
157155
}
158156

159-
/// See [`into_bytes`][_FromUtf8Error::into_bytes].
157+
/// See [`string::FromUtf8Error::into_bytes`].
160158
pub fn into_bytes(mut self) -> Vec<u8> {
161159
// Panic safety: `take` is only called here and on `Drop`.
162160
let Some(err) = self.inner.take() else {
@@ -175,26 +173,37 @@ impl Drop for FromUtf8Error {
175173
}
176174

177175
impl SecretBox<str> {
176+
/// Create a [`SecretString`] from a UTF-8 byte buffer.
177+
///
178178
/// See [`String::from_utf8`].
179-
pub fn from_utf8(mut other: SecretBox<[u8]>) -> Result<Self, FromUtf8Error> {
180-
Self::try_from(take(&mut other.inner_secret).into_vec())
179+
pub fn from_utf8(buf: Vec<u8>) -> Result<Self, FromUtf8Error> {
180+
String::from_utf8(buf)
181+
.map(SecretBox::from)
182+
.map_err(FromUtf8Error::new)
181183
}
182184

183-
/// Like [`String::from_utf8`], except the buffer is truncated to `len` first.
184-
pub fn from_utf8_len(mut other: SecretBox<[u8]>, len: usize) -> Result<Self, FromUtf8Error> {
185-
let mut buf = take(&mut other.inner_secret).into_vec();
186-
buf.truncate(len);
187-
Self::try_from(buf)
185+
/// Create a [`SecretString`] from a <code>[SecretBox]&lt;\[u8]&gt;</code>.
186+
///
187+
/// This works like [`String::from_utf8`], i.e., it does not allocate but rather takes
188+
/// ownership of the backing buffer. Note that the result will have the whole buffer’s
189+
/// contents; to perform truncation, see [`SecretString::from_utf8_box_len`].
190+
pub fn from_utf8_box(mut other: SecretBox<[u8]>) -> Result<Self, FromUtf8Error> {
191+
Self::from_utf8(take(&mut other.inner_secret).into_vec())
188192
}
189-
}
190-
191-
impl TryFrom<Vec<u8>> for SecretBox<str> {
192-
type Error = FromUtf8Error;
193193

194-
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
195-
String::from_utf8(value)
196-
.map(SecretBox::from)
197-
.map_err(FromUtf8Error::new)
194+
/// Create a [`SecretString`] from a portion of a <code>[SecretBox]&lt;\[u8]&gt;</code>.
195+
///
196+
/// This works like [`String::from_utf8`], except that the buffer is truncated to the specified
197+
/// length before the string is created. Note that the allocation is not resized; if the buffer
198+
/// is much larger than the resulting string, this is wasteful, and it is probably better to
199+
/// call [`SecretString::from`] on the slice to make a new allocation with only the needed size.
200+
pub fn from_utf8_box_len(
201+
mut other: SecretBox<[u8]>,
202+
len: usize,
203+
) -> Result<Self, FromUtf8Error> {
204+
let mut buf = take(&mut other.inner_secret).into_vec();
205+
buf.truncate(len);
206+
Self::from_utf8(buf)
198207
}
199208
}
200209

0 commit comments

Comments
 (0)