A better Rust ATProto crate

various little doc formatting fixes

Orual 87879fab 5f91bd57

Changed files
+44 -17
crates
+1
Cargo.lock
··· 1140 1140 "http", 1141 1141 "jacquard-api", 1142 1142 "jacquard-common", 1143 + "jacquard-derive", 1143 1144 "miette", 1144 1145 "reqwest", 1145 1146 "serde",
+1 -1
crates/jacquard-api/Cargo.toml
··· 12 12 description.workspace = true 13 13 14 14 [features] 15 - default = ["app_bsky", "com_atproto", "tools_ozone", "chat_bsky"] 15 + default = [ "com_atproto"] 16 16 app_bsky = [] 17 17 chat_bsky = [] 18 18 com_atproto = []
+7
crates/jacquard-api/src/lib.rs
··· 3 3 // This file was automatically generated from Lexicon schemas. 4 4 // Any manual changes will be overwritten on the next regeneration. 5 5 6 + #[cfg(feature = "app_bsky")] 6 7 pub mod app_bsky; 8 + 9 + #[cfg(feature = "chat_bsky")] 7 10 pub mod chat_bsky; 11 + 12 + #[cfg(feature = "com_atproto")] 8 13 pub mod com_atproto; 14 + 15 + #[cfg(feature = "tools_ozone")] 9 16 pub mod tools_ozone;
+1 -1
crates/jacquard-common/src/cowstr.rs
··· 9 9 10 10 use crate::IntoStatic; 11 11 12 - /// Shamelessly copied from https://github.com/bearcove/merde 12 + /// Shamelessly copied from [](https://github.com/bearcove/merde) 13 13 /// A copy-on-write immutable string type that uses [`SmolStr`] for 14 14 /// the "owned" variant. 15 15 ///
+1 -1
crates/jacquard-common/src/into_static.rs
··· 7 7 use std::hash::Hash; 8 8 use std::sync::Arc; 9 9 10 - /// Shamelessly copied from https://github.com/bearcove/merde 10 + /// Shamelessly copied from [](https://github.com/bearcove/merde) 11 11 /// Allow turning a value into an "owned" variant, which can then be 12 12 /// returned, moved, etc. 13 13 ///
+1 -1
crates/jacquard-common/src/types/aturi.rs
··· 14 14 15 15 /// at:// URI type 16 16 /// 17 - /// based on the regex here: https://github.com/bluesky-social/atproto/blob/main/packages/syntax/src/aturi_validation.ts 17 + /// based on the regex here: [](https://github.com/bluesky-social/atproto/blob/main/packages/syntax/src/aturi_validation.ts) 18 18 /// 19 19 /// Doesn't support the query segment, but then neither does the Typescript SDK. 20 20 #[derive(PartialEq, Eq, Debug)]
+2 -2
crates/jacquard-common/src/types/collection.rs
··· 26 26 /// 27 27 /// Panics if [`Self::NSID`] is not a valid NSID. 28 28 /// 29 - /// [`Nsid`]: string::Nsid 29 + /// [`Nsid`]: crate::types::string::Nsid 30 30 fn nsid() -> crate::types::nsid::Nsid<'static> { 31 31 Nsid::new_static(Self::NSID).expect("should be valid NSID") 32 32 } ··· 39 39 /// > [`RecordKey`]. 40 40 /// 41 41 /// [Repo Data Structure v3]: https://atproto.com/specs/repository#repo-data-structure-v3 42 - /// [`Nsid`]: string::Nsid 42 + /// [`Nsid`]: crate::types::string::Nsid 43 43 fn repo_path<'u, T: RecordKeyType>( 44 44 rkey: &'u crate::types::recordkey::RecordKey<T>, 45 45 ) -> UriPath<'u> {
+1 -1
crates/jacquard-common/src/types/did.rs
··· 76 76 /// Infallible constructor for when you *know* the string is a valid DID. 77 77 /// Will panic on invalid DIDs. If you're manually decoding atproto records 78 78 /// or API values you know are valid (rather than using serde), this is the one to use. 79 - /// The From<String> and From<CowStr> impls use the same logic. 79 + /// The `From<String>` and `From<CowStr>` impls use the same logic. 80 80 pub fn raw(did: &'d str) -> Self { 81 81 let did = did.strip_prefix("at://").unwrap_or(did); 82 82 if did.len() > 2048 {
+1 -1
crates/jacquard-common/src/types/handle.rs
··· 95 95 /// Infallible constructor for when you *know* the string is a valid handle. 96 96 /// Will panic on invalid handles. If you're manually decoding atproto records 97 97 /// or API values you know are valid (rather than using serde), this is the one to use. 98 - /// The From<String> and From<CowStr> impls use the same logic. 98 + /// The `From<String>` and `From<CowStr>` impls use the same logic. 99 99 /// 100 100 /// Accepts (and strips) preceding '@' or 'at://' if present 101 101 pub fn raw(handle: &'h str) -> Self {
+1 -1
crates/jacquard-common/src/types/ident.rs
··· 49 49 /// Infallible constructor for when you *know* the string is a valid identifier. 50 50 /// Will panic on invalid identifiers. If you're manually decoding atproto records 51 51 /// or API values you know are valid (rather than using serde), this is the one to use. 52 - /// The From<String> and From<CowStr> impls use the same logic. 52 + /// The `From<String>` and `From<CowStr>` impls use the same logic. 53 53 pub fn raw(ident: &'i str) -> Self { 54 54 if let Ok(did) = ident.parse() { 55 55 AtIdentifier::Did(did)
+1 -1
crates/jacquard-common/src/types/language.rs
··· 34 34 /// Infallible constructor for when you *know* the string is a valid IETF language tag. 35 35 /// Will panic on invalid tag. If you're manually decoding atproto records 36 36 /// or API values you know are valid (rather than using serde), this is the one to use. 37 - /// The From<String> and From<CowStr> impls use the same logic. 37 + /// The `From<String>` and `From<CowStr>` impls use the same logic. 38 38 pub fn raw(lang: impl AsRef<str>) -> Self { 39 39 let lang = lang.as_ref(); 40 40 let tag = langtag::LangTag::new(lang).expect("valid IETF language tag");
+1 -1
crates/jacquard-common/src/types/nsid.rs
··· 71 71 /// Infallible constructor for when you *know* the string is a valid NSID. 72 72 /// Will panic on invalid NSIDs. If you're manually decoding atproto records 73 73 /// or API values you know are valid (rather than using serde), this is the one to use. 74 - /// The From<String> and From<CowStr> impls use the same logic. 74 + /// The `From<String>` and `From<CowStr>` impls use the same logic. 75 75 pub fn raw(nsid: &'n str) -> Self { 76 76 if nsid.len() > 317 { 77 77 panic!("NSID too long")
+3 -3
crates/jacquard-common/src/types/recordkey.rs
··· 14 14 /// This is deliberately public (so that consumers can develop specialized record key types), 15 15 /// but is marked as unsafe, because the implementer is expected to uphold the invariants 16 16 /// required by this trait, namely compliance with the [spec](https://atproto.com/specs/record-key) 17 - /// as described by [`RKEY_REGEX`](RKEY_REGEX). 17 + /// as described by [`RKEY_REGEX`]. 18 18 /// 19 19 /// This crate provides implementations for TID, NSID, literals, and generic strings 20 20 pub unsafe trait RecordKeyType: Clone + Serialize { ··· 57 57 } 58 58 59 59 /// ATProto Record Key (type `any`) 60 - /// Catch-all for any string meeting the overall Record Key requirements detailed https://atproto.com/specs/record-key 60 + /// Catch-all for any string meeting the overall Record Key requirements detailed [](https://atproto.com/specs/record-key) 61 61 #[derive(Clone, PartialEq, Eq, Serialize, Hash)] 62 62 #[serde(transparent)] 63 63 #[repr(transparent)] ··· 298 298 /// Infallible constructor for when you *know* the string is a valid rkey. 299 299 /// Will panic on invalid rkeys. If you're manually decoding atproto records 300 300 /// or API values you know are valid (rather than using serde), this is the one to use. 301 - /// The From<String> and From<CowStr> impls use the same logic. 301 + /// The `From<String>` and `From<CowStr>` impls use the same logic. 302 302 pub fn raw(rkey: &str) -> Self { 303 303 if !rkey.eq_ignore_ascii_case(T::LITERAL) { 304 304 panic!(
+1 -1
crates/jacquard-common/src/types/tid.rs
··· 71 71 /// Infallible constructor for when you *know* the string is a valid TID. 72 72 /// Will panic on invalid TID. If you're manually decoding atproto records 73 73 /// or API values you know are valid (rather than using serde), this is the one to use. 74 - /// The From<String> and From<CowStr> impls use the same logic. 74 + /// The `From<String>` and `From<CowStr>` impls use the same logic. 75 75 pub fn raw(tid: impl AsRef<str>) -> Self { 76 76 let tid = tid.as_ref(); 77 77 if tid.len() != 13 {
+10 -1
crates/jacquard-lexicon/src/codegen.rs
··· 1089 1089 path 1090 1090 }; 1091 1091 1092 + let is_root = dir.components().count() == 0; 1092 1093 let mods: Vec<_> = module_names 1093 1094 .iter() 1094 1095 .map(|name| { 1095 1096 let ident = syn::Ident::new(name, proc_macro2::Span::call_site()); 1096 - quote! { pub mod #ident; } 1097 + if is_root { 1098 + // Top-level modules get feature gates 1099 + quote! { 1100 + #[cfg(feature = #name)] 1101 + pub mod #ident; 1102 + } 1103 + } else { 1104 + quote! { pub mod #ident; } 1105 + } 1097 1106 }) 1098 1107 .collect(); 1099 1108
+6 -1
crates/jacquard/Cargo.toml
··· 6 6 version.workspace = true 7 7 edition.workspace = true 8 8 9 - # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 + [features] 10 + default = ["api_all"] 11 + derive = ["dep:jacquard-derive"] 12 + api = ["jacquard-api/com_atproto"] 13 + api_all = ["api", "jacquard-api/app_bsky", "jacquard-api/chat_bsky", "jacquard-api/tools_ozone"] 10 14 11 15 [lib] 12 16 name = "jacquard" ··· 22 26 http = "1.3.1" 23 27 jacquard-api = { version = "0.1.0", path = "../jacquard-api" } 24 28 jacquard-common = { path = "../jacquard-common" } 29 + jacquard-derive = { path = "../jacquard-derive", optional = true } 25 30 miette = "7.6.0" 26 31 reqwest = { version = "0.12.23", default-features = false, features = ["charset", "http2", "json", "system-proxy", "gzip", "rustls-tls"] } 27 32 serde = { version = "1.0", features = ["derive"] }
+5
crates/jacquard/src/lib.rs
··· 1 1 pub mod client; 2 2 3 3 // Re-export common types 4 + #[cfg(feature = "api")] 5 + pub use jacquard_api as api; 4 6 pub use jacquard_common::*; 7 + 8 + #[cfg(feature = "derive")] 9 + pub use jacquard_derive::*;