• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

loresoft / FluentCommand / 15638433985

13 Jun 2025 03:39PM UTC coverage: 54.709% (+0.5%) from 54.174%
15638433985

push

github

pwelter34
misc updates

1692 of 3584 branches covered (47.21%)

Branch coverage included in aggregate %.

114 of 156 new or added lines in 9 files covered. (73.08%)

15 existing lines in 5 files now uncovered.

4291 of 7352 relevant lines covered (58.37%)

233.09 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.63
/src/FluentCommand/ConcurrencyToken.cs
1
using FluentCommand.Internal;
2

3
namespace FluentCommand;
4

5
/// <summary>
6
/// A structure to hold concurrency token
7
/// </summary>
8
/// <remarks>
9
/// This structure is commonly used to represent SQL Server <c>rowversion</c> (also known as <c>timestamp</c>) columns for optimistic concurrency control.
10
/// </remarks>
11
public readonly struct ConcurrencyToken : IEquatable<ConcurrencyToken>
12
{
13
    /// <summary>
14
    /// The default empty token
15
    /// </summary>
16
    public static readonly ConcurrencyToken None = new([]);
1✔
17

18
    /// <summary>
19
    /// Gets the underlying value of the token.
20
    /// </summary>
21
    /// <value>
22
    /// The underlying value of the token.
23
    /// </value>
24
    public byte[] Value { get; }
45✔
25

26
    /// <summary>
27
    /// Initializes a new instance of the <see cref="ConcurrencyToken"/> struct.
28
    /// </summary>
29
    /// <param name="value">The value.</param>
30
    public ConcurrencyToken(byte[] value)
31
    {
32
        Value = value ?? [];
145✔
33
    }
145✔
34

35
    /// <summary>
36
    /// Initializes a new instance of the <see cref="ConcurrencyToken"/> struct.
37
    /// </summary>
38
    /// <param name="value">The value.</param>
39
    public ConcurrencyToken(string value)
40
    {
41
#if NET5_0_OR_GREATER
42
        Value = string.IsNullOrEmpty(value) ? [] : Convert.FromHexString(value);
3✔
43
#else
44
        Value = string.IsNullOrEmpty(value) ? [] : FromHexString(value);
45
#endif
46
    }
3✔
47

48
    /// <summary>
49
    /// Initializes a new instance of the <see cref="ConcurrencyToken"/> struct from a <see cref="long"/> value.
50
    /// </summary>
51
    /// <param name="value">The long value.</param>
52
    public ConcurrencyToken(long value)
53
    {
54
        Value = BitConverter.GetBytes(value);
2✔
55
    }
2✔
56

57
    /// <summary>
58
    /// Initializes a new instance of the <see cref="ConcurrencyToken"/> struct from a <see cref="ulong"/> value.
59
    /// </summary>
60
    /// <param name="value">The ulong value.</param>
61
    public ConcurrencyToken(ulong value)
62
    {
63
        Value = BitConverter.GetBytes(value);
2✔
64
    }
2✔
65

66
    /// <inheritdoc />
67
    public override string ToString()
68
    {
69
#if NET5_0_OR_GREATER
70
        return Value != null ? Convert.ToHexString(Value) : null;
2!
71
#else
72
        return Value != null ? ToHexString(Value) : null;
73
#endif
74
    }
75

76
    /// <inheritdoc />
77
    public override bool Equals(object obj)
78
    {
79
        return obj is ConcurrencyToken token && Equals(token);
×
80
    }
81

82
    /// <inheritdoc />
83
    public bool Equals(ConcurrencyToken other)
84
    {
85
        return EqualityComparer<byte[]>.Default.Equals(Value, other.Value);
6✔
86
    }
87

88
    /// <inheritdoc />
89
    public override int GetHashCode()
90
    {
91
        return Value.GetHashCode();
×
92
    }
93

94

95
    /// <summary>
96
    /// Performs an implicit conversion from <see cref="ConcurrencyToken"/> to byte array.
97
    /// </summary>
98
    /// <param name="token">The concurrency token.</param>
99
    /// <returns>
100
    /// The result of the conversion.
101
    /// </returns>
102
    public static implicit operator byte[](ConcurrencyToken token) => token.Value;
1✔
103

104
    /// <summary>
105
    /// Performs an implicit conversion from <see cref="ConcurrencyToken"/> to <see cref="System.String"/>.
106
    /// </summary>
107
    /// <param name="token">The concurrency token.</param>
108
    /// <returns>
109
    /// The result of the conversion.
110
    /// </returns>
111
    public static implicit operator string(ConcurrencyToken token) => token.ToString();
1✔
112

113
    /// <summary>
114
    /// Performs an implicit conversion from <see cref="ConcurrencyToken"/> to <see cref="long"/>.
115
    /// </summary>
116
    /// <param name="token">The concurrency token.</param>
117
    /// <returns>
118
    /// The result of the conversion.
119
    /// </returns>
120
    public static implicit operator long(ConcurrencyToken token)
121
    {
122
        if (token.Value == null || token.Value.Length == 0)
2!
NEW
123
            return 0L;
×
124

125
        if (token.Value.Length < sizeof(long))
2✔
126
            throw new InvalidCastException("The token value is too short to convert to a long.");
1✔
127

128
        // Use little-endian to match BitConverter default
129
        return BitConverter.ToInt64(token.Value, 0);
1✔
130
    }
131

132
    /// <summary>
133
    /// Performs an implicit conversion from <see cref="ConcurrencyToken"/> to <see cref="ulong"/>.
134
    /// </summary>
135
    /// <param name="token">The concurrency token.</param>
136
    /// <returns>
137
    /// The result of the conversion.
138
    /// </returns>
139
    public static implicit operator ulong(ConcurrencyToken token)
140
    {
141
        if (token.Value == null || token.Value.Length == 0)
2!
NEW
142
            return 0UL;
×
143

144
        if (token.Value.Length < sizeof(ulong))
2✔
145
            throw new InvalidCastException("The token value is too short to convert to a ulong.");
1✔
146

147
        // Use little-endian to match BitConverter default
148
        return BitConverter.ToUInt64(token.Value, 0);
1✔
149
    }
150

151

152
    /// <summary>
153
    /// Performs an implicit conversion from byte array to <see cref="ConcurrencyToken"/>.
154
    /// </summary>
155
    /// <param name="token">The concurrency token.</param>
156
    /// <returns>
157
    /// The result of the conversion.
158
    /// </returns>
159
    public static implicit operator ConcurrencyToken(byte[] token) => new(token);
53✔
160

161
    /// <summary>
162
    /// Performs an implicit conversion from <see cref="System.String"/> to <see cref="ConcurrencyToken"/>.
163
    /// </summary>
164
    /// <param name="token">The concurrency token.</param>
165
    /// <returns>
166
    /// The result of the conversion.
167
    /// </returns>
168
    public static implicit operator ConcurrencyToken(string token) => new(token);
1✔
169

170
    /// <summary>
171
    /// Performs an implicit conversion from <see cref="long"/> to <see cref="ConcurrencyToken"/>.
172
    /// </summary>
173
    /// <param name="value">The long value.</param>
174
    /// <returns>
175
    /// The result of the conversion.
176
    /// </returns>
177
    public static implicit operator ConcurrencyToken(long value)
178
    {
179
        var bytes = BitConverter.GetBytes(value);
1✔
180
        return new ConcurrencyToken(bytes);
1✔
181
    }
182

183
    /// <summary>
184
    /// Performs an implicit conversion from <see cref="ulong"/> to <see cref="ConcurrencyToken"/>.
185
    /// </summary>
186
    /// <param name="value">The ulong value.</param>
187
    /// <returns>
188
    /// The result of the conversion.
189
    /// </returns>
190
    public static implicit operator ConcurrencyToken(ulong value)
191
    {
192
        var bytes = BitConverter.GetBytes(value);
1✔
193
        return new ConcurrencyToken(bytes);
1✔
194
    }
195

196

197
    /// <summary>
198
    /// Determines whether two <see cref="ConcurrencyToken"/> instances are equal.
199
    /// </summary>
200
    /// <param name="left">The first <see cref="ConcurrencyToken"/> to compare.</param>
201
    /// <param name="right">The second <see cref="ConcurrencyToken"/> to compare.</param>
202
    /// <returns>
203
    /// <see langword="true"/> if the two <see cref="ConcurrencyToken"/> instances are equal; otherwise, <see langword="false"/>.
204
    /// </returns>
205
    public static bool operator ==(ConcurrencyToken left, ConcurrencyToken right) => left.Equals(right);
4✔
206

207
    /// <summary>
208
    /// Determines whether two <see cref="ConcurrencyToken"/> instances are not equal.
209
    /// </summary>
210
    /// <param name="left">The first <see cref="ConcurrencyToken"/> to compare.</param>
211
    /// <param name="right">The second <see cref="ConcurrencyToken"/> to compare.</param>
212
    /// <returns>
213
    /// <see langword="true"/> if the two <see cref="ConcurrencyToken"/> instances are not equal; otherwise, <see langword="false"/>.
214
    /// </returns>
215
    public static bool operator !=(ConcurrencyToken left, ConcurrencyToken right) => !(left == right);
2✔
216

217

218
#if NETSTANDARD2_0
219
    private static string ToHexString(byte[] bytes)
220
    {
221
        var hex = StringBuilderCache.Acquire(bytes.Length * 2);
222

223
        foreach (var b in bytes)
224
            hex.Append(b.ToString("X2"));
225

226
        return StringBuilderCache.ToString(hex);
227
    }
228

229
    private static byte[] FromHexString(string hexString)
230
    {
231
        var hexLength = hexString.Length;
232
        var bytes = new byte[hexLength / 2];
233

234
        for (var i = 0; i < hexLength; i += 2)
235
            bytes[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
236

237
        return bytes;
238
    }
239
#endif
240
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc