fn rav1d_log: Replace with safe write! calls to a fully safe Rav1dLogger#619
Merged
fn rav1d_log: Replace with safe write! calls to a fully safe Rav1dLogger#619
fn rav1d_log: Replace with safe write! calls to a fully safe Rav1dLogger#619Conversation
|
Since rust-lang/rust#117472 has been merged, I think cstr crate could be removed sometime. |
Collaborator
Author
Oh, that's awesome! Thanks for letting me know! I saw the RFC got accepted earlier but I didn't realize it would be stabilized so soon. We'll remove |
rinon
reviewed
Dec 14, 2023
rinon
reviewed
Dec 14, 2023
rinon
reviewed
Dec 14, 2023
…1dLogger`.
The existing variadic `rav1d_log` calls are replaced with `write!` calls
to an `Option<Rav1dLogger>` field.
`enum Rav1dLogger`'s interface is `fn write_fmt`, which `write!` calls.
These are defined as part of `trait Rav1dLog`, similar to `trait {io,fmt}::Write`.
The difference is that no errors are returned (we don't really need them)
and crucially, they are `&self` methods as opposed to `&mut self` methods,
which keeps things much simpler for the borrow checker.
`enum Rav1dLogger` can be `Dav1d` or `Std{out,err}` for now.
The `Dav1d` variant is necessary to convert to/from the `Dav1dLogger`,
and `Stderr` is the default logger used (and `Stdout` is trivially similar).
There will presumably be other loggers desired,
but it's easier to leave those for later once we know their desired behaviors better.
The `Dav1d` variant is called by implementing `fmt::Write`,
which lets us just implement `fn write_str` and have `fn write_fmt` auto-implemented.
`fn write_str` is implemented correctly but with poor performance by printing byte by byte.
This is to avoid dealing with intermediary null characters
and having to allocate a new null-terminated `CString`.
This is for logging so perf isn't important,
and if better perf is desired, users can switch
to the Rust API, which has no such limitation.
Then we construct a bijection between `{D,R}av1dLogger`
to allow the bidirectional conversions needed in the `DAV1D_API`s.
This is done by storing the `Std{out,err}` variants as special `Dav1dLogger::callback` `fn`s.
During the conversion back, if the callback is one of those special `fn`s,
we can decode it back into the same `Rav1dLogger` it originally was.
With use of the `Dav1dLogger::cookie` field, this can be extended
to other `Rav1dLogger` variants in the future as well.
9740d25 to
349b43c
Compare
This was the wrong default. It was the zero value, not the actual default. And users of the C API will just set the fields directly, so go back to the that in the binaries.
…until `c"strings"`'s stabilization reaches stable.
….callback.unwrap()`.
… if`, ... with a `match` with `if guards.
…nd into the binaries. The binaries aren't important, so it's useful to fully remove these from the important `rav1d` lib.
0232c47 to
18271ff
Compare
rinon
approved these changes
Dec 18, 2023
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The existing variadic and
unsaferav1d_logcalls are replaced withwrite!calls to anOption<Rav1dLogger>field.enum Rav1dLogger's interface isfn write_fmt, whichwrite!calls. These are defined as part oftrait Rav1dLog, similar totrait {io,fmt}::Write. The difference is that no errors are returned (we don't really need them) and crucially, they are&selfmethods as opposed to&mut selfmethods, which keeps things much simpler for the borrow checker.enum Rav1dLoggercan beDav1dorStd{out,err}for now. TheDav1dvariant is necessary to convert to/from theDav1dLogger, andStderris the default logger used (andStdoutis trivially similar). There will presumably be other loggers desired, but it's easier to leave those for later once we know their desired behaviors better.The
Dav1dvariant is called by implementingfmt::Write, which lets us just implementfn write_strand havefn write_fmtauto-implemented.fn write_stris implemented correctly but with poor performance by printing byte by byte. This is to avoid dealing with intermediary null characters and having to allocate a new null-terminatedCString. This is for logging so perf isn't important, and if better perf is desired, users can switch to the Rust API, which has no such limitation.Then we construct a bijection between
{D,R}av1dLoggerto allow the bidirectional conversions needed in theDAV1D_APIs. This is done by storing theStd{out,err}variants as specialDav1dLogger::callbackfns. During the conversion back, if the callback is one of those specialfns, we can decode it back into the sameRav1dLoggerit originally was. With use of theDav1dLogger::cookiefield, this can be extended to otherRav1dLoggervariants in the future as well.This also makes it fairly easy to eliminate
#.