Open DaniPopes opened 1 month ago
AutoStream can be consumed to get the wrapped S: RawStream, but there is currently no way to get a reference to it.
Could you add to the PR description the use case for why this would be needed?
Changes Missing Coverage | Covered Lines | Changed/Added Lines | % | ||
---|---|---|---|---|---|
crates/anstream/src/strip.rs | 0 | 4 | 0.0% | ||
crates/anstream/src/wincon.rs | 0 | 4 | 0.0% | ||
crates/anstream/src/auto.rs | 0 | 10 | 0.0% | ||
<!-- | Total: | 0 | 18 | 0.0% | --> |
Totals | |
---|---|
Change from base Build 11282311767: | -0.5% |
Covered Lines: | 1221 |
Relevant Lines: | 2373 |
Could you add to the PR description the use case for why this would be needed?
Done.
My use case for this is being able to get the &mut dyn Write while storing AutoStream<Box
>, and to either write directly to it or downcast it to Vec to get the access to the written bytes.
Please expand on why
note: generally I require Issues first where this is all figured out. It isn't always ideal to have these conversations in PRs.
Figured it would be straight-forward enough that it wouldn't require an issue.
I have a potentially Vec<u8>
buffer inside of a Box<dyn Write>
, I want a reference to it so I can copy/take the written bytes out of it to return them as a stand-alone String
or stored somewhere else separately, while keeping the AutoStream
instance.
Currently I have to either store a raw pointer to the Box<dyn Write>
separately so I can get a reference to it later, or have something like two instances of struct SharedBuffer(Arc<Mutex<Vec<u8>>>)
so I can access my buffer just because it's not exposed through the AutoStream
API.
Correct me if I'm wrong, but given that AutoStream
already guarantees that it stores an owned S
because of the into_inner
method, it should also be fine to provide getters to this instance.
Figured it would be straight-forward enough that it wouldn't require an issue.
Correct me if I'm wrong, but given that AutoStream already guarantees that it stores an owned S because of the into_inner method, it should also be fine to provide getters to this instance.
AutoStream
is stateful and care was taken into the design to try to minimize the chance that the inner
would be read from or written to mid-state. into_inner
is an explicit acknowledgement that you are abandoning that state while references, particularly mutable references, can muck this up.
I need to weigh out your use case and the complexity foisted on you against helping to prevent bugs for others. The more generally applicable it seems, the more it weighs in favor of making the change.
I have a potentially Vec
buffer inside of a Box , I want a reference to it so I can copy/take the written bytes out of it to return them as a stand-alone String or stored somewhere else separately, while keeping the AutoStream instance.
Maybe asked a different way, what problem are you trying to solve? Why do you need a single AutoStream
alive while pulling its state out?
I can get a reference to it later, or have something like two instances of struct SharedBuffer(Arc<Mutex<Vec
>>) so I can access my buffer just because it's not exposed through the AutoStream API.
Depending on your use case, you may be able to use RefCell
.
AutoStream is stateful and care was taken into the design to try to minimize the chance that the inner would be read from or written to mid-state. into_inner is an explicit acknowledgement that you are abandoning that state while references, particularly mutable references, can muck this up.
Hmm, another interesting design idea that I don't think of enough is the use of extension traits to opt-in to potentially dangerious (but not unsafe
) behavior, like indexmap does with https://docs.rs/indexmap/latest/indexmap/map/raw_entry_v1/trait.RawEntryApiV1.html
Maybe asked a different way, what problem are you trying to solve? Why do you need a single AutoStream alive while pulling its state out?
I am using similar setup to the rustc diagnostics system:
HumanEmitter
stores its output as AutoStream<Box<dyn Write>>
(rustc uses Box<dyn termcolor::WriteColor>
which in principle is the same)JsonEmitter
uses HumanEmitter
internally to emit to a Vec<u8>
My goal is to obtain the &[u8]
to the buffer of emitted diagnostics. I have thought of 3 possible ways of achieving this:
&mut Vec<u8>
; this requires a. making HumanEmitter generic over the writer type and b. a non-static inner writer type, which only works in the temporary JsonEmitter
case, and not when I want to query for this buffer through dyn Emitter
or HumanEmitter<dyn...>
Box<dyn WriteExt>
, which has extra methods for what I need from the writer, namely something like fn buffer(&self) -> Option<&[u8]>
; this is not possible through AutoStream
because the inner writer type must be one of the predefined RawStream
, and requires access to itTypeId
alongside the writer on creation so that the original type can be retrieved later with a dynamic downcast; this also requires access to a pointer to the inner writerHmm, another interesting design idea that I don't think of enough is the use of extension traits to opt-in to potentially dangerious (but not unsafe) behavior
That would be fine by me if it is deemed necessary for this API. I would imagine that it wouldn't be required for immutable references.
Thanks for explanation.
Are you always using Vec<u8>
Is there a reason not to just use AutoStream<Vec<u8>>
or even just Vec<u8>
and adapt it later when the read the Vec<u8>
and then do something with it? With deferred processing, that was mostly my intent of how to handle this. The design is focused on keeping ANSI escape codes until you present it to the user.
AutoStream
can be consumed to get the wrappedS: RawStream
, but there is currently no way to get a reference to it.My use case for this is being able to get the
&mut dyn Write
while storingAutoStream<Box<dyn Write>>
, and to either write directly to it or downcast it toVec<u8>
to get the access to the written bytes.