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

 
 
 

Contributors

Languages