mz_expr/
id.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
10use std::fmt;
11
12use mz_lowertest::MzReflect;
13use mz_proto::{ProtoType, RustType, TryFromProtoError};
14use mz_repr::GlobalId;
15use proptest_derive::Arbitrary;
16use serde::{Deserialize, Serialize};
17
18include!(concat!(env!("OUT_DIR"), "/mz_expr.id.rs"));
19
20/// An opaque identifier for a dataflow component. In other words, identifies
21/// the target of a [`MirRelationExpr::Get`](crate::MirRelationExpr::Get).
22#[derive(
23    Arbitrary,
24    Clone,
25    Copy,
26    Debug,
27    Eq,
28    PartialEq,
29    Ord,
30    PartialOrd,
31    Hash,
32    Serialize,
33    Deserialize,
34    MzReflect,
35)]
36pub enum Id {
37    /// An identifier that refers to a local component of a dataflow.
38    Local(LocalId),
39    /// An identifier that refers to a global dataflow.
40    #[proptest(value = "Id::Global(GlobalId::System(2))")]
41    Global(GlobalId),
42}
43
44impl fmt::Display for Id {
45    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46        match self {
47            Id::Local(id) => id.fmt(f),
48            Id::Global(id) => id.fmt(f),
49        }
50    }
51}
52
53impl RustType<ProtoId> for Id {
54    fn into_proto(&self) -> ProtoId {
55        ProtoId {
56            kind: Some(match self {
57                Id::Global(g) => proto_id::Kind::Global(g.into_proto()),
58                Id::Local(l) => proto_id::Kind::Local(l.into_proto()),
59            }),
60        }
61    }
62
63    fn from_proto(proto: ProtoId) -> Result<Self, TryFromProtoError> {
64        match proto.kind {
65            Some(proto_id::Kind::Global(x)) => Ok(Id::Global(x.into_rust()?)),
66            Some(proto_id::Kind::Local(x)) => Ok(Id::Local(x.into_rust()?)),
67            None => Err(TryFromProtoError::missing_field("ProtoId::kind")),
68        }
69    }
70}
71
72/// The identifier for a local component of a dataflow.
73#[derive(
74    Arbitrary,
75    Clone,
76    Copy,
77    Debug,
78    Eq,
79    PartialEq,
80    Ord,
81    PartialOrd,
82    Hash,
83    Serialize,
84    Deserialize,
85    MzReflect,
86)]
87pub struct LocalId(pub(crate) u64);
88
89impl LocalId {
90    /// Constructs a new local identifier. It is the caller's responsibility
91    /// to provide a unique `v`.
92    pub fn new(v: u64) -> LocalId {
93        LocalId(v)
94    }
95}
96
97impl From<&LocalId> for u64 {
98    fn from(id: &LocalId) -> Self {
99        id.0
100    }
101}
102
103impl fmt::Display for LocalId {
104    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
105        write!(f, "l{}", self.0)
106    }
107}
108
109impl RustType<ProtoLocalId> for LocalId {
110    fn into_proto(&self) -> ProtoLocalId {
111        ProtoLocalId { value: self.0 }
112    }
113
114    fn from_proto(proto: ProtoLocalId) -> Result<Self, TryFromProtoError> {
115        Ok(LocalId::new(proto.value))
116    }
117}
118
119/// Unique identifier for an instantiation of a source.
120#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
121pub struct SourceInstanceId {
122    /// The ID of the source, shared across all instances.
123    pub source_id: GlobalId,
124    /// The ID of the timely dataflow containing this instantiation of this
125    /// source.
126    pub dataflow_id: usize,
127}
128
129impl fmt::Display for SourceInstanceId {
130    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131        write!(f, "{}/{}", self.source_id, self.dataflow_id)
132    }
133}
134
135#[cfg(test)]
136mod tests {
137    use mz_ore::assert_ok;
138    use mz_proto::protobuf_roundtrip;
139    use proptest::prelude::*;
140
141    use super::*;
142
143    proptest! {
144        #[mz_ore::test]
145        fn id_protobuf_roundtrip(expect in any::<Id>()) {
146            let actual = protobuf_roundtrip::<_, ProtoId>(&expect);
147            assert_ok!(actual);
148            assert_eq!(actual.unwrap(), expect);
149        }
150    }
151}