Skip to content

Commit

Permalink
feat: Update implementation of PhoneNumber struct
Browse files Browse the repository at this point in the history
- Changed the implemented interface from `IStringWithRegexValueObject` to `IRegexValueObject`
- Updated the key features section in the README.md file
  • Loading branch information
dgmjr committed Oct 29, 2023
1 parent fdb3028 commit c9a91d3
Show file tree
Hide file tree
Showing 15 changed files with 100 additions and 106 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ The `PhoneNumber` struct encapsulates parsing, validation, and formatting of pho

Key features:

- Implements `IStringWithRegexValueObject` for parsing and validation.
- Implements `IRegexValueObject` for parsing and validation.
- Leverages `libphonenumber` for parsing into components.
- Provides implicit conversions to/from string.
- Generates a tel: URI from the number.
Expand Down
2 changes: 1 addition & 1 deletion Tests/PrimitivesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace Dgmjr.Primitives.Tests;

public abstract class PrimitivesTests<TPrimitive, TSelf> : ILog
where TPrimitive : IStringWithRegexValueObject<TPrimitive>
where TPrimitive : IRegexValueObject<TPrimitive>
where TSelf : PrimitivesTests<TPrimitive, TSelf>
{
public ILogger Logger { get; }
Expand Down
9 changes: 9 additions & 0 deletions src/Abstractions/IResourceIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ namespace Dgmjr.Abstractions;

public interface IResourceIdentifier
{
/// <summary>The <see cref="UriComponents.Scheme" /> of the resource identifier (if it exists), <see langword="null" /> or <see cref="string.Empty" /> otherwise.</summary>
string? Scheme { get; }

/// <summary>The <see cref="UriComponents.PathAndQuery" /> of the resource identifier (if it exists), <see langword="null" /> or <see cref="string.Empty" /> otherwise.</summary>
string? PathAndQuery { get; }

/// <summary>
/// "<inheritdoc cref="DoubleSlashes" path="/value" />" iff they were included in the original string, <see langword="null" /> or <see cref="string.Empty" /> otherwise.
/// </summary>
/// <value>//</value>
string? DoubleSlashes { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@ namespace Dgmjr.Abstractions;
public interface IResourceIdentifierWithAuthorityHostPortQueryAndFragment
: IResourceIdentifierWithQueryAndFragment
{
/// <summary>
/// "<inheritdoc cref="DoubleSlashes" path="/value" />" iff they were included in the original string, <see langword="null" /> or <see cref="string.Empty" /> otherwise.
/// </summary>
/// <value>//</value>
string? DoubleSlashes { get; }

/// <summary>
/// The <see cref="System.UriComponents.StrongAuthority" /> (user authentication) component of the resource identifier (if it exists), <see langword="null" /> or <see cref="string.Empty" /> otherwise.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions src/Abstractions/IStringWithRegexValueObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace System;
#if !NETSTANDARD2_0_OR_GREATER
using Validation = global::Validation;
#endif
public interface IStringWithRegexValueObject<TSelf>
public interface IRegexValueObject<TSelf>
: IComparable<TSelf>,
IComparable,
IEquatable<TSelf>,
Expand All @@ -13,7 +13,7 @@ public interface IStringWithRegexValueObject<TSelf>
IParsable<TSelf>,
IUriConvertible<TSelf>
#endif
where TSelf : IStringWithRegexValueObject<TSelf>
where TSelf : IRegexValueObject<TSelf>
{
/// <summary>Gets The value of the value object as a string. Will be <see langword="null" /> or <see cref="string.Empty" /> iff <see cref="IsEmpty" /> == <see langword="true" /></summary>
string Value { get; }
Expand Down
3 changes: 3 additions & 0 deletions src/Dgmjr.Primitives.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,7 @@
<ItemGroup>
<Using Include="Dgmjr.Primitives.Constants" Static="true" />
</ItemGroup>
<ItemGroup>
<PackageTag Include="primitives" />
</ItemGroup>
</Project>
16 changes: 8 additions & 8 deletions src/EmailAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace System.Net.Mail;
)]
[StructLayout(LayoutKind.Auto)]
[EmailAddress.JConverter]
public partial record struct EmailAddress : IStringWithRegexValueObject<EmailAddress>, IFormattable
public partial record struct EmailAddress : IRegexValueObject<EmailAddress>, IFormattable
{
/// <summary>
/// The example value string.
Expand All @@ -60,27 +60,27 @@ public partial record struct EmailAddress : IStringWithRegexValueObject<EmailAdd
/// <summary>
/// Gets the description.
/// </summary>
static string IStringWithRegexValueObject<EmailAddress>.Description => Description;
static string IRegexValueObject<EmailAddress>.Description => Description;

/// <summary>
/// Gets the example value.
/// </summary>
static EmailAddress IStringWithRegexValueObject<EmailAddress>.ExampleValue =>
static EmailAddress IRegexValueObject<EmailAddress>.ExampleValue =>
From(ExampleValueString);

/// <summary>
/// Gets the regex string.
/// </summary>
static string IStringWithRegexValueObject<EmailAddress>.RegexString => RegexString;
static string IRegexValueObject<EmailAddress>.RegexString => RegexString;

public static ExternalDocsTuple ExternalDocs =>
("Email Address", new Uri("https://en.wikipedia.org/wiki/Email_address"));
#else
readonly Regx IStringWithRegexValueObject<EmailAddress>.Regex() => Regex();
readonly Regx IRegexValueObject<EmailAddress>.Regex() => Regex();

readonly string IStringWithRegexValueObject<EmailAddress>.RegexString => RegexString;
readonly string IStringWithRegexValueObject<EmailAddress>.Description => Description;
readonly EmailAddress IStringWithRegexValueObject<EmailAddress>.ExampleValue =>
readonly string IRegexValueObject<EmailAddress>.RegexString => RegexString;
readonly string IRegexValueObject<EmailAddress>.Description => Description;
readonly EmailAddress IRegexValueObject<EmailAddress>.ExampleValue =>
From(ExampleValueString);
#endif

Expand Down
14 changes: 7 additions & 7 deletions src/ObjectId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ namespace System;
)]
// [RegexDto(ObjectId.RegexString)]
public readonly partial record struct ObjectId
: IStringWithRegexValueObject<ObjectId>,
: IRegexValueObject<ObjectId>,
IComparable<ObjectId>,
IComparable,
IEquatable<ObjectId>
{
public const string Description =
"A ObjectId is a 24-digit (96-bit) hexadecimal string that uniquely identifies an object in a database";
#if NET6_0_OR_GREATER
static string IStringWithRegexValueObject<ObjectId>.Description => Description;
static string IRegexValueObject<ObjectId>.Description => Description;
#endif
public const string EmptyValue = "000000000000000000000000";
public const int Length = 24;
Expand Down Expand Up @@ -77,7 +77,7 @@ public readonly partial record struct ObjectId
public string OriginalString { get; init; }

#if NET6_0_OR_GREATER
static string IStringWithRegexValueObject<ObjectId>.RegexString => RegexString;
static string IRegexValueObject<ObjectId>.RegexString => RegexString;
#endif

public const string ExampleValueString = "abcdef0123456789abcdef01";
Expand All @@ -88,13 +88,13 @@ public readonly partial record struct ObjectId
};

#if !NET6_0_OR_GREATER
readonly Regex IStringWithRegexValueObject<ObjectId>.Regex() => Regex();
readonly Regex IRegexValueObject<ObjectId>.Regex() => Regex();

readonly string IStringWithRegexValueObject<ObjectId>.RegexString => RegexString;
readonly string IRegexValueObject<ObjectId>.RegexString => RegexString;

readonly string IStringWithRegexValueObject<ObjectId>.Description => Description;
readonly string IRegexValueObject<ObjectId>.Description => Description;

readonly ObjectId IStringWithRegexValueObject<ObjectId>.ExampleValue => ExampleValue;
readonly ObjectId IRegexValueObject<ObjectId>.ExampleValue => ExampleValue;
#endif

public static ObjectId Parse(string s) =>
Expand Down
12 changes: 6 additions & 6 deletions src/OpenApiRegistrations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static class OpenApiRegistrations
{
#if NET6_0_OR_GREATER
public static WebApplicationBuilder Describe<T>(this WebApplicationBuilder builder)
where T : IStringWithRegexValueObject<T>
where T : IRegexValueObject<T>
{
builder.Services.Describe<T>();
return builder;
Expand All @@ -32,7 +32,7 @@ public static WebApplicationBuilder Describe<T>(this WebApplicationBuilder build

#if NETSTANDARD2_0_OR_GREATER
public static IServiceCollection Describe<T>(this IServiceCollection services)
where T : IStringWithRegexValueObject<T>
where T : IRegexValueObject<T>
{
services.ConfigureSwaggerGen(options =>
{
Expand Down Expand Up @@ -74,18 +74,18 @@ as IEnumerable<ExternalDocsTuple>
// options.SchemaGeneratorOptions.CustomTypeMappings[typeof(T)] = () => new OpenApiSchema
// {
// Type = "string",
// Pattern = typeof(T).GetRuntimeProperty(nameof(IStringWithRegexValueObject<ObjectId>.RegexString)).GetValue(null) as string,
// Pattern = typeof(T).GetRuntimeProperty(nameof(IRegexValueObject<ObjectId>.RegexString)).GetValue(null) as string,
// Format = typeof(T).Name,
// Description = typeof(T).GetRuntimeProperty(nameof(IStringWithRegexValueObject<ObjectId>.Description)).GetValue(null) as string,
// Example = new OpenApiString(typeof(T).GetRuntimeProperty(nameof(IStringWithRegexValueObject<ObjectId>.ExampleValue)).GetValue(null).ToString())
// Description = typeof(T).GetRuntimeProperty(nameof(IRegexValueObject<ObjectId>.Description)).GetValue(null) as string,
// Example = new OpenApiString(typeof(T).GetRuntimeProperty(nameof(IRegexValueObject<ObjectId>.ExampleValue)).GetValue(null).ToString())
// };
#endif
});
return services;
}
#else
public static IServiceCollection Describe<T>(this IServiceCollection services)
where T : IStringWithRegexValueObject<T>
where T : IRegexValueObject<T>
{
throw new PlatformNotSupportedException("This feature is not supported by this framework. Upgrade to .NET Standard 2.0 or higher to use it.");
}
Expand Down
18 changes: 9 additions & 9 deletions src/PhoneNumber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace System.Domain;
)]
[StructLayout(LayoutKind.Auto)]
[PhoneNumber.JConverter]
public partial record struct PhoneNumber : IStringWithRegexValueObject<PhoneNumber>
public partial record struct PhoneNumber : IRegexValueObject<PhoneNumber>
{
/// <summary>
/// The string that will be prefixed to the number when converting it to a URI
Expand Down Expand Up @@ -86,12 +86,12 @@ public static PhoneNumber FromUri(Uri u) =>
};

#if NET6_0_OR_GREATER
static string IStringWithRegexValueObject<PhoneNumber>.RegexString => RegexString;
static string IStringWithRegexValueObject<PhoneNumber>.Description => Description;
static string IRegexValueObject<PhoneNumber>.RegexString => RegexString;
static string IRegexValueObject<PhoneNumber>.Description => Description;
#else
readonly string IStringWithRegexValueObject<PhoneNumber>.RegexString => RegexString;
readonly string IStringWithRegexValueObject<PhoneNumber>.Description => Description;
readonly PhoneNumber IStringWithRegexValueObject<PhoneNumber>.ExampleValue => ExampleValue;
readonly string IRegexValueObject<PhoneNumber>.RegexString => RegexString;
readonly string IRegexValueObject<PhoneNumber>.Description => Description;
readonly PhoneNumber IRegexValueObject<PhoneNumber>.ExampleValue => ExampleValue;
#endif

public override readonly string ToString() =>
Expand Down Expand Up @@ -134,11 +134,11 @@ or InvalidOperationException
public static partial Regex Regex();
#elif NET6_0_OR_GREATER
public static Regex Regex() => new(RegexString, RegexOptions);
// Regex IStringWithRegexValueObject<PhoneNumber>.RegexString => Regex();
// Regex IRegexValueObject<PhoneNumber>.RegexString => Regex();
#else
private static readonly Regex _regex = new(RegexString, RegexOptions);

readonly Regex IStringWithRegexValueObject<PhoneNumber>.Regex() => _regex;
readonly Regex IRegexValueObject<PhoneNumber>.Regex() => _regex;
#endif

public static implicit operator PhoneNumber?(string? s) =>
Expand Down Expand Up @@ -175,7 +175,7 @@ public static Validation Validate(string s) =>
#else
public static Validation Validate(string s) =>
Util.IsViablePhoneNumber(s)
&& ((IStringWithRegexValueObject<PhoneNumber>)ExampleValue).Regex().IsMatch(s)
&& ((IRegexValueObject<PhoneNumber>)ExampleValue).Regex().IsMatch(s)
? Validation.Ok
: Validation.Invalid("Phone number is not valid.");
#endif
Expand Down
24 changes: 12 additions & 12 deletions src/iri.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ namespace System;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Validation = Vogen.Validation;
using Vogen;
#endif

/// <summary>
/// Represents an "internationalized resource identifier (IRI)"
/// </summary>
/// <summary>Represents an "internationalized resource identifier" (IRI)</summary>
#if NETSTANDARD2_0_OR_GREATER
[RegexDto(_RegexString, RegexOptions: uri._RegexOptions)]
[SystemTextJsonConverter]
[StructLayout(LayoutKind.Auto)]
#endif
[DebuggerDisplay("{ToString()}")]
public readonly partial record struct iri
: IStringWithRegexValueObject<iri>,
: IRegexValueObject<iri>,
IResourceIdentifierWithAuthorityHostPortQueryAndFragment
#if NET7_0_OR_GREATER
,
Expand Down Expand Up @@ -71,16 +71,16 @@ public readonly partial record struct iri

public readonly string Value => ToString();
#if NET6_0_OR_GREATER
static string IStringWithRegexValueObject<iri>.RegexString => RegexString;
static string IStringWithRegexValueObject<iri>.Description => Description;
static iri IStringWithRegexValueObject<iri>.Empty => EmptyStringValue;
static iri IStringWithRegexValueObject<iri>.ExampleValue => new(ExampleStringValue);
static string IRegexValueObject<iri>.RegexString => RegexString;
static string IRegexValueObject<iri>.Description => Description;
static iri IRegexValueObject<iri>.Empty => EmptyStringValue;
static iri IRegexValueObject<iri>.ExampleValue => new(ExampleStringValue);
#else
readonly string IStringWithRegexValueObject<iri>.Description => Description;
readonly iri IStringWithRegexValueObject<iri>.ExampleValue => ExampleStringValue;
readonly string IStringWithRegexValueObject<iri>.RegexString => RegexString;
readonly string IRegexValueObject<iri>.Description => Description;
readonly iri IRegexValueObject<iri>.ExampleValue => ExampleStringValue;
readonly string IRegexValueObject<iri>.RegexString => RegexString;

readonly Regex IStringWithRegexValueObject<iri>.Regex() => Regex();
readonly Regex IRegexValueObject<iri>.Regex() => Regex();
#endif

// public static iri Parse(string iri) => From(iri);
Expand Down
28 changes: 11 additions & 17 deletions src/uri.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,14 @@ namespace System;
#if !NETSTANDARD2_0_OR_GREATER
using Validation = global::Validation;
#endif
/// <summary>
/// Represents an "uniform resource identifier (URI)"
/// </summary>
/// <summary>Represents a "uniform resource identifier" (URI)</summary>
[RegexDto(uri._RegexString, RegexOptions: uri._RegexOptions)]
[uri.JConverter]
[DebuggerDisplay("{ToString()}")]
[StructLayout(LayoutKind.Auto)]
#if NET6_0_OR_GREATER
#endif
public readonly partial record struct uri : IStringWithRegexValueObject<uri>, IResourceIdentifier
public readonly partial record struct uri : IRegexValueObject<uri>, IResourceIdentifier
#if NET7_0_OR_GREATER
,
IUriConvertible<uri>
Expand Down Expand Up @@ -80,22 +78,18 @@ namespace System;

public readonly string Value => ToString();
#if NET6_0_OR_GREATER
static string IStringWithRegexValueObject<uri>.RegexString => RegexString;
static string IStringWithRegexValueObject<uri>.Description => Description;
static uri IStringWithRegexValueObject<uri>.Empty => EmptyStringValue;
static uri IStringWithRegexValueObject<uri>.ExampleValue => new(ExampleStringValue);
static string IRegexValueObject<uri>.RegexString => RegexString;
static string IRegexValueObject<uri>.Description => Description;
static uri IRegexValueObject<uri>.Empty => EmptyStringValue;
static uri IRegexValueObject<uri>.ExampleValue => new(ExampleStringValue);

static uri IStringWithRegexValueObject<uri>.Parse(string s) =>
From(s) with
{
OriginalString = s
};
static uri IRegexValueObject<uri>.Parse(string s) => From(s) with { OriginalString = s };
#else
readonly string IStringWithRegexValueObject<uri>.Description => Description;
readonly uri IStringWithRegexValueObject<uri>.ExampleValue => ExampleStringValue;
readonly string IStringWithRegexValueObject<uri>.RegexString => RegexString;
readonly string IRegexValueObject<uri>.Description => Description;
readonly uri IRegexValueObject<uri>.ExampleValue => ExampleStringValue;
readonly string IRegexValueObject<uri>.RegexString => RegexString;

readonly Regex IStringWithRegexValueObject<uri>.Regex() => Regex();
readonly Regex IRegexValueObject<uri>.Regex() => Regex();
#endif

public readonly Uri Uri => this;
Expand Down
20 changes: 9 additions & 11 deletions src/url.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,13 @@ namespace System;
#if !NETSTANDARD2_0_OR_GREATER
using Validation = global::Validation;
#endif
/// <summary>
/// Represents an "uniform resource locator (URL)"
/// </summary>
/// <summary>Represents a "uniform resource locator" (URL)</summary>
[RegexDto(url._RegexString, RegexOptions: uri._RegexOptions)]
[url.JConverter]
[StructLayout(LayoutKind.Auto)]
[DebuggerDisplay("{ToString()}")]
public readonly partial record struct url
: IStringWithRegexValueObject<url>,
: IRegexValueObject<url>,
IResourceIdentifierWithQueryAndFragment
#if NET7_0_OR_GREATER
,
Expand Down Expand Up @@ -71,15 +69,15 @@ public readonly partial record struct url

public readonly string Value => ToString();
#if NET6_0_OR_GREATER
static string IStringWithRegexValueObject<url>.Description => Description;
static string IStringWithRegexValueObject<url>.RegexString => RegexString;
static url IStringWithRegexValueObject<url>.ExampleValue => ExampleStringValue;
static string IRegexValueObject<url>.Description => Description;
static string IRegexValueObject<url>.RegexString => RegexString;
static url IRegexValueObject<url>.ExampleValue => ExampleStringValue;
#else
readonly string IStringWithRegexValueObject<url>.Description => Description;
readonly url IStringWithRegexValueObject<url>.ExampleValue => ExampleStringValue;
readonly string IStringWithRegexValueObject<url>.RegexString => RegexString;
readonly string IRegexValueObject<url>.Description => Description;
readonly url IRegexValueObject<url>.ExampleValue => ExampleStringValue;
readonly string IRegexValueObject<url>.RegexString => RegexString;

readonly Regex IStringWithRegexValueObject<url>.Regex() => Regex();
readonly Regex IRegexValueObject<url>.Regex() => Regex();
#endif

public readonly Uri Uri => this;
Expand Down
Loading

0 comments on commit c9a91d3

Please sign in to comment.