Smart pointer which owns its target

I created a smaller example here:

#![feature(generic_associated_types)]

mod deref_owned {
    use std::borrow::Cow;
    use std::ops::{Deref, DerefMut};

    /// Smart pointer to owned inner value
    #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
    pub struct Owned<T>(pub T);

    impl<T> Deref for Owned<T> {
        type Target = T;
        /// Returns a reference to the contained value
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }

    impl<T> DerefMut for Owned<T> {
        /// Returns a mutable reference to the contained value
        fn deref_mut(&mut self) -> &mut Self::Target {
            &mut self.0
        }
    }

    /// Pointer types that can be converted into an owned type
    pub trait IntoOwned: Sized {
        /// The type the pointer can be converted into
        type Owned;
        /// Convert into owned type
        fn into_owned(self) -> Self::Owned;
    }

    impl<'a, T> IntoOwned for &'a T
    where
        T: ?Sized + ToOwned,
    {
        type Owned = <T as ToOwned>::Owned;
        fn into_owned(self) -> Self::Owned {
            self.to_owned()
        }
    }

    impl<'a, T> IntoOwned for Cow<'a, T>
    where
        T: ?Sized + ToOwned,
    {
        type Owned = <T as ToOwned>::Owned;
        fn into_owned(self) -> <Self as IntoOwned>::Owned {
            Cow::into_owned(self)
        }
    }

    impl<T> IntoOwned for Owned<T> {
        type Owned = T;
        fn into_owned(self) -> Self::Owned {
            self.0
        }
    }
}

use deref_owned::*;

use std::fmt::Debug;
use std::ops::Deref;

trait Parse<T: ?Sized> {
    type Pointer<'a>: Deref<Target = T> + IntoOwned + Debug
    where
        Self: 'a;
    fn parse(&self) -> Option<Self::Pointer<'_>>;
}

impl Parse<[u8]> for [u8] {
    type Pointer<'a> = &'a [u8]; // zero-cost
    fn parse(&self) -> Option<Self::Pointer<'_>> {
        Some(self)
    }
}

impl Parse<str> for [u8] {
    type Pointer<'a> = &'a str; // zero-cost
    fn parse(&self) -> Option<Self::Pointer<'_>> {
        std::str::from_utf8(self).ok()
    }
}

impl Parse<i32> for [u8] {
    type Pointer<'a> = Owned<i32>; // smart pointer that drops owned pointee
    /*
    type Pointer<'a> = i32; // won't work
    type Pointer<'a> = std::borrow::Cow<'static, i32>; // comes with runtime overhead
    type Pointer<'a> = Box<i32>; // unnecessary heap allocation
    */
    fn parse(&self) -> Option<Self::Pointer<'_>> {
        Parse::<str>::parse(self)
            .and_then(|s| s.parse::<i32>().ok())
            .map(|i| Owned(i))
            //.map(|i| std::borrow::Cow::Owned(i)) // runtime overhead
            //.map(|i| Box::new(i)) // heap allocation
    }
}

fn foo<T, U>(input: &U)
where
    T: ?Sized,
    U: ?Sized + Parse<T>,
{
    println!(
        "Parsed as {}: {:?}",
        std::any::type_name::<T>(),
        input.parse()
    );
}

fn bar(input: &(impl ?Sized + Parse<str>)) {
    match input.parse() {
        Some(parsed) => println!(
            "{} has {} bytes and {} chars",
            &*parsed,
            parsed.len(),
            parsed.chars().count()
        ),
        None => println!("could not parse"),
    }
}

fn main() {
    let s = b"12345" as &[u8];
    foo::<[u8], _>(s);
    foo::<str, _>(s);
    foo::<i32, _>(s);
    bar(b"H\xC3\xBChnerleiter" as &[u8]);
}

(Playground)

Output:

Parsed as [u8]: Some([49, 50, 51, 52, 53])
Parsed as str: Some("12345")
Parsed as i32: Some(Owned(12345))
Hühnerleiter has 13 bytes and 12 chars

Note how I could use Cow or Box (if I remove the IntoOwned bound, since it's not implemented yet for Box<T> where T: Sized), but each comes with overhead.

Now this is interesting. Look at Box::into_inner, which is unstable. See also tracking issue #80437. It might be another use case for an IntoOwned (or "consuming" ToOwned) trait.

I can't replace Owned<i32> with just i32 in the above example of impl Parse<i32> for [u8]. At least I didn't find a way how to do it.

Beside being Deref, it manages the ownership of the pointee (i.e. the pointer will drop the pointee when the pointer is dropped). That sort of management is one of the aspects a smart pointer is about, I guess.