dmesg: implement print json.
This commit is contained in:
parent
a044bece47
commit
d1066420e7
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -905,6 +905,8 @@ version = "0.0.1"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"uucore",
|
||||
]
|
||||
|
||||
|
@ -14,3 +14,5 @@ path = "src/main.rs"
|
||||
clap = { workspace = true }
|
||||
uucore = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
|
@ -3,6 +3,8 @@ use regex::Regex;
|
||||
use std::fs;
|
||||
use uucore::error::UResult;
|
||||
|
||||
mod json;
|
||||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let mut dmesg = Dmesg::new();
|
||||
@ -42,7 +44,7 @@ mod options {
|
||||
struct Dmesg<'a> {
|
||||
kmsg_file: &'a str,
|
||||
output_format: OutputFormat,
|
||||
_records: Option<Vec<Record>>,
|
||||
records: Option<Vec<Record>>,
|
||||
}
|
||||
|
||||
impl Dmesg<'_> {
|
||||
@ -50,7 +52,7 @@ impl Dmesg<'_> {
|
||||
Dmesg {
|
||||
kmsg_file: "/dev/kmsg",
|
||||
output_format: OutputFormat::Normal,
|
||||
_records: None,
|
||||
records: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +65,7 @@ impl Dmesg<'_> {
|
||||
records.push(Record::from_str_fields(pri_fac, seq, time, msg.to_string()));
|
||||
}
|
||||
}
|
||||
self._records = Some(records);
|
||||
self.records = Some(records);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
@ -91,7 +93,18 @@ impl Dmesg<'_> {
|
||||
Ok(lines)
|
||||
}
|
||||
|
||||
fn print(&self) {}
|
||||
fn print(&self) {
|
||||
match self.output_format {
|
||||
OutputFormat::Json => self.print_json(),
|
||||
OutputFormat::Normal => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn print_json(&self) {
|
||||
if let Some(records) = &self.records {
|
||||
println!("{}", json::serialize_records(records));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum OutputFormat {
|
||||
|
137
src/uu/dmesg/src/json.rs
Normal file
137
src/uu/dmesg/src/json.rs
Normal file
@ -0,0 +1,137 @@
|
||||
use serde::Serialize;
|
||||
use std::io;
|
||||
|
||||
pub fn serialize_records(records: &Vec<crate::Record>) -> String {
|
||||
let json = Dmesg::from(records);
|
||||
let formatter = DmesgFormatter::new();
|
||||
let mut buf = vec![];
|
||||
let mut serializer = serde_json::Serializer::with_formatter(&mut buf, formatter);
|
||||
json.serialize(&mut serializer).unwrap();
|
||||
String::from_utf8_lossy(&buf).to_string()
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct Dmesg<'a> {
|
||||
dmesg: Vec<Record<'a>>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct Record<'a> {
|
||||
pri: u32,
|
||||
time: u64,
|
||||
msg: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Vec<crate::Record>> for Dmesg<'a> {
|
||||
fn from(value: &'a Vec<crate::Record>) -> Self {
|
||||
let mut dmesg_json = Dmesg { dmesg: vec![] };
|
||||
for record in value {
|
||||
let record_json = Record {
|
||||
pri: record._priority_facility,
|
||||
time: record._timestamp_us,
|
||||
msg: &record._message,
|
||||
};
|
||||
dmesg_json.dmesg.push(record_json);
|
||||
}
|
||||
dmesg_json
|
||||
}
|
||||
}
|
||||
|
||||
struct DmesgFormatter {
|
||||
nesting_depth: i32,
|
||||
}
|
||||
|
||||
impl DmesgFormatter {
|
||||
const SINGLE_INDENTATION: &[u8] = b" ";
|
||||
|
||||
fn new() -> Self {
|
||||
DmesgFormatter { nesting_depth: 0 }
|
||||
}
|
||||
|
||||
fn write_indentation<W>(&mut self, writer: &mut W) -> io::Result<()>
|
||||
where
|
||||
W: ?Sized + io::Write,
|
||||
{
|
||||
for _ in 0..self.nesting_depth {
|
||||
writer.write_all(Self::SINGLE_INDENTATION)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl serde_json::ser::Formatter for DmesgFormatter {
|
||||
fn begin_object<W>(&mut self, writer: &mut W) -> io::Result<()>
|
||||
where
|
||||
W: ?Sized + io::Write,
|
||||
{
|
||||
self.nesting_depth += 1;
|
||||
writer.write_all(b"{\n")
|
||||
}
|
||||
|
||||
fn end_object<W>(&mut self, writer: &mut W) -> io::Result<()>
|
||||
where
|
||||
W: ?Sized + io::Write,
|
||||
{
|
||||
writer.write_all(b"\n")?;
|
||||
self.nesting_depth -= 1;
|
||||
self.write_indentation(writer)?;
|
||||
writer.write_all(b"}")
|
||||
}
|
||||
|
||||
fn begin_array<W>(&mut self, writer: &mut W) -> io::Result<()>
|
||||
where
|
||||
W: ?Sized + io::Write,
|
||||
{
|
||||
self.nesting_depth += 1;
|
||||
writer.write_all(b"[\n")
|
||||
}
|
||||
|
||||
fn end_array<W>(&mut self, writer: &mut W) -> io::Result<()>
|
||||
where
|
||||
W: ?Sized + io::Write,
|
||||
{
|
||||
writer.write_all(b"\n")?;
|
||||
self.nesting_depth -= 1;
|
||||
self.write_indentation(writer)?;
|
||||
writer.write_all(b"]")
|
||||
}
|
||||
|
||||
fn begin_object_key<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
|
||||
where
|
||||
W: ?Sized + io::Write,
|
||||
{
|
||||
if !first {
|
||||
writer.write_all(b",\n")?;
|
||||
}
|
||||
self.write_indentation(writer)
|
||||
}
|
||||
|
||||
fn begin_object_value<W>(&mut self, writer: &mut W) -> io::Result<()>
|
||||
where
|
||||
W: ?Sized + io::Write,
|
||||
{
|
||||
writer.write_all(b": ")
|
||||
}
|
||||
|
||||
fn begin_array_value<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
|
||||
where
|
||||
W: ?Sized + io::Write,
|
||||
{
|
||||
if first {
|
||||
self.write_indentation(writer)
|
||||
} else {
|
||||
writer.write_all(b",")
|
||||
}
|
||||
}
|
||||
|
||||
fn write_u64<W>(&mut self, writer: &mut W, value: u64) -> io::Result<()>
|
||||
where
|
||||
W: ?Sized + io::Write,
|
||||
{
|
||||
// The only u64 field in Dmesg is time, which requires a specific format
|
||||
let seconds = value / 1000000;
|
||||
let sub_seconds = value % 1000000;
|
||||
let repr = format!("{:>5}.{:0>6}", seconds, sub_seconds);
|
||||
writer.write_all(repr.as_bytes())
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user