es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Exponiendo solamente una variante concreta de un tipo privado genérico en una biblioteca de Rust.

Tengo una crate de biblioteca Rust con código estructurado de la siguiente manera:

pub struct Foo<X> {
    x: X,
}

pub fn foo() -> Foo<u32> {
    // ...
}

// + funciones privadas

En particular, aunque la biblioteca utiliza diferentes variantes de Foo internamente (por ejemplo, Foo <u8>, Foo <u32>), Foo solo aparece en la API pública de la biblioteca como Foo <u32>.

Exponer el genérico Foo como lo hago actualmente hace que la API pública de la biblioteca y su documentación sean innecesariamente complejas: el usuario nunca obtendrá un Foo de la biblioteca que no sea un Foo <u32>. Por lo tanto, me gustaría de alguna manera solo exponer y documentar públicamente Foo <u32> (idealmente con un nombre diferente y no genérico, por ejemplo, Bar) y hacer que Foo sea privado.

He intentado usar un alias de tipo (type Bar = Foo <u32>), pero parece que estos se expanden automáticamente por cargo doc (y tampoco parecen tener una visibilidad separada).

Probablemente podría copiar la definición de Foo <X> y llamarla en su lugar Bar, y luego implementar algo como From <Foo <u32>> para Bar. Sin embargo, mi definición real de Foo <X> es bastante compleja, por lo que me gustaría evitar eso.

¿Hay otra forma de lograr mi objetivo?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Sí, se podría usar el atributo #[doc(hidden)] para ocultar la estructura Foo y sus funciones públicas en la documentación generada. Luego, se podría crear una nueva estructura pública Bar que sea en realidad un alias de Foo<u32>. Aquí hay un ejemplo:

    #[doc(hidden)]
    pub struct Foo<x> {
        x: X,
    }
    
    impl<x> Foo<x> {
        pub fn new(x: X) -> Self {
            Foo { x }
        }
    
        // + funciones privadas
    }
    
    pub struct Bar {
        inner: Foo<u32>,
    }
    
    impl Bar {
        pub fn new(x: u32) -> Self {
            let inner = Foo::new(x);
            Bar { inner }
        }
    
        // + funciones públicas que usan inner como un Foo<u32>
    }
    
    impl From<><u32>> for Bar {
        fn from(foo: Foo<u32>) -> Self {
            Bar { inner: foo }
        }
    }
    
    

    Con este enfoque, el usuario solo verá Bar y su API pública en la documentación. Sin embargo, aún se podría usar Foo<x> y sus funciones privadas internamente.

Comments are closed.