Skip to content

Commit 30b4c65

Browse files
committed
Centralize field names for consistent JSON and text output
The great field name unification of 2025. JSON said "operstate", text said "STATE" - now they both agree on "state" (lowercase for JSON, UPPERCASE for text, as nature intended). Added src/fields.rs as the single source of truth for all field names across all subcommands. Text output uses to_text_key() to convert to UPPERCASE, JSON uses the constants directly. Breaking changes to JSON output (text output unchanged): - net: operstate -> state, mac_address -> mac, speed_mbps -> speed - pci: subsystem_vendor_id -> subsys_vendor, subsystem_device_id -> subsys_device Shorter names win. Consistency wins. Everyone wins.
1 parent ff33c91 commit 30b4c65

12 files changed

Lines changed: 585 additions & 331 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "kv"
3-
version = "0.4.2"
3+
version = "0.5.0"
44
edition = "2024"
55
rust-version = "1.85"
66
description = "kv (kernel view): a portable system inspector for Linux"

src/block.rs

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//! either as subdirectories of /sys/block/<disk>/ or as separate entries.
99
1010
use crate::cli::GlobalOptions;
11+
use crate::fields::{block as f, to_text_key};
1112
use crate::filter::{opt_str, Filterable};
1213
use crate::io;
1314
use crate::json::{begin_kv_output, JsonWriter};
@@ -181,40 +182,40 @@ impl BlockDevice {
181182
pub fn print_text(&self, verbose: bool, human: bool) {
182183
let mut parts = Vec::new();
183184

184-
parts.push(format!("NAME={}", self.name));
185-
parts.push(format!("TYPE={}", self.dev_type.as_str()));
186-
parts.push(format!("MAJMIN={}:{}", self.major, self.minor));
185+
parts.push(format!("{}={}", to_text_key(f::NAME), self.name));
186+
parts.push(format!("{}={}", to_text_key(f::TYPE), self.dev_type.as_str()));
187+
parts.push(format!("{}={}:{}", to_text_key(f::MAJMIN), self.major, self.minor));
187188

188189
if human {
189190
let size = io::format_sectors_human(self.size_sectors, self.sector_size);
190-
parts.push(format!("SIZE={}", size));
191+
parts.push(format!("{}={}", to_text_key(f::SIZE), size));
191192
} else {
192-
parts.push(format!("SIZE_SECTORS={}", self.size_sectors));
193+
parts.push(format!("{}={}", to_text_key(f::SIZE_SECTORS), self.size_sectors));
193194
}
194195

195196
if let Some(ref parent) = self.parent {
196-
parts.push(format!("PARENT={}", parent));
197+
parts.push(format!("{}={}", to_text_key(f::PARENT), parent));
197198
}
198199

199200
if let Some(ref mp) = self.mountpoint {
200-
parts.push(format!("MOUNTPOINT=\"{}\"", mp));
201+
parts.push(format!("{}=\"{}\"", to_text_key(f::MOUNTPOINT), mp));
201202
}
202203

203204
if verbose {
204205
if !human {
205-
parts.push(format!("SECTOR_SIZE={}", self.sector_size));
206+
parts.push(format!("{}={}", to_text_key(f::SECTOR_SIZE), self.sector_size));
206207
}
207-
parts.push(format!("REMOVABLE={}", if self.removable { 1 } else { 0 }));
208-
parts.push(format!("RO={}", if self.ro { 1 } else { 0 }));
208+
parts.push(format!("{}={}", to_text_key(f::REMOVABLE), if self.removable { 1 } else { 0 }));
209+
parts.push(format!("{}={}", to_text_key(f::RO), if self.ro { 1 } else { 0 }));
209210

210211
if let Some(ref model) = self.model {
211-
parts.push(format!("MODEL=\"{}\"", model.trim()));
212+
parts.push(format!("{}=\"{}\"", to_text_key(f::MODEL), model.trim()));
212213
}
213214
if let Some(rot) = self.rotational {
214-
parts.push(format!("ROTATIONAL={}", if rot { 1 } else { 0 }));
215+
parts.push(format!("{}={}", to_text_key(f::ROTATIONAL), if rot { 1 } else { 0 }));
215216
}
216217
if let Some(ref sched) = self.scheduler {
217-
parts.push(format!("SCHEDULER={}", sched));
218+
parts.push(format!("{}={}", to_text_key(f::SCHEDULER), sched));
218219
}
219220
}
220221

@@ -352,32 +353,32 @@ fn print_json(devices: &[BlockDevice], pretty: bool, verbose: bool, human: bool)
352353
fn write_device_json(w: &mut JsonWriter, dev: &BlockDevice, verbose: bool, human: bool) {
353354
w.array_object_begin();
354355

355-
w.field_str("name", &dev.name);
356-
w.field_str("type", dev.dev_type.as_str());
357-
w.field_u64("major", dev.major as u64);
358-
w.field_u64("minor", dev.minor as u64);
356+
w.field_str(f::NAME, &dev.name);
357+
w.field_str(f::TYPE, dev.dev_type.as_str());
358+
w.field_u64(f::MAJOR, dev.major as u64);
359+
w.field_u64(f::MINOR, dev.minor as u64);
359360

360361
if human {
361362
let size = io::format_sectors_human(dev.size_sectors, dev.sector_size);
362-
w.field_str("size", &size);
363+
w.field_str(f::SIZE, &size);
363364
} else {
364-
w.field_u64("size_sectors", dev.size_sectors);
365+
w.field_u64(f::SIZE_SECTORS, dev.size_sectors);
365366
}
366367

367-
w.field_str_opt("parent", dev.parent.as_deref());
368-
w.field_str_opt("mountpoint", dev.mountpoint.as_deref());
368+
w.field_str_opt(f::PARENT, dev.parent.as_deref());
369+
w.field_str_opt(f::MOUNTPOINT, dev.mountpoint.as_deref());
369370

370371
if verbose {
371372
if !human {
372-
w.field_u64("sector_size", dev.sector_size as u64);
373+
w.field_u64(f::SECTOR_SIZE, dev.sector_size as u64);
373374
}
374-
w.field_bool("removable", dev.removable);
375-
w.field_bool("ro", dev.ro);
376-
w.field_str_opt("model", dev.model.as_deref());
375+
w.field_bool(f::REMOVABLE, dev.removable);
376+
w.field_bool(f::RO, dev.ro);
377+
w.field_str_opt(f::MODEL, dev.model.as_deref());
377378
if let Some(rot) = dev.rotational {
378-
w.field_bool("rotational", rot);
379+
w.field_bool(f::ROTATIONAL, rot);
379380
}
380-
w.field_str_opt("scheduler", dev.scheduler.as_deref());
381+
w.field_str_opt(f::SCHEDULER, dev.scheduler.as_deref());
381382
}
382383

383384
w.array_object_end();

src/cpu.rs

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//! but some fields may be missing on some platforms. That's life in embedded.
1111
1212
use crate::cli::GlobalOptions;
13+
use crate::fields::{cpu as f, to_text_key};
1314
use crate::io;
1415
use crate::json::{begin_kv_output, JsonWriter};
1516
use std::collections::HashSet;
@@ -168,51 +169,51 @@ impl CpuInfo {
168169
pub fn print_text(&self, verbose: bool) {
169170
let mut parts = Vec::new();
170171

171-
parts.push(format!("LOGICAL_CPUS={}", self.logical_cpus));
172+
parts.push(format!("{}={}", to_text_key(f::LOGICAL_CPUS), self.logical_cpus));
172173

173174
if let Some(ref name) = self.model_name {
174175
// Quote model name since it often has spaces
175-
parts.push(format!("MODEL_NAME=\"{}\"", name));
176+
parts.push(format!("{}=\"{}\"", to_text_key(f::MODEL_NAME), name));
176177
}
177178

178179
if let Some(ref vendor) = self.vendor_id {
179-
parts.push(format!("VENDOR_ID={}", vendor));
180+
parts.push(format!("{}={}", to_text_key(f::VENDOR_ID), vendor));
180181
}
181182

182183
if let Some(sockets) = self.sockets {
183-
parts.push(format!("SOCKETS={}", sockets));
184+
parts.push(format!("{}={}", to_text_key(f::SOCKETS), sockets));
184185
}
185186

186187
if let Some(cores) = self.cores_per_socket {
187-
parts.push(format!("CORES_PER_SOCKET={}", cores));
188+
parts.push(format!("{}={}", to_text_key(f::CORES_PER_SOCKET), cores));
188189
}
189190

190191
// RISC-V specific fields (always show if present, very informative)
191192
if let Some(ref isa) = self.isa {
192-
parts.push(format!("ISA={}", isa));
193+
parts.push(format!("{}={}", to_text_key(f::ISA), isa));
193194
}
194195
if let Some(ref mmu) = self.mmu {
195-
parts.push(format!("MMU={}", mmu));
196+
parts.push(format!("{}={}", to_text_key(f::MMU), mmu));
196197
}
197198

198199
if verbose {
199200
if let Some(family) = self.cpu_family {
200-
parts.push(format!("CPU_FAMILY={}", family));
201+
parts.push(format!("{}={}", to_text_key(f::CPU_FAMILY), family));
201202
}
202203
if let Some(model) = self.model {
203-
parts.push(format!("MODEL={}", model));
204+
parts.push(format!("{}={}", to_text_key(f::MODEL), model));
204205
}
205206
if let Some(stepping) = self.stepping {
206-
parts.push(format!("STEPPING={}", stepping));
207+
parts.push(format!("{}={}", to_text_key(f::STEPPING), stepping));
207208
}
208209
if let Some(mhz) = self.cpu_mhz {
209-
parts.push(format!("CPU_MHZ={:.2}", mhz));
210+
parts.push(format!("{}={:.2}", to_text_key(f::CPU_MHZ), mhz));
210211
}
211212
if let Some(ref cache) = self.cache_size {
212-
parts.push(format!("CACHE_SIZE=\"{}\"", cache));
213+
parts.push(format!("{}=\"{}\"", to_text_key(f::CACHE_SIZE), cache));
213214
}
214215
if let Some(ref arch) = self.architecture {
215-
parts.push(format!("ARCHITECTURE={}", arch));
216+
parts.push(format!("{}={}", to_text_key(f::ARCHITECTURE), arch));
216217
}
217218
}
218219

@@ -225,26 +226,26 @@ impl CpuInfo {
225226

226227
w.field_object("data");
227228

228-
w.field_u64("logical_cpus", self.logical_cpus as u64);
229-
w.field_str_opt("model_name", self.model_name.as_deref());
230-
w.field_str_opt("vendor_id", self.vendor_id.as_deref());
231-
w.field_u64_opt("sockets", self.sockets.map(|v| v as u64));
232-
w.field_u64_opt("cores_per_socket", self.cores_per_socket.map(|v| v as u64));
229+
w.field_u64(f::LOGICAL_CPUS, self.logical_cpus as u64);
230+
w.field_str_opt(f::MODEL_NAME, self.model_name.as_deref());
231+
w.field_str_opt(f::VENDOR_ID, self.vendor_id.as_deref());
232+
w.field_u64_opt(f::SOCKETS, self.sockets.map(|v| v as u64));
233+
w.field_u64_opt(f::CORES_PER_SOCKET, self.cores_per_socket.map(|v| v as u64));
233234
// RISC-V specific
234-
w.field_str_opt("isa", self.isa.as_deref());
235-
w.field_str_opt("mmu", self.mmu.as_deref());
235+
w.field_str_opt(f::ISA, self.isa.as_deref());
236+
w.field_str_opt(f::MMU, self.mmu.as_deref());
236237

237238
if verbose {
238-
w.field_u64_opt("cpu_family", self.cpu_family.map(|v| v as u64));
239-
w.field_u64_opt("model", self.model.map(|v| v as u64));
240-
w.field_u64_opt("stepping", self.stepping.map(|v| v as u64));
239+
w.field_u64_opt(f::CPU_FAMILY, self.cpu_family.map(|v| v as u64));
240+
w.field_u64_opt(f::MODEL, self.model.map(|v| v as u64));
241+
w.field_u64_opt(f::STEPPING, self.stepping.map(|v| v as u64));
241242
// For MHz we'll use string to preserve precision
242243
if let Some(mhz) = self.cpu_mhz {
243-
w.field_str("cpu_mhz", &format!("{:.2}", mhz));
244+
w.field_str(f::CPU_MHZ, &format!("{:.2}", mhz));
244245
}
245-
w.field_str_opt("cache_size", self.cache_size.as_deref());
246-
w.field_str_opt("architecture", self.architecture.as_deref());
247-
w.field_str_opt("flags", self.flags.as_deref());
246+
w.field_str_opt(f::CACHE_SIZE, self.cache_size.as_deref());
247+
w.field_str_opt(f::ARCHITECTURE, self.architecture.as_deref());
248+
w.field_str_opt(f::FLAGS, self.flags.as_deref());
248249
}
249250

250251
w.end_field_object();
@@ -332,24 +333,24 @@ pub fn collect(_verbose: bool) -> Option<CpuInfo> {
332333
pub fn write_json(w: &mut JsonWriter, info: &CpuInfo, verbose: bool) {
333334
w.field_object("cpu");
334335

335-
w.field_u64("logical_cpus", info.logical_cpus as u64);
336-
w.field_str_opt("model_name", info.model_name.as_deref());
337-
w.field_str_opt("vendor_id", info.vendor_id.as_deref());
338-
w.field_u64_opt("sockets", info.sockets.map(|v| v as u64));
339-
w.field_u64_opt("cores_per_socket", info.cores_per_socket.map(|v| v as u64));
336+
w.field_u64(f::LOGICAL_CPUS, info.logical_cpus as u64);
337+
w.field_str_opt(f::MODEL_NAME, info.model_name.as_deref());
338+
w.field_str_opt(f::VENDOR_ID, info.vendor_id.as_deref());
339+
w.field_u64_opt(f::SOCKETS, info.sockets.map(|v| v as u64));
340+
w.field_u64_opt(f::CORES_PER_SOCKET, info.cores_per_socket.map(|v| v as u64));
340341
// RISC-V specific
341-
w.field_str_opt("isa", info.isa.as_deref());
342-
w.field_str_opt("mmu", info.mmu.as_deref());
342+
w.field_str_opt(f::ISA, info.isa.as_deref());
343+
w.field_str_opt(f::MMU, info.mmu.as_deref());
343344

344345
if verbose {
345-
w.field_u64_opt("cpu_family", info.cpu_family.map(|v| v as u64));
346-
w.field_u64_opt("model", info.model.map(|v| v as u64));
347-
w.field_u64_opt("stepping", info.stepping.map(|v| v as u64));
346+
w.field_u64_opt(f::CPU_FAMILY, info.cpu_family.map(|v| v as u64));
347+
w.field_u64_opt(f::MODEL, info.model.map(|v| v as u64));
348+
w.field_u64_opt(f::STEPPING, info.stepping.map(|v| v as u64));
348349
if let Some(mhz) = info.cpu_mhz {
349-
w.field_str("cpu_mhz", &format!("{:.2}", mhz));
350+
w.field_str(f::CPU_MHZ, &format!("{:.2}", mhz));
350351
}
351-
w.field_str_opt("cache_size", info.cache_size.as_deref());
352-
w.field_str_opt("architecture", info.architecture.as_deref());
352+
w.field_str_opt(f::CACHE_SIZE, info.cache_size.as_deref());
353+
w.field_str_opt(f::ARCHITECTURE, info.architecture.as_deref());
353354
}
354355

355356
w.end_field_object();

0 commit comments

Comments
 (0)