client_core/store/
prefix.rs1use super::models::{MatchInfo, ResolveError};
2use super::Store;
3use rusqlite::params;
4
5pub const MIN_PREFIX: usize = 4;
6const MAX_CANDIDATES: i64 = 6;
7
8pub fn resolve_clip_id(store: &Store, prefix: &str) -> Result<String, ResolveError> {
9 if prefix.len() < MIN_PREFIX {
10 return Err(ResolveError::TooShort);
11 }
12 let pattern = format!("{prefix}%");
13 let matches: Vec<MatchInfo> = store.with_conn(|conn| {
14 let mut stmt = conn.prepare(
15 "SELECT id, source, content_type, created_at, COALESCE(SUBSTR(CAST(content AS TEXT), 1, 40), '') AS preview
16 FROM clips WHERE id LIKE ?1 ORDER BY created_at DESC LIMIT ?2"
17 )?;
18 let rows: Vec<MatchInfo> = stmt
19 .query_map(params![pattern, MAX_CANDIDATES], |r| {
20 Ok(MatchInfo {
21 id: r.get(0)?,
22 source: r.get(1)?,
23 content_type: r.get(2)?,
24 created_at: r.get(3)?,
25 preview: r.get(4)?,
26 })
27 })?
28 .filter_map(|r| r.ok())
29 .collect();
30 Ok(rows)
31 })?;
32 match matches.as_slice() {
33 [] => Err(ResolveError::NotFound),
34 [one] => Ok(one.id.clone()),
35 _many => Err(ResolveError::Ambiguous {
36 candidates: matches,
37 }),
38 }
39}
40
41pub fn resolve_device_id(store: &Store, prefix: &str) -> Result<String, ResolveError> {
42 if prefix.len() < MIN_PREFIX {
43 return Err(ResolveError::TooShort);
44 }
45 let pattern = format!("{prefix}%");
46 let mut matches: Vec<MatchInfo> = store.with_conn(|conn| {
47 let mut stmt = conn.prepare(
48 "SELECT id, hostname AS source, '' AS content_type, COALESCE(last_push_at, 0), COALESCE(nickname, hostname)
49 FROM devices WHERE id LIKE ?1 LIMIT ?2"
50 )?;
51 let rows: Vec<MatchInfo> = stmt
52 .query_map(params![pattern, MAX_CANDIDATES], |r| {
53 Ok(MatchInfo {
54 id: r.get(0)?,
55 source: r.get(1)?,
56 content_type: r.get(2)?,
57 created_at: r.get(3)?,
58 preview: r.get(4)?,
59 })
60 })?
61 .filter_map(|r| r.ok())
62 .collect();
63 Ok(rows)
64 })?;
65 match matches.len() {
66 0 => Err(ResolveError::NotFound),
67 1 => Ok(matches.remove(0).id),
68 _ => Err(ResolveError::Ambiguous {
69 candidates: matches,
70 }),
71 }
72}