writeable

Trait TryWriteable

Source
pub trait TryWriteable {
    type Error;

    // Required method
    fn try_write_to_parts<S: PartsWrite + ?Sized>(
        &self,
        sink: &mut S,
    ) -> Result<Result<(), Self::Error>, Error>;

    // Provided methods
    fn try_write_to<W: Write + ?Sized>(
        &self,
        sink: &mut W,
    ) -> Result<Result<(), Self::Error>, Error> { ... }
    fn writeable_length_hint(&self) -> LengthHint { ... }
    fn try_write_to_string(
        &self,
    ) -> Result<Cow<'_, str>, (Self::Error, Cow<'_, str>)> { ... }
    fn writeable_cmp_bytes(&self, other: &[u8]) -> Ordering { ... }
}
Expand description

A writeable object that can fail while writing.

The default Writeable trait returns a fmt::Error, which originates from the sink. In contrast, this trait allows the writeable itself to trigger an error as well.

Implementations are expected to always make a best attempt at writing to the sink and should write replacement values in the error state. Therefore, the returned Result can be safely ignored to emulate a “lossy” mode.

Any error substrings should be annotated with Part::ERROR.

§Implementer Notes

This trait requires that implementers make a best attempt at writing to the sink, even in the error state, such as with a placeholder or fallback string.

In TryWriteable::try_write_to_parts(), error substrings should be annotated with Part::ERROR. Because of this, writing to parts is not default-implemented like it is on Writeable.

The trait is implemented on Result<T, E> where T and E both implement Writeable; In the Ok case, T is written, and in the Err case, E is written as a fallback value. This impl, which writes Part::ERROR, can be used as a basis for more advanced impls.

§Examples

Implementing on a custom type:

use core::fmt;
use writeable::LengthHint;
use writeable::PartsWrite;
use writeable::TryWriteable;

#[derive(Debug, PartialEq, Eq)]
enum HelloWorldWriteableError {
    MissingName,
}

#[derive(Debug, PartialEq, Eq)]
struct HelloWorldWriteable {
    pub name: Option<&'static str>,
}

impl TryWriteable for HelloWorldWriteable {
    type Error = HelloWorldWriteableError;

    fn try_write_to_parts<S: PartsWrite + ?Sized>(
        &self,
        sink: &mut S,
    ) -> Result<Result<(), Self::Error>, fmt::Error> {
        sink.write_str("Hello, ")?;
        // Use `impl TryWriteable for Result` to generate the error part:
        let err = self.name.ok_or("nobody").try_write_to_parts(sink)?.err();
        sink.write_char('!')?;
        // Return a doubly-wrapped Result.
        // The outer Result is for fmt::Error, handled by the `?`s above.
        // The inner Result is for our own Self::Error.
        if err.is_none() {
            Ok(Ok(()))
        } else {
            Ok(Err(HelloWorldWriteableError::MissingName))
        }
    }

    fn writeable_length_hint(&self) -> LengthHint {
        self.name.ok_or("nobody").writeable_length_hint() + 8
    }
}

// Success case:
writeable::assert_try_writeable_eq!(
    HelloWorldWriteable {
        name: Some("Alice")
    },
    "Hello, Alice!"
);

// Failure case, including the ERROR part:
writeable::assert_try_writeable_parts_eq!(
    HelloWorldWriteable { name: None },
    "Hello, nobody!",
    Err(HelloWorldWriteableError::MissingName),
    [(7, 13, writeable::Part::ERROR)]
);

Required Associated Types§

Required Methods§

Source

fn try_write_to_parts<S: PartsWrite + ?Sized>( &self, sink: &mut S, ) -> Result<Result<(), Self::Error>, Error>

Writes the content of this writeable to a sink with parts (annotations).

For more information, see:

Provided Methods§

Source

fn try_write_to<W: Write + ?Sized>( &self, sink: &mut W, ) -> Result<Result<(), Self::Error>, Error>

Writes the content of this writeable to a sink.

If the sink hits an error, writing immediately ends, Err(fmt::Error) is returned, and the sink does not contain valid output.

If the writeable hits an error, writing is continued with a replacement value, Ok(Err(TryWriteable::Error)) is returned, and the caller may continue using the sink.

§Lossy Mode

The fmt::Error should always be handled, but the TryWriteable::Error can be ignored if a fallback string is desired instead of an error.

To handle the sink error, but not the writeable error, write:

let _ = my_writeable.try_write_to(&mut sink)?;
§Examples

The following examples use Result<&str, usize>, which implements TryWriteable because both &str and usize do.

Success case:

use writeable::TryWriteable;

let w: Result<&str, usize> = Ok("success");
let mut sink = String::new();
let result = w.try_write_to(&mut sink);

assert_eq!(result, Ok(Ok(())));
assert_eq!(sink, "success");

Failure case:

use writeable::TryWriteable;

let w: Result<&str, usize> = Err(44);
let mut sink = String::new();
let result = w.try_write_to(&mut sink);

assert_eq!(result, Ok(Err(44)));
assert_eq!(sink, "44");
Source

fn writeable_length_hint(&self) -> LengthHint

Returns a hint for the number of UTF-8 bytes that will be written to the sink.

This function returns the length of the “lossy mode” string; for more information, see TryWriteable::try_write_to().

Source

fn try_write_to_string( &self, ) -> Result<Cow<'_, str>, (Self::Error, Cow<'_, str>)>

Writes the content of this writeable to a string.

In the failure case, this function returns the error and the best-effort string (“lossy mode”).

Examples

// use the best-effort string
let r1: Cow<str> = Ok::<&str, u8>("ok")
    .try_write_to_string()
    .unwrap_or_else(|(_, s)| s);
// propagate the error
let r2: Result<Cow<str>, u8> = Ok::<&str, u8>("ok")
    .try_write_to_string()
    .map_err(|(e, _)| e);
Source

fn writeable_cmp_bytes(&self, other: &[u8]) -> Ordering

Compares the content of this writeable to a byte slice.

This function compares the “lossy mode” string; for more information, see TryWriteable::try_write_to().

For more information, see Writeable::writeable_cmp_bytes().

§Examples
use core::cmp::Ordering;
use core::fmt;
use writeable::TryWriteable;

#[derive(Debug, PartialEq, Eq)]
enum HelloWorldWriteableError {
    MissingName
}

#[derive(Debug, PartialEq, Eq)]
struct HelloWorldWriteable {
    pub name: Option<&'static str>
}

impl TryWriteable for HelloWorldWriteable {
    type Error = HelloWorldWriteableError;
    // see impl in TryWriteable docs
}

// Success case:
let writeable = HelloWorldWriteable { name: Some("Alice") };
let writeable_str = writeable.try_write_to_string().expect("name is Some");

assert_eq!(Ordering::Equal, writeable.writeable_cmp_bytes(b"Hello, Alice!"));

assert_eq!(Ordering::Greater, writeable.writeable_cmp_bytes(b"Alice!"));
assert_eq!(Ordering::Greater, (*writeable_str).cmp("Alice!"));

assert_eq!(Ordering::Less, writeable.writeable_cmp_bytes(b"Hello, Bob!"));
assert_eq!(Ordering::Less, (*writeable_str).cmp("Hello, Bob!"));

// Failure case:
let writeable = HelloWorldWriteable { name: None };
let mut writeable_str = String::new();
let _ = writeable.try_write_to(&mut writeable_str).expect("write to String is infallible");

assert_eq!(Ordering::Equal, writeable.writeable_cmp_bytes(b"Hello, nobody!"));

assert_eq!(Ordering::Greater, writeable.writeable_cmp_bytes(b"Hello, alice!"));
assert_eq!(Ordering::Greater, (*writeable_str).cmp("Hello, alice!"));

assert_eq!(Ordering::Less, writeable.writeable_cmp_bytes(b"Hello, zero!"));
assert_eq!(Ordering::Less, (*writeable_str).cmp("Hello, zero!"));

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl<T, E> TryWriteable for Result<T, E>
where T: Writeable, E: Writeable + Clone,

Source§

type Error = E

Source§

fn try_write_to<W: Write + ?Sized>( &self, sink: &mut W, ) -> Result<Result<(), Self::Error>, Error>

Source§

fn try_write_to_parts<S: PartsWrite + ?Sized>( &self, sink: &mut S, ) -> Result<Result<(), Self::Error>, Error>

Source§

fn writeable_length_hint(&self) -> LengthHint

Source§

fn try_write_to_string( &self, ) -> Result<Cow<'_, str>, (Self::Error, Cow<'_, str>)>

Source§

fn writeable_cmp_bytes(&self, other: &[u8]) -> Ordering

Implementors§