aster_forge_cloud_files_core/
cursor.rs

1//! Distinct opaque continuation tokens for listing, change tracking, and native directory streams.
2
3use std::fmt;
4
5use crate::{CloudFilesCoreError, Result};
6
7macro_rules! opaque_cursor {
8    ($name:ident, $field:literal, $docs:literal) => {
9        #[doc = $docs]
10        #[derive(Clone, PartialEq, Eq, Hash)]
11        pub struct $name(Vec<u8>);
12
13        impl $name {
14            /// Creates a non-empty opaque continuation token.
15            /// # Errors
16            ///
17            /// Returns an error when validation fails or an underlying backend, store, or platform
18            /// operation fails.
19            pub fn new(value: impl Into<Vec<u8>>) -> Result<Self> {
20                let value = value.into();
21                if value.is_empty() {
22                    return Err(CloudFilesCoreError::empty($field));
23                }
24                Ok(Self(value))
25            }
26
27            /// Copies a non-empty continuation token from a byte slice.
28            /// # Errors
29            ///
30            /// Returns an error when validation fails or an underlying backend, store, or platform
31            /// operation fails.
32            pub fn from_slice(value: &[u8]) -> Result<Self> {
33                Self::new(value.to_vec())
34            }
35
36            /// Returns the opaque token bytes.
37            pub fn as_bytes(&self) -> &[u8] {
38                &self.0
39            }
40
41            /// Consumes the token and returns its opaque bytes.
42            pub fn into_bytes(self) -> Vec<u8> {
43                self.0
44            }
45        }
46
47        impl fmt::Debug for $name {
48            fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
49                formatter
50                    .debug_struct(stringify!($name))
51                    .field("byte_len", &self.0.len())
52                    .finish()
53            }
54        }
55    };
56}
57
58opaque_cursor!(
59    PageCursor,
60    "page cursor",
61    "Backend list-pagination position for one enumeration sequence."
62);
63opaque_cursor!(
64    ChangeCursor,
65    "change cursor",
66    "Durable backend checkpoint for an incremental change stream."
67);
68opaque_cursor!(
69    DirectoryCookie,
70    "directory cookie",
71    "Continuation token scoped to one native open-directory stream."
72);