pub struct DiplomatWrite { /* private fields */ }Expand description
An object that can one can write UTF-8 strings to
This allows the C API to write to arbitrary kinds of objects, for example a C++ std::string or a char buffer.
The way to use this object is to fill out the buf, len, cap fields with
appropriate values for the buffer, its current length, and its current capacity,
and flush and grow with appropriate callbacks (using context to reference any
state they need). This object will be passed by mutable reference to the Rust side,
and Rust will write to it, calling grow() as necessary. Once done, it will call flush()
to update any state on context (e.g. adding a null terminator, updating the length).
The object on the foreign side will be directly usable after this, the foreign side
need not perform additional state updates after passing an DiplomatWrite to
a function.
May be extended in the future to support further invariants
DiplomatWrite will not perform any cleanup on context or buf, these are logically
“borrows” from the FFI side.
§DiplomatWrite is Polymorphic
Instances of DiplomatWrite can be created from multiple different sources.
There are two constructors available in diplomat_runtime:
- [
diplomat_simple_write()] to write to a fixed-size buffer. diplomat_buffer_write_create()to write to a Vec allocated by Rust. A wrapper is provided:RustWriteVec.
Backends may have additional constructors for writing to various shapes of buffer.
⚠️ Because DiplomatWrite is polymorphic, the destructor must know how the instance
was constructed. It is therefore unsound to use functions such as core::mem::swap
on instances of DiplomatWrite with potentially different sources. For example,
the following code is not safe:
use diplomat_runtime::DiplomatWrite;
fn bad(write: &mut DiplomatWrite) {
let mut some_other_write: DiplomatWrite = unimplemented!();
// Not safe! The two `DiplomatWrite`s have different invariants
core::mem::swap(write, &mut some_other_write);
}As a result, any function that returns an owned DiplomatWrite or a &mut DiplomatWrite
must be unsafe. For an example, see [RustWriteVec::borrow_mut].
Diplomat backends guarantee they will only ever hand the same type of DiplomatWrite object to Rust
code; this is only something you need to worry about if using RustWriteVec,
or DiplomatWrite objects manually created in Rust via APIs like diplomat_simple_write.
§Safety invariants:
flush()andgrow()will be passedselfincludingcontextand it should always be safe to do so.contextmay be null, howeverflush()andgrow()must then be ready to receive it as such.bufmust be a valid pointer tocapbytes of memorybufmust point tolenconsecutive properly initialized bytescapmust be less than or equal to isize::MAXgrow()must either return false or updatebufandcapfor a valid buffer of at least the requested buffer size.- If grow_failed is true all safety invariants on buf/cap/len MUST still hold.
DiplomatWrite::flush()will be automatically called by Diplomat.flush()might also be called (erroneously) on the Rust side (it’s a public method), so it must be idempotent.