A better Rust ATProto crate

test directories reworked a bit, prepping for crates.io release

Orual df48cd53 590fc90f

Changed files
+442 -1454
crates
jacquard
jacquard-api
jacquard-common
jacquard-derive
jacquard-lexicon
nix
modules
+20
Cargo.lock
··· 618 618 ] 619 619 620 620 [[package]] 621 + name = "fastrand" 622 + version = "2.3.0" 623 + source = "registry+https://github.com/rust-lang/crates.io-index" 624 + checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 625 + 626 + [[package]] 621 627 name = "find-msvc-tools" 622 628 version = "0.1.2" 623 629 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1225 1231 "serde_repr", 1226 1232 "serde_with", 1227 1233 "syn 2.0.106", 1234 + "tempfile", 1228 1235 "thiserror 2.0.17", 1229 1236 ] 1230 1237 ··· 2163 2170 dependencies = [ 2164 2171 "core-foundation-sys", 2165 2172 "libc", 2173 + ] 2174 + 2175 + [[package]] 2176 + name = "tempfile" 2177 + version = "3.23.0" 2178 + source = "registry+https://github.com/rust-lang/crates.io-index" 2179 + checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" 2180 + dependencies = [ 2181 + "fastrand", 2182 + "getrandom 0.3.3", 2183 + "once_cell", 2184 + "rustix", 2185 + "windows-sys 0.60.2", 2166 2186 ] 2167 2187 2168 2188 [[package]]
+2 -2
Cargo.toml
··· 11 11 keywords = ["atproto", "at protocol", "bluesky", "api", "client"] 12 12 categories = ["api-bindings", "web-programming::http-client"] 13 13 readme = "README.md" 14 - documentation = "https://docs.rs/jacquard" 15 14 exclude = [".direnv"] 16 - 15 + homepage = "https://tangled.org/@nonbinary.computer/jacquard" 16 + license-file = "LICENSE" 17 17 18 18 description = "Simple and powerful AT Protocol client library for Rust" 19 19
+369 -17
LICENSE
··· 1 - MIT License 1 + Mozilla Public License Version 2.0 2 + ================================== 3 + 4 + 1. Definitions 5 + -------------- 6 + 7 + 1.1. "Contributor" 8 + means each individual or legal entity that creates, contributes to 9 + the creation of, or owns Covered Software. 10 + 11 + 1.2. "Contributor Version" 12 + means the combination of the Contributions of others (if any) used 13 + by a Contributor and that particular Contributor's Contribution. 14 + 15 + 1.3. "Contribution" 16 + means Covered Software of a particular Contributor. 17 + 18 + 1.4. "Covered Software" 19 + means Source Code Form to which the initial Contributor has attached 20 + the notice in Exhibit A, the Executable Form of such Source Code 21 + Form, and Modifications of such Source Code Form, in each case 22 + including portions thereof. 23 + 24 + 1.5. "Incompatible With Secondary Licenses" 25 + means 26 + 27 + (a) that the initial Contributor has attached the notice described 28 + in Exhibit B to the Covered Software; or 29 + 30 + (b) that the Covered Software was made available under the terms of 31 + version 1.1 or earlier of the License, but not also under the 32 + terms of a Secondary License. 33 + 34 + 1.6. "Executable Form" 35 + means any form of the work other than Source Code Form. 36 + 37 + 1.7. "Larger Work" 38 + means a work that combines Covered Software with other material, in 39 + a separate file or files, that is not Covered Software. 40 + 41 + 1.8. "License" 42 + means this document. 43 + 44 + 1.9. "Licensable" 45 + means having the right to grant, to the maximum extent possible, 46 + whether at the time of the initial grant or subsequently, any and 47 + all of the rights conveyed by this License. 48 + 49 + 1.10. "Modifications" 50 + means any of the following: 51 + 52 + (a) any file in Source Code Form that results from an addition to, 53 + deletion from, or modification of the contents of Covered 54 + Software; or 55 + 56 + (b) any new file in Source Code Form that contains any Covered 57 + Software. 58 + 59 + 1.11. "Patent Claims" of a Contributor 60 + means any patent claim(s), including without limitation, method, 61 + process, and apparatus claims, in any patent Licensable by such 62 + Contributor that would be infringed, but for the grant of the 63 + License, by the making, using, selling, offering for sale, having 64 + made, import, or transfer of either its Contributions or its 65 + Contributor Version. 66 + 67 + 1.12. "Secondary License" 68 + means either the GNU General Public License, Version 2.0, the GNU 69 + Lesser General Public License, Version 2.1, the GNU Affero General 70 + Public License, Version 3.0, or any later versions of those 71 + licenses. 72 + 73 + 1.13. "Source Code Form" 74 + means the form of the work preferred for making modifications. 75 + 76 + 1.14. "You" (or "Your") 77 + means an individual or a legal entity exercising rights under this 78 + License. For legal entities, "You" includes any entity that 79 + controls, is controlled by, or is under common control with You. For 80 + purposes of this definition, "control" means (a) the power, direct 81 + or indirect, to cause the direction or management of such entity, 82 + whether by contract or otherwise, or (b) ownership of more than 83 + fifty percent (50%) of the outstanding shares or beneficial 84 + ownership of such entity. 85 + 86 + 2. License Grants and Conditions 87 + -------------------------------- 88 + 89 + 2.1. Grants 90 + 91 + Each Contributor hereby grants You a world-wide, royalty-free, 92 + non-exclusive license: 93 + 94 + (a) under intellectual property rights (other than patent or trademark) 95 + Licensable by such Contributor to use, reproduce, make available, 96 + modify, display, perform, distribute, and otherwise exploit its 97 + Contributions, either on an unmodified basis, with Modifications, or 98 + as part of a Larger Work; and 2 99 3 - Copyright (c) 2023 Orual 100 + (b) under Patent Claims of such Contributor to make, use, sell, offer 101 + for sale, have made, import, and otherwise transfer either its 102 + Contributions or its Contributor Version. 4 103 5 - Permission is hereby granted, free of charge, to any person obtaining a copy 6 - of this software and associated documentation files (the "Software"), to deal 7 - in the Software without restriction, including without limitation the rights 8 - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 - copies of the Software, and to permit persons to whom the Software is 10 - furnished to do so, subject to the following conditions: 104 + 2.2. Effective Date 11 105 12 - The above copyright notice and this permission notice shall be included in all 13 - copies or substantial portions of the Software. 106 + The licenses granted in Section 2.1 with respect to any Contribution 107 + become effective for each Contribution on the date the Contributor first 108 + distributes such Contribution. 14 109 15 - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 - SOFTWARE. 110 + 2.3. Limitations on Grant Scope 111 + 112 + The licenses granted in this Section 2 are the only rights granted under 113 + this License. No additional rights or licenses will be implied from the 114 + distribution or licensing of Covered Software under this License. 115 + Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 + Contributor: 117 + 118 + (a) for any code that a Contributor has removed from Covered Software; 119 + or 120 + 121 + (b) for infringements caused by: (i) Your and any other third party's 122 + modifications of Covered Software, or (ii) the combination of its 123 + Contributions with other software (except as part of its Contributor 124 + Version); or 125 + 126 + (c) under Patent Claims infringed by Covered Software in the absence of 127 + its Contributions. 128 + 129 + This License does not grant any rights in the trademarks, service marks, 130 + or logos of any Contributor (except as may be necessary to comply with 131 + the notice requirements in Section 3.4). 132 + 133 + 2.4. Subsequent Licenses 134 + 135 + No Contributor makes additional grants as a result of Your choice to 136 + distribute the Covered Software under a subsequent version of this 137 + License (see Section 10.2) or under the terms of a Secondary License (if 138 + permitted under the terms of Section 3.3). 139 + 140 + 2.5. Representation 141 + 142 + Each Contributor represents that the Contributor believes its 143 + Contributions are its original creation(s) or it has sufficient rights 144 + to grant the rights to its Contributions conveyed by this License. 145 + 146 + 2.6. Fair Use 147 + 148 + This License is not intended to limit any rights You have under 149 + applicable copyright doctrines of fair use, fair dealing, or other 150 + equivalents. 151 + 152 + 2.7. Conditions 153 + 154 + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 + in Section 2.1. 156 + 157 + 3. Responsibilities 158 + ------------------- 159 + 160 + 3.1. Distribution of Source Form 161 + 162 + All distribution of Covered Software in Source Code Form, including any 163 + Modifications that You create or to which You contribute, must be under 164 + the terms of this License. You must inform recipients that the Source 165 + Code Form of the Covered Software is governed by the terms of this 166 + License, and how they can obtain a copy of this License. You may not 167 + attempt to alter or restrict the recipients' rights in the Source Code 168 + Form. 169 + 170 + 3.2. Distribution of Executable Form 171 + 172 + If You distribute Covered Software in Executable Form then: 173 + 174 + (a) such Covered Software must also be made available in Source Code 175 + Form, as described in Section 3.1, and You must inform recipients of 176 + the Executable Form how they can obtain a copy of such Source Code 177 + Form by reasonable means in a timely manner, at a charge no more 178 + than the cost of distribution to the recipient; and 179 + 180 + (b) You may distribute such Executable Form under the terms of this 181 + License, or sublicense it under different terms, provided that the 182 + license for the Executable Form does not attempt to limit or alter 183 + the recipients' rights in the Source Code Form under this License. 184 + 185 + 3.3. Distribution of a Larger Work 186 + 187 + You may create and distribute a Larger Work under terms of Your choice, 188 + provided that You also comply with the requirements of this License for 189 + the Covered Software. If the Larger Work is a combination of Covered 190 + Software with a work governed by one or more Secondary Licenses, and the 191 + Covered Software is not Incompatible With Secondary Licenses, this 192 + License permits You to additionally distribute such Covered Software 193 + under the terms of such Secondary License(s), so that the recipient of 194 + the Larger Work may, at their option, further distribute the Covered 195 + Software under the terms of either this License or such Secondary 196 + License(s). 197 + 198 + 3.4. Notices 199 + 200 + You may not remove or alter the substance of any license notices 201 + (including copyright notices, patent notices, disclaimers of warranty, 202 + or limitations of liability) contained within the Source Code Form of 203 + the Covered Software, except that You may alter any license notices to 204 + the extent required to remedy known factual inaccuracies. 205 + 206 + 3.5. Application of Additional Terms 207 + 208 + You may choose to offer, and to charge a fee for, warranty, support, 209 + indemnity or liability obligations to one or more recipients of Covered 210 + Software. However, You may do so only on Your own behalf, and not on 211 + behalf of any Contributor. You must make it absolutely clear that any 212 + such warranty, support, indemnity, or liability obligation is offered by 213 + You alone, and You hereby agree to indemnify every Contributor for any 214 + liability incurred by such Contributor as a result of warranty, support, 215 + indemnity or liability terms You offer. You may include additional 216 + disclaimers of warranty and limitations of liability specific to any 217 + jurisdiction. 218 + 219 + 4. Inability to Comply Due to Statute or Regulation 220 + --------------------------------------------------- 221 + 222 + If it is impossible for You to comply with any of the terms of this 223 + License with respect to some or all of the Covered Software due to 224 + statute, judicial order, or regulation then You must: (a) comply with 225 + the terms of this License to the maximum extent possible; and (b) 226 + describe the limitations and the code they affect. Such description must 227 + be placed in a text file included with all distributions of the Covered 228 + Software under this License. Except to the extent prohibited by statute 229 + or regulation, such description must be sufficiently detailed for a 230 + recipient of ordinary skill to be able to understand it. 231 + 232 + 5. Termination 233 + -------------- 234 + 235 + 5.1. The rights granted under this License will terminate automatically 236 + if You fail to comply with any of its terms. However, if You become 237 + compliant, then the rights granted under this License from a particular 238 + Contributor are reinstated (a) provisionally, unless and until such 239 + Contributor explicitly and finally terminates Your grants, and (b) on an 240 + ongoing basis, if such Contributor fails to notify You of the 241 + non-compliance by some reasonable means prior to 60 days after You have 242 + come back into compliance. Moreover, Your grants from a particular 243 + Contributor are reinstated on an ongoing basis if such Contributor 244 + notifies You of the non-compliance by some reasonable means, this is the 245 + first time You have received notice of non-compliance with this License 246 + from such Contributor, and You become compliant prior to 30 days after 247 + Your receipt of the notice. 248 + 249 + 5.2. If You initiate litigation against any entity by asserting a patent 250 + infringement claim (excluding declaratory judgment actions, 251 + counter-claims, and cross-claims) alleging that a Contributor Version 252 + directly or indirectly infringes any patent, then the rights granted to 253 + You by any and all Contributors for the Covered Software under Section 254 + 2.1 of this License shall terminate. 255 + 256 + 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 + end user license agreements (excluding distributors and resellers) which 258 + have been validly granted by You or Your distributors under this License 259 + prior to termination shall survive termination. 260 + 261 + ************************************************************************ 262 + * * 263 + * 6. Disclaimer of Warranty * 264 + * ------------------------- * 265 + * * 266 + * Covered Software is provided under this License on an "as is" * 267 + * basis, without warranty of any kind, either expressed, implied, or * 268 + * statutory, including, without limitation, warranties that the * 269 + * Covered Software is free of defects, merchantable, fit for a * 270 + * particular purpose or non-infringing. The entire risk as to the * 271 + * quality and performance of the Covered Software is with You. * 272 + * Should any Covered Software prove defective in any respect, You * 273 + * (not any Contributor) assume the cost of any necessary servicing, * 274 + * repair, or correction. This disclaimer of warranty constitutes an * 275 + * essential part of this License. No use of any Covered Software is * 276 + * authorized under this License except under this disclaimer. * 277 + * * 278 + ************************************************************************ 279 + 280 + ************************************************************************ 281 + * * 282 + * 7. Limitation of Liability * 283 + * -------------------------- * 284 + * * 285 + * Under no circumstances and under no legal theory, whether tort * 286 + * (including negligence), contract, or otherwise, shall any * 287 + * Contributor, or anyone who distributes Covered Software as * 288 + * permitted above, be liable to You for any direct, indirect, * 289 + * special, incidental, or consequential damages of any character * 290 + * including, without limitation, damages for lost profits, loss of * 291 + * goodwill, work stoppage, computer failure or malfunction, or any * 292 + * and all other commercial damages or losses, even if such party * 293 + * shall have been informed of the possibility of such damages. This * 294 + * limitation of liability shall not apply to liability for death or * 295 + * personal injury resulting from such party's negligence to the * 296 + * extent applicable law prohibits such limitation. Some * 297 + * jurisdictions do not allow the exclusion or limitation of * 298 + * incidental or consequential damages, so this exclusion and * 299 + * limitation may not apply to You. * 300 + * * 301 + ************************************************************************ 302 + 303 + 8. Litigation 304 + ------------- 305 + 306 + Any litigation relating to this License may be brought only in the 307 + courts of a jurisdiction where the defendant maintains its principal 308 + place of business and such litigation shall be governed by laws of that 309 + jurisdiction, without reference to its conflict-of-law provisions. 310 + Nothing in this Section shall prevent a party's ability to bring 311 + cross-claims or counter-claims. 312 + 313 + 9. Miscellaneous 314 + ---------------- 315 + 316 + This License represents the complete agreement concerning the subject 317 + matter hereof. If any provision of this License is held to be 318 + unenforceable, such provision shall be reformed only to the extent 319 + necessary to make it enforceable. Any law or regulation which provides 320 + that the language of a contract shall be construed against the drafter 321 + shall not be used to construe this License against a Contributor. 322 + 323 + 10. Versions of the License 324 + --------------------------- 325 + 326 + 10.1. New Versions 327 + 328 + Mozilla Foundation is the license steward. Except as provided in Section 329 + 10.3, no one other than the license steward has the right to modify or 330 + publish new versions of this License. Each version will be given a 331 + distinguishing version number. 332 + 333 + 10.2. Effect of New Versions 334 + 335 + You may distribute the Covered Software under the terms of the version 336 + of the License under which You originally received the Covered Software, 337 + or under the terms of any subsequent version published by the license 338 + steward. 339 + 340 + 10.3. Modified Versions 341 + 342 + If you create software not governed by this License, and you want to 343 + create a new license for such software, you may create and use a 344 + modified version of this License if you rename the license and remove 345 + any references to the name of the license steward (except to note that 346 + such modified license differs from this License). 347 + 348 + 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 + Licenses 350 + 351 + If You choose to distribute Source Code Form that is Incompatible With 352 + Secondary Licenses under the terms of this version of the License, the 353 + notice described in Exhibit B of this License must be attached. 354 + 355 + Exhibit A - Source Code Form License Notice 356 + ------------------------------------------- 357 + 358 + This Source Code Form is subject to the terms of the Mozilla Public 359 + License, v. 2.0. If a copy of the MPL was not distributed with this 360 + file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 + 362 + If it is not possible or desirable to put the notice in a particular 363 + file, then You may include the notice in a location (such as a LICENSE 364 + file in a relevant directory) where a recipient would be likely to look 365 + for such a notice. 366 + 367 + You may add additional accurate notices of copyright ownership. 368 + 369 + Exhibit B - "Incompatible With Secondary Licenses" Notice 370 + --------------------------------------------------------- 371 + 372 + This Source Code Form is "Incompatible With Secondary Licenses", as 373 + defined by the Mozilla Public License, v. 2.0.
+13 -11
README.md
··· 2 2 3 3 A suite of Rust crates for the AT Protocol. 4 4 5 + 6 + ## Goals 7 + 8 + - Validated, spec-compliant, easy to work with, and performant baseline types (including typed at:// uris) 9 + - Batteries-included, but easily replaceable batteries. 10 + - Easy to extend with custom lexicons 11 + - lexicon Value type for working with unknown atproto data (dag-cbor or json) 12 + - order of magnitude less boilerplate than some existing crates 13 + - either the codegen produces code that's easy to work with, or there are good handwritten wrappers 14 + - didDoc type with helper methods for getting handles, multikey, and PDS endpoint 15 + - use as much or as little from the crates as you need 16 + 17 + 5 18 ## Example 6 19 7 20 Dead simple api client. Logs in, prints the latest 5 posts from your timeline. ··· 72 85 Ok(()) 73 86 } 74 87 ``` 75 - 76 - ## Goals 77 - 78 - - Validated, spec-compliant, easy to work with, and performant baseline types (including typed at:// uris) 79 - - Batteries-included, but easily replaceable batteries. 80 - - Easy to extend with custom lexicons 81 - - lexicon Value type for working with unknown atproto data (dag-cbor or json) 82 - - order of magnitude less boilerplate than some existing crates 83 - - either the codegen produces code that's easy to work with, or there are good handwritten wrappers 84 - - didDoc type with helper methods for getting handles, multikey, and PDS endpoint 85 - - use as much or as little from the crates as you need 86 88 87 89 ## Development 88 90
+3 -3
crates/jacquard-api/Cargo.toml
··· 8 8 keywords.workspace = true 9 9 categories.workspace = true 10 10 readme.workspace = true 11 - documentation = "https://docs.rs/jacquard-api" 12 11 exclude.workspace = true 12 + license-file.workspace = true 13 13 14 14 [features] 15 15 default = [ "com_atproto"] ··· 21 21 [dependencies] 22 22 bon = "3" 23 23 bytes = { workspace = true, features = ["serde"] } 24 - jacquard-common = { path = "../jacquard-common" } 25 - jacquard-derive = { path = "../jacquard-derive" } 24 + jacquard-common = { version = "0.1.0", path = "../jacquard-common" } 25 + jacquard-derive = { version = "0.1.0", path = "../jacquard-derive" } 26 26 miette.workspace = true 27 27 serde.workspace = true 28 28 thiserror.workspace = true
+1 -2
crates/jacquard-common/Cargo.toml
··· 8 8 keywords.workspace = true 9 9 categories.workspace = true 10 10 readme.workspace = true 11 - documentation = "https://docs.rs/jacquard-common" 12 11 exclude.workspace = true 13 - 12 + license-file.workspace = true 14 13 15 14 16 15 [dependencies]
+2 -2
crates/jacquard-derive/Cargo.toml
··· 8 8 keywords.workspace = true 9 9 categories.workspace = true 10 10 readme.workspace = true 11 - documentation = "https://docs.rs/jacquard-derive" 12 11 exclude.workspace = true 12 + license-file.workspace = true 13 13 14 14 [lib] 15 15 proc-macro = true ··· 28 28 29 29 30 30 [dev-dependencies] 31 - jacquard-common = { path = "../jacquard-common" } 31 + jacquard-common = { version = "0.1.0", path = "../jacquard-common" }
+5 -2
crates/jacquard-lexicon/Cargo.toml
··· 8 8 keywords.workspace = true 9 9 categories.workspace = true 10 10 readme.workspace = true 11 - documentation.workspace = true 12 11 exclude.workspace = true 12 + license-file.workspace = true 13 13 14 14 [[bin]] 15 15 name = "jacquard-codegen" ··· 19 19 clap.workspace = true 20 20 heck.workspace = true 21 21 itertools.workspace = true 22 - jacquard-common = { path = "../jacquard-common" } 22 + jacquard-common = { version = "0.1.0", path = "../jacquard-common" } 23 23 miette = { workspace = true, features = ["fancy"] } 24 24 prettyplease.workspace = true 25 25 proc-macro2.workspace = true ··· 30 30 serde_with.workspace = true 31 31 syn.workspace = true 32 32 thiserror.workspace = true 33 + 34 + [dev-dependencies] 35 + tempfile = { version = "3.23.0" }
+21 -35
crates/jacquard-lexicon/src/codegen.rs
··· 264 264 let mut fields = Vec::new(); 265 265 for (field_name, field_type) in &obj.properties { 266 266 let is_required = required.contains(field_name); 267 - let field_tokens = 268 - self.generate_field(nsid, parent_type_name, field_name, field_type, is_required, is_builder)?; 267 + let field_tokens = self.generate_field( 268 + nsid, 269 + parent_type_name, 270 + field_name, 271 + field_type, 272 + is_required, 273 + is_builder, 274 + )?; 269 275 fields.push(field_tokens); 270 276 } 271 277 ··· 1667 1673 LexXrpcParametersProperty::Integer(_) => (quote! { i64 }, false, false), 1668 1674 LexXrpcParametersProperty::String(s) => { 1669 1675 let is_cowstr = s.format.is_none(); // CowStr for plain strings 1670 - (self.string_to_rust_type(s), self.string_needs_lifetime(s), is_cowstr) 1671 - } 1672 - LexXrpcParametersProperty::Unknown(_) => { 1673 - (quote! { jacquard_common::types::value::Data<'a> }, true, false) 1676 + ( 1677 + self.string_to_rust_type(s), 1678 + self.string_needs_lifetime(s), 1679 + is_cowstr, 1680 + ) 1674 1681 } 1682 + LexXrpcParametersProperty::Unknown(_) => ( 1683 + quote! { jacquard_common::types::value::Data<'a> }, 1684 + true, 1685 + false, 1686 + ), 1675 1687 LexXrpcParametersProperty::Array(arr) => { 1676 1688 let needs_lifetime = match &arr.items { 1677 1689 crate::lexicon::LexPrimitiveArrayItem::Boolean(_) ··· 2472 2484 LexiconCorpus::load_from_dir("tests/fixtures/test_lexicons").expect("load corpus"); 2473 2485 let codegen = CodeGenerator::new(&corpus, "test_generated"); 2474 2486 2475 - let output_dir = std::path::PathBuf::from("target/test_codegen_output"); 2487 + let tmp_dir = 2488 + tempfile::tempdir().expect("should be able to create temp directory for output"); 2489 + let output_dir = std::path::PathBuf::from(tmp_dir.path()); 2476 2490 2477 2491 // Clean up any previous test output 2478 2492 let _ = std::fs::remove_dir_all(&output_dir); ··· 2494 2508 .expect("read post.rs"); 2495 2509 assert!(post_content.contains("pub struct Post")); 2496 2510 assert!(post_content.contains("jacquard_common")); 2497 - } 2498 - 2499 - #[test] 2500 - #[ignore] // run manually: cargo test test_generate_full_atproto -- --ignored 2501 - fn test_generate_full_atproto() { 2502 - let corpus = LexiconCorpus::load_from_dir("tests/fixtures/lexicons/atproto/lexicons") 2503 - .expect("load atproto corpus"); 2504 - let codegen = CodeGenerator::new(&corpus, "crate"); 2505 - 2506 - let output_dir = std::path::PathBuf::from("../jacquard-api/src"); 2507 - 2508 - // Clean up existing generated code 2509 - if output_dir.exists() { 2510 - for entry in std::fs::read_dir(&output_dir).expect("read output dir") { 2511 - let entry = entry.expect("dir entry"); 2512 - let path = entry.path(); 2513 - if path.is_dir() { 2514 - std::fs::remove_dir_all(&path).ok(); 2515 - } else if path.extension().map_or(false, |e| e == "rs") { 2516 - std::fs::remove_file(&path).ok(); 2517 - } 2518 - } 2519 - } 2520 - 2521 - // Generate and write 2522 - codegen.write_to_disk(&output_dir).expect("write to disk"); 2523 - 2524 - println!("\n✨ Generated full atproto API to {:?}", output_dir); 2525 2511 } 2526 2512 }
-8
crates/jacquard-lexicon/target/test_codegen_output/app_bsky.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // This file was automatically generated from Lexicon schemas. 4 - // Any manual changes will be overwritten on the next regeneration. 5 - 6 - pub mod embed; 7 - pub mod feed; 8 - pub mod richtext;
-10
crates/jacquard-lexicon/target/test_codegen_output/app_bsky/embed.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // This file was automatically generated from Lexicon schemas. 4 - // Any manual changes will be overwritten on the next regeneration. 5 - 6 - pub mod external; 7 - pub mod images; 8 - pub mod record; 9 - pub mod record_with_media; 10 - pub mod video;
-99
crates/jacquard-lexicon/target/test_codegen_output/app_bsky/embed/external.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // Lexicon: app.bsky.embed.external 4 - // 5 - // This file was automatically generated from Lexicon schemas. 6 - // Any manual changes will be overwritten on the next regeneration. 7 - 8 - #[jacquard_derive::lexicon] 9 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 10 - #[serde(rename_all = "camelCase")] 11 - pub struct External<'a> { 12 - #[serde(borrow)] 13 - pub description: jacquard_common::CowStr<'a>, 14 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 15 - #[serde(borrow)] 16 - pub thumb: std::option::Option<jacquard_common::types::blob::Blob<'a>>, 17 - #[serde(borrow)] 18 - pub title: jacquard_common::CowStr<'a>, 19 - #[serde(borrow)] 20 - pub uri: jacquard_common::types::string::Uri<'a>, 21 - } 22 - 23 - impl jacquard_common::IntoStatic for External<'_> { 24 - type Output = External<'static>; 25 - fn into_static(self) -> Self::Output { 26 - External { 27 - description: self.description.into_static(), 28 - thumb: self.thumb.into_static(), 29 - title: self.title.into_static(), 30 - uri: self.uri.into_static(), 31 - extra_data: self.extra_data.into_static(), 32 - } 33 - } 34 - } 35 - 36 - ///A representation of some externally linked content (eg, a URL and 'card'), embedded in a Bluesky record (eg, a post). 37 - #[jacquard_derive::lexicon] 38 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 39 - #[serde(rename_all = "camelCase")] 40 - pub struct ExternalRecord<'a> { 41 - #[serde(borrow)] 42 - pub external: test_generated::app_bsky::embed::external::External<'a>, 43 - } 44 - 45 - impl jacquard_common::IntoStatic for ExternalRecord<'_> { 46 - type Output = ExternalRecord<'static>; 47 - fn into_static(self) -> Self::Output { 48 - ExternalRecord { 49 - external: self.external.into_static(), 50 - extra_data: self.extra_data.into_static(), 51 - } 52 - } 53 - } 54 - 55 - #[jacquard_derive::lexicon] 56 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 57 - #[serde(rename_all = "camelCase")] 58 - pub struct View<'a> { 59 - #[serde(borrow)] 60 - pub external: test_generated::app_bsky::embed::external::ViewExternal<'a>, 61 - } 62 - 63 - impl jacquard_common::IntoStatic for View<'_> { 64 - type Output = View<'static>; 65 - fn into_static(self) -> Self::Output { 66 - View { 67 - external: self.external.into_static(), 68 - extra_data: self.extra_data.into_static(), 69 - } 70 - } 71 - } 72 - 73 - #[jacquard_derive::lexicon] 74 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 75 - #[serde(rename_all = "camelCase")] 76 - pub struct ViewExternal<'a> { 77 - #[serde(borrow)] 78 - pub description: jacquard_common::CowStr<'a>, 79 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 80 - #[serde(borrow)] 81 - pub thumb: std::option::Option<jacquard_common::types::string::Uri<'a>>, 82 - #[serde(borrow)] 83 - pub title: jacquard_common::CowStr<'a>, 84 - #[serde(borrow)] 85 - pub uri: jacquard_common::types::string::Uri<'a>, 86 - } 87 - 88 - impl jacquard_common::IntoStatic for ViewExternal<'_> { 89 - type Output = ViewExternal<'static>; 90 - fn into_static(self) -> Self::Output { 91 - ViewExternal { 92 - description: self.description.into_static(), 93 - thumb: self.thumb.into_static(), 94 - title: self.title.into_static(), 95 - uri: self.uri.into_static(), 96 - extra_data: self.extra_data.into_static(), 97 - } 98 - } 99 - }
-99
crates/jacquard-lexicon/target/test_codegen_output/app_bsky/embed/images.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // Lexicon: app.bsky.embed.images 4 - // 5 - // This file was automatically generated from Lexicon schemas. 6 - // Any manual changes will be overwritten on the next regeneration. 7 - 8 - #[jacquard_derive::lexicon] 9 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 10 - #[serde(rename_all = "camelCase")] 11 - pub struct Image<'a> { 12 - ///Alt text description of the image, for accessibility. 13 - #[serde(borrow)] 14 - pub alt: jacquard_common::CowStr<'a>, 15 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 16 - #[serde(borrow)] 17 - pub aspect_ratio: std::option::Option<jacquard_common::types::value::Data<'a>>, 18 - #[serde(borrow)] 19 - pub image: jacquard_common::types::blob::Blob<'a>, 20 - } 21 - 22 - impl jacquard_common::IntoStatic for Image<'_> { 23 - type Output = Image<'static>; 24 - fn into_static(self) -> Self::Output { 25 - Image { 26 - alt: self.alt.into_static(), 27 - aspect_ratio: self.aspect_ratio.into_static(), 28 - image: self.image.into_static(), 29 - extra_data: self.extra_data.into_static(), 30 - } 31 - } 32 - } 33 - 34 - #[jacquard_derive::lexicon] 35 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 36 - #[serde(rename_all = "camelCase")] 37 - pub struct Images<'a> { 38 - #[serde(borrow)] 39 - pub images: Vec<test_generated::app_bsky::embed::images::Image<'a>>, 40 - } 41 - 42 - impl jacquard_common::IntoStatic for Images<'_> { 43 - type Output = Images<'static>; 44 - fn into_static(self) -> Self::Output { 45 - Images { 46 - images: self.images.into_static(), 47 - extra_data: self.extra_data.into_static(), 48 - } 49 - } 50 - } 51 - 52 - #[jacquard_derive::lexicon] 53 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 54 - #[serde(rename_all = "camelCase")] 55 - pub struct View<'a> { 56 - #[serde(borrow)] 57 - pub images: Vec<test_generated::app_bsky::embed::images::ViewImage<'a>>, 58 - } 59 - 60 - impl jacquard_common::IntoStatic for View<'_> { 61 - type Output = View<'static>; 62 - fn into_static(self) -> Self::Output { 63 - View { 64 - images: self.images.into_static(), 65 - extra_data: self.extra_data.into_static(), 66 - } 67 - } 68 - } 69 - 70 - #[jacquard_derive::lexicon] 71 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 72 - #[serde(rename_all = "camelCase")] 73 - pub struct ViewImage<'a> { 74 - ///Alt text description of the image, for accessibility. 75 - #[serde(borrow)] 76 - pub alt: jacquard_common::CowStr<'a>, 77 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 78 - #[serde(borrow)] 79 - pub aspect_ratio: std::option::Option<jacquard_common::types::value::Data<'a>>, 80 - ///Fully-qualified URL where a large version of the image can be fetched. May or may not be the exact original blob. For example, CDN location provided by the App View. 81 - #[serde(borrow)] 82 - pub fullsize: jacquard_common::types::string::Uri<'a>, 83 - ///Fully-qualified URL where a thumbnail of the image can be fetched. For example, CDN location provided by the App View. 84 - #[serde(borrow)] 85 - pub thumb: jacquard_common::types::string::Uri<'a>, 86 - } 87 - 88 - impl jacquard_common::IntoStatic for ViewImage<'_> { 89 - type Output = ViewImage<'static>; 90 - fn into_static(self) -> Self::Output { 91 - ViewImage { 92 - alt: self.alt.into_static(), 93 - aspect_ratio: self.aspect_ratio.into_static(), 94 - fullsize: self.fullsize.into_static(), 95 - thumb: self.thumb.into_static(), 96 - extra_data: self.extra_data.into_static(), 97 - } 98 - } 99 - }
-169
crates/jacquard-lexicon/target/test_codegen_output/app_bsky/embed/record.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // Lexicon: app.bsky.embed.record 4 - // 5 - // This file was automatically generated from Lexicon schemas. 6 - // Any manual changes will be overwritten on the next regeneration. 7 - 8 - #[jacquard_derive::lexicon] 9 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 10 - #[serde(rename_all = "camelCase")] 11 - pub struct Record<'a> { 12 - #[serde(borrow)] 13 - pub record: test_generated::com_atproto::repo::strong_ref::StrongRef<'a>, 14 - } 15 - 16 - impl jacquard_common::IntoStatic for Record<'_> { 17 - type Output = Record<'static>; 18 - fn into_static(self) -> Self::Output { 19 - Record { 20 - record: self.record.into_static(), 21 - extra_data: self.extra_data.into_static(), 22 - } 23 - } 24 - } 25 - 26 - #[jacquard_derive::lexicon] 27 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 28 - #[serde(rename_all = "camelCase")] 29 - pub struct View<'a> { 30 - #[serde(borrow)] 31 - pub record: ViewRecordRecord<'a>, 32 - } 33 - 34 - #[jacquard_derive::open_union] 35 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 36 - #[serde(tag = "$type")] 37 - #[serde(bound(deserialize = "'de: 'a"))] 38 - pub enum ViewRecordRecord<'a> {} 39 - impl jacquard_common::IntoStatic for ViewRecordRecord<'_> { 40 - type Output = ViewRecordRecord<'static>; 41 - fn into_static(self) -> Self::Output { 42 - match self { 43 - ViewRecordRecord::Unknown(v) => ViewRecordRecord::Unknown(v.into_static()), 44 - } 45 - } 46 - } 47 - 48 - impl jacquard_common::IntoStatic for View<'_> { 49 - type Output = View<'static>; 50 - fn into_static(self) -> Self::Output { 51 - View { 52 - record: self.record.into_static(), 53 - extra_data: self.extra_data.into_static(), 54 - } 55 - } 56 - } 57 - 58 - #[jacquard_derive::lexicon] 59 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 60 - #[serde(rename_all = "camelCase")] 61 - pub struct ViewBlocked<'a> { 62 - #[serde(borrow)] 63 - pub author: jacquard_common::types::value::Data<'a>, 64 - pub blocked: bool, 65 - #[serde(borrow)] 66 - pub uri: jacquard_common::types::string::AtUri<'a>, 67 - } 68 - 69 - impl jacquard_common::IntoStatic for ViewBlocked<'_> { 70 - type Output = ViewBlocked<'static>; 71 - fn into_static(self) -> Self::Output { 72 - ViewBlocked { 73 - author: self.author.into_static(), 74 - blocked: self.blocked.into_static(), 75 - uri: self.uri.into_static(), 76 - extra_data: self.extra_data.into_static(), 77 - } 78 - } 79 - } 80 - 81 - #[jacquard_derive::lexicon] 82 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 83 - #[serde(rename_all = "camelCase")] 84 - pub struct ViewDetached<'a> { 85 - pub detached: bool, 86 - #[serde(borrow)] 87 - pub uri: jacquard_common::types::string::AtUri<'a>, 88 - } 89 - 90 - impl jacquard_common::IntoStatic for ViewDetached<'_> { 91 - type Output = ViewDetached<'static>; 92 - fn into_static(self) -> Self::Output { 93 - ViewDetached { 94 - detached: self.detached.into_static(), 95 - uri: self.uri.into_static(), 96 - extra_data: self.extra_data.into_static(), 97 - } 98 - } 99 - } 100 - 101 - #[jacquard_derive::lexicon] 102 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 103 - #[serde(rename_all = "camelCase")] 104 - pub struct ViewNotFound<'a> { 105 - pub not_found: bool, 106 - #[serde(borrow)] 107 - pub uri: jacquard_common::types::string::AtUri<'a>, 108 - } 109 - 110 - impl jacquard_common::IntoStatic for ViewNotFound<'_> { 111 - type Output = ViewNotFound<'static>; 112 - fn into_static(self) -> Self::Output { 113 - ViewNotFound { 114 - not_found: self.not_found.into_static(), 115 - uri: self.uri.into_static(), 116 - extra_data: self.extra_data.into_static(), 117 - } 118 - } 119 - } 120 - 121 - #[jacquard_derive::lexicon] 122 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 123 - #[serde(rename_all = "camelCase")] 124 - pub struct ViewRecord<'a> { 125 - #[serde(borrow)] 126 - pub author: jacquard_common::types::value::Data<'a>, 127 - #[serde(borrow)] 128 - pub cid: jacquard_common::types::string::Cid<'a>, 129 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 130 - #[serde(borrow)] 131 - pub embeds: std::option::Option<Vec<jacquard_common::types::value::Data<'a>>>, 132 - pub indexed_at: jacquard_common::types::string::Datetime, 133 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 134 - #[serde(borrow)] 135 - pub labels: std::option::Option<Vec<test_generated::com_atproto::label::Label<'a>>>, 136 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 137 - pub like_count: std::option::Option<i64>, 138 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 139 - pub quote_count: std::option::Option<i64>, 140 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 141 - pub reply_count: std::option::Option<i64>, 142 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 143 - pub repost_count: std::option::Option<i64>, 144 - #[serde(borrow)] 145 - pub uri: jacquard_common::types::string::AtUri<'a>, 146 - ///The record data itself. 147 - #[serde(borrow)] 148 - pub value: jacquard_common::types::value::Data<'a>, 149 - } 150 - 151 - impl jacquard_common::IntoStatic for ViewRecord<'_> { 152 - type Output = ViewRecord<'static>; 153 - fn into_static(self) -> Self::Output { 154 - ViewRecord { 155 - author: self.author.into_static(), 156 - cid: self.cid.into_static(), 157 - embeds: self.embeds.into_static(), 158 - indexed_at: self.indexed_at.into_static(), 159 - labels: self.labels.into_static(), 160 - like_count: self.like_count.into_static(), 161 - quote_count: self.quote_count.into_static(), 162 - reply_count: self.reply_count.into_static(), 163 - repost_count: self.repost_count.into_static(), 164 - uri: self.uri.into_static(), 165 - value: self.value.into_static(), 166 - extra_data: self.extra_data.into_static(), 167 - } 168 - } 169 - }
-110
crates/jacquard-lexicon/target/test_codegen_output/app_bsky/embed/record_with_media.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // Lexicon: app.bsky.embed.recordWithMedia 4 - // 5 - // This file was automatically generated from Lexicon schemas. 6 - // Any manual changes will be overwritten on the next regeneration. 7 - 8 - #[jacquard_derive::lexicon] 9 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 10 - #[serde(rename_all = "camelCase")] 11 - pub struct RecordWithMedia<'a> { 12 - #[serde(borrow)] 13 - pub media: RecordWithMediaRecordMedia<'a>, 14 - #[serde(borrow)] 15 - pub record: test_generated::app_bsky::embed::record::Record<'a>, 16 - } 17 - 18 - #[jacquard_derive::open_union] 19 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 20 - #[serde(tag = "$type")] 21 - #[serde(bound(deserialize = "'de: 'a"))] 22 - pub enum RecordWithMediaRecordMedia<'a> { 23 - #[serde(rename = "app.bsky.embed.images")] 24 - Images(Box<test_generated::app_bsky::embed::images::Images<'a>>), 25 - #[serde(rename = "app.bsky.embed.video")] 26 - Video(Box<test_generated::app_bsky::embed::video::Video<'a>>), 27 - #[serde(rename = "app.bsky.embed.external")] 28 - External(Box<test_generated::app_bsky::embed::external::ExternalRecord<'a>>), 29 - } 30 - 31 - impl jacquard_common::IntoStatic for RecordWithMediaRecordMedia<'_> { 32 - type Output = RecordWithMediaRecordMedia<'static>; 33 - fn into_static(self) -> Self::Output { 34 - match self { 35 - RecordWithMediaRecordMedia::Images(v) => { 36 - RecordWithMediaRecordMedia::Images(v.into_static()) 37 - } 38 - RecordWithMediaRecordMedia::Video(v) => { 39 - RecordWithMediaRecordMedia::Video(v.into_static()) 40 - } 41 - RecordWithMediaRecordMedia::External(v) => { 42 - RecordWithMediaRecordMedia::External(v.into_static()) 43 - } 44 - RecordWithMediaRecordMedia::Unknown(v) => { 45 - RecordWithMediaRecordMedia::Unknown(v.into_static()) 46 - } 47 - } 48 - } 49 - } 50 - 51 - impl jacquard_common::IntoStatic for RecordWithMedia<'_> { 52 - type Output = RecordWithMedia<'static>; 53 - fn into_static(self) -> Self::Output { 54 - RecordWithMedia { 55 - media: self.media.into_static(), 56 - record: self.record.into_static(), 57 - extra_data: self.extra_data.into_static(), 58 - } 59 - } 60 - } 61 - 62 - #[jacquard_derive::lexicon] 63 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 64 - #[serde(rename_all = "camelCase")] 65 - pub struct View<'a> { 66 - #[serde(borrow)] 67 - pub media: ViewRecordMedia<'a>, 68 - #[serde(borrow)] 69 - pub record: test_generated::app_bsky::embed::record::View<'a>, 70 - } 71 - 72 - #[jacquard_derive::open_union] 73 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 74 - #[serde(tag = "$type")] 75 - #[serde(bound(deserialize = "'de: 'a"))] 76 - pub enum ViewRecordMedia<'a> { 77 - #[serde(rename = "app.bsky.embed.images#view")] 78 - ImagesView(Box<test_generated::app_bsky::embed::images::View<'a>>), 79 - #[serde(rename = "app.bsky.embed.video#view")] 80 - VideoView(Box<test_generated::app_bsky::embed::video::View<'a>>), 81 - #[serde(rename = "app.bsky.embed.external#view")] 82 - ExternalView(Box<test_generated::app_bsky::embed::external::View<'a>>), 83 - } 84 - 85 - impl jacquard_common::IntoStatic for ViewRecordMedia<'_> { 86 - type Output = ViewRecordMedia<'static>; 87 - fn into_static(self) -> Self::Output { 88 - match self { 89 - ViewRecordMedia::ImagesView(v) => { 90 - ViewRecordMedia::ImagesView(v.into_static()) 91 - } 92 - ViewRecordMedia::VideoView(v) => ViewRecordMedia::VideoView(v.into_static()), 93 - ViewRecordMedia::ExternalView(v) => { 94 - ViewRecordMedia::ExternalView(v.into_static()) 95 - } 96 - ViewRecordMedia::Unknown(v) => ViewRecordMedia::Unknown(v.into_static()), 97 - } 98 - } 99 - } 100 - 101 - impl jacquard_common::IntoStatic for View<'_> { 102 - type Output = View<'static>; 103 - fn into_static(self) -> Self::Output { 104 - View { 105 - media: self.media.into_static(), 106 - record: self.record.into_static(), 107 - extra_data: self.extra_data.into_static(), 108 - } 109 - } 110 - }
-93
crates/jacquard-lexicon/target/test_codegen_output/app_bsky/embed/video.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // Lexicon: app.bsky.embed.video 4 - // 5 - // This file was automatically generated from Lexicon schemas. 6 - // Any manual changes will be overwritten on the next regeneration. 7 - 8 - #[jacquard_derive::lexicon] 9 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 10 - #[serde(rename_all = "camelCase")] 11 - pub struct Caption<'a> { 12 - #[serde(borrow)] 13 - pub file: jacquard_common::types::blob::Blob<'a>, 14 - pub lang: jacquard_common::types::string::Language, 15 - } 16 - 17 - impl jacquard_common::IntoStatic for Caption<'_> { 18 - type Output = Caption<'static>; 19 - fn into_static(self) -> Self::Output { 20 - Caption { 21 - file: self.file.into_static(), 22 - lang: self.lang.into_static(), 23 - extra_data: self.extra_data.into_static(), 24 - } 25 - } 26 - } 27 - 28 - #[jacquard_derive::lexicon] 29 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 30 - #[serde(rename_all = "camelCase")] 31 - pub struct Video<'a> { 32 - ///Alt text description of the video, for accessibility. 33 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 34 - #[serde(borrow)] 35 - pub alt: std::option::Option<jacquard_common::CowStr<'a>>, 36 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 37 - #[serde(borrow)] 38 - pub aspect_ratio: std::option::Option<jacquard_common::types::value::Data<'a>>, 39 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 40 - #[serde(borrow)] 41 - pub captions: std::option::Option< 42 - Vec<test_generated::app_bsky::embed::video::Caption<'a>>, 43 - >, 44 - ///The mp4 video file. May be up to 100mb, formerly limited to 50mb. 45 - #[serde(borrow)] 46 - pub video: jacquard_common::types::blob::Blob<'a>, 47 - } 48 - 49 - impl jacquard_common::IntoStatic for Video<'_> { 50 - type Output = Video<'static>; 51 - fn into_static(self) -> Self::Output { 52 - Video { 53 - alt: self.alt.into_static(), 54 - aspect_ratio: self.aspect_ratio.into_static(), 55 - captions: self.captions.into_static(), 56 - video: self.video.into_static(), 57 - extra_data: self.extra_data.into_static(), 58 - } 59 - } 60 - } 61 - 62 - #[jacquard_derive::lexicon] 63 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 64 - #[serde(rename_all = "camelCase")] 65 - pub struct View<'a> { 66 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 67 - #[serde(borrow)] 68 - pub alt: std::option::Option<jacquard_common::CowStr<'a>>, 69 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 70 - #[serde(borrow)] 71 - pub aspect_ratio: std::option::Option<jacquard_common::types::value::Data<'a>>, 72 - #[serde(borrow)] 73 - pub cid: jacquard_common::types::string::Cid<'a>, 74 - #[serde(borrow)] 75 - pub playlist: jacquard_common::types::string::Uri<'a>, 76 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 77 - #[serde(borrow)] 78 - pub thumbnail: std::option::Option<jacquard_common::types::string::Uri<'a>>, 79 - } 80 - 81 - impl jacquard_common::IntoStatic for View<'_> { 82 - type Output = View<'static>; 83 - fn into_static(self) -> Self::Output { 84 - View { 85 - alt: self.alt.into_static(), 86 - aspect_ratio: self.aspect_ratio.into_static(), 87 - cid: self.cid.into_static(), 88 - playlist: self.playlist.into_static(), 89 - thumbnail: self.thumbnail.into_static(), 90 - extra_data: self.extra_data.into_static(), 91 - } 92 - } 93 - }
-7
crates/jacquard-lexicon/target/test_codegen_output/app_bsky/feed.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // This file was automatically generated from Lexicon schemas. 4 - // Any manual changes will be overwritten on the next regeneration. 5 - 6 - pub mod get_author_feed; 7 - pub mod post;
-128
crates/jacquard-lexicon/target/test_codegen_output/app_bsky/feed/get_author_feed.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // Lexicon: app.bsky.feed.getAuthorFeed 4 - // 5 - // This file was automatically generated from Lexicon schemas. 6 - // Any manual changes will be overwritten on the next regeneration. 7 - 8 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 9 - #[serde(rename_all = "camelCase")] 10 - pub struct GetAuthorFeed<'a> { 11 - #[serde(borrow)] 12 - pub actor: jacquard_common::types::ident::AtIdentifier<'a>, 13 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 14 - #[serde(borrow)] 15 - pub cursor: std::option::Option<jacquard_common::CowStr<'a>>, 16 - ///(default: "posts_with_replies") 17 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 18 - #[serde(borrow)] 19 - pub filter: std::option::Option<jacquard_common::CowStr<'a>>, 20 - ///(default: false) 21 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 22 - pub include_pins: std::option::Option<bool>, 23 - ///(default: 50, min: 1, max: 100) 24 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 25 - pub limit: std::option::Option<i64>, 26 - } 27 - 28 - impl jacquard_common::IntoStatic for GetAuthorFeed<'_> { 29 - type Output = GetAuthorFeed<'static>; 30 - fn into_static(self) -> Self::Output { 31 - GetAuthorFeed { 32 - actor: self.actor.into_static(), 33 - cursor: self.cursor.into_static(), 34 - filter: self.filter.into_static(), 35 - include_pins: self.include_pins.into_static(), 36 - limit: self.limit.into_static(), 37 - } 38 - } 39 - } 40 - 41 - #[jacquard_derive::lexicon] 42 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 43 - #[serde(rename_all = "camelCase")] 44 - pub struct GetAuthorFeedOutput<'a> { 45 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 46 - #[serde(borrow)] 47 - pub cursor: std::option::Option<jacquard_common::CowStr<'a>>, 48 - #[serde(borrow)] 49 - pub feed: Vec<jacquard_common::types::value::Data<'a>>, 50 - } 51 - 52 - impl jacquard_common::IntoStatic for GetAuthorFeedOutput<'_> { 53 - type Output = GetAuthorFeedOutput<'static>; 54 - fn into_static(self) -> Self::Output { 55 - GetAuthorFeedOutput { 56 - cursor: self.cursor.into_static(), 57 - feed: self.feed.into_static(), 58 - extra_data: self.extra_data.into_static(), 59 - } 60 - } 61 - } 62 - 63 - #[jacquard_derive::open_union] 64 - #[derive( 65 - serde::Serialize, 66 - serde::Deserialize, 67 - Debug, 68 - Clone, 69 - PartialEq, 70 - Eq, 71 - thiserror::Error, 72 - miette::Diagnostic 73 - )] 74 - #[serde(tag = "error", content = "message")] 75 - #[serde(bound(deserialize = "'de: 'a"))] 76 - pub enum GetAuthorFeedError<'a> { 77 - #[serde(rename = "BlockedActor")] 78 - BlockedActor(std::option::Option<String>), 79 - #[serde(rename = "BlockedByActor")] 80 - BlockedByActor(std::option::Option<String>), 81 - } 82 - 83 - impl std::fmt::Display for GetAuthorFeedError<'_> { 84 - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 85 - match self { 86 - Self::BlockedActor(msg) => { 87 - write!(f, "BlockedActor")?; 88 - if let Some(msg) = msg { 89 - write!(f, ": {}", msg)?; 90 - } 91 - Ok(()) 92 - } 93 - Self::BlockedByActor(msg) => { 94 - write!(f, "BlockedByActor")?; 95 - if let Some(msg) = msg { 96 - write!(f, ": {}", msg)?; 97 - } 98 - Ok(()) 99 - } 100 - Self::Unknown(err) => write!(f, "Unknown error: {:?}", err), 101 - } 102 - } 103 - } 104 - 105 - impl jacquard_common::IntoStatic for GetAuthorFeedError<'_> { 106 - type Output = GetAuthorFeedError<'static>; 107 - fn into_static(self) -> Self::Output { 108 - match self { 109 - GetAuthorFeedError::BlockedActor(v) => { 110 - GetAuthorFeedError::BlockedActor(v.into_static()) 111 - } 112 - GetAuthorFeedError::BlockedByActor(v) => { 113 - GetAuthorFeedError::BlockedByActor(v.into_static()) 114 - } 115 - GetAuthorFeedError::Unknown(v) => { 116 - GetAuthorFeedError::Unknown(v.into_static()) 117 - } 118 - } 119 - } 120 - } 121 - 122 - impl jacquard_common::types::xrpc::XrpcRequest for GetAuthorFeed<'_> { 123 - const NSID: &'static str = "app.bsky.feed.getAuthorFeed"; 124 - const METHOD: jacquard_common::types::xrpc::XrpcMethod = jacquard_common::types::xrpc::XrpcMethod::Query; 125 - const OUTPUT_ENCODING: &'static str = "application/json"; 126 - type Output<'de> = GetAuthorFeedOutput<'de>; 127 - type Err<'de> = GetAuthorFeedError<'de>; 128 - }
-192
crates/jacquard-lexicon/target/test_codegen_output/app_bsky/feed/post.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // Lexicon: app.bsky.feed.post 4 - // 5 - // This file was automatically generated from Lexicon schemas. 6 - // Any manual changes will be overwritten on the next regeneration. 7 - 8 - ///Deprecated: use facets instead. 9 - #[jacquard_derive::lexicon] 10 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 11 - #[serde(rename_all = "camelCase")] 12 - pub struct Entity<'a> { 13 - #[serde(borrow)] 14 - pub index: test_generated::app_bsky::feed::post::TextSlice<'a>, 15 - ///Expected values are 'mention' and 'link'. 16 - #[serde(borrow)] 17 - pub r#type: jacquard_common::CowStr<'a>, 18 - #[serde(borrow)] 19 - pub value: jacquard_common::CowStr<'a>, 20 - } 21 - 22 - impl jacquard_common::IntoStatic for Entity<'_> { 23 - type Output = Entity<'static>; 24 - fn into_static(self) -> Self::Output { 25 - Entity { 26 - index: self.index.into_static(), 27 - r#type: self.r#type.into_static(), 28 - value: self.value.into_static(), 29 - extra_data: self.extra_data.into_static(), 30 - } 31 - } 32 - } 33 - 34 - ///Record containing a Bluesky post. 35 - #[jacquard_derive::lexicon] 36 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 37 - #[serde(rename_all = "camelCase")] 38 - pub struct Post<'a> { 39 - ///Client-declared timestamp when this post was originally created. 40 - pub created_at: jacquard_common::types::string::Datetime, 41 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 42 - #[serde(borrow)] 43 - pub embed: std::option::Option<PostRecordEmbed<'a>>, 44 - ///DEPRECATED: replaced by app.bsky.richtext.facet. 45 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 46 - #[serde(borrow)] 47 - pub entities: std::option::Option< 48 - Vec<test_generated::app_bsky::feed::post::Entity<'a>>, 49 - >, 50 - ///Annotations of text (mentions, URLs, hashtags, etc) 51 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 52 - #[serde(borrow)] 53 - pub facets: std::option::Option< 54 - Vec<test_generated::app_bsky::richtext::facet::Facet<'a>>, 55 - >, 56 - ///Self-label values for this post. Effectively content warnings. 57 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 58 - #[serde(borrow)] 59 - pub labels: std::option::Option<PostRecordLabels<'a>>, 60 - ///Indicates human language of post primary text content. 61 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 62 - pub langs: std::option::Option<Vec<jacquard_common::types::string::Language>>, 63 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 64 - #[serde(borrow)] 65 - pub reply: std::option::Option<test_generated::app_bsky::feed::post::ReplyRef<'a>>, 66 - ///Additional hashtags, in addition to any included in post text and facets. 67 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 68 - #[serde(borrow)] 69 - pub tags: std::option::Option<Vec<jacquard_common::CowStr<'a>>>, 70 - ///The primary post content. May be an empty string, if there are embeds. 71 - #[serde(borrow)] 72 - pub text: jacquard_common::CowStr<'a>, 73 - } 74 - 75 - #[jacquard_derive::open_union] 76 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 77 - #[serde(tag = "$type")] 78 - #[serde(bound(deserialize = "'de: 'a"))] 79 - pub enum PostRecordEmbed<'a> { 80 - #[serde(rename = "app.bsky.embed.images")] 81 - Images(Box<test_generated::app_bsky::embed::images::Images<'a>>), 82 - #[serde(rename = "app.bsky.embed.video")] 83 - Video(Box<test_generated::app_bsky::embed::video::Video<'a>>), 84 - #[serde(rename = "app.bsky.embed.external")] 85 - External(Box<test_generated::app_bsky::embed::external::ExternalRecord<'a>>), 86 - #[serde(rename = "app.bsky.embed.record")] 87 - Record(Box<test_generated::app_bsky::embed::record::Record<'a>>), 88 - #[serde(rename = "app.bsky.embed.recordWithMedia")] 89 - RecordWithMedia( 90 - Box<test_generated::app_bsky::embed::record_with_media::RecordWithMedia<'a>>, 91 - ), 92 - } 93 - 94 - impl jacquard_common::IntoStatic for PostRecordEmbed<'_> { 95 - type Output = PostRecordEmbed<'static>; 96 - fn into_static(self) -> Self::Output { 97 - match self { 98 - PostRecordEmbed::Images(v) => PostRecordEmbed::Images(v.into_static()), 99 - PostRecordEmbed::Video(v) => PostRecordEmbed::Video(v.into_static()), 100 - PostRecordEmbed::External(v) => PostRecordEmbed::External(v.into_static()), 101 - PostRecordEmbed::Record(v) => PostRecordEmbed::Record(v.into_static()), 102 - PostRecordEmbed::RecordWithMedia(v) => { 103 - PostRecordEmbed::RecordWithMedia(v.into_static()) 104 - } 105 - PostRecordEmbed::Unknown(v) => PostRecordEmbed::Unknown(v.into_static()), 106 - } 107 - } 108 - } 109 - 110 - #[jacquard_derive::open_union] 111 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 112 - #[serde(tag = "$type")] 113 - #[serde(bound(deserialize = "'de: 'a"))] 114 - pub enum PostRecordLabels<'a> { 115 - #[serde(rename = "com.atproto.label.defs#selfLabels")] 116 - DefsSelfLabels(Box<test_generated::com_atproto::label::SelfLabels<'a>>), 117 - } 118 - 119 - impl jacquard_common::IntoStatic for PostRecordLabels<'_> { 120 - type Output = PostRecordLabels<'static>; 121 - fn into_static(self) -> Self::Output { 122 - match self { 123 - PostRecordLabels::DefsSelfLabels(v) => { 124 - PostRecordLabels::DefsSelfLabels(v.into_static()) 125 - } 126 - PostRecordLabels::Unknown(v) => PostRecordLabels::Unknown(v.into_static()), 127 - } 128 - } 129 - } 130 - 131 - impl jacquard_common::types::collection::Collection for Post<'_> { 132 - const NSID: &'static str = "app.bsky.feed.post"; 133 - } 134 - 135 - impl jacquard_common::IntoStatic for Post<'_> { 136 - type Output = Post<'static>; 137 - fn into_static(self) -> Self::Output { 138 - Post { 139 - created_at: self.created_at.into_static(), 140 - embed: self.embed.into_static(), 141 - entities: self.entities.into_static(), 142 - facets: self.facets.into_static(), 143 - labels: self.labels.into_static(), 144 - langs: self.langs.into_static(), 145 - reply: self.reply.into_static(), 146 - tags: self.tags.into_static(), 147 - text: self.text.into_static(), 148 - extra_data: self.extra_data.into_static(), 149 - } 150 - } 151 - } 152 - 153 - #[jacquard_derive::lexicon] 154 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 155 - #[serde(rename_all = "camelCase")] 156 - pub struct ReplyRef<'a> { 157 - #[serde(borrow)] 158 - pub parent: test_generated::com_atproto::repo::strong_ref::StrongRef<'a>, 159 - #[serde(borrow)] 160 - pub root: test_generated::com_atproto::repo::strong_ref::StrongRef<'a>, 161 - } 162 - 163 - impl jacquard_common::IntoStatic for ReplyRef<'_> { 164 - type Output = ReplyRef<'static>; 165 - fn into_static(self) -> Self::Output { 166 - ReplyRef { 167 - parent: self.parent.into_static(), 168 - root: self.root.into_static(), 169 - extra_data: self.extra_data.into_static(), 170 - } 171 - } 172 - } 173 - 174 - ///Deprecated. Use app.bsky.richtext instead -- A text segment. Start is inclusive, end is exclusive. Indices are for utf16-encoded strings. 175 - #[jacquard_derive::lexicon] 176 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 177 - #[serde(rename_all = "camelCase")] 178 - pub struct TextSlice<'a> { 179 - pub end: i64, 180 - pub start: i64, 181 - } 182 - 183 - impl jacquard_common::IntoStatic for TextSlice<'_> { 184 - type Output = TextSlice<'static>; 185 - fn into_static(self) -> Self::Output { 186 - TextSlice { 187 - end: self.end.into_static(), 188 - start: self.start.into_static(), 189 - extra_data: self.extra_data.into_static(), 190 - } 191 - } 192 - }
-6
crates/jacquard-lexicon/target/test_codegen_output/app_bsky/richtext.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // This file was automatically generated from Lexicon schemas. 4 - // Any manual changes will be overwritten on the next regeneration. 5 - 6 - pub mod facet;
-105
crates/jacquard-lexicon/target/test_codegen_output/app_bsky/richtext/facet.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // Lexicon: app.bsky.richtext.facet 4 - // 5 - // This file was automatically generated from Lexicon schemas. 6 - // Any manual changes will be overwritten on the next regeneration. 7 - 8 - ///Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets. 9 - #[jacquard_derive::lexicon] 10 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 11 - #[serde(rename_all = "camelCase")] 12 - pub struct ByteSlice<'a> { 13 - pub byte_end: i64, 14 - pub byte_start: i64, 15 - } 16 - 17 - impl jacquard_common::IntoStatic for ByteSlice<'_> { 18 - type Output = ByteSlice<'static>; 19 - fn into_static(self) -> Self::Output { 20 - ByteSlice { 21 - byte_end: self.byte_end.into_static(), 22 - byte_start: self.byte_start.into_static(), 23 - extra_data: self.extra_data.into_static(), 24 - } 25 - } 26 - } 27 - 28 - ///Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL. 29 - #[jacquard_derive::lexicon] 30 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 31 - #[serde(rename_all = "camelCase")] 32 - pub struct Link<'a> { 33 - #[serde(borrow)] 34 - pub uri: jacquard_common::types::string::Uri<'a>, 35 - } 36 - 37 - impl jacquard_common::IntoStatic for Link<'_> { 38 - type Output = Link<'static>; 39 - fn into_static(self) -> Self::Output { 40 - Link { 41 - uri: self.uri.into_static(), 42 - extra_data: self.extra_data.into_static(), 43 - } 44 - } 45 - } 46 - 47 - ///Annotation of a sub-string within rich text. 48 - #[jacquard_derive::lexicon] 49 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 50 - #[serde(rename_all = "camelCase")] 51 - pub struct Facet<'a> { 52 - #[serde(borrow)] 53 - pub features: Vec<jacquard_common::types::value::Data<'a>>, 54 - #[serde(borrow)] 55 - pub index: test_generated::app_bsky::richtext::facet::ByteSlice<'a>, 56 - } 57 - 58 - impl jacquard_common::IntoStatic for Facet<'_> { 59 - type Output = Facet<'static>; 60 - fn into_static(self) -> Self::Output { 61 - Facet { 62 - features: self.features.into_static(), 63 - index: self.index.into_static(), 64 - extra_data: self.extra_data.into_static(), 65 - } 66 - } 67 - } 68 - 69 - ///Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID. 70 - #[jacquard_derive::lexicon] 71 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 72 - #[serde(rename_all = "camelCase")] 73 - pub struct Mention<'a> { 74 - #[serde(borrow)] 75 - pub did: jacquard_common::types::string::Did<'a>, 76 - } 77 - 78 - impl jacquard_common::IntoStatic for Mention<'_> { 79 - type Output = Mention<'static>; 80 - fn into_static(self) -> Self::Output { 81 - Mention { 82 - did: self.did.into_static(), 83 - extra_data: self.extra_data.into_static(), 84 - } 85 - } 86 - } 87 - 88 - ///Facet feature for a hashtag. The text usually includes a '#' prefix, but the facet reference should not (except in the case of 'double hash tags'). 89 - #[jacquard_derive::lexicon] 90 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 91 - #[serde(rename_all = "camelCase")] 92 - pub struct Tag<'a> { 93 - #[serde(borrow)] 94 - pub tag: jacquard_common::CowStr<'a>, 95 - } 96 - 97 - impl jacquard_common::IntoStatic for Tag<'_> { 98 - type Output = Tag<'static>; 99 - fn into_static(self) -> Self::Output { 100 - Tag { 101 - tag: self.tag.into_static(), 102 - extra_data: self.extra_data.into_static(), 103 - } 104 - } 105 - }
-7
crates/jacquard-lexicon/target/test_codegen_output/com_atproto.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // This file was automatically generated from Lexicon schemas. 4 - // Any manual changes will be overwritten on the next regeneration. 5 - 6 - pub mod label; 7 - pub mod repo;
-287
crates/jacquard-lexicon/target/test_codegen_output/com_atproto/label.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // Lexicon: com.atproto.label.defs 4 - // 5 - // This file was automatically generated from Lexicon schemas. 6 - // Any manual changes will be overwritten on the next regeneration. 7 - 8 - ///Metadata tag on an atproto resource (eg, repo or record). 9 - #[jacquard_derive::lexicon] 10 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 11 - #[serde(rename_all = "camelCase")] 12 - pub struct Label<'a> { 13 - ///Optionally, CID specifying the specific version of 'uri' resource this label applies to. 14 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 15 - #[serde(borrow)] 16 - pub cid: std::option::Option<jacquard_common::types::string::Cid<'a>>, 17 - ///Timestamp when this label was created. 18 - pub cts: jacquard_common::types::string::Datetime, 19 - ///Timestamp at which this label expires (no longer applies). 20 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 21 - pub exp: std::option::Option<jacquard_common::types::string::Datetime>, 22 - ///If true, this is a negation label, overwriting a previous label. 23 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 24 - pub neg: std::option::Option<bool>, 25 - ///Signature of dag-cbor encoded label. 26 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 27 - pub sig: std::option::Option<bytes::Bytes>, 28 - ///DID of the actor who created this label. 29 - #[serde(borrow)] 30 - pub src: jacquard_common::types::string::Did<'a>, 31 - ///AT URI of the record, repository (account), or other resource that this label applies to. 32 - #[serde(borrow)] 33 - pub uri: jacquard_common::types::string::Uri<'a>, 34 - ///The short string name of the value or type of this label. 35 - #[serde(borrow)] 36 - pub val: jacquard_common::CowStr<'a>, 37 - ///The AT Protocol version of the label object. 38 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 39 - pub ver: std::option::Option<i64>, 40 - } 41 - 42 - impl jacquard_common::IntoStatic for Label<'_> { 43 - type Output = Label<'static>; 44 - fn into_static(self) -> Self::Output { 45 - Label { 46 - cid: self.cid.into_static(), 47 - cts: self.cts.into_static(), 48 - exp: self.exp.into_static(), 49 - neg: self.neg.into_static(), 50 - sig: self.sig.into_static(), 51 - src: self.src.into_static(), 52 - uri: self.uri.into_static(), 53 - val: self.val.into_static(), 54 - ver: self.ver.into_static(), 55 - extra_data: self.extra_data.into_static(), 56 - } 57 - } 58 - } 59 - 60 - #[derive(Debug, Clone, PartialEq, Eq, Hash)] 61 - pub enum LabelValue<'a> { 62 - Hide, 63 - NoPromote, 64 - Warn, 65 - NoUnauthenticated, 66 - DmcaViolation, 67 - Doxxing, 68 - Porn, 69 - Sexual, 70 - Nudity, 71 - Nsfl, 72 - Gore, 73 - Other(jacquard_common::CowStr<'a>), 74 - } 75 - 76 - impl<'a> LabelValue<'a> { 77 - pub fn as_str(&self) -> &str { 78 - match self { 79 - Self::Hide => "!hide", 80 - Self::NoPromote => "!no-promote", 81 - Self::Warn => "!warn", 82 - Self::NoUnauthenticated => "!no-unauthenticated", 83 - Self::DmcaViolation => "dmca-violation", 84 - Self::Doxxing => "doxxing", 85 - Self::Porn => "porn", 86 - Self::Sexual => "sexual", 87 - Self::Nudity => "nudity", 88 - Self::Nsfl => "nsfl", 89 - Self::Gore => "gore", 90 - Self::Other(s) => s.as_ref(), 91 - } 92 - } 93 - } 94 - 95 - impl<'a> From<&'a str> for LabelValue<'a> { 96 - fn from(s: &'a str) -> Self { 97 - match s { 98 - "!hide" => Self::Hide, 99 - "!no-promote" => Self::NoPromote, 100 - "!warn" => Self::Warn, 101 - "!no-unauthenticated" => Self::NoUnauthenticated, 102 - "dmca-violation" => Self::DmcaViolation, 103 - "doxxing" => Self::Doxxing, 104 - "porn" => Self::Porn, 105 - "sexual" => Self::Sexual, 106 - "nudity" => Self::Nudity, 107 - "nsfl" => Self::Nsfl, 108 - "gore" => Self::Gore, 109 - _ => Self::Other(jacquard_common::CowStr::from(s)), 110 - } 111 - } 112 - } 113 - 114 - impl<'a> From<String> for LabelValue<'a> { 115 - fn from(s: String) -> Self { 116 - match s.as_str() { 117 - "!hide" => Self::Hide, 118 - "!no-promote" => Self::NoPromote, 119 - "!warn" => Self::Warn, 120 - "!no-unauthenticated" => Self::NoUnauthenticated, 121 - "dmca-violation" => Self::DmcaViolation, 122 - "doxxing" => Self::Doxxing, 123 - "porn" => Self::Porn, 124 - "sexual" => Self::Sexual, 125 - "nudity" => Self::Nudity, 126 - "nsfl" => Self::Nsfl, 127 - "gore" => Self::Gore, 128 - _ => Self::Other(jacquard_common::CowStr::from(s)), 129 - } 130 - } 131 - } 132 - 133 - impl<'a> AsRef<str> for LabelValue<'a> { 134 - fn as_ref(&self) -> &str { 135 - self.as_str() 136 - } 137 - } 138 - 139 - impl<'a> serde::Serialize for LabelValue<'a> { 140 - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 141 - where 142 - S: serde::Serializer, 143 - { 144 - serializer.serialize_str(self.as_str()) 145 - } 146 - } 147 - 148 - impl<'de, 'a> serde::Deserialize<'de> for LabelValue<'a> 149 - where 150 - 'de: 'a, 151 - { 152 - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 153 - where 154 - D: serde::Deserializer<'de>, 155 - { 156 - let s = <&'de str>::deserialize(deserializer)?; 157 - Ok(Self::from(s)) 158 - } 159 - } 160 - 161 - impl jacquard_common::IntoStatic for LabelValue<'_> { 162 - type Output = LabelValue<'static>; 163 - fn into_static(self) -> Self::Output { 164 - match self { 165 - LabelValue::Hide => LabelValue::Hide, 166 - LabelValue::NoPromote => LabelValue::NoPromote, 167 - LabelValue::Warn => LabelValue::Warn, 168 - LabelValue::NoUnauthenticated => LabelValue::NoUnauthenticated, 169 - LabelValue::DmcaViolation => LabelValue::DmcaViolation, 170 - LabelValue::Doxxing => LabelValue::Doxxing, 171 - LabelValue::Porn => LabelValue::Porn, 172 - LabelValue::Sexual => LabelValue::Sexual, 173 - LabelValue::Nudity => LabelValue::Nudity, 174 - LabelValue::Nsfl => LabelValue::Nsfl, 175 - LabelValue::Gore => LabelValue::Gore, 176 - LabelValue::Other(v) => LabelValue::Other(v.into_static()), 177 - } 178 - } 179 - } 180 - 181 - ///Declares a label value and its expected interpretations and behaviors. 182 - #[jacquard_derive::lexicon] 183 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 184 - #[serde(rename_all = "camelCase")] 185 - pub struct LabelValueDefinition<'a> { 186 - ///Does the user need to have adult content enabled in order to configure this label? 187 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 188 - pub adult_only: std::option::Option<bool>, 189 - ///What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing. 190 - #[serde(borrow)] 191 - pub blurs: jacquard_common::CowStr<'a>, 192 - ///The default setting for this label. 193 - #[serde(skip_serializing_if = "std::option::Option::is_none")] 194 - #[serde(borrow)] 195 - pub default_setting: std::option::Option<jacquard_common::CowStr<'a>>, 196 - ///The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+). 197 - #[serde(borrow)] 198 - pub identifier: jacquard_common::CowStr<'a>, 199 - #[serde(borrow)] 200 - pub locales: Vec< 201 - test_generated::com_atproto::label::LabelValueDefinitionStrings<'a>, 202 - >, 203 - ///How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing. 204 - #[serde(borrow)] 205 - pub severity: jacquard_common::CowStr<'a>, 206 - } 207 - 208 - impl jacquard_common::IntoStatic for LabelValueDefinition<'_> { 209 - type Output = LabelValueDefinition<'static>; 210 - fn into_static(self) -> Self::Output { 211 - LabelValueDefinition { 212 - adult_only: self.adult_only.into_static(), 213 - blurs: self.blurs.into_static(), 214 - default_setting: self.default_setting.into_static(), 215 - identifier: self.identifier.into_static(), 216 - locales: self.locales.into_static(), 217 - severity: self.severity.into_static(), 218 - extra_data: self.extra_data.into_static(), 219 - } 220 - } 221 - } 222 - 223 - ///Strings which describe the label in the UI, localized into a specific language. 224 - #[jacquard_derive::lexicon] 225 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 226 - #[serde(rename_all = "camelCase")] 227 - pub struct LabelValueDefinitionStrings<'a> { 228 - ///A longer description of what the label means and why it might be applied. 229 - #[serde(borrow)] 230 - pub description: jacquard_common::CowStr<'a>, 231 - ///The code of the language these strings are written in. 232 - pub lang: jacquard_common::types::string::Language, 233 - ///A short human-readable name for the label. 234 - #[serde(borrow)] 235 - pub name: jacquard_common::CowStr<'a>, 236 - } 237 - 238 - impl jacquard_common::IntoStatic for LabelValueDefinitionStrings<'_> { 239 - type Output = LabelValueDefinitionStrings<'static>; 240 - fn into_static(self) -> Self::Output { 241 - LabelValueDefinitionStrings { 242 - description: self.description.into_static(), 243 - lang: self.lang.into_static(), 244 - name: self.name.into_static(), 245 - extra_data: self.extra_data.into_static(), 246 - } 247 - } 248 - } 249 - 250 - ///Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel. 251 - #[jacquard_derive::lexicon] 252 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 253 - #[serde(rename_all = "camelCase")] 254 - pub struct SelfLabel<'a> { 255 - ///The short string name of the value or type of this label. 256 - #[serde(borrow)] 257 - pub val: jacquard_common::CowStr<'a>, 258 - } 259 - 260 - impl jacquard_common::IntoStatic for SelfLabel<'_> { 261 - type Output = SelfLabel<'static>; 262 - fn into_static(self) -> Self::Output { 263 - SelfLabel { 264 - val: self.val.into_static(), 265 - extra_data: self.extra_data.into_static(), 266 - } 267 - } 268 - } 269 - 270 - ///Metadata tags on an atproto record, published by the author within the record. 271 - #[jacquard_derive::lexicon] 272 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 273 - #[serde(rename_all = "camelCase")] 274 - pub struct SelfLabels<'a> { 275 - #[serde(borrow)] 276 - pub values: Vec<test_generated::com_atproto::label::SelfLabel<'a>>, 277 - } 278 - 279 - impl jacquard_common::IntoStatic for SelfLabels<'_> { 280 - type Output = SelfLabels<'static>; 281 - fn into_static(self) -> Self::Output { 282 - SelfLabels { 283 - values: self.values.into_static(), 284 - extra_data: self.extra_data.into_static(), 285 - } 286 - } 287 - }
-6
crates/jacquard-lexicon/target/test_codegen_output/com_atproto/repo.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // This file was automatically generated from Lexicon schemas. 4 - // Any manual changes will be overwritten on the next regeneration. 5 - 6 - pub mod strong_ref;
-27
crates/jacquard-lexicon/target/test_codegen_output/com_atproto/repo/strong_ref.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // Lexicon: com.atproto.repo.strongRef 4 - // 5 - // This file was automatically generated from Lexicon schemas. 6 - // Any manual changes will be overwritten on the next regeneration. 7 - 8 - #[jacquard_derive::lexicon] 9 - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 10 - #[serde(rename_all = "camelCase")] 11 - pub struct StrongRef<'a> { 12 - #[serde(borrow)] 13 - pub cid: jacquard_common::types::string::Cid<'a>, 14 - #[serde(borrow)] 15 - pub uri: jacquard_common::types::string::AtUri<'a>, 16 - } 17 - 18 - impl jacquard_common::IntoStatic for StrongRef<'_> { 19 - type Output = StrongRef<'static>; 20 - fn into_static(self) -> Self::Output { 21 - StrongRef { 22 - cid: self.cid.into_static(), 23 - uri: self.uri.into_static(), 24 - extra_data: self.extra_data.into_static(), 25 - } 26 - } 27 - }
-7
crates/jacquard-lexicon/target/test_codegen_output/lib.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // This file was automatically generated from Lexicon schemas. 4 - // Any manual changes will be overwritten on the next regeneration. 5 - 6 - pub mod app_bsky; 7 - pub mod com_atproto;
-15
crates/jacquard-lexicon/tests/regen_api.rs
··· 1 - use jacquard_lexicon::codegen::CodeGenerator; 2 - use jacquard_lexicon::corpus::LexiconCorpus; 3 - 4 - #[test] 5 - #[ignore] // Run with: cargo test --test regen_api -- --ignored 6 - fn regenerate_api() { 7 - let corpus = LexiconCorpus::load_from_dir("tests/fixtures/lexicons/atproto/lexicons").expect("load corpus"); 8 - let codegen = CodeGenerator::new(&corpus, "crate"); 9 - 10 - codegen 11 - .write_to_disk(std::path::Path::new("../jacquard-api/src")) 12 - .expect("write to disk"); 13 - 14 - println!("Generated {} lexicons", corpus.len()); 15 - }
+4 -4
crates/jacquard/Cargo.toml
··· 8 8 keywords.workspace = true 9 9 categories.workspace = true 10 10 readme.workspace = true 11 - documentation.workspace = true 12 11 exclude.workspace = true 12 + license-file.workspace = true 13 13 14 14 [features] 15 15 default = ["api_all"] ··· 29 29 bytes.workspace = true 30 30 clap.workspace = true 31 31 http.workspace = true 32 - jacquard-api = { path = "../jacquard-api" } 33 - jacquard-common = { path = "../jacquard-common" } 34 - jacquard-derive = { path = "../jacquard-derive", optional = true } 32 + jacquard-api = { version = "0.1.0", path = "../jacquard-api" } 33 + jacquard-common = { version = "0.1.0", path = "../jacquard-common" } 34 + jacquard-derive = { version = "0.1.0", path = "../jacquard-derive", optional = true } 35 35 miette.workspace = true 36 36 reqwest = { workspace = true, features = ["charset", "http2", "json", "system-proxy", "gzip", "rustls-tls"] } 37 37 serde.workspace = true
+1
nix/modules/devshell.nix
··· 17 17 nixd # Nix language server 18 18 bacon 19 19 rust-analyzer 20 + cargo-release 20 21 ]; 21 22 }; 22 23 };
+1 -1
rust-toolchain.toml
··· 1 1 [toolchain] 2 2 channel = "stable" 3 - profile = "complete" 3 + profile = "default"