use rusqlite::{params, Connection}; use serde::{Deserialize, Serialize}; use std::rc::Rc; use std::sync::{Arc, Mutex}; use std::iter::repeat_with; const ID_LENGTH: usize = 20; pub type SegmentId = String; #[derive(Debug, Serialize, Deserialize)] pub struct Segment { pub id: Option, pub from: u64, pub to: u64, } // TODO: find a way to remove this unsafe unsafe impl Sync for DataService {} pub struct DataService { connection: Arc>, } impl DataService { pub fn new() -> anyhow::Result { let conn = Connection::open("./data.db")?; conn.execute( "CREATE TABLE IF NOT EXISTS segment ( id TEXT PRIMARY KEY, start INTEGER NOT NULL, end INTEGER NOT NULL )", [], )?; Ok(DataService { connection: Arc::new(Mutex::new(conn)), }) } // returns id of created segment pub fn insert_segment(&self, segment: &Segment) -> anyhow::Result { let id: SegmentId = repeat_with(fastrand::alphanumeric) .take(ID_LENGTH) .collect(); { // merging // TODO extract intersected ids } // TODO: merge with other segments self.connection.lock().unwrap().execute( "INSERT INTO segment (id, start, end) VALUES (?1, ?2, ?3)", params![id, segment.from, segment.to], )?; Ok(id) } pub fn get_segments_inside(&self, from: u64, to: u64) -> anyhow::Result> { let conn = self.connection.lock().unwrap(); let mut stmt = conn.prepare("SELECT id, start, end FROM segment WHERE ?1 < start AND end < ?2")?; let res = stmt .query_map(params![from, to], |row| { Ok(Segment { id: row.get(0)?, from: row.get(1)?, to: row.get(2)?, }) })? .map(|e| e.unwrap()) .collect(); Ok(res) } pub fn get_segments_intersected(&self, from: u64, to: u64) -> anyhow::Result> { let conn = self.connection.lock().unwrap(); let mut stmt = conn.prepare("SELECT id, start, end FROM segment WHERE (start <= ?1 and ?1 <= end) OR (start <= ?2 AND ?2 <= end) OR (?1 <= start AND start <= ?2) OR (?1 <= end AND end <= ?2) ")?; let res = stmt .query_map(params![from, to], |row| { Ok(Segment { id: row.get(0)?, from: row.get(1)?, to: row.get(2)?, }) })? .map(|e| e.unwrap()) .collect(); Ok(res) } pub fn delete_segments(&self, ids: &Vec) { let v = Rc::new(ids); } }