1use serde::{Deserialize, Serialize};
4
5use crate::identifier::QualifiedName;
6use crate::ir::column_type::ColumnType;
7
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10pub struct Cast {
11 pub source: QualifiedName,
13 pub target: QualifiedName,
15 pub method: CastMethod,
17 pub context: CastContext,
19 pub comment: Option<String>,
21}
22
23#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
25pub enum CastMethod {
26 Function {
31 name: QualifiedName,
33 arg_types: Vec<ColumnType>,
35 },
36 Inout,
38 Binary,
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
44#[serde(rename_all = "snake_case")]
45pub enum CastContext {
46 Explicit,
48 Assignment,
50 Implicit,
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use crate::identifier::{Identifier, QualifiedName};
58
59 fn id(s: &str) -> Identifier {
60 Identifier::from_unquoted(s).unwrap()
61 }
62
63 fn qname(schema: &str, name: &str) -> QualifiedName {
64 QualifiedName::new(id(schema), id(name))
65 }
66
67 fn cast_function() -> Cast {
68 Cast {
69 source: qname("app", "my_type"),
70 target: qname("pg_catalog", "text"),
71 method: CastMethod::Function {
72 name: qname("app", "my_type_to_text"),
73 arg_types: vec![ColumnType::Integer],
74 },
75 context: CastContext::Explicit,
76 comment: Some("Converts my_type to text.".to_string()),
77 }
78 }
79
80 fn cast_inout() -> Cast {
81 Cast {
82 source: qname("app", "domain_a"),
83 target: qname("app", "domain_b"),
84 method: CastMethod::Inout,
85 context: CastContext::Assignment,
86 comment: None,
87 }
88 }
89
90 fn cast_binary() -> Cast {
91 Cast {
92 source: qname("app", "type_x"),
93 target: qname("app", "type_y"),
94 method: CastMethod::Binary,
95 context: CastContext::Implicit,
96 comment: None,
97 }
98 }
99
100 #[test]
101 fn cast_function_serde_round_trip() {
102 let c = cast_function();
103 let json = serde_json::to_string(&c).unwrap();
104 let back: Cast = serde_json::from_str(&json).unwrap();
105 assert_eq!(c, back);
106 }
107
108 #[test]
109 fn cast_inout_serde_round_trip() {
110 let c = cast_inout();
111 let json = serde_json::to_string(&c).unwrap();
112 let back: Cast = serde_json::from_str(&json).unwrap();
113 assert_eq!(c, back);
114 }
115
116 #[test]
117 fn cast_binary_serde_round_trip() {
118 let c = cast_binary();
119 let json = serde_json::to_string(&c).unwrap();
120 let back: Cast = serde_json::from_str(&json).unwrap();
121 assert_eq!(c, back);
122 }
123
124 #[test]
125 fn cast_context_serde_variants() {
126 let explicit = serde_json::to_string(&CastContext::Explicit).unwrap();
127 let assignment = serde_json::to_string(&CastContext::Assignment).unwrap();
128 let implicit = serde_json::to_string(&CastContext::Implicit).unwrap();
129 assert_eq!(explicit, "\"explicit\"");
130 assert_eq!(assignment, "\"assignment\"");
131 assert_eq!(implicit, "\"implicit\"");
132
133 let back_e: CastContext = serde_json::from_str(&explicit).unwrap();
134 let back_a: CastContext = serde_json::from_str(&assignment).unwrap();
135 let back_i: CastContext = serde_json::from_str(&implicit).unwrap();
136 assert_eq!(back_e, CastContext::Explicit);
137 assert_eq!(back_a, CastContext::Assignment);
138 assert_eq!(back_i, CastContext::Implicit);
139 }
140}