DiplomatWrite

Struct DiplomatWrite 

Source
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:

  1. [diplomat_simple_write()] to write to a fixed-size buffer.
  2. 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() and grow() will be passed self including context and it should always be safe to do so. context may be null, however flush() and grow() must then be ready to receive it as such.
  • buf must be a valid pointer to cap bytes of memory
  • buf must point to len consecutive properly initialized bytes
  • cap must be less than or equal to isize::MAX
  • grow() must either return false or update buf and cap for 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.

Implementations§

Source§

impl DiplomatWrite

Source

pub fn flush(&mut self)

Call this function before releasing the buffer to C

Source

pub fn as_bytes(&self) -> &[u8]

Returns a pointer to the buffer’s bytes.

If growth has failed, this returns what has been written so far.

Trait Implementations§

Source§

impl Borrow<DiplomatWrite> for RustWriteVec

Source§

fn borrow(&self) -> &DiplomatWrite

Immutably borrows from an owned value. Read more
Source§

impl Write for DiplomatWrite

Source§

fn write_str(&mut self, s: &str) -> Result<(), Error>

Writes a string slice into this writer, returning whether the write succeeded. Read more
1.1.0 · Source§

fn write_char(&mut self, c: char) -> Result<(), Error>

Writes a char into this writer, returning whether the write succeeded. Read more
1.0.0 · Source§

fn write_fmt(&mut self, args: Arguments<'_>) -> Result<(), Error>

Glue for usage of the write! macro with implementors of this trait. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.