aster_forge_cloud_files_core/
cursor.rs1use 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 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 pub fn from_slice(value: &[u8]) -> Result<Self> {
33 Self::new(value.to_vec())
34 }
35
36 pub fn as_bytes(&self) -> &[u8] {
38 &self.0
39 }
40
41 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);