Phone.cs (12044B)
1 using Std; 2 using Std.Clone; 3 using Std.Cmp; 4 using Std.Convert; 5 using Std.Error; 6 using Std.Hashing; 7 using Std.Maybe; 8 using Std.Ops; 9 using Std.Result; 10 using System; 11 using System.Diagnostics; 12 using System.Globalization; 13 using System.Runtime.InteropServices; 14 using System.Text; 15 #region Namespaces 16 namespace Phones { 17 #region Types 18 [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 1, Size = 1)] 19 public readonly struct PhoneErr: ISum<PhoneErr.Tag, PhoneErr.Tag, PhoneErr.Tag, PhoneErr.Tag, PhoneErr.Tag, PhoneErr.Tag>, IClone<PhoneErr>, IEquality<PhoneErr>, IError, IHashable, IInto<PhoneErr> { 20 21 #region Type-level Constructors 22 #endregion 23 24 #region Instance Constructors 25 public PhoneErr() => throw new InvalidOperationException("Parameterless constructor is not allowed to be called!"); 26 PhoneErr(Tag val) => Var = val; 27 #endregion 28 29 #region Type-level Fields 30 public static readonly PhoneErr InvalidMask = new(Tag.InvalidMask); 31 public static readonly PhoneErr InvalidAreaCode = new(Tag.InvalidAreaCode); 32 public static readonly PhoneErr InvalidCentralOfficeCode = new(Tag.InvalidCentralOfficeCode); 33 public static readonly PhoneErr InvalidLineNumber = new(Tag.InvalidLineNumber); 34 public static readonly PhoneErr InvalidLength = new(Tag.InvalidLength); 35 public static readonly PhoneErr InvalidChar = new(Tag.InvalidChar); 36 #endregion 37 38 #region Instance Fields 39 [FieldOffset(0)] public readonly Tag Var; 40 #endregion 41 42 #region Type-level Properties 43 #endregion 44 45 #region Instance Properties 46 public readonly Var6 Variant => (Var6)Var; 47 public readonly Tag Variant0 => Var == Tag.InvalidMask ? Var : throw new InvalidOperationException($"The PhoneErr variant, {Var.ToString()} is not InvalidMask!"); 48 public readonly Tag Variant1 => Var == Tag.InvalidAreaCode ? Var : throw new InvalidOperationException($"The PhoneErr variant, {Var.ToString()} is not InvalidAreaCode!"); 49 public readonly Tag Variant2 => Var == Tag.InvalidCentralOfficeCode ? Var : throw new InvalidOperationException($"The PhoneErr variant, {Var.ToString()} is not InvalidCentralOfficeCode!"); 50 public readonly Tag Variant3 => Var == Tag.InvalidLineNumber ? Var : throw new InvalidOperationException($"The PhoneErr variant, {Var.ToString()} is not InvalidLineNumber!"); 51 public readonly Tag Variant4 => Var == Tag.InvalidLength ? Var : throw new InvalidOperationException($"The PhoneErr variant, {Var.ToString()} is not InvalidLength!"); 52 public readonly Tag Variant5 => Var == Tag.InvalidChar ? Var : throw new InvalidOperationException($"The PhoneErr variant, {Var.ToString()} is not InvalidChar!"); 53 #endregion 54 55 #region Type-level Functions 56 #endregion 57 58 #region Instance Functions 59 public readonly PhoneErr Clone() => this; 60 public readonly bool Equals(in PhoneErr other) => this == other; 61 public override readonly bool Equals(object? _) => false; 62 public override readonly int GetHashCode() => 0; 63 public readonly Unit Hash<THasher>(ref THasher hasher) where THasher: notnull, IHasher => hasher.WriteUnsafe(this); 64 public readonly PhoneErr Into() => this; 65 public readonly string IntoString() => ToString(); 66 readonly string IInto<string>.Into() => IntoString(); 67 public readonly Maybe<IError> Source() => Maybe<IError>.None(); 68 public readonly Maybe<StackTrace> StackTrace() => Maybe<StackTrace>.None(); 69 public override readonly string ToString() => $"PhoneErr({Var.ToString()})"; 70 readonly Result<PhoneErr, Bottom> ITryInto<PhoneErr, Bottom>.TryInto() => new(this); 71 readonly Result<string, Bottom> ITryInto<string, Bottom>.TryInto() => new(ToString()); 72 #endregion 73 74 #region Operators 75 public static bool operator !=(PhoneErr val0, PhoneErr val1) => !(val0 == val1); 76 public static bool operator ==(PhoneErr val0, PhoneErr val1) => val0.Var == val1.Var; 77 #endregion 78 79 #region Types 80 public enum Tag: byte { 81 InvalidMask = byte.MinValue, 82 InvalidAreaCode = 1, 83 InvalidCentralOfficeCode = 2, 84 InvalidLineNumber = 3, 85 InvalidLength = 4, 86 InvalidChar = 5, 87 } 88 #endregion 89 } 90 [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 2, Size = 6)] 91 public readonly struct Phone: IClone<Phone>, IEquality<Phone>, IOrd<Phone>, IHashable, IInto<Phone>, IInto<string>, IInto<ulong>, ITryFrom<Phone, string, PhoneErr>, ITryFrom<Phone, ulong, PhoneErr> { 92 93 #region Type-level Constructors 94 #endregion 95 96 #region Instance Constructors 97 public Phone() => throw new InvalidOperationException("Parameterless constructor is not allowed to be called."); 98 Phone(ushort area, ushort office, ushort line) => (AreaCode, CentralOfficeCode, LineNumber) = (area, office, line); 99 #endregion 100 101 #region Type-level Fields 102 public const byte CountryCode = 1; 103 public const byte InternationalCallPrefix = 11; 104 static readonly Fn<PhoneErr, PhoneErr> fMaskErr = (_) => PhoneErr.InvalidMask; 105 #endregion 106 107 #region Instance Fields 108 [FieldOffset(0)] public readonly ushort AreaCode; 109 [FieldOffset(2)] public readonly ushort CentralOfficeCode; 110 [FieldOffset(4)] public readonly ushort LineNumber; 111 #endregion 112 113 #region Type-level Properties 114 #endregion 115 116 #region Instance Properties 117 #endregion 118 119 #region Type-level Functions 120 public static Result<Phone, PhoneErr> TryFrom(ulong mask) => (mask >> 48) == ulong.MinValue ? TryFromParts((ushort)(mask & 0xFFFFul), (ushort)((mask << 32) >> 48), (ushort)(mask >> 32)).MapErr(fMaskErr) : new(PhoneErr.InvalidMask); 121 public static Result<Phone, PhoneErr> TryFromParts(ushort areaCode, ushort centralOfficeCode, ushort lineNumber) => areaCode is > 199 and < 1000 && areaCode % 100 < 90 ? centralOfficeCode is > 199 and < 1000 && centralOfficeCode % 100 != 11 ? lineNumber < 10000 ? new(new Phone(areaCode, centralOfficeCode, lineNumber)) : new(PhoneErr.InvalidLineNumber) : new(PhoneErr.InvalidCentralOfficeCode) : new(PhoneErr.InvalidAreaCode); 122 public static Result<Phone, PhoneErr> TryFromConcatenatedString(ReadOnlySpan<char> phone) => phone.Length == 10 ? ushort.TryParse(phone[..3], NumberStyles.None, CultureInfo.InvariantCulture, out var area) && ushort.TryParse(phone[3..6], NumberStyles.None, CultureInfo.InvariantCulture, out var office) && ushort.TryParse(phone[6..], NumberStyles.None, CultureInfo.InvariantCulture, out var line) ? TryFromParts(area, office, line) : new(PhoneErr.InvalidChar) : new(PhoneErr.InvalidLength); 123 public static Result<Phone, PhoneErr> TryFromHyphenatedString(ReadOnlySpan<char> phone) => phone.Length == 12 ? phone[3] == '-' && phone[7] == '-' && ushort.TryParse(phone[..3], NumberStyles.None, CultureInfo.InvariantCulture, out var area) && ushort.TryParse(phone[4..7], NumberStyles.None, CultureInfo.InvariantCulture, out var office) && ushort.TryParse(phone[8..], NumberStyles.None, CultureInfo.InvariantCulture, out var line) ? TryFromParts(area, office, line) : new(PhoneErr.InvalidChar) : new(PhoneErr.InvalidLength); 124 public static Result<Phone, PhoneErr> TryFromStandardString(ReadOnlySpan<char> phone) => phone.Length == 14 ? phone[0] == '(' && phone[4] == ')' && phone[5] == ' ' && phone[9] == '-' && ushort.TryParse(phone[1..4], NumberStyles.None, CultureInfo.InvariantCulture, out var area) && ushort.TryParse(phone[6..9], NumberStyles.None, CultureInfo.InvariantCulture, out var office) && ushort.TryParse(phone[10..], NumberStyles.None, CultureInfo.InvariantCulture, out var line) ? TryFromParts(area, office, line) : new(PhoneErr.InvalidChar) : new(PhoneErr.InvalidLength); 125 public static Result<Phone, PhoneErr> TryFromTypicalFormatStringWithCallingCode(ReadOnlySpan<char> phone) => phone.Length == 15 ? phone[0] == '+' && phone[1] == '1' && phone[2] == ' ' && phone[6] == ' ' && phone[10] == '-' && ushort.TryParse(phone[3..6], NumberStyles.None, CultureInfo.InvariantCulture, out var area) && ushort.TryParse(phone[7..10], NumberStyles.None, CultureInfo.InvariantCulture, out var office) && ushort.TryParse(phone[11..], NumberStyles.None, CultureInfo.InvariantCulture, out var line) ? TryFromParts(area, office, line) : new(PhoneErr.InvalidChar) : new(PhoneErr.InvalidLength); 126 public static Result<Phone, PhoneErr> TryFromChars(ReadOnlySpan<char> phone) => phone.Length == 10 ? TryFromConcatenatedString(phone) : phone.Length == 12 ? TryFromHyphenatedString(phone) : phone.Length == 14 ? TryFromStandardString(phone) : phone.Length == 15 ? TryFromTypicalFormatStringWithCallingCode(phone) : new(PhoneErr.InvalidLength); 127 public static Result<Phone, PhoneErr> TryFrom(string phone) => TryFromChars(phone.AsSpan()); 128 #endregion 129 130 #region Instance Functions 131 public readonly Phone Clone() => this; 132 public readonly Ordering Cmp(in Phone other) => IntoMask().CompareTo(other.IntoMask()) switch { 133 > 0 => Ordering.Greater, 134 0 => Ordering.Equivalent, 135 _ => Ordering.Less, 136 }; 137 public readonly bool Equals(in Phone other) => this == other; 138 public override readonly bool Equals(object? _) => false; 139 public override readonly int GetHashCode() => 0; 140 public readonly Unit Hash<THasher>(ref THasher hasher) where THasher: notnull, IHasher => hasher.WriteUnsafe(this); 141 public readonly ulong IntoMask() => (((ulong)LineNumber) << 32) | (((ulong)CentralOfficeCode) << 16) | AreaCode; 142 public readonly Phone Into() => this; 143 public readonly string IntoTypicalFormatStringWithCallingCode() => new StringBuilder("+1 ", 15).Append(AreaCode.ToString("D3")).Append(' ').Append(CentralOfficeCode.ToString("D3")).Append('-').Append(LineNumber.ToString("D4")).ToString(); 144 public readonly string IntoStandardString() => new StringBuilder("(", 14).Append(AreaCode.ToString("D3")).Append(") ").Append(CentralOfficeCode.ToString("D3")).Append('-').Append(LineNumber.ToString("D4")).ToString(); 145 public readonly string IntoHyphenatedString() => new StringBuilder(AreaCode.ToString("D3"), 12).Append('-').Append(CentralOfficeCode.ToString("D3")).Append('-').Append(LineNumber.ToString("D4")).ToString(); 146 public readonly string IntoConcatenatedString() => ToString(); 147 readonly string IInto<string>.Into() => IntoConcatenatedString(); 148 readonly ulong IInto<ulong>.Into() => IntoMask(); 149 public readonly Maybe<Ordering> PartialCmp(in Phone other) => new(Cmp(in other)); 150 public override readonly string ToString() => new StringBuilder(AreaCode.ToString("D3"), 10).Append(CentralOfficeCode.ToString("D3")).Append(LineNumber.ToString("D4")).ToString(); 151 readonly Result<Phone, Bottom> ITryInto<Phone, Bottom>.TryInto() => new(this); 152 readonly Result<string, Bottom> ITryInto<string, Bottom>.TryInto() => new(ToString()); 153 readonly Result<ulong, Bottom> ITryInto<ulong, Bottom>.TryInto() => new(IntoMask()); 154 #endregion 155 156 #region Operators 157 public static bool operator <(Phone val0, Phone val1) => val0.Cmp(in val1).Var == Ordering.Ord.Less; 158 public static bool operator <=(Phone val0, Phone val1) => !(val0 > val1); 159 public static bool operator !=(Phone val0, Phone val1) => !(val0 == val1); 160 public static bool operator ==(Phone val0, Phone val1) => val0.IntoMask() == val1.IntoMask(); 161 public static bool operator >(Phone val0, Phone val1) => val0.Cmp(in val1).Var == Ordering.Ord.Greater; 162 public static bool operator >=(Phone val0, Phone val1) => !(val0 < val1); 163 #endregion 164 165 #region Types 166 #endregion 167 } 168 #endregion 169 170 #region Namespaces 171 #endregion 172 } 173 #endregion