Skip to main content

reifydb_sdk/state/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4pub mod cache;
5pub mod ffi;
6pub mod keyed;
7pub mod row;
8pub mod single;
9pub mod utils;
10pub mod window;
11
12use std::ops::Bound;
13
14use reifydb_core::encoded::{key::EncodedKey, row::EncodedRow};
15
16use crate::{
17	error::Result,
18	operator::{FFIOperator, context::OperatorContext},
19};
20
21/// State manager providing state operations with EncodedKey and EncodedRow
22pub struct State<'a> {
23	ctx: &'a mut OperatorContext,
24}
25
26impl<'a> State<'a> {
27	/// Create a new state manager
28	pub(crate) fn new(ctx: &'a mut OperatorContext) -> Self {
29		Self {
30			ctx,
31		}
32	}
33
34	/// Get a value from state by key
35	pub fn get(&self, key: &EncodedKey) -> Result<Option<EncodedRow>> {
36		ffi::get(self.ctx, key)
37	}
38
39	/// Set a value in state by key
40	pub fn set(&mut self, key: &EncodedKey, value: &EncodedRow) -> Result<()> {
41		ffi::set(self.ctx, key, value)
42	}
43
44	/// Remove a value from state by key
45	pub fn remove(&mut self, key: &EncodedKey) -> Result<()> {
46		ffi::remove(self.ctx, key)
47	}
48
49	/// Check if a key exists in state
50	pub fn contains(&self, key: &EncodedKey) -> Result<bool> {
51		Ok(ffi::get(self.ctx, key)?.is_some())
52	}
53
54	/// Clear all state for this operator
55	pub fn clear(&mut self) -> Result<()> {
56		ffi::clear(self.ctx)
57	}
58
59	/// Scan state entries with a given key prefix
60	pub fn scan_prefix(&self, prefix: &EncodedKey) -> Result<Vec<(EncodedKey, EncodedRow)>> {
61		ffi::prefix(self.ctx, prefix)
62	}
63
64	/// Get all keys with a given prefix
65	pub fn keys_with_prefix(&self, prefix: &EncodedKey) -> Result<Vec<EncodedKey>> {
66		let entries = self.scan_prefix(prefix)?;
67		Ok(entries.into_iter().map(|(k, _)| k).collect())
68	}
69
70	/// Scan state entries within a given range
71	pub fn range(
72		&self,
73		start: Bound<&EncodedKey>,
74		end: Bound<&EncodedKey>,
75	) -> Result<Vec<(EncodedKey, EncodedRow)>> {
76		ffi::range(self.ctx, start, end)
77	}
78}
79
80/// Raw Stateful operations for FFI operators
81///
82/// This trait provides low-level key-value state operations for FFI operators.
83/// It mirrors the internal `RawStatefulOperator` trait but works through the FFI boundary.
84///
85/// # Example
86///
87/// ```ignore
88/// impl FFIRawStatefulOperator for MyOperator {}
89///
90/// // In your operator implementation:
91/// fn apply(&mut self, ctx: &mut OperatorContext, input: Change) -> Result<Change> {
92///     let key = EncodedKey::new(b"counter".to_vec());
93///     let value = self.state_get(ctx, &key)?;
94///     // ... use state
95/// }
96/// ```
97pub trait FFIRawStatefulOperator: FFIOperator {
98	/// Get raw bytes for a key
99	fn state_get(&self, ctx: &mut OperatorContext, key: &EncodedKey) -> Result<Option<EncodedRow>> {
100		ctx.state().get(key)
101	}
102
103	/// Set raw bytes for a key
104	fn state_set(&self, ctx: &mut OperatorContext, key: &EncodedKey, value: &EncodedRow) -> Result<()> {
105		ctx.state().set(key, value)
106	}
107
108	/// Remove a key
109	fn state_remove(&self, ctx: &mut OperatorContext, key: &EncodedKey) -> Result<()> {
110		ctx.state().remove(key)
111	}
112
113	/// Scan all keys with a prefix
114	fn state_scan_prefix(
115		&self,
116		ctx: &mut OperatorContext,
117		prefix: &EncodedKey,
118	) -> Result<Vec<(EncodedKey, EncodedRow)>> {
119		ctx.state().scan_prefix(prefix)
120	}
121
122	/// Get all keys with a prefix
123	fn state_keys_with_prefix(&self, ctx: &mut OperatorContext, prefix: &EncodedKey) -> Result<Vec<EncodedKey>> {
124		ctx.state().keys_with_prefix(prefix)
125	}
126
127	/// Check if a key exists
128	fn state_contains(&self, ctx: &mut OperatorContext, key: &EncodedKey) -> Result<bool> {
129		ctx.state().contains(key)
130	}
131
132	/// Clear all state for this operator
133	fn state_clear(&self, ctx: &mut OperatorContext) -> Result<()> {
134		ctx.state().clear()
135	}
136
137	/// Scan all keys within a range
138	fn state_scan_range(
139		&self,
140		ctx: &mut OperatorContext,
141		start: Bound<&EncodedKey>,
142		end: Bound<&EncodedKey>,
143	) -> Result<Vec<(EncodedKey, EncodedRow)>> {
144		ctx.state().range(start, end)
145	}
146}