{"id":34837134,"url":"https://github.com/modelingevolution/bytes","last_synced_at":"2026-01-20T17:55:23.326Z","repository":{"id":313060641,"uuid":"1049723220","full_name":"modelingevolution/bytes","owner":"modelingevolution","description":null,"archived":false,"fork":false,"pushed_at":"2025-09-03T20:28:56.000Z","size":54,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-10-03T23:42:33.771Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/modelingevolution.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-03T12:01:50.000Z","updated_at":"2025-09-03T20:28:51.000Z","dependencies_parsed_at":"2025-09-03T18:36:00.039Z","dependency_job_id":null,"html_url":"https://github.com/modelingevolution/bytes","commit_stats":null,"previous_names":["modelingevolution/bytes"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/modelingevolution/bytes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modelingevolution%2Fbytes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modelingevolution%2Fbytes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modelingevolution%2Fbytes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modelingevolution%2Fbytes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/modelingevolution","download_url":"https://codeload.github.com/modelingevolution/bytes/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modelingevolution%2Fbytes/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28032377,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-25T02:00:05.988Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-25T16:07:24.063Z","updated_at":"2025-12-25T16:09:15.158Z","avatar_url":"https://github.com/modelingevolution.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ModelingEvolution.Bytes\n\n[![NuGet](https://img.shields.io/nuget/v/ModelingEvolution.Bytes.svg)](https://www.nuget.org/packages/ModelingEvolution.Bytes/)\n[![NuGet Downloads](https://img.shields.io/nuget/dt/ModelingEvolution.Bytes.svg)](https://www.nuget.org/packages/ModelingEvolution.Bytes/)\n[![Build Status](https://github.com/modelingevolution/bytes/actions/workflows/ci.yml/badge.svg)](https://github.com/modelingevolution/bytes/actions/workflows/ci.yml)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\nA high-performance struct for representing byte sizes with human-readable formatting, arithmetic operations, and full serialization support including dictionary key compatibility.\n\n## Features\n\n- **Value type struct** - Stack allocated, efficient, and thread-safe\n- **Human-readable formatting** - Automatically formats as \"1.5 KB\", \"2.3 MB\", etc.\n- **Full arithmetic support** - Addition, subtraction, multiplication, division\n- **Implicit conversions** - Seamlessly convert between numeric types and Bytes\n- **Parsing support** - Parse strings like \"1.5GB\" or \"2048\"\n- **JSON serialization** - Full support including use as dictionary keys\n- **DataContract support** - XML/Binary serialization without ProtoBuf dependencies\n- **Zero allocations** - Optimized for performance\n- **Cross-platform** - Targets .NET 8.0 and .NET 9.0\n\n## Installation\n\n```bash\ndotnet add package ModelingEvolution.Bytes\n```\n\n## Quick Start\n\n```csharp\nusing ModelingEvolution;\n\n// Create from numeric values\nBytes size1 = 1024;                    // 1 KB\nBytes size2 = new Bytes(1536);         // 1.5 KB\nBytes size3 = Bytes.FromFile(\"file.txt\");\n\n// Parse from strings\nBytes size4 = \"2.5 GB\";                // Implicit conversion\nBytes size5 = Bytes.Parse(\"100 MB\");\n\n// Arithmetic operations\nvar total = size1 + size2;             // 2.5 KB\nvar difference = size2 - size1;        // 512 bytes\nvar scaled = size1 * 4;                // 4 KB\nvar divided = size2 / 2;               // 768 bytes\n\n// Display formatting\nConsole.WriteLine(size2);              // \"1.5 KB\"\nlong rawBytes = size2;                 // 1536 (implicit conversion)\n\n// Comparisons\nif (size1 \u003c size2)\n    Console.WriteLine(\"size1 is smaller\");\n\n// Use in collections\nvar dictionary = new Dictionary\u003cBytes, string\u003e\n{\n    [Bytes.Parse(\"1GB\")] = \"Large file\",\n    [Bytes.Parse(\"1MB\")] = \"Small file\"\n};\n```\n\n## JSON Serialization\n\nThe `Bytes` struct includes full JSON support with a custom converter that handles both regular serialization and dictionary key scenarios:\n\n```csharp\nusing System.Text.Json;\n\n// Simple serialization\nvar bytes = new Bytes(1024);\nvar json = JsonSerializer.Serialize(bytes);        // \"1024\"\nvar deserialized = JsonSerializer.Deserialize\u003cBytes\u003e(json);\n\n// As dictionary keys\nvar dict = new Dictionary\u003cBytes, string\u003e\n{\n    [new Bytes(1024)] = \"Config\",\n    [new Bytes(1048576)] = \"Data\"\n};\nvar dictJson = JsonSerializer.Serialize(dict);\n// {\"1024\":\"Config\",\"1048576\":\"Data\"}\n\n// Complex objects\npublic class FileInfo\n{\n    public string Name { get; set; }\n    public Bytes Size { get; set; }\n}\n\nvar file = new FileInfo { Name = \"video.mp4\", Size = \"1.5GB\" };\nvar fileJson = JsonSerializer.Serialize(file);\n```\n\n## DataContract Serialization\n\nFull support for WCF/XML serialization without ProtoBuf dependencies:\n\n```csharp\nusing System.Runtime.Serialization;\n\n[DataContract]\npublic class Document\n{\n    [DataMember]\n    public string Title { get; set; }\n    \n    [DataMember]\n    public Bytes FileSize { get; set; }\n}\n\n// XML serialization works out of the box\nvar serializer = new DataContractSerializer(typeof(Document));\n```\n\n## Protobuf Serialization\n\nFull support for Protobuf-net serialization - works directly with no configuration needed:\n\n```csharp\nusing ProtoBuf;\n\n[ProtoContract]\npublic class FileInfo\n{\n    [ProtoMember(1)]\n    public string Name { get; set; }\n    \n    [ProtoMember(2)]\n    public Bytes Size { get; set; }  // Works directly!\n}\n\n// Serialize with Protobuf\nvar file = new FileInfo { Name = \"video.mp4\", Size = \"1.5GB\" };\nusing var stream = new MemoryStream();\nSerializer.Serialize(stream, file);\n```\n\nThe `Bytes` struct uses `[DataContract]` attributes which Protobuf-net recognizes, enabling seamless serialization.\n\n## Parsing Formats\n\nThe parser supports various formats with case-insensitive suffixes:\n\n```csharp\n// Numeric values\nBytes.Parse(\"1024\")          // 1024 bytes\nBytes.Parse(\"1,024\")         // 1024 bytes (with thousands separator)\n\n// With size suffixes\nBytes.Parse(\"1KB\")           // 1024 bytes\nBytes.Parse(\"1 KB\")          // 1024 bytes (with space)\nBytes.Parse(\"1.5MB\")         // 1572864 bytes\nBytes.Parse(\"2.5 GB\")        // 2684354560 bytes\n\n// Case insensitive\nBytes.Parse(\"1kb\")           // 1024 bytes\nBytes.Parse(\"1Kb\")           // 1024 bytes\n\n// Supported suffixes\n// B, KB, MB, GB, TB, PB, EB\n```\n\n## Implicit Conversions\n\nThe struct provides extensive implicit conversion support:\n\n```csharp\n// From numeric types to Bytes\nBytes fromInt = 1024;\nBytes fromUint = 2048u;\nBytes fromLong = 1099511627776L;\nBytes fromUlong = 1125899906842624UL;\nBytes fromString = \"1.5KB\";\n\n// From Bytes to numeric types\nint intValue = new Bytes(1024);\nuint uintValue = new Bytes(2048);\nlong longValue = new Bytes(1099511627776L);\nulong ulongValue = new Bytes(1125899906842624L);\ndouble doubleValue = new Bytes(1536);\n```\n\n## Performance Considerations\n\n- **Readonly struct**: Prevents defensive copies and ensures thread-safety\n- **Value type**: Stack allocated, no GC pressure\n- **Optimized formatting**: Caches formatted strings when precision is specified\n- **Zero allocations**: Parse and format operations minimize allocations\n\n## Thread Safety\n\nThe `Bytes` struct is immutable and thread-safe. All operations create new instances rather than modifying existing ones.\n\n## Examples\n\n### File Size Analysis\n```csharp\nvar files = Directory.GetFiles(@\"C:\\MyFolder\")\n    .Select(f =\u003e new { Path = f, Size = Bytes.FromFile(f) })\n    .OrderByDescending(f =\u003e f.Size)\n    .Take(10);\n\nforeach (var file in files)\n    Console.WriteLine($\"{file.Path}: {file.Size}\");\n```\n\n### Configuration with Size Limits\n```csharp\npublic class UploadConfig\n{\n    public Bytes MaxFileSize { get; set; } = \"100MB\";\n    public Bytes MaxTotalSize { get; set; } = \"1GB\";\n    \n    public bool IsAllowed(Bytes fileSize) \n        =\u003e fileSize \u003c= MaxFileSize;\n}\n```\n\n### Progress Tracking\n```csharp\npublic class DownloadProgress\n{\n    public Bytes Downloaded { get; private set; }\n    public Bytes Total { get; private set; }\n    \n    public double PercentComplete =\u003e \n        (long)Total \u003e 0 ? (double)Downloaded / Total * 100 : 0;\n    \n    public void Update(Bytes bytesReceived)\n    {\n        Downloaded += bytesReceived;\n        Console.WriteLine($\"Downloaded: {Downloaded} / {Total} ({PercentComplete:F1}%)\");\n    }\n}\n```\n\n## License\n\nMIT\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## Support\n\nFor issues and feature requests, please use the [GitHub issue tracker](https://github.com/modelingevolution/bytes/issues).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmodelingevolution%2Fbytes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmodelingevolution%2Fbytes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmodelingevolution%2Fbytes/lists"}