|
| 1 | +# size-parser |
| 2 | + |
| 3 | +A utility crate for parsing and handling memory sizes with serde support. |
| 4 | + |
| 5 | +## Features |
| 6 | + |
| 7 | +- Parse memory size strings with various suffixes (K, M, G, T) |
| 8 | +- Support for hexadecimal values (0x prefix) |
| 9 | +- Optional serde serialization/deserialization support |
| 10 | +- Human-readable formatting |
| 11 | +- Type-safe memory size handling |
| 12 | + |
| 13 | +## Usage |
| 14 | + |
| 15 | +Add this to your `Cargo.toml`: |
| 16 | + |
| 17 | +```toml |
| 18 | +[dependencies] |
| 19 | +size-parser = { path = "../size-parser" } |
| 20 | + |
| 21 | +# For serde support |
| 22 | +size-parser = { path = "../size-parser", features = ["serde"] } |
| 23 | +``` |
| 24 | + |
| 25 | +## Examples |
| 26 | + |
| 27 | +### Basic Usage |
| 28 | + |
| 29 | +```rust |
| 30 | +use size_parser::MemorySize; |
| 31 | + |
| 32 | +// Parse from string |
| 33 | +let size = MemorySize::parse("2G").unwrap(); |
| 34 | +assert_eq!(size.bytes(), 2 * 1024 * 1024 * 1024); |
| 35 | + |
| 36 | +// Parse hexadecimal |
| 37 | +let size = MemorySize::parse("0x1000").unwrap(); |
| 38 | +assert_eq!(size.bytes(), 4096); |
| 39 | + |
| 40 | +// Create from bytes |
| 41 | +let size = MemorySize::from_bytes(1024); |
| 42 | +assert_eq!(size.bytes(), 1024); |
| 43 | + |
| 44 | +// Using FromStr trait |
| 45 | +let size: MemorySize = "2G".parse().unwrap(); |
| 46 | +assert_eq!(size.bytes(), 2 * 1024 * 1024 * 1024); |
| 47 | +``` |
| 48 | + |
| 49 | +### Supported Formats |
| 50 | + |
| 51 | +- Plain numbers: `"1024"`, `"2048"` |
| 52 | +- Hexadecimal: `"0x1000"`, `"0X2000"` |
| 53 | +- With suffixes: `"2K"`, `"4M"`, `"1G"`, `"2T"` (case-insensitive) |
| 54 | + |
| 55 | +Suffixes use binary (1024-based) multipliers: |
| 56 | +- K/k: 1024 bytes |
| 57 | +- M/m: 1024² bytes |
| 58 | +- G/g: 1024³ bytes |
| 59 | +- T/t: 1024⁴ bytes |
| 60 | + |
| 61 | +### Human-readable Formatting |
| 62 | + |
| 63 | +```rust |
| 64 | +let size = MemorySize::from_bytes(1536); |
| 65 | +println!("{}", size); // Prints: "1.5K" |
| 66 | + |
| 67 | +let size = MemorySize::from_bytes(2 * 1024 * 1024 * 1024); |
| 68 | +println!("{}", size); // Prints: "2G" |
| 69 | +``` |
| 70 | + |
| 71 | +### Serde Support (with "serde" feature) |
| 72 | + |
| 73 | +#### Using MemorySize Type |
| 74 | + |
| 75 | +```rust |
| 76 | +use size_parser::MemorySize; |
| 77 | +use serde::{Deserialize, Serialize}; |
| 78 | + |
| 79 | +#[derive(Serialize, Deserialize)] |
| 80 | +struct Config { |
| 81 | + memory: MemorySize, |
| 82 | +} |
| 83 | + |
| 84 | +let config = Config { |
| 85 | + memory: MemorySize::parse("2G").unwrap(), |
| 86 | +}; |
| 87 | + |
| 88 | +// Serializes as: {"memory": "2G"} |
| 89 | +let json = serde_json::to_string(&config).unwrap(); |
| 90 | + |
| 91 | +// Can deserialize from various formats |
| 92 | +let config: Config = serde_json::from_str(r#"{"memory": "1024M"}"#).unwrap(); |
| 93 | +``` |
| 94 | + |
| 95 | +#### Using Field Attributes with Numeric Types |
| 96 | + |
| 97 | +You can also use serde field attributes to serialize/deserialize memory sizes directly into any numeric type that can be converted to/from u64: |
| 98 | + |
| 99 | +```rust |
| 100 | +use serde::{Deserialize, Serialize}; |
| 101 | + |
| 102 | +#[derive(Serialize, Deserialize)] |
| 103 | +struct MyConfig { |
| 104 | + #[serde(with = "size_parser::human_size")] |
| 105 | + memory_size: u64, |
| 106 | + #[serde(with = "size_parser::human_size")] |
| 107 | + buffer_size: usize, |
| 108 | + #[serde(with = "size_parser::human_size")] |
| 109 | + cache_size: u32, |
| 110 | +} |
| 111 | + |
| 112 | +let config = MyConfig { |
| 113 | + memory_size: 2 * 1024 * 1024 * 1024, // 2GB |
| 114 | + buffer_size: 512 * 1024, // 512KB |
| 115 | + cache_size: 64 * 1024, // 64KB |
| 116 | +}; |
| 117 | + |
| 118 | +// Serializes as: {"memory_size": "2G", "buffer_size": "512K", "cache_size": "64K"} |
| 119 | +let json = serde_json::to_string(&config).unwrap(); |
| 120 | + |
| 121 | +// Can deserialize from human-readable formats |
| 122 | +let config: MyConfig = serde_json::from_str(r#"{"memory_size": "1G", "buffer_size": "256K", "cache_size": "32K"}"#).unwrap(); |
| 123 | +assert_eq!(config.memory_size, 1024 * 1024 * 1024); |
| 124 | +assert_eq!(config.buffer_size, 256 * 1024); |
| 125 | +assert_eq!(config.cache_size, 32 * 1024); |
| 126 | +``` |
| 127 | + |
| 128 | +**Supported numeric types:** |
| 129 | +- `u64`, `u32`, `u16`, `u8` - unsigned integers |
| 130 | +- `usize` - platform-dependent unsigned integer |
| 131 | +- Any type that implements `TryFrom<u64>` and `Into<u64>` |
| 132 | + |
| 133 | +The generic implementation automatically handles overflow checking and provides clear error messages when values are too large for the target type. |
| 134 | + |
| 135 | +### Compatibility Function |
| 136 | + |
| 137 | +For compatibility with existing code, a standalone function is also provided: |
| 138 | + |
| 139 | +```rust |
| 140 | +use size_parser::parse_memory_size; |
| 141 | + |
| 142 | +let bytes = parse_memory_size("2G").unwrap(); |
| 143 | +assert_eq!(bytes, 2 * 1024 * 1024 * 1024); |
| 144 | +``` |
| 145 | + |
| 146 | +## License |
| 147 | + |
| 148 | +Apache-2.0 |
0 commit comments