1- using Newtonsoft . Json ;
2- using System . Diagnostics . CodeAnalysis ;
1+ using System . Diagnostics . CodeAnalysis ;
32using System . Text . RegularExpressions ;
3+ using Newtonsoft . Json ;
44
55namespace Intersect . Plugins . Manifests . Types ;
66
77/// <summary>
8- /// Structure that defines an <see cref="Author"/> that can be represented as an <see cref="Author"/> <see cref="string"/>.
8+ /// Structure that defines an <see cref="Author" /> that can be represented as an <see cref="Author" />
9+ /// <see cref="string" />.
910/// </summary>
1011[ JsonConverter ( typeof ( AuthorStringConverter ) ) ]
1112public partial struct Author : IComparable < Author > , IEquatable < Author > , IEquatable < string > , ICloneable , IComparable
1213{
1314 #region Constants
1415
1516 /// <summary>
16- /// Expression that defines what qualifies as an <see cref="Author"/> <see cref="string"/>.
17- ///
18- /// Can be summarized as <code>Name[ <Email>][ (Homepage)]</code>
17+ /// Expression that defines what qualifies as an <see cref="Author" /> <see cref="string" />.
18+ /// Can be summarized as <code>Name[ <Email>][ (Homepage)]</code>
1919 /// </summary>
20- public static readonly Regex AuthorStringExpression =
21- new Regex ( @"^\s*(.+?)(?:\s+<([^>]+)>)?(?:\s+\(([^\\)]+)\))?\s*$" ) ;
20+ public static readonly Regex AuthorStringExpression = new ( @"^\s*(.+?)(?:\s+<([^>]+)>)?(?:\s+\(([^\\)]+)\))?\s*$" ) ;
2221
2322 /// <summary>
24- /// The empty <see cref="Author"/> created using the default constructor.
23+ /// The empty <see cref="Author" /> created using the default constructor.
2524 /// </summary>
26- public static Author Empty => new Author ( ) ;
25+ public static Author Empty => new ( ) ;
2726
2827 #endregion Constants
2928
3029 #region Fields
3130
3231 /// <summary>
33- /// Email address of the <see cref="Author"/> (not validated).
32+ /// Email address of the <see cref="Author" /> (not validated).
3433 /// </summary>
3534 public readonly string Email ;
3635
3736 /// <summary>
38- /// Homepage (URL) of the <see cref="Author"/> (not validated).
37+ /// Homepage (URL) of the <see cref="Author" /> (not validated).
3938 /// </summary>
4039 public readonly string Homepage ;
4140
4241 /// <summary>
43- /// Name of the <see cref="Author"/>.
42+ /// Name of the <see cref="Author" />.
4443 /// </summary>
4544 public readonly string Name ;
4645
4746 /// <summary>
48- /// Precomputed hash code.
47+ /// Precomputed hash code.
4948 /// </summary>
50- private readonly int mHashCode ;
49+ private readonly int _hashCode ;
5150
5251 #endregion Fields
5352
5453 #region Constructors
5554
5655 /// <summary>
57- /// Constructs an <see cref="Author"/> from a <see cref="string"/>.
56+ /// Constructs an <see cref="Author" /> from a <see cref="string" />.
5857 /// </summary>
59- /// <param name="authorString">an <see cref="Author"/> <see cref="string"/></param>
60- /// <exception cref="ArgumentNullException">thrown if <paramref name="authorString"/> is null, empty, or whitespace</exception>
61- /// <exception cref="ArgumentException">thrown if <paramref name="authorString"/> does not match the format defined by <see cref="AuthorStringExpression" /></exception>
62- /// <seealso cref="AuthorStringExpression"/>
58+ /// <param name="authorString">an <see cref="Author" /> <see cref="string" /></param>
59+ /// <exception cref="ArgumentNullException">thrown if <paramref name="authorString" /> is null, empty, or whitespace</exception>
60+ /// <exception cref="ArgumentException">
61+ /// thrown if <paramref name="authorString" /> does not match the format defined by
62+ /// <see cref="AuthorStringExpression" />
63+ /// </exception>
64+ /// <seealso cref="AuthorStringExpression" />
6365 public Author ( string authorString )
6466 {
6567 if ( string . IsNullOrWhiteSpace ( authorString ) )
@@ -76,106 +78,149 @@ public Author(string authorString)
7678 Email = email . Value ;
7779 Homepage = homepage . Value ;
7880
79- mHashCode = HashCode . Combine ( Name , Email , Homepage ) ;
81+ _hashCode = HashCode . Combine ( Name , Email , Homepage ) ;
8082 }
8183
8284 /// <summary>
83- /// Constructs an <see cref="Author"/> from an explicitly defined name, email, and homepage.
85+ /// Constructs an <see cref="Author" /> from an explicitly defined name, email, and homepage.
8486 /// </summary>
85- /// <param name="name">the name of the <see cref="Author"/></param>
86- /// <param name="email">the email address of the <see cref="Author"/></param>
87- /// <param name="homepage">the homepage of the <see cref="Author"/></param>
87+ /// <param name="name">the name of the <see cref="Author" /></param>
88+ /// <param name="email">the email address of the <see cref="Author" /></param>
89+ /// <param name="homepage">the homepage of the <see cref="Author" /></param>
8890 [ JsonConstructor ]
8991 public Author ( string name , string email , string ? homepage = default )
9092 {
9193 Name = name ;
9294 Email = email ;
9395 Homepage = homepage ?? string . Empty ;
9496
95- mHashCode = HashCode . Combine ( Name , Email , Homepage ) ;
97+ _hashCode = HashCode . Combine ( Name , Email , Homepage ) ;
9698 }
9799
98100 #endregion Constructors
99101
100102 #region Properties
101103
104+ private string [ ] ? _parts ;
105+
102106 /// <summary>
103- /// Gets the parts as an enumerable for <see cref="CompareTo(Author)"/>.
107+ /// Gets the parts as an enumerable for <see cref="CompareTo(Author)" />.
104108 /// </summary>
105- private IEnumerable < string > Parts => new [ ] { Name , Email , Homepage } ;
109+ private string [ ] Parts => _parts ??= [ Name , Email , Homepage ] ;
106110
107111 #endregion Properties
108112
109113 #region Methods
110114
111- /// <inheritdoc cref="ICloneable.Clone"/>
112- public Author Clone ( ) => new Author ( Name , Email , Homepage ) ;
115+ /// <inheritdoc cref="ICloneable.Clone" />
116+ public Author Clone ( )
117+ {
118+ return new Author ( Name , Email , Homepage ) ;
119+ }
113120
114- object ICloneable . Clone ( ) => Clone ( ) ;
121+ object ICloneable . Clone ( )
122+ {
123+ return Clone ( ) ;
124+ }
115125
116126 /// <inheritdoc />
117- public int CompareTo ( object obj ) =>
118- obj is Author other
127+ public int CompareTo ( object obj )
128+ {
129+ return obj is Author other
119130 ? CompareTo ( other )
120131 : throw new NotSupportedException ( "Comparison only supported with Author." ) ;
132+ }
121133
122134 /// <inheritdoc />
123- public int CompareTo ( Author other ) => HashCode . Combine ( Parts , other . Parts ) ;
135+ public int CompareTo ( Author other )
136+ {
137+ var parts = Parts ;
138+ var otherParts = other . Parts ;
139+ var lengthComparison = parts . Length . CompareTo ( otherParts . Length ) ;
140+ return lengthComparison != 0
141+ ? lengthComparison
142+ : parts . Select ( ( t , index ) => string . Compare ( t , otherParts [ index ] , StringComparison . Ordinal ) )
143+ . FirstOrDefault ( comparison => comparison != 0 ) ;
144+ }
124145
125146 /// <inheritdoc />
126- public override bool Equals ( object ? obj ) => obj is Author author && Equals ( author ) ;
147+ public override bool Equals ( object ? obj )
148+ {
149+ return obj is Author author && Equals ( author ) ;
150+ }
127151
128152 /// <inheritdoc />
129- public bool Equals ( Author other ) => this == other ;
153+ public bool Equals ( Author other )
154+ {
155+ return this == other ;
156+ }
130157
131158 /// <inheritdoc />
132- public bool Equals ( string ? other ) => other is not null && other == this ;
159+ public bool Equals ( string ? other )
160+ {
161+ return other is not null && other == this ;
162+ }
133163
134164 /// <inheritdoc />
135- public override int GetHashCode ( ) => mHashCode ;
165+ public override int GetHashCode ( )
166+ {
167+ return _hashCode ;
168+ }
136169
137170 /// <inheritdoc />
138- public override string ToString ( ) =>
139- $ "{ Name } { ( string . IsNullOrEmpty ( Email ) ? "" : $ " <{ Email } >") } { ( string . IsNullOrEmpty ( Homepage ) ? "" : $ " ({ Homepage } )") } ";
171+ public override string ToString ( )
172+ {
173+ return
174+ $ "{ Name } { ( string . IsNullOrEmpty ( Email ) ? "" : $ " <{ Email } >") } { ( string . IsNullOrEmpty ( Homepage ) ? "" : $ " ({ Homepage } )") } ";
175+ }
140176
141177 #endregion Methods
142178
143179 #region Operators
144180
145181 /// <summary>
146- /// Converts a <see cref="string"/> to an <see cref="Author"/>.
182+ /// Converts a <see cref="string" /> to an <see cref="Author" />.
147183 /// </summary>
148- /// <param name="authorString">an <see cref="Author"/> <see cref="string"/></param>
149- public static implicit operator Author ( string authorString ) =>
150- authorString == null ? Empty : new Author ( authorString ) ;
184+ /// <param name="authorString">an <see cref="Author" /> <see cref="string" /></param>
185+ public static implicit operator Author ( string authorString )
186+ {
187+ return authorString == null ? Empty : new Author ( authorString ) ;
188+ }
151189
152190 /// <summary>
153- /// Converts an <see cref="Author"/> to a <see cref="string"/>.
191+ /// Converts an <see cref="Author" /> to a <see cref="string" />.
154192 /// </summary>
155- /// <param name="author">an <see cref="Author"/></param>
156- public static implicit operator string ( Author author ) => author . ToString ( ) ;
193+ /// <param name="author">an <see cref="Author" /></param>
194+ public static implicit operator string ( Author author )
195+ {
196+ return author . ToString ( ) ;
197+ }
157198
158199 /// <summary>
159- /// Checks if two <see cref="Author"/>s are not equal.
200+ /// Checks if two <see cref="Author" />s are not equal.
160201 /// </summary>
161202 /// <param name="a"></param>
162203 /// <param name="b"></param>
163204 /// <returns>if any of the parts are not equal</returns>
164- public static bool operator != ( Author a , Author b ) =>
165- ! string . Equals ( a . Name , b . Name , StringComparison . Ordinal ) ||
166- ! string . Equals ( a . Email , b . Email , StringComparison . Ordinal ) ||
167- ! string . Equals ( a . Homepage , b . Homepage , StringComparison . Ordinal ) ;
205+ public static bool operator != ( Author a , Author b )
206+ {
207+ return ! string . Equals ( a . Name , b . Name , StringComparison . Ordinal ) ||
208+ ! string . Equals ( a . Email , b . Email , StringComparison . Ordinal ) ||
209+ ! string . Equals ( a . Homepage , b . Homepage , StringComparison . Ordinal ) ;
210+ }
168211
169212 /// <summary>
170- /// Checks if two <see cref="Author"/>s are equal.
213+ /// Checks if two <see cref="Author" />s are equal.
171214 /// </summary>
172215 /// <param name="a"></param>
173216 /// <param name="b"></param>
174217 /// <returns>if all of the parts are equal</returns>
175- public static bool operator == ( Author a , Author b ) =>
176- string . Equals ( a . Name , b . Name , StringComparison . Ordinal ) &&
177- string . Equals ( a . Email , b . Email , StringComparison . Ordinal ) &&
178- string . Equals ( a . Homepage , b . Homepage , StringComparison . Ordinal ) ;
218+ public static bool operator == ( Author a , Author b )
219+ {
220+ return string . Equals ( a . Name , b . Name , StringComparison . Ordinal ) &&
221+ string . Equals ( a . Email , b . Email , StringComparison . Ordinal ) &&
222+ string . Equals ( a . Homepage , b . Homepage , StringComparison . Ordinal ) ;
223+ }
179224
180225 #endregion Operators
181226
@@ -199,15 +244,19 @@ public override Author ReadJson(
199244 Author existingValue ,
200245 bool hasExistingValue ,
201246 JsonSerializer serializer
202- ) =>
247+ )
248+ {
203249 throw new NotImplementedException ( ) ;
250+ }
204251
205252 /// <inheritdoc />
206- public override void WriteJson ( JsonWriter writer , Author value , JsonSerializer serializer ) =>
253+ public override void WriteJson ( JsonWriter writer , Author value , JsonSerializer serializer )
254+ {
207255 writer ? . WriteValue ( value . ToString ( ) ) ;
256+ }
208257
209258 #endregion Methods
210259 }
211260
212261 #endregion Classes
213- }
262+ }
0 commit comments