Simple zero-dependency visitor for kv::Value #440
Labels
No labels
bug
duplicate
easy
enhancement
help wanted
invalid
question
rfc
structured-logging
wontfix
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-rust-lang/log#440
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Motivation
Users want to be able to visit simple primitives captured in
kv::Values but currently resort to chaining calls like:This is flaky and not fun to write. The goal of the current design is that if you're serializing values you probably already have a serialization framework handy (either
std::fmt,serde, orsval) that you'll want to use.There are reasons to want to visit values without pulling one of these in though. For example, https://github.com/Thomasdezeeuw/std-logger/pull/29#discussion_r553903486 wants to write custom formatting logic to make use of
IoSlices, and others don't want the additional mental overhead in learning another framework.Proposal
Add a simple zero-dependency visit API for
log::kv::Valuethat can be used instead of chainingto_*methods or learning a full serialization framework. It intentionally won't support complex values, but should be enough for simple cases to get off the ground with. A new trait,kv::value::Visitorwill be added with the following methods:with a default implementation looking something like:
A
Valuecan be visited using an inherentvisitmethod:Other methods can be overridden to customize their behavior.
Migrating from
value::VisitortosvalorserdeIf callers want to switch from
value::Visitortosvalorserdeto support more complex serialization needs, the change will be from callingValue::visitto either<Value as sval::Value>::streamor<Value as serde::Serialize>::serialize.Questions
Why not add these to
source::Visitor?The
source::Visitortrait is centred aroundvisit_pair, which lets us build higher-level methods on top, likeget. If we add other methods tosource::Visitorit may become confusing how the trait should be implemented to support these higher-level methods.Why does
visit_anytake aValue?The
Valuetype is a carrier for a bunch of trait implementations,fmt::Debug,fmt::Display, and possiblysval::Value, andserde::Serialize. By passing in aValuehere we give the caller flexibility to decide what trait they want to use without adding a lot of complexity to thevalue::Visitortrait.If we wanted to re-introduce the
FillAPI which would be needed to do zero-cost bridging betweenlogandtracingthen thisVisitortype could be used in place of thatSlot, which is really just avalue::Visitor.I've updated the proposed trait based on the design that ended up coming out of
value-bagin https://github.com/sval-rs/value-bag/pull/16All it really does is add a
'vlifetime to thevalue::Visitortrait, so that it becomes possible to capture borrowed strings across calls if you need. This'vlifetime will be the same as the'kvsinVisitor::visit_pair<'kvs>so it ends up being threaded all the way through from a borrow of theSourceto visitors of theValues.Now that we've got
0.4.14out we can make progress on this 🎉@KodrAus what parts are missing to implement this?
Hey @Thomasdezeeuw 👋
The implementation work was actually all there, so I've opened up #467 that surfaces the visitor API.