From 285ec938d7c8eab89a60f140edceecd1ad407f25 Mon Sep 17 00:00:00 2001 From: Gavrilikhin Daniil Date: Sat, 23 Mar 2024 19:11:44 +0800 Subject: [PATCH] Add DisplayWithDb --- components/salsa-2022/src/display.rs | 27 ++++++++++ components/salsa-2022/src/lib.rs | 2 + salsa-2022-tests/tests/display.rs | 76 ++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 components/salsa-2022/src/display.rs create mode 100644 salsa-2022-tests/tests/display.rs diff --git a/components/salsa-2022/src/display.rs b/components/salsa-2022/src/display.rs new file mode 100644 index 00000000..4ddfc028 --- /dev/null +++ b/components/salsa-2022/src/display.rs @@ -0,0 +1,27 @@ +use std::fmt::{self, Display, Formatter}; + +pub trait DisplayWithDb<'db, DB: ?Sized + 'db> { + fn fmt_with(&self, db: &DB, f: &mut Formatter<'_>) -> fmt::Result; + + fn display_with(&self, db: &DB) -> impl Display { + FormatterFn(|f| self.fmt_with(db, f)) + } + + fn to_string_with(&self, db: &DB) -> String { + self.display_with(db).to_string() + } +} + +// TODO: replace with `[std::fmt::FormatterFn]` when it becomes stable +struct FormatterFn(pub F) +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result; + +impl Display for FormatterFn +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0)(f) + } +} diff --git a/components/salsa-2022/src/lib.rs b/components/salsa-2022/src/lib.rs index d3fe4ddd..d6f5c9e4 100644 --- a/components/salsa-2022/src/lib.rs +++ b/components/salsa-2022/src/lib.rs @@ -3,6 +3,7 @@ pub mod cancelled; pub mod cycle; pub mod database; pub mod debug; +pub mod display; pub mod durability; pub mod event; pub mod function; @@ -32,6 +33,7 @@ pub use self::database::ParallelDatabase; pub use self::database::Snapshot; pub use self::debug::DebugWith; pub use self::debug::DebugWithDb; +pub use self::display::DisplayWithDb; pub use self::durability::Durability; pub use self::event::Event; pub use self::event::EventKind; diff --git a/salsa-2022-tests/tests/display.rs b/salsa-2022-tests/tests/display.rs new file mode 100644 index 00000000..0ac1341d --- /dev/null +++ b/salsa-2022-tests/tests/display.rs @@ -0,0 +1,76 @@ +//! Test that `DisplayWithDb` works correctly + +use std::fmt::Display; + +use expect_test::expect; +use salsa::DisplayWithDb; + +#[salsa::jar(db = Db)] +struct Jar(MyInput, ComplexStruct); + +trait Db: salsa::DbWithJar {} + +#[salsa::input] +struct MyInput { + field: u32, +} + +impl<'db> DisplayWithDb<'db, dyn Db + 'db> for MyInput { + fn fmt_with(&self, db: &dyn Db, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "MyInput({})", self.field(db)) + } +} + +#[derive(Debug, Eq, PartialEq, Clone)] +struct NotSalsa { + field: String, +} + +impl Display for NotSalsa { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "NotSalsa({})", self.field) + } +} + +#[salsa::input] +struct ComplexStruct { + my_input: MyInput, + not_salsa: NotSalsa, +} + +impl<'db> DisplayWithDb<'db, dyn Db + 'db> for ComplexStruct { + fn fmt_with(&self, db: &dyn Db, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "ComplexStruct {{ {}, {} }}", + self.my_input(db).display_with(db), + self.not_salsa(db) + ) + } +} + +#[salsa::db(Jar)] +#[derive(Default)] +struct Database { + storage: salsa::Storage, +} + +impl salsa::Database for Database {} + +impl Db for Database {} + +#[test] +fn input() { + let db = Database::default(); + + let input = MyInput::new(&db, 22); + let not_salsa = NotSalsa { + field: "it's salsa time".to_string(), + }; + let complex_struct = ComplexStruct::new(&db, input, not_salsa); + + // all fields + let actual = format!("{}", complex_struct.display_with(&db)); + let expected = expect!["ComplexStruct { MyInput(22), NotSalsa(it's salsa time) }"]; + expected.assert_eq(&actual); +}