-
-
Notifications
You must be signed in to change notification settings - Fork 73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] display hints (:x
, :b
, :a
)
#270
Comments
to expand on this: existing probe-run versions like 0.1.6 expect a certain format string syntax. if we extend the format string syntax in defmt 0.1.x then probe-run 0.1.6 will fail to decode the defmt data. The failure mode is silent failure: the log stream stops and the application keeps running. for that reason any change in the format string syntax needs to be done in defmt 0.2.0. That defmt version will work with a probe-run 0.2.0, which will not work with defmt 0.1.0: the tool will reject apps that use defmt 0.1 -- it will refuse to flash them and tell you to use a different probe-run version |
note that the goal of this RFC is not to list upfront all the possible display hints but rather specify the feature in a way that let us add new display hints without those additions being breaking changes. That way we can add display hints in the 0.2.x series |
The prosposed syntax feels somewhat ambiguous...?
Alternative 1: join both into string, and require the hints to be "prefixes" to the type. info!("{}", 42);
info!("{:u8}", 42);
info!("{:x}", 42);
info!("{:xu8}", 42);
Alternative 2: specify type with one special char, hint with another. For example using info!("{}", 42);
info!("{=u8}", 42);
info!("{:x}", 42);
info!("{:x=u8}", 42);
info!("{=u8:x}", 42);
Just to clarify, this means the decoder ignores unknown hints, but the macros still reject unknown hints?
👍 to the prefix: removes ambiguity and makes pasting to other tools do the right thing.
I'd say format hint How does it interact with structs? my guess is like this: struct S { x: &str }
info!("{}", S { x: "hello!" });
// -> INFO S { x: hello! }
info!("{:?}", S { x: "hello!" });
// -> INFO S { x: "hello!" } |
Printing quoted strings is also useful for |
we'll like to ease migration from log and have some level of inter-op between defmt and log so I think we'd like to use the syntax for the type is not set in stone. prefixing it with a different symbol, e.g. as a side note we also considered moving the type info to the arguments, e.g. using type ascription syntax: // alternative
info!("{:x}", x: u8);
// this proposal
info!("{:u8:x}", x); but this is incompatible with the "bitfield range" type:
yes
this is unspecified. as far as forward compatibility is concerned I think it should be possible to have macros reject unknown hints at compile time. the main compatibility problem is: using a newer defmt patch version with an old probe-run (that supports the defmt major.minor version). as long as the probe-run's parser ignores unknown hints we should be fine; it should be OK if the macros' parser errors on unknown hints.
good question
this looks odd to me because in my mind |
Yeah, IMO it's the best thing. Macros shouldn't silently ignore errors, otherwise you can typo your format hint and waste time trying to figure out why is it doing nothing.
Yeah this looks odd to me too, but it's what current defmt does. It makes sense to print all structs quoted (the generated Format impl could just put |
I have incorporated the feedback into the RFC (issue description)
we need to specify what's the behavior of "hint collision": struct S { x: u8 }
impl Format for S {
fn format(&self, f: &mut Formatter) {
write!(f, "{:b}", self.x);
}
}
// does this use hexadecimal notation or binary notation?
info!("{:x}", S { x: 16 }); the impl fmt::Debug for S {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "S {{ x: {:b} }}", self.x)
// ^ cannot be overriden
}
}
// the `x` specifier is ignored
println!("{:x?}", S { x: 16 }); // -> S { x: 1000 } |
Using the innermost specifier sounds like a reasonable thing to do |
313: add display hints e.g. :x, :b, :a r=japaric a=japaric **breaking-change** this changes the format string syntax as specified in RFC #270 ``` rust // OLD syntax: will be rejected info!("{:u8}", 42); // NEW syntax: types are prefixed by '='; display hints are prefixed by ':' info!("{=u8:x}", 42); // Note that this works too and is now in line with the Rust std formatting syntax info!("{:x}", 42); ``` Display hints that have been implemented: - Binary (`:b`), e.g. `0b1010` - Upper case hexadecimal (`:X`), e.g. `0xA0` - Lower case hexadecimal (`:x`), e.g. `0xa0` - ASCII (`:a`), e.g. `b"he\xffllo` (works on byte slices `[u8]`) - Debug (`:?`), e.g. `"Hello"` (works on strings) TODO - [ ] update book and API doc FIXME - [ ] `derive(Format)` on structs that contains string fields formats those fields "Display"-style (w/o double quotes) (may not be necessary to block this PR on that fix though) Co-authored-by: Jorge Aparicio <jorge.aparicio@ferrous-systems.com>
implemented in #313 |
this is a feature proposed for version 0.2.0.
(this feature cannot be implemented in the 0.1.x series because it involves breaking changes in the wire format, parser and/or decoder.)
the design is not final and it's still being reviewed by the knurling team.
1. optional type annotation
(0.2's
{}
=== 0.1's{:?}
)In v0.2.0, the empty format parameter (
{}
) will be accepted. It will be understood as 'this is someimpl Format
value'.it will still possible to specify the type using the
=$type
syntax to improve encoding sizewhen format parameter includes both type and hint the type must come first:
:x=u8
is not valid syntax(this restriction could be lifted in the future)
this feature combined with feature (3) will ease migration from the
log!
macro to the defmt macros:if
{:$hint}
is a valid core::fmt format string then it's also a valid defmt format string2. default to
Display
-like format (fallback toDebug
)in 0.2.0 types, like strings, will be formatted "
Display
-like", that is without double quotes and escaped charactersif a type has no
Display
-like formatting option, it will formatted in aDebug
-like fashionIn 0.1.x this was not well specified
3. display hints
syntax
"display hints" can be tacked onto format parameters to tell a
defmt
printer that you want a value to be formatted (on the host side) in a certain wayas this is a hint, a printer (the host) may choose to ignore the hint
the hint propagates inwards and applies to struct / enum fields (recursively)
initial support
initially we plan to support the following hints:
x
(lowercase),X
(uppercase) hexadecimalb
binarya
ASCII?
Debugthe ASCII hint applies to byte arrays and slices.
when the printer sees this hint it should format the bytes using Rust's byte string literal notation.
Example:
?
formats the value in a Debug-like manner.For the
str
type this means the string will be double quoted and escapedforward compatibility
to allow for the possibility of adding more display hints in the v0.2.x series, defmt tools should ignore display hints they don't understand instead of throwing runtime errors.
macros will validate display hints and reject unknown hints at compile time
#[derive(Format)]
this macro will apply the
:?
display hint to all struct / enum fields.this way string fields will be printed with double quotes and escaped characters
this makes the behavior closer to the behavior of
#[derive(Debug)]
impl notes
unresolved questions
a.
0x1234_5678
/0b1111_0000
(with0x
suffix and grouping)pros:
cons:
b.
0x12345678
/0b11110000
(with0x
suffix and no grouping)pros:
valid Rust syntax
all programs understand this hexadecimal / binary format
cons:
harder to read large/long values
is the type / display order fixed? or is:x:u8
accepted?how to switch toDebug
-like format (e.g. for strings)?:?
or:#
?change type syntax to something less ambiguous? e.g.=u8
=u8:x
struct inter-operationshould macros reject unknown display hints?changelog
2020-11-25
added:
:?
is the "Debug"-like display hint=u8
(instead of:u8
) for type information:?
hint to struct / enum fieldsThe text was updated successfully, but these errors were encountered: