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
91 changes: 62 additions & 29 deletions src/back_end/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/back_end/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ panic = "abort"

[dependencies]
dirs = "6.0.0"
rusqlite = { version = "0.37.0", features = ["bundled"] }
serde = { version = "1.0.219", features = ["derive"] }
sqlite = "0.37.0"
toml = "0.9.5"
webbrowser = "1.0.5"
118 changes: 118 additions & 0 deletions src/back_end/src/core/sqlite.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use rusqlite::Connection;
use std::ffi::{CStr, c_char};

#[derive(PartialEq, Eq, Debug)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum QueryResult {
OK,
OPEN_DATABASE_ERR,
C_STR_CONVERT_ERR,
EXECUTE_SQL_ERR,
}

const INIT_QUERY: &str = r"--sql
CREATE TABLE IF NOT EXISTS clipboard_cache (
id INTEGER PRIMARY KEY AUTOINCREMENT,
content_hash TEXT NOT NULL UNIQUE,
time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
content TEXT NOT NULL,
content_type TEXT NOT NULL,
is_pinned BOOLEAN NOT NULL DEFAULT FALSE
);
";

#[unsafe(no_mangle)]
/// # Safety
/// Careful with unsafe context & raw pointers.
pub unsafe extern "C" fn raw_init_clipboard_cache(
file_path: *const c_char,
) -> QueryResult {
unsafe {
use QueryResult as R;

let Ok(file_path_cstr) = CStr::from_ptr(file_path).to_str() else {
return R::C_STR_CONVERT_ERR;
};

let Ok(sql) = Connection::open(file_path_cstr) else {
return R::OPEN_DATABASE_ERR;
};

let is_err = sql.execute(INIT_QUERY, ()).is_err();

if is_err {
return R::EXECUTE_SQL_ERR;
}

R::OK
}
}

#[repr(C)]
pub struct TextClipboard {
pub content: *const c_char,
pub content_hash: *const c_char,
pub content_type: *const c_char,
pub is_pinned: bool,
}

/// # Safety
/// Careful with raw pointers & memory leaks.
#[must_use]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn raw_add_text_clipboard(
db_path: *const c_char,
text_clipboard: TextClipboard,
) -> QueryResult {
use QueryResult as R;

unsafe {
let Ok(file_path_cstr) = CStr::from_ptr(db_path).to_str() else {
return R::C_STR_CONVERT_ERR;
};

let Ok(sql) = Connection::open(file_path_cstr) else {
return R::OPEN_DATABASE_ERR;
};

let Ok(content_str) = CStr::from_ptr(text_clipboard.content).to_str()
else {
return R::C_STR_CONVERT_ERR;
};

let Ok(content_hash_str) =
CStr::from_ptr(text_clipboard.content_hash).to_str()
else {
return R::C_STR_CONVERT_ERR;
};

let Ok(content_type_str) =
CStr::from_ptr(text_clipboard.content_type).to_str()
else {
return R::C_STR_CONVERT_ERR;
};

let query = r"
INSERT INTO clipboard_cache (content, content_hash, content_type, is_pinned)
VALUES (?, ?, ?, ?)
";

let binds = (
content_str,
content_hash_str,
content_type_str,
text_clipboard.is_pinned,
);
let is_err = sql.execute(query, binds).is_err();

/* For panic testing only. Don't remove it. */
/* sql.execute(query, binds).unwrap(); */

if is_err {
return R::EXECUTE_SQL_ERR;
}

R::OK
}
}
3 changes: 3 additions & 0 deletions src/back_end/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ pub mod utils {
pub mod browser;
pub mod fs_utils;
pub mod memory;
}

pub mod core {
pub mod sqlite;
}

Expand Down
48 changes: 0 additions & 48 deletions src/back_end/src/utils/sqlite.rs

This file was deleted.

41 changes: 41 additions & 0 deletions src/back_end/tests/sqlite.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#[test]
fn test_add_text_clipboard() {
use back_end::core::sqlite::{
QueryResult, TextClipboard, raw_add_text_clipboard,
raw_init_clipboard_cache,
};
use std::ffi::CString;
use std::fs;

use QueryResult as R;
use TextClipboard as T;

let content = CString::new("my clipboard content").unwrap();
let content_hash = CString::new("my hash abc xyz ").unwrap();
let content_type = CString::new("text").unwrap();
let db_path = CString::new("test.db").unwrap();

let _ = fs::remove_file(db_path.to_str().unwrap());

let text_clipboard = T {
content: content.as_ptr(),
content_hash: content_hash.as_ptr(),
content_type: content_type.as_ptr(),
is_pinned: false,
};

unsafe {
let init_result = raw_init_clipboard_cache(db_path.as_ptr());
let result = raw_add_text_clipboard(db_path.as_ptr(), text_clipboard);

assert_ne!(init_result, R::C_STR_CONVERT_ERR);
assert_ne!(init_result, R::EXECUTE_SQL_ERR);
assert_ne!(init_result, R::OPEN_DATABASE_ERR);
assert_eq!(init_result, R::OK);

assert_ne!(result, R::C_STR_CONVERT_ERR);
assert_ne!(result, R::EXECUTE_SQL_ERR);
assert_ne!(result, R::OPEN_DATABASE_ERR);
assert_eq!(result, R::OK);
}
}
2 changes: 1 addition & 1 deletion src/ffi/namespace/include/sqlite.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "../../raw/sqlite.hxx"

namespace Lazyboard::ffi {
inline auto init_clipboard_cache(const char *path) -> InitDatabaseStatus {
inline auto init_clipboard_cache(const char *path) -> QueryResult {
auto status = raw_init_clipboard_cache(path);

return status;
Expand Down
10 changes: 5 additions & 5 deletions src/ffi/raw/sqlite.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ extern "C" {
#include <cstdint>
using std::uint8_t;

enum class InitDatabaseStatus : uint8_t {
enum class QueryResult : uint8_t {
OK,
CREATE_DATABASE_FAILED,
C_STR_CONVERT_FAILED,
EXECUTE_SQL_FAILED
OPEN_DATABASE_ERR,
C_STR_CONVERT_ERR,
EXECUTE_SQL_ERR
};

auto raw_init_clipboard_cache(const char *path) -> InitDatabaseStatus;
auto raw_init_clipboard_cache(const char *path) -> QueryResult;

#if defined(__cplusplus)
}
Expand Down
Loading