marshallpierce / base64-serde

Integration between rust-base64 and serde

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Expose types based on the four base64 configurations from this crate itself

Arnavion opened this issue · comments

Is there a reason why lib.rs does not have

base64_serde_type!(pub Base64Standard, STANDARD);
base64_serde_type!(pub Base64StandardNoPad, STANDARD_NO_PAD);
base64_serde_type!(pub Base64UrlSafe, URL_SAFE);
base64_serde_type!(pub Base64UrlSafeNoPad, URL_SAFE_NO_PAD);

?

These come to mind:

  • Every addition to the public API should "carry its weight" -- it should provide real value to compensate for the necessary limitation on future API evolution that any addition carries with it. In this case, you're saving the cost of writing one line like the above by writing a use line... I'm not sure that's actually even an improvement for the consumer, as the pre-built type would be less explicit in what it's doing.
  • You missed one (MIME), which brings up the next point: having lists of names that need to match across crates feels like a pretty bad idea.

it should provide real value to compensate for the necessary limitation on future API evolution that any addition carries with it.

What limitation on future API evolution could be created? Any change that leads to a breaking change in the user's crate necessitates a version bump of this crate, regardless of whether the macro was expanded in this crate or theirs.


In this case, you're saving the cost of writing one line like the above

My real use case is somewhat complicated in that I don't have an easy place to invoke the macro in my crate, but I'm not using it as motivation for this issue.

My motivation is completely that there is precedent in crates that provide separate serde impls from the base crate, like url_serde, and I expected the same from this crate.


the pre-built type would be less explicit in what it's doing.

This does not follow. It provides as much information as the name base64::STANDARD provides in the base64 crate. What an item means is only discovered by reading the docs for the item.


You missed one (MIME)

Indeed, I didn't realize MIME was a configuration. I was used to the names of the encodings from golang's library.


having lists of names that need to match across crates feels like a pretty bad idea.

  • There are only five of them.

  • If more are added to the base64 crate but not to this crate, and the user wants to use the new Config, the original method of invoking the macro with a custom Config still exists. If any is removed or renamed from base64, that would happen behind a version bump and the compilation of neither this crate nor the crates that depend on it would be affected.

  • There would be an argument for not providing pre-configured types if this crate was completely independent from the base64 crate. But it isn't - base64 is a required dep of this crate and thus this crate is associated with a particular base64 version.

What limitation on future API evolution could be created?

Naming conventions, for one.

My real use case is somewhat complicated in that I don't have an easy place to invoke the macro in my crate, but I'm not using it as motivation for this issue.

I'm OK with it being a motivation. :) I'm curious why that is; is there some quirk of the Rust's module system that I'm not thinking of that would mean you couldn't just put it in the root of your crate or something like that? Why would having a type in this crate be easier to use than a type in your crate?

This does not follow. It provides as much information as the name base64::STANDARD provides in the base64 crate. What an item means is only discovered by reading the docs for the item.

I guess we'll just have to agree to disagree, then. I don't consider documentation equivalent in explicitness to code.

While there are other crates and libraries that do things differently. I happen to think that that's a bad precedent. If an API is so cumbersome that it's worth duplicating lists of names or other options across libraries to save users from the burden, IMO that is a problem that should be solved by means other than embracing the chaos. Such bloat also clutters the API, giving consumers more to read before they can figure out what it is that they want. A careful consumer might wonder if a hypothetical pre-baked type is equivalent to applying the macro themselves, or is there some other harder to reproduce aspect of the pre-baked types.

In this situation, the presence of, say, URL_SAFE has value because the precise configuration of that particular alphabet is finicky, and users shouldn't have to deal with that, But, it's behind a Config abstraction, and if the rest of the ecosystem can't just use that as is, there should be a better reason than "I like that line of code better than this line of code".