You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: shareable.rs
    path of file: ./repos/grafbase/engine/crates/parser-sdl/src/rules/federation
    
    the code of the file until where you have to start completion: use engine_parser::{types::ConstDirective, Positioned};

use crate::rules::{directive::Directive, visitor::VisitorContext};

#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct ShareableDirective;

impl ShareableDirective {
    pub fn from_directives(
        directives: &[Positioned<ConstDirective>],
        _ctx: &mut VisitorContext<'_>,
    ) -> Option<ShareableDirective> {
        directives.iter().find(|directive| directive.name.node == "shareable")?;

        Some(ShareableDirective)
    }
}

impl Directive for ShareableDirective {
    fn definition() -> String {
        r"
        directive @shareable on OBJECT | FIELD_DEFINITION
        "
        .to_string()
    }
}

#[cfg(test)]
mod tests 
    
    fn shareable_on_basic_type() {
        let schema = r#"
            extend schema @federation(version: "2.3")

            type User @key(fields: "id", resolvable: false) @shareable {
                id: ID!
            }
        "#;

        let registry = crate::to_parse_result_with_variables(schema, &HashMap::new())
            .unwrap()
            .registry;

        insta::assert_snapshot!(registry.export_sdl(true), @r###"
        extend schema @link(
        	url: "https://specs.apollo.dev/federation/v2.3",
        	import: ["@key", "@tag", "@shareable", "@inaccessible", "@override", "@external", "@provides", "@requires", "@composeDirective", "@interfaceObject"]
        )
        type User @key(fields: "id" resolvable: false) @shareable {
        	id: ID!
        }
        "###);
    }