1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use crate::{StrongBuf, Validator};
pub use imp::Strong;
mod imp {
#[cfg(feature = "diesel")]
use crate::impl_diesel::SqlStrong;
use crate::Validator;
use std::marker::PhantomData;
#[allow(non_camel_case_types)]
#[cfg_attr(
feature = "diesel",
derive(AsExpression),
sql_type = "SqlStrong<Ctx>",
diesel(not_sized)
)]
#[repr(transparent)]
pub struct Strong<Ctx: Validator> {
phantom: PhantomData<Ctx>,
inner: str
}
impl<Ctx: Validator> Strong<Ctx> {
#[inline]
pub fn validate<S: AsRef<str> + ?Sized>(s: &S) -> Result<&Self, Ctx::Err> {
Ctx::validate(s.as_ref())?;
Ok(unsafe { Self::no_validate(s) })
}
#[inline]
pub unsafe fn no_validate<S: AsRef<str> + ?Sized>(s: &S) -> &Self {
&*(s.as_ref() as *const str as *const Self)
}
#[inline]
pub fn as_str(&self) -> &str { &self.inner }
#[inline(always)]
pub fn as_bytes(&self) -> &[u8] { self.inner.as_bytes() }
}
}
impl<Ctx: Validator> Strong<Ctx> {
pub fn valid(&self) -> Result<&Self, Ctx::Err> {
Ctx::validate(self.as_str())?;
Ok(&self)
}
pub fn to_strong_buf(&self) -> StrongBuf<Ctx> {
unsafe { StrongBuf::no_validate(self.as_str().to_string()) }
}
pub fn count_chars(&self) -> usize { self.as_str().chars().count() }
pub fn map<F>(&self, f: F) -> Result<&Strong<Ctx>, Ctx::Err>
where
F: FnOnce(&str) -> &str
{
let s = f(self.as_str());
Strong::validate(s)
}
pub fn trim(&self) -> Result<&Strong<Ctx>, Ctx::Err> { self.map(str::trim) }
pub fn trim_start(&self) -> Result<&Strong<Ctx>, Ctx::Err> { self.map(str::trim_start) }
pub fn trim_end(&self) -> Result<&Strong<Ctx>, Ctx::Err> { self.map(str::trim_end) }
}
impl<Ctx> ToOwned for Strong<Ctx>
where
Ctx: Validator
{
type Owned = StrongBuf<Ctx>;
#[inline]
fn to_owned(&self) -> StrongBuf<Ctx> {
unsafe { StrongBuf::from_utf8_unchecked(self.as_bytes().to_owned()) }
}
}