Code Monkey home page Code Monkey logo

Comments (12)

SergioBenitez avatar SergioBenitez commented on May 22, 2024 2

@dhruvkb There isn't currently. I'll be getting to a version of what I posted above soon.

from figment.

SergioBenitez avatar SergioBenitez commented on May 22, 2024 1

I went ahead and hard-coded adjoin, which provides the requested functionality. It would be nice to get the generic version in, but hopefully this suffices for now. If someone else comes across this issue with a use-case for the generic version, I'd be really interesting in hearing it!

from figment.

SergioBenitez avatar SergioBenitez commented on May 22, 2024 1

@SergioBenitez I'm actually looking for a function where the latter values overwrites the former value (like merge), except in the case of vectors where they are concatenated (like adjoin)... an admerge, if you will.

I made the changes I need in a fork as a demo. I'd be happy to open a PR if you would consider merging this.

Sure, let's get it merged!

from figment.

SergioBenitez avatar SergioBenitez commented on May 22, 2024

It's an interesting concept, but I'm not sure how this would really work. What kind of API are you envisioning? Do you have a use-case motivating the idea?

from figment.

LeSnake04 avatar LeSnake04 commented on May 22, 2024

My usecase is a list of saved objects (In my case search and replace filters). My goal is that I as Developer do some prebuild ones, the OS maintaers or package maintainers can provide some and the user can save them.

How I would mark this when defining the struct

#[derive(Serialize, Desearialize)]
#[figment]
struct Config {
    #[figment(append_vec)]
    presets: Vec<Preset>
    // Treat this vector like you do now
    other_vec: Vec<String>
}

#[derive(Serialize, Desearialize)]
struct Preset {
    name: String,
    search: String,
    replace: String
}

from figment.

SergioBenitez avatar SergioBenitez commented on May 22, 2024

I thought about this some more today. One idea is to make join and merge configurable.

Internally, Figment has a provide method on Figment that switches between joining and merging. We could expose this method and make it easier to use. We would still provide join and merge, but we'd also allow completely custom conflict-resolution via provide. I think this would be awesome.

I'd be open to API ideas here. I don't have any specific ideas in mind. We obviously want it to be simple to implement the merge, join, and append strategy you've specified above. I'd be totally open to design ideas.

from figment.

LeSnake04 avatar LeSnake04 commented on May 22, 2024

That would be great, so we can handle special cases/needs like this without having to work around the existing implementation.

There should be an easy way to only overwrite it for specific fields though:

#[derive(Serialize, Desearialize, Figment)]
struct Config {
    #[figment(custom_parser)]
    presets: Vec<Preset>
    // Treat this vector like you do now
    other_vec: Vec<String>
}

#[derive(Serialize, Desearialize)]
struct Preset {
    name: String,
    search: String,
    replace: String
}

That way the default one should just skip the field, but parse all other ones, and panic (if possible, send a compiler error) when there is no custom parser for the fields marked.

Maybe it makes sense, to do this specific thing build in, since I assume what I am doing is rather common. But custom parsers would make it more flexible for others.

from figment.

SergioBenitez avatar SergioBenitez commented on May 22, 2024

Figment doesn't have a custom derive now, and I don't think we should add one. It adds a lot of complexity to the codebase, especially in terms of publishing and testing, and it adds a whole layer of compatibility issues with user's code. Plus, there's really no need for it in this case.

The approach I want to take, and the one I was alluding to, is to make the aforementioned provide() method generic on the conflict resolution mechanism:

fn provide<T: Provider, R: Resolver>(self, provider: T, resolver: R) -> Self;

The question is what the Resolver trait should look like. The current implementation of something similar in Figment is pretty complex, and it's probably not what we want to expose. But something like it would be nice. I'll think about this a bit more now and report back when I have something.

from figment.

SergioBenitez avatar SergioBenitez commented on May 22, 2024

Update: I have a working implementation of the idea that I'm not yet quite happy enough with. Implementing the "join vector" strategy looks like this:

/// ```rust
/// use figment::Figment;
/// use figment::coalesce::JoinVecs;
///
/// let vec: Vec<u8> = Figment::new()
///     .join(("k", vec![1, 2, 3]))
///     .provide(("k", vec![4, 5, 6]), JoinVecs)
///     .extract_inner("k")
///     .unwrap();
///
/// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]);
/// ```
pub struct JoinVecs;

impl Coalescer for JoinVecs {
    fn coalesce_selection(&mut self, first: Profile, second: Profile) -> Profile {
        first.join_with(second, self)
    }

    fn coalesce_data(&mut self, first: Data, second: Data) -> Data {
        first.join_with(second, self)
    }

    fn coalesce_value(&mut self, first: Value, second: Value) -> Value {
        first.join_with(second, self)
    }

    fn coalesce_dict(&mut self, first: Dict, second: Dict) -> Dict {
        first.join_with(second, self)
    }

    fn coalesce_array(&mut self, mut first: Vec<Value>, mut second: Vec<Value>) -> Vec<Value> {
        first.extend(second.drain(..));
        first
    }
}

from figment.

dhruvkb avatar dhruvkb commented on May 22, 2024

I need this feature. Is there a workaround to have vectors being appended instead of overwritten before this feature is included to the library?

from figment.

LeSnake04 avatar LeSnake04 commented on May 22, 2024

My current woraround is using custom code that reads a conf.d type of dir and replacing the value Figment generated.

let global_sets_dir = PathBuf::from("/etc/renameplus/sets.d");
  let user_sets_dir = {
   let mut out = dirs::config_dir().context("Failed to get config dir")?;
   out.push("renameplus");
   out.push("sets.d");
   out
  };
  if !user_sets_dir.exists() {
   err_log +=
    std::fs::create_dir_all(&user_sets_dir).context("Failed to create user sets.d");
  }
  let global_config_path = "/etc/renameplus.toml";
  let user_config_path: PathBuf = {
   let mut out = dirs::config_dir().context("Failed to get config dir")?;
   out.push("renameplus");
   out.push("config.toml");
   out
  };
  let mut conf: Self = err_log
   .push_result(
    Figment::new()
     .merge(Toml::file(global_config_path))
     .merge(Toml::file(user_config_path))
     .merge(Env::prefixed("renameplus_"))
     .extract()
     .context("Failed to parse config"),
   )
   .unwrap_or_default();
  let sets: Vec<ReplaceSetData> = {
   let mut out: Vec<ReplaceSetData> = Self::builtin_sets()
    .into_iter()
    .map(|set| ReplaceSetData {
     used: conf.is_set_default(&set.name),
     set,
     editable: false,
    })
    .collect();
   err_log += conf.find_sets(&mut out, global_sets_dir, false);
   err_log += conf.find_sets(&mut out, user_sets_dir, true);
   out
  };
  conf.sets = Some(sets);

from figment.

dhruvkb avatar dhruvkb commented on May 22, 2024

@SergioBenitez I'm actually looking for a function where the latter values overwrites the former value (like merge), except in the case of vectors where they are concatenated (like adjoin)... an admerge, if you will.

I made the changes I need in a fork as a demo. I'd be happy to open a PR if you would consider merging this.

from figment.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.