very fast at protocol indexer with flexible filtering, xrpc queries, cursor-backed event stream, and more, built on fjall
rust fjall at-protocol atproto indexer
58
fork

Configure Feed

Select the types of activity you want to include in your feed.

[backlinks] rewrite code to look better and use smolstr where we can

dawn a657c0c9 1aaaaee1

+17 -21
+6 -6
src/backlinks/links.rs
··· 1 1 use jacquard_common::Data; 2 2 use jacquard_common::types::string::AtprotoStr; 3 3 use jacquard_common::types::uri::Uri; 4 - use smol_str::SmolStr; 4 + use smol_str::{SmolStr, format_smolstr}; 5 5 6 6 pub struct Link { 7 7 /// dotted field path within the record, e.g. `.subject.uri` or `.facets[].features[app.bsky.richtext.facet#link].uri` ··· 12 12 /// extract all link targets from a record, with their field paths. 13 13 /// 14 14 /// paths follow the same convention as constellation: 15 - /// - start with `.` (root-level field `subject` → `.subject`) 15 + /// - start with `.` (root-level field `subject` -> `.subject`) 16 16 /// - object keys: `{parent}.{key}` 17 17 /// - plain array elements: `{parent}[]` 18 18 /// - typed array elements (objects with `$type`): `{parent}[{$type}]` ··· 50 50 _ => None, 51 51 }); 52 52 match type_tag { 53 - Some(t) => format!("{path}[{t}]"), 54 - None => format!("{path}[]"), 53 + Some(t) => format_smolstr!("{path}[{t}]"), 54 + None => format_smolstr!("{path}[]"), 55 55 } 56 56 } 57 - _ => format!("{path}[]"), 57 + _ => format_smolstr!("{path}[]"), 58 58 }; 59 59 walk(item, &child_path, links); 60 60 } 61 61 } 62 62 Data::Object(obj) => { 63 63 for (k, v) in &obj.0 { 64 - walk(v, &format!("{path}.{k}"), links); 64 + walk(v, &format_smolstr!("{path}.{k}"), links); 65 65 } 66 66 } 67 67 _ => {}
+1 -1
src/backlinks/mod.rs
··· 148 148 let mut next_cursor = None; 149 149 150 150 for item in iter { 151 - let (key, _) = item.into_inner().into_diagnostic()?; 151 + let key = item.key().into_diagnostic()?; 152 152 if !key.starts_with(scan_prefix.as_slice()) { 153 153 break; 154 154 }
+9 -13
src/backlinks/store.rs
··· 58 58 /// path should include the leading `.` (e.g. `.subject.uri`). always ends with `|`. 59 59 pub fn reverse_scan_prefix(target: &str, collection: Option<&str>, path: Option<&str>) -> Vec<u8> { 60 60 let col_len = collection.map_or(0, |c| c.len() + 1); 61 - let path_len = if collection.is_some() { 62 - path.map_or(0, |p| p.len() + 1) 63 - } else { 64 - 0 65 - }; 61 + let path_len = collection 62 + .is_some() 63 + .then(|| path.map_or(0, |p| p.len() + 1)) 64 + .unwrap_or(0); 66 65 let mut prefix = Vec::with_capacity(2 + target.len() + 1 + col_len + path_len); 67 66 prefix.push(b'r'); 68 67 prefix.push(SEP); ··· 95 94 /// reverse key format: `r|{target}|{collection}|{path}|{did}|{rkey}` 96 95 /// parses the last four `|`-separated segments from the right. 97 96 pub fn source_from_reverse_key(key: &[u8]) -> Option<(&str, &str, &str, &str)> { 98 - let rkey_sep = key.iter().rposition(|&b| b == SEP)?; 99 - let rkey = std::str::from_utf8(&key[rkey_sep + 1..]).ok()?; 100 - let did_sep = key[..rkey_sep].iter().rposition(|&b| b == SEP)?; 101 - let did = std::str::from_utf8(&key[did_sep + 1..rkey_sep]).ok()?; 102 - let path_sep = key[..did_sep].iter().rposition(|&b| b == SEP)?; 103 - let path = std::str::from_utf8(&key[path_sep + 1..did_sep]).ok()?; 104 - let col_sep = key[..path_sep].iter().rposition(|&b| b == SEP)?; 105 - let col = std::str::from_utf8(&key[col_sep + 1..path_sep]).ok()?; 97 + let mut parts = key.rsplit(|&b| b == SEP); 98 + let rkey = std::str::from_utf8(parts.next()?).ok()?; 99 + let did = std::str::from_utf8(parts.next()?).ok()?; 100 + let path = std::str::from_utf8(parts.next()?).ok()?; 101 + let col = std::str::from_utf8(parts.next()?).ok()?; 106 102 Some((col, path, did, rkey)) 107 103 } 108 104
+1 -1
src/control.rs
··· 61 61 /// let hydrant = Hydrant::from_env().await?; 62 62 /// 63 63 /// tokio::select! { 64 - /// r = hydrant.run() => r, 64 + /// r = hydrant.run()? => r, 65 65 /// r = hydrant.serve(3000) => r, 66 66 /// } 67 67 /// }