Skip to main content

little_durable_objects/
actor_state.rs

1mod actor;
2
3use serde::{Deserialize, Serialize};
4use std::fmt;
5
6use anyhow::{Result, ensure};
7
8pub(crate) use self::actor::{ActorExecutionAdmission, ActorExecutionLocks};
9
10#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
11pub struct ActorStorageKey(String);
12
13impl ActorStorageKey {
14    pub fn new<S>(id: S) -> Self
15    where
16        S: Into<String>,
17    {
18        Self(id.into())
19    }
20
21    pub fn as_str(&self) -> &str {
22        &self.0
23    }
24
25    pub fn validate(&self) -> Result<()> {
26        ensure!(!self.0.is_empty(), "actor storage key must not be empty");
27        ensure!(
28            self.0.len() <= 255,
29            "actor storage key must be at most 255 bytes"
30        );
31        ensure!(
32            self.0 != "." && self.0 != "..",
33            "actor storage key must not be a relative path component"
34        );
35        ensure!(
36            !self
37                .0
38                .chars()
39                .any(|character| character == '/' || character == '\\' || character.is_control()),
40            "actor storage key must not contain path separators or control characters"
41        );
42
43        Ok(())
44    }
45}
46
47impl fmt::Display for ActorStorageKey {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        f.write_str(&self.0)
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn accepts_a_single_safe_storage_component() {
59        ActorStorageKey::new("tenant_1.session-123")
60            .validate()
61            .expect("valid actor storage key");
62    }
63
64    #[test]
65    fn rejects_ids_that_can_escape_or_reshape_storage_paths() {
66        for id in [
67            "",
68            ".",
69            "..",
70            "../other",
71            "nested/object",
72            "windows\\path",
73            "bad\0id",
74        ] {
75            ActorStorageKey::new(id)
76                .validate()
77                .expect_err("unsafe actor storage key");
78        }
79    }
80}