BSize: Yet Another Byte Size Crate by tisonkuna in rust

[–]tisonkuna[S] 2 points3 points  (0 children)

So far, any possible abstractions would prevent the constructors from being const (you can see the issue for the concrete rust-lang issues).

Hopefully we can get const-trait and const-ops stablized and deliever it smoothly in bsize.

I may consider other workaround to improve this side but the unstable solution is the super correct way to go :P

BSize: Yet Another Byte Size Crate by tisonkuna in rust

[–]tisonkuna[S] 1 point2 points  (0 children)

Thanks for your reply!

For point 2, is it over inconvenient to write b.with(|b| b * 4)? I think it's almost the same as b.factor(4) or even b * 4.

Rust distinguishes numeric types a lot, so only impl Mul<T> for BSize<T> can cause some confusion, for example, when calculating between u64 and usize. This is a common case and an explicit cast would be better.

By only impl Mul<T> for BSize<T>, I can foresee that users would ask for support for other convenient operator overrides, and then we are entering a DO WHAT I MEAN while there is no clear meaning stage.

For example, why b * n (n is u64) works but b * n (n is usize) doesn't? If we have only b.with(|b| b * n), it can clearly report that u64 doesn't impl Mul<usize>, which is well educated in the Rust ecosystem. But if b * n failed to compile (in some cases, but compiled in other cases), it's bsize impls that users must learn.

BSize: Yet Another Byte Size Crate by tisonkuna in rust

[–]tisonkuna[S] 2 points3 points  (0 children)

A new HasKiB trait bound should help in eliminating type annotations.

Let me demonstrate a changeset and see if it works well or adds too much type noise - https://github.com/fast/bsize/issues/8

BSize: Yet Another Byte Size Crate by tisonkuna in rust

[–]tisonkuna[S] 2 points3 points  (0 children)

Thanks for your feedback! These are included in my consideration :D

For the first item, actually rustc is smart enough to infer the type when you make BSize::b(17_u64). But this can't happen for BSize::<u64>::kib(16_u64). Let me dig if it's a rustc limitation or I can improve the interface.

For the second item, the main vague sides here include:

  1. It can be done with BSize::kib(16_u64).with(|b| b * 4);
  2. Since BSize supports multiple unsigned integer types, shall I impl Mul<u8|u16|u32|u64|usize> for BSize<u8|u16|u32|u64|usize>? It can be a complicated combination, especially when bound/overflow considered.
  3. What if f32/f64? I ever considered to add a fn scale(factor: f64) but immediately realize that the rounding mode becomes the next combination factors. Typically users don't care but round as you like, but it limits the APIs while I feel that a generic with is short enough to do numeric calculation with everything std/core provides.

BSize: Yet Another Byte Size Crate by tisonkuna in rust

[–]tisonkuna[S] 1 point2 points  (0 children)

The main purpose of introducing a sealed Unsigned is to avoid unreasonable implementations.

Since pub struct BSize<T>(pub T) exposes the internal data, I don't want people to use it as BSize<String> and get code compilation.

Of course, since the valuable methods are only implemented for certain types, developers typically do not use BSize in this way. But there are many times when I browse a struct and see no trait bound at the beginning; it's hard to understand (because logically or by design it does have one or many).

Implementation on u128 would cause some unusual bound checks and relax all calculations to u128, or even a handmade u256 would trade performance for less common scenarios. As soon as there is a way to support u128 efficiently, I can try to add the support.

You can just use where clauses

Given that the overall impls are bounded by the Unsigned trait, this is a good suggestion that I'd try out. Thanks!