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}