1
+ using System . Text ;
1
2
using BrazilModels . Json ;
2
3
3
4
namespace BrazilModels ;
@@ -12,7 +13,15 @@ namespace BrazilModels;
12
13
[ System . Text . Json . Serialization . JsonConverter ( typeof ( StringSystemTextJsonConverter < Email > ) ) ]
13
14
[ TypeConverter ( typeof ( StringTypeConverter < Email > ) ) ]
14
15
[ DebuggerDisplay ( "{DebuggerDisplay(),nq}" ) ]
15
- public readonly record struct Email : IComparable < Email > , IFormattable
16
+ public readonly record struct Email : IComparable < Email > , IStringValue
17
+ #if NET8_0_OR_GREATER
18
+ , ISpanFormattable
19
+ , ISpanParsable < Email >
20
+ , IUtf8SpanFormattable
21
+ , IUtf8SpanParsable < Email >
22
+ #else
23
+ , IFormattable
24
+ #endif
16
25
{
17
26
/// <summary>
18
27
/// String representation of the Email
@@ -30,6 +39,24 @@ public Email(string email)
30
39
this . Value = email . ToLowerInvariant ( ) ;
31
40
}
32
41
42
+ /// <summary>
43
+ /// Create a new email instance
44
+ /// </summary>
45
+ /// <exception cref="InvalidOperationException"></exception>
46
+ /// <exception cref="ArgumentNullException"></exception>
47
+ public Email ( ReadOnlySpan < char > email )
48
+ {
49
+ if ( email . IsEmptyOrWhiteSpace ( ) )
50
+ throw new ArgumentException ( "Invalid value argument" ) ;
51
+
52
+ this . Value = email . ToString ( ) . ToLowerInvariant ( ) ;
53
+ }
54
+
55
+ /// <summary>
56
+ /// Returns true if is empty
57
+ /// </summary>
58
+ public bool IsEmpty => string . IsNullOrWhiteSpace ( Value ) ;
59
+
33
60
/// <inheritdoc />
34
61
public override string ToString ( ) => Value ;
35
62
@@ -38,7 +65,7 @@ string IFormattable.ToString(string? format, IFormatProvider? formatProvider) =>
38
65
Value . ToString ( formatProvider ) ;
39
66
40
67
/// <summary>
41
- /// Get Email instance of an Value string
68
+ /// Get Email instance of a Value string
42
69
/// </summary>
43
70
/// <exception cref="InvalidOperationException"></exception>
44
71
/// <exception cref="ArgumentNullException"></exception>
@@ -52,20 +79,35 @@ public static implicit operator string(Email email)
52
79
=> email . Value ;
53
80
54
81
/// <summary>
55
- /// Try parse an Value string to an Email instance
82
+ /// Try parse a char span to an Email instance
56
83
/// </summary>
57
- public static bool TryParse ( string ? value , out Email email )
84
+ public static bool TryParse ( ReadOnlySpan < char > value , out Email email )
58
85
{
59
86
email = default ;
60
- if ( value is null || ! IsValid ( value ) )
87
+ if ( value . IsEmpty || ! IsValid ( value ) )
61
88
return false ;
62
89
63
90
email = new ( value ) ;
64
91
return true ;
65
92
}
66
93
67
94
/// <summary>
68
- /// Parse an Value string to an Email instance
95
+ /// Try parse a Value string to an Email instance
96
+ /// </summary>
97
+ public static bool TryParse ( string ? value , out Email email )
98
+ {
99
+ email = default ;
100
+ return value is not null && TryParse ( value . AsSpan ( ) , out email ) ;
101
+ }
102
+
103
+ /// <summary>
104
+ /// Try parse a UTF8 byte span to an Email instance
105
+ /// </summary>
106
+ public static bool TryParse ( ReadOnlySpan < byte > value , out Email result ) =>
107
+ TryParse ( Encoding . UTF8 . GetString ( value ) . AsSpan ( ) , out result ) ;
108
+
109
+ /// <summary>
110
+ /// Parse a Value string to an Email instance
69
111
/// </summary>
70
112
/// <exception cref="InvalidOperationException"></exception>
71
113
/// <exception cref="ArgumentNullException"></exception>
@@ -74,15 +116,30 @@ public static Email Parse(string value) =>
74
116
? valid
75
117
: throw new InvalidOperationException ( $ "Invalid E-mail { value } ") ;
76
118
119
+ /// <summary>
120
+ /// Parse a Value string to an Email instance
121
+ /// </summary>
122
+ /// <exception cref="InvalidOperationException"></exception>
123
+ /// <exception cref="ArgumentNullException"></exception>
124
+ public static Email Parse ( ReadOnlySpan < char > value ) =>
125
+ TryParse ( value , out var valid )
126
+ ? valid
127
+ : throw new InvalidOperationException ( $ "Invalid E-mail { value } ") ;
128
+
129
+ /// <summary>
130
+ /// Parse an UTF8 byte span to an Email instance
131
+ /// </summary>
132
+ public static Email Parse ( ReadOnlySpan < byte > value ) => Parse ( Encoding . UTF8 . GetString ( value ) ) ;
133
+
77
134
/// <summary>
78
135
/// Validate Email string
79
136
/// </summary>
80
137
/// <param name="value"></param>
81
138
/// <returns></returns>
82
- public static bool IsValid ( string ? value )
139
+ public static bool IsValid ( ReadOnlySpan < char > value )
83
140
{
84
141
const string at = "@" ;
85
- if ( value is null )
142
+ if ( value . IsEmptyOrWhiteSpace ( ) )
86
143
return false ;
87
144
88
145
var index = value . IndexOf ( at , StringComparison . OrdinalIgnoreCase ) ;
@@ -92,9 +149,65 @@ public static bool IsValid(string? value)
92
149
index == value . LastIndexOf ( at , StringComparison . OrdinalIgnoreCase ) ;
93
150
}
94
151
152
+ /// <summary>
153
+ /// Validate Email string
154
+ /// </summary>
155
+ /// <param name="value"></param>
156
+ /// <returns></returns>
157
+ public static bool IsValid ( string ? value ) => value is not null && IsValid ( value . AsSpan ( ) ) ;
158
+
95
159
/// <inheritdoc />
96
160
public int CompareTo ( Email other ) =>
97
161
string . Compare ( Value , other . Value , StringComparison . OrdinalIgnoreCase ) ;
98
162
99
163
string DebuggerDisplay ( ) => $ "EMAIL{{{Value}}}";
164
+
165
+
166
+ #if NET8_0_OR_GREATER
167
+ bool ISpanFormattable . TryFormat (
168
+ Span < char > destination , out int charsWritten ,
169
+ ReadOnlySpan < char > format , IFormatProvider ? provider
170
+ )
171
+ {
172
+ charsWritten = 0 ;
173
+ if ( destination . IsEmpty ) return false ;
174
+
175
+ if ( destination . Length < Value . Length )
176
+ return false ;
177
+
178
+ charsWritten = Value . Length ;
179
+ Value . CopyTo ( destination ) ;
180
+ return true ;
181
+ }
182
+
183
+ bool IUtf8SpanFormattable . TryFormat (
184
+ Span < byte > utf8Destination , out int bytesWritten ,
185
+ ReadOnlySpan < char > format , IFormatProvider ? provider
186
+ )
187
+ {
188
+ bytesWritten = 0 ;
189
+ if ( utf8Destination . IsEmpty ) return false ;
190
+ return Encoding . UTF8 . TryGetBytes ( Value , utf8Destination , out bytesWritten ) ;
191
+ }
192
+
193
+ static Email IParsable < Email > . Parse ( string s , IFormatProvider ? provider ) => Parse ( s ) ;
194
+
195
+ static bool IParsable < Email > . TryParse ( string ? s , IFormatProvider ? provider , out Email result ) =>
196
+ TryParse ( s , out result ) ;
197
+
198
+ static Email ISpanParsable < Email > . Parse ( ReadOnlySpan < char > s , IFormatProvider ? provider ) =>
199
+ Parse ( s ) ;
200
+
201
+ static bool ISpanParsable < Email > . TryParse (
202
+ ReadOnlySpan < char > s , IFormatProvider ? provider , out Email result ) =>
203
+ TryParse ( s , out result ) ;
204
+
205
+ static Email IUtf8SpanParsable < Email > . Parse (
206
+ ReadOnlySpan < byte > utf8Text , IFormatProvider ? provider ) => Parse ( utf8Text ) ;
207
+
208
+ static bool IUtf8SpanParsable < Email > . TryParse ( ReadOnlySpan < byte > utf8Text ,
209
+ IFormatProvider ? provider , out Email result ) => TryParse ( utf8Text , out result ) ;
210
+
211
+ static int IStringValue . ValueSize { get ; } = 255 ;
212
+ #endif
100
213
}
0 commit comments