go_away/
lib.rs

1//! # Go Away
2//!
3//! Go Away is a small library for generating go types & marshalling code from Rust type
4//! definitions.  It's intended for use when you have existing rust code that is using serde for
5//! JSON serialization and you want to allow go services or clients to interact with that code.
6//!
7//! It may be expanded to other languages at some point but it's mostly been built to service a
8//! very specific need and might never evolve past that.
9//!
10//! Use is fairly simple:
11//!
12//! ```rust
13//! use go_away::{TypeMetadata, TypeRegistry};
14//!
15//! // First, derive TypeMetadata on some types:
16//!
17//! #[derive(TypeMetadata)]
18//! struct MyType {
19//!     my_field: String
20//! }
21//!
22//! // Then you can register this type inside a `TypeRegistry`
23//!
24//! let mut registry = TypeRegistry::new();
25//! MyType::metadata(&mut registry);
26//!
27//! // And get some go code to write out to a file:
28//! let go_code = go_away::registry_to_output::<go_away::GoType>(&registry);
29//! ```
30//!
31//! Note that the output go code does not contain any package definitions or required imports.
32//! It's expected that any code that calls `go-away` will add this for itself.
33//!
34
35#![warn(missing_docs)]
36
37mod alias;
38mod metadata;
39mod output;
40mod registry;
41mod type_id;
42
43pub mod types;
44
45pub use alias::TypeAlias;
46pub use metadata::TypeMetadata;
47pub use output::{GoType, KotlinType, SwiftType, TypeScriptType};
48pub use registry::TypeRegistry;
49pub use type_id::TypeId;
50
51pub use go_away_derive::TypeMetadata;
52
53use registry::Type;
54use std::fmt::Display;
55
56/// Generates code for all the types in the TypeRegistry
57///
58/// You should provide `go_away::GoType` or `go_away::TypeScriptType` as a generic
59/// parameter with turbofish syntax to decide which format to output.
60///
61/// Note that this is a WIP API and is likely to be ditched/changed in future releases.
62pub fn registry_to_output<'a, Format>(registry: &'a TypeRegistry) -> String
63where
64    Format: From<&'a Type> + Display,
65{
66    use std::fmt::Write;
67
68    let mut output = String::new();
69    for id in registry.structs.iter().rev() {
70        let ty = registry.types.get(id).unwrap();
71        write!(&mut output, "{}", Format::from(ty)).unwrap();
72    }
73    for id in registry.unions.iter().rev() {
74        let ty = registry.types.get(id).unwrap();
75        write!(&mut output, "{}", Format::from(ty)).unwrap();
76    }
77    for id in registry.newtypes.iter().rev() {
78        let ty = registry.types.get(id).unwrap();
79        write!(&mut output, "{}", Format::from(ty)).unwrap();
80    }
81    for id in registry.enums.iter().rev() {
82        let ty = registry.types.get(id).unwrap();
83        write!(&mut output, "{}", Format::from(ty)).unwrap();
84    }
85    for id in registry.aliases.iter().rev() {
86        let ty = registry.types.get(id).unwrap();
87        write!(&mut output, "{}", Format::from(ty)).unwrap();
88    }
89
90    output
91}
92
93impl<'a> From<&'a registry::Type> for output::go::GoType<'a> {
94    fn from(ty: &'a registry::Type) -> Self {
95        match ty {
96            registry::Type::Struct(inner) => output::go::GoType::Struct(inner),
97            registry::Type::Enum(inner) => output::go::GoType::Enum(inner),
98            registry::Type::Union(inner) => output::go::GoType::Union(inner),
99            registry::Type::NewType(inner) => output::go::GoType::NewType(inner),
100            registry::Type::Alias(inner) => output::go::GoType::Alias(inner),
101        }
102    }
103}
104
105impl<'a> From<&'a registry::Type> for output::typescript::TypeScriptType<'a> {
106    fn from(ty: &'a registry::Type) -> Self {
107        match ty {
108            registry::Type::Struct(inner) => output::typescript::TypeScriptType::Struct(inner),
109            registry::Type::Enum(inner) => output::typescript::TypeScriptType::Enum(inner),
110            registry::Type::Union(inner) => output::typescript::TypeScriptType::Union(inner),
111            registry::Type::NewType(inner) => output::typescript::TypeScriptType::NewType(inner),
112            registry::Type::Alias(inner) => output::typescript::TypeScriptType::Alias(inner),
113        }
114    }
115}
116
117impl<'a> From<&'a registry::Type> for output::swift::SwiftType<'a> {
118    fn from(ty: &'a registry::Type) -> Self {
119        match ty {
120            registry::Type::Struct(inner) => SwiftType::Struct(inner),
121            registry::Type::Enum(inner) => SwiftType::Enum(inner),
122            registry::Type::Union(inner) => SwiftType::Union(inner),
123            registry::Type::NewType(inner) => SwiftType::NewType(inner),
124            registry::Type::Alias(inner) => SwiftType::Alias(inner),
125        }
126    }
127}
128
129impl<'a> From<&'a registry::Type> for KotlinType<'a> {
130    fn from(ty: &'a registry::Type) -> Self {
131        match ty {
132            registry::Type::Struct(inner) => KotlinType::Struct(inner),
133            registry::Type::Enum(inner) => KotlinType::Enum(inner),
134            registry::Type::Union(inner) => KotlinType::Union(inner),
135            registry::Type::NewType(inner) => KotlinType::NewType(inner),
136            registry::Type::Alias(inner) => KotlinType::Alias(inner),
137        }
138    }
139}