1#![allow(clippy::complexity)]
2pub mod codec;
3pub mod error;
4pub mod migration;
5pub mod reactive;
6pub mod store;
7
8use serde::Serialize;
9use serde::de::DeserializeOwned;
10use std::sync::Arc;
11
12pub use error::Result;
13pub use inventory;
14pub use reactive::{
15 AccessMode, Change, Field, InterceptDisposer, IntoPipeline, MapChange, MapSubscription,
16 Pipeline, Reactive, ReactiveMap, ReactiveScope, ReadOnly, ReadOnlyMode, RpState, RpStateNode,
17 Signal, SignalSubscription, StoreSubscription, Writable, WritableMode,
18};
19pub use serde;
20pub use serde_json;
21
22pub use store::{
23 StateScope, Store, StoreEvent, StoreOp, SubscriptionKind, builder::StoreBuilder,
24 config::StoreConfig, reactive_map, reactive_map_with_path, scoped_path,
25};
26
27pub use migration::{MigrationContext, MigrationError, MigrationReport, Migrator};
28pub use rpstate_macros::{RpType, rpstate};
29
30#[cfg(feature = "json")]
31pub use store::backend::json::JsonStore;
32
33#[cfg(feature = "redb")]
34pub use store::backend::redb::RedbStore;
35
36#[cfg(feature = "redb")]
37pub type DefaultStore = RedbStore;
38
39#[cfg(all(feature = "json", not(feature = "redb")))]
40pub type DefaultStore = JsonStore;
41
42#[cfg(not(any(feature = "json", feature = "redb")))]
43compile_error!(
44 "rpstate requires at least one backend feature to be enabled. \
45 Please enable either 'redb' (recommended) or 'json' in your Cargo.toml."
46);
47
48pub fn field<TScope, TValue>(
49 store: &Arc<DefaultStore>,
50 key: &str,
51 default: TValue,
52) -> Result<Field<TValue, DefaultStore, WritableMode>>
53where
54 TScope: StateScope,
55 TValue: Serialize + Default + DeserializeOwned + Clone + Send + Sync + 'static,
56{
57 store::field::<TScope, TValue, DefaultStore>(store, key, default)
58}
59
60#[macro_export]
61macro_rules! register_migrations {
62 ($T:ty) => {
63 #[cfg(not(target_arch = "wasm32"))]
64 ::inventory::submit! {
65 $crate::migration::registry::MigrationStepEntry {
66 prefix: <$T as $crate::StateScope>::PREFIX,
67 target_version: 0,
68 description: "",
69 dependencies: <$T as $crate::migration::registry::HasMigrations>::MIGRATION_DEPS,
70 run: |_| Ok(()),
71 }
72 }
73 };
74}
75
76#[macro_export]
77macro_rules! migrate {
78 (
79 $old:path => $new:path,
80 rename: $rename:tt,
81 convert: $convert:tt,
82 |$($args:ident),* $(,)?| $logic_block:block
83 ) => {
84 $crate::migrate!(@route $old => $new, rename: $rename, convert: $convert, |$($args),*| $logic_block);
85 };
86
87 (
88 $old:path => $new:path,
89 rename: $rename:tt,
90 |$($args:ident),* $(,)?| $logic_block:block
91 ) => {
92 $crate::migrate!(@route $old => $new, rename: $rename, |$($args),*| $logic_block);
93 };
94
95 (
96 $old:path => $new:path,
97 convert: $convert:tt,
98 |$($args:ident),* $(,)?| $logic_block:block
99 ) => {
100 $crate::migrate!(@route $old => $new, rename: [], convert: $convert, |$($args),*| $logic_block);
101 };
102
103 (
104 $old:path => $new:path,
105 |$($args:ident),* $(,)?| $logic_block:block
106 ) => {
107 $crate::migrate!(@route $old => $new, rename: [], |$($args),*| $logic_block);
108 };
109
110 (@route $old:path => $new:path, rename: $rename:tt $(, convert: $convert:tt)? , |$old_val:ident| $logic_block:block) => {
111 $crate::migrate!(@impl $old => $new, rename: $rename $(, convert: $convert)? , |$old_val, _unused_ctx| $logic_block);
112 };
113
114 (@route $old:path => $new:path, rename: $rename:tt $(, convert: $convert:tt)? , |$old_val:ident, $ctx_val:ident| $logic_block:block) => {
115 $crate::migrate!(@impl $old => $new, rename: $rename $(, convert: $convert)? , |$old_val, $ctx_val| $logic_block);
116 };
117
118 (
119 @impl $old:path => $new:path,
120 rename: [$($old_f:ident => $new_f:ident),* $(,)?]
121 $(, convert: [$($conv_f:ident : $conv_old:ty => $conv_new:ty),* $(,)?])?
122 , |$old_val:ident, $ctx_val:ident| $logic_block:block
123 ) => {
124 const _: () = {
125 #[allow(dead_code, clippy::no_effect, unused_variables)]
126 fn _check_fields(old: &$old, new: &$new) {
127 $(
128 let _ = &old.$old_f;
129 let _ = &new.$new_f;
130 )*
131 }
132 };
133
134 impl $crate::migration::migrate_from::MigrateFrom<$old> for $new {
135 const RENAMES: &'static [(&'static str, &'static str)] = &[
136 $((stringify!($old_f), stringify!($new_f))),*
137 ];
138
139 const CONVERTS: &'static [(&'static str, u64, u64)] = &[
140 $($( (
141 stringify!($conv_f),
142 <$conv_old as $crate::migration::types::RpType>::TYPE_HASH,
143 <$conv_new as $crate::migration::types::RpType>::TYPE_HASH,
144 ) ),*)?
145 ];
146
147 fn migrate($old_val: $old, $ctx_val: &mut $crate::migration::MigrationContext) -> $crate::Result<Self> {
148 $logic_block
149 }
150 }
151
152 $crate::inventory::submit! {
153 $crate::migration::registry::MigrationStepEntry {
154 prefix: <$new as $crate::migration::fields::RpStateFields>::PARENT_PREFIX,
155 target_version: <$new as $crate::migration::fields::RpStateFields>::VERSION,
156 dependencies: <$new as $crate::migration::fields::RpStateFields>::MIGRATION_DEPS,
157 description: "migrate!",
158 schema_hash: <$new as $crate::migration::fields::RpStateFields>::SCHEMA_HASH,
159 fields: <$new as $crate::migration::fields::RpStateFields>::FIELDS,
160 run: |ctx| {
161 use $crate::migration::fields::RpStateFields;
162 use $crate::migration::migrate_from::MigrateFrom;
163
164 let old_data = <$old as RpStateFields>::load_struct(ctx)?;
165 let new_data = <$new as MigrateFrom<$old>>::migrate(old_data, ctx)?;
166
167 for field in <$old as RpStateFields>::FIELDS {
168 let is_renamed = <$new as MigrateFrom<$old>>::RENAMES
169 .iter()
170 .any(|(old_k, _)| *old_k == field.name);
171 let is_kept = <$new as RpStateFields>::FIELDS
172 .iter()
173 .any(|f| f.name == field.name);
174
175 if is_renamed || !is_kept {
176 ctx.delete(field.name)?;
177 }
178 }
179
180 new_data.save_struct(ctx)?;
181 Ok(())
182 }
183 }
184 }
185 };
186}
187
188#[macro_export]
189macro_rules! migrate_field {
190 ($ctx:ident, $old_obj:ident . $field:ident) => {
191 $ctx.nested::<_, _>(stringify!($field), $old_obj.$field)?
192 };
193
194 ($ctx:ident, $key:expr, $old_val:expr) => {
195 $ctx.nested::<_, _>($key, $old_val)?
196 };
197}
198
199pub mod tauri_codegen;