Skip to main content

orleans_rust_client/
key.rs

1//! Grain key types.
2//!
3//! Orleans grains are addressed by a compound identity. This crate models the
4//! three primitive key kinds Orleans supports for single-key grains. Compound
5//! keys (`IGrainWithGuidCompoundKey`, `IGrainWithIntegerCompoundKey`) are not
6//! modelled in v0.
7
8use uuid::Uuid;
9
10use crate::generated::pb;
11
12/// The primary key used to address an Orleans grain activation.
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum GrainKey {
15    /// `IGrainWithStringKey`.
16    String(String),
17    /// `IGrainWithIntegerKey`.
18    Int64(i64),
19    /// `IGrainWithGuidKey`.
20    Guid(Uuid),
21}
22
23impl GrainKey {
24    /// The stable name of this key kind, matching the values reported in a
25    /// grain contract's `supported_key_kinds`.
26    #[must_use]
27    pub fn kind_name(&self) -> &'static str {
28        match self {
29            GrainKey::String(_) => "string",
30            GrainKey::Int64(_) => "int64",
31            GrainKey::Guid(_) => "guid",
32        }
33    }
34
35    pub(crate) fn to_proto(&self) -> pb::GrainKey {
36        let kind = match self {
37            GrainKey::String(s) => pb::grain_key::Kind::StringKey(s.clone()),
38            GrainKey::Int64(i) => pb::grain_key::Kind::Int64Key(*i),
39            GrainKey::Guid(g) => pb::grain_key::Kind::GuidKey(g.to_string()),
40        };
41        pb::GrainKey { kind: Some(kind) }
42    }
43}
44
45impl From<String> for GrainKey {
46    fn from(value: String) -> Self {
47        GrainKey::String(value)
48    }
49}
50
51impl From<&str> for GrainKey {
52    fn from(value: &str) -> Self {
53        GrainKey::String(value.to_owned())
54    }
55}
56
57impl From<i64> for GrainKey {
58    fn from(value: i64) -> Self {
59        GrainKey::Int64(value)
60    }
61}
62
63impl From<Uuid> for GrainKey {
64    fn from(value: Uuid) -> Self {
65        GrainKey::Guid(value)
66    }
67}
68
69impl std::fmt::Display for GrainKey {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        match self {
72            GrainKey::String(s) => write!(f, "{s}"),
73            GrainKey::Int64(i) => write!(f, "{i}"),
74            GrainKey::Guid(g) => write!(f, "{g}"),
75        }
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn conversions_pick_the_right_variant() {
85        assert_eq!(GrainKey::from("k"), GrainKey::String("k".to_owned()));
86        assert_eq!(
87            GrainKey::from("k".to_owned()),
88            GrainKey::String("k".to_owned())
89        );
90        assert_eq!(GrainKey::from(7_i64), GrainKey::Int64(7));
91        let id = Uuid::nil();
92        assert_eq!(GrainKey::from(id), GrainKey::Guid(id));
93    }
94
95    #[test]
96    fn kind_names_are_stable() {
97        assert_eq!(GrainKey::String(String::new()).kind_name(), "string");
98        assert_eq!(GrainKey::Int64(0).kind_name(), "int64");
99        assert_eq!(GrainKey::Guid(Uuid::nil()).kind_name(), "guid");
100    }
101
102    #[test]
103    fn to_proto_maps_each_variant() {
104        assert!(matches!(
105            GrainKey::String("s".into()).to_proto().kind,
106            Some(pb::grain_key::Kind::StringKey(ref s)) if s == "s"
107        ));
108        assert!(matches!(
109            GrainKey::Int64(9).to_proto().kind,
110            Some(pb::grain_key::Kind::Int64Key(9))
111        ));
112        let id = Uuid::from_u128(0x1234);
113        match GrainKey::Guid(id).to_proto().kind {
114            Some(pb::grain_key::Kind::GuidKey(s)) => assert_eq!(s, id.to_string()),
115            other => panic!("unexpected {other:?}"),
116        }
117    }
118
119    #[test]
120    fn display_round_trips_value() {
121        assert_eq!(GrainKey::Int64(42).to_string(), "42");
122        assert_eq!(GrainKey::String("abc".into()).to_string(), "abc");
123        let id = Uuid::from_u128(0x1234);
124        assert_eq!(GrainKey::Guid(id).to_string(), id.to_string());
125    }
126}