Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/actions/android/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ runs:
- name: Setup
shell: bash
run: |
rustup toolchain install nightly-2025-04-15-x86_64-unknown-linux-gnu
rustup component add rust-src --toolchain nightly-2025-04-15-x86_64-unknown-linux-gnu
rustup toolchain install nightly-2025-10-31-x86_64-unknown-linux-gnu
rustup component add rust-src --toolchain nightly-2025-10-31-x86_64-unknown-linux-gnu
rustup target add \
aarch64-linux-android \
armv7-linux-androideabi \
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/linux/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ runs:
- name: Install Rust Nightly
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-04-15
toolchain: nightly-2025-10-31
components: rust-src
targets: aarch64-unknown-linux-gnu,x86_64-unknown-linux-gnu,i686-unknown-linux-gnu,riscv64gc-unknown-linux-gnu,armv7-unknown-linux-gnueabihf

Expand Down
2 changes: 1 addition & 1 deletion .github/actions/macos/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ runs:
- name: Install Rust Nightly
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-04-15
toolchain: nightly-2025-10-31
components: rust-src
targets: x86_64-apple-darwin,aarch64-apple-darwin

Expand Down
2 changes: 1 addition & 1 deletion .github/actions/wasm/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ runs:
- name: Install Rust Nightly
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-04-15
toolchain: nightly-2025-10-31
components: rust-src

- name: Setup emsdk
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/windows/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ runs:
- name: Install Rust Nightly
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-04-15
toolchain: nightly-2025-10-31
components: rust-src
targets: x86_64-pc-windows-msvc,aarch64-pc-windows-msvc,i686-pc-windows-msvc

Expand Down
4 changes: 2 additions & 2 deletions .github/actions/xcframework/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ runs:
- name: Setup
shell: bash
run: |
rustup toolchain install nightly-2025-04-15-aarch64-apple-darwin
rustup component add rust-src --toolchain nightly-2025-04-15-aarch64-apple-darwin
rustup toolchain install nightly-2025-10-31-aarch64-apple-darwin
rustup component add rust-src --toolchain nightly-2025-10-31-aarch64-apple-darwin
rustup target add \
x86_64-apple-darwin \
aarch64-apple-darwin \
Expand Down
44 changes: 40 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,14 @@ jobs:
- name: Install Rust Nightly
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-04-15
toolchain: nightly-2025-10-31
components: rust-src,rustfmt,clippy

- name: Check formatting
run: cargo fmt --all --check

- name: Build
run: |
# Need a debug build for the dart tests
cargo build -p powersync_loadable

cargo build -p powersync_loadable --release
cargo build -p powersync_core --release --features static
cargo build -p powersync_sqlite --release
Expand Down Expand Up @@ -189,6 +186,40 @@ jobs:
CORE_TEST_SQLITE=.dart_tool/sqlite3/latest/libsqlite3.dylib dart test -P skip_slow
CORE_TEST_SQLITE=.dart_tool/sqlite3/minimum/libsqlite3.dylib dart test -P skip_slow

build_stable_rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true

- uses: dart-lang/setup-dart@v1
- name: Install Rust Stable
uses: dtolnay/rust-toolchain@stable

- uses: actions/cache@v4
id: sqlite_build
with:
path: dart/.dart_tool/sqlite3/
key: ${{ matrix.os }}-${{ hashFiles('dart/tool/') }}

- name: Setup Dart tests
working-directory: dart
run: |
dart pub get
dart run tool/download_sqlite3.dart
dart analyze

- name: Compile with stable Rust
run: |
cargo +stable build -p powersync_loadable

- name: Dart tests with stable Rust
working-directory: dart
run: |
CORE_TEST_SQLITE=.dart_tool/sqlite3/latest/libsqlite3.so dart test
CORE_TEST_SQLITE=.dart_tool/sqlite3/minimum/libsqlite3.so dart test

valgrind:
name: Testing with Valgrind on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
Expand All @@ -201,6 +232,11 @@ jobs:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install Rust Nightly
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2025-10-31
components: rust-src

- name: Install valgrind
run: sudo apt update && sudo apt install -y valgrind
Expand Down
2 changes: 2 additions & 0 deletions android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ fun Exec.rustCompilation(project: String, output: String? = null) {
"-Zbuild-std",
"-p",
project,
"--features",
"nightly"
)
}

Expand Down
7 changes: 4 additions & 3 deletions crates/core/src/bson/de.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use core::assert_matches::debug_assert_matches;

use serde::{
de::{
self, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, VariantAccess,
Expand Down Expand Up @@ -250,7 +248,10 @@ impl<'de> SeqAccess<'de> for Deserializer<'de> {
}

// Skip name
debug_assert_matches!(self.position, DeserializerPosition::BeforeName { .. });
assert!(matches!(
self.position,
DeserializerPosition::BeforeName { .. }
));
self.prepare_to_read(true)?;

// And deserialize value!
Expand Down
3 changes: 1 addition & 2 deletions crates/core/src/bson/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ pub fn from_bytes<'de, T: Deserialize<'de>>(bytes: &'de [u8]) -> Result<T, BsonE
#[cfg(test)]
mod test {
use alloc::{vec, vec::Vec};
use core::assert_matches::assert_matches;

use crate::sync::line::{SyncLine, TokenExpiresIn};

Expand Down Expand Up @@ -53,7 +52,7 @@ mod test {
let bson = b"\x1b\x00\x00\x00\x10token_expires_in\x00<\x00\x00\x00\x00";

let expected: SyncLine = from_bytes(bson.as_slice()).expect("should deserialize");
assert_matches!(expected, SyncLine::KeepAlive(TokenExpiresIn(60)));
assert!(matches!(expected, SyncLine::KeepAlive(TokenExpiresIn(60))))
}

#[test]
Expand Down
3 changes: 1 addition & 2 deletions crates/core/src/fix_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,11 @@ pub fn register(db: *mut sqlite::sqlite3) -> Result<(), ResultCode> {

#[cfg(test)]
mod test {
use core::assert_matches::assert_matches;

use super::remove_duplicate_key_encoding;

fn assert_unaffected(source: &str) {
assert_matches!(remove_duplicate_key_encoding(source), None);
assert!(matches!(remove_duplicate_key_encoding(source), None));
}

#[test]
Expand Down
5 changes: 0 additions & 5 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
#![no_std]
#![feature(btree_set_entry)]
#![feature(assert_matches)]
#![feature(strict_overflow_ops)]
#![feature(vec_into_raw_parts)]

extern crate alloc;

use core::ffi::{c_char, c_int};
Expand Down
9 changes: 7 additions & 2 deletions crates/core/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl DatabaseState {
Self::default()
}

pub fn view_schema(&self) -> Option<Ref<Schema>> {
pub fn view_schema(&'_ self) -> Option<Ref<'_, Schema>> {
let schema_ref = self.schema.borrow();
if schema_ref.is_none() {
None
Expand Down Expand Up @@ -63,7 +63,12 @@ impl DatabaseState {

pub fn track_update(&self, tbl: &str) {
let mut set = self.pending_updates.borrow_mut();
set.get_or_insert_with(tbl, str::to_string);
// TODO: Use set.get_or_insert_with(tbl, str::to_string) after btree_set_entry is stable,
// https://github.com/rust-lang/rust/issues/133549
if !set.contains(tbl) {
// Check whether the set contains the entry first to avoid an unconditional allocation.
set.insert(tbl.to_string());
}
}

pub fn track_rollback(&self) {
Expand Down
37 changes: 21 additions & 16 deletions crates/core/src/sync/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,35 +325,34 @@ impl<'a, 'de: 'a> Deserialize<'de> for OplogData<'a> {

#[cfg(test)]
mod tests {
use core::assert_matches::assert_matches;

use alloc::string::ToString;

use super::*;

fn deserialize(source: &str) -> SyncLine {
fn deserialize(source: &'_ str) -> SyncLine<'_> {
serde_json::from_str(source).expect("Should have deserialized")
}

#[test]
fn parse_token_expires_in() {
assert_matches!(
assert!(matches!(
deserialize(r#"{"token_expires_in": 123}"#),
SyncLine::KeepAlive(TokenExpiresIn(123))
);
));
}

#[test]
fn parse_checkpoint() {
assert_matches!(
assert!(matches!(
deserialize(r#"{"checkpoint": {"last_op_id": "10", "buckets": []}}"#),
SyncLine::Checkpoint(Checkpoint {
last_op_id: 10,
write_checkpoint: None,
buckets: _,
streams: _,
})
);
));

let SyncLine::Checkpoint(checkpoint) = deserialize(
r#"{"checkpoint": {"last_op_id": "10", "buckets": [{"bucket": "a", "checksum": 10}]}}"#,
Expand All @@ -379,7 +378,7 @@ mod tests {
assert_eq!(bucket.checksum, 10u32.into());
assert_eq!(bucket.priority, Some(BucketPriority { number: 1 }));

assert_matches!(
assert!(matches!(
deserialize(
r#"{"checkpoint":{"write_checkpoint":null,"last_op_id":"1","buckets":[{"bucket":"a","checksum":0,"priority":3,"count":1}]}}"#
),
Expand All @@ -389,7 +388,7 @@ mod tests {
buckets: _,
streams: _,
})
);
));
}

#[test]
Expand Down Expand Up @@ -426,23 +425,23 @@ mod tests {

#[test]
fn parse_checkpoint_complete() {
assert_matches!(
assert!(matches!(
deserialize(r#"{"checkpoint_complete": {"last_op_id": "10"}}"#),
SyncLine::CheckpointComplete(CheckpointComplete {
// last_op_id: 10
})
);
));
}

#[test]
fn parse_checkpoint_partially_complete() {
assert_matches!(
assert!(matches!(
deserialize(r#"{"partial_checkpoint_complete": {"last_op_id": "10", "priority": 1}}"#),
SyncLine::CheckpointPartiallyComplete(CheckpointPartiallyComplete {
//last_op_id: 10,
priority: BucketPriority { number: 1 }
})
);
));
}

#[test]
Expand All @@ -463,7 +462,7 @@ mod tests {
assert_eq!(data.data.len(), 1);
let entry = &data.data[0];
assert_eq!(entry.checksum, 10u32.into());
assert_matches!(
assert!(matches!(
&data.data[0],
OplogEntry {
checksum: _,
Expand All @@ -474,13 +473,19 @@ mod tests {
subkey: None,
data: _,
}
);
));
}

#[test]
fn parse_unknown() {
assert_matches!(deserialize("{\"foo\": {}}"), SyncLine::UnknownSyncLine);
assert_matches!(deserialize("{\"foo\": 123}"), SyncLine::UnknownSyncLine);
assert!(matches!(
deserialize("{\"foo\": {}}"),
SyncLine::UnknownSyncLine
));
assert!(matches!(
deserialize("{\"foo\": 123}"),
SyncLine::UnknownSyncLine
));
}

#[test]
Expand Down
6 changes: 3 additions & 3 deletions crates/core/src/sync/storage_adapter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use core::{assert_matches::debug_assert_matches, fmt::Display};
use core::fmt::Display;

use alloc::{rc::Rc, string::ToString, vec::Vec};
use serde::Serialize;
Expand Down Expand Up @@ -140,7 +140,7 @@ impl StorageAdapter {
Ok(())
}

pub fn step_progress(&self) -> Result<Option<PersistedBucketProgress>, ResultCode> {
pub fn step_progress(&'_ self) -> Result<Option<PersistedBucketProgress<'_>>, ResultCode> {
if self.progress_stmt.step()? == ResultCode::ROW {
let bucket = self.progress_stmt.column_text(0)?;
let count_at_last = self.progress_stmt.column_int64(1);
Expand Down Expand Up @@ -181,7 +181,7 @@ impl StorageAdapter {
.into_db_result(self.db)?;
bucket_statement.bind_text(1, bucket, sqlite::Destructor::STATIC)?;
let res = bucket_statement.step()?;
debug_assert_matches!(res, ResultCode::ROW);
debug_assert_eq!(res, ResultCode::ROW);

let bucket_id = bucket_statement.column_int64(0);
let last_applied_op = bucket_statement.column_int64(1);
Expand Down
7 changes: 5 additions & 2 deletions crates/core/src/sync/sync_status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,11 @@ impl ActiveStreamSubscription {
}

pub fn mark_associated_with_bucket(&mut self, bucket: &OwnedBucketChecksum) {
self.associated_buckets
.get_or_insert_with(&bucket.bucket, |key| key.clone());
// This avoids an allocation if the bucket is already tracked. TODO: Use get_or_insert_with
// after https://github.com/rust-lang/rust/issues/133549 is stable.
if !self.associated_buckets.contains(&bucket.bucket) {
self.associated_buckets.insert(bucket.bucket.clone());
}

self.priority = Some(match self.priority {
None => bucket.priority,
Expand Down
8 changes: 4 additions & 4 deletions crates/core/src/sync_local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,16 +483,16 @@ impl<'a> RawTableWithCachedStatements<'a> {
}

fn put_statement(
&mut self,
&'_ mut self,
db: *mut sqlite::sqlite3,
) -> Result<&PreparedPendingStatement, PowerSyncError> {
) -> Result<&'_ PreparedPendingStatement<'_>, PowerSyncError> {
Self::prepare_lazily(db, &mut self.cached_put, &self.definition.put)
}

fn delete_statement(
&mut self,
&'_ mut self,
db: *mut sqlite::sqlite3,
) -> Result<&PreparedPendingStatement, PowerSyncError> {
) -> Result<&'_ PreparedPendingStatement<'_>, PowerSyncError> {
Self::prepare_lazily(db, &mut self.cached_delete, &self.definition.delete)
}
}
Expand Down
Loading