diff --git a/src/NATS.Client.ObjectStore/Models/ObjectMetadata.cs b/src/NATS.Client.ObjectStore/Models/ObjectMetadata.cs
index 4a3e94259..92b199250 100644
--- a/src/NATS.Client.ObjectStore/Models/ObjectMetadata.cs
+++ b/src/NATS.Client.ObjectStore/Models/ObjectMetadata.cs
@@ -35,11 +35,12 @@ public record ObjectMetadata
public string? Nuid { get; set; }
///
- /// Max chunk size
+ /// The size of the object in bytes.
+ /// It only includes the size of the object itself, not the metadata.
///
[JsonPropertyName("size")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
- public int Size { get; set; }
+ public ulong Size { get; set; }
///
/// Modified timestamp
@@ -53,7 +54,7 @@ public record ObjectMetadata
///
[JsonPropertyName("chunks")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
- public int Chunks { get; set; }
+ public uint Chunks { get; set; }
///
/// Object digest
diff --git a/src/NATS.Client.ObjectStore/NatsObjStore.cs b/src/NATS.Client.ObjectStore/NatsObjStore.cs
index 759d0f0b1..befdca53c 100644
--- a/src/NATS.Client.ObjectStore/NatsObjStore.cs
+++ b/src/NATS.Client.ObjectStore/NatsObjStore.cs
@@ -83,7 +83,7 @@ public async ValueTask GetAsync(string key, Stream stream, bool
string digest;
var chunks = 0;
- var size = 0;
+ ulong size = 0;
using (var sha256 = SHA256.Create())
{
#if NETSTANDARD2_0
@@ -107,7 +107,7 @@ public async ValueTask GetAsync(string key, Stream stream, bool
{
using var memoryOwner = msg.Data;
chunks++;
- size += memoryOwner.Memory.Length;
+ size += (ulong)memoryOwner.Memory.Length;
#if NETSTANDARD2_0
var segment = memoryOwner.DangerousGetArray();
await hashedStream.WriteAsync(segment.Array, segment.Offset, segment.Count, cancellationToken);
@@ -182,8 +182,8 @@ public async ValueTask PutAsync(ObjectMetadata meta, Stream stre
meta.Options.MaxChunkSize = DefaultChunkSize;
}
- var size = 0;
- var chunks = 0;
+ ulong size = 0;
+ uint chunks = 0;
var chunkSize = meta.Options.MaxChunkSize.Value;
string digest;
@@ -250,7 +250,7 @@ public async ValueTask PutAsync(ObjectMetadata meta, Stream stre
if (currentChunkSize > 0)
{
- size += currentChunkSize;
+ size += (ulong)currentChunkSize;
chunks++;
}
diff --git a/tests/NATS.Client.ObjectStore.Tests/ObjectStoreTest.cs b/tests/NATS.Client.ObjectStore.Tests/ObjectStoreTest.cs
index acbe86ecf..6fe6634b7 100644
--- a/tests/NATS.Client.ObjectStore.Tests/ObjectStoreTest.cs
+++ b/tests/NATS.Client.ObjectStore.Tests/ObjectStoreTest.cs
@@ -82,7 +82,7 @@ public async Task Put_chunks()
Assert.Equal($"SHA-256={sha}", data.Digest);
Assert.Equal(chunks, data.Chunks);
- Assert.Equal(size, data.Size);
+ Assert.Equal((ulong)size, data.Size);
}
// buffer with smaller last chunk
@@ -102,7 +102,7 @@ public async Task Put_chunks()
Assert.Equal($"SHA-256={sha}", data.Digest);
Assert.Equal(chunks, data.Chunks);
- Assert.Equal(size, data.Size);
+ Assert.Equal((ulong)size, data.Size);
}
// Object name checks
@@ -195,7 +195,7 @@ public async Task Delete_object()
await store.PutAsync("k1", new byte[] { 65, 66, 67 }, cancellationToken);
var info = await store.GetInfoAsync("k1", cancellationToken: cancellationToken);
- Assert.Equal(3, info.Size);
+ Assert.Equal(3UL, info.Size);
var bytes = await store.GetBytesAsync("k1", cancellationToken);
Assert.Equal(bytes, new byte[] { 65, 66, 67 });
@@ -207,8 +207,8 @@ public async Task Delete_object()
var info2 = await store.GetInfoAsync("k1", showDeleted: true, cancellationToken: cancellationToken);
Assert.True(info2.Deleted);
- Assert.Equal(0, info2.Size);
- Assert.Equal(0, info2.Chunks);
+ Assert.Equal(0UL, info2.Size);
+ Assert.Equal(0U, info2.Chunks);
Assert.Equal(string.Empty, info2.Digest);
// Put again
@@ -622,4 +622,45 @@ await Assert.ThrowsAsync(async () =>
await b1.GetBytesAsync("name1", cancellationToken: cancellationToken);
});
}
+
+ [Fact]
+ public async Task Metadata_field_types_match_spec()
+ {
+ var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
+ var cancellationToken = cts.Token;
+
+ await using var server = await NatsServerProcess.StartAsync();
+ await using var nats = new NatsConnection(new NatsOpts { Url = server.Url });
+ var js = new NatsJSContext(nats);
+ var obj = new NatsObjContext(js);
+
+ var store = await obj.CreateObjectStoreAsync(new NatsObjConfig("b1"), cancellationToken);
+
+ // Test that Size property is ulong (uint64 in NATS spec)
+ var metadata = new ObjectMetadata { Name = "test" };
+ metadata.Size = ulong.MaxValue; // Should compile without error
+ Assert.Equal(18446744073709551615UL, metadata.Size);
+
+ // Test that Chunks property is uint (uint32 in NATS spec)
+ metadata.Chunks = uint.MaxValue; // Should compile without error
+ Assert.Equal(4294967295U, metadata.Chunks);
+
+ // Test with actual object metadata from store
+ await store.PutAsync("k1", new byte[] { 1, 2, 3 }, cancellationToken: cancellationToken);
+ var info = await store.GetInfoAsync("k1", cancellationToken: cancellationToken);
+
+ // Verify Size is ulong
+#pragma warning disable IDE0007
+ // ReSharper disable once SuggestVarOrType_BuiltInTypes
+ ulong size = info.Size; // Should compile without error
+#pragma warning restore IDE0007
+ Assert.Equal(3UL, size);
+
+ // Verify Chunks is uint
+#pragma warning disable IDE0007
+ // ReSharper disable once SuggestVarOrType_BuiltInTypes
+ uint chunks = info.Chunks; // Should compile without error
+#pragma warning restore IDE0007
+ Assert.Equal(1U, chunks);
+ }
}
diff --git a/tests/NATS.Client.ObjectStore.Tests/WatcherTest.cs b/tests/NATS.Client.ObjectStore.Tests/WatcherTest.cs
index ff4268c53..73fa43f0f 100644
--- a/tests/NATS.Client.ObjectStore.Tests/WatcherTest.cs
+++ b/tests/NATS.Client.ObjectStore.Tests/WatcherTest.cs
@@ -30,7 +30,7 @@ public async Task Watcher_test()
{
count++;
signal.Pulse();
- Assert.Equal(count, info.Size);
+ Assert.Equal((ulong)count, info.Size);
if (count == 3)
break;
}