1use crate::*;
2use proto_types::field_descriptor_proto::Type as DescriptorType;
3
4pub trait AsProtoType {
8 fn proto_type() -> ProtoType;
10}
11
12pub trait AsProtoField {
16 fn as_proto_field() -> FieldType;
17}
18
19impl<T> AsProtoField for Option<T>
20where
21 T: AsProtoType,
22{
23 #[inline]
24 fn as_proto_field() -> FieldType {
25 let type_ = T::proto_type();
26
27 if type_.is_message() {
28 FieldType::Normal(type_)
29 } else {
30 FieldType::Optional(type_)
31 }
32 }
33}
34
35impl<T: AsProtoType> AsProtoField for T {
36 #[inline]
37 fn as_proto_field() -> FieldType {
38 FieldType::Normal(T::proto_type())
39 }
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
44#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
45pub enum FieldType {
46 Normal(ProtoType),
47 Map {
48 keys: ProtoMapKey,
49 values: ProtoType,
50 },
51 Repeated(ProtoType),
52 Optional(ProtoType),
53}
54
55pub(crate) struct Sealed;
56
57pub trait AsProtoMapKey {
59 fn as_proto_map_key() -> ProtoMapKey;
60
61 #[doc(hidden)]
62 #[allow(private_interfaces)]
63 const SEALED: Sealed;
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
69pub enum ProtoMapKey {
70 String,
71 Bool,
72 Int32,
73 Int64,
74 Sint32,
75 Sint64,
76 Sfixed32,
77 Sfixed64,
78 Fixed32,
79 Fixed64,
80 Uint32,
81 Uint64,
82}
83
84impl ProtoMapKey {
85 #[must_use]
87 pub fn into_type(self) -> ProtoType {
88 self.into()
89 }
90}
91
92impl From<ProtoMapKey> for ProtoType {
93 fn from(value: ProtoMapKey) -> Self {
94 Self::Scalar(value.into())
95 }
96}
97
98impl From<ProtoMapKey> for ProtoScalar {
99 fn from(value: ProtoMapKey) -> Self {
100 match value {
101 ProtoMapKey::String => Self::String,
102 ProtoMapKey::Bool => Self::Bool,
103 ProtoMapKey::Int32 => Self::Int32,
104 ProtoMapKey::Int64 => Self::Int64,
105 ProtoMapKey::Sint32 => Self::Sint32,
106 ProtoMapKey::Sint64 => Self::Sint64,
107 ProtoMapKey::Sfixed32 => Self::Sfixed32,
108 ProtoMapKey::Sfixed64 => Self::Sfixed64,
109 ProtoMapKey::Fixed32 => Self::Fixed32,
110 ProtoMapKey::Fixed64 => Self::Fixed64,
111 ProtoMapKey::Uint32 => Self::Uint32,
112 ProtoMapKey::Uint64 => Self::Uint64,
113 }
114 }
115}
116
117impl Display for ProtoMapKey {
118 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
119 match self {
120 Self::Int32 => write!(f, "int32"),
121 Self::Int64 => write!(f, "int64"),
122 Self::Uint32 => write!(f, "uint32"),
123 Self::Uint64 => write!(f, "uint64"),
124 Self::Sint32 => write!(f, "sint32"),
125 Self::Sint64 => write!(f, "sint64"),
126 Self::Fixed32 => write!(f, "fixed32"),
127 Self::Fixed64 => write!(f, "fixed64"),
128 Self::Sfixed32 => write!(f, "sfixed32"),
129 Self::Sfixed64 => write!(f, "sfixed64"),
130 Self::Bool => write!(f, "bool"),
131 Self::String => write!(f, "string"),
132 }
133 }
134}
135
136#[derive(Debug, Clone, PartialEq, Eq, Copy)]
138#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
139pub enum ProtoScalar {
140 Double,
141 Float,
142 Int32,
143 Int64,
144 Uint32,
145 Uint64,
146 Sint32,
147 Sint64,
148 Fixed32,
149 Fixed64,
150 Sfixed32,
151 Sfixed64,
152 Bool,
153 String,
154 Bytes,
155}
156
157impl From<ProtoScalar> for DescriptorType {
158 #[inline]
159 fn from(value: ProtoScalar) -> Self {
160 match value {
161 ProtoScalar::Double => Self::Double,
162 ProtoScalar::Float => Self::Float,
163 ProtoScalar::Int32 => Self::Int32,
164 ProtoScalar::Int64 => Self::Int64,
165 ProtoScalar::Uint32 => Self::Uint32,
166 ProtoScalar::Uint64 => Self::Uint64,
167 ProtoScalar::Sint32 => Self::Sint32,
168 ProtoScalar::Sint64 => Self::Sint64,
169 ProtoScalar::Fixed32 => Self::Fixed32,
170 ProtoScalar::Fixed64 => Self::Fixed64,
171 ProtoScalar::Sfixed32 => Self::Sfixed32,
172 ProtoScalar::Sfixed64 => Self::Sfixed64,
173 ProtoScalar::Bool => Self::Bool,
174 ProtoScalar::String => Self::String,
175 ProtoScalar::Bytes => Self::Bytes,
176 }
177 }
178}
179
180impl Display for ProtoScalar {
181 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
182 match self {
183 Self::Double => write!(f, "double"),
184 Self::Float => write!(f, "float"),
185 Self::Int32 => write!(f, "int32"),
186 Self::Int64 => write!(f, "int64"),
187 Self::Uint32 => write!(f, "uint32"),
188 Self::Uint64 => write!(f, "uint64"),
189 Self::Sint32 => write!(f, "sint32"),
190 Self::Sint64 => write!(f, "sint64"),
191 Self::Fixed32 => write!(f, "fixed32"),
192 Self::Fixed64 => write!(f, "fixed64"),
193 Self::Sfixed32 => write!(f, "sfixed32"),
194 Self::Sfixed64 => write!(f, "sfixed64"),
195 Self::Bool => write!(f, "bool"),
196 Self::String => write!(f, "string"),
197 Self::Bytes => write!(f, "bytes"),
198 }
199 }
200}
201
202#[derive(Debug, Clone, PartialEq, Eq)]
204#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
205pub enum ProtoType {
206 Scalar(ProtoScalar),
207 Message(ProtoPath),
208 Enum(ProtoPath),
209}
210
211impl From<ProtoType> for DescriptorType {
212 #[inline]
213 fn from(value: ProtoType) -> Self {
214 match value {
215 ProtoType::Scalar(scalar) => scalar.into(),
216 ProtoType::Message(_) => Self::Message,
217 ProtoType::Enum(_) => Self::Enum,
218 }
219 }
220}
221
222impl Display for ProtoType {
223 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
224 match self {
225 Self::Scalar(proto_scalar) => write!(f, "{proto_scalar}"),
226 Self::Message(proto_path) | Self::Enum(proto_path) => write!(f, "{proto_path}"),
227 }
228 }
229}
230
231impl ProtoType {
232 #[must_use]
236 pub const fn is_message(&self) -> bool {
237 matches!(self, Self::Message { .. })
238 }
239
240 #[must_use]
244 pub const fn is_enum(&self) -> bool {
245 matches!(self, Self::Enum(..))
246 }
247}
248
249impl FieldType {
250 pub(crate) fn render(&self, current_package: &FixedStr) -> Cow<'_, str> {
251 let name = self.render_name(current_package);
252
253 match self {
254 Self::Normal(_) | Self::Map { .. } => name,
255 Self::Repeated(_) => format!("repeated {name}").into(),
256 Self::Optional(inner) => {
257 if inner.is_message() {
258 name
259 } else {
260 format!("optional {name}").into()
261 }
262 }
263 }
264 }
265
266 pub(crate) fn render_name(&self, current_package: &FixedStr) -> Cow<'_, str> {
267 match self {
268 Self::Normal(type_info) | Self::Repeated(type_info) | Self::Optional(type_info) => {
269 type_info.render_name(current_package)
270 }
271 Self::Map { keys, values } => format!(
272 "map<{}, {}>",
273 keys.into_type().render_name(current_package),
274 values.render_name(current_package)
275 )
276 .into(),
277 }
278 }
279}
280
281impl ProtoType {
282 pub(crate) fn render_name(&self, current_package: &FixedStr) -> Cow<'_, str> {
283 match self {
284 Self::Scalar(scalar) => scalar.to_string().into(),
285 Self::Message(path) | Self::Enum(path) => {
286 if *path.package == **current_package {
287 path.name.as_ref().into()
288 } else {
289 format!("{}.{}", path.package, path.name).into()
290 }
291 }
292 }
293 }
294
295 pub(crate) fn register_import(&self, imports: &mut FileImports) {
296 match self {
297 Self::Scalar { .. } => {}
298 Self::Message(path) | Self::Enum(path) => imports.insert_from_path(path),
299 }
300 }
301}
302
303impl ProtoPath {
304 pub(crate) fn render_name(&self, current_package: &FixedStr) -> Cow<'_, str> {
305 if self.package == *current_package {
306 self.name.as_ref().into()
307 } else {
308 format!("{}.{}", self.package, self.name).into()
309 }
310 }
311}
312
313#[derive(Debug, Clone, PartialEq, Eq)]
315#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
316pub struct ProtoPath {
317 pub name: FixedStr,
318 pub package: FixedStr,
319 pub file: FixedStr,
320}
321
322impl Display for ProtoPath {
323 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
324 let Self { name, package, .. } = self;
325
326 write!(f, "{package}.{name}")
327 }
328}