Skip to content

Commit

Permalink
Add support for zero-padding
Browse files Browse the repository at this point in the history
  • Loading branch information
andresovela committed Dec 15, 2023
1 parent 73f9781 commit 8783f58
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 27 deletions.
26 changes: 22 additions & 4 deletions decoder/src/log/format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ pub(super) enum Alignment {
Right,
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub(super) enum Padding {
Space,
Zero,
}

/// Representation of a segment of the formatting string.
#[derive(Debug, PartialEq, Clone)]
pub(super) struct LogSegment {
Expand All @@ -129,6 +135,7 @@ pub(super) struct LogFormat {
pub(super) color: Option<LogColor>,
pub(super) style: Option<Vec<colored::Styles>>,
pub(super) alignment: Option<Alignment>,
pub(super) padding: Option<Padding>,
}

impl LogSegment {
Expand All @@ -140,6 +147,7 @@ impl LogSegment {
style: None,
width: None,
alignment: None,
padding: None,
},
}
}
Expand Down Expand Up @@ -169,6 +177,12 @@ impl LogSegment {
self.format.alignment = Some(alignment);
self
}

#[cfg(test)]
pub(crate) const fn with_padding(mut self, padding: Padding) -> Self {
self.format.padding = Some(padding);
self
}
}

pub struct Formatter {
Expand Down Expand Up @@ -686,12 +700,16 @@ fn build_formatted_string(

let alignment = format.alignment.unwrap_or(Alignment::Left);
let width = format.width.unwrap_or(default_width);
let padding = format.padding.unwrap_or(Padding::Space);

let mut result = String::new();
match alignment {
Alignment::Left => write!(&mut result, "{colored_str:<0$}", width),
Alignment::Center => write!(&mut result, "{colored_str:^0$}", width),
Alignment::Right => write!(&mut result, "{colored_str:>0$}", width),
match (alignment, padding) {
(Alignment::Left, Padding::Space) => write!(&mut result, "{colored_str:<0$}", width),
(Alignment::Left, Padding::Zero) => write!(&mut result, "{colored_str:0<0$}", width),
(Alignment::Center, Padding::Space) => write!(&mut result, "{colored_str:^0$}", width),
(Alignment::Center, Padding::Zero) => write!(&mut result, "{colored_str:0^0$}", width),
(Alignment::Right, Padding::Space) => write!(&mut result, "{colored_str:>0$}", width),
(Alignment::Right, Padding::Zero) => write!(&mut result, "{colored_str:0>0$}", width),
}
.expect("Failed to format string: \"{colored_str}\"");
result
Expand Down
77 changes: 54 additions & 23 deletions decoder/src/log/format/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
//! [format specifiers]: LogMetadata
//! [format parameters]: LogFormat
use super::{Alignment, LogColor, LogFormat, LogMetadata, LogSegment};
use super::{Alignment, LogColor, LogFormat, LogMetadata, LogSegment, Padding};

use nom::{
branch::alt,
Expand All @@ -133,7 +133,7 @@ use std::str::FromStr;
#[derive(Debug, PartialEq, Clone)]
enum IntermediateOutput {
Metadata(LogMetadata),
WidthAndAlignment((usize, Option<Alignment>)),
WidthAndAlignment((usize, Padding, Option<Alignment>)),
Color(LogColor),
Style(colored::Styles),
NestedLogSegment(LogSegment),
Expand Down Expand Up @@ -200,7 +200,7 @@ fn parse_metadata(input: &str) -> IResult<&str, IntermediateOutput, ()> {
"m" => LogMetadata::ModulePath,
"t" => LogMetadata::Timestamp,
_ => {
if s == "f".repeat(s.len()) {
if !s.is_empty() && s == "f".repeat(s.len()) {
LogMetadata::FileName(s.len() as u8)
} else {
return Err(());
Expand Down Expand Up @@ -253,11 +253,21 @@ fn parse_width_and_alignment(input: &str) -> IResult<&str, IntermediateOutput, (
_ => Err(()),
}))(input)?;

let (input, width) = map_res(digit1, move |s: &str| s.parse::<usize>())(input)?;
let (input, width) = digit1.parse(input)?;

let padding = if width.starts_with('0') {
Padding::Zero
} else {
Padding::Space
};

let Ok(width) = width.parse::<usize>() else {
return Err(nom::Err::Error(()));
};

Ok((
input,
IntermediateOutput::WidthAndAlignment((width, alignment)),
IntermediateOutput::WidthAndAlignment((width, padding, alignment)),
))
}

Expand Down Expand Up @@ -347,9 +357,9 @@ fn build_log_segment<const NEST: bool>(
return Err(nom::Err::Failure(()));
};

let (width, alignment) = width_and_alignment
.map(|(w, a)| (Some(w), a))
.unwrap_or((None, None));
let (width, padding, alignment) = width_and_alignment
.map(|(w, p, a)| (Some(w), Some(p), a))
.unwrap_or((None, None, None));

Ok(LogSegment {
metadata,
Expand All @@ -358,6 +368,7 @@ fn build_log_segment<const NEST: bool>(
style,
width,
alignment,
padding,
},
})
}
Expand Down Expand Up @@ -512,12 +523,6 @@ mod tests {
assert_eq!(result, Ok(("", LogSegment::new(LogMetadata::Timestamp))));
}

#[test]
fn test_parse_invalid_file_path_argument() {
let result = parse_argument::<false>("{FFFF}");
assert!(result.is_err());
}

#[test]
fn test_parse_argument_with_color() {
let result = parse_log_segment::<false>("t:werror");
Expand All @@ -532,6 +537,7 @@ mod tests {
let expected_output = LogSegment::new(LogMetadata::Timestamp)
.with_width(8)
.with_alignment(Alignment::Right)
.with_padding(Padding::Space)
.with_color(LogColor::Color(colored::Color::White));
assert_eq!(result, Ok(("", expected_output)));
}
Expand All @@ -542,6 +548,7 @@ mod tests {
let expected_output = LogSegment::new(LogMetadata::FileName(1))
.with_width(25)
.with_alignment(Alignment::Left)
.with_padding(Padding::Space)
.with_color(LogColor::WarnError);
assert_eq!(result, Ok(("", expected_output)));
}
Expand All @@ -557,7 +564,10 @@ mod tests {
let result = parse_width_and_alignment("12");
assert_eq!(
result,
Ok(("", IntermediateOutput::WidthAndAlignment((12, None))))
Ok((
"",
IntermediateOutput::WidthAndAlignment((12, Padding::Space, None))
))
);
}

Expand All @@ -568,7 +578,19 @@ mod tests {
result,
Ok((
"",
IntermediateOutput::WidthAndAlignment((12, Some(Alignment::Right)))
IntermediateOutput::WidthAndAlignment((12, Padding::Space, Some(Alignment::Right)))
))
);
}

#[test]
fn test_parse_width_with_zero_padding_no_alignment() {
let result = parse_width_and_alignment("012");
assert_eq!(
result,
Ok((
"",
IntermediateOutput::WidthAndAlignment((12, Padding::Zero, None))
))
);
}
Expand All @@ -594,6 +616,7 @@ mod tests {
LogSegment::new(LogMetadata::String("T".to_string())),
LogSegment::new(LogMetadata::Timestamp)
.with_width(8)
.with_padding(Padding::Space)
.with_alignment(Alignment::Right),
LogSegment::new(LogMetadata::String(" [".to_string())),
LogSegment::new(LogMetadata::LogLevel)
Expand All @@ -606,7 +629,8 @@ mod tests {
LogSegment::new(LogMetadata::String(":".to_string())),
LogSegment::new(LogMetadata::LineNumber)
.with_color(LogColor::Color(colored::Color::White))
.with_width(3),
.with_width(3)
.with_padding(Padding::Space),
LogSegment::new(LogMetadata::String(" ".to_string())),
LogSegment::new(LogMetadata::Log).with_color(LogColor::WarnError),
];
Expand Down Expand Up @@ -645,6 +669,7 @@ mod tests {
LogSegment::new(LogMetadata::LogLevel)
.with_alignment(Alignment::Left)
.with_width(5)
.with_padding(Padding::Space)
.with_style(colored::Styles::Bold),
LogSegment::new(LogMetadata::String("]".to_string())),
]))
Expand Down Expand Up @@ -673,18 +698,21 @@ mod tests {
LogSegment::new(LogMetadata::String("[".to_string())),
LogSegment::new(LogMetadata::LogLevel)
.with_alignment(Alignment::Left)
.with_width(5),
.with_width(5)
.with_padding(Padding::Space),
LogSegment::new(LogMetadata::String("]".to_string())),
]))
.with_style(colored::Styles::Bold),
LogSegment::new(LogMetadata::String(" ".to_string())),
LogSegment::new(LogMetadata::FileName(1))
.with_alignment(Alignment::Right)
.with_width(20),
.with_width(20)
.with_padding(Padding::Space),
LogSegment::new(LogMetadata::String(":".to_string())),
]))
.with_alignment(Alignment::Left)
.with_width(30),
.with_width(30)
.with_padding(Padding::Space),
LogSegment::new(LogMetadata::String(" ".to_string())),
LogSegment::new(LogMetadata::Log),
];
Expand All @@ -701,18 +729,21 @@ mod tests {
LogSegment::new(LogMetadata::String("[".to_string())),
LogSegment::new(LogMetadata::LogLevel)
.with_alignment(Alignment::Left)
.with_width(5),
.with_width(5)
.with_padding(Padding::Space),
LogSegment::new(LogMetadata::String("]".to_string())),
]))
.with_style(colored::Styles::Bold),
LogSegment::new(LogMetadata::String(" ".to_string())),
LogSegment::new(LogMetadata::FileName(2))
.with_alignment(Alignment::Right)
.with_width(20),
.with_width(20)
.with_padding(Padding::Space),
LogSegment::new(LogMetadata::String(":".to_string())),
]))
.with_alignment(Alignment::Left)
.with_width(30),
.with_width(30)
.with_padding(Padding::Space),
LogSegment::new(LogMetadata::String(" ".to_string())),
LogSegment::new(LogMetadata::Log),
]))
Expand Down

0 comments on commit 8783f58

Please sign in to comment.