Skip to content

ByteCapacity refactor #101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .ci/windows/versions.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"erlang": "27.1.2",
"rabbitmq": "4.0.4"
"erlang": "27.2",
"rabbitmq": "4.0.5"
}
10 changes: 9 additions & 1 deletion .github/workflows/wf_build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
path: |
~/.nuget/packages
~/AppData/Local/NuGet/v3-cache
key: ${{ runner.os }}-v0-nuget-${{ hashFiles('**/*.csproj') }}
key: ${{ runner.os }}-v0-nuget-${{ hashFiles('**/*.csproj','Directory.Packages.props') }}
restore-keys: |
${{ runner.os }}-v0-nuget-
- name: Build (Debug)
Expand Down Expand Up @@ -55,6 +55,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/cache@v4
with:
path: |
~/.nuget/packages
~/.local/share/NuGet/v3-cache
key: ${{ runner.os }}-v0-nuget-${{ hashFiles('**/*.csproj','Directory.Packages.props') }}
restore-keys: |
${{ runner.os }}-v0-nuget-
- name: Build (Debug)
run: dotnet build ${{ github.workspace }}/Build.csproj
- name: Verify
Expand Down
1 change: 0 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<IncludeSymbols>true</IncludeSymbols>
<IsPackable>false</IsPackable>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<PackageId>$(AssemblyName)</PackageId>
<PackageProjectUrl>https://github.com/rabbitmq/rabbitmq-amqp-dotnet-client</PackageProjectUrl>
<PackageReleaseNotes>https://github.com/rabbitmq/rabbitmq-amqp-dotnet-client/releases/latest</PackageReleaseNotes>
Expand Down
130 changes: 105 additions & 25 deletions RabbitMQ.AMQP.Client/ByteCapacity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,63 +7,114 @@

namespace RabbitMQ.AMQP.Client
{
public partial class ByteCapacity : IEquatable<ByteCapacity>
/// <summary>
/// Class for specifying a binary size, with units
/// </summary>
public class ByteCapacity : IEquatable<ByteCapacity>
{
private const int KilobytesMultiplier = 1000;
private const int MegabytesMultiplier = 1000 * 1000;
private const int GigabytesMultiplier = 1000 * 1000 * 1000;
private const long TerabytesMultiplier = 1000L * 1000L * 1000L * 1000L;

private static readonly Regex s_sizeRegex = new(@"^(\d+)([kKmMgGtTpP]?[bB]?)$", RegexOptions.Compiled);

private readonly long _bytes;
private string _input;

private ByteCapacity(long bytes, string input)
/// <summary>
///
/// </summary>
/// <param name="bytes"></param>
public ByteCapacity(long bytes)
{
_input = input;
_bytes = bytes;
}

private ByteCapacity(long bytes) : this(bytes, bytes.ToString())
{
}

private const int KilobytesMultiplier = 1000;
private const int MegabytesMultiplier = 1000 * 1000;
private const int GigabytesMultiplier = 1000 * 1000 * 1000;
private const long TerabytesMultiplier = 1000L * 1000L * 1000L * 1000L;

/// <summary>
/// Specify an amount in bytes
/// </summary>
/// <param name="bytes">The size, in bytes</param>
/// <returns><see cref="ByteCapacity"/></returns>
public static ByteCapacity B(long bytes)
{
return new ByteCapacity(bytes);
}

public static ByteCapacity Kb(long megabytes)
/// <summary>
/// Specify an amount, in kilobytes
/// </summary>
/// <param name="kilobytes">The size, in kilobytes</param>
/// <returns><see cref="ByteCapacity"/></returns>
public static ByteCapacity Kb(long kilobytes)
{
return new ByteCapacity(megabytes * KilobytesMultiplier);
return new ByteCapacity(kilobytes * KilobytesMultiplier);
}

/// <summary>
/// Specify an amount, in megabytes
/// </summary>
/// <param name="megabytes">The size, in megabytes</param>
/// <returns><see cref="ByteCapacity"/></returns>
public static ByteCapacity Mb(long megabytes)
{
return new ByteCapacity(megabytes * MegabytesMultiplier);
}

/// <summary>
/// Specify an amount, in gigabytes
/// </summary>
/// <param name="gigabytes">The size, in gigabytes</param>
/// <returns><see cref="ByteCapacity"/></returns>
public static ByteCapacity Gb(long gigabytes)
{
return new ByteCapacity(gigabytes * GigabytesMultiplier);
}

/// <summary>
/// Specify an amount, in terabytes
/// </summary>
/// <param name="terabytes">The size, in terabytes</param>
/// <returns><see cref="ByteCapacity"/></returns>
public static ByteCapacity Tb(long terabytes)
{
return new ByteCapacity(terabytes * TerabytesMultiplier);
}

private static readonly Regex s_sizeRegex = new Regex(@"^(\d+)([kKmMgGtTpP]?[bB]?)$", RegexOptions.Compiled);
/// <summary>
/// Explicitly convert a string into a <see cref="ByteCapacity"/>
/// </summary>
/// <param name="value">The value, as string</param>
/// <returns><see cref="ByteCapacity"/></returns>
public static explicit operator ByteCapacity(string value)
{
return Parse(value);
}

/// <summary>
/// Cast a <see cref="ByteCapacity"/> into a <see cref="long"/>
/// </summary>
/// <param name="value">The value</param>
/// <returns>The total number of bytes.</returns>
public static implicit operator long(ByteCapacity value)
{
return value._bytes;
}

public static ByteCapacity From(string value)
/// <summary>
/// Parse a string into a <see cref="ByteCapacity"/>
/// </summary>
/// <param name="value">The value, as string</param>
/// <returns><see cref="ByteCapacity"/></returns>
public static ByteCapacity Parse(string value)
{
Match match = s_sizeRegex.Match(value);
if (!match.Success)
{
throw new ArgumentException("Invalid capacity size format.", nameof(value));
}

var size = long.Parse(match.Groups[1].Value);
var unit = match.Groups[2].Value.ToLower();
long size = long.Parse(match.Groups[1].Value);
string unit = match.Groups[2].Value.ToLowerInvariant();

return unit switch
{
Expand All @@ -75,24 +126,53 @@ public static ByteCapacity From(string value)
};
}

public long ToBytes()
/// <summary>
/// Returns a value indicating whether this instance is equal to a specified <see cref="ByteCapacity"/> value.
/// </summary>
/// <param name="obj">An object to compare with this instance.</param>
/// <returns>true if obj is an instance of <see cref="ByteCapacity"/>and equals the value of this instance; otherwise, false.</returns>
public override bool Equals(object? obj)
{
return _bytes;
if (obj is null)
{
return false;
}

if (ReferenceEquals(this, obj))
{
return true;
}

return Equals(obj as ByteCapacity);
}

public bool Equals(ByteCapacity? other)
/// <summary>
/// Returns a value indicating whether this instance is equal to a specified <see cref="ByteCapacity"/> value.
/// </summary>
/// <param name="obj">An object to compare with this instance.</param>
/// <returns>true if obj has the same value as this instance; otherwise, false.</returns>
public bool Equals(ByteCapacity? obj)
{
if (ReferenceEquals(null, other))
if (obj is null)
{
return false;
}

if (ReferenceEquals(this, other))
if (ReferenceEquals(this, obj))
{
return true;
}

return _bytes == other._bytes;
return _bytes == obj._bytes;
}

/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return _bytes.GetHashCode();
}
}
}
8 changes: 4 additions & 4 deletions RabbitMQ.AMQP.Client/Impl/AmqpQueueSpecification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,8 @@ public IQueueSpecification OverflowStrategy(OverFlowStrategy overflow)

public IQueueSpecification MaxLengthBytes(ByteCapacity maxLengthBytes)
{
Utils.ValidatePositive("Max length", maxLengthBytes.ToBytes());
_queueArguments["x-max-length-bytes"] = maxLengthBytes.ToBytes();
Utils.ValidatePositive("Max length", maxLengthBytes);
_queueArguments["x-max-length-bytes"] = (long)maxLengthBytes;
return this;
}

Expand Down Expand Up @@ -385,8 +385,8 @@ public IStreamSpecification MaxAge(TimeSpan maxAge)

public IStreamSpecification MaxSegmentSizeBytes(ByteCapacity maxSegmentSize)
{
Utils.ValidatePositive("x-stream-max-segment-size-bytes", maxSegmentSize.ToBytes());
_parent._queueArguments["x-stream-max-segment-size-bytes"] = maxSegmentSize.ToBytes();
Utils.ValidatePositive("x-stream-max-segment-size-bytes", maxSegmentSize);
_parent._queueArguments["x-stream-max-segment-size-bytes"] = (long)maxSegmentSize;
return this;
}

Expand Down
12 changes: 8 additions & 4 deletions RabbitMQ.AMQP.Client/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const RabbitMQ.AMQP.Client.Consts.Queues = "queues" -> string!
const RabbitMQ.AMQP.Client.MetricsReporter.MeterName = "RabbitMQ.Amqp" -> string!
const RabbitMQ.AMQP.Client.MetricsReporter.MetricPrefix = "rabbitmq.amqp" -> string!
override RabbitMQ.AMQP.Client.BackOffDelayPolicy.ToString() -> string!
override RabbitMQ.AMQP.Client.ByteCapacity.Equals(object? obj) -> bool
override RabbitMQ.AMQP.Client.ByteCapacity.GetHashCode() -> int
override RabbitMQ.AMQP.Client.ClusterConnectionSettings.Equals(object? obj) -> bool
override RabbitMQ.AMQP.Client.ClusterConnectionSettings.GetHashCode() -> int
override RabbitMQ.AMQP.Client.ConnectionSettings.Equals(object? obj) -> bool
Expand Down Expand Up @@ -48,8 +50,8 @@ RabbitMQ.AMQP.Client.BackOffDelayPolicy.Reset() -> void
RabbitMQ.AMQP.Client.BadRequestException
RabbitMQ.AMQP.Client.BadRequestException.BadRequestException(string! message) -> void
RabbitMQ.AMQP.Client.ByteCapacity
RabbitMQ.AMQP.Client.ByteCapacity.Equals(RabbitMQ.AMQP.Client.ByteCapacity? other) -> bool
RabbitMQ.AMQP.Client.ByteCapacity.ToBytes() -> long
RabbitMQ.AMQP.Client.ByteCapacity.ByteCapacity(long bytes) -> void
RabbitMQ.AMQP.Client.ByteCapacity.Equals(RabbitMQ.AMQP.Client.ByteCapacity? obj) -> bool
RabbitMQ.AMQP.Client.ClassicQueueMode
RabbitMQ.AMQP.Client.ClassicQueueMode.Default = 0 -> RabbitMQ.AMQP.Client.ClassicQueueMode
RabbitMQ.AMQP.Client.ClassicQueueMode.Lazy = 1 -> RabbitMQ.AMQP.Client.ClassicQueueMode
Expand Down Expand Up @@ -762,10 +764,12 @@ RabbitMQ.AMQP.Client.TlsSettings.RemoteCertificateValidationCallback.set -> void
RabbitMQ.AMQP.Client.TlsSettings.TlsSettings() -> void
RabbitMQ.AMQP.Client.TlsSettings.TlsSettings(System.Security.Authentication.SslProtocols protocols) -> void
static RabbitMQ.AMQP.Client.ByteCapacity.B(long bytes) -> RabbitMQ.AMQP.Client.ByteCapacity!
static RabbitMQ.AMQP.Client.ByteCapacity.From(string! value) -> RabbitMQ.AMQP.Client.ByteCapacity!
static RabbitMQ.AMQP.Client.ByteCapacity.explicit operator RabbitMQ.AMQP.Client.ByteCapacity!(string! value) -> RabbitMQ.AMQP.Client.ByteCapacity!
static RabbitMQ.AMQP.Client.ByteCapacity.Gb(long gigabytes) -> RabbitMQ.AMQP.Client.ByteCapacity!
static RabbitMQ.AMQP.Client.ByteCapacity.Kb(long megabytes) -> RabbitMQ.AMQP.Client.ByteCapacity!
static RabbitMQ.AMQP.Client.ByteCapacity.implicit operator long(RabbitMQ.AMQP.Client.ByteCapacity! value) -> long
static RabbitMQ.AMQP.Client.ByteCapacity.Kb(long kilobytes) -> RabbitMQ.AMQP.Client.ByteCapacity!
static RabbitMQ.AMQP.Client.ByteCapacity.Mb(long megabytes) -> RabbitMQ.AMQP.Client.ByteCapacity!
static RabbitMQ.AMQP.Client.ByteCapacity.Parse(string! value) -> RabbitMQ.AMQP.Client.ByteCapacity!
static RabbitMQ.AMQP.Client.ByteCapacity.Tb(long terabytes) -> RabbitMQ.AMQP.Client.ByteCapacity!
static RabbitMQ.AMQP.Client.ConnectionSettings.ProcessUriSegmentsForVirtualHost(System.Uri! uri) -> string!
static RabbitMQ.AMQP.Client.ConnectionSettings.ProcessUserInfo(System.Uri! uri) -> (string? user, string? password)
Expand Down
1 change: 1 addition & 0 deletions RabbitMQ.AMQP.Client/RabbitMQ.AMQP.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
-->
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);CS1591</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
14 changes: 7 additions & 7 deletions Tests/ByteCapacityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class ByteCapacityTests
[InlineData("23TB", 23 * 1000L * 1000L * 1000L * 1000L)]
public void FromShouldReturnTheCorrectBytesValues(string input, long expectedBytes)
{
Assert.Equal(expectedBytes, ByteCapacity.From(input).ToBytes());
Assert.Equal(expectedBytes, (ByteCapacity)input);
}

[Theory]
Expand All @@ -38,17 +38,17 @@ public void FromShouldReturnTheCorrectBytesValues(string input, long expectedByt

public void FromShouldThrowExceptionWhenInvalidInput(string input)
{
Assert.Throws<ArgumentException>(() => ByteCapacity.From(input));
Assert.Throws<ArgumentException>(() => (ByteCapacity)input);
}

[Fact]
public void ByteCapacityShouldReturnTheValidBytes()
{
Assert.Equal(99, ByteCapacity.B(99).ToBytes());
Assert.Equal(76000, ByteCapacity.Kb(76).ToBytes());
Assert.Equal(789 * 1000 * 1000, ByteCapacity.Mb(789).ToBytes());
Assert.Equal(134 * 1000L * 1000L * 1000L, ByteCapacity.Gb(134).ToBytes());
Assert.Equal(12 * 1000L * 1000L * 1000L * 1000L, ByteCapacity.Tb(12).ToBytes());
Assert.Equal(99, (long)ByteCapacity.B(99));
Assert.Equal(76000, (long)ByteCapacity.Kb(76));
Assert.Equal(789 * 1000 * 1000, (long)ByteCapacity.Mb(789));
Assert.Equal(134 * 1000L * 1000L * 1000L, (long)ByteCapacity.Gb(134));
Assert.Equal(12 * 1000L * 1000L * 1000L * 1000L, (long)ByteCapacity.Tb(12));
}

[Theory]
Expand Down
1 change: 1 addition & 0 deletions Tests/Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<IsTestProject>true</IsTestProject>
<Nullable>enable</Nullable>
<SignAssembly>True</SignAssembly>
<NoWarn>$(NoWarn);CS1591</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
Loading