go_away/output/kotlin/
mod.rs1use crate::{
2 output::prelude::*,
3 types::{self, Alias, NewType, Struct},
4};
5
6use self::{enums::Enum, structs::KotlinStruct, unions::Union};
7
8use super::go::FieldType;
9
10mod data_classes;
11mod enums;
12mod kserializer;
13mod structs;
14mod unions;
15
16#[cfg(test)]
17mod tests;
18
19pub enum KotlinType<'a> {
24 Struct(&'a Struct),
26 NewType(&'a NewType),
28 Alias(&'a Alias),
30 Enum(&'a types::Enum),
32 Union(&'a types::Union),
34}
35
36impl fmt::Display for KotlinType<'_> {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 match self {
39 KotlinType::Struct(details) => {
40 let struct_ = KotlinStruct::new(&details.name).with_fields(&details.fields);
41 writeln!(f, "{struct_}")?;
42 }
43 KotlinType::NewType(details) => {
44 let struct_ = KotlinStruct::newtype(&details.name, &details.inner);
45 writeln!(f, "{struct_}")?;
46 }
47 KotlinType::Alias(details) => {
48 writeln!(
49 f,
50 "typealias {} = {}",
51 details.name,
52 details.inner.kotlin_type()
53 )?;
54 }
55 KotlinType::Enum(details) => {
56 let enum_ = Enum::new(&details.name).with_variants(&details.variants);
57 writeln!(f, "{enum_}")?;
58 }
59 KotlinType::Union(details) => {
60 let union_ = Union::new(&details.name, details.representation.clone())
61 .with_variants(&details.variants);
62 writeln!(f, "{union_}")?;
63 }
64 }
65 Ok(())
66 }
67}
68
69impl FieldType {
70 fn kotlin_type(&self) -> String {
71 use crate::types::Primitive;
72
73 match self {
74 FieldType::Named(type_ref) => type_ref.name().to_string(),
75 FieldType::Optional(inner) => format!("{}?", inner.kotlin_type()),
76 FieldType::List(inner) => format!("List<{}>", inner.kotlin_type()),
77 FieldType::Map { key, value } => {
78 format!("Map<{}, {}>", key.kotlin_type(), value.kotlin_type())
79 }
80 FieldType::Primitive(Primitive::String) => "String".to_string(),
81 FieldType::Primitive(Primitive::Float) => "Double".to_string(),
82 FieldType::Primitive(Primitive::Int) => "Long".to_string(),
83 FieldType::Primitive(Primitive::Bool) => "Boolean".to_string(),
84 FieldType::Primitive(Primitive::Time) => {
85 todo!("Need to implement time support for kotlin")
87 }
88 }
89 }
90
91 fn default_str(&self) -> &'static str {
92 match self {
93 FieldType::Optional(_) => " = null",
94 _ => "",
95 }
96 }
97
98 fn serializer(&self) -> String {
99 match self {
100 FieldType::Optional(inner) => {
101 format!("{}.nullable", inner.serializer())
102 }
103 FieldType::List(inner) => {
104 format!("ListSerializer({})", inner.serializer())
105 }
106 FieldType::Map { key, value } => {
107 format!(
108 "MapSerializer({}, {})",
109 key.serializer(),
110 value.serializer()
111 )
112 }
113 FieldType::Named(_) | FieldType::Primitive(_) => {
114 format!("{}.serializer()", self.kotlin_type())
115 }
116 }
117 }
118}
119
120fn to_camel_case(s: &str) -> String {
121 let mut buf = String::with_capacity(s.len());
122 let mut prev_is_underscore = false;
123 let mut first = true;
124 for c in s.chars() {
125 if c == '_' {
126 prev_is_underscore = true;
127 } else if prev_is_underscore {
128 buf.push(c.to_ascii_uppercase());
129 prev_is_underscore = false;
130 } else if c.is_uppercase() && !first {
131 buf.push(c);
132 } else {
133 buf.push(c.to_ascii_lowercase());
134 }
135 first = false;
136 }
137 buf
138}
139
140fn to_screaming_snake_case(s: &str) -> String {
141 let mut buf = String::with_capacity(s.len());
142 let mut first = true;
143 for c in s.chars() {
144 if c.is_uppercase() {
145 if !first {
146 buf.push('_');
147 }
148 buf.push(c);
149 } else {
150 buf.push(c.to_ascii_uppercase());
151 }
152 first = false;
153 }
154 buf
155}