type_reflect 0.6.2

Extensible runtime reflection through a Derive macro
Documentation
#![allow(incomplete_features)]
#![feature(specialization)]
#![feature(let_chains)]
pub use core::convert::AsRef;
use std::ffi::OsStr;
use type_reflect_macros;

use std::fs::File;
pub use std::io::Write;
pub use std::path::Path;

pub use ts_quote::ts_string;
pub use type_reflect_macros::export_types;
pub use type_reflect_macros::Reflect;
pub mod struct_type;
pub use struct_type::*;
pub use type_reflect_core::*;
pub mod zod;
pub use zod::Zod;
pub mod rust;
pub use rust::Rust;
pub mod enum_type;
pub use enum_type::*;
pub mod alias_type;
pub use alias_type::*;

pub mod type_script;
pub use type_script::TypeScript;

pub mod ts_validation;
pub use ts_validation::TSValidation;

pub mod ts_format;
pub use ts_format::TSFormat;

pub use serde::{Deserialize, Serialize};
pub use serde_json;

/// Any type implementing the `Emittable` trait
/// can be used with a `TypeEmitter` to generate
/// the target representation.
///
/// Generally the `Emittable` trait implementation
/// will be generated by the `Reflect` derive macro.
pub trait Emittable {
    fn emit_with<E: TypeEmitter>(emitter: &mut E) -> String;
}

/// init_destination_file is called to generate the target file
///
/// Args:
///     - path: the path at which the file should be created,
///         relative to the current working directory at runtime
///     - prefix: a prefix which will be added to the output file,
///         for instance if it's needed to inject additional imports
///         to make the target work
pub fn init_destination_file<P: std::fmt::Debug + Clone, Pref>(
    path: P,
    prefix: Pref,
) -> Result<File, std::io::Error>
where
    P: AsRef<Path>,
    Pref: AsRef<[u8]>,
{
    let mut file = match File::create(path.clone()) {
        Ok(file) => file,
        Err(err) => {
            eprintln!("Error creating file: {:?}", path);
            return Err(err);
        }
    };
    file.write_all(prefix.as_ref())?;
    Ok(file)
}

pub fn write_postfix<P: std::fmt::Debug + Clone, Post>(
    path: P,
    postfix: Post,
) -> Result<(), std::io::Error>
where
    P: AsRef<Path>,
    Post: AsRef<[u8]>,
{
    let mut file = std::fs::OpenOptions::new()
        .write(true)
        .append(true)
        .open(path)?;
    file.write_all(postfix.as_ref())?;
    Ok(())
}

/// The `TypeEmitter` trait defines how an `Emittable` can be used
/// to generate the desired target representation.
///
/// So for example, the Zod component defines how a type representation,
/// as generated by the `Reflect` derive macro, will be translated into
/// the Zed representation
pub trait TypeEmitter {
    // /// init_destination_file is called to generate the target file
    // ///
    // /// Args:
    // ///     - path: the path at which the file should be created,
    // ///         relative to the current working directory at runtime
    // ///     - prefix: a prefix which will be added to the output file,
    // ///         for instance if it's needed to inject additional imports
    // ///         to make the target work
    // fn init_destination_file<P: std::fmt::Debug + Clone, Pref>(
    //     &mut self,
    //     path: P,
    //     prefix: Pref,
    // ) -> Result<File, std::io::Error>
    // where
    //     P: AsRef<Path>,
    //     Pref: AsRef<[u8]>,
    // {
    //     let mut file = match File::create(path.clone()) {
    //         Ok(file) => file,
    //         Err(err) => {
    //             eprintln!("Error creating file: {:?}", path);
    //             return Err(err);
    //         }
    //     };
    //     file.write_all(prefix.as_ref())?;
    //     file.write_all(self.prefix().as_bytes())?;
    //     file.write_all("\n".as_ref())?;
    //     Ok(file)
    // }

    /// finalize is called after all the types have been
    /// emitted into the destination file
    ///
    /// Here additional cleanup or post-procesing can be done,
    /// for example linting or code-formatting
    fn finalize<P>(&mut self, path: P) -> Result<(), std::io::Error>
    where
        P: AsRef<OsStr>;

    /// The prefix method generates text for a prefix
    /// which will be prefixed to the target file.
    ///
    /// This would, for example, be the place to provide imports
    /// required for the target language or framework.
    fn prefix(&mut self) -> String;
    fn emit<T: Emittable>(&mut self) -> String
    where
        Self: Sized,
    {
        T::emit_with::<Self>(self)
    }

    /// Emit a struct representation from a struct type
    fn emit_struct<T>(&mut self) -> String
    where
        T: StructType;

    /// Emit an enum representation from an enum type
    fn emit_enum<T>(&mut self) -> String
    where
        T: EnumReflectionType;

    /// Emit a type-alias representation from an alias type
    fn emit_alias<T>(&mut self) -> String
    where
        T: AliasType;
}

pub trait RustType {
    fn emit_rust(&self) -> String;
}