Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: init workspace & delete history #548

Merged
merged 7 commits into from
Oct 17, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,25 @@ import java.io.File
import java.util.*
import com.toeverything.jwst.Workspace
import kotlin.jvm.optionals.getOrNull
import kotlin.random.Random

fun <T> Optional<T>.unwrap(): T? = orElse(null)

fun String.hexStringToByteArray(): ByteArray {
return this.chunked(2)
.map { it.toInt(16).toByte() }
.toByteArray()
}

fun getStaticWorkspace(): String {
return "010895E2C0E01D0027010A73706163653A6D6574610570616765730027010C73706163653A626C6F636B73047465737401280095E2C0E01D010B7379733A666C61766F757201770474657374270095E2C0E01D010C7379733A6368696C6472656E00280095E2C0E01D010B7379733A63726561746564017B4278B38B757B900028010D73706163653A757064617465640474657374017B4278B38B757B9000280095E2C0E01D010970726F703A74657374017703616263A895E2C0E01D05017B4278B38B757B90000195E2C0E01D010501"
}

fun getRandomId(): String {
val chars = "abcdefghijklmnopqrstuvwxyz0123456789"
return (1..8).map { chars[Random.nextInt(chars.length)] }.joinToString("")
}

class MainActivity : AppCompatActivity() {

@RequiresApi(Build.VERSION_CODES.TIRAMISU)
Expand All @@ -24,6 +40,10 @@ class MainActivity : AppCompatActivity() {
val database = File(filesDir, "jwst.db")
val storage = Storage(database.absolutePath, "ws://10.0.2.2:3000/collaboration", "debug")

storage.initWorkspace(getRandomId(), getStaticWorkspace().hexStringToByteArray())
val text = storage.getWorkspace("test1").get().get("test").get().get("test").get()
Log.i("jwst", "text: $text")

storage.getWorkspace("test").unwrap()?.let { workspace ->
setupWorkspace(workspace)

Expand Down Expand Up @@ -60,7 +80,6 @@ class MainActivity : AppCompatActivity() {
Log.i("jwst", searchResult3)

while (true) {

Log.i("jwst", " getting root")
workspace.get("root").unwrap()?.let { block ->
block.get("test").ifPresent { value ->
Expand Down
4 changes: 2 additions & 2 deletions apps/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '8.1.0' apply false
id 'com.android.library' version '8.1.0' apply false
id 'com.android.application' version '8.1.2' apply false
id 'com.android.library' version '8.1.2' apply false
id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
}
18 changes: 12 additions & 6 deletions apps/swift/OctoBaseSwift/RustXcframework.xcframework/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,24 @@
<key>AvailableLibraries</key>
<array>
<dict>
<key>BinaryPath</key>
<string>liboctobase.a</string>
<key>HeadersPath</key>
<string>Headers</string>
<key>LibraryIdentifier</key>
<string>ios-arm64-simulator</string>
<string>macos-arm64</string>
<key>LibraryPath</key>
<string>liboctobase.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
<string>macos</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>liboctobase.a</string>
<key>HeadersPath</key>
<string>Headers</string>
<key>LibraryIdentifier</key>
Expand All @@ -35,18 +37,22 @@
<string>ios</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>liboctobase.a</string>
<key>HeadersPath</key>
<string>Headers</string>
<key>LibraryIdentifier</key>
<string>macos-arm64</string>
<string>ios-arm64-simulator</string>
<key>LibraryPath</key>
<string>liboctobase.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>macos</string>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ bool __swift_bridge__$Storage$is_connected(void* self);
bool __swift_bridge__$Storage$is_finished(void* self);
bool __swift_bridge__$Storage$is_error(void* self);
void* __swift_bridge__$Storage$get_sync_state(void* self);
bool __swift_bridge__$Storage$init(void* self, void* workspace_id, void* data);
void* __swift_bridge__$Storage$export(void* self, void* workspace_id);
void* __swift_bridge__$Storage$connect(void* self, void* workspace_id, void* remote);
void* __swift_bridge__$Storage$get_last_synced(void* self);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ bool __swift_bridge__$Storage$is_connected(void* self);
bool __swift_bridge__$Storage$is_finished(void* self);
bool __swift_bridge__$Storage$is_error(void* self);
void* __swift_bridge__$Storage$get_sync_state(void* self);
bool __swift_bridge__$Storage$init(void* self, void* workspace_id, void* data);
void* __swift_bridge__$Storage$export(void* self, void* workspace_id);
void* __swift_bridge__$Storage$connect(void* self, void* workspace_id, void* remote);
void* __swift_bridge__$Storage$get_last_synced(void* self);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ bool __swift_bridge__$Storage$is_connected(void* self);
bool __swift_bridge__$Storage$is_finished(void* self);
bool __swift_bridge__$Storage$is_error(void* self);
void* __swift_bridge__$Storage$get_sync_state(void* self);
bool __swift_bridge__$Storage$init(void* self, void* workspace_id, void* data);
void* __swift_bridge__$Storage$export(void* self, void* workspace_id);
void* __swift_bridge__$Storage$connect(void* self, void* workspace_id, void* remote);
void* __swift_bridge__$Storage$get_last_synced(void* self);

Expand Down
8 changes: 8 additions & 0 deletions apps/swift/OctoBaseSwift/Sources/OctoBase/jwst-swift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,14 @@ public class StorageRefMut: StorageRef {
}
}
extension StorageRefMut {
public func init<GenericIntoRustString: IntoRustString>(_ workspace_id: GenericIntoRustString, _ data: RustVec<UInt8>) -> Bool {
__swift_bridge__$Storage$init(ptr, { let rustString = workspace_id.intoRustString(); rustString.isOwned = false; return rustString.ptr }(), { let val = data; val.isOwned = false; return val.ptr }())
}

public func export<GenericIntoRustString: IntoRustString>(_ workspace_id: GenericIntoRustString) -> Optional<RustVec<UInt8>> {
{ let val = __swift_bridge__$Storage$export(ptr, { let rustString = workspace_id.intoRustString(); rustString.isOwned = false; return rustString.ptr }()); if val != nil { return RustVec(ptr: val!) } else { return nil } }()
}

public func connect<GenericIntoRustString: IntoRustString>(_ workspace_id: GenericIntoRustString, _ remote: GenericIntoRustString) -> Optional<Workspace> {
{ let val = __swift_bridge__$Storage$connect(ptr, { let rustString = workspace_id.intoRustString(); rustString.isOwned = false; return rustString.ptr }(), { let rustString = remote.intoRustString(); rustString.isOwned = false; return rustString.ptr }()); if val != nil { return Workspace(ptr: val!) } else { return nil } }()
}
Expand Down
2 changes: 1 addition & 1 deletion libs/jwst-binding/jwst-jni/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ publishing {
release(MavenPublication) {
groupId = 'com.toeverything'
artifactId = 'octobase'
version = '0.2.6'
version = '0.2.7'

afterEvaluate {
from components.release
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,26 @@ class Storage constructor(path: String, private val remote: String = "", private

val error get() = this.storage.error()

fun initWorkspace(id: String, data: ByteArray): Result<Unit> {
val success = this.storage.init(id,data)
return if (success) {
Result.success(Unit)
} else {
val error = this.storage.error().orElse("Unknown error")
Result.failure(Exception(error))
}
}

fun exportWorkspace(id: String): Result<ByteArray> {
val data = this.storage.export(id)
return if (data.isNotEmpty()) {
Result.success(data)
} else {
val error = this.storage.error().orElse("Unknown error")
Result.failure(Exception(error))
}
}

fun getWorkspace(id: String): Optional<Workspace> {
return this.storage.connect(id, this.remote.takeIf { it.isNotEmpty() }?.let { "$it/$id" } ?: "").map { Workspace(it) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ public final boolean is_error() {
}
private static native @NonNull String do_get_sync_state(long self);

public final boolean init(@NonNull String workspace_id, @NonNull byte [] data) {
boolean ret = do_init(mNativeObj, workspace_id, data);

return ret;
}
private static native boolean do_init(long self, @NonNull String workspace_id, byte [] data);

public final byte [] export(@NonNull String workspace_id) {
byte [] ret = do_export(mNativeObj, workspace_id);

return ret;
}
private static native byte [] do_export(long self, @NonNull String workspace_id);

public final @NonNull java.util.Optional<Workspace> connect(@NonNull String workspace_id, @NonNull String remote) {
long ret = do_connect(mNativeObj, workspace_id, remote);
java.util.Optional<Workspace> convRet;
Expand Down
31 changes: 30 additions & 1 deletion libs/jwst-binding/jwst-jni/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,32 @@ fn main() {
.chain(["use jni_sys::*;"].iter())
.chain(
[
r#"foreign_typemap!(
($p:r_type) Vec<u8> => jbyteArray {
let slice = &($p)[..];
let slice = unsafe { std::mem::transmute::<&[u8], &[i8]>(slice) };
let raw = JavaByteArray::from_slice_to_raw(slice, env);
$out = raw;
};
($p:f_type) => "jbyteArray";
);

foreign_typemap!(
($p:r_type) Vec<u8> => jbyteArray {
let slice = &($p)[..];
let slice = unsafe { std::mem::transmute::<&[u8], &[i8]>(slice) };
let raw = JavaByteArray::from_slice_to_raw(slice, env);
$out = raw;
};
($p:f_type) => "jbyteArray";
($p:r_type) &'a [u8] <= jbyteArray {
let arr = JavaByteArray::new(env, $p);
let slice = arr.to_slice();
let slice = unsafe { std::mem::transmute::<&[i8], &[u8]>(slice) };
$out = slice;
};
($p:f_type) <= "jbyteArray";
);"#,
r#"foreign_class!(
class JwstStorage {
self_type JwstStorage;
Expand All @@ -30,6 +56,8 @@ fn main() {
fn JwstStorage::is_finished(&self) -> bool;
fn JwstStorage::is_error(&self) -> bool;
fn JwstStorage::get_sync_state(&self) -> String;
fn JwstStorage::init(&mut self, workspace_id: String, data: &[u8]) -> bool; alias init;
fn JwstStorage::export(&mut self, workspace_id: String) -> Vec<u8>; alias export;
fn JwstStorage::connect(&mut self, workspace_id: String, remote: String) -> Option<Workspace>; alias connect;
fn JwstStorage::get_last_synced(&self) ->Vec<i64>;
}
Expand Down Expand Up @@ -82,7 +110,7 @@ foreign_class!(
.join("\n");
fs::write(&in_temp, &template).unwrap();

let template_changed = fs::read_to_string(in_src).unwrap() != template;
let template_changed = fs::read_to_string(&in_src).unwrap() != template;

if template_changed || !in_temp.with_extension("").exists() || !jni_dir.exists() {
// delete the lib folder then create it again to prevent obsolete files
Expand All @@ -104,6 +132,7 @@ foreign_class!(
!= fs::read_to_string(in_temp.with_extension("")).unwrap()
{
fs::copy(in_temp.with_extension("out"), in_temp.with_extension("")).unwrap();
fs::copy(in_temp.with_extension("out"), in_src).unwrap();
}
}
}
28 changes: 28 additions & 0 deletions libs/jwst-binding/jwst-jni/src/java_glue.rs.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,32 @@
use crate::*;

use jni_sys::*;
foreign_typemap!(
($p:r_type) Vec<u8> => jbyteArray {
let slice = &($p)[..];
let slice = unsafe { std::mem::transmute::<&[u8], &[i8]>(slice) };
let raw = JavaByteArray::from_slice_to_raw(slice, env);
$out = raw;
};
($p:f_type) => "jbyteArray";
);

foreign_typemap!(
($p:r_type) Vec<u8> => jbyteArray {
let slice = &($p)[..];
let slice = unsafe { std::mem::transmute::<&[u8], &[i8]>(slice) };
let raw = JavaByteArray::from_slice_to_raw(slice, env);
$out = raw;
};
($p:f_type) => "jbyteArray";
($p:r_type) &'a [u8] <= jbyteArray {
let arr = JavaByteArray::new(env, $p);
let slice = arr.to_slice();
let slice = unsafe { std::mem::transmute::<&[i8], &[u8]>(slice) };
$out = slice;
};
($p:f_type) <= "jbyteArray";
);
foreign_class!(
class JwstStorage {
self_type JwstStorage;
Expand All @@ -13,6 +39,8 @@ foreign_class!(
fn JwstStorage::is_finished(&self) -> bool;
fn JwstStorage::is_error(&self) -> bool;
fn JwstStorage::get_sync_state(&self) -> String;
fn JwstStorage::init(&mut self, workspace_id: String, data: &[u8]) -> bool; alias init;
fn JwstStorage::export(&mut self, workspace_id: String) -> Vec<u8>; alias export;
fn JwstStorage::connect(&mut self, workspace_id: String, remote: String) -> Option<Workspace>; alias connect;
fn JwstStorage::get_last_synced(&self) ->Vec<i64>;
}
Expand Down
48 changes: 48 additions & 0 deletions libs/jwst-binding/jwst-jni/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,54 @@ impl JwstStorage {
}
}

pub fn init(&mut self, workspace_id: String, data: &[u8]) -> bool {
match self.init_workspace(workspace_id, data) {
Ok(_) => true,
Err(e) => {
let error = format!("Failed to init workspace: {:?}", e);
error!("{}", error);
self.error = Some(error);
false
}
}
}

fn init_workspace(&self, workspace_id: String, data: &[u8]) -> JwstStorageResult {
let rt = Arc::new(
Builder::new_multi_thread()
.worker_threads(1)
.enable_all()
.thread_name("jwst-jni-init")
.build()
.map_err(JwstStorageError::SyncThread)?,
);
rt.block_on(self.storage.init_workspace(workspace_id, data.to_vec()))
}

pub fn export(&mut self, workspace_id: String) -> Vec<u8> {
match self.export_workspace(workspace_id) {
Ok(data) => data,
Err(e) => {
let error = format!("Failed to export workspace: {:?}", e);
error!("{}", error);
self.error = Some(error);
vec![]
}
}
}

fn export_workspace(&self, workspace_id: String) -> JwstStorageResult<Vec<u8>> {
let rt = Arc::new(
Builder::new_multi_thread()
.worker_threads(1)
.enable_all()
.thread_name("jwst-jni-export")
.build()
.map_err(JwstStorageError::SyncThread)?,
);
rt.block_on(self.storage.export_workspace(workspace_id))
}

pub fn connect(&mut self, workspace_id: String, remote: String) -> Option<Workspace> {
match self.sync(workspace_id, remote) {
Ok(workspace) => Some(workspace),
Expand Down
4 changes: 4 additions & 0 deletions libs/jwst-binding/jwst-swift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ mod ffi {

fn get_sync_state(self: &Storage) -> String;

fn init(self: &mut Storage, workspace_id: String, data: Vec<u8>) -> bool;

fn export(self: &mut Storage, workspace_id: String) -> Option<Vec<u8>>;

fn connect(self: &mut Storage, workspace_id: String, remote: String) -> Option<Workspace>;

fn get_last_synced(self: &Storage) -> Vec<i64>;
Expand Down
Loading