From 8499f2e49a4568364e7054639d1c3d0a17857a0d Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 6 May 2025 08:53:50 +0000 Subject: [PATCH 01/19] Update cgp to v0.4.0 --- Cargo.lock | 141 +++++++++++++++++++---------------------------------- Cargo.toml | 40 ++++++++------- flake.lock | 6 +-- 3 files changed, 73 insertions(+), 114 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f781e42..5d87666 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,9 +100,8 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cgp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "255ecfdb81d1786bf4212e1e038e5f6da8836cbb5603ce2347308ede426dbcea" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ "cgp-async", "cgp-core", @@ -111,9 +110,8 @@ dependencies = [ [[package]] name = "cgp-async" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cca3a368634ced2b77f1e00e7ebb0872402a1d8fd6dbf05880329b0a001b37e" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ "cgp-async-macro", "cgp-sync", @@ -121,9 +119,8 @@ dependencies = [ [[package]] name = "cgp-async-macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1656912abbbf7ff2fe11c9680ae5883afe79cac6f2f51bd486d04a3fbba9426" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ "proc-macro2", "quote", @@ -132,65 +129,37 @@ dependencies = [ [[package]] name = "cgp-component" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12793289566a983f8a3151448cb8820bcc4704c34a0a9cf19bb1ed48e0844e81" - -[[package]] -name = "cgp-component-macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f37331b62cbb29d159d2c3bc3c21bdc885576d9c024d0e9ea4cb3e7513138897" -dependencies = [ - "cgp-component-macro-lib", - "syn", -] - -[[package]] -name = "cgp-component-macro-lib" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29461124d295bf42c48106e81cb0f89a4eb64132752b916d5ec5df9875d03d58" -dependencies = [ - "itertools", - "prettyplease", - "proc-macro2", - "quote", - "syn", -] +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" [[package]] name = "cgp-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021293135043b9a4f630a1fea79c1cee2de5161e71902e2cd665965945d4b546" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ "cgp-async", "cgp-component", - "cgp-component-macro", "cgp-error", "cgp-field", - "cgp-field-macro", + "cgp-macro", "cgp-type", ] [[package]] name = "cgp-error" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4b69e873357e304d1a7a91894f40f98543a5f1fac84b3087037110826e4afe" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ "cgp-async", "cgp-component", - "cgp-component-macro", + "cgp-macro", "cgp-type", ] [[package]] name = "cgp-error-anyhow" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e69c88a7ec1ce29d204d6f9d3b975933a050dc1b1b71da646fc74e56f0cdbe7" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ "anyhow", "cgp-core", @@ -198,18 +167,16 @@ dependencies = [ [[package]] name = "cgp-error-extra" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb44c5e45fb8de9d5e8d77a4736c01d09fdee2f4e822b5ea5a3b6243ddbdd9c" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ - "cgp-error", + "cgp-core", ] [[package]] name = "cgp-extra" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04a67b3e5c5fd4420c0fd16c1e93a9e28a7e10f9aa911b66d7a2b9588fbb11c4" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ "cgp-error-extra", "cgp-inner", @@ -219,44 +186,42 @@ dependencies = [ [[package]] name = "cgp-field" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193dec7508c4b4efd6a1ef5eac6789eb0a297561e55dcb8cd377a904f055a176" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ "cgp-component", + "cgp-macro", "cgp-type", ] [[package]] -name = "cgp-field-macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7853451aedcc73c0edf67d44ca9652a7b1ba8a18ac0499f4fced1ac845b7711" +name = "cgp-inner" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ - "cgp-field-macro-lib", - "proc-macro2", + "cgp-component", + "cgp-macro", ] [[package]] -name = "cgp-field-macro-lib" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "785d154b6d17929919e3bee306c515c7d78e420303605829e48116fcef2ccf9e" +name = "cgp-macro" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ - "prettyplease", - "proc-macro2", - "quote", + "cgp-macro-lib", "syn", ] [[package]] -name = "cgp-inner" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4e35f1ad7bfb5df01c9f263d054ba53ff87c3d1da20cb5c0872191df904583" +name = "cgp-macro-lib" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ - "cgp-component", - "cgp-component-macro", + "itertools", + "prettyplease", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -276,42 +241,38 @@ dependencies = [ [[package]] name = "cgp-run" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec7009079ecfd0a5db07a5dda0e7cece70b1774ead842a42919a93b4662eb96" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ "cgp-async", "cgp-component", - "cgp-component-macro", "cgp-error", + "cgp-macro", ] [[package]] name = "cgp-runtime" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332d92088b07754adbde9ecdf894b8c3b9303b287c8d82d11f8886a394121925" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ "cgp-core", ] [[package]] name = "cgp-sync" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb37ca18a65f3603aaa307ba76d92f64025db56160143a0e96466b5855d61a29" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ "cgp-async-macro", ] [[package]] name = "cgp-type" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a4638c888a38fbb1c88406c224c38d7b9e230a306e7b07f796280b89f5baa54" +version = "0.4.0" +source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" dependencies = [ "cgp-component", - "cgp-component-macro", + "cgp-macro", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 20945d3..2f37435 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -cgp = { version = "0.3.0" } -cgp-error-anyhow = { version = "0.3.0" } +cgp = { version = "0.4.0" } +cgp-error-anyhow = { version = "0.4.0" } serde = { version = "1", features = ["derive"] } reqwest = { version = "0.12.12", features = [ "blocking", "json" ] } itertools = { version = "0.14.0" } @@ -15,22 +15,20 @@ datetime = { version = "0.5.2" } sha1 = { version = "0.10.6" } [patch.crates-io] -# cgp = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-core = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-extra = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-async = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-async-macro = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-component = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-component-macro = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-component-macro-lib = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-type = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-field = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-field-macro = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-field-macro-lib = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-error = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-error-extra = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-error-anyhow = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-run = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-runtime = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-sync = { git = "https://github.com/contextgeneric/cgp.git" } -# cgp-inner = { git = "https://github.com/contextgeneric/cgp.git" } +cgp = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-core = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-extra = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-async = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-async-macro = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-component = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-macro = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-macro-lib = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-type = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-field = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-error = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-error-extra = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-error-anyhow = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-run = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-runtime = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-sync = { git = "https://github.com/contextgeneric/cgp.git" } +cgp-inner = { git = "https://github.com/contextgeneric/cgp.git" } diff --git a/flake.lock b/flake.lock index 94820cf..1442493 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1730272153, - "narHash": "sha256-B5WRZYsRlJgwVHIV6DvidFN7VX7Fg9uuwkRW9Ha8z+w=", + "lastModified": 1746397377, + "narHash": "sha256-5oLdRa3vWSRbuqPIFFmQBGGUqaYZBxX+GGtN9f/n4lU=", "owner": "nixos", "repo": "nixpkgs", - "rev": "2d2a9ddbe3f2c00747398f3dc9b05f7f2ebb0f53", + "rev": "ed30f8aba41605e3ab46421e3dcb4510ec560ff8", "type": "github" }, "original": { From e6e8bc22bf5a748a3a7d8265ca2bfe132f06b1da Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 6 May 2025 11:07:55 +0000 Subject: [PATCH 02/19] Fix chapters up to Associated Types --- Cargo.lock | 34 ++-- content/associated-types.md | 240 +++++++++++--------------- content/component-macros.md | 12 +- content/consumer-provider-link.md | 24 +-- content/debugging-techniques.md | 23 ++- content/delegated-error-raiser.md | 4 +- content/error-handling.md | 10 +- content/error-reporting.md | 56 +++--- content/error-wrapping.md | 12 +- content/field-accessors.md | 6 +- content/generic-accessor-providers.md | 12 +- content/provider-delegation.md | 50 +++--- content/use-field-pattern.md | 6 +- 13 files changed, 228 insertions(+), 261 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5d87666..bb703f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,7 +101,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cgp" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-async", "cgp-core", @@ -111,7 +111,7 @@ dependencies = [ [[package]] name = "cgp-async" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-async-macro", "cgp-sync", @@ -120,7 +120,7 @@ dependencies = [ [[package]] name = "cgp-async-macro" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "proc-macro2", "quote", @@ -130,12 +130,12 @@ dependencies = [ [[package]] name = "cgp-component" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" [[package]] name = "cgp-core" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-async", "cgp-component", @@ -148,7 +148,7 @@ dependencies = [ [[package]] name = "cgp-error" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-async", "cgp-component", @@ -159,7 +159,7 @@ dependencies = [ [[package]] name = "cgp-error-anyhow" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "anyhow", "cgp-core", @@ -168,7 +168,7 @@ dependencies = [ [[package]] name = "cgp-error-extra" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-core", ] @@ -176,7 +176,7 @@ dependencies = [ [[package]] name = "cgp-extra" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-error-extra", "cgp-inner", @@ -187,7 +187,7 @@ dependencies = [ [[package]] name = "cgp-field" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-component", "cgp-macro", @@ -197,7 +197,7 @@ dependencies = [ [[package]] name = "cgp-inner" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-component", "cgp-macro", @@ -206,7 +206,7 @@ dependencies = [ [[package]] name = "cgp-macro" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-macro-lib", "syn", @@ -215,7 +215,7 @@ dependencies = [ [[package]] name = "cgp-macro-lib" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "itertools", "prettyplease", @@ -242,7 +242,7 @@ dependencies = [ [[package]] name = "cgp-run" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-async", "cgp-component", @@ -253,7 +253,7 @@ dependencies = [ [[package]] name = "cgp-runtime" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-core", ] @@ -261,7 +261,7 @@ dependencies = [ [[package]] name = "cgp-sync" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-async-macro", ] @@ -269,7 +269,7 @@ dependencies = [ [[package]] name = "cgp-type" version = "0.4.0" -source = "git+https://github.com/contextgeneric/cgp.git#5cc02c7ab0bced98a3833679b6d36041dbbfbf31" +source = "git+https://github.com/contextgeneric/cgp.git#759bd220bf52ea5fe6ebfc4490322d63a6085f9f" dependencies = [ "cgp-component", "cgp-macro", diff --git a/content/associated-types.md b/content/associated-types.md index f0a068e..6ff5d9a 100644 --- a/content/associated-types.md +++ b/content/associated-types.md @@ -15,23 +15,17 @@ pub mod traits { use anyhow::Error; use cgp::prelude::*; - #[cgp_component { - provider: AuthTokenValidator, - }] + #[cgp_component(AuthTokenValidator)] pub trait CanValidateAuthToken { fn validate_auth_token(&self, auth_token: &str) -> Result<(), Error>; } - #[cgp_component { - provider: AuthTokenExpiryFetcher, - }] + #[cgp_component(AuthTokenExpiryFetcher)] pub trait CanFetchAuthTokenExpiry { fn fetch_auth_token_expiry(&self, auth_token: &str) -> Result; } - #[cgp_component { - provider: CurrentTimeGetter, - }] + #[cgp_component(CurrentTimeGetter)] pub trait HasCurrentTime { fn current_time(&self) -> Result; } @@ -41,11 +35,11 @@ pub mod impls { use std::time::{SystemTime, UNIX_EPOCH}; use anyhow::{anyhow, Error}; + use cgp::prelude::*; use super::traits::*; - pub struct ValidateTokenIsNotExpired; - + #[cgp_new_provider] impl AuthTokenValidator for ValidateTokenIsNotExpired where Context: HasCurrentTime + CanFetchAuthTokenExpiry, @@ -63,8 +57,7 @@ pub mod impls { } } - pub struct GetSystemTimestamp; - + #[cgp_new_provider] impl CurrentTimeGetter for GetSystemTimestamp { fn current_time(_context: &Context) -> Result { let now = SystemTime::now() @@ -86,16 +79,11 @@ pub mod contexts { use super::impls::*; use super::traits::*; + #[cgp_context] pub struct MockApp { pub auth_tokens_store: BTreeMap, } - pub struct MockAppComponents; - - impl HasComponents for MockApp { - type Components = MockAppComponents; - } - delegate_components! { MockAppComponents { CurrentTimeGetterComponent: GetSystemTimestamp, @@ -103,6 +91,7 @@ pub mod contexts { } } + #[cgp_provider] impl AuthTokenExpiryFetcher for MockAppComponents { fn fetch_auth_token_expiry( context: &MockApp, @@ -116,9 +105,11 @@ pub mod contexts { } } - pub trait CanUseMockApp: CanValidateAuthToken {} - - impl CanUseMockApp for MockApp {} + check_components! { + CanUseMockApp for MockApp { + AuthTokenValidatorComponent, + } + } } # # } @@ -155,18 +146,12 @@ A more flexible approach is to define an _abstract_ `Time` type that allows us t # use cgp::prelude::*; -#[cgp_component { - name: TimeTypeComponent, - provider: ProvideTimeType, -}] +#[cgp_component(TimeTypeProviderComponent)] pub trait HasTimeType { type Time: Eq + Ord; } -#[cgp_component { - name: AuthTokenTypeComponent, - provider: ProvideAuthTokenType, -}] +#[cgp_component(AuthTokenTypeProviderComponent)] pub trait HasAuthTokenType { type AuthToken; } @@ -174,7 +159,7 @@ pub trait HasAuthTokenType { Here, we define the `HasTimeType` trait with an associated type `Time`, which is constrained to types that implement `Eq` and `Ord` so that they can be compared. Similarly, the `HasAuthTokenType` trait defines an associated type `AuthToken`, without any additional constraints. -Similar to regular trait methods, CGP allows us to auto-derive blanket implementations that delegate the associated types to providers using `HasComponents` and `DelegateComponent`. Therefore, we can use `#[cgp_component]` on traits containing associated types as well. +Similar to regular trait methods, CGP allows us to auto-derive blanket implementations that delegate the associated types to providers using `HasProvider` and `DelegateComponent`. Therefore, we can use `#[cgp_component]` on traits containing associated types as well. With these type traits in place, we can now update our authentication components to leverage abstract types within the trait methods: @@ -187,39 +172,27 @@ With these type traits in place, we can now update our authentication components # use anyhow::Error; # use cgp::prelude::*; # -# #[cgp_component { -# name: TimeTypeComponent, -# provider: ProvideTimeType, -# }] +# #[cgp_component(TimeTypeProviderComponent)] # pub trait HasTimeType { # type Time: Eq + Ord; # } # -# #[cgp_component { -# name: AuthTokenTypeComponent, -# provider: ProvideAuthTokenType, -# }] +# #[cgp_component(AuthTokenTypeProvider)] # pub trait HasAuthTokenType { # type AuthToken; # } # -#[cgp_component { - provider: AuthTokenValidator, -}] +#[cgp_component(AuthTokenValidator)] pub trait CanValidateAuthToken: HasAuthTokenType { fn validate_auth_token(&self, auth_token: &Self::AuthToken) -> Result<(), Error>; } -#[cgp_component { - provider: AuthTokenExpiryFetcher, -}] +#[cgp_component(AuthTokenExpiryFetcher)] pub trait CanFetchAuthTokenExpiry: HasAuthTokenType + HasTimeType { fn fetch_auth_token_expiry(&self, auth_token: &Self::AuthToken) -> Result; } -#[cgp_component { - provider: CurrentTimeGetter, -}] +#[cgp_component(CurrentTimeGetter)] pub trait HasCurrentTime: HasTimeType { fn current_time(&self) -> Result; } @@ -236,45 +209,32 @@ With the abstract types defined, we can now update `ValidateTokenIsNotExpired` t # use anyhow::{anyhow, Error}; # use cgp::prelude::*; # -# #[cgp_component { -# name: TimeTypeComponent, -# provider: ProvideTimeType, -# }] +# #[cgp_component(TimeTypeProviderComponent)] # pub trait HasTimeType { # type Time: Eq + Ord; # } # -# #[cgp_component { -# name: AuthTokenTypeComponent, -# provider: ProvideAuthTokenType, -# }] +# #[cgp_component(AuthTokenTypeProviderComponent)] # pub trait HasAuthTokenType { # type AuthToken; # } # -# #[cgp_component { -# provider: AuthTokenValidator, -# }] +# #[cgp_component(AuthTokenValidator)] # pub trait CanValidateAuthToken: HasAuthTokenType { # fn validate_auth_token(&self, auth_token: &Self::AuthToken) -> Result<(), Error>; # } # -# #[cgp_component { -# provider: AuthTokenExpiryFetcher, -# }] +# #[cgp_component(AuthTokenExpiryFetcher)] # pub trait CanFetchAuthTokenExpiry: HasAuthTokenType + HasTimeType { # fn fetch_auth_token_expiry(&self, auth_token: &Self::AuthToken) -> Result; # } # -# #[cgp_component { -# provider: CurrentTimeGetter, -# }] +# #[cgp_component(CurrentTimeGetter)] # pub trait HasCurrentTime: HasTimeType { # fn current_time(&self) -> Result; # } # -pub struct ValidateTokenIsNotExpired; - +#[cgp_new_provider] impl AuthTokenValidator for ValidateTokenIsNotExpired where Context: HasCurrentTime + CanFetchAuthTokenExpiry, @@ -309,8 +269,15 @@ Here's how you can define the same types with `cgp_type!`: # use cgp::prelude::*; -cgp_type!( Time: Eq + Ord ); -cgp_type!( AuthToken ); +#[cgp_type] +pub trait HasTimeType { + type Time: Eq + Ord; +} + +#[cgp_type] +pub trait HasAuthTokenType { + type AuthToken; +} ``` The `cgp_type!` macro accepts the name of an abstract type, `$name`, along with any applicable constraints for that type. It then automatically generates the same implementation as the `cgp_component` macro: a consumer trait named `Has{$name}Type`, a provider trait named `Provide{$name}Type`, and a component name type named `${name}TypeComponent`. Each of the generated traits includes an associated type defined as `type $name: $constraints;`. @@ -327,9 +294,7 @@ At first glance, it might seem overly verbose to define multiple type traits and # use cgp::prelude::*; # use anyhow::Error; # -#[cgp_component { - provider: AppImpl, -}] +#[cgp_component(AppImpl)] pub trait AppTrait { type Time: Eq + Ord; @@ -366,7 +331,10 @@ The minimalism philosophy of CGP extends to the constraints placed on associated # # use cgp::prelude::*; # -cgp_type!( Time: Eq + Ord ); +#[cgp_type] +pub trait HasTimeType { + type Time: Eq + Ord; +} ``` Here, the associated `Time` type is constrained by `Eq + Ord`. This means that all concrete implementations of `Time` must satisfy these constraints, regardless of whether they are actually required by the providers. In fact, if we revisit our previous examples, we notice that the `Eq` constraint isn’t used anywhere. @@ -382,33 +350,32 @@ Fortunately, CGP allows us to apply the same principle of impl-side dependencies # use anyhow::{anyhow, Error}; # use cgp::prelude::*; # -cgp_type!( Time ); - -# cgp_type!( AuthToken ); +#[cgp_type] +pub trait HasTimeType { + type Time: Eq + Ord; +} # -# #[cgp_component { -# provider: AuthTokenValidator, -# }] +# #[cgp_type] +# pub trait HasAuthTokenType { +# type AuthToken; +# } +# +# #[cgp_component(AuthTokenValidator)] # pub trait CanValidateAuthToken: HasAuthTokenType { # fn validate_auth_token(&self, auth_token: &Self::AuthToken) -> Result<(), Error>; # } # -# #[cgp_component { -# provider: AuthTokenExpiryFetcher, -# }] +# #[cgp_component(AuthTokenExpiryFetcher)] # pub trait CanFetchAuthTokenExpiry: HasAuthTokenType + HasTimeType { # fn fetch_auth_token_expiry(&self, auth_token: &Self::AuthToken) -> Result; # } # -# #[cgp_component { -# provider: CurrentTimeGetter, -# }] +# #[cgp_component(CurrentTimeGetter)] # pub trait HasCurrentTime: HasTimeType { # fn current_time(&self) -> Result; # } # -pub struct ValidateTokenIsNotExpired; - +#[cgp_new_provider] impl AuthTokenValidator for ValidateTokenIsNotExpired where Context: HasCurrentTime + CanFetchAuthTokenExpiry, @@ -452,10 +419,7 @@ With type abstraction in place, we can define context-generic providers for the # use cgp::prelude::*; # use anyhow::Error; # -# #[cgp_component { -# name: TimeTypeComponent, -# provider: ProvideTimeType, -# }] +# #[cgp_type] # pub trait HasTimeType { # type Time: Eq + Ord; # } @@ -469,10 +433,12 @@ With type abstraction in place, we can define context-generic providers for the # pub struct UseInstant; -impl ProvideTimeType for UseInstant { +#[cgp_provider] +impl TimeTypeProvider for UseInstant { type Time = Instant; } +#[cgp_provider] impl CurrentTimeGetter for UseInstant where Context: HasTimeType