Skip to content

Commit

Permalink
Change the display_with argument behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
zhiburt committed Feb 2, 2025
1 parent 8fe621f commit cca0604
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 56 deletions.
47 changes: 25 additions & 22 deletions tabled/examples/derive/display_with.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,45 @@
//! * Attribute arguments can be directly overridden with static values, effectively ignoring the
//! augmented fields natural value entirely. Even an entire object can be passed as context with `self`.
use std::borrow::Cow;

use tabled::{Table, Tabled};

#[derive(Tabled)]
struct Country {
name: String,
#[tabled(display_with = "str::to_uppercase")]
capital: String,
#[tabled(display_with("display_perimeter", self))]
#[tabled(display_with("perimeter", self, false))]
area_km2: f32,
#[tabled(display_with("tabled::derive::display::option", "unknown"))]
currency: Option<String>,
}

impl Country {
fn new(name: &str, capital: &str, area_km2: f32) -> Self {
Self {
name: name.to_string(),
capital: capital.to_string(),
area_km2,
}
}
}

fn display_perimeter(country: &Country) -> Cow<'_, str> {
if country.area_km2 > 1_000_000.0 {
"BIG".into()
} else {
"small".into()
}
fn perimeter<'a>(area: &f32, country: &Country, _milies: bool) -> String {
let is_big = *area > 1_000_000.0f32;
let big_sign = if is_big { "B" } else { "" };
format!("{} {}", country.area_km2, big_sign)
}

fn main() {
let data = [
Country::new("Afghanistan", "Kabul", 652867.0),
Country::new("Angola", "Luanda", 1246700.0),
Country::new("Canada", "Ottawa", 9984670.0),
Country {
name: String::from("Afghanistan"),
capital: String::from("Kabul"),
area_km2: 652867.0,
currency: Some(String::from("Afghan afghani (AFN)")),
},
Country {
name: String::from("Angola"),
capital: String::from("Luanda"),
area_km2: 1246700.0,
currency: None,
},
Country {
name: String::from("Canada"),
capital: String::from("Ottawa"),
area_km2: 9984670.0,
currency: None,
},
];

let table = Table::new(data);
Expand Down
56 changes: 50 additions & 6 deletions tabled/src/derive/display/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ use core::fmt::Debug;
/// A function which is usefull in conjuntion with
/// `#[tabled(display_with)]` and `#[tabled(display_type)]`.
///
/// It can be used with any [`Option`] type.
/// You must provide a second argument which represents a value be printed in case of [`None`].
///
/// # Example
///
/// ```
/// use tabled::Tabled;
/// use tabled::derive::display;
Expand Down Expand Up @@ -51,6 +56,9 @@ where
/// A function which is usefull in conjuntion with
/// `#[tabled(display_with)]` and `#[tabled(display_type)]`.
///
/// It can be used with any type which implements a [`Debug`].
/// So rather then [`std::fmt::Display`] usage we will be using a debug implementation.
///
/// ```
/// use tabled::Tabled;
/// use tabled::derive::display;
Expand All @@ -63,12 +71,6 @@ where
/// state: Option<&'a str>
/// }
///
/// #[derive(Debug)]
/// pub enum State {
/// Proved,
/// Investigation,
/// }
///
/// let data = vec![
/// ZKP { application: "Decentralized Identity", state: Some("Proved") },
/// ZKP { application: "Voting Systems", state: Some("Investigation") },
Expand Down Expand Up @@ -96,3 +98,45 @@ where
{
format!("{:?}", value)
}

/// A function which is usefull in conjuntion with
/// `#[tabled(display_with)]` and `#[tabled(display_type)]`.
///
/// It just returns an empty string.
///
/// ```
/// use tabled::Tabled;
/// use tabled::derive::display;
/// use testing_table::assert_table;
///
/// #[derive(Tabled)]
/// pub struct ZKP<'a> {
/// application: &'a str,
/// #[tabled(display_with = "display::empty")]
/// state: Option<&'a str>
/// }
///
/// let data = vec![
/// ZKP { application: "Decentralized Identity", state: Some("Proved") },
/// ZKP { application: "Voting Systems", state: Some("Investigation") },
/// ZKP { application: "Privacy-Preserving Transactions", state: None },
/// ];
///
/// let table = tabled::Table::new(data);
///
/// assert_table!(
/// table,
/// r#"+---------------------------------+-------+"#
/// r#"| application | state |"#
/// r#"+---------------------------------+-------+"#
/// r#"| Decentralized Identity | |"#
/// r#"+---------------------------------+-------+"#
/// r#"| Voting Systems | |"#
/// r#"+---------------------------------+-------+"#
/// r#"| Privacy-Preserving Transactions | |"#
/// r#"+---------------------------------+-------+"#
/// );
/// ```
pub fn empty<T>(_value: &T) -> String {
String::new()
}
4 changes: 2 additions & 2 deletions tabled/src/derive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ pub mod display;
/// }
///
/// impl MyRecord {
/// fn display_valid(&self) -> String {
/// match self.valid {
/// fn display_valid(_: &Option<bool>, s: &Self) -> String {
/// match s.valid {
/// Some(s) => format!("is valid thing = {}", s),
/// None => format!("is not valid"),
/// }
Expand Down
38 changes: 19 additions & 19 deletions tabled/tests/derive/derive_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ mod tuple {
{ 0 Some("v2") },
{ ["0", "1"], ["0", "some 1 234"] },
pre: {
fn display_option(val: usize, text: &str) -> String {
fn display_option(_opt: &Option<sstr>, val: usize, text: &str) -> String {
format!("some {val} {text}")
}
}
Expand Down Expand Up @@ -204,7 +204,7 @@ mod tuple {
{ ["0", "1"], ["0", "some v2"] },
pre: {
impl TestType {
fn display_option(o: &TestType) -> String {
fn display_option(_opt: &Option<sstr>, o: &TestType) -> String {
match o.1 {
Some(s) => format!("some {s}"),
None => "none".to_string(),
Expand All @@ -220,7 +220,7 @@ mod tuple {
{ 0 Some("v2") },
{ ["0", "1"], ["0", "some v2"] },
pre: {
fn display_option(o: &TestType) -> String {
fn display_option(_opt: &Option<sstr>, o: &TestType) -> String {
match o.1 {
Some(s) => format!("some {s}"),
None => "none".to_string(),
Expand All @@ -235,7 +235,7 @@ mod tuple {
{ 0 Some("v2") },
{ ["0", "1"], ["0", "some 0.0"] },
pre: {
fn display_option(o1: u8, o2: u8) -> String {
fn display_option(_opt: &Option<sstr>, o1: u8, o2: u8) -> String {
format!("some {o1}.{o2}")
}
}
Expand Down Expand Up @@ -364,7 +364,7 @@ mod enum_ {
}
},
{
fn display<T>(_: &T) -> String {
fn display<T>(_opt: &sstr, _: &T) -> String {
"asd".to_string()
}
},
Expand Down Expand Up @@ -413,7 +413,7 @@ mod enum_ {
},
{
impl TestType {
fn format<const ID: usize>(&self) -> String {
fn format<const ID: usize>(_opt: &sstr, _: &Self) -> String {
ID.to_string()
}
}
Expand All @@ -439,7 +439,7 @@ mod enum_ {
},
{
impl TestType {
fn format<const ID: usize>(&self, _: sstr) -> String {
fn format<const ID: usize>(_opt: &sstr, _: &Self, _: sstr) -> String {
ID.to_string()
}
}
Expand All @@ -465,7 +465,7 @@ mod enum_ {
},
{
impl TestType {
fn format<const ID: usize>(&self, _: sstr) -> String {
fn format<const ID: usize>(_opt: &sstr, _: &Self, _: sstr) -> String {
ID.to_string()
}
}
Expand Down Expand Up @@ -1064,7 +1064,7 @@ mod structure {
}
}
{
fn display_option(v1: usize, v2: usize, v3: usize) -> String {
fn display_option(_opt: &Option<sstr>, v1: usize, v2: usize, v3: usize) -> String {
format!("{v1} {v2} {v3}")
}
}
Expand All @@ -1081,7 +1081,7 @@ mod structure {
}
}
{
fn display_option(v1: &u8, v2: usize, v3: usize) -> String {
fn display_option(_opt: &Option<sstr>, v1: &u8, v2: usize, v3: usize) -> String {
format!("{v1} {v2} {v3}")
}
}
Expand Down Expand Up @@ -1121,7 +1121,7 @@ mod structure {
}
{
impl TestType {
fn display_option(o: &TestType) -> String {
fn display_option(_opt: &Option<sstr>, o: &TestType) -> String {
match o.f2 {
Some(s) => format!("some {s}"),
None => "none".to_string(),
Expand All @@ -1143,8 +1143,8 @@ mod structure {
}
{
impl TestType {
fn display_option(&self) -> String {
match self.f2 {
fn display_option(_opt: &Option<sstr>, s: &Self) -> String {
match s.f2 {
Some(s) => format!("some {s}"),
None => "none".to_string(),
}
Expand All @@ -1164,7 +1164,7 @@ mod structure {
}
}
{
fn display_option(o: &TestType) -> String {
fn display_option(_opt: &Option<sstr>, o: &TestType) -> String {
match o.f2 {
Some(s) => format!("some {s}"),
None => "none".to_string(),
Expand All @@ -1186,7 +1186,7 @@ mod structure {
}
}
{
fn display_option(v1: &[u8; 2], v4: String) -> String {
fn display_option(_opt: &Option<sstr>, v1: &[u8; 2], v4: String) -> String {
format!("{} {} {v4}", v1[0], v1[1])
}
}
Expand Down Expand Up @@ -1579,15 +1579,15 @@ fn test_macros_in_display_with() {
national_currency_short: String,
}

fn display_perimeter(country: &Country) -> std::borrow::Cow<'_, str> {
fn display_perimeter(_area: &f32, country: &Country) -> sstr {
if country.area_km2 > 1_000_000.0 {
"Very Big Land".into()
"Very Big Land"
} else {
"Big Land".into()
"Big Land"
}
}

fn display_capital(country: String) -> std::borrow::Cow<'static, str> {
fn display_capital(_capital: &str, country: String) -> std::borrow::Cow<'static, str> {
format!("{country}!").into()
}
}
Expand Down
13 changes: 6 additions & 7 deletions tabled_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,20 +503,19 @@ fn get_field_fields(
field_name: FieldNameFn,
type_attrs: &TypeAttributes,
) -> TokenStream {
// TODO: Remove this `format!`?

if attr.inline {
return quote! { #field.fields() };
}

if let Some(func) = &attr.display_with {
let args = match &attr.display_with_args {
None => Some(quote!(&#field)),
Some(args) => args_to_tokens(fields, field_name, args),
Some(args) => args_to_tokens_with(fields, field, field_name, args),
None => quote!(&#field),
};

let result = match args {
Some(args) => use_function(&args, func),
None => use_function_no_args(func),
};
let result = use_function(&args, func);

return quote!(vec![::std::borrow::Cow::from(format!("{}", #result))]);
} else if let Some(custom_format) = &attr.format {
Expand All @@ -536,7 +535,7 @@ fn get_field_fields(
if let Some(i) = find_display_type(field_type, &type_attrs.display_types) {
let (_, func, args) = &type_attrs.display_types[i];
let args = args_to_tokens_with(fields, field, field_name, args);
let func = use_function(&args, &func);
let func = use_function(&args, func);

return quote!(vec![::std::borrow::Cow::from(format!("{}", #func))]);
}
Expand Down

0 comments on commit cca0604

Please sign in to comment.