mail_headers_ng/data/
inner_item.rs1use std::ops::Deref;
2use std::sync::Arc;
3use std::borrow::ToOwned;
4
5use self::super::super::owning_ref_rs::OwningRef;
7use soft_ascii_string::{SoftAsciiString, SoftAsciiStr};
8
9#[cfg(feature="serde")]
10use serde::{Serialize, Deserialize, Serializer, Deserializer, de::Error as __Error};
11
12
13#[derive(Debug, Clone, Hash, Eq)]
17pub enum InnerAscii {
18 Owned(SoftAsciiString),
19 Shared(OwningRef<'static, Arc<String>, SoftAsciiStr>)
21}
22
23impl InnerAscii {
24
25 pub fn into_shared(self) -> Self {
38 match self {
39 InnerAscii::Owned(value) => {
40 let buffer: Arc<String> = Arc::new(value.into());
41 let orf = OwningRef::new(buffer).map(|data: &String| {
42 SoftAsciiStr::from_unchecked(&**data)
44 });
45 InnerAscii::Shared(orf)
46 }
47 v => v
48 }
49 }
50}
51
52#[derive(Debug, Clone, Hash, Eq)]
56pub enum InnerUtf8 {
57 Owned(String),
58 Shared(OwningRef<'static, Arc<String>, str>)
60}
61
62impl InnerUtf8 {
63
64 pub fn into_shared(self) -> Self {
70 match self {
71 InnerUtf8::Owned(value) => {
72 let buffer = Arc::new(value);
73 let orf = OwningRef::new(buffer)
74 .map(|rced| &**rced);
75 InnerUtf8::Shared(orf)
76 }
77 v => v
78 }
79 }
80}
81
82
83macro_rules! inner_impl {
84 ($name:ident, $owned_form:ty, $borrowed_form:ty) => (
85 impl $name {
86 pub fn new<S: Into<$owned_form>>( data: S ) -> Self {
87 $name::Owned( data.into() )
88 }
89 }
90 impl From<$owned_form> for $name {
91 fn from( data: $owned_form ) -> Self {
92 Self::new( data )
93 }
94 }
95
96 impl Into<$owned_form> for $name {
97 fn into(self) -> $owned_form {
98 match self {
99 $name::Owned( owned ) => owned,
100 $name::Shared( shared ) => {
101 let as_ref: &$borrowed_form = &*shared;
102 as_ref.to_owned()
103 }
104 }
105 }
106 }
107
108 impl Deref for $name {
109 type Target = $borrowed_form;
110
111 fn deref( &self ) -> &$borrowed_form{
112 match *self {
113 $name::Owned( ref string ) => &*string,
114 $name::Shared( ref owning_ref ) => &*owning_ref
115 }
116 }
117 }
118
119 #[cfg(feature="serde")]
120 impl Serialize for $name {
121 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
122 where S: Serializer
123 {
124 let borrowed: &$borrowed_form = &*self;
125 let as_ref: &str = borrowed.as_ref();
126 serializer.serialize_str( as_ref )
127 }
128 }
129
130 impl PartialEq for $name {
131 fn eq(&self, other: &$name) -> bool {
132 let me: &$borrowed_form = &*self;
133 let other: &$borrowed_form = &*other;
134 me == other
135 }
136 }
137
138 impl AsRef<str> for $name {
139 fn as_ref(&self) -> &str {
140 self.as_str()
141 }
142 }
143 );
144}
145
146inner_impl!{ InnerAscii, SoftAsciiString, SoftAsciiStr }
147inner_impl!{ InnerUtf8, String, str }
148impl InnerAscii {
151 pub fn as_str( &self ) -> &str {
152 match *self {
153 InnerAscii::Owned( ref owned ) => owned.as_str(),
154 InnerAscii::Shared( ref shared ) => shared.as_str()
155 }
156 }
157}
158
159#[cfg(feature="serde")]
160impl<'de> Deserialize<'de> for InnerAscii {
161 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
162 where D: Deserializer<'de>
163 {
164 let content = String::deserialize(deserializer)
165 .map_err(|err| D::Error::custom(err))?;
166 let content = SoftAsciiString::from_string(content)
167 .map_err(|err| D::Error::custom(err))?;
168 Ok(InnerAscii::from(content))
169 }
170}
171
172impl InnerUtf8 {
173 pub fn as_str( &self ) -> &str {
174 match *self {
175 InnerUtf8::Owned( ref owned ) => owned.as_str(),
176 InnerUtf8::Shared( ref shared ) => &**shared
177 }
178 }
179}
180
181#[cfg(feature="serde")]
182impl<'de> Deserialize<'de> for InnerUtf8 {
183 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
184 where D: Deserializer<'de>
185 {
186 let content = String::deserialize(deserializer)
187 .map_err(|err| D::Error::custom(err))?;
188 Ok(InnerUtf8::from(content))
189 }
190}
191
192
193#[cfg(test)]
194mod test {
195 use super::*;
196
197 #[test]
198 fn inner_ascii_item_eq() {
199 let a = InnerAscii::Owned( SoftAsciiString::from_string( "same" ).unwrap() );
200 let b = InnerAscii::Shared(
201 OwningRef::new(Arc::new("same".to_owned()))
202 .map(|v| SoftAsciiStr::from_unchecked(&**v))
203 );
204 assert_eq!( a, b );
205 }
206
207 #[test]
208 fn inner_ascii_item_neq() {
209 let a = InnerAscii::Owned( SoftAsciiString::from_string( "same" ).unwrap() );
210 let b = InnerAscii::Shared(
211 OwningRef::new(Arc::new("not same".to_owned()))
212 .map(|v| SoftAsciiStr::from_unchecked(&**v))
213 );
214 assert_ne!( a, b );
215 }
216
217 #[test]
218 fn inner_utf8_item_eq() {
219 let a = InnerUtf8::Owned( String::from( "same" ) );
220 let b = InnerUtf8::Shared(
221 OwningRef::new(
222 Arc::new( String::from( "same" ) ) )
223 .map(|v| &**v)
224 );
225 assert_eq!( a, b );
226 }
227
228 #[test]
229 fn inner_utf8_item_neq() {
230 let a = InnerUtf8::Owned( String::from( "same" ) );
231 let b = InnerUtf8::Shared(
232 OwningRef::new(
233 Arc::new( String::from( "not same" ) ) )
234 .map(|v| &**v)
235 );
236 assert_ne!( a, b );
237 }
238
239 #[test]
240 fn has_as_str() {
241 use std::borrow::ToOwned;
242
243 assert_eq!(
244 "hy",
245 InnerAscii::Owned( SoftAsciiStr::from_unchecked("hy").to_owned() ).as_str()
246 );
247 assert_eq!(
248 "hy",
249 InnerUtf8::Owned( "hy".into() ).as_str()
250 );
251 }
252}