go_away/output/swift/
mod.rs1use crate::{
2 output::{prelude::*, swift::enums::Enum},
3 types::{self, Alias, Field, NewType, Struct},
4};
5
6use self::{
7 coding_keys::{CodingKey, CodingKeys},
8 structs::SwiftStruct,
9 unions::Union,
10};
11
12use super::go::FieldType;
13
14mod coding_keys;
15mod enums;
16mod structs;
17mod unions;
18
19mod codable;
20#[cfg(test)]
21mod tests;
22
23pub enum SwiftType<'a> {
28 Struct(&'a Struct),
30 NewType(&'a NewType),
32 Alias(&'a Alias),
34 Enum(&'a types::Enum),
36 Union(&'a types::Union),
38}
39
40impl fmt::Display for SwiftType<'_> {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 match self {
43 SwiftType::Struct(details) => {
44 let struct_ = SwiftStruct::new(&details.name).with_fields(&details.fields);
45 writeln!(f, "{struct_}")?;
46 }
47 SwiftType::NewType(details) => {
48 let struct_ = SwiftStruct::newtype(&details.name, &details.inner);
49 writeln!(f, "{struct_}")?;
50 }
51 SwiftType::Alias(details) => {
52 writeln!(
53 f,
54 "typealias {} = {}",
55 details.name,
56 details.inner.swift_type()
57 )?;
58 }
59 SwiftType::Enum(details) => {
60 let enum_ = Enum::new(&details.name).with_variants(&details.variants);
61 writeln!(f, "{enum_}")?;
62 }
63 SwiftType::Union(details) => {
64 let union_ = Union::new(&details.name, details.representation.clone())
65 .with_variants(&details.variants);
66 writeln!(f, "{union_}")?;
67 }
68 }
69 Ok(())
70 }
71}
72
73pub struct SwiftField<'a>(&'a Field);
74
75impl fmt::Display for SwiftField<'_> {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
77 let details = self.0;
78 write!(
79 f,
80 r#"public var {}: {}"#,
81 to_camel_case(&details.name),
82 details.ty.swift_type(),
83 )
84 }
85}
86
87impl FieldType {
88 fn swift_type(&self) -> String {
89 use crate::types::Primitive;
90
91 match self {
92 FieldType::Named(type_ref) => type_ref.name().to_string(),
93 FieldType::Optional(inner) => format!("{}?", inner.swift_type()),
94 FieldType::List(inner) => format!("[{}]", inner.swift_type()),
95 FieldType::Map { key, value } => {
96 format!("[{}: {}]", key.swift_type(), value.swift_type())
97 }
98 FieldType::Primitive(Primitive::String) => "String".to_string(),
99 FieldType::Primitive(Primitive::Float) => "Double".to_string(),
100 FieldType::Primitive(Primitive::Int) => "Int64".to_string(),
101 FieldType::Primitive(Primitive::Bool) => "Bool".to_string(),
102 FieldType::Primitive(Primitive::Time) => {
103 todo!("Need to implement time support for swift")
105 }
106 }
107 }
108}
109
110fn to_camel_case(s: &str) -> String {
111 let mut buf = String::with_capacity(s.len());
112 let mut prev_is_underscore = false;
113 let mut first = true;
114 for c in s.chars() {
115 if c == '_' {
116 prev_is_underscore = true;
117 } else if prev_is_underscore {
118 buf.push(c.to_ascii_uppercase());
119 prev_is_underscore = false;
120 } else if c.is_uppercase() && !first {
121 buf.push(c);
122 } else {
123 buf.push(c.to_ascii_lowercase());
124 }
125 first = false;
126 }
127 buf
128}