I am seeking to extend the pattern by utilizing default arguments in Rust as seen in previous question by someone which is using an "arguments" struct and the From
/Into
traits.
However, as you can see, the code clearly looks very redundant and adding associated functions to Foo
struct would require more code for the From
/Into
traits accordingly.
type FileName = Option<String>;
pub struct BarArg {
a: f64,
b: FileName,
}
impl Default for BarArg {
fn default() -> Self {
BarArg { a: 1.0, b: None }
}
}
impl From<()> for BarArg {
fn from(_: ()) -> Self {
Self::default()
}
}
impl From<f64> for BarArg {
fn from(a: f64) -> Self {
Self {
a,
..Self::default()
}
}
}
impl From<Option<String>> for BarArg {
fn from(b: Option<String>) -> Self {
Self {
b,
..Self::default()
}
}
}
impl From<(f64, Option<String>)> for BarArg {
fn from((a, b): (f64, Option<String>)) -> Self {
Self { a, b }
}
}
pub struct BazArg {
a: i32,
b: FileName,
}
impl Default for BazArg {
fn default() -> Self {
BazArg { a: 1, b: None }
}
}
impl From<()> for BazArg {
fn from(_: ()) -> Self {
Self::default()
}
}
impl From<i32> for BazArg {
fn from(a: i32) -> Self {
Self {
a,
..Self::default()
}
}
}
impl From<Option<String>> for BazArg {
fn from(b: Option<String>) -> Self {
Self {
b,
..Self::default()
}
}
}
impl From<(i32, Option<String>)> for BazArg {
fn from((a, b): (i32, Option<String>)) -> Self {
Self { a, b }
}
}
struct Foo;
impl Foo {
pub fn bar<A>(bar_arg: A)
where
A: Into<BarArg>,
{
match bar_arg.into().b {
Some(b) => {
println!("FileName is: {:?}", b);
}
None => {
println!("No FileName was passed");
}
};
}
pub fn baz<A>(baz_arg: A)
where
A: Into<BazArg>,
{
match baz_arg.into().b {
Some(b) => {
println!("FileName is: {:?}", b);
}
None => {
println!("No FileName was passed");
}
};
}
}
fn main() {
Foo::bar(());
Foo::bar(Some("bar.toml".to_string()));
Foo::baz(());
Foo::baz(Some("baz.toml".to_string()));
}
Is there any way to somehow implement these codes in a non-redundant and concise manner?