Skip to main content

str_newtype/
lib.rs

1//! This library provides a handy derive macro to create type-safe wrappers
2//! around borrowed and owned string types (`str` and `String`), guaranteeing
3//! through the type system that those string have been validated.
4//!
5//! With this derive macro, all you need to do is define the base borrowed type,
6//! specify the name of the associated owned type and what trait you want them
7//! to implement.
8//!
9//! # Example
10//!
11//! In this example, we wish to define the types `FooStr` and `FooString`,
12//! similar to `str` (borrowed) and `String` (owned), with the extra guarantee
13//! that the string is always equal to `"foo"`.
14//!
15//! ```
16//! use str_newtype::StrNewType;
17//!
18//! /// An `str` that is equal to `"foo"`.
19//! #[derive(StrNewType)]
20//! #[newtype(owned(FooString))]
21//! pub struct FooStr(str);
22//!
23//! impl FooStr {
24//!   pub const fn validate_bytes(s: &[u8]) -> bool {
25//!     s.len() == 3 && s[0] == b'f' && s[1] == b'f' && s[2] == b'f'
26//!   }
27//!
28//!   pub const fn validate_str(s: &str) -> bool {
29//!     Self::validate_bytes(s.as_bytes())
30//!   }
31//! }
32//! ```
33//!
34//! The validation methods (`validate_*`) are provided by us, but `StrNewType`
35//! will use them to derive the following:
36//! - An error type `InvalidFooStr<T = String>(pub T)`;
37//! - A constructor `FooStr::new<T: ?Sized + AsRef<[u8]>>(input: &T) -> Result<&Self, InvalidFooStr<&T>>`
38//! - `FooStr: Deref<Target = str>` implementation
39//! - `FooStr: AsRef<str>` implementation
40//! - `FooStr: Borrow<str>` implementation
41//!
42//! Since we added the `owned(FooString)` attribute, it will also generate:
43//! - A sized/owned version of `FooStr`: `struct FooString(String);`
44//! - A constructor `FooString::new<T: Buffer>(s: T) -> Result<Self, InvalidFooStr<T>>`
45//! - `FooString: Deref<Target = FooStr>`
46//! - `FooString: AsRef<FooStr>` implementation
47//! - `FooString: Borrow<FooStr>` implementation
48//!
49//! And much more. See the the [`StrNewType`] documentation for a full
50//! specification of what items are derived and how it can be controlled with
51//! the `newtype` attribute.
52#![cfg_attr(not(feature = "std"), no_std)]
53pub use str_newtype_derive::StrNewType;
54
55/// Trusted byte buffer type.
56///
57/// # Safety
58///
59/// Any interior mutability in the buffer type must not affect the `as_bytes`
60/// and `into_bytes` methods. In other words, as long as `self` is borrowed
61/// immutably those functions must always return the same result.
62#[cfg(feature = "std")]
63pub unsafe trait Buffer: Sized {
64	/// Borrows the buffer bytes.
65	fn as_bytes(&self) -> &[u8];
66
67	/// Turns this buffer into a byte array.
68	fn into_bytes(self) -> Vec<u8>;
69}
70
71#[cfg(feature = "std")]
72unsafe impl Buffer for Vec<u8> {
73	fn as_bytes(&self) -> &[u8] {
74		self
75	}
76
77	fn into_bytes(self) -> Vec<u8> {
78		self
79	}
80}
81
82#[cfg(feature = "std")]
83unsafe impl Buffer for String {
84	fn as_bytes(&self) -> &[u8] {
85		self.as_bytes()
86	}
87
88	fn into_bytes(self) -> Vec<u8> {
89		self.into_bytes()
90	}
91}