Json: Feature request: Core trait implementations for Value and Number

Created on 14 Oct 2020  路  3Comments  路  Source: serde-rs/json

Working with Values and Numbers would be much less arduous if certain common traits were implemented. My suggestions:

Value:

  • PartialOrd
  • Ord (this one's debatable)

Number:

  • PartialOrd
  • Ord
  • Add
  • AddAssign
  • Sub
  • SubAssign
  • Mul
  • MulAssign
  • Div
  • DivAssign
  • Neg

I recognize that most of the numeric traits would involve some implicit casting, but I feel that's a reasonable thing to do here.

I'm not sure whether leaving these off was a design decision or whether it just hasn't been implemented by anyone. In the latter case I may be able to implement them myself.

Most helpful comment

I second this. I would add Hash to the list.

Right now I'm working on essentially diffing two json trees, and being able to easily do set operations on arrays would be useful!

All 3 comments

I second this. I would add Hash to the list.

Right now I'm working on essentially diffing two json trees, and being able to easily do set operations on arrays would be useful!

It looks like Hash can be derived for everything in the Value type except for f64.

Hash is not implemented for f64, but the requirements on Hash are:

k1 == k2 -> hash(k1) == hash(k2)

Strictly speaking, since NaN != NaN there's nothing there prohibiting hash(NaN) == hash(NaN) or hash(NaN) != hash(NaN). Also, since floating points have distinct binary encodings for -0 and 0, we'd have to make a special case for that, but beyond this all other values of f64 should follow that requirement. So, for our purposes, maybe it's ok to impl Hash for Number something like this:

impl Hash for N {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match self {
            N::PosInt(n) => n.hash(state),
            N::NegInt(n) => n.hash(state),
            N::Float(n) => {
                if *n == 0.0f64 || *n == -0.0f64 {
                    0.0f64.to_be_bytes().hash(state);
                } else {
                    n.to_be_bytes().hash(state);
                }
            }
        }
    }
}

Is this sensible? Maybe only behind a feature flag?

I'd also be interested in this, I have a situation in which I'd like to ensure that objects that are identical in value have exactly the same structure (order of keys in Value::Map and order of Values inside Vec<Value> for Value::Array). Having Ord implemented on Value would make this much simpler.

This might also be too niche a concern. 馃榾 Just want to mention it in case this is helpful context.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

allan-simon picture allan-simon  路  6Comments

dtolnay picture dtolnay  路  3Comments

AerialX picture AerialX  路  5Comments

dtolnay picture dtolnay  路  6Comments

nlordell picture nlordell  路  4Comments