diff --git a/complex objects/cargo/Cargo.lock b/complex objects/cargo/Cargo.lock index 45de625..b46e64a 100644 --- a/complex objects/cargo/Cargo.lock +++ b/complex objects/cargo/Cargo.lock @@ -5,7 +5,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "0.7.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -25,7 +25,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "combine" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -37,6 +37,10 @@ name = "error-chain" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ffi-utils" +version = "0.1.0" + [[package]] name = "fuchsia-zircon" version = "0.2.1" @@ -50,7 +54,7 @@ name = "fuchsia-zircon-sys" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -58,24 +62,13 @@ name = "gcc" version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "greetings" -version = "0.1.1" -dependencies = [ - "jni 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "rusqlite 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "jni" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "combine 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "combine 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "jni-sys 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -97,7 +90,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -115,11 +108,36 @@ name = "linked-hash-map" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "list" +version = "0.1.0" +dependencies = [ + "ffi-utils 0.1.0", + "jni 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rusqlite 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "store 0.1.0", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "log" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "logins" +version = "0.1.0" +dependencies = [ + "ffi-utils 0.1.0", + "jni 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rusqlite 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "store 0.1.0", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lru-cache" version = "0.1.1" @@ -139,7 +157,7 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -158,17 +176,36 @@ dependencies = [ "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "store" +version = "0.1.0" +dependencies = [ + "ffi-utils 0.1.0", + "jni 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rusqlite 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "time" version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "toodle" +version = "0.1.0" +dependencies = [ + "ffi-utils 0.1.0", + "list 0.1.0", + "logins 0.1.0", + "store 0.1.0", +] + [[package]] name = "uuid" version = "0.4.0" @@ -194,19 +231,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" -"checksum bitflags 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab1c7dc97f39523ffa63f3096291612e630cf3ed75aa6b9fad436bac4c700274" +"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" "checksum cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" -"checksum combine 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c279781ad7b9b480fe265770ea5cb87fcbdc8ea1b2b6930d60a206e781dc6c" +"checksum combine 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1645a65a99c7c8d345761f4b75a6ffe5be3b3b27a93ee731fccc5050ba6be97c" "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" "checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159" "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" -"checksum jni 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "914c602e3a81f89761661fca05eb0e1f1834985aeae4074394e030c4181cfa07" +"checksum jni 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cffc930ce6a38a4013e30567b559bdc79f601013ba4a81e65dbda9207263efd4" "checksum jni-sys 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "de0aaaba8809ab8d83a53fe2b313b996b79e8632b855eae9f70ad4323dca91b8" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "56cce3130fd040c28df6f495c8492e5ec5808fb4c9093c310df02b0c8f030148" +"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" "checksum libsqlite3-sys 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "370090ad578ba845a3ad4f383ceb3deba7abd51ab1915ad1f2c982cc6035e31c" "checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" diff --git a/complex objects/cargo/Cargo.toml b/complex objects/cargo/Cargo.toml index 86729a2..2986df2 100644 --- a/complex objects/cargo/Cargo.toml +++ b/complex objects/cargo/Cargo.toml @@ -1,23 +1,21 @@ [package] -name = "greetings" -version = "0.1.1" -authors = ["fluffyemily "] -description = "Example static library project built for iOS" -publish = false - -[target.'cfg(target_os="android")'.dependencies] -jni = { version = "0.5", default-features = false } +name = "toodle" +version = "0.1.0" +authors = ["Emily Toop "] +description = "Cross Platform Library for providing To Do List data" [lib] -name = "greetings" +name = "toodle" crate-type = ["staticlib", "cdylib"] -[dependencies] -time = "0.1.38" -uuid = { version = "0.4", features = ["v4"] } -libc = "0.2.32" +[dependencies.ffi-utils] +path = "ffi-utils" + +[dependencies.store] +path = "store" + +[dependencies.logins] +path = "logins" -[dependencies.rusqlite] -version = "0.12" -# System sqlite might be very old. -features = ["bundled", "limits"] +[dependencies.list] +path = "list" diff --git a/complex objects/cargo/ffi-utils/Cargo.toml b/complex objects/cargo/ffi-utils/Cargo.toml new file mode 100644 index 0000000..6ed4ef4 --- /dev/null +++ b/complex objects/cargo/ffi-utils/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "ffi-utils" +version = "0.1.0" +authors = ["Emily Toop "] + +[dependencies] diff --git a/complex objects/cargo/ffi-utils/src/lib.rs b/complex objects/cargo/ffi-utils/src/lib.rs new file mode 100644 index 0000000..00dc579 --- /dev/null +++ b/complex objects/cargo/ffi-utils/src/lib.rs @@ -0,0 +1,30 @@ +// Copyright 2016 Mozilla +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use +// this file except in compliance with the License. You may obtain a copy of the +// License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +pub mod strings { + use std::os::raw::c_char; + use std::ffi::{ + CString, + CStr + }; + + pub fn c_char_to_string(cchar: *const c_char) -> String { + let c_str = unsafe { CStr::from_ptr(cchar) }; + let r_str = match c_str.to_str() { + Err(_) => "", + Ok(string) => string, + }; + r_str.to_string() + } + + pub fn string_to_c_char(r_string: String) -> *mut c_char { + CString::new(r_string).unwrap().into_raw() + } +} diff --git a/complex objects/cargo/list/Cargo.toml b/complex objects/cargo/list/Cargo.toml new file mode 100644 index 0000000..6e9cc81 --- /dev/null +++ b/complex objects/cargo/list/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "list" +version = "0.1.0" +authors = ["Emily Toop "] + +[target.'cfg(target_os="android")'.dependencies] +jni = { version = "0.5", default-features = false } + +[dependencies] +time = "0.1.38" +uuid = { version = "0.4", features = ["v4"] } +libc = "0.2.32" + +[dependencies.store] +path = "../store" + +[dependencies.ffi-utils] +path = "../ffi-utils" + +[dependencies.rusqlite] +version = "0.12" +# System sqlite might be very old. +features = ["bundled", "limits"] diff --git a/complex objects/cargo/src/categories.h b/complex objects/cargo/list/categories.h similarity index 68% rename from complex objects/cargo/src/categories.h rename to complex objects/cargo/list/categories.h index 2b4bcbc..8259724 100644 --- a/complex objects/cargo/src/categories.h +++ b/complex objects/cargo/list/categories.h @@ -3,20 +3,20 @@ #import "items.h" -struct category_manager; +struct list_manager; struct category; struct item; -const struct category** get_all_categories(const struct category_manager* manager); -const void category_manager_create_item(const struct category_manager* manager, const struct item *item, size_t category_id); -const void category_manager_update_item(const struct category_manager* manager, const struct item *item); +const struct category** get_all_categories(const struct list_manager* manager); +const void category_manager_create_item(const struct list_manager* manager, const struct item *item, size_t category_id); +const void category_manager_update_item(const struct list_manager* manager, const struct item *item); const size_t category_list_count(const struct category** list); const void category_list_destroy(const struct category** list); const struct category* category_list_item_at(const struct category** list, size_t index); const void add_category(const struct category** list, const struct category* category); -struct category* category_new(const struct category_manager* manager, const char* name); +struct category* category_new(const struct list_manager* manager, const char* name); const void category_destroy(const struct category* category); const size_t category_get_id(const struct category* category); const char* category_get_name(const struct category* category); diff --git a/complex objects/cargo/src/items.h b/complex objects/cargo/list/items.h similarity index 100% rename from complex objects/cargo/src/items.h rename to complex objects/cargo/list/items.h diff --git a/complex objects/cargo/list/src/categories.rs b/complex objects/cargo/list/src/categories.rs new file mode 100644 index 0000000..ccd61d0 --- /dev/null +++ b/complex objects/cargo/list/src/categories.rs @@ -0,0 +1,102 @@ +// Copyright 2016 Mozilla +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use +// this file except in compliance with the License. You may obtain a copy of the +// License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +use libc::size_t; +use std::os::raw::{ + c_char, + c_int +}; + +use ffi_utils::strings::string_to_c_char; +use items::Item; + +#[derive(Debug, Clone)] +pub struct Category { + pub id: isize, + pub name: String, + pub items: Vec +} + +impl Drop for Category { + fn drop(&mut self) { + println!("{:?} is being deallocated", self); + } +} + +#[no_mangle] +pub unsafe extern "C" fn category_destroy(category: *mut Category) { + let _ = Box::from_raw(category); +} + +#[no_mangle] +pub unsafe extern "C" fn category_get_id(category: *const Category) -> c_int { + let category = &*category; + category.id as c_int +} + +#[no_mangle] +pub unsafe extern "C" fn category_get_name(category: *const Category) -> *mut c_char { + let category = &*category; + string_to_c_char(category.name.clone()) +} + +#[no_mangle] +pub unsafe extern "C" fn category_get_items(category: *const Category) -> *mut Vec { + let category = &*category; + let boxed_items = Box::new(category.items.clone()); + Box::into_raw(boxed_items) +} + +#[no_mangle] +pub unsafe extern "C" fn category_items_count(category: *const Category) -> c_int { + let category = &*category; + category.items.len() as c_int +} + +#[no_mangle] +pub unsafe extern "C" fn category_item_at(item_list: *const Vec, index: size_t) -> *const Item { + let item_list = &*item_list; + let index = index as usize; + let item = Box::new(item_list[index].clone()); + Box::into_raw(item) +} + +#[no_mangle] +pub unsafe extern "C" fn category_list_destroy(category_list: *mut Vec) { + let _ = Box::from_raw(category_list); +} + +#[no_mangle] +pub unsafe extern "C" fn category_list_count(category_list: *const Vec) -> c_int { + let category_list = &*category_list; + category_list.len() as c_int +} + +#[no_mangle] +pub unsafe extern "C" fn category_list_item_at(category_list: *const Vec, index: size_t) -> *const Category { + let category_list = &*category_list; + let index = index as usize; + let category = Box::new(category_list[index].clone()); + Box::into_raw(category) +} + +#[no_mangle] +pub unsafe extern "C" fn add_category(category_list: *mut Vec, category: *const Category) { + let category_list = &mut*category_list; + let category = &*category; + category_list.push((*category).clone()) +} + +#[no_mangle] +pub unsafe extern "C" fn category_add_item(category: *mut Category, item: *const Item) { + let category = &mut*category; + let item = &*item; + category.items.push((*item).clone()); +} diff --git a/complex objects/cargo/src/items.rs b/complex objects/cargo/list/src/items.rs similarity index 99% rename from complex objects/cargo/src/items.rs rename to complex objects/cargo/list/src/items.rs index 782a90e..bdc74e0 100644 --- a/complex objects/cargo/src/items.rs +++ b/complex objects/cargo/list/src/items.rs @@ -18,7 +18,7 @@ use std::ptr; use time::Timespec; use time::now; -use utils::{ +use ffi_utils::strings::{ string_to_c_char, c_char_to_string, }; diff --git a/complex objects/cargo/list/src/lib.rs b/complex objects/cargo/list/src/lib.rs new file mode 100644 index 0000000..3e08128 --- /dev/null +++ b/complex objects/cargo/list/src/lib.rs @@ -0,0 +1,230 @@ +// Copyright 2016 Mozilla +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use +// this file except in compliance with the License. You may obtain a copy of the +// License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +extern crate libc; +extern crate rusqlite; +extern crate time; +extern crate uuid; +extern crate store; +extern crate ffi_utils; + +use std::os::raw::{ + c_char, + c_int +}; +use std::sync::{ + Arc, +}; + +pub mod categories; +pub mod items; + +use categories::Category; +use ffi_utils::strings::c_char_to_string; +use items::Item; +use store::Store; + + +#[derive(Debug)] +#[repr(C)] +pub struct ListManager { + store: Arc, +} + +impl ListManager { + pub fn new(store: Arc) -> ListManager { + let manager = ListManager { + store: store, + }; + manager.create_categories_table(); + manager.create_items_table(); + manager + } + + pub fn create_categories_table(&self) { + let sql = r#"CREATE TABLE IF NOT EXISTS categories ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL + )"#; + let db = self.store.write_connection(); + match db.execute(sql, &[]).unwrap() { + 1 => { + self.create_category("To Do".to_string()); + }, + _ => {} + }; + } + + pub fn create_category(&self, name: String) -> Option { + let sql = r#"INSERT INTO categories (name) VALUES (?)"#; + let db = self.store.write_connection(); + db.execute(sql, &[&name]).unwrap(); + self.fetch_category(&name) + } + + pub fn fetch_category(&self, name: &String) -> Option { + let sql = r#"SELECT id, name FROM categories WHERE name=?"#; + + let conn = self.store.read_connection(); + let mut stmt = conn.prepare(sql).unwrap(); + let mut category_iter = stmt.query_map(&[name], |row| { + Category { + id: row.get(0), + name: row.get(1), + items: Vec::new() + } + }).unwrap(); + + if let Some(result) = category_iter.next() { + if let Some(mut category) = result.ok() { + category.items = self.fetch_items_for_category(&category); + Some(category) + } else { + None + } + } else { + println!("No category found"); + None + } + } + + pub fn fetch_categories(&self) -> Vec { + let sql = r#"SELECT id, name + FROM categories"#; + let conn = self.store.read_connection(); + let mut stmt = conn.prepare(sql).unwrap(); + let mut category_iter = stmt.query_map(&[], |row| { + Category { + id: row.get(0), + name: row.get(1), + items: Vec::new() + } + }).unwrap(); + + let mut category_list: Vec = Vec::new(); + while let Some(result) = category_iter.next() { + if let Some(mut category) = result.ok() { + category.items = self.fetch_items_for_category(&category); + category_list.push(category); + } + } + category_list + } + + pub fn create_items_table(&self) { + let sql = r#"CREATE TABLE IF NOT EXISTS items ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + description TEXT NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + due_date DATETIME, + is_complete TINYINT DEFAULT 0, + category REFERENCES categories(id) + )"#; + let db = self.store.write_connection(); + db.execute(sql, &[]).unwrap(); + } + + pub fn fetch_items_for_category(&self, category: &Category) -> Vec { + let sql = r#"SELECT id, description, created_at, due_date, is_complete + FROM items + WHERE category=?"#; + let conn = self.store.read_connection(); + let mut stmt = conn.prepare(sql).unwrap(); + let mut item_iter = stmt.query_map(&[&category.id], |row| { + let complete: i64 = row.get(4); + Item { + id: row.get(0), + description: row.get(1), + created_at: row.get(2), + due_date: row.get(3), + is_complete: complete != 0 + } + }).unwrap(); + + let mut item_list: Vec = Vec::new(); + while let Some(result) = item_iter.next() { + if let Some(i) = result.ok() { + item_list.push(i); + } + } + item_list + } + + pub fn create_item(&self, item: &Item, category_id: i64) -> Option { + println!("Creating item {:?} in category {:?}", item, category_id); + let sql = r#"INSERT INTO items (description, created_at, due_date, is_complete, category) VALUES (?, ?, ?, ?, ?)"#; + let conn = self.store.write_connection(); + let mut stmt = conn.prepare(sql).unwrap(); + match stmt.insert(&[&item.description, &item.created_at, &item.due_date, &item.is_complete, &category_id]) { + Ok(row_id) => { + let fetch_sql = r#"SELECT id, description, created_at, due_date, is_complete FROM items WHERE rowid=?"#; + stmt = conn.prepare(fetch_sql).unwrap(); + let mut item_iter = stmt.query_map(&[&row_id], |row| { + let complete: i64 = row.get(4); + Item { + id: row.get(0), + description: row.get(1), + created_at: row.get(2), + due_date: row.get(3), + is_complete: complete != 0 + } + }).unwrap(); + + if let Some(result) = item_iter.next() { + result.ok() + } else { + println!("No item found"); + None + } + }, + Err(e) => { + println!("Failed to create item {:?}", e); + None + } + } + } + + pub fn update_item(&self, item: &Item) { + let sql = r#"UPDATE items SET description=?, due_date=?, is_complete=? WHERE id=?"#; + let conn = self.store.write_connection(); + let _ = conn.execute(sql, &[&item.description, &item.due_date, &item.is_complete, &item.id]); + } +} + + +#[no_mangle] +pub unsafe extern "C" fn get_all_categories(manager: *const Arc) -> *mut Vec { + let manager = &*manager; + let category_list = Box::new(manager.fetch_categories()); + Box::into_raw(category_list) +} + +#[no_mangle] +pub unsafe extern "C" fn category_manager_create_item(manager: *const Arc, item: *const Item, category_id: c_int) { + let manager = &*manager; + let item = &*item; + let cat_id = category_id as i64; + manager.create_item(item, cat_id); +} + +#[no_mangle] +pub unsafe extern "C" fn category_manager_update_item(manager: *const Arc, item: *const Item) { + let manager = &*manager; + let item = &*item; + manager.update_item(item) +} + +#[no_mangle] +pub unsafe extern "C" fn category_new(manager: *const Arc, name: *const c_char) -> *mut Category { + let manager = &*manager; + let name = c_char_to_string(name); + let category = Box::new(manager.create_category(name).unwrap()); + Box::into_raw(category) +} diff --git a/complex objects/cargo/logins/Cargo.toml b/complex objects/cargo/logins/Cargo.toml new file mode 100644 index 0000000..ec97446 --- /dev/null +++ b/complex objects/cargo/logins/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "logins" +version = "0.1.0" +authors = ["Emily Toop "] + +[target.'cfg(target_os="android")'.dependencies] +jni = { version = "0.5", default-features = false } + +[dependencies] +time = "0.1.38" +uuid = { version = "0.4", features = ["v4"] } + +[dependencies.store] +path = "../store" + +[dependencies.ffi-utils] +path = "../ffi-utils" + +[dependencies.rusqlite] +version = "0.12" +# System sqlite might be very old. +features = ["bundled", "limits"] diff --git a/complex objects/cargo/src/logins.h b/complex objects/cargo/logins/logins.h similarity index 99% rename from complex objects/cargo/src/logins.h rename to complex objects/cargo/logins/logins.h index 7666777..3e8dcca 100644 --- a/complex objects/cargo/src/logins.h +++ b/complex objects/cargo/logins/logins.h @@ -12,8 +12,6 @@ typedef enum { Invalid = 3, } LoginStatus; - - struct login; struct login_manager; @@ -23,7 +21,6 @@ struct login* create_login(const struct login_manager* manager, const char* user const LoginStatus validate_login(const struct login_manager* manager, const char* username, const char* password); // Accessors for Login properties -const LoginStatus login_is_valid(const struct login* data); const size_t login_get_id(const struct login* data); const char* login_get_username(const struct login* data); const char* login_get_password(const struct login* data); @@ -33,3 +30,4 @@ const size_t login_get_time_created(const struct login* data); const size_t login_get_time_last_used(const struct login* data); const size_t login_get_time_password_changed(const struct login* data); const size_t login_get_times_used(const struct login* data); +const LoginStatus login_is_valid(const struct login* data); diff --git a/complex objects/cargo/src/logins.rs b/complex objects/cargo/logins/src/lib.rs similarity index 85% rename from complex objects/cargo/src/logins.rs rename to complex objects/cargo/logins/src/lib.rs index a8a5658..6bffd0a 100644 --- a/complex objects/cargo/src/logins.rs +++ b/complex objects/cargo/logins/src/lib.rs @@ -8,40 +8,44 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. +extern crate rusqlite; +extern crate time; +extern crate uuid; +extern crate ffi_utils; +extern crate store; + use std::os::raw::{ c_char, c_int} ; use std::sync::{ Arc, - Mutex }; - -use rusqlite::Connection; use time::{ now, Timespec }; use uuid::Uuid; -use utils::{ +use ffi_utils::strings::{ c_char_to_string, - read_connection, string_to_c_char }; +use store::Store; #[derive(Debug)] +#[repr(C)] pub struct LoginManager { - pub conn: Arc>, - uri: String + pub store: Arc, } impl LoginManager { - pub fn new(uri: String, conn: Arc>) -> LoginManager { - LoginManager { - conn: conn, - uri: uri - } + pub fn new(store: Arc) -> LoginManager { + let manager = LoginManager { + store: store, + }; + manager.create_logins_table(); + manager } pub fn create_logins_table(&self) { @@ -55,16 +59,16 @@ impl LoginManager { time_password_changed DATETIME DEFAULT CURRENT_TIMESTAMP, times_used INTEGER DEFAULT 0 )"#; - let db = self.conn.lock().unwrap(); - db.execute(sql, &[]).unwrap(); + let conn = self.store.write_connection(); + conn.execute(sql, &[]).unwrap(); } pub fn fetch_login(&self, username: String, password: String) -> Option { let sql = r#"SELECT id, username, password, guid, time_created, time_last_used, time_password_changed, times_used - FROM logins - WHERE username=? - LIMIT 1"#; - let db = read_connection(&self.uri); + FROM logins + WHERE username=? + LIMIT 1"#; + let db = self.store.read_connection(); let mut stmt = db.prepare(sql).unwrap(); let mut login_iter = stmt.query_map(&[&username], |row| { Login { @@ -79,28 +83,27 @@ impl LoginManager { is_valid: LoginStatus::Valid } }).unwrap(); - match login_iter.next() { - Some(result) => { - match result { - Ok(mut login) => { - if login.password != password { - login.is_valid = LoginStatus::IncorrectPassword; - } - Some(login) - }, - Err(_) => { - None + + if let Some(result) = login_iter.next() { + match result.ok() { + Some(mut login) => { + if login.password != password { + login.is_valid = LoginStatus::IncorrectPassword; } - } - }, - None => None + Some(login) + }, + None => None + } + } else { + println!("No item found"); + None } } pub fn create_login(&self, username: String, password: String) -> Option { let sql = r#"INSERT INTO logins (username, password, guid, time_last_used, times_used) VALUES (?1, ?2, ?3, ?4, ?5)"#; let time_last_used:Option = None; - let db = self.conn.lock().unwrap(); + let db = self.store.write_connection(); db.execute(sql, &[&username, &password, &Uuid::new_v4().simple().to_string(), &time_last_used, &0]).unwrap(); self.fetch_login(username, password) } @@ -110,7 +113,7 @@ impl LoginManager { login.times_used = login.times_used+1; login.time_last_used = Some(now().to_timespec()); - let db = self.conn.lock().unwrap(); + let db = self.store.write_connection(); db.execute(sql, &[&login.time_last_used, &login.times_used, &login.id]).unwrap(); } } diff --git a/complex objects/cargo/src/categories.rs b/complex objects/cargo/src/categories.rs deleted file mode 100644 index 21e9913..0000000 --- a/complex objects/cargo/src/categories.rs +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright 2016 Mozilla -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use -// this file except in compliance with the License. You may obtain a copy of the -// License at http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software distributed -// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -use libc::size_t; -use std::os::raw::{ - c_char, - c_int -}; -use std::sync::{ - Arc, - Mutex -}; - -use rusqlite::Connection; - -use items::Item; -use utils::{ - c_char_to_string, - read_connection, - string_to_c_char -}; - -#[derive(Debug)] -pub struct CategoryManager { - conn: Arc>, - uri: String -} - -impl CategoryManager { - pub fn new(uri: String, conn: Arc>) -> CategoryManager { - CategoryManager { - conn: conn, - uri: uri - } - } - - pub fn create_categories_table(&self) { - let sql = r#"CREATE TABLE IF NOT EXISTS categories ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL - )"#; - let db = self.conn.lock().unwrap(); - match db.execute(sql, &[]).unwrap() { - 1 => { - self.create_category("To Do".to_string()); - }, - _ => {} - }; - } - - pub fn create_category(&self, name: String) -> Option { - let sql = r#"INSERT INTO categories (name) VALUES (?)"#; - let db = self.conn.lock().unwrap(); - db.execute(sql, &[&name]).unwrap(); - self.fetch_category(&name) - } - - pub fn fetch_category(&self, name: &String) -> Option { - let sql = r#"SELECT id, name FROM categories WHERE name=?"#; - - let db = read_connection(&self.uri); - let mut stmt = db.prepare(sql).unwrap(); - let mut category_iter = stmt.query_map(&[name], |row| { - Category { - id: row.get(0), - name: row.get(1), - items: Vec::new() - } - }).unwrap(); - - match category_iter.next() { - Some(result) => { - match result { - Ok(mut category) => { - category.items = self.fetch_items_for_category(&category); - Some(category) - }, - Err(_) => None - } - }, - None => None - } - } - - pub fn fetch_categories(&self) -> Vec { - let sql = r#"SELECT id, name - FROM categories"#; - let db = read_connection(&self.uri); - let mut stmt = db.prepare(sql).unwrap(); - let mut category_iter = stmt.query_map(&[], |row| { - Category { - id: row.get(0), - name: row.get(1), - items: Vec::new() - } - }).unwrap(); - - let mut category_list: Vec = Vec::new(); - loop { - match category_iter.next() { - Some(result) => { - match result { - Ok(mut category) => { - category.items = self.fetch_items_for_category(&category); - category_list.push(category); - }, - Err(_) => {} - } - }, - None => break - } - } - category_list - } - - pub fn create_items_table(&self) { - let sql = r#"CREATE TABLE IF NOT EXISTS items ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - description TEXT NOT NULL, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - due_date DATETIME, - is_complete TINYINT DEFAULT 0, - category REFERENCES categories(id) - )"#; - let db = self.conn.lock().unwrap(); - db.execute(sql, &[]).unwrap(); - } - - pub fn fetch_items_for_category(&self, category: &Category) -> Vec { - let sql = r#"SELECT id, description, created_at, due_date, is_complete - FROM items - WHERE category=?"#; - let db = read_connection(&self.uri); - let mut stmt = db.prepare(sql).unwrap(); - let mut item_iter = stmt.query_map(&[&category.id], |row| { - let complete: i64 = row.get(4); - Item { - id: row.get(0), - description: row.get(1), - created_at: row.get(2), - due_date: row.get(3), - is_complete: complete != 0 - } - }).unwrap(); - - let mut item_list: Vec = Vec::new(); - - loop { - match item_iter.next() { - Some(result) => { - match result { - Ok(i) => { - item_list.push(i); - }, - Err(_) => {} - } - }, - None => break - } - } - item_list - } - - pub fn create_item(&self, item: &Item, category_id: i64) -> Option { - let sql = r#"INSERT INTO items (description, created_at, due_date, is_complete, category) VALUES (?, ?, ?, ?, ?)"#; - let db = self.conn.lock().unwrap(); - let mut stmt = db.prepare(sql).unwrap(); - match stmt.insert(&[&item.description, &item.created_at, &item.due_date, &item.is_complete, &category_id]) { - Ok(row_id) => { - let fetch_sql = r#"SELECT id, description, created_at, due_date, is_complete FROM items WHERE rowid=?"#; - stmt = db.prepare(fetch_sql).unwrap(); - let mut item_iter = stmt.query_map(&[&row_id], |row| { - let complete: i64 = row.get(4); - Item { - id: row.get(0), - description: row.get(1), - created_at: row.get(2), - due_date: row.get(3), - is_complete: complete != 0 - } - }).unwrap(); - match item_iter.next() { - Some(result) => { - match result { - Ok(item) => Some(item), - Err(e) => { - println!("Failed to fetch item {:?}", e); - None - } - } - }, - None => { - None - } - } - }, - Err(e) => { - println!("Failed to create item {:?}", e); - None - } - } - } - - pub fn update_item(&self, item: &Item) { - let sql = r#"UPDATE items SET description=?, due_date=?, is_complete=? WHERE id=?"#; - let db = self.conn.lock().unwrap(); - let _ = db.execute(sql, &[&item.description, &item.due_date, &item.is_complete, &item.id]); - } -} - -#[derive(Debug, Clone)] -pub struct Category { - pub id: isize, - pub name: String, - pub items: Vec -} - -impl Drop for Category { - fn drop(&mut self) { - println!("{:?} is being deallocated", self); - } -} - -#[no_mangle] -pub unsafe extern "C" fn get_all_categories(manager: *const Arc) -> *mut Vec { - let manager = &*manager; - let category_list = Box::new(manager.fetch_categories()); - Box::into_raw(category_list) -} - -#[no_mangle] -pub unsafe extern "C" fn category_manager_create_item(manager: *const Arc, item: *const Item, category_id: c_int) { - let manager = &*manager; - let item = &*item; - let cat_id = category_id as i64; - manager.create_item(item, cat_id); -} - -#[no_mangle] -pub unsafe extern "C" fn category_manager_update_item(manager: *const Arc, item: *const Item) { - let manager = &*manager; - let item = &*item; - manager.update_item(item) -} - -#[no_mangle] -pub unsafe extern "C" fn category_new(manager: *const Arc, name: *const c_char) -> *mut Category { - let manager = &*manager; - let name = c_char_to_string(name); - let category = Box::new(manager.create_category(name).unwrap()); - Box::into_raw(category) -} - -#[no_mangle] -pub unsafe extern "C" fn category_destroy(category: *mut Category) { - let _ = Box::from_raw(category); -} - -#[no_mangle] -pub unsafe extern "C" fn category_get_id(category: *const Category) -> c_int { - let category = &*category; - category.id as c_int -} - -#[no_mangle] -pub unsafe extern "C" fn category_get_name(category: *const Category) -> *mut c_char { - let category = &*category; - string_to_c_char(category.name.clone()) -} - -#[no_mangle] -pub unsafe extern "C" fn category_get_items(category: *const Category) -> *mut Vec { - let category = &*category; - let boxed_items = Box::new(category.items.clone()); - Box::into_raw(boxed_items) -} - -#[no_mangle] -pub unsafe extern "C" fn category_items_count(category: *const Category) -> c_int { - let category = &*category; - category.items.len() as c_int -} - -#[no_mangle] -pub unsafe extern "C" fn category_item_at(item_list: *const Vec, index: size_t) -> *const Item { - let item_list = &*item_list; - let index = index as usize; - let item = Box::new(item_list[index].clone()); - Box::into_raw(item) -} - -#[no_mangle] -pub unsafe extern "C" fn category_list_destroy(category_list: *mut Vec) { - let _ = Box::from_raw(category_list); -} - -#[no_mangle] -pub unsafe extern "C" fn category_list_count(category_list: *const Vec) -> c_int { - let category_list = &*category_list; - category_list.len() as c_int -} - -#[no_mangle] -pub unsafe extern "C" fn category_list_item_at(category_list: *const Vec, index: size_t) -> *const Category { - let category_list = &*category_list; - let index = index as usize; - let category = Box::new(category_list[index].clone()); - Box::into_raw(category) -} - -#[no_mangle] -pub unsafe extern "C" fn add_category(category_list: *mut Vec, category: *const Category) { - let category_list = &mut*category_list; - let category = &*category; - category_list.push((*category).clone()) -} - -#[no_mangle] -pub unsafe extern "C" fn category_add_item(category: *mut Category, item: *const Item) { - let category = &mut*category; - let item = &*item; - category.items.push((*item).clone()); -} diff --git a/complex objects/cargo/src/db.h b/complex objects/cargo/src/db.h deleted file mode 100644 index f23f3f6..0000000 --- a/complex objects/cargo/src/db.h +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include "logins.h" -#include "categories.h" - -struct store; - -struct store* new_store(const char* uri); -void store_destroy(struct store* data); - -struct login_manager* store_logins(struct store* store); -struct category_manager* store_categories(struct store* store); - - diff --git a/complex objects/cargo/src/db.rs b/complex objects/cargo/src/db.rs deleted file mode 100644 index 68d4af4..0000000 --- a/complex objects/cargo/src/db.rs +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2016 Mozilla -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use -// this file except in compliance with the License. You may obtain a copy of the -// License at http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software distributed -// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -use std::os::raw::{ - c_char -}; -use std::sync::{ - Arc, - Mutex -}; - -use rusqlite::{ - Connection, -}; - -use logins::{ - LoginManager -}; -use categories::{ - CategoryManager -}; -use utils::{ - c_char_to_string, - read_connection -}; - -#[derive(Debug)] -pub struct Store { - pub conn: Arc>, - pub uri: String, - pub logins: Arc, - pub categories: Arc -} - -impl Drop for Store { - fn drop(&mut self) { - println!("{:?} is being deallocated", self); - } -} - -impl Store { - pub fn new(uri: String) -> Self { - let conn = Arc::new(Mutex::new(Connection::open(uri.clone()).unwrap())); - Store { - conn: conn.clone(), - uri: uri.clone(), - logins: Arc::new(LoginManager::new(uri.clone(), conn.clone())), - categories: Arc::new(CategoryManager::new(uri.clone(), conn)) - } - } -} - -#[no_mangle] -pub extern "C" fn new_store(uri: *const c_char) -> *mut Store { - let uri = c_char_to_string(uri); - let store = Store::new(uri); - // create tables - store.logins.create_logins_table(); - store.categories.create_categories_table(); - store.categories.create_items_table(); - Box::into_raw(Box::new(store)) -} - -#[no_mangle] -pub unsafe extern "C" fn store_destroy(data: *mut Store) { - let _ = Box::from_raw(data); -} - -#[no_mangle] -pub unsafe extern "C" fn store_logins(store: *mut Store) -> *mut Arc { - let store = &*store; - let logins = Box::new(store.logins.clone()); - Box::into_raw(logins) -} - -#[no_mangle] -pub unsafe extern "C" fn store_categories(store: *mut Store) -> *mut Arc { - let store = &*store; - let cats = Box::new(store.categories.clone()); - Box::into_raw(cats) -} - -#[no_mangle] -pub unsafe extern "C" fn store_write_connection(store: *mut Store) -> *mut Arc> { - let store = &*store; - let conn = Box::new(store.conn.clone()); - Box::into_raw(conn) -} - -#[no_mangle] -pub unsafe extern "C" fn store_read_connection(store: *mut Store) -> *mut Arc { - let store = &*store; - let conn = Box::new(read_connection(&store.uri)); - Box::into_raw(conn) -} - - - - - diff --git a/complex objects/cargo/src/lib.rs b/complex objects/cargo/src/lib.rs index 7cc8e68..d234631 100644 --- a/complex objects/cargo/src/lib.rs +++ b/complex objects/cargo/src/lib.rs @@ -8,13 +8,59 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. -extern crate libc; -extern crate rusqlite; -extern crate time; -extern crate uuid; - -pub mod logins; -pub mod categories; -pub mod items; -pub mod utils; -pub mod db; +extern crate ffi_utils; +extern crate store; +extern crate logins; +extern crate list; + +use std::os::raw::{ + c_char +}; +use std::sync::{ + Arc, +}; + +use ffi_utils::strings::c_char_to_string; +use logins::LoginManager; +use list::ListManager; +use store::Store; + +pub struct Toodle { + store: Arc, + logins: Arc, + list: Arc +} + +impl Toodle { + fn new(uri: String) -> Toodle { + let store = Arc::new(Store::new(uri)); + Toodle { + store: store.clone(), + logins: Arc::new(LoginManager::new(store.clone())), + list: Arc::new(ListManager::new(store.clone())) + } + } +} + +#[no_mangle] +pub extern "C" fn new_toodle(uri: *const c_char) -> *mut Toodle { + let uri = c_char_to_string(uri); + Box::into_raw(Box::new(Toodle::new(uri))) +} + +#[no_mangle] +pub unsafe extern "C" fn toodle_destroy(toodle: *mut Toodle) { + let _ = Box::from_raw(toodle); +} + +#[no_mangle] +pub unsafe extern "C" fn toodle_logins(toodle: *mut Toodle) -> *mut Arc { + let toodle = &*toodle; + Box::into_raw(Box::new(toodle.logins.clone())) +} + +#[no_mangle] +pub unsafe extern "C" fn toodle_list(toodle: *mut Toodle) -> *mut Arc { + let toodle = &*toodle; + Box::into_raw(Box::new(toodle.list.clone())) +} diff --git a/complex objects/cargo/src/toodle.h b/complex objects/cargo/src/toodle.h new file mode 100644 index 0000000..81fb2e4 --- /dev/null +++ b/complex objects/cargo/src/toodle.h @@ -0,0 +1,11 @@ +#include +#include "logins.h" +#include "categories.h" + +struct toodle; + +struct toodle* new_toodle(const char* uri); +void toodle_destroy(struct toodle* toodle); + +struct login_manager* toodle_logins(struct toodle* toodle); +struct list_manager* toodle_list(struct toodle* toodle); diff --git a/complex objects/cargo/src/utils.rs b/complex objects/cargo/src/utils.rs deleted file mode 100644 index 47cd20c..0000000 --- a/complex objects/cargo/src/utils.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 Mozilla -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not use -// this file except in compliance with the License. You may obtain a copy of the -// License at http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software distributed -// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -use std::os::raw::c_char; -use std::ffi::{ - CString, - CStr -}; -use std::sync::{ - Arc -}; - -use rusqlite; -use rusqlite::Connection; - -pub fn c_char_to_string(cchar: *const c_char) -> String { - let c_str = unsafe { CStr::from_ptr(cchar) }; - let r_str = match c_str.to_str() { - Err(_) => "", - Ok(string) => string, - }; - r_str.to_string() -} - -pub fn string_to_c_char(r_string: String) -> *mut c_char { - CString::new(r_string).unwrap().into_raw() -} - -pub fn read_connection(uri: &String) -> Arc { - Arc::new(Connection::open_with_flags(uri.clone(), rusqlite::SQLITE_OPEN_READ_ONLY).unwrap()) -} diff --git a/complex objects/cargo/store/Cargo.toml b/complex objects/cargo/store/Cargo.toml new file mode 100644 index 0000000..eb55ab9 --- /dev/null +++ b/complex objects/cargo/store/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "store" +version = "0.1.0" +authors = ["Emily Toop "] + +[target.'cfg(target_os="android")'.dependencies] +jni = { version = "0.5", default-features = false } + +[dependencies.rusqlite] +version = "0.12" +# System sqlite might be very old. +features = ["bundled", "limits"] + +[dependencies.ffi-utils] +path = "../ffi-utils" diff --git a/complex objects/cargo/store/src/lib.rs b/complex objects/cargo/store/src/lib.rs new file mode 100644 index 0000000..85eb883 --- /dev/null +++ b/complex objects/cargo/store/src/lib.rs @@ -0,0 +1,68 @@ +// Copyright 2016 Mozilla +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use +// this file except in compliance with the License. You may obtain a copy of the +// License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +extern crate rusqlite; +extern crate ffi_utils; + +use std::os::raw::{ + c_char +}; +use std::sync::{ + Arc, + Mutex +}; + +use rusqlite::{ + Connection +}; + +use ffi_utils::strings::c_char_to_string; + +#[derive(Debug)] +#[repr(C)] +pub struct Store { + conn: Mutex>, + uri: String, +} + +impl Drop for Store { + fn drop(&mut self) { + println!("{:?} is being deallocated", self); + } +} + +impl Store { + pub fn new(uri: String) -> Self { + Store { + conn: Mutex::new(Arc::new(Connection::open(uri.clone()).unwrap())), + uri: uri.clone(), + } + } + + pub fn write_connection(&self) -> Arc { + self.conn.lock().unwrap().clone() + } + + pub fn read_connection(&self) -> Arc { + Arc::new(Connection::open_with_flags(self.uri.clone(), rusqlite::SQLITE_OPEN_READ_ONLY).unwrap()) + } +} + +#[no_mangle] +pub extern "C" fn new_store(uri: *const c_char) -> *mut Arc { + let uri = c_char_to_string(uri); + let store = Arc::new(Store::new(uri)); + Box::into_raw(Box::new(store)) +} + +#[no_mangle] +pub unsafe extern "C" fn store_destroy(data: *mut Store) { + let _ = Box::from_raw(data); +} diff --git a/complex objects/cargo/store/store.h b/complex objects/cargo/store/store.h new file mode 100644 index 0000000..12143ee --- /dev/null +++ b/complex objects/cargo/store/store.h @@ -0,0 +1,8 @@ +#include + +struct store; + +struct store* new_store(const char* uri); +void store_destroy(struct store* store); + + diff --git a/complex objects/ios/ComplexRust/Store/Store.swift b/complex objects/ios/ComplexRust/Store/Store.swift deleted file mode 100644 index ae9664f..0000000 --- a/complex objects/ios/ComplexRust/Store/Store.swift +++ /dev/null @@ -1,39 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -import Foundation - -class Store: RustObject { - - class var sharedInstance: Store { - struct Static { - static let instance: Store = Store() - } - return Static.instance - } - - var raw: OpaquePointer - - required init(raw: OpaquePointer) { - self.raw = raw - } - - convenience init() { - let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) - let documentsURL = paths[0] - let storeURI = documentsURL.appendingPathComponent("todolist.db", isDirectory: false).absoluteString - self.init(raw: new_store(storeURI)) - } - - var logins: LoginManager { - return LoginManager(raw: store_logins(self.raw)); - } - - var categories: CategoryManager { - return CategoryManager(raw: store_categories(self.raw)); - } -} - -class Singleton { -} diff --git a/complex objects/ios/ComplexRust.xcodeproj/project.pbxproj b/complex objects/ios/Toodle.xcodeproj/project.pbxproj similarity index 85% rename from complex objects/ios/ComplexRust.xcodeproj/project.pbxproj rename to complex objects/ios/Toodle.xcodeproj/project.pbxproj index 878fa8f..813bb9b 100644 --- a/complex objects/ios/ComplexRust.xcodeproj/project.pbxproj +++ b/complex objects/ios/Toodle.xcodeproj/project.pbxproj @@ -7,9 +7,10 @@ objects = { /* Begin PBXBuildFile section */ - 7B2BA8971F963D1E0093D191 /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B2BA8961F963D1E0093D191 /* Store.swift */; }; + 7B1F2D701FB0D379000246C9 /* ToodleLib.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1F2D6F1FB0D379000246C9 /* ToodleLib.swift */; }; 7B2BA8C71F97B24E0093D191 /* ToDoListItemsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B2BA8C61F97B24E0093D191 /* ToDoListItemsTableViewController.swift */; }; - 7B47BBD61F9A3E7A00FCA5AA /* CategoryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B47BBD51F9A3E7A00FCA5AA /* CategoryManager.swift */; }; + 7B383BAD1FB20F000099B12E /* libtoodle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B9D81B01FB0CFC30027C605 /* libtoodle.a */; }; + 7B47BBD61F9A3E7A00FCA5AA /* ListManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B47BBD51F9A3E7A00FCA5AA /* ListManager.swift */; }; 7B47BBD81F9A3EDE00FCA5AA /* LoginManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B47BBD71F9A3EDE00FCA5AA /* LoginManager.swift */; }; 7B47BBDE1F9A518D00FCA5AA /* ItemViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B47BBDD1F9A518D00FCA5AA /* ItemViewController.swift */; }; 7B9F01101F794DB2000407E5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9F010F1F794DB2000407E5 /* AppDelegate.swift */; }; @@ -25,20 +26,20 @@ 7B9F013E1F827D7B000407E5 /* Category.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9F013D1F827D7B000407E5 /* Category.swift */; }; 7BB2204D1F8F976C00ACD7AF /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB2204C1F8F976C00ACD7AF /* Item.swift */; }; 7BB220541F8FA72500ACD7AF /* RustObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB220531F8FA72500ACD7AF /* RustObject.swift */; }; - 7BCBDDEA1FAB6019001F8B06 /* libgreetings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B9F01291F794F49000407E5 /* libgreetings.a */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 7B2BA8951F963D130093D191 /* db.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = db.h; path = ../../../cargo/src/db.h; sourceTree = ""; }; - 7B2BA8961F963D1E0093D191 /* Store.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = ""; }; - 7B2BA8981F963D3D0093D191 /* items.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = items.h; path = ../../../../cargo/src/items.h; sourceTree = ""; }; - 7B2BA8991F963D530093D191 /* categories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = categories.h; path = ../../../../cargo/src/categories.h; sourceTree = ""; }; - 7B2BA89A1F963D660093D191 /* logins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = logins.h; path = ../../../../cargo/src/logins.h; sourceTree = ""; }; + 7B1F2D6D1FB0D335000246C9 /* items.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = items.h; path = ../../../../../cargo/list/items.h; sourceTree = ""; }; + 7B1F2D6E1FB0D343000246C9 /* categories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = categories.h; path = ../../../../../cargo/list/categories.h; sourceTree = ""; }; + 7B1F2D6F1FB0D379000246C9 /* ToodleLib.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToodleLib.swift; sourceTree = ""; }; 7B2BA8C61F97B24E0093D191 /* ToDoListItemsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToDoListItemsTableViewController.swift; sourceTree = ""; }; - 7B47BBD51F9A3E7A00FCA5AA /* CategoryManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryManager.swift; sourceTree = ""; }; + 7B47BBD51F9A3E7A00FCA5AA /* ListManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListManager.swift; sourceTree = ""; }; 7B47BBD71F9A3EDE00FCA5AA /* LoginManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginManager.swift; sourceTree = ""; }; 7B47BBDD1F9A518D00FCA5AA /* ItemViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemViewController.swift; sourceTree = ""; }; - 7B9F010C1F794DB2000407E5 /* ComplexRust.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ComplexRust.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B9D81B01FB0CFC30027C605 /* libtoodle.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtoodle.a; path = ../cargo/target/universal/release/libtoodle.a; sourceTree = ""; }; + 7B9D81B31FB0D0460027C605 /* toodle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = toodle.h; path = ../../../cargo/src/toodle.h; sourceTree = ""; }; + 7B9D81B61FB0D0750027C605 /* logins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = logins.h; path = ../../../../cargo/logins/logins.h; sourceTree = ""; }; + 7B9F010C1F794DB2000407E5 /* Toodle.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Toodle.app; sourceTree = BUILT_PRODUCTS_DIR; }; 7B9F010F1F794DB2000407E5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7B9F01111F794DB2000407E5 /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = ""; }; 7B9F01141F794DB2000407E5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -63,24 +64,33 @@ buildActionMask = 2147483647; files = ( 7B9F01281F794F3B000407E5 /* libresolv.tbd in Frameworks */, - 7BCBDDEA1FAB6019001F8B06 /* libgreetings.a in Frameworks */, + 7B383BAD1FB20F000099B12E /* libtoodle.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 7B2BA8941F963C5C0093D191 /* Store */ = { + 7B1F2D6C1FB0D318000246C9 /* List */ = { isa = PBXGroup; children = ( - 7BB220531F8FA72500ACD7AF /* RustObject.swift */, + 7B47BBD51F9A3E7A00FCA5AA /* ListManager.swift */, 7BB2204B1F8F975F00ACD7AF /* Items */, 7B9F013C1F827D5D000407E5 /* Categories */, + ); + path = List; + sourceTree = ""; + }; + 7B2BA8941F963C5C0093D191 /* Rust */ = { + isa = PBXGroup; + children = ( + 7B9D81B31FB0D0460027C605 /* toodle.h */, + 7BB220531F8FA72500ACD7AF /* RustObject.swift */, + 7B1F2D6C1FB0D318000246C9 /* List */, 7B9F012B1F795075000407E5 /* Logins */, - 7B2BA8951F963D130093D191 /* db.h */, - 7B2BA8961F963D1E0093D191 /* Store.swift */, + 7B1F2D6F1FB0D379000246C9 /* ToodleLib.swift */, ); - path = Store; + path = Rust; sourceTree = ""; }; 7B47BBDF1F9A51A100FCA5AA /* Controllers */ = { @@ -99,7 +109,7 @@ 7B9F01031F794DB1000407E5 = { isa = PBXGroup; children = ( - 7B9F010E1F794DB2000407E5 /* ComplexRust */, + 7B9F010E1F794DB2000407E5 /* Toodle */, 7B9F010D1F794DB2000407E5 /* Products */, 7B9F01261F794F3B000407E5 /* Frameworks */, ); @@ -108,15 +118,15 @@ 7B9F010D1F794DB2000407E5 /* Products */ = { isa = PBXGroup; children = ( - 7B9F010C1F794DB2000407E5 /* ComplexRust.app */, + 7B9F010C1F794DB2000407E5 /* Toodle.app */, ); name = Products; sourceTree = ""; }; - 7B9F010E1F794DB2000407E5 /* ComplexRust */ = { + 7B9F010E1F794DB2000407E5 /* Toodle */ = { isa = PBXGroup; children = ( - 7B2BA8941F963C5C0093D191 /* Store */, + 7B2BA8941F963C5C0093D191 /* Rust */, 7B9F01241F794ED6000407E5 /* ComplexRust-Bridging-Header.h */, 7B9F010F1F794DB2000407E5 /* AppDelegate.swift */, 7B9F011B1F794DB2000407E5 /* Info.plist */, @@ -125,12 +135,13 @@ 7B9F01181F794DB2000407E5 /* LaunchScreen.storyboard */, 7B9F01341F7D1634000407E5 /* NSLayoutConstraint+Utils.swift */, ); - path = ComplexRust; + path = Toodle; sourceTree = ""; }; 7B9F01261F794F3B000407E5 /* Frameworks */ = { isa = PBXGroup; children = ( + 7B9D81B01FB0CFC30027C605 /* libtoodle.a */, 7B9F01291F794F49000407E5 /* libgreetings.a */, 7B9F01271F794F3B000407E5 /* libresolv.tbd */, ); @@ -140,7 +151,7 @@ 7B9F012B1F795075000407E5 /* Logins */ = { isa = PBXGroup; children = ( - 7B2BA89A1F963D660093D191 /* logins.h */, + 7B9D81B61FB0D0750027C605 /* logins.h */, 7B9F012C1F7950AE000407E5 /* Login.swift */, 7B47BBD71F9A3EDE00FCA5AA /* LoginManager.swift */, ); @@ -150,9 +161,8 @@ 7B9F013C1F827D5D000407E5 /* Categories */ = { isa = PBXGroup; children = ( - 7B2BA8991F963D530093D191 /* categories.h */, + 7B1F2D6E1FB0D343000246C9 /* categories.h */, 7B9F013D1F827D7B000407E5 /* Category.swift */, - 7B47BBD51F9A3E7A00FCA5AA /* CategoryManager.swift */, ); path = Categories; sourceTree = ""; @@ -160,7 +170,7 @@ 7BB2204B1F8F975F00ACD7AF /* Items */ = { isa = PBXGroup; children = ( - 7B2BA8981F963D3D0093D191 /* items.h */, + 7B1F2D6D1FB0D335000246C9 /* items.h */, 7BB2204C1F8F976C00ACD7AF /* Item.swift */, ); path = Items; @@ -169,9 +179,9 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 7B9F010B1F794DB1000407E5 /* ComplexRust */ = { + 7B9F010B1F794DB1000407E5 /* Toodle */ = { isa = PBXNativeTarget; - buildConfigurationList = 7B9F011E1F794DB2000407E5 /* Build configuration list for PBXNativeTarget "ComplexRust" */; + buildConfigurationList = 7B9F011E1F794DB2000407E5 /* Build configuration list for PBXNativeTarget "Toodle" */; buildPhases = ( 7B9F01081F794DB1000407E5 /* Sources */, 7B9F01091F794DB1000407E5 /* Frameworks */, @@ -181,9 +191,9 @@ ); dependencies = ( ); - name = ComplexRust; + name = Toodle; productName = ComplexRust; - productReference = 7B9F010C1F794DB2000407E5 /* ComplexRust.app */; + productReference = 7B9F010C1F794DB2000407E5 /* Toodle.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -202,7 +212,7 @@ }; }; }; - buildConfigurationList = 7B9F01071F794DB1000407E5 /* Build configuration list for PBXProject "ComplexRust" */; + buildConfigurationList = 7B9F01071F794DB1000407E5 /* Build configuration list for PBXProject "Toodle" */; compatibilityVersion = "Xcode 8.0"; developmentRegion = en; hasScannedForEncodings = 0; @@ -215,7 +225,7 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 7B9F010B1F794DB1000407E5 /* ComplexRust */, + 7B9F010B1F794DB1000407E5 /* Toodle */, ); }; /* End PBXProject section */ @@ -243,12 +253,12 @@ 7B9F012D1F7950AE000407E5 /* Login.swift in Sources */, 7B9F01311F7D13A5000407E5 /* NewLoginViewController.swift in Sources */, 7BB2204D1F8F976C00ACD7AF /* Item.swift in Sources */, + 7B1F2D701FB0D379000246C9 /* ToodleLib.swift in Sources */, 7B47BBD81F9A3EDE00FCA5AA /* LoginManager.swift in Sources */, 7B47BBDE1F9A518D00FCA5AA /* ItemViewController.swift in Sources */, - 7B2BA8971F963D1E0093D191 /* Store.swift in Sources */, 7B9F01121F794DB2000407E5 /* LoginViewController.swift in Sources */, 7B2BA8C71F97B24E0093D191 /* ToDoListItemsTableViewController.swift in Sources */, - 7B47BBD61F9A3E7A00FCA5AA /* CategoryManager.swift in Sources */, + 7B47BBD61F9A3E7A00FCA5AA /* ListManager.swift in Sources */, 7B9F013B1F827A23000407E5 /* ToDoListCategoryViewController.swift in Sources */, 7B9F01101F794DB2000407E5 /* AppDelegate.swift in Sources */, 7B9F013E1F827D7B000407E5 /* Category.swift in Sources */, @@ -393,7 +403,7 @@ INFOPLIST_FILE = ComplexRust/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/../cargo/target/universal/release"; - PRODUCT_BUNDLE_IDENTIFIER = com.mozilla.ComplexRust; + PRODUCT_BUNDLE_IDENTIFIER = com.mozilla.Toodle; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/ComplexRust/ComplexRust-Bridging-Header.h"; SWIFT_VERSION = 4.0; @@ -410,7 +420,7 @@ INFOPLIST_FILE = ComplexRust/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/../cargo/target/universal/release"; - PRODUCT_BUNDLE_IDENTIFIER = com.mozilla.ComplexRust; + PRODUCT_BUNDLE_IDENTIFIER = com.mozilla.Toodle; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/ComplexRust/ComplexRust-Bridging-Header.h"; SWIFT_VERSION = 4.0; @@ -421,7 +431,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 7B9F01071F794DB1000407E5 /* Build configuration list for PBXProject "ComplexRust" */ = { + 7B9F01071F794DB1000407E5 /* Build configuration list for PBXProject "Toodle" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B9F011C1F794DB2000407E5 /* Debug */, @@ -430,7 +440,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 7B9F011E1F794DB2000407E5 /* Build configuration list for PBXNativeTarget "ComplexRust" */ = { + 7B9F011E1F794DB2000407E5 /* Build configuration list for PBXNativeTarget "Toodle" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B9F011F1F794DB2000407E5 /* Debug */, diff --git a/complex objects/ios/ComplexRust.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/complex objects/ios/Toodle.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from complex objects/ios/ComplexRust.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to complex objects/ios/Toodle.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/complex objects/ios/ComplexRust/AppDelegate.swift b/complex objects/ios/Toodle/AppDelegate.swift similarity index 100% rename from complex objects/ios/ComplexRust/AppDelegate.swift rename to complex objects/ios/Toodle/AppDelegate.swift diff --git a/complex objects/ios/ComplexRust/Assets.xcassets/AppIcon.appiconset/Contents.json b/complex objects/ios/Toodle/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from complex objects/ios/ComplexRust/Assets.xcassets/AppIcon.appiconset/Contents.json rename to complex objects/ios/Toodle/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/complex objects/ios/ComplexRust/Base.lproj/LaunchScreen.storyboard b/complex objects/ios/Toodle/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from complex objects/ios/ComplexRust/Base.lproj/LaunchScreen.storyboard rename to complex objects/ios/Toodle/Base.lproj/LaunchScreen.storyboard diff --git a/complex objects/ios/ComplexRust/ComplexRust-Bridging-Header.h b/complex objects/ios/Toodle/ComplexRust-Bridging-Header.h similarity index 94% rename from complex objects/ios/ComplexRust/ComplexRust-Bridging-Header.h rename to complex objects/ios/Toodle/ComplexRust-Bridging-Header.h index 7ec2e05..ec289ba 100644 --- a/complex objects/ios/ComplexRust/ComplexRust-Bridging-Header.h +++ b/complex objects/ios/Toodle/ComplexRust-Bridging-Header.h @@ -5,6 +5,6 @@ #ifndef ComplexRust_Bridging_Header_h #define ComplexRust_Bridging_Header_h -#import "db.h" +#import "toodle.h" #endif /* ComplexRust_Bridging_Header_h */ diff --git a/complex objects/ios/ComplexRust/Controllers/Base.lproj/Main.storyboard b/complex objects/ios/Toodle/Controllers/Base.lproj/Main.storyboard similarity index 100% rename from complex objects/ios/ComplexRust/Controllers/Base.lproj/Main.storyboard rename to complex objects/ios/Toodle/Controllers/Base.lproj/Main.storyboard diff --git a/complex objects/ios/ComplexRust/Controllers/ItemViewController.swift b/complex objects/ios/Toodle/Controllers/ItemViewController.swift similarity index 98% rename from complex objects/ios/ComplexRust/Controllers/ItemViewController.swift rename to complex objects/ios/Toodle/Controllers/ItemViewController.swift index 505c7ee..96d77dc 100644 --- a/complex objects/ios/ComplexRust/Controllers/ItemViewController.swift +++ b/complex objects/ios/Toodle/Controllers/ItemViewController.swift @@ -226,9 +226,9 @@ class ItemViewController: UIViewController { currentItem.isComplete = (self.statusValueLabel.text ?? "") != "Complete" if let _ = currentItem.id { - try? Store.sharedInstance.categories.update(item: currentItem) + try? ToodleLib.sharedInstance.list.update(item: currentItem) } else { - Store.sharedInstance.categories.add(item: currentItem, toCategory: category) + ToodleLib.sharedInstance.list.add(item: currentItem, toCategory: category) } self.delegate?.itemSaveSuccess(item: currentItem) } diff --git a/complex objects/ios/ComplexRust/Controllers/LoginViewController.swift b/complex objects/ios/Toodle/Controllers/LoginViewController.swift similarity index 98% rename from complex objects/ios/ComplexRust/Controllers/LoginViewController.swift rename to complex objects/ios/Toodle/Controllers/LoginViewController.swift index 5a651eb..d88091d 100644 --- a/complex objects/ios/ComplexRust/Controllers/LoginViewController.swift +++ b/complex objects/ios/Toodle/Controllers/LoginViewController.swift @@ -18,8 +18,8 @@ class LoginViewController: UIViewController { return newVC }() - lazy var dbStore: Store = { - return Store.sharedInstance + lazy var dbStore: ToodleLib = { + return ToodleLib.sharedInstance }() var messageLabel: UILabel = { diff --git a/complex objects/ios/ComplexRust/Controllers/NewLoginViewController.swift b/complex objects/ios/Toodle/Controllers/NewLoginViewController.swift similarity index 97% rename from complex objects/ios/ComplexRust/Controllers/NewLoginViewController.swift rename to complex objects/ios/Toodle/Controllers/NewLoginViewController.swift index 4461f78..885cc72 100644 --- a/complex objects/ios/ComplexRust/Controllers/NewLoginViewController.swift +++ b/complex objects/ios/Toodle/Controllers/NewLoginViewController.swift @@ -115,7 +115,7 @@ class NewLoginViewController: UIViewController { guard password == confirmedPassword else { return print("Password's do not match") } - guard let _ = Store.sharedInstance.logins.createLogin(withUsername: username, andPassword: password) else { + guard let _ = ToodleLib.sharedInstance.logins.createLogin(withUsername: username, andPassword: password) else { return print("failed to create login") } self.delegate?.accountCreationSuccess(withUsername: username, andPassword: password) diff --git a/complex objects/ios/ComplexRust/Controllers/ToDoListCategoryViewController.swift b/complex objects/ios/Toodle/Controllers/ToDoListCategoryViewController.swift similarity index 93% rename from complex objects/ios/ComplexRust/Controllers/ToDoListCategoryViewController.swift rename to complex objects/ios/Toodle/Controllers/ToDoListCategoryViewController.swift index 3772c78..5867100 100644 --- a/complex objects/ios/ComplexRust/Controllers/ToDoListCategoryViewController.swift +++ b/complex objects/ios/Toodle/Controllers/ToDoListCategoryViewController.swift @@ -8,8 +8,8 @@ class ToDoListCategoryViewController: UITableViewController { var categories: [Category] = [] - lazy var dbStore: Store = { - return Store.sharedInstance + lazy var dbStore: ToodleLib = { + return ToodleLib.sharedInstance }() lazy var newCategoryAlertController: UIAlertController = { @@ -31,7 +31,7 @@ class ToDoListCategoryViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() self.title = "Toodle" - categories = self.dbStore.categories.allCategories() + categories = self.dbStore.list.allCategories() self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.add, target: self, action: #selector(newCategory)) } @@ -66,7 +66,7 @@ class ToDoListCategoryViewController: UITableViewController { } fileprivate func createCategory(categoryName: String) { - let category = self.dbStore.categories.createCategory(withName: categoryName) + let category = self.dbStore.list.createCategory(withName: categoryName) self.categories.append(category) self.tableView.reloadData() } diff --git a/complex objects/ios/ComplexRust/Controllers/ToDoListItemsTableViewController.swift b/complex objects/ios/Toodle/Controllers/ToDoListItemsTableViewController.swift similarity index 100% rename from complex objects/ios/ComplexRust/Controllers/ToDoListItemsTableViewController.swift rename to complex objects/ios/Toodle/Controllers/ToDoListItemsTableViewController.swift diff --git a/complex objects/ios/ComplexRust/Info.plist b/complex objects/ios/Toodle/Info.plist similarity index 100% rename from complex objects/ios/ComplexRust/Info.plist rename to complex objects/ios/Toodle/Info.plist diff --git a/complex objects/ios/ComplexRust/NSLayoutConstraint+Utils.swift b/complex objects/ios/Toodle/NSLayoutConstraint+Utils.swift similarity index 100% rename from complex objects/ios/ComplexRust/NSLayoutConstraint+Utils.swift rename to complex objects/ios/Toodle/NSLayoutConstraint+Utils.swift diff --git a/complex objects/ios/ComplexRust/Store/Categories/Category.swift b/complex objects/ios/Toodle/Rust/List/Categories/Category.swift similarity index 100% rename from complex objects/ios/ComplexRust/Store/Categories/Category.swift rename to complex objects/ios/Toodle/Rust/List/Categories/Category.swift diff --git a/complex objects/ios/ComplexRust/Store/Items/Item.swift b/complex objects/ios/Toodle/Rust/List/Items/Item.swift similarity index 100% rename from complex objects/ios/ComplexRust/Store/Items/Item.swift rename to complex objects/ios/Toodle/Rust/List/Items/Item.swift diff --git a/complex objects/ios/ComplexRust/Store/Categories/CategoryManager.swift b/complex objects/ios/Toodle/Rust/List/ListManager.swift similarity index 96% rename from complex objects/ios/ComplexRust/Store/Categories/CategoryManager.swift rename to complex objects/ios/Toodle/Rust/List/ListManager.swift index 2a483f9..c07915f 100644 --- a/complex objects/ios/ComplexRust/Store/Categories/CategoryManager.swift +++ b/complex objects/ios/Toodle/Rust/List/ListManager.swift @@ -4,7 +4,7 @@ import Foundation -class CategoryManager: RustObject { +class ListManager: RustObject { let raw: OpaquePointer required init(raw: OpaquePointer) { diff --git a/complex objects/ios/ComplexRust/Store/Logins/Login.swift b/complex objects/ios/Toodle/Rust/Logins/Login.swift similarity index 100% rename from complex objects/ios/ComplexRust/Store/Logins/Login.swift rename to complex objects/ios/Toodle/Rust/Logins/Login.swift diff --git a/complex objects/ios/ComplexRust/Store/Logins/LoginManager.swift b/complex objects/ios/Toodle/Rust/Logins/LoginManager.swift similarity index 100% rename from complex objects/ios/ComplexRust/Store/Logins/LoginManager.swift rename to complex objects/ios/Toodle/Rust/Logins/LoginManager.swift diff --git a/complex objects/ios/ComplexRust/Store/RustObject.swift b/complex objects/ios/Toodle/Rust/RustObject.swift similarity index 100% rename from complex objects/ios/ComplexRust/Store/RustObject.swift rename to complex objects/ios/Toodle/Rust/RustObject.swift diff --git a/complex objects/ios/Toodle/Rust/ToodleLib.swift b/complex objects/ios/Toodle/Rust/ToodleLib.swift new file mode 100644 index 0000000..2725db1 --- /dev/null +++ b/complex objects/ios/Toodle/Rust/ToodleLib.swift @@ -0,0 +1,43 @@ +///* This Source Code Form is subject to the terms of the Mozilla Public +// * License, v. 2.0. If a copy of the MPL was not distributed with this +// * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import Foundation + +class ToodleLib: RustObject { + + class var sharedInstance: ToodleLib { + struct Static { + static let instance: ToodleLib = ToodleLib() + } + return Static.instance + } + + var raw: OpaquePointer + + required init(raw: OpaquePointer) { + self.raw = raw + } + + convenience init() { + let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) + let documentsURL = paths[0] + let storeURI = documentsURL.appendingPathComponent("todolist.db", isDirectory: false).absoluteString + self.init(raw: new_toodle(storeURI)) + } + + deinit { + toodle_destroy(raw) + } + + var logins: LoginManager { + return LoginManager(raw: toodle_logins(self.raw)); + } + + var list: ListManager { + return ListManager(raw: toodle_list(self.raw)); + } +} + +class Singleton { +}