Skip to main content

mz_catalog/durable/objects/serialization/
foreign.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! This module is responsible for serializing objects from crates other than
11//! `mz_catalog` into protobuf.
12
13use std::time::Duration;
14
15use mz_compute_types::config::ComputeReplicaLogging;
16use mz_controller_types::ReplicaId;
17use mz_persist_types::ShardId;
18use mz_proto::TryFromProtoError;
19use mz_repr::adt::mz_acl_item::{AclMode, MzAclItem};
20use mz_repr::network_policy_id::NetworkPolicyId;
21use mz_repr::role_id::RoleId;
22use mz_repr::{CatalogItemId, GlobalId, RelationVersion};
23use mz_sql::catalog::{
24    AutoProvisionSource, CatalogItemType, ObjectType, RoleAttributes, RoleMembership, RoleVars,
25};
26use mz_sql::names::{
27    CommentObjectId, DatabaseId, ResolvedDatabaseSpecifier, SchemaId, SchemaSpecifier,
28};
29use mz_sql::plan::{
30    AutoScalingStrategy, ClusterSchedule, NetworkPolicyRule, NetworkPolicyRuleAction,
31    NetworkPolicyRuleDirection, OnHydration, OnTimeoutAction, PolicyAddress,
32};
33use mz_sql::session::vars::OwnedVarInput;
34use mz_storage_types::instances::StorageInstanceId;
35
36use crate::durable::objects::serialization::{ProtoMapEntry, ProtoType, RustType, proto};
37
38impl RustType<proto::Duration> for Duration {
39    fn into_proto(&self) -> proto::Duration {
40        proto::Duration {
41            secs: self.as_secs(),
42            nanos: self.subsec_nanos(),
43        }
44    }
45
46    fn from_proto(proto: proto::Duration) -> Result<Self, TryFromProtoError> {
47        Ok(Duration::new(proto.secs, proto.nanos))
48    }
49}
50
51impl RustType<proto::RoleId> for RoleId {
52    fn into_proto(&self) -> proto::RoleId {
53        match self {
54            RoleId::User(id) => proto::RoleId::User(*id),
55            RoleId::System(id) => proto::RoleId::System(*id),
56            RoleId::Predefined(id) => proto::RoleId::Predefined(*id),
57            RoleId::Public => proto::RoleId::Public,
58        }
59    }
60
61    fn from_proto(proto: proto::RoleId) -> Result<Self, TryFromProtoError> {
62        let id = match proto {
63            proto::RoleId::User(id) => RoleId::User(id),
64            proto::RoleId::System(id) => RoleId::System(id),
65            proto::RoleId::Predefined(id) => RoleId::Predefined(id),
66            proto::RoleId::Public => RoleId::Public,
67        };
68        Ok(id)
69    }
70}
71
72impl RustType<proto::AclMode> for AclMode {
73    fn into_proto(&self) -> proto::AclMode {
74        proto::AclMode {
75            bitflags: self.bits(),
76        }
77    }
78
79    fn from_proto(proto: proto::AclMode) -> Result<Self, TryFromProtoError> {
80        AclMode::from_bits(proto.bitflags).ok_or_else(|| {
81            TryFromProtoError::InvalidBitFlags(format!("Invalid AclMode from catalog {proto:?}"))
82        })
83    }
84}
85
86impl RustType<proto::MzAclItem> for MzAclItem {
87    fn into_proto(&self) -> proto::MzAclItem {
88        proto::MzAclItem {
89            grantee: self.grantee.into_proto(),
90            grantor: self.grantor.into_proto(),
91            acl_mode: self.acl_mode.into_proto(),
92        }
93    }
94
95    fn from_proto(proto: proto::MzAclItem) -> Result<Self, TryFromProtoError> {
96        Ok(MzAclItem {
97            grantee: proto.grantee.into_rust()?,
98            grantor: proto.grantor.into_rust()?,
99            acl_mode: proto.acl_mode.into_rust()?,
100        })
101    }
102}
103
104impl RustType<proto::AutoProvisionSource> for AutoProvisionSource {
105    fn into_proto(&self) -> proto::AutoProvisionSource {
106        match self {
107            AutoProvisionSource::Oidc => proto::AutoProvisionSource::Oidc,
108            AutoProvisionSource::Frontegg => proto::AutoProvisionSource::Frontegg,
109            AutoProvisionSource::None => proto::AutoProvisionSource::None,
110        }
111    }
112
113    fn from_proto(proto: proto::AutoProvisionSource) -> Result<Self, TryFromProtoError> {
114        Ok(match proto {
115            proto::AutoProvisionSource::Oidc => AutoProvisionSource::Oidc,
116            proto::AutoProvisionSource::Frontegg => AutoProvisionSource::Frontegg,
117            proto::AutoProvisionSource::None => AutoProvisionSource::None,
118        })
119    }
120}
121
122impl RustType<proto::RoleAttributes> for RoleAttributes {
123    fn into_proto(&self) -> proto::RoleAttributes {
124        proto::RoleAttributes {
125            inherit: self.inherit,
126            superuser: self.superuser,
127            login: self.login,
128            auto_provision_source: self.auto_provision_source.into_proto(),
129        }
130    }
131
132    fn from_proto(proto: proto::RoleAttributes) -> Result<Self, TryFromProtoError> {
133        let mut attributes = RoleAttributes::new();
134
135        attributes.inherit = proto.inherit;
136        attributes.superuser = proto.superuser;
137        attributes.login = proto.login;
138        attributes.auto_provision_source = proto.auto_provision_source.into_rust()?;
139
140        Ok(attributes)
141    }
142}
143
144impl RustType<proto::RoleVar> for OwnedVarInput {
145    fn into_proto(&self) -> proto::RoleVar {
146        match self.clone() {
147            OwnedVarInput::Flat(v) => proto::RoleVar::Flat(v),
148            OwnedVarInput::SqlSet(entries) => proto::RoleVar::SqlSet(entries),
149        }
150    }
151
152    fn from_proto(proto: proto::RoleVar) -> Result<Self, TryFromProtoError> {
153        let result = match proto {
154            proto::RoleVar::Flat(v) => OwnedVarInput::Flat(v),
155            proto::RoleVar::SqlSet(entries) => OwnedVarInput::SqlSet(entries),
156        };
157        Ok(result)
158    }
159}
160
161impl RustType<proto::RoleVars> for RoleVars {
162    fn into_proto(&self) -> proto::RoleVars {
163        let entries = self
164            .map
165            .clone()
166            .into_iter()
167            .map(|(key, val)| proto::RoleVarsEntry {
168                key,
169                val: val.into_proto(),
170            })
171            .collect();
172
173        proto::RoleVars { entries }
174    }
175
176    fn from_proto(proto: proto::RoleVars) -> Result<Self, TryFromProtoError> {
177        let map = proto
178            .entries
179            .into_iter()
180            .map(|entry| {
181                let val = entry.val.into_rust()?;
182                Ok::<_, TryFromProtoError>((entry.key, val))
183            })
184            .collect::<Result<_, _>>()?;
185
186        Ok(RoleVars { map })
187    }
188}
189
190impl RustType<proto::NetworkPolicyId> for NetworkPolicyId {
191    fn into_proto(&self) -> proto::NetworkPolicyId {
192        match self {
193            NetworkPolicyId::User(id) => proto::NetworkPolicyId::User(*id),
194            NetworkPolicyId::System(id) => proto::NetworkPolicyId::System(*id),
195        }
196    }
197
198    fn from_proto(proto: proto::NetworkPolicyId) -> Result<Self, TryFromProtoError> {
199        let id = match proto {
200            proto::NetworkPolicyId::User(id) => NetworkPolicyId::User(id),
201            proto::NetworkPolicyId::System(id) => NetworkPolicyId::System(id),
202        };
203        Ok(id)
204    }
205}
206
207impl RustType<proto::CatalogItemType> for CatalogItemType {
208    fn into_proto(&self) -> proto::CatalogItemType {
209        match self {
210            CatalogItemType::Table => proto::CatalogItemType::Table,
211            CatalogItemType::Source => proto::CatalogItemType::Source,
212            CatalogItemType::Sink => proto::CatalogItemType::Sink,
213            CatalogItemType::View => proto::CatalogItemType::View,
214            CatalogItemType::MaterializedView => proto::CatalogItemType::MaterializedView,
215            CatalogItemType::Index => proto::CatalogItemType::Index,
216            CatalogItemType::Type => proto::CatalogItemType::Type,
217            CatalogItemType::Func => proto::CatalogItemType::Func,
218            CatalogItemType::Secret => proto::CatalogItemType::Secret,
219            CatalogItemType::Connection => proto::CatalogItemType::Connection,
220            CatalogItemType::MetricSink => proto::CatalogItemType::MetricSink,
221        }
222    }
223
224    fn from_proto(proto: proto::CatalogItemType) -> Result<Self, TryFromProtoError> {
225        let item_type = match proto {
226            proto::CatalogItemType::Table => CatalogItemType::Table,
227            proto::CatalogItemType::Source => CatalogItemType::Source,
228            proto::CatalogItemType::Sink => CatalogItemType::Sink,
229            proto::CatalogItemType::View => CatalogItemType::View,
230            proto::CatalogItemType::MaterializedView => CatalogItemType::MaterializedView,
231            proto::CatalogItemType::Index => CatalogItemType::Index,
232            proto::CatalogItemType::Type => CatalogItemType::Type,
233            proto::CatalogItemType::Func => CatalogItemType::Func,
234            proto::CatalogItemType::Secret => CatalogItemType::Secret,
235            proto::CatalogItemType::Connection => CatalogItemType::Connection,
236            proto::CatalogItemType::MetricSink => CatalogItemType::MetricSink,
237            proto::CatalogItemType::Unknown => {
238                return Err(TryFromProtoError::unknown_enum_variant("CatalogItemType"));
239            }
240        };
241        Ok(item_type)
242    }
243}
244
245impl RustType<proto::ObjectType> for ObjectType {
246    fn into_proto(&self) -> proto::ObjectType {
247        match self {
248            ObjectType::Table => proto::ObjectType::Table,
249            ObjectType::View => proto::ObjectType::View,
250            ObjectType::MaterializedView => proto::ObjectType::MaterializedView,
251            ObjectType::Source => proto::ObjectType::Source,
252            ObjectType::Sink => proto::ObjectType::Sink,
253            ObjectType::Index => proto::ObjectType::Index,
254            ObjectType::Type => proto::ObjectType::Type,
255            ObjectType::Role => proto::ObjectType::Role,
256            ObjectType::Cluster => proto::ObjectType::Cluster,
257            ObjectType::ClusterReplica => proto::ObjectType::ClusterReplica,
258            ObjectType::Secret => proto::ObjectType::Secret,
259            ObjectType::Connection => proto::ObjectType::Connection,
260            ObjectType::Database => proto::ObjectType::Database,
261            ObjectType::Schema => proto::ObjectType::Schema,
262            ObjectType::Func => proto::ObjectType::Func,
263            ObjectType::NetworkPolicy => proto::ObjectType::NetworkPolicy,
264            ObjectType::MetricSink => proto::ObjectType::MetricSink,
265        }
266    }
267
268    fn from_proto(proto: proto::ObjectType) -> Result<Self, TryFromProtoError> {
269        match proto {
270            proto::ObjectType::Table => Ok(ObjectType::Table),
271            proto::ObjectType::View => Ok(ObjectType::View),
272            proto::ObjectType::MaterializedView => Ok(ObjectType::MaterializedView),
273            proto::ObjectType::Source => Ok(ObjectType::Source),
274            proto::ObjectType::Sink => Ok(ObjectType::Sink),
275            proto::ObjectType::Index => Ok(ObjectType::Index),
276            proto::ObjectType::Type => Ok(ObjectType::Type),
277            proto::ObjectType::Role => Ok(ObjectType::Role),
278            proto::ObjectType::Cluster => Ok(ObjectType::Cluster),
279            proto::ObjectType::ClusterReplica => Ok(ObjectType::ClusterReplica),
280            proto::ObjectType::Secret => Ok(ObjectType::Secret),
281            proto::ObjectType::Connection => Ok(ObjectType::Connection),
282            proto::ObjectType::Database => Ok(ObjectType::Database),
283            proto::ObjectType::Schema => Ok(ObjectType::Schema),
284            proto::ObjectType::Func => Ok(ObjectType::Func),
285            proto::ObjectType::NetworkPolicy => Ok(ObjectType::NetworkPolicy),
286            proto::ObjectType::MetricSink => Ok(ObjectType::MetricSink),
287            proto::ObjectType::Unknown => Err(TryFromProtoError::unknown_enum_variant(
288                "ObjectType::Unknown",
289            )),
290        }
291    }
292}
293
294impl RustType<proto::RoleMembership> for RoleMembership {
295    fn into_proto(&self) -> proto::RoleMembership {
296        proto::RoleMembership {
297            map: self
298                .map
299                .iter()
300                .map(|(key, val)| proto::RoleMembershipEntry {
301                    key: key.into_proto(),
302                    value: val.into_proto(),
303                })
304                .collect(),
305        }
306    }
307
308    fn from_proto(proto: proto::RoleMembership) -> Result<Self, TryFromProtoError> {
309        Ok(RoleMembership {
310            map: proto
311                .map
312                .into_iter()
313                .map(|e| {
314                    let key = e.key.into_rust()?;
315                    let val = e.value.into_rust()?;
316
317                    Ok((key, val))
318                })
319                .collect::<Result<_, TryFromProtoError>>()?,
320        })
321    }
322}
323
324impl RustType<proto::ResolvedDatabaseSpecifier> for ResolvedDatabaseSpecifier {
325    fn into_proto(&self) -> proto::ResolvedDatabaseSpecifier {
326        match self {
327            ResolvedDatabaseSpecifier::Ambient => proto::ResolvedDatabaseSpecifier::Ambient,
328            ResolvedDatabaseSpecifier::Id(database_id) => {
329                proto::ResolvedDatabaseSpecifier::Id(database_id.into_proto())
330            }
331        }
332    }
333
334    fn from_proto(proto: proto::ResolvedDatabaseSpecifier) -> Result<Self, TryFromProtoError> {
335        let spec = match proto {
336            proto::ResolvedDatabaseSpecifier::Ambient => ResolvedDatabaseSpecifier::Ambient,
337            proto::ResolvedDatabaseSpecifier::Id(database_id) => {
338                ResolvedDatabaseSpecifier::Id(database_id.into_rust()?)
339            }
340        };
341        Ok(spec)
342    }
343}
344
345impl RustType<proto::SchemaSpecifier> for SchemaSpecifier {
346    fn into_proto(&self) -> proto::SchemaSpecifier {
347        match self {
348            SchemaSpecifier::Temporary => proto::SchemaSpecifier::Temporary,
349            SchemaSpecifier::Id(schema_id) => proto::SchemaSpecifier::Id(schema_id.into_proto()),
350        }
351    }
352
353    fn from_proto(proto: proto::SchemaSpecifier) -> Result<Self, TryFromProtoError> {
354        let spec = match proto {
355            proto::SchemaSpecifier::Temporary => SchemaSpecifier::Temporary,
356            proto::SchemaSpecifier::Id(schema_id) => SchemaSpecifier::Id(schema_id.into_rust()?),
357        };
358        Ok(spec)
359    }
360}
361
362impl RustType<proto::SchemaId> for SchemaId {
363    fn into_proto(&self) -> proto::SchemaId {
364        match self {
365            SchemaId::User(id) => proto::SchemaId::User(*id),
366            SchemaId::System(id) => proto::SchemaId::System(*id),
367        }
368    }
369
370    fn from_proto(proto: proto::SchemaId) -> Result<Self, TryFromProtoError> {
371        let id = match proto {
372            proto::SchemaId::User(id) => SchemaId::User(id),
373            proto::SchemaId::System(id) => SchemaId::System(id),
374        };
375        Ok(id)
376    }
377}
378
379impl RustType<proto::DatabaseId> for DatabaseId {
380    fn into_proto(&self) -> proto::DatabaseId {
381        match self {
382            DatabaseId::User(id) => proto::DatabaseId::User(*id),
383            DatabaseId::System(id) => proto::DatabaseId::System(*id),
384        }
385    }
386
387    fn from_proto(proto: proto::DatabaseId) -> Result<Self, TryFromProtoError> {
388        match proto {
389            proto::DatabaseId::User(id) => Ok(DatabaseId::User(id)),
390            proto::DatabaseId::System(id) => Ok(DatabaseId::System(id)),
391        }
392    }
393}
394
395impl RustType<proto::CommentObject> for CommentObjectId {
396    fn into_proto(&self) -> proto::CommentObject {
397        match self {
398            CommentObjectId::Table(global_id) => {
399                proto::CommentObject::Table(global_id.into_proto())
400            }
401            CommentObjectId::View(global_id) => proto::CommentObject::View(global_id.into_proto()),
402            CommentObjectId::MaterializedView(global_id) => {
403                proto::CommentObject::MaterializedView(global_id.into_proto())
404            }
405            CommentObjectId::Source(global_id) => {
406                proto::CommentObject::Source(global_id.into_proto())
407            }
408            CommentObjectId::Sink(global_id) => proto::CommentObject::Sink(global_id.into_proto()),
409            CommentObjectId::MetricSink(global_id) => {
410                proto::CommentObject::MetricSink(global_id.into_proto())
411            }
412            CommentObjectId::Index(global_id) => {
413                proto::CommentObject::Index(global_id.into_proto())
414            }
415            CommentObjectId::Func(global_id) => proto::CommentObject::Func(global_id.into_proto()),
416            CommentObjectId::Connection(global_id) => {
417                proto::CommentObject::Connection(global_id.into_proto())
418            }
419            CommentObjectId::Type(global_id) => proto::CommentObject::Type(global_id.into_proto()),
420            CommentObjectId::Secret(global_id) => {
421                proto::CommentObject::Secret(global_id.into_proto())
422            }
423            CommentObjectId::Role(role_id) => proto::CommentObject::Role(role_id.into_proto()),
424            CommentObjectId::Database(database_id) => {
425                proto::CommentObject::Database(database_id.into_proto())
426            }
427            CommentObjectId::NetworkPolicy(network_policy_id) => {
428                proto::CommentObject::NetworkPolicy(network_policy_id.into_proto())
429            }
430            CommentObjectId::Schema((database, schema)) => {
431                proto::CommentObject::Schema(proto::ResolvedSchema {
432                    database: database.into_proto(),
433                    schema: schema.into_proto(),
434                })
435            }
436            CommentObjectId::Cluster(cluster_id) => {
437                proto::CommentObject::Cluster(cluster_id.into_proto())
438            }
439            CommentObjectId::ClusterReplica((cluster_id, replica_id)) => {
440                let cluster_replica_id = proto::ClusterReplicaId {
441                    cluster_id: cluster_id.into_proto(),
442                    replica_id: replica_id.into_proto(),
443                };
444                proto::CommentObject::ClusterReplica(cluster_replica_id)
445            }
446        }
447    }
448
449    fn from_proto(proto: proto::CommentObject) -> Result<Self, TryFromProtoError> {
450        let id = match proto {
451            proto::CommentObject::Table(item_id) => CommentObjectId::Table(item_id.into_rust()?),
452            proto::CommentObject::View(item_id) => CommentObjectId::View(item_id.into_rust()?),
453            proto::CommentObject::MaterializedView(item_id) => {
454                CommentObjectId::MaterializedView(item_id.into_rust()?)
455            }
456            proto::CommentObject::Source(item_id) => CommentObjectId::Source(item_id.into_rust()?),
457            proto::CommentObject::Sink(item_id) => CommentObjectId::Sink(item_id.into_rust()?),
458            proto::CommentObject::MetricSink(item_id) => {
459                CommentObjectId::MetricSink(item_id.into_rust()?)
460            }
461            proto::CommentObject::Index(item_id) => CommentObjectId::Index(item_id.into_rust()?),
462            proto::CommentObject::Func(item_id) => CommentObjectId::Func(item_id.into_rust()?),
463            proto::CommentObject::Connection(item_id) => {
464                CommentObjectId::Connection(item_id.into_rust()?)
465            }
466            proto::CommentObject::Type(item_id) => CommentObjectId::Type(item_id.into_rust()?),
467            proto::CommentObject::Secret(item_id) => CommentObjectId::Secret(item_id.into_rust()?),
468            proto::CommentObject::NetworkPolicy(global_id) => {
469                CommentObjectId::NetworkPolicy(global_id.into_rust()?)
470            }
471            proto::CommentObject::Role(role_id) => CommentObjectId::Role(role_id.into_rust()?),
472            proto::CommentObject::Database(database_id) => {
473                CommentObjectId::Database(database_id.into_rust()?)
474            }
475            proto::CommentObject::Schema(resolved_schema) => {
476                let database = resolved_schema.database.into_rust()?;
477                let schema = resolved_schema.schema.into_rust()?;
478                CommentObjectId::Schema((database, schema))
479            }
480            proto::CommentObject::Cluster(cluster_id) => {
481                CommentObjectId::Cluster(cluster_id.into_rust()?)
482            }
483            proto::CommentObject::ClusterReplica(cluster_replica_id) => {
484                let cluster_id = cluster_replica_id.cluster_id.into_rust()?;
485                let replica_id = cluster_replica_id.replica_id.into_rust()?;
486                CommentObjectId::ClusterReplica((cluster_id, replica_id))
487            }
488        };
489        Ok(id)
490    }
491}
492
493impl RustType<proto::EpochMillis> for u64 {
494    fn into_proto(&self) -> proto::EpochMillis {
495        proto::EpochMillis { millis: *self }
496    }
497
498    fn from_proto(proto: proto::EpochMillis) -> Result<Self, TryFromProtoError> {
499        Ok(proto.millis)
500    }
501}
502
503impl RustType<proto::CatalogItemId> for CatalogItemId {
504    fn into_proto(&self) -> proto::CatalogItemId {
505        match self {
506            CatalogItemId::System(x) => proto::CatalogItemId::System(*x),
507            CatalogItemId::IntrospectionSourceIndex(x) => {
508                proto::CatalogItemId::IntrospectionSourceIndex(*x)
509            }
510            CatalogItemId::User(x) => proto::CatalogItemId::User(*x),
511            CatalogItemId::Transient(x) => proto::CatalogItemId::Transient(*x),
512        }
513    }
514
515    fn from_proto(proto: proto::CatalogItemId) -> Result<Self, TryFromProtoError> {
516        match proto {
517            proto::CatalogItemId::System(x) => Ok(CatalogItemId::System(x)),
518            proto::CatalogItemId::IntrospectionSourceIndex(x) => {
519                Ok(CatalogItemId::IntrospectionSourceIndex(x))
520            }
521            proto::CatalogItemId::User(x) => Ok(CatalogItemId::User(x)),
522            proto::CatalogItemId::Transient(x) => Ok(CatalogItemId::Transient(x)),
523        }
524    }
525}
526
527impl RustType<proto::GlobalId> for GlobalId {
528    fn into_proto(&self) -> proto::GlobalId {
529        match self {
530            GlobalId::System(x) => proto::GlobalId::System(*x),
531            GlobalId::IntrospectionSourceIndex(x) => proto::GlobalId::IntrospectionSourceIndex(*x),
532            GlobalId::User(x) => proto::GlobalId::User(*x),
533            GlobalId::Transient(x) => proto::GlobalId::Transient(*x),
534            GlobalId::Explain => proto::GlobalId::Explain,
535        }
536    }
537
538    fn from_proto(proto: proto::GlobalId) -> Result<Self, TryFromProtoError> {
539        match proto {
540            proto::GlobalId::System(x) => Ok(GlobalId::System(x)),
541            proto::GlobalId::IntrospectionSourceIndex(x) => {
542                Ok(GlobalId::IntrospectionSourceIndex(x))
543            }
544            proto::GlobalId::User(x) => Ok(GlobalId::User(x)),
545            proto::GlobalId::Transient(x) => Ok(GlobalId::Transient(x)),
546            proto::GlobalId::Explain => Ok(GlobalId::Explain),
547        }
548    }
549}
550
551impl RustType<proto::ClusterId> for StorageInstanceId {
552    fn into_proto(&self) -> proto::ClusterId {
553        match self {
554            StorageInstanceId::User(id) => proto::ClusterId::User(*id),
555            StorageInstanceId::System(id) => proto::ClusterId::System(*id),
556        }
557    }
558
559    fn from_proto(proto: proto::ClusterId) -> Result<Self, TryFromProtoError> {
560        let id = match proto {
561            proto::ClusterId::User(id) => StorageInstanceId::user(id).ok_or_else(|| {
562                TryFromProtoError::InvalidPersistState(format!(
563                    "{id} is not a valid StorageInstanceId"
564                ))
565            })?,
566            proto::ClusterId::System(id) => StorageInstanceId::system(id).ok_or_else(|| {
567                TryFromProtoError::InvalidPersistState(format!(
568                    "{id} is not a valid StorageInstanceId"
569                ))
570            })?,
571        };
572        Ok(id)
573    }
574}
575
576impl RustType<proto::ReplicaId> for ReplicaId {
577    fn into_proto(&self) -> proto::ReplicaId {
578        match self {
579            Self::System(id) => proto::ReplicaId::System(*id),
580            Self::User(id) => proto::ReplicaId::User(*id),
581        }
582    }
583
584    fn from_proto(proto: proto::ReplicaId) -> Result<Self, TryFromProtoError> {
585        match proto {
586            proto::ReplicaId::System(id) => Ok(Self::System(id)),
587            proto::ReplicaId::User(id) => Ok(Self::User(id)),
588        }
589    }
590}
591
592impl ProtoMapEntry<String, String> for proto::OptimizerFeatureOverride {
593    fn from_rust<'a>(entry: (&'a String, &'a String)) -> Self {
594        proto::OptimizerFeatureOverride {
595            name: entry.0.into_proto(),
596            value: entry.1.into_proto(),
597        }
598    }
599
600    fn into_rust(self) -> Result<(String, String), TryFromProtoError> {
601        Ok((self.name.into_rust()?, self.value.into_rust()?))
602    }
603}
604
605impl RustType<proto::ClusterSchedule> for ClusterSchedule {
606    fn into_proto(&self) -> proto::ClusterSchedule {
607        match self {
608            ClusterSchedule::Manual => proto::ClusterSchedule::Manual,
609            ClusterSchedule::Refresh {
610                hydration_time_estimate,
611            } => proto::ClusterSchedule::Refresh(proto::ClusterScheduleRefreshOptions {
612                rehydration_time_estimate: hydration_time_estimate.into_proto(),
613            }),
614        }
615    }
616
617    fn from_proto(proto: proto::ClusterSchedule) -> Result<Self, TryFromProtoError> {
618        match proto {
619            proto::ClusterSchedule::Manual => Ok(ClusterSchedule::Manual),
620            proto::ClusterSchedule::Refresh(csro) => Ok(ClusterSchedule::Refresh {
621                hydration_time_estimate: csro.rehydration_time_estimate.into_rust()?,
622            }),
623        }
624    }
625}
626
627impl RustType<proto::AutoScalingStrategy> for AutoScalingStrategy {
628    fn into_proto(&self) -> proto::AutoScalingStrategy {
629        proto::AutoScalingStrategy {
630            on_hydration: self.on_hydration.into_proto(),
631        }
632    }
633
634    fn from_proto(proto: proto::AutoScalingStrategy) -> Result<Self, TryFromProtoError> {
635        Ok(Self {
636            on_hydration: proto.on_hydration.into_rust()?,
637        })
638    }
639}
640
641impl RustType<proto::OnHydration> for OnHydration {
642    fn into_proto(&self) -> proto::OnHydration {
643        proto::OnHydration {
644            hydration_size: self.hydration_size.clone(),
645            linger_duration: self.linger_duration.into_proto(),
646        }
647    }
648
649    fn from_proto(proto: proto::OnHydration) -> Result<Self, TryFromProtoError> {
650        Ok(Self {
651            hydration_size: proto.hydration_size,
652            linger_duration: proto.linger_duration.into_rust()?,
653        })
654    }
655}
656
657impl RustType<proto::OnTimeoutAction> for OnTimeoutAction {
658    fn into_proto(&self) -> proto::OnTimeoutAction {
659        match self {
660            OnTimeoutAction::Commit => proto::OnTimeoutAction::Commit,
661            OnTimeoutAction::Rollback => proto::OnTimeoutAction::Rollback,
662        }
663    }
664
665    fn from_proto(proto: proto::OnTimeoutAction) -> Result<Self, TryFromProtoError> {
666        Ok(match proto {
667            proto::OnTimeoutAction::Commit => OnTimeoutAction::Commit,
668            proto::OnTimeoutAction::Rollback => OnTimeoutAction::Rollback,
669        })
670    }
671}
672
673impl RustType<proto::ReplicaLogging> for ComputeReplicaLogging {
674    fn into_proto(&self) -> proto::ReplicaLogging {
675        proto::ReplicaLogging {
676            log_logging: self.log_logging,
677            interval: self.interval.into_proto(),
678        }
679    }
680
681    fn from_proto(proto: proto::ReplicaLogging) -> Result<Self, TryFromProtoError> {
682        Ok(ComputeReplicaLogging {
683            log_logging: proto.log_logging,
684            interval: proto.interval.into_rust()?,
685        })
686    }
687}
688
689impl RustType<proto::Version> for RelationVersion {
690    fn into_proto(&self) -> proto::Version {
691        proto::Version {
692            value: self.into_raw(),
693        }
694    }
695
696    fn from_proto(proto: proto::Version) -> Result<Self, TryFromProtoError> {
697        Ok(RelationVersion::from_raw(proto.value))
698    }
699}
700
701impl RustType<proto::NetworkPolicyRule> for NetworkPolicyRule {
702    fn into_proto(&self) -> proto::NetworkPolicyRule {
703        proto::NetworkPolicyRule {
704            name: self.name.clone(),
705            action: match self.action {
706                NetworkPolicyRuleAction::Allow => proto::NetworkPolicyRuleAction::Allow,
707            },
708            direction: match self.direction {
709                NetworkPolicyRuleDirection::Ingress => proto::NetworkPolicyRuleDirection::Ingress,
710            },
711            address: self.address.clone().to_string(),
712        }
713    }
714
715    fn from_proto(proto: proto::NetworkPolicyRule) -> Result<Self, TryFromProtoError> {
716        Ok(NetworkPolicyRule {
717            name: proto.name,
718            action: match proto.action {
719                proto::NetworkPolicyRuleAction::Allow => NetworkPolicyRuleAction::Allow,
720            },
721            address: PolicyAddress::from(proto.address),
722            direction: match proto.direction {
723                proto::NetworkPolicyRuleDirection::Ingress => NetworkPolicyRuleDirection::Ingress,
724            },
725        })
726    }
727}
728
729impl RustType<String> for ShardId {
730    // Delegates to the `mz_proto` encoding, so that both stay identical.
731    fn into_proto(&self) -> String {
732        mz_proto::RustType::into_proto(self)
733    }
734
735    fn from_proto(proto: String) -> Result<Self, TryFromProtoError> {
736        mz_proto::RustType::from_proto(proto)
737    }
738}