japaric / ufmt

a smaller, faster and panic-free alternative to core::fmt
Apache License 2.0
352 stars 40 forks source link

uwrite with alloc::string::String? no_std target #31

Open dragonnn opened 3 years ago

dragonnn commented 3 years ago

Hi! I am trying to craft a environment for my embedded board. Trying to use ufmt uwrite! with alloc::string::String but getting such errors:

error[E0599]: the method `do_as_formatter` exists for struct `String`, but its trait bounds were not satisfied
   --> src/main.rs:24:9
    |
24  |         ufmt::uwrite!(s, "hello from rust: {}!\n", i);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `String` due to unsatisfied trait bounds
    | 
   ::: /home/mateusz/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/string.rs:278:1
    |
278 | pub struct String {
    | -----------------
    | |
    | doesn't satisfy `String: UnstableDoAsFormatter`
    | doesn't satisfy `String: uWrite`
    |
    = note: the following trait bounds were not satisfied:
            `String: uWrite`
            which is required by `String: UnstableDoAsFormatter`
            `str: uWrite`
            which is required by `str: UnstableDoAsFormatter`
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

I already have a working allocator since the underlying system is based on nuttx and I just use libc_alloc with uses malloc and other options from directly nuttx libc. I would be really grateful for any help, I am stuck with that currently

benma commented 3 years ago

I have the exact same question / problem.

bjorn3 commented 3 years ago

https://github.com/japaric/ufmt/blob/4cbb9561b6807c214d6887e293ff00cdadd5afcc/write/src/lib.rs#L40-L48

looks like uWrite is only implemented for String when using std.

benma commented 3 years ago

It would be good to add a alloc feature and use alloc::string::String instead, making this work better in no_std environments.

benma commented 3 years ago

As a workaround one can make a newtype struct UString(String) and implement uWrite on it, something along these lines:

    pub struct UString(pub String);
    impl ufmt::uWrite for UString {
        type Error = core::convert::Infallible;

        fn write_str(&mut self, s: &str) -> Result<(), core::convert::Infallible> {
            self.0.push_str(s);
            Ok(())
        }
    }
    impl ufmt::uDisplay for UString {
        fn fmt<W>(&self, f: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
        where
            W: ufmt::uWrite + ?Sized,
        {
            <str as ufmt::uDisplay>::fmt(&self.0, f)
        }
    }
dragonnn commented 3 years ago

It would be good to add a alloc feature and use alloc::string::String instead, making this work better in no_std environments.

Yup! That would be perfect