Internal visibility for trait methods

I currently trying to implement some wrapper over C++ library. I want to create a trait, that works with any type that provides specific field while I don't want to show this field to end users.

Here is my sample code:

enum COCR {}

#[derive(Debug)]
pub struct OcrTesseract {
    value: *mut COCR
}

trait OcrImpl {
    fn get_value(&self) -> *mut COCR;
}

impl OcrImpl for OcrTesseract {
    fn get_value(&self) -> *mut COCR {
        self.value
    }
}

pub trait Ocr {
     ... some methods here
}

impl<T: OcrImpl> Ocr for T {
   ... some methods here
}

It could work fine, but it doesn't, because OcrImpl is private.

error[E0445]: private trait 'text::ocr::OcrImpl' in public interface

That's understandable, but I don't see how I can limit function within this trait itself.

In terms of C# code I'd like to use following:

public interface IOcrImpl 
{
   internal COCR GetValue();
}

public static class Ocr
{
   public static void SomeMethod<T>(this T self) where T : IOcrImpl
   {
       var value = self.GetValue();
       // do stuff
   }
}

so IOcrImpl is visible to users, but is practically useless because they have no access to internal method while I can work with it.

Is it possible to do in Rust, or probably there is some RFC for it, or probably I'm just doing the wrong thing... Please, give me some advice. I actually need something like:

pub trait OcrImpl {
    pub(crate) fn get_value(&self) -> *mut COCR;
}

I currently use following workaround:

mod private {
    pub enum COCR {}

    pub trait OcrImpl {
        fn get_value(&self) -> *mut COCR;
    }
}

pub trait OcrImplInterface : private::OcrImpl {}

And it really does its job. However, it there any cleaner way to do it?

2 Likes

This can be handled by re-structuring your modules and re-exporting only the staff that should be public to the user.

This could look something like:

mod api {
    pub use self::inner::Ocr;
    
    mod inner {
        pub enum COCR {}

        #[derive(Debug)]
        pub struct OcrTesseract {
            value: *mut COCR,
        }

        pub trait OcrImpl {
            fn get_value(&self) -> *mut COCR;
        }

        impl OcrImpl for OcrTesseract {
            fn get_value(&self) -> *mut COCR {
                self.value
            }
        }

        pub trait Ocr {
            fn some() {}
        }

        impl<T: OcrImpl> Ocr for T {
            fn some() {}
        }
    }
}

Playground example

2 Likes