Skip to content

modelingevolution/bytes

Repository files navigation

ModelingEvolution.Bytes

NuGet NuGet Downloads Build Status License

A high-performance struct for representing byte sizes with human-readable formatting, arithmetic operations, and full serialization support including dictionary key compatibility.

Features

  • Value type struct - Stack allocated, efficient, and thread-safe
  • Human-readable formatting - Automatically formats as "1.5 KB", "2.3 MB", etc.
  • Full arithmetic support - Addition, subtraction, multiplication, division
  • Implicit conversions - Seamlessly convert between numeric types and Bytes
  • Parsing support - Parse strings like "1.5GB" or "2048"
  • JSON serialization - Full support including use as dictionary keys
  • DataContract support - XML/Binary serialization without ProtoBuf dependencies
  • Zero allocations - Optimized for performance
  • Cross-platform - Targets .NET 8.0 and .NET 9.0

Installation

dotnet add package ModelingEvolution.Bytes

Quick Start

using ModelingEvolution;

// Create from numeric values
Bytes size1 = 1024;                    // 1 KB
Bytes size2 = new Bytes(1536);         // 1.5 KB
Bytes size3 = Bytes.FromFile("file.txt");

// Parse from strings
Bytes size4 = "2.5 GB";                // Implicit conversion
Bytes size5 = Bytes.Parse("100 MB");

// Arithmetic operations
var total = size1 + size2;             // 2.5 KB
var difference = size2 - size1;        // 512 bytes
var scaled = size1 * 4;                // 4 KB
var divided = size2 / 2;               // 768 bytes

// Display formatting
Console.WriteLine(size2);              // "1.5 KB"
long rawBytes = size2;                 // 1536 (implicit conversion)

// Comparisons
if (size1 < size2)
    Console.WriteLine("size1 is smaller");

// Use in collections
var dictionary = new Dictionary<Bytes, string>
{
    [Bytes.Parse("1GB")] = "Large file",
    [Bytes.Parse("1MB")] = "Small file"
};

JSON Serialization

The Bytes struct includes full JSON support with a custom converter that handles both regular serialization and dictionary key scenarios:

using System.Text.Json;

// Simple serialization
var bytes = new Bytes(1024);
var json = JsonSerializer.Serialize(bytes);        // "1024"
var deserialized = JsonSerializer.Deserialize<Bytes>(json);

// As dictionary keys
var dict = new Dictionary<Bytes, string>
{
    [new Bytes(1024)] = "Config",
    [new Bytes(1048576)] = "Data"
};
var dictJson = JsonSerializer.Serialize(dict);
// {"1024":"Config","1048576":"Data"}

// Complex objects
public class FileInfo
{
    public string Name { get; set; }
    public Bytes Size { get; set; }
}

var file = new FileInfo { Name = "video.mp4", Size = "1.5GB" };
var fileJson = JsonSerializer.Serialize(file);

DataContract Serialization

Full support for WCF/XML serialization without ProtoBuf dependencies:

using System.Runtime.Serialization;

[DataContract]
public class Document
{
    [DataMember]
    public string Title { get; set; }
    
    [DataMember]
    public Bytes FileSize { get; set; }
}

// XML serialization works out of the box
var serializer = new DataContractSerializer(typeof(Document));

Protobuf Serialization

Full support for Protobuf-net serialization - works directly with no configuration needed:

using ProtoBuf;

[ProtoContract]
public class FileInfo
{
    [ProtoMember(1)]
    public string Name { get; set; }
    
    [ProtoMember(2)]
    public Bytes Size { get; set; }  // Works directly!
}

// Serialize with Protobuf
var file = new FileInfo { Name = "video.mp4", Size = "1.5GB" };
using var stream = new MemoryStream();
Serializer.Serialize(stream, file);

The Bytes struct uses [DataContract] attributes which Protobuf-net recognizes, enabling seamless serialization.

Parsing Formats

The parser supports various formats with case-insensitive suffixes:

// Numeric values
Bytes.Parse("1024")          // 1024 bytes
Bytes.Parse("1,024")         // 1024 bytes (with thousands separator)

// With size suffixes
Bytes.Parse("1KB")           // 1024 bytes
Bytes.Parse("1 KB")          // 1024 bytes (with space)
Bytes.Parse("1.5MB")         // 1572864 bytes
Bytes.Parse("2.5 GB")        // 2684354560 bytes

// Case insensitive
Bytes.Parse("1kb")           // 1024 bytes
Bytes.Parse("1Kb")           // 1024 bytes

// Supported suffixes
// B, KB, MB, GB, TB, PB, EB

Implicit Conversions

The struct provides extensive implicit conversion support:

// From numeric types to Bytes
Bytes fromInt = 1024;
Bytes fromUint = 2048u;
Bytes fromLong = 1099511627776L;
Bytes fromUlong = 1125899906842624UL;
Bytes fromString = "1.5KB";

// From Bytes to numeric types
int intValue = new Bytes(1024);
uint uintValue = new Bytes(2048);
long longValue = new Bytes(1099511627776L);
ulong ulongValue = new Bytes(1125899906842624L);
double doubleValue = new Bytes(1536);

Performance Considerations

  • Readonly struct: Prevents defensive copies and ensures thread-safety
  • Value type: Stack allocated, no GC pressure
  • Optimized formatting: Caches formatted strings when precision is specified
  • Zero allocations: Parse and format operations minimize allocations

Thread Safety

The Bytes struct is immutable and thread-safe. All operations create new instances rather than modifying existing ones.

Examples

File Size Analysis

var files = Directory.GetFiles(@"C:\MyFolder")
    .Select(f => new { Path = f, Size = Bytes.FromFile(f) })
    .OrderByDescending(f => f.Size)
    .Take(10);

foreach (var file in files)
    Console.WriteLine($"{file.Path}: {file.Size}");

Configuration with Size Limits

public class UploadConfig
{
    public Bytes MaxFileSize { get; set; } = "100MB";
    public Bytes MaxTotalSize { get; set; } = "1GB";
    
    public bool IsAllowed(Bytes fileSize) 
        => fileSize <= MaxFileSize;
}

Progress Tracking

public class DownloadProgress
{
    public Bytes Downloaded { get; private set; }
    public Bytes Total { get; private set; }
    
    public double PercentComplete => 
        (long)Total > 0 ? (double)Downloaded / Total * 100 : 0;
    
    public void Update(Bytes bytesReceived)
    {
        Downloaded += bytesReceived;
        Console.WriteLine($"Downloaded: {Downloaded} / {Total} ({PercentComplete:F1}%)");
    }
}

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For issues and feature requests, please use the GitHub issue tracker.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages